Snap for 10453563 from 8abd3d9d1b81c0a0b52af70aeac9ba93692d8002 to mainline-media-release

Change-Id: I2d908c85a1b553cb5d93ba4d3ff90e0938d39c99
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 160bc34..479ca7f 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,3 +1,3 @@
 GitHub Issues are for bugs and feature requests. To make bugs and feature requests more easy to find and organize, we close issues that are deemed out of scope for GitHub Issues.
 
-The openthread-users Google Group is the recommended place for users to discuss OpenThread and interact directly with the OpenThread community. https://groups.google.com/forum/#!forum/openthread-users
+OpenThread GitHub Discussions is the recommended place for users to discuss OpenThread and interact directly with the OpenThread community. https://github.com/openthread/openthread/discussions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index ac4e986..d158eea 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -84,6 +84,7 @@
     name: package-${{ matrix.compiler }}
     runs-on: ubuntu-20.04
     strategy:
+      fail-fast: false
       matrix:
         include:
           - compiler: gcc
@@ -134,7 +135,7 @@
     - uses: actions/checkout@v2
       with:
         repository: ARMmbed/mbedtls
-        ref: v3.0.0
+        ref: v3.1.0
         path: third_party/mbedtls/repo
     - name: Build
       run: |
@@ -144,6 +145,7 @@
     name: arm-gcc-${{ matrix.gcc_ver }}
     runs-on: ubuntu-18.04
     strategy:
+      fail-fast: false
       matrix:
         include:
           - gcc_ver: 4
@@ -184,8 +186,9 @@
     name: gcc-${{ matrix.gcc_ver }}
     runs-on: ubuntu-18.04
     strategy:
+      fail-fast: false
       matrix:
-        gcc_ver: [5, 6, 7, 8, 9, 10]
+        gcc_ver: [5, 6, 7, 8, 9, 10, 11]
     env:
       CC: gcc-${{ matrix.gcc_ver }}
       CXX: g++-${{ matrix.gcc_ver }}
@@ -196,6 +199,11 @@
     - name: Bootstrap
       run: |
         sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
+        case ${{ matrix.gcc_ver }} in
+          11)
+            sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
+            ;;
+        esac
         sudo apt-get --no-install-recommends install -y gcc-${{ matrix.gcc_ver }} g++-${{ matrix.gcc_ver }} ninja-build libreadline-dev libncurses-dev
     - name: Build
       run: |
@@ -206,8 +214,9 @@
     name: clang-${{ matrix.clang_ver }}
     runs-on: ubuntu-20.04
     strategy:
+      fail-fast: false
       matrix:
-        clang_ver: ["6.0", "7", "8", "9"]
+        clang_ver: ["6.0", "7", "8", "9", "10", "11", "12", "13"]
     env:
       CC: clang-${{ matrix.clang_ver }}
       CXX: clang++-${{ matrix.clang_ver }}
@@ -217,7 +226,14 @@
           submodules: true
       - name: Bootstrap
         run: |
-          sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
+          sudo rm /etc/apt/sources.list.d/*
+          wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
+          echo 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal main
+          deb-src http://apt.llvm.org/focal/ llvm-toolchain-focal main
+          # 13
+          deb http://apt.llvm.org/focal/ llvm-toolchain-focal-13 main
+          deb-src http://apt.llvm.org/focal/ llvm-toolchain-focal-13 main' | sudo tee -a /etc/apt/sources.list
+          sudo apt-get update
           sudo apt-get --no-install-recommends install -y clang-${{ matrix.clang_ver }} clang++-${{ matrix.clang_ver }} ninja-build libreadline-dev libncurses-dev
       - name: Build
         run: |
@@ -228,8 +244,9 @@
     name: clang-m32-${{ matrix.clang_ver }}
     runs-on: ubuntu-20.04
     strategy:
+      fail-fast: false
       matrix:
-        clang_ver: ["6.0", "7", "8", "9"]
+        clang_ver: ["6.0", "7", "8", "9", "10", "11", "12", "13"]
     env:
       CC: clang-${{ matrix.clang_ver }}
       CXX: clang++-${{ matrix.clang_ver }}
@@ -243,6 +260,12 @@
       - name: Bootstrap
         run: |
           sudo dpkg --add-architecture i386
+          wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
+          echo 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal main
+          deb-src http://apt.llvm.org/focal/ llvm-toolchain-focal main
+          # 13
+          deb http://apt.llvm.org/focal/ llvm-toolchain-focal-13 main
+          deb-src http://apt.llvm.org/focal/ llvm-toolchain-focal-13 main' | sudo tee -a /etc/apt/sources.list
           sudo apt-get update
           sudo apt-get --no-install-recommends install -y clang-${{ matrix.clang_ver }} clang++-${{ matrix.clang_ver }} ninja-build
           sudo apt-get --no-install-recommends install -y g++-multilib libreadline-dev:i386 libncurses-dev:i386
@@ -273,13 +296,14 @@
   macos:
     name: macos-${{ matrix.CC }}
     strategy:
+      fail-fast: false
       matrix:
         include:
           - CC: clang
             CXX: clang++
           - CC: gcc
             CXX: g++
-    runs-on: macos-10.15
+    runs-on: macos-12
     env:
       CC: ${{ matrix.CC }}
       CXX: ${{ matrix.CXX }}
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 627f0a9..339bb1a 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -44,10 +44,10 @@
     name: buildx-${{ matrix.docker_name }}
     runs-on: ubuntu-20.04
     strategy:
+      fail-fast: false
       matrix:
         include:
           - docker_name: environment
-          - docker_name: codelab_otsim
     steps:
     - uses: actions/checkout@v2
       with:
diff --git a/.github/workflows/otbr.yml b/.github/workflows/otbr.yml
index d20d562..6f9412b 100644
--- a/.github/workflows/otbr.yml
+++ b/.github/workflows/otbr.yml
@@ -46,7 +46,7 @@
       REFERENCE_DEVICE: 1
       VIRTUAL_TIME: 0
       PACKET_VERIFICATION: 1
-      THREAD_VERSION: 1.2
+      THREAD_VERSION: 1.3
       INTER_OP: 1
       COVERAGE: 1
       MULTIPLY: 1
@@ -83,41 +83,80 @@
         sudo -E ./script/test cert_suite ./tests/scripts/thread-cert/backbone/*.py || (sudo chmod a+r *.log *.json *.pcap && false)
     - uses: actions/upload-artifact@v2
       with:
-        name: cov-thread-1-2-backbone-docker
+        name: cov-thread-1-3-backbone-docker
         path: /tmp/coverage/
     - uses: actions/upload-artifact@v2
       if: ${{ failure() }}
       with:
-        name: thread-1-2-backbone-results
+        name: thread-1-3-backbone-results
         path: |
           *.pcap
           *.json
           *.log
+          coredump_*
+          otbr-agent_*
     - name: Generate Coverage
       run: |
         ./script/test generate_coverage gcc
     - uses: actions/upload-artifact@v2
       with:
-        name: cov-thread-1-2-backbone
+        name: cov-thread-1-3-backbone
         path: tmp/coverage.info
 
   thread-border-router:
     runs-on: ubuntu-20.04
     strategy:
+      fail-fast: false
       matrix:
         include:
           - otbr_mdns: "mDNSResponder"
             otbr_trel: 0
+            cert_scripts: ./tests/scripts/thread-cert/border_router/*.py
+            packet_verification: 1
+            nat64: 0
+            description: ""
           - otbr_mdns: "mDNSResponder"
             otbr_trel: 1
+            cert_scripts: ./tests/scripts/thread-cert/border_router/*.py
+            packet_verification: 2
+            nat64: 0
+            description: ""
+          - otbr_mdns: "mDNSResponder"
+            otbr_trel: 0
+            cert_scripts: ./tests/scripts/thread-cert/border_router/MATN/*.py
+            packet_verification: 1
+            nat64: 0
+            description: "MATN"
+          - otbr_mdns: "mDNSResponder"
+            otbr_trel: 0
+            cert_scripts: ./tests/scripts/thread-cert/border_router/LowPower/*.py
+            packet_verification: 1
+            nat64: 0
+            description: "LowPower"
+          - otbr_mdns: "mDNSResponder"
+            otbr_trel: 0
+            cert_scripts: ./tests/scripts/thread-cert/border_router/nat64/*.py
+            packet_verification: 1
+            nat64: 1
+            description: "nat64"
           - otbr_mdns: "avahi"
             otbr_trel: 0
-    name: BR (${{ matrix.otbr_mdns }}, TREL=${{matrix.otbr_trel}})
+            cert_scripts: ./tests/scripts/thread-cert/border_router/*.py
+            packet_verification: 1
+            nat64: 0
+            description: ""
+          - otbr_mdns: "avahi"
+            otbr_trel: 1
+            cert_scripts: ./tests/scripts/thread-cert/border_router/*.py
+            packet_verification: 2
+            nat64: 0
+            description: ""
+    name: BR ${{ matrix.description }} (${{ matrix.otbr_mdns }}, TREL=${{matrix.otbr_trel}})
     env:
       REFERENCE_DEVICE: 1
       VIRTUAL_TIME: 0
-      PACKET_VERIFICATION: 1
-      THREAD_VERSION: 1.2
+      PACKET_VERIFICATION: ${{ matrix.packet_verification }}
+      THREAD_VERSION: 1.3
       INTER_OP: 1
       COVERAGE: 1
       MULTIPLY: 1
@@ -125,6 +164,8 @@
       PYTHONUNBUFFERED: 1
       VERBOSE: 1
       BORDER_ROUTING: 1
+      NAT64: ${{ matrix.nat64 }}
+      MAX_JOBS: 3
     steps:
     - uses: actions/checkout@v2
     - name: Build OTBR Docker
@@ -148,7 +189,7 @@
       run: |
         export CI_ENV="$(bash <(curl -s https://codecov.io/env)) -e GITHUB_ACTIONS -e COVERAGE"
         echo "CI_ENV=${CI_ENV}"
-        sudo -E ./script/test cert_suite ./tests/scripts/thread-cert/border_router/*.py || (sudo chmod a+r *.log *.json *.pcap && false)
+        sudo -E ./script/test cert_suite ${{ matrix.cert_scripts }} || (sudo chmod a+r *.log *.json *.pcap && false)
     - uses: actions/upload-artifact@v2
       with:
         name: cov-thread-border-router-docker
@@ -161,6 +202,8 @@
           *.pcap
           *.json
           *.log
+          coredump_*
+          otbr-agent_*
     - name: Generate Coverage
       run: |
         ./script/test generate_coverage gcc
@@ -185,17 +228,18 @@
       with:
         path: coverage/
     - name: Combine Coverage
+      continue-on-error: true
       run: |
         script/test combine_coverage
     - name: Upload Coverage
-      uses: codecov/codecov-action@v1
+      continue-on-error: true
+      uses: codecov/codecov-action@v2
       with:
         files: final.info
         fail_ci_if_error: true
 
   delete-coverage-artifacts:
     needs: upload-coverage
-    if: always()
     runs-on: ubuntu-20.04
     steps:
     - uses: geekyeggo/delete-artifact@1-glob-support
diff --git a/.github/workflows/otci.yml b/.github/workflows/otci.yml
index 0d7acf6..a1e3a9b 100644
--- a/.github/workflows/otci.yml
+++ b/.github/workflows/otci.yml
@@ -44,6 +44,7 @@
     name: cli-sim VIRTUAL_TIME=${{ matrix.virtual_time }}
     runs-on: ubuntu-20.04
     strategy:
+      fail-fast: false
       matrix:
         virtual_time: [0, 1]
     env:
@@ -60,7 +61,7 @@
     - name: Build
       run: |
         ./bootstrap
-        make -f examples/Makefile-simulation THREAD_VERSION=1.2 DUA=1 MLR=1 BACKBONE_ROUTER=1 CSL_RECEIVER=1
+        make -f examples/Makefile-simulation THREAD_VERSION=1.3 DUA=1 MLR=1 BACKBONE_ROUTER=1 CSL_RECEIVER=1
     - name: Install OTCI Python Library
       run: |
         (cd tools/otci && python3 setup.py install --user)
diff --git a/.github/workflows/otns.yml b/.github/workflows/otns.yml
new file mode 100644
index 0000000..46dc33c
--- /dev/null
+++ b/.github/workflows/otns.yml
@@ -0,0 +1,205 @@
+#
+#  Copyright (c) 2020, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+name: OTNS
+
+on: [push, pull_request]
+
+env:
+  COVERAGE: 1
+  REFERENCE_DEVICE: 1
+  VIRTUAL_TIME: 1
+  VIRTUAL_TIME_UART: 1
+  MAX_NETWORK_SIZE: 999
+  GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+
+jobs:
+
+  cancel-previous-runs:
+    runs-on: ubuntu-20.04
+    steps:
+    - uses: rokroskar/workflow-run-cleanup-action@master
+      env:
+        GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+      if: "github.ref != 'refs/heads/main'"
+
+  unittests:
+    name: Unittests
+    runs-on: ubuntu-20.04
+    steps:
+    - uses: actions/checkout@v2
+    - uses: actions/setup-go@v1
+      with:
+        go-version: '1.14'
+    - name: Set up Python 3.6
+      uses: actions/setup-python@v1
+      with:
+        python-version: 3.6
+    - name: Bootstrap
+      run: |
+        sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
+        sudo apt-get --no-install-recommends install -y g++-multilib lcov ninja-build
+        ./bootstrap
+    - name: Run
+      run: |
+        export OT_DIR=$PWD
+        ./script/git-tool clone --depth 1 https://github.com/openthread/ot-ns.git /tmp/otns
+        (
+          cd /tmp/otns
+          ./script/test py-unittests
+        )
+    - uses: actions/upload-artifact@v2
+      if: ${{ failure() }}
+      with:
+        name: unittests-pcaps
+        path: |
+          ./output/*/bin/*.pcap
+          ./output/*/bin/*.replay
+    - name: Generate Coverage
+      run: |
+        ./script/test generate_coverage gcc
+    - uses: actions/upload-artifact@v2
+      with:
+        name: cov-otns-unittests
+        path: tmp/coverage.info
+
+  examples:
+    name: Examples
+    runs-on: ubuntu-20.04
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions/setup-go@v1
+        with:
+          go-version: '1.14'
+      - name: Set up Python 3.6
+        uses: actions/setup-python@v1
+        with:
+          python-version: 3.6
+      - name: Bootstrap
+        run: |
+          sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
+          sudo apt-get --no-install-recommends install -y g++-multilib lcov ninja-build
+          ./bootstrap
+      - name: Run
+        run: |
+          export OT_DIR=$PWD
+          ./script/git-tool clone --depth 1 https://github.com/openthread/ot-ns.git /tmp/otns
+          (
+            cd /tmp/otns
+            ./script/test py-examples
+          )
+      - uses: actions/upload-artifact@v2
+        if: ${{ failure() }}
+        with:
+          name: examples-pcaps
+          path: |
+            ./output/*/bin/*.pcap
+            ./output/*/bin/*.replay
+      - name: Generate Coverage
+        run: |
+          ./script/test generate_coverage gcc
+      - uses: actions/upload-artifact@v2
+        with:
+          name: cov-otns-examples
+          path: tmp/coverage.info
+
+  stress-tests:
+    name: Stress ${{ matrix.suite }}
+    runs-on: ubuntu-20.04
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - suite: "network-forming"
+            stress_level: 8
+          - suite: "commissioning"
+            stress_level: 14
+          - suite: "connectivity"
+            stress_level: 6
+          - suite: "network-latency"
+            stress_level: 10
+          - suite: "multicast-performance"
+            stress_level: 10
+          - suite: "otns-performance"
+            stress_level: 10
+    env:
+      STRESS_LEVEL: ${{ matrix.stress_level }}
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions/setup-go@v1
+        with:
+          go-version: '1.14'
+      - name: Set up Python 3.6
+        uses: actions/setup-python@v1
+        with:
+          python-version: 3.6
+      - name: Bootstrap
+        run: |
+          sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
+          sudo apt-get --no-install-recommends install -y g++-multilib lcov ninja-build
+          ./bootstrap
+      - name: Run
+        run: |
+          export OT_DIR=$PWD
+          ./script/git-tool clone --depth 1 https://github.com/openthread/ot-ns.git /tmp/otns
+          (
+            cd /tmp/otns
+            ./script/test stress-tests ${{ matrix.suite }}
+          )
+      - uses: actions/upload-artifact@v2
+        if: ${{ failure() }}
+        with:
+          name: stress-tests-${{ matrix.suite }}-pcaps
+          path: |
+            ./output/*/bin/*.pcap
+            ./output/*/bin/*.replay
+      - name: Generate Coverage
+        run: |
+          ./script/test generate_coverage gcc
+      - uses: actions/upload-artifact@v2
+        with:
+          name: cov-otns-stress-tests-${{ matrix.suite }}
+          path: tmp/coverage.info
+
+  upload-coverage:
+    needs:
+      - unittests
+      - examples
+      - stress-tests
+    runs-on: ubuntu-20.04
+    steps:
+      - uses: actions/checkout@v2
+      - name: Bootstrap
+        run: |
+          sudo apt-get --no-install-recommends install -y lcov
+      - uses: actions/download-artifact@v2
+        with:
+          path: coverage/
+      - name: Upload Coverage
+        run: |
+          script/test upload_codecov
diff --git a/.github/workflows/posix.yml b/.github/workflows/posix.yml
index fc57a19..2ec9fa5 100644
--- a/.github/workflows/posix.yml
+++ b/.github/workflows/posix.yml
@@ -183,6 +183,7 @@
     name: pty-linux OT_DAEMON=${{ matrix.OT_DAEMON }}
     runs-on: ubuntu-20.04
     strategy:
+      fail-fast: false
       matrix:
         OT_DAEMON: ['off', 'on']
     env:
@@ -225,8 +226,9 @@
 
   pty-macos:
     name: pty-macos OT_DAEMON=${{ matrix.OT_DAEMON }}
-    runs-on: macos-10.15
+    runs-on: macos-12
     strategy:
+      fail-fast: false
       matrix:
         OT_DAEMON: ['off', 'on']
     env:
@@ -291,14 +293,13 @@
       run: |
         script/test combine_coverage
     - name: Upload Coverage
-      uses: codecov/codecov-action@v1
+      uses: codecov/codecov-action@v2
       with:
         files: final.info
         fail_ci_if_error: true
 
   delete-coverage-artifacts:
     needs: upload-coverage
-    if: always()
     runs-on: ubuntu-20.04
     steps:
     - uses: geekyeggo/delete-artifact@1-glob-support
diff --git a/.github/workflows/simulation-1.1.yml b/.github/workflows/simulation-1.1.yml
index 02d96fb..3754c9d 100644
--- a/.github/workflows/simulation-1.1.yml
+++ b/.github/workflows/simulation-1.1.yml
@@ -66,60 +66,6 @@
         ./bootstrap
         VERBOSE=1 make -f examples/Makefile-simulation distcheck
 
-  cli-ftd-otns:
-    runs-on: ubuntu-20.04
-    env:
-      CFLAGS: -m32
-      CXXFLAGS: -m32
-      LDFLAGS: -m32
-      COVERAGE: 1
-      REFERENCE_DEVICE: 1
-      THREAD_VERSION: 1.1
-      VIRTUAL_TIME: 1
-      VIRTUAL_TIME_UART: 1
-      MAX_NETWORK_SIZE: 999
-    steps:
-    - uses: actions/checkout@v2
-      with:
-        submodules: true
-    - uses: actions/setup-go@v1
-      with:
-        go-version: '1.14'
-    - name: Set up Python 3.6
-      uses: actions/setup-python@v1
-      with:
-        python-version: 3.6
-    - name: Bootstrap
-      run: |
-        sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
-        sudo apt-get --no-install-recommends install -y g++-multilib lcov ninja-build
-        ./bootstrap
-    - name: Run OTNS Tests
-      env:
-        GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
-      run: |
-        export OT_DIR=$PWD
-        mkdir -p /tmp/otns
-        (
-          ./script/git-tool clone --depth 1 https://github.com/openthread/ot-ns.git /tmp/otns
-          cd /tmp/otns
-          ./script/test py-unittests py-examples
-        )
-    - uses: actions/upload-artifact@v2
-      if: ${{ failure() }}
-      with:
-        name: cli-ftd-otns-pcaps
-        path: |
-          ./output/*/bin/*.pcap
-          ./output/*/bin/*.replay
-    - name: Generate Coverage
-      run: |
-        ./script/test generate_coverage gcc
-    - uses: actions/upload-artifact@v2
-      with:
-        name: cov-cli-ftd-otns
-        path: tmp/coverage.info
-
   packet-verification:
     runs-on: ubuntu-20.04
     env:
@@ -204,6 +150,7 @@
     name: cli-mtd MESSAGE_USE_HEAP=${{ matrix.message_use_heap }}
     runs-on: ubuntu-20.04
     strategy:
+      fail-fast: false
       matrix:
         message_use_heap: [0, 1]
     env:
@@ -401,100 +348,8 @@
         name: cov-multiple-instance
         path: tmp/coverage.info
 
-  ncp-gcc-m32:
-    runs-on: ubuntu-20.04
-    env:
-      CFLAGS: -m32
-      CXXFLAGS: -m32
-      LDFLAGS: -m32
-      COVERAGE: 1
-      GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
-      NODE_TYPE: ncp-sim
-      PYTHONUNBUFFERED: 1
-      REFERENCE_DEVICE: 1
-      THREAD_VERSION: 1.1
-      VIRTUAL_TIME: 1
-    steps:
-    - uses: actions/checkout@v2
-      with:
-        submodules: true
-    - name: Bootstrap
-      run: |
-        sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
-        sudo apt-get --no-install-recommends install -y g++-multilib python3-setuptools python3-wheel lcov
-        python3 -m pip install -r tests/scripts/thread-cert/requirements.txt
-        pyspineldir=$(mktemp -d -t pyspinel_XXXXXX)
-        ./script/git-tool clone https://github.com/openthread/pyspinel.git --depth 1 "${pyspineldir}"
-        cd "${pyspineldir}"
-        pip3 install .
-    - name: Build
-      run: |
-        ./bootstrap
-        make -f examples/Makefile-simulation
-    - name: Run
-      run: |
-        VERBOSE=1 make -f examples/Makefile-simulation check
-    - uses: actions/upload-artifact@v2
-      if: ${{ failure() }}
-      with:
-        name: ncp-gcc-m32-thread-cert
-        path: build/simulation/tests/scripts/thread-cert
-    - name: Generate Coverage
-      run: |
-        ./script/test generate_coverage gcc
-    - uses: actions/upload-artifact@v2
-      with:
-        name: cov-ncp-gcc-m32
-        path: tmp/coverage.info
-
-  ncp-clang:
-    runs-on: ubuntu-20.04
-    env:
-      COVERAGE: 1
-      GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
-      NODE_TYPE: ncp-sim
-      PYTHONUNBUFFERED: 1
-      REFERENCE_DEVICE: 1
-      THREAD_VERSION: 1.1
-      VIRTUAL_TIME: 1
-      CC: clang-10
-      CXX: clang++-10
-    steps:
-    - uses: actions/checkout@v2
-      with:
-        submodules: true
-    - name: Bootstrap
-      run: |
-        sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
-        sudo apt-get --no-install-recommends install -y clang-10 clang++-10 python3-setuptools python3-wheel llvm lcov
-        python3 -m pip install -r tests/scripts/thread-cert/requirements.txt
-        pyspineldir=$(mktemp -d -t pyspinel_XXXXXX)
-        ./script/git-tool clone https://github.com/openthread/pyspinel.git --depth 1 "${pyspineldir}"
-        cd "${pyspineldir}"
-        pip3 install .
-    - name: Build
-      run: |
-        ./bootstrap
-        make -f examples/Makefile-simulation
-    - name: Run
-      run: |
-        VERBOSE=1 make -f examples/Makefile-simulation check
-    - uses: actions/upload-artifact@v2
-      if: ${{ failure() }}
-      with:
-        name: cli-clang-thread-cert
-        path: build/simulation/tests/scripts/thread-cert
-    - name: Generate Coverage
-      run: |
-        ./script/test generate_coverage llvm
-    - uses: actions/upload-artifact@v2
-      with:
-        name: cov-ncp-clang
-        path: tmp/coverage.info
-
   upload-coverage:
     needs:
-    - cli-ftd-otns
     - packet-verification
     - cli-ftd
     - cli-mtd
@@ -502,8 +357,6 @@
     - expects
     - ot-commissioner
     - multiple-instance
-    - ncp-gcc-m32
-    - ncp-clang
     runs-on: ubuntu-20.04
     steps:
     - uses: actions/checkout@v2
@@ -519,14 +372,13 @@
       run: |
         script/test combine_coverage
     - name: Upload Coverage
-      uses: codecov/codecov-action@v1
+      uses: codecov/codecov-action@v2
       with:
         files: final.info
         fail_ci_if_error: true
 
   delete-coverage-artifacts:
     needs: upload-coverage
-    if: always()
     runs-on: ubuntu-20.04
     steps:
     - uses: geekyeggo/delete-artifact@1-glob-support
diff --git a/.github/workflows/simulation-1.2.yml b/.github/workflows/simulation-1.2.yml
index df19047..2616646 100644
--- a/.github/workflows/simulation-1.2.yml
+++ b/.github/workflows/simulation-1.2.yml
@@ -26,7 +26,7 @@
 #  POSSIBILITY OF SUCH DAMAGE.
 #
 
-name: Simulation 1.2
+name: Simulation 1.3
 
 on: [push, pull_request]
 
@@ -40,20 +40,21 @@
         GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
       if: "github.ref != 'refs/heads/main'"
 
-  thread-1-2:
-    name: thread-1-2-${{ matrix.compiler.c }}-${{ matrix.arch }}
+  thread-1-3:
+    name: thread-1-3-${{ matrix.compiler.c }}-${{ matrix.arch }}
     runs-on: ubuntu-20.04
     env:
       CFLAGS: -${{ matrix.arch }}
       CXXFLAGS: -${{ matrix.arch }}
       LDFLAGS: -${{ matrix.arch }}
       COVERAGE: 1
-      THREAD_VERSION: 1.2
+      THREAD_VERSION: 1.3
       VIRTUAL_TIME: 1
       INTER_OP: 1
       CC: ${{ matrix.compiler.c }}
       CXX: ${{ matrix.compiler.cxx }}
     strategy:
+      fail-fast: false
       matrix:
         compiler: [{c: "gcc", cxx: "g++", gcov: "gcc"}, { c: "clang-10", cxx: "clang++-10", gcov: "llvm"}]
         arch: ["m32", "m64"]
@@ -86,12 +87,12 @@
     - uses: actions/upload-artifact@v2
       if: ${{ failure() }}
       with:
-        name: thread-1-2-${{ matrix.compiler.c }}-${{ matrix.arch }}-pcaps
+        name: thread-1-3-${{ matrix.compiler.c }}-${{ matrix.arch }}-pcaps
         path: "*.pcap"
     - uses: actions/upload-artifact@v2
       if: ${{ failure() && env.CRASHED == '1' }}
       with:
-        name: core-packet-verification-thread-1-2
+        name: core-packet-verification-thread-1-3
         path: |
           ./ot-core-dump/*
     - name: Generate Coverage
@@ -99,7 +100,7 @@
         ./script/test generate_coverage "${{ matrix.compiler.gcov }}"
     - uses: actions/upload-artifact@v2
       with:
-        name: cov-thread-1-2-${{ matrix.compiler.c }}-${{ matrix.arch }}
+        name: cov-thread-1-3-${{ matrix.compiler.c }}-${{ matrix.arch }}
         path: tmp/coverage.info
 
   packet-verification-low-power:
@@ -109,7 +110,7 @@
       VIRTUAL_TIME: 1
       COVERAGE: 1
       PACKET_VERIFICATION: 1
-      THREAD_VERSION: 1.2
+      THREAD_VERSION: 1.3
       MAC_FILTER: 1
       INTER_OP: 1
       INTER_OP_BBR: 0
@@ -163,13 +164,13 @@
         name: cov-packet-verification-low-power
         path: tmp/coverage.info
 
-  packet-verification-1-1-on-1-2:
+  packet-verification-1-1-on-1-3:
     runs-on: ubuntu-20.04
     env:
       REFERENCE_DEVICE: 1
       VIRTUAL_TIME: 1
       PACKET_VERIFICATION: 1
-      THREAD_VERSION: 1.2
+      THREAD_VERSION: 1.3
       MULTIPLY: 3
     steps:
     - uses: actions/checkout@v2
@@ -192,7 +193,7 @@
     - uses: actions/upload-artifact@v2
       if: ${{ failure() }}
       with:
-        name: packet-verification-1.1-on-1.2-pcaps
+        name: packet-verification-1.1-on-1.3-pcaps
         path: |
           *.pcap
           *.json
@@ -201,14 +202,14 @@
         ./script/test generate_coverage gcc
     - uses: actions/upload-artifact@v2
       with:
-        name: cov-packet-verification-1-1-on-1-2
+        name: cov-packet-verification-1-1-on-1-3
         path: tmp/coverage.info
 
   expects:
     runs-on: ubuntu-20.04
     env:
       COVERAGE: 1
-      THREAD_VERSION: 1.2
+      THREAD_VERSION: 1.3
       VIRTUAL_TIME: 0
     steps:
     - uses: actions/checkout@v2
@@ -231,7 +232,7 @@
     - uses: actions/upload-artifact@v2
       if: ${{ failure() && env.CRASHED == '1' }}
       with:
-        name: core-expect-1-2
+        name: core-expect-1-3
         path: |
           ./ot-core-dump/*
     - name: Generate Coverage
@@ -242,13 +243,13 @@
         name: cov-expects
         path: tmp/coverage.info
 
-  thread-1-2-posix:
+  thread-1-3-posix:
     runs-on: ubuntu-20.04
     env:
       COVERAGE: 1
       PYTHONUNBUFFERED: 1
       READLINE: readline
-      THREAD_VERSION: 1.2
+      THREAD_VERSION: 1.3
       OT_NODE_TYPE: rcp
       USE_MTD: 1
       VIRTUAL_TIME: 1
@@ -284,12 +285,12 @@
     - uses: actions/upload-artifact@v2
       if: ${{ failure() }}
       with:
-        name: thread-1-2-posix-pcaps
+        name: thread-1-3-posix-pcaps
         path: "*.pcap"
     - uses: actions/upload-artifact@v2
       if: ${{ failure() && env.CRASHED == '1' }}
       with:
-        name: core-thread-1-2-posix
+        name: core-thread-1-3-posix
         path: |
             ./ot-core-dump/*
     - name: Generate Coverage
@@ -297,16 +298,16 @@
         ./script/test generate_coverage gcc
     - uses: actions/upload-artifact@v2
       with:
-        name: cov-thread-1-2-posix
+        name: cov-thread-1-3-posix
         path: tmp/coverage.info
 
   upload-coverage:
     needs:
-    - thread-1-2
+    - thread-1-3
     - packet-verification-low-power
-    - packet-verification-1-1-on-1-2
+    - packet-verification-1-1-on-1-3
     - expects
-    - thread-1-2-posix
+    - thread-1-3-posix
     runs-on: ubuntu-20.04
     steps:
     - uses: actions/checkout@v2
@@ -322,14 +323,13 @@
       run: |
         script/test combine_coverage
     - name: Upload Coverage
-      uses: codecov/codecov-action@v1
+      uses: codecov/codecov-action@v2
       with:
         files: final.info
         fail_ci_if_error: true
 
   delete-coverage-artifacts:
     needs: upload-coverage
-    if: always()
     runs-on: ubuntu-20.04
     steps:
     - uses: geekyeggo/delete-artifact@1-glob-support
diff --git a/.github/workflows/size.yml b/.github/workflows/size.yml
index f22d9e4..763fb45 100644
--- a/.github/workflows/size.yml
+++ b/.github/workflows/size.yml
@@ -48,7 +48,7 @@
       if: "github.event_name == 'push'"
       run: |
         python3 -m pip install --upgrade setuptools wheel
-        python3 -m pip install mdv
+        python3 -m pip install git+https://github.com/axiros/terminal_markdown_viewer.git
     - name: Run
       env:
         OT_BASE_BRANCH: "${{ github.base_ref }}"
diff --git a/.github/workflows/toranj.yml b/.github/workflows/toranj.yml
index ff88daa..221913f 100644
--- a/.github/workflows/toranj.yml
+++ b/.github/workflows/toranj.yml
@@ -40,10 +40,11 @@
         GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
       if: "github.ref != 'refs/heads/main'"
 
-  toranj:
-    name: toranj-${{ matrix.TORANJ_RADIO }}
+  toranj-ncp:
+    name: toranj-ncp-${{ matrix.TORANJ_RADIO }}
     runs-on: ubuntu-18.04
     strategy:
+      fail-fast: false
       matrix:
         TORANJ_RADIO: ['15.4', 'trel', 'multi']
     env:
@@ -82,12 +83,47 @@
     - uses: actions/upload-artifact@v2
       if: "matrix.TORANJ_RADIO != 'multi'"
       with:
-        name: cov-toranj-${{ matrix.TORANJ_RADIO }}
+        name: cov-toranj-ncp-${{ matrix.TORANJ_RADIO }}
+        path: tmp/coverage.info
+
+  toranj-cli:
+    name: toranj-cli-${{ matrix.TORANJ_RADIO }}
+    runs-on: ubuntu-18.04
+    strategy:
+      matrix:
+        TORANJ_RADIO: ['15.4']
+    env:
+      COVERAGE: 1
+      TORANJ_RADIO : ${{ matrix.TORANJ_RADIO }}
+      TORANJ_CLI: 1
+    steps:
+    - uses: actions/checkout@v2
+      with:
+        submodules: true
+    - name: Bootstrap
+      env:
+        GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+      run: |
+        sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
+        sudo apt-get --no-install-recommends install -y lcov
+        python3 -m pip install -r tests/scripts/thread-cert/requirements.txt
+    - name: Build & Run
+      run: |
+        top_builddir=$(pwd)/build/toranj ./tests/toranj/start.sh
+    - name: Generate Coverage
+      if: "matrix.TORANJ_RADIO != 'multi'"
+      run: |
+        ./script/test generate_coverage gcc
+    - uses: actions/upload-artifact@v2
+      if: "matrix.TORANJ_RADIO != 'multi'"
+      with:
+        name: cov-toranj-cli-${{ matrix.TORANJ_RADIO }}
         path: tmp/coverage.info
 
   upload-coverage:
     needs:
-    - toranj
+    - toranj-ncp
+    - toranj-cli
     runs-on: ubuntu-18.04
     steps:
     - uses: actions/checkout@v2
@@ -103,14 +139,13 @@
       run: |
         script/test combine_coverage
     - name: Upload Coverage
-      uses: codecov/codecov-action@v1
+      uses: codecov/codecov-action@v2
       with:
         files: final.info
         fail_ci_if_error: true
 
   delete-coverage-artifacts:
     needs: upload-coverage
-    if: always()
     runs-on: ubuntu-20.04
     steps:
     - uses: geekyeggo/delete-artifact@1-glob-support
diff --git a/Android.bp b/Android.bp
index 4913872..93f283d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -69,34 +69,21 @@
 }
 
 cc_defaults {
-    name : "ot_cflags_defaults",
+    name : "ot_posix_cflags_defaults",
     cflags: [
-        "-DOPENTHREAD_CONFIG_COMMISSIONER_ENABLE=1",
-        "-DOPENTHREAD_CONFIG_IP6_SLAAC_ENABLE=1",
-        "-DOPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE=1",
-        "-DOPENTHREAD_CONFIG_MAC_FILTER_ENABLE=1",
-        "-DOPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE=1",
+        "-DMBEDTLS_CONFIG_FILE=\"mbedtls-config.h\"",
+        "-DOPENTHREAD_CONFIG_FILE=\"src/android/openthread-android-config.h\"",
         "-DOPENTHREAD_FTD=1",
         "-DOPENTHREAD_POSIX=1",
-        "-DOPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE=1",
-        "-DOPENTHREAD_CONFIG_ANDROID_VERSION_HEADER_ENABLE=1",
-        "-DOPENTHREAD_CONFIG_ECDSA_ENABLE=1",
-        "-DOPENTHREAD_CONFIG_SRP_SERVER_ENABLE=1",
-        "-DOPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE=1",
-        "-DOPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"src/android/openthread-core-android-config.h\"",
-        "-DOPENTHREAD_CONFIG_FILE=\"src/android/openthread-android-config.h\"",
-        "-DOPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE=1",
-        "-DOPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE=1",
-        "-DOPENTHREAD_CONFIG_UNSECURE_TRAFFIC_MANAGED_BY_STACK_ENABLE=1",
-        "-DOPENTHREAD_CONFIG_PING_SENDER_ENABLE=1",
         "-DOPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE=1",
-        "-DOPENTHREAD_POSIX_CONFIG_RCP_BUS=OT_POSIX_RCP_BUS_SPI",
+        "-DOPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"src/android/openthread-core-android-config.h\"",
+        "-DOPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE=1",
+        "-DOPENTHREAD_CONFIG_JOINER_ENABLE=1",
         "-DPACKAGE=\"openthread\"",
         "-DPACKAGE_BUGREPORT=\"openthread-devel@googlegroups.com\"",
         "-DPACKAGE_NAME=\"OPENTHREAD\"",
         "-DPACKAGE_TARNAME=\"openthread\"",
         "-DPACKAGE_URL=\"http://github.com/openthread/openthread\"",
-        "-DMBEDTLS_CONFIG_FILE=\"mbedtls-config.h\"",
         "-DSPINEL_PLATFORM_HEADER=\"spinel_platform.h\"",
     ],
 }
@@ -116,26 +103,49 @@
     module_type: "cc_defaults",
     config_namespace: "openthread",
     bool_variables: ["diag"],
+    variables: ["rcp_bus"],
     properties: ["cflags"],
 }
 
+soong_config_string_variable {
+    name: "rcp_bus",
+    values: ["spi", "uart", "hal"],
+}
+
 ot_config_cc_defaults {
     name: "ot_config_defaults",
     soong_config_variables: {
         diag: {
             cflags: ["-DOPENTHREAD_CONFIG_DIAG_ENABLE=1"],
         },
+        rcp_bus: {
+            spi: {
+                cflags: ["-DOPENTHREAD_POSIX_CONFIG_RCP_BUS=OT_POSIX_RCP_BUS_SPI"]
+            },
+            hal: {
+                cflags: [
+                    "-DOPENTHREAD_POSIX_CONFIG_RCP_BUS=OT_POSIX_RCP_BUS_VENDOR",
+                ]
+            },
+            conditions_default: {
+                cflags: [
+                    "-DOPENTHREAD_POSIX_CONFIG_RCP_BUS=OT_POSIX_RCP_BUS_UART",
+                    "-DOPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE=1",
+                ]
+            },
+        },
     },
 }
 
 cc_library_static {
     name: "ot-core",
-    defaults: ["ot_cflags_defaults", "ot_config_defaults"],
+    defaults: ["ot_posix_cflags_defaults", "ot_config_defaults"],
     generated_headers: ["ot_version_header"],
 
     local_include_dirs: [
         "include",
         "src",
+        "src/android/thread_network_hal",
         "src/cli",
         "src/core",
         "src/ncp",
@@ -163,10 +173,13 @@
     ],
 
     srcs: [
+        "src/android/thread_network_hal/hal_interface.cpp",
+        "src/android/thread_network_hal/vendor_interface.cpp",
         "src/core/api/backbone_router_api.cpp",
         "src/core/api/backbone_router_ftd_api.cpp",
         "src/core/api/border_agent_api.cpp",
         "src/core/api/border_router_api.cpp",
+        "src/core/api/border_routing_api.cpp",
         "src/core/api/channel_manager_api.cpp",
         "src/core/api/channel_monitor_api.cpp",
         "src/core/api/child_supervision_api.cpp",
@@ -180,7 +193,6 @@
         "src/core/api/diags_api.cpp",
         "src/core/api/dns_api.cpp",
         "src/core/api/dns_server_api.cpp",
-        "src/core/api/entropy_api.cpp",
         "src/core/api/error_api.cpp",
         "src/core/api/heap_api.cpp",
         "src/core/api/icmp6_api.cpp",
@@ -217,20 +229,25 @@
         "src/core/backbone_router/bbr_manager.cpp",
         "src/core/backbone_router/multicast_listeners_table.cpp",
         "src/core/backbone_router/ndproxy_table.cpp",
-        "src/core/border_router/infra_if_platform.cpp",
-        "src/core/border_router/router_advertisement.cpp",
+        "src/core/border_router/infra_if.cpp",
         "src/core/border_router/routing_manager.cpp",
         "src/core/coap/coap.cpp",
         "src/core/coap/coap_message.cpp",
         "src/core/coap/coap_secure.cpp",
+        "src/core/common/binary_search.cpp",
         "src/core/common/crc16.cpp",
+        "src/core/common/data.cpp",
         "src/core/common/error.cpp",
+        "src/core/common/frame_builder.cpp",
+        "src/core/common/frame_data.cpp",
+        "src/core/common/heap.cpp",
+        "src/core/common/heap_data.cpp",
         "src/core/common/heap_string.cpp",
         "src/core/common/instance.cpp",
-        "src/core/common/logging.cpp",
+        "src/core/common/log.cpp",
         "src/core/common/message.cpp",
         "src/core/common/notifier.cpp",
-        "src/core/common/random_manager.cpp",
+        "src/core/common/random.cpp",
         "src/core/common/settings.cpp",
         "src/core/common/string.cpp",
         "src/core/common/tasklet.cpp",
@@ -270,11 +287,13 @@
         "src/core/meshcop/dataset_updater.cpp",
         "src/core/meshcop/dtls.cpp",
         "src/core/meshcop/energy_scan_client.cpp",
+        "src/core/meshcop/extended_panid.cpp",
         "src/core/meshcop/joiner.cpp",
         "src/core/meshcop/joiner_router.cpp",
         "src/core/meshcop/meshcop.cpp",
         "src/core/meshcop/meshcop_leader.cpp",
         "src/core/meshcop/meshcop_tlvs.cpp",
+        "src/core/meshcop/network_name.cpp",
         "src/core/meshcop/panid_query_client.cpp",
         "src/core/meshcop/timestamp.cpp",
         "src/core/net/checksum.cpp",
@@ -284,12 +303,13 @@
         "src/core/net/dns_types.cpp",
         "src/core/net/dnssd_server.cpp",
         "src/core/net/icmp6.cpp",
-        "src/core/net/ip4_address.cpp",
+        "src/core/net/ip4_types.cpp",
         "src/core/net/ip6.cpp",
         "src/core/net/ip6_address.cpp",
         "src/core/net/ip6_filter.cpp",
         "src/core/net/ip6_headers.cpp",
         "src/core/net/ip6_mpl.cpp",
+        "src/core/net/nd6.cpp",
         "src/core/net/nd_agent.cpp",
         "src/core/net/netif.cpp",
         "src/core/net/sntp_client.cpp",
@@ -350,7 +370,6 @@
         "src/core/utils/flash.cpp",
         "src/core/utils/heap.cpp",
         "src/core/utils/jam_detector.cpp",
-        "src/core/utils/lookup_table.cpp",
         "src/core/utils/otns.cpp",
         "src/core/utils/parse_cmdline.cpp",
         "src/core/utils/ping_sender.cpp",
@@ -363,8 +382,6 @@
         "src/lib/spinel/spinel_decoder.cpp",
         "src/lib/spinel/spinel_encoder.cpp",
         "src/lib/url/url.cpp",
-        "src/posix/cli_readline.cpp",
-        "src/posix/cli_stdio.cpp",
         "src/posix/platform/alarm.cpp",
         "src/posix/platform/backbone.cpp",
         "src/posix/platform/daemon.cpp",
@@ -382,7 +399,7 @@
         "src/posix/platform/settings.cpp",
         "src/posix/platform/spi_interface.cpp",
         "src/posix/platform/system.cpp",
-        "src/posix/platform/trel_udp6.cpp",
+        "src/posix/platform/trel.cpp",
         "src/posix/platform/udp.cpp",
         "third_party/mbedtls/repo/library/aes.c",
         "third_party/mbedtls/repo/library/asn1parse.c",
@@ -393,6 +410,7 @@
         "third_party/mbedtls/repo/library/cipher.c",
         "third_party/mbedtls/repo/library/cipher_wrap.c",
         "third_party/mbedtls/repo/library/cmac.c",
+        "third_party/mbedtls/repo/library/constant_time.c",
         "third_party/mbedtls/repo/library/ctr_drbg.c",
         "third_party/mbedtls/repo/library/debug.c",
         "third_party/mbedtls/repo/library/ecdh.c",
@@ -428,9 +446,38 @@
 }
 
 cc_library_static {
+    name: "openthread-tcplp",
+
+    local_include_dirs: [
+        "include",
+    ],
+
+    cflags: [
+        "-Wno-sign-compare",
+        "-Wno-conversion",
+        "-Wno-unused-parameter",
+    ],
+
+    srcs: [
+        "third_party/tcplp/bsdtcp/cc/cc_newreno.c",
+        "third_party/tcplp/bsdtcp/tcp_input.c",
+        "third_party/tcplp/bsdtcp/tcp_output.c",
+        "third_party/tcplp/bsdtcp/tcp_reass.c",
+        "third_party/tcplp/bsdtcp/tcp_sack.c",
+        "third_party/tcplp/bsdtcp/tcp_subr.c",
+        "third_party/tcplp/bsdtcp/tcp_timer.c",
+        "third_party/tcplp/bsdtcp/tcp_timewait.c",
+        "third_party/tcplp/bsdtcp/tcp_usrreq.c",
+        "third_party/tcplp/lib/bitmap.c",
+        "third_party/tcplp/lib/cbuf.c",
+        "third_party/tcplp/lib/lbuf.c",
+    ],
+}
+
+cc_library_static {
     name: "libopenthread-cli",
 
-    defaults: ["ot_cflags_defaults", "ot_config_defaults"],
+    defaults: ["ot_posix_cflags_defaults", "ot_config_defaults"],
     generated_headers: ["ot_version_header"],
 
     local_include_dirs: [
@@ -444,7 +491,11 @@
         "third_party/mbedtls/repo/include",
     ],
 
-    cflags: ["-DOPENTHREAD_CONFIG_UART_CLI_RAW=1"],
+    cflags: [
+        "-DOPENTHREAD_CONFIG_CLI_UART_TX_BUFFER_SIZE=3500",
+        "-DOPENTHREAD_CONFIG_CLI_UART_RX_BUFFER_SIZE=3500",
+        "-DOPENTHREAD_CONFIG_UART_CLI_RAW=1",
+    ],
 
     cppflags: [
         "-std=c++11",
@@ -471,7 +522,7 @@
 cc_binary {
     name: "ot-ctl",
 
-    defaults: ["ot_cflags_defaults"],
+    defaults: ["ot_posix_cflags_defaults"],
     generated_headers: ["ot_version_header"],
 
     cppflags: [
@@ -488,3 +539,331 @@
 
     srcs: ["src/posix/client.cpp"],
 }
+
+cc_defaults {
+    name: "ot_rcp_cflags_defaults",
+    cflags: [
+        "-DOPENTHREAD_RADIO=1",
+    ],
+}
+
+cc_defaults {
+    name : "ot_simulation_cflags_defaults",
+
+    local_include_dirs: [
+        "examples/platforms/simulation",
+        "examples/platforms",
+        "include",
+        "src",
+        "src/cli",
+        "src/core",
+        "src/ncp",
+        "src/lib/hdlc",
+        "third_party",
+        "third_party/mbedtls",
+        "third_party/mbedtls/repo/include",
+    ],
+
+    export_include_dirs: [
+        "include",
+        "src",
+    ],
+
+    cflags: [
+        "-DMBEDTLS_CONFIG_FILE=\"mbedtls-config.h\"",
+        "-DOPENTHREAD_CONFIG_ANDROID_VERSION_HEADER_ENABLE=1",
+        "-DOPENTHREAD_CONFIG_FILE=\"openthread-config-android-version.h\"",
+        "-DOPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE=1",
+        "-DOPENTHREAD_CONFIG_MAC_FILTER_ENABLE=1",
+        "-DOPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1",
+        "-DOPENTHREAD_EXAMPLES_SIMULATION=1",
+        "-DOPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"examples/platforms/simulation/openthread-core-simulation-config.h\"",
+        "-DPACKAGE=\"openthread\"",
+        "-DPACKAGE_BUGREPORT=\"openthread-devel@googlegroups.com\"",
+        "-DPACKAGE_NAME=\"OPENTHREAD\"",
+        "-DPACKAGE_TARNAME=\"openthread\"",
+        "-DPACKAGE_URL=\"http://github.com/openthread/openthread\"",
+        "-DSPINEL_PLATFORM_HEADER=\"spinel_platform.h\"",
+    ],
+}
+
+cc_library_static {
+    name: "openthread-simulation",
+    vendor: true,
+
+    defaults: [
+        "ot_rcp_cflags_defaults",
+        "ot_simulation_cflags_defaults",
+    ],
+
+    srcs: [
+        "examples/platforms/simulation/alarm.c",
+        "examples/platforms/simulation/crypto.c",
+        "examples/platforms/simulation/diag.c",
+        "examples/platforms/simulation/entropy.c",
+        "examples/platforms/simulation/flash.c",
+        "examples/platforms/simulation/infra_if.c",
+        "examples/platforms/simulation/logging.c",
+        "examples/platforms/simulation/misc.c",
+        "examples/platforms/simulation/radio.c",
+        "examples/platforms/simulation/spi-stubs.c",
+        "examples/platforms/simulation/system.c",
+        "examples/platforms/simulation/trel.c",
+        "examples/platforms/simulation/uart.c",
+        "examples/platforms/utils/link_metrics.cpp",
+        "examples/platforms/utils/mac_frame.cpp",
+        "examples/platforms/utils/soft_source_match_table.c",
+        "src/lib/platform/exit_code.c",
+        "third_party/mbedtls/repo/library/aes.c",
+        "third_party/mbedtls/repo/library/asn1parse.c",
+        "third_party/mbedtls/repo/library/asn1write.c",
+        "third_party/mbedtls/repo/library/base64.c",
+        "third_party/mbedtls/repo/library/bignum.c",
+        "third_party/mbedtls/repo/library/ccm.c",
+        "third_party/mbedtls/repo/library/cipher.c",
+        "third_party/mbedtls/repo/library/cipher_wrap.c",
+        "third_party/mbedtls/repo/library/cmac.c",
+        "third_party/mbedtls/repo/library/ctr_drbg.c",
+        "third_party/mbedtls/repo/library/debug.c",
+        "third_party/mbedtls/repo/library/entropy.c",
+        "third_party/mbedtls/repo/library/entropy_poll.c",
+        "third_party/mbedtls/repo/library/hmac_drbg.c",
+        "third_party/mbedtls/repo/library/md.c",
+        "third_party/mbedtls/repo/library/memory_buffer_alloc.c",
+        "third_party/mbedtls/repo/library/oid.c",
+        "third_party/mbedtls/repo/library/platform.c",
+        "third_party/mbedtls/repo/library/platform_util.c",
+        "third_party/mbedtls/repo/library/sha256.c",
+    ],
+
+    cflags: [
+        "-D_BSD_SOURCE=1",
+        "-D_DEFAULT_SOURCE=1",
+    ],
+}
+
+cc_library_static {
+    name: "openthread-radio",
+    vendor: true,
+
+    defaults: [
+        "ot_rcp_cflags_defaults",
+        "ot_simulation_cflags_defaults",
+    ],
+
+    generated_headers: ["ot_version_header"],
+    shared_libs: [
+        "libcutils",
+    ],
+
+    srcs: [
+        "src/core/api/diags_api.cpp",
+        "src/core/api/error_api.cpp",
+        "src/core/api/instance_api.cpp",
+        "src/core/api/link_raw_api.cpp",
+        "src/core/api/logging_api.cpp",
+        "src/core/api/random_noncrypto_api.cpp",
+        "src/core/api/tasklet_api.cpp",
+        "src/core/common/binary_search.cpp",
+        "src/core/common/error.cpp",
+        "src/core/common/instance.cpp",
+        "src/core/common/log.cpp",
+        "src/core/common/random.cpp",
+        "src/core/common/string.cpp",
+        "src/core/common/tasklet.cpp",
+        "src/core/common/timer.cpp",
+        "src/core/common/uptime.cpp",
+        "src/core/crypto/aes_ccm.cpp",
+        "src/core/crypto/aes_ecb.cpp",
+        "src/core/crypto/crypto_platform.cpp",
+        "src/core/crypto/storage.cpp",
+        "src/core/diags/factory_diags.cpp",
+        "src/core/mac/link_raw.cpp",
+        "src/core/mac/mac_frame.cpp",
+        "src/core/mac/mac_types.cpp",
+        "src/core/mac/sub_mac.cpp",
+        "src/core/mac/sub_mac_callbacks.cpp",
+        "src/core/radio/radio.cpp",
+        "src/core/radio/radio_callbacks.cpp",
+        "src/core/radio/radio_platform.cpp",
+        "src/core/thread/link_quality.cpp",
+        "src/core/utils/parse_cmdline.cpp",
+    ],
+}
+
+cc_library_static {
+    name: "openthread-hdlc",
+    vendor: true,
+    defaults: [
+        "ot_rcp_cflags_defaults",
+        "ot_simulation_cflags_defaults",
+    ],
+    export_include_dirs: [
+        "include",
+        "src",
+    ],
+    srcs: [
+        "src/lib/hdlc/hdlc.cpp",
+    ],
+}
+
+cc_library_static {
+    name: "openthread-url",
+    vendor: true,
+    local_include_dirs: [
+        "include",
+        "src",
+        "src/core",
+        "src/lib/url",
+    ],
+    export_include_dirs: [
+        "include",
+        "src",
+    ],
+    srcs: [
+        "src/lib/url/url.cpp",
+    ],
+}
+
+cc_library_static {
+    name: "openthread-platform",
+    vendor: true,
+    local_include_dirs: [
+        "include",
+        "src",
+        "src/core",
+        "src/lib/platform",
+    ],
+    export_include_dirs: [
+        "include",
+        "src",
+    ],
+    srcs: [
+        "src/lib/platform/exit_code.c",
+    ],
+}
+
+
+cc_library_static {
+    name: "openthread-spinel-rcp",
+    vendor: true,
+
+    defaults: [
+        "ot_rcp_cflags_defaults",
+        "ot_simulation_cflags_defaults",
+    ],
+
+    export_include_dirs: [
+        "include",
+        "src",
+    ],
+
+    srcs: [
+        "src/lib/spinel/spinel.c",
+        "src/lib/spinel/spinel_buffer.cpp",
+        "src/lib/spinel/spinel_decoder.cpp",
+        "src/lib/spinel/spinel_encoder.cpp",
+    ],
+}
+
+cc_library_static {
+    name: "openthread-rcp",
+    vendor: true,
+
+    defaults: [
+        "ot_rcp_cflags_defaults",
+        "ot_simulation_cflags_defaults",
+    ],
+
+    srcs: [
+        "src/ncp/changed_props_set.cpp",
+        "src/ncp/ncp_base.cpp",
+        "src/ncp/ncp_base_dispatcher.cpp",
+        "src/ncp/ncp_base_radio.cpp",
+        "src/ncp/ncp_spi.cpp",
+        "src/ncp/ncp_hdlc.cpp",
+    ],
+}
+
+cc_binary {
+    name: "ot-rcp",
+    vendor: true,
+    defaults: [
+        "ot_rcp_cflags_defaults",
+        "ot_simulation_cflags_defaults",
+    ],
+
+    srcs: [
+        "examples/apps/ncp/main.c",
+        "examples/apps/ncp/ncp.c",
+    ],
+
+    static_libs: [
+        "openthread-hdlc",
+        "openthread-radio",
+        "openthread-spinel-rcp",
+        "openthread-rcp",
+        "openthread-simulation",
+        "openthread-radio",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libutils",
+    ],
+}
+
+cc_library_static {
+    name: "openthread-posix",
+    vendor: true,
+    local_include_dirs: [
+        "include",
+        "src",
+        "src/core",
+        "src/lib/platform",
+        "src/posix/platform",
+        "src/posix/platform/include",
+    ],
+    export_include_dirs: [
+        "include",
+        "src/core",
+        "src/posix/platform",
+        "src/posix/platform/include",
+    ],
+
+    cflags: [
+        "-DOPENTHREAD_POSIX_CONFIG_RCP_BUS=OT_POSIX_RCP_BUS_UART",
+        "-DOPENTHREAD_OSIX_CONFIG_RCP_PTY_ENABLE=1",
+    ],
+
+    cppflags: [
+        "-Wno-non-virtual-dtor",
+    ],
+
+    srcs: [
+        "src/posix/platform/alarm.cpp",
+        "src/posix/platform/mainloop.cpp",
+        "src/posix/platform/hdlc_interface.cpp",
+    ],
+}
+
+cc_library_static {
+    name: "openthread-common",
+    vendor: true,
+    local_include_dirs: [
+        "include",
+        "src",
+        "src/core",
+    ],
+
+    export_include_dirs: [
+        "include",
+        "src/core",
+    ],
+
+    srcs: [
+        "src/core/common/error.cpp",
+        "src/core/api/error_api.cpp",
+    ],
+}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 540550e..642332f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -58,7 +58,6 @@
     target_compile_definitions(ot-config INTERFACE "BYTE_ORDER_BIG_ENDIAN=1")
 endif()
 
-include("${PROJECT_SOURCE_DIR}/etc/cmake/checks.cmake")
 include("${PROJECT_SOURCE_DIR}/etc/cmake/options.cmake")
 include("${PROJECT_SOURCE_DIR}/etc/cmake/functions.cmake")
 
@@ -103,12 +102,14 @@
 endif()
 message(STATUS "Package Version: ${OT_PACKAGE_VERSION}")
 
-set(OT_THREAD_VERSION "1.2" CACHE STRING "Thread version chosen by the user at configure time")
-set_property(CACHE OT_THREAD_VERSION PROPERTY STRINGS "1.1" "1.2")
+set(OT_THREAD_VERSION "1.3" CACHE STRING "Thread version chosen by the user at configure time")
+set_property(CACHE OT_THREAD_VERSION PROPERTY STRINGS "1.1" "1.2" "1.3")
 if(${OT_THREAD_VERSION} EQUAL "1.1")
     target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_THREAD_VERSION=OT_THREAD_VERSION_1_1")
 elseif(${OT_THREAD_VERSION} EQUAL "1.2")
     target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_THREAD_VERSION=OT_THREAD_VERSION_1_2")
+elseif(${OT_THREAD_VERSION} EQUAL "1.3")
+    target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_THREAD_VERSION=OT_THREAD_VERSION_1_3")
 else()
     message(FATAL_ERROR "Thread version unknown: ${OT_THREAD_VERSION}")
 endif()
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e0da93b..2e99d4d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -165,4 +165,24 @@
 
 ## Contributing Documentation
 
-Documentation undergoes the same review process as code and contributions may be mirrored on our [openthread.io](https://openthread.io) website. See the [Documentation Style Guide](https://github.com/openthread/ot-docs/blob/main/STYLE_GUIDE.md) for more information on how to author and format documentation for contribution.
+Documentation undergoes the same review process as code and contributions may be mirrored on our [openthread.io](https://openthread.io) website.
+
+### Codelabs and Guides
+
+To review and contribute to OpenThread Codelabs and Guides, refer to the following GitHub repositories:
+
+- [Codelabs](https://github.com/openthread/ot-docs/tree/main/site/en/codelabs)
+- [Guides](https://github.com/openthread/ot-docs/tree/main/site/en/guides)
+
+For information on how to author and format documentation for contribution, refer to the [Documentation Style Guide](https://github.com/openthread/ot-docs/blob/main/STYLE_GUIDE.md).
+
+### API Reference topics
+
+API Reference topics use [Doxygen comment blocks](https://www.doxygen.nl/manual/docblocks.html) to render the HTML output on [https://openthread.io/reference](https://openthread.io/reference). OpenThread scripts support the following Doxygen [special commands](https://www.doxygen.nl/manual/commands.html):
+
+- @file
+- @brief
+- @param
+- @returns
+
+You can find most of these comments in the [OpenThread header files](https://github.com/openthread/openthread/tree/main/include/openthread). To review an example, refer to [`border_agent.h`](https://github.com/openthread/openthread/tree/main/include/openthread/border_agent.h). The Doxygen comments in `border_agent.h` output the [Border Agent](https://openthread.io/reference/group/api-border-agent) reference topic on openthread.io. For more information, refer to [Comments](https://github.com/openthread/openthread/blob/main/STYLE_GUIDE.md#comments) in the OpenThread Coding Conventions and Style guide.
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..9c186e6
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,18 @@
+name: "openthread"
+description:
+    "OpenThread is an open-source implementation of the Thread networking "
+    "protocol."
+
+third_party {
+  url {
+    type: HOMEPAGE
+    value: "https://github.com/openthread/openthread"
+  }
+  url {
+    type: GIT
+    value: "https://github.com/openthread/openthread.git"
+  }
+  version: "1882fad68add5edc98a5235360b5f8a48e303c65"
+  last_upgrade_date { year: 2022 month: 11 day: 15 }
+  license_type: NOTICE
+}
diff --git a/NOTICE b/NOTICE
index 962490e..94a2d71 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,5 +1,5 @@
-OpenThread is an open source implementation of the Thread 1.1.1 Final Specification.
-The Thread 1.1.1 Final Specification is promulgated by the Thread Group. The Thread
+OpenThread is an open source implementation of the Thread 1.2.0 Final Specification.
+The Thread 1.2.0 Final Specification is promulgated by the Thread Group. The Thread
 Group is a non-profit organization formed for the purposes of defining one or
 more specifications, best practices, reference architectures, implementation
 guidelines and certification programs to promote the availability of compliant
@@ -7,10 +7,10 @@
 information about the benefits thereof, can be found at http://threadgroup.org.
 
 OpenThread is not affiliated with or endorsed by the Thread Group. Implementation
-of this OpenThread code does not assure compliance with the Thread 1.1.1 Final
+of this OpenThread code does not assure compliance with the Thread 1.2.0 Final
 Specification and does not convey the right to identify any final product as Thread
 certified. Members of the Thread Group may hold patents and other intellectual
-property rights relating to the Thread 1.1.1 Final Specification, ownership and
+property rights relating to the Thread 1.2.0 Final Specification, ownership and
 licenses of which are subject to the Thread Group’s IP Policies, and not this license.
 
 The included copyright to the OpenThread code is subject to the license in the
diff --git a/OWNERS b/OWNERS
index 4097108..888425b 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,3 +1,5 @@
+# Bug component: 1203089
+
+include platform/packages/modules/ThreadNetwork:/OWNERS
+
 rquattle@google.com
-xyk@google.com
-zhanglongxia@google.com
diff --git a/README.md b/README.md
index 5370128..6574588 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@
 
 **...OS and platform agnostic**, with a narrow platform abstraction layer and a small memory footprint, making it highly portable. It supports both system-on-chip (SoC) and network co-processor (NCP) designs.
 
-**...a Thread Certified Component**, implementing all features defined in the [Thread 1.1.1 specification](https://www.threadgroup.org/support#specifications), including all Thread networking layers (IPv6, 6LoWPAN, IEEE 802.15.4 with MAC security, Mesh Link Establishment, Mesh Routing) and device roles, as well as [Border Router](https://github.com/openthread/ot-br-posix) support.
+**...a Thread Certified Component**, implementing all features defined in the [Thread 1.2 specification](https://www.threadgroup.org/support#specifications), including all Thread networking layers (IPv6, 6LoWPAN, IEEE 802.15.4 with MAC security, Mesh Link Establishment, Mesh Routing) and device roles, as well as [Border Router](https://github.com/openthread/ot-br-posix) support.
 
 More information about Thread can be found at [threadgroup.org](http://threadgroup.org/). Thread is a registered trademark of the Thread Group, Inc.
 
@@ -29,7 +29,7 @@
 
 # Who supports OpenThread?
 
-<a href="https://www.arm.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-arm.png" alt="ARM" width="200px"></a><a href="https://www.cascoda.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-cascoda.png" alt="Cascoda" width="200px"></a><a href="https://www.espressif.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-espressif-github.png" alt="Espressif" width="200px"></a><a href="https://www.google.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-google.png" alt="Google" width="200px"></a><a href="http://www.nordicsemi.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-nordic.png" alt="Nordic" width="200px"></a><a href="http://www.nxp.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-nxp.png" alt="NXP" width="200px"></a><a href="http://www.qorvo.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-qorvo.png" alt="Qorvo" width="200px"></a><a href="https://www.qualcomm.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-qc.png" alt="Qualcomm" width="200px"></a><a href="https://www.samsung.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-samsung.png" alt="Samsung" width="200px"></a><a href="https://www.silabs.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-silabs.png" alt="Silicon Labs" width="200px"></a><a href="https://www.st.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-stm.png" alt="STMicroelectronics" width="200px"></a><a href="https://www.synopsys.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-synopsys.png" alt="Synopsys" width="200px"></a><a href="https://www.telink-semi.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-telink-github.png" alt="Telink Semiconductor" width="200px"></a><a href="https://www.ti.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-ti.png" alt="Texas Instruments" width="200px"></a><a href="https://www.zephyrproject.org/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-zephyr.png" alt="Zephyr Project" width="200px"></a>
+<a href="https://www.arm.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-arm.png" alt="ARM" width="200px"></a><a href="https://www.cascoda.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-cascoda.png" alt="Cascoda" width="200px"></a><a href="https://www.espressif.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-espressif-github.png" alt="Espressif" width="200px"></a><a href="https://www.google.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-google.png" alt="Google" width="200px"></a><a href="https://www.infineon.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-infineon.png" alt="Infineon" width="200px"></a><a href="http://www.nordicsemi.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-nordic.png" alt="Nordic" width="200px"></a><a href="http://www.nxp.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-nxp.png" alt="NXP" width="200px"></a><a href="http://www.qorvo.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-qorvo.png" alt="Qorvo" width="200px"></a><a href="https://www.qualcomm.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-qc.png" alt="Qualcomm" width="200px"></a><a href="https://www.samsung.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-samsung.png" alt="Samsung" width="200px"></a><a href="https://www.silabs.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-silabs.png" alt="Silicon Labs" width="200px"></a><a href="https://www.st.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-stm.png" alt="STMicroelectronics" width="200px"></a><a href="https://www.synopsys.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-synopsys.png" alt="Synopsys" width="200px"></a><a href="https://www.telink-semi.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-telink-github.png" alt="Telink Semiconductor" width="200px"></a><a href="https://www.ti.com/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-ti.png" alt="Texas Instruments" width="200px"></a><a href="https://www.zephyrproject.org/"><img src="https://github.com/openthread/openthread/raw/main/doc/images/ot-contrib-zephyr.png" alt="Zephyr Project" width="200px"></a>
 
 # Getting started
 
@@ -66,10 +66,7 @@
 
 # Need help?
 
-There are numerous avenues for OpenThread support:
+OpenThread support is available on GitHub:
 
 - Bugs and feature requests — [submit to the Issue Tracker](https://github.com/openthread/openthread/issues)
-- Stack Overflow — [post questions using the `openthread` tag](http://stackoverflow.com/questions/tagged/openthread)
-- Google Groups — [discussion and announcements at openthread-users](https://groups.google.com/forum/#!forum/openthread-users)
-
-The openthread-users Google Group is the recommended place for users to discuss OpenThread and interact directly with the OpenThread team.
+- Community Discussion - [ask questions, share ideas, and engage with other community members](https://github.com/openthread/openthread/discussions)
diff --git a/STYLE_GUIDE.md b/STYLE_GUIDE.md
index 0feed05..d8ea624 100644
--- a/STYLE_GUIDE.md
+++ b/STYLE_GUIDE.md
@@ -176,6 +176,14 @@
   - Describes the purpose, function, and influence of each parameter as well as whether it is an input, an output, or both.
   - Describes the return value, if present, and the expected range or constraints of it.
 
+If your description is longer than 120 characters, continue the comment on the next line:
+
+```
+ * @brief
+ *   Records the history of different events, for example RX and TX messages or network info changes. All tracked
+ *   entries are timestamped.
+```
+
 # Python
 
 ## Standards
diff --git a/bootstrap b/bootstrap
index 881f2c5..637c45c 100755
--- a/bootstrap
+++ b/bootstrap
@@ -39,7 +39,8 @@
 abs_srcdir=$(cd "$(dirname "${0}")" && pwd)
 
 # filter out knowning information from stderr which is causing GitHub annotation check warnings.
-(cd "$abs_srcdir" && exec "$abs_srcdir/$nlbuild_autotools_stem/scripts/bootstrap" -I "$abs_srcdir/$nlbuild_autotools_stem" "${@}") 2> \
-    >(grep -v "installing 'third_party/nlbuild-autotools/repo/third_party/autoconf/missing'" \
+(cd "$abs_srcdir" && exec "$abs_srcdir/$nlbuild_autotools_stem/scripts/bootstrap" -I "$abs_srcdir/$nlbuild_autotools_stem" "${@}") 2> >(
+    grep -v "installing 'third_party/nlbuild-autotools/repo/third_party/autoconf/missing'" \
         | grep -v "installing 'third_party/nlbuild-autotools/repo/third_party/autoconf/compile'" \
-        | grep -v "installing 'third_party/nlbuild-autotools/repo/third_party/autoconf/depcomp'" 1>&2)
+        | grep -v "installing 'third_party/nlbuild-autotools/repo/third_party/autoconf/depcomp'" 1>&2
+)
diff --git a/configure.ac b/configure.ac
index 04b18b2..8c0c7fc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -990,6 +990,7 @@
 LIBS="${LIBS} ${NL_COVERAGE_LIBS}"
 LDFLAGS="${LDFLAGS} ${NL_COVERAGE_LDFLAGS}"
 
+CPPFLAGS="${CPPFLAGS} -DOPENTHREAD_CONFIG_FILE='\"openthread-config-generic.h\"'"
 # At this point, we can restore the compiler flags to whatever the
 # user passed in, now that we're clear of an -Werror issues by
 # transforming -Wno-error back to -Werror.
diff --git a/doc/images/ot-contrib-infineon.png b/doc/images/ot-contrib-infineon.png
new file mode 100644
index 0000000..293a52c
--- /dev/null
+++ b/doc/images/ot-contrib-infineon.png
Binary files differ
diff --git a/doc/ot_api_doc.h b/doc/ot_api_doc.h
index 203feb1..3d58b68 100644
--- a/doc/ot_api_doc.h
+++ b/doc/ot_api_doc.h
@@ -57,9 +57,19 @@
  * @defgroup api-dnssd-server         DNS-SD Server
  * @defgroup api-icmp6                ICMPv6
  * @defgroup api-ip6                  IPv6
+ * @defgroup api-nat64                NAT64
  * @defgroup api-srp                  SRP
  * @defgroup api-ping-sender          Ping Sender
+ *
+ * @defgroup api-tcp-group            TCP
+ *
+ * @{
+ *
  * @defgroup api-tcp                  TCP
+ * @defgroup api-tcp-ext              TCP Abstractions
+ *
+ * @}
+ *
  * @defgroup api-udp-group            UDP
  *
  * @{
@@ -84,6 +94,7 @@
  * @defgroup api-message              Message
  *
  * @defgroup api-multi-radio          Multi Radio Link
+ * @defgroup api-trel                 TREL - Thread Stack
  *
  * @defgroup api-thread               Thread
  *
@@ -92,6 +103,7 @@
  * @defgroup api-backbone-router      Backbone Router
  * @defgroup api-border-agent         Border Agent
  * @defgroup api-border-router        Border Router
+ * @defgroup api-border-routing       Border Routing Manager
  * @defgroup api-commissioner         Commissioner
  * @defgroup api-thread-general       General
  * @brief This module includes functions for all Thread roles.
@@ -120,13 +132,12 @@
  * @}
  *
  * @defgroup api-cli                  Command Line Interface
- * @defgroup api-crypto               Crypto
- * @defgroup api-entropy              Entropy Source
- * @defgroup api-factory-diagnostics  Factory Diagnostics
+ * @defgroup api-crypto               Crypto - Thread Stack
+ * @defgroup api-factory-diagnostics  Factory Diagnostics - Thread Stack
  * @defgroup api-heap                 Heap
  * @defgroup api-history-tracker      History Tracker
  * @defgroup api-jam-detection        Jam Detection
- * @defgroup api-logging              Logging
+ * @defgroup api-logging              Logging - Thread Stack
  * @defgroup api-ncp                  Network Co-Processor
  * @defgroup api-network-time         Network Time Synchronization
  * @defgroup api-random-group         Random Number Generator
@@ -154,9 +165,10 @@
  * @{
  *
  * @defgroup plat-alarm               Alarm
+ * @defgroup plat-crypto              Crypto - Platform
  * @defgroup plat-entropy             Entropy
- * @defgroup plat-factory-diagnostics Factory Diagnostics
- * @defgroup plat-logging             Logging
+ * @defgroup plat-factory-diagnostics Factory Diagnostics - Platform
+ * @defgroup plat-logging             Logging - Platform
  * @defgroup plat-memory              Memory
  * @defgroup plat-messagepool         Message Pool
  * @defgroup plat-misc                Miscellaneous
@@ -166,7 +178,8 @@
  * @defgroup plat-spi-slave           SPI Slave
  * @defgroup plat-time                Time Service
  * @defgroup plat-toolchain           Toolchain
- * @defgroup plat-trel                TREL
+ * @defgroup plat-trel                TREL - Platform
+ * @defgroup plat-infra-if            Infrastructure Interface
  *
  * @}
  *
diff --git a/etc/cmake/options.cmake b/etc/cmake/options.cmake
index 9d31eca..521b7fa 100644
--- a/etc/cmake/options.cmake
+++ b/etc/cmake/options.cmake
@@ -82,6 +82,11 @@
     target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE=1")
 endif()
 
+option(OT_BORDER_ROUTING_NAT64 "enable border routing NAT64 support")
+if(OT_BORDER_ROUTING_NAT64)
+    target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE=1")
+endif()
+
 if(NOT OT_EXTERNAL_MBEDTLS)
     set(OT_MBEDTLS mbedtls)
     target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS=1")
@@ -129,7 +134,7 @@
 
 option(OT_COAP_OBSERVE "enable coap observe (RFC7641) api support")
 if(OT_COAP_OBSERVE)
-    list(APPEND OT_PRIVATE_DEFINES "OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE=1")
+    target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE=1")
 endif()
 
 option(OT_COMMISSIONER "enable commissioner support")
@@ -179,6 +184,11 @@
     target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE=1")
 endif()
 
+option(OT_DNS_DSO "enable DNS Stateful Operations (DSO) support")
+if(OT_DNS_DSO)
+    target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_DNS_DSO_ENABLE=1")
+endif()
+
 option(OT_DNSSD_SERVER "enable DNS-SD server support")
 if(OT_DNSSD_SERVER)
     target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE=1")
@@ -350,6 +360,11 @@
     target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE=1")
 endif()
 
+option(OT_TX_BEACON_PAYLOAD "enable Thread beacon payload in outgoing beacons")
+if (OT_TX_BEACON_PAYLOAD)
+    target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE=1")
+endif()
+
 option(OT_UDP_FORWARD "enable UDP forward support")
 if(OT_UDP_FORWARD)
     target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE=1")
@@ -360,13 +375,17 @@
     target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_UPTIME_ENABLE=1")
 endif()
 
+option(OT_FIREWALL "enable firewall")
+if (OT_FIREWALL)
+    target_compile_definitions(ot-config INTERFACE "OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE=1")
+endif()
+
 option(OT_FULL_LOGS "enable full logs")
 if(OT_FULL_LOGS)
     if(NOT OT_LOG_LEVEL)
         target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_LEVEL=OT_LOG_LEVEL_DEBG")
     endif()
     target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL=1")
-    target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_PREPEND_REGION=1")
 endif()
 
 option(OT_OTNS "enable OTNS support")
@@ -381,6 +400,8 @@
     message(FATAL_ERROR "Invalid max RCP restoration count: ${OT_RCP_RESTORATION_MAX_COUNT}")
 endif()
 
+option(OT_EXCLUDE_TCPLP_LIB "exclude TCPlp library from build")
+
 # Checks
 if(OT_PLATFORM_UDP AND OT_UDP_FORWARD)
     message(FATAL_ERROR "OT_PLATFORM_UDP and OT_UDP_FORWARD are exclusive")
diff --git a/etc/docker/codelab_otsim/Dockerfile b/etc/docker/codelab_otsim/Dockerfile
deleted file mode 100644
index 9f99992..0000000
--- a/etc/docker/codelab_otsim/Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-# Ubuntu image with tools required to build OpenThread
-FROM ubuntu:18.04
-
-ENV DEBIAN_FRONTEND noninteractive
-ARG OT_GIT_REF=main
-
-# Install dependencies:
-RUN apt-get update -qq
-
-# Install packages needed for build and runtime:
-RUN apt-get --no-install-recommends install -y git sudo software-properties-common \
-    ca-certificates \
-    && update-ca-certificates
-
-# Install OpenThread
-RUN mkdir -p ~/src/openthread && \
-    cd ~/src/openthread && \
-    git init . && \
-    git fetch https://github.com/openthread/openthread.git ${OT_GIT_REF} && \
-    git checkout FETCH_HEAD && \
-    ./script/bootstrap && \
-    ./bootstrap && \
-    make -f examples/Makefile-simulation
-
-# Install OpenThread Daemon and ot-ctl
-RUN cd ~/src/openthread && make -f src/posix/Makefile-posix DAEMON=1
diff --git a/etc/docker/environment/Dockerfile b/etc/docker/environment/Dockerfile
index cc6c274..3c297de 100644
--- a/etc/docker/environment/Dockerfile
+++ b/etc/docker/environment/Dockerfile
@@ -16,10 +16,14 @@
         python3-setuptools \
         software-properties-common \
         sudo \
+        netbase \
+        inetutils-ping \
+        ca-certificates \
+    && update-ca-certificates \
     && python3 -m pip install -U cmake \
     && python3 -m pip install wheel
 
-# setup openthread
+# set up openthread simulation cli example apps 
 WORKDIR /
 COPY . openthread
 RUN set -x \
@@ -27,5 +31,11 @@
     && ./script/bootstrap \
     && mkdir build \
     && cd build \
-    && cmake -GNinja -DOT_PLATFORM=simulation .. \
+    && cmake -GNinja -DOT_COMMISSIONER=ON -DOT_JOINER=ON -DOT_PLATFORM=simulation .. \
     && ninja
+
+# set up ot-daemon
+WORKDIR /
+RUN set -x \
+    && cd openthread \
+    && ./script/cmake-build posix -DOT_DAEMON=ON
diff --git a/etc/gn/openthread.gni b/etc/gn/openthread.gni
index 1a8f285..fe494b0 100644
--- a/etc/gn/openthread.gni
+++ b/etc/gn/openthread.gni
@@ -26,9 +26,6 @@
 #
 
 _openthread_config_file = ""
-if (current_os == "fuchsia") {
-  _openthread_config_file = "<openthread-config-android.h>"
-}
 
 declare_args() {
   # OpenThread config header.
@@ -234,6 +231,9 @@
     # Enable builtin mbedtls management
     openthread_config_enable_builtin_mbedtls_management =
         openthread_external_mbedtls == ""
+
+    # Enable radio coexistence
+    openthread_config_coexistence_enable = false
   }
 }
 
diff --git a/examples/Makefile-simulation b/examples/Makefile-simulation
index 0df78dc..f16ce89 100644
--- a/examples/Makefile-simulation
+++ b/examples/Makefile-simulation
@@ -51,6 +51,7 @@
 DHCP6_SERVER                   ?= 1
 DIAGNOSTIC                     ?= 1
 DNS_CLIENT                     ?= 1
+DNS_DSO                        ?= 1
 DNSSD_SERVER                   ?= 1
 ECDSA                          ?= 1
 HISTORY_TRACKER                ?= 1
diff --git a/examples/README.md b/examples/README.md
index 9a1861d..2d0f5d5 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -11,6 +11,8 @@
 | BIG_ENDIAN | OT_BIG_ENDIAN | Allows the host platform to use big-endian byte order. |
 | BORDER_AGENT | OT_BORDER_AGENT | Enables support for border agent. In most cases, enable this switch if you are building On-mesh Commissioner or Border Router with External Commissioning support. |
 | BORDER_ROUTER | OT_BORDER_ROUTER | Enables support for Border Router. This switch is usually combined with the BORDER_AGENT and UDP_FORWARD (or PLATFORM_UDP in case of RCP design) switches to build Border Router device. |
+| BORDER_ROUTING | OT_BORDER_ROUTING | Enables bi-directional border routing between Thread and Infrastructure networks for Border Router. |
+| BORDER_ROUTING_NAT64 | OT_BORDER_ROUTING_NAT64 | Enables NAT64 border routing support for Border Router. |
 | BUILTIN_MBEDTLS_MANAGEMENT | OT_BUILTIN_MBEDTLS_MANAGEMENT | Enables the built-in mbedTLS management. Enable this switch if the external mbedTLS is used, but mbedTLS memory allocation and debug config should be managed internally by OpenThread. |
 | CHANNEL_MANAGER | OT_CHANNEL_MANAGER | Enables support for channel manager. Enable this switch on devices that are supposed to request a Thread network channel change. This switch should be used only with an FTD build. |
 | CHANNEL_MONITOR | OT_CHANNEL_MONITOR | Enables support for channel monitor. Enable this switch on devices that are supposed to determine the cleaner channels. |
@@ -32,10 +34,12 @@
 | DEBUG_UART | not implemented | Enables the Debug UART platform feature. |
 | DEBUG_UART_LOG | not implemented | Enables the log output for the debug UART. Requires OPENTHREAD_CONFIG_ENABLE_DEBUG_UART to be enabled. |
 | DNS_CLIENT | OT_DNS_CLIENT | Enables support for DNS client. Enable this switch on a device that sends a DNS query for AAAA (IPv6) record. |
+| DNS_DSO | OT_DNS_DSO | Enables support for DNS Stateful Operations (DSO). |
 | DNSSD_SERVER | OT_DNSSD_SERVER | Enables support for DNS-SD server. DNS-SD server use service information from local SRP server to resolve DNS-SD query questions. |
 | DUA | OT_DUA | Enables the Domain Unicast Address feature for Thread 1.2. |
 | DYNAMIC_LOG_LEVEL | not implemented | Enables the dynamic log level feature. Enable this switch if OpenThread log level is required to be set at runtime. See [Logging guide](https://openthread.io/guides/build/logs) to learn more. |
 | ECDSA | OT_ECDSA | Enables support for Elliptic Curve Digital Signature Algorithm. Enable this switch if ECDSA digital signature is used by application. |
+| EXCLUDE_TCPLP_LIB | OT_EXCLUDE_TCPLP_LIB | Exclude TCPlp library from the build. |
 | EXTERNAL_HEAP | OT_EXTERNAL_HEAP | Enables support for external heap. Enable this switch if the platform uses its own heap. Make sure to specify the external heap Calloc and Free functions to be used by the OpenThread stack. |
 | FULL_LOGS | OT_FULL_LOGS | Enables all log levels and regions. This switch sets the log level to OT_LOG_LEVEL_DEBG and turns on all region flags. See [Logging guide](https://openthread.io/guides/build/logs) to learn more. |
 | HISTORY_TRACKER | OT_HISTORY_TRACKER | Enables support for History Tracker. |
diff --git a/examples/apps/cli/README.md b/examples/apps/cli/README.md
index a18db68..42b096d 100644
--- a/examples/apps/cli/README.md
+++ b/examples/apps/cli/README.md
@@ -34,7 +34,7 @@
 Network Name: OpenThread-8f28
 PAN ID: 0x8f28
 PSKc: c23a76e98f1a6483639b1ac1271e2e27
-Security Policy: 0, onrcb
+Security Policy: 0, onrc
 Done
 > dataset commit active
 Done
diff --git a/examples/apps/cli/cli_uart.cpp b/examples/apps/cli/cli_uart.cpp
index 2b3b10f..b7fa502 100644
--- a/examples/apps/cli/cli_uart.cpp
+++ b/examples/apps/cli/cli_uart.cpp
@@ -33,11 +33,11 @@
 
 #include <openthread-system.h>
 #include <openthread/cli.h>
+#include <openthread/logging.h>
 
 #include "cli/cli_config.h"
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
-#include "common/logging.hpp"
 #include "utils/uart.h"
 
 #if OPENTHREAD_POSIX
diff --git a/examples/apps/cli/main.c b/examples/apps/cli/main.c
index 4d0440c..165f32f 100644
--- a/examples/apps/cli/main.c
+++ b/examples/apps/cli/main.c
@@ -39,6 +39,8 @@
 #include "cli/cli_config.h"
 #include "common/code_utils.hpp"
 
+#include "lib/platform/reset_util.h"
+
 /**
  * This function initializes the CLI app.
  *
@@ -47,19 +49,6 @@
  */
 extern void otAppCliInit(otInstance *aInstance);
 
-#if OPENTHREAD_EXAMPLES_SIMULATION
-#include <setjmp.h>
-#include <unistd.h>
-
-jmp_buf gResetJump;
-
-void __gcov_flush();
-#endif
-
-#ifndef OPENTHREAD_ENABLE_COVERAGE
-#define OPENTHREAD_ENABLE_COVERAGE 0
-#endif
-
 #if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
 void *otPlatCAlloc(size_t aNum, size_t aSize)
 {
@@ -93,16 +82,7 @@
 {
     otInstance *instance;
 
-#if OPENTHREAD_EXAMPLES_SIMULATION
-    if (setjmp(gResetJump))
-    {
-        alarm(0);
-#if OPENTHREAD_ENABLE_COVERAGE
-        __gcov_flush();
-#endif
-        execvp(argv[0], argv);
-    }
-#endif
+    OT_SETUP_RESET_JUMP(argv);
 
 #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
     size_t   otInstanceBufferLength = 0;
@@ -150,21 +130,13 @@
     return 0;
 }
 
-/*
- * Provide, if required an "otPlatLog()" function
- */
 #if OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_APP
 void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
 {
     va_list ap;
+
     va_start(ap, aFormat);
     otCliPlatLogv(aLogLevel, aLogRegion, aFormat, ap);
     va_end(ap);
 }
-
-void otPlatLogLine(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aLogLine)
-{
-    otCliPlatLogLine(aLogLevel, aLogRegion, aLogLine);
-}
-
 #endif
diff --git a/examples/apps/cli/radio.cmake b/examples/apps/cli/radio.cmake
index dc3e4e9..4302adc 100644
--- a/examples/apps/cli/radio.cmake
+++ b/examples/apps/cli/radio.cmake
@@ -37,13 +37,17 @@
     set(OT_PLATFORM_LIB_RCP ${OT_PLATFORM_LIB})
 endif()
 
+if(NOT DEFINED OT_MBEDTLS_RCP)
+    set(OT_MBEDTLS_RCP ${OT_MBEDTLS})
+endif()
+
 target_link_libraries(ot-cli-radio PRIVATE
     openthread-cli-radio
     ${OT_PLATFORM_LIB_RCP}
     openthread-radio-cli
     ${OT_PLATFORM_LIB_RCP}
     openthread-cli-radio
-    ${OT_MBEDTLS}
+    ${OT_MBEDTLS_RCP}
     ot-config
 )
 
diff --git a/examples/apps/ncp/main.c b/examples/apps/ncp/main.c
index fa2558c..af50d14 100644
--- a/examples/apps/ncp/main.c
+++ b/examples/apps/ncp/main.c
@@ -36,6 +36,7 @@
 
 #include "openthread-system.h"
 
+#include "lib/platform/reset_util.h"
 /**
  * This function initializes the NCP app.
  *
@@ -44,19 +45,6 @@
  */
 extern void otAppNcpInit(otInstance *aInstance);
 
-#if OPENTHREAD_EXAMPLES_SIMULATION
-#include <setjmp.h>
-#include <unistd.h>
-
-jmp_buf gResetJump;
-
-void __gcov_flush();
-#endif
-
-#ifndef OPENTHREAD_ENABLE_COVERAGE
-#define OPENTHREAD_ENABLE_COVERAGE 0
-#endif
-
 #if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
 void *otPlatCAlloc(size_t aNum, size_t aSize)
 {
@@ -78,16 +66,7 @@
 {
     otInstance *instance;
 
-#if OPENTHREAD_EXAMPLES_SIMULATION
-    if (setjmp(gResetJump))
-    {
-        alarm(0);
-#if OPENTHREAD_ENABLE_COVERAGE
-        __gcov_flush();
-#endif
-        execvp(argv[0], argv);
-    }
-#endif
+    OT_SETUP_RESET_JUMP(argv);
 
 #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
     size_t   otInstanceBufferLength = 0;
diff --git a/examples/common-switches.mk b/examples/common-switches.mk
index 33687fe..ac05ccd 100644
--- a/examples/common-switches.mk
+++ b/examples/common-switches.mk
@@ -34,6 +34,7 @@
 BORDER_AGENT              ?= 0
 BORDER_ROUTER             ?= 0
 BORDER_ROUTING            ?= 0
+BORDER_ROUTING_NAT64	  ?= 0
 COAP                      ?= 0
 COAP_BLOCK                ?= 0
 COAP_OBSERVE              ?= 0
@@ -51,6 +52,7 @@
 DISABLE_DOC               ?= 0
 DISABLE_TOOLS             ?= 0
 DNS_CLIENT                ?= 0
+DNS_DSO                   ?= 0
 DNSSD_SERVER              ?= 0
 DUA                       ?= 0
 DYNAMIC_LOG_LEVEL         ?= 0
@@ -84,7 +86,7 @@
 SNTP_CLIENT               ?= 0
 SRP_CLIENT                ?= 0
 SRP_SERVER                ?= 0
-THREAD_VERSION            ?= 1.2
+THREAD_VERSION            ?= 1.3
 TIME_SYNC                 ?= 0
 TREL                      ?= 0
 UDP_FORWARD               ?= 0
@@ -115,6 +117,10 @@
 COMMONCFLAGS                   += -DOPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE=1
 endif
 
+ifeq ($(BORDER_ROUTING_NAT64),1)
+COMMONCFLAGS		       += -DOPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE=1
+endif
+
 ifeq ($(COAP),1)
 COMMONCFLAGS                   += -DOPENTHREAD_CONFIG_COAP_API_ENABLE=1
 endif
@@ -197,6 +203,10 @@
 COMMONCFLAGS                   += -DOPENTHREAD_CONFIG_DNS_CLIENT_ENABLE=1
 endif
 
+ifeq ($(DNS_DSO),1)
+COMMONCFLAGS                   += -DOPENTHREAD_CONFIG_DNS_DSO_ENABLE=1
+endif
+
 ifeq ($(DNSSD_SERVER),1)
 COMMONCFLAGS                   += -DOPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE=1
 endif
@@ -323,6 +333,8 @@
 COMMONCFLAGS                   += -DOPENTHREAD_CONFIG_THREAD_VERSION=2
 else ifeq ($(THREAD_VERSION),1.2)
 COMMONCFLAGS                   += -DOPENTHREAD_CONFIG_THREAD_VERSION=3
+else ifeq ($(THREAD_VERSION),1.3)
+COMMONCFLAGS                   += -DOPENTHREAD_CONFIG_THREAD_VERSION=4
 endif
 
 ifeq ($(TIME_SYNC),1)
@@ -378,5 +390,5 @@
 COMMONCFLAGS += -DOPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT=${RCP_RESTORATION_MAX_COUNT}
 
 ifeq ($(FULL_LOGS),1)
-COMMONCFLAGS += -DOPENTHREAD_CONFIG_LOG_LEVEL=OT_LOG_LEVEL_DEBG -DOPENTHREAD_CONFIG_LOG_PREPEND_LEVEL=1 -DOPENTHREAD_CONFIG_LOG_PREPEND_REGION=1
+COMMONCFLAGS += -DOPENTHREAD_CONFIG_LOG_LEVEL=OT_LOG_LEVEL_DEBG -DOPENTHREAD_CONFIG_LOG_PREPEND_LEVEL=1
 endif
diff --git a/examples/platforms/cc2538/radio.c b/examples/platforms/cc2538/radio.c
index a8bbd99..0878f11 100644
--- a/examples/platforms/cc2538/radio.c
+++ b/examples/platforms/cc2538/radio.c
@@ -33,12 +33,12 @@
  */
 
 #include <openthread/config.h>
+#include <openthread/logging.h>
 #include <openthread/platform/alarm-milli.h>
 #include <openthread/platform/diag.h>
 #include <openthread/platform/radio.h>
 
 #include "platform-cc2538.h"
-#include "common/logging.hpp"
 #include "utils/code_utils.h"
 
 #define RFCORE_XREG_RFIRQM0 0x4008868C // RF interrupt masks
diff --git a/examples/platforms/simulation/CMakeLists.txt b/examples/platforms/simulation/CMakeLists.txt
index 869a1ae..883ee64 100644
--- a/examples/platforms/simulation/CMakeLists.txt
+++ b/examples/platforms/simulation/CMakeLists.txt
@@ -61,6 +61,7 @@
     alarm.c
     crypto.c
     diag.c
+    dso_transport.c
     entropy.c
     flash.c
     infra_if.c
@@ -101,7 +102,7 @@
 if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
     set(CPACK_PACKAGE_NAME "openthread-simulation")
     set(CPACK_GENERATOR "DEB")
-    set(CPACK_DEBIAN_PACKAGE_MAINTAINER "OpenThread Authors <openthread-users@googlegroups.com")
-    set(CPACK_PACKAGE_CONTACT "OpenThread Authors <openthread-users@googlegroups.com")
+    set(CPACK_DEBIAN_PACKAGE_MAINTAINER "OpenThread Authors (https://github.com/openthread/openthread)")
+    set(CPACK_PACKAGE_CONTACT "OpenThread Authors (https://github.com/openthread/openthread)")
     include(CPack)
 endif()
diff --git a/examples/platforms/simulation/Makefile.am b/examples/platforms/simulation/Makefile.am
index cdcad7a..227e2ae 100644
--- a/examples/platforms/simulation/Makefile.am
+++ b/examples/platforms/simulation/Makefile.am
@@ -43,6 +43,7 @@
     alarm.c                                 \
     crypto.c                                \
     diag.c                                  \
+    dso_transport.c                         \
     entropy.c                               \
     flash.c                                 \
     infra_if.c                              \
diff --git a/examples/platforms/simulation/alarm.c b/examples/platforms/simulation/alarm.c
index a6f416e..2795672 100644
--- a/examples/platforms/simulation/alarm.c
+++ b/examples/platforms/simulation/alarm.c
@@ -47,11 +47,11 @@
 timer_t sMicroTimer;
 #endif // __linux__
 
+#include <openthread/logging.h>
 #include <openthread/platform/alarm-micro.h>
 #include <openthread/platform/alarm-milli.h>
 #include <openthread/platform/diag.h>
 
-#include "core/common/logging.hpp"
 #include "lib/platform/exit_code.h"
 
 #define MS_PER_S 1000
@@ -270,7 +270,7 @@
             remaining = 1;
         }
 
-        aTimeout->tv_sec  = (time_t)remaining / US_PER_S;
+        aTimeout->tv_sec  = (time_t)(remaining / US_PER_S);
         aTimeout->tv_usec = remaining % US_PER_S;
     }
 }
diff --git a/include/openthread/entropy.h b/examples/platforms/simulation/dso_transport.c
similarity index 64%
copy from include/openthread/entropy.h
copy to examples/platforms/simulation/dso_transport.c
index bc07c30..f510731 100644
--- a/include/openthread/entropy.h
+++ b/examples/platforms/simulation/dso_transport.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2019, The OpenThread Authors.
+ *  Copyright (c) 2021, The OpenThread Authors.
  *  All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -26,45 +26,34 @@
  *  POSSIBILITY OF SUCH DAMAGE.
  */
 
-/**
- * @file
- * @brief
- *  This file defines the OpenThread entropy source API.
- */
+#include "platform-simulation.h"
 
-#ifndef OPENTHREAD_ENTROPY_H_
-#define OPENTHREAD_ENTROPY_H_
+#include <openthread/platform/dso_transport.h>
 
-#include <mbedtls/entropy.h>
+#if OPENTHREAD_CONFIG_DNS_DSO_ENABLE
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+void otPlatDsoEnableListening(otInstance *aInstance, bool aEnable)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+    OT_UNUSED_VARIABLE(aEnable);
+}
 
-/**
- * @addtogroup api-entropy
- *
- * @brief
- *   This module includes functions that manages entropy source.
- *
- * @{
- *
- */
+void otPlatDsoConnect(otPlatDsoConnection *aConnection, const otSockAddr *aPeerSockAddr)
+{
+    OT_UNUSED_VARIABLE(aConnection);
+    OT_UNUSED_VARIABLE(aPeerSockAddr);
+}
 
-/**
- * This function returns initialized mbedtls_entropy_context.
- *
- * @returns  A pointer to initialized mbedtls_entropy_context.
- */
-mbedtls_entropy_context *otEntropyMbedTlsContextGet(void);
+void otPlatDsoSend(otPlatDsoConnection *aConnection, otMessage *aMessage)
+{
+    OT_UNUSED_VARIABLE(aConnection);
+    OT_UNUSED_VARIABLE(aMessage);
+}
 
-/**
- * @}
- *
- */
+void otPlatDsoDisconnect(otPlatDsoConnection *aConnection, otPlatDsoDisconnectMode aMode)
+{
+    OT_UNUSED_VARIABLE(aConnection);
+    OT_UNUSED_VARIABLE(aMode);
+}
 
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // OPENTHREAD_ENTROPY_H_
+#endif // #if OPENTHREAD_CONFIG_DNS_DSO_ENABLE
diff --git a/examples/platforms/simulation/flash.c b/examples/platforms/simulation/flash.c
index 561ad45..ce07f3a 100644
--- a/examples/platforms/simulation/flash.c
+++ b/examples/platforms/simulation/flash.c
@@ -37,9 +37,9 @@
 #include <unistd.h>
 
 #include <openthread/config.h>
+#include <openthread/logging.h>
 #include <openthread/platform/flash.h>
 
-#include "core/common/logging.hpp"
 #include "lib/platform/exit_code.h"
 
 static int sFlashFd = -1;
diff --git a/examples/platforms/simulation/logging.c b/examples/platforms/simulation/logging.c
index 5b0d6ea..8b90c43 100644
--- a/examples/platforms/simulation/logging.c
+++ b/examples/platforms/simulation/logging.c
@@ -43,37 +43,22 @@
 
 #include "utils/code_utils.h"
 
-// Macro to append content to end of the log string.
-
-#define LOG_PRINTF(...)                                                                   \
-    charsWritten = snprintf(&logString[offset], sizeof(logString) - offset, __VA_ARGS__); \
-    otEXPECT_ACTION(charsWritten >= 0, logString[offset] = 0);                            \
-    offset += (unsigned int)charsWritten;                                                 \
-    otEXPECT_ACTION(offset < sizeof(logString), logString[sizeof(logString) - 1] = 0)
-
 #if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED)
 OT_TOOL_WEAK void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
 {
     OT_UNUSED_VARIABLE(aLogLevel);
     OT_UNUSED_VARIABLE(aLogRegion);
 
-    char         logString[512];
-    unsigned int offset;
-    int          charsWritten;
-    va_list      args;
+    char    logString[512];
+    int     offset;
+    va_list args;
 
-    offset = 0;
-
-    LOG_PRINTF("[%d] ", gNodeId);
+    offset = snprintf(logString, sizeof(logString), "[%d]", gNodeId);
 
     va_start(args, aFormat);
-    charsWritten = vsnprintf(&logString[offset], sizeof(logString) - offset, aFormat, args);
+    vsnprintf(&logString[offset], sizeof(logString) - (uint16_t)offset, aFormat, args);
     va_end(args);
 
-    otEXPECT_ACTION(charsWritten >= 0, logString[offset] = 0);
-
-exit:
     syslog(LOG_CRIT, "%s", logString);
 }
-
-#endif // #if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED)
+#endif
diff --git a/examples/platforms/simulation/openthread-core-simulation-config.h b/examples/platforms/simulation/openthread-core-simulation-config.h
index 6657131..879f069 100644
--- a/examples/platforms/simulation/openthread-core-simulation-config.h
+++ b/examples/platforms/simulation/openthread-core-simulation-config.h
@@ -200,6 +200,16 @@
 #endif
 
 /**
+ * @def OPENTHREAD_CONFIG_MLE_MAX_CHILDREN
+ *
+ * The maximum number of children.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MLE_MAX_CHILDREN
+#define OPENTHREAD_CONFIG_MLE_MAX_CHILDREN 128
+#endif
+
+/**
  * @def OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
  *
  * Define as 1 for a child to inform its previous parent when it attaches to a new parent.
diff --git a/examples/platforms/simulation/platform-simulation.h b/examples/platforms/simulation/platform-simulation.h
index b0abf63..9379421 100644
--- a/examples/platforms/simulation/platform-simulation.h
+++ b/examples/platforms/simulation/platform-simulation.h
@@ -161,12 +161,13 @@
 /**
  * This function updates the file descriptor sets with file descriptors used by the radio driver.
  *
- * @param[inout]  aReadFdSet   A pointer to the read file descriptors.
- * @param[inout]  aWriteFdSet  A pointer to the write file descriptors.
- * @param[inout]  aMaxFd       A pointer to the max file descriptor.
+ * @param[in,out]  aReadFdSet   A pointer to the read file descriptors.
+ * @param[in,out]  aWriteFdSet  A pointer to the write file descriptors.
+ * @param[in,out]  aTimeout     A pointer to the timeout.
+ * @param[in,out]  aMaxFd       A pointer to the max file descriptor.
  *
  */
-void platformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd);
+void platformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, struct timeval *aTimeout, int *aMaxFd);
 
 /**
  * This function performs radio driver processing.
@@ -187,9 +188,9 @@
 /**
  * This function updates the file descriptor sets with file descriptors used by the UART driver.
  *
- * @param[inout]  aReadFdSet   A pointer to the read file descriptors.
- * @param[inout]  aWriteFdSet  A pointer to the write file descriptors.
- * @param[inout]  aMaxFd       A pointer to the max file descriptor.
+ * @param[in,out]  aReadFdSet   A pointer to the read file descriptors.
+ * @param[in,out]  aWriteFdSet  A pointer to the write file descriptors.
+ * @param[in,out]  aMaxFd       A pointer to the max file descriptor.
  *
  */
 void platformUartUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSet, int *aMaxFd);
@@ -250,10 +251,10 @@
 /**
  * This function updates the file descriptor sets with file descriptors used by the TREL.
  *
- * @param[inout]  aReadFdSet   A pointer to the read file descriptors.
- * @param[inout]  aWriteFdSet  A pointer to the write file descriptors.
- * @param[inout]  aTimeout     A pointer to the timeout.
- * @param[inout]  aMaxFd       A pointer to the max file descriptor.
+ * @param[in,out]  aReadFdSet   A pointer to the read file descriptors.
+ * @param[in,out]  aWriteFdSet  A pointer to the write file descriptors.
+ * @param[in,out]  aTimeout     A pointer to the timeout.
+ * @param[in,out]  aMaxFd       A pointer to the max file descriptor.
  *
  */
 void platformTrelUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, struct timeval *aTimeout, int *aMaxFd);
diff --git a/examples/platforms/simulation/radio.c b/examples/platforms/simulation/radio.c
index 2faaa2f..2b627c2 100644
--- a/examples/platforms/simulation/radio.c
+++ b/examples/platforms/simulation/radio.c
@@ -29,6 +29,7 @@
 #include "platform-simulation.h"
 
 #include <errno.h>
+#include <sys/time.h>
 
 #include <openthread/dataset.h>
 #include <openthread/link.h>
@@ -47,6 +48,9 @@
 // The IPv4 group for receiving packets of radio simulation
 #define OT_RADIO_GROUP "224.0.0.116"
 
+#define MS_PER_S 1000
+#define US_PER_MS 1000
+
 enum
 {
     IEEE802154_ACK_LENGTH = 5,
@@ -75,6 +79,10 @@
 static uint16_t sPort       = 0;
 #endif
 
+static int8_t   sEnergyScanResult  = OT_RADIO_RSSI_INVALID;
+static bool     sEnergyScanning    = false;
+static uint32_t sEnergyScanEndTime = 0;
+
 enum
 {
     SIM_RADIO_CHANNEL_MIN = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN,
@@ -156,6 +164,13 @@
 static otMacKeyMaterial sNextKey;
 static otRadioKeyType   sKeyType;
 
+static int8_t GetRssi(uint16_t aChannel);
+
+static bool IsTimeAfterOrEqual(uint32_t aTimeA, uint32_t aTimeB)
+{
+    return (aTimeA - aTimeB) < (1U << 31);
+}
+
 static void ReverseExtAddress(otExtAddress *aReversed, const otExtAddress *aOrigin)
 {
     for (size_t i = 0; i < sizeof(*aReversed); i++)
@@ -493,20 +508,23 @@
 int8_t otPlatRadioGetRssi(otInstance *aInstance)
 {
     OT_UNUSED_VARIABLE(aInstance);
-
     assert(aInstance != NULL);
 
-    int8_t   rssi    = SIM_LOW_RSSI_SAMPLE;
-    uint8_t  channel = sReceiveFrame.mChannel;
+    return GetRssi(sReceiveFrame.mChannel);
+}
+
+static int8_t GetRssi(uint16_t aChannel)
+{
+    int8_t   rssi = SIM_LOW_RSSI_SAMPLE;
     uint32_t probabilityThreshold;
 
-    otEXPECT((SIM_RADIO_CHANNEL_MIN <= channel) && channel <= (SIM_RADIO_CHANNEL_MAX));
+    otEXPECT((SIM_RADIO_CHANNEL_MIN <= aChannel) && aChannel <= (SIM_RADIO_CHANNEL_MAX));
 
     // To emulate a simple interference model, we return either a high or
     // a low  RSSI value with a fixed probability per each channel. The
     // probability is increased per channel by a constant.
 
-    probabilityThreshold = (channel - SIM_RADIO_CHANNEL_MIN) * SIM_HIGH_RSSI_PROB_INC_PER_CHANNEL;
+    probabilityThreshold = (aChannel - SIM_RADIO_CHANNEL_MIN) * SIM_HIGH_RSSI_PROB_INC_PER_CHANNEL;
 
     if (otRandomNonCryptoGetUint16() < (probabilityThreshold * 0xffff / 100))
     {
@@ -736,7 +754,7 @@
     radioReceive(aInstance);
 }
 #else
-void platformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd)
+void platformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, struct timeval *aTimeout, int *aMaxFd)
 {
     if (aReadFdSet != NULL && (sState != OT_RADIO_STATE_TRANSMIT || sTxWait))
     {
@@ -757,6 +775,25 @@
             *aMaxFd = sTxFd;
         }
     }
+
+    if (sEnergyScanning)
+    {
+        struct timeval tv  = {0, 0};
+        uint32_t       now = otPlatAlarmMilliGetNow();
+
+        if (IsTimeAfterOrEqual(sEnergyScanEndTime, now))
+        {
+            uint32_t remaining = sEnergyScanEndTime - now;
+
+            tv.tv_sec  = remaining / MS_PER_S;
+            tv.tv_usec = (remaining % MS_PER_S) * US_PER_MS;
+        }
+
+        if (timercmp(&tv, aTimeout, <))
+        {
+            *aTimeout = tv;
+        }
+    }
 }
 
 // no need to close in virtual time mode.
@@ -811,11 +848,16 @@
         }
     }
 #endif
-
     if (platformRadioIsTransmitPending())
     {
         radioSendMessage(aInstance);
     }
+
+    if (sEnergyScanning && IsTimeAfterOrEqual(otPlatAlarmMilliGetNow(), sEnergyScanEndTime))
+    {
+        sEnergyScanning = false;
+        otPlatRadioEnergyScanDone(aInstance, sEnergyScanResult);
+    }
 }
 
 void radioTransmit(struct RadioMessage *aMessage, const struct otRadioFrame *aFrame)
@@ -982,13 +1024,22 @@
 {
     OT_UNUSED_VARIABLE(aInstance);
     OT_UNUSED_VARIABLE(aScanChannel);
-    OT_UNUSED_VARIABLE(aScanDuration);
+
+    otError error = OT_ERROR_NONE;
 
     assert(aInstance != NULL);
     assert(aScanChannel >= SIM_RADIO_CHANNEL_MIN && aScanChannel <= SIM_RADIO_CHANNEL_MAX);
     assert(aScanDuration > 0);
 
-    return OT_ERROR_NOT_IMPLEMENTED;
+    otEXPECT_ACTION((gRadioCaps & OT_RADIO_CAPS_ENERGY_SCAN), error = OT_ERROR_NOT_IMPLEMENTED);
+    otEXPECT_ACTION(!sEnergyScanning, error = OT_ERROR_BUSY);
+
+    sEnergyScanResult  = GetRssi(aScanChannel);
+    sEnergyScanning    = true;
+    sEnergyScanEndTime = otPlatAlarmMilliGetNow() + aScanDuration;
+
+exit:
+    return error;
 }
 
 otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower)
diff --git a/examples/platforms/simulation/system.c b/examples/platforms/simulation/system.c
index 57bb30c..f9282a6 100644
--- a/examples/platforms/simulation/system.c
+++ b/examples/platforms/simulation/system.c
@@ -70,10 +70,11 @@
  */
 enum
 {
-    OT_SIM_OPT_HELP        = 'h',
-    OT_SIM_OPT_SLEEP_TO_TX = 't',
-    OT_SIM_OPT_TIME_SPEED  = 's',
-    OT_SIM_OPT_UNKNOWN     = '?',
+    OT_SIM_OPT_HELP               = 'h',
+    OT_SIM_OPT_ENABLE_ENERGY_SCAN = 'E',
+    OT_SIM_OPT_SLEEP_TO_TX        = 't',
+    OT_SIM_OPT_TIME_SPEED         = 's',
+    OT_SIM_OPT_UNKNOWN            = '?',
 };
 
 static void PrintUsage(const char *aProgramName, int aExitCode)
@@ -82,9 +83,10 @@
             "Syntax:\n"
             "    %s [Options] NodeId\n"
             "Options:\n"
-            "    -h --help              Display this usage information.\n"
-            "    -t --sleep-to-tx       Let radio support direct transition from sleep to TX with CSMA.\n"
-            "    -s --time-speed=val    Speed up the time in simulation.\n",
+            "    -h --help                  Display this usage information.\n"
+            "    -E --enable-energy-scan    Enable energy scan capability.\n"
+            "    -t --sleep-to-tx           Let radio support direct transition from sleep to TX with CSMA.\n"
+            "    -s --time-speed=val        Speed up the time in simulation.\n",
             aProgramName);
 
     exit(aExitCode);
@@ -97,6 +99,7 @@
 
     static const struct option long_options[] = {
         {"help", no_argument, 0, OT_SIM_OPT_HELP},
+        {"enable-energy-scan", no_argument, 0, OT_SIM_OPT_SLEEP_TO_TX},
         {"sleep-to-tx", no_argument, 0, OT_SIM_OPT_SLEEP_TO_TX},
         {"time-speed", required_argument, 0, OT_SIM_OPT_TIME_SPEED},
         {0, 0, 0, 0},
@@ -112,7 +115,7 @@
 
     while (true)
     {
-        int c = getopt_long(aArgCount, aArgVector, "hts:", long_options, NULL);
+        int c = getopt_long(aArgCount, aArgVector, "Ehts:", long_options, NULL);
 
         if (c == -1)
         {
@@ -127,6 +130,9 @@
         case OT_SIM_OPT_HELP:
             PrintUsage(aArgVector[0], EXIT_SUCCESS);
             break;
+        case OT_SIM_OPT_ENABLE_ENERGY_SCAN:
+            gRadioCaps |= OT_RADIO_CAPS_ENERGY_SCAN;
+            break;
         case OT_SIM_OPT_SLEEP_TO_TX:
             gRadioCaps |= OT_RADIO_CAPS_SLEEP_TO_TX;
             break;
@@ -197,8 +203,8 @@
     FD_ZERO(&error_fds);
 
     platformUartUpdateFdSet(&read_fds, &write_fds, &error_fds, &max_fd);
-    platformRadioUpdateFdSet(&read_fds, &write_fds, &max_fd);
     platformAlarmUpdateTimeout(&timeout);
+    platformRadioUpdateFdSet(&read_fds, &write_fds, &timeout, &max_fd);
 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
     platformTrelUpdateFdSet(&read_fds, &write_fds, &timeout, &max_fd);
 #endif
diff --git a/examples/platforms/simulation/trel.c b/examples/platforms/simulation/trel.c
index 8e53962..20c6b30 100644
--- a/examples/platforms/simulation/trel.c
+++ b/examples/platforms/simulation/trel.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2019, The OpenThread Authors.
+ *  Copyright (c) 2019-21, The OpenThread Authors.
  *  All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@
 #include "platform-simulation.h"
 
 #include <openthread/random_noncrypto.h>
-#include <openthread/platform/trel-udp6.h>
+#include <openthread/platform/trel.h>
 
 #include "utils/code_utils.h"
 
@@ -44,38 +44,39 @@
 
 #define TREL_MAX_PACKET_SIZE 1800
 
-#define TREL_MAX_PENDING_TX 5
+#define TREL_MAX_PENDING_TX 64
 
-OT_TOOL_PACKED_BEGIN
-struct PacketHeader
+#define TREL_MAX_SERVICE_TXT_DATA_LEN 128
+
+typedef enum MessageType
 {
-    otIp6Address mSrcIp6Address;
-    otIp6Address mDestIp6Address;
-    uint16_t     mPort;
-} OT_TOOL_PACKED_END;
+    TREL_DATA_MESSAGE,
+    TREL_DNSSD_BROWSE_MESSAGE,
+    TREL_DNSSD_ADD_SERVICE_MESSAGE,
+    TREL_DNSSD_REMOVE_SERVICE_MESSAGE,
+} MessageType;
 
-typedef struct PacketHeader PacketHeader;
-
-OT_TOOL_PACKED_BEGIN
-struct Packet
+typedef struct Message
 {
-    PacketHeader mHeader;
-    uint8_t      mPayload[TREL_MAX_PACKET_SIZE];
-    uint16_t     mLength; // Total packet length including the header.
-} OT_TOOL_PACKED_END;
-
-typedef struct Packet Packet;
+    MessageType mType;
+    otSockAddr  mSockAddr;                   // Destination (when TREL_DATA_MESSAGE), or peer addr (when DNS-SD service)
+    uint16_t    mDataLength;                 // mData length
+    uint8_t     mData[TREL_MAX_PACKET_SIZE]; // TREL UDP packet (when TREL_DATA_MESSAGE), or service TXT data.
+} Message;
 
 static uint8_t sNumPendingTx = 0;
-static Packet  sPendingTx[TREL_MAX_PENDING_TX];
+static Message sPendingTx[TREL_MAX_PENDING_TX];
 
-static int          sTxFd       = -1;
-static int          sRxFd       = -1;
-static uint16_t     sPortOffset = 0;
-static bool         sEnabled    = true;
-static otIp6Address sUnicastAddress;
-static otIp6Address sMulticastAddress;
-static uint16_t     sUdpPort;
+static int      sTxFd       = -1;
+static int      sRxFd       = -1;
+static uint16_t sPortOffset = 0;
+static bool     sEnabled    = false;
+static uint16_t sUdpPort;
+
+static bool     sServiceRegistered = false;
+static uint16_t sServicePort;
+static uint8_t  sServiceTxtLength;
+static char     sServiceTxtData[TREL_MAX_SERVICE_TXT_DATA_LEN];
 
 #if DEBUG_LOG
 static void dumpBuffer(const void *aBuffer, uint16_t aLength)
@@ -91,19 +92,30 @@
     fprintf(stderr, "]");
 }
 
-static const char *ip6AddrToString(const void *aAddress)
+static const char *messageTypeToString(MessageType aType)
 {
-    static char string[INET6_ADDRSTRLEN];
+    const char *str = "unknown";
 
-    return inet_ntop(AF_INET6, aAddress, string, sizeof(string));
+    switch (aType)
+    {
+    case TREL_DATA_MESSAGE:
+        str = "data";
+        break;
+    case TREL_DNSSD_BROWSE_MESSAGE:
+        str = "browse";
+        break;
+    case TREL_DNSSD_ADD_SERVICE_MESSAGE:
+        str = "add-service";
+        break;
+    case TREL_DNSSD_REMOVE_SERVICE_MESSAGE:
+        str = "remove-service";
+        break;
+    }
+
+    return str;
 }
 #endif
 
-static bool ip6AddrsAreEqual(const otIp6Address *aFirst, const otIp6Address *aSecond)
-{
-    return (memcmp(aFirst, aSecond, sizeof(otIp6Address)) == 0);
-}
-
 static void initFds(void)
 {
     int                fd;
@@ -115,8 +127,9 @@
 
     otEXPECT_ACTION((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1, perror("socket(sTxFd)"));
 
+    sUdpPort                 = (uint16_t)(TREL_SIM_PORT + sPortOffset + gNodeId);
     sockaddr.sin_family      = AF_INET;
-    sockaddr.sin_port        = htons((uint16_t)(TREL_SIM_PORT + sPortOffset + gNodeId));
+    sockaddr.sin_port        = htons(sUdpPort);
     sockaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
 
     otEXPECT_ACTION(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &sockaddr.sin_addr, sizeof(sockaddr.sin_addr)) != -1,
@@ -177,7 +190,12 @@
     }
 }
 
-static void sendPendingTxPackets(void)
+static uint16_t getMessageSize(const Message *aMessage)
+{
+    return (uint16_t)(&aMessage->mData[aMessage->mDataLength] - (const uint8_t *)aMessage);
+}
+
+static void sendPendingTxMessages(void)
 {
     ssize_t            rval;
     struct sockaddr_in sockaddr;
@@ -190,13 +208,14 @@
 
     for (uint8_t i = 0; i < sNumPendingTx; i++)
     {
+        uint16_t size = getMessageSize(&sPendingTx[i]);
+
 #if DEBUG_LOG
-        fprintf(stderr, "\n[trel-udp] Sending packet (num:%d)", i);
-        dumpBuffer(&sPendingTx[i], sPendingTx[i].mLength);
-        fprintf(stderr, "\n");
+        fprintf(stderr, "\r\n[trel-sim] Sending message (num:%d, type:%s, port:%u)\r\n", i,
+                messageTypeToString(sPendingTx[i].mType), sPendingTx[i].mSockAddr.mPort);
 #endif
 
-        rval = sendto(sTxFd, &sPendingTx[i], sPendingTx[i].mLength, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
+        rval = sendto(sTxFd, &sPendingTx[i], size, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
 
         if (rval < 0)
         {
@@ -208,83 +227,167 @@
     sNumPendingTx = 0;
 }
 
+static void sendBrowseMessage(void)
+{
+    Message *message;
+
+    assert(sNumPendingTx < TREL_MAX_PENDING_TX);
+    message = &sPendingTx[sNumPendingTx++];
+
+    message->mType       = TREL_DNSSD_BROWSE_MESSAGE;
+    message->mDataLength = 0;
+
+#if DEBUG_LOG
+    fprintf(stderr, "\r\n[trel-sim] sendBrowseMessage()\r\n");
+#endif
+}
+
+static void sendServiceMessage(MessageType aType)
+{
+    Message *message;
+
+    assert((aType == TREL_DNSSD_ADD_SERVICE_MESSAGE) || (aType == TREL_DNSSD_REMOVE_SERVICE_MESSAGE));
+
+    assert(sNumPendingTx < TREL_MAX_PENDING_TX);
+    message = &sPendingTx[sNumPendingTx++];
+
+    message->mType = aType;
+    memset(&message->mSockAddr, 0, sizeof(otSockAddr));
+    message->mSockAddr.mPort = sServicePort;
+    message->mDataLength     = sServiceTxtLength;
+    memcpy(message->mData, sServiceTxtData, sServiceTxtLength);
+
+#if DEBUG_LOG
+    fprintf(stderr, "\r\n[trel-sim] sendServiceMessage(%s): service-port:%u, txt-len:%u\r\n",
+            aType == TREL_DNSSD_ADD_SERVICE_MESSAGE ? "add" : "remove", sServicePort, sServiceTxtLength);
+#endif
+}
+
+static void processMessage(otInstance *aInstance, Message *aMessage, uint16_t aLength)
+{
+    otPlatTrelPeerInfo peerInfo;
+
+#if DEBUG_LOG
+    fprintf(stderr, "\r\n[trel-sim] processMessage(len:%u, type:%s, port:%u)\r\n", aLength,
+            messageTypeToString(aMessage->mType), aMessage->mSockAddr.mPort);
+#endif
+
+    otEXPECT(aLength > 0);
+    otEXPECT(getMessageSize(aMessage) == aLength);
+
+    switch (aMessage->mType)
+    {
+    case TREL_DATA_MESSAGE:
+        otEXPECT(aMessage->mSockAddr.mPort == sUdpPort);
+        otPlatTrelHandleReceived(aInstance, aMessage->mData, aMessage->mDataLength);
+        break;
+
+    case TREL_DNSSD_BROWSE_MESSAGE:
+        sendServiceMessage(TREL_DNSSD_ADD_SERVICE_MESSAGE);
+        break;
+
+    case TREL_DNSSD_ADD_SERVICE_MESSAGE:
+    case TREL_DNSSD_REMOVE_SERVICE_MESSAGE:
+        memset(&peerInfo, 0, sizeof(peerInfo));
+        peerInfo.mRemoved   = (aMessage->mType == TREL_DNSSD_REMOVE_SERVICE_MESSAGE);
+        peerInfo.mTxtData   = aMessage->mData;
+        peerInfo.mTxtLength = (uint8_t)(aMessage->mDataLength);
+        peerInfo.mSockAddr  = aMessage->mSockAddr;
+        otPlatTrelHandleDiscoveredPeerInfo(aInstance, &peerInfo);
+        break;
+    }
+
+exit:
+    return;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 // otPlatTrel
 
-void otPlatTrelUdp6Init(otInstance *aInstance, const otIp6Address *aUnicastAddress, uint16_t aUdpPort)
+void otPlatTrelEnable(otInstance *aInstance, uint16_t *aUdpPort)
 {
     OT_UNUSED_VARIABLE(aInstance);
 
-    sUnicastAddress = *aUnicastAddress;
-    sUdpPort        = aUdpPort;
+    *aUdpPort = sUdpPort;
 
 #if DEBUG_LOG
-    fprintf(stderr, "\n[trel-udp6] otPlatTrelUdp6Init(aUnicastAddress:%s, aUdpPort:%d)\n",
-            ip6AddrToString(aUnicastAddress), aUdpPort);
+    fprintf(stderr, "\r\n[trel-sim] otPlatTrelEnable() *aUdpPort=%u\r\n", *aUdpPort);
 #endif
-}
-
-void otPlatTrelUdp6UpdateAddress(otInstance *aInstance, const otIp6Address *aUnicastAddress)
-{
-    OT_UNUSED_VARIABLE(aInstance);
-
-    sUnicastAddress = *aUnicastAddress;
-
-#if DEBUG_LOG
-    fprintf(stderr, "\n[trel-udp6] otPlatTrelUdp6UpdateAddress(aUnicastAddress:%s)\n",
-            ip6AddrToString(aUnicastAddress));
-#endif
-}
-
-void otPlatTrelUdp6SubscribeMulticastAddress(otInstance *aInstance, const otIp6Address *aMulticastAddress)
-{
-    OT_UNUSED_VARIABLE(aInstance);
-
-    sMulticastAddress = *aMulticastAddress;
-
-#if DEBUG_LOG
-    fprintf(stderr, "\n[trel-udp6] otPlatTrelUdp6SubscribeMulticastAddress(aMulticastAddress:%s)\n",
-            ip6AddrToString(aMulticastAddress));
-#endif
-}
-
-otError otPlatTrelUdp6SendTo(otInstance *        aInstance,
-                             const uint8_t *     aBuffer,
-                             uint16_t            aLength,
-                             const otIp6Address *aDestAddress)
-{
-    otError error = OT_ERROR_NONE;
-    Packet *packet;
-
-    OT_UNUSED_VARIABLE(aInstance);
-
-    otEXPECT(sEnabled);
-    otEXPECT_ACTION(sNumPendingTx < TREL_MAX_PENDING_TX, error = OT_ERROR_ABORT);
-    otEXPECT_ACTION(aLength <= TREL_MAX_PACKET_SIZE, error = OT_ERROR_ABORT);
-
-    packet                          = &sPendingTx[sNumPendingTx++];
-    packet->mHeader.mSrcIp6Address  = sUnicastAddress;
-    packet->mHeader.mDestIp6Address = *aDestAddress;
-    packet->mHeader.mPort           = sUdpPort;
-    packet->mLength                 = aLength + sizeof(PacketHeader);
-    memcpy(packet->mPayload, aBuffer, aLength);
-
-exit:
-    return error;
-}
-
-otError otPlatTrelUdp6SetTestMode(otInstance *aInstance, bool aEnable)
-{
-    OT_UNUSED_VARIABLE(aInstance);
-
-    sEnabled = aEnable;
 
     if (!sEnabled)
     {
-        sNumPendingTx = 0;
+        sEnabled = true;
+        sendBrowseMessage();
+    }
+}
+
+void otPlatTrelDisable(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+#if DEBUG_LOG
+    fprintf(stderr, "\r\n[trel-sim] otPlatTrelDisable()\r\n");
+#endif
+
+    if (sEnabled)
+    {
+        sEnabled = false;
+
+        if (sServiceRegistered)
+        {
+            sendServiceMessage(TREL_DNSSD_REMOVE_SERVICE_MESSAGE);
+            sServiceRegistered = false;
+        }
+    }
+}
+
+void otPlatTrelRegisterService(otInstance *aInstance, uint16_t aPort, const uint8_t *aTxtData, uint8_t aTxtLength)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    assert(aTxtLength <= TREL_MAX_SERVICE_TXT_DATA_LEN);
+
+    if (sServiceRegistered)
+    {
+        sendServiceMessage(TREL_DNSSD_REMOVE_SERVICE_MESSAGE);
     }
 
-    return OT_ERROR_NONE;
+    sServiceRegistered = true;
+    sServicePort       = aPort;
+    sServiceTxtLength  = aTxtLength;
+    memcpy(sServiceTxtData, aTxtData, aTxtLength);
+
+    sendServiceMessage(TREL_DNSSD_ADD_SERVICE_MESSAGE);
+
+#if DEBUG_LOG
+    fprintf(stderr, "\r\n[trel-sim] otPlatTrelRegisterService(aPort:%d, aTxtData:", aPort);
+    dumpBuffer(aTxtData, aTxtLength);
+    fprintf(stderr, ")\r\n");
+#endif
+}
+
+void otPlatTrelSend(otInstance *      aInstance,
+                    const uint8_t *   aUdpPayload,
+                    uint16_t          aUdpPayloadLen,
+                    const otSockAddr *aDestSockAddr)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    Message *message;
+
+    assert(sNumPendingTx < TREL_MAX_PENDING_TX);
+    assert(aUdpPayloadLen <= TREL_MAX_PACKET_SIZE);
+
+    message = &sPendingTx[sNumPendingTx++];
+
+    message->mType       = TREL_DATA_MESSAGE;
+    message->mSockAddr   = *aDestSockAddr;
+    message->mDataLength = aUdpPayloadLen;
+    memcpy(message->mData, aUdpPayload, aUdpPayloadLen);
+
+#if DEBUG_LOG
+    fprintf(stderr, "\r\n[trel-sim] otPlatTrelSend(len:%u, port:%u)\r\n", aUdpPayloadLen, aDestSockAddr->mPort);
+#endif
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -304,7 +407,7 @@
 
         if (*endptr != '\0')
         {
-            fprintf(stderr, "\nInvalid PORT_OFFSET: %s\n", str);
+            fprintf(stderr, "\r\nInvalid PORT_OFFSET: %s\r\n", str);
             exit(EXIT_FAILURE);
         }
 
@@ -351,15 +454,17 @@
 {
     if (FD_ISSET(sTxFd, aWriteFdSet) && (sNumPendingTx > 0))
     {
-        sendPendingTxPackets();
+        sendPendingTxMessages();
     }
 
     if (FD_ISSET(sRxFd, aReadFdSet))
     {
-        Packet  rxPacket;
+        Message message;
         ssize_t rval;
 
-        rval = recvfrom(sRxFd, (char *)&rxPacket, sizeof(rxPacket) - sizeof(rxPacket.mLength), 0, NULL, NULL);
+        message.mDataLength = 0;
+
+        rval = recvfrom(sRxFd, (char *)&message, sizeof(message), 0, NULL, NULL);
 
         if (rval < 0)
         {
@@ -367,27 +472,14 @@
             exit(EXIT_FAILURE);
         }
 
-        rxPacket.mLength = (uint16_t)(rval);
-
-#if DEBUG_LOG
-        fprintf(stderr, "\n[trel-udp6] recvdPacket()");
-        fprintf(stderr, " src:%s", ip6AddrToString(&rxPacket.mHeader.mSrcIp6Address));
-        fprintf(stderr, " dst:%s", ip6AddrToString(&rxPacket.mHeader.mDestIp6Address));
-        fprintf(stderr, " port:%u ", rxPacket.mHeader.mPort);
-        dumpBuffer(&rxPacket, rxPacket.mLength);
-        fprintf(stderr, "\n");
-#endif
-        if (sEnabled && (rxPacket.mHeader.mPort == sUdpPort) &&
-            (ip6AddrsAreEqual(&rxPacket.mHeader.mDestIp6Address, &sUnicastAddress) ||
-             ip6AddrsAreEqual(&rxPacket.mHeader.mDestIp6Address, &sMulticastAddress)))
-        {
-            otPlatTrelUdp6HandleReceived(aInstance, rxPacket.mPayload, rxPacket.mLength - sizeof(PacketHeader));
-        }
+        processMessage(aInstance, &message, (uint16_t)(rval));
     }
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+
 // This is added for RCP build to be built ok
-OT_TOOL_WEAK void otPlatTrelUdp6HandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength)
+OT_TOOL_WEAK void otPlatTrelHandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength)
 {
     OT_UNUSED_VARIABLE(aInstance);
     OT_UNUSED_VARIABLE(aBuffer);
@@ -396,4 +488,12 @@
     assert(false);
 }
 
+OT_TOOL_WEAK void otPlatTrelHandleDiscoveredPeerInfo(otInstance *aInstance, const otPlatTrelPeerInfo *aInfo)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+    OT_UNUSED_VARIABLE(aInfo);
+
+    assert(false);
+}
+
 #endif // OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
diff --git a/examples/platforms/utils/link_metrics.cpp b/examples/platforms/utils/link_metrics.cpp
index 88ed632..a09fab4 100644
--- a/examples/platforms/utils/link_metrics.cpp
+++ b/examples/platforms/utils/link_metrics.cpp
@@ -153,7 +153,7 @@
 
 enum
 {
-    kMaxEnhAckProbingInitiator = 10,
+    kMaxEnhAckProbingInitiator = OPENTHREAD_CONFIG_MLE_LINK_METRICS_MAX_SERIES_SUPPORTED,
 };
 
 typedef Pool<LinkMetricsDataInfo, kMaxEnhAckProbingInitiator> LinkMetricsDataInfoPool;
diff --git a/examples/platforms/utils/logging_rtt.c b/examples/platforms/utils/logging_rtt.c
index 3372cab..e58db65 100644
--- a/examples/platforms/utils/logging_rtt.c
+++ b/examples/platforms/utils/logging_rtt.c
@@ -93,8 +93,8 @@
 /**
  * Function for printing actual timestamp.
  *
- * @param[inout]  aLogString Pointer to the log buffer.
- * @param[in]     aMaxSize   Maximum size of the log buffer.
+ * @param[in,out]  aLogString Pointer to the log buffer.
+ * @param[in]      aMaxSize   Maximum size of the log buffer.
  *
  * @returns  Number of bytes successfully written to the log buffer.
  */
@@ -108,9 +108,9 @@
 /**
  * Function for printing log level.
  *
- * @param[inout]  aLogString  Pointer to log buffer.
- * @param[in]     aMaxSize    Maximum size of log buffer.
- * @param[in]     aLogLevel   Log level.
+ * @param[in,out]  aLogString  Pointer to log buffer.
+ * @param[in]      aMaxSize    Maximum size of log buffer.
+ * @param[in]      aLogLevel   Log level.
  *
  * @returns  Number of bytes successfully written to the log buffer.
  */
diff --git a/examples/platforms/utils/mac_frame.h b/examples/platforms/utils/mac_frame.h
index 1d6c39a..8f0c679 100644
--- a/examples/platforms/utils/mac_frame.h
+++ b/examples/platforms/utils/mac_frame.h
@@ -228,7 +228,7 @@
 /**
  * Set CSL IE content into the frame.
  *
- * @param[inout]    aFrame         A pointer to the frame to be modified.
+ * @param[in,out]   aFrame         A pointer to the frame to be modified.
  * @param[in]       aCslPeriod     CSL Period in CSL IE.
  * @param[in]       aCslPhase      CSL Phase in CSL IE.
  *
@@ -270,7 +270,7 @@
 /**
  * Set key ID to @p aFrame with key ID mode 1.
  *
- * @param[inout]    aFrame     A pointer to the frame to be modified.
+ * @param[in,out]   aFrame     A pointer to the frame to be modified.
  * @param[in]       aKeyId     Key ID to be set to the frame.
  *
  */
@@ -289,7 +289,7 @@
 /**
  * Set frame counter to @p aFrame.
  *
- * @param[inout]    aFrame         A pointer to the frame to be modified.
+ * @param[in,out]   aFrame         A pointer to the frame to be modified.
  * @param[in]       aFrameCounter  Frame counter to be set to the frame.
  *
  */
diff --git a/examples/platforms/utils/otns_utils.cpp b/examples/platforms/utils/otns_utils.cpp
index b2875e1..e343503 100644
--- a/examples/platforms/utils/otns_utils.cpp
+++ b/examples/platforms/utils/otns_utils.cpp
@@ -31,7 +31,9 @@
 #include <openthread/platform/otns.h>
 #include <openthread/platform/toolchain.h>
 
-#include "common/logging.hpp"
+#include "common/log.hpp"
+
+using namespace ot;
 
 /*
  * Implementation note:
@@ -43,7 +45,7 @@
 OT_TOOL_WEAK
 void otPlatOtnsStatus(const char *aStatus)
 {
-    otLogOtns("[OTNS] %s", aStatus);
+    LogAlways("[OTNS] %s", aStatus);
 }
 
 #endif // OPENTHREAD_CONFIG_OTNS_ENABLE
diff --git a/examples/platforms/utils/settings_ram.c b/examples/platforms/utils/settings_ram.c
index bd20c00..fd4abd9 100644
--- a/examples/platforms/utils/settings_ram.c
+++ b/examples/platforms/utils/settings_ram.c
@@ -57,9 +57,11 @@
 } OT_TOOL_PACKED_END;
 
 // settings API
-void otPlatSettingsInit(otInstance *aInstance)
+void otPlatSettingsInit(otInstance *aInstance, const uint16_t *aSensitiveKeys, uint16_t aSensitiveKeysLength)
 {
     OT_UNUSED_VARIABLE(aInstance);
+    OT_UNUSED_VARIABLE(aSensitiveKeys);
+    OT_UNUSED_VARIABLE(aSensitiveKeysLength);
 
     sSettingsBufLength = 0;
 }
@@ -229,7 +231,7 @@
 
 void otPlatSettingsWipe(otInstance *aInstance)
 {
-    otPlatSettingsInit(aInstance);
+    otPlatSettingsInit(aInstance, NULL, 0);
 }
 
 #endif // OPENTHREAD_SETTINGS_RAM
diff --git a/examples/platforms/utils/soft_source_match_table.c b/examples/platforms/utils/soft_source_match_table.c
index 67fbdca..458d1b5 100644
--- a/examples/platforms/utils/soft_source_match_table.c
+++ b/examples/platforms/utils/soft_source_match_table.c
@@ -39,7 +39,8 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "common/logging.hpp"
+#include <openthread/logging.h>
+
 #include "utils/code_utils.h"
 
 #if RADIO_CONFIG_SRC_MATCH_SHORT_ENTRY_NUM || RADIO_CONFIG_SRC_MATCH_EXT_ENTRY_NUM
diff --git a/include/Makefile.am b/include/Makefile.am
index 2d7273a..722775d 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -39,6 +39,7 @@
     openthread/backbone_router_ftd.h      \
     openthread/border_agent.h             \
     openthread/border_router.h            \
+    openthread/border_routing.h           \
     openthread/channel_manager.h          \
     openthread/channel_monitor.h          \
     openthread/child_supervision.h        \
@@ -55,7 +56,6 @@
     openthread/dns.h                      \
     openthread/dns_client.h               \
     openthread/dnssd_server.h             \
-    openthread/entropy.h                  \
     openthread/error.h                    \
     openthread/heap.h                     \
     openthread/history_tracker.h          \
@@ -70,6 +70,7 @@
     openthread/logging.h                  \
     openthread/message.h                  \
     openthread/multi_radio.h              \
+    openthread/nat64.h                    \
     openthread/ncp.h                      \
     openthread/netdata.h                  \
     openthread/netdata_publisher.h        \
@@ -85,8 +86,10 @@
     openthread/srp_server.h               \
     openthread/tasklet.h                  \
     openthread/tcp.h                      \
+    openthread/tcp_ext.h                  \
     openthread/thread.h                   \
     openthread/thread_ftd.h               \
+    openthread/trel.h                     \
     openthread/udp.h                      \
     $(NULL)
 
@@ -99,6 +102,7 @@
     openthread/platform/crypto.h          \
     openthread/platform/debug_uart.h      \
     openthread/platform/diag.h            \
+    openthread/platform/dso_transport.h   \
     openthread/platform/entropy.h         \
     openthread/platform/flash.h           \
     openthread/platform/infra_if.h        \
@@ -112,7 +116,7 @@
     openthread/platform/spi-slave.h       \
     openthread/platform/time.h            \
     openthread/platform/toolchain.h       \
-    openthread/platform/trel-udp6.h       \
+    openthread/platform/trel.h            \
     openthread/platform/udp.h             \
     $(NULL)
 
diff --git a/include/openthread-config-android.h b/include/openthread-config-android.h
deleted file mode 100644
index 9b07c81..0000000
--- a/include/openthread-config-android.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *  Copyright (c) 2018, The OpenThread Authors.
- *  All rights reserved.
- *
- *  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, 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.
- */
-
-#ifdef OPENTHREAD_CONFIG_ANDROID_VERSION_HEADER_ENABLE
-#include <openthread-config-android-version.h>
-#endif
-
-/* Define to 1 to enable the border agent feature. */
-#define OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE 1
-
-/* Define to 1 if you want to enable Border Router */
-#define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 1
-
-/* Define to 1 if you want to enable channel manager feature */
-#define OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE 0
-
-/* Define to 1 if you want to use channel monitor feature */
-#define OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE 0
-
-/* Define to 1 if you want to use child supervision feature */
-#define OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE 1
-
-/* Define to 1 to enable dtls support. */
-#define OPENTHREAD_CONFIG_DTLS_ENABLE 1
-
-/* Define to 1 if you want to use jam detection feature */
-#define OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE 1
-
-/* Define to 1 to enable the joiner role. */
-#define OPENTHREAD_CONFIG_JOINER_ENABLE 1
-
-/* Define to 1 if you want to use legacy network support */
-#define OPENTHREAD_CONFIG_LEGACY_ENABLE 1
-
-/* Define to 1 to enable the NCP HDLC interface. */
-#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1
-
-/* Define to 1 to enable posix platform. */
-#define OPENTHREAD_PLATFORM_POSIX 1
-
-/* Define to 1 if you want to enable Service */
-#define OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE 1
-
-/* OpenThread examples */
-#define OPENTHREAD_EXAMPLES none
diff --git a/include/openthread/BUILD.gn b/include/openthread/BUILD.gn
index 089c941..931c7ac 100644
--- a/include/openthread/BUILD.gn
+++ b/include/openthread/BUILD.gn
@@ -27,27 +27,10 @@
 
 import("../../etc/gn/openthread.gni")
 
-copy("copy_openthread_config_generic") {
-  sources = [ "../../etc/cmake/openthread-config-generic.h.in" ]
-  outputs = [ "${root_gen_dir}/include/{{source_name_part}}" ]
-}
-
-config("openthread_config_generic_config") {
-  include_dirs = [ "${root_gen_dir}/include" ]
-}
-
-source_set("openthread_config_generic") {
-  sources = [ "${root_gen_dir}/include/openthread-config-generic.h" ]
-  deps = [ ":copy_openthread_config_generic" ]
-  public_configs = [ ":openthread_config_generic_config" ]
-}
-
 source_set("openthread_config") {
   public = [ "config.h" ]
 
-  if (openthread_config_file == "") {
-    public_deps = [ ":openthread_config_generic" ]
-  } else {
+  if (openthread_config_file != "") {
     public_deps = openthread_config_deps
   }
 
@@ -60,6 +43,7 @@
     "backbone_router_ftd.h",
     "border_agent.h",
     "border_router.h",
+    "border_routing.h",
     "channel_manager.h",
     "channel_monitor.h",
     "child_supervision.h",
@@ -76,7 +60,6 @@
     "dns.h",
     "dns_client.h",
     "dnssd_server.h",
-    "entropy.h",
     "error.h",
     "heap.h",
     "history_tracker.h",
@@ -91,6 +74,7 @@
     "logging.h",
     "message.h",
     "multi_radio.h",
+    "nat64.h",
     "ncp.h",
     "netdata.h",
     "netdata_publisher.h",
@@ -102,6 +86,7 @@
     "platform/crypto.h",
     "platform/debug_uart.h",
     "platform/diag.h",
+    "platform/dso_transport.h",
     "platform/entropy.h",
     "platform/flash.h",
     "platform/infra_if.h",
@@ -115,7 +100,7 @@
     "platform/spi-slave.h",
     "platform/time.h",
     "platform/toolchain.h",
-    "platform/trel-udp6.h",
+    "platform/trel.h",
     "platform/udp.h",
     "random_crypto.h",
     "random_noncrypto.h",
@@ -126,8 +111,10 @@
     "srp_server.h",
     "tasklet.h",
     "tcp.h",
+    "tcp_ext.h",
     "thread.h",
     "thread_ftd.h",
+    "trel.h",
     "udp.h",
   ]
 
diff --git a/include/openthread/backbone_router_ftd.h b/include/openthread/backbone_router_ftd.h
index 741aade..a619687 100644
--- a/include/openthread/backbone_router_ftd.h
+++ b/include/openthread/backbone_router_ftd.h
@@ -291,12 +291,12 @@
 /**
  * This function gets the next Multicast Listener info (using an iterator).
  *
- * @param[in]     aInstance    A pointer to an OpenThread instance.
- * @param[inout]  aIterator    A pointer to the iterator. On success the iterator will be updated to point to next
- *                             Multicast Listener. To get the first entry the iterator should be set to
- *                             OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ITERATOR_INIT.
- * @param[out]    aListenerInfo  A pointer to an `otBackboneRouterMulticastListenerInfo` where information of next
- *                               Multicast Listener is placed (on success).
+ * @param[in]      aInstance      A pointer to an OpenThread instance.
+ * @param[in,out]  aIterator      A pointer to the iterator. On success the iterator will be updated to point to next
+ *                                Multicast Listener. To get the first entry the iterator should be set to
+ *                                OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ITERATOR_INIT.
+ * @param[out]     aListenerInfo  A pointer to an `otBackboneRouterMulticastListenerInfo` where information of next
+ *                                Multicast Listener is placed (on success).
  *
  * @retval OT_ERROR_NONE       Successfully found the next Multicast Listener info (@p aListenerInfo was successfully
  *                             updated).
@@ -351,12 +351,12 @@
  * Represents the Backbone Router ND Proxy info.
  *
  */
-struct otBackboneRouterNdProxyInfo
+typedef struct otBackboneRouterNdProxyInfo
 {
     otIp6InterfaceIdentifier *mMeshLocalIid;             ///< Mesh-local IID
     uint32_t                  mTimeSinceLastTransaction; ///< Time since last transaction (Seconds)
     uint16_t                  mRloc16;                   ///< RLOC16
-};
+} otBackboneRouterNdProxyInfo;
 
 /**
  * This method gets the Backbone Router ND Proxy info.
diff --git a/include/openthread/border_agent.h b/include/openthread/border_agent.h
index 0b267a8..83babfa 100644
--- a/include/openthread/border_agent.h
+++ b/include/openthread/border_agent.h
@@ -63,17 +63,17 @@
 } otBorderAgentState;
 
 /**
- * This function gets the state of Thread Border Agent role.
+ * Gets the #otBorderAgentState of the Thread Border Agent role.
  *
  * @param[in]  aInstance  A pointer to an OpenThread instance.
  *
- * @returns State of the Border Agent.
+ * @returns The current #otBorderAgentState of the Border Agent.
  *
  */
 otBorderAgentState otBorderAgentGetState(otInstance *aInstance);
 
 /**
- * This function gets the UDP port of Thread Border Agent service.
+ * Gets the UDP port of the Thread Border Agent service.
  *
  * @param[in]  aInstance  A pointer to an OpenThread instance.
  *
diff --git a/include/openthread/border_router.h b/include/openthread/border_router.h
index 7774727..fb7dab0 100644
--- a/include/openthread/border_router.h
+++ b/include/openthread/border_router.h
@@ -35,6 +35,7 @@
 #ifndef OPENTHREAD_BORDER_ROUTER_H_
 #define OPENTHREAD_BORDER_ROUTER_H_
 
+#include <openthread/border_routing.h>
 #include <openthread/ip6.h>
 #include <openthread/netdata.h>
 
@@ -53,78 +54,13 @@
  */
 
 /**
- * This method initializes the Border Routing Manager on given infrastructure interface.
- *
- * @note  This method MUST be called before any other otBorderRouting* APIs.
- *
- * @param[in]  aInstance          A pointer to an OpenThread instance.
- * @param[in]  aInfraIfIndex      The infrastructure interface index.
- * @param[in]  aInfraIfIsRunning  A boolean that indicates whether the infrastructure
- *                                interface is running.
- *
- * @retval  OT_ERROR_NONE           Successfully started the Border Routing Manager on given infrastructure.
- * @retval  OT_ERROR_INVALID_STATE  The Border Routing Manager has already been initialized.
- * @retval  OT_ERROR_INVALID_ARGS   The index of the infrastructure interface is not valid.
- * @retval  OT_ERROR_FAILED         Internal failure. Usually due to failure in generating random prefixes.
- *
- * @sa otPlatInfraIfStateChanged.
- *
- */
-otError otBorderRoutingInit(otInstance *aInstance, uint32_t aInfraIfIndex, bool aInfraIfIsRunning);
-
-/**
- * This method enables/disables the Border Routing Manager.
- *
- * @note  The Border Routing Manager is disabled by default.
- *
- * @param[in]  aInstance  A pointer to an OpenThread instance.
- * @param[in]  aEnabled   A boolean to enable/disable the routing manager.
- *
- * @retval  OT_ERROR_INVALID_STATE  The Border Routing Manager is not initialized yet.
- * @retval  OT_ERROR_NONE           Successfully enabled/disabled the Border Routing Manager.
- *
- */
-otError otBorderRoutingSetEnabled(otInstance *aInstance, bool aEnabled);
-
-/**
- * This method returns the off-mesh-routable (OMR) prefix.
- *
- * The randomly generated 64-bit prefix will be published
- * in the Thread network if there isn't already an OMR prefix.
- *
- * @param[in]   aInstance  A pointer to an OpenThread instance.
- * @param[out]  aPrefix    A pointer to where the prefix will be output to.
- *
- * @retval  OT_ERROR_INVALID_STATE  The Border Routing Manager is not initialized yet.
- * @retval  OT_ERROR_NONE           Successfully retrieved the OMR prefix.
- *
- */
-otError otBorderRoutingGetOmrPrefix(otInstance *aInstance, otIp6Prefix *aPrefix);
-
-/**
- * This method returns the on-link prefix for the adjacent infrastructure link.
- *
- * The randomly generated 64-bit prefix will be advertised
- * on the infrastructure link if there isn't already a usable
- * on-link prefix being advertised on the link.
- *
- * @param[in]   aInstance  A pointer to an OpenThread instance.
- * @param[out]  aPrefix    A pointer to where the prefix will be output to.
- *
- * @retval  OT_ERROR_INVALID_STATE  The Border Routing Manager is not initialized yet.
- * @retval  OT_ERROR_NONE           Successfully retrieved the on-link prefix.
- *
- */
-otError otBorderRoutingGetOnLinkPrefix(otInstance *aInstance, otIp6Prefix *aPrefix);
-
-/**
  * This method provides a full or stable copy of the local Thread Network Data.
  *
- * @param[in]     aInstance    A pointer to an OpenThread instance.
- * @param[in]     aStable      TRUE when copying the stable version, FALSE when copying the full version.
- * @param[out]    aData        A pointer to the data buffer.
- * @param[inout]  aDataLength  On entry, size of the data buffer pointed to by @p aData.
- *                             On exit, number of copied bytes.
+ * @param[in]      aInstance    A pointer to an OpenThread instance.
+ * @param[in]      aStable      TRUE when copying the stable version, FALSE when copying the full version.
+ * @param[out]     aData        A pointer to the data buffer.
+ * @param[in,out]  aDataLength  On entry, size of the data buffer pointed to by @p aData.
+ *                              On exit, number of copied bytes.
  */
 otError otBorderRouterGetNetData(otInstance *aInstance, bool aStable, uint8_t *aData, uint8_t *aDataLength);
 
@@ -160,10 +96,10 @@
 /**
  * This function gets the next On Mesh Prefix in the local Network Data.
  *
- * @param[in]     aInstance  A pointer to an OpenThread instance.
- * @param[inout]  aIterator  A pointer to the Network Data iterator context. To get the first on-mesh entry
-                             it should be set to OT_NETWORK_DATA_ITERATOR_INIT.
- * @param[out]    aConfig    A pointer to the On Mesh Prefix information.
+ * @param[in]      aInstance  A pointer to an OpenThread instance.
+ * @param[in,out]  aIterator  A pointer to the Network Data iterator context. To get the first on-mesh entry
+                              it should be set to OT_NETWORK_DATA_ITERATOR_INIT.
+ * @param[out]     aConfig    A pointer to the On Mesh Prefix information.
  *
  * @retval OT_ERROR_NONE       Successfully found the next On Mesh prefix.
  * @retval OT_ERROR_NOT_FOUND  No subsequent On Mesh prefix exists in the Thread Network Data.
@@ -205,10 +141,10 @@
 /**
  * This function gets the next external route in the local Network Data.
  *
- * @param[in]     aInstance  A pointer to an OpenThread instance.
- * @param[inout]  aIterator  A pointer to the Network Data iterator context. To get the first external route entry
-                             it should be set to OT_NETWORK_DATA_ITERATOR_INIT.
- * @param[out]    aConfig    A pointer to the External Route information.
+ * @param[in]      aInstance  A pointer to an OpenThread instance.
+ * @param[in,out]  aIterator  A pointer to the Network Data iterator context. To get the first external route entry
+                              it should be set to OT_NETWORK_DATA_ITERATOR_INIT.
+ * @param[out]     aConfig    A pointer to the External Route information.
  *
  * @retval OT_ERROR_NONE       Successfully found the next External Route.
  * @retval OT_ERROR_NOT_FOUND  No subsequent external route entry exists in the Thread Network Data.
diff --git a/include/openthread/border_routing.h b/include/openthread/border_routing.h
new file mode 100644
index 0000000..8cfec1b
--- /dev/null
+++ b/include/openthread/border_routing.h
@@ -0,0 +1,270 @@
+/*
+ *  Copyright (c) 2021-22, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ * @brief
+ *  This file defines the OpenThread Border Routing Manager API.
+ */
+
+#ifndef OPENTHREAD_BORDER_ROUTING_H_
+#define OPENTHREAD_BORDER_ROUTING_H_
+
+#include <openthread/error.h>
+#include <openthread/ip6.h>
+#include <openthread/netdata.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup api-border-routing
+ *
+ * @brief
+ *  This module includes definitions related to Border Routing Manager.
+ *
+ *
+ * @{
+ *
+ * All the functions in this module require `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE` to be enabled.
+ *
+ * Border Routing Manager handles bi-directional routing between Thread network and adjacent infrastructure link (AIL).
+ *
+ * It emits ICMRv6 ND Router Advertisement (RA) messages on AIL to advertise on-link and route prefixes. It also
+ * processes received RA messages from infrastructure and mirrors the discovered prefixes on the Thread Network Data to
+ * ensure devices on Thread mesh can reach AIL through the Border Router.
+ *
+ * Routing Manager manages the Off-Mesh Routable (OMR) prefix on the Thread Network data which configures Thread
+ * devices with a suitable Off-Mesh Routable IPv6 address. It announces the reachability of this prefix on AIL by
+ * including it in the emitted RA messages as an IPv6 Route Information Option (RIO).
+ *
+ * Routing Manager also monitors and adds on-link prefix on the infrastructure network. If a router on AIL is already
+ * providing RA messages containing an IPv6 Prefix Information Option (PIO) that enables IPv6 devices on the link to
+ * self-configure their own routable unicast IPv6 address, this address can be used by Thread devices to reach AIL. If
+ * Border Router finds no such RA message on AIL, it generates a ULA on-link prefix which it then advertises on AIL in
+ * the emitted RA messages.
+ *
+ */
+
+/**
+ * This structure represents an iterator to iterate through the Border Router's discovered prefix table.
+ *
+ * The fields in this type are opaque (intended for use by OpenThread core only) and therefore should not be
+ * accessed or used by caller.
+ *
+ * Before using an iterator, it MUST be initialized using `otBorderRoutingPrefixTableInitIterator()`.
+ *
+ */
+typedef struct otBorderRoutingPrefixTableIterator
+{
+    const void *mPtr1;
+    const void *mPtr2;
+    uint32_t    mData32;
+} otBorderRoutingPrefixTableIterator;
+
+/**
+ * This structure represents an entry from the discovered prefix table.
+ *
+ * The entries in the discovered table track the Prefix/Route Info Options in the received Router Advertisement messages
+ * from other routers on infrastructure link.
+ *
+ */
+typedef struct otBorderRoutingPrefixTableEntry
+{
+    otIp6Address      mRouterAddress;       ///< IPv6 address of the router.
+    otIp6Prefix       mPrefix;              ///< The discovered IPv6 prefix.
+    bool              mIsOnLink;            ///< Indicates whether the prefix is on-link or route prefix.
+    uint32_t          mMsecSinceLastUpdate; ///< Milliseconds since last update of this prefix.
+    uint32_t          mValidLifetime;       ///< Valid lifetime of the prefix (in seconds).
+    otRoutePreference mRoutePreference;     ///< Route preference when `mIsOnlink` is false.
+    uint32_t          mPreferredLifetime;   ///< Preferred lifetime of the on-link prefix when `mIsOnLink` is true.
+} otBorderRoutingPrefixTableEntry;
+
+/**
+ * This method initializes the Border Routing Manager on given infrastructure interface.
+ *
+ * @note  This method MUST be called before any other otBorderRouting* APIs.
+ *
+ * @param[in]  aInstance          A pointer to an OpenThread instance.
+ * @param[in]  aInfraIfIndex      The infrastructure interface index.
+ * @param[in]  aInfraIfIsRunning  A boolean that indicates whether the infrastructure
+ *                                interface is running.
+ *
+ * @retval  OT_ERROR_NONE           Successfully started the Border Routing Manager on given infrastructure.
+ * @retval  OT_ERROR_INVALID_STATE  The Border Routing Manager has already been initialized.
+ * @retval  OT_ERROR_INVALID_ARGS   The index of the infrastructure interface is not valid.
+ * @retval  OT_ERROR_FAILED         Internal failure. Usually due to failure in generating random prefixes.
+ *
+ * @sa otPlatInfraIfStateChanged.
+ *
+ */
+otError otBorderRoutingInit(otInstance *aInstance, uint32_t aInfraIfIndex, bool aInfraIfIsRunning);
+
+/**
+ * Enables or disables the Border Routing Manager.
+ *
+ * @note  The Border Routing Manager is disabled by default.
+ *
+ * @param[in]  aInstance  A pointer to an OpenThread instance.
+ * @param[in]  aEnabled   A boolean to enable/disable the routing manager.
+ *
+ * @retval  OT_ERROR_INVALID_STATE  The Border Routing Manager is not initialized yet.
+ * @retval  OT_ERROR_NONE           Successfully enabled/disabled the Border Routing Manager.
+ *
+ */
+otError otBorderRoutingSetEnabled(otInstance *aInstance, bool aEnabled);
+
+/**
+ * This function gets the preference used when advertising Route Info Options (e.g., for discovered OMR prefixes) in
+ * Router Advertisement messages sent over the infrastructure link.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ * @returns The OMR prefix advertisement preference.
+ *
+ */
+otRoutePreference otBorderRoutingGetRouteInfoOptionPreference(otInstance *aInstance);
+
+/**
+ * This function sets the preference to use when advertising Route Info Options in Router Advertisement messages sent
+ * over the infrastructure link, for example for discovered OMR prefixes.
+ *
+ * By default BR will use `medium` preference level, but this function allows the default value to be changed. As an
+ * example, it can be set to `low` preference in the case where device is a temporary BR (a mobile BR or a
+ * battery-powered BR) to indicate that other BRs (if any) should be preferred over this BR on the infrastructure link.
+ *
+ * @param[in] aInstance     A pointer to an OpenThread instance.
+ * @param[in] aPreference   The route preference to use.
+ *
+ */
+void otBorderRoutingSetRouteInfoOptionPreference(otInstance *aInstance, otRoutePreference aPreference);
+
+/**
+ * Gets the local Off-Mesh-Routable (OMR) Prefix, for example `fdfc:1ff5:1512:5622::/64`.
+ *
+ * An OMR Prefix is a randomly generated 64-bit prefix that's published in the
+ * Thread network if there isn't already an OMR prefix. This prefix can be reached
+ * from the local Wi-Fi or Ethernet network.
+ *
+ * @param[in]   aInstance  A pointer to an OpenThread instance.
+ * @param[out]  aPrefix    A pointer to where the prefix will be output to.
+ *
+ * @retval  OT_ERROR_INVALID_STATE  The Border Routing Manager is not initialized yet.
+ * @retval  OT_ERROR_NONE           Successfully retrieved the OMR prefix.
+ *
+ */
+otError otBorderRoutingGetOmrPrefix(otInstance *aInstance, otIp6Prefix *aPrefix);
+
+/**
+ * Gets the currently favored Off-Mesh-Routable (OMR) Prefix.
+ *
+ * The favored OMR prefix can be discovered from Network Data or can be this device's local OMR prefix.
+ *
+ * @param[in]   aInstance    A pointer to an OpenThread instance.
+ * @param[out]  aPrefix      A pointer to output the favored OMR prefix.
+ * @param[out]  aPreference  A pointer to output the preference associated the favored prefix.
+ *
+ * @retval  OT_ERROR_INVALID_STATE  The Border Routing Manager is not initialized yet.
+ * @retval  OT_ERROR_NONE           Successfully retrieved the favored OMR prefix.
+ *
+ */
+otError otBorderRoutingGetFavoredOmrPrefix(otInstance *aInstance, otIp6Prefix *aPrefix, otRoutePreference *aPreference);
+
+/**
+ * Gets the On-Link Prefix for the adjacent infrastructure link, for example `fd41:2650:a6f5:0::/64`.
+ *
+ * An On-Link Prefix is a 64-bit prefix that's advertised on the infrastructure link if there isn't already a usable
+ * on-link prefix being advertised on the link.
+ *
+ * @param[in]   aInstance  A pointer to an OpenThread instance.
+ * @param[out]  aPrefix    A pointer to where the prefix will be output to.
+ *
+ * @retval  OT_ERROR_INVALID_STATE  The Border Routing Manager is not initialized yet.
+ * @retval  OT_ERROR_NONE           Successfully retrieved the on-link prefix.
+ *
+ */
+otError otBorderRoutingGetOnLinkPrefix(otInstance *aInstance, otIp6Prefix *aPrefix);
+
+/**
+ * Gets the local NAT64 Prefix of the Border Router.
+ *
+ * NAT64 Prefix might not be advertised in the Thread network.
+ *
+ * `OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE` must be enabled.
+ *
+ * @param[in]   aInstance   A pointer to an OpenThread instance.
+ * @param[out]  aPrefix     A pointer to where the prefix will be output to.
+ *
+ * @retval  OT_ERROR_INVALID_STATE  The Border Routing Manager is not initialized yet.
+ * @retval  OT_ERROR_NONE           Successfully retrieved the NAT64 prefix.
+ *
+ */
+otError otBorderRoutingGetNat64Prefix(otInstance *aInstance, otIp6Prefix *aPrefix);
+
+/**
+ * This function initializes an `otBorderRoutingPrefixTableIterator`.
+ *
+ * An iterator MUST be initialized before it is used.
+ *
+ * An iterator can be initialized again to restart from the beginning of the table.
+ *
+ * When iterating over entries in the table, to ensure the update times `mMsecSinceLastUpdate` of entries are
+ * consistent, they are given relative to the time the iterator was initialized.
+ *
+ * @param[in]  aInstance  The OpenThread instance.
+ * @param[out] aIterator  A pointer to the iterator to initialize.
+ *
+ */
+void otBorderRoutingPrefixTableInitIterator(otInstance *aInstance, otBorderRoutingPrefixTableIterator *aIterator);
+
+/**
+ * This function iterates over the entries in the Border Router's discovered prefix table.
+ *
+ * @param[in]     aInstance    The OpenThread instance.
+ * @param[in,out] aIterator    A pointer to the iterator.
+ * @param[out]    aEntry       A pointer to the entry to populate.
+ *
+ * @retval OT_ERROR_NONE        Iterated to the next entry, @p aEntry and @p aIterator are updated.
+ * @retval OT_ERROR_NOT_FOUND   No more entries in the table.
+ *
+ */
+otError otBorderRoutingGetNextPrefixTableEntry(otInstance *                        aInstance,
+                                               otBorderRoutingPrefixTableIterator *aIterator,
+                                               otBorderRoutingPrefixTableEntry *   aEntry);
+
+/**
+ * @}
+ *
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_BORDER_ROUTING_H_
diff --git a/include/openthread/cli.h b/include/openthread/cli.h
index 56c9868..3fa5c56 100644
--- a/include/openthread/cli.h
+++ b/include/openthread/cli.h
@@ -70,9 +70,9 @@
 /**
  * This function pointer is called to notify about Console output.
  *
- * @param[in]  aBuf        A pointer to a buffer with an output.
- * @param[in]  aBufLength  A length of the output data stored in the buffer.
  * @param[out] aContext    A user context pointer.
+ * @param[in]  aFormat     The format string.
+ * @param[in]  aArguments  The format string arguments.
  *
  * @returns                Number of bytes written by the callback.
  *
@@ -147,16 +147,6 @@
 void otCliPlatLogv(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, va_list aArgs);
 
 /**
- * Function to write the OpenThread Log to the CLI console.
- *
- * @param[in]  aLogLevel   The log level.
- * @param[in]  aLogRegion  The log region.
- * @param[in]  aLogLine    A pointer to the log line string.
- *
- */
-void otCliPlatLogLine(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aLogLine);
-
-/**
  * @}
  *
  */
diff --git a/include/openthread/coap.h b/include/openthread/coap.h
index 7e23120..c2e036b 100644
--- a/include/openthread/coap.h
+++ b/include/openthread/coap.h
@@ -389,9 +389,9 @@
  * is enabled.
  *
  * @param[in]       aContext     A pointer to application-specific context.
- * @param[inout]    aBlock       A pointer to where the block segment can be written to.
+ * @param[in,out]   aBlock       A pointer to where the block segment can be written to.
  * @param[in]       aPosition    The position in a sequence from which to obtain the block segment.
- * @param[inout]    aBlockLength On entry, the maximum block segment length in bytes.
+ * @param[in,out]   aBlockLength On entry, the maximum block segment length in bytes.
  * @param[out]      aMore        A pointer to the flag if more block segments will follow.
  *
  * @warning By changing the value of aBlockLength, the block size of the whole exchange is
@@ -485,9 +485,9 @@
 /**
  * This function initializes the CoAP header.
  *
- * @param[inout] aMessage   A pointer to the CoAP message to initialize.
- * @param[in]    aType      CoAP message type.
- * @param[in]    aCode      CoAP message code.
+ * @param[in,out] aMessage   A pointer to the CoAP message to initialize.
+ * @param[in]     aType      CoAP message type.
+ * @param[in]     aCode      CoAP message code.
  *
  */
 void otCoapMessageInit(otMessage *aMessage, otCoapType aType, otCoapCode aCode);
@@ -497,10 +497,10 @@
  *
  * @note Both message ID and token are set according to @p aRequest.
  *
- * @param[inout] aResponse  A pointer to the CoAP response message.
- * @param[in]    aRequest   A pointer to the CoAP request message.
- * @param[in]    aType      CoAP message type.
- * @param[in]    aCode      CoAP message code.
+ * @param[in,out]  aResponse  A pointer to the CoAP response message.
+ * @param[in]      aRequest   A pointer to the CoAP request message.
+ * @param[in]      aType      CoAP message type.
+ * @param[in]      aCode      CoAP message code.
  *
  * @retval OT_ERROR_NONE     Successfully initialized the response message.
  * @retval OT_ERROR_NO_BUFS  Insufficient message buffers available to initialize the response message.
@@ -511,9 +511,9 @@
 /**
  * This function sets the Token value and length in a header.
  *
- * @param[inout]  aMessage          A pointer to the CoAP message.
- * @param[in]     aToken            A pointer to the Token value.
- * @param[in]     aTokenLength      The Length of @p aToken.
+ * @param[in,out]  aMessage          A pointer to the CoAP message.
+ * @param[in]      aToken            A pointer to the Token value.
+ * @param[in]      aTokenLength      The Length of @p aToken.
  *
  * @retval OT_ERROR_NONE     Successfully set the Token value.
  * @retval OT_ERROR_NO_BUFS  Insufficient buffers to set the Token value.
@@ -524,8 +524,8 @@
 /**
  * This function sets the Token length and randomizes its value.
  *
- * @param[inout]  aMessage      A pointer to the CoAP message.
- * @param[in]     aTokenLength  The Length of a Token to set.
+ * @param[in,out]  aMessage      A pointer to the CoAP message.
+ * @param[in]      aTokenLength  The Length of a Token to set.
  *
  */
 void otCoapMessageGenerateToken(otMessage *aMessage, uint8_t aTokenLength);
@@ -540,8 +540,8 @@
  * and if the desired format type code isn't listed in otCoapOptionContentFormat,
  * this base function should be used instead.
  *
- * @param[inout]  aMessage          A pointer to the CoAP message.
- * @param[in]     aContentFormat    One of the content formats listed in
+ * @param[in,out]  aMessage          A pointer to the CoAP message.
+ * @param[in]      aContentFormat    One of the content formats listed in
  *                                  otCoapOptionContentFormat above.
  *
  * @retval OT_ERROR_NONE          Successfully appended the option.
@@ -554,10 +554,10 @@
 /**
  * This function appends a CoAP option in a header.
  *
- * @param[inout]  aMessage  A pointer to the CoAP message.
- * @param[in]     aNumber   The CoAP Option number.
- * @param[in]     aLength   The CoAP Option length.
- * @param[in]     aValue    A pointer to the CoAP value.
+ * @param[in,out]  aMessage  A pointer to the CoAP message.
+ * @param[in]      aNumber   The CoAP Option number.
+ * @param[in]      aLength   The CoAP Option length.
+ * @param[in]      aValue    A pointer to the CoAP value.
  *
  * @retval OT_ERROR_NONE          Successfully appended the option.
  * @retval OT_ERROR_INVALID_ARGS  The option type is not equal or greater than the last option type.
@@ -570,9 +570,9 @@
  * This function appends an unsigned integer CoAP option as specified in
  * https://tools.ietf.org/html/rfc7252#section-3.2
  *
- * @param[inout]  aMessage A pointer to the CoAP message.
- * @param[in]     aNumber  The CoAP Option number.
- * @param[in]     aValue   The CoAP Option unsigned integer value.
+ * @param[in,out]  aMessage A pointer to the CoAP message.
+ * @param[in]      aNumber  The CoAP Option number.
+ * @param[in]      aValue   The CoAP Option unsigned integer value.
  *
  * @retval OT_ERROR_NONE          Successfully appended the option.
  * @retval OT_ERROR_INVALID_ARGS  The option type is not equal or greater than the last option type.
@@ -585,8 +585,8 @@
 /**
  * This function appends an Observe option.
  *
- * @param[inout]  aMessage  A pointer to the CoAP message.
- * @param[in]     aObserve  Observe field value.
+ * @param[in,out]  aMessage  A pointer to the CoAP message.
+ * @param[in]      aObserve  Observe field value.
  *
  * @retval OT_ERROR_NONE          Successfully appended the option.
  * @retval OT_ERROR_INVALID_ARGS  The option type is not equal or greater than the last option type.
@@ -598,8 +598,8 @@
 /**
  * This function appends a Uri-Path option.
  *
- * @param[inout]  aMessage  A pointer to the CoAP message.
- * @param[in]     aUriPath  A pointer to a NULL-terminated string.
+ * @param[in,out]  aMessage  A pointer to the CoAP message.
+ * @param[in]      aUriPath  A pointer to a NULL-terminated string.
  *
  * @retval OT_ERROR_NONE          Successfully appended the option.
  * @retval OT_ERROR_INVALID_ARGS  The option type is not equal or greater than the last option type.
@@ -621,10 +621,10 @@
 /**
  * This function appends a Block2 option
  *
- * @param[inout]  aMessage  A pointer to the CoAP message.
- * @param[in]     aNum      Current block number.
- * @param[in]     aMore     Boolean to indicate more blocks are to be sent.
- * @param[in]     aSize     Block Size Exponent.
+ * @param[in,out]  aMessage  A pointer to the CoAP message.
+ * @param[in]      aNum      Current block number.
+ * @param[in]      aMore     Boolean to indicate more blocks are to be sent.
+ * @param[in]      aSize     Block Size Exponent.
  *
  * @retval OT_ERROR_NONE          Successfully appended the option.
  * @retval OT_ERROR_INVALID_ARGS  The option type is not equal or greater than the last option type.
@@ -636,10 +636,10 @@
 /**
  * This function appends a Block1 option
  *
- * @param[inout]  aMessage  A pointer to the CoAP message.
- * @param[in]     aNum      Current block number.
- * @param[in]     aMore     Boolean to indicate more blocks are to be sent.
- * @param[in]     aSize     Block Size Exponent.
+ * @param[in,out]  aMessage  A pointer to the CoAP message.
+ * @param[in]      aNum      Current block number.
+ * @param[in]      aMore     Boolean to indicate more blocks are to be sent.
+ * @param[in]      aSize     Block Size Exponent.
  *
  * @retval OT_ERROR_NONE          Successfully appended the option.
  * @retval OT_ERROR_INVALID_ARGS  The option type is not equal or greater than the last option type.
@@ -651,8 +651,8 @@
 /**
  * This function appends a Proxy-Uri option.
  *
- * @param[inout]  aMessage  A pointer to the CoAP message.
- * @param[in]     aUriPath  A pointer to a NULL-terminated string.
+ * @param[in,out]  aMessage  A pointer to the CoAP message.
+ * @param[in]      aUriPath  A pointer to a NULL-terminated string.
  *
  * @retval OT_ERROR_NONE          Successfully appended the option.
  * @retval OT_ERROR_INVALID_ARGS  The option type is not equal or greater than the last option type.
@@ -664,8 +664,8 @@
 /**
  * This function appends a Max-Age option.
  *
- * @param[inout]  aMessage  A pointer to the CoAP message.
- * @param[in]     aMaxAge   The Max-Age value.
+ * @param[in,out]  aMessage  A pointer to the CoAP message.
+ * @param[in]      aMaxAge   The Max-Age value.
  *
  * @retval OT_ERROR_NONE          Successfully appended the option.
  * @retval OT_ERROR_INVALID_ARGS  The option type is not equal or greater than the last option type.
@@ -677,8 +677,8 @@
 /**
  * This function appends a single Uri-Query option.
  *
- * @param[inout]  aMessage  A pointer to the CoAP message.
- * @param[in]     aUriQuery A pointer to NULL-terminated string, which should contain a single key=value pair.
+ * @param[in,out]  aMessage  A pointer to the CoAP message.
+ * @param[in]      aUriQuery A pointer to NULL-terminated string, which should contain a single key=value pair.
  *
  * @retval OT_ERROR_NONE          Successfully appended the option.
  * @retval OT_ERROR_INVALID_ARGS  The option type is not equal or greater than the last option type.
@@ -689,7 +689,7 @@
 /**
  * This function adds Payload Marker indicating beginning of the payload to the CoAP header.
  *
- * @param[inout]  aMessage  A pointer to the CoAP message.
+ * @param[in,out]  aMessage  A pointer to the CoAP message.
  *
  * @retval OT_ERROR_NONE     Payload Marker successfully added.
  * @retval OT_ERROR_NO_BUFS  Header Payload Marker exceeds the buffer size.
@@ -718,6 +718,15 @@
 otCoapCode otCoapMessageGetCode(const otMessage *aMessage);
 
 /**
+ * This function sets the Code value.
+ *
+ * @param[in,out]  aMessage  A pointer to the CoAP message to initialize.
+ * @param[in]      aCode     CoAP message code.
+ *
+ */
+void otCoapMessageSetCode(otMessage *aMessage, otCoapCode aCode);
+
+/**
  * This method returns the CoAP Code as human readable string.
  *
  * @param[in]   aMessage    A pointer to the CoAP message.
@@ -760,8 +769,8 @@
 /**
  * This function initialises an iterator for the options in the given message.
  *
- * @param[inout]  aIterator A pointer to the CoAP message option iterator.
- * @param[in]     aMessage  A pointer to the CoAP message.
+ * @param[in,out]  aIterator A pointer to the CoAP message option iterator.
+ * @param[in]      aMessage  A pointer to the CoAP message.
  *
  * @retval  OT_ERROR_NONE   Successfully initialised.
  * @retval  OT_ERROR_PARSE  Message state is inconsistent.
@@ -783,7 +792,7 @@
 /**
  * This function returns a pointer to the first option.
  *
- * @param[inout]  aIterator A pointer to the CoAP message option iterator.
+ * @param[in,out]  aIterator A pointer to the CoAP message option iterator.
  *
  * @returns A pointer to the first option. If no option is present NULL pointer is returned.
  *
@@ -804,7 +813,7 @@
 /**
  * This function returns a pointer to the next option.
  *
- * @param[inout]  aIterator A pointer to the CoAP message option iterator.
+ * @param[in,out]  aIterator A pointer to the CoAP message option iterator.
  *
  * @returns A pointer to the next option. If no more options are present NULL pointer is returned.
  *
@@ -815,7 +824,7 @@
  * This function fills current option value into @p aValue assuming the current value is an unsigned integer encoded
  * according to https://tools.ietf.org/html/rfc7252#section-3.2
  *
- * @param[inout]    aIterator   A pointer to the CoAP message option iterator.
+ * @param[in,out]   aIterator   A pointer to the CoAP message option iterator.
  * @param[out]      aValue      A pointer to an unsigned integer to receive the option value.
  *
  * @retval  OT_ERROR_NONE       Successfully filled value.
@@ -829,8 +838,8 @@
 /**
  * This function fills current option value into @p aValue.
  *
- * @param[inout]  aIterator A pointer to the CoAP message option iterator.
- * @param[out]    aValue    A pointer to a buffer to receive the option value.
+ * @param[in,out]  aIterator A pointer to the CoAP message option iterator.
+ * @param[out]     aValue    A pointer to a buffer to receive the option value.
  *
  * @retval  OT_ERROR_NONE       Successfully filled value.
  * @retval  OT_ERROR_NOT_FOUND  No current option.
diff --git a/include/openthread/commissioner.h b/include/openthread/commissioner.h
index f142edc..d632fd0 100644
--- a/include/openthread/commissioner.h
+++ b/include/openthread/commissioner.h
@@ -154,10 +154,8 @@
 /**
  * This function pointer is called whenever the commissioner state changes.
  *
- * @param[in]  aChannelMask       The channel mask value.
- * @param[in]  aEnergyList        A pointer to the energy measurement list.
- * @param[in]  aEnergyListLength  Number of entries in @p aEnergyListLength.
- * @param[in]  aContext           A pointer to application-specific context.
+ * @param[in]  aState    The Commissioner state.
+ * @param[in]  aContext  A pointer to application-specific context.
  *
  */
 typedef void (*otCommissionerStateCallback)(otCommissionerState aState, void *aContext);
@@ -206,6 +204,29 @@
 otError otCommissionerStop(otInstance *aInstance);
 
 /**
+ * This function returns the Commissioner Id.
+ *
+ * @param[in]  aInstance         A pointer to an OpenThread instance.
+ *
+ * @returns The Commissioner Id.
+ *
+ */
+const char *otCommissionerGetId(otInstance *aInstance);
+
+/**
+ * This function sets the Commissioner Id.
+ *
+ * @param[in]  aInstance     A pointer to an OpenThread instance.
+ * @param[in]  aId           A pointer to a string character array. Must be null terminated.
+ *
+ * @retval OT_ERROR_NONE            Successfully set the Commissioner Id.
+ * @retval OT_ERROR_INVALID_ARGS    Given name is too long.
+ * @retval OT_ERROR_INVALID_STATE   The commissioner is active and id cannot be changed.
+ *
+ */
+otError otCommissionerSetId(otInstance *aInstance, const char *aId);
+
+/**
  * This function adds a Joiner entry.
  *
  * @param[in]  aInstance          A pointer to an OpenThread instance.
@@ -251,7 +272,7 @@
  * This method get joiner info at aIterator position.
  *
  * @param[in]      aInstance   A pointer to instance.
- * @param[inout]   aIterator   A pointer to the Joiner Info iterator context.
+ * @param[in,out]  aIterator   A pointer to the Joiner Info iterator context.
  * @param[out]     aJoiner     A reference to Joiner info.
  *
  * @retval OT_ERROR_NONE       Successfully get the Joiner info.
@@ -280,7 +301,7 @@
  * This function removes a Joiner entry.
  *
  * @param[in]  aInstance          A pointer to an OpenThread instance.
- * @param[in]  aEui64             A pointer to the Joiner Discerner.
+ * @param[in]  aDiscerner         A pointer to the Joiner Discerner.
  *
  * @retval OT_ERROR_NONE          Successfully removed the Joiner.
  * @retval OT_ERROR_NOT_FOUND     The Joiner specified by @p aEui64 was not found.
diff --git a/include/openthread/config.h b/include/openthread/config.h
index 2a5fd26..090532c 100644
--- a/include/openthread/config.h
+++ b/include/openthread/config.h
@@ -41,10 +41,8 @@
  * The OpenThread feature configuration file.
  *
  */
-#if !defined(OPENTHREAD_CONFIG_FILE)
-#define OPENTHREAD_CONFIG_FILE <openthread-config-generic.h>
-#endif
-
+#if defined(OPENTHREAD_CONFIG_FILE)
 #include OPENTHREAD_CONFIG_FILE
+#endif
 
 #endif // OPENTHREAD_CONFIG_H_
diff --git a/include/openthread/crypto.h b/include/openthread/crypto.h
index a1a3d36..3be657b 100644
--- a/include/openthread/crypto.h
+++ b/include/openthread/crypto.h
@@ -89,20 +89,20 @@
 /**
  * This method performs AES CCM computation.
  *
- * @param[in]     aKey           A pointer to the key.
- * @param[in]     aTagLength     Length of tag in bytes.
- * @param[in]     aNonce         A pointer to the nonce.
- * @param[in]     aNonceLength   Length of nonce in bytes.
+ * @param[in]      aKey           A pointer to the key.
+ * @param[in]      aTagLength     Length of tag in bytes.
+ * @param[in]      aNonce         A pointer to the nonce.
+ * @param[in]      aNonceLength   Length of nonce in bytes.
  *
- * @param[in]     aHeader        A pointer to the header.
- * @param[in]     aHeaderLength  Length of header in bytes.
+ * @param[in]      aHeader        A pointer to the header.
+ * @param[in]      aHeaderLength  Length of header in bytes.
  *
- * @param[inout]  aPlainText     A pointer to the plaintext.
- * @param[inout]  aCipherText    A pointer to the ciphertext.
- * @param[in]     aLength        Plaintext length in bytes.
- * @param[in]     aEncrypt       `true` on encrypt and `false` on decrypt.
+ * @param[in,out]  aPlainText     A pointer to the plaintext.
+ * @param[in,out]  aCipherText    A pointer to the ciphertext.
+ * @param[in]      aLength        Plaintext length in bytes.
+ * @param[in]      aEncrypt       `true` on encrypt and `false` on decrypt.
  *
- * @param[out]    aTag           A pointer to the tag.
+ * @param[out]     aTag           A pointer to the tag.
  *
  */
 void otCryptoAesCcm(const otCryptoKey *aKey,
@@ -120,12 +120,12 @@
 /**
  * This method creates ECDSA sign.
  *
- * @param[out]    aOutput            An output buffer where ECDSA sign should be stored.
- * @param[inout]  aOutputLength      The length of the @p aOutput buffer.
- * @param[in]     aInputHash         An input hash.
- * @param[in]     aInputHashLength   The length of the @p aInputHash buffer.
- * @param[in]     aPrivateKey        A private key in PEM format.
- * @param[in]     aPrivateKeyLength  The length of the @p aPrivateKey buffer.
+ * @param[out]     aOutput            An output buffer where ECDSA sign should be stored.
+ * @param[in,out]  aOutputLength      The length of the @p aOutput buffer.
+ * @param[in]      aInputHash         An input hash.
+ * @param[in]      aInputHashLength   The length of the @p aInputHash buffer.
+ * @param[in]      aPrivateKey        A private key in PEM format.
+ * @param[in]      aPrivateKeyLength  The length of the @p aPrivateKey buffer.
  *
  * @retval  OT_ERROR_NONE         ECDSA sign has been created successfully.
  * @retval  OT_ERROR_NO_BUFS      Output buffer is too small.
diff --git a/include/openthread/dataset.h b/include/openthread/dataset.h
index 6e899b1..63e1e26 100644
--- a/include/openthread/dataset.h
+++ b/include/openthread/dataset.h
@@ -152,7 +152,6 @@
     bool    mNativeCommissioningEnabled : 1;     ///< Native Commissioning using PSKc is allowed
     bool    mRoutersEnabled : 1;                 ///< Thread 1.0/1.1.x Routers are enabled
     bool    mExternalCommissioningEnabled : 1;   ///< External Commissioner authentication is allowed
-    bool    mBeaconsEnabled : 1;                 ///< Thread 1.0/1.1.x Beacons are enabled
     bool    mCommercialCommissioningEnabled : 1; ///< Commercial Commissioning is enabled
     bool    mAutonomousEnrollmentEnabled : 1;    ///< Autonomous Enrollment is enabled
     bool    mNetworkKeyProvisioningEnabled : 1;  ///< Network Key Provisioning is enabled
@@ -215,6 +214,17 @@
 } otOperationalDatasetComponents;
 
 /**
+ * This structure represents a Thread Dataset timestamp component.
+ *
+ */
+typedef struct otTimestamp
+{
+    uint64_t mSeconds;
+    uint16_t mTicks;
+    bool     mAuthoritative;
+} otTimestamp;
+
+/**
  * This structure represents an Active or Pending Operational Dataset.
  *
  * Components in Dataset are optional. `mComponets` structure specifies which components are present in the Dataset.
@@ -222,8 +232,8 @@
  */
 typedef struct otOperationalDataset
 {
-    uint64_t                       mActiveTimestamp;  ///< Active Timestamp
-    uint64_t                       mPendingTimestamp; ///< Pending Timestamp
+    otTimestamp                    mActiveTimestamp;  ///< Active Timestamp
+    otTimestamp                    mPendingTimestamp; ///< Pending Timestamp
     otNetworkKey                   mNetworkKey;       ///< Network Key
     otNetworkName                  mNetworkName;      ///< Network Name
     otExtendedPanId                mExtendedPanId;    ///< Extended PAN ID
diff --git a/include/openthread/dns_client.h b/include/openthread/dns_client.h
index e212062..17817c1 100644
--- a/include/openthread/dns_client.h
+++ b/include/openthread/dns_client.h
@@ -199,6 +199,8 @@
  *
  * @retval OT_ERROR_NONE          Query sent successfully. @p aCallback will be invoked to report the status.
  * @retval OT_ERROR_NO_BUFS       Insufficient buffer to prepare and send query.
+ * @retval OT_ERROR_INVALID_ARGS  The host name is not valid format.
+ * @retval OT_ERROR_INVALID_STATE Cannot send query since Thread interface is not up.
  *
  */
 otError otDnsClientResolveAddress(otInstance *            aInstance,
@@ -208,6 +210,36 @@
                                   const otDnsQueryConfig *aConfig);
 
 /**
+ * This function sends an address resolution DNS query for A (IPv4) record(s) for a given host name.
+ *
+ * This function requires and is available when `OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE` is enabled.
+ *
+ * When a successful response is received, the addresses are returned from @p aCallback as NAT64 IPv6 translated
+ * versions of the IPv4 addresses from the query response.
+ *
+ * The @p aConfig can be NULL. In this case the default config (from `otDnsClientGetDefaultConfig()`) will be used as
+ * the config for this query. In a non-NULL @p aConfig, some of the fields can be left unspecified (value zero). The
+ * unspecified fields are then replaced by the values from the default config.
+ *
+ * @param[in]  aInstance        A pointer to an OpenThread instance.
+ * @param[in]  aHostName        The host name for which to query the address (MUST NOT be NULL).
+ * @param[in]  aCallback        A function pointer that shall be called on response reception or time-out.
+ * @param[in]  aContext         A pointer to arbitrary context information.
+ * @param[in]  aConfig          A pointer to the config to use for this query.
+ *
+ * @retval OT_ERROR_NONE          Query sent successfully. @p aCallback will be invoked to report the status.
+ * @retval OT_ERROR_NO_BUFS       Insufficient buffer to prepare and send query.
+ * @retval OT_ERROR_INVALID_ARGS  The host name is not valid format or NAT64 is not enabled in config.
+ * @retval OT_ERROR_INVALID_STATE Cannot send query since Thread interface is not up.
+ *
+ */
+otError otDnsClientResolveIp4Address(otInstance *            aInstance,
+                                     const char *            aHostName,
+                                     otDnsAddressCallback    aCallback,
+                                     void *                  aContext,
+                                     const otDnsQueryConfig *aConfig);
+
+/**
  * This function gets the full host name associated with an address resolution DNS response.
  *
  * This function MUST only be used from `otDnsAddressCallback`.
@@ -239,9 +271,10 @@
  * @param[out] aTtl          A pointer to an `uint32_t` to output TTL for the address. It can be NULL if caller does not
  *                           want to get the TTL.
  *
- * @retval OT_ERROR_NONE       The address was read successfully.
- * @retval OT_ERROR_NOT_FOUND  No address record in @p aResponse at @p aIndex.
- * @retval OT_ERROR_PARSE      Could not parse the records in the @p aResponse.
+ * @retval OT_ERROR_NONE           The address was read successfully.
+ * @retval OT_ERROR_NOT_FOUND      No address record in @p aResponse at @p aIndex.
+ * @retval OT_ERROR_PARSE          Could not parse the records in the @p aResponse.
+ * @retval OT_ERROR_INVALID_STATE  No NAT64 prefix (applicable only when NAT64 is allowed).
  *
  */
 otError otDnsAddressResponseGetAddress(const otDnsAddressResponse *aResponse,
diff --git a/include/openthread/dnssd_server.h b/include/openthread/dnssd_server.h
index abcac36..7366698 100644
--- a/include/openthread/dnssd_server.h
+++ b/include/openthread/dnssd_server.h
@@ -148,6 +148,22 @@
 } otDnssdQueryType;
 
 /**
+ * This structure contains the counters of DNS-SD server.
+ *
+ */
+typedef struct otDnssdCounters
+{
+    uint32_t mSuccessResponse;        ///< The number of successful responses
+    uint32_t mServerFailureResponse;  ///< The number of server failure responses
+    uint32_t mFormatErrorResponse;    ///< The number of format error responses
+    uint32_t mNameErrorResponse;      ///< The number of name error responses
+    uint32_t mNotImplementedResponse; ///< The number of 'not implemented' responses
+    uint32_t mOtherResponse;          ///< The number of other responses
+
+    uint32_t mResolvedBySrp; ///< The number of queries completely resolved by the local SRP server
+} otDnssdCounters;
+
+/**
  * This function sets DNS-SD server query callbacks.
  *
  * The DNS-SD server calls @p aSubscribe to subscribe to a service or service instance to resolve a DNS-SD query and @p
@@ -220,6 +236,16 @@
 otDnssdQueryType otDnssdGetQueryTypeAndName(const otDnssdQuery *aQuery, char (*aNameOutput)[OT_DNS_MAX_NAME_SIZE]);
 
 /**
+ * This function returns the counters of the DNS-SD server.
+ *
+ * @param[in]  aInstance  The OpenThread instance structure.
+ *
+ * @returns  A pointer to the counters of the DNS-SD server.
+ *
+ */
+const otDnssdCounters *otDnssdGetCounters(otInstance *aInstance);
+
+/**
  * @}
  *
  */
diff --git a/include/openthread/history_tracker.h b/include/openthread/history_tracker.h
index 0cce3e7..a8dc7c3 100644
--- a/include/openthread/history_tracker.h
+++ b/include/openthread/history_tracker.h
@@ -29,6 +29,7 @@
 
 #include <openthread/instance.h>
 #include <openthread/ip6.h>
+#include <openthread/netdata.h>
 #include <openthread/thread.h>
 
 #ifdef __cplusplus
@@ -38,18 +39,13 @@
 /**
  * @addtogroup api-history-tracker
  *
- * @{
- *
- */
-
-/**
  * @brief
- *   This header defines the public API for History Tracker.
+ *   Records the history of different events, for example RX and TX messages or network info changes. All tracked
+ *   entries are timestamped.
  *
- *   History Tracker module records history of different events (e.g. RX and TX messages or network info changes, etc.)
- *   as the Thread network operates. All tracked entries are timestamped.
+ * The functions in this module are available when `OPENTHREAD_CONFIG_HISTOR_TRACKER_ENABLE` is enabled.
  *
- *   The functions in this module are available when `OPENTHREAD_CONFIG_HISTOR_TRACKER_ENABLE` is enabled.
+ * @{
  *
  */
 
@@ -197,6 +193,36 @@
 } otHistoryTrackerNeighborInfo;
 
 /**
+ * This enumeration defines the events for a Network Data entry (i.e., whether an entry is added or removed).
+ *
+ */
+typedef enum
+{
+    OT_HISTORY_TRACKER_NET_DATA_ENTRY_ADDED   = 0, ///< Network data entry is added.
+    OT_HISTORY_TRACKER_NET_DATA_ENTRY_REMOVED = 1, ///< Network data entry is removed.
+} otHistoryTrackerNetDataEvent;
+
+/**
+ * This structure represent a Network Data on mesh prefix info.
+ *
+ */
+typedef struct otHistoryTrackerOnMeshPrefixInfo
+{
+    otBorderRouterConfig         mPrefix; ///< The on mesh prefix entry.
+    otHistoryTrackerNetDataEvent mEvent;  ///< Indicates the event (added/removed).
+} otHistoryTrackerOnMeshPrefixInfo;
+
+/**
+ * This structure represent a Network Data extern route info.
+ *
+ */
+typedef struct otHistoryTrackerExternalRouteInfo
+{
+    otExternalRouteConfig        mRoute; ///< The external route entry.
+    otHistoryTrackerNetDataEvent mEvent; ///< Indicates the event (added/removed).
+} otHistoryTrackerExternalRouteInfo;
+
+/**
  * This function initializes an `otHistoryTrackerIterator`.
  *
  * An iterator MUST be initialized before it is used.
@@ -215,12 +241,12 @@
 /**
  * This function iterates over the entries in the network info history list.
  *
- * @param[in]    aInstance   A pointer to the OpenThread instance.
- * @param[inout] aIterator   A pointer to an iterator. MUST be initialized or the behavior is undefined.
- * @param[out]   aEntryAge   A pointer to a variable to output the entry's age. MUST NOT be NULL.
- *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
- *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
- *                           older than max age.
+ * @param[in]     aInstance   A pointer to the OpenThread instance.
+ * @param[in,out] aIterator   A pointer to an iterator. MUST be initialized or the behavior is undefined.
+ * @param[out]    aEntryAge   A pointer to a variable to output the entry's age. MUST NOT be NULL.
+ *                            Age is provided as the duration (in milliseconds) from when entry was recorded to
+ *                            @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
+ *                            older than max age.
  *
  * @returns A pointer to `otHistoryTrackerNetworkInfo` entry or `NULL` if no more entries in the list.
  *
@@ -232,9 +258,9 @@
 /**
  * This function iterates over the entries in the unicast address history list.
  *
- * @param[in]    aInstance   A pointer to the OpenThread instance.
- * @param[inout] aIterator   A pointer to an iterator. MUST be initialized or the behavior is undefined.
- * @param[out]   aEntryAge   A pointer to a variable to output the entry's age. MUST NOT be NULL.
+ * @param[in]     aInstance  A pointer to the OpenThread instance.
+ * @param[in,out] aIterator  A pointer to an iterator. MUST be initialized or the behavior is undefined.
+ * @param[out]    aEntryAge  A pointer to a variable to output the entry's age. MUST NOT be NULL.
  *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
  *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
  *                           older than max age.
@@ -250,9 +276,9 @@
 /**
  * This function iterates over the entries in the multicast address history list.
  *
- * @param[in]    aInstance   A pointer to the OpenThread instance.
- * @param[inout] aIterator   A pointer to an iterator. MUST be initialized or the behavior is undefined.
- * @param[out]   aEntryAge   A pointer to a variable to output the entry's age. MUST NOT be NULL.
+ * @param[in]     aInstance  A pointer to the OpenThread instance.
+ * @param[in,out] aIterator  A pointer to an iterator. MUST be initialized or the behavior is undefined.
+ * @param[out]    aEntryAge  A pointer to a variable to output the entry's age. MUST NOT be NULL.
  *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
  *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
  *                           older than max age.
@@ -268,9 +294,9 @@
 /**
  * This function iterates over the entries in the RX message history list.
  *
- * @param[in]    aInstance   A pointer to the OpenThread instance.
- * @param[inout] aIterator   A pointer to an iterator. MUST be initialized or the behavior is undefined.
- * @param[out]   aEntryAge   A pointer to a variable to output the entry's age. MUST NOT be NULL.
+ * @param[in]     aInstance  A pointer to the OpenThread instance.
+ * @param[in,out] aIterator  A pointer to an iterator. MUST be initialized or the behavior is undefined.
+ * @param[out]    aEntryAge  A pointer to a variable to output the entry's age. MUST NOT be NULL.
  *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
  *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
  *                           older than max age.
@@ -285,9 +311,9 @@
 /**
  * This function iterates over the entries in the TX message history list.
  *
- * @param[in]    aInstance   A pointer to the OpenThread instance.
- * @param[inout] aIterator   A pointer to an iterator. MUST be initialized or the behavior is undefined.
- * @param[out]   aEntryAge   A pointer to a variable to output the entry's age. MUST NOT be NULL.
+ * @param[in]     aInstance  A pointer to the OpenThread instance.
+ * @param[in,out] aIterator  A pointer to an iterator. MUST be initialized or the behavior is undefined.
+ * @param[out]    aEntryAge  A pointer to a variable to output the entry's age. MUST NOT be NULL.
  *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
  *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
  *                           older than max age.
@@ -302,9 +328,9 @@
 /**
  * This function iterates over the entries in the neighbor history list.
  *
- * @param[in]    aInstance   A pointer to the OpenThread instance.
- * @param[inout] aIterator   A pointer to an iterator. MUST be initialized or the behavior is undefined.
- * @param[out]   aEntryAge   A pointer to a variable to output the entry's age. MUST NOT be NULL.
+ * @param[in]     aInstance  A pointer to the OpenThread instance.
+ * @param[in,out] aIterator  A pointer to an iterator. MUST be initialized or the behavior is undefined.
+ * @param[out]    aEntryAge  A pointer to a variable to output the entry's age. MUST NOT be NULL.
  *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
  *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
  *                           older than max age.
@@ -317,6 +343,41 @@
                                                                            uint32_t *                aEntryAge);
 
 /**
+ * This function iterates over the entries in the Network Data on mesh prefix entry history list.
+ *
+ * @param[in]     aInstance  A pointer to the OpenThread instance.
+ * @param[in,out] aIterator  A pointer to an iterator. MUST be initialized or the behavior is undefined.
+ * @param[out]    aEntryAge  A pointer to a variable to output the entry's age. MUST NOT be NULL.
+ *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
+ *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
+ *                           older than max age.
+ *
+ * @returns The `otHistoryTrackerOnMeshPrefixInfo` entry or `NULL` if no more entries in the list.
+ *
+ */
+const otHistoryTrackerOnMeshPrefixInfo *otHistoryTrackerIterateOnMeshPrefixHistory(otInstance *              aInstance,
+                                                                                   otHistoryTrackerIterator *aIterator,
+                                                                                   uint32_t *                aEntryAge);
+
+/**
+ * This function iterates over the entries in the Network Data external route entry history list.
+ *
+ * @param[in]     aInstance  A pointer to the OpenThread instance.
+ * @param[in,out] aIterator  A pointer to an iterator. MUST be initialized or the behavior is undefined.
+ * @param[out]    aEntryAge  A pointer to a variable to output the entry's age. MUST NOT be NULL.
+ *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
+ *                           @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
+ *                           older than max age.
+ *
+ * @returns The `otHistoryTrackerExternalRouteInfo` entry or `NULL` if no more entries in the list.
+ *
+ */
+const otHistoryTrackerExternalRouteInfo *otHistoryTrackerIterateExternalRouteHistory(
+    otInstance *              aInstance,
+    otHistoryTrackerIterator *aIterator,
+    uint32_t *                aEntryAge);
+
+/**
  * This function converts a given entry age to a human-readable string.
  *
  * The entry age string follows the format "<hh>:<mm>:<ss>.<mmmm>" for hours, minutes, seconds and millisecond (if
diff --git a/include/openthread/instance.h b/include/openthread/instance.h
index 9143431..db89b62 100644
--- a/include/openthread/instance.h
+++ b/include/openthread/instance.h
@@ -53,7 +53,7 @@
  * @note This number versions both OpenThread platform and user APIs.
  *
  */
-#define OPENTHREAD_API_VERSION (172)
+#define OPENTHREAD_API_VERSION (230)
 
 /**
  * @addtogroup api-instance
@@ -78,9 +78,9 @@
  *
  * This function is available and can only be used when support for multiple OpenThread instances is enabled.
  *
- * @param[in]    aInstanceBuffer      The buffer for OpenThread to use for allocating the otInstance structure.
- * @param[inout] aInstanceBufferSize  On input, the size of aInstanceBuffer. On output, if not enough space for
- *                                    otInstance, the number of bytes required for otInstance.
+ * @param[in]     aInstanceBuffer      The buffer for OpenThread to use for allocating the otInstance structure.
+ * @param[in,out] aInstanceBufferSize  On input, the size of aInstanceBuffer. On output, if not enough space for
+ *                                     otInstance, the number of bytes required for otInstance.
  *
  * @returns  A pointer to the new OpenThread instance.
  *
diff --git a/include/openthread/ip6.h b/include/openthread/ip6.h
index e802359..f624b42 100644
--- a/include/openthread/ip6.h
+++ b/include/openthread/ip6.h
@@ -329,8 +329,8 @@
  *
  * @retval OT_ERROR_NONE           Successfully subscribed to the Network Interface Multicast Address.
  * @retval OT_ERROR_ALREADY        The multicast address is already subscribed.
- * @retval OT_ERROR_INVALID_ARGS   The IP Address indicated by @p aAddress is invalid address.
- * @retval OT_ERROR_INVALID_STATE  The Network Interface is not up.
+ * @retval OT_ERROR_INVALID_ARGS   The IP Address indicated by @p aAddress is an invalid multicast address.
+ * @retval OT_ERROR_REJECTED       The IP Address indicated by @p aAddress is an internal multicast address.
  * @retval OT_ERROR_NO_BUFS        The Network Interface is already storing the maximum allowed external multicast
  *                                 addresses.
  *
@@ -344,8 +344,9 @@
  * @param[in]  aAddress  A pointer to an IP Address.
  *
  * @retval OT_ERROR_NONE          Successfully unsubscribed to the Network Interface Multicast Address.
- * @retval OT_ERROR_INVALID_ARGS  The IP Address indicated by @p aAddress is an internal address.
+ * @retval OT_ERROR_REJECTED      The IP Address indicated by @p aAddress is an internal address.
  * @retval OT_ERROR_NOT_FOUND     The IP Address indicated by @p aAddress was not found.
+ *
  */
 otError otIp6UnsubscribeMulticastAddress(otInstance *aInstance, const otIp6Address *aAddress);
 
@@ -692,8 +693,8 @@
 /**
  * This function perform OpenThread source address selection.
  *
- * @param[in]     aInstance     A pointer to an OpenThread instance.
- * @param[inout]  aMessageInfo  A pointer to the message information.
+ * @param[in]      aInstance     A pointer to an OpenThread instance.
+ * @param[in,out]  aMessageInfo  A pointer to the message information.
  *
  * @retval  OT_ERROR_NONE       Found a source address and is filled into mSockAddr of @p aMessageInfo.
  * @retval  OT_ERROR_NOT_FOUND  No source address was found and @p aMessageInfo is unchanged.
@@ -733,7 +734,7 @@
  * when it is about to add a SLAAC address based on a prefix. Its boolean return value determines whether the address
  * is filtered (not added) or not.
  *
- * @param[in] aInstacne   A pointer to an OpenThread instance.
+ * @param[in] aInstance   A pointer to an OpenThread instance.
  * @param[in] aPrefix     A pointer to prefix for which SLAAC address is about to be added.
  *
  * @retval TRUE    Indicates that the SLAAC address based on the prefix should be filtered and NOT added.
@@ -780,6 +781,8 @@
                                                         const otIp6Address *aFailedAddresses,
                                                         uint8_t             aFailedAddressNum);
 
+#define OT_IP6_MAX_MLR_ADDRESSES 15 ///< Max number of IPv6 addresses supported by Multicast Listener Registration.
+
 /**
  * This function registers Multicast Listeners to Primary Backbone Router.
  *
diff --git a/include/openthread/joiner.h b/include/openthread/joiner.h
index 15e35c2..a1873f7 100644
--- a/include/openthread/joiner.h
+++ b/include/openthread/joiner.h
@@ -94,7 +94,7 @@
 typedef void (*otJoinerCallback)(otError aError, void *aContext);
 
 /**
- * This function enables the Thread Joiner role.
+ * Enables the Thread Joiner role.
  *
  * @param[in]  aInstance         A pointer to an OpenThread instance.
  * @param[in]  aPskd             A pointer to the PSKd.
@@ -123,7 +123,7 @@
                       void *           aContext);
 
 /**
- * This function disables the Thread Joiner role.
+ * Disables the Thread Joiner role.
  *
  * @param[in]  aInstance  A pointer to an OpenThread instance.
  *
@@ -131,7 +131,7 @@
 void otJoinerStop(otInstance *aInstance);
 
 /**
- * This function returns the Joiner State.
+ * Gets the Joiner State.
  *
  * @param[in]  aInstance  A pointer to an OpenThread instance.
  *
@@ -146,12 +146,12 @@
 otJoinerState otJoinerGetState(otInstance *aInstance);
 
 /**
- * This method gets the Joiner ID.
+ * Gets the Joiner ID.
  *
  * If a Joiner Discerner is not set, Joiner ID is the first 64 bits of the result of computing SHA-256 over
  * factory-assigned IEEE EUI-64. Otherwise the Joiner ID is calculated from the Joiner Discerner value.
  *
- * The Joiner ID is also used as the device's IEEE 802.15.4 Extended Address during commissioning process.
+ * The Joiner ID is also used as the device's IEEE 802.15.4 Extended Address during the commissioning process.
  *
  * @param[in]   aInstance  A pointer to the OpenThread instance.
  *
@@ -161,13 +161,11 @@
 const otExtAddress *otJoinerGetId(otInstance *aInstance);
 
 /**
- * This method sets the Joiner Discerner.
+ * Sets the Joiner Discerner.
  *
- * The Joiner Discerner is used to calculate the Joiner ID used during commissioning/joining process.
- *
- * By default (when a discerner is not provided or set to NULL), Joiner ID is derived as first 64 bits of the result
- * of computing SHA-256 over factory-assigned IEEE EUI-64. Note that this is the main behavior expected by Thread
- * specification.
+ * The Joiner Discerner is used to calculate the Joiner ID during the Thread Commissioning process. For more
+ * information, refer to #otJoinerGetId.
+ * @note The Joiner Discerner takes the place of the Joiner EUI-64 during the joiner session of Thread Commissioning.
  *
  * @param[in]   aInstance    A pointer to the OpenThread instance.
  * @param[in]   aDiscerner   A pointer to a Joiner Discerner. If NULL clears any previously set discerner.
@@ -180,7 +178,7 @@
 otError otJoinerSetDiscerner(otInstance *aInstance, otJoinerDiscerner *aDiscerner);
 
 /**
- * This method gets the Joiner Discerner.
+ * Gets the Joiner Discerner. For more information, refer to #otJoinerSetDiscerner.
  *
  * @param[in]   aInstance       A pointer to the OpenThread instance.
  *
@@ -190,6 +188,16 @@
 const otJoinerDiscerner *otJoinerGetDiscerner(otInstance *aInstance);
 
 /**
+ * This function converts a given joiner state enumeration value to a human-readable string.
+ *
+ * @param[in] aState   The joiner state.
+ *
+ * @returns A human-readable string representation of @p aState.
+ *
+ */
+const char *otJoinerStateToString(otJoinerState aState);
+
+/**
  * @}
  *
  */
diff --git a/include/openthread/link.h b/include/openthread/link.h
index 2289135..0a7280c 100644
--- a/include/openthread/link.h
+++ b/include/openthread/link.h
@@ -60,11 +60,12 @@
  */
 typedef struct otThreadLinkInfo
 {
-    uint16_t mPanId;        ///< Source PAN ID
-    uint8_t  mChannel;      ///< 802.15.4 Channel
-    int8_t   mRss;          ///< Received Signal Strength in dBm.
-    uint8_t  mLqi;          ///< Link Quality Indicator for a received message.
-    bool     mLinkSecurity; ///< Indicates whether or not link security is enabled.
+    uint16_t mPanId;                   ///< Source PAN ID
+    uint8_t  mChannel;                 ///< 802.15.4 Channel
+    int8_t   mRss;                     ///< Received Signal Strength in dBm.
+    uint8_t  mLqi;                     ///< Link Quality Indicator for a received message.
+    bool     mLinkSecurity : 1;        ///< Indicates whether or not link security is enabled.
+    bool     mIsDstPanIdBroadcast : 1; ///< Indicates whether or not destination PAN ID is broadcast.
 
     // Applicable/Required only when time sync feature (`OPENTHREAD_CONFIG_TIME_SYNC_ENABLE`) is enabled.
     uint8_t mTimeSyncSeq;       ///< The time sync sequence.
@@ -378,18 +379,22 @@
  */
 typedef struct otActiveScanResult
 {
-    otExtAddress    mExtAddress;     ///< IEEE 802.15.4 Extended Address
-    otNetworkName   mNetworkName;    ///< Thread Network Name
-    otExtendedPanId mExtendedPanId;  ///< Thread Extended PAN ID
-    otSteeringData  mSteeringData;   ///< Steering Data
-    uint16_t        mPanId;          ///< IEEE 802.15.4 PAN ID
-    uint16_t        mJoinerUdpPort;  ///< Joiner UDP Port
-    uint8_t         mChannel;        ///< IEEE 802.15.4 Channel
-    int8_t          mRssi;           ///< RSSI (dBm)
-    uint8_t         mLqi;            ///< LQI
-    unsigned int    mVersion : 4;    ///< Version
-    bool            mIsNative : 1;   ///< Native Commissioner flag
-    bool            mIsJoinable : 1; ///< Joining Permitted flag
+    otExtAddress    mExtAddress;    ///< IEEE 802.15.4 Extended Address
+    otNetworkName   mNetworkName;   ///< Thread Network Name
+    otExtendedPanId mExtendedPanId; ///< Thread Extended PAN ID
+    otSteeringData  mSteeringData;  ///< Steering Data
+    uint16_t        mPanId;         ///< IEEE 802.15.4 PAN ID
+    uint16_t        mJoinerUdpPort; ///< Joiner UDP Port
+    uint8_t         mChannel;       ///< IEEE 802.15.4 Channel
+    int8_t          mRssi;          ///< RSSI (dBm)
+    uint8_t         mLqi;           ///< LQI
+    unsigned int    mVersion : 4;   ///< Version
+    bool            mIsNative : 1;  ///< Native Commissioner flag
+    bool            mDiscover : 1;  ///< Result from MLE Discovery
+
+    // Applicable/Required only when beacon payload parsing feature
+    // (`OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE`) is enabled.
+    bool mIsJoinable : 1; ///< Joining Permitted flag
 } otActiveScanResult;
 
 /**
@@ -485,7 +490,6 @@
  * @param[in] aInstance  A pointer to an OpenThread instance.
  *
  * @retval OT_ERROR_NONE           Successfully enqueued an IEEE 802.15.4 Data Request message.
- * @retval OT_ERROR_ALREADY        An IEEE 802.15.4 Data Request message is already enqueued.
  * @retval OT_ERROR_INVALID_STATE  Device is not in rx-off-when-idle mode.
  * @retval OT_ERROR_NO_BUFS        Insufficient message buffers available.
  *
@@ -772,10 +776,10 @@
  *
  * This function is available when OPENTHREAD_CONFIG_MAC_FILTER_ENABLE configuration is enabled.
  *
- * @param[in]     aInstance  A pointer to an OpenThread instance.
- * @param[inout]  aIterator  A pointer to the MAC filter iterator context. To get the first in-use address filter entry,
- *                           it should be set to OT_MAC_FILTER_ITERATOR_INIT. MUST NOT be NULL.
- * @param[out]    aEntry     A pointer to where the information is placed. MUST NOT be NULL.
+ * @param[in]      aInstance  A pointer to an OpenThread instance.
+ * @param[in,out]  aIterator  A pointer to the MAC filter iterator context. To get the first in-use address filter
+ *                            entry, it should be set to OT_MAC_FILTER_ITERATOR_INIT. MUST NOT be NULL.
+ * @param[out]     aEntry     A pointer to where the information is placed. MUST NOT be NULL.
  *
  * @retval OT_ERROR_NONE          Successfully retrieved an in-use address filter entry.
  * @retval OT_ERROR_NOT_FOUND     No subsequent entry exists.
@@ -851,12 +855,12 @@
  *
  * This function is available when OPENTHREAD_CONFIG_MAC_FILTER_ENABLE configuration is enabled.
  *
- * @param[in]     aInstance  A pointer to an OpenThread instance.
- * @param[inout]  aIterator  A pointer to the MAC filter iterator context. MUST NOT be NULL.
- *                           To get the first entry, it should be set to OT_MAC_FILTER_ITERATOR_INIT.
- * @param[out]    aEntry     A pointer to where the information is placed. The last entry would have the extended
- *                           address as all 0xff to indicate the default received signal strength if it was set.
-                             @p aEntry MUST NOT be NULL.
+ * @param[in]      aInstance  A pointer to an OpenThread instance.
+ * @param[in,out]  aIterator  A pointer to the MAC filter iterator context. MUST NOT be NULL.
+ *                            To get the first entry, it should be set to OT_MAC_FILTER_ITERATOR_INIT.
+ * @param[out]     aEntry     A pointer to where the information is placed. The last entry would have the extended
+ *                            address as all 0xff to indicate the default received signal strength if it was set.
+                              @p aEntry MUST NOT be NULL.
  *
  * @retval OT_ERROR_NONE          Successfully retrieved the next entry.
  * @retval OT_ERROR_NOT_FOUND     No subsequent entry exists.
@@ -865,6 +869,33 @@
 otError otLinkFilterGetNextRssIn(otInstance *aInstance, otMacFilterIterator *aIterator, otMacFilterEntry *aEntry);
 
 /**
+ * This function enables/disables IEEE 802.15.4 radio filter mode.
+ *
+ * This function is available when OPENTHREAD_CONFIG_MAC_FILTER_ENABLE configuration is enabled.
+ *
+ * The radio filter is mainly intended for testing. It can be used to temporarily block all tx/rx on the 802.15.4 radio.
+ * When radio filter is enabled, radio is put to sleep instead of receive (to ensure device does not receive any frame
+ * and/or potentially send ack). Also the frame transmission requests return immediately without sending the frame over
+ * the air (return "no ack" error if ack is requested, otherwise return success).
+ *
+ * @param[in] aInstance         A pointer to an OpenThread instance.
+ * @param[in] aFilterEnabled    TRUE to enable radio filter, FALSE to disable
+ *
+ */
+void otLinkSetRadioFilterEnabled(otInstance *aInstance, bool aFilterEnabled);
+
+/**
+ * This function indicates whether the IEEE 802.15.4 radio filter is enabled or not.
+ *
+ * This function is available when OPENTHREAD_CONFIG_MAC_FILTER_ENABLE configuration is enabled.
+ *
+ * @retval TRUE   If the radio filter is enabled.
+ * @retval FALSE  If the radio filter is disabled.
+ *
+ */
+bool otLinkIsRadioFilterEnabled(otInstance *aInstance);
+
+/**
  * This method converts received signal strength to link quality.
  *
  * @param[in]  aInstance  A pointer to an OpenThread instance.
diff --git a/include/openthread/link_raw.h b/include/openthread/link_raw.h
index 116fea6..02293e9 100644
--- a/include/openthread/link_raw.h
+++ b/include/openthread/link_raw.h
@@ -236,6 +236,7 @@
  * @param[in]  aCallback        A pointer to a function called on completion of a scanned channel.
  *
  * @retval OT_ERROR_NONE             Successfully started scanning the channel.
+ * @retval OT_ERROR_BUSY             The radio is performing enery scanning.
  * @retval OT_ERROR_NOT_IMPLEMENTED  The radio doesn't support energy scanning.
  * @retval OT_ERROR_INVALID_STATE    If the raw link-layer isn't enabled.
  *
diff --git a/include/openthread/logging.h b/include/openthread/logging.h
index b406301..b07e643 100644
--- a/include/openthread/logging.h
+++ b/include/openthread/logging.h
@@ -77,6 +77,144 @@
 otError otLoggingSetLevel(otLogLevel aLogLevel);
 
 /**
+ * This function emits a log message at critical log level.
+ *
+ * This function is intended for use by platform. If `OPENTHREAD_CONFIG_LOG_PLATFORM` is not set or the current log
+ * level is below critical, this function does not emit any log message.
+ *
+ * @param[in]  aFormat  The format string.
+ * @param[in]  ...      Arguments for the format specification.
+ *
+ */
+void otLogCritPlat(const char *aFormat, ...);
+
+/**
+ * This function emits a log message at warning log level.
+ *
+ * This function is intended for use by platform. If `OPENTHREAD_CONFIG_LOG_PLATFORM` is not set or the current log
+ * level is below warning, this function does not emit any log message.
+ *
+ * @param[in]  aFormat  The format string.
+ * @param[in]  ...      Arguments for the format specification.
+ *
+ */
+void otLogWarnPlat(const char *aFormat, ...);
+
+/**
+ * This function emits a log message at note log level.
+ *
+ * This function is intended for use by platform. If `OPENTHREAD_CONFIG_LOG_PLATFORM` is not set or the current log
+ * level is below note, this function does not emit any log message.
+ *
+ * @param[in]  aFormat  The format string.
+ * @param[in]  ...      Arguments for the format specification.
+ *
+ */
+void otLogNotePlat(const char *aFormat, ...);
+
+/**
+ * This function emits a log message at info log level.
+ *
+ * This function is intended for use by platform. If `OPENTHREAD_CONFIG_LOG_PLATFORM` is not set or the current log
+ * level is below info, this function does not emit any log message.
+ *
+ * @param[in]  aFormat  The format string.
+ * @param[in]  ...      Arguments for the format specification.
+ *
+ */
+void otLogInfoPlat(const char *aFormat, ...);
+
+/**
+ * This function emits a log message at debug log level.
+ *
+ * This function is intended for use by platform. If `OPENTHREAD_CONFIG_LOG_PLATFORM` is not set or the current log
+ * level is below debug, this function does not emit any log message.
+ *
+ * @param[in]  aFormat  The format string.
+ * @param[in]  ...      Arguments for the format specification.
+ *
+ */
+void otLogDebgPlat(const char *aFormat, ...);
+
+/**
+ * This function generates a memory dump at critical log level.
+ *
+ * If `OPENTHREAD_CONFIG_LOG_PLATFORM` or `OPENTHREAD_CONFIG_LOG_PKT_DUMP` is not set or the current log level is below
+ * critical this function does not emit any log message.
+ *
+ * @param[in]  aText         A string that is printed before the bytes.
+ * @param[in]  aData         A pointer to the data buffer.
+ * @param[in]  aDataLength   Number of bytes in @p aData.
+ *
+ */
+void otDumpCritPlat(const char *aText, const void *aData, uint16_t aDataLength);
+
+/**
+ * This function generates a memory dump at warning log level.
+ *
+ * If `OPENTHREAD_CONFIG_LOG_PLATFORM` or `OPENTHREAD_CONFIG_LOG_PKT_DUMP` is not set or the current log level is below
+ * warning this function does not emit any log message.
+ *
+ * @param[in]  aText         A string that is printed before the bytes.
+ * @param[in]  aData         A pointer to the data buffer.
+ * @param[in]  aDataLength   Number of bytes in @p aData.
+ *
+ */
+void otDumpWarnPlat(const char *aText, const void *aData, uint16_t aDataLength);
+
+/**
+ * This function generates a memory dump at note log level.
+ *
+ * If `OPENTHREAD_CONFIG_LOG_PLATFORM` or `OPENTHREAD_CONFIG_LOG_PKT_DUMP` is not set or the current log level is below
+ * note this function does not emit any log message.
+ *
+ * @param[in]  aText         A string that is printed before the bytes.
+ * @param[in]  aData         A pointer to the data buffer.
+ * @param[in]  aDataLength   Number of bytes in @p aData.
+ *
+ */
+void otDumpNotePlat(const char *aText, const void *aData, uint16_t aDataLength);
+
+/**
+ * This function generates a memory dump at info log level.
+ *
+ * If `OPENTHREAD_CONFIG_LOG_PLATFORM` or `OPENTHREAD_CONFIG_LOG_PKT_DUMP` is not set or the current log level is below
+ * info this function does not emit any log message.
+ *
+ * @param[in]  aText         A string that is printed before the bytes.
+ * @param[in]  aData         A pointer to the data buffer.
+ * @param[in]  aDataLength   Number of bytes in @p aData.
+ *
+ */
+void otDumpInfoPlat(const char *aText, const void *aData, uint16_t aDataLength);
+
+/**
+ * This function generates a memory dump at debug log level.
+ *
+ * If `OPENTHREAD_CONFIG_LOG_PLATFORM` or `OPENTHREAD_CONFIG_LOG_PKT_DUMP` is not set or the current log level is below
+ * debug this function does not emit any log message.
+ *
+ * @param[in]  aText         A string that is printed before the bytes.
+ * @param[in]  aData         A pointer to the data buffer.
+ * @param[in]  aDataLength   Number of bytes in @p aData.
+ *
+ */
+void otDumpDebgPlat(const char *aText, const void *aData, uint16_t aDataLength);
+
+/**
+ * This function emits a log message at a given log level.
+ *
+ * This function is intended for use by CLI only. If `OPENTHREAD_CONFIG_LOG_CLI` is not set or the current log
+ * level is below the given log level, this function does not emit any log message.
+ *
+ * @param[in]  aLogLevel The log level.
+ * @param[in]  aFormat   The format string.
+ * @param[in]  ...       Arguments for the format specification.
+ *
+ */
+void otLogCli(otLogLevel aLogLevel, const char *aFormat, ...);
+
+/**
  * @}
  *
  */
diff --git a/include/openthread/message.h b/include/openthread/message.h
index 0b1430e..d94c176 100644
--- a/include/openthread/message.h
+++ b/include/openthread/message.h
@@ -59,34 +59,6 @@
 typedef struct otMessage otMessage;
 
 /**
- * This structure represents the message buffer information.
- *
- */
-typedef struct otBufferInfo
-{
-    uint16_t mTotalBuffers;            ///< The number of buffers in the pool.
-    uint16_t mFreeBuffers;             ///< The number of free message buffers.
-    uint16_t m6loSendMessages;         ///< The number of messages in the 6lo send queue.
-    uint16_t m6loSendBuffers;          ///< The number of buffers in the 6lo send queue.
-    uint16_t m6loReassemblyMessages;   ///< The number of messages in the 6LoWPAN reassembly queue.
-    uint16_t m6loReassemblyBuffers;    ///< The number of buffers in the 6LoWPAN reassembly queue.
-    uint16_t mIp6Messages;             ///< The number of messages in the IPv6 send queue.
-    uint16_t mIp6Buffers;              ///< The number of buffers in the IPv6 send queue.
-    uint16_t mMplMessages;             ///< The number of messages in the MPL send queue.
-    uint16_t mMplBuffers;              ///< The number of buffers in the MPL send queue.
-    uint16_t mMleMessages;             ///< The number of messages in the MLE send queue.
-    uint16_t mMleBuffers;              ///< The number of buffers in the MLE send queue.
-    uint16_t mArpMessages;             ///< The number of messages in the ARP send queue.
-    uint16_t mArpBuffers;              ///< The number of buffers in the ARP send queue.
-    uint16_t mCoapMessages;            ///< The number of messages in the CoAP send queue.
-    uint16_t mCoapBuffers;             ///< The number of buffers in the CoAP send queue.
-    uint16_t mCoapSecureMessages;      ///< The number of messages in the CoAP secure send queue.
-    uint16_t mCoapSecureBuffers;       ///< The number of buffers in the CoAP secure send queue.
-    uint16_t mApplicationCoapMessages; ///< The number of messages in the application CoAP send queue.
-    uint16_t mApplicationCoapBuffers;  ///< The number of buffers in the application CoAP send queue.
-} otBufferInfo;
-
-/**
  * This enumeration defines the OpenThread message priority levels.
  *
  */
@@ -299,6 +271,35 @@
 } otMessageQueue;
 
 /**
+ * This structure represents information about a message queue.
+ *
+ */
+typedef struct otMessageQueueInfo
+{
+    uint16_t mNumMessages; ///< Number of messages in the queue.
+    uint16_t mNumBuffers;  ///< Number of data buffers used by messages in the queue.
+    uint32_t mTotalBytes;  ///< Total number of bytes used by all messages in the queue.
+} otMessageQueueInfo;
+
+/**
+ * This structure represents the message buffer information for different queues used by OpenThread stack.
+ *
+ */
+typedef struct otBufferInfo
+{
+    uint16_t           mTotalBuffers;         ///< The total number of buffers in the messages pool (0xffff if unknown).
+    uint16_t           mFreeBuffers;          ///< The number of free buffers (0xffff if unknown).
+    otMessageQueueInfo m6loSendQueue;         ///< Info about 6LoWPAN send queue.
+    otMessageQueueInfo m6loReassemblyQueue;   ///< Info about 6LoWPAN reassembly queue.
+    otMessageQueueInfo mIp6Queue;             ///< Info about IPv6 send queue.
+    otMessageQueueInfo mMplQueue;             ///< Info about MPL send queue.
+    otMessageQueueInfo mMleQueue;             ///< Info about MLE delayed message queue.
+    otMessageQueueInfo mCoapQueue;            ///< Info about CoAP/TMF send queue.
+    otMessageQueueInfo mCoapSecureQueue;      ///< Info about CoAP secure send queue.
+    otMessageQueueInfo mApplicationCoapQueue; ///< Info about application CoAP send queue.
+} otBufferInfo;
+
+/**
  * Initialize the message queue.
  *
  * This function MUST be called once and only once for a `otMessageQueue` instance before any other `otMessageQueue`
diff --git a/include/openthread/entropy.h b/include/openthread/nat64.h
similarity index 60%
copy from include/openthread/entropy.h
copy to include/openthread/nat64.h
index bc07c30..55bef4d 100644
--- a/include/openthread/entropy.h
+++ b/include/openthread/nat64.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2019, The OpenThread Authors.
+ *  Copyright (c) 2022, The OpenThread Authors.
  *  All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -29,34 +29,63 @@
 /**
  * @file
  * @brief
- *  This file defines the OpenThread entropy source API.
+ *  This file defines the OpenThread API for NAT64 on a border router.
  */
 
-#ifndef OPENTHREAD_ENTROPY_H_
-#define OPENTHREAD_ENTROPY_H_
+#ifndef OPENTHREAD_NAT64_H_
+#define OPENTHREAD_NAT64_H_
 
-#include <mbedtls/entropy.h>
+#include <openthread/message.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
- * @addtogroup api-entropy
+ * @addtogroup api-nat64
  *
- * @brief
- *   This module includes functions that manages entropy source.
+ * @brief This module includes functions and structs for the NAT64 function on the border router. These functions are
+ * only available when `OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE` is enabled.
  *
  * @{
  *
  */
 
+#define OT_IP4_ADDRESS_SIZE 4 ///< Size of an IPv4 address (bytes)
+
 /**
- * This function returns initialized mbedtls_entropy_context.
+ * @struct otIp4Address
  *
- * @returns  A pointer to initialized mbedtls_entropy_context.
+ * This structure represents an IPv4 address.
+ *
  */
-mbedtls_entropy_context *otEntropyMbedTlsContextGet(void);
+OT_TOOL_PACKED_BEGIN
+struct otIp4Address
+{
+    union OT_TOOL_PACKED_FIELD
+    {
+        uint8_t  m8[OT_IP4_ADDRESS_SIZE]; ///< 8-bit fields
+        uint32_t m32;                     ///< 32-bit representation
+    } mFields;
+} OT_TOOL_PACKED_END;
+
+/**
+ * This structure represents an IPv4 address.
+ *
+ */
+typedef struct otIp4Address otIp4Address;
+
+/**
+ * @struct otIp4Cidr
+ *
+ * This structure represents an IPv4 CIDR block.
+ *
+ */
+typedef struct otIp4Cidr
+{
+    otIp4Address mAddress;
+    uint8_t      mLength;
+} otIp4Cidr;
 
 /**
  * @}
@@ -64,7 +93,7 @@
  */
 
 #ifdef __cplusplus
-} // extern "C"
+}
 #endif
 
-#endif // OPENTHREAD_ENTROPY_H_
+#endif // OPENTHREAD_NAT64_H_
diff --git a/include/openthread/netdata.h b/include/openthread/netdata.h
index f67ea9b..74b92e8 100644
--- a/include/openthread/netdata.h
+++ b/include/openthread/netdata.h
@@ -127,11 +127,11 @@
 /**
  * This method provides a full or stable copy of the Partition's Thread Network Data.
  *
- * @param[in]     aInstance    A pointer to an OpenThread instance.
- * @param[in]     aStable      TRUE when copying the stable version, FALSE when copying the full version.
- * @param[out]    aData        A pointer to the data buffer.
- * @param[inout]  aDataLength  On entry, size of the data buffer pointed to by @p aData.
- *                             On exit, number of copied bytes.
+ * @param[in]      aInstance    A pointer to an OpenThread instance.
+ * @param[in]      aStable      TRUE when copying the stable version, FALSE when copying the full version.
+ * @param[out]     aData        A pointer to the data buffer.
+ * @param[in,out]  aDataLength  On entry, size of the data buffer pointed to by @p aData.
+ *                              On exit, number of copied bytes.
  *
  */
 otError otNetDataGet(otInstance *aInstance, bool aStable, uint8_t *aData, uint8_t *aDataLength);
@@ -139,10 +139,10 @@
 /**
  * This function gets the next On Mesh Prefix in the partition's Network Data.
  *
- * @param[in]     aInstance  A pointer to an OpenThread instance.
- * @param[inout]  aIterator  A pointer to the Network Data iterator context. To get the first on-mesh entry
-                             it should be set to OT_NETWORK_DATA_ITERATOR_INIT.
- * @param[out]    aConfig    A pointer to where the On Mesh Prefix information will be placed.
+ * @param[in]      aInstance  A pointer to an OpenThread instance.
+ * @param[in,out]  aIterator  A pointer to the Network Data iterator context. To get the first on-mesh entry
+                              it should be set to OT_NETWORK_DATA_ITERATOR_INIT.
+ * @param[out]     aConfig    A pointer to where the On Mesh Prefix information will be placed.
  *
  * @retval OT_ERROR_NONE       Successfully found the next On Mesh prefix.
  * @retval OT_ERROR_NOT_FOUND  No subsequent On Mesh prefix exists in the Thread Network Data.
@@ -155,10 +155,10 @@
 /**
  * This function gets the next external route in the partition's Network Data.
  *
- * @param[in]     aInstance  A pointer to an OpenThread instance.
- * @param[inout]  aIterator  A pointer to the Network Data iterator context. To get the first external route entry
-                             it should be set to OT_NETWORK_DATA_ITERATOR_INIT.
- * @param[out]    aConfig    A pointer to where the External Route information will be placed.
+ * @param[in]      aInstance  A pointer to an OpenThread instance.
+ * @param[in,out]  aIterator  A pointer to the Network Data iterator context. To get the first external route entry
+                              it should be set to OT_NETWORK_DATA_ITERATOR_INIT.
+ * @param[out]     aConfig    A pointer to where the External Route information will be placed.
  *
  * @retval OT_ERROR_NONE       Successfully found the next External Route.
  * @retval OT_ERROR_NOT_FOUND  No subsequent external route entry exists in the Thread Network Data.
@@ -169,10 +169,10 @@
 /**
  * This function gets the next service in the partition's Network Data.
  *
- * @param[in]     aInstance  A pointer to an OpenThread instance.
- * @param[inout]  aIterator  A pointer to the Network Data iterator context. To get the first service entry
-                             it should be set to OT_NETWORK_DATA_ITERATOR_INIT.
- * @param[out]    aConfig    A pointer to where the service information will be placed.
+ * @param[in]      aInstance  A pointer to an OpenThread instance.
+ * @param[in,out]  aIterator  A pointer to the Network Data iterator context. To get the first service entry
+                              it should be set to OT_NETWORK_DATA_ITERATOR_INIT.
+ * @param[out]     aConfig    A pointer to where the service information will be placed.
  *
  * @retval OT_ERROR_NONE       Successfully found the next service.
  * @retval OT_ERROR_NOT_FOUND  No subsequent service exists in the partition's Network Data.
@@ -231,6 +231,20 @@
                                                       const struct otJoinerDiscerner *aDiscerner);
 
 /**
+ * This function checks whether a given Prefix can act as a valid OMR prefix and also the Leader's Network Data contains
+ * this prefix.
+ *
+ * @param[in]  aInstance  A pointer to an OpenThread instance.
+ * @param[in]  aPrefix    A pointer to the IPv6 prefix.
+ *
+ * @returns  Whether @p aPrefix is a valid OMR prefix and Leader's Network Data contains the OMR prefix @p aPrefix.
+ *
+ * @note This API is only available when `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE` is used.
+ *
+ */
+bool otNetDataContainsOmrPrefix(otInstance *aInstance, const otIp6Prefix *aPrefix);
+
+/**
  * @}
  *
  */
diff --git a/include/openthread/netdata_publisher.h b/include/openthread/netdata_publisher.h
index fa44686..2c38e15 100644
--- a/include/openthread/netdata_publisher.h
+++ b/include/openthread/netdata_publisher.h
@@ -175,10 +175,10 @@
                                                 void *                                  aContext);
 
 /**
- * This function unpublishes any previously added "DNS/SRP (Anycast or Unicast) Service" entry from the Thread Network
+ * Unpublishes any previously added DNS/SRP (Anycast or Unicast) Service entry from the Thread Network
  * Data.
  *
- * This function requires the feature `OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE` to be enabled.
+ * `OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE` must be enabled.
  *
  * @param[in] aInstance  A pointer to an OpenThread instance.
  *
@@ -192,12 +192,18 @@
  *
  * Only stable entries can be published (i.e.,`aConfig.mStable` MUST be TRUE).
  *
+ * A subsequent call to this method will replace a previous request for the same prefix. In particular, if the new call
+ * only changes the flags (e.g., preference level) and the prefix is already added in the Network Data, the change to
+ * flags is immediately reflected in the Network Data. This ensures that existing entries in the Network Data are not
+ * abruptly removed. Note that a change in the preference level can potentially later cause the entry to be removed
+ * from the Network Data after determining there are other nodes that are publishing the same prefix with the same or
+ * higher preference.
+ *
  * @param[in] aInstance           A pointer to an OpenThread instance.
  * @param[in] aConfig             The on-mesh prefix config to publish (MUST NOT be NULL).
  *
  * @retval OT_ERROR_NONE          The on-mesh prefix is published successfully.
  * @retval OT_ERROR_INVALID_ARGS  The @p aConfig is not valid (bad prefix, invalid flag combinations, or not stable).
- * @retval OT_ERROR_ALREADY       An entry with the same prefix is already in the published list.
  * @retval OT_ERROR_NO_BUFS       Could not allocate an entry for the new request. Publisher supports a limited number
  *                                of entries (shared between on-mesh prefix and external route) determined by config
  *                                `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES`.
@@ -213,12 +219,18 @@
  *
  * Only stable entries can be published (i.e.,`aConfig.mStable` MUST be TRUE).
  *
+ * A subsequent call to this method will replace a previous request for the same prefix. In particular, if the new call
+ * only changes the flags (e.g., preference level) and the prefix is already added in the Network Data, the change to
+ * flags is immediately reflected in the Network Data. This ensures that existing entries in the Network Data are not
+ * abruptly removed. Note that a change in the preference level can potentially later cause the entry to be removed
+ * from the Network Data after determining there are other nodes that are publishing the same prefix with the same or
+ * higher preference.
+ *
  * @param[in] aInstance           A pointer to an OpenThread instance.
  * @param[in] aConfig             The external route config to publish (MUST NOT be NULL).
  *
  * @retval OT_ERROR_NONE          The external route is published successfully.
  * @retval OT_ERROR_INVALID_ARGS  The @p aConfig is not valid (bad prefix, invalid flag combinations, or not stable).
- * @retval OT_ERROR_ALREADY       An entry with the same prefix is already in the published list.
  * @retval OT_ERROR_NO_BUFS       Could not allocate an entry for the new request. Publisher supports a limited number
  *                                of entries (shared between on-mesh prefix and external route) determined by config
  *                                `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES`.
@@ -258,9 +270,9 @@
                                          void *                           aContext);
 
 /**
- * This function unpublishes a previously published prefix (on-mesh or external route).
+ * Unpublishes a previously published On-Mesh or External Route Prefix.
  *
- * This function requires the feature `OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE` to be enabled.
+ * `OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE` must be enabled.
  *
  * @param[in] aInstance          A pointer to an OpenThread instance.
  * @param[in] aPrefix            The prefix to unpublish (MUST NOT be NULL).
diff --git a/include/openthread/netdiag.h b/include/openthread/netdiag.h
index 2d291a0..d402383 100644
--- a/include/openthread/netdiag.h
+++ b/include/openthread/netdiag.h
@@ -264,10 +264,10 @@
 /**
  * This function gets the next Network Diagnostic TLV in the message.
  *
- * @param[in]     aMessage         A pointer to a message.
- * @param[inout]  aIterator        A pointer to the Network Diagnostic iterator context. To get the first
- *                                 Network Diagnostic TLV it should be set to OT_NETWORK_DIAGNOSTIC_ITERATOR_INIT.
- * @param[out]    aNetworkDiagTlv  A pointer to where the Network Diagnostic TLV information will be placed.
+ * @param[in]      aMessage         A pointer to a message.
+ * @param[in,out]  aIterator        A pointer to the Network Diagnostic iterator context. To get the first
+ *                                  Network Diagnostic TLV it should be set to OT_NETWORK_DIAGNOSTIC_ITERATOR_INIT.
+ * @param[out]     aNetworkDiagTlv  A pointer to where the Network Diagnostic TLV information will be placed.
  *
  * @retval OT_ERROR_NONE       Successfully found the next Network Diagnostic TLV.
  * @retval OT_ERROR_NOT_FOUND  No subsequent Network Diagnostic TLV exists in the message.
diff --git a/include/openthread/network_time.h b/include/openthread/network_time.h
index 23ab7e2..5e77231 100644
--- a/include/openthread/network_time.h
+++ b/include/openthread/network_time.h
@@ -78,8 +78,8 @@
 /**
  * Get the Thread network time.
  *
- * @param[in]    aInstance     The OpenThread instance structure.
- * @param[inout] aNetworkTime  The Thread network time in microseconds.
+ * @param[in]     aInstance     The OpenThread instance structure.
+ * @param[in,out] aNetworkTime  The Thread network time in microseconds.
  *
  * @returns The time synchronization status.
  *
diff --git a/include/openthread/platform/crypto.h b/include/openthread/platform/crypto.h
index efe40ab..7cadc8e 100644
--- a/include/openthread/platform/crypto.h
+++ b/include/openthread/platform/crypto.h
@@ -133,22 +133,19 @@
 /**
  * Initialize the Crypto module.
  *
- * @retval OT_ERROR_NONE          Successfully initialized Crypto module.
- * @retval OT_ERROR_FAILED        Failed to initialize Crypto module.
- *
  */
-otError otPlatCryptoInit(void);
+void otPlatCryptoInit(void);
 
 /**
  * Import a key into PSA ITS.
  *
- * @param[inout] aKeyRef           Pointer to the key ref to be used for crypto operations.
- * @param[in]    aKeyType          Key Type encoding for the key.
- * @param[in]    aKeyAlgorithm     Key algorithm encoding for the key.
- * @param[in]    aKeyUsage         Key Usage encoding for the key (combinations of `OT_CRYPTO_KEY_USAGE_*`).
- * @param[in]    aKeyPersistence   Key Persistence for this key
- * @param[in]    aKey              Actual key to be imported.
- * @param[in]    aKeyLen           Length of the key to be imported.
+ * @param[in,out] aKeyRef           Pointer to the key ref to be used for crypto operations.
+ * @param[in]     aKeyType          Key Type encoding for the key.
+ * @param[in]     aKeyAlgorithm     Key algorithm encoding for the key.
+ * @param[in]     aKeyUsage         Key Usage encoding for the key (combinations of `OT_CRYPTO_KEY_USAGE_*`).
+ * @param[in]     aKeyPersistence   Key Persistence for this key
+ * @param[in]     aKey              Actual key to be imported.
+ * @param[in]     aKeyLen           Length of the key to be imported.
  *
  * @retval OT_ERROR_NONE          Successfully imported the key.
  * @retval OT_ERROR_FAILED        Failed to import the key.
@@ -377,7 +374,7 @@
  *
  * @param[in]  aContext           Operation context for HKDF operation.
  * @param[in]  aSalt              Pointer to the Salt for HKDF.
- * @param[in]  aInfoLength        length of Salt.
+ * @param[in]  aSaltLength        Length of Salt.
  * @param[in]  aInputKey          Pointer to the input key.
  *
  * @retval OT_ERROR_NONE          HKDF Extract was successful.
@@ -458,7 +455,6 @@
  * Finish SHA-256 operation.
  *
  * @param[in]  aContext           Context for SHA-256 operation.
- * @param[in]  aContextSize       Context size SHA-256 operation.
  * @param[in]  aHash              A pointer to the output buffer, where hash needs to be stored.
  * @param[in]  aHashSize          The length of @p aHash in bytes.
  *
@@ -470,6 +466,30 @@
 otError otPlatCryptoSha256Finish(otCryptoContext *aContext, uint8_t *aHash, uint16_t aHashSize);
 
 /**
+ * Initialize cryptographically-secure pseudorandom number generator (CSPRNG).
+ *
+ */
+void otPlatCryptoRandomInit(void);
+
+/**
+ * Deinitialize cryptographically-secure pseudorandom number generator (CSPRNG).
+ *
+ */
+void otPlatCryptoRandomDeinit(void);
+
+/**
+ * Fills a given buffer with cryptographically secure random bytes.
+ *
+ * @param[out] aBuffer  A pointer to a buffer to fill with the random bytes.
+ * @param[in]  aSize    Size of buffer (number of bytes to fill).
+ *
+ * @retval OT_ERROR_NONE     Successfully filled buffer with random values.
+ * @retval OT_ERROR_FAILED   Operation failed.
+ *
+ */
+otError otPlatCryptoRandomGet(uint8_t *aBuffer, uint16_t aSize);
+
+/**
  * @}
  *
  */
diff --git a/include/openthread/platform/dso_transport.h b/include/openthread/platform/dso_transport.h
new file mode 100644
index 0000000..348ee82
--- /dev/null
+++ b/include/openthread/platform/dso_transport.h
@@ -0,0 +1,202 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ * @brief
+ *   This file includes the platform abstraction for DNS Stateful Operations (DSO) transport.
+ */
+
+#ifndef OPENTHREAD_PLATFORM_DSO_TRANSPORT_H_
+#define OPENTHREAD_PLATFORM_DSO_TRANSPORT_H_
+
+#include <stdint.h>
+
+#include <openthread/error.h>
+#include <openthread/instance.h>
+#include <openthread/ip6.h>
+#include <openthread/message.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This structure represents a DSO connection.
+ *
+ * It is an opaque struct (the platform implementation only deals with pointers to this struct).
+ *
+ */
+typedef struct otPlatDsoConnection otPlatDsoConnection;
+
+/**
+ * This function can be used by DSO platform implementation to get the the OpenThread instance associated with a
+ * connection instance.
+ *
+ * @param[in] aConnection   A pointer to the DSO connection.
+ *
+ * @returns A pointer to the `otInstance`.
+ *
+ */
+extern otInstance *otPlatDsoGetInstance(otPlatDsoConnection *aConnection);
+
+/**
+ * This function starts or stops listening for incoming connection requests on transport layer.
+ *
+ * For DNS-over-TLS, the transport layer MUST listen on port 853 and follow RFC 7858.
+ *
+ * While listening is enabled, if a connection request is received, the `otPlatDsoAccept()` callback MUST be called.
+ *
+ * @param[in] aInstance    The OpenThread instance.
+ * @param[in] aEnable      TRUE to start listening, FALSE to stop listening.
+ *
+ */
+void otPlatDsoEnableListening(otInstance *aInstance, bool aEnable);
+
+/**
+ * This function is a callback from the DSO platform to indicate an incoming connection request when listening is
+ * enabled.
+ *
+ * This function determines whether or not to accept the connection request. It returns a non-null `otPlatDsoConnection`
+ * pointer if the request is to be accepted, or `NULL` if the request is to be rejected.
+ *
+ * If a non-null connection pointer is returned, the platform layer MUST continue establishing the connection with the
+ * peer. The platform reports the outcome by invoking `otPlatDsoHandleConnected()` callback on success or
+ * `otPlatDsoHandleDisconnected()` callback on failure.
+ *
+ * @param[in] aInstance      The OpenThread instance.
+ * @param[in] aPeerSockAddr  The socket address (IPv6 address and port number) of the peer requesting connection.
+ *
+ * @returns A pointer to the `otPlatDsoConnection` to use if to accept, or `NULL` if to reject.
+ *
+ */
+extern otPlatDsoConnection *otPlatDsoAccept(otInstance *aInstance, const otSockAddr *aPeerSockAddr);
+
+/**
+ * This function requests the platform layer to initiate establishing a connection with a peer.
+ *
+ * The platform reports the outcome by invoking `otPlatDsoHandleConnected()` callback on success or
+ * `otPlatDsoHandleDisconnected()` callback (on failure).
+ *
+ * @param[in] aConnection     The connection.
+ * @param[in] aPeerSockAddr   The socket address (IPv6 address and port number) of the peer to connect to.
+ *
+ */
+void otPlatDsoConnect(otPlatDsoConnection *aConnection, const otSockAddr *aPeerSockAddr);
+
+/**
+ * This function is a callback from the platform layer to indicate that a connection is successfully established.
+ *
+ * It MUST be called either after accepting an incoming connection (`otPlatDsoAccept`) or after a `otPlatDsoConnect()`
+ * call.
+ *
+ * Only after this callback, the connection can be used to send and receive messages.
+ *
+ * @param[in] aConnection     The connection.
+ *
+ */
+extern void otPlatDsoHandleConnected(otPlatDsoConnection *aConnection);
+
+/**
+ * This function sends a DSO message to the peer on a connection.
+ *
+ * This function is used only after the connection is successfully established (after `otPlatDsoHandleConnected()`
+ * callback).
+ *
+ * This function passes the ownership of the @p aMessage to the DSO platform layer, and the platform implementation is
+ * expected to free the message once it is no longer needed.
+ *
+ * The @p aMessage contains the DNS message (starting with DNS header). Note that it does not contain the the length
+ * field that is needed when sending over TLS/TCP transport. The platform layer MUST therefore include the length
+ * field when passing the message to TLS/TCP layer.
+ *
+ * @param[in] aConnection   The connection to send on.
+ * @param[in] aMessage      The message to send.
+ *
+ */
+void otPlatDsoSend(otPlatDsoConnection *aConnection, otMessage *aMessage);
+
+/**
+ * This function is a callback from the platform layer to indicate that a DNS message was received over a connection.
+ *
+ * The platform MUST call this function only after the connection is successfully established (after callback
+ * `otPlatDsoHandleConnected()` is invoked).
+ *
+ * This function passes the ownership of the @p aMessage from the DSO platform layer to OpenThread. OpenThread will
+ * free the message when no longer needed.
+ *
+ * The @p aMessage MUST contain the DNS message (starting with DNS header) and not include the length field that may
+ * be included in TCP/TLS exchange.
+ *
+ * @param[in] aConnection   The connection on which the message was received.
+ * @param[in] aMessage      The received message.
+ *
+ */
+extern void otPlatDsoHandleReceive(otPlatDsoConnection *aConnection, otMessage *aMessage);
+
+/**
+ * This enumeration defines disconnect modes.
+ *
+ */
+typedef enum
+{
+    OT_PLAT_DSO_DISCONNECT_MODE_GRACEFULLY_CLOSE, ///< Gracefully close the connection.
+    OT_PLAT_DSO_DISCONNECT_MODE_FORCIBLY_ABORT,   ///< Forcibly abort the connection.
+} otPlatDsoDisconnectMode;
+
+/**
+ * This function requests a connection to be disconnected.
+ *
+ * After calling this function, the DSO platform implementation MUST NOT maintain `aConnection` pointer (platform
+ * MUST NOT call any callbacks using this `Connection` pointer anymore). In particular, calling `otPlatDsoDisconnect()`
+ * MUST NOT trigger the callback `otPlatDsoHandleDisconnected()`.
+ *
+ * @param[in] aConnection   The connection to disconnect
+ * @param[in] aMode         The disconnect mode (close gracefully or forcibly abort).
+ *
+ */
+void otPlatDsoDisconnect(otPlatDsoConnection *aConnection, otPlatDsoDisconnectMode aMode);
+
+/**
+ * This function is a callback from the platform layer to indicate that peer closed/aborted the connection or the
+ * connection establishment failed (e.g., peer rejected a connection request).
+ *
+ * After calling this function, the DSO platform implementation MUST NOT maintain `aConnection` pointer (platform
+ * MUST NOT call any callbacks using this `Connection` pointer anymore).
+ *
+ * @param[in] aConnection   The connection which disconnected.
+ * @param[in] aMode         The disconnect mode (closed gracefully or forcibly aborted).
+ *
+ */
+extern void otPlatDsoHandleDisconnected(otPlatDsoConnection *aConnection, otPlatDsoDisconnectMode aMode);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_PLATFORM_DSO_TRANSPORT_H_
diff --git a/include/openthread/platform/infra_if.h b/include/openthread/platform/infra_if.h
index 7bd18e0..9242213 100644
--- a/include/openthread/platform/infra_if.h
+++ b/include/openthread/platform/infra_if.h
@@ -47,6 +47,16 @@
 #endif
 
 /**
+ * @addtogroup plat-infra-if
+ *
+ * @brief
+ *   This module includes the platform abstraction for the adjacent infrastructure network interface.
+ *
+ * @{
+ *
+ */
+
+/**
  * This method tells whether an infra interface has the given IPv6 address assigned.
  *
  * @param[in]  aInfraIfIndex  The index of the infra interface.
@@ -123,6 +133,11 @@
  */
 extern otError otPlatInfraIfStateChanged(otInstance *aInstance, uint32_t aInfraIfIndex, bool aIsRunning);
 
+/**
+ * @}
+ *
+ */
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
diff --git a/include/openthread/platform/logging.h b/include/openthread/platform/logging.h
index acf88cd..adf123f 100644
--- a/include/openthread/platform/logging.h
+++ b/include/openthread/platform/logging.h
@@ -115,6 +115,10 @@
 /**
  * This enumeration represents log regions.
  *
+ * The support for log region is removed and instead each core module can define its own name to appended to the logs.
+ * However, the `otLogRegion` enumeration is still defined as before to help with platforms which we may be using it
+ * in their `otPlatLog()` implementation. The OT core will always emit all logs with `OT_LOG_REGION_CORE`.
+ *
  */
 typedef enum otLogRegion
 {
@@ -146,6 +150,9 @@
 /**
  * This function outputs logs.
  *
+ * Note that the support for log region is removed. The OT core will always emit all logs with `OT_LOG_REGION_CORE`
+ * as @p aLogRegion.
+ *
  * @param[in]  aLogLevel   The log level.
  * @param[in]  aLogRegion  The log region.
  * @param[in]  aFormat     A pointer to the format string.
@@ -155,20 +162,17 @@
 void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...);
 
 /**
- * This (optional) platform function outputs a prepared log line.
+ * This function handles OpenThread log level changes.
  *
- * This platform function is used by OpenThread core when `OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY` is not enabled
- * (in this case, the OT core itself will prepare a full log line).
+ * This platform function is called whenever the OpenThread log level changes.
+ * This platform function is optional since an empty weak implementation has been provided.
  *
- * Note that this function is optional and if not provided by platform layer, a default (weak) implementation is
- * provided and used by OpenThread core as `otPlatLog(aLogLevel, aLogResion, "%s", aLogLine)`.
+ * @note Only applicable when `OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE=1`.
  *
- * @param[in]  aLogLevel   The log level.
- * @param[in]  aLogRegion  The log region.
- * @param[in]  aLogLine    A pointer to a log line string.
+ * @param[in]  aLogLevel  The new OpenThread log level.
  *
  */
-void otPlatLogLine(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aLogLine);
+void otPlatLogHandleLevelChanged(otLogLevel aLogLevel);
 
 /**
  * @}
diff --git a/include/openthread/platform/radio.h b/include/openthread/platform/radio.h
index 02e58ae..b95acd5 100644
--- a/include/openthread/platform/radio.h
+++ b/include/openthread/platform/radio.h
@@ -57,7 +57,7 @@
  */
 
 /**
- * @defgroup radio-types Types
+ * @defgroup radio-types Radio Types
  *
  * @brief
  *   This module includes the platform abstraction for a radio frame.
@@ -399,7 +399,7 @@
  */
 
 /**
- * @defgroup radio-config Configuration
+ * @defgroup radio-config Radio Configuration
  *
  * @brief
  *   This module includes the platform abstraction for radio configuration.
@@ -442,7 +442,7 @@
 int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance);
 
 /**
- * Get the factory-assigned IEEE EUI-64 for this interface.
+ * Gets the factory-assigned IEEE EUI-64 for this interface.
  *
  * @param[in]  aInstance   The OpenThread instance structure.
  * @param[out] aIeeeEui64  A pointer to the factory-assigned IEEE EUI-64.
@@ -614,7 +614,10 @@
 void otPlatRadioSetMacFrameCounter(otInstance *aInstance, uint32_t aMacFrameCounter);
 
 /**
- * Get the current estimated time (64bits width) of the radio chip.
+ * Get the current estimated time (in microseconds) of the radio chip.
+ *
+ * This microsecond timer must be a free-running timer. The timer must continue to advance with microsecond precision
+ * even when the radio is in the sleep state.
  *
  * @param[in]   aInstance    A pointer to an OpenThread instance.
  *
@@ -640,7 +643,7 @@
  */
 
 /**
- * @defgroup radio-operation Operation
+ * @defgroup radio-operation Radio Operation
  *
  * @brief
  *   This module includes the platform abstraction for radio operations.
@@ -854,6 +857,7 @@
  * @param[in] aScanDuration  The duration, in milliseconds, for the channel to be scanned.
  *
  * @retval OT_ERROR_NONE             Successfully started scanning the channel.
+ * @retval OT_ERROR_BUSY             The radio is performing enery scanning.
  * @retval OT_ERROR_NOT_IMPLEMENTED  The radio doesn't support energy scanning.
  *
  */
@@ -1057,14 +1061,14 @@
 uint8_t otPlatRadioGetCslAccuracy(otInstance *aInstance);
 
 /**
- * Get the current uncertainty, in units of 10 us, of the clock used for scheduling CSL operations.
+ * The fixed uncertainty of the Device for scheduling CSL Transmissions in units of 10 microseconds.
  *
  * @param[in]   aInstance    A pointer to an OpenThread instance.
  *
- * @returns The current CSL Clock Uncertainty in units of 10 us.
+ * @returns The CSL Uncertainty in units of 10 us.
  *
  */
-uint8_t otPlatRadioGetCslClockUncertainty(otInstance *aInstance);
+uint8_t otPlatRadioGetCslUncertainty(otInstance *aInstance);
 
 /**
  * Set the max transmit power for a specific channel.
@@ -1123,8 +1127,8 @@
  * @param[in]  aInstance     The OpenThread instance structure.
  * @param[in]  aLinkMetrics  This parameter specifies what metrics to query. Per spec 4.11.3.4.4.6, at most 2 metrics
  *                           can be specified. The probing would be disabled if @p `aLinkMetrics` is bitwise 0.
- * @param[in]  aShortAddr    The short address of the Probing Initiator.
- * @param[in]  aExtAddr      The extended source address of the Probing Initiator. @p aExtAddr MUST NOT be `NULL`.
+ * @param[in]  aShortAddress The short address of the Probing Initiator.
+ * @param[in]  aExtAddress   The extended source address of the Probing Initiator. @p aExtAddr MUST NOT be `NULL`.
  *
  * @retval  OT_ERROR_NONE            Successfully configured the Enhanced-ACK Based Probing.
  * @retval  OT_ERROR_INVALID_ARGS    @p aExtAddress is `NULL`.
diff --git a/include/openthread/platform/settings.h b/include/openthread/platform/settings.h
index 17a68a0..2a4892b 100644
--- a/include/openthread/platform/settings.h
+++ b/include/openthread/platform/settings.h
@@ -54,8 +54,9 @@
 /**
  * This enumeration defines the keys of settings.
  *
- * Note: When adding a new setings key, if the settings corresponding to the key contains security sensitive
- *       information, the developer MUST add the key to the array `kCriticalKeys`.
+ * Note: When adding a new settings key, if the settings corresponding to the key contains security sensitive
+ *       information, the developer MUST add the key to the array `aSensitiveKeys` which is passed in
+ *       `otPlatSettingsInit()`.
  *
  */
 enum
@@ -65,23 +66,39 @@
     OT_SETTINGS_KEY_NETWORK_INFO         = 0x0003, ///< Thread network information.
     OT_SETTINGS_KEY_PARENT_INFO          = 0x0004, ///< Parent information.
     OT_SETTINGS_KEY_CHILD_INFO           = 0x0005, ///< Child information.
-    OT_SETTINGS_KEY_RESERVED             = 0x0006, ///< Reserved (previously auto-start).
     OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY = 0x0007, ///< SLAAC key to generate semantically opaque IID.
     OT_SETTINGS_KEY_DAD_INFO             = 0x0008, ///< Duplicate Address Detection (DAD) information.
-    OT_SETTINGS_KEY_OMR_PREFIX           = 0x0009, ///< Off-mesh routable (OMR) prefix.
-    OT_SETTINGS_KEY_ON_LINK_PREFIX       = 0x000a, ///< On-link prefix for infrastructure link.
     OT_SETTINGS_KEY_SRP_ECDSA_KEY        = 0x000b, ///< SRP client ECDSA public/private key pair.
     OT_SETTINGS_KEY_SRP_CLIENT_INFO      = 0x000c, ///< The SRP client info (selected SRP server address).
     OT_SETTINGS_KEY_SRP_SERVER_INFO      = 0x000d, ///< The SRP server info (UDP port).
+    OT_SETTINGS_KEY_BR_ULA_PREFIX        = 0x000f, ///< BR ULA prefix.
+
+    // Deprecated and reserved key values:
+    //
+    //   0x0006  previously auto-start.
+    //   0x0009  previously OMR prefix.
+    //   0x000a  previously on-link prefix.
+    //   0x000e  previously NAT64 prefix.
+
+    // Keys in range 0x8000-0xffff are reserved for vendor-specific use.
+    OT_SETTINGS_KEY_VENDOR_RESERVED_MIN = 0x8000,
+    OT_SETTINGS_KEY_VENDOR_RESERVED_MAX = 0xffff,
 };
 
 /**
  * Performs any initialization for the settings subsystem, if necessary.
  *
- * @param[in]  aInstance The OpenThread instance structure.
+ * This function also sets the sensitive keys that should be stored in the secure area.
+ *
+ * Note that the memory pointed by @p aSensitiveKeys MUST not be released before @p aInstance is destroyed.
+ *
+ * @param[in]  aInstance             The OpenThread instance structure.
+ * @param[in]  aSensitiveKeys        A pointer to an array containing the list of sensitive keys. May be NULL only if
+ *                                   @p aSensitiveKeysLength is 0, which means that there is no sensitive keys.
+ * @param[in]  aSensitiveKeysLength  The number of entries in the @p aSensitiveKeys array.
  *
  */
-void otPlatSettingsInit(otInstance *aInstance);
+void otPlatSettingsInit(otInstance *aInstance, const uint16_t *aSensitiveKeys, uint16_t aSensitiveKeysLength);
 
 /**
  * Performs any de-initialization for the settings subsystem, if necessary.
@@ -92,91 +109,99 @@
 void otPlatSettingsDeinit(otInstance *aInstance);
 
 /**
- * This function sets the critical keys that should be stored in the secure area.
+ * Fetches the value of a setting.
  *
- * Note that the memory pointed by @p aKeys MUST not be released before @p aInstance is destroyed.
+ * This function fetches the value of the setting identified
+ * by @p aKey and write it to the memory pointed to by aValue.
+ * It then writes the length to the integer pointed to by
+ * @p aValueLength. The initial value of @p aValueLength is the
+ * maximum number of bytes to be written to @p aValue.
  *
- * @param[in]  aInstance    The OpenThread instance structure.
- * @param[in]  aKeys        A pointer to an array containing the list of critical keys.
- * @param[in]  aKeysLength  The number of entries in the @p aKeys array.
+ * This function can be used to check for the existence of
+ * a key without fetching the value by setting @p aValue and
+ * @p aValueLength to NULL. You can also check the length of
+ * the setting without fetching it by setting only aValue
+ * to NULL.
  *
- */
-void otPlatSettingsSetCriticalKeys(otInstance *aInstance, const uint16_t *aKeys, uint16_t aKeysLength);
-
-/// Fetches the value of a setting
-/** This function fetches the value of the setting identified
- *  by aKey and write it to the memory pointed to by aValue.
- *  It then writes the length to the integer pointed to by
- *  aValueLength. The initial value of aValueLength is the
- *  maximum number of bytes to be written to aValue.
+ * Note that the underlying storage implementation is not
+ * required to maintain the order of settings with multiple
+ * values. The order of such values MAY change after ANY
+ * write operation to the store.
  *
- *  This function can be used to check for the existence of
- *  a key without fetching the value by setting aValue and
- *  aValueLength to NULL. You can also check the length of
- *  the setting without fetching it by setting only aValue
- *  to NULL.
- *
- *  Note that the underlying storage implementation is not
- *  required to maintain the order of settings with multiple
- *  values. The order of such values MAY change after ANY
- *  write operation to the store.
- *
- *  @param[in]     aInstance     The OpenThread instance structure.
- *  @param[in]     aKey          The key associated with the requested setting.
- *  @param[in]     aIndex        The index of the specific item to get.
- *  @param[out]    aValue        A pointer to where the value of the setting should be written. May be set to NULL if
+ * @param[in]      aInstance     The OpenThread instance structure.
+ * @param[in]      aKey          The key associated with the requested setting.
+ * @param[in]      aIndex        The index of the specific item to get.
+ * @param[out]     aValue        A pointer to where the value of the setting should be written. May be set to NULL if
  *                               just testing for the presence or length of a setting.
- *  @param[inout]  aValueLength  A pointer to the length of the value. When called, this pointer should point to an
- *                               integer containing the maximum value size that can be written to aValue. At return,
+ * @param[in,out]  aValueLength  A pointer to the length of the value. When called, this pointer should point to an
+ *                               integer containing the maximum value size that can be written to @p aValue. At return,
  *                               the actual length of the setting is written. This may be set to NULL if performing
  *                               a presence check.
  *
- *  @retval OT_ERROR_NONE             The given setting was found and fetched successfully.
- *  @retval OT_ERROR_NOT_FOUND        The given setting was not found in the setting store.
- *  @retval OT_ERROR_NOT_IMPLEMENTED  This function is not implemented on this platform.
+ * @retval OT_ERROR_NONE             The given setting was found and fetched successfully.
+ * @retval OT_ERROR_NOT_FOUND        The given setting was not found in the setting store.
+ * @retval OT_ERROR_NOT_IMPLEMENTED  This function is not implemented on this platform.
  */
 otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength);
 
-/// Sets or replaces the value of a setting
-/** This function sets or replaces the value of a setting
- *  identified by aKey. If there was more than one
- *  value previously associated with aKey, then they are
- *  all deleted and replaced with this single entry.
+/**
+ * Sets or replaces the value of a setting.
  *
- *  Calling this function successfully may cause unrelated
- *  settings with multiple values to be reordered.
+ * This function sets or replaces the value of a setting
+ * identified by @p aKey.
  *
- *  @param[in]  aInstance     The OpenThread instance structure.
- *  @param[in]  aKey          The key associated with the setting to change.
- *  @param[in]  aValue        A pointer to where the new value of the setting should be read from. MUST NOT be NULL if
- *                            aValueLength is non-zero.
- *  @param[in]  aValueLength  The length of the data pointed to by aValue. May be zero.
+ * Calling this function successfully may cause unrelated
+ * settings with multiple values to be reordered.
  *
- *  @retval OT_ERROR_NONE             The given setting was changed or staged.
- *  @retval OT_ERROR_NOT_IMPLEMENTED  This function is not implemented on this platform.
- *  @retval OT_ERROR_NO_BUFS          No space remaining to store the given setting.
+ * OpenThread stack guarantees to use `otPlatSettingsSet()`
+ * method for a @p aKey that was either previously set using
+ * `otPlatSettingsSet()` (i.e., contains a single value) or
+ * is empty and/or fully deleted (contains no value).
+ *
+ * Platform layer can rely and use this fact for optimizing
+ * its implementation.
+ *
+ * @param[in]  aInstance     The OpenThread instance structure.
+ * @param[in]  aKey          The key associated with the setting to change.
+ * @param[in]  aValue        A pointer to where the new value of the setting should be read from. MUST NOT be NULL if
+ *                           @p aValueLength is non-zero.
+ * @param[in]  aValueLength  The length of the data pointed to by aValue. May be zero.
+ *
+ * @retval OT_ERROR_NONE             The given setting was changed or staged.
+ * @retval OT_ERROR_NOT_IMPLEMENTED  This function is not implemented on this platform.
+ * @retval OT_ERROR_NO_BUFS          No space remaining to store the given setting.
  */
 otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
 
-/// Adds a value to a setting
-/** This function adds the value to a setting
- *  identified by aKey, without replacing any existing
- *  values.
+/**
+ * Adds a value to a setting.
  *
- *  Note that the underlying implementation is not required
- *  to maintain the order of the items associated with a
- *  specific key. The added value may be added to the end,
- *  the beginning, or even somewhere in the middle. The order
- *  of any pre-existing values may also change.
+ * This function adds the value to a setting
+ * identified by @p aKey, without replacing any existing
+ * values.
  *
- *  Calling this function successfully may cause unrelated
- *  settings with multiple values to be reordered.
+ * Note that the underlying implementation is not required
+ * to maintain the order of the items associated with a
+ * specific key. The added value may be added to the end,
+ * the beginning, or even somewhere in the middle. The order
+ * of any pre-existing values may also change.
+ *
+ * Calling this function successfully may cause unrelated
+ * settings with multiple values to be reordered.
+ *
+ * OpenThread stack guarantees to use `otPlatSettingsAdd()`
+ * method for a @p aKey that was either previously managed by
+ * `otPlatSettingsAdd()` (i.e., contains one or more items) or
+ * is empty and/or fully deleted (contains no value).
+ *
+ * Platform layer can rely and use this fact for optimizing
+ * its implementation.
  *
  * @param[in]  aInstance     The OpenThread instance structure.
  * @param[in]  aKey          The key associated with the setting to change.
  * @param[in]  aValue        A pointer to where the new value of the setting should be read from. MUST NOT be NULL
- *                           if aValueLength is non-zero.
- * @param[in]  aValueLength  The length of the data pointed to by aValue. May be zero.
+ *                           if @p aValueLength is non-zero.
+ * @param[in]  aValueLength  The length of the data pointed to by @p aValue. May be zero.
  *
  * @retval OT_ERROR_NONE             The given setting was added or staged to be added.
  * @retval OT_ERROR_NOT_IMPLEMENTED  This function is not implemented on this platform.
@@ -184,29 +209,34 @@
  */
 otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
 
-/// Removes a setting from the setting store
-/** This function deletes a specific value from the
- *  setting identified by aKey from the settings store.
+/**
+ * Removes a setting from the setting store.
  *
- *  Note that the underlying implementation is not required
- *  to maintain the order of the items associated with a
- *  specific key.
+ * This function deletes a specific value from the
+ * setting identified by aKey from the settings store.
  *
- *  @param[in] aInstance  The OpenThread instance structure.
- *  @param[in] aKey       The key associated with the requested setting.
- *  @param[in] aIndex     The index of the value to be removed. If set to -1, all values for this aKey will be removed.
+ * Note that the underlying implementation is not required
+ * to maintain the order of the items associated with a
+ * specific key.
  *
- *  @retval OT_ERROR_NONE             The given key and index was found and removed successfully.
- *  @retval OT_ERROR_NOT_FOUND        The given key or index was not found in the setting store.
- *  @retval OT_ERROR_NOT_IMPLEMENTED  This function is not implemented on this platform.
+ * @param[in] aInstance  The OpenThread instance structure.
+ * @param[in] aKey       The key associated with the requested setting.
+ * @param[in] aIndex     The index of the value to be removed. If set to -1, all values for this @p aKey will be
+ *                       removed.
+ *
+ * @retval OT_ERROR_NONE             The given key and index was found and removed successfully.
+ * @retval OT_ERROR_NOT_FOUND        The given key or index was not found in the setting store.
+ * @retval OT_ERROR_NOT_IMPLEMENTED  This function is not implemented on this platform.
  */
 otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex);
 
-/// Removes all settings from the setting store
-/** This function deletes all settings from the settings
- *  store, resetting it to its initial factory state.
+/**
+ * Removes all settings from the setting store.
  *
- *  @param[in] aInstance  The OpenThread instance structure.
+ * This function deletes all settings from the settings
+ * store, resetting it to its initial factory state.
+ *
+ * @param[in] aInstance  The OpenThread instance structure.
  */
 void otPlatSettingsWipe(otInstance *aInstance);
 
diff --git a/include/openthread/platform/trel-udp6.h b/include/openthread/platform/trel-udp6.h
deleted file mode 100644
index 4c0f9e2..0000000
--- a/include/openthread/platform/trel-udp6.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- *  Copyright (c) 2019, The OpenThread Authors.
- *  All rights reserved.
- *
- *  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, 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
- * @brief
- *   This file includes the platform abstraction for Thread Radio Encapsulation Link (TREL) using an IPv6/UDP interface.
- *
- */
-
-#ifndef OPENTHREAD_PLATFORM_TREL_UDP6_H_
-#define OPENTHREAD_PLATFORM_TREL_UDP6_H_
-
-#include <stdint.h>
-
-#include <openthread/error.h>
-#include <openthread/instance.h>
-#include <openthread/ip6.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @addtogroup plat-trel
- *
- * @brief
- *   This module includes the platform abstraction for Thread Radio Encapsulation Link (TREL) using an IPv6/UDP
- *   interface.
- *
- * @{
- *
- */
-
-/**
- * This function initializes the TREL IPv6/UDP interface.
- *
- * This function is called before any other TREL platform functions.
- *
- * @param[in] aInstance        The OpenThread instance structure.
- * @param[in] aUnicastAddress  The unicast address to add to interface and use as tx source and rx destination.
- * @param[in] aUdpPort         A UDP port number to use.
- *
- */
-void otPlatTrelUdp6Init(otInstance *aInstance, const otIp6Address *aUnicastAddress, uint16_t aUdpPort);
-
-/**
- * This function updates the unicast IPv6 address for TREL IPv6/UDP interface.
- *
- * The interface should only have one unicast IPv6 address. Calling this function replaces any previously set unicast
- * IPv6 address (during initialization from `otPlatTrelUdp6Init` or earlier calls to `otPlatTrelUdp6UpdateAddress()`).
- *
- * @param[in] aInstance        The OpenThread instance structure.
- * @param[in] aUnicastAddress  The unicast address to add to interface and use for as tx source and rx destination.
- *
- */
-void otPlatTrelUdp6UpdateAddress(otInstance *aInstance, const otIp6Address *aUnicastAddress);
-
-/**
- * This function subscribes the TREL IPv6/UDP interface to a new multicast address.
- *
- * This function may be called multiple times to subscribe to different addresses. The interface should accept/receive
- * packets destined to any previously subscribed multicast address in addition to the unicast address added from the
- * `otPlatTrelUdp6Init()` function when interface was initialized.
- *
- * @param[in] aInstance          The OpenThread instance structure.
- * @param[in] aMulticastAddress  A multicast IPv6 address.
- *
- */
-void otPlatTrelUdp6SubscribeMulticastAddress(otInstance *aInstance, const otIp6Address *aMulticastAddress);
-
-/**
- * This function requests a packet to be sent to a given destination.
- *
- * @param[in] aInstance        The OpenThread instance structure.
- * @param[in] aBuffer          A pointer to buffer containing the packet to send.
- * @param[in] aLength          Packet length (number of bytes).
- * @param[in] aDestAddress     The destination IPv6 address (can be a unicast or a multicast IPv6 address).
- *
- * @retval OT_ERROR_NONE    The tx request was handled successfully.
- * @retval OT_ERROR_ABORT   The interface is not ready and tx was aborted
- *
- */
-otError otPlatTrelUdp6SendTo(otInstance *        aInstance,
-                             const uint8_t *     aBuffer,
-                             uint16_t            aLength,
-                             const otIp6Address *aDestAddress);
-
-/**
- * This function is a callback from platform to notify of a received packet.
- *
- * @note The buffer content (up to its specified length) may get changed during processing by OpenThread core (e.g.,
- * decrypted in place), so the platform implementation should expect that after returning from this function the
- * packet @p aBuffer content may have been altered.
- *
- * @param[in] aInstance        The OpenThread instance structure.
- * @param[in] aBuffer          A buffer containing the received packet.
- * @param[in] aLength          Packet length (number of bytes).
- *
- */
-extern void otPlatTrelUdp6HandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength);
-
-/**
- * This optional function is intended for testing only. It changes the test mode status for TREL interface.
- *
- * This function requests TREL interface to be temporarily disabled or enabled. When disabled all traffic flow through
- * the TREL interface should be silently dropped.
- *
- * A default weak implementation of this method is provided by OpenThread (returning NOT_IMPLEMENTED).
- *
- * @param[in] aInstance        The OpenThread instance structure.
- * @param[in] aEnable          Indicates whether to enable/disable the TREL interface.
- *
- * @retval OT_ERROR_NONE             Successfully changed the TREL interface test status (enabled/disabled).
- * @retval OT_ERROR_FAILED           Failed to enable the TREL interface.
- * @retval OT_ERROR_NOT_IMPLEMENTED  This function is not provided by the platform.
- *
- */
-otError otPlatTrelUdp6SetTestMode(otInstance *aInstance, bool aEnable);
-
-/**
- * @}
- *
- */
-
-#ifdef __cplusplus
-} // end of extern "C"
-#endif
-
-#endif // OPENTHREAD_PLATFORM_TREL_UDP6_H_
diff --git a/include/openthread/platform/trel.h b/include/openthread/platform/trel.h
new file mode 100644
index 0000000..d4e0475
--- /dev/null
+++ b/include/openthread/platform/trel.h
@@ -0,0 +1,209 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ * @brief
+ *   This file includes the platform abstraction for Thread Radio Encapsulation Link (TREL) using DNS-SD and UDP/IPv6.
+ *
+ */
+
+#ifndef OPENTHREAD_PLATFORM_TREL_H_
+#define OPENTHREAD_PLATFORM_TREL_H_
+
+#include <stdint.h>
+
+#include <openthread/error.h>
+#include <openthread/instance.h>
+#include <openthread/ip6.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup plat-trel
+ *
+ * @brief
+ *   This module includes the platform abstraction for Thread Radio Encapsulation Link (TREL) using DNS-SD and
+ *   UDP/IPv6.
+ *
+ * @{
+ *
+ */
+
+/**
+ * This function initializes and enables TREL platform layer.
+ *
+ * Upon this call, the platform layer MUST perform the following:
+ *
+ * 1) TREL platform layer MUST open a UDP socket to listen for and receive TREL messages from peers. The socket is
+ * bound to an ephemeral port number chosen by the platform layer. The port number MUST be returned in @p aUdpPort.
+ * The socket is also bound to network interface(s) on which TREL is to be supported. The socket and the chosen port
+ * should stay valid while TREL is enabled.
+ *
+ * 2) Platform layer MUST initiate an ongoing DNS-SD browse on the service name "_trel._udp" within the local browsing
+ * domain to discover other devices supporting TREL. The ongoing browse will produce two different types of events:
+ * "add" events and "remove" events.  When the browse is started, it should produce an "add" event for every TREL peer
+ * currently present on the network.  Whenever a TREL peer goes offline, a "remove" event should be produced. "remove"
+ * events are not guaranteed, however. When a TREL service instance is discovered, a new ongoing DNS-SD query for an
+ * AAAA record should be started on the hostname indicated in the SRV record of the discovered instance. If multiple
+ * host IPv6 addressees are discovered for a peer, one with highest scope among all addresses MUST be reported (if
+ * there are multiple address at same scope, one must be selected randomly).
+ *
+ * TREL platform MUST signal back the discovered peer info using `otPlatTrelHandleDiscoveredPeerInfo()` callback. This
+ * callback MUST be invoked when a new peer is discovered, when there is a change in an existing entry (e.g., new
+ * TXT record or new port number or new IPv6 address), or when the peer is removed.
+ *
+ * @param[in]  aInstance  The OpenThread instance.
+ * @param[out] aUdpPort   A pointer to return the selected port number by platform layer.
+ *
+ */
+void otPlatTrelEnable(otInstance *aInstance, uint16_t *aUdpPort);
+
+/**
+ * This function disables TREL platform layer.
+ *
+ * After this call, the platform layer MUST stop DNS-SD browse on the service name "_trel._udp", stop advertising the
+ * TREL DNS-SD service (from `otPlatTrelRegisterService()`) and MUST close the UDP socket used to receive TREL messages.
+ *
+ * @pram[in]  aInstance  The OpenThread instance.
+ *
+ */
+void otPlatTrelDisable(otInstance *aInstance);
+
+/**
+ * This structure represents a TREL peer info discovered using DNS-SD browse on the service name "_trel._udp".
+ *
+ */
+typedef struct otPlatTrelPeerInfo
+{
+    /**
+     * This boolean flag indicates whether the entry is being removed or added.
+     *
+     * - TRUE indicates that peer is removed.
+     * - FALSE indicates that it is a new entry or an update to an existing entry.
+     *
+     */
+    bool mRemoved;
+
+    /**
+     * The TXT record data (encoded as specified by DNS-SD) from the SRV record of the discovered TREL peer service
+     * instance.
+     *
+     */
+    const uint8_t *mTxtData;
+
+    uint16_t mTxtLength; ///< Number of bytes in @p mTxtData buffer.
+
+    /**
+     * The TREL peer socket address (IPv6 address and port number).
+     *
+     * The port number is determined from the SRV record of the discovered TREL peer service instance. The IPv6 address
+     * is determined from the DNS-SD query for AAAA records on the hostname indicated in the SRV record of the
+     * discovered service instance. If multiple host IPv6 addressees are discovered, one with highest scope is used.
+     *
+     */
+    otSockAddr mSockAddr;
+} otPlatTrelPeerInfo;
+
+/**
+ * This is a callback function from platform layer to report a discovered TREL peer info.
+ *
+ * @note The @p aInfo structure and its content (e.g., the `mTxtData` buffer) does not need to persist after returning
+ * from this call. OpenThread code will make a copy of all the info it needs.
+ *
+ * @param[in] aInstance   The OpenThread instance.
+ * @param[in] aInfo       A pointer to the TREL peer info.
+ *
+ */
+extern void otPlatTrelHandleDiscoveredPeerInfo(otInstance *aInstance, const otPlatTrelPeerInfo *aInfo);
+
+/**
+ * This function registers a new service to be advertised using DNS-SD [RFC6763].
+ *
+ * The service name is "_trel._udp". The platform should use its own hostname, which when combined with the service
+ * name and the local DNS-SD domain name will produce the full service instance name, for example
+ * "example-host._trel._udp.local.".
+ *
+ * The domain under which the service instance name appears will be 'local' for mDNS, and will be whatever domain is
+ * used for service registration in the case of a non-mDNS local DNS-SD service.
+ *
+ * A subsequent call to this function updates the previous service. It is used to update the TXT record data and/or the
+ * port number.
+ *
+ * The @p aTxtData buffer is not persisted after the return from this function. The platform layer MUST NOT keep the
+ * pointer and instead copy the content if needed.
+ *
+ * @param[in] aInstance   The OpenThread instance.
+ * @param[in] aPort       The port number to include in the SRV record of the advertised service.
+ * @param[in] aTxtData    A pointer to the TXT record data (encoded) to be include in the advertised service.
+ * @param[in] aTxtLength  The length of @p aTxtData (number of bytes).
+ *
+ *
+ */
+void otPlatTrelRegisterService(otInstance *aInstance, uint16_t aPort, const uint8_t *aTxtData, uint8_t aTxtLength);
+
+/**
+ * This function requests a TREL UDP packet to be sent to a given destination.
+ *
+ * @param[in] aInstance        The OpenThread instance structure.
+ * @param[in] aUdpPayload      A pointer to UDP payload.
+ * @param[in] aUdpPayloadLen   The payload length (number of bytes).
+ * @param[in] aDestSockAddr    The destination socket address.
+ *
+ */
+void otPlatTrelSend(otInstance *      aInstance,
+                    const uint8_t *   aUdpPayload,
+                    uint16_t          aUdpPayloadLen,
+                    const otSockAddr *aDestSockAddr);
+
+/**
+ * This function is a callback from platform to notify of a received TREL UDP packet.
+ *
+ * @note The buffer content (up to its specified length) may get changed during processing by OpenThread core (e.g.,
+ * decrypted in place), so the platform implementation should expect that after returning from this function the
+ * @p aBuffer content may have been altered.
+ *
+ * @param[in] aInstance        The OpenThread instance structure.
+ * @param[in] aBuffer          A buffer containing the received UDP payload.
+ * @param[in] aLength          UDP payload length (number of bytes).
+ *
+ */
+extern void otPlatTrelHandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength);
+
+/**
+ * @}
+ *
+ */
+
+#ifdef __cplusplus
+} // end of extern "C"
+#endif
+
+#endif // OPENTHREAD_PLATFORM_TREL_H_
diff --git a/include/openthread/random_crypto.h b/include/openthread/random_crypto.h
index da4ba7b..937136a 100644
--- a/include/openthread/random_crypto.h
+++ b/include/openthread/random_crypto.h
@@ -64,13 +64,6 @@
 otError otRandomCryptoFillBuffer(uint8_t *aBuffer, uint16_t aSize);
 
 /**
- * This function returns initialized mbedtls_ctr_drbg_context.
- *
- * @returns  A pointer to initialized mbedtls_ctr_drbg_context.
- */
-mbedtls_ctr_drbg_context *otRandomCryptoMbedTlsContextGet(void);
-
-/**
  * @}
  *
  */
diff --git a/include/openthread/server.h b/include/openthread/server.h
index 05f3205..0d177c7 100644
--- a/include/openthread/server.h
+++ b/include/openthread/server.h
@@ -54,11 +54,11 @@
 /**
  * This method provides a full or stable copy of the local Thread Network Data.
  *
- * @param[in]     aInstance    A pointer to an OpenThread instance.
- * @param[in]     aStable      TRUE when copying the stable version, FALSE when copying the full version.
- * @param[out]    aData        A pointer to the data buffer.
- * @param[inout]  aDataLength  On entry, size of the data buffer pointed to by @p aData.
- *                             On exit, number of copied bytes.
+ * @param[in]      aInstance    A pointer to an OpenThread instance.
+ * @param[in]      aStable      TRUE when copying the stable version, FALSE when copying the full version.
+ * @param[out]     aData        A pointer to the data buffer.
+ * @param[in,out]  aDataLength  On entry, size of the data buffer pointed to by @p aData.
+ *                              On exit, number of copied bytes.
  *
  */
 otError otServerGetNetDataLocal(otInstance *aInstance, bool aStable, uint8_t *aData, uint8_t *aDataLength);
@@ -102,10 +102,10 @@
 /**
  * This function gets the next service in the local Network Data.
  *
- * @param[in]     aInstance  A pointer to an OpenThread instance.
- * @param[inout]  aIterator  A pointer to the Network Data iterator context. To get the first service entry
-                             it should be set to OT_NETWORK_DATA_ITERATOR_INIT.
- * @param[out]    aConfig    A pointer to where the service information will be placed.
+ * @param[in]      aInstance  A pointer to an OpenThread instance.
+ * @param[in,out]  aIterator  A pointer to the Network Data iterator context. To get the first service entry
+                              it should be set to OT_NETWORK_DATA_ITERATOR_INIT.
+ * @param[out]     aConfig    A pointer to where the service information will be placed.
  *
  * @retval OT_ERROR_NONE       Successfully found the next service.
  * @retval OT_ERROR_NOT_FOUND  No subsequent service exists in the Thread Network Data.
diff --git a/include/openthread/srp_client.h b/include/openthread/srp_client.h
index ba7801e..bb291d4 100644
--- a/include/openthread/srp_client.h
+++ b/include/openthread/srp_client.h
@@ -75,8 +75,9 @@
 typedef struct otSrpClientHostInfo
 {
     const char *         mName;         ///< Host name (label) string (NULL if not yet set).
-    const otIp6Address * mAddresses;    ///< Pointer to an array of host IPv6 addresses (NULL if not yet set).
+    const otIp6Address * mAddresses;    ///< Array of host IPv6 addresses (NULL if not set or auto address is enabled).
     uint8_t              mNumAddresses; ///< Number of IPv6 addresses in `mAddresses` array.
+    bool                 mAutoAddress;  ///< Indicates whether auto address mode is enabled or not.
     otSrpClientItemState mState;        ///< Host info state.
 } otSrpClientHostInfo;
 
@@ -160,7 +161,7 @@
  *
  * @param[in] aError            The error (see above).
  * @param[in] aHostInfo         A pointer to host info.
- * @param[in] aService          The head of linked-list containing all services (excluding the ones removed). NULL if
+ * @param[in] aServices         The head of linked-list containing all services (excluding the ones removed). NULL if
  *                              the list is empty.
  * @param[in] aRemovedServices  The head of linked-list containing all removed services. NULL if the list is empty.
  * @param[in] aContext          A pointer to an arbitrary context (provided when callback was registered).
@@ -180,9 +181,9 @@
  * This callback is invoked when auto-start mode is enabled and the SRP client is either automatically started or
  * stopped.
  *
- * @param[in] aServerSockAddress   A non-NULL pointer indicates SRP server was started and pointer will give the
- *                                 selected server socket address. A NULL pointer indicates SRP server was stopped.
- * @param[in] aContext             A pointer to an arbitrary context (provided when callback was registered).
+ * @param[in] aServerSockAddr   A non-NULL pointer indicates SRP server was started and pointer will give the
+ *                              selected server socket address. A NULL pointer indicates SRP server was stopped.
+ * @param[in] aContext          A pointer to an arbitrary context (provided when callback was registered).
  *
  */
 typedef void (*otSrpClientAutoStartCallback)(const otSockAddr *aServerSockAddr, void *aContext);
@@ -316,6 +317,34 @@
 bool otSrpClientIsAutoStartModeEnabled(otInstance *aInstance);
 
 /**
+ * This function gets the TTL value in every record included in SRP update requests.
+ *
+ * Note that this is the TTL requested by the SRP client. The server may choose to accept a different TTL.
+ *
+ * By default, the TTL will equal the lease interval. Passing 0 or a value larger than the lease interval via
+ * `otSrpClientSetTtl()` will also cause the TTL to equal the lease interval.
+ *
+ * @param[in] aInstance  A pointer to the OpenThread instance.
+ *
+ * @returns The TTL (in seconds).
+ *
+ */
+uint32_t otSrpClientGetTtl(otInstance *aInstance);
+
+/**
+ * This function sets the TTL value in every record included in SRP update requests.
+ *
+ * Changing the TTL does not impact the TTL of already registered services/host-info.
+ * It only affects future SRP update messages (i.e., adding new services and/or refreshes of the existing services).
+ *
+ * @param[in] aInstance   A pointer to the OpenThread instance.
+ * @param[in] aTtl        The TTL (in seconds). If value is zero or greater than lease interval, the TTL is set to the
+ *                        lease interval.
+ *
+ */
+void otSrpClientSetTtl(otInstance *aInstance, uint32_t aTtl);
+
+/**
  * This function gets the lease interval used in SRP update requests.
  *
  * Note that this is the lease duration requested by the SRP client. The server may choose to accept a different lease
@@ -401,6 +430,27 @@
 otError otSrpClientSetHostName(otInstance *aInstance, const char *aName);
 
 /**
+ * This function enables auto host address mode.
+ *
+ * When enabled host IPv6 addresses are automatically set by SRP client using all the unicast addresses on Thread netif
+ * excluding all link-local and mesh-local addresses. If there is no valid address, then Mesh Local EID address is
+ * added. The SRP client will automatically re-register when/if addresses on Thread netif are updated (new addresses
+ * are added or existing addresses are removed).
+ *
+ * The auto host address mode can be enabled before start or during operation of SRP client except when the host info
+ * is being removed (client is busy handling a remove request from an call to `otSrpClientRemoveHostAndServices()` and
+ * host info still being in  either `STATE_TO_REMOVE` or `STATE_REMOVING` states).
+ *
+ * After auto host address mode is enabled, it can be disabled by a call to `otSrpClientSetHostAddresses()` which
+ * then explicitly sets the host addresses.
+ *
+ * @retval OT_ERROR_NONE            Successfully enabled auto host address mode.
+ * @retval OT_ERROR_INVALID_STATE   Host is being removed and therefore cannot enable auto host address mode.
+ *
+ */
+otError otSrpClientEnableAutoHostAddress(otInstance *aInstance);
+
+/**
  * This function sets/updates the list of host IPv6 address.
  *
  * Host IPv6 addresses can be set/changed before start or during operation of SRP client (e.g. to add/remove or change
@@ -408,15 +458,18 @@
  * request from an earlier call to `otSrpClientRemoveHostAndServices()` and host info still being in  either
  * `STATE_TO_REMOVE` or `STATE_REMOVING` states).
  *
- * The host IPv6 address array pointed to by @p aAddresses MUST persist and remain unchanged after returning from this
- * function (with `OT_ERROR_NONE`). OpenThread will save the pointer to the array.
+ * The host IPv6 address array pointed to by @p aIp6Addresses MUST persist and remain unchanged after returning from
+ * this function (with `OT_ERROR_NONE`). OpenThread will save the pointer to the array.
  *
  * After a successful call to this function, `otSrpClientCallback` will be called to report the status of the address
  * registration with SRP server.
  *
+ * Calling this function disables auto host address mode if it was previously enabled from a successful call to
+ * `otSrpClientEnableAutoHostAddress()`.
+ *
  * @param[in] aInstance           A pointer to the OpenThread instance.
- * @param[in] aAddresses          A pointer to the an array containing the host IPv6 addresses.
- * @param[in] aNumAddresses       The number of addresses in the @p aAddresses array.
+ * @param[in] aIp6Addresses       A pointer to the an array containing the host IPv6 addresses.
+ * @param[in] aNumAddresses       The number of addresses in the @p aIp6Addresses array.
  *
  * @retval OT_ERROR_NONE            The host IPv6 address list change started successfully. The `otSrpClientCallback`
  *                                  will be called to report the status of registering addresses with server.
diff --git a/include/openthread/srp_server.h b/include/openthread/srp_server.h
index 1eceb2b..fba7174 100644
--- a/include/openthread/srp_server.h
+++ b/include/openthread/srp_server.h
@@ -156,6 +156,16 @@
 } otSrpServerAddressMode;
 
 /**
+ * This structure includes SRP server TTL configurations.
+ *
+ */
+typedef struct otSrpServerTtlConfig
+{
+    uint32_t mMinTtl; ///< The minimum TTL in seconds.
+    uint32_t mMaxTtl; ///< The maximum TTL in seconds.
+} otSrpServerTtlConfig;
+
+/**
  * This structure includes SRP server LEASE and KEY-LEASE configurations.
  *
  */
@@ -168,6 +178,32 @@
 } otSrpServerLeaseConfig;
 
 /**
+ * This structure includes SRP server lease information of a host/service.
+ *
+ */
+typedef struct otSrpServerLeaseInfo
+{
+    uint32_t mLease;             ///< The lease time of a host/service in milliseconds.
+    uint32_t mKeyLease;          ///< The key lease time of a host/service in milliseconds.
+    uint32_t mRemainingLease;    ///< The remaining lease time of the host/service in milliseconds.
+    uint32_t mRemainingKeyLease; ///< The remaining key lease time of a host/service in milliseconds.
+} otSrpServerLeaseInfo;
+
+/**
+ * This structure includes the statistics of SRP server responses.
+ *
+ */
+typedef struct otSrpServerResponseCounters
+{
+    uint32_t mSuccess;       ///< The number of successful responses.
+    uint32_t mServerFailure; ///< The number of server failure responses.
+    uint32_t mFormatError;   ///< The number of format error responses.
+    uint32_t mNameExists;    ///< The number of 'name exists' responses.
+    uint32_t mRefused;       ///< The number of refused responses.
+    uint32_t mOther;         ///< The number of other responses.
+} otSrpServerResponseCounters;
+
+/**
  * This function returns the domain authorized to the SRP server.
  *
  * If the domain if not set by SetDomain, "default.service.arpa." will be returned.
@@ -208,6 +244,16 @@
 otSrpServerState otSrpServerGetState(otInstance *aInstance);
 
 /**
+ * This function returns the port the SRP server is listening to.
+ *
+ * @param[in]  aInstance  A pointer to an OpenThread instance.
+ *
+ * @returns  The port of the SRP server. It returns 0 if the server is not running.
+ *
+ */
+uint16_t otSrpServerGetPort(otInstance *aInstance);
+
+/**
  * This function returns the address mode being used by the SRP server.
  *
  * @param[in] aInstance  A pointer to an OpenThread instance.
@@ -263,6 +309,30 @@
 void otSrpServerSetEnabled(otInstance *aInstance, bool aEnabled);
 
 /**
+ * This function returns SRP server TTL configuration.
+ *
+ * @param[in]   aInstance   A pointer to an OpenThread instance.
+ * @param[out]  aTtlConfig  A pointer to an `otSrpServerTtlConfig` instance.
+ *
+ */
+void otSrpServerGetTtlConfig(otInstance *aInstance, otSrpServerTtlConfig *aTtlConfig);
+
+/**
+ * This function sets SRP server TTL configuration.
+ *
+ * The granted TTL will always be no greater than the max lease interval configured via `otSrpServerSetLeaseConfig()`,
+ * regardless of the minimum and maximum TTL configuration.
+ *
+ * @param[in]  aInstance   A pointer to an OpenThread instance.
+ * @param[in]  aTtlConfig  A pointer to an `otSrpServerTtlConfig` instance.
+ *
+ * @retval  OT_ERROR_NONE          Successfully set the TTL configuration.
+ * @retval  OT_ERROR_INVALID_ARGS  The TTL configuration is not valid.
+ *
+ */
+otError otSrpServerSetTtlConfig(otInstance *aInstance, const otSrpServerTtlConfig *aTtlConfig);
+
+/**
  * This function returns SRP server LEASE and KEY-LEASE configurations.
  *
  * @param[in]   aInstance     A pointer to an OpenThread instance.
@@ -366,6 +436,16 @@
 const otSrpServerHost *otSrpServerGetNextHost(otInstance *aInstance, const otSrpServerHost *aHost);
 
 /**
+ * This function returns the response counters of the SRP server.
+ *
+ * @param[in]  aInstance  A pointer to an OpenThread instance.
+ *
+ * @returns  A pointer to the response counters of the SRP server.
+ *
+ */
+const otSrpServerResponseCounters *otSrpServerGetResponseCounters(otInstance *aInstance);
+
+/**
  * This function tells if the SRP service host has been deleted.
  *
  * A SRP service host can be deleted but retains its name for future uses.
@@ -400,6 +480,15 @@
 const otIp6Address *otSrpServerHostGetAddresses(const otSrpServerHost *aHost, uint8_t *aAddressesNum);
 
 /**
+ * This function returns the LEASE and KEY-LEASE information of a given host.
+ *
+ * @param[in]   aHost       A pointer to the SRP server host.
+ * @param[out]  aLeaseInfo  A pointer to where to output the LEASE and KEY-LEASE information.
+ *
+ */
+void otSrpServerHostGetLeaseInfo(const otSrpServerHost *aHost, otSrpServerLeaseInfo *aLeaseInfo);
+
+/**
  * This function returns the next service (excluding any sub-type services) of given host.
  *
  * @note This function is being deprecated and will be removed. `otSrpServerHostFindNextService()` can be used
@@ -563,6 +652,16 @@
 uint16_t otSrpServerServiceGetPriority(const otSrpServerService *aService);
 
 /**
+ * This function returns the TTL of the service instance.
+ *
+ * @param[in]  aService  A pointer to the SRP service.
+ *
+ * @returns  The TTL of the service instance..
+ *
+ */
+uint32_t otSrpServerServiceGetTtl(const otSrpServerService *aService);
+
+/**
  * This function returns the TXT record data of the service instance.
  *
  * @param[in]  aService        A pointer to the SRP service.
@@ -584,6 +683,14 @@
 const otSrpServerHost *otSrpServerServiceGetHost(const otSrpServerService *aService);
 
 /**
+ * This function returns the LEASE and KEY-LEASE information of a given service.
+ *
+ * @param[in]   aService    A pointer to the SRP server service.
+ * @param[out]  aLeaseInfo  A pointer to where to output the LEASE and KEY-LEASE information.
+ *
+ */
+void otSrpServerServiceGetLeaseInfo(const otSrpServerService *aService, otSrpServerLeaseInfo *aLeaseInfo);
+/**
  * @}
  *
  */
diff --git a/include/openthread/tcp.h b/include/openthread/tcp.h
index a0d4b3a..6cc11f7 100644
--- a/include/openthread/tcp.h
+++ b/include/openthread/tcp.h
@@ -29,7 +29,7 @@
 /**
  * @file
  * @brief
- *  This file defines the OpenThread TCP API.
+ *   This file defines the OpenThread TCP API.
  *
  */
 
@@ -64,7 +64,7 @@
 {
     struct otLinkedBuffer *mNext;   ///< Pointer to the next linked buffer in the chain, or NULL if it is the end.
     const uint8_t *        mData;   ///< Pointer to data referenced by this linked buffer.
-    uint16_t               mLength; ///< Length of this linked buffer (number of bytes).
+    size_t                 mLength; ///< Length of this linked buffer (number of bytes).
 } otLinkedBuffer;
 
 struct otTcpEndpoint;
@@ -95,47 +95,74 @@
 typedef void (*otTcpSendDone)(otTcpEndpoint *aEndpoint, otLinkedBuffer *aData);
 
 /**
- * This callback informs the application that the first @p aNumBytes in the
- * send buffer have been acknowledged by the connection peer and that their
- * underlying memory can be reclaimed by the application.
+ * This callback informs the application if forward progress has been made in
+ * transferring data from the send buffer to the recipient. This callback is
+ * not necessary for correct TCP operation. Most applications can just rely on
+ * the otTcpSendDone() callback to reclaim linked buffers once the TCP stack is
+ * done using them. The purpose of this callback is to support advanced
+ * applications that benefit from finer-grained information about how the
+ * the connection is making forward progress in transferring data to the
+ * connection peer.
  *
- * This callback is not necessary for correct TCP operation. Most applications
- * can just rely on the otTcpSendDone() callback. If an application wants
- * fine-grained feedback as memory in the send buffer becomes available again
- * (instead of waiting for an entire linked buffer's worth of data becomes
- * available) or some indication as to whether the connection is making forward
- * progress, it can register this callback.
+ * This callback's operation is closely tied to TCP's send buffer. The send
+ * buffer can be understood as having two regions. First, there is the
+ * "in-flight" region at the head (front) of the send buffer. It corresponds
+ * to data which has been sent to the recipient, but is not yet acknowledged.
+ * Second, there is the "backlog" region, which consists of all data in the
+ * send buffer that is not in the "in-flight" region. The "backlog" region
+ * corresponds to data that is queued for sending, but has not yet been sent.
  *
- * @param[in]  aEndpoint  The TCP endpoint for the connection.
- * @param[in]  aNumBytes  The number of bytes newly acknowledged by the connection peer.
+ * The callback is invoked in response to two types of events. First, the
+ * "in-flight" region of the send buffer may shrink (e.g., when the recipient
+ * acknowledges data that we sent earlier). Second, the "backlog" region of the
+ * send buffer may shrink (e.g., new data was sent out). These two conditions
+ * often occur at the same time, in response to an ACK segment from the
+ * connection peer, which is why they are combined in a single callback.
+ *
+ * The TCP stack only uses the @p aInSendBuffer bytes at the tail of the send
+ * buffer; when @p aInSendBuffer decreases by an amount x, it means that x
+ * additional bytes that were formerly at the head of the send buffer are no
+ * longer part of the send buffer and can now be reclaimed (i.e., overwritten)
+ * by the application. Note that the otLinkedBuffer structure itself can only
+ * be reclaimed once all bytes that it references are no longer part of the
+ * send buffer.
+ *
+ * This callback subsumes otTcpSendDone(), in the following sense: applications
+ * can determine when linked buffers can be reclaimed by comparing
+ * @p aInSendBuffer with how many bytes are in each linked buffer. However, we
+ * expect otTcpSendDone(), which directly conveys which otLinkedBuffers can be
+ * reclaimed, to be much simpler to use. If both callbacks are registered and
+ * are triggered by the same event (e.g., the same ACK segment received), then
+ * the otTcpSendDone() callback will be triggered first, followed by this
+ * callback.
+ *
+ * Additionally, this callback provides @p aBacklog, which indicates how many
+ * bytes of data in the send buffer are not yet in flight. For applications
+ * that only want to add data to the send buffer when there is an assurance
+ * that it will be sent out soon, it may be desirable to only send out data
+ * when @p aBacklog is suitably small (0 or close to 0). For example, an
+ * application may use @p aBacklog so that it can react to queue buildup by
+ * dropping or aggregating data to avoid creating a backlog of data.
+ *
+ * After a call to otTcpSendByReference() or otTcpSendByExtension() with a
+ * positive number of bytes, the otTcpForwardProgress() callback is guaranteed
+ * to be called, to indicate when the bytes that were added to the send buffer
+ * are sent out. The call to otTcpForwardProgress() may be made immediately
+ * after the bytes are added to the send buffer (if some of those bytes are
+ * immediately sent out, reducing the backlog), or sometime in the future (once
+ * the connection sends out some or all of the data, reducing the backlog). By
+ * "immediately," we mean that the callback is immediately scheduled for
+ * execution in a tasklet; to avoid reentrancy-related complexity, the
+ * otTcpForwardProgress() callback is never directly called from the
+ * otTcpSendByReference() or otTcpSendByExtension() functions.
+ *
+ * @param[in]  aEndpoint      The TCP endpoint for the connection.
+ * @param[in]  aInSendBuffer  The number of bytes in the send buffer (sum of "in-flight" and "backlog" regions).
+ * @param[in]  aBacklog       The number of bytes that are queued for sending but have not yet been sent (the "backlog"
+ *                            region).
  *
  */
-typedef void (*otTcpBytesAcked)(otTcpEndpoint *aEndpoint, size_t aNumBytes);
-
-/**
- * This callback informs the application that if data is added to the send
- * buffer, some of it will be transmitted immediately without delay, as opposed
- * to being queued for transmission once the peer ACKs some data.
- *
- * After a call to otTcpSendByReference() or otTcpSendByExtension(), the
- * otTcpSendReady() callback is guaranteed to be called, either immediately (if
- * the connection is already ready) or sometime in the future (once the
- * connection becomes ready for more data).
- *
- * This callback is not necessary for correct TCP operation. If more data is
- * added to the send buffer than can be transmitted without delay, it will
- * simply be queued for transmission at a later time. This callback should be
- * used only in cases where some assurance is desired that data added to the
- * send buffer will be sent soon (e.g., TCP won't wait for the recipient to
- * ACK some other data first before sending this data out). For example, you
- * may use this callback if you'd rather have your data be dropped than develop
- * a backlog of data in your send buffer. But for most applications, where this
- * isn't a concern, it's expected that one would not use this callback at all.
- *
- * @param[in]  aEndpoint  The TCP endpoint for the connection.
- *
- */
-typedef void (*otTcpSendReady)(otTcpEndpoint *aEndpoint);
+typedef void (*otTcpForwardProgress)(otTcpEndpoint *aEndpoint, size_t aInSendBuffer, size_t aBacklog);
 
 /**
  * This callback indicates the number of bytes available for consumption from
@@ -192,6 +219,16 @@
 typedef void (*otTcpDisconnected)(otTcpEndpoint *aEndpoint, otTcpDisconnectedReason aReason);
 
 /**
+ * OT_TCP_ENDPOINT_TCB_SIZE_BASE and OT_TCP_ENDPOINT_TCB_NUM_POINTERS are
+ * chosen such that the mTcb field of otTcpEndpoint has the same size as
+ * struct tcpcb in TCPlp. This is necessary because the mTcb field, although
+ * opaque in its declaration, is treated as struct tcpcb in the TCP
+ * implementation.
+ */
+#define OT_TCP_ENDPOINT_TCB_SIZE_BASE 368
+#define OT_TCP_ENDPOINT_TCB_NUM_PTR 36
+
+/**
  * This structure represents a TCP endpoint.
  *
  * An TCP endpoint acts an endpoint of TCP connection. It can be used to
@@ -205,19 +242,27 @@
  */
 struct otTcpEndpoint
 {
-    struct otTcpEndpoint *mNext;     ///< A pointer to the next TCP endpoint (internal use only)
-    otInstance *          mInstance; ///< A pointer to the OpenThread instance associated with this TCP endpoint
-    void *                mContext;  ///< A pointer to application-specific context
+    union
+    {
+        uint8_t  mSize[OT_TCP_ENDPOINT_TCB_SIZE_BASE + OT_TCP_ENDPOINT_TCB_NUM_PTR * sizeof(void *)];
+        uint64_t mAlign;
+    } mTcb;
+
+    struct otTcpEndpoint *mNext;    ///< A pointer to the next TCP endpoint (internal use only)
+    void *                mContext; ///< A pointer to application-specific context
 
     otTcpEstablished      mEstablishedCallback;      ///< "Established" callback function
     otTcpSendDone         mSendDoneCallback;         ///< "Send done" callback function
-    otTcpSendReady        mSendReadyCallback;        ///< "Send ready" callback function
+    otTcpForwardProgress  mForwardProgressCallback;  ///< "Forward progress" callback function
     otTcpReceiveAvailable mReceiveAvailableCallback; ///< "Receive available" callback function
     otTcpDisconnected     mDisconnectedCallback;     ///< "Disconnected" callback function
 
     uint32_t mTimers[4];
 
-    /* Other implementation-defined fields go here. */
+    otLinkedBuffer mReceiveLinks[2];
+    otSockAddr     mSockAddr;
+
+    uint8_t mPendingCallbacks;
 };
 
 /**
@@ -230,8 +275,7 @@
 
     otTcpEstablished      mEstablishedCallback;      ///< "Established" callback function
     otTcpSendDone         mSendDoneCallback;         ///< "Send done" callback function
-    otTcpBytesAcked       mBytesAckedCallback;       ///< "Bytes acked" callback
-    otTcpSendReady        mSendReadyCallback;        ///< "Send ready" callback function
+    otTcpForwardProgress  mForwardProgressCallback;  ///< "Forward progress" callback function
     otTcpReceiveAvailable mReceiveAvailableCallback; ///< "Receive available" callback function
     otTcpDisconnected     mDisconnectedCallback;     ///< "Disconnected" callback function
 
@@ -281,7 +325,9 @@
  * @retval OT_ERROR_FAILED  Failed to open the TCP endpoint.
  *
  */
-otError otTcpEndpointInitialize(otInstance *aInstance, otTcpEndpoint *aEndpoint, otTcpEndpointInitializeArgs *aArgs);
+otError otTcpEndpointInitialize(otInstance *                       aInstance,
+                                otTcpEndpoint *                    aEndpoint,
+                                const otTcpEndpointInitializeArgs *aArgs);
 
 /**
  * Obtains the otInstance that was associated with @p aEndpoint upon
@@ -438,7 +484,7 @@
  * @retval OT_ERROR_FAILED  Failed to complete the operation.
  *
  */
-otError otTcpReceiveByReference(const otTcpEndpoint *aEndpoint, const otLinkedBuffer **aBuffer);
+otError otTcpReceiveByReference(otTcpEndpoint *aEndpoint, const otLinkedBuffer **aBuffer);
 
 /**
  * Reorganizes the receive buffer to be entirely contiguous in memory.
@@ -498,9 +544,10 @@
  *
  * This immediately makes the TCP endpoint free for use for another connection
  * and empties the send and receive buffers, transferring ownership of any data
- * provided by the application in otTcpSendByReference() calls back to
- * the application. The TCP endpoint's callbacks and memory for the receive
- * buffer remain associated with the TCP endpoint.
+ * provided by the application in otTcpSendByReference() and
+ * otTcpSendByExtension() calls back to the application. The TCP endpoint's
+ * callbacks and memory for the receive buffer remain associated with the
+ * TCP endpoint.
  *
  * @param[in]  aEndpoint  A pointer to the TCP endpoint structure representing the TCP endpoint to abort.
  *
@@ -599,6 +646,16 @@
 typedef void (*otTcpAcceptDone)(otTcpListener *aListener, otTcpEndpoint *aEndpoint, const otSockAddr *aPeer);
 
 /**
+ * OT_TCP_LISTENER_TCB_SIZE_BASE and OT_TCP_LISTENER_TCB_NUM_POINTERS are
+ * chosen such that the mTcbListener field of otTcpListener has the same size
+ * as struct tcpcb_listen in TCPlp. This is necessary because the mTcbListen
+ * field, though opaque in its declaration, is treated as struct tcpcb in the
+ * TCP implementation.
+ */
+#define OT_TCP_LISTENER_TCB_SIZE_BASE 16
+#define OT_TCP_LISTENER_TCB_NUM_PTR 3
+
+/**
  * This structure represents a TCP listener.
  *
  * A TCP listener is used to listen for and accept incoming TCP connections.
@@ -610,14 +667,17 @@
  */
 struct otTcpListener
 {
-    struct otTcpListener *mNext;     ///< A pointer to the next TCP listener (internal use only)
-    otInstance *          mInstance; ///< A pointer to the OpenThread instance associated with this TCP listener
-    void *                mContext;  ///< A pointer to application-specific context
+    union
+    {
+        uint8_t mSize[OT_TCP_LISTENER_TCB_SIZE_BASE + OT_TCP_LISTENER_TCB_NUM_PTR * sizeof(void *)];
+        void *  mAlign;
+    } mTcbListen;
+
+    struct otTcpListener *mNext;    ///< A pointer to the next TCP listener (internal use only)
+    void *                mContext; ///< A pointer to application-specific context
 
     otTcpAcceptReady mAcceptReadyCallback; ///< "Accept ready" callback function
     otTcpAcceptDone  mAcceptDoneCallback;  ///< "Accept done" callback function
-
-    /* Other implementation-defined fields go here. */
 };
 
 /**
@@ -649,7 +709,9 @@
  * @retval OT_ERROR_FAILED  Failed to open the TCP listener.
  *
  */
-otError otTcpListenerInitialize(otInstance *aInstance, otTcpListener *aListener, otTcpListenerInitializeArgs *aArgs);
+otError otTcpListenerInitialize(otInstance *                       aInstance,
+                                otTcpListener *                    aListener,
+                                const otTcpListenerInitializeArgs *aArgs);
 
 /**
  * Obtains the otInstance that was associated with @p aListener upon
diff --git a/include/openthread/tcp_ext.h b/include/openthread/tcp_ext.h
new file mode 100644
index 0000000..5c0ddc6
--- /dev/null
+++ b/include/openthread/tcp_ext.h
@@ -0,0 +1,216 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ * @brief
+ *   This file defines extensions to the OpenThread TCP API.
+ *
+ */
+
+#ifndef OPENTHREAD_TCP_EXT_H_
+#define OPENTHREAD_TCP_EXT_H_
+
+#include <openthread/tcp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup api-tcp-ext
+ *
+ * @brief
+ *   This module includes easy-to-use abstractions on top of the base TCP API.
+ *
+ * @{
+ *
+ */
+
+/**
+ * This structure represents a circular send buffer for use with a TCP endpoint.
+ *
+ * Using a circular send buffer is optional. Applications can use a TCP
+ * endpoint to send data by managing otLinkedBuffers directly. However, some
+ * applications may find it more convenient to have a circular send buffer;
+ * such applications can call otTcpCircularSendBufferWrite() to "attach" a
+ * circular send buffer to a TCP endpoint and send out data on that TCP
+ * endpoint, relying on the circular send buffer to manage the underlying
+ * otLinkedBuffers.
+ *
+ * otTcpCircularSendBuffer is implemented on top of the otLinkedBuffer-based
+ * API provided by an otTcpEndpoint. Once attached to an otTcpEndpoint, an
+ * otTcpCircularSendBuffer performs all the work of managing otLinkedBuffers
+ * for the connection. This means that, once an otTcpCircularSendBuffer is
+ * attached to an otTcpEndpoint, the application should not call
+ * otTcpSendByReference() or otTcpSendByExtension() on that otTcpEndpoint.
+ * Instead, the application should use otTcpCircularSendBufferWrite() to add
+ * data to the send buffer.
+ *
+ * The otTcpForwardProgress() callback is the intended way for users to learn
+ * when space becomes available in the circular send buffer. On an
+ * otTcpEndpoint to which an otTcpCircularSendBuffer is attached, the
+ * application MUST install an otTcpForwardProgress() callback and call
+ * otTcpCircularSendBufferHandleForwardProgress() on the attached
+ * otTcpCircularSendBuffer at the start of the callback function. It is
+ * recommended that the user NOT install an otTcpSendDone() callback, as all
+ * management of otLinkedBuffers is handled by the circular send buffer.
+ *
+ * The application should not inspect the fields of this structure directly; it
+ * should only interact with it via the TCP Circular Send Buffer API functions
+ * whose signature are provided in this file.
+ *
+ */
+typedef struct otTcpCircularSendBuffer
+{
+    const uint8_t *mDataBuffer;   ///< Pointer to data in the circular send buffer
+    size_t         mCapacity;     ///< Length of the circular send buffer
+    size_t         mStartIndex;   ///< Index of the first valid byte in the send buffer
+    size_t         mCapacityUsed; ///< Number of bytes stored in the send buffer
+
+    otLinkedBuffer mSendLinks[2];
+    uint8_t        mFirstSendLinkIndex;
+} otTcpCircularSendBuffer;
+
+/**
+ * Initializes a TCP circular send buffer.
+ *
+ * @param[in]  aSendBuffer      A pointer to the TCP circular send buffer to initialize.
+ * @param[in]  aDataBuffer      A pointer to memory to use to store data in the TCP circular send buffer.
+ * @param[in]  aCapacity        The capacity, in bytes, of the TCP circular send buffer, which must equal the size of
+ *                              the memory pointed to by @p aDataBuffer .
+ */
+void otTcpCircularSendBufferInitialize(otTcpCircularSendBuffer *aSendBuffer, void *aDataBuffer, size_t aCapacity);
+
+/**
+ * Sends out data on a TCP endpoint, using the provided TCP circular send
+ * buffer to manage buffering.
+ *
+ * Once this function is called, @p aSendBuffer and @p aEndpoint are considered
+ * "attached" to each other. While they are attached, ALL send operations for
+ * @p aEndpoint must be made using @p aSendBuffer and ALL operations on
+ * @p aSendBuffer must be associated with @p aEndpoint .
+ *
+ * The only way to "detach" a TCP circular send buffer and a TCP endpoint is to
+ * wait for the send buffer to become completely empty. This can happen in two
+ * ways: (1) all data in the send buffer is sent and acknowledged in the normal
+ * course of TCP protocol operation, or (2) the connection is terminated.
+ *
+ * The recommended usage pattern is to use a single TCP circular send buffer
+ * with a TCP endpoint, and to send data on that TCP endpoint only via its
+ * associated TCP circular buffer. This recommended usage pattern sidesteps the
+ * issues described above by always using a TCP endpoint and TCP circular send
+ * buffer together.
+ *
+ * If the circular send buffer reaches capacity, only a prefix of the provided
+ * data is copied into the circular send buffer.
+ *
+ * @param[in]   aEndpoint    The TCP endpoint on which to send out data.
+ * @param[in]   aSendBuffer  The TCP circular send buffer into which to copy data.
+ * @param[in]   aData        A pointer to data to copy into the TCP circular send buffer.
+ * @param[in]   aLength      The length of the data pointed to by @p aData to copy into the TCP circular send buffer.
+ * @param[out]  aWritten     Populated with the amount of data copied into the send buffer, which might be less than
+ *                           @p aLength if the send buffer reaches capacity.
+ *
+ * @returns OT_ERROR_NONE    Successfully copied data into the send buffer and sent it on the TCP endpoint.
+ * @returns OT_ERROR_FAILED  Failed to send out data on the TCP endpoint.
+ */
+otError otTcpCircularSendBufferWrite(otTcpEndpoint *          aEndpoint,
+                                     otTcpCircularSendBuffer *aSendBuffer,
+                                     void *                   aData,
+                                     size_t                   aLength,
+                                     size_t *                 aWritten);
+
+/**
+ * Performs circular-send-buffer-specific handling in the otTcpForwardProgress
+ * callback.
+ *
+ * The application is expected to install an otTcpForwardProgress() callback on
+ * the otTcpEndpoint, and call this function at the start of the callback
+ * function for circular-send-buffer-specific processing.
+ *
+ * In the callback function, the application can determine the amount of free
+ * space in the circular send buffer by calling
+ * otTcpCircularSendBufferFreeSpace(), or by comparing @p aInSendBuffer with
+ * the send buffer's capacity, chosen by the user when calling
+ * otTcpCircularSendBufferInitialize().
+ *
+ * @param[in]  aSendBuffer    A pointer to the TCP circular send buffer for the endpoint for which
+ *                            otTcpForwardProgress() was invoked.
+ * @param[in]  aInSendBuffer  Value of @p aInSendBuffer passed to the otTcpForwardProgress() callback.
+ */
+void otTcpCircularSendBufferHandleForwardProgress(otTcpCircularSendBuffer *aSendBuffer, size_t aInSendBuffer);
+
+/**
+ * Returns the amount of free space in the TCP circular send buffer.
+ *
+ * This operation will always succeed.
+ *
+ * @param[in]  aSendBuffer  A pointer to the TCP circular send buffer whose amount of free space to return.
+ *
+ * @return The amount of free space in the send buffer.
+ */
+size_t otTcpCircularSendBufferFreeSpace(otTcpCircularSendBuffer *aSendBuffer);
+
+/**
+ * Forcibly discards all data in the circular send buffer.
+ *
+ * The application is expected to call this function when a TCP connection is
+ * terminated unceremoniously (e.g., if the application calls
+ * otTcpEndpointAbort() or is informed of a reset connection via the
+ * otTcpConnectionLost() callback).
+ *
+ * Calling this function on a nonempty TCP circular send buffer attached to a
+ * TCP endpoint results in undefined behavior.
+ *
+ * @param[in]  aSendBuffer  The TCP circular send buffer whose data to discard.
+ */
+void otTcpCircularSendBufferForceDiscardAll(otTcpCircularSendBuffer *aSendBuffer);
+
+/**
+ * Deinitializes a TCP circular send buffer, detaching it if attached.
+ *
+ * If the TCP circular send buffer is not empty, then this operation will fail.
+ *
+ * @param[in]  aSendBuffer  The TCP circular send buffer to deinitialize.
+ *
+ * @retval OT_ERROR_NONE    Successfully deinitialize the TCP circular send buffer.
+ * @retval OT_ERROR_BUSY    Circular buffer contains data and cannot be deinitialized.
+ */
+otError otTcpCircularSendBufferDeinitialize(otTcpCircularSendBuffer *aSendBuffer);
+
+/**
+ * @}
+ *
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_TCP_EXT_H_
diff --git a/include/openthread/thread.h b/include/openthread/thread.h
index cbac610..04cb747 100644
--- a/include/openthread/thread.h
+++ b/include/openthread/thread.h
@@ -168,10 +168,7 @@
     uint16_t mBetterPartitionAttachAttempts; ///< Number of attempts to attach to a better partition.
 
     /**
-     * Number of times device changed its parents.
-     *
-     * Support for this counter requires the feature option OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH to
-     * be enabled.
+     * Number of times device changed its parent.
      *
      * A parent change can happen if device detaches from its current parent and attaches to a different one, or even
      * while device is attached when the periodic parent search feature is enabled  (please see option
@@ -198,10 +195,21 @@
 } otThreadParentResponseInfo;
 
 /**
+ * This callback informs the application that the detaching process has finished.
+ *
+ * @param[in] aContext A pointer to application-specific context.
+ *
+ */
+typedef void (*otDetachGracefullyCallback)(void *aContext);
+
+/**
  * This function starts Thread protocol operation.
  *
  * The interface must be up when calling this function.
  *
+ * Calling this function with @p aEnabled set to FALSE stops any ongoing processes of detaching started by
+ * otThreadDetachGracefully(). Its callback will be called.
+ *
  * @param[in] aInstance A pointer to an OpenThread instance.
  * @param[in] aEnabled  TRUE if Thread is enabled, FALSE otherwise.
  *
@@ -717,10 +725,10 @@
  * This function gets the next neighbor information. It is used to go through the entries of
  * the neighbor table.
  *
- * @param[in]     aInstance  A pointer to an OpenThread instance.
- * @param[inout]  aIterator  A pointer to the iterator context. To get the first neighbor entry
-                             it should be set to OT_NEIGHBOR_INFO_ITERATOR_INIT.
- * @param[out]    aInfo      A pointer to the neighbor information.
+ * @param[in]      aInstance  A pointer to an OpenThread instance.
+ * @param[in,out]  aIterator  A pointer to the iterator context. To get the first neighbor entry
+                              it should be set to OT_NEIGHBOR_INFO_ITERATOR_INIT.
+ * @param[out]     aInfo      A pointer to the neighbor information.
  *
  * @retval OT_ERROR_NONE         Successfully found the next neighbor entry in table.
  * @retval OT_ERROR_NOT_FOUND     No subsequent neighbor entry exists in the table.
@@ -875,7 +883,7 @@
 /**
  * This function pointer is called every time an MLE Parent Response message is received.
  *
- * @param[in]  aStats    pointer to a location on stack holding the stats data.
+ * @param[in]  aInfo     A pointer to a location on stack holding the stats data.
  * @param[in]  aContext  A pointer to callback client-specific context.
  *
  */
@@ -1013,6 +1021,21 @@
                                                   uint32_t                  aTimeSinceLastTransaction);
 
 /**
+ * This function notifies other nodes in the network (if any) and then stops Thread protocol operation.
+ *
+ * It sends an Address Release if it's a router, or sets its child timeout to 0 if it's a child.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aCallback A pointer to a function that is called upon finishing detaching.
+ * @param[in] aContext  A pointer to callback application-specific context.
+ *
+ * @retval OT_ERROR_NONE Successfully started detaching.
+ * @retval OT_ERROR_BUSY Detaching is already in progress.
+ *
+ */
+otError otThreadDetachGracefully(otInstance *aInstance, otDetachGracefullyCallback aCallback, void *aContext);
+
+/**
  * @}
  *
  */
diff --git a/include/openthread/thread_ftd.h b/include/openthread/thread_ftd.h
index 2f0375f..ea052de 100644
--- a/include/openthread/thread_ftd.h
+++ b/include/openthread/thread_ftd.h
@@ -484,12 +484,12 @@
 /**
  * This function gets the next IPv6 address (using an iterator) for a given child.
  *
- * @param[in]     aInstance    A pointer to an OpenThread instance.
- * @param[in]     aChildIndex  The child index.
- * @param[inout]  aIterator    A pointer to the iterator. On success the iterator will be updated to point to next
- *                             entry in the list. To get the first IPv6 address the iterator should be set to
- *                             OT_CHILD_IP6_ADDRESS_ITERATOR_INIT.
- * @param[out]    aAddress     A pointer to an IPv6 address where the child's next address is placed (on success).
+ * @param[in]      aInstance    A pointer to an OpenThread instance.
+ * @param[in]      aChildIndex  The child index.
+ * @param[in,out]  aIterator    A pointer to the iterator. On success the iterator will be updated to point to next
+ *                              entry in the list. To get the first IPv6 address the iterator should be set to
+ *                              OT_CHILD_IP6_ADDRESS_ITERATOR_INIT.
+ * @param[out]     aAddress     A pointer to an IPv6 address where the child's next address is placed (on success).
  *
  * @retval OT_ERROR_NONE          Successfully found the next IPv6 address (@p aAddress was successfully updated).
  * @retval OT_ERROR_NOT_FOUND     The child has no subsequent IPv6 address entry.
@@ -540,11 +540,11 @@
 /**
  * This function gets the next EID cache entry (using an iterator).
  *
- * @param[in]    aInstance   A pointer to an OpenThread instance.
- * @param[out]   aEntryInfo  A pointer to where the EID cache entry information is placed.
- * @param[inout] aIterator   A pointer to an iterator. It will be updated to point to next entry on success. To get the
- *                           first entry, initialize the iterator by setting all its fields to zero (e.g., `memset` the
- *                           the iterator structure to zero).
+ * @param[in]     aInstance   A pointer to an OpenThread instance.
+ * @param[out]    aEntryInfo  A pointer to where the EID cache entry information is placed.
+ * @param[in,out] aIterator   A pointer to an iterator. It will be updated to point to next entry on success. To get
+ *                            the first entry, initialize the iterator by setting all its fields to zero
+ *                            (e.g., `memset` the iterator structure to zero).
  *
  * @retval OT_ERROR_NONE          Successfully populated @p aEntryInfo for next EID cache entry.
  * @retval OT_ERROR_NOT_FOUND     No more entries in the address cache table.
@@ -605,7 +605,7 @@
  * non-volatile memory.
  *
  * @param[in]  aInstance   A pointer to an OpenThread instance.
- * @param[in]  aPskcRef    Key Reference to the new Thread PSKc.
+ * @param[in]  aKeyRef     Key Reference to the new Thread PSKc.
  *
  * @retval OT_ERROR_NONE           Successfully set the Thread PSKc.
  * @retval OT_ERROR_INVALID_STATE  Thread protocols are enabled.
@@ -740,6 +740,50 @@
 void otThreadSetCcmEnabled(otInstance *aInstance, bool aEnabled);
 
 /**
+ * This function sets whether the Security Policy TLV version-threshold for routing (VR field) is enabled.
+ *
+ * @note This API requires `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE`, and is only used by Thread Test Harness
+ *       to indicate that thread protocol version check VR should be skipped.
+ *
+ * @param[in]  aInstance  A pointer to an OpenThread instance.
+ * @param[in]  aEnabled   TRUE to enable Security Policy TLV version-threshold for routing, FALSE otherwise.
+ *
+ */
+void otThreadSetThreadVersionCheckEnabled(otInstance *aInstance, bool aEnabled);
+
+/**
+ * This function gets the range of router IDs that are allowed to assign to nodes within the thread network.
+ *
+ * @note This API requires `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE`, and is only used for test purpose. All the
+ * router IDs in the range [aMinRouterId, aMaxRouterId] are allowed.
+ *
+ * @param[in]   aInstance     A pointer to an OpenThread instance.
+ * @param[out]  aMinRouterId  The minimum router ID.
+ * @param[out]  aMaxRouterId  The maximum router ID.
+ *
+ * @sa otThreadSetRouterIdRange
+ *
+ */
+void otThreadGetRouterIdRange(otInstance *aInstance, uint8_t *aMinRouterId, uint8_t *aMaxRouterId);
+
+/**
+ * This function sets the range of router IDs that are allowed to assign to nodes within the thread network.
+ *
+ * @note This API requires `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE`, and is only used for test purpose. All the
+ * router IDs in the range [aMinRouterId, aMaxRouterId] are allowed.
+ *
+ * @param[in]  aInstance     A pointer to an OpenThread instance.
+ * @param[in]  aMinRouterId  The minimum router ID.
+ * @param[in]  aMaxRouterId  The maximum router ID.
+ *
+ * @retval  OT_ERROR_NONE           Successfully set the range.
+ * @retval  OT_ERROR_INVALID_ARGS   aMinRouterId > aMaxRouterId, or the range is not covered by [0, 62].
+ *
+ * @sa otThreadGetRouterIdRange
+ *
+ */
+otError otThreadSetRouterIdRange(otInstance *aInstance, uint8_t aMinRouterId, uint8_t aMaxRouterId);
+/**
  * @}
  *
  */
diff --git a/include/openthread/trel.h b/include/openthread/trel.h
new file mode 100644
index 0000000..e2dcbdb
--- /dev/null
+++ b/include/openthread/trel.h
@@ -0,0 +1,168 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ * @brief
+ *  This file defines the OpenThread TREL (Thread Radio Encapsulation Link) APIs for Thread Over Infrastructure.
+ *
+ */
+
+#ifndef OPENTHREAD_TREL_H_
+#define OPENTHREAD_TREL_H_
+
+#include <openthread/dataset.h>
+#include <openthread/ip6.h>
+#include <openthread/platform/radio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup api-trel
+ *
+ * @brief
+ *   This module defines Thread Radio Encapsulation Link (TREL) APIs for Thread Over Infrastructure.
+ *
+ *   The functions in this module require `OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE` to be enabled.
+ *
+ * @{
+ *
+ */
+
+/**
+ * This struct represents a TREL peer.
+ *
+ */
+typedef struct otTrelPeer
+{
+    otExtAddress    mExtAddress; ///< The Extended MAC Address of TREL peer.
+    otExtendedPanId mExtPanId;   ///< The Extended PAN Identifier of TREL peer.
+    otSockAddr      mSockAddr;   ///< The IPv6 socket address of TREL peer.
+} otTrelPeer;
+
+/**
+ * This type represents an iterator for iterating over TREL peer table entries.
+ *
+ */
+typedef uint16_t otTrelPeerIterator;
+
+/**
+ * This function enables TREL operation.
+ *
+ * This function initiates an ongoing DNS-SD browse on the service name "_trel._udp" within the local browsing domain
+ * to discover other devices supporting TREL. Device also registers a new service to be advertised using DNS-SD,
+ * with the service name is "_trel._udp" indicating its support for TREL. Device is then ready to receive TREL messages
+ * from peers.
+ *
+ * @note By default the OpenThread stack enables the TREL operation on start.
+ *
+ * @param[in] aInstance   The OpenThread instance.
+ *
+ */
+void otTrelEnable(otInstance *aInstance);
+
+/**
+ * This function disables TREL operation.
+ *
+ * This function stops the DNS-SD browse on the service name "_trel._udp", stops advertising TREL DNS-SD service, and
+ * clears the TREL peer table.
+ *
+ * @param[in] aInstance   The OpenThread instance.
+ *
+ */
+void otTrelDisable(otInstance *aInstance);
+
+/**
+ * This function indicates whether the TREL operation is enabled.
+ *
+ * @param[in] aInstance   The OpenThread instance.
+ *
+ * @retval TRUE if the TREL operation is enabled.
+ * @retval FALSE if the TREL operation is disabled.
+ *
+ */
+bool otTrelIsEnabled(otInstance *aInstance);
+
+/**
+ * This function initializes a peer table iterator.
+ *
+ * @param[in] aInstance   The OpenThread instance.
+ * @param[in] aIterator   The iterator to initialize.
+ *
+ */
+void otTrelInitPeerIterator(otInstance *aInstance, otTrelPeerIterator *aIterator);
+
+/**
+ * This function iterates over the peer table entries and get the next entry from the table
+ *
+ * @param[in] aInstance   The OpenThread instance.
+ * @param[in] aIterator   The iterator. MUST be initialized.
+ *
+ * @returns A pointer to the next `otTrelPeer` entry or `NULL` if no more entries in the table.
+ *
+ */
+const otTrelPeer *otTrelGetNextPeer(otInstance *aInstance, otTrelPeerIterator *aIterator);
+
+/**
+ * This function sets the filter mode (enables/disables filtering).
+ *
+ * When filter mode is enabled, any rx and tx traffic through TREL interface is silently dropped. This is mainly
+ * intended for use during testing.
+ *
+ * Unlike `otTrel{Enable/Disable}()` which fully starts/stops the TREL operation, when filter mode is enabled the
+ * TREL interface continues to be enabled.
+ *
+ * @param[in] aInstance   The OpenThread instance.
+ * @param[in] aFiltered   TRUE to enable filter mode, FALSE to disable filter mode.
+ *
+ */
+void otTrelSetFilterEnabled(otInstance *aInstance, bool aEnable);
+
+/**
+ * This function indicates whether or not the filter mode is enabled.
+ *
+ * @param[in] aInstance   The OpenThread instance.
+ *
+ * @retval TRUE if the TREL filter mode is enabled.
+ * @retval FALSE if the TREL filter mode is disabled.
+ *
+ */
+bool otTrelIsFilterEnabled(otInstance *aInstance);
+
+/**
+ * @}
+ *
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_TREL_H_
diff --git a/script/bootstrap b/script/bootstrap
index 688db89..9a4479c 100755
--- a/script/bootstrap
+++ b/script/bootstrap
@@ -100,7 +100,7 @@
 
     # add ARM toolchain
     brew tap ArmMbed/homebrew-formulae
-    brew install arm-none-eabi-gcc
+    brew install armmbed/formulae/arm-none-eabi-gcc
 
     # check for gcc for simulation
     if ! command -v gcc; then
diff --git a/script/check-android-build b/script/check-android-build
index cf20557..6647b9f 100755
--- a/script/check-android-build
+++ b/script/check-android-build
@@ -51,12 +51,12 @@
 
     datetime="$(date)"
     cat >openthread-config-datetime.h <<EOF
-#include <openthread-config-android.h>
 #define OPENTHREAD_BUILD_DATETIME "$datetime"
 EOF
 
     OPENTHREAD_PROJECT_CFLAGS="-I$PWD -DOPENTHREAD_CONFIG_FILE=\\\"openthread-config-datetime.h\\\" \
-        -DOPENTHREAD_PROJECT_CORE_CONFIG_FILE=\\\"openthread-core-posix-config.h\\\"" \
+        -DOPENTHREAD_PROJECT_CORE_CONFIG_FILE=\\\"openthread-core-posix-config.h\\\" \
+        -std=c99" \
         make showcommands ot-cli
     grep "$datetime" -ao "out/target/product/generic/system/bin/ot-cli"
     make clean-ot-cli
diff --git a/script/check-arm-build-autotools b/script/check-arm-build-autotools
index 4390ff8..e994c20 100755
--- a/script/check-arm-build-autotools
+++ b/script/check-arm-build-autotools
@@ -43,7 +43,7 @@
         "DNS_CLIENT=1"
         "JOINER=1"
         "SLAAC=1"
-        # cc2538 does not have enough resources to support Thread 1.2
+        # cc2538 does not have enough resources to support Thread 1.3
         "THREAD_VERSION=1.1"
     )
 
diff --git a/script/check-arm-build-cmake b/script/check-arm-build-cmake
index d8210ab..3ee62b0 100755
--- a/script/check-arm-build-cmake
+++ b/script/check-arm-build-cmake
@@ -51,7 +51,7 @@
 build_cc2538()
 {
     local options=(
-        # cc2538 does not have enough resources to support Thread 1.2
+        # cc2538 does not have enough resources to support Thread 1.3
         "-DOT_THREAD_VERSION=1.1"
     )
 
diff --git a/script/check-gn-build b/script/check-gn-build
index 2a02c3f..68b17a7 100755
--- a/script/check-gn-build
+++ b/script/check-gn-build
@@ -43,10 +43,10 @@
     ninja -C gn-out
     test -f gn-out/obj/src/core/libopenthread-ftd.a
 
-    # Check GN build for OT1.2
+    # Check GN build for OT1.3
     rm gn-out -r || true
     mkdir gn-out
-    echo 'openthread_config_thread_version = "1.2"' >gn-out/args.gn
+    echo 'openthread_config_thread_version = "1.3"' >gn-out/args.gn
     gn gen --check gn-out
     gn args gn-out --list
     ninja -C gn-out
diff --git a/script/check-ncp-rcp-migrate b/script/check-ncp-rcp-migrate
index 1001ccc..ce38eb5 100755
--- a/script/check-ncp-rcp-migrate
+++ b/script/check-ncp-rcp-migrate
@@ -83,7 +83,7 @@
 expect "Done"
 send "thread start\r\n"
 expect "Done"
-sleep 5
+sleep 10
 send "state\r\n"
 expect "leader"
 expect "Done"
diff --git a/script/check-posix-build-cmake b/script/check-posix-build-cmake
index 11d8b95..cf9a4f5 100755
--- a/script/check-posix-build-cmake
+++ b/script/check-posix-build-cmake
@@ -63,6 +63,9 @@
         reset_source
         build -DOT_POSIX_CONFIG_RCP_BUS=SPI "$@"
     fi
+
+    reset_source
+    build -DOT_POSIX_CONFIG_RCP_BUS=VENDOR "$@"
 }
 
 main "$@"
diff --git a/script/check-posix-pty b/script/check-posix-pty
index 4aad564..716d154 100755
--- a/script/check-posix-pty
+++ b/script/check-posix-pty
@@ -182,7 +182,7 @@
 expect "Done"
 send "thread start\r\n"
 expect "Done"
-sleep 5
+sleep 10
 send "state\r\n"
 expect "leader"
 expect "Done"
@@ -207,7 +207,7 @@
     sleep 5
 
     # wait until the node becomes leader
-    timeout_run 5 wait_for_leader
+    timeout_run 10 wait_for_leader
 
     # wait coap service start
     sleep 5
diff --git a/script/check-scan-build b/script/check-scan-build
index 7ae01d8..06329d9 100755
--- a/script/check-scan-build
+++ b/script/check-scan-build
@@ -36,6 +36,8 @@
     "-DOT_BUILD_EXECUTABLES=OFF"
     "-DOT_BORDER_AGENT=ON"
     "-DOT_BORDER_ROUTER=ON"
+    "-DOT_BORDER_ROUTING=ON"
+    "-DOT_BORDER_ROUTING_NAT64=ON"
     "-DOT_COAP=ON"
     "-DOT_COAP_BLOCK=ON"
     "-DOT_COAP_OBSERVE=ON"
@@ -51,6 +53,7 @@
     "-DOT_DHCP6_SERVER=ON"
     "-DOT_DIAGNOSTIC=ON"
     "-DOT_DNS_CLIENT=ON"
+    "-DOT_DNS_DSO=ON"
     "-DOT_ECDSA=ON"
     "-DOT_EXTERNAL_MBEDTLS=external"
     "-DOT_IP6_FRAGM=ON"
diff --git a/script/check-simulation-build-autotools b/script/check-simulation-build-autotools
index 2511baf..aa6f631 100755
--- a/script/check-simulation-build-autotools
+++ b/script/check-simulation-build-autotools
@@ -43,6 +43,7 @@
         "-DOPENTHREAD_CONFIG_ANYCAST_LOCATOR=1"
         "-DOPENTHREAD_CONFIG_BORDER_AGENT_ENABLE=1"
         "-DOPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE=1"
+        "-DOPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE=1"
         "-DOPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE=1"
         "-DOPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE=1"
         "-DOPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE=1"
@@ -54,6 +55,7 @@
         "-DOPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE=1"
         "-DOPENTHREAD_CONFIG_DIAG_ENABLE=1"
         "-DOPENTHREAD_CONFIG_DNS_CLIENT_ENABLE=1"
+        "-DOPENTHREAD_CONFIG_DNS_DSO_ENABLE=1"
         "-DOPENTHREAD_CONFIG_ECDSA_ENABLE=1"
         "-DOPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE=1"
         "-DOPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE=1"
@@ -87,9 +89,11 @@
         "-DOPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE=1"
         "-DOPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE=1"
         "-DOPENTHREAD_CONFIG_UDP_FORWARD_ENABLE=1"
+        "-DOPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE=1"
+        "-DOPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE=1"
     )
 
-    local options_1_2=(
+    local options_1_3=(
         "-DOPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE=1"
         "-DOPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE=1"
         "-DOPENTHREAD_CONFIG_DUA_ENABLE=1"
@@ -97,28 +101,24 @@
     )
 
     # Build Thread 1.1 with full features and no log
-    export CPPFLAGS="${options[*]} -DOPENTHREAD_CONFIG_LOG_LEVEL=OT_LOG_LEVEL_NONE"
+    export CPPFLAGS="${options[*]}"
     reset_source
-    make -f examples/Makefile-simulation THREAD_VERSION=1.1
+    make -f examples/Makefile-simulation THREAD_VERSION=1.1 LOG_OUTPUT=NONE
 
     # Build Thread 1.1 with full features and full logs
     export CPPFLAGS="${options[*]}"
     reset_source
     make -f examples/Makefile-simulation THREAD_VERSION=1.1 FULL_LOGS=1
 
-    # Build Thread 1.1 with full features and full logs (Logs defined as macros)
-    export CPPFLAGS="${options[*]} -DOPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY=1"
-    make -f examples/Makefile-simulation THREAD_VERSION=1.1 FULL_LOGS=1
-
-    # Build Thread 1.2 with full features and logs
-    export CPPFLAGS="${options[*]} ${options_1_2[*]} -DOPENTHREAD_CONFIG_LOG_LEVEL=OT_LOG_LEVEL_NONE"
+    # Build Thread 1.3 with full features and logs
+    export CPPFLAGS="${options[*]} ${options_1_3[*]}"
     reset_source
-    make -f examples/Makefile-simulation THREAD_VERSION=1.2
+    make -f examples/Makefile-simulation THREAD_VERSION=1.3 LOG_OUTPUT=NONE
 
-    # Build Thread 1.2 with full features and full logs
-    export CPPFLAGS="${options[*]} ${options_1_2[*]}"
+    # Build Thread 1.3 with full features and full logs
+    export CPPFLAGS="${options[*]} ${options_1_3[*]}"
     reset_source
-    make -f examples/Makefile-simulation THREAD_VERSION=1.2 FULL_LOGS=1
+    make -f examples/Makefile-simulation THREAD_VERSION=1.3 FULL_LOGS=1
 
     # Build Thread 1.1 with ASSERT disabled
     export CPPFLAGS="${options[*]} -DOPENTHREAD_CONFIG_ASSERT_ENABLE=0"
@@ -129,6 +129,11 @@
     export CPPFLAGS="${options[*]}"
     reset_source
     make -f examples/Makefile-simulation THREAD_VERSION=1.1 OTNS=1
+
+    # Build Thread 1.3 with external heap and msg pool using heap
+    export CPPFLAGS="${options[*]} ${options_1_3[*]} -DOPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE=1"
+    reset_source
+    make -f examples/Makefile-simulation THREAD_VERSION=1.3
 }
 
 build_nest_common()
diff --git a/script/check-simulation-build-cmake b/script/check-simulation-build-cmake
index 2b22ff2..f296ab1 100755
--- a/script/check-simulation-build-cmake
+++ b/script/check-simulation-build-cmake
@@ -53,25 +53,26 @@
         -DOT_FTD=OFF \
         -DOT_MTD=OFF
 
-    # Thread 1.2 options
+    # Thread 1.3 options
     local options=(
+        "-DOT_BACKBONE_ROUTER=ON"
+        "-DOT_BORDER_ROUTING=ON"
+        "-DOT_CSL_RECEIVER=ON"
+        "-DOT_MLR=ON"
         "-DOT_OTNS=ON"
         "-DOT_SIMULATION_VIRTUAL_TIME=ON"
-        "-DOT_THREAD_VERSION=1.2"
-        "-DOT_MLR=ON"
-        "-DOT_BACKBONE_ROUTER=ON"
-        "-DOT_CSL_RECEIVER=ON"
+        "-DOT_THREAD_VERSION=1.3"
     )
 
-    # Build Thread 1.2 with full features
+    # Build Thread 1.3 with full features
     reset_source
     "$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_DUA=ON
 
-    # Build Thread 1.2 Backbone Router without DUA ND Proxying
+    # Build Thread 1.3 Backbone Router without DUA ND Proxying
     reset_source
     "$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_BACKBONE_ROUTER_DUA_NDPROXYING=OFF
 
-    # Build Thread 1.2 Backbone Router without Multicast Routing
+    # Build Thread 1.3 Backbone Router without Multicast Routing
     reset_source
     "$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_BACKBONE_ROUTER_MULTICAST_ROUTING=OFF
 
@@ -81,13 +82,17 @@
         -DOT_THREAD_VERSION=1.1 \
         -DOT_VENDOR_EXTENSION=../../src/core/common/extension_example.cpp
 
-    # Build Thread 1.2 with no additional features
+    # Build Thread 1.3 with no additional features
     reset_source
-    "$(dirname "$0")"/cmake-build simulation -DOT_THREAD_VERSION=1.2
+    "$(dirname "$0")"/cmake-build simulation -DOT_THREAD_VERSION=1.3
 
-    # Build Thread 1.2 with full features and OT_ASSERT=OFF
+    # Build Thread 1.3 with full features and OT_ASSERT=OFF
     reset_source
     "$(dirname "$0")"/cmake-build simulation "${options[@]}" -DOT_DUA=ON -DOT_ASSERT=OFF
+
+    # Build with RAM settings
+    reset_source
+    "$(dirname "$0")"/cmake-build simulation -DOT_SETTINGS_RAM=ON
 }
 
 build_toranj()
diff --git a/script/check-size b/script/check-size
index 2163d05..e81c0bf 100755
--- a/script/check-size
+++ b/script/check-size
@@ -151,9 +151,9 @@
 
     local thread_version=$1
 
-    if [[ ${thread_version} == "1.2" ]]; then
+    if [[ ${thread_version} != "1.1" ]]; then
         options+=(
-            "-DOT_THREAD_VERSION=1.2"
+            "-DOT_THREAD_VERSION=1.3"
             "-DOT_BACKBONE_ROUTER=ON"
             "-DOT_DUA=ON"
             "-DOT_MLR=ON"
@@ -243,7 +243,7 @@
     "${reporter}" init OpenThread
 
     size_nrf52840_version 1.1
-    size_nrf52840_version 1.2
+    size_nrf52840_version 1.3
 
     "${reporter}" post
 }
diff --git a/script/cmake-build b/script/cmake-build
index d3ccf0d..b91b7be 100755
--- a/script/cmake-build
+++ b/script/cmake-build
@@ -63,7 +63,9 @@
 
 OT_CMAKE_NINJA_TARGET=${OT_CMAKE_NINJA_TARGET:-}
 
-readonly OT_SRCDIR="$(pwd)"
+OT_SRCDIR="$(cd "$(dirname "$0")"/.. && pwd)"
+
+readonly OT_SRCDIR
 readonly OT_PLATFORMS=(cc2538 simulation posix)
 readonly OT_POSIX_SIM_COMMON_OPTIONS=(
     "-DOT_ANYCAST_LOCATOR=ON"
diff --git a/script/make-pretty b/script/make-pretty
index 06477d8..22201c3 100755
--- a/script/make-pretty
+++ b/script/make-pretty
@@ -82,6 +82,8 @@
     '-DOT_BACKBONE_ROUTER=ON'
     '-DOT_BORDER_AGENT=ON'
     '-DOT_BORDER_ROUTER=ON'
+    '-DOT_BORDER_ROUTING=ON'
+    '-DOT_BORDER_ROUTING_NAT64=ON'
     '-DOT_CHANNEL_MANAGER=ON'
     '-DOT_CHANNEL_MONITOR=ON'
     '-DOT_CHILD_SUPERVISION=ON'
@@ -96,6 +98,7 @@
     '-DOT_DHCP6_SERVER=ON'
     '-DOT_DIAGNOSTIC=ON'
     '-DOT_DNS_CLIENT=ON'
+    '-DOT_DNS_DSO=ON'
     '-DOT_DNSSD_SERVER=ON'
     '-DOT_DUA=ON'
     '-DOT_MLR=ON'
@@ -118,7 +121,7 @@
     '-DOT_SNTP_CLIENT=ON'
     '-DOT_SRP_CLIENT=ON'
     '-DOT_SRP_SERVER=ON'
-    '-DOT_THREAD_VERSION=1.2'
+    '-DOT_THREAD_VERSION=1.3'
     '-DOT_TREL=ON'
     '-DOT_COVERAGE=ON'
     '-DOT_LOG_LEVEL_DYNAMIC=ON'
@@ -174,7 +177,7 @@
 
     (mkdir -p ./build/cmake-tidy \
         && cd ./build/cmake-tidy \
-        && THREAD_VERSION=1.2 cmake "${OT_CLANG_TIDY_BUILD_OPTS[@]}" ../.. \
+        && THREAD_VERSION=1.3 cmake "${OT_CLANG_TIDY_BUILD_OPTS[@]}" ../.. \
         && ../../script/clang-tidy -header-filter='.*' -checks="${OT_CLANG_TIDY_CHECKS}" -j"$OT_BUILD_JOBS" "${OT_CLANG_TIDY_FIX_DIRS[@]}" -fix)
 }
 
@@ -187,7 +190,7 @@
     (
         mkdir -p ./build/cmake-tidy \
             && cd ./build/cmake-tidy \
-            && THREAD_VERSION=1.2 cmake "${OT_CLANG_TIDY_BUILD_OPTS[@]}" ../.. \
+            && THREAD_VERSION=1.3 cmake "${OT_CLANG_TIDY_BUILD_OPTS[@]}" ../.. \
             && ../../script/clang-tidy -header-filter='.*' -checks="${OT_CLANG_TIDY_CHECKS}" -j"$OT_BUILD_JOBS" "${OT_CLANG_TIDY_FIX_DIRS[@]}" \
             | grep -v -E "third_party" >output.txt
         if grep -q "warning: \|error: " output.txt; then
diff --git a/script/test b/script/test
index d92edc3..be16f85 100755
--- a/script/test
+++ b/script/test
@@ -42,10 +42,11 @@
 
 readonly OT_NODE_TYPE="${OT_NODE_TYPE:-cli}"
 readonly OT_NATIVE_IP="${OT_NATIVE_IP:-0}"
-readonly THREAD_VERSION="${THREAD_VERSION:-1.2}"
+readonly THREAD_VERSION="${THREAD_VERSION:-1.3}"
 readonly INTER_OP="${INTER_OP:-0}"
 readonly VERBOSE="${VERBOSE:-0}"
 readonly BORDER_ROUTING="${BORDER_ROUTING:-1}"
+readonly NAT64="${NAT64:-0}"
 readonly INTER_OP_BBR="${INTER_OP_BBR:-1}"
 
 readonly OT_COREDUMP_DIR="${PWD}/ot-core-dump"
@@ -60,6 +61,7 @@
         "-DBUILD_TESTING=ON"
         "-DOT_ANYCAST_LOCATOR=ON"
         "-DOT_DNS_CLIENT=ON"
+        "-DOT_DNS_DSO=ON"
         "-DOT_DNSSD_SERVER=ON"
         "-DOT_ECDSA=ON"
         "-DOT_EXTERNAL_HEAP=ON"
@@ -79,7 +81,7 @@
         options+=("-DOT_FULL_LOGS=ON")
     fi
 
-    if [[ ${version} == "1.2" ]]; then
+    if [[ ${version} != "1.1" ]]; then
         options+=("-DOT_DUA=ON")
         options+=("-DOT_MLR=ON")
     fi
@@ -88,7 +90,7 @@
         options+=("-DOT_SIMULATION_VIRTUAL_TIME=ON")
     fi
 
-    if [[ ${version} == "1.2" ]]; then
+    if [[ ${version} != "1.1" ]]; then
         options+=("-DOT_CSL_RECEIVER=ON")
         options+=("-DOT_LINK_METRICS_INITIATOR=ON")
         options+=("-DOT_LINK_METRICS_SUBJECT=ON")
@@ -104,7 +106,7 @@
         OT_CMAKE_NINJA_TARGET=ot-rcp OT_CMAKE_BUILD_DIR="${OT_BUILDDIR}/openthread-simulation-${version}" "${OT_SRCDIR}"/script/cmake-build simulation "${options[@]}" "-DOT_SIMULATION_VIRTUAL_TIME_UART=ON"
     fi
 
-    if [[ ${version} == "1.2" && ${INTER_OP_BBR} == 1 ]]; then
+    if [[ ${version} != "1.1" && ${INTER_OP_BBR} == 1 ]]; then
 
         options+=("-DOT_BACKBONE_ROUTER=ON")
 
@@ -122,7 +124,7 @@
     local version="$1"
     local options=("-DOT_MESSAGE_USE_HEAP=ON" "-DOT_THREAD_VERSION=${version}" "-DBUILD_TESTING=ON")
 
-    if [[ ${version} == "1.2" ]]; then
+    if [[ ${version} != "1.1" ]]; then
         options+=("-DOT_DUA=ON")
         options+=("-DOT_MLR=ON")
     fi
@@ -145,7 +147,7 @@
 
     OT_CMAKE_BUILD_DIR="${OT_BUILDDIR}/openthread-posix-${version}" "${OT_SRCDIR}"/script/cmake-build posix "${options[@]}"
 
-    if [[ ${version} == "1.2" && ${INTER_OP_BBR} == 1 ]]; then
+    if [[ ${version} != "1.1" && ${INTER_OP_BBR} == 1 ]]; then
 
         options+=("-DOT_BACKBONE_ROUTER=ON")
 
@@ -168,7 +170,7 @@
 {
     build_for_one_version "${THREAD_VERSION}"
 
-    if [[ ${THREAD_VERSION} == "1.2" && ${INTER_OP} == "1" ]]; then
+    if [[ ${THREAD_VERSION} != "1.1" && ${INTER_OP} == "1" ]]; then
         build_for_one_version 1.1
     fi
 }
@@ -199,8 +201,8 @@
 {
     do_unit_version "${THREAD_VERSION}"
 
-    if [[ ${THREAD_VERSION} == "1.2" && ${INTER_OP_BBR} == 1 ]]; then
-        do_unit_version "1.2-bbr"
+    if [[ ${THREAD_VERSION} != "1.1" && ${INTER_OP_BBR} == 1 ]]; then
+        do_unit_version "1.3-bbr"
     fi
 }
 
@@ -218,8 +220,8 @@
             ;;
     esac
 
-    if [[ ${THREAD_VERSION} == "1.2" ]]; then
-        export top_builddir_1_2_bbr="${OT_BUILDDIR}/openthread-simulation-1.2-bbr"
+    if [[ ${THREAD_VERSION} != "1.1" ]]; then
+        export top_builddir_1_3_bbr="${OT_BUILDDIR}/openthread-simulation-1.3-bbr"
         if [[ ${INTER_OP} == "1" ]]; then
             export top_builddir_1_1="${OT_BUILDDIR}/openthread-simulation-1.1"
         fi
@@ -236,8 +238,8 @@
 {
     export top_builddir="${OT_BUILDDIR}/openthread-simulation-${THREAD_VERSION}"
 
-    if [[ ${THREAD_VERSION} == "1.2" ]]; then
-        export top_builddir_1_2_bbr="${OT_BUILDDIR}/openthread-simulation-1.2-bbr"
+    if [[ ${THREAD_VERSION} != "1.1" ]]; then
+        export top_builddir_1_3_bbr="${OT_BUILDDIR}/openthread-simulation-1.3-bbr"
         if [[ ${INTER_OP} == "1" ]]; then
             export top_builddir_1_1="${OT_BUILDDIR}/openthread-simulation-1.1"
         fi
@@ -246,6 +248,8 @@
     export PYTHONPATH=tests/scripts/thread-cert
     export VIRTUAL_TIME
 
+    sudo modprobe ip6table_filter
+
     python3 tests/scripts/thread-cert/run_cert_suite.py --multiply "${MULTIPLY:-1}" "$@"
     exit 0
 }
@@ -287,9 +291,15 @@
     )
 
     if [[ ${TREL} == 1 ]]; then
-        otbr_options+=("-DOT_TREL=ON")
+        otbr_options+=("-DOTBR_TREL=ON")
     else
-        otbr_options+=("-DOT_TREL=OFF")
+        otbr_options+=("-DOTBR_TREL=OFF")
+    fi
+
+    if [[ ${NAT64} == 1 ]]; then
+        otbr_options+=("-DOTBR_BORDER_ROUTING_NAT64=ON")
+    else
+        otbr_options+=("-DOTBR_BORDER_ROUTING_NAT64=OFF")
     fi
 
     local otbr_docker_image=${OTBR_DOCKER_IMAGE:-otbr-ot12-backbone-ci}
@@ -314,7 +324,7 @@
             --build-arg BACKBONE_ROUTER=1 \
             --build-arg REFERENCE_DEVICE=1 \
             --build-arg OT_BACKBONE_CI=1 \
-            --build-arg NAT64=0 \
+            --build-arg NAT64="${NAT64}" \
             --build-arg REST_API=0 \
             --build-arg WEB_GUI=0 \
             --build-arg MDNS="${OTBR_MDNS:-mDNSResponder}" \
@@ -376,7 +386,7 @@
             test_patterns=(-name 'tun-*.exp')
         else
             test_patterns=(-name 'posix-*.exp' -o -name 'cli-*.exp')
-            if [[ ${THREAD_VERSION} == "1.2" ]]; then
+            if [[ ${THREAD_VERSION} != "1.1" ]]; then
                 test_patterns+=(-o -name 'v1_2-*.exp')
             fi
         fi
@@ -411,9 +421,9 @@
     VERBOSE         1 to build or test verbosely. The default is 0.
     VIRTUAL_TIME    1 for virtual time, otherwise real time. The default value is 0 when running expect tests,
                     otherwise default value is 1.
-    THREAD_VERSION  1.1 for Thread 1.1 stack, 1.2 for Thread 1.2 stack. The default is 1.2.
-    INTER_OP        1 to build 1.1 together. Only works when THREAD_VERSION is 1.2. The default is 0.
-    INTER_OP_BBR    1 to build bbr version together. Only works when THREAD_VERSION is 1.2. The default is 1.
+    THREAD_VERSION  1.1 for Thread 1.1 stack, 1.3 for Thread 1.3 stack. The default is 1.3.
+    INTER_OP        1 to build 1.1 together. Only works when THREAD_VERSION is 1.3. The default is 0.
+    INTER_OP_BBR    1 to build bbr version together. Only works when THREAD_VERSION is 1.3. The default is 1.
 
 COMMANDS:
     clean           Clean built files to prepare for new build.
@@ -445,7 +455,7 @@
     THREAD_VERSION=1.1 VIRTUAL_TIME=0 $0 clean build cert tests/scripts/thread-cert/Cert_5_1_01_RouterAttach.py
     THREAD_VERSION=1.1 VIRTUAL_TIME=0 $0 cert tests/scripts/thread-cert/Cert_5_1_02_ChildAddressTimeout.py
 
-    # Test Thread 1.2 with real time, use 'INTER_OP=1' when the case needs both versions.
+    # Test Thread 1.3 with real time, use 'INTER_OP=1' when the case needs both versions.
     VIRTUAL_TIME=0 $0 clean build cert tests/scripts/thread-cert/v1_2_test_enhanced_keep_alive.py
     INTER_OP=1 VIRTUAL_TIME=0 $0 clean build cert tests/scripts/thread-cert/v1_2_router_5_1_1.py
     INTER_OP=1 VIRTUAL_TIME=0 $0 clean build cert_suite tests/scripts/thread-cert/v1_2_*
@@ -549,10 +559,10 @@
         export RADIO_DEVICE="${OT_BUILDDIR}/openthread-simulation-${THREAD_VERSION}/examples/apps/ncp/ot-rcp"
         export OT_CLI_PATH="${OT_BUILDDIR}/openthread-posix-${THREAD_VERSION}/src/posix/ot-cli"
 
-        if [[ ${THREAD_VERSION} == "1.2" ]]; then
+        if [[ ${THREAD_VERSION} != "1.1" ]]; then
             export RADIO_DEVICE_1_1="${OT_BUILDDIR}/openthread-simulation-1.1/examples/apps/ncp/ot-rcp"
             export OT_CLI_PATH_1_1="${OT_BUILDDIR}/openthread-posix-1.1/src/posix/ot-cli"
-            export OT_CLI_PATH_1_2_BBR="${OT_BUILDDIR}/openthread-posix-1.2-bbr/src/posix/ot-cli"
+            export OT_CLI_PATH_BBR="${OT_BUILDDIR}/openthread-posix-1.3-bbr/src/posix/ot-cli"
         fi
     fi
 
@@ -596,7 +606,7 @@
     fi
 
     [[ ${VIRTUAL_TIME} == 1 ]] && echo "Using virtual time" || echo "Using real time"
-    [[ ${THREAD_VERSION} == "1.2" ]] && echo "Using Thread 1.2 stack" || echo "Using Thread 1.1 stack"
+    [[ ${THREAD_VERSION} != "1.1" ]] && echo "Using Thread 1.3 stack" || echo "Using Thread 1.1 stack"
 
     while [[ $# != 0 ]]; do
         case "$1" in
diff --git a/src/android/openthread-android-config.h b/src/android/openthread-android-config.h
index b9a2271..f6dde3b 100644
--- a/src/android/openthread-android-config.h
+++ b/src/android/openthread-android-config.h
@@ -26,7 +26,7 @@
  *  POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <openthread-config-android.h>
+#include "openthread-config-android-version.h"
 
 /**
  * @def OPENTHREAD_CONFIG_CLI_TX_BUFFER_SIZE
diff --git a/src/android/openthread-core-android-config.h b/src/android/openthread-core-android-config.h
index 18ce1e6..a91da51 100644
--- a/src/android/openthread-core-android-config.h
+++ b/src/android/openthread-core-android-config.h
@@ -43,7 +43,7 @@
  * The run time data path.
  *
  */
-#define OPENTHREAD_CONFIG_POSIX_SETTINGS_PATH "/data/misc/thread"
+#define OPENTHREAD_CONFIG_POSIX_SETTINGS_PATH "/data/misc/threadnetwork"
 
 /**
  * @def OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME
@@ -51,7 +51,7 @@
  * Define socket basename used by POSIX app daemon.
  *
  */
-#define OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME "/data/misc/thread/openthread-%s"
+#define OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME "/data/misc/threadnetwork/openthread-%s"
 
 /**
  * @def OPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE
@@ -250,14 +250,6 @@
 #define OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL 1
 
 /**
- * @def OPENTHREAD_CONFIG_LOG_PREPEND_REGION
- *
- * Define to prepend the log region to all log messages
- *
- */
-#define OPENTHREAD_CONFIG_LOG_PREPEND_REGION 1
-
-/**
  * @def OPENTHREAD_CONFIG_LOG_SUFFIX
  *
  * Define suffix to append at the end of logs.
@@ -266,29 +258,6 @@
 #define OPENTHREAD_CONFIG_LOG_SUFFIX ""
 
 /**
- * Enable logs for all regions.
- *
- * Note that particularly, we enable `OPENTHREAD_CONFIG_LOG_PLATFORM` (which is not enabled by default in OT). The
- * platform region is used by radio-spinel platform code interacting with RCP.
- *
- */
-#define OPENTHREAD_CONFIG_LOG_API 1
-#define OPENTHREAD_CONFIG_LOG_MLE 1
-#define OPENTHREAD_CONFIG_LOG_ARP 1
-#define OPENTHREAD_CONFIG_LOG_NETDATA 1
-#define OPENTHREAD_CONFIG_LOG_ICMP 1
-#define OPENTHREAD_CONFIG_LOG_IP6 1
-#define OPENTHREAD_CONFIG_LOG_MAC 1
-#define OPENTHREAD_CONFIG_LOG_MEM 1
-#define OPENTHREAD_CONFIG_LOG_PKT_DUMP 1
-#define OPENTHREAD_CONFIG_LOG_NETDIAG 1
-#define OPENTHREAD_CONFIG_LOG_PLATFORM 1
-#define OPENTHREAD_CONFIG_LOG_CLI 1
-#define OPENTHREAD_CONFIG_LOG_COAP 1
-#define OPENTHREAD_CONFIG_LOG_CORE 1
-#define OPENTHREAD_CONFIG_LOG_UTIL 1
-
-/**
  * @def OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
  *
  * Define to 1 if you want to enable radio coexistence implemented in platform.
@@ -304,12 +273,17 @@
  */
 #define OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE 0
 
-/**
- * @def OPENTHREAD_POSIX_TUN_DEVICE
- *
- * Define TUN device name.
- *
- */
-#define OPENTHREAD_POSIX_TUN_DEVICE "/dev/tun"
+#define OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE 1
+#define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 1
+#define OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE 1
+#define OPENTHREAD_CONFIG_ECDSA_ENABLE 1
+#define OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE 1
+#define OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE 1
+#define OPENTHREAD_CONFIG_MAC_FILTER_ENABLE 1
+#define OPENTHREAD_CONFIG_PING_SENDER_ENABLE 1
+#define OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE 1
+#define OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE 1
+#define OPENTHREAD_CONFIG_SRP_SERVER_ENABLE 1
+#define OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE 1
 
 #endif // OPENTHREAD_CORE_ANDROID_CONFIG_H_
diff --git a/src/android/thread_network_hal/hal_interface.cpp b/src/android/thread_network_hal/hal_interface.cpp
new file mode 100644
index 0000000..25d6292
--- /dev/null
+++ b/src/android/thread_network_hal/hal_interface.cpp
@@ -0,0 +1,290 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes the implementation for the IPC Binder interface to radio Co-Processor (RCP).
+ */
+
+#include "hal_interface.hpp"
+
+#if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR
+
+#include <linux/gpio.h>
+#include <linux/ioctl.h>
+#include <linux/spi/spidev.h>
+#include <sys/select.h>
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+namespace ot {
+namespace Posix {
+using ::aidl::android::hardware::threadnetwork::IThreadChip;
+using ::aidl::android::hardware::threadnetwork::IThreadChipCallback;
+using ::ndk::ScopedAStatus;
+
+using ot::Spinel::SpinelInterface;
+
+HalInterface::HalInterface(SpinelInterface::ReceiveFrameCallback aCallback,
+                           void *                                aCallbackContext,
+                           SpinelInterface::RxFrameBuffer &      aFrameBuffer)
+    : mRxFrameCallback(aCallback)
+    , mRxFrameContext(aCallbackContext)
+    , mRxFrameBuffer(aFrameBuffer)
+    , mThreadChip(nullptr)
+    , mThreadChipCallback(nullptr)
+    , mDeathRecipient(AIBinder_DeathRecipient_new(BinderDeathCallback))
+    , mBinderFd(-1)
+{
+    OT_ASSERT(mRxFrameCallback != nullptr);
+}
+
+otError HalInterface::Init(const Url::Url &aRadioUrl)
+{
+    static const std::string            kServicePrefix = std::string() + IThreadChip::descriptor + "/chip";
+    uint32_t                            id             = 0;
+    const char *                        value;
+    binder_status_t                     binderStatus;
+    ScopedAStatus                       ndkStatus;
+    std::shared_ptr<ThreadChipCallback> callback;
+    std::string                         serviceName;
+
+    binderStatus = ABinderProcess_setupPolling(&mBinderFd);
+    VerifyOrDie(binderStatus == ::STATUS_OK, OT_EXIT_FAILURE);
+    VerifyOrDie(mBinderFd >= 0, OT_EXIT_FAILURE);
+
+    if ((value = aRadioUrl.GetValue("id")) != nullptr)
+    {
+        id = static_cast<uint32_t>(atoi(value));
+    }
+
+    serviceName = kServicePrefix + std::to_string(id);
+    otLogInfoPlat("[HAL] Wait for getting the service %s ...", serviceName.c_str());
+    mThreadChip = IThreadChip::fromBinder(::ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
+    VerifyOrDie(mThreadChip != nullptr, OT_EXIT_FAILURE);
+
+    callback = ndk::SharedRefBase::make<ThreadChipCallback>(this);
+    VerifyOrDie(callback->asBinder().get() != nullptr, OT_EXIT_FAILURE);
+
+    mThreadChipCallback = IThreadChipCallback::fromBinder(callback->asBinder());
+    VerifyOrDie(mThreadChipCallback != nullptr, OT_EXIT_FAILURE);
+
+    VerifyOrDie(AIBinder_linkToDeath(mThreadChip->asBinder().get(), mDeathRecipient.get(), this) == STATUS_OK,
+                OT_EXIT_FAILURE);
+
+    ndkStatus = mThreadChip->open(mThreadChipCallback);
+    if (!ndkStatus.isOk())
+    {
+        otLogCritPlat("[HAL] Open the HAL interface failed: %s", ndkStatus.getMessage());
+        DieNow(OT_EXIT_FAILURE);
+    }
+
+    otLogInfoPlat("[HAL] Successfully got the service %s", serviceName.c_str());
+
+    return OT_ERROR_NONE;
+}
+
+void HalInterface::BinderDeathCallback(void *aContext)
+{
+    OT_UNUSED_VARIABLE(aContext);
+
+    otLogInfoPlat("[HAL] Thread network HAL is dead, exit!");
+    DieNow(OT_EXIT_FAILURE);
+}
+
+HalInterface::~HalInterface(void)
+{
+    Deinit();
+}
+
+void HalInterface::Deinit(void)
+{
+    if (mThreadChip != nullptr)
+    {
+        mThreadChip->close();
+        AIBinder_unlinkToDeath(mThreadChip->asBinder().get(), mDeathRecipient.get(), this);
+        mThreadChip         = nullptr;
+        mThreadChipCallback = nullptr;
+    }
+
+    if (mBinderFd >= 0)
+    {
+        close(mBinderFd);
+    }
+}
+
+uint32_t HalInterface::GetBusSpeed(void) const
+{
+    static const uint32_t kBusSpeed = 1000000;
+    return kBusSpeed;
+}
+
+void HalInterface::OnRcpReset(void)
+{
+    mThreadChip->reset();
+}
+
+void HalInterface::UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, int &aMaxFd, struct timeval &aTimeout)
+{
+    OT_UNUSED_VARIABLE(aWriteFdSet);
+    OT_UNUSED_VARIABLE(aTimeout);
+
+    if (mBinderFd >= 0)
+    {
+        FD_SET(mBinderFd, &aReadFdSet);
+        aMaxFd = std::max(aMaxFd, mBinderFd);
+    }
+}
+
+void HalInterface::Process(const RadioProcessContext &aContext)
+{
+    if ((mBinderFd >= 0) && FD_ISSET(mBinderFd, aContext.mReadFdSet))
+    {
+        ABinderProcess_handlePolledCommands();
+    }
+}
+
+otError HalInterface::WaitForFrame(uint64_t aTimeoutUs)
+{
+    otError        error = OT_ERROR_NONE;
+    struct timeval timeout;
+    fd_set         readFdSet;
+    int            ret;
+
+    VerifyOrExit(mBinderFd >= 0, error = OT_ERROR_FAILED);
+
+    timeout.tv_sec  = static_cast<time_t>(aTimeoutUs / US_PER_S);
+    timeout.tv_usec = static_cast<suseconds_t>(aTimeoutUs % US_PER_S);
+
+    FD_ZERO(&readFdSet);
+    FD_SET(mBinderFd, &readFdSet);
+
+    ret = select(mBinderFd + 1, &readFdSet, nullptr, nullptr, &timeout);
+
+    if ((ret > 0) && FD_ISSET(mBinderFd, &readFdSet))
+    {
+        ABinderProcess_handlePolledCommands();
+    }
+    else if (ret == 0)
+    {
+        ExitNow(error = OT_ERROR_RESPONSE_TIMEOUT);
+    }
+    else if (errno != EINTR)
+    {
+        DieNow(OT_EXIT_ERROR_ERRNO);
+    }
+
+exit:
+
+    if (error != OT_ERROR_NONE)
+    {
+        otLogWarnPlat("[HAL] Wait for frame failed: %s", otThreadErrorToString(error));
+    }
+
+    return error;
+}
+
+otError HalInterface::SendFrame(const uint8_t *aFrame, uint16_t aLength)
+{
+    otError       error = OT_ERROR_NONE;
+    ScopedAStatus status;
+
+    VerifyOrExit((aFrame != nullptr) && (aLength <= kMaxFrameSize), error = OT_ERROR_INVALID_ARGS);
+    status = mThreadChip->sendSpinelFrame(std::vector<uint8_t>(aFrame, aFrame + aLength));
+    VerifyOrExit(!status.isOk(), error = OT_ERROR_NONE);
+    error = StatusToError(status);
+    otLogWarnPlat("[HAL] Send frame to HAL interface failed: %s", otThreadErrorToString(error));
+
+exit:
+    return error;
+}
+
+void HalInterface::ReceiveFrameCallback(const std::vector<uint8_t> &aFrame)
+{
+    otError error = OT_ERROR_NONE;
+
+    VerifyOrExit(aFrame.size() > 0, error = OT_ERROR_FAILED);
+
+    for (uint32_t i = 0; i < aFrame.size(); i++)
+    {
+        if ((error = mRxFrameBuffer.WriteByte(aFrame[i])) != OT_ERROR_NONE)
+        {
+            otLogNotePlat("[HAL] Drop the received spinel frame: %s", otThreadErrorToString(error));
+            mRxFrameBuffer.DiscardFrame();
+            ExitNow();
+        }
+    }
+
+    mRxFrameCallback(mRxFrameContext);
+
+exit:
+    return;
+}
+
+otError HalInterface::StatusToError(ScopedAStatus &aStatus)
+{
+    otError error = OT_ERROR_FAILED;
+
+    VerifyOrExit(!aStatus.isOk(), error = OT_ERROR_NONE);
+
+    if (aStatus.getExceptionCode() == EX_ILLEGAL_STATE)
+    {
+        error = OT_ERROR_INVALID_STATE;
+    }
+    else if (aStatus.getExceptionCode() == EX_ILLEGAL_ARGUMENT)
+    {
+        error = OT_ERROR_INVALID_ARGS;
+    }
+    else if (aStatus.getExceptionCode() == EX_SERVICE_SPECIFIC)
+    {
+        switch (aStatus.getServiceSpecificError())
+        {
+        case IThreadChip::ERROR_FAILED:
+            error = OT_ERROR_FAILED;
+            break;
+        case IThreadChip::ERROR_BUSY:
+            error = OT_ERROR_BUSY;
+            break;
+        case IThreadChip::ERROR_NO_BUFS:
+            error = OT_ERROR_NO_BUFS;
+            break;
+        default:
+            error = OT_ERROR_FAILED;
+            break;
+        }
+    }
+
+exit:
+    return error;
+}
+
+} // namespace Posix
+} // namespace ot
+
+#endif // OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR
diff --git a/src/android/thread_network_hal/hal_interface.hpp b/src/android/thread_network_hal/hal_interface.hpp
new file mode 100644
index 0000000..da19390
--- /dev/null
+++ b/src/android/thread_network_hal/hal_interface.hpp
@@ -0,0 +1,210 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes definitions for the IPC binder interface to radio (RCP).
+ */
+
+#ifndef ANDROID_THREAD_NETWORK_HAL_INTERFACE_HPP_
+#define ANDROID_THREAD_NETWORK_HAL_INTERFACE_HPP_
+
+#include "openthread-posix-config.h"
+
+#include "platform-posix.h"
+#include "lib/spinel/spinel_interface.hpp"
+
+#include <openthread/openthread-system.h>
+
+#if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR
+
+#include <aidl/android/hardware/threadnetwork/BnThreadChipCallback.h>
+#include <aidl/android/hardware/threadnetwork/IThreadChip.h>
+#include <aidl/android/hardware/threadnetwork/IThreadChipCallback.h>
+
+namespace ot {
+namespace Posix {
+
+/**
+ * This class defines an IPC Binder interface to the Radio Co-processor (RCP).
+ *
+ */
+class HalInterface
+{
+public:
+    /**
+     * This constructor initializes the object.
+     *
+     * @param[in] aCallback         A reference to a `Callback` object.
+     * @param[in] aCallbackContext  The context pointer passed to the callback.
+     * @param[in] aFrameBuffer      A reference to a `RxFrameBuffer` object.
+     *
+     */
+    HalInterface(Spinel::SpinelInterface::ReceiveFrameCallback aCallback,
+                 void                                         *aCallbackContext,
+                 Spinel::SpinelInterface::RxFrameBuffer       &aFrameBuffer);
+
+    /**
+     * This destructor deinitializes the object.
+     *
+     */
+    ~HalInterface(void);
+
+    /**
+     * This method initializes the interface to the Radio Co-processor (RCP).
+     *
+     * @note This method should be called before reading and sending spinel frames to the interface.
+     *
+     * @param[in]  aRadioUrl          Arguments parsed from radio url.
+     *
+     * @retval OT_ERROR_NONE          The interface is initialized successfully.
+     * @retval OT_ERROR_ALREADY       The interface is already initialized.
+     * @retval OT_ERROR_INVALID_ARGS  The UART device or executable cannot be found or failed to open/run.
+     *
+     */
+    otError Init(const Url::Url &aRadioUrl);
+
+    /**
+     * This method deinitializes the interface to the RCP.
+     *
+     */
+    void Deinit(void);
+
+    /**
+     * This method encodes and sends a spinel frame to Radio Co-processor (RCP) over the socket.
+     *
+     * @param[in] aFrame     A pointer to buffer containing the spinel frame to send.
+     * @param[in] aLength    The length (number of bytes) in the frame.
+     *
+     * @retval OT_ERROR_NONE     Successfully encoded and sent the spinel frame.
+     * @retval OT_ERROR_BUSY     Failed due to another operation is on going.
+     * @retval OT_ERROR_NO_BUFS  Insufficient buffer space available to encode the frame.
+     * @retval OT_ERROR_FAILED   Failed to call the HAL to send the frame.
+     *
+     */
+    otError SendFrame(const uint8_t *aFrame, uint16_t aLength);
+
+    /**
+     * This method waits for receiving part or all of spinel frame within specified interval.
+     *
+     * @param[in]  aTimeout  The timeout value in microseconds.
+     *
+     * @retval OT_ERROR_NONE             Part or all of spinel frame is received.
+     * @retval OT_ERROR_RESPONSE_TIMEOUT No spinel frame is received within @p aTimeout.
+     *
+     */
+    otError WaitForFrame(uint64_t aTimeoutUs);
+
+    /**
+     * This method updates the file descriptor sets with file descriptors used by the radio driver.
+     *
+     * @param[inout]  aReadFdSet   A reference to the read file descriptors.
+     * @param[inout]  aWriteFdSet  A reference to the write file descriptors.
+     * @param[inout]  aMaxFd       A reference to the max file descriptor.
+     * @param[inout]  aTimeout     A reference to the timeout.
+     *
+     */
+    void UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, int &aMaxFd, struct timeval &aTimeout);
+
+    /**
+     * This method performs radio driver processing.
+     *
+     * @param[in]   aContext        The context containing fd_sets.
+     *
+     */
+    void Process(const RadioProcessContext &aContext);
+
+    /**
+     * This method returns the bus speed between the host and the radio.
+     *
+     * @returns   Bus speed in bits/second.
+     *
+     */
+    uint32_t GetBusSpeed(void) const;
+
+    /**
+     * This method is called when RCP failure detected and resets internal states of the interface.
+     *
+     */
+    void OnRcpReset(void);
+
+    /**
+     * This method is called when RCP is reset to recreate the connection with it.
+     * Intentionally empty.
+     *
+     */
+    otError ResetConnection(void) { return OT_ERROR_NONE; }
+
+private:
+    void        ReceiveFrameCallback(const std::vector<uint8_t> &aFrame);
+    static void BinderDeathCallback(void *aContext);
+    otError     StatusToError(::ndk::ScopedAStatus &aStatus);
+
+    class ThreadChipCallback : public ::aidl::android::hardware::threadnetwork::BnThreadChipCallback
+    {
+    public:
+        ThreadChipCallback(HalInterface *aInterface)
+            : mInterface(aInterface)
+        {
+        }
+
+        ::ndk::ScopedAStatus onReceiveSpinelFrame(const std::vector<uint8_t> &in_aFrame)
+        {
+            mInterface->ReceiveFrameCallback(in_aFrame);
+            return ndk::ScopedAStatus::ok();
+        }
+
+    private:
+        HalInterface *mInterface;
+    };
+
+    enum
+    {
+        kMaxFrameSize = Spinel::SpinelInterface::kMaxFrameSize,
+    };
+
+    Spinel::SpinelInterface::ReceiveFrameCallback mRxFrameCallback;
+    void                                         *mRxFrameContext;
+    Spinel::SpinelInterface::RxFrameBuffer       &mRxFrameBuffer;
+
+    std::shared_ptr<::aidl::android::hardware::threadnetwork::IThreadChip>         mThreadChip;
+    std::shared_ptr<::aidl::android::hardware::threadnetwork::IThreadChipCallback> mThreadChipCallback;
+
+    ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+    int                                  mBinderFd;
+
+    // Non-copyable, intentionally not implemented.
+    HalInterface(const HalInterface &);
+    HalInterface &operator=(const HalInterface &);
+};
+
+} // namespace Posix
+} // namespace ot
+
+#endif // OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR
+#endif // ANDROID_THREAD_NETWORK_HAL_INTERFACE_HPP_
diff --git a/src/android/thread_network_hal/vendor_interface.cpp b/src/android/thread_network_hal/vendor_interface.cpp
new file mode 100644
index 0000000..fb8c66f
--- /dev/null
+++ b/src/android/thread_network_hal/vendor_interface.cpp
@@ -0,0 +1,116 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes the implementation for the vendor defined radio spinel interface
+ *   to radio Co-Processor (RCP).
+ */
+
+#include "vendor_interface.hpp"
+
+#if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR
+
+#include <linux/gpio.h>
+#include <linux/ioctl.h>
+#include <linux/spi/spidev.h>
+#include <sys/select.h>
+
+#include <memory>
+
+#include "hal_interface.hpp"
+
+namespace ot {
+namespace Posix {
+using ot::Spinel::SpinelInterface;
+
+HalInterface *sHalInterface = nullptr;
+
+VendorInterface::VendorInterface(SpinelInterface::ReceiveFrameCallback aCallback,
+                                 void                                 *aCallbackContext,
+                                 SpinelInterface::RxFrameBuffer       &aFrameBuffer)
+{
+    sHalInterface = new HalInterface(aCallback, aCallbackContext, aFrameBuffer);
+    assert(sHalInterface != nullptr);
+}
+
+otError VendorInterface::Init(const Url::Url &aRadioUrl)
+{
+    return sHalInterface->Init(aRadioUrl);
+}
+
+VendorInterface::~VendorInterface(void)
+{
+    sHalInterface->Deinit();
+    delete sHalInterface;
+    sHalInterface = nullptr;
+}
+
+void VendorInterface::Deinit(void)
+{
+    sHalInterface->Deinit();
+}
+
+uint32_t VendorInterface::GetBusSpeed(void) const
+{
+    return sHalInterface->GetBusSpeed();
+}
+
+void VendorInterface::OnRcpReset(void)
+{
+    sHalInterface->OnRcpReset();
+}
+
+void VendorInterface::UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, int &aMaxFd, struct timeval &aTimeout)
+{
+    sHalInterface->UpdateFdSet(aReadFdSet, aWriteFdSet, aMaxFd, aTimeout);
+}
+
+void VendorInterface::Process(const RadioProcessContext &aContext)
+{
+    sHalInterface->Process(aContext);
+}
+
+otError VendorInterface::WaitForFrame(uint64_t aTimeoutUs)
+{
+    return sHalInterface->WaitForFrame(aTimeoutUs);
+}
+
+otError VendorInterface::SendFrame(const uint8_t *aFrame, uint16_t aLength)
+{
+    return sHalInterface->SendFrame(aFrame, aLength);
+}
+
+otError VendorInterface::ResetConnection(void)
+{
+    return sHalInterface->ResetConnection();
+}
+} // namespace Posix
+} // namespace ot
+
+#endif // OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_SPI
diff --git a/src/cli/README.md b/src/cli/README.md
index 707cf74..c088da4 100644
--- a/src/cli/README.md
+++ b/src/cli/README.md
@@ -62,7 +62,6 @@
 - [leaderdata](#leaderdata)
 - [leaderweight](#leaderweight)
 - [linkmetrics](#linkmetrics-mgmt-ipaddr-enhanced-ack-clear)
-- [linkquality](#linkquality-extaddr)
 - [locate](#locate)
 - [log](#log-filename-filename)
 - [mac](#mac-retries-direct)
@@ -89,12 +88,13 @@
 - [prefix](#prefix)
 - [promiscuous](#promiscuous)
 - [pskc](#pskc--p-keypassphrase)
+- [radiofilter](#radiofilter)
 - [rcp](#rcp)
 - [region](#region)
 - [releaserouterid](#releaserouterid-routerid)
 - [reset](#reset)
 - [rloc16](#rloc16)
-- [route](#route-add-prefix-s-prf)
+- [route](#route)
 - [router](#router-list)
 - [routerdowngradethreshold](#routerdowngradethreshold)
 - [routereligible](#routereligible)
@@ -106,8 +106,10 @@
 - [sntp](#sntp-query-sntp-server-ip-sntp-server-port)
 - [state](#state)
 - [srp](README_SRP.md)
+- [tcp](README_TCP.md)
 - [thread](#thread-start)
-- [trel](#trel-enable)
+- [trel](#trel)
+- [tvcheck](#tvcheck-enable)
 - [txpower](#txpower)
 - [udp](README_UDP.md)
 - [unsecureport](#unsecureport-add-port)
@@ -380,23 +382,60 @@
 Done
 ```
 
+### br nat64prefix
+
+Get the local NAT64 prefix of the Border Router.
+
+`OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE` is required.
+
+```bash
+> br nat64prefix
+fd14:1078:b3d5:b0b0:0:0::/96
+Done
+```
+
+### br rioprf
+
+Get the preference used when advertising Route Info Options (e.g., for discovered OMR prefixes) in emitted Router Advertisement message.
+
+```bash
+> br rioprf
+med
+Done
+```
+
+### br rioprf \<prf\>
+
+Set the preference (which may be 'high', 'med', or 'low') to use when advertising Route Info Options (e.g., for discovered OMR prefixes) in emitted Router Advertisement message.
+
+```bash
+> br rioprf low
+Done
+```
+
 ### bufferinfo
 
 Show the current message buffer information.
 
+- The `total` shows total number of message buffers in pool.
+- The `free` shows the number of free message buffers.
+- This is then followed by info about different queues used by OpenThread stack, each line representing info about a queue.
+  - The first number shows number messages in the queue.
+  - The second number shows number of buffers used by all messages in the queue.
+  - The third number shows total number of bytes of all messages in the queue.
+
 ```bash
 > bufferinfo
 total: 40
 free: 40
-6lo send: 0 0
-6lo reas: 0 0
-ip6: 0 0
-mpl: 0 0
-mle: 0 0
-arp: 0 0
-coap: 0 0
-coap secure: 0 0
-application coap: 0 0
+6lo send: 0 0 0
+6lo reas: 0 0 0
+ip6: 0 0 0
+mpl: 0 0 0
+mle: 0 0 0
+coap: 0 0 0
+coap secure: 0 0 0
+application coap: 0 0 0
 Done
 ```
 
@@ -1277,6 +1316,16 @@
 Done
 ```
 
+Use `-v` to get more verbose informations about the address.
+
+```bash
+> ipaddr -v
+fdde:ad00:beef:0:0:ff:fe00:0 origin:thread
+fdde:ad00:beef:0:558:f56b:d688:799 origin:thread
+fe80:0:0:0:f3d9:2a82:c8d8:fe43 origin:thread
+Done
+```
+
 ### ipaddr add \<ipaddr\>
 
 Add an IPv6 address to the Thread interface.
@@ -1596,25 +1645,6 @@
  - RSSI: -18 (dBm) (Exponential Moving Average)
 ```
 
-### linkquality \<extaddr\>
-
-Get the link quality on the link to a given extended address.
-
-```bash
-> linkquality 36c1dd7a4f5201ff
-3
-Done
-```
-
-### linkquality \<extaddr\> \<linkquality\>
-
-Set the link quality on the link to a given extended address.
-
-```bash
-> linkquality 36c1dd7a4f5201ff 3
-Done
-```
-
 ### locate
 
 Gets the current state (`In Progress` or `Idle`) of anycast locator.
@@ -2146,6 +2176,15 @@
 Done
 ```
 
+### prefix meshlocal <prefix>
+
+Set the mesh local prefix.
+
+```bash
+> prefix meshlocal fdde:ad00:beef:0::/64
+Done
+```
+
 ### prefix remove \<prefix\>
 
 Invalidate a prefix in the Network Data.
@@ -2183,6 +2222,44 @@
 Done
 ```
 
+### radiofilter
+
+`OPENTHREAD_CONFIG_MAC_FILTER_ENABLE` is required.
+
+The radio filter is mainly intended for testing. It can be used to temporarily block all tx/rx on the IEEE 802.15.4 radio.
+
+When radio filter is enabled, radio is put to sleep instead of receive (to ensure device does not receive any frame and/or potentially send ack). Also the frame transmission requests return immediately without sending the frame over the air (return "no ack" error if ack is requested, otherwise return success).
+
+Get radio filter status (enabled or disabled).
+
+```bash
+> radiofilter
+Disabled
+Done
+```
+
+### radiofilter enable
+
+`OPENTHREAD_CONFIG_MAC_FILTER_ENABLE` is required.
+
+Enable radio radio filter.
+
+```bash
+> radiofilter enable
+Done
+```
+
+### radiofilter disable
+
+`OPENTHREAD_CONFIG_MAC_FILTER_ENABLE` is required.
+
+Disable radio radio filter.
+
+```bash
+> radiofilter disable
+Done
+```
+
 ### rcp
 
 RCP-related commands.
@@ -2418,9 +2495,9 @@
 
 ```bash
 > scan
-| J | Network Name     | Extended PAN     | PAN  | MAC Address      | Ch | dBm | LQI |
-+---+------------------+------------------+------+------------------+----+-----+-----+
-| 0 | OpenThread       | dead00beef00cafe | ffff | f1d92a82c8d8fe43 | 11 | -20 |   0 |
+| PAN  | MAC Address      | Ch | dBm | LQI |
++------+------------------+----+-----+-----+
+| ffff | f1d92a82c8d8fe43 | 11 | -20 |   0 |
 Done
 ```
 
@@ -2570,13 +2647,21 @@
 Done
 ```
 
+### trel
+
+Indicate whether TREL radio operation is enabled or not.
+
+`OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE` is required for all `trel` sub-commands.
+
+```bash
+> trel
+Enabled
+Done
+```
+
 ### trel enable
 
-Enable TREL radio link.
-
-`OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE` is required.
-
-Note: TREL radio link can be enabled only when a valid TREL URL was specified.
+Enable TREL operation.
 
 ```bash
 > trel enable
@@ -2585,15 +2670,88 @@
 
 ### trel disable
 
-Disable TREL radio link.
-
-`OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE` is required.
+Disable TREL operation.
 
 ```bash
 > trel disable
 Done
 ```
 
+### trel filter
+
+Indicate whether TREL filter mode is enabled or not
+
+When filter mode is enabled, any rx and tx traffic through TREL interface is silently dropped. This is mainly intended for use during testing.
+
+```bash
+> trel filter
+Disabled
+Done
+```
+
+### trel filter enable
+
+Enable TREL filter mode.
+
+```bash
+> trel filter enable
+Done
+```
+
+### trel filter disable
+
+Disable TREL filter mode.
+
+```bash
+> trel filter disable
+Done
+```
+
+### trel peers [list]
+
+Get the TREL peer table in table format or as a list.
+
+```bash
+> trel peers
+| No  | Ext MAC Address  | Ext PAN Id       | IPv6 Socket Address                              |
++-----+------------------+------------------+--------------------------------------------------+
+|   1 | 5e5785ba3a63adb9 | f0d9c001f00d2e43 | [fe80:0:0:0:cc79:2a29:d311:1aea]:9202            |
+|   2 | ce792a29d3111aea | dead00beef00cafe | [fe80:0:0:0:5c57:85ba:3a63:adb9]:9203            |
+Done
+
+> trel peers list
+001 ExtAddr:5e5785ba3a63adb9 ExtPanId:f0d9c001f00d2e43 SockAddr:[fe80:0:0:0:cc79:2a29:d311:1aea]:9202
+002 ExtAddr:ce792a29d3111aea ExtPanId:dead00beef00cafe SockAddr:[fe80:0:0:0:5c57:85ba:3a63:adb9]:9203
+>>>>>>> [trel] implement new TREL model using DNS-SD
+Done
+```
+
+### tvcheck enable
+
+Enable thread version check when upgrading to router or leader.
+
+Note: Thread version check is enabled by default.
+
+`OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is required.
+
+```bash
+> tvcheck enable
+Done
+```
+
+### tvcheck disable
+
+Enable thread version check when upgrading to router or leader.
+
+Note: Thread version check is enabled by default.
+
+`OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is required.
+
+```bash
+> tvcheck disable
+Done
+```
+
 ### txpower
 
 Get the transmit power in dBm.
diff --git a/src/cli/README_COMMISSIONER.md b/src/cli/README_COMMISSIONER.md
index 7cd7079..013b416 100644
--- a/src/cli/README_COMMISSIONER.md
+++ b/src/cli/README_COMMISSIONER.md
@@ -11,6 +11,7 @@
 - [energy](#energy)
 - [joiner add](#joiner-add)
 - [joiner remove](#joiner-remove)
+- [joiner table](#joiner-table)
 - [mgmtget](#mgmtget)
 - [mgmtset](#mgmtset)
 - [panid](#panid)
@@ -120,6 +121,22 @@
 Done
 ```
 
+### joiner table
+
+Usage: `commissioner joiner table`
+
+List all Joiner entries.
+
+```bash
+> commissioner joiner table
+| ID                    | PSKd                             | Expiration |
++-----------------------+----------------------------------+------------+
+|                     * |                           J01NME |      81015 |
+|      d45e64fa83f81cf7 |                           J01NME |     101204 |
+| 0x0000000000000abc/12 |                           J01NME |     114360 |
+Done
+```
+
 ### mgmtget
 
 Usage: `commissioner mgmtget [locator] [sessionid] [steeringdata] [joinerudpport] [-x <TLV Types>]`
@@ -183,6 +200,27 @@
 Done
 ```
 
+### id
+
+Usage: `commissioner id`
+
+Get the commissioner id.
+
+```bash
+> commissioner id
+OpenThread Commissioner
+Done
+```
+
+### id \<name\>
+
+Set the commissioner id.
+
+```bash
+> commissioner id "Custom Commissioner Id"
+Done
+```
+
 ### start
 
 Usage: `commissioner start`
diff --git a/src/cli/README_COMMISSIONING.md b/src/cli/README_COMMISSIONING.md
index 237b65d..8262a8c 100644
--- a/src/cli/README_COMMISSIONING.md
+++ b/src/cli/README_COMMISSIONING.md
@@ -21,7 +21,7 @@
    Network Name: OpenThread-8f28
    PAN ID: 0x8f28
    PSKc: c23a76e98f1a6483639b1ac1271e2e27
-   Security Policy: 0, onrcb
+   Security Policy: 0, onrc
    Done
    ```
 
@@ -107,7 +107,7 @@
    Network Name: OpenThread-8f28
    PAN ID: 0x8f28
    PSKc: c23a76e98f1a6483639b1ac1271e2e27
-   Security Policy: 0, onrcb
+   Security Policy: 0, onrc
    Done
    ```
 
diff --git a/src/cli/README_DATASET.md b/src/cli/README_DATASET.md
index a9f678f..87cd4d2 100644
--- a/src/cli/README_DATASET.md
+++ b/src/cli/README_DATASET.md
@@ -44,7 +44,7 @@
    Network Name: OpenThread-8f28
    PAN ID: 0x8f28
    PSKc: c23a76e98f1a6483639b1ac1271e2e27
-   Security Policy: 0, onrcb
+   Security Policy: 0, onrc
    Done
    ```
 
@@ -103,7 +103,7 @@
    Network Name: OpenThread-8f28
    PAN ID: 0x8f28
    PSKc: c23a76e98f1a6483639b1ac1271e2e27
-   Security Policy: 0, onrcb
+   Security Policy: 0, onrc
    Done
    ```
 
@@ -180,7 +180,7 @@
 Network Name: OpenThread-8f28
 PAN ID: 0x8f28
 PSKc: c23a76e98f1a6483639b1ac1271e2e27
-Security Policy: 0, onrcb
+Security Policy: 0, onrc
 Done
 ```
 
@@ -196,7 +196,7 @@
 
 Usage: `dataset activetimestamp [timestamp]`
 
-Get active timestamp.
+Get active timestamp seconds.
 
 ```bash
 > dataset activetimestamp
@@ -204,7 +204,7 @@
 Done
 ```
 
-Set active timestamp.
+Set active timestamp seconds.
 
 ```bash
 > dataset activetimestamp 123456789
@@ -359,7 +359,7 @@
 Send MGMT_ACTIVE_SET or MGMT_PENDING_SET.
 
 ```bash
-> dataset mgmtsetcommand active activetimestamp 123 securitypolicy 1 onrcb
+> dataset mgmtsetcommand active activetimestamp 123 securitypolicy 1 onrc
 Done
 ```
 
@@ -441,7 +441,7 @@
 Network Name: OpenThread-8f28
 PAN ID: 0x8f28
 PSKc: c23a76e98f1a6483639b1ac1271e2e27
-Security Policy: 0, onrcb
+Security Policy: 0, onrc
 Done
 ```
 
@@ -457,7 +457,7 @@
 
 Usage: `dataset pendingtimestamp [timestamp]`
 
-Get pending timestamp.
+Get pending timestamp seconds.
 
 ```bash
 > dataset pendingtimestamp
@@ -465,7 +465,7 @@
 Done
 ```
 
-Set pending timestamp.
+Set pending timestamp seconds.
 
 ```bash
 > dataset pendingtimestamp 123456789
@@ -497,13 +497,13 @@
 
 ### securitypolicy
 
-Usage: `dataset securitypolicy [<rotationtime> [onrcbCepR]]`
+Usage: `dataset securitypolicy [<rotationtime> [onrcCepR]]`
 
 Get security policy.
 
 ```bash
 > dataset securitypolicy
-672 onrcb
+672 onrc
 Done
 ```
 
@@ -513,14 +513,13 @@
 - n: Native Commissioning using PSKc is allowed.
 - r: Thread 1.x Routers are enabled.
 - c: External Commissioner authentication is allowed using PSKc.
-- b: Thread 1.x Beacons are enabled.
 - C: Thread 1.2 Commercial Commissioning is enabled.
 - e: Thread 1.2 Autonomous Enrollment is enabled.
 - p: Thread 1.2 Network Key Provisioning is enabled.
 - R: Non-CCM routers are allowed in Thread 1.2 CCM networks.
 
 ```bash
-> dataset securitypolicy 672 onrcb
+> dataset securitypolicy 672 onrc
 Done
 ```
 
diff --git a/src/cli/README_HISTORY.md b/src/cli/README_HISTORY.md
index b11a57e..e3ea55d 100644
--- a/src/cli/README_HISTORY.md
+++ b/src/cli/README_HISTORY.md
@@ -15,6 +15,8 @@
 - [ipmaddr](#ipmaddr)
 - [neighbor](#neighbor)
 - [netinfo](#netinfo)
+- [prefix](#prefix)
+- [route](#route)
 - [rx](#rx)
 - [rxtx](#rxtx)
 - [tx](#tx)
@@ -52,6 +54,8 @@
 ipmaddr
 neighbor
 netinfo
+prefix
+route
 rx
 rxtx
 tx
@@ -67,7 +71,7 @@
 
 - Event: Added or Removed.
 - Address: Unicast address along with its prefix length (in bits).
-- Origin: Thread, SLAAC, DHCPv6, or Manual.
+- Origin: thread, slaac, dhcp6, or manual.
 - Address Scope.
 - Flags: Preferred, Valid, and RLOC (whether the address is RLOC).
 
@@ -77,15 +81,15 @@
 > history ipaddr
 | Age                  | Event   | Address / PrefixLength                      | Origin |Scope| P | V | R |
 +----------------------+---------+---------------------------------------------+--------+-----+---+---+---+
-|         00:00:04.991 | Removed | 2001:dead:beef:cafe:c4cb:caba:8d55:e30b/64  | SLAAC  |  14 | Y | Y | N |
-|         00:00:44.647 | Added   | 2001:dead:beef:cafe:c4cb:caba:8d55:e30b/64  | SLAAC  |  14 | Y | Y | N |
-|         00:01:07.199 | Added   | fd00:0:0:0:0:0:0:1/64                       | Manual |  14 | Y | Y | N |
-|         00:02:17.885 | Added   | fdde:ad00:beef:0:0:ff:fe00:fc00/64          | Thread |   3 | N | Y | N |
-|         00:02:17.885 | Added   | fdde:ad00:beef:0:0:ff:fe00:5400/64          | Thread |   3 | N | Y | Y |
-|         00:02:20.107 | Removed | fdde:ad00:beef:0:0:ff:fe00:5400/64          | Thread |   3 | N | Y | Y |
-|         00:02:21.575 | Added   | fdde:ad00:beef:0:0:ff:fe00:5400/64          | Thread |   3 | N | Y | Y |
-|         00:02:21.575 | Added   | fdde:ad00:beef:0:ecea:c4fc:ad96:4655/64     | Thread |   3 | N | Y | N |
-|         00:02:23.904 | Added   | fe80:0:0:0:3c12:a4d2:fbe0:31ad/64           | Thread |   2 | Y | Y | N |
+|         00:00:04.991 | Removed | 2001:dead:beef:cafe:c4cb:caba:8d55:e30b/64  | slaac  |  14 | Y | Y | N |
+|         00:00:44.647 | Added   | 2001:dead:beef:cafe:c4cb:caba:8d55:e30b/64  | slaac  |  14 | Y | Y | N |
+|         00:01:07.199 | Added   | fd00:0:0:0:0:0:0:1/64                       | manual |  14 | Y | Y | N |
+|         00:02:17.885 | Added   | fdde:ad00:beef:0:0:ff:fe00:fc00/64          | thread |   3 | N | Y | N |
+|         00:02:17.885 | Added   | fdde:ad00:beef:0:0:ff:fe00:5400/64          | thread |   3 | N | Y | Y |
+|         00:02:20.107 | Removed | fdde:ad00:beef:0:0:ff:fe00:5400/64          | thread |   3 | N | Y | Y |
+|         00:02:21.575 | Added   | fdde:ad00:beef:0:0:ff:fe00:5400/64          | thread |   3 | N | Y | Y |
+|         00:02:21.575 | Added   | fdde:ad00:beef:0:ecea:c4fc:ad96:4655/64     | thread |   3 | N | Y | N |
+|         00:02:23.904 | Added   | fe80:0:0:0:3c12:a4d2:fbe0:31ad/64           | thread |   2 | Y | Y | N |
 Done
 ```
 
@@ -93,11 +97,11 @@
 
 ```bash
 > history ipaddr list 5
-00:00:20.327 -> event:Removed address:2001:dead:beef:cafe:c4cb:caba:8d55:e30b prefixlen:64 origin:SLAAC scope:14 preferred:yes valid:yes rloc:no
-00:00:59.983 -> event:Added address:2001:dead:beef:cafe:c4cb:caba:8d55:e30b prefixlen:64 origin:SLAAC scope:14 preferred:yes valid:yes rloc:no
-00:01:22.535 -> event:Added address:fd00:0:0:0:0:0:0:1 prefixlen:64 origin:Manual scope:14 preferred:yes valid:yes rloc:no
-00:02:33.221 -> event:Added address:fdde:ad00:beef:0:0:ff:fe00:fc00 prefixlen:64 origin:Thread scope:3 preferred:no valid:yes rloc:no
-00:02:33.221 -> event:Added address:fdde:ad00:beef:0:0:ff:fe00:5400 prefixlen:64 origin:Thread scope:3 preferred:no valid:yes rloc:yes
+00:00:20.327 -> event:Removed address:2001:dead:beef:cafe:c4cb:caba:8d55:e30b prefixlen:64 origin:slaac scope:14 preferred:yes valid:yes rloc:no
+00:00:59.983 -> event:Added address:2001:dead:beef:cafe:c4cb:caba:8d55:e30b prefixlen:64 origin:slaac scope:14 preferred:yes valid:yes rloc:no
+00:01:22.535 -> event:Added address:fd00:0:0:0:0:0:0:1 prefixlen:64 origin:manual scope:14 preferred:yes valid:yes rloc:no
+00:02:33.221 -> event:Added address:fdde:ad00:beef:0:0:ff:fe00:fc00 prefixlen:64 origin:thread scope:3 preferred:no valid:yes rloc:no
+00:02:33.221 -> event:Added address:fdde:ad00:beef:0:0:ff:fe00:5400 prefixlen:64 origin:thread scope:3 preferred:no valid:yes rloc:yes
 Done
 ```
 
@@ -243,6 +247,96 @@
 Done
 ```
 
+### prefix
+
+Usage `history prefix [list] [<num-entries>]`
+
+Print the Network Data on mesh prefix history. Each item provides:
+
+- Event (`Added` or `Removed`)
+- Prefix
+- Flags
+- Preference (`high`, `med`, `low`)
+- RLOC16
+
+The flags are as follows:
+
+- `p`: Preferred flag
+- `a`: Stateless IPv6 Address Autoconfiguration flag
+- `d`: DHCPv6 IPv6 Address Configuration flag
+- `c`: DHCPv6 Other Configuration flag
+- `r`: Default Route flag
+- `o`: On Mesh flag
+- `s`: Stable flag
+- `n`: Nd Dns flag
+- `D`: Domain Prefix flag
+
+Print the history as a table.
+
+```bash
+> history prefix
+| Age                  | Event   | Prefix                                      | Flags     | Pref | RLOC16 |
++----------------------+---------+---------------------------------------------+-----------+------+--------+
+|         00:00:10.663 | Added   | fd00:1111:2222:3333::/64                    | paro      | med  | 0x5400 |
+|         00:01:02.054 | Removed | fd00:dead:beef:1::/64                       | paros     | high | 0x5400 |
+|         00:01:21.136 | Added   | fd00:abba:cddd:0::/64                       | paos      | med  | 0x5400 |
+|         00:01:45.144 | Added   | fd00:dead:beef:1::/64                       | paros     | high | 0x3c00 |
+|         00:01:50.944 | Added   | fd00:dead:beef:1::/64                       | paros     | high | 0x5400 |
+|         00:01:59.887 | Added   | fd00:dead:beef:1::/64                       | paros     | med  | 0x8800 |
+Done
+```
+
+Print the history as a list.
+
+```bash
+> history prefix list
+00:04:12.487 -> event:Added prefix:fd00:1111:2222:3333::/64 flags:paro pref:med rloc16:0x5400
+00:05:03.878 -> event:Removed prefix:fd00:dead:beef:1::/64 flags:paros pref:high rloc16:0x5400
+00:05:22.960 -> event:Added prefix:fd00:abba:cddd:0::/64 flags:paos pref:med rloc16:0x5400
+00:05:46.968 -> event:Added prefix:fd00:dead:beef:1::/64 flags:paros pref:high rloc16:0x3c00
+00:05:52.768 -> event:Added prefix:fd00:dead:beef:1::/64 flags:paros pref:high rloc16:0x5400
+00:06:01.711 -> event:Added prefix:fd00:dead:beef:1::/64 flags:paros pref:med rloc16:0x8800
+```
+
+### prefix
+
+Usage `history route [list] [<num-entries>]`
+
+Print the Network Data external route history. Each item provides:
+
+- Event (`Added` or `Removed`)
+- Route
+- Flags
+- Preference (`high`, `med`, `low`)
+- RLOC16
+
+The flags are as follows:
+
+- `s`: Stable flag
+- `n`: NAT64 flag
+
+Print the history as a table.
+
+```bash
+history route
+| Age                  | Event   | Route                                       | Flags     | Pref | RLOC16 |
++----------------------+---------+---------------------------------------------+-----------+------+--------+
+|         00:00:05.456 | Removed | fd00:1111:0::/48                            | s         | med  | 0x3c00 |
+|         00:00:29.310 | Added   | fd00:1111:0::/48                            | s         | med  | 0x3c00 |
+|         00:00:42.822 | Added   | fd00:1111:0::/48                            | s         | med  | 0x5400 |
+|         00:01:27.688 | Added   | fd00:aaaa:bbbb:cccc::/64                    | s         | med  | 0x8800 |
+Done
+```
+
+Print the history as a list (last two entries).
+
+```bash
+> history route list 2
+00:00:48.704 -> event:Removed route:fd00:1111:0::/48 flags:s pref:med rloc16:0x3c00
+00:01:12.558 -> event:Added route:fd00:1111:0::/48 flags:s pref:med rloc16:0x3c00
+Done
+```
+
 ### rx
 
 Usage `history rx [list] [<num-entries>]`
diff --git a/src/cli/README_JOINER.md b/src/cli/README_JOINER.md
index 715ccdb..9f85be5 100644
--- a/src/cli/README_JOINER.md
+++ b/src/cli/README_JOINER.md
@@ -10,6 +10,7 @@
 - [discerner](#discerner)
 - [id](#id)
 - [start](#start)
+- [state](#state)
 - [stop](#stop)
 
 ## Command Details
@@ -25,6 +26,7 @@
 help
 id
 start
+state
 stop
 Done
 ```
@@ -75,6 +77,25 @@
 Done
 ```
 
+### state
+
+Usage: `joiner state`
+
+Print the Joiner state.
+
+- Idle
+- Discover
+- Connecting
+- Connected
+- Entrust
+- Joined
+
+```bash
+> joiner state
+Idle
+Done
+```
+
 ### stop
 
 Usage: `joiner stop`
diff --git a/src/cli/README_NETDATA.md b/src/cli/README_NETDATA.md
index 5554a9f..68c3b43 100644
--- a/src/cli/README_NETDATA.md
+++ b/src/cli/README_NETDATA.md
@@ -27,7 +27,7 @@
    Network Name: OpenThread-8f28
    PAN ID: 0x8f28
    PSKc: c23a76e98f1a6483639b1ac1271e2e27
-   Security Policy: 0, onrcb
+   Security Policy: 0, onrc
    Done
    ```
 
@@ -244,7 +244,7 @@
 
 ### show
 
-Usage: `netdata show [-x]`
+Usage: `netdata show [local] [-x]`
 
 Print Network Data received from the Leader.
 
@@ -257,7 +257,7 @@
 Done
 ```
 
-Print Network Data as hex-encoded TLVs.
+Print Network Data received from the Leader as hex-encoded TLVs.
 
 ```bash
 > netdata show -x
@@ -265,6 +265,25 @@
 Done
 ```
 
+Print local Network Data to sync with Leader.
+
+```bash
+> netdata show local
+Prefixes:
+fd00:dead:beef:cafe::/64 paros med dc00
+Routes:
+Services:
+Done
+```
+
+Print local Network Data to sync with Leader as hex-encoded TLVs.
+
+```bash
+> netdata show local -x
+08040b02174703140040fd00deadbeefcafe0504dc00330007021140
+Done
+```
+
 ### netdata steeringdata check \<eui64\>|\<discerner\>
 
 Check whether the steering data includes a joiner.
diff --git a/src/cli/README_SRP.md b/src/cli/README_SRP.md
index 645f44f..a0ab5ba 100644
--- a/src/cli/README_SRP.md
+++ b/src/cli/README_SRP.md
@@ -25,7 +25,7 @@
 Network Name: OpenThread-f7af
 PAN ID: 0xf7af
 PSKc: b658e40f174e3a11be149b302ef07a0f
-Security Policy: 672, onrcb
+Security Policy: 672, onrc
 Done
 > dataset commit active
 Done
diff --git a/src/cli/README_SRP_CLIENT.md b/src/cli/README_SRP_CLIENT.md
index 5cbe94f..ae48fbf 100644
--- a/src/cli/README_SRP_CLIENT.md
+++ b/src/cli/README_SRP_CLIENT.md
@@ -15,6 +15,7 @@
 - [start](#start)
 - [state](#state)
 - [stop](#stop)
+- [ttl](#ttl)
 
 ## Command Details
 
@@ -36,6 +37,7 @@
 start
 state
 stop
+ttl
 Done
 ```
 
@@ -137,6 +139,14 @@
 Done
 ```
 
+When auto host address mode is enabled.
+
+```bash
+srp client host
+name:"dev1234", state:Registered, addrs:auto
+Done
+```
+
 ### host name
 
 Usage: `srp client host name [name]`
@@ -158,9 +168,17 @@
 
 ### host address
 
-Usage : `srp client host address [<address> ...]`
+Usage : `srp client host address [auto | <address> ...]`
 
-Get the list of host addresses.
+Indicate auto address mode is enabled.
+
+```bash
+> srp client host address
+auto
+Done
+```
+
+Get the list of host addresses (when auto host address is not enabled).
 
 ```bash
 > srp client host address
@@ -169,7 +187,14 @@
 Done
 ```
 
-Set the list of host addresses (can be set while client is running to update the host addresses)
+Enable auto host address mode. When enabled client will automatically use all Thread netif unicast addresses excluding all link-local and mesh-local addresses. If there is no valid address, then Mesh Local EID address is added. SRP client will automatically re-register if/when addresses on Thread netif get changed (e.g., new address is added or existing address is removed).
+
+```bash
+> srp client host address auto
+Done
+```
+
+Explicitly set the list of host addresses (can be set while client is running to update the host addresses), also disabled auto host address mode.
 
 ```bash
 > srp client host address fd00::cafe
@@ -409,3 +434,23 @@
 > srp client stop
 Done
 ```
+
+### ttl
+
+Usage: `srp client ttl [value]`
+
+Get the TTL (in seconds).
+
+```bash
+> srp client ttl
+7200
+Done
+>
+```
+
+Set the TTL.
+
+```bash
+> srp client ttl 3600
+Done
+```
diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp
index 70b5dd1..7178527 100644
--- a/src/cli/cli.cpp
+++ b/src/cli/cli.cpp
@@ -82,10 +82,9 @@
 #include <openthread/platform/debug_uart.h>
 #endif
 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
-#include <openthread/platform/trel-udp6.h>
+#include <openthread/trel.h>
 #endif
 
-#include "common/logging.hpp"
 #include "common/new.hpp"
 #include "common/string.hpp"
 #include "mac/channel_mask.hpp"
@@ -93,8 +92,6 @@
 namespace ot {
 namespace Cli {
 
-constexpr Interpreter::Command Interpreter::sCommands[];
-
 Interpreter *Interpreter::sInterpreter = nullptr;
 static OT_DEFINE_ALIGNED_VAR(sInterpreterRaw, sizeof(Interpreter), uint64_t);
 
@@ -200,7 +197,7 @@
 }
 
 #if OPENTHREAD_CONFIG_DIAG_ENABLE
-otError Interpreter::ProcessDiag(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("diag")>(Arg aArgs[])
 {
     otError error;
     char *  args[kMaxArgs];
@@ -217,47 +214,27 @@
 }
 #endif
 
-otError Interpreter::ProcessHelp(Arg aArgs[])
-{
-    OT_UNUSED_VARIABLE(aArgs);
-
-    for (const Command &command : sCommands)
-    {
-        OutputLine(command.mName);
-    }
-
-    for (uint8_t i = 0; i < mUserCommandsLength; i++)
-    {
-        OutputLine("%s", mUserCommands[i].mName);
-    }
-
-    return OT_ERROR_NONE;
-}
-
-otError Interpreter::ProcessVersion(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("version")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
     if (aArgs[0].IsEmpty())
     {
         OutputLine("%s", otGetVersionString());
-        ExitNow();
     }
-
-    if (aArgs[0] == "api")
+    else if (aArgs[0] == "api")
     {
         OutputLine("%d", OPENTHREAD_API_VERSION);
     }
     else
     {
-        ExitNow(error = OT_ERROR_INVALID_COMMAND);
+        error = OT_ERROR_INVALID_COMMAND;
     }
 
-exit:
     return error;
 }
 
-otError Interpreter::ProcessReset(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("reset")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -268,9 +245,8 @@
 
 void Interpreter::ProcessLine(char *aBuf)
 {
-    Arg            args[kMaxArgs + 1];
-    const Command *command;
-    otError        error = OT_ERROR_NONE;
+    Arg     args[kMaxArgs + 1];
+    otError error = OT_ERROR_NONE;
 
     OT_ASSERT(aBuf != nullptr);
 
@@ -286,23 +262,14 @@
     LogInput(args);
 
 #if OPENTHREAD_CONFIG_DIAG_ENABLE
-    if (otDiagIsEnabled(GetInstancePtr()) && (args[0] != "diag"))
+    if (otDiagIsEnabled(GetInstancePtr()) && (args[0] != "diag") && (args[0] != "factoryreset"))
     {
         OutputLine("under diagnostics mode, execute 'diag stop' before running any other commands.");
         ExitNow(error = OT_ERROR_INVALID_STATE);
     }
 #endif
 
-    command = Utils::LookupTable::Find(args[0].GetCString(), sCommands);
-
-    if (command != nullptr)
-    {
-        error = (this->*command->mHandler)(args + 1);
-    }
-    else
-    {
-        error = ProcessUserCommands(args);
-    }
+    error = ProcessCommand(args);
 
 exit:
     if ((error != OT_ERROR_NONE) || !args[0].IsEmpty())
@@ -434,63 +401,147 @@
 
 #endif // OPENTHREAD_CONFIG_PING_SENDER_ENABLE
 
+otError Interpreter::ParsePreference(const Arg &aArg, otRoutePreference &aPreference)
+{
+    otError error = OT_ERROR_NONE;
+
+    if (aArg == "high")
+    {
+        aPreference = OT_ROUTE_PREFERENCE_HIGH;
+    }
+    else if (aArg == "med")
+    {
+        aPreference = OT_ROUTE_PREFERENCE_MED;
+    }
+    else if (aArg == "low")
+    {
+        aPreference = OT_ROUTE_PREFERENCE_LOW;
+    }
+    else
+    {
+        error = OT_ERROR_INVALID_ARGS;
+    }
+
+    return error;
+}
+
+const char *Interpreter::PreferenceToString(signed int aPreference)
+{
+    const char *str = "";
+
+    switch (aPreference)
+    {
+    case OT_ROUTE_PREFERENCE_LOW:
+        str = "low";
+        break;
+
+    case OT_ROUTE_PREFERENCE_MED:
+        str = "med";
+        break;
+
+    case OT_ROUTE_PREFERENCE_HIGH:
+        str = "high";
+        break;
+
+    default:
+        break;
+    }
+
+    return str;
+}
+
 #if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
-otError Interpreter::ProcessHistory(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("history")>(Arg aArgs[])
 {
     return mHistory.Process(aArgs);
 }
 #endif
 
 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
-otError Interpreter::ProcessBorderAgent(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("ba")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
+    /**
+     * @cli ba port
+     * @code
+     * ba port
+     * 49153
+     * Done
+     * @endcode
+     * @par api_copy
+     * #otBorderAgentGetUdpPort
+     */
     if (aArgs[0] == "port")
     {
         OutputLine("%hu", otBorderAgentGetUdpPort(GetInstancePtr()));
     }
+    /**
+     * @cli ba state
+     * @code
+     * ba state
+     * Started
+     * Done
+     * @endcode
+     * @par api_copy
+     * #otBorderAgentGetState
+     */
     else if (aArgs[0] == "state")
     {
-        const char *state;
+        static const char *const kStateStrings[] = {
+            "Stopped"  // (0) OT_BORDER_AGENT_STATE_STOPPED
+            "Started", // (1) OT_BORDER_AGENT_STATE_STARTED
+            "Active",  // (2) OT_BORDER_AGENT_STATE_ACTIVE
+        };
 
-        switch (otBorderAgentGetState(GetInstancePtr()))
-        {
-        case OT_BORDER_AGENT_STATE_STOPPED:
-            state = "Stopped";
-            break;
-        case OT_BORDER_AGENT_STATE_STARTED:
-            state = "Started";
-            break;
-        case OT_BORDER_AGENT_STATE_ACTIVE:
-            state = "Active";
-            break;
-        default:
-            state = "Unknown";
-            break;
-        }
-        OutputLine(state);
+        static_assert(0 == OT_BORDER_AGENT_STATE_STOPPED, "OT_BORDER_AGENT_STATE_STOPPED value is incorrect");
+        static_assert(1 == OT_BORDER_AGENT_STATE_STARTED, "OT_BORDER_AGENT_STATE_STARTED value is incorrect");
+        static_assert(2 == OT_BORDER_AGENT_STATE_ACTIVE, "OT_BORDER_AGENT_STATE_ACTIVE value is incorrect");
+
+        OutputLine("%s", Stringify(otBorderAgentGetState(GetInstancePtr()), kStateStrings));
     }
     else
     {
-        ExitNow(error = OT_ERROR_INVALID_COMMAND);
+        error = OT_ERROR_INVALID_COMMAND;
     }
 
-exit:
     return error;
 }
-#endif
+#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
 
 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
-otError Interpreter::ProcessBorderRouting(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("br")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
     bool    enable;
 
+    /**
+     * @cli br (enable,disable)
+     * @code
+     * br enable
+     * Done
+     * @endcode
+     * @code
+     * br disable
+     * Done
+     * @endcode
+     * @par api_copy
+     * #otBorderRoutingSetEnabled
+     */
     if (ParseEnableOrDisable(aArgs[0], enable) == OT_ERROR_NONE)
     {
         SuccessOrExit(error = otBorderRoutingSetEnabled(GetInstancePtr(), enable));
     }
+    /**
+     * @cli br omrprefix
+     * @code
+     * br omrprefix
+     * fdfc:1ff5:1512:5622::/64
+     * Done
+     * @endcode
+     * @par api_copy
+     * #otBorderRoutingGetOmrPrefix
+     */
     else if (aArgs[0] == "omrprefix")
     {
         otIp6Prefix omrPrefix;
@@ -498,6 +549,35 @@
         SuccessOrExit(error = otBorderRoutingGetOmrPrefix(GetInstancePtr(), &omrPrefix));
         OutputIp6PrefixLine(omrPrefix);
     }
+    /**
+     * @cli br favoredomrprefix
+     * @code
+     * br favoredomrprefix
+     * fdfc:1ff5:1512:5622::/64 prf:low
+     * Done
+     * @endcode
+     * @par api_copy
+     * #otBorderRoutingGetFavoredOmrPrefix
+     */
+    else if (aArgs[0] == "favoredomrprefix")
+    {
+        otIp6Prefix       prefix;
+        otRoutePreference preference;
+
+        SuccessOrExit(error = otBorderRoutingGetFavoredOmrPrefix(GetInstancePtr(), &prefix, &preference));
+        OutputIp6Prefix(prefix);
+        OutputLine(" prf:%s", PreferenceToString(preference));
+    }
+    /**
+     * @cli br onlinkprefix
+     * @code
+     * br onlinkprefix
+     * fd41:2650:a6f5:0::/64
+     * Done
+     * @endcode
+     * @par api_copy
+     * #otBorderRoutingGetOnLinkPrefix
+     */
     else if (aArgs[0] == "onlinkprefix")
     {
         otIp6Prefix onLinkPrefix;
@@ -505,18 +585,109 @@
         SuccessOrExit(error = otBorderRoutingGetOnLinkPrefix(GetInstancePtr(), &onLinkPrefix));
         OutputIp6PrefixLine(onLinkPrefix);
     }
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
+    /**
+     * @cli br nat64prefix
+     * @code
+     * br nat64prefix
+     * fd14:1078:b3d5:b0b0:0:0::/96
+     * Done
+     * @endcode
+     * @par api_copy
+     * #otBorderRoutingGetNat64Prefix
+     */
+    else if (aArgs[0] == "nat64prefix")
+    {
+        otIp6Prefix nat64Prefix;
+
+        SuccessOrExit(error = otBorderRoutingGetNat64Prefix(GetInstancePtr(), &nat64Prefix));
+        OutputIp6PrefixLine(nat64Prefix);
+    }
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
+    /**
+     * @cli br rioprf (high,med,low)
+     * @code
+     * br rioprf
+     * med
+     * Done
+     * @endcode
+     * @code
+     * br rioprf low
+     * Done
+     * @endcode
+     * @cparam br rioprf [@ca{high}|@ca{med}|@ca{low}]
+     * @par api_copy
+     * #otBorderRoutingSetRouteInfoOptionPreference
+     *
+     */
+    else if (aArgs[0] == "rioprf")
+    {
+        if (aArgs[1].IsEmpty())
+        {
+            OutputLine("%s", PreferenceToString(otBorderRoutingGetRouteInfoOptionPreference(GetInstancePtr())));
+        }
+        else
+        {
+            otRoutePreference preference;
+
+            SuccessOrExit(error = ParsePreference(aArgs[1], preference));
+            otBorderRoutingSetRouteInfoOptionPreference(GetInstancePtr(), preference);
+        }
+    }
+    /**
+     * @cli br prefixtable
+     * @code
+     * br prefixtable
+     * prefix:fd00:1234:5678:0::/64, on-link:no, ms-since-rx:29526, lifetime:1800, route-prf:med,
+     * router:ff02:0:0:0:0:0:0:1
+     * prefix:1200:abba:baba:0::/64, on-link:yes, ms-since-rx:29527, lifetime:1800, preferred:1800,
+     * router:ff02:0:0:0:0:0:0:1
+     * Done
+     * @endcode
+     * @par api_copy
+     * #otBorderRoutingGetNextPrefixTableEntry
+     *
+     */
+    else if (aArgs[0] == "prefixtable")
+    {
+        otBorderRoutingPrefixTableIterator iterator;
+        otBorderRoutingPrefixTableEntry    entry;
+
+        otBorderRoutingPrefixTableInitIterator(GetInstancePtr(), &iterator);
+
+        while (otBorderRoutingGetNextPrefixTableEntry(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE)
+        {
+            char string[OT_IP6_PREFIX_STRING_SIZE];
+
+            otIp6PrefixToString(&entry.mPrefix, string, sizeof(string));
+            OutputFormat("prefix:%s, on-link:%s, ms-since-rx:%u, lifetime:%u, ", string, entry.mIsOnLink ? "yes" : "no",
+                         entry.mMsecSinceLastUpdate, entry.mValidLifetime);
+
+            if (entry.mIsOnLink)
+            {
+                OutputFormat("preferred:%u, ", entry.mPreferredLifetime);
+            }
+            else
+            {
+                OutputFormat("route-prf:%s, ", PreferenceToString(entry.mRoutePreference));
+            }
+
+            otIp6AddressToString(&entry.mRouterAddress, string, sizeof(string));
+            OutputLine("router:%s", string);
+        }
+    }
     else
     {
-        ExitNow(error = OT_ERROR_INVALID_COMMAND);
+        error = OT_ERROR_INVALID_COMMAND;
     }
 
 exit:
     return error;
 }
-#endif
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
 
 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-otError Interpreter::ProcessBackboneRouter(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("bbr")>(Arg aArgs[])
 {
     otError                error = OT_ERROR_INVALID_COMMAND;
     otBackboneRouterConfig config;
@@ -664,18 +835,17 @@
     }
     else if (aArgs[0] == "state")
     {
-        switch (otBackboneRouterGetState(GetInstancePtr()))
-        {
-        case OT_BACKBONE_ROUTER_STATE_DISABLED:
-            OutputLine("Disabled");
-            break;
-        case OT_BACKBONE_ROUTER_STATE_SECONDARY:
-            OutputLine("Secondary");
-            break;
-        case OT_BACKBONE_ROUTER_STATE_PRIMARY:
-            OutputLine("Primary");
-            break;
-        }
+        static const char *const kStateStrings[] = {
+            "Disabled",  // (0) OT_BACKBONE_ROUTER_STATE_DISABLED
+            "Secondary", // (1) OT_BACKBONE_ROUTER_STATE_SECONDARY
+            "Primary",   // (2) OT_BACKBONE_ROUTER_STATE_PRIMARY
+        };
+
+        static_assert(0 == OT_BACKBONE_ROUTER_STATE_DISABLED, "OT_BACKBONE_ROUTER_STATE_DISABLED value is incorrect");
+        static_assert(1 == OT_BACKBONE_ROUTER_STATE_SECONDARY, "OT_BACKBONE_ROUTER_STATE_SECONDARY value is incorrect");
+        static_assert(2 == OT_BACKBONE_ROUTER_STATE_PRIMARY, "OT_BACKBONE_ROUTER_STATE_PRIMARY value is incorrect");
+
+        OutputLine("%s", Stringify(otBackboneRouterGetState(GetInstancePtr()), kStateStrings));
     }
     else if (aArgs[0] == "config")
     {
@@ -726,7 +896,7 @@
 }
 #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
 
-otError Interpreter::ProcessDomainName(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("domainname")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -744,7 +914,7 @@
 }
 
 #if OPENTHREAD_CONFIG_DUA_ENABLE
-otError Interpreter::ProcessDua(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("dua")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -783,27 +953,25 @@
 
 #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
 
-otError Interpreter::ProcessBufferInfo(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("bufferinfo")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
     struct BufferInfoName
     {
-        const uint16_t otBufferInfo::*mNumMessagesPtr;
-        const uint16_t otBufferInfo::*mNumBuffersPtr;
-        const char *                  mName;
+        const otMessageQueueInfo otBufferInfo::*mQueuePtr;
+        const char *                            mName;
     };
 
     static const BufferInfoName kBufferInfoNames[] = {
-        {&otBufferInfo::m6loSendMessages, &otBufferInfo::m6loSendBuffers, "6lo send"},
-        {&otBufferInfo::m6loReassemblyMessages, &otBufferInfo::m6loReassemblyBuffers, "6lo reas"},
-        {&otBufferInfo::mIp6Messages, &otBufferInfo::mIp6Buffers, "ip6"},
-        {&otBufferInfo::mMplMessages, &otBufferInfo::mMplBuffers, "mpl"},
-        {&otBufferInfo::mMleMessages, &otBufferInfo::mMleBuffers, "mle"},
-        {&otBufferInfo::mArpMessages, &otBufferInfo::mArpBuffers, "arp"},
-        {&otBufferInfo::mCoapMessages, &otBufferInfo::mCoapBuffers, "coap"},
-        {&otBufferInfo::mCoapSecureMessages, &otBufferInfo::mCoapSecureBuffers, "coap secure"},
-        {&otBufferInfo::mApplicationCoapMessages, &otBufferInfo::mApplicationCoapBuffers, "application coap"},
+        {&otBufferInfo::m6loSendQueue, "6lo send"},
+        {&otBufferInfo::m6loReassemblyQueue, "6lo reas"},
+        {&otBufferInfo::mIp6Queue, "ip6"},
+        {&otBufferInfo::mMplQueue, "mpl"},
+        {&otBufferInfo::mMleQueue, "mle"},
+        {&otBufferInfo::mCoapQueue, "coap"},
+        {&otBufferInfo::mCoapSecureQueue, "coap secure"},
+        {&otBufferInfo::mApplicationCoapQueue, "application coap"},
     };
 
     otBufferInfo bufferInfo;
@@ -815,13 +983,14 @@
 
     for (const BufferInfoName &info : kBufferInfoNames)
     {
-        OutputLine("%s: %d %d", info.mName, bufferInfo.*info.mNumMessagesPtr, bufferInfo.*info.mNumBuffersPtr);
+        OutputLine("%s: %u %u %u", info.mName, (bufferInfo.*info.mQueuePtr).mNumMessages,
+                   (bufferInfo.*info.mQueuePtr).mNumBuffers, (bufferInfo.*info.mQueuePtr).mTotalBytes);
     }
 
     return OT_ERROR_NONE;
 }
 
-otError Interpreter::ProcessCcaThreshold(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("ccathreshold")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
     int8_t  cca;
@@ -842,22 +1011,37 @@
 }
 
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-otError Interpreter::ProcessCcm(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("ccm")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
     bool    enable;
 
     VerifyOrExit(!aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_COMMAND);
 
-    SuccessOrExit(error = ParseEnableOrDisable(aArgs[1], enable));
+    SuccessOrExit(error = ParseEnableOrDisable(aArgs[0], enable));
     otThreadSetCcmEnabled(GetInstancePtr(), enable);
 
 exit:
     return error;
 }
+
+template <> otError Interpreter::Process<Cmd("tvcheck")>(Arg aArgs[])
+{
+    otError error = OT_ERROR_NONE;
+    bool    enable;
+
+    VerifyOrExit(!aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_COMMAND);
+
+    SuccessOrExit(error = ParseEnableOrDisable(aArgs[0], enable));
+    otThreadSetThreadVersionCheckEnabled(GetInstancePtr(), enable);
+
+exit:
+    return error;
+}
+
 #endif
 
-otError Interpreter::ProcessChannel(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("channel")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -994,7 +1178,7 @@
 }
 
 #if OPENTHREAD_FTD
-otError Interpreter::ProcessChild(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("child")>(Arg aArgs[])
 {
     otError          error = OT_ERROR_NONE;
     otChildInfo      childInfo;
@@ -1082,7 +1266,7 @@
     return error;
 }
 
-otError Interpreter::ProcessChildIp(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("childip")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -1128,14 +1312,14 @@
     return error;
 }
 
-otError Interpreter::ProcessChildMax(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("childmax")>(Arg aArgs[])
 {
     return ProcessGetSet(aArgs, otThreadGetMaxAllowedChildren, otThreadSetMaxAllowedChildren);
 }
 #endif // OPENTHREAD_FTD
 
 #if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
-otError Interpreter::ProcessChildSupervision(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("childsupervision")>(Arg aArgs[])
 {
     otError error = OT_ERROR_INVALID_ARGS;
 
@@ -1154,27 +1338,27 @@
 }
 #endif // OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
 
-otError Interpreter::ProcessChildTimeout(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("childtimeout")>(Arg aArgs[])
 {
     return ProcessGetSet(aArgs, otThreadGetChildTimeout, otThreadSetChildTimeout);
 }
 
 #if OPENTHREAD_CONFIG_COAP_API_ENABLE
-otError Interpreter::ProcessCoap(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("coap")>(Arg aArgs[])
 {
     return mCoap.Process(aArgs);
 }
 #endif
 
 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
-otError Interpreter::ProcessCoapSecure(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("coaps")>(Arg aArgs[])
 {
     return mCoapSecure.Process(aArgs);
 }
 #endif
 
 #if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
-otError Interpreter::ProcessCoexMetrics(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("coex")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
     bool    enable;
@@ -1240,7 +1424,7 @@
     }
     else
     {
-        ExitNow(error = OT_ERROR_INVALID_ARGS);
+        error = OT_ERROR_INVALID_ARGS;
     }
 
 exit:
@@ -1249,13 +1433,13 @@
 #endif // OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
 
 #if OPENTHREAD_FTD
-otError Interpreter::ProcessContextIdReuseDelay(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("contextreusedelay")>(Arg aArgs[])
 {
     return ProcessGetSet(aArgs, otThreadGetContextIdReuseDelay, otThreadSetContextIdReuseDelay);
 }
 #endif
 
-otError Interpreter::ProcessCounters(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("counters")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -1332,7 +1516,7 @@
         }
         else
         {
-            ExitNow(error = OT_ERROR_INVALID_ARGS);
+            error = OT_ERROR_INVALID_ARGS;
         }
     }
     else if (aArgs[0] == "mle")
@@ -1370,7 +1554,7 @@
         }
         else
         {
-            ExitNow(error = OT_ERROR_INVALID_ARGS);
+            error = OT_ERROR_INVALID_ARGS;
         }
     }
     else if (aArgs[0] == "ip")
@@ -1403,23 +1587,21 @@
         }
         else
         {
-            ExitNow(error = OT_ERROR_INVALID_ARGS);
+            error = OT_ERROR_INVALID_ARGS;
         }
     }
     else
     {
-        ExitNow(error = OT_ERROR_INVALID_ARGS);
+        error = OT_ERROR_INVALID_ARGS;
     }
 
-exit:
     return error;
 }
 
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-otError Interpreter::ProcessCsl(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("csl")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
-    ;
 
     if (aArgs[0].IsEmpty())
     {
@@ -1450,7 +1632,7 @@
 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
 
 #if OPENTHREAD_FTD
-otError Interpreter::ProcessDelayTimerMin(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("delaytimermin")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -1466,7 +1648,7 @@
     }
     else
     {
-        ExitNow(error = OT_ERROR_INVALID_ARGS);
+        error = OT_ERROR_INVALID_ARGS;
     }
 
 exit:
@@ -1474,7 +1656,26 @@
 }
 #endif
 
-otError Interpreter::ProcessDiscover(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("detach")>(Arg aArgs[])
+{
+    otError error = OT_ERROR_NONE;
+
+    if (aArgs[0] == "async")
+    {
+        SuccessOrExit(error = otThreadDetachGracefully(GetInstancePtr(), nullptr, nullptr));
+    }
+    else
+    {
+        SuccessOrExit(error =
+                          otThreadDetachGracefully(GetInstancePtr(), &Interpreter::HandleDetachGracefullyResult, this));
+        error = OT_ERROR_PENDING;
+    }
+
+exit:
+    return error;
+}
+
+template <> otError Interpreter::Process<Cmd("discover")>(Arg aArgs[])
 {
     otError  error        = OT_ERROR_NONE;
     uint32_t scanChannels = 0;
@@ -1491,7 +1692,15 @@
     SuccessOrExit(error = otThreadDiscover(GetInstancePtr(), scanChannels, OT_PANID_BROADCAST, false, false,
                                            &Interpreter::HandleActiveScanResult, this));
 
-    OutputScanTableHeader();
+    static const char *const kScanTableTitles[] = {
+        "Network Name", "Extended PAN", "PAN", "MAC Address", "Ch", "dBm", "LQI",
+    };
+
+    static const uint8_t kScanTableColumnWidths[] = {
+        18, 18, 6, 18, 4, 5, 5,
+    };
+
+    OutputTableHeader(kScanTableTitles, kScanTableColumnWidths);
 
     error = OT_ERROR_PENDING;
 
@@ -1499,7 +1708,7 @@
     return error;
 }
 
-otError Interpreter::ProcessDns(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("dns")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -1536,9 +1745,8 @@
         {
             const otDnsQueryConfig *defaultConfig = otDnsClientGetDefaultConfig(GetInstancePtr());
 
-            OutputFormat("Server: [");
-            OutputIp6Address(defaultConfig->mServerSockAddr.mAddress);
-            OutputLine("]:%d", defaultConfig->mServerSockAddr.mPort);
+            OutputFormat("Server: ");
+            OutputSockAddrLine(defaultConfig->mServerSockAddr);
             OutputLine("ResponseTimeout: %u ms", defaultConfig->mResponseTimeout);
             OutputLine("MaxTxAttempts: %u", defaultConfig->mMaxTxAttempts);
             OutputLine("RecursionDesired: %s",
@@ -1558,6 +1766,16 @@
                                                         &Interpreter::HandleDnsAddressResponse, this, config));
         error = OT_ERROR_PENDING;
     }
+#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
+    else if (aArgs[0] == "resolve4")
+    {
+        VerifyOrExit(!aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+        SuccessOrExit(error = GetDnsConfig(aArgs + 2, config));
+        SuccessOrExit(error = otDnsClientResolveIp4Address(GetInstancePtr(), aArgs[1].GetCString(),
+                                                           &Interpreter::HandleDnsAddressResponse, this, config));
+        error = OT_ERROR_PENDING;
+    }
+#endif
 #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
     else if (aArgs[0] == "browse")
     {
@@ -1754,7 +1972,7 @@
         "retry",
     };
 
-    return static_cast<uint8_t>(aState) < OT_ARRAY_LENGTH(kStateStrings) ? kStateStrings[aState] : "unknown";
+    return Interpreter::Stringify(aState, kStateStrings);
 }
 
 void Interpreter::OutputEidCacheEntry(const otCacheEntryInfo &aEntry)
@@ -1785,7 +2003,7 @@
     OutputLine("");
 }
 
-otError Interpreter::ProcessEidCache(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("eidcache")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -1805,7 +2023,17 @@
 }
 #endif
 
-otError Interpreter::ProcessEui64(Arg aArgs[])
+/**
+ * @cli eui64
+ * @code
+ * eui64
+ * 0615aae900124b00
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otPlatRadioGetIeeeEui64
+ */
+template <> otError Interpreter::Process<Cmd("eui64")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -1821,7 +2049,7 @@
     return error;
 }
 
-otError Interpreter::ProcessExtAddress(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("extaddr")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -1841,7 +2069,7 @@
     return error;
 }
 
-otError Interpreter::ProcessLog(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("log")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -1880,7 +2108,7 @@
     return error;
 }
 
-otError Interpreter::ProcessExtPanId(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("extpanid")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -1900,7 +2128,7 @@
     return error;
 }
 
-otError Interpreter::ProcessFactoryReset(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("factoryreset")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -1910,7 +2138,7 @@
 }
 
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-otError Interpreter::ProcessFake(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("fake")>(Arg aArgs[])
 {
     otError error = OT_ERROR_INVALID_COMMAND;
 
@@ -1944,7 +2172,7 @@
 }
 #endif
 
-otError Interpreter::ProcessFem(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("fem")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -1981,7 +2209,7 @@
     return error;
 }
 
-otError Interpreter::ProcessIfconfig(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("ifconfig")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -2013,38 +2241,33 @@
     return error;
 }
 
-otError Interpreter::ProcessIpAddrAdd(Arg aArgs[])
+const char *Interpreter::AddressOriginToString(uint8_t aOrigin)
 {
-    otError        error;
-    otNetifAddress aAddress;
+    static const char *const kOriginStrings[4] = {
+        "thread", // 0, OT_ADDRESS_ORIGIN_THREAD
+        "slaac",  // 1, OT_ADDRESS_ORIGIN_SLAAC
+        "dhcp6",  // 2, OT_ADDRESS_ORIGIN_DHCPV6
+        "manual", // 3, OT_ADDRESS_ORIGIN_MANUAL
+    };
 
-    SuccessOrExit(error = aArgs[0].ParseAsIp6Address(aAddress.mAddress));
-    aAddress.mPrefixLength  = 64;
-    aAddress.mPreferred     = true;
-    aAddress.mValid         = true;
-    aAddress.mAddressOrigin = OT_ADDRESS_ORIGIN_MANUAL;
+    static_assert(0 == OT_ADDRESS_ORIGIN_THREAD, "OT_ADDRESS_ORIGIN_THREAD value is incorrect");
+    static_assert(1 == OT_ADDRESS_ORIGIN_SLAAC, "OT_ADDRESS_ORIGIN_SLAAC value is incorrect");
+    static_assert(2 == OT_ADDRESS_ORIGIN_DHCPV6, "OT_ADDRESS_ORIGIN_DHCPV6 value is incorrect");
+    static_assert(3 == OT_ADDRESS_ORIGIN_MANUAL, "OT_ADDRESS_ORIGIN_MANUAL value is incorrect");
 
-    error = otIp6AddUnicastAddress(GetInstancePtr(), &aAddress);
-
-exit:
-    return error;
+    return Stringify(aOrigin, kOriginStrings);
 }
 
-otError Interpreter::ProcessIpAddrDel(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("ipaddr")>(Arg aArgs[])
 {
-    otError      error;
-    otIp6Address address;
+    otError error   = OT_ERROR_NONE;
+    bool    verbose = false;
 
-    SuccessOrExit(error = aArgs[0].ParseAsIp6Address(address));
-    error = otIp6RemoveUnicastAddress(GetInstancePtr(), &address);
-
-exit:
-    return error;
-}
-
-otError Interpreter::ProcessIpAddr(Arg aArgs[])
-{
-    otError error = OT_ERROR_NONE;
+    if (aArgs[0] == "-v")
+    {
+        aArgs++;
+        verbose = true;
+    }
 
     if (aArgs[0].IsEmpty())
     {
@@ -2052,86 +2275,57 @@
 
         for (const otNetifAddress *addr = unicastAddrs; addr; addr = addr->mNext)
         {
-            OutputIp6AddressLine(addr->mAddress);
+            OutputIp6Address(addr->mAddress);
+
+            if (verbose)
+            {
+                OutputFormat(" origin:%s", AddressOriginToString(addr->mAddressOrigin));
+            }
+
+            OutputLine("");
         }
     }
+    else if (aArgs[0] == "add")
+    {
+        otNetifAddress address;
+
+        SuccessOrExit(error = aArgs[1].ParseAsIp6Address(address.mAddress));
+        address.mPrefixLength  = 64;
+        address.mPreferred     = true;
+        address.mValid         = true;
+        address.mAddressOrigin = OT_ADDRESS_ORIGIN_MANUAL;
+
+        error = otIp6AddUnicastAddress(GetInstancePtr(), &address);
+    }
+    else if (aArgs[0] == "del")
+    {
+        otIp6Address address;
+
+        SuccessOrExit(error = aArgs[1].ParseAsIp6Address(address));
+        error = otIp6RemoveUnicastAddress(GetInstancePtr(), &address);
+    }
+    else if (aArgs[0] == "linklocal")
+    {
+        OutputIp6AddressLine(*otThreadGetLinkLocalIp6Address(GetInstancePtr()));
+    }
+    else if (aArgs[0] == "rloc")
+    {
+        OutputIp6AddressLine(*otThreadGetRloc(GetInstancePtr()));
+    }
+    else if (aArgs[0] == "mleid")
+    {
+        OutputIp6AddressLine(*otThreadGetMeshLocalEid(GetInstancePtr()));
+    }
     else
     {
-        if (aArgs[0] == "add")
-        {
-            SuccessOrExit(error = ProcessIpAddrAdd(aArgs + 1));
-        }
-        else if (aArgs[0] == "del")
-        {
-            SuccessOrExit(error = ProcessIpAddrDel(aArgs + 1));
-        }
-        else if (aArgs[0] == "linklocal")
-        {
-            OutputIp6AddressLine(*otThreadGetLinkLocalIp6Address(GetInstancePtr()));
-        }
-        else if (aArgs[0] == "rloc")
-        {
-            OutputIp6AddressLine(*otThreadGetRloc(GetInstancePtr()));
-        }
-        else if (aArgs[0] == "mleid")
-        {
-            OutputIp6AddressLine(*otThreadGetMeshLocalEid(GetInstancePtr()));
-        }
-        else
-        {
-            ExitNow(error = OT_ERROR_INVALID_COMMAND);
-        }
+        error = OT_ERROR_INVALID_COMMAND;
     }
 
 exit:
     return error;
 }
 
-otError Interpreter::ProcessIpMulticastAddrAdd(Arg aArgs[])
-{
-    otError      error;
-    otIp6Address address;
-
-    SuccessOrExit(error = aArgs[0].ParseAsIp6Address(address));
-    error = otIp6SubscribeMulticastAddress(GetInstancePtr(), &address);
-
-exit:
-    return error;
-}
-
-otError Interpreter::ProcessIpMulticastAddrDel(Arg aArgs[])
-{
-    otError      error;
-    otIp6Address address;
-
-    SuccessOrExit(error = aArgs[0].ParseAsIp6Address(address));
-    error = otIp6UnsubscribeMulticastAddress(GetInstancePtr(), &address);
-
-exit:
-    return error;
-}
-
-otError Interpreter::ProcessMulticastPromiscuous(Arg aArgs[])
-{
-    otError error = OT_ERROR_NONE;
-
-    if (aArgs[0].IsEmpty())
-    {
-        OutputEnabledDisabledStatus(otIp6IsMulticastPromiscuousEnabled(GetInstancePtr()));
-    }
-    else
-    {
-        bool enable;
-
-        SuccessOrExit(error = ParseEnableOrDisable(aArgs[0], enable));
-        otIp6SetMulticastPromiscuousEnabled(GetInstancePtr(), enable);
-    }
-
-exit:
-    return error;
-}
-
-otError Interpreter::ProcessIpMulticastAddr(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("ipmaddr")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -2143,39 +2337,62 @@
             OutputIp6AddressLine(addr->mAddress);
         }
     }
-    else
+    else if (aArgs[0] == "add")
     {
-        if (aArgs[0] == "add")
+        otIp6Address address;
+
+        aArgs++;
+
+        do
         {
-            SuccessOrExit(error = ProcessIpMulticastAddrAdd(aArgs + 1));
+            SuccessOrExit(error = aArgs->ParseAsIp6Address(address));
+            SuccessOrExit(error = otIp6SubscribeMulticastAddress(GetInstancePtr(), &address));
         }
-        else if (aArgs[0] == "del")
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+        while (!(++aArgs)->IsEmpty());
+#else
+        while (false);
+#endif
+    }
+    else if (aArgs[0] == "del")
+    {
+        otIp6Address address;
+
+        SuccessOrExit(error = aArgs[1].ParseAsIp6Address(address));
+        error = otIp6UnsubscribeMulticastAddress(GetInstancePtr(), &address);
+    }
+    else if (aArgs[0] == "promiscuous")
+    {
+        if (aArgs[1].IsEmpty())
         {
-            SuccessOrExit(error = ProcessIpMulticastAddrDel(aArgs + 1));
-        }
-        else if (aArgs[0] == "promiscuous")
-        {
-            SuccessOrExit(error = ProcessMulticastPromiscuous(aArgs + 1));
-        }
-        else if (aArgs[0] == "llatn")
-        {
-            OutputIp6AddressLine(*otThreadGetLinkLocalAllThreadNodesMulticastAddress(GetInstancePtr()));
-        }
-        else if (aArgs[0] == "rlatn")
-        {
-            OutputIp6AddressLine(*otThreadGetRealmLocalAllThreadNodesMulticastAddress(GetInstancePtr()));
+            OutputEnabledDisabledStatus(otIp6IsMulticastPromiscuousEnabled(GetInstancePtr()));
         }
         else
         {
-            ExitNow(error = OT_ERROR_INVALID_COMMAND);
+            bool enable;
+
+            SuccessOrExit(error = ParseEnableOrDisable(aArgs[1], enable));
+            otIp6SetMulticastPromiscuousEnabled(GetInstancePtr(), enable);
         }
     }
+    else if (aArgs[0] == "llatn")
+    {
+        OutputIp6AddressLine(*otThreadGetLinkLocalAllThreadNodesMulticastAddress(GetInstancePtr()));
+    }
+    else if (aArgs[0] == "rlatn")
+    {
+        OutputIp6AddressLine(*otThreadGetRealmLocalAllThreadNodesMulticastAddress(GetInstancePtr()));
+    }
+    else
+    {
+        error = OT_ERROR_INVALID_COMMAND;
+    }
 
 exit:
     return error;
 }
 
-otError Interpreter::ProcessKeySequence(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("keysequence")>(Arg aArgs[])
 {
     otError error = OT_ERROR_INVALID_ARGS;
 
@@ -2191,7 +2408,7 @@
     return error;
 }
 
-otError Interpreter::ProcessLeaderData(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("leaderdata")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -2211,7 +2428,7 @@
 }
 
 #if OPENTHREAD_FTD
-otError Interpreter::ProcessPartitionId(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("partitionid")>(Arg aArgs[])
 {
     otError error = OT_ERROR_INVALID_COMMAND;
 
@@ -2230,7 +2447,7 @@
     return error;
 }
 
-otError Interpreter::ProcessLeaderWeight(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("leaderweight")>(Arg aArgs[])
 {
     return ProcessGetSet(aArgs, otThreadGetLocalLeaderWeight, otThreadSetLocalLeaderWeight);
 }
@@ -2325,52 +2542,64 @@
 
 const char *Interpreter::LinkMetricsStatusToStr(uint8_t aStatus)
 {
-    uint8_t            strIndex                = 0;
-    static const char *linkMetricsStatusText[] = {
-        "Success",
-        "Cannot support new series",
-        "Series ID already registered",
-        "Series ID not recognized",
-        "No matching series ID",
-        "Other error",
-        "Unknown error",
+    static const char *const kStatusStrings[] = {
+        "Success",                      // (0) OT_LINK_METRICS_STATUS_SUCCESS
+        "Cannot support new series",    // (1) OT_LINK_METRICS_STATUS_CANNOT_SUPPORT_NEW_SERIES
+        "Series ID already registered", // (2) OT_LINK_METRICS_STATUS_SERIESID_ALREADY_REGISTERED
+        "Series ID not recognized",     // (3) OT_LINK_METRICS_STATUS_SERIESID_NOT_RECOGNIZED
+        "No matching series ID",        // (4) OT_LINK_METRICS_STATUS_NO_MATCHING_FRAMES_RECEIVED
     };
 
-    switch (aStatus)
+    const char *str = "Unknown error";
+
+    static_assert(0 == OT_LINK_METRICS_STATUS_SUCCESS, "STATUS_SUCCESS is incorrect");
+    static_assert(1 == OT_LINK_METRICS_STATUS_CANNOT_SUPPORT_NEW_SERIES, "CANNOT_SUPPORT_NEW_SERIES is incorrect");
+    static_assert(2 == OT_LINK_METRICS_STATUS_SERIESID_ALREADY_REGISTERED, "SERIESID_ALREADY_REGISTERED is incorrect");
+    static_assert(3 == OT_LINK_METRICS_STATUS_SERIESID_NOT_RECOGNIZED, "SERIESID_NOT_RECOGNIZED is incorrect");
+    static_assert(4 == OT_LINK_METRICS_STATUS_NO_MATCHING_FRAMES_RECEIVED, "NO_MATCHING_FRAMES_RECEIVED is incorrect");
+
+    if (aStatus < OT_ARRAY_LENGTH(kStatusStrings))
     {
-    case OT_LINK_METRICS_STATUS_SUCCESS:
-        strIndex = 0;
-        break;
-    case OT_LINK_METRICS_STATUS_CANNOT_SUPPORT_NEW_SERIES:
-        strIndex = 1;
-        break;
-    case OT_LINK_METRICS_STATUS_SERIESID_ALREADY_REGISTERED:
-        strIndex = 2;
-        break;
-    case OT_LINK_METRICS_STATUS_SERIESID_NOT_RECOGNIZED:
-        strIndex = 3;
-        break;
-    case OT_LINK_METRICS_STATUS_NO_MATCHING_FRAMES_RECEIVED:
-        strIndex = 4;
-        break;
-    case OT_LINK_METRICS_STATUS_OTHER_ERROR:
-        strIndex = 5;
-        break;
-    default:
-        strIndex = 6;
-        break;
+        str = kStatusStrings[aStatus];
+    }
+    else if (aStatus == OT_LINK_METRICS_STATUS_OTHER_ERROR)
+    {
+        str = "Other error";
     }
 
-    return linkMetricsStatusText[strIndex];
+    return str;
 }
 
-otError Interpreter::ProcessLinkMetrics(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("linkmetrics")>(Arg aArgs[])
 {
     otError error = OT_ERROR_INVALID_COMMAND;
 
     if (aArgs[0] == "query")
     {
-        error = ProcessLinkMetricsQuery(aArgs + 1);
+        otIp6Address  address;
+        otLinkMetrics linkMetrics;
+
+        SuccessOrExit(error = aArgs[1].ParseAsIp6Address(address));
+
+        if (aArgs[2] == "single")
+        {
+            VerifyOrExit(!aArgs[3].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+            SuccessOrExit(error = ParseLinkMetricsFlags(linkMetrics, aArgs[3]));
+            error = otLinkMetricsQuery(GetInstancePtr(), &address, /* aSeriesId */ 0, &linkMetrics,
+                                       &Interpreter::HandleLinkMetricsReport, this);
+        }
+        else if (aArgs[2] == "forward")
+        {
+            uint8_t seriesId;
+
+            SuccessOrExit(error = aArgs[3].ParseAsUint8(seriesId));
+            error = otLinkMetricsQuery(GetInstancePtr(), &address, seriesId, nullptr,
+                                       &Interpreter::HandleLinkMetricsReport, this);
+        }
+        else
+        {
+            error = OT_ERROR_INVALID_ARGS;
+        }
     }
     else if (aArgs[0] == "mgmt")
     {
@@ -2378,38 +2607,15 @@
     }
     else if (aArgs[0] == "probe")
     {
-        error = ProcessLinkMetricsProbe(aArgs + 1);
-    }
+        otIp6Address address;
+        uint8_t      seriesId;
+        uint8_t      length;
 
-    return error;
-}
-
-otError Interpreter::ProcessLinkMetricsQuery(Arg aArgs[])
-{
-    otError       error;
-    otIp6Address  address;
-    otLinkMetrics linkMetrics;
-
-    SuccessOrExit(error = aArgs[0].ParseAsIp6Address(address));
-
-    if (aArgs[1] == "single")
-    {
-        VerifyOrExit(!aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
-        SuccessOrExit(error = ParseLinkMetricsFlags(linkMetrics, aArgs[2]));
-        error = otLinkMetricsQuery(GetInstancePtr(), &address, /* aSeriesId */ 0, &linkMetrics,
-                                   &Interpreter::HandleLinkMetricsReport, this);
-    }
-    else if (aArgs[1] == "forward")
-    {
-        uint8_t seriesId;
-
+        SuccessOrExit(error = aArgs[1].ParseAsIp6Address(address));
         SuccessOrExit(error = aArgs[2].ParseAsUint8(seriesId));
-        error = otLinkMetricsQuery(GetInstancePtr(), &address, seriesId, nullptr, &Interpreter::HandleLinkMetricsReport,
-                                   this);
-    }
-    else
-    {
-        error = OT_ERROR_INVALID_ARGS;
+        SuccessOrExit(error = aArgs[3].ParseAsUint8(length));
+
+        error = otLinkMetricsSendLinkProbe(GetInstancePtr(), &address, seriesId, length);
     }
 
 exit:
@@ -2553,27 +2759,11 @@
     return error;
 }
 
-otError Interpreter::ProcessLinkMetricsProbe(Arg aArgs[])
-{
-    otError      error = OT_ERROR_INVALID_ARGS;
-    otIp6Address address;
-    uint8_t      seriesId = 0;
-    uint8_t      length   = 0;
-
-    SuccessOrExit(error = aArgs[0].ParseAsIp6Address(address));
-    SuccessOrExit(error = aArgs[1].ParseAsUint8(seriesId));
-    SuccessOrExit(error = aArgs[2].ParseAsUint8(length));
-
-    error = otLinkMetricsSendLinkProbe(GetInstancePtr(), &address, seriesId, length);
-
-exit:
-    return error;
-}
 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
 
 #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
 
-otError Interpreter::ProcessLocate(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("locate")>(Arg aArgs[])
 {
     otError      error = OT_ERROR_INVALID_ARGS;
     otIp6Address anycastAddress;
@@ -2624,21 +2814,18 @@
 #endif //  OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
 
 #if OPENTHREAD_FTD
-otError Interpreter::ProcessPskc(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("pskc")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
+    otPskc  pskc;
 
     if (aArgs[0].IsEmpty())
     {
-        otPskc pskc;
-
         otThreadGetPskc(GetInstancePtr(), &pskc);
         OutputBytesLine(pskc.m8);
     }
     else
     {
-        otPskc pskc;
-
         if (aArgs[1].IsEmpty())
         {
             SuccessOrExit(error = aArgs[0].ParseAsHexString(pskc.m8));
@@ -2655,7 +2842,7 @@
             ExitNow(error = OT_ERROR_INVALID_ARGS);
         }
 
-        SuccessOrExit(error = otThreadSetPskc(GetInstancePtr(), &pskc));
+        error = otThreadSetPskc(GetInstancePtr(), &pskc);
     }
 
 exit:
@@ -2663,7 +2850,7 @@
 }
 
 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
-otError Interpreter::ProcessPskcRef(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("pskcref")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -2684,7 +2871,7 @@
             ExitNow(error = OT_ERROR_INVALID_ARGS);
         }
 
-        SuccessOrExit(error = otThreadSetPskcRef(GetInstancePtr(), pskcRef));
+        error = otThreadSetPskcRef(GetInstancePtr(), pskcRef);
     }
 
 exit:
@@ -2694,7 +2881,7 @@
 #endif // OPENTHREAD_FTD
 
 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-otError Interpreter::ProcessMlIid(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("mliid")>(Arg aArgs[])
 {
     otError                  error = OT_ERROR_NONE;
     otIp6InterfaceIdentifier iid;
@@ -2711,51 +2898,45 @@
 
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
 
-otError Interpreter::ProcessMlr(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("mlr")>(Arg aArgs[])
 {
     otError error = OT_ERROR_INVALID_COMMAND;
 
     if (aArgs[0] == "reg")
     {
-        error = ProcessMlrReg(aArgs + 1);
-    }
+        otIp6Address addresses[OT_IP6_MAX_MLR_ADDRESSES];
+        uint32_t     timeout;
+        bool         hasTimeout   = false;
+        uint8_t      numAddresses = 0;
 
-    return error;
-}
-
-otError Interpreter::ProcessMlrReg(Arg aArgs[])
-{
-    otError      error = OT_ERROR_NONE;
-    otIp6Address addresses[kIp6AddressesNumMax];
-    uint32_t     timeout;
-    bool         hasTimeout   = false;
-    uint8_t      numAddresses = 0;
-
-    while (aArgs->ParseAsIp6Address(addresses[numAddresses]) == OT_ERROR_NONE)
-    {
         aArgs++;
-        numAddresses++;
 
-        if (numAddresses == OT_ARRAY_LENGTH(addresses))
+        while (aArgs->ParseAsIp6Address(addresses[numAddresses]) == OT_ERROR_NONE)
         {
-            break;
+            aArgs++;
+            numAddresses++;
+
+            if (numAddresses == OT_ARRAY_LENGTH(addresses))
+            {
+                break;
+            }
         }
+
+        if (aArgs->ParseAsUint32(timeout) == OT_ERROR_NONE)
+        {
+            aArgs++;
+            hasTimeout = true;
+        }
+
+        VerifyOrExit(aArgs->IsEmpty() && (numAddresses > 0), error = OT_ERROR_INVALID_ARGS);
+
+        SuccessOrExit(error = otIp6RegisterMulticastListeners(GetInstancePtr(), addresses, numAddresses,
+                                                              hasTimeout ? &timeout : nullptr,
+                                                              Interpreter::HandleMlrRegResult, this));
+
+        error = OT_ERROR_PENDING;
     }
 
-    if (aArgs->ParseAsUint32(timeout) == OT_ERROR_NONE)
-    {
-        aArgs++;
-        hasTimeout = true;
-    }
-
-    VerifyOrExit(aArgs->IsEmpty() && (numAddresses > 0), error = OT_ERROR_INVALID_ARGS);
-
-    SuccessOrExit(error = otIp6RegisterMulticastListeners(GetInstancePtr(), addresses, numAddresses,
-                                                          hasTimeout ? &timeout : nullptr,
-                                                          Interpreter::HandleMlrRegResult, this));
-
-    error = OT_ERROR_PENDING;
-
 exit:
     return error;
 }
@@ -2789,7 +2970,7 @@
 
 #endif // (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
 
-otError Interpreter::ProcessMode(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("mode")>(Arg aArgs[])
 {
     otError          error = OT_ERROR_NONE;
     otLinkModeConfig linkMode;
@@ -2834,7 +3015,7 @@
     return error;
 }
 
-otError Interpreter::ProcessMultiRadio(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("multiradio")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -2922,7 +3103,7 @@
 #endif // OPENTHREAD_CONFIG_MULTI_RADIO
 
 #if OPENTHREAD_FTD
-otError Interpreter::ProcessNeighbor(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("neighbor")>(Arg aArgs[])
 {
     otError                error = OT_ERROR_NONE;
     otNeighborInfo         neighborInfo;
@@ -2979,7 +3160,7 @@
 }
 #endif // OPENTHREAD_FTD
 
-otError Interpreter::ProcessNetstat(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("netstat")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -3002,27 +3183,22 @@
 }
 
 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-otError Interpreter::ProcessServiceList(void)
-{
-    otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
-    otServiceConfig       config;
-
-    while (otServerGetNextService(GetInstancePtr(), &iterator, &config) == OT_ERROR_NONE)
-    {
-        mNetworkData.OutputService(config);
-    }
-
-    return OT_ERROR_NONE;
-}
-
-otError Interpreter::ProcessService(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("service")>(Arg aArgs[])
 {
     otError         error = OT_ERROR_INVALID_COMMAND;
     otServiceConfig cfg;
 
     if (aArgs[0].IsEmpty())
     {
-        error = ProcessServiceList();
+        otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
+        otServiceConfig       config;
+
+        while (otServerGetNextService(GetInstancePtr(), &iterator, &config) == OT_ERROR_NONE)
+        {
+            mNetworkData.OutputService(config);
+        }
+
+        error = OT_ERROR_NONE;
     }
     else
     {
@@ -3058,19 +3234,19 @@
 }
 #endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
 
-otError Interpreter::ProcessNetworkData(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("netdata")>(Arg aArgs[])
 {
     return mNetworkData.Process(aArgs);
 }
 
 #if OPENTHREAD_FTD
-otError Interpreter::ProcessNetworkIdTimeout(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("networkidtimeout")>(Arg aArgs[])
 {
     return ProcessGetSet(aArgs, otThreadGetNetworkIdTimeout, otThreadSetNetworkIdTimeout);
 }
 #endif
 
-otError Interpreter::ProcessNetworkKey(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("networkkey")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -3094,7 +3270,7 @@
 }
 
 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
-otError Interpreter::ProcessNetworkKeyRef(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("networkkeyref")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -3115,7 +3291,7 @@
 }
 #endif
 
-otError Interpreter::ProcessNetworkName(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("networkname")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -3133,7 +3309,7 @@
 }
 
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-otError Interpreter::ProcessNetworkTime(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("networktime")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -3183,7 +3359,7 @@
 }
 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
 
-otError Interpreter::ProcessPanId(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("panid")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -3199,7 +3375,7 @@
     return error;
 }
 
-otError Interpreter::ProcessParent(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("parent")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -3219,12 +3395,37 @@
 }
 
 #if OPENTHREAD_FTD
-otError Interpreter::ProcessParentPriority(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("parentpriority")>(Arg aArgs[])
 {
     return ProcessGetSet(aArgs, otThreadGetParentPriority, otThreadSetParentPriority);
 }
 #endif
 
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+template <> otError Interpreter::Process<Cmd("routeridrange")>(Arg *aArgs)
+{
+    uint8_t minRouterId;
+    uint8_t maxRouterId;
+    otError error = OT_ERROR_NONE;
+
+    if (aArgs[0].IsEmpty())
+    {
+        otThreadGetRouterIdRange(GetInstancePtr(), &minRouterId, &maxRouterId);
+        OutputLine("%d %d", minRouterId, maxRouterId);
+    }
+    else
+    {
+        SuccessOrExit(error = aArgs[0].ParseAsUint8(minRouterId));
+        SuccessOrExit(error = aArgs[1].ParseAsUint8(maxRouterId));
+        VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+        error = otThreadSetRouterIdRange(GetInstancePtr(), minRouterId, maxRouterId);
+    }
+
+exit:
+    return error;
+}
+#endif
+
 #if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
 
 void Interpreter::HandlePingReply(const otPingSenderReply *aReply, void *aContext)
@@ -3271,7 +3472,7 @@
     }
 }
 
-otError Interpreter::ProcessPing(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("ping")>(Arg aArgs[])
 {
     otError            error = OT_ERROR_NONE;
     otPingSenderConfig config;
@@ -3368,12 +3569,12 @@
 
 #endif // OPENTHREAD_CONFIG_PING_SENDER_ENABLE
 
-otError Interpreter::ProcessPollPeriod(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("pollperiod")>(Arg aArgs[])
 {
     return ProcessGetSet(aArgs, otLinkGetPollPeriod, otLinkSetPollPeriod);
 }
 
-otError Interpreter::ProcessPromiscuous(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("promiscuous")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -3490,17 +3691,11 @@
 
     for (; !aArgs->IsEmpty(); aArgs++)
     {
-        if (*aArgs == "high")
+        otRoutePreference preference;
+
+        if (ParsePreference(*aArgs, preference) == OT_ERROR_NONE)
         {
-            aConfig.mPreference = OT_ROUTE_PREFERENCE_HIGH;
-        }
-        else if (*aArgs == "med")
-        {
-            aConfig.mPreference = OT_ROUTE_PREFERENCE_MED;
-        }
-        else if (*aArgs == "low")
-        {
-            aConfig.mPreference = OT_ROUTE_PREFERENCE_LOW;
+            aConfig.mPreference = preference;
         }
         else
         {
@@ -3556,78 +3751,114 @@
     return error;
 }
 
-otError Interpreter::ProcessPrefixAdd(Arg aArgs[])
-{
-    otError              error = OT_ERROR_NONE;
-    otBorderRouterConfig config;
-
-    SuccessOrExit(error = ParsePrefix(aArgs, config));
-    error = otBorderRouterAddOnMeshPrefix(GetInstancePtr(), &config);
-
-exit:
-    return error;
-}
-
-otError Interpreter::ProcessPrefixRemove(Arg aArgs[])
-{
-    otError     error = OT_ERROR_NONE;
-    otIp6Prefix prefix;
-
-    SuccessOrExit(error = aArgs[0].ParseAsIp6Prefix(prefix));
-
-    error = otBorderRouterRemoveOnMeshPrefix(GetInstancePtr(), &prefix);
-
-exit:
-    return error;
-}
-
-otError Interpreter::ProcessPrefixList(void)
-{
-    otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
-    otBorderRouterConfig  config;
-
-    while (otBorderRouterGetNextOnMeshPrefix(GetInstancePtr(), &iterator, &config) == OT_ERROR_NONE)
-    {
-        mNetworkData.OutputPrefix(config);
-    }
-
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
-    if (otBackboneRouterGetState(GetInstancePtr()) == OT_BACKBONE_ROUTER_STATE_DISABLED)
-    {
-        SuccessOrExit(otBackboneRouterGetDomainPrefix(GetInstancePtr(), &config));
-        OutputFormat("- ");
-        mNetworkData.OutputPrefix(config);
-    }
-    // Else already printed via above while loop.
-exit:
-#endif
-
-    return OT_ERROR_NONE;
-}
-
-otError Interpreter::ProcessPrefix(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("prefix")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
+    /**
+     * @cli prefix
+     * @code
+     * prefix
+     * 2001:dead:beef:cafe::/64 paros med
+     * - fd00:7d03:7d03:7d03::/64 prosD med
+     * Done
+     * @endcode
+     * @par
+     * Get the prefix list in the local Network Data.
+     * @note For the Thread 1.2 border router with backbone capability, the local Domain Prefix
+     * is listed as well and includes the `D` flag. If backbone functionality is disabled, a dash
+     * `-` is printed before the local Domain Prefix.
+     * @par
+     * For more information about #otBorderRouterConfig flags, refer to @overview.
+     * @sa otBorderRouterGetNextOnMeshPrefix
+     */
     if (aArgs[0].IsEmpty())
     {
-        SuccessOrExit(error = ProcessPrefixList());
+        otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
+        otBorderRouterConfig  config;
+
+        while (otBorderRouterGetNextOnMeshPrefix(GetInstancePtr(), &iterator, &config) == OT_ERROR_NONE)
+        {
+            mNetworkData.OutputPrefix(config);
+        }
+
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
+        if (otBackboneRouterGetState(GetInstancePtr()) == OT_BACKBONE_ROUTER_STATE_DISABLED)
+        {
+            SuccessOrExit(otBackboneRouterGetDomainPrefix(GetInstancePtr(), &config));
+            OutputFormat("- ");
+            mNetworkData.OutputPrefix(config);
+        }
+#endif
     }
+    /**
+     * @cli prefix add
+     * @code
+     * prefix add 2001:dead:beef:cafe::/64 paros med
+     * Done
+     * @endcode
+     * @code
+     * prefix add fd00:7d03:7d03:7d03::/64 prosD low
+     * Done
+     * @endcode
+     * @cparam prefix add @ca{prefix} [@ca{padcrosnD}] [@ca{high}|@ca{med}|@ca{low}]
+     * OT CLI uses mapped arguments to configure #otBorderRouterConfig values. @moreinfo{the @overview}.
+     * @par
+     * Adds a valid prefix to the Network Data.
+     * @sa otBorderRouterAddOnMeshPrefix
+     */
     else if (aArgs[0] == "add")
     {
-        SuccessOrExit(error = ProcessPrefixAdd(aArgs + 1));
+        otBorderRouterConfig config;
+
+        SuccessOrExit(error = ParsePrefix(aArgs + 1, config));
+        error = otBorderRouterAddOnMeshPrefix(GetInstancePtr(), &config);
     }
+    /**
+     * @cli prefix remove
+     * @code
+     * prefix remove 2001:dead:beef:cafe::/64
+     * Done
+     * @endcode
+     * @par api_copy
+     * #otBorderRouterRemoveOnMeshPrefix
+     */
     else if (aArgs[0] == "remove")
     {
-        SuccessOrExit(error = ProcessPrefixRemove(aArgs + 1));
+        otIp6Prefix prefix;
+
+        SuccessOrExit(error = aArgs[1].ParseAsIp6Prefix(prefix));
+        error = otBorderRouterRemoveOnMeshPrefix(GetInstancePtr(), &prefix);
     }
+    /**
+     * @cli prefix meshlocal
+     * @code
+     * prefix meshlocal
+     * fdde:ad00:beef:0::/64
+     * Done
+     * @endcode
+     * @par
+     * Get the mesh local prefix.
+     */
     else if (aArgs[0] == "meshlocal")
     {
-        OutputIp6PrefixLine(*otThreadGetMeshLocalPrefix(GetInstancePtr()));
+        if (aArgs[1].IsEmpty())
+        {
+            OutputIp6PrefixLine(*otThreadGetMeshLocalPrefix(GetInstancePtr()));
+        }
+        else
+        {
+            otIp6Prefix prefix;
+
+            SuccessOrExit(error = aArgs[1].ParseAsIp6Prefix(prefix));
+            VerifyOrExit(prefix.mLength == OT_IP6_PREFIX_BITSIZE, error = OT_ERROR_INVALID_ARGS);
+            error =
+                otThreadSetMeshLocalPrefix(GetInstancePtr(), reinterpret_cast<otMeshLocalPrefix *>(&prefix.mPrefix));
+        }
     }
     else
     {
-        ExitNow(error = OT_ERROR_INVALID_COMMAND);
+        error = OT_ERROR_INVALID_COMMAND;
     }
 
 exit:
@@ -3636,13 +3867,35 @@
 #endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
 
 #if OPENTHREAD_FTD
-otError Interpreter::ProcessPreferRouterId(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("preferrouterid")>(Arg aArgs[])
 {
     return ProcessSet(aArgs, otThreadSetPreferredRouterId);
 }
 #endif
 
-otError Interpreter::ProcessRcp(Arg aArgs[])
+#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
+template <> otError Interpreter::Process<Cmd("radiofilter")>(Arg aArgs[])
+{
+    otError error = OT_ERROR_NONE;
+
+    if (aArgs[0].IsEmpty())
+    {
+        OutputEnabledDisabledStatus(otLinkIsRadioFilterEnabled(GetInstancePtr()));
+    }
+    else
+    {
+        bool enable;
+
+        SuccessOrExit(error = ParseEnableOrDisable(aArgs[0], enable));
+        otLinkSetRadioFilterEnabled(GetInstancePtr(), enable);
+    }
+
+exit:
+    return error;
+}
+#endif
+
+template <> otError Interpreter::Process<Cmd("rcp")>(Arg aArgs[])
 {
     otError     error   = OT_ERROR_NONE;
     const char *version = otPlatRadioGetVersionString(GetInstancePtr());
@@ -3662,7 +3915,7 @@
     return error;
 }
 
-otError Interpreter::ProcessRegion(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("region")>(Arg aArgs[])
 {
     otError  error = OT_ERROR_NONE;
     uint16_t regionCode;
@@ -3686,13 +3939,13 @@
 }
 
 #if OPENTHREAD_FTD
-otError Interpreter::ProcessReleaseRouterId(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("releaserouterid")>(Arg aArgs[])
 {
     return ProcessSet(aArgs, otThreadReleaseRouterId);
 }
 #endif
 
-otError Interpreter::ProcessRloc16(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("rloc16")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -3713,6 +3966,8 @@
 
     for (; !aArgs->IsEmpty(); aArgs++)
     {
+        otRoutePreference preference;
+
         if (*aArgs == "s")
         {
             aConfig.mStable = true;
@@ -3721,17 +3976,9 @@
         {
             aConfig.mNat64 = true;
         }
-        else if (*aArgs == "high")
+        else if (ParsePreference(*aArgs, preference) == OT_ERROR_NONE)
         {
-            aConfig.mPreference = OT_ROUTE_PREFERENCE_HIGH;
-        }
-        else if (*aArgs == "med")
-        {
-            aConfig.mPreference = OT_ROUTE_PREFERENCE_MED;
-        }
-        else if (*aArgs == "low")
-        {
-            aConfig.mPreference = OT_ROUTE_PREFERENCE_LOW;
+            aConfig.mPreference = preference;
         }
         else
         {
@@ -3743,63 +3990,37 @@
     return error;
 }
 
-otError Interpreter::ProcessRouteAdd(Arg aArgs[])
-{
-    otError               error;
-    otExternalRouteConfig config;
-
-    SuccessOrExit(error = ParseRoute(aArgs, config));
-    error = otBorderRouterAddRoute(GetInstancePtr(), &config);
-
-exit:
-    return error;
-}
-
-otError Interpreter::ProcessRouteRemove(Arg aArgs[])
-{
-    otError     error = OT_ERROR_NONE;
-    otIp6Prefix prefix;
-
-    SuccessOrExit(error = aArgs[0].ParseAsIp6Prefix(prefix));
-
-    error = otBorderRouterRemoveRoute(GetInstancePtr(), &prefix);
-
-exit:
-    return error;
-}
-
-otError Interpreter::ProcessRouteList(void)
-{
-    otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
-    otExternalRouteConfig config;
-
-    while (otBorderRouterGetNextRoute(GetInstancePtr(), &iterator, &config) == OT_ERROR_NONE)
-    {
-        mNetworkData.OutputRoute(config);
-    }
-
-    return OT_ERROR_NONE;
-}
-
-otError Interpreter::ProcessRoute(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("route")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
     if (aArgs[0].IsEmpty())
     {
-        SuccessOrExit(error = ProcessRouteList());
+        otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
+        otExternalRouteConfig config;
+
+        while (otBorderRouterGetNextRoute(GetInstancePtr(), &iterator, &config) == OT_ERROR_NONE)
+        {
+            mNetworkData.OutputRoute(config);
+        }
     }
     else if (aArgs[0] == "add")
     {
-        SuccessOrExit(error = ProcessRouteAdd(aArgs + 1));
+        otExternalRouteConfig config;
+
+        SuccessOrExit(error = ParseRoute(aArgs + 1, config));
+        error = otBorderRouterAddRoute(GetInstancePtr(), &config);
     }
     else if (aArgs[0] == "remove")
     {
-        SuccessOrExit(error = ProcessRouteRemove(aArgs + 1));
+        otIp6Prefix prefix;
+
+        SuccessOrExit(error = aArgs[1].ParseAsIp6Prefix(prefix));
+        error = otBorderRouterRemoveRoute(GetInstancePtr(), &prefix);
     }
     else
     {
-        ExitNow(error = OT_ERROR_INVALID_COMMAND);
+        error = OT_ERROR_INVALID_COMMAND;
     }
 
 exit:
@@ -3808,7 +4029,7 @@
 #endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
 
 #if OPENTHREAD_FTD
-otError Interpreter::ProcessRouter(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("router")>(Arg aArgs[])
 {
     otError      error = OT_ERROR_NONE;
     otRouterInfo routerInfo;
@@ -3893,12 +4114,12 @@
     return error;
 }
 
-otError Interpreter::ProcessRouterDowngradeThreshold(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("routerdowngradethreshold")>(Arg aArgs[])
 {
     return ProcessGetSet(aArgs, otThreadGetRouterDowngradeThreshold, otThreadSetRouterDowngradeThreshold);
 }
 
-otError Interpreter::ProcessRouterEligible(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("routereligible")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -3918,18 +4139,18 @@
     return error;
 }
 
-otError Interpreter::ProcessRouterSelectionJitter(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("routerselectionjitter")>(Arg aArgs[])
 {
     return ProcessGetSet(aArgs, otThreadGetRouterSelectionJitter, otThreadSetRouterSelectionJitter);
 }
 
-otError Interpreter::ProcessRouterUpgradeThreshold(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("routerupgradethreshold")>(Arg aArgs[])
 {
     return ProcessGetSet(aArgs, otThreadGetRouterUpgradeThreshold, otThreadSetRouterUpgradeThreshold);
 }
 #endif // OPENTHREAD_FTD
 
-otError Interpreter::ProcessScan(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("scan")>(Arg aArgs[])
 {
     otError  error        = OT_ERROR_NONE;
     uint32_t scanChannels = 0;
@@ -3968,7 +4189,11 @@
     }
     else
     {
-        OutputScanTableHeader();
+        static const char *const kScanTableTitles[]       = {"PAN", "MAC Address", "Ch", "dBm", "LQI"};
+        static const uint8_t     kScanTableColumnWidths[] = {6, 18, 4, 5, 5};
+
+        OutputTableHeader(kScanTableTitles, kScanTableColumnWidths);
+
         SuccessOrExit(error = otLinkActiveScan(GetInstancePtr(), scanChannels, scanDuration,
                                                &Interpreter::HandleActiveScanResult, this));
     }
@@ -3979,19 +4204,6 @@
     return error;
 }
 
-void Interpreter::OutputScanTableHeader(void)
-{
-    static const char *const kScanTableTitles[] = {
-        "J", "Network Name", "Extended PAN", "PAN", "MAC Address", "Ch", "dBm", "LQI",
-    };
-
-    static const uint8_t kScanTableColumnWidths[] = {
-        3, 18, 18, 6, 18, 4, 5, 5,
-    };
-
-    OutputTableHeader(kScanTableTitles, kScanTableColumnWidths);
-}
-
 void Interpreter::HandleActiveScanResult(otActiveScanResult *aResult, void *aContext)
 {
     static_cast<Interpreter *>(aContext)->HandleActiveScanResult(aResult);
@@ -4005,13 +4217,14 @@
         ExitNow();
     }
 
-    OutputFormat("| %d ", aResult->mIsJoinable);
+    if (aResult->mDiscover)
+    {
+        OutputFormat("| %-16s ", aResult->mNetworkName.m8);
 
-    OutputFormat("| %-16s ", aResult->mNetworkName.m8);
-
-    OutputFormat("| ");
-    OutputBytes(aResult->mExtendedPanId.m8);
-    OutputFormat(" ");
+        OutputFormat("| ");
+        OutputBytes(aResult->mExtendedPanId.m8);
+        OutputFormat(" ");
+    }
 
     OutputFormat("| %04x | ", aResult->mPanId);
     OutputExtAddress(aResult->mExtAddress);
@@ -4042,24 +4255,17 @@
     return;
 }
 
-otError Interpreter::ProcessSingleton(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("singleton")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
-    if (otThreadIsSingleton(GetInstancePtr()))
-    {
-        OutputLine("true");
-    }
-    else
-    {
-        OutputLine("false");
-    }
+    OutputLine(otThreadIsSingleton(GetInstancePtr()) ? "true" : "false");
 
     return OT_ERROR_NONE;
 }
 
 #if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
-otError Interpreter::ProcessSntp(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("sntp")>(Arg aArgs[])
 {
     otError          error = OT_ERROR_NONE;
     uint16_t         port  = OT_SNTP_DEFAULT_SERVER_PORT;
@@ -4129,7 +4335,7 @@
 #endif // OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
 
 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE || OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
-otError Interpreter::ProcessSrp(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("srp")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -4164,7 +4370,7 @@
 }
 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE || OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
 
-otError Interpreter::ProcessState(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("state")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -4172,38 +4378,33 @@
     {
         OutputLine("%s", otThreadDeviceRoleToString(otThreadGetDeviceRole(GetInstancePtr())));
     }
+    else if (aArgs[0] == "detached")
+    {
+        error = otThreadBecomeDetached(GetInstancePtr());
+    }
+    else if (aArgs[0] == "child")
+    {
+        error = otThreadBecomeChild(GetInstancePtr());
+    }
+#if OPENTHREAD_FTD
+    else if (aArgs[0] == "router")
+    {
+        error = otThreadBecomeRouter(GetInstancePtr());
+    }
+    else if (aArgs[0] == "leader")
+    {
+        error = otThreadBecomeLeader(GetInstancePtr());
+    }
+#endif
     else
     {
-        if (aArgs[0] == "detached")
-        {
-            SuccessOrExit(error = otThreadBecomeDetached(GetInstancePtr()));
-        }
-        else if (aArgs[0] == "child")
-        {
-            SuccessOrExit(error = otThreadBecomeChild(GetInstancePtr()));
-        }
-
-#if OPENTHREAD_FTD
-        else if (aArgs[0] == "router")
-        {
-            SuccessOrExit(error = otThreadBecomeRouter(GetInstancePtr()));
-        }
-        else if (aArgs[0] == "leader")
-        {
-            SuccessOrExit(error = otThreadBecomeLeader(GetInstancePtr()));
-        }
-#endif
-        else
-        {
-            ExitNow(error = OT_ERROR_INVALID_ARGS);
-        }
+        error = OT_ERROR_INVALID_ARGS;
     }
 
-exit:
     return error;
 }
 
-otError Interpreter::ProcessThread(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("thread")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -4227,12 +4428,12 @@
     return error;
 }
 
-otError Interpreter::ProcessDataset(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("dataset")>(Arg aArgs[])
 {
     return mDataset.Process(aArgs);
 }
 
-otError Interpreter::ProcessTxPower(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("txpower")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
     int8_t  power;
@@ -4245,7 +4446,7 @@
     else
     {
         SuccessOrExit(error = aArgs[0].ParseAsInt8(power));
-        SuccessOrExit(error = otPlatRadioSetTransmitPower(GetInstancePtr(), power));
+        error = otPlatRadioSetTransmitPower(GetInstancePtr(), power);
     }
 
 exit:
@@ -4253,18 +4454,18 @@
 }
 
 #if OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE
-otError Interpreter::ProcessTcp(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("tcp")>(Arg aArgs[])
 {
     return mTcp.Process(aArgs);
 }
 #endif
 
-otError Interpreter::ProcessUdp(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("udp")>(Arg aArgs[])
 {
     return mUdp.Process(aArgs);
 }
 
-otError Interpreter::ProcessUnsecurePort(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("unsecureport")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -4302,15 +4503,14 @@
     }
     else
     {
-        ExitNow(error = OT_ERROR_INVALID_COMMAND);
+        error = OT_ERROR_INVALID_COMMAND;
     }
 
-exit:
     return error;
 }
 
 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
-otError Interpreter::ProcessUptime(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("uptime")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -4335,28 +4535,28 @@
 #endif
 
 #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
-otError Interpreter::ProcessCommissioner(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("commissioner")>(Arg aArgs[])
 {
     return mCommissioner.Process(aArgs);
 }
 #endif
 
 #if OPENTHREAD_CONFIG_JOINER_ENABLE
-otError Interpreter::ProcessJoiner(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("joiner")>(Arg aArgs[])
 {
     return mJoiner.Process(aArgs);
 }
 #endif
 
 #if OPENTHREAD_FTD
-otError Interpreter::ProcessJoinerPort(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("joinerport")>(Arg aArgs[])
 {
     return ProcessGetSet(aArgs, otThreadGetJoinerUdpPort, otThreadSetJoinerUdpPort);
 }
 #endif
 
 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
-otError Interpreter::ProcessMacFilter(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("macfilter")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -4364,20 +4564,17 @@
     {
         PrintMacFilter();
     }
+    else if (aArgs[0] == "addr")
+    {
+        error = ProcessMacFilterAddress(aArgs + 1);
+    }
+    else if (aArgs[0] == "rss")
+    {
+        error = ProcessMacFilterRss(aArgs + 1);
+    }
     else
     {
-        if (aArgs[0] == "addr")
-        {
-            error = ProcessMacFilterAddress(aArgs + 1);
-        }
-        else if (aArgs[0] == "rss")
-        {
-            error = ProcessMacFilterRss(aArgs + 1);
-        }
-        else
-        {
-            error = OT_ERROR_INVALID_COMMAND;
-        }
+        error = OT_ERROR_INVALID_COMMAND;
     }
 
     return error;
@@ -4385,34 +4582,14 @@
 
 void Interpreter::PrintMacFilter(void)
 {
-    otMacFilterEntry       entry;
-    otMacFilterIterator    iterator = OT_MAC_FILTER_ITERATOR_INIT;
-    otMacFilterAddressMode mode     = otLinkFilterGetAddressMode(GetInstancePtr());
+    otMacFilterEntry    entry;
+    otMacFilterIterator iterator = OT_MAC_FILTER_ITERATOR_INIT;
 
-    if (mode == OT_MAC_FILTER_ADDRESS_MODE_DISABLED)
-    {
-        OutputLine("Address Mode: Disabled");
-    }
-    else if (mode == OT_MAC_FILTER_ADDRESS_MODE_ALLOWLIST)
-    {
-        OutputLine("Address Mode: Allowlist");
-    }
-    else if (mode == OT_MAC_FILTER_ADDRESS_MODE_DENYLIST)
-    {
-        OutputLine("Address Mode: Denylist");
-    }
+    OutputLine("Address Mode: %s", MacFilterAddressModeToString(otLinkFilterGetAddressMode(GetInstancePtr())));
 
     while (otLinkFilterGetNextAddress(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE)
     {
-        OutputExtAddress(entry.mExtAddress);
-
-        if (entry.mRssIn != OT_MAC_FILTER_FIXED_RSS_DISABLED)
-        {
-            OutputFormat(" : rss %d (lqi %d)", entry.mRssIn,
-                         otLinkConvertRssToLinkQuality(GetInstancePtr(), entry.mRssIn));
-        }
-
-        OutputLine("");
+        OutputMacFilterEntry(entry);
     }
 
     iterator = OT_MAC_FILTER_ITERATOR_INIT;
@@ -4437,94 +4614,70 @@
         }
         else
         {
-            OutputExtAddress(entry.mExtAddress);
-            OutputLine(" : rss %d (lqi %d)", entry.mRssIn,
-                       otLinkConvertRssToLinkQuality(GetInstancePtr(), entry.mRssIn));
+            OutputMacFilterEntry(entry);
         }
     }
 }
 
 otError Interpreter::ProcessMacFilterAddress(Arg aArgs[])
 {
-    otError                error = OT_ERROR_NONE;
-    otExtAddress           extAddr;
-    otMacFilterEntry       entry;
-    otMacFilterIterator    iterator = OT_MAC_FILTER_ITERATOR_INIT;
-    otMacFilterAddressMode mode     = otLinkFilterGetAddressMode(GetInstancePtr());
+    otError      error = OT_ERROR_NONE;
+    otExtAddress extAddr;
 
     if (aArgs[0].IsEmpty())
     {
-        if (mode == OT_MAC_FILTER_ADDRESS_MODE_DISABLED)
-        {
-            OutputLine("Disabled");
-        }
-        else if (mode == OT_MAC_FILTER_ADDRESS_MODE_ALLOWLIST)
-        {
-            OutputLine("Allowlist");
-        }
-        else if (mode == OT_MAC_FILTER_ADDRESS_MODE_DENYLIST)
-        {
-            OutputLine("Denylist");
-        }
+        otMacFilterIterator iterator = OT_MAC_FILTER_ITERATOR_INIT;
+        otMacFilterEntry    entry;
+
+        OutputLine("%s", MacFilterAddressModeToString(otLinkFilterGetAddressMode(GetInstancePtr())));
 
         while (otLinkFilterGetNextAddress(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE)
         {
-            OutputExtAddress(entry.mExtAddress);
-
-            if (entry.mRssIn != OT_MAC_FILTER_FIXED_RSS_DISABLED)
-            {
-                OutputFormat(" : rss %d (lqi %d)", entry.mRssIn,
-                             otLinkConvertRssToLinkQuality(GetInstancePtr(), entry.mRssIn));
-            }
-
-            OutputLine("");
+            OutputMacFilterEntry(entry);
         }
     }
+    else if (aArgs[0] == "disable")
+    {
+        VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+        otLinkFilterSetAddressMode(GetInstancePtr(), OT_MAC_FILTER_ADDRESS_MODE_DISABLED);
+    }
+    else if (aArgs[0] == "allowlist")
+    {
+        VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+        otLinkFilterSetAddressMode(GetInstancePtr(), OT_MAC_FILTER_ADDRESS_MODE_ALLOWLIST);
+    }
+    else if (aArgs[0] == "denylist")
+    {
+        VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+        otLinkFilterSetAddressMode(GetInstancePtr(), OT_MAC_FILTER_ADDRESS_MODE_DENYLIST);
+    }
+    else if (aArgs[0] == "add")
+    {
+        SuccessOrExit(error = aArgs[1].ParseAsHexString(extAddr.m8));
+        error = otLinkFilterAddAddress(GetInstancePtr(), &extAddr);
+
+        VerifyOrExit(error == OT_ERROR_NONE || error == OT_ERROR_ALREADY);
+
+        if (!aArgs[2].IsEmpty())
+        {
+            int8_t rss;
+
+            SuccessOrExit(error = aArgs[2].ParseAsInt8(rss));
+            SuccessOrExit(error = otLinkFilterAddRssIn(GetInstancePtr(), &extAddr, rss));
+        }
+    }
+    else if (aArgs[0] == "remove")
+    {
+        SuccessOrExit(error = aArgs[1].ParseAsHexString(extAddr.m8));
+        otLinkFilterRemoveAddress(GetInstancePtr(), &extAddr);
+    }
+    else if (aArgs[0] == "clear")
+    {
+        otLinkFilterClearAddresses(GetInstancePtr());
+    }
     else
     {
-        if (aArgs[0] == "disable")
-        {
-            VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
-            otLinkFilterSetAddressMode(GetInstancePtr(), OT_MAC_FILTER_ADDRESS_MODE_DISABLED);
-        }
-        else if (aArgs[0] == "allowlist")
-        {
-            VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
-            otLinkFilterSetAddressMode(GetInstancePtr(), OT_MAC_FILTER_ADDRESS_MODE_ALLOWLIST);
-        }
-        else if (aArgs[0] == "denylist")
-        {
-            VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
-            otLinkFilterSetAddressMode(GetInstancePtr(), OT_MAC_FILTER_ADDRESS_MODE_DENYLIST);
-        }
-        else if (aArgs[0] == "add")
-        {
-            SuccessOrExit(error = aArgs[1].ParseAsHexString(extAddr.m8));
-            error = otLinkFilterAddAddress(GetInstancePtr(), &extAddr);
-
-            VerifyOrExit(error == OT_ERROR_NONE || error == OT_ERROR_ALREADY);
-
-            if (!aArgs[2].IsEmpty())
-            {
-                int8_t rss;
-
-                SuccessOrExit(error = aArgs[2].ParseAsInt8(rss));
-                SuccessOrExit(error = otLinkFilterAddRssIn(GetInstancePtr(), &extAddr, rss));
-            }
-        }
-        else if (aArgs[0] == "remove")
-        {
-            SuccessOrExit(error = aArgs[1].ParseAsHexString(extAddr.m8));
-            otLinkFilterRemoveAddress(GetInstancePtr(), &extAddr);
-        }
-        else if (aArgs[0] == "clear")
-        {
-            otLinkFilterClearAddresses(GetInstancePtr());
-        }
-        else
-        {
-            error = OT_ERROR_INVALID_COMMAND;
-        }
+        error = OT_ERROR_INVALID_COMMAND;
     }
 
 exit:
@@ -4560,148 +4713,236 @@
             }
             else
             {
-                OutputExtAddress(entry.mExtAddress);
-                OutputLine(" : rss %d (lqi %d)", entry.mRssIn,
-                           otLinkConvertRssToLinkQuality(GetInstancePtr(), entry.mRssIn));
+                OutputMacFilterEntry(entry);
             }
         }
     }
-    else
+    else if (aArgs[0] == "add-lqi")
     {
-        if (aArgs[0] == "add-lqi")
-        {
-            uint8_t linkQuality;
+        uint8_t linkQuality;
 
-            SuccessOrExit(error = aArgs[2].ParseAsUint8(linkQuality));
-            VerifyOrExit(linkQuality <= 3, error = OT_ERROR_INVALID_ARGS);
-            rss = otLinkConvertLinkQualityToRss(GetInstancePtr(), linkQuality);
+        SuccessOrExit(error = aArgs[2].ParseAsUint8(linkQuality));
+        VerifyOrExit(linkQuality <= 3, error = OT_ERROR_INVALID_ARGS);
+        rss = otLinkConvertLinkQualityToRss(GetInstancePtr(), linkQuality);
 
-            if (aArgs[1] == "*")
-            {
-                otLinkFilterSetDefaultRssIn(GetInstancePtr(), rss);
-            }
-            else
-            {
-                SuccessOrExit(error = aArgs[1].ParseAsHexString(extAddr.m8));
-                SuccessOrExit(error = otLinkFilterAddRssIn(GetInstancePtr(), &extAddr, rss));
-            }
-        }
-        else if (aArgs[0] == "add")
+        if (aArgs[1] == "*")
         {
-            SuccessOrExit(error = aArgs[2].ParseAsInt8(rss));
-
-            if (aArgs[1] == "*")
-            {
-                otLinkFilterSetDefaultRssIn(GetInstancePtr(), rss);
-            }
-            else
-            {
-                SuccessOrExit(error = aArgs[1].ParseAsHexString(extAddr.m8));
-                SuccessOrExit(error = otLinkFilterAddRssIn(GetInstancePtr(), &extAddr, rss));
-            }
-        }
-        else if (aArgs[0] == "remove")
-        {
-            if (aArgs[1] == "*")
-            {
-                otLinkFilterClearDefaultRssIn(GetInstancePtr());
-            }
-            else
-            {
-                SuccessOrExit(error = aArgs[1].ParseAsHexString(extAddr.m8));
-                otLinkFilterRemoveRssIn(GetInstancePtr(), &extAddr);
-            }
-        }
-        else if (aArgs[0] == "clear")
-        {
-            otLinkFilterClearAllRssIn(GetInstancePtr());
+            otLinkFilterSetDefaultRssIn(GetInstancePtr(), rss);
         }
         else
         {
-            error = OT_ERROR_INVALID_COMMAND;
+            SuccessOrExit(error = aArgs[1].ParseAsHexString(extAddr.m8));
+            error = otLinkFilterAddRssIn(GetInstancePtr(), &extAddr, rss);
         }
     }
-
-exit:
-    return error;
-}
-
-#endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
-
-otError Interpreter::ProcessMac(Arg aArgs[])
-{
-    otError error = OT_ERROR_NONE;
-
-    if (aArgs[0] == "retries")
+    else if (aArgs[0] == "add")
     {
-        error = ProcessMacRetries(aArgs + 1);
+        SuccessOrExit(error = aArgs[2].ParseAsInt8(rss));
+
+        if (aArgs[1] == "*")
+        {
+            otLinkFilterSetDefaultRssIn(GetInstancePtr(), rss);
+        }
+        else
+        {
+            SuccessOrExit(error = aArgs[1].ParseAsHexString(extAddr.m8));
+            error = otLinkFilterAddRssIn(GetInstancePtr(), &extAddr, rss);
+        }
     }
-#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-    else if (aArgs[0] == "send")
+    else if (aArgs[0] == "remove")
     {
-        error = ProcessMacSend(aArgs + 1);
+        if (aArgs[1] == "*")
+        {
+            otLinkFilterClearDefaultRssIn(GetInstancePtr());
+        }
+        else
+        {
+            SuccessOrExit(error = aArgs[1].ParseAsHexString(extAddr.m8));
+            otLinkFilterRemoveRssIn(GetInstancePtr(), &extAddr);
+        }
     }
-#endif
+    else if (aArgs[0] == "clear")
+    {
+        otLinkFilterClearAllRssIn(GetInstancePtr());
+    }
     else
     {
         error = OT_ERROR_INVALID_COMMAND;
     }
 
+exit:
     return error;
 }
 
-otError Interpreter::ProcessMacRetries(Arg aArgs[])
+void Interpreter::OutputMacFilterEntry(const otMacFilterEntry &aEntry)
+{
+    OutputExtAddress(aEntry.mExtAddress);
+
+    if (aEntry.mRssIn != OT_MAC_FILTER_FIXED_RSS_DISABLED)
+    {
+        OutputFormat(" : rss %d (lqi %d)", aEntry.mRssIn,
+                     otLinkConvertRssToLinkQuality(GetInstancePtr(), aEntry.mRssIn));
+    }
+
+    OutputLine("");
+}
+
+const char *Interpreter::MacFilterAddressModeToString(otMacFilterAddressMode aMode)
+{
+    static const char *const kModeStrings[] = {
+        "Disabled",  // (0) OT_MAC_FILTER_ADDRESS_MODE_DISABLED
+        "Allowlist", // (1) OT_MAC_FILTER_ADDRESS_MODE_ALLOWLIST
+        "Denylist",  // (2) OT_MAC_FILTER_ADDRESS_MODE_DENYLIST
+    };
+
+    static_assert(0 == OT_MAC_FILTER_ADDRESS_MODE_DISABLED, "OT_MAC_FILTER_ADDRESS_MODE_DISABLED value is incorrect");
+    static_assert(1 == OT_MAC_FILTER_ADDRESS_MODE_ALLOWLIST, "OT_MAC_FILTER_ADDRESS_MODE_ALLOWLIST value is incorrect");
+    static_assert(2 == OT_MAC_FILTER_ADDRESS_MODE_DENYLIST, "OT_MAC_FILTER_ADDRESS_MODE_DENYLIST value is incorrect");
+
+    return Stringify(aMode, kModeStrings);
+}
+
+#endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
+
+template <> otError Interpreter::Process<Cmd("mac")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
-    if (aArgs[0] == "direct")
+    if (aArgs[0] == "retries")
     {
-        error = ProcessGetSet(aArgs + 1, otLinkGetMaxFrameRetriesDirect, otLinkSetMaxFrameRetriesDirect);
-    }
+        if (aArgs[1] == "direct")
+        {
+            error = ProcessGetSet(aArgs + 2, otLinkGetMaxFrameRetriesDirect, otLinkSetMaxFrameRetriesDirect);
+        }
 #if OPENTHREAD_FTD
-    else if (aArgs[0] == "indirect")
+        else if (aArgs[1] == "indirect")
+        {
+            error = ProcessGetSet(aArgs + 2, otLinkGetMaxFrameRetriesIndirect, otLinkSetMaxFrameRetriesIndirect);
+        }
+#endif
+        else
+        {
+            error = OT_ERROR_INVALID_ARGS;
+        }
+    }
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+    else if (aArgs[0] == "send")
     {
-        error = ProcessGetSet(aArgs + 1, otLinkGetMaxFrameRetriesIndirect, otLinkSetMaxFrameRetriesIndirect);
+        VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+
+        if (aArgs[1] == "datarequest")
+        {
+            error = otLinkSendDataRequest(GetInstancePtr());
+        }
+        else if (aArgs[1] == "emptydata")
+        {
+            error = otLinkSendEmptyData(GetInstancePtr());
+        }
+        else
+        {
+            error = OT_ERROR_INVALID_ARGS;
+        }
     }
 #endif
     else
     {
-        error = OT_ERROR_INVALID_ARGS;
-    }
-
-    return error;
-}
-
-#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-otError Interpreter::ProcessMacSend(Arg aArgs[])
-{
-    otError error = OT_ERROR_INVALID_ARGS;
-
-    VerifyOrExit(aArgs[1].IsEmpty());
-
-    if (aArgs[0] == "datarequest")
-    {
-        error = otLinkSendDataRequest(GetInstancePtr());
-    }
-    else if (aArgs[0] == "emptydata")
-    {
-        error = otLinkSendEmptyData(GetInstancePtr());
+        error = OT_ERROR_INVALID_COMMAND;
+        ExitNow(); // To silence unused `exit` label warning when `REFERENCE_DEVICE_ENABLE` is not enabled.
     }
 
 exit:
     return error;
 }
-#endif
 
 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
-otError Interpreter::ProcessTrel(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("trel")>(Arg aArgs[])
 {
-    otError error;
+    otError error = OT_ERROR_NONE;
     bool    enable;
 
-    SuccessOrExit(error = ParseEnableOrDisable(aArgs[0], enable));
+    if (aArgs[0].IsEmpty())
+    {
+        OutputEnabledDisabledStatus(otTrelIsEnabled(GetInstancePtr()));
+    }
+    else if (ParseEnableOrDisable(aArgs[0], enable) == OT_ERROR_NONE)
+    {
+        if (enable)
+        {
+            otTrelEnable(GetInstancePtr());
+        }
+        else
+        {
+            otTrelDisable(GetInstancePtr());
+        }
+    }
+    else if (aArgs[0] == "filter")
+    {
+        if (aArgs[1].IsEmpty())
+        {
+            OutputEnabledDisabledStatus(otTrelIsFilterEnabled(GetInstancePtr()));
+        }
+        else
+        {
+            SuccessOrExit(error = ParseEnableOrDisable(aArgs[1], enable));
+            otTrelSetFilterEnabled(GetInstancePtr(), enable);
+        }
+    }
+    else if (aArgs[0] == "peers")
+    {
+        uint16_t           index = 0;
+        otTrelPeerIterator iterator;
+        const otTrelPeer * peer;
+        bool               isTable = true;
 
-    error = otPlatTrelUdp6SetTestMode(GetInstancePtr(), enable);
+        if (aArgs[1] == "list")
+        {
+            isTable = false;
+        }
+        else
+        {
+            VerifyOrExit(aArgs[1].IsEmpty(), error = kErrorInvalidArgs);
+        }
+
+        if (isTable)
+        {
+            static const char *const kTrelPeerTableTitles[] = {"No", "Ext MAC Address", "Ext PAN Id",
+                                                               "IPv6 Socket Address"};
+
+            static const uint8_t kTrelPeerTableColumnWidths[] = {5, 18, 18, 50};
+
+            OutputTableHeader(kTrelPeerTableTitles, kTrelPeerTableColumnWidths);
+        }
+
+        otTrelInitPeerIterator(GetInstancePtr(), &iterator);
+
+        while ((peer = otTrelGetNextPeer(GetInstancePtr(), &iterator)) != nullptr)
+        {
+            if (!isTable)
+            {
+                OutputFormat("%03u ExtAddr:", ++index);
+                OutputExtAddress(peer->mExtAddress);
+                OutputFormat(" ExtPanId:");
+                OutputBytes(peer->mExtPanId.m8);
+                OutputFormat(" SockAddr:");
+                OutputSockAddrLine(peer->mSockAddr);
+            }
+            else
+            {
+                char string[OT_IP6_SOCK_ADDR_STRING_SIZE];
+
+                OutputFormat("| %3u | ", ++index);
+                OutputExtAddress(peer->mExtAddress);
+                OutputFormat(" | ");
+                OutputBytes(peer->mExtPanId.m8);
+                otIp6SockAddrToString(&peer->mSockAddr, string, sizeof(string));
+                OutputLine(" | %-48s |", string);
+            }
+        }
+    }
+    else
+    {
+        error = OT_ERROR_INVALID_ARGS;
+    }
 
 exit:
     return error;
@@ -4709,7 +4950,7 @@
 #endif
 
 #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
-otError Interpreter::ProcessNetworkDiagnostic(Arg aArgs[])
+template <> otError Interpreter::Process<Cmd("networkdiagnostic")>(Arg aArgs[])
 {
     otError      error = OT_ERROR_NONE;
     otIp6Address address;
@@ -4786,7 +5027,7 @@
     OutputLine("");
 
     // Output Network Diagnostic TLV values in standard YAML format.
-    while ((aError = otThreadGetNextDiagnosticTlv(aMessage, &iterator, &diagTlv)) == OT_ERROR_NONE)
+    while (otThreadGetNextDiagnosticTlv(aMessage, &iterator, &diagTlv) == OT_ERROR_NONE)
     {
         switch (diagTlv.mType)
         {
@@ -4934,6 +5175,17 @@
 }
 #endif // OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
 
+void Interpreter::HandleDetachGracefullyResult(void *aContext)
+{
+    static_cast<Interpreter *>(aContext)->HandleDetachGracefullyResult();
+}
+
+void Interpreter::HandleDetachGracefullyResult(void)
+{
+    OutputLine("Finished detaching");
+    OutputResult(OT_ERROR_NONE);
+}
+
 void Interpreter::HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo &aInfo)
 {
     OutputFormat("~ Discovery Request from ");
@@ -4952,6 +5204,7 @@
 
 void Interpreter::OutputPrompt(void)
 {
+#if OPENTHREAD_CONFIG_CLI_PROMPT_ENABLE
     static const char sPrompt[] = "> ";
 
     // The `OutputFormat()` below is adding the prompt which is not
@@ -4962,6 +5215,7 @@
     SetEmittingCommandOutput(false);
     OutputFormat("%s", sPrompt);
     SetEmittingCommandOutput(true);
+#endif // OPENTHREAD_CONFIG_CLI_PROMPT_ENABLE
 }
 
 void Interpreter::HandleTimer(Timer &aTimer)
@@ -4990,6 +5244,252 @@
     mTimer.Start(aTimeoutMilli);
 }
 
+otError Interpreter::ProcessCommand(Arg aArgs[])
+{
+#define CmdEntry(aCommandString)                                   \
+    {                                                              \
+        aCommandString, &Interpreter::Process<Cmd(aCommandString)> \
+    }
+
+    static constexpr Command kCommands[] = {
+#if OPENTHREAD_FTD || OPENTHREAD_MTD
+#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
+        CmdEntry("ba"),
+#endif
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+        CmdEntry("bbr"),
+#endif
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+        CmdEntry("br"),
+#endif
+        CmdEntry("bufferinfo"),
+        CmdEntry("ccathreshold"),
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+        CmdEntry("ccm"),
+#endif
+        CmdEntry("channel"),
+#if OPENTHREAD_FTD
+        CmdEntry("child"),
+        CmdEntry("childip"),
+        CmdEntry("childmax"),
+#endif
+#if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
+        CmdEntry("childsupervision"),
+#endif
+        CmdEntry("childtimeout"),
+#if OPENTHREAD_CONFIG_COAP_API_ENABLE
+        CmdEntry("coap"),
+#endif
+#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
+        CmdEntry("coaps"),
+#endif
+#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
+        CmdEntry("coex"),
+#endif
+#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
+        CmdEntry("commissioner"),
+#endif
+#if OPENTHREAD_FTD
+        CmdEntry("contextreusedelay"),
+#endif
+        CmdEntry("counters"),
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+        CmdEntry("csl"),
+#endif
+        CmdEntry("dataset"),
+#if OPENTHREAD_FTD
+        CmdEntry("delaytimermin"),
+#endif
+        CmdEntry("detach"),
+#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
+#if OPENTHREAD_CONFIG_DIAG_ENABLE
+        CmdEntry("diag"),
+#endif
+#if OPENTHREAD_FTD || OPENTHREAD_MTD
+        CmdEntry("discover"),
+        CmdEntry("dns"),
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+        CmdEntry("domainname"),
+#endif
+#if OPENTHREAD_CONFIG_DUA_ENABLE
+        CmdEntry("dua"),
+#endif
+#if OPENTHREAD_FTD
+        CmdEntry("eidcache"),
+#endif
+        CmdEntry("eui64"),
+        CmdEntry("extaddr"),
+        CmdEntry("extpanid"),
+        CmdEntry("factoryreset"),
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+        CmdEntry("fake"),
+#endif
+        CmdEntry("fem"),
+#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
+#if OPENTHREAD_FTD || OPENTHREAD_MTD
+#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
+        CmdEntry("history"),
+#endif
+        CmdEntry("ifconfig"),
+        CmdEntry("ipaddr"),
+        CmdEntry("ipmaddr"),
+#if OPENTHREAD_CONFIG_JOINER_ENABLE
+        CmdEntry("joiner"),
+#endif
+#if OPENTHREAD_FTD
+        CmdEntry("joinerport"),
+#endif
+        CmdEntry("keysequence"),
+        CmdEntry("leaderdata"),
+#if OPENTHREAD_FTD
+        CmdEntry("leaderweight"),
+#endif
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
+        CmdEntry("linkmetrics"),
+#endif
+#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
+        CmdEntry("locate"),
+#endif
+        CmdEntry("log"),
+        CmdEntry("mac"),
+#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
+        CmdEntry("macfilter"),
+#endif
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+        CmdEntry("mliid"),
+#endif
+#if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
+        CmdEntry("mlr"),
+#endif
+        CmdEntry("mode"),
+        CmdEntry("multiradio"),
+#if OPENTHREAD_FTD
+        CmdEntry("neighbor"),
+#endif
+        CmdEntry("netdata"),
+        CmdEntry("netstat"),
+#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
+        CmdEntry("networkdiagnostic"),
+#endif
+#if OPENTHREAD_FTD
+        CmdEntry("networkidtimeout"),
+#endif
+        CmdEntry("networkkey"),
+#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+        CmdEntry("networkkeyref"),
+#endif
+        CmdEntry("networkname"),
+#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+        CmdEntry("networktime"),
+#endif
+        CmdEntry("panid"),
+        CmdEntry("parent"),
+#if OPENTHREAD_FTD
+        CmdEntry("parentpriority"),
+        CmdEntry("partitionid"),
+#endif
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+        CmdEntry("ping"),
+#endif
+        CmdEntry("pollperiod"),
+#if OPENTHREAD_FTD
+        CmdEntry("preferrouterid"),
+#endif
+#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
+        CmdEntry("prefix"),
+#endif
+        CmdEntry("promiscuous"),
+#if OPENTHREAD_FTD
+        CmdEntry("pskc"),
+#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+        CmdEntry("pskcref"),
+#endif
+#endif
+#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
+        CmdEntry("radiofilter"),
+#endif
+        CmdEntry("rcp"),
+        CmdEntry("region"),
+#if OPENTHREAD_FTD
+        CmdEntry("releaserouterid"),
+#endif
+#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
+        CmdEntry("reset"),
+#if OPENTHREAD_FTD || OPENTHREAD_MTD
+        CmdEntry("rloc16"),
+#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
+        CmdEntry("route"),
+#endif
+#if OPENTHREAD_FTD
+        CmdEntry("router"),
+        CmdEntry("routerdowngradethreshold"),
+        CmdEntry("routereligible"),
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+        CmdEntry("routeridrange"),
+#endif
+        CmdEntry("routerselectionjitter"),
+        CmdEntry("routerupgradethreshold"),
+#endif
+        CmdEntry("scan"),
+#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
+        CmdEntry("service"),
+#endif
+        CmdEntry("singleton"),
+#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
+        CmdEntry("sntp"),
+#endif
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE || OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+        CmdEntry("srp"),
+#endif
+        CmdEntry("state"),
+#if OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE
+        CmdEntry("tcp"),
+#endif
+        CmdEntry("thread"),
+#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
+        CmdEntry("trel"),
+#endif
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+        CmdEntry("tvcheck"),
+#endif
+        CmdEntry("txpower"),
+        CmdEntry("udp"),
+        CmdEntry("unsecureport"),
+#if OPENTHREAD_CONFIG_UPTIME_ENABLE
+        CmdEntry("uptime"),
+#endif
+#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
+        CmdEntry("version"),
+    };
+
+#undef CmdEntry
+
+    static_assert(BinarySearch::IsSorted(kCommands), "Command Table is not sorted");
+
+    otError        error   = OT_ERROR_NONE;
+    const Command *command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
+
+    if (command != nullptr)
+    {
+        error = (this->*command->mHandler)(aArgs + 1);
+    }
+    else if (aArgs[0] == "help")
+    {
+        OutputCommandTable(kCommands);
+
+        for (uint8_t i = 0; i < mUserCommandsLength; i++)
+        {
+            OutputLine("%s", mUserCommands[i].mName);
+        }
+    }
+    else
+    {
+        error = ProcessUserCommands(aArgs);
+    }
+
+    return error;
+}
+
 extern "C" void otCliInit(otInstance *aInstance, otCliOutputCallback aCallback, void *aContext)
 {
     Interpreter::Initialize(aInstance, aCallback, aContext);
@@ -5041,21 +5541,6 @@
     return;
 }
 
-extern "C" void otCliPlatLogLine(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aLogLine)
-{
-    OT_UNUSED_VARIABLE(aLogLevel);
-    OT_UNUSED_VARIABLE(aLogRegion);
-
-    VerifyOrExit(Interpreter::IsInitialized());
-
-    Interpreter::GetInterpreter().SetEmittingCommandOutput(false);
-    Interpreter::GetInterpreter().OutputLine(aLogLine);
-    Interpreter::GetInterpreter().SetEmittingCommandOutput(true);
-
-exit:
-    return;
-}
-
 } // namespace Cli
 } // namespace ot
 
diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp
index f35e3ac..f4aadbb 100644
--- a/src/cli/cli.hpp
+++ b/src/cli/cli.hpp
@@ -46,6 +46,8 @@
 #include <openthread/instance.h>
 #include <openthread/ip6.h>
 #include <openthread/link.h>
+#include <openthread/logging.h>
+#include <openthread/netdata.h>
 #include <openthread/ping_sender.h>
 #include <openthread/sntp.h>
 #if OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE
@@ -76,8 +78,6 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/type_traits.hpp"
-#include "utils/lookup_table.hpp"
-#include "utils/parse_cmdline.hpp"
 
 namespace ot {
 
@@ -91,7 +91,6 @@
 namespace Cli {
 
 extern "C" void otCliPlatLogv(otLogLevel, otLogRegion, const char *, va_list);
-extern "C" void otCliPlatLogLine(otLogLevel, otLogRegion, const char *);
 extern "C" void otCliAppendResult(otError aError);
 extern "C" void otCliOutputBytes(const uint8_t *aBytes, uint8_t aLength);
 extern "C" void otCliOutputFormat(const char *aFmt, ...);
@@ -109,7 +108,6 @@
     friend class SrpClient;
 #endif
     friend void otCliPlatLogv(otLogLevel, otLogRegion, const char *, va_list);
-    friend void otCliPlatLogLine(otLogLevel, otLogRegion, const char *);
     friend void otCliAppendResult(otError aError);
     friend void otCliOutputBytes(const uint8_t *aBytes, uint8_t aLength);
     friend void otCliOutputFormat(const char *aFmt, ...);
@@ -168,7 +166,7 @@
     /**
      * This static method checks a given argument string against "enable" or "disable" commands.
      *
-     * @param[in]  aArgs    The argument string to parse.
+     * @param[in]  aArg     The argument string to parse.
      * @param[out] aEnable  Boolean variable to return outcome on success.
      *                      Set to TRUE for "enable" command, and FALSE for "disable" command.
      *
@@ -181,9 +179,9 @@
     /**
      * This method sets the user command table.
      *
-     * @param[in]  aUserCommands  A pointer to an array with user commands.
-     * @param[in]  aLength        @p aUserCommands length.
-     * @param[in]  aContext       @p aUserCommands length.
+     * @param[in]  aCommands  A pointer to an array with user commands.
+     * @param[in]  aLength    @p aUserCommands length.
+     * @param[in]  aContext   @p aUserCommands length.
      *
      */
     void SetUserCommands(const otCliCommand *aCommands, uint8_t aLength, void *aContext);
@@ -204,6 +202,39 @@
      */
     static const char *LinkModeToString(const otLinkModeConfig &aLinkMode, char (&aStringBuffer)[kLinkModeStringSize]);
 
+    /**
+     * This method converts an IPv6 address origin `OT_ADDRESS_ORIGIN_*` value to human-readable string.
+     *
+     * @param[in] aOrigin   The IPv6 address origin to convert.
+     *
+     * @returns A human-readable string representation of @p aOrigin.
+     *
+     */
+    static const char *AddressOriginToString(uint8_t aOrigin);
+
+    /**
+     * This static method parses a given argument string as a route preference comparing it against  "high", "med", or
+     * "low".
+     *
+     * @param[in]  aArg          The argument string to parse.
+     * @param[out] aPreference   Reference to a `otRoutePreference` to return the parsed preference.
+     *
+     * @retval OT_ERROR_NONE             Successfully parsed @p aArg and updated @p aPreference.
+     * @retval OT_ERROR_INVALID_ARG      @p aArg is not a valid preference string "high", "med", or "low".
+     *
+     */
+    static otError ParsePreference(const Arg &aArg, otRoutePreference &aPreference);
+
+    /**
+     * This static method converts a route preference value to human-readable string.
+     *
+     * @param[in] aPreference   The preference value to convert (`OT_ROUTE_PREFERENCE_*` values).
+     *
+     * @returns A string representation @p aPreference.
+     *
+     */
+    static const char *PreferenceToString(signed int aPreference);
+
 protected:
     static Interpreter *sInterpreter;
 
@@ -219,11 +250,7 @@
     static constexpr uint32_t kNetworkDiagnosticTimeoutMsecs = 5000;
     static constexpr uint32_t kLocateTimeoutMsecs            = 2500;
 
-    struct Command
-    {
-        const char *mName;
-        otError (Interpreter::*mHandler)(Arg aArgs[]);
-    };
+    using Command = CommandEntry<Interpreter>;
 
     template <typename ValueType> using GetHandler         = ValueType (&)(otInstance *);
     template <typename ValueType> using SetHandler         = void (&)(otInstance *, ValueType);
@@ -313,33 +340,15 @@
     static otError ParseRoute(Arg aArgs[], otExternalRouteConfig &aConfig);
 #endif
 
-    // Process methods on FTD/MTD/RCP
-#if OPENTHREAD_CONFIG_DIAG_ENABLE
-    otError ProcessDiag(Arg aArgs[]);
-#endif
-    otError ProcessHelp(Arg aArgs[]);
-    otError ProcessHistory(Arg aArgs[]);
-    otError ProcessReset(Arg aArgs[]);
+    otError ProcessCommand(Arg aArgs[]);
+
+    template <CommandId kCommandId> otError Process(Arg aArgs[]);
+
     otError ProcessUserCommands(Arg aArgs[]);
-    otError ProcessVersion(Arg aArgs[]);
 
-    // Process methods only on FTD/MTD
 #if OPENTHREAD_FTD || OPENTHREAD_MTD
-    otError ProcessCcaThreshold(Arg aArgs[]);
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-    otError ProcessCcm(Arg aArgs[]);
-#endif
-    otError ProcessBufferInfo(Arg aArgs[]);
-    otError ProcessChannel(Arg aArgs[]);
-#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
-    otError ProcessBorderAgent(Arg aArgs[]);
-#endif
-#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
-    otError ProcessBorderRouting(Arg aArgs[]);
-#endif
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-    otError ProcessBackboneRouter(Arg aArgs[]);
 
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
     otError ProcessBackboneRouterLocal(Arg aArgs[]);
 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
@@ -347,94 +356,18 @@
     void    PrintMulticastListenersTable(void);
 #endif
 #endif
-
-    otError ProcessDomainName(Arg aArgs[]);
-
-#if OPENTHREAD_CONFIG_DUA_ENABLE
-    otError ProcessDua(Arg aArgs[]);
 #endif
 
-#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-
 #if OPENTHREAD_FTD
-    otError ProcessChild(Arg aArgs[]);
-    otError ProcessChildIp(Arg aArgs[]);
-    otError ProcessChildMax(Arg aArgs[]);
-#endif
-#if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
-    otError ProcessChildSupervision(Arg aArgs[]);
-#endif
-    otError ProcessChildTimeout(Arg aArgs[]);
-#if OPENTHREAD_CONFIG_COAP_API_ENABLE
-    otError ProcessCoap(Arg aArgs[]);
-#endif
-#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
-    otError ProcessCoapSecure(Arg aArgs[]);
-#endif
-#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
-    otError ProcessCoexMetrics(Arg aArgs[]);
-#endif
-#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
-    otError ProcessCommissioner(Arg aArgs[]);
-#endif
-#if OPENTHREAD_FTD
-    otError ProcessContextIdReuseDelay(Arg aArgs[]);
-#endif
-    otError ProcessCounters(Arg aArgs[]);
-    otError ProcessCsl(Arg aArgs[]);
-#if OPENTHREAD_FTD
-    otError ProcessDelayTimerMin(Arg aArgs[]);
-#endif
-    otError ProcessDiscover(Arg aArgs[]);
-    otError ProcessDns(Arg aArgs[]);
-#if OPENTHREAD_FTD
-    void    OutputEidCacheEntry(const otCacheEntryInfo &aEntry);
-    otError ProcessEidCache(Arg aArgs[]);
-#endif
-    otError ProcessEui64(Arg aArgs[]);
-#if OPENTHREAD_POSIX && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
-    otError ProcessExit(Arg aArgs[]);
-#endif
-    otError ProcessLog(Arg aArgs[]);
-    otError ProcessExtAddress(Arg aArgs[]);
-    otError ProcessExtPanId(Arg aArgs[]);
-    otError ProcessFactoryReset(Arg aArgs[]);
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-    otError ProcessFake(Arg aArgs[]);
-#endif
-    otError ProcessFem(Arg aArgs[]);
-    otError ProcessIfconfig(Arg aArgs[]);
-    otError ProcessIpAddr(Arg aArgs[]);
-    otError ProcessIpAddrAdd(Arg aArgs[]);
-    otError ProcessIpAddrDel(Arg aArgs[]);
-    otError ProcessIpMulticastAddr(Arg aArgs[]);
-    otError ProcessIpMulticastAddrAdd(Arg aArgs[]);
-    otError ProcessIpMulticastAddrDel(Arg aArgs[]);
-    otError ProcessMulticastPromiscuous(Arg aArgs[]);
-#if OPENTHREAD_CONFIG_JOINER_ENABLE
-    otError ProcessJoiner(Arg aArgs[]);
-#endif
-#if OPENTHREAD_FTD
-    otError ProcessJoinerPort(Arg aArgs[]);
-#endif
-    otError ProcessKeySequence(Arg aArgs[]);
-    otError ProcessLeaderData(Arg aArgs[]);
-#if OPENTHREAD_FTD
-    otError ProcessPartitionId(Arg aArgs[]);
-    otError ProcessLeaderWeight(Arg aArgs[]);
-#endif
-#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-    otError ProcessMlIid(Arg aArgs[]);
+    void OutputEidCacheEntry(const otCacheEntryInfo &aEntry);
 #endif
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
-    otError ProcessLinkMetrics(Arg aArgs[]);
     otError ProcessLinkMetricsQuery(Arg aArgs[]);
     otError ProcessLinkMetricsMgmt(Arg aArgs[]);
     otError ProcessLinkMetricsProbe(Arg aArgs[]);
     otError ParseLinkMetricsFlags(otLinkMetrics &aLinkMetrics, const Arg &aFlags);
 #endif
 #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
-    otError     ProcessLocate(Arg aArgs[]);
     static void HandleLocateResult(void *              aContext,
                                    otError             aError,
                                    const otIp6Address *aMeshLocalAddress,
@@ -442,10 +375,6 @@
     void        HandleLocateResult(otError aError, const otIp6Address *aMeshLocalAddress, uint16_t aRloc16);
 #endif
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
-    otError ProcessMlr(Arg aArgs[]);
-
-    otError ProcessMlrReg(Arg aArgs[]);
-
     static void HandleMlrRegResult(void *              aContext,
                                    otError             aError,
                                    uint8_t             aMlrStatus,
@@ -456,120 +385,22 @@
                                    const otIp6Address *aFailedAddresses,
                                    uint8_t             aFailedAddressNum);
 #endif
-    otError ProcessMode(Arg aArgs[]);
-    otError ProcessMultiRadio(Arg aArgs[]);
 #if OPENTHREAD_CONFIG_MULTI_RADIO
     void OutputMultiRadioInfo(const otMultiRadioNeighborInfo &aMultiRadioInfo);
 #endif
-#if OPENTHREAD_FTD
-    otError ProcessNeighbor(Arg aArgs[]);
-#endif
-    otError ProcessNetworkData(Arg aArgs[]);
-    otError ProcessNetworkDataPrefix(void);
-    otError ProcessNetworkDataRoute(void);
-    otError ProcessNetworkDataService(void);
 
-    otError ProcessNetstat(Arg aArgs[]);
-#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-    otError ProcessService(Arg aArgs[]);
-    otError ProcessServiceList(void);
-#endif
-#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
-    otError ProcessNetworkDiagnostic(Arg aArgs[]);
-#endif
-#if OPENTHREAD_FTD
-    otError ProcessNetworkIdTimeout(Arg aArgs[]);
-#endif
-    otError ProcessNetworkKey(Arg aArgs[]);
-#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
-    otError ProcessNetworkKeyRef(Arg aArgs[]);
-#endif
-    otError ProcessNetworkName(Arg aArgs[]);
-#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-    otError ProcessNetworkTime(Arg aArgs[]);
-#endif
-    otError ProcessPanId(Arg aArgs[]);
-    otError ProcessParent(Arg aArgs[]);
-#if OPENTHREAD_FTD
-    otError ProcessParentPriority(Arg aArgs[]);
-#endif
-#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
-    otError ProcessPing(Arg aArgs[]);
-#endif
-    otError ProcessPollPeriod(Arg aArgs[]);
-#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
-    otError ProcessPrefix(Arg aArgs[]);
-    otError ProcessPrefixAdd(Arg aArgs[]);
-    otError ProcessPrefixRemove(Arg aArgs[]);
-    otError ProcessPrefixList(void);
-#endif
-    otError ProcessPromiscuous(Arg aArgs[]);
-#if OPENTHREAD_FTD
-    otError ProcessPreferRouterId(Arg aArgs[]);
-    otError ProcessPskc(Arg aArgs[]);
-#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
-    otError ProcessPskcRef(Arg aArgs[]);
-#endif
-#endif
-    otError ProcessRcp(Arg aArgs[]);
-    otError ProcessRegion(Arg aArgs[]);
-#if OPENTHREAD_FTD
-    otError ProcessReleaseRouterId(Arg aArgs[]);
-#endif
-#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
-    otError ProcessRoute(Arg aArgs[]);
-    otError ProcessRouteAdd(Arg aArgs[]);
-    otError ProcessRouteRemove(Arg aArgs[]);
-    otError ProcessRouteList(void);
-#endif
-#if OPENTHREAD_FTD
-    otError ProcessRouter(Arg aArgs[]);
-    otError ProcessRouterDowngradeThreshold(Arg aArgs[]);
-    otError ProcessRouterEligible(Arg aArgs[]);
-    otError ProcessRouterSelectionJitter(Arg aArgs[]);
-    otError ProcessRouterUpgradeThreshold(Arg aArgs[]);
-#endif
-    otError ProcessRloc16(Arg aArgs[]);
-    otError ProcessScan(Arg aArgs[]);
-    otError ProcessSingleton(Arg aArgs[]);
-#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
-    otError ProcessSntp(Arg aArgs[]);
-#endif
-#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE || OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
-    otError ProcessSrp(Arg aArgs[]);
-#endif
-    otError ProcessState(Arg aArgs[]);
-    otError ProcessThread(Arg aArgs[]);
-    otError ProcessDataset(Arg aArgs[]);
-    otError ProcessTxPower(Arg aArgs[]);
-#if OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE
-    otError ProcessTcp(Arg aArgs[]);
-#endif
-    otError ProcessUdp(Arg aArgs[]);
-    otError ProcessUnsecurePort(Arg aArgs[]);
-#if OPENTHREAD_CONFIG_UPTIME_ENABLE
-    otError ProcessUptime(Arg aArgs[]);
-#endif
 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
-    otError ProcessMacFilter(Arg aArgs[]);
-    void    PrintMacFilter(void);
-    otError ProcessMacFilterAddress(Arg aArgs[]);
-    otError ProcessMacFilterRss(Arg aArgs[]);
-#endif
-    otError ProcessMac(Arg aArgs[]);
-    otError ProcessMacRetries(Arg aArgs[]);
-#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-    otError ProcessMacSend(Arg aArgs[]);
-#endif
-#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
-    otError ProcessTrel(Arg aArgs[]);
+    void               PrintMacFilter(void);
+    otError            ProcessMacFilterAddress(Arg aArgs[]);
+    otError            ProcessMacFilterRss(Arg aArgs[]);
+    void               OutputMacFilterEntry(const otMacFilterEntry &aEntry);
+    static const char *MacFilterAddressModeToString(otMacFilterAddressMode aMode);
 #endif
 
 #if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
     static void HandlePingReply(const otPingSenderReply *aReply, void *aContext);
     static void HandlePingStatistics(const otPingSenderStatistics *aStatistics, void *aContext);
 #endif
-    void        OutputScanTableHeader(void);
     static void HandleActiveScanResult(otActiveScanResult *aResult, void *aContext);
     static void HandleEnergyScanResult(otEnergyScanResult *aResult, void *aContext);
     static void HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx, void *aContext);
@@ -645,6 +476,9 @@
     const char *LinkMetricsStatusToStr(uint8_t aStatus);
 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
 
+    static void HandleDetachGracefullyResult(void *aContext);
+    void        HandleDetachGracefullyResult(void);
+
     static void HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo *aInfo, void *aContext)
     {
         static_cast<Interpreter *>(aContext)->HandleDiscoveryRequest(*aInfo);
@@ -658,212 +492,6 @@
     static void HandleTimer(Timer &aTimer);
     void        HandleTimer(void);
 
-    // Commands supported by radio:
-    // [diag, help, reset, version]
-    static constexpr Command sCommands[] = {
-#if OPENTHREAD_FTD || OPENTHREAD_MTD
-#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
-        {"ba", &Interpreter::ProcessBorderAgent},
-#endif
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-        {"bbr", &Interpreter::ProcessBackboneRouter},
-#endif
-#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
-        {"br", &Interpreter::ProcessBorderRouting},
-#endif
-        {"bufferinfo", &Interpreter::ProcessBufferInfo},
-        {"ccathreshold", &Interpreter::ProcessCcaThreshold},
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-        {"ccm", &Interpreter::ProcessCcm},
-#endif
-        {"channel", &Interpreter::ProcessChannel},
-#if OPENTHREAD_FTD
-        {"child", &Interpreter::ProcessChild},
-        {"childip", &Interpreter::ProcessChildIp},
-        {"childmax", &Interpreter::ProcessChildMax},
-#endif
-#if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
-        {"childsupervision", &Interpreter::ProcessChildSupervision},
-#endif
-        {"childtimeout", &Interpreter::ProcessChildTimeout},
-#if OPENTHREAD_CONFIG_COAP_API_ENABLE
-        {"coap", &Interpreter::ProcessCoap},
-#endif
-#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
-        {"coaps", &Interpreter::ProcessCoapSecure},
-#endif
-#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
-        {"coex", &Interpreter::ProcessCoexMetrics},
-#endif
-#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
-        {"commissioner", &Interpreter::ProcessCommissioner},
-#endif
-#if OPENTHREAD_FTD
-        {"contextreusedelay", &Interpreter::ProcessContextIdReuseDelay},
-#endif
-        {"counters", &Interpreter::ProcessCounters},
-#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-        {"csl", &Interpreter::ProcessCsl},
-#endif
-        {"dataset", &Interpreter::ProcessDataset},
-#if OPENTHREAD_FTD
-        {"delaytimermin", &Interpreter::ProcessDelayTimerMin},
-#endif
-#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
-#if OPENTHREAD_CONFIG_DIAG_ENABLE
-        {"diag", &Interpreter::ProcessDiag},
-#endif
-#if OPENTHREAD_FTD || OPENTHREAD_MTD
-        {"discover", &Interpreter::ProcessDiscover},
-        {"dns", &Interpreter::ProcessDns},
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-        {"domainname", &Interpreter::ProcessDomainName},
-#endif
-#if OPENTHREAD_CONFIG_DUA_ENABLE
-        {"dua", &Interpreter::ProcessDua},
-#endif
-#if OPENTHREAD_FTD
-        {"eidcache", &Interpreter::ProcessEidCache},
-#endif
-        {"eui64", &Interpreter::ProcessEui64},
-        {"extaddr", &Interpreter::ProcessExtAddress},
-        {"extpanid", &Interpreter::ProcessExtPanId},
-        {"factoryreset", &Interpreter::ProcessFactoryReset},
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-        {"fake", &Interpreter::ProcessFake},
-#endif
-        {"fem", &Interpreter::ProcessFem},
-#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
-        {"help", &Interpreter::ProcessHelp},
-#if OPENTHREAD_FTD || OPENTHREAD_MTD
-#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
-        {"history", &Interpreter::ProcessHistory},
-#endif
-        {"ifconfig", &Interpreter::ProcessIfconfig},
-        {"ipaddr", &Interpreter::ProcessIpAddr},
-        {"ipmaddr", &Interpreter::ProcessIpMulticastAddr},
-#if OPENTHREAD_CONFIG_JOINER_ENABLE
-        {"joiner", &Interpreter::ProcessJoiner},
-#endif
-#if OPENTHREAD_FTD
-        {"joinerport", &Interpreter::ProcessJoinerPort},
-#endif
-        {"keysequence", &Interpreter::ProcessKeySequence},
-        {"leaderdata", &Interpreter::ProcessLeaderData},
-#if OPENTHREAD_FTD
-        {"leaderweight", &Interpreter::ProcessLeaderWeight},
-#endif
-#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
-        {"linkmetrics", &Interpreter::ProcessLinkMetrics},
-#endif
-#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
-        {"locate", &Interpreter::ProcessLocate},
-#endif
-        {"log", &Interpreter::ProcessLog},
-        {"mac", &Interpreter::ProcessMac},
-#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
-        {"macfilter", &Interpreter::ProcessMacFilter},
-#endif
-#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-        {"mliid", &Interpreter::ProcessMlIid},
-#endif
-#if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
-        {"mlr", &Interpreter::ProcessMlr},
-#endif
-        {"mode", &Interpreter::ProcessMode},
-        {"multiradio", &Interpreter::ProcessMultiRadio},
-#if OPENTHREAD_FTD
-        {"neighbor", &Interpreter::ProcessNeighbor},
-#endif
-        {"netdata", &Interpreter::ProcessNetworkData},
-        {"netstat", &Interpreter::ProcessNetstat},
-#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
-        {"networkdiagnostic", &Interpreter::ProcessNetworkDiagnostic},
-#endif
-#if OPENTHREAD_FTD
-        {"networkidtimeout", &Interpreter::ProcessNetworkIdTimeout},
-#endif
-        {"networkkey", &Interpreter::ProcessNetworkKey},
-#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
-        {"networkkeyref", &Interpreter::ProcessNetworkKeyRef},
-#endif
-        {"networkname", &Interpreter::ProcessNetworkName},
-#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-        {"networktime", &Interpreter::ProcessNetworkTime},
-#endif
-        {"panid", &Interpreter::ProcessPanId},
-        {"parent", &Interpreter::ProcessParent},
-#if OPENTHREAD_FTD
-        {"parentpriority", &Interpreter::ProcessParentPriority},
-        {"partitionid", &Interpreter::ProcessPartitionId},
-#endif
-#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
-        {"ping", &Interpreter::ProcessPing},
-#endif
-        {"pollperiod", &Interpreter::ProcessPollPeriod},
-#if OPENTHREAD_FTD
-        {"preferrouterid", &Interpreter::ProcessPreferRouterId},
-#endif
-#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
-        {"prefix", &Interpreter::ProcessPrefix},
-#endif
-        {"promiscuous", &Interpreter::ProcessPromiscuous},
-#if OPENTHREAD_FTD
-        {"pskc", &Interpreter::ProcessPskc},
-#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
-        {"pskcref", &Interpreter::ProcessPskcRef},
-#endif
-#endif
-        {"rcp", &Interpreter::ProcessRcp},
-        {"region", &Interpreter::ProcessRegion},
-#if OPENTHREAD_FTD
-        {"releaserouterid", &Interpreter::ProcessReleaseRouterId},
-#endif
-#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
-        {"reset", &Interpreter::ProcessReset},
-#if OPENTHREAD_FTD || OPENTHREAD_MTD
-        {"rloc16", &Interpreter::ProcessRloc16},
-#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
-        {"route", &Interpreter::ProcessRoute},
-#endif
-#if OPENTHREAD_FTD
-        {"router", &Interpreter::ProcessRouter},
-        {"routerdowngradethreshold", &Interpreter::ProcessRouterDowngradeThreshold},
-        {"routereligible", &Interpreter::ProcessRouterEligible},
-        {"routerselectionjitter", &Interpreter::ProcessRouterSelectionJitter},
-        {"routerupgradethreshold", &Interpreter::ProcessRouterUpgradeThreshold},
-#endif
-        {"scan", &Interpreter::ProcessScan},
-#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-        {"service", &Interpreter::ProcessService},
-#endif
-        {"singleton", &Interpreter::ProcessSingleton},
-#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
-        {"sntp", &Interpreter::ProcessSntp},
-#endif
-#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE || OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
-        {"srp", &Interpreter::ProcessSrp},
-#endif
-        {"state", &Interpreter::ProcessState},
-#if OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE
-        {"tcp", &Interpreter::ProcessTcp},
-#endif
-        {"thread", &Interpreter::ProcessThread},
-#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
-        {"trel", &Interpreter::ProcessTrel},
-#endif
-        {"txpower", &Interpreter::ProcessTxPower},
-        {"udp", &Interpreter::ProcessUdp},
-        {"unsecureport", &Interpreter::ProcessUnsecurePort},
-#if OPENTHREAD_CONFIG_UPTIME_ENABLE
-        {"uptime", &Interpreter::ProcessUptime},
-#endif
-#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
-        {"version", &Interpreter::ProcessVersion},
-    };
-
-    static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
-
     const otCliCommand *mUserCommands;
     uint8_t             mUserCommandsLength;
     void *              mUserCommandsContext;
diff --git a/src/cli/cli_coap.cpp b/src/cli/cli_coap.cpp
index 56175f9..5d7c260 100644
--- a/src/cli/cli_coap.cpp
+++ b/src/cli/cli_coap.cpp
@@ -44,8 +44,6 @@
 namespace ot {
 namespace Cli {
 
-constexpr Coap::Command Coap::sCommands[];
-
 Coap::Coap(Output &aOutput)
     : OutputWrapper(aOutput)
     , mUseDefaultRequestTxParameters(true)
@@ -144,7 +142,7 @@
 }
 
 #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
-otError Coap::ProcessCancel(Arg aArgs[])
+template <> otError Coap::Process<Cmd("cancel")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -152,19 +150,7 @@
 }
 #endif
 
-otError Coap::ProcessHelp(Arg aArgs[])
-{
-    OT_UNUSED_VARIABLE(aArgs);
-
-    for (const Command &command : sCommands)
-    {
-        OutputLine(command.mName);
-    }
-
-    return OT_ERROR_NONE;
-}
-
-otError Coap::ProcessResource(Arg aArgs[])
+template <> otError Coap::Process<Cmd("resource")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -203,7 +189,7 @@
     return error;
 }
 
-otError Coap::ProcessSet(Arg aArgs[])
+template <> otError Coap::Process<Cmd("set")>(Arg aArgs[])
 {
 #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
     otMessage *   notificationMessage = nullptr;
@@ -264,14 +250,14 @@
     return error;
 }
 
-otError Coap::ProcessStart(Arg aArgs[])
+template <> otError Coap::Process<Cmd("start")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
     return otCoapStart(GetInstancePtr(), OT_DEFAULT_COAP_PORT);
 }
 
-otError Coap::ProcessStop(Arg aArgs[])
+template <> otError Coap::Process<Cmd("stop")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -284,7 +270,7 @@
     return otCoapStop(GetInstancePtr());
 }
 
-otError Coap::ProcessParameters(Arg aArgs[])
+template <> otError Coap::Process<Cmd("parameters")>(Arg aArgs[])
 {
     otError             error = OT_ERROR_NONE;
     bool *              defaultTxParameters;
@@ -342,28 +328,28 @@
     return error;
 }
 
-otError Coap::ProcessGet(Arg aArgs[])
+template <> otError Coap::Process<Cmd("get")>(Arg aArgs[])
 {
     return ProcessRequest(aArgs, OT_COAP_CODE_GET);
 }
 
-otError Coap::ProcessPost(Arg aArgs[])
+template <> otError Coap::Process<Cmd("post")>(Arg aArgs[])
 {
     return ProcessRequest(aArgs, OT_COAP_CODE_POST);
 }
 
-otError Coap::ProcessPut(Arg aArgs[])
+template <> otError Coap::Process<Cmd("put")>(Arg aArgs[])
 {
     return ProcessRequest(aArgs, OT_COAP_CODE_PUT);
 }
 
-otError Coap::ProcessDelete(Arg aArgs[])
+template <> otError Coap::Process<Cmd("delete")>(Arg aArgs[])
 {
     return ProcessRequest(aArgs, OT_COAP_CODE_DELETE);
 }
 
 #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
-otError Coap::ProcessObserve(Arg aArgs[])
+template <> otError Coap::Process<Cmd("observe")>(Arg aArgs[])
 {
     return ProcessRequest(aArgs, OT_COAP_CODE_GET, /* aCoapObserve */ true);
 }
@@ -577,17 +563,44 @@
 
 otError Coap::Process(Arg aArgs[])
 {
-    otError        error = OT_ERROR_INVALID_ARGS;
-    const Command *command;
-
-    if (aArgs[0].IsEmpty())
-    {
-        IgnoreError(ProcessHelp(aArgs));
-        ExitNow();
+#define CmdEntry(aCommandString)                            \
+    {                                                       \
+        aCommandString, &Coap::Process<Cmd(aCommandString)> \
     }
 
-    command = Utils::LookupTable::Find(aArgs[0].GetCString(), sCommands);
-    VerifyOrExit(command != nullptr, error = OT_ERROR_INVALID_COMMAND);
+    static constexpr Command kCommands[] = {
+#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
+        CmdEntry("cancel"),
+#endif
+        CmdEntry("delete"),
+        CmdEntry("get"),
+#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
+        CmdEntry("observe"),
+#endif
+        CmdEntry("parameters"),
+        CmdEntry("post"),
+        CmdEntry("put"),
+        CmdEntry("resource"),
+        CmdEntry("set"),
+        CmdEntry("start"),
+        CmdEntry("stop"),
+    };
+
+#undef CmdEntry
+
+    static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
+
+    otError        error = OT_ERROR_INVALID_COMMAND;
+    const Command *command;
+
+    if (aArgs[0].IsEmpty() || (aArgs[0] == "help"))
+    {
+        OutputCommandTable(kCommands);
+        ExitNow(error = aArgs[0].IsEmpty() ? OT_ERROR_INVALID_ARGS : OT_ERROR_NONE);
+    }
+
+    command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
+    VerifyOrExit(command != nullptr);
 
     error = (this->*command->mHandler)(aArgs + 1);
 
diff --git a/src/cli/cli_coap.hpp b/src/cli/cli_coap.hpp
index f1d158c..afa56bf 100644
--- a/src/cli/cli_coap.hpp
+++ b/src/cli/cli_coap.hpp
@@ -41,8 +41,6 @@
 #include <openthread/coap.h>
 
 #include "cli/cli_output.hpp"
-#include "utils/lookup_table.hpp"
-#include "utils/parse_cmdline.hpp"
 
 namespace ot {
 namespace Cli {
@@ -79,11 +77,7 @@
         kMaxBufferSize = 16
     };
 
-    struct Command
-    {
-        const char *mName;
-        otError (Coap::*mHandler)(Arg aArgs[]);
-    };
+    using Command = CommandEntry<Coap>;
 
 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
     enum BlockType : uint8_t{
@@ -92,6 +86,8 @@
     };
 #endif
 
+    template <CommandId kCommandId> otError Process(Arg aArgs[]);
+
 #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
     otError CancelResourceSubscription(void);
     void    CancelSubscriber(void);
@@ -99,23 +95,6 @@
 
     void PrintPayload(otMessage *aMessage);
 
-    otError ProcessHelp(Arg aArgs[]);
-#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
-    otError ProcessCancel(Arg aArgs[]);
-#endif
-    otError ProcessDelete(Arg aArgs[]);
-    otError ProcessGet(Arg aArgs[]);
-#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
-    otError ProcessObserve(Arg aArgs[]);
-#endif
-    otError ProcessParameters(Arg aArgs[]);
-    otError ProcessPost(Arg aArgs[]);
-    otError ProcessPut(Arg aArgs[]);
-    otError ProcessResource(Arg aArgs[]);
-    otError ProcessSet(Arg aArgs[]);
-    otError ProcessStart(Arg aArgs[]);
-    otError ProcessStop(Arg aArgs[]);
-
 #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
     otError ProcessRequest(Arg aArgs[], otCoapCode aCoapCode, bool aCoapObserve = false);
 #else
@@ -167,27 +146,6 @@
         return mUseDefaultResponseTxParameters ? nullptr : &mResponseTxParameters;
     }
 
-    static constexpr Command sCommands[] = {
-#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
-        {"cancel", &Coap::ProcessCancel},
-#endif
-        {"delete", &Coap::ProcessDelete},
-        {"get", &Coap::ProcessGet},
-        {"help", &Coap::ProcessHelp},
-#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
-        {"observe", &Coap::ProcessObserve},
-#endif
-        {"parameters", &Coap::ProcessParameters},
-        {"post", &Coap::ProcessPost},
-        {"put", &Coap::ProcessPut},
-        {"resource", &Coap::ProcessResource},
-        {"set", &Coap::ProcessSet},
-        {"start", &Coap::ProcessStart},
-        {"stop", &Coap::ProcessStop},
-    };
-
-    static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
-
     bool mUseDefaultRequestTxParameters;
     bool mUseDefaultResponseTxParameters;
 
diff --git a/src/cli/cli_coap_secure.cpp b/src/cli/cli_coap_secure.cpp
index f684894..aae4798 100644
--- a/src/cli/cli_coap_secure.cpp
+++ b/src/cli/cli_coap_secure.cpp
@@ -468,7 +468,7 @@
         ExitNow();
     }
 
-    command = Utils::LookupTable::Find(aArgs[0].GetCString(), sCommands);
+    command = BinarySearch::Find(aArgs[0].GetCString(), sCommands);
     VerifyOrExit(command != nullptr, error = OT_ERROR_INVALID_COMMAND);
 
     error = (this->*command->mHandler)(aArgs + 1);
diff --git a/src/cli/cli_coap_secure.hpp b/src/cli/cli_coap_secure.hpp
index 18f7897..3bd4872 100644
--- a/src/cli/cli_coap_secure.hpp
+++ b/src/cli/cli_coap_secure.hpp
@@ -43,8 +43,6 @@
 #include <openthread/coap_secure.h>
 
 #include "cli/cli_output.hpp"
-#include "utils/lookup_table.hpp"
-#include "utils/parse_cmdline.hpp"
 
 #ifndef CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER
 #define CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER 0
@@ -87,11 +85,7 @@
         kPskIdMaxLength = 32
     };
 
-    struct Command
-    {
-        const char *mName;
-        otError (CoapSecure::*mHandler)(Arg aArgs[]);
-    };
+    using Command = CommandEntry<CoapSecure>;
 
 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
     enum BlockType : uint8_t{
@@ -175,7 +169,7 @@
 #endif
     };
 
-    static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
+    static_assert(BinarySearch::IsSorted(sCommands), "Command Table is not sorted");
 
 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
     otCoapBlockwiseResource mResource;
diff --git a/src/cli/cli_commissioner.cpp b/src/cli/cli_commissioner.cpp
index 122259c..bbbcfce 100644
--- a/src/cli/cli_commissioner.cpp
+++ b/src/cli/cli_commissioner.cpp
@@ -40,21 +40,7 @@
 namespace ot {
 namespace Cli {
 
-constexpr Commissioner::Command Commissioner::sCommands[];
-
-otError Commissioner::ProcessHelp(Arg aArgs[])
-{
-    OT_UNUSED_VARIABLE(aArgs);
-
-    for (const Command &command : sCommands)
-    {
-        OutputLine(command.mName);
-    }
-
-    return OT_ERROR_NONE;
-}
-
-otError Commissioner::ProcessAnnounce(Arg aArgs[])
+template <> otError Commissioner::Process<Cmd("announce")>(Arg aArgs[])
 {
     otError      error;
     uint32_t     mask;
@@ -73,7 +59,7 @@
     return error;
 }
 
-otError Commissioner::ProcessEnergy(Arg aArgs[])
+template <> otError Commissioner::Process<Cmd("energy")>(Arg aArgs[])
 {
     otError      error;
     uint32_t     mask;
@@ -95,13 +81,54 @@
     return error;
 }
 
-otError Commissioner::ProcessJoiner(Arg aArgs[])
+template <> otError Commissioner::Process<Cmd("joiner")>(Arg aArgs[])
 {
     otError             error = OT_ERROR_NONE;
     otExtAddress        addr;
     const otExtAddress *addrPtr = nullptr;
     otJoinerDiscerner   discerner;
 
+    if (aArgs[0] == "table")
+    {
+        uint16_t     iter = 0;
+        otJoinerInfo joinerInfo;
+
+        static const char *const kJoinerTableTitles[] = {"ID", "PSKd", "Expiration"};
+
+        static const uint8_t kJoinerTableColumnWidths[] = {
+            23,
+            34,
+            12,
+        };
+
+        OutputTableHeader(kJoinerTableTitles, kJoinerTableColumnWidths);
+
+        while (otCommissionerGetNextJoinerInfo(GetInstancePtr(), &iter, &joinerInfo) == OT_ERROR_NONE)
+        {
+            switch (joinerInfo.mType)
+            {
+            case OT_JOINER_INFO_TYPE_ANY:
+                OutputFormat("| %21s", "*");
+                break;
+
+            case OT_JOINER_INFO_TYPE_EUI64:
+                OutputFormat("|      ");
+                OutputExtAddress(joinerInfo.mSharedId.mEui64);
+                break;
+
+            case OT_JOINER_INFO_TYPE_DISCERNER:
+                OutputFormat("| 0x%016llx/%2u", static_cast<unsigned long long>(joinerInfo.mSharedId.mDiscerner.mValue),
+                             joinerInfo.mSharedId.mDiscerner.mLength);
+                break;
+            }
+
+            OutputFormat(" | %32s | %10d |", joinerInfo.mPskd.m8, joinerInfo.mExpirationTime);
+            OutputLine("");
+        }
+
+        ExitNow(error = OT_ERROR_NONE);
+    }
+
     VerifyOrExit(!aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
 
     memset(&discerner, 0, sizeof(discerner));
@@ -163,7 +190,7 @@
     return error;
 }
 
-otError Commissioner::ProcessMgmtGet(Arg aArgs[])
+template <> otError Commissioner::Process<Cmd("mgmtget")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
     uint8_t tlvs[32];
@@ -210,7 +237,7 @@
     return error;
 }
 
-otError Commissioner::ProcessMgmtSet(Arg aArgs[])
+template <> otError Commissioner::Process<Cmd("mgmtset")>(Arg aArgs[])
 {
     otError                error;
     otCommissioningDataset dataset;
@@ -272,7 +299,7 @@
     return error;
 }
 
-otError Commissioner::ProcessPanId(Arg aArgs[])
+template <> otError Commissioner::Process<Cmd("panid")>(Arg aArgs[])
 {
     otError      error;
     uint16_t     panId;
@@ -289,14 +316,14 @@
     return error;
 }
 
-otError Commissioner::ProcessProvisioningUrl(Arg aArgs[])
+template <> otError Commissioner::Process<Cmd("provisioningurl")>(Arg aArgs[])
 {
     // If aArgs[0] is empty, `GetCString() will return `nullptr`
     /// which will correctly clear the provisioning URL.
     return otCommissionerSetProvisioningUrl(GetInstancePtr(), aArgs[0].GetCString());
 }
 
-otError Commissioner::ProcessSessionId(Arg aArgs[])
+template <> otError Commissioner::Process<Cmd("sessionid")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -305,7 +332,24 @@
     return OT_ERROR_NONE;
 }
 
-otError Commissioner::ProcessStart(Arg aArgs[])
+template <> otError Commissioner::Process<Cmd("id")>(Arg aArgs[])
+{
+    otError error;
+
+    if (aArgs[0].IsEmpty())
+    {
+        OutputLine("%s", otCommissionerGetId(GetInstancePtr()));
+        error = OT_ERROR_NONE;
+    }
+    else
+    {
+        error = otCommissionerSetId(GetInstancePtr(), aArgs[0].GetCString());
+    }
+
+    return error;
+}
+
+template <> otError Commissioner::Process<Cmd("start")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -325,22 +369,17 @@
 
 const char *Commissioner::StateToString(otCommissionerState aState)
 {
-    const char *rval = "unknown";
+    static const char *const kStateString[] = {
+        "disabled",    // (0) OT_COMMISSIONER_STATE_DISABLED
+        "petitioning", // (1) OT_COMMISSIONER_STATE_PETITION
+        "active",      // (2) OT_COMMISSIONER_STATE_ACTIVE
+    };
 
-    switch (aState)
-    {
-    case OT_COMMISSIONER_STATE_DISABLED:
-        rval = "disabled";
-        break;
-    case OT_COMMISSIONER_STATE_PETITION:
-        rval = "petitioning";
-        break;
-    case OT_COMMISSIONER_STATE_ACTIVE:
-        rval = "active";
-        break;
-    }
+    static_assert(0 == OT_COMMISSIONER_STATE_DISABLED, "OT_COMMISSIONER_STATE_DISABLED value is incorrect");
+    static_assert(1 == OT_COMMISSIONER_STATE_PETITION, "OT_COMMISSIONER_STATE_PETITION value is incorrect");
+    static_assert(2 == OT_COMMISSIONER_STATE_ACTIVE, "OT_COMMISSIONER_STATE_ACTIVE value is incorrect");
 
-    return rval;
+    return Stringify(aState, kStateString);
 }
 
 void Commissioner::HandleJoinerEvent(otCommissionerJoinerEvent aEvent,
@@ -355,28 +394,23 @@
                                      const otJoinerInfo *      aJoinerInfo,
                                      const otExtAddress *      aJoinerId)
 {
+    static const char *const kEventStrings[] = {
+        "start",    // (0) OT_COMMISSIONER_JOINER_START
+        "connect",  // (1) OT_COMMISSIONER_JOINER_CONNECTED
+        "finalize", // (2) OT_COMMISSIONER_JOINER_FINALIZE
+        "end",      // (3) OT_COMMISSIONER_JOINER_END
+        "remove",   // (4) OT_COMMISSIONER_JOINER_REMOVED
+    };
+
+    static_assert(0 == OT_COMMISSIONER_JOINER_START, "OT_COMMISSIONER_JOINER_START value is incorrect");
+    static_assert(1 == OT_COMMISSIONER_JOINER_CONNECTED, "OT_COMMISSIONER_JOINER_CONNECTED value is incorrect");
+    static_assert(2 == OT_COMMISSIONER_JOINER_FINALIZE, "OT_COMMISSIONER_JOINER_FINALIZE value is incorrect");
+    static_assert(3 == OT_COMMISSIONER_JOINER_END, "OT_COMMISSIONER_JOINER_END value is incorrect");
+    static_assert(4 == OT_COMMISSIONER_JOINER_REMOVED, "OT_COMMISSIONER_JOINER_REMOVED value is incorrect");
+
     OT_UNUSED_VARIABLE(aJoinerInfo);
 
-    OutputFormat("Commissioner: Joiner ");
-
-    switch (aEvent)
-    {
-    case OT_COMMISSIONER_JOINER_START:
-        OutputFormat("start ");
-        break;
-    case OT_COMMISSIONER_JOINER_CONNECTED:
-        OutputFormat("connect ");
-        break;
-    case OT_COMMISSIONER_JOINER_FINALIZE:
-        OutputFormat("finalize ");
-        break;
-    case OT_COMMISSIONER_JOINER_END:
-        OutputFormat("end ");
-        break;
-    case OT_COMMISSIONER_JOINER_REMOVED:
-        OutputFormat("remove ");
-        break;
-    }
+    OutputFormat("Commissioner: Joiner %s ", Stringify(aEvent, kEventStrings));
 
     if (aJoinerId != nullptr)
     {
@@ -386,14 +420,14 @@
     OutputLine("");
 }
 
-otError Commissioner::ProcessStop(Arg aArgs[])
+template <> otError Commissioner::Process<Cmd("stop")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
     return otCommissionerStop(GetInstancePtr());
 }
 
-otError Commissioner::ProcessState(Arg aArgs[])
+template <> otError Commissioner::Process<Cmd("state")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -404,16 +438,31 @@
 
 otError Commissioner::Process(Arg aArgs[])
 {
+#define CmdEntry(aCommandString)                                    \
+    {                                                               \
+        aCommandString, &Commissioner::Process<Cmd(aCommandString)> \
+    }
+
+    static constexpr Command kCommands[] = {
+        CmdEntry("announce"),  CmdEntry("energy"),  CmdEntry("id"),    CmdEntry("joiner"),
+        CmdEntry("mgmtget"),   CmdEntry("mgmtset"), CmdEntry("panid"), CmdEntry("provisioningurl"),
+        CmdEntry("sessionid"), CmdEntry("start"),   CmdEntry("state"), CmdEntry("stop"),
+    };
+
+#undef CmdEntry
+
+    static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
+
     otError        error = OT_ERROR_INVALID_COMMAND;
     const Command *command;
 
-    if (aArgs[0].IsEmpty())
+    if (aArgs[0].IsEmpty() || (aArgs[0] == "help"))
     {
-        IgnoreError(ProcessHelp(aArgs));
-        ExitNow();
+        OutputCommandTable(kCommands);
+        ExitNow(error = aArgs[0].IsEmpty() ? error : OT_ERROR_NONE);
     }
 
-    command = Utils::LookupTable::Find(aArgs[0].GetCString(), sCommands);
+    command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
     VerifyOrExit(command != nullptr);
 
     error = (this->*command->mHandler)(aArgs + 1);
diff --git a/src/cli/cli_commissioner.hpp b/src/cli/cli_commissioner.hpp
index 175c5cd..d63089d 100644
--- a/src/cli/cli_commissioner.hpp
+++ b/src/cli/cli_commissioner.hpp
@@ -39,8 +39,6 @@
 #include <openthread/commissioner.h>
 
 #include "cli/cli_output.hpp"
-#include "utils/lookup_table.hpp"
-#include "utils/parse_cmdline.hpp"
 
 #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
 
@@ -81,24 +79,9 @@
         kDefaultJoinerTimeout = 120, ///< Default timeout for Joiners, in seconds.
     };
 
-    struct Command
-    {
-        const char *mName;
-        otError (Commissioner::*mHandler)(Arg aArgs[]);
-    };
+    using Command = CommandEntry<Commissioner>;
 
-    otError ProcessHelp(Arg aArgs[]);
-    otError ProcessAnnounce(Arg aArgs[]);
-    otError ProcessEnergy(Arg aArgs[]);
-    otError ProcessJoiner(Arg aArgs[]);
-    otError ProcessMgmtGet(Arg aArgs[]);
-    otError ProcessMgmtSet(Arg aArgs[]);
-    otError ProcessPanId(Arg aArgs[]);
-    otError ProcessProvisioningUrl(Arg aArgs[]);
-    otError ProcessSessionId(Arg aArgs[]);
-    otError ProcessStart(Arg aArgs[]);
-    otError ProcessState(Arg aArgs[]);
-    otError ProcessStop(Arg aArgs[]);
+    template <CommandId kCommandId> otError Process(Arg aArgs[]);
 
     static void HandleStateChanged(otCommissionerState aState, void *aContext);
     void        HandleStateChanged(otCommissionerState aState);
@@ -121,17 +104,6 @@
     void        HandlePanIdConflict(uint16_t aPanId, uint32_t aChannelMask);
 
     static const char *StateToString(otCommissionerState aState);
-
-    static constexpr Command sCommands[] = {
-        {"announce", &Commissioner::ProcessAnnounce},   {"energy", &Commissioner::ProcessEnergy},
-        {"help", &Commissioner::ProcessHelp},           {"joiner", &Commissioner::ProcessJoiner},
-        {"mgmtget", &Commissioner::ProcessMgmtGet},     {"mgmtset", &Commissioner::ProcessMgmtSet},
-        {"panid", &Commissioner::ProcessPanId},         {"provisioningurl", &Commissioner::ProcessProvisioningUrl},
-        {"sessionid", &Commissioner::ProcessSessionId}, {"start", &Commissioner::ProcessStart},
-        {"state", &Commissioner::ProcessState},         {"stop", &Commissioner::ProcessStop},
-    };
-
-    static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
 };
 
 } // namespace Cli
diff --git a/src/cli/cli_config.h b/src/cli/cli_config.h
index 96148e3..36aedc6 100644
--- a/src/cli/cli_config.h
+++ b/src/cli/cli_config.h
@@ -113,4 +113,17 @@
 #define OPENTHREAD_CONFIG_CLI_LOG_INPUT_OUTPUT_LOG_STRING_SIZE OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH
 #endif
 
+/**
+ * @def OPENTHREAD_CONFIG_CLI_PROMPT_ENABLE
+ *
+ * Enable CLI prompt.
+ *
+ * When enabled, the CLI will print prompt on the output after processing a command.
+ * Otherwise, no prompt is added to the output.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_CLI_PROMPT_ENABLE
+#define OPENTHREAD_CONFIG_CLI_PROMPT_ENABLE 1
+#endif
+
 #endif // CONFIG_CLI_H_
diff --git a/src/cli/cli_dataset.cpp b/src/cli/cli_dataset.cpp
index 158a6c9..573436a 100644
--- a/src/cli/cli_dataset.cpp
+++ b/src/cli/cli_dataset.cpp
@@ -45,19 +45,18 @@
 namespace ot {
 namespace Cli {
 
-constexpr Dataset::Command Dataset::sCommands[];
-otOperationalDataset       Dataset::sDataset;
+otOperationalDataset Dataset::sDataset;
 
 otError Dataset::Print(otOperationalDataset &aDataset)
 {
     if (aDataset.mComponents.mIsPendingTimestampPresent)
     {
-        OutputLine("Pending Timestamp: %lu", aDataset.mPendingTimestamp);
+        OutputLine("Pending Timestamp: %lu", aDataset.mPendingTimestamp.mSeconds);
     }
 
     if (aDataset.mComponents.mIsActiveTimestampPresent)
     {
-        OutputLine("Active Timestamp: %lu", aDataset.mActiveTimestamp);
+        OutputLine("Active Timestamp: %lu", aDataset.mActiveTimestamp.mSeconds);
     }
 
     if (aDataset.mComponents.mIsChannelPresent)
@@ -119,38 +118,7 @@
     return OT_ERROR_NONE;
 }
 
-otError Dataset::Process(Arg aArgs[])
-{
-    otError        error = OT_ERROR_INVALID_COMMAND;
-    const Command *command;
-
-    if (aArgs[0].IsEmpty())
-    {
-        ExitNow(error = Print(sDataset));
-    }
-
-    command = Utils::LookupTable::Find(aArgs[0].GetCString(), sCommands);
-    VerifyOrExit(command != nullptr);
-
-    error = (this->*command->mHandler)(aArgs + 1);
-
-exit:
-    return error;
-}
-
-otError Dataset::ProcessHelp(Arg aArgs[])
-{
-    OT_UNUSED_VARIABLE(aArgs);
-
-    for (const Command &command : sCommands)
-    {
-        OutputLine(command.mName);
-    }
-
-    return OT_ERROR_NONE;
-}
-
-otError Dataset::ProcessInit(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("init")>(Arg aArgs[])
 {
     otError error = OT_ERROR_INVALID_ARGS;
 
@@ -183,7 +151,7 @@
     return error;
 }
 
-otError Dataset::ProcessActive(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("active")>(Arg aArgs[])
 {
     otError error = OT_ERROR_INVALID_ARGS;
 
@@ -206,7 +174,7 @@
     return error;
 }
 
-otError Dataset::ProcessPending(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("pending")>(Arg aArgs[])
 {
     otError error = OT_ERROR_INVALID_ARGS;
 
@@ -229,7 +197,7 @@
     return error;
 }
 
-otError Dataset::ProcessActiveTimestamp(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("activetimestamp")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -237,12 +205,14 @@
     {
         if (sDataset.mComponents.mIsActiveTimestampPresent)
         {
-            OutputLine("%lu", sDataset.mActiveTimestamp);
+            OutputLine("%lu", sDataset.mActiveTimestamp.mSeconds);
         }
     }
     else
     {
-        SuccessOrExit(error = aArgs[0].ParseAsUint64(sDataset.mActiveTimestamp));
+        SuccessOrExit(error = aArgs[0].ParseAsUint64(sDataset.mActiveTimestamp.mSeconds));
+        sDataset.mActiveTimestamp.mTicks               = 0;
+        sDataset.mActiveTimestamp.mAuthoritative       = false;
         sDataset.mComponents.mIsActiveTimestampPresent = true;
     }
 
@@ -250,7 +220,7 @@
     return error;
 }
 
-otError Dataset::ProcessChannel(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("channel")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -271,7 +241,7 @@
     return error;
 }
 
-otError Dataset::ProcessChannelMask(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("channelmask")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -292,7 +262,7 @@
     return error;
 }
 
-otError Dataset::ProcessClear(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("clear")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -300,7 +270,7 @@
     return OT_ERROR_NONE;
 }
 
-otError Dataset::ProcessCommit(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("commit")>(Arg aArgs[])
 {
     otError error = OT_ERROR_INVALID_ARGS;
 
@@ -316,7 +286,7 @@
     return error;
 }
 
-otError Dataset::ProcessDelay(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("delay")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -337,7 +307,7 @@
     return error;
 }
 
-otError Dataset::ProcessExtPanId(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("extpanid")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -358,7 +328,7 @@
     return error;
 }
 
-otError Dataset::ProcessMeshLocalPrefix(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("meshlocalprefix")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -384,7 +354,7 @@
     return error;
 }
 
-otError Dataset::ProcessNetworkKey(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("networkkey")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -405,7 +375,7 @@
     return error;
 }
 
-otError Dataset::ProcessNetworkName(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("networkname")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -426,7 +396,7 @@
     return error;
 }
 
-otError Dataset::ProcessPanId(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("panid")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -447,7 +417,7 @@
     return error;
 }
 
-otError Dataset::ProcessPendingTimestamp(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("pendingtimestamp")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -455,12 +425,14 @@
     {
         if (sDataset.mComponents.mIsPendingTimestampPresent)
         {
-            OutputLine("%lu", sDataset.mPendingTimestamp);
+            OutputLine("%lu", sDataset.mPendingTimestamp.mSeconds);
         }
     }
     else
     {
-        SuccessOrExit(error = aArgs[0].ParseAsUint64(sDataset.mPendingTimestamp));
+        SuccessOrExit(error = aArgs[0].ParseAsUint64(sDataset.mPendingTimestamp.mSeconds));
+        sDataset.mPendingTimestamp.mTicks               = 0;
+        sDataset.mPendingTimestamp.mAuthoritative       = false;
         sDataset.mComponents.mIsPendingTimestampPresent = true;
     }
 
@@ -468,7 +440,7 @@
     return error;
 }
 
-otError Dataset::ProcessMgmtSetCommand(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("mgmtsetcommand")>(Arg aArgs[])
 {
     otError              error = OT_ERROR_NONE;
     otOperationalDataset dataset;
@@ -482,14 +454,18 @@
         if (*arg == "activetimestamp")
         {
             arg++;
+            SuccessOrExit(error = arg->ParseAsUint64(dataset.mActiveTimestamp.mSeconds));
+            dataset.mActiveTimestamp.mTicks               = 0;
+            dataset.mActiveTimestamp.mAuthoritative       = false;
             dataset.mComponents.mIsActiveTimestampPresent = true;
-            SuccessOrExit(error = arg->ParseAsUint64(dataset.mActiveTimestamp));
         }
         else if (*arg == "pendingtimestamp")
         {
             arg++;
+            SuccessOrExit(error = arg->ParseAsUint64(dataset.mPendingTimestamp.mSeconds));
+            dataset.mPendingTimestamp.mTicks               = 0;
+            dataset.mPendingTimestamp.mAuthoritative       = false;
             dataset.mComponents.mIsPendingTimestampPresent = true;
-            SuccessOrExit(error = arg->ParseAsUint64(dataset.mPendingTimestamp));
         }
         else if (*arg == "networkkey")
         {
@@ -583,7 +559,7 @@
     return error;
 }
 
-otError Dataset::ProcessMgmtGetCommand(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("mgmtgetcommand")>(Arg aArgs[])
 {
     otError                        error = OT_ERROR_NONE;
     otOperationalDatasetComponents datasetComponents;
@@ -676,7 +652,7 @@
     return error;
 }
 
-otError Dataset::ProcessPskc(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("pskc")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -743,11 +719,6 @@
         OutputFormat("c");
     }
 
-    if (aSecurityPolicy.mBeaconsEnabled)
-    {
-        OutputFormat("b");
-    }
-
     if (aSecurityPolicy.mCommercialCommissioningEnabled)
     {
         OutputFormat("C");
@@ -803,10 +774,6 @@
             policy.mExternalCommissioningEnabled = true;
             break;
 
-        case 'b':
-            policy.mBeaconsEnabled = true;
-            break;
-
         case 'C':
             policy.mCommercialCommissioningEnabled = true;
             break;
@@ -839,7 +806,7 @@
     return error;
 }
 
-otError Dataset::ProcessSecurityPolicy(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("securitypolicy")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -862,7 +829,7 @@
     return error;
 }
 
-otError Dataset::ProcessSet(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("set")>(Arg aArgs[])
 {
     otError                error = OT_ERROR_NONE;
     MeshCoP::Dataset::Type datasetType;
@@ -907,7 +874,7 @@
 
 #if OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE && OPENTHREAD_FTD
 
-otError Dataset::ProcessUpdater(Arg aArgs[])
+template <> otError Dataset::Process<Cmd("updater")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -943,5 +910,65 @@
 
 #endif // OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE && OPENTHREAD_FTD
 
+otError Dataset::Process(Arg aArgs[])
+{
+#define CmdEntry(aCommandString)                               \
+    {                                                          \
+        aCommandString, &Dataset::Process<Cmd(aCommandString)> \
+    }
+
+    static constexpr Command kCommands[] = {
+        CmdEntry("active"),
+        CmdEntry("activetimestamp"),
+        CmdEntry("channel"),
+        CmdEntry("channelmask"),
+        CmdEntry("clear"),
+        CmdEntry("commit"),
+        CmdEntry("delay"),
+        CmdEntry("extpanid"),
+        CmdEntry("init"),
+        CmdEntry("meshlocalprefix"),
+        CmdEntry("mgmtgetcommand"),
+        CmdEntry("mgmtsetcommand"),
+        CmdEntry("networkkey"),
+        CmdEntry("networkname"),
+        CmdEntry("panid"),
+        CmdEntry("pending"),
+        CmdEntry("pendingtimestamp"),
+        CmdEntry("pskc"),
+        CmdEntry("securitypolicy"),
+        CmdEntry("set"),
+#if OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE && OPENTHREAD_FTD
+        CmdEntry("updater"),
+#endif
+    };
+
+#undef CmdEntry
+
+    static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
+
+    otError        error = OT_ERROR_INVALID_COMMAND;
+    const Command *command;
+
+    if (aArgs[0].IsEmpty())
+    {
+        ExitNow(error = Print(sDataset));
+    }
+
+    if (aArgs[0] == "help")
+    {
+        OutputCommandTable(kCommands);
+        ExitNow(error = OT_ERROR_NONE);
+    }
+
+    command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
+    VerifyOrExit(command != nullptr);
+
+    error = (this->*command->mHandler)(aArgs + 1);
+
+exit:
+    return error;
+}
+
 } // namespace Cli
 } // namespace ot
diff --git a/src/cli/cli_dataset.hpp b/src/cli/cli_dataset.hpp
index b712c6c..980bb5d 100644
--- a/src/cli/cli_dataset.hpp
+++ b/src/cli/cli_dataset.hpp
@@ -41,8 +41,6 @@
 #include <openthread/dataset.h>
 
 #include "cli/cli_output.hpp"
-#include "utils/lookup_table.hpp"
-#include "utils/parse_cmdline.hpp"
 
 namespace ot {
 namespace Cli {
@@ -70,36 +68,12 @@
     otError Process(Arg aArgs[]);
 
 private:
-    struct Command
-    {
-        const char *mName;
-        otError (Dataset::*mHandler)(Arg aArgs[]);
-    };
+    using Command = CommandEntry<Dataset>;
+
+    template <CommandId kCommandId> otError Process(Arg aArgs[]);
 
     otError Print(otOperationalDataset &aDataset);
 
-    otError ProcessHelp(Arg aArgs[]);
-    otError ProcessActive(Arg aArgs[]);
-    otError ProcessActiveTimestamp(Arg aArgs[]);
-    otError ProcessChannel(Arg aArgs[]);
-    otError ProcessChannelMask(Arg aArgs[]);
-    otError ProcessClear(Arg aArgs[]);
-    otError ProcessCommit(Arg aArgs[]);
-    otError ProcessDelay(Arg aArgs[]);
-    otError ProcessExtPanId(Arg aArgs[]);
-    otError ProcessInit(Arg aArgs[]);
-    otError ProcessMeshLocalPrefix(Arg aArgs[]);
-    otError ProcessNetworkName(Arg aArgs[]);
-    otError ProcessNetworkKey(Arg aArgs[]);
-    otError ProcessPanId(Arg aArgs[]);
-    otError ProcessPending(Arg aArgs[]);
-    otError ProcessPendingTimestamp(Arg aArgs[]);
-    otError ProcessMgmtSetCommand(Arg aArgs[]);
-    otError ProcessMgmtGetCommand(Arg aArgs[]);
-    otError ProcessPskc(Arg aArgs[]);
-    otError ProcessSecurityPolicy(Arg aArgs[]);
-    otError ProcessSet(Arg aArgs[]);
-
 #if OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE && OPENTHREAD_FTD
     otError     ProcessUpdater(Arg aArgs[]);
     static void HandleDatasetUpdater(otError aError, void *aContext);
@@ -109,35 +83,6 @@
     void    OutputSecurityPolicy(const otSecurityPolicy &aSecurityPolicy);
     otError ParseSecurityPolicy(otSecurityPolicy &aSecurityPolicy, Arg *&aArgs);
 
-    static constexpr Command sCommands[] = {
-        {"active", &Dataset::ProcessActive},
-        {"activetimestamp", &Dataset::ProcessActiveTimestamp},
-        {"channel", &Dataset::ProcessChannel},
-        {"channelmask", &Dataset::ProcessChannelMask},
-        {"clear", &Dataset::ProcessClear},
-        {"commit", &Dataset::ProcessCommit},
-        {"delay", &Dataset::ProcessDelay},
-        {"extpanid", &Dataset::ProcessExtPanId},
-        {"help", &Dataset::ProcessHelp},
-        {"init", &Dataset::ProcessInit},
-        {"meshlocalprefix", &Dataset::ProcessMeshLocalPrefix},
-        {"mgmtgetcommand", &Dataset::ProcessMgmtGetCommand},
-        {"mgmtsetcommand", &Dataset::ProcessMgmtSetCommand},
-        {"networkkey", &Dataset::ProcessNetworkKey},
-        {"networkname", &Dataset::ProcessNetworkName},
-        {"panid", &Dataset::ProcessPanId},
-        {"pending", &Dataset::ProcessPending},
-        {"pendingtimestamp", &Dataset::ProcessPendingTimestamp},
-        {"pskc", &Dataset::ProcessPskc},
-        {"securitypolicy", &Dataset::ProcessSecurityPolicy},
-        {"set", &Dataset::ProcessSet},
-#if OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE && OPENTHREAD_FTD
-        {"updater", &Dataset::ProcessUpdater},
-#endif
-    };
-
-    static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
-
     static otOperationalDataset sDataset;
 };
 
diff --git a/src/cli/cli_history.cpp b/src/cli/cli_history.cpp
index 2292e01..3dc856b 100644
--- a/src/cli/cli_history.cpp
+++ b/src/cli/cli_history.cpp
@@ -42,19 +42,10 @@
 namespace ot {
 namespace Cli {
 
-constexpr History::Command History::sCommands[];
-
-otError History::ProcessHelp(Arg aArgs[])
-{
-    OT_UNUSED_VARIABLE(aArgs);
-
-    for (const Command &command : sCommands)
-    {
-        OutputLine(command.mName);
-    }
-
-    return OT_ERROR_NONE;
-}
+static const char *const kSimpleEventStrings[] = {
+    "Added",  // (0) OT_HISTORY_TRACKER_{NET_DATA_ENTRY/ADDRESSS_EVENT}_ADDED
+    "Removed" // (1) OT_HISTORY_TRACKER_{NET_DATA_ENTRY/ADDRESS_EVENT}_REMOVED
+};
 
 otError History::ParseArgs(Arg aArgs[], bool &aIsList, uint16_t &aNumEntries) const
 {
@@ -80,13 +71,8 @@
     return aArgs[0].IsEmpty() ? OT_ERROR_NONE : OT_ERROR_INVALID_ARGS;
 }
 
-otError History::ProcessIpAddr(Arg aArgs[])
+template <> otError History::Process<Cmd("ipaddr")>(Arg aArgs[])
 {
-    static const char *const kEventStrings[] = {
-        "Added",  // (0) OT_HISTORY_TRACKER_ADDRESS_EVENT_ADDED
-        "Removed" // (1) OT_HISTORY_TRACKER_ADDRESS_EVENT_REMOVED
-    };
-
     otError                                   error;
     bool                                      isList;
     uint16_t                                  numEntries;
@@ -126,18 +112,21 @@
 
         if (!isList)
         {
-            sprintf(&addressString[strlen(addressString)], "/%d", info->mPrefixLength);
+            size_t len = strlen(addressString);
 
-            OutputLine("| %20s | %-7s | %-43s | %-6s | %3d | %c | %c | %c |", ageString, kEventStrings[info->mEvent],
-                       addressString, AddressOriginToString(info->mAddressOrigin), info->mScope,
+            snprintf(&addressString[len], sizeof(addressString) - len, "/%d", info->mPrefixLength);
+
+            OutputLine("| %20s | %-7s | %-43s | %-6s | %3d | %c | %c | %c |", ageString,
+                       Stringify(info->mEvent, kSimpleEventStrings), addressString,
+                       Interpreter::AddressOriginToString(info->mAddressOrigin), info->mScope,
                        info->mPreferred ? 'Y' : 'N', info->mValid ? 'Y' : 'N', info->mRloc ? 'Y' : 'N');
         }
         else
         {
             OutputLine("%s -> event:%s address:%s prefixlen:%d origin:%s scope:%d preferred:%s valid:%s rloc:%s",
-                       ageString, kEventStrings[info->mEvent], addressString, info->mPrefixLength,
-                       AddressOriginToString(info->mAddressOrigin), info->mScope, info->mPreferred ? "yes" : "no",
-                       info->mValid ? "yes" : "no", info->mRloc ? "yes" : "no");
+                       ageString, Stringify(info->mEvent, kSimpleEventStrings), addressString, info->mPrefixLength,
+                       Interpreter::AddressOriginToString(info->mAddressOrigin), info->mScope,
+                       info->mPreferred ? "yes" : "no", info->mValid ? "yes" : "no", info->mRloc ? "yes" : "no");
         }
     }
 
@@ -145,7 +134,7 @@
     return error;
 }
 
-otError History::ProcessIpMulticastAddr(Arg aArgs[])
+template <> otError History::Process<Cmd("ipmaddr")>(Arg aArgs[])
 {
     static const char *const kEventStrings[] = {
         "Subscribed",  // (0) OT_HISTORY_TRACKER_ADDRESS_EVENT_ADDED
@@ -194,14 +183,15 @@
         otIp6AddressToString(&info->mAddress, addressString, sizeof(addressString));
 
         OutputLine(isList ? "%s -> event:%s address:%s origin:%s" : "| %20s | %-12s | %-39s | %-6s |", ageString,
-                   kEventStrings[info->mEvent], addressString, AddressOriginToString(info->mAddressOrigin));
+                   Stringify(info->mEvent, kEventStrings), addressString,
+                   Interpreter::AddressOriginToString(info->mAddressOrigin));
     }
 
 exit:
     return error;
 }
 
-otError History::ProcessNeighbor(Arg aArgs[])
+template <> otError History::Process<Cmd("neighbor")>(Arg aArgs[])
 {
     static const char *const kEventString[] = {
         /* (0) OT_HISTORY_TRACKER_NEIGHBOR_EVENT_ADDED     -> */ "Added",
@@ -266,7 +256,7 @@
     return error;
 }
 
-otError History::ProcessNetInfo(Arg aArgs[])
+template <> otError History::Process<Cmd("netinfo")>(Arg aArgs[])
 {
     otError                            error;
     bool                               isList;
@@ -309,77 +299,36 @@
     return error;
 }
 
-otError History::ProcessRx(Arg aArgs[])
+template <> otError History::Process<Cmd("rx")>(Arg aArgs[])
 {
     return ProcessRxTxHistory(kRx, aArgs);
 }
 
-otError History::ProcessRxTx(Arg aArgs[])
+template <> otError History::Process<Cmd("rxtx")>(Arg aArgs[])
 {
     return ProcessRxTxHistory(kRxTx, aArgs);
 }
 
-otError History::ProcessTx(Arg aArgs[])
+template <> otError History::Process<Cmd("tx")>(Arg aArgs[])
 {
     return ProcessRxTxHistory(kTx, aArgs);
 }
 
-const char *History::AddressOriginToString(uint8_t aOrigin)
-{
-    const char *str = "Unknown";
-
-    switch (aOrigin)
-    {
-    case OT_ADDRESS_ORIGIN_THREAD:
-        str = "Thread";
-        break;
-
-    case OT_ADDRESS_ORIGIN_SLAAC:
-        str = "SLAAC";
-        break;
-
-    case OT_ADDRESS_ORIGIN_DHCPV6:
-        str = "DHCPv6";
-        break;
-
-    case OT_ADDRESS_ORIGIN_MANUAL:
-        str = "Manual";
-        break;
-
-    default:
-        break;
-    }
-
-    return str;
-}
-
 const char *History::MessagePriorityToString(uint8_t aPriority)
 {
-    const char *str = "unkn";
+    static const char *const kPriorityStrings[] = {
+        "low",  // (0) OT_HISTORY_TRACKER_MSG_PRIORITY_LOW
+        "norm", // (1) OT_HISTORY_TRACKER_MSG_PRIORITY_NORMAL
+        "high", // (2) OT_HISTORY_TRACKER_MSG_PRIORITY_HIGH
+        "net",  // (3) OT_HISTORY_TRACKER_MSG_PRIORITY_NET
+    };
 
-    switch (aPriority)
-    {
-    case OT_HISTORY_TRACKER_MSG_PRIORITY_LOW:
-        str = "low";
-        break;
+    static_assert(0 == OT_HISTORY_TRACKER_MSG_PRIORITY_LOW, "MSG_PRIORITY_LOW value is incorrect");
+    static_assert(1 == OT_HISTORY_TRACKER_MSG_PRIORITY_NORMAL, "MSG_PRIORITY_NORMAL value is incorrect");
+    static_assert(2 == OT_HISTORY_TRACKER_MSG_PRIORITY_HIGH, "MSG_PRIORITY_HIGH value is incorrect");
+    static_assert(3 == OT_HISTORY_TRACKER_MSG_PRIORITY_NET, "MSG_PRIORITY_NET value is incorrect");
 
-    case OT_HISTORY_TRACKER_MSG_PRIORITY_NORMAL:
-        str = "norm";
-        break;
-
-    case OT_HISTORY_TRACKER_MSG_PRIORITY_HIGH:
-        str = "high";
-        break;
-
-    case OT_HISTORY_TRACKER_MSG_PRIORITY_NET:
-        str = "net";
-        break;
-
-    default:
-        break;
-    }
-
-    return str;
+    return Stringify(aPriority, kPriorityStrings, "unkn");
 }
 
 const char *History::RadioTypeToString(const otHistoryTrackerMessageInfo &aInfo)
@@ -542,7 +491,6 @@
     constexpr uint8_t kIndentSize = 4;
 
     char ageString[OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE];
-    char addrString[OT_IP6_SOCK_ADDR_STRING_SIZE];
 
     otHistoryTrackerEntryAgeToString(aEntryAge, ageString, sizeof(ageString));
 
@@ -561,11 +509,11 @@
 
     OutputLine(" %s:0x%04x radio:%s", aIsRx ? "from" : "to", aInfo.mNeighborRloc16, RadioTypeToString(aInfo));
 
-    otIp6SockAddrToString(&aInfo.mSource, addrString, sizeof(addrString));
-    OutputLine(kIndentSize, "src:%s", addrString);
+    OutputFormat(kIndentSize, "src:");
+    OutputSockAddrLine(aInfo.mSource);
 
-    otIp6SockAddrToString(&aInfo.mDestination, addrString, sizeof(addrString));
-    OutputLine(kIndentSize, "dst:%s", addrString);
+    OutputFormat(kIndentSize, "dst:");
+    OutputSockAddrLine(aInfo.mDestination);
 }
 
 void History::OutputRxTxEntryTableFormat(const otHistoryTrackerMessageInfo &aInfo, uint32_t aEntryAge, bool aIsRx)
@@ -611,18 +559,132 @@
     OutputLine("| %20s | dst: %-70s |", "", addrString);
 }
 
+template <> otError History::Process<Cmd("prefix")>(Arg aArgs[])
+{
+    otError                                 error;
+    bool                                    isList;
+    uint16_t                                numEntries;
+    otHistoryTrackerIterator                iterator;
+    const otHistoryTrackerOnMeshPrefixInfo *info;
+    uint32_t                                entryAge;
+    char                                    ageString[OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE];
+    char                                    prefixString[OT_IP6_PREFIX_STRING_SIZE];
+    NetworkData::FlagsString                flagsString;
+
+    static_assert(0 == OT_HISTORY_TRACKER_NET_DATA_ENTRY_ADDED, "NET_DATA_ENTRY_ADDED value is incorrect");
+    static_assert(1 == OT_HISTORY_TRACKER_NET_DATA_ENTRY_REMOVED, "NET_DATA_ENTRY_REMOVED value is incorrect");
+
+    SuccessOrExit(error = ParseArgs(aArgs, isList, numEntries));
+
+    if (!isList)
+    {
+        // | Age                  | Event   | Prefix                                      | Flags     | Pref | RLOC16 |
+        // +----------------------+---------+---------------------------------------------+-----------+------+--------+
+
+        static const char *const kPrefixTitles[]       = {"Age", "Event", "Prefix", "Flags", "Pref", "RLOC16"};
+        static const uint8_t     kPrefixColumnWidths[] = {22, 9, 45, 11, 6, 8};
+
+        OutputTableHeader(kPrefixTitles, kPrefixColumnWidths);
+    }
+
+    otHistoryTrackerInitIterator(&iterator);
+
+    for (uint16_t index = 0; (numEntries == 0) || (index < numEntries); index++)
+    {
+        info = otHistoryTrackerIterateOnMeshPrefixHistory(GetInstancePtr(), &iterator, &entryAge);
+        VerifyOrExit(info != nullptr);
+
+        otHistoryTrackerEntryAgeToString(entryAge, ageString, sizeof(ageString));
+
+        otIp6PrefixToString(&info->mPrefix.mPrefix, prefixString, sizeof(prefixString));
+        NetworkData::PrefixFlagsToString(info->mPrefix, flagsString);
+
+        OutputLine(isList ? "%s -> event:%s prefix:%s flags:%s pref:%s rloc16:0x%04x"
+                          : "| %20s | %-7s | %-43s | %-9s | %-4s | 0x%04x |",
+                   ageString, Stringify(info->mEvent, kSimpleEventStrings), prefixString, flagsString,
+                   Interpreter::PreferenceToString(info->mPrefix.mPreference), info->mPrefix.mRloc16);
+    }
+
+exit:
+    return error;
+}
+
+template <> otError History::Process<Cmd("route")>(Arg aArgs[])
+{
+    otError                                  error;
+    bool                                     isList;
+    uint16_t                                 numEntries;
+    otHistoryTrackerIterator                 iterator;
+    const otHistoryTrackerExternalRouteInfo *info;
+    uint32_t                                 entryAge;
+    char                                     ageString[OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE];
+    char                                     prefixString[OT_IP6_PREFIX_STRING_SIZE];
+    NetworkData::FlagsString                 flagsString;
+
+    static_assert(0 == OT_HISTORY_TRACKER_NET_DATA_ENTRY_ADDED, "NET_DATA_ENTRY_ADDED value is incorrect");
+    static_assert(1 == OT_HISTORY_TRACKER_NET_DATA_ENTRY_REMOVED, "NET_DATA_ENTRY_REMOVED value is incorrect");
+
+    SuccessOrExit(error = ParseArgs(aArgs, isList, numEntries));
+
+    if (!isList)
+    {
+        // | Age                  | Event   | Route                                       | Flags     | Pref | RLOC16 |
+        // +----------------------+---------+---------------------------------------------+-----------+------+--------+
+
+        static const char *const kRouteTitles[]       = {"Age", "Event", "Route", "Flags", "Pref", "RLOC16"};
+        static const uint8_t     kRouteColumnWidths[] = {22, 9, 45, 11, 6, 8};
+
+        OutputTableHeader(kRouteTitles, kRouteColumnWidths);
+    }
+
+    otHistoryTrackerInitIterator(&iterator);
+
+    for (uint16_t index = 0; (numEntries == 0) || (index < numEntries); index++)
+    {
+        info = otHistoryTrackerIterateExternalRouteHistory(GetInstancePtr(), &iterator, &entryAge);
+        VerifyOrExit(info != nullptr);
+
+        otHistoryTrackerEntryAgeToString(entryAge, ageString, sizeof(ageString));
+
+        otIp6PrefixToString(&info->mRoute.mPrefix, prefixString, sizeof(prefixString));
+        NetworkData::RouteFlagsToString(info->mRoute, flagsString);
+
+        OutputLine(isList ? "%s -> event:%s route:%s flags:%s pref:%s rloc16:0x%04x"
+                          : "| %20s | %-7s | %-43s | %-9s | %-4s | 0x%04x |",
+                   ageString, Stringify(info->mEvent, kSimpleEventStrings), prefixString, flagsString,
+                   Interpreter::PreferenceToString(info->mRoute.mPreference), info->mRoute.mRloc16);
+    }
+
+exit:
+    return error;
+}
+
 otError History::Process(Arg aArgs[])
 {
+#define CmdEntry(aCommandString)                               \
+    {                                                          \
+        aCommandString, &History::Process<Cmd(aCommandString)> \
+    }
+
+    static constexpr Command kCommands[] = {
+        CmdEntry("ipaddr"), CmdEntry("ipmaddr"), CmdEntry("neighbor"), CmdEntry("netinfo"), CmdEntry("prefix"),
+        CmdEntry("route"),  CmdEntry("rx"),      CmdEntry("rxtx"),     CmdEntry("tx"),
+    };
+
+#undef CmdEntry
+
+    static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
+
     otError        error = OT_ERROR_INVALID_COMMAND;
     const Command *command;
 
-    if (aArgs[0].IsEmpty())
+    if (aArgs[0].IsEmpty() || (aArgs[0] == "help"))
     {
-        IgnoreError(ProcessHelp(aArgs));
-        ExitNow();
+        OutputCommandTable(kCommands);
+        ExitNow(error = aArgs[0].IsEmpty() ? error : OT_ERROR_NONE);
     }
 
-    command = Utils::LookupTable::Find(aArgs[0].GetCString(), sCommands);
+    command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
     VerifyOrExit(command != nullptr);
 
     error = (this->*command->mHandler)(aArgs + 1);
@@ -634,4 +696,4 @@
 } // namespace Cli
 } // namespace ot
 
-#endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+#endif // OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
diff --git a/src/cli/cli_history.hpp b/src/cli/cli_history.hpp
index 61ea899..a17a667 100644
--- a/src/cli/cli_history.hpp
+++ b/src/cli/cli_history.hpp
@@ -40,8 +40,6 @@
 
 #include "cli/cli_config.h"
 #include "cli/cli_output.hpp"
-#include "utils/lookup_table.hpp"
-#include "utils/parse_cmdline.hpp"
 
 #if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
 
@@ -81,11 +79,7 @@
     static constexpr uint16_t kShortAddrBroadcast = 0xffff;
     static constexpr int8_t   kInvalidRss         = OT_RADIO_RSSI_INVALID;
 
-    struct Command
-    {
-        const char *mName;
-        otError (History::*mHandler)(Arg aArgs[]);
-    };
+    using Command = CommandEntry<History>;
 
     enum RxTx : uint8_t
     {
@@ -94,37 +88,16 @@
         kRxTx,
     };
 
-    otError ProcessHelp(Arg aArgs[]);
-    otError ProcessIpAddr(Arg aArgs[]);
-    otError ProcessIpMulticastAddr(Arg aArgs[]);
-    otError ProcessNetInfo(Arg aArgs[]);
-    otError ProcessNeighbor(Arg aArgs[]);
-    otError ProcessRx(Arg aArgs[]);
-    otError ProcessRxTx(Arg aArgs[]);
-    otError ProcessTx(Arg aArgs[]);
+    template <CommandId kCommandId> otError Process(Arg aArgs[]);
 
     otError ParseArgs(Arg aArgs[], bool &aIsList, uint16_t &aNumEntries) const;
     otError ProcessRxTxHistory(RxTx aRxTx, Arg aArgs[]);
     void    OutputRxTxEntryListFormat(const otHistoryTrackerMessageInfo &aInfo, uint32_t aEntryAge, bool aIsRx);
     void    OutputRxTxEntryTableFormat(const otHistoryTrackerMessageInfo &aInfo, uint32_t aEntryAge, bool aIsRx);
 
-    static const char *AddressOriginToString(uint8_t aOrigin);
     static const char *MessagePriorityToString(uint8_t aPriority);
     static const char *RadioTypeToString(const otHistoryTrackerMessageInfo &aInfo);
     static const char *MessageTypeToString(const otHistoryTrackerMessageInfo &aInfo);
-
-    static constexpr Command sCommands[] = {
-        {"help", &History::ProcessHelp},
-        {"ipaddr", &History::ProcessIpAddr},
-        {"ipmaddr", &History::ProcessIpMulticastAddr},
-        {"neighbor", &History::ProcessNeighbor},
-        {"netinfo", &History::ProcessNetInfo},
-        {"rx", &History::ProcessRx},
-        {"rxtx", &History::ProcessRxTx},
-        {"tx", &History::ProcessTx},
-    };
-
-    static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
 };
 
 } // namespace Cli
diff --git a/src/cli/cli_joiner.cpp b/src/cli/cli_joiner.cpp
index 231d043..82d0d37 100644
--- a/src/cli/cli_joiner.cpp
+++ b/src/cli/cli_joiner.cpp
@@ -42,12 +42,20 @@
 namespace ot {
 namespace Cli {
 
-constexpr Joiner::Command Joiner::sCommands[];
-
-otError Joiner::ProcessDiscerner(Arg aArgs[])
+template <> otError Joiner::Process<Cmd("discerner")>(Arg aArgs[])
 {
     otError error = OT_ERROR_INVALID_ARGS;
 
+    /**
+     * @cli joiner discerner
+     * @code
+     * joiner discerner
+     * 0xabc/12
+     * Done
+     * @endcode
+     * @par api_copy
+     * #otJoinerGetDiscerner
+     */
     if (aArgs[0].IsEmpty())
     {
         const otJoinerDiscerner *discerner = otJoinerGetDiscerner(GetInstancePtr());
@@ -63,10 +71,31 @@
 
         memset(&discerner, 0, sizeof(discerner));
 
+        /**
+         * @cli joiner discerner clear
+         * @code
+         * joiner discerner clear
+         * Done
+         * @endcode
+         * @par
+         * Clear the %Joiner discerner.
+         */
         if (aArgs[0] == "clear")
         {
             error = otJoinerSetDiscerner(GetInstancePtr(), nullptr);
         }
+        /**
+         * @cli joiner discerner (set)
+         * @code
+         * joiner discerner 0xabc/12
+         * Done
+         * @endcode
+         * @cparam joiner discerner @ca{discerner}
+         * *   Use `{number}/{length}` to set the `discerner`.
+         * *   `joiner discerner clear` sets `aDiscerner` to `nullptr`.
+         * @par api_copy
+         * #otJoinerSetDiscerner
+         */
         else
         {
             VerifyOrExit(aArgs[1].IsEmpty());
@@ -79,19 +108,17 @@
     return error;
 }
 
-otError Joiner::ProcessHelp(Arg aArgs[])
-{
-    OT_UNUSED_VARIABLE(aArgs);
-
-    for (const Command &command : sCommands)
-    {
-        OutputLine(command.mName);
-    }
-
-    return OT_ERROR_NONE;
-}
-
-otError Joiner::ProcessId(Arg aArgs[])
+/**
+ * @cli joiner id
+ * @code
+ * joiner id
+ * d65e64fa83f81cf7
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otJoinerGetId
+ */
+template <> otError Joiner::Process<Cmd("id")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -100,7 +127,21 @@
     return OT_ERROR_NONE;
 }
 
-otError Joiner::ProcessStart(Arg aArgs[])
+/**
+ * @cli joiner start
+ * @code
+ * joiner start J01NM3
+ * Done
+ * @endcode
+ * @cparam joiner start @ca{joining-device-credential} [@ca{provisioning-url}]
+ * *   `joining-device-credential`: %Joiner Passphrase. Must be a string of all uppercase alphanumeric
+ *     characters (0-9 and A-Y, excluding I, O, Q, and Z for readability), with a length between 6 and
+ *     32 characters.
+ * *   `provisioning-url`: Provisioning URL for the %Joiner (optional).
+ * @par api_copy
+ * #otJoinerStart
+ */
+template <> otError Joiner::Process<Cmd("start")>(Arg aArgs[])
 {
     otError error;
 
@@ -108,7 +149,7 @@
 
     error = otJoinerStart(GetInstancePtr(),
                           aArgs[0].GetCString(),           // aPskd
-                          aArgs[1].GetCString(),           // aProvisioningUrl (nullptr if aArgs[1] is empty)
+                          aArgs[1].GetCString(),           // aProvisioningUrl (`nullptr` if aArgs[1] is empty)
                           PACKAGE_NAME,                    // aVendorName
                           OPENTHREAD_CONFIG_PLATFORM_INFO, // aVendorModel
                           PACKAGE_VERSION,                 // aVendorSwVersion
@@ -119,7 +160,16 @@
     return error;
 }
 
-otError Joiner::ProcessStop(Arg aArgs[])
+/**
+ * @cli joiner stop
+ * @code
+ * joiner stop
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otJoinerStop
+ */
+template <> otError Joiner::Process<Cmd("stop")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -128,18 +178,72 @@
     return OT_ERROR_NONE;
 }
 
+/**
+ * @cli joiner state
+ * @code
+ * joiner state
+ * Idle
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otJoinerGetState
+ * @par
+ * Returns one of the following states:
+ * *   `Idle`
+ * *   `Discover`
+ * *   `Connecting`
+ * *   `Connected`
+ * *   `Entrust`
+ * *   `Joined`
+ */
+template <> otError Joiner::Process<Cmd("state")>(Arg aArgs[])
+{
+    OT_UNUSED_VARIABLE(aArgs);
+
+    OutputLine("%s", otJoinerStateToString(otJoinerGetState(GetInstancePtr())));
+
+    return OT_ERROR_NONE;
+}
+
 otError Joiner::Process(Arg aArgs[])
 {
+#define CmdEntry(aCommandString)                              \
+    {                                                         \
+        aCommandString, &Joiner::Process<Cmd(aCommandString)> \
+    }
+
+    static constexpr Command kCommands[] = {
+        CmdEntry("discerner"), CmdEntry("id"), CmdEntry("start"), CmdEntry("state"), CmdEntry("stop"),
+    };
+
+#undef CmdEntry
+
+    static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
+
     otError        error = OT_ERROR_INVALID_COMMAND;
     const Command *command;
 
-    if (aArgs[0].IsEmpty())
+    /**
+     * @cli joiner help
+     * @code
+     * joiner help
+     * help
+     * id
+     * start
+     * state
+     * stop
+     * Done
+     * @endcode
+     * @par
+     * Print the `joiner` help menu.
+     */
+    if (aArgs[0].IsEmpty() || (aArgs[0] == "help"))
     {
-        IgnoreError(ProcessHelp(aArgs));
-        ExitNow();
+        OutputCommandTable(kCommands);
+        ExitNow(error = aArgs[0].IsEmpty() ? error : OT_ERROR_NONE);
     }
 
-    command = Utils::LookupTable::Find(aArgs[0].GetCString(), sCommands);
+    command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
     VerifyOrExit(command != nullptr);
 
     error = (this->*command->mHandler)(aArgs + 1);
diff --git a/src/cli/cli_joiner.hpp b/src/cli/cli_joiner.hpp
index a97f00e..d2bc640 100644
--- a/src/cli/cli_joiner.hpp
+++ b/src/cli/cli_joiner.hpp
@@ -39,8 +39,6 @@
 #include <openthread/joiner.h>
 
 #include "cli/cli_output.hpp"
-#include "utils/lookup_table.hpp"
-#include "utils/parse_cmdline.hpp"
 
 #if OPENTHREAD_CONFIG_JOINER_ENABLE
 
@@ -76,27 +74,12 @@
     otError Process(Arg aArgs[]);
 
 private:
-    struct Command
-    {
-        const char *mName;
-        otError (Joiner::*mHandler)(Arg aArgs[]);
-    };
+    using Command = CommandEntry<Joiner>;
 
-    otError ProcessDiscerner(Arg aArgs[]);
-    otError ProcessHelp(Arg aArgs[]);
-    otError ProcessId(Arg aArgs[]);
-    otError ProcessStart(Arg aArgs[]);
-    otError ProcessStop(Arg aArgs[]);
+    template <CommandId kCommandId> otError Process(Arg aArgs[]);
 
     static void HandleCallback(otError aError, void *aContext);
     void        HandleCallback(otError aError);
-
-    static constexpr Command sCommands[] = {
-        {"discerner", &Joiner::ProcessDiscerner}, {"help", &Joiner::ProcessHelp}, {"id", &Joiner::ProcessId},
-        {"start", &Joiner::ProcessStart},         {"stop", &Joiner::ProcessStop},
-    };
-
-    static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
 };
 
 } // namespace Cli
diff --git a/src/cli/cli_network_data.cpp b/src/cli/cli_network_data.cpp
index 9765fb2..1c3de90 100644
--- a/src/cli/cli_network_data.cpp
+++ b/src/cli/cli_network_data.cpp
@@ -43,22 +43,9 @@
 namespace ot {
 namespace Cli {
 
-constexpr NetworkData::Command NetworkData::sCommands[];
-
-void NetworkData::OutputPrefix(const otBorderRouterConfig &aConfig)
+void NetworkData::PrefixFlagsToString(const otBorderRouterConfig &aConfig, FlagsString &aString)
 {
-    enum
-    {
-        // BorderRouter flag is `uint16_t` (though some of the bits are
-        // reserved for future use), so we use 17 chars string (16 flags
-        // plus null char at end of string).
-        kMaxFlagStringSize = 17,
-    };
-
-    char  flagsString[kMaxFlagStringSize];
-    char *flagsPtr = &flagsString[0];
-
-    OutputIp6Prefix(aConfig.mPrefix);
+    char *flagsPtr = &aString[0];
 
     if (aConfig.mPreferred)
     {
@@ -106,31 +93,27 @@
     }
 
     *flagsPtr = '\0';
+}
 
-    if (flagsPtr != &flagsString[0])
+void NetworkData::OutputPrefix(const otBorderRouterConfig &aConfig)
+{
+    FlagsString flagsString;
+
+    OutputIp6Prefix(aConfig.mPrefix);
+
+    PrefixFlagsToString(aConfig, flagsString);
+
+    if (flagsString[0] != '\0')
     {
         OutputFormat(" %s", flagsString);
     }
 
-    OutputPreference(aConfig.mPreference);
-
-    OutputLine(" %04x", aConfig.mRloc16);
+    OutputLine(" %s %04x", Interpreter::PreferenceToString(aConfig.mPreference), aConfig.mRloc16);
 }
 
-void NetworkData::OutputRoute(const otExternalRouteConfig &aConfig)
+void NetworkData::RouteFlagsToString(const otExternalRouteConfig &aConfig, FlagsString &aString)
 {
-    enum
-    {
-        // ExternalRoute flag is `uint8_t` (though some of the bits are
-        // reserved for future use), so we use 9 chars string (8 flags
-        // plus null char at end of string).
-        kMaxFlagStringSize = 9,
-    };
-
-    char  flagsString[kMaxFlagStringSize];
-    char *flagsPtr = &flagsString[0];
-
-    OutputIp6Prefix(aConfig.mPrefix);
+    char *flagsPtr = &aString[0];
 
     if (aConfig.mStable)
     {
@@ -143,36 +126,22 @@
     }
 
     *flagsPtr = '\0';
+}
 
-    if (flagsPtr != &flagsString[0])
+void NetworkData::OutputRoute(const otExternalRouteConfig &aConfig)
+{
+    FlagsString flagsString;
+
+    OutputIp6Prefix(aConfig.mPrefix);
+
+    RouteFlagsToString(aConfig, flagsString);
+
+    if (flagsString[0] != '\0')
     {
         OutputFormat(" %s", flagsString);
     }
 
-    OutputPreference(aConfig.mPreference);
-
-    OutputLine(" %04x", aConfig.mRloc16);
-}
-
-void NetworkData::OutputPreference(signed int aPreference)
-{
-    switch (aPreference)
-    {
-    case OT_ROUTE_PREFERENCE_LOW:
-        OutputFormat(" low");
-        break;
-
-    case OT_ROUTE_PREFERENCE_MED:
-        OutputFormat(" med");
-        break;
-
-    case OT_ROUTE_PREFERENCE_HIGH:
-        OutputFormat(" high");
-        break;
-
-    default:
-        break;
-    }
+    OutputLine(" %s %04x", Interpreter::PreferenceToString(aConfig.mPreference), aConfig.mRloc16);
 }
 
 void NetworkData::OutputService(const otServiceConfig &aConfig)
@@ -190,26 +159,32 @@
     OutputLine(" %04x", aConfig.mServerConfig.mRloc16);
 }
 
-otError NetworkData::ProcessHelp(Arg aArgs[])
-{
-    OT_UNUSED_VARIABLE(aArgs);
-
-    for (const Command &command : sCommands)
-    {
-        OutputLine(command.mName);
-    }
-
-    return OT_ERROR_NONE;
-}
-
 #if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
-otError NetworkData::ProcessPublish(Arg aArgs[])
+template <> otError NetworkData::Process<Cmd("publish")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
     if (aArgs[0] == "dnssrp")
     {
+        /**
+         * @cli netdata publish dnssrp anycast
+         * @code
+         * netdata publish dnssrp anycast 1
+         * Done
+         * @endcode
+         * @cparam netdata publish dnssrp anycast @ca{seq-num}
+         * @par
+         * Publishes a DNS/SRP Service Anycast Address with a sequence number. Any current
+         * DNS/SRP Service entry being published from a previous `publish dnssrp{anycast|unicast}`
+         * command is removed and replaced with the new arguments.
+         * @par
+         * `OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE` must be enabled.
+         * @csa{netdata publish dnssrp unicast (addr,port)}
+         * @csa{netdata publish dnssrp unicast (mle)}
+         * @sa otNetDataPublishDnsSrpServiceAnycast
+         * @endcli
+         */
         if (aArgs[1] == "anycast")
         {
             uint8_t sequenceNumber;
@@ -224,6 +199,26 @@
             otIp6Address address;
             uint16_t     port;
 
+            /**
+             * @cli netdata publish dnssrp unicast (mle)
+             * @code
+             * netdata publish dnssrp unicast 50152
+             * Done
+             * @endcode
+             * @cparam netdata publish dnssrp unicast @ca{port}
+             * @par
+             * Publishes the device's Mesh-Local EID with a port number. MLE and port information is
+             * included in the Server TLV data. To use a different Unicast address, use the
+             * `netdata publish dnssrp unicast (addr,port)` command.
+             * @par
+             * Any current DNS/SRP Service entry being published from a previous
+             * `publish dnssrp{anycast|unicast}` command is removed and replaced with the new arguments.
+             * @par
+             * `OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE` must be enabled.
+             * @csa{netdata publish dnssrp unicast (addr,port)}
+             * @csa{netdata publish dnssrp anycast}
+             * @sa otNetDataPublishDnsSrpServiceUnicastMeshLocalEid
+             */
             if (aArgs[3].IsEmpty())
             {
                 SuccessOrExit(error = aArgs[2].ParseAsUint16(port));
@@ -231,6 +226,24 @@
                 ExitNow();
             }
 
+            /**
+             * @cli netdata publish dnssrp unicast (addr,port)
+             * @code
+             * netdata publish dnssrp unicast fd00::1234 51525
+             * Done
+             * @endcode
+             * @cparam netdata publish dnssrp unicast @ca{address} @ca{port}
+             * @par
+             * Publishes a DNS/SRP Service Unicast Address with an address and port number. The address
+             * and port information is included in Service TLV data. Any current DNS/SRP Service entry being
+             * published from a previous `publish dnssrp{anycast|unicast}` command is removed and replaced
+             * with the new arguments.
+             * @par
+             * `OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE` must be enabled.
+             * @csa{netdata publish dnssrp unicast (mle)}
+             * @csa{netdata publish dnssrp anycast}
+             * @sa otNetDataPublishDnsSrpServiceUnicast
+             */
             SuccessOrExit(error = aArgs[2].ParseAsIp6Address(address));
             SuccessOrExit(error = aArgs[3].ParseAsUint16(port));
             otNetDataPublishDnsSrpServiceUnicast(GetInstancePtr(), &address, port);
@@ -240,6 +253,18 @@
 #endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
 
 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
+    /**
+     * @cli netdata publish prefix
+     * @code
+     * netdata publish prefix fd00:1234:5678::/64 paos med
+     * Done
+     * @endcode
+     * @cparam netdata publish prefix @ca{prefix} [@ca{padcrosnD}] [@ca{high}|@ca{med}|@ca{low}]
+     * OT CLI uses mapped arguments to configure #otBorderRouterConfig values. @moreinfo{the @overview}.
+     * @par
+     * Publish an on-mesh prefix entry. @moreinfo{@netdata}.
+     * @sa otNetDataPublishOnMeshPrefix
+     */
     if (aArgs[0] == "prefix")
     {
         otBorderRouterConfig config;
@@ -249,6 +274,18 @@
         ExitNow();
     }
 
+    /**
+     * @cli netdata publish route
+     * @code
+     * netdata publish route fd00:1234:5678::/64 s high
+     * Done
+     * @endcode
+     * @cparam publish route @ca{prefix} [@ca{sn}] [@ca{high}|@ca{med}|@ca{low}]
+     * OT CLI uses mapped arguments to configure #otExternalRouteConfig values. @moreinfo{the @overview}.
+     * @par
+     * Publish an external route entry. @moreinfo{@netdata}.
+     * @sa otNetDataPublishExternalRoute
+     */
     if (aArgs[0] == "route")
     {
         otExternalRouteConfig config;
@@ -265,10 +302,19 @@
     return error;
 }
 
-otError NetworkData::ProcessUnpublish(Arg aArgs[])
+template <> otError NetworkData::Process<Cmd("unpublish")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
+/**
+ * @cli netdata unpublish dnssrp
+ * @code
+ * netdata unpublish dnssrp
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otNetDataUnpublishDnsSrpService
+ */
 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
     if (aArgs[0] == "dnssrp")
     {
@@ -277,6 +323,18 @@
     }
 #endif
 
+/**
+ * @cli netdata unpublish (prefix)
+ * @code
+ * netdata unpublish fd00:1234:5678::/64
+ * Done
+ * @endcode
+ * @cparam netdata unpublish @ca{prefix}
+ * @par api_copy
+ * #otNetDataUnpublishPrefix
+ * @par
+ * @moreinfo{@netdata}.
+ */
 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
     {
         otIp6Prefix prefix;
@@ -297,7 +355,23 @@
 #endif // OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
 
 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-otError NetworkData::ProcessRegister(Arg aArgs[])
+/**
+ * @cli netdata register
+ * @code
+ * netdata register
+ * Done
+ * @endcode
+ * @par
+ * Register configured prefixes, routes, and services with the Leader.
+ * @par
+ * OT CLI checks for `OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE`. If OTBR is enabled, it
+ * registers local Network Data with the Leader. Otherwise, it calls the CLI function `otServerRegister`.
+ * @moreinfo{@netdata}.
+ * @csa{prefix add}
+ * @sa otBorderRouterRegister
+ * @sa otServerAddService
+ */
+template <> otError NetworkData::Process<Cmd("register")>(Arg aArgs[])
 {
     OT_UNUSED_VARIABLE(aArgs);
 
@@ -314,7 +388,7 @@
 }
 #endif
 
-otError NetworkData::ProcessSteeringData(Arg aArgs[])
+template <> otError NetworkData::Process<Cmd("steeringdata")>(Arg aArgs[])
 {
     otError           error;
     otExtAddress      addr;
@@ -332,10 +406,38 @@
 
     SuccessOrExit(error);
 
+    /**
+     * @cli netdata steeringdata check (discerner)
+     * @code
+     * netdata steeringdata check 0xabc/12
+     * Done
+     * @endcode
+     * @code
+     * netdata steeringdata check 0xdef/12
+     * Error 23: NotFound
+     * @endcode
+     * @cparam netdata steeringdata check @ca{discerner}
+     * *   `discerner`: The %Joiner discerner in format `{number}/{length}`.
+     * @par api_copy
+     * #otNetDataSteeringDataCheckJoinerWithDiscerner
+     * @csa{joiner discerner}
+     */
     if (discerner.mLength)
     {
         error = otNetDataSteeringDataCheckJoinerWithDiscerner(GetInstancePtr(), &discerner);
     }
+    /**
+     * @cli netdata steeringdata check (eui64)
+     * @code
+     * netdata steeringdata check d45e64fa83f81cf7
+     * Done
+     * @endcode
+     * @cparam netdata steeringdata check @ca{eui64}
+     * *   `eui64`: The IEEE EUI-64 of the %Joiner.
+     * @par api_copy
+     * #otNetDataSteeringDataCheckJoiner
+     * @csa{eui64}
+     */
     else
     {
         error = otNetDataSteeringDataCheckJoiner(GetInstancePtr(), &addr);
@@ -345,52 +447,124 @@
     return error;
 }
 
-void NetworkData::OutputPrefixes(void)
+otError NetworkData::GetNextPrefix(otNetworkDataIterator *aIterator, otBorderRouterConfig *aConfig, bool aLocal)
+{
+    otError error;
+
+    if (aLocal)
+    {
+#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
+        error = otBorderRouterGetNextOnMeshPrefix(GetInstancePtr(), aIterator, aConfig);
+#else
+        error = OT_ERROR_NOT_FOUND;
+#endif
+    }
+    else
+    {
+        error = otNetDataGetNextOnMeshPrefix(GetInstancePtr(), aIterator, aConfig);
+    }
+
+    return error;
+}
+
+void NetworkData::OutputPrefixes(bool aLocal)
 {
     otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
     otBorderRouterConfig  config;
 
     OutputLine("Prefixes:");
 
-    while (otNetDataGetNextOnMeshPrefix(GetInstancePtr(), &iterator, &config) == OT_ERROR_NONE)
+    while (GetNextPrefix(&iterator, &config, aLocal) == OT_ERROR_NONE)
     {
         OutputPrefix(config);
     }
 }
 
-void NetworkData::OutputRoutes(void)
+otError NetworkData::GetNextRoute(otNetworkDataIterator *aIterator, otExternalRouteConfig *aConfig, bool aLocal)
+{
+    otError error;
+
+    if (aLocal)
+    {
+#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
+        error = otBorderRouterGetNextRoute(GetInstancePtr(), aIterator, aConfig);
+#else
+        error = OT_ERROR_NOT_FOUND;
+#endif
+    }
+    else
+    {
+        error = otNetDataGetNextRoute(GetInstancePtr(), aIterator, aConfig);
+    }
+
+    return error;
+}
+
+void NetworkData::OutputRoutes(bool aLocal)
 {
     otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
     otExternalRouteConfig config;
 
     OutputLine("Routes:");
 
-    while (otNetDataGetNextRoute(GetInstancePtr(), &iterator, &config) == OT_ERROR_NONE)
+    while (GetNextRoute(&iterator, &config, aLocal) == OT_ERROR_NONE)
     {
         OutputRoute(config);
     }
 }
 
-void NetworkData::OutputServices(void)
+otError NetworkData::GetNextService(otNetworkDataIterator *aIterator, otServiceConfig *aConfig, bool aLocal)
+{
+    otError error;
+
+    if (aLocal)
+    {
+#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
+        error = otServerGetNextService(GetInstancePtr(), aIterator, aConfig);
+#else
+        error = OT_ERROR_NOT_FOUND;
+#endif
+    }
+    else
+    {
+        error = otNetDataGetNextService(GetInstancePtr(), aIterator, aConfig);
+    }
+
+    return error;
+}
+
+void NetworkData::OutputServices(bool aLocal)
 {
     otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
     otServiceConfig       config;
 
     OutputLine("Services:");
 
-    while (otNetDataGetNextService(GetInstancePtr(), &iterator, &config) == OT_ERROR_NONE)
+    while (GetNextService(&iterator, &config, aLocal) == OT_ERROR_NONE)
     {
         OutputService(config);
     }
 }
 
-otError NetworkData::OutputBinary(void)
+otError NetworkData::OutputBinary(bool aLocal)
 {
-    otError error = OT_ERROR_NONE;
+    otError error;
     uint8_t data[255];
     uint8_t len = sizeof(data);
 
-    SuccessOrExit(error = otNetDataGet(GetInstancePtr(), false, data, &len));
+    if (aLocal)
+    {
+#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
+        error = otBorderRouterGetNetData(GetInstancePtr(), false, data, &len);
+#else
+        error = OT_ERROR_NOT_IMPLEMENTED;
+#endif
+    }
+    else
+    {
+        error = otNetDataGet(GetInstancePtr(), false, data, &len);
+    }
+    SuccessOrExit(error);
 
     OutputBytesLine(data, static_cast<uint8_t>(len));
 
@@ -398,37 +572,146 @@
     return error;
 }
 
-otError NetworkData::ProcessShow(Arg aArgs[])
+/**
+ * @cli netdata show
+ * @code
+ * netdata show
+ * Prefixes:
+ * fd00:dead:beef:cafe::/64 paros med dc00
+ * Routes:
+ * fd49:7770:7fc5:0::/64 s med 4000
+ * Services:
+ * 44970 5d c000 s 4000
+ * 44970 01 9a04b000000e10 s 4000
+ * Done
+ * @endcode
+ * @code
+ * netdata show -x
+ * 08040b02174703140040fd00deadbeefcafe0504dc00330007021140
+ * Done
+ * @endcode
+ * @cparam netdata show [@ca{-x}]
+ * *   The optional `-x` argument gets Network Data as hex-encoded TLVs.
+ * @par
+ * `netdata show` from OT CLI gets full Network Data received from the Leader. This command uses several
+ * API functions to combine prefixes, routes, and services, including #otNetDataGetNextOnMeshPrefix,
+ * #otNetDataGetNextRoute, and #otNetDataGetNextService.
+ * @par
+ * @moreinfo{@netdata}.
+ * @csa{br omrprefix}
+ * @csa{br onlinkprefix}
+ * @sa otBorderRouterGetNetData
+ */
+template <> otError NetworkData::Process<Cmd("show")>(Arg aArgs[])
 {
-    otError error = OT_ERROR_INVALID_ARGS;
+    otError error  = OT_ERROR_INVALID_ARGS;
+    bool    local  = false;
+    bool    binary = false;
 
-    if (aArgs[0].IsEmpty())
+    for (uint8_t i = 0; !aArgs[i].IsEmpty(); i++)
     {
-        OutputPrefixes();
-        OutputRoutes();
-        OutputServices();
+        /**
+         * @cli netdata show local
+         * @code
+         * netdata show local
+         * Prefixes:
+         * fd00:dead:beef:cafe::/64 paros med dc00
+         * Routes:
+         * Services:
+         * Done
+         * @endcode
+         * @code
+         * netdata show local -x
+         * 08040b02174703140040fd00deadbeefcafe0504dc00330007021140
+         * Done
+         * @endcode
+         * @cparam netdata show local [@ca{-x}]
+         * *   The optional `-x` argument gets local Network Data as hex-encoded TLVs.
+         * @par
+         * Print local Network Data to sync with the Leader.
+         * @csa{netdata show}
+         */
+        if (aArgs[i] == "local")
+        {
+            local = true;
+        }
+        else if (aArgs[i] == "-x")
+        {
+            binary = true;
+        }
+        else
+        {
+            ExitNow(error = OT_ERROR_INVALID_ARGS);
+        }
+    }
+
+    if (binary)
+    {
+        error = OutputBinary(local);
+    }
+    else
+    {
+        OutputPrefixes(local);
+        OutputRoutes(local);
+        OutputServices(local);
         error = OT_ERROR_NONE;
     }
-    else if (aArgs[0] == "-x")
-    {
-        error = OutputBinary();
-    }
 
+exit:
     return error;
 }
 
 otError NetworkData::Process(Arg aArgs[])
 {
+#define CmdEntry(aCommandString)                                   \
+    {                                                              \
+        aCommandString, &NetworkData::Process<Cmd(aCommandString)> \
+    }
+
+    static constexpr Command kCommands[] = {
+#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
+        CmdEntry("publish"),
+#endif
+#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
+        CmdEntry("register"),
+#endif
+        CmdEntry("show"),
+        CmdEntry("steeringdata"),
+#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
+        CmdEntry("unpublish"),
+#endif
+    };
+
+#undef CmdEntry
+
+    static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
+
     otError        error = OT_ERROR_INVALID_COMMAND;
     const Command *command;
 
-    if (aArgs[0].IsEmpty())
+    /**
+     * @cli netdata help
+     * @code
+     * netdata help
+     * help
+     * publish
+     * register
+     * show
+     * steeringdata
+     * unpublish
+     * Done
+     * @endcode
+     * @par
+     * Gets a list of `netdata` CLI commands.
+     * @sa @netdata
+     */
+    if (aArgs[0].IsEmpty() || (aArgs[0] == "help"))
     {
-        IgnoreError(ProcessHelp(aArgs));
-        ExitNow();
+        OutputCommandTable(kCommands);
+        ExitNow(error = aArgs[0].IsEmpty() ? error : OT_ERROR_NONE);
     }
 
-    command = Utils::LookupTable::Find(aArgs[0].GetCString(), sCommands);
+    command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
     VerifyOrExit(command != nullptr);
 
     error = (this->*command->mHandler)(aArgs + 1);
diff --git a/src/cli/cli_network_data.hpp b/src/cli/cli_network_data.hpp
index e830455..d46ba9e 100644
--- a/src/cli/cli_network_data.hpp
+++ b/src/cli/cli_network_data.hpp
@@ -39,8 +39,6 @@
 #include <openthread/netdata.h>
 
 #include "cli/cli_output.hpp"
-#include "utils/lookup_table.hpp"
-#include "utils/parse_cmdline.hpp"
 
 namespace ot {
 namespace Cli {
@@ -55,6 +53,18 @@
     typedef Utils::CmdLineParser::Arg Arg;
 
     /**
+     * This constant specifies the string size for representing Network Data prefix/route entry flags.
+     *
+     * BorderRouter (OnMeshPrefix) TLV uses `uint16_t` for its flags and ExternalRoute uses `uint8_t`, though some of
+     * the bits are not currently used and reserved for future, so 17 chars string (16 flags plus null char at end of
+     * string) covers current and future flags.
+     *
+     */
+    static constexpr uint16_t kFlagsStringSize = 17;
+
+    typedef char FlagsString[kFlagsStringSize]; ///< Flags String type (char array of `kFlagsStringSize`).
+
+    /**
      * Constructor
      *
      * @param[in]  aOutput The CLI console output context
@@ -97,46 +107,37 @@
      */
     void OutputService(const otServiceConfig &aConfig);
 
+    /**
+     * This method converts the flags from a given prefix config to string.
+     *
+     * @param[in]  aConfig  The prefix config.
+     * @param[out] aString  The string to populate from @a Config flags.
+     *
+     */
+    static void PrefixFlagsToString(const otBorderRouterConfig &aConfig, FlagsString &aString);
+
+    /**
+     * This method converts the flags from a given route config to string.
+     *
+     * @param[in]  aConfig  The route config.
+     * @param[out] aString  The string to populate from @a Config flags.
+     *
+     */
+    static void RouteFlagsToString(const otExternalRouteConfig &aConfig, FlagsString &aString);
+
 private:
-    struct Command
-    {
-        const char *mName;
-        otError (NetworkData::*mHandler)(Arg aArgs[]);
-    };
+    using Command = CommandEntry<NetworkData>;
 
-    otError ProcessHelp(Arg aArgs[]);
-#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
-    otError ProcessPublish(Arg aArgs[]);
-    otError ProcessUnpublish(Arg aArgs[]);
-#endif
-#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-    otError ProcessRegister(Arg aArgs[]);
-#endif
-    otError ProcessShow(Arg aArgs[]);
-    otError ProcessSteeringData(Arg aArgs[]);
+    template <CommandId kCommandId> otError Process(Arg aArgs[]);
 
-    otError OutputBinary(void);
-    void    OutputPrefixes(void);
-    void    OutputRoutes(void);
-    void    OutputServices(void);
-    void    OutputPreference(signed int aPreference);
+    otError GetNextPrefix(otNetworkDataIterator *aIterator, otBorderRouterConfig *aConfig, bool aLocal);
+    otError GetNextRoute(otNetworkDataIterator *aIterator, otExternalRouteConfig *aConfig, bool aLocal);
+    otError GetNextService(otNetworkDataIterator *aIterator, otServiceConfig *aConfig, bool aLocal);
 
-    static constexpr Command sCommands[] = {
-        {"help", &NetworkData::ProcessHelp},
-#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
-        {"publish", &NetworkData::ProcessPublish},
-#endif
-#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-        {"register", &NetworkData::ProcessRegister},
-#endif
-        {"show", &NetworkData::ProcessShow},
-        {"steeringdata", &NetworkData::ProcessSteeringData},
-#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
-        {"unpublish", &NetworkData::ProcessUnpublish},
-#endif
-    };
-
-    static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
+    otError OutputBinary(bool aLocal);
+    void    OutputPrefixes(bool aLocal);
+    void    OutputRoutes(bool aLocal);
+    void    OutputServices(bool aLocal);
 };
 
 } // namespace Cli
diff --git a/src/cli/cli_output.cpp b/src/cli/cli_output.cpp
index 99a3e6f..bd61c25 100644
--- a/src/cli/cli_output.cpp
+++ b/src/cli/cli_output.cpp
@@ -40,13 +40,15 @@
 #if OPENTHREAD_FTD || OPENTHREAD_MTD
 #include <openthread/dns.h>
 #endif
+#include <openthread/logging.h>
 
-#include "common/logging.hpp"
 #include "common/string.hpp"
 
 namespace ot {
 namespace Cli {
 
+const char OutputBase::kUnknownString[] = "unknown";
+
 Output::Output(otInstance *aInstance, otCliOutputCallback aCallback, void *aCallbackContext)
     : mInstance(aInstance)
     , mCallback(aCallback)
@@ -174,6 +176,21 @@
     OutputLine("");
 }
 
+void Output::OutputSockAddr(const otSockAddr &aSockAddr)
+{
+    char string[OT_IP6_SOCK_ADDR_STRING_SIZE];
+
+    otIp6SockAddrToString(&aSockAddr, string, sizeof(string));
+
+    return OutputFormat("%s", string);
+}
+
+void Output::OutputSockAddrLine(const otSockAddr &aSockAddr)
+{
+    OutputSockAddr(aSockAddr);
+    OutputLine("");
+}
+
 void Output::OutputDnsTxtData(const uint8_t *aTxtData, uint16_t aTxtDataLength)
 {
     otDnsTxtEntry         entry;
@@ -262,7 +279,7 @@
 
         if (lineEnd > mOutputString)
         {
-            otLogNoteCli("Output: %s", mOutputString);
+            otLogCli(OT_LOG_LEVEL_DEBG, "Output: %s", mOutputString);
         }
 
         lineEnd++;
@@ -303,7 +320,7 @@
 
     if (truncated)
     {
-        otLogNoteCli("Output: %s ...", mOutputString);
+        otLogCli(OT_LOG_LEVEL_DEBG, "Output: %s ...", mOutputString);
         mOutputLength = 0;
     }
 
@@ -322,7 +339,7 @@
         inputString.Append(isFirst ? "%s" : " %s", aArgs->GetCString());
     }
 
-    otLogNoteCli("Input: %s", inputString.AsCString());
+    otLogCli(OT_LOG_LEVEL_DEBG, "Input: %s", inputString.AsCString());
 }
 #endif
 
diff --git a/src/cli/cli_output.hpp b/src/cli/cli_output.hpp
index d0f95a6..61e8997 100644
--- a/src/cli/cli_output.hpp
+++ b/src/cli/cli_output.hpp
@@ -41,16 +41,115 @@
 #include <openthread/cli.h>
 
 #include "cli_config.h"
+
+#include "common/binary_search.hpp"
+#include "common/string.hpp"
 #include "utils/parse_cmdline.hpp"
 
 namespace ot {
 namespace Cli {
 
 /**
+ * This type represents a ID number value associated with a CLI command string.
+ *
+ */
+typedef uint64_t CommandId;
+
+/**
+ * This `constexpr` function converts a CLI command string to its associated `CommandId` value.
+ *
+ * @param[in] aString   The CLI command string.
+ *
+ * @returns The associated `CommandId` with @p aString.
+ *
+ */
+constexpr static CommandId Cmd(const char *aString)
+{
+    return (aString[0] == '\0') ? 0 : (static_cast<uint8_t>(aString[0]) + Cmd(aString + 1) * 255u);
+}
+
+/**
+ * This class is the base class for `Output` and `OutputWrapper` providing common helper methods.
+ *
+ */
+class OutputBase
+{
+public:
+    typedef Utils::CmdLineParser::Arg Arg; ///< An argument
+
+    /**
+     * This structure represent a CLI command table entry, mapping a command with `aName` to a handler method.
+     *
+     * @tparam Cli    The CLI module type.
+     *
+     */
+    template <typename Cli> struct CommandEntry
+    {
+        typedef otError (Cli::*Handler)(Arg aArgs[]); ///< The handler method pointer type.
+
+        /**
+         * This method compares the entry's name with a given name.
+         *
+         * @param aName    The name string to compare with.
+         *
+         * @return zero means perfect match, positive (> 0) indicates @p aName is larger than entry's name, and
+         *         negative (< 0) indicates @p aName is smaller than entry's name.
+         *
+         */
+        int Compare(const char *aName) const { return strcmp(aName, mName); }
+
+        /**
+         * This `constexpr` method compares two entries to check if they are in order.
+         *
+         * @param[in] aFirst     The first entry.
+         * @param[in] aSecond    The second entry.
+         *
+         * @retval TRUE  if @p aFirst and @p aSecond are in order, i.e. `aFirst < aSecond`.
+         * @retval FALSE if @p aFirst and @p aSecond are not in order, i.e. `aFirst >= aSecond`.
+         *
+         */
+        constexpr static bool AreInOrder(const CommandEntry &aFirst, const CommandEntry &aSecond)
+        {
+            return AreStringsInOrder(aFirst.mName, aSecond.mName);
+        }
+
+        const char *mName;    ///< The command name.
+        Handler     mHandler; ///< The handler method pointer.
+    };
+
+    static const char kUnknownString[]; // Constant string "unknown".
+
+    /**
+     * This template static method converts an enumeration value to a string using a table array.
+     *
+     * @tparam EnumType       The `enum` type.
+     * @tparam kLength        The table array length (number of entries in the array).
+     *
+     * @param[in] aEnum       The enumeration value to convert (MUST be of `EnumType`).
+     * @param[in] aTable      A reference to the array of strings of length @p kLength. `aTable[e]` is the string
+     *                        representation of enumeration value `e`.
+     * @param[in] aNotFound   The string to return if the @p aEnum is not in the @p aTable.
+     *
+     * @returns The string representation of @p aEnum from @p aTable, or @p aNotFound if it is not in the table.
+     *
+     */
+    template <typename EnumType, uint16_t kLength>
+    static const char *Stringify(EnumType aEnum,
+                                 const char *const (&aTable)[kLength],
+                                 const char *aNotFound = kUnknownString)
+    {
+        return (static_cast<uint16_t>(aEnum) < kLength) ? aTable[static_cast<uint16_t>(aEnum)] : aNotFound;
+    }
+
+protected:
+    OutputBase(void) = default;
+};
+
+/**
  * This class provides CLI output helper methods.
  *
  */
-class Output
+class Output : public OutputBase
 {
 public:
     /**
@@ -240,6 +339,22 @@
     void OutputIp6PrefixLine(const otIp6NetworkPrefix &aPrefix);
 
     /**
+     * This method outputs an IPv6 socket address to the CLI console.
+     *
+     * @param[in] aSockAddr   A reference to the IPv6 socket address.
+     *
+     */
+    void OutputSockAddr(const otSockAddr &aSockAddr);
+
+    /**
+     * This method outputs an IPv6 socket address to the CLI console and at the end it also outputs newline "\r\n".
+     *
+     * @param[in] aSockAddr   A reference to the IPv6 socket address.
+     *
+     */
+    void OutputSockAddrLine(const otSockAddr &aSockAddr);
+
+    /**
      * This method outputs DNS TXT data to the CLI console.
      *
      * @param[in] aTxtData        A pointer to a buffer containing the DNS TXT data.
@@ -264,7 +379,7 @@
      * @tparam kTableNumColumns   The number columns in the table.
      *
      * @param[in] aTitles   An array specifying the table column titles.
-     * @param[in] aWidth    An array specifying the table column widths (in number of chars).
+     * @param[in] aWidths   An array specifying the table column widths (in number of chars).
      *
      */
     template <uint8_t kTableNumColumns>
@@ -284,7 +399,7 @@
      *
      * @tparam kTableNumColumns   The number columns in the table.
      *
-     * @param[in] aWidth    An array specifying the table column widths (in number of chars).
+     * @param[in] aWidths   An array specifying the table column widths (in number of chars).
      *
      */
     template <uint8_t kTableNumColumns> void OutputTableSeparator(const uint8_t (&aWidths)[kTableNumColumns])
@@ -292,9 +407,24 @@
         OutputTableSeparator(kTableNumColumns, &aWidths[0]);
     }
 
-protected:
-    typedef Utils::CmdLineParser::Arg Arg;
+    /**
+     * This method outputs the list of commands from a given command table.
+     *
+     * @tparam Cli      The CLI module type.
+     * @tparam kLength  The length of command table array.
+     *
+     * @param[in] aCommandTable   The command table array.
+     *
+     */
+    template <typename Cli, uint16_t kLength> void OutputCommandTable(const CommandEntry<Cli> (&aCommandTable)[kLength])
+    {
+        for (const CommandEntry<Cli> &entry : aCommandTable)
+        {
+            OutputLine("%s", entry.mName);
+        }
+    }
 
+protected:
     void OutputFormatV(const char *aFormat, va_list aArguments);
 
 #if OPENTHREAD_CONFIG_CLI_LOG_INPUT_OUTPUT_ENABLE
@@ -321,7 +451,7 @@
 #endif
 };
 
-class OutputWrapper
+class OutputWrapper : public OutputBase
 {
 protected:
     explicit OutputWrapper(Output &aOutput)
@@ -375,6 +505,8 @@
     void OutputIp6PrefixLine(const otIp6Prefix &aPrefix) { mOutput.OutputIp6PrefixLine(aPrefix); }
     void OutputIp6Prefix(const otIp6NetworkPrefix &aPrefix) { mOutput.OutputIp6Prefix(aPrefix); }
     void OutputIp6PrefixLine(const otIp6NetworkPrefix &aPrefix) { mOutput.OutputIp6PrefixLine(aPrefix); }
+    void OutputSockAddr(const otSockAddr &aSockAddr) { mOutput.OutputSockAddr(aSockAddr); }
+    void OutputSockAddrLine(const otSockAddr &aSockAddr) { mOutput.OutputSockAddrLine(aSockAddr); }
     void OutputDnsTxtData(const uint8_t *aTxtData, uint16_t aTxtDataLength)
     {
         mOutput.OutputDnsTxtData(aTxtData, aTxtDataLength);
@@ -392,6 +524,11 @@
         mOutput.OutputTableSeparator(aWidths);
     }
 
+    template <typename Cli, uint16_t kLength> void OutputCommandTable(const CommandEntry<Cli> (&aCommandTable)[kLength])
+    {
+        mOutput.OutputCommandTable(aCommandTable);
+    }
+
 private:
     Output &mOutput;
 };
diff --git a/src/cli/cli_srp_client.cpp b/src/cli/cli_srp_client.cpp
index 980e743..0732ac2 100644
--- a/src/cli/cli_srp_client.cpp
+++ b/src/cli/cli_srp_client.cpp
@@ -42,8 +42,6 @@
 namespace ot {
 namespace Cli {
 
-constexpr SrpClient::Command SrpClient::sCommands[];
-
 static otError CopyString(char *aDest, uint16_t aDestSize, const char *aSource)
 {
     // Copies a string from `aSource` to `aDestination` (char array),
@@ -66,29 +64,9 @@
     otSrpClientSetCallback(GetInstancePtr(), SrpClient::HandleCallback, this);
 }
 
-otError SrpClient::Process(Arg aArgs[])
-{
-    otError        error = OT_ERROR_INVALID_COMMAND;
-    const Command *command;
-
-    if (aArgs[0].IsEmpty())
-    {
-        IgnoreError(ProcessHelp(aArgs));
-        ExitNow();
-    }
-
-    command = Utils::LookupTable::Find(aArgs[0].GetCString(), sCommands);
-    VerifyOrExit(command != nullptr);
-
-    error = (this->*command->mHandler)(aArgs + 1);
-
-exit:
-    return error;
-}
-
 #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
 
-otError SrpClient::ProcessAutoStart(Arg aArgs[])
+template <> otError SrpClient::Process<Cmd("autostart")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
     bool    enable;
@@ -116,7 +94,7 @@
 
 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
 
-otError SrpClient::ProcessCallback(Arg aArgs[])
+template <> otError SrpClient::Process<Cmd("callback")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -132,29 +110,15 @@
     return error;
 }
 
-otError SrpClient::ProcessHelp(Arg aArgs[])
-{
-    OT_UNUSED_VARIABLE(aArgs);
-
-    for (const Command &command : sCommands)
-    {
-        OutputLine(command.mName);
-    }
-
-    return OT_ERROR_NONE;
-}
-
-otError SrpClient::ProcessHost(Arg aArgs[])
+template <> otError SrpClient::Process<Cmd("host")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
     if (aArgs[0].IsEmpty())
     {
         OutputHostInfo(0, *otSrpClientGetHostInfo(GetInstancePtr()));
-        ExitNow();
     }
-
-    if (aArgs[0] == "name")
+    else if (aArgs[0] == "name")
     {
         if (aArgs[1].IsEmpty())
         {
@@ -196,10 +160,21 @@
         {
             const otSrpClientHostInfo *hostInfo = otSrpClientGetHostInfo(GetInstancePtr());
 
-            for (uint8_t index = 0; index < hostInfo->mNumAddresses; index++)
+            if (hostInfo->mAutoAddress)
             {
-                OutputIp6AddressLine(hostInfo->mAddresses[index]);
+                OutputLine("auto");
             }
+            else
+            {
+                for (uint8_t index = 0; index < hostInfo->mNumAddresses; index++)
+                {
+                    OutputIp6AddressLine(hostInfo->mAddresses[index]);
+                }
+            }
+        }
+        else if (aArgs[1] == "auto")
+        {
+            error = otSrpClientEnableAutoHostAddress(GetInstancePtr());
         }
         else
         {
@@ -267,28 +242,25 @@
     return error;
 }
 
-otError SrpClient::ProcessLeaseInterval(Arg aArgs[])
+template <> otError SrpClient::Process<Cmd("leaseinterval")>(Arg aArgs[])
 {
     return Interpreter::GetInterpreter().ProcessGetSet(aArgs, otSrpClientGetLeaseInterval, otSrpClientSetLeaseInterval);
 }
 
-otError SrpClient::ProcessKeyLeaseInterval(Arg aArgs[])
+template <> otError SrpClient::Process<Cmd("keyleaseinterval")>(Arg aArgs[])
 {
     return Interpreter::GetInterpreter().ProcessGetSet(aArgs, otSrpClientGetKeyLeaseInterval,
                                                        otSrpClientSetKeyLeaseInterval);
 }
 
-otError SrpClient::ProcessServer(Arg aArgs[])
+template <> otError SrpClient::Process<Cmd("server")>(Arg aArgs[])
 {
     otError           error          = OT_ERROR_NONE;
     const otSockAddr *serverSockAddr = otSrpClientGetServerAddress(GetInstancePtr());
 
     if (aArgs[0].IsEmpty())
     {
-        char string[OT_IP6_SOCK_ADDR_STRING_SIZE];
-
-        otIp6SockAddrToString(serverSockAddr, string, sizeof(string));
-        OutputLine(string);
+        OutputSockAddrLine(*serverSockAddr);
         ExitNow();
     }
 
@@ -311,7 +283,7 @@
     return error;
 }
 
-otError SrpClient::ProcessService(Arg aArgs[])
+template <> otError SrpClient::Process<Cmd("service")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
     bool    isRemove;
@@ -319,10 +291,8 @@
     if (aArgs[0].IsEmpty())
     {
         OutputServiceList(0, otSrpClientGetServices(GetInstancePtr()));
-        ExitNow();
     }
-
-    if (aArgs[0] == "add")
+    else if (aArgs[0] == "add")
     {
         error = ProcessServiceAdd(aArgs);
     }
@@ -488,19 +458,28 @@
         OutputFormat("(null)");
     }
 
-    OutputFormat(", state:%s, addrs:[", otSrpClientItemStateToString(aHostInfo.mState));
+    OutputFormat(", state:%s, addrs:", otSrpClientItemStateToString(aHostInfo.mState));
 
-    for (uint8_t index = 0; index < aHostInfo.mNumAddresses; index++)
+    if (aHostInfo.mAutoAddress)
     {
-        if (index > 0)
+        OutputLine("auto");
+    }
+    else
+    {
+        OutputFormat("[");
+
+        for (uint8_t index = 0; index < aHostInfo.mNumAddresses; index++)
         {
-            OutputFormat(", ");
+            if (index > 0)
+            {
+                OutputFormat(", ");
+            }
+
+            OutputIp6Address(aHostInfo.mAddresses[index]);
         }
 
-        OutputIp6Address(aHostInfo.mAddresses[index]);
+        OutputLine("]");
     }
-
-    OutputLine("]");
 }
 
 void SrpClient::OutputServiceList(uint8_t aIndentSize, const otSrpClientService *aServices)
@@ -528,7 +507,7 @@
                aService.mPort, aService.mPriority, aService.mWeight);
 }
 
-otError SrpClient::ProcessStart(Arg aArgs[])
+template <> otError SrpClient::Process<Cmd("start")>(Arg aArgs[])
 {
     otError    error = OT_ERROR_NONE;
     otSockAddr serverSockAddr;
@@ -543,7 +522,7 @@
     return error;
 }
 
-otError SrpClient::ProcessState(Arg aArgs[])
+template <> otError SrpClient::Process<Cmd("state")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -555,7 +534,7 @@
     return error;
 }
 
-otError SrpClient::ProcessStop(Arg aArgs[])
+template <> otError SrpClient::Process<Cmd("stop")>(Arg aArgs[])
 {
     otError error = OT_ERROR_NONE;
 
@@ -566,6 +545,11 @@
     return error;
 }
 
+template <> otError SrpClient::Process<Cmd("ttl")>(Arg aArgs[])
+{
+    return Interpreter::GetInterpreter().ProcessGetSet(aArgs, otSrpClientGetTtl, otSrpClientSetTtl);
+}
+
 void SrpClient::HandleCallback(otError                    aError,
                                const otSrpClientHostInfo *aHostInfo,
                                const otSrpClientService * aServices,
@@ -609,6 +593,39 @@
     }
 }
 
+otError SrpClient::Process(Arg aArgs[])
+{
+#define CmdEntry(aCommandString)                                 \
+    {                                                            \
+        aCommandString, &SrpClient::Process<Cmd(aCommandString)> \
+    }
+
+    static constexpr Command kCommands[] = {
+        CmdEntry("autostart"),     CmdEntry("callback"), CmdEntry("host"),    CmdEntry("keyleaseinterval"),
+        CmdEntry("leaseinterval"), CmdEntry("server"),   CmdEntry("service"), CmdEntry("start"),
+        CmdEntry("state"),         CmdEntry("stop"),     CmdEntry("ttl"),
+    };
+
+    static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
+
+    otError        error = OT_ERROR_INVALID_COMMAND;
+    const Command *command;
+
+    if (aArgs[0].IsEmpty() || (aArgs[0] == "help"))
+    {
+        OutputCommandTable(kCommands);
+        ExitNow(error = aArgs[0].IsEmpty() ? error : OT_ERROR_NONE);
+    }
+
+    command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
+    VerifyOrExit(command != nullptr);
+
+    error = (this->*command->mHandler)(aArgs + 1);
+
+exit:
+    return error;
+}
+
 } // namespace Cli
 } // namespace ot
 
diff --git a/src/cli/cli_srp_client.hpp b/src/cli/cli_srp_client.hpp
index deafedd..b868e6f 100644
--- a/src/cli/cli_srp_client.hpp
+++ b/src/cli/cli_srp_client.hpp
@@ -41,8 +41,6 @@
 
 #include "cli/cli_config.h"
 #include "cli/cli_output.hpp"
-#include "utils/lookup_table.hpp"
-#include "utils/parse_cmdline.hpp"
 
 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
 
@@ -81,24 +79,11 @@
         kIndentSize       = 4,
     };
 
-    struct Command
-    {
-        const char *mName;
-        otError (SrpClient::*mHandler)(Arg aArgs[]);
-    };
+    using Command = CommandEntry<SrpClient>;
 
-    otError ProcessAutoStart(Arg aArgs[]);
-    otError ProcessCallback(Arg aArgs[]);
-    otError ProcessHelp(Arg aArgs[]);
-    otError ProcessHost(Arg aArgs[]);
-    otError ProcessLeaseInterval(Arg aArgs[]);
-    otError ProcessKeyLeaseInterval(Arg aArgs[]);
-    otError ProcessServer(Arg aArgs[]);
-    otError ProcessService(Arg aArgs[]);
+    template <CommandId kCommandId> otError Process(Arg aArgs[]);
+
     otError ProcessServiceAdd(Arg aArgs[]);
-    otError ProcessStart(Arg aArgs[]);
-    otError ProcessState(Arg aArgs[]);
-    otError ProcessStop(Arg aArgs[]);
 
     void OutputHostInfo(uint8_t aIndentSize, const otSrpClientHostInfo &aHostInfo);
     void OutputServiceList(uint8_t aIndentSize, const otSrpClientService *aServices);
@@ -114,22 +99,6 @@
                                const otSrpClientService * aServices,
                                const otSrpClientService * aRemovedServices);
 
-    static constexpr Command sCommands[] = {
-        {"autostart", &SrpClient::ProcessAutoStart},
-        {"callback", &SrpClient::ProcessCallback},
-        {"help", &SrpClient::ProcessHelp},
-        {"host", &SrpClient::ProcessHost},
-        {"keyleaseinterval", &SrpClient::ProcessKeyLeaseInterval},
-        {"leaseinterval", &SrpClient::ProcessLeaseInterval},
-        {"server", &SrpClient::ProcessServer},
-        {"service", &SrpClient::ProcessService},
-        {"start", &SrpClient::ProcessStart},
-        {"state", &SrpClient::ProcessState},
-        {"stop", &SrpClient::ProcessStop},
-    };
-
-    static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
-
     bool mCallbackEnabled;
 };
 
diff --git a/src/cli/cli_srp_server.cpp b/src/cli/cli_srp_server.cpp
index 9120a29..e13b8ec 100644
--- a/src/cli/cli_srp_server.cpp
+++ b/src/cli/cli_srp_server.cpp
@@ -56,7 +56,7 @@
         ExitNow();
     }
 
-    command = Utils::LookupTable::Find(aArgs[0].GetCString(), sCommands);
+    command = BinarySearch::Find(aArgs[0].GetCString(), sCommands);
     VerifyOrExit(command != nullptr);
 
     error = (this->*command->mHandler)(aArgs + 1);
@@ -114,23 +114,19 @@
 
 otError SrpServer::ProcessState(Arg aArgs[])
 {
+    static const char *const kStateStrings[] = {
+        "disabled", // (0) OT_SRP_SERVER_STATE_DISABLED
+        "running",  // (1) OT_SRP_SERVER_STATE_RUNNING
+        "stopped",  // (2) OT_SRP_SERVER_STATE_STOPPED
+    };
+
     OT_UNUSED_VARIABLE(aArgs);
 
-    switch (otSrpServerGetState(GetInstancePtr()))
-    {
-    case OT_SRP_SERVER_STATE_DISABLED:
-        OutputLine("disabled");
-        break;
-    case OT_SRP_SERVER_STATE_RUNNING:
-        OutputLine("running");
-        break;
-    case OT_SRP_SERVER_STATE_STOPPED:
-        OutputLine("stopped");
-        break;
-    default:
-        OutputLine("invalid state");
-        break;
-    }
+    static_assert(0 == OT_SRP_SERVER_STATE_DISABLED, "OT_SRP_SERVER_STATE_DISABLED value is incorrect");
+    static_assert(1 == OT_SRP_SERVER_STATE_RUNNING, "OT_SRP_SERVER_STATE_RUNNING value is incorrect");
+    static_assert(2 == OT_SRP_SERVER_STATE_STOPPED, "OT_SRP_SERVER_STATE_STOPPED value is incorrect");
+
+    OutputLine("%s", Stringify(otSrpServerGetState(GetInstancePtr()), kStateStrings));
 
     return OT_ERROR_NONE;
 }
@@ -153,6 +149,30 @@
     return OT_ERROR_NONE;
 }
 
+otError SrpServer::ProcessTtl(Arg aArgs[])
+{
+    otError              error = OT_ERROR_NONE;
+    otSrpServerTtlConfig ttlConfig;
+
+    if (aArgs[0].IsEmpty())
+    {
+        otSrpServerGetTtlConfig(GetInstancePtr(), &ttlConfig);
+        OutputLine("min ttl: %u", ttlConfig.mMinTtl);
+        OutputLine("max ttl: %u", ttlConfig.mMaxTtl);
+    }
+    else
+    {
+        SuccessOrExit(error = aArgs[0].ParseAsUint32(ttlConfig.mMinTtl));
+        SuccessOrExit(error = aArgs[1].ParseAsUint32(ttlConfig.mMaxTtl));
+        VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+
+        error = otSrpServerSetTtlConfig(GetInstancePtr(), &ttlConfig);
+    }
+
+exit:
+    return error;
+}
+
 otError SrpServer::ProcessLease(Arg aArgs[])
 {
     otError                error = OT_ERROR_NONE;
@@ -216,7 +236,7 @@
             }
         }
 
-        OutputFormat("]\r\n");
+        OutputLine("]");
     }
 
 exit:
@@ -293,6 +313,7 @@
             OutputLine(kIndentSize, "port: %hu", otSrpServerServiceGetPort(service));
             OutputLine(kIndentSize, "priority: %hu", otSrpServerServiceGetPriority(service));
             OutputLine(kIndentSize, "weight: %hu", otSrpServerServiceGetWeight(service));
+            OutputLine(kIndentSize, "ttl: %hu", otSrpServerServiceGetTtl(service));
 
             txtData = otSrpServerServiceGetTxtData(service, &txtDataLength);
             OutputFormat(kIndentSize, "TXT: ");
diff --git a/src/cli/cli_srp_server.hpp b/src/cli/cli_srp_server.hpp
index 60e9f9b..363f591 100644
--- a/src/cli/cli_srp_server.hpp
+++ b/src/cli/cli_srp_server.hpp
@@ -39,8 +39,6 @@
 #include <openthread/srp_server.h>
 
 #include "cli/cli_output.hpp"
-#include "utils/lookup_table.hpp"
-#include "utils/parse_cmdline.hpp"
 
 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
 
@@ -81,11 +79,7 @@
 private:
     static constexpr uint8_t kIndentSize = 4;
 
-    struct Command
-    {
-        const char *mName;
-        otError (SrpServer::*mHandler)(Arg aArgs[]);
-    };
+    using Command = CommandEntry<SrpServer>;
 
     otError ProcessAddrMode(Arg aArgs[]);
     otError ProcessDomain(Arg aArgs[]);
@@ -96,6 +90,7 @@
     otError ProcessHost(Arg aArgs[]);
     otError ProcessService(Arg aArgs[]);
     otError ProcessSeqNum(Arg aArgs[]);
+    otError ProcessTtl(Arg aArgs[]);
     otError ProcessHelp(Arg aArgs[]);
 
     void OutputHostAddresses(const otSrpServerHost *aHost);
@@ -106,9 +101,10 @@
         {"help", &SrpServer::ProcessHelp},         {"host", &SrpServer::ProcessHost},
         {"lease", &SrpServer::ProcessLease},       {"seqnum", &SrpServer::ProcessSeqNum},
         {"service", &SrpServer::ProcessService},   {"state", &SrpServer::ProcessState},
+        {"ttl", &SrpServer::ProcessTtl},
     };
 
-    static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
+    static_assert(BinarySearch::IsSorted(sCommands), "Command Table is not sorted");
 };
 
 } // namespace Cli
diff --git a/src/cli/cli_tcp.cpp b/src/cli/cli_tcp.cpp
index d16e63a..97076e9 100644
--- a/src/cli/cli_tcp.cpp
+++ b/src/cli/cli_tcp.cpp
@@ -322,7 +322,7 @@
 
     VerifyOrExit(!aArgs[0].IsEmpty(), IgnoreError(ProcessHelp(nullptr)));
 
-    command = Utils::LookupTable::Find(aArgs[0].GetCString(), sCommands);
+    command = BinarySearch::Find(aArgs[0].GetCString(), sCommands);
     VerifyOrExit(command != nullptr, error = OT_ERROR_INVALID_COMMAND);
 
     error = (this->*command->mHandler)(aArgs + 1);
@@ -448,26 +448,23 @@
 
 void TcpExample::HandleTcpDisconnected(otTcpEndpoint *aEndpoint, otTcpDisconnectedReason aReason)
 {
+    static const char *const kReasonStrings[] = {
+        "Disconnected",            // (0) OT_TCP_DISCONNECTED_REASON_NORMAL
+        "Connection refused",      // (1) OT_TCP_DISCONNECTED_REASON_REFUSED
+        "Connection reset",        // (2) OT_TCP_DISCONNECTED_REASON_RESET
+        "Entered TIME-WAIT state", // (3) OT_TCP_DISCONNECTED_REASON_TIME_WAIT
+        "Connection timed out",    // (4) OT_TCP_DISCONNECTED_REASON_TIMED_OUT
+    };
+
     OT_UNUSED_VARIABLE(aEndpoint);
 
-    switch (aReason)
-    {
-    case OT_TCP_DISCONNECTED_REASON_NORMAL:
-        OutputLine("TCP: Disconnected");
-        break;
-    case OT_TCP_DISCONNECTED_REASON_TIME_WAIT:
-        OutputLine("TCP: Entered TIME-WAIT state");
-        break;
-    case OT_TCP_DISCONNECTED_REASON_TIMED_OUT:
-        OutputLine("TCP: Connection timed out");
-        break;
-    case OT_TCP_DISCONNECTED_REASON_REFUSED:
-        OutputLine("TCP: Connection refused");
-        break;
-    case OT_TCP_DISCONNECTED_REASON_RESET:
-        OutputLine("TCP: Connection reset");
-        break;
-    }
+    static_assert(0 == OT_TCP_DISCONNECTED_REASON_NORMAL, "OT_TCP_DISCONNECTED_REASON_NORMAL value is incorrect");
+    static_assert(1 == OT_TCP_DISCONNECTED_REASON_REFUSED, "OT_TCP_DISCONNECTED_REASON_REFUSED value is incorrect");
+    static_assert(2 == OT_TCP_DISCONNECTED_REASON_RESET, "OT_TCP_DISCONNECTED_REASON_RESET value is incorrect");
+    static_assert(3 == OT_TCP_DISCONNECTED_REASON_TIME_WAIT, "OT_TCP_DISCONNECTED_REASON_TIME_WAIT value is incorrect");
+    static_assert(4 == OT_TCP_DISCONNECTED_REASON_TIMED_OUT, "OT_TCP_DISCONNECTED_REASON_TIMED_OUT value is incorrect");
+
+    OutputLine("TCP: %s", Stringify(aReason, kReasonStrings));
 
     // We set this to false even for the TIME-WAIT state, so that we can reuse
     // the active socket if an incoming connection comes in instead of waiting
@@ -475,7 +472,7 @@
     mEndpointConnected = false;
     mSendBusy          = false;
 
-    // Mark the benchmark as inactive if the connction was disconnected.
+    // Mark the benchmark as inactive if the connection was disconnected.
     if (mBenchmarkBytesTotal != 0)
     {
         mBenchmarkBytesTotal = 0;
@@ -491,9 +488,9 @@
 
     if (mEndpointConnected)
     {
-        OutputFormat("TCP: Ignoring incoming connection request from [");
-        OutputIp6Address(aPeer->mAddress);
-        OutputLine("]:%u (active socket is busy)", static_cast<unsigned int>(aPeer->mPort));
+        OutputFormat("TCP: Ignoring incoming connection request from ");
+        OutputSockAddr(*aPeer);
+        OutputLine(" (active socket is busy)");
 
         return OT_TCP_INCOMING_CONNECTION_ACTION_DEFER;
     }
@@ -507,9 +504,8 @@
     OT_UNUSED_VARIABLE(aListener);
     OT_UNUSED_VARIABLE(aEndpoint);
 
-    OutputFormat("Accepted connection from [");
-    OutputIp6Address(aPeer->mAddress);
-    OutputLine("]:%u", static_cast<unsigned int>(aPeer->mPort));
+    OutputFormat("Accepted connection from ");
+    OutputSockAddrLine(*aPeer);
 }
 
 } // namespace Cli
diff --git a/src/cli/cli_tcp.hpp b/src/cli/cli_tcp.hpp
index 7972b61..4bebc96 100644
--- a/src/cli/cli_tcp.hpp
+++ b/src/cli/cli_tcp.hpp
@@ -41,8 +41,6 @@
 #include "cli/cli_config.h"
 #include "cli/cli_output.hpp"
 #include "common/time.hpp"
-#include "utils/lookup_table.hpp"
-#include "utils/parse_cmdline.hpp"
 
 namespace ot {
 namespace Cli {
@@ -73,11 +71,7 @@
     otError Process(Arg aArgs[]);
 
 private:
-    struct Command
-    {
-        const char *mName;
-        otError (TcpExample::*mHandler)(Arg aArgs[]);
-    };
+    using Command = CommandEntry<TcpExample>;
 
     otError ProcessHelp(Arg aArgs[]);
     otError ProcessInit(Arg aArgs[]);
@@ -131,7 +125,7 @@
         {"stoplistening", &TcpExample::ProcessStopListening},
     };
 
-    static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
+    static_assert(BinarySearch::IsSorted(sCommands), "Command Table is not sorted");
 
     otTcpEndpoint mEndpoint;
     otTcpListener mListener;
diff --git a/src/cli/cli_udp.cpp b/src/cli/cli_udp.cpp
index 06ae961..62ad057 100644
--- a/src/cli/cli_udp.cpp
+++ b/src/cli/cli_udp.cpp
@@ -277,7 +277,7 @@
         ExitNow();
     }
 
-    command = Utils::LookupTable::Find(aArgs[0].GetCString(), sCommands);
+    command = BinarySearch::Find(aArgs[0].GetCString(), sCommands);
     VerifyOrExit(command != nullptr, error = OT_ERROR_INVALID_COMMAND);
 
     error = (this->*command->mHandler)(aArgs + 1);
diff --git a/src/cli/cli_udp.hpp b/src/cli/cli_udp.hpp
index 85a4ba1..bd8ba54 100644
--- a/src/cli/cli_udp.hpp
+++ b/src/cli/cli_udp.hpp
@@ -39,8 +39,6 @@
 #include <openthread/udp.h>
 
 #include "cli/cli_output.hpp"
-#include "utils/lookup_table.hpp"
-#include "utils/parse_cmdline.hpp"
 
 namespace ot {
 namespace Cli {
@@ -57,7 +55,7 @@
     /**
      * Constructor
      *
-     * @param[in]  aOutputContext The CLI console output context.
+     * @param[in]  aOutput The CLI console output context.
      *
      */
     explicit UdpExample(Output &aOutput);
@@ -71,11 +69,7 @@
     otError Process(Arg aArgs[]);
 
 private:
-    struct Command
-    {
-        const char *mName;
-        otError (UdpExample::*mHandler)(Arg aArgs[]);
-    };
+    using Command = CommandEntry<UdpExample>;
 
     otError ProcessHelp(Arg aArgs[]);
     otError ProcessBind(Arg aArgs[]);
@@ -101,7 +95,7 @@
         {"send", &UdpExample::ProcessSend},
     };
 
-    static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
+    static_assert(BinarySearch::IsSorted(sCommands), "Command Table is not sorted");
 
     bool        mLinkSecurityEnabled;
     otUdpSocket mSocket;
diff --git a/src/cli/radio.cmake b/src/cli/radio.cmake
index 9b69a9e..3e7354a 100644
--- a/src/cli/radio.cmake
+++ b/src/cli/radio.cmake
@@ -46,10 +46,14 @@
         cli_output.cpp
 )
 
+if(NOT DEFINED OT_MBEDTLS_RCP)
+    set(OT_MBEDTLS_RCP ${OT_MBEDTLS})
+endif()
+
 target_link_libraries(openthread-cli-radio
     PUBLIC
         openthread-radio
     PRIVATE
-        ${OT_MBEDTLS}
+        ${OT_MBEDTLS_RCP}
         ot-config
 )
diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn
index 0a44232..299059f 100644
--- a/src/core/BUILD.gn
+++ b/src/core/BUILD.gn
@@ -37,6 +37,8 @@
       defines += [ "OPENTHREAD_CONFIG_THREAD_VERSION=OT_THREAD_VERSION_1_1" ]
     } else if (openthread_config_thread_version == "1.2") {
       defines += [ "OPENTHREAD_CONFIG_THREAD_VERSION=OT_THREAD_VERSION_1_2" ]
+    } else if (openthread_config_thread_version == "1.3") {
+      defines += [ "OPENTHREAD_CONFIG_THREAD_VERSION=OT_THREAD_VERSION_1_3" ]
     } else if (openthread_config_thread_version != "") {
       assert(false,
              "Unrecognized Thread version: ${openthread_config_thread_version}")
@@ -259,12 +261,15 @@
     if (openthread_config_full_logs) {
       defines += [ "OPENTHREAD_CONFIG_LOG_LEVEL=OT_LOG_LEVEL_DEBG" ]
       defines += [ "OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL=1" ]
-      defines += [ "OPENTHREAD_CONFIG_LOG_PREPEND_REGION=1" ]
     }
 
     if (openthread_config_otns_enable) {
       defines += [ "OPENTHREAD_CONFIG_OTNS_ENABLE=1" ]
     }
+
+    if (openthread_config_coexistence_enable) {
+      defines += [ "OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE=1" ]
+    }
   }
 }
 
@@ -303,6 +308,7 @@
   "api/backbone_router_ftd_api.cpp",
   "api/border_agent_api.cpp",
   "api/border_router_api.cpp",
+  "api/border_routing_api.cpp",
   "api/channel_manager_api.cpp",
   "api/channel_monitor_api.cpp",
   "api/child_supervision_api.cpp",
@@ -316,7 +322,6 @@
   "api/diags_api.cpp",
   "api/dns_api.cpp",
   "api/dns_server_api.cpp",
-  "api/entropy_api.cpp",
   "api/error_api.cpp",
   "api/heap_api.cpp",
   "api/history_tracker_api.cpp",
@@ -347,6 +352,7 @@
   "api/tcp_api.cpp",
   "api/thread_api.cpp",
   "api/thread_ftd_api.cpp",
+  "api/trel_api.cpp",
   "api/udp_api.cpp",
   "backbone_router/backbone_tmf.cpp",
   "backbone_router/backbone_tmf.hpp",
@@ -360,9 +366,8 @@
   "backbone_router/multicast_listeners_table.hpp",
   "backbone_router/ndproxy_table.cpp",
   "backbone_router/ndproxy_table.hpp",
-  "border_router/infra_if_platform.cpp",
-  "border_router/router_advertisement.cpp",
-  "border_router/router_advertisement.hpp",
+  "border_router/infra_if.cpp",
+  "border_router/infra_if.hpp",
   "border_router/routing_manager.cpp",
   "border_router/routing_manager.hpp",
   "coap/coap.cpp",
@@ -371,15 +376,20 @@
   "coap/coap_message.hpp",
   "coap/coap_secure.cpp",
   "coap/coap_secure.hpp",
+  "common/appender.cpp",
+  "common/appender.hpp",
   "common/arg_macros.hpp",
   "common/array.hpp",
   "common/as_core_type.hpp",
+  "common/binary_search.cpp",
+  "common/binary_search.hpp",
   "common/bit_vector.hpp",
   "common/clearable.hpp",
   "common/code_utils.hpp",
   "common/const_cast.hpp",
   "common/crc16.cpp",
   "common/crc16.hpp",
+  "common/data.cpp",
   "common/data.hpp",
   "common/debug.hpp",
   "common/encoding.hpp",
@@ -387,6 +397,16 @@
   "common/error.cpp",
   "common/error.hpp",
   "common/extension.hpp",
+  "common/frame_builder.cpp",
+  "common/frame_builder.hpp",
+  "common/frame_data.cpp",
+  "common/frame_data.hpp",
+  "common/heap.cpp",
+  "common/heap.hpp",
+  "common/heap_allocatable.hpp",
+  "common/heap_array.hpp",
+  "common/heap_data.cpp",
+  "common/heap_data.hpp",
   "common/heap_string.cpp",
   "common/heap_string.hpp",
   "common/instance.cpp",
@@ -395,7 +415,8 @@
   "common/linked_list.hpp",
   "common/locator.hpp",
   "common/locator_getters.hpp",
-  "common/logging.cpp",
+  "common/log.cpp",
+  "common/log.hpp",
   "common/logging.hpp",
   "common/message.cpp",
   "common/message.hpp",
@@ -404,10 +425,14 @@
   "common/notifier.cpp",
   "common/notifier.hpp",
   "common/numeric_limits.hpp",
+  "common/owned_ptr.hpp",
+  "common/owning_list.hpp",
   "common/pool.hpp",
+  "common/ptr_wrapper.hpp",
+  "common/random.cpp",
   "common/random.hpp",
-  "common/random_manager.cpp",
-  "common/random_manager.hpp",
+  "common/retain_ptr.hpp",
+  "common/serial_number.hpp",
   "common/settings.cpp",
   "common/settings.hpp",
   "common/settings_driver.hpp",
@@ -435,6 +460,7 @@
   "crypto/crypto_platform.cpp",
   "crypto/ecdsa.cpp",
   "crypto/ecdsa.hpp",
+  "crypto/ecdsa_tinycrypt.cpp",
   "crypto/hkdf_sha256.cpp",
   "crypto/hkdf_sha256.hpp",
   "crypto/hmac_sha256.cpp",
@@ -489,6 +515,8 @@
   "meshcop/dtls.hpp",
   "meshcop/energy_scan_client.cpp",
   "meshcop/energy_scan_client.hpp",
+  "meshcop/extended_panid.cpp",
+  "meshcop/extended_panid.hpp",
   "meshcop/joiner.cpp",
   "meshcop/joiner.hpp",
   "meshcop/joiner_router.cpp",
@@ -499,6 +527,8 @@
   "meshcop/meshcop_leader.hpp",
   "meshcop/meshcop_tlvs.cpp",
   "meshcop/meshcop_tlvs.hpp",
+  "meshcop/network_name.cpp",
+  "meshcop/network_name.hpp",
   "meshcop/panid_query_client.cpp",
   "meshcop/panid_query_client.hpp",
   "meshcop/timestamp.cpp",
@@ -512,14 +542,16 @@
   "net/dhcp6_server.hpp",
   "net/dns_client.cpp",
   "net/dns_client.hpp",
+  "net/dns_dso.cpp",
+  "net/dns_dso.hpp",
   "net/dns_types.cpp",
   "net/dns_types.hpp",
   "net/dnssd_server.cpp",
   "net/dnssd_server.hpp",
   "net/icmp6.cpp",
   "net/icmp6.hpp",
-  "net/ip4_address.cpp",
-  "net/ip4_address.hpp",
+  "net/ip4_types.cpp",
+  "net/ip4_types.hpp",
   "net/ip6.cpp",
   "net/ip6.hpp",
   "net/ip6_address.cpp",
@@ -530,6 +562,9 @@
   "net/ip6_headers.hpp",
   "net/ip6_mpl.cpp",
   "net/ip6_mpl.hpp",
+  "net/ip6_types.hpp",
+  "net/nd6.cpp",
+  "net/nd6.hpp",
   "net/nd_agent.cpp",
   "net/nd_agent.hpp",
   "net/netif.cpp",
@@ -658,8 +693,6 @@
   "utils/history_tracker.hpp",
   "utils/jam_detector.cpp",
   "utils/jam_detector.hpp",
-  "utils/lookup_table.cpp",
-  "utils/lookup_table.hpp",
   "utils/otns.cpp",
   "utils/otns.hpp",
   "utils/parse_cmdline.cpp",
@@ -680,10 +713,12 @@
   "api/logging_api.cpp",
   "api/random_noncrypto_api.cpp",
   "api/tasklet_api.cpp",
+  "common/binary_search.cpp",
+  "common/binary_search.hpp",
   "common/error.hpp",
   "common/instance.cpp",
-  "common/logging.cpp",
-  "common/random_manager.cpp",
+  "common/log.cpp",
+  "common/random.cpp",
   "common/string.cpp",
   "common/tasklet.cpp",
   "common/timer.cpp",
@@ -702,7 +737,6 @@
   "radio/radio_callbacks.cpp",
   "radio/radio_platform.cpp",
   "thread/link_quality.cpp",
-  "utils/lookup_table.cpp",
   "utils/parse_cmdline.cpp",
 ]
 
@@ -730,6 +764,7 @@
     "config/dhcp6_server.h",
     "config/diag.h",
     "config/dns_client.h",
+    "config/dns_dso.h",
     "config/dnssd_server.h",
     "config/dtls.h",
     "config/history_tracker.h",
@@ -739,10 +774,10 @@
     "config/link_raw.h",
     "config/logging.h",
     "config/mac.h",
+    "config/misc.h",
     "config/mle.h",
     "config/netdata_publisher.h",
     "config/openthread-core-config-check.h",
-    "config/openthread-core-default-config.h",
     "config/parent_search.h",
     "config/ping_sender.h",
     "config/platform.h",
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 6f0b1f1..ce36689 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -35,6 +35,7 @@
     api/backbone_router_ftd_api.cpp
     api/border_agent_api.cpp
     api/border_router_api.cpp
+    api/border_routing_api.cpp
     api/channel_manager_api.cpp
     api/channel_monitor_api.cpp
     api/child_supervision_api.cpp
@@ -48,7 +49,6 @@
     api/diags_api.cpp
     api/dns_api.cpp
     api/dns_server_api.cpp
-    api/entropy_api.cpp
     api/error_api.cpp
     api/heap_api.cpp
     api/history_tracker_api.cpp
@@ -79,6 +79,7 @@
     api/tcp_api.cpp
     api/thread_api.cpp
     api/thread_ftd_api.cpp
+    api/trel_api.cpp
     api/udp_api.cpp
     backbone_router/backbone_tmf.cpp
     backbone_router/bbr_leader.cpp
@@ -86,20 +87,26 @@
     backbone_router/bbr_manager.cpp
     backbone_router/multicast_listeners_table.cpp
     backbone_router/ndproxy_table.cpp
-    border_router/infra_if_platform.cpp
-    border_router/router_advertisement.cpp
+    border_router/infra_if.cpp
     border_router/routing_manager.cpp
     coap/coap.cpp
     coap/coap_message.cpp
     coap/coap_secure.cpp
+    common/appender.cpp
+    common/binary_search.cpp
     common/crc16.cpp
+    common/data.cpp
     common/error.cpp
+    common/frame_builder.cpp
+    common/frame_data.cpp
+    common/heap.cpp
+    common/heap_data.cpp
     common/heap_string.cpp
     common/instance.cpp
-    common/logging.cpp
+    common/log.cpp
     common/message.cpp
     common/notifier.cpp
-    common/random_manager.cpp
+    common/random.cpp
     common/settings.cpp
     common/string.cpp
     common/tasklet.cpp
@@ -112,6 +119,7 @@
     crypto/aes_ecb.cpp
     crypto/crypto_platform.cpp
     crypto/ecdsa.cpp
+    crypto/ecdsa_tinycrypt.cpp
     crypto/hkdf_sha256.cpp
     crypto/hmac_sha256.cpp
     crypto/mbedtls.cpp
@@ -140,26 +148,30 @@
     meshcop/dataset_updater.cpp
     meshcop/dtls.cpp
     meshcop/energy_scan_client.cpp
+    meshcop/extended_panid.cpp
     meshcop/joiner.cpp
     meshcop/joiner_router.cpp
     meshcop/meshcop.cpp
     meshcop/meshcop_leader.cpp
     meshcop/meshcop_tlvs.cpp
+    meshcop/network_name.cpp
     meshcop/panid_query_client.cpp
     meshcop/timestamp.cpp
     net/checksum.cpp
     net/dhcp6_client.cpp
     net/dhcp6_server.cpp
     net/dns_client.cpp
+    net/dns_dso.cpp
     net/dns_types.cpp
     net/dnssd_server.cpp
     net/icmp6.cpp
-    net/ip4_address.cpp
+    net/ip4_types.cpp
     net/ip6.cpp
     net/ip6_address.cpp
     net/ip6_filter.cpp
     net/ip6_headers.cpp
     net/ip6_mpl.cpp
+    net/nd6.cpp
     net/nd_agent.cpp
     net/netif.cpp
     net/sntp_client.cpp
@@ -222,7 +234,6 @@
     utils/heap.cpp
     utils/history_tracker.cpp
     utils/jam_detector.cpp
-    utils/lookup_table.cpp
     utils/otns.cpp
     utils/parse_cmdline.cpp
     utils/ping_sender.cpp
@@ -238,10 +249,11 @@
     api/logging_api.cpp
     api/random_noncrypto_api.cpp
     api/tasklet_api.cpp
+    common/binary_search.cpp
     common/error.cpp
     common/instance.cpp
-    common/logging.cpp
-    common/random_manager.cpp
+    common/log.cpp
+    common/random.cpp
     common/string.cpp
     common/tasklet.cpp
     common/timer.cpp
@@ -260,7 +272,6 @@
     radio/radio_callbacks.cpp
     radio/radio_platform.cpp
     thread/link_quality.cpp
-    utils/lookup_table.cpp
     utils/parse_cmdline.cpp
 )
 
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index 0cff052..7b180ea 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -125,6 +125,7 @@
     api/backbone_router_ftd_api.cpp               \
     api/border_agent_api.cpp                      \
     api/border_router_api.cpp                     \
+    api/border_routing_api.cpp                    \
     api/channel_manager_api.cpp                   \
     api/channel_monitor_api.cpp                   \
     api/child_supervision_api.cpp                 \
@@ -138,7 +139,6 @@
     api/diags_api.cpp                             \
     api/dns_api.cpp                               \
     api/dns_server_api.cpp                        \
-    api/entropy_api.cpp                           \
     api/error_api.cpp                             \
     api/heap_api.cpp                              \
     api/history_tracker_api.cpp                   \
@@ -169,6 +169,7 @@
     api/tcp_api.cpp                               \
     api/thread_api.cpp                            \
     api/thread_ftd_api.cpp                        \
+    api/trel_api.cpp                              \
     api/udp_api.cpp                               \
     backbone_router/backbone_tmf.cpp              \
     backbone_router/bbr_leader.cpp                \
@@ -176,20 +177,26 @@
     backbone_router/bbr_manager.cpp               \
     backbone_router/multicast_listeners_table.cpp \
     backbone_router/ndproxy_table.cpp             \
-    border_router/infra_if_platform.cpp           \
-    border_router/router_advertisement.cpp        \
+    border_router/infra_if.cpp                    \
     border_router/routing_manager.cpp             \
     coap/coap.cpp                                 \
     coap/coap_message.cpp                         \
     coap/coap_secure.cpp                          \
+    common/appender.cpp                           \
+    common/binary_search.cpp                      \
     common/crc16.cpp                              \
+    common/data.cpp                               \
     common/error.cpp                              \
+    common/frame_builder.cpp                      \
+    common/frame_data.cpp                         \
+    common/heap.cpp                               \
+    common/heap_data.cpp                          \
     common/heap_string.cpp                        \
     common/instance.cpp                           \
-    common/logging.cpp                            \
+    common/log.cpp                                \
     common/message.cpp                            \
     common/notifier.cpp                           \
-    common/random_manager.cpp                     \
+    common/random.cpp                             \
     common/settings.cpp                           \
     common/string.cpp                             \
     common/tasklet.cpp                            \
@@ -202,6 +209,7 @@
     crypto/aes_ecb.cpp                            \
     crypto/crypto_platform.cpp                    \
     crypto/ecdsa.cpp                              \
+    crypto/ecdsa_tinycrypt.cpp                    \
     crypto/hkdf_sha256.cpp                        \
     crypto/hmac_sha256.cpp                        \
     crypto/mbedtls.cpp                            \
@@ -230,26 +238,30 @@
     meshcop/dataset_updater.cpp                   \
     meshcop/dtls.cpp                              \
     meshcop/energy_scan_client.cpp                \
+    meshcop/extended_panid.cpp                    \
     meshcop/joiner.cpp                            \
     meshcop/joiner_router.cpp                     \
     meshcop/meshcop.cpp                           \
     meshcop/meshcop_leader.cpp                    \
     meshcop/meshcop_tlvs.cpp                      \
+    meshcop/network_name.cpp                      \
     meshcop/panid_query_client.cpp                \
     meshcop/timestamp.cpp                         \
     net/checksum.cpp                              \
     net/dhcp6_client.cpp                          \
     net/dhcp6_server.cpp                          \
     net/dns_client.cpp                            \
+    net/dns_dso.cpp                               \
     net/dns_types.cpp                             \
     net/dnssd_server.cpp                          \
     net/icmp6.cpp                                 \
-    net/ip4_address.cpp                           \
+    net/ip4_types.cpp                             \
     net/ip6.cpp                                   \
     net/ip6_address.cpp                           \
     net/ip6_filter.cpp                            \
     net/ip6_headers.cpp                           \
     net/ip6_mpl.cpp                               \
+    net/nd6.cpp                                   \
     net/nd_agent.cpp                              \
     net/netif.cpp                                 \
     net/sntp_client.cpp                           \
@@ -312,7 +324,6 @@
     utils/heap.cpp                                \
     utils/history_tracker.cpp                     \
     utils/jam_detector.cpp                        \
-    utils/lookup_table.cpp                        \
     utils/otns.cpp                                \
     utils/parse_cmdline.cpp                       \
     utils/ping_sender.cpp                         \
@@ -328,10 +339,11 @@
     api/logging_api.cpp                      \
     api/random_noncrypto_api.cpp             \
     api/tasklet_api.cpp                      \
+    common/binary_search.cpp                 \
     common/error.cpp                         \
     common/instance.cpp                      \
-    common/logging.cpp                       \
-    common/random_manager.cpp                \
+    common/log.cpp                           \
+    common/random.cpp                        \
     common/string.cpp                        \
     common/tasklet.cpp                       \
     common/timer.cpp                         \
@@ -350,7 +362,6 @@
     radio/radio_callbacks.cpp                \
     radio/radio_platform.cpp                 \
     thread/link_quality.cpp                  \
-    utils/lookup_table.cpp                   \
     utils/parse_cmdline.cpp                  \
     $(NULL)
 
@@ -407,14 +418,16 @@
     backbone_router/bbr_manager.hpp               \
     backbone_router/multicast_listeners_table.hpp \
     backbone_router/ndproxy_table.hpp             \
-    border_router/router_advertisement.hpp        \
+    border_router/infra_if.hpp                    \
     border_router/routing_manager.hpp             \
     coap/coap.hpp                                 \
     coap/coap_message.hpp                         \
     coap/coap_secure.hpp                          \
+    common/appender.hpp                           \
     common/arg_macros.hpp                         \
     common/array.hpp                              \
     common/as_core_type.hpp                       \
+    common/binary_search.hpp                      \
     common/bit_vector.hpp                         \
     common/clearable.hpp                          \
     common/code_utils.hpp                         \
@@ -426,21 +439,32 @@
     common/equatable.hpp                          \
     common/error.hpp                              \
     common/extension.hpp                          \
+    common/frame_builder.hpp                      \
+    common/frame_data.hpp                         \
+    common/heap.hpp                               \
+    common/heap_allocatable.hpp                   \
+    common/heap_array.hpp                         \
+    common/heap_data.hpp                          \
     common/heap_string.hpp                        \
     common/instance.hpp                           \
     common/iterator_utils.hpp                     \
     common/linked_list.hpp                        \
     common/locator.hpp                            \
     common/locator_getters.hpp                    \
+    common/log.hpp                                \
     common/logging.hpp                            \
     common/message.hpp                            \
     common/new.hpp                                \
     common/non_copyable.hpp                       \
     common/notifier.hpp                           \
     common/numeric_limits.hpp                     \
+    common/owned_ptr.hpp                          \
+    common/owning_list.hpp                        \
     common/pool.hpp                               \
+    common/ptr_wrapper.hpp                        \
     common/random.hpp                             \
-    common/random_manager.hpp                     \
+    common/retain_ptr.hpp                         \
+    common/serial_number.hpp                      \
     common/settings.hpp                           \
     common/settings_driver.hpp                    \
     common/string.hpp                             \
@@ -466,6 +490,7 @@
     config/dhcp6_server.h                         \
     config/diag.h                                 \
     config/dns_client.h                           \
+    config/dns_dso.h                              \
     config/dnssd_server.h                         \
     config/dtls.h                                 \
     config/history_tracker.h                      \
@@ -475,10 +500,10 @@
     config/link_raw.h                             \
     config/logging.h                              \
     config/mac.h                                  \
+    config/misc.h                                 \
     config/mle.h                                  \
     config/netdata_publisher.h                    \
     config/openthread-core-config-check.h         \
-    config/openthread-core-default-config.h       \
     config/parent_search.h                        \
     config/ping_sender.h                          \
     config/platform.h                             \
@@ -518,11 +543,13 @@
     meshcop/dataset_updater.hpp                   \
     meshcop/dtls.hpp                              \
     meshcop/energy_scan_client.hpp                \
+    meshcop/extended_panid.hpp                    \
     meshcop/joiner.hpp                            \
     meshcop/joiner_router.hpp                     \
     meshcop/meshcop.hpp                           \
     meshcop/meshcop_leader.hpp                    \
     meshcop/meshcop_tlvs.hpp                      \
+    meshcop/network_name.hpp                      \
     meshcop/panid_query_client.hpp                \
     meshcop/timestamp.hpp                         \
     net/checksum.hpp                              \
@@ -530,15 +557,18 @@
     net/dhcp6_client.hpp                          \
     net/dhcp6_server.hpp                          \
     net/dns_client.hpp                            \
+    net/dns_dso.hpp                               \
     net/dns_types.hpp                             \
     net/dnssd_server.hpp                          \
     net/icmp6.hpp                                 \
-    net/ip4_address.hpp                           \
+    net/ip4_types.hpp                             \
     net/ip6.hpp                                   \
     net/ip6_address.hpp                           \
     net/ip6_filter.hpp                            \
     net/ip6_headers.hpp                           \
     net/ip6_mpl.hpp                               \
+    net/ip6_types.hpp                             \
+    net/nd6.hpp                                   \
     net/nd_agent.hpp                              \
     net/netif.hpp                                 \
     net/sntp_client.hpp                           \
@@ -606,7 +636,6 @@
     utils/heap.hpp                                \
     utils/history_tracker.hpp                     \
     utils/jam_detector.hpp                        \
-    utils/lookup_table.hpp                        \
     utils/otns.hpp                                \
     utils/parse_cmdline.hpp                       \
     utils/ping_sender.hpp                         \
diff --git a/src/core/api/backbone_router_ftd_api.cpp b/src/core/api/backbone_router_ftd_api.cpp
index 16380be..d8e5169 100644
--- a/src/core/api/backbone_router_ftd_api.cpp
+++ b/src/core/api/backbone_router_ftd_api.cpp
@@ -176,6 +176,7 @@
                                                                                     TimerMilli::GetNow() + aTimeout);
 }
 #endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
+
 #endif // OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
 
 #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
diff --git a/src/core/api/border_router_api.cpp b/src/core/api/border_router_api.cpp
index 69fd097..2ef3c4d 100644
--- a/src/core/api/border_router_api.cpp
+++ b/src/core/api/border_router_api.cpp
@@ -38,37 +38,15 @@
 #include <openthread/border_router.h>
 
 #include "border_router/routing_manager.hpp"
-#include "common/as_core_type.hpp"
 #include "common/debug.hpp"
+#include "common/instance.hpp"
 
 using namespace ot;
 
-#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
-otError otBorderRoutingInit(otInstance *aInstance, uint32_t aInfraIfIndex, bool aInfraIfIsRunning)
-{
-    return AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().Init(aInfraIfIndex, aInfraIfIsRunning);
-}
-
-otError otBorderRoutingSetEnabled(otInstance *aInstance, bool aEnabled)
-{
-    return AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().SetEnabled(aEnabled);
-}
-
-otError otBorderRoutingGetOmrPrefix(otInstance *aInstance, otIp6Prefix *aPrefix)
-{
-    return AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().GetOmrPrefix(AsCoreType(aPrefix));
-}
-
-otError otBorderRoutingGetOnLinkPrefix(otInstance *aInstance, otIp6Prefix *aPrefix)
-{
-    return AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(AsCoreType(aPrefix));
-}
-
-#endif
-
 otError otBorderRouterGetNetData(otInstance *aInstance, bool aStable, uint8_t *aData, uint8_t *aDataLength)
 {
-    return AsCoreType(aInstance).Get<NetworkData::Local>().CopyNetworkData(aStable, aData, *aDataLength);
+    return AsCoreType(aInstance).Get<NetworkData::Local>().CopyNetworkData(
+        aStable ? NetworkData::kStableSubset : NetworkData::kFullSet, aData, *aDataLength);
 }
 
 otError otBorderRouterAddOnMeshPrefix(otInstance *aInstance, const otBorderRouterConfig *aConfig)
diff --git a/src/core/api/border_routing_api.cpp b/src/core/api/border_routing_api.cpp
new file mode 100644
index 0000000..1d942c5
--- /dev/null
+++ b/src/core/api/border_routing_api.cpp
@@ -0,0 +1,109 @@
+/*
+ *  Copyright (c) 2021-22, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file implements the OpenThread Border Routing Manager API.
+ */
+
+#include "openthread-core-config.h"
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+
+#include <openthread/border_routing.h>
+
+#include "border_router/routing_manager.hpp"
+#include "common/instance.hpp"
+
+using namespace ot;
+
+otError otBorderRoutingInit(otInstance *aInstance, uint32_t aInfraIfIndex, bool aInfraIfIsRunning)
+{
+    return AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().Init(aInfraIfIndex, aInfraIfIsRunning);
+}
+
+otError otBorderRoutingSetEnabled(otInstance *aInstance, bool aEnabled)
+{
+    return AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().SetEnabled(aEnabled);
+}
+
+otRoutePreference otBorderRoutingGetRouteInfoOptionPreference(otInstance *aInstance)
+{
+    return static_cast<otRoutePreference>(
+        AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().GetRouteInfoOptionPreference());
+}
+
+void otBorderRoutingSetRouteInfoOptionPreference(otInstance *aInstance, otRoutePreference aPreference)
+{
+    AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().SetRouteInfoOptionPreference(
+        static_cast<NetworkData::RoutePreference>(aPreference));
+}
+
+otError otBorderRoutingGetOmrPrefix(otInstance *aInstance, otIp6Prefix *aPrefix)
+{
+    return AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().GetOmrPrefix(AsCoreType(aPrefix));
+}
+
+otError otBorderRoutingGetFavoredOmrPrefix(otInstance *aInstance, otIp6Prefix *aPrefix, otRoutePreference *aPreference)
+{
+    otError                                       error;
+    BorderRouter::RoutingManager::RoutePreference preference;
+
+    SuccessOrExit(error = AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().GetFavoredOmrPrefix(
+                      AsCoreType(aPrefix), preference));
+    *aPreference = static_cast<otRoutePreference>(preference);
+
+exit:
+    return error;
+}
+
+otError otBorderRoutingGetOnLinkPrefix(otInstance *aInstance, otIp6Prefix *aPrefix)
+{
+    return AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(AsCoreType(aPrefix));
+}
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
+otError otBorderRoutingGetNat64Prefix(otInstance *aInstance, otIp6Prefix *aPrefix)
+{
+    return AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().GetNat64Prefix(AsCoreType(aPrefix));
+}
+#endif
+
+void otBorderRoutingPrefixTableInitIterator(otInstance *aInstance, otBorderRoutingPrefixTableIterator *aIterator)
+{
+    AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().InitPrefixTableIterator(*aIterator);
+}
+
+otError otBorderRoutingGetNextPrefixTableEntry(otInstance *                        aInstance,
+                                               otBorderRoutingPrefixTableIterator *aIterator,
+                                               otBorderRoutingPrefixTableEntry *   aEntry)
+{
+    return AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().GetNextPrefixTableEntry(*aIterator, *aEntry);
+}
+
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
diff --git a/src/core/api/coap_api.cpp b/src/core/api/coap_api.cpp
index 4835367..4dfb35e 100644
--- a/src/core/api/coap_api.cpp
+++ b/src/core/api/coap_api.cpp
@@ -144,6 +144,11 @@
     return static_cast<otCoapCode>(AsCoapMessage(aMessage).GetCode());
 }
 
+void otCoapMessageSetCode(otMessage *aMessage, otCoapCode aCode)
+{
+    AsCoapMessage(aMessage).SetCode(MapEnum(aCode));
+}
+
 const char *otCoapMessageCodeToString(const otMessage *aMessage)
 {
     return AsCoapMessage(aMessage).CodeToString();
diff --git a/src/core/api/commissioner_api.cpp b/src/core/api/commissioner_api.cpp
index 83eaf4b..9c5b575 100644
--- a/src/core/api/commissioner_api.cpp
+++ b/src/core/api/commissioner_api.cpp
@@ -50,9 +50,19 @@
     return AsCoreType(aInstance).Get<MeshCoP::Commissioner>().Start(aStateCallback, aJoinerCallback, aCallbackContext);
 }
 
+const char *otCommissionerGetId(otInstance *aInstance)
+{
+    return AsCoreType(aInstance).Get<MeshCoP::Commissioner>().GetId();
+}
+
+otError otCommissionerSetId(otInstance *aInstance, const char *aId)
+{
+    return AsCoreType(aInstance).Get<MeshCoP::Commissioner>().SetId(aId);
+}
+
 otError otCommissionerStop(otInstance *aInstance)
 {
-    return AsCoreType(aInstance).Get<MeshCoP::Commissioner>().Stop(/* aResign */ true);
+    return AsCoreType(aInstance).Get<MeshCoP::Commissioner>().Stop();
 }
 
 otError otCommissionerAddJoiner(otInstance *aInstance, const otExtAddress *aEui64, const char *aPskd, uint32_t aTimeout)
@@ -161,7 +171,8 @@
                                   const uint8_t *               aTlvs,
                                   uint8_t                       aLength)
 {
-    return AsCoreType(aInstance).Get<MeshCoP::Commissioner>().SendMgmtCommissionerSetRequest(*aDataset, aTlvs, aLength);
+    return AsCoreType(aInstance).Get<MeshCoP::Commissioner>().SendMgmtCommissionerSetRequest(AsCoreType(aDataset),
+                                                                                             aTlvs, aLength);
 }
 
 uint16_t otCommissionerGetSessionId(otInstance *aInstance)
diff --git a/src/core/api/dataset_api.cpp b/src/core/api/dataset_api.cpp
index a4153d2..457c783 100644
--- a/src/core/api/dataset_api.cpp
+++ b/src/core/api/dataset_api.cpp
@@ -44,63 +44,63 @@
 
 bool otDatasetIsCommissioned(otInstance *aInstance)
 {
-    return AsCoreType(aInstance).Get<MeshCoP::ActiveDataset>().IsCommissioned();
+    return AsCoreType(aInstance).Get<MeshCoP::ActiveDatasetManager>().IsCommissioned();
 }
 
 otError otDatasetGetActive(otInstance *aInstance, otOperationalDataset *aDataset)
 {
     OT_ASSERT(aDataset != nullptr);
 
-    return AsCoreType(aInstance).Get<MeshCoP::ActiveDataset>().Read(AsCoreType(aDataset));
+    return AsCoreType(aInstance).Get<MeshCoP::ActiveDatasetManager>().Read(AsCoreType(aDataset));
 }
 
 otError otDatasetGetActiveTlvs(otInstance *aInstance, otOperationalDatasetTlvs *aDataset)
 {
     OT_ASSERT(aDataset != nullptr);
 
-    return AsCoreType(aInstance).Get<MeshCoP::ActiveDataset>().Read(*aDataset);
+    return AsCoreType(aInstance).Get<MeshCoP::ActiveDatasetManager>().Read(*aDataset);
 }
 
 otError otDatasetSetActive(otInstance *aInstance, const otOperationalDataset *aDataset)
 {
     OT_ASSERT(aDataset != nullptr);
 
-    return AsCoreType(aInstance).Get<MeshCoP::ActiveDataset>().Save(AsCoreType(aDataset));
+    return AsCoreType(aInstance).Get<MeshCoP::ActiveDatasetManager>().Save(AsCoreType(aDataset));
 }
 
 otError otDatasetSetActiveTlvs(otInstance *aInstance, const otOperationalDatasetTlvs *aDataset)
 {
     OT_ASSERT(aDataset != nullptr);
 
-    return AsCoreType(aInstance).Get<MeshCoP::ActiveDataset>().Save(*aDataset);
+    return AsCoreType(aInstance).Get<MeshCoP::ActiveDatasetManager>().Save(*aDataset);
 }
 
 otError otDatasetGetPending(otInstance *aInstance, otOperationalDataset *aDataset)
 {
     OT_ASSERT(aDataset != nullptr);
 
-    return AsCoreType(aInstance).Get<MeshCoP::PendingDataset>().Read(AsCoreType(aDataset));
+    return AsCoreType(aInstance).Get<MeshCoP::PendingDatasetManager>().Read(AsCoreType(aDataset));
 }
 
 otError otDatasetGetPendingTlvs(otInstance *aInstance, otOperationalDatasetTlvs *aDataset)
 {
     OT_ASSERT(aDataset != nullptr);
 
-    return AsCoreType(aInstance).Get<MeshCoP::PendingDataset>().Read(*aDataset);
+    return AsCoreType(aInstance).Get<MeshCoP::PendingDatasetManager>().Read(*aDataset);
 }
 
 otError otDatasetSetPending(otInstance *aInstance, const otOperationalDataset *aDataset)
 {
     OT_ASSERT(aDataset != nullptr);
 
-    return AsCoreType(aInstance).Get<MeshCoP::PendingDataset>().Save(AsCoreType(aDataset));
+    return AsCoreType(aInstance).Get<MeshCoP::PendingDatasetManager>().Save(AsCoreType(aDataset));
 }
 
 otError otDatasetSetPendingTlvs(otInstance *aInstance, const otOperationalDatasetTlvs *aDataset)
 {
     OT_ASSERT(aDataset != nullptr);
 
-    return AsCoreType(aInstance).Get<MeshCoP::PendingDataset>().Save(*aDataset);
+    return AsCoreType(aInstance).Get<MeshCoP::PendingDatasetManager>().Save(*aDataset);
 }
 
 otError otDatasetSendMgmtActiveGet(otInstance *                          aInstance,
@@ -109,8 +109,8 @@
                                    uint8_t                               aLength,
                                    const otIp6Address *                  aAddress)
 {
-    return AsCoreType(aInstance).Get<MeshCoP::ActiveDataset>().SendGetRequest(AsCoreType(aDatasetComponents), aTlvTypes,
-                                                                              aLength, aAddress);
+    return AsCoreType(aInstance).Get<MeshCoP::ActiveDatasetManager>().SendGetRequest(AsCoreType(aDatasetComponents),
+                                                                                     aTlvTypes, aLength, aAddress);
 }
 
 otError otDatasetSendMgmtActiveSet(otInstance *                aInstance,
@@ -120,8 +120,8 @@
                                    otDatasetMgmtSetCallback    aCallback,
                                    void *                      aContext)
 {
-    return AsCoreType(aInstance).Get<MeshCoP::ActiveDataset>().SendSetRequest(AsCoreType(aDataset), aTlvs, aLength,
-                                                                              aCallback, aContext);
+    return AsCoreType(aInstance).Get<MeshCoP::ActiveDatasetManager>().SendSetRequest(AsCoreType(aDataset), aTlvs,
+                                                                                     aLength, aCallback, aContext);
 }
 
 otError otDatasetSendMgmtPendingGet(otInstance *                          aInstance,
@@ -130,8 +130,8 @@
                                     uint8_t                               aLength,
                                     const otIp6Address *                  aAddress)
 {
-    return AsCoreType(aInstance).Get<MeshCoP::PendingDataset>().SendGetRequest(AsCoreType(aDatasetComponents),
-                                                                               aTlvTypes, aLength, aAddress);
+    return AsCoreType(aInstance).Get<MeshCoP::PendingDatasetManager>().SendGetRequest(AsCoreType(aDatasetComponents),
+                                                                                      aTlvTypes, aLength, aAddress);
 }
 
 otError otDatasetSendMgmtPendingSet(otInstance *                aInstance,
@@ -141,8 +141,8 @@
                                     otDatasetMgmtSetCallback    aCallback,
                                     void *                      aContext)
 {
-    return AsCoreType(aInstance).Get<MeshCoP::PendingDataset>().SendSetRequest(AsCoreType(aDataset), aTlvs, aLength,
-                                                                               aCallback, aContext);
+    return AsCoreType(aInstance).Get<MeshCoP::PendingDatasetManager>().SendSetRequest(AsCoreType(aDataset), aTlvs,
+                                                                                      aLength, aCallback, aContext);
 }
 
 #if OPENTHREAD_FTD
diff --git a/src/core/api/dataset_ftd_api.cpp b/src/core/api/dataset_ftd_api.cpp
index 4c26088..ea1792d 100644
--- a/src/core/api/dataset_ftd_api.cpp
+++ b/src/core/api/dataset_ftd_api.cpp
@@ -44,7 +44,7 @@
 
 otError otDatasetCreateNewNetwork(otInstance *aInstance, otOperationalDataset *aDataset)
 {
-    return AsCoreType(aInstance).Get<MeshCoP::ActiveDataset>().CreateNewNetwork(AsCoreType(aDataset));
+    return AsCoreType(aInstance).Get<MeshCoP::ActiveDatasetManager>().CreateNewNetwork(AsCoreType(aDataset));
 }
 
 uint32_t otDatasetGetDelayTimerMinimal(otInstance *aInstance)
diff --git a/src/core/api/dns_api.cpp b/src/core/api/dns_api.cpp
index 436eb05..d9bdda7 100644
--- a/src/core/api/dns_api.cpp
+++ b/src/core/api/dns_api.cpp
@@ -35,7 +35,8 @@
 
 #include <openthread/dns_client.h>
 
-#include "common/as_core_type.hpp"
+#include "common/instance.hpp"
+#include "net/dns_types.hpp"
 
 using namespace ot;
 
@@ -90,6 +91,18 @@
                                                                    AsCoreTypePtr(aConfig));
 }
 
+#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
+otError otDnsClientResolveIp4Address(otInstance *            aInstance,
+                                     const char *            aHostName,
+                                     otDnsAddressCallback    aCallback,
+                                     void *                  aContext,
+                                     const otDnsQueryConfig *aConfig)
+{
+    return AsCoreType(aInstance).Get<Dns::Client>().ResolveIp4Address(aHostName, aCallback, aContext,
+                                                                      AsCoreTypePtr(aConfig));
+}
+#endif
+
 otError otDnsAddressResponseGetHostName(const otDnsAddressResponse *aResponse,
                                         char *                      aNameBuffer,
                                         uint16_t                    aNameBufferSize)
diff --git a/src/core/api/dns_server_api.cpp b/src/core/api/dns_server_api.cpp
index ccd233a..5b09448 100644
--- a/src/core/api/dns_server_api.cpp
+++ b/src/core/api/dns_server_api.cpp
@@ -33,7 +33,7 @@
 
 #include "openthread-core-config.h"
 
-#include "common/as_core_type.hpp"
+#include "common/instance.hpp"
 #include "net/dns_types.hpp"
 #include "net/dnssd_server.hpp"
 
@@ -81,4 +81,9 @@
     return MapEnum(Dns::ServiceDiscovery::Server::GetQueryTypeAndName(aQuery, *aNameOutput));
 }
 
+const otDnssdCounters *otDnssdGetCounters(otInstance *aInstance)
+{
+    return &AsCoreType(aInstance).Get<Dns::ServiceDiscovery::Server>().GetCounters();
+}
+
 #endif // OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
diff --git a/src/core/api/heap_api.cpp b/src/core/api/heap_api.cpp
index e3cd90d..e306c61 100644
--- a/src/core/api/heap_api.cpp
+++ b/src/core/api/heap_api.cpp
@@ -35,7 +35,7 @@
 
 #include <openthread/heap.h>
 
-#include "common/instance.hpp"
+#include "common/heap.hpp"
 
 #if OPENTHREAD_RADIO
 
@@ -62,11 +62,11 @@
 #else  // OPENTHREAD_RADIO
 void *otHeapCAlloc(size_t aCount, size_t aSize)
 {
-    return ot::Instance::HeapCAlloc(aCount, aSize);
+    return ot::Heap::CAlloc(aCount, aSize);
 }
 
 void otHeapFree(void *aPointer)
 {
-    ot::Instance::HeapFree(aPointer);
+    ot::Heap::Free(aPointer);
 }
 #endif // OPENTHREAD_RADIO
diff --git a/src/core/api/history_tracker_api.cpp b/src/core/api/history_tracker_api.cpp
index a9714ef..5e52b36 100644
--- a/src/core/api/history_tracker_api.cpp
+++ b/src/core/api/history_tracker_api.cpp
@@ -94,6 +94,23 @@
     return AsCoreType(aInstance).Get<Utils::HistoryTracker>().IterateNeighborHistory(AsCoreType(aIterator), *aEntryAge);
 }
 
+const otHistoryTrackerOnMeshPrefixInfo *otHistoryTrackerIterateOnMeshPrefixHistory(otInstance *              aInstance,
+                                                                                   otHistoryTrackerIterator *aIterator,
+                                                                                   uint32_t *                aEntryAge)
+{
+    return AsCoreType(aInstance).Get<Utils::HistoryTracker>().IterateOnMeshPrefixHistory(AsCoreType(aIterator),
+                                                                                         *aEntryAge);
+}
+
+const otHistoryTrackerExternalRouteInfo *otHistoryTrackerIterateExternalRouteHistory(
+    otInstance *              aInstance,
+    otHistoryTrackerIterator *aIterator,
+    uint32_t *                aEntryAge)
+{
+    return AsCoreType(aInstance).Get<Utils::HistoryTracker>().IterateExternalRouteHistory(AsCoreType(aIterator),
+                                                                                          *aEntryAge);
+}
+
 void otHistoryTrackerEntryAgeToString(uint32_t aEntryAge, char *aBuffer, uint16_t aSize)
 {
     Utils::HistoryTracker::EntryAgeToString(aEntryAge, aBuffer, aSize);
diff --git a/src/core/api/instance_api.cpp b/src/core/api/instance_api.cpp
index f9cc00e..5557f68 100644
--- a/src/core/api/instance_api.cpp
+++ b/src/core/api/instance_api.cpp
@@ -38,7 +38,6 @@
 
 #include "common/as_core_type.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
 #include "common/new.hpp"
 #include "radio/radio.hpp"
 
@@ -51,7 +50,7 @@
 #endif
 #else // __ANDROID__
 #if defined(__DATE__)
-#define OPENTHREAD_BUILD_DATETIME "; " __DATE__ " " __TIME__
+#define OPENTHREAD_BUILD_DATETIME __DATE__ " " __TIME__
 #endif
 #endif // __ANDROID__
 #endif // !defined(OPENTHREAD_BUILD_DATETIME)
@@ -64,7 +63,6 @@
     Instance *instance;
 
     instance = Instance::Init(aInstanceBuffer, aInstanceBufferSize);
-    otLogInfoApi("otInstance Initialized");
 
     return instance;
 }
@@ -179,10 +177,10 @@
 #endif
     const char sVersion[] = PACKAGE_NAME "/" PACKAGE_VERSION "; " OPENTHREAD_CONFIG_PLATFORM_INFO
 #ifdef OPENTHREAD_BUILD_DATETIME
-        OPENTHREAD_BUILD_DATETIME
+                                         "; " OPENTHREAD_BUILD_DATETIME
 #endif
 #ifdef PLATFORM_VERSION_ATTR_SUFFIX
-            PLATFORM_VERSION_ATTR_SUFFIX
+                                             PLATFORM_VERSION_ATTR_SUFFIX
 #endif
         ; // Trailing semicolon to end statement.
 
diff --git a/src/core/api/ip6_api.cpp b/src/core/api/ip6_api.cpp
index 6aa9e71..b12b35e 100644
--- a/src/core/api/ip6_api.cpp
+++ b/src/core/api/ip6_api.cpp
@@ -37,10 +37,7 @@
 
 #include "common/as_core_type.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
-#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
 #include "utils/slaac_address.hpp"
-#endif
 
 using namespace ot;
 
@@ -135,7 +132,8 @@
 
 otError otIp6Send(otInstance *aInstance, otMessage *aMessage)
 {
-    return AsCoreType(aInstance).Get<Ip6::Ip6>().SendRaw(AsCoreType(aMessage));
+    return AsCoreType(aInstance).Get<Ip6::Ip6>().SendRaw(AsCoreType(aMessage),
+                                                         !OPENTHREAD_CONFIG_IP6_ALLOW_LOOP_BACK_HOST_DATAGRAMS);
 }
 
 otMessage *otIp6NewMessage(otInstance *aInstance, const otMessageSettings *aSettings)
diff --git a/src/core/api/joiner_api.cpp b/src/core/api/joiner_api.cpp
index f311366..2ee2ac3 100644
--- a/src/core/api/joiner_api.cpp
+++ b/src/core/api/joiner_api.cpp
@@ -38,6 +38,7 @@
 #include <openthread/joiner.h>
 
 #include "common/as_core_type.hpp"
+#include "common/debug.hpp"
 #include "common/locator_getters.hpp"
 
 using namespace ot;
@@ -93,4 +94,11 @@
     return AsCoreType(aInstance).Get<MeshCoP::Joiner>().GetDiscerner();
 }
 
+const char *otJoinerStateToString(otJoinerState aState)
+{
+    OT_ASSERT(aState <= OT_JOINER_STATE_JOINED);
+
+    return MeshCoP::Joiner::StateToString(MapEnum(aState));
+}
+
 #endif // OPENTHREAD_CONFIG_JOINER_ENABLE
diff --git a/src/core/api/link_api.cpp b/src/core/api/link_api.cpp
index a327054..ff5922d 100644
--- a/src/core/api/link_api.cpp
+++ b/src/core/api/link_api.cpp
@@ -77,8 +77,8 @@
     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
 
     SuccessOrExit(error = instance.Get<Mac::Mac>().SetPanChannel(aChannel));
-    instance.Get<MeshCoP::ActiveDataset>().Clear();
-    instance.Get<MeshCoP::PendingDataset>().Clear();
+    instance.Get<MeshCoP::ActiveDatasetManager>().Clear();
+    instance.Get<MeshCoP::PendingDatasetManager>().Clear();
 
 exit:
     return error;
@@ -141,8 +141,8 @@
     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
 
     instance.Get<Mac::Mac>().SetPanId(aPanId);
-    instance.Get<MeshCoP::ActiveDataset>().Clear();
-    instance.Get<MeshCoP::PendingDataset>().Clear();
+    instance.Get<MeshCoP::ActiveDatasetManager>().Clear();
+    instance.Get<MeshCoP::PendingDatasetManager>().Clear();
 
 exit:
     return error;
@@ -266,6 +266,20 @@
     return AsCoreType(aInstance).Get<Mac::Filter>().GetNextRssIn(*aIterator, *aEntry);
 }
 
+#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
+void otLinkSetRadioFilterEnabled(otInstance *aInstance, bool aFilterEnabled)
+{
+    return AsCoreType(aInstance).Get<Mac::Mac>().SetRadioFilterEnabled(aFilterEnabled);
+}
+
+bool otLinkIsRadioFilterEnabled(otInstance *aInstance)
+{
+    return AsCoreType(aInstance).Get<Mac::Mac>().IsRadioFilterEnabled();
+}
+#endif
+
+#endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
+
 uint8_t otLinkConvertRssToLinkQuality(otInstance *aInstance, int8_t aRss)
 {
     return LinkQualityInfo::ConvertRssToLinkQuality(AsCoreType(aInstance).Get<Mac::Mac>().GetNoiseFloor(), aRss);
@@ -274,11 +288,9 @@
 int8_t otLinkConvertLinkQualityToRss(otInstance *aInstance, uint8_t aLinkQuality)
 {
     return LinkQualityInfo::ConvertLinkQualityToRss(AsCoreType(aInstance).Get<Mac::Mac>().GetNoiseFloor(),
-                                                    aLinkQuality);
+                                                    static_cast<LinkQuality>(aLinkQuality));
 }
 
-#endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
-
 #if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
 const uint32_t *otLinkGetTxDirectRetrySuccessHistogram(otInstance *aInstance, uint8_t *aNumberOfEntries)
 {
diff --git a/src/core/api/link_metrics_api.cpp b/src/core/api/link_metrics_api.cpp
index bc4668a..b14a915 100644
--- a/src/core/api/link_metrics_api.cpp
+++ b/src/core/api/link_metrics_api.cpp
@@ -38,6 +38,7 @@
 #include <openthread/link_metrics.h>
 
 #include "common/as_core_type.hpp"
+#include "common/locator_getters.hpp"
 
 using namespace ot;
 
diff --git a/src/core/api/logging_api.cpp b/src/core/api/logging_api.cpp
index b00147c..3218837 100644
--- a/src/core/api/logging_api.cpp
+++ b/src/core/api/logging_api.cpp
@@ -33,19 +33,17 @@
 
 #include "openthread-core-config.h"
 
-#include <openthread/logging.h>
+#include "common/code_utils.hpp"
+#include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
+#include "common/log.hpp"
 
 using namespace ot;
 
 otLogLevel otLoggingGetLevel(void)
 {
-#if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
-    return Instance::GetLogLevel();
-#else
-    return static_cast<otLogLevel>(OPENTHREAD_CONFIG_LOG_LEVEL);
-#endif
+    return static_cast<otLogLevel>(Instance::GetLogLevel());
 }
 
 #if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
@@ -53,15 +51,154 @@
 {
     Error error = kErrorNone;
 
-    if (aLogLevel <= OT_LOG_LEVEL_DEBG && aLogLevel >= OT_LOG_LEVEL_NONE)
-    {
-        Instance::SetLogLevel(aLogLevel);
-    }
-    else
-    {
-        error = kErrorInvalidArgs;
-    }
+    VerifyOrExit(aLogLevel <= kLogLevelDebg && aLogLevel >= kLogLevelNone, error = kErrorInvalidArgs);
+    Instance::SetLogLevel(static_cast<LogLevel>(aLogLevel));
 
+exit:
     return error;
 }
 #endif
+
+static const char kPlatformModuleName[] = "Platform";
+
+void otLogCritPlat(const char *aFormat, ...)
+{
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_CRIT) && OPENTHREAD_CONFIG_LOG_PLATFORM
+    va_list args;
+
+    va_start(args, aFormat);
+    Logger::LogVarArgs(kPlatformModuleName, kLogLevelCrit, aFormat, args);
+    va_end(args);
+#else
+    OT_UNUSED_VARIABLE(aFormat);
+    OT_UNUSED_VARIABLE(kPlatformModuleName);
+#endif
+}
+
+void otLogWarnPlat(const char *aFormat, ...)
+{
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN) && OPENTHREAD_CONFIG_LOG_PLATFORM
+    va_list args;
+
+    va_start(args, aFormat);
+    Logger::LogVarArgs(kPlatformModuleName, kLogLevelWarn, aFormat, args);
+    va_end(args);
+#else
+    OT_UNUSED_VARIABLE(aFormat);
+#endif
+}
+
+void otLogNotePlat(const char *aFormat, ...)
+{
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE) && OPENTHREAD_CONFIG_LOG_PLATFORM
+    va_list args;
+
+    va_start(args, aFormat);
+    Logger::LogVarArgs(kPlatformModuleName, kLogLevelNote, aFormat, args);
+    va_end(args);
+#else
+    OT_UNUSED_VARIABLE(aFormat);
+#endif
+}
+
+void otLogInfoPlat(const char *aFormat, ...)
+{
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) && OPENTHREAD_CONFIG_LOG_PLATFORM
+    va_list args;
+
+    va_start(args, aFormat);
+    Logger::LogVarArgs(kPlatformModuleName, kLogLevelInfo, aFormat, args);
+    va_end(args);
+#else
+    OT_UNUSED_VARIABLE(aFormat);
+#endif
+}
+
+void otLogDebgPlat(const char *aFormat, ...)
+{
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_DEBG) && OPENTHREAD_CONFIG_LOG_PLATFORM
+    va_list args;
+
+    va_start(args, aFormat);
+    Logger::LogVarArgs(kPlatformModuleName, kLogLevelDebg, aFormat, args);
+    va_end(args);
+#else
+    OT_UNUSED_VARIABLE(aFormat);
+#endif
+}
+
+void otDumpCritPlat(const char *aText, const void *aData, uint16_t aDataLength)
+{
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_CRIT) && OPENTHREAD_CONFIG_LOG_PLATFORM && OPENTHREAD_CONFIG_LOG_PKT_DUMP
+    Logger::DumpInModule(kPlatformModuleName, kLogLevelCrit, aText, aData, aDataLength);
+#else
+    OT_UNUSED_VARIABLE(aText);
+    OT_UNUSED_VARIABLE(aData);
+    OT_UNUSED_VARIABLE(aDataLength);
+#endif
+}
+
+void otDumpWarnPlat(const char *aText, const void *aData, uint16_t aDataLength)
+{
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN) && OPENTHREAD_CONFIG_LOG_PLATFORM && OPENTHREAD_CONFIG_LOG_PKT_DUMP
+    Logger::DumpInModule(kPlatformModuleName, kLogLevelWarn, aText, aData, aDataLength);
+#else
+    OT_UNUSED_VARIABLE(aText);
+    OT_UNUSED_VARIABLE(aData);
+    OT_UNUSED_VARIABLE(aDataLength);
+#endif
+}
+
+void otDumpNotePlat(const char *aText, const void *aData, uint16_t aDataLength)
+{
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE) && OPENTHREAD_CONFIG_LOG_PLATFORM && OPENTHREAD_CONFIG_LOG_PKT_DUMP
+    Logger::DumpInModule(kPlatformModuleName, kLogLevelNote, aText, aData, aDataLength);
+#else
+    OT_UNUSED_VARIABLE(aText);
+    OT_UNUSED_VARIABLE(aData);
+    OT_UNUSED_VARIABLE(aDataLength);
+#endif
+}
+
+void otDumpInfoPlat(const char *aText, const void *aData, uint16_t aDataLength)
+{
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) && OPENTHREAD_CONFIG_LOG_PLATFORM && OPENTHREAD_CONFIG_LOG_PKT_DUMP
+    Logger::DumpInModule(kPlatformModuleName, kLogLevelInfo, aText, aData, aDataLength);
+#else
+    OT_UNUSED_VARIABLE(aText);
+    OT_UNUSED_VARIABLE(aData);
+    OT_UNUSED_VARIABLE(aDataLength);
+#endif
+}
+
+void otDumpDebgPlat(const char *aText, const void *aData, uint16_t aDataLength)
+{
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_DEBG) && OPENTHREAD_CONFIG_LOG_PLATFORM && OPENTHREAD_CONFIG_LOG_PKT_DUMP
+    Logger::DumpInModule(kPlatformModuleName, kLogLevelDebg, aText, aData, aDataLength);
+#else
+    OT_UNUSED_VARIABLE(aText);
+    OT_UNUSED_VARIABLE(aData);
+    OT_UNUSED_VARIABLE(aDataLength);
+#endif
+}
+
+void otLogCli(otLogLevel aLogLevel, const char *aFormat, ...)
+{
+#if OT_SHOULD_LOG && OPENTHREAD_CONFIG_LOG_CLI
+    static const char kCliModuleName[] = "Cli";
+
+    va_list args;
+
+    OT_ASSERT(aLogLevel >= kLogLevelNone && aLogLevel <= kLogLevelDebg);
+    VerifyOrExit(aLogLevel >= kLogLevelNone && aLogLevel <= kLogLevelDebg);
+
+    va_start(args, aFormat);
+    Logger::LogVarArgs(kCliModuleName, static_cast<LogLevel>(aLogLevel), aFormat, args);
+    va_end(args);
+exit:
+#else
+    OT_UNUSED_VARIABLE(aLogLevel);
+    OT_UNUSED_VARIABLE(aFormat);
+#endif
+    return;
+}
diff --git a/src/core/api/message_api.cpp b/src/core/api/message_api.cpp
index 81d9baf..ecc3bfc 100644
--- a/src/core/api/message_api.cpp
+++ b/src/core/api/message_api.cpp
@@ -145,61 +145,6 @@
 #if OPENTHREAD_MTD || OPENTHREAD_FTD
 void otMessageGetBufferInfo(otInstance *aInstance, otBufferInfo *aBufferInfo)
 {
-    uint16_t  messages, buffers;
-    Instance &instance = AsCoreType(aInstance);
-
-    aBufferInfo->mTotalBuffers = instance.Get<MessagePool>().GetTotalBufferCount();
-
-    aBufferInfo->mFreeBuffers = instance.Get<MessagePool>().GetFreeBufferCount();
-
-    instance.Get<MeshForwarder>().GetSendQueue().GetInfo(aBufferInfo->m6loSendMessages, aBufferInfo->m6loSendBuffers);
-
-    instance.Get<MeshForwarder>().GetReassemblyQueue().GetInfo(aBufferInfo->m6loReassemblyMessages,
-                                                               aBufferInfo->m6loReassemblyBuffers);
-
-#if OPENTHREAD_FTD
-    instance.Get<MeshForwarder>().GetResolvingQueue().GetInfo(aBufferInfo->mArpMessages, aBufferInfo->mArpBuffers);
-#else
-    aBufferInfo->mArpMessages             = 0;
-    aBufferInfo->mArpBuffers              = 0;
-#endif
-
-    instance.Get<Ip6::Ip6>().GetSendQueue().GetInfo(aBufferInfo->mIp6Messages, aBufferInfo->mIp6Buffers);
-
-#if OPENTHREAD_FTD
-    instance.Get<Ip6::Mpl>().GetBufferedMessageSet().GetInfo(aBufferInfo->mMplMessages, aBufferInfo->mMplBuffers);
-#else
-    aBufferInfo->mMplMessages             = 0;
-    aBufferInfo->mMplBuffers              = 0;
-#endif
-
-    instance.Get<Mle::MleRouter>().GetMessageQueue().GetInfo(aBufferInfo->mMleMessages, aBufferInfo->mMleBuffers);
-
-    instance.Get<Tmf::Agent>().GetRequestMessages().GetInfo(aBufferInfo->mCoapMessages, aBufferInfo->mCoapBuffers);
-    instance.Get<Tmf::Agent>().GetCachedResponses().GetInfo(messages, buffers);
-    aBufferInfo->mCoapMessages += messages;
-    aBufferInfo->mCoapBuffers += buffers;
-
-#if OPENTHREAD_CONFIG_DTLS_ENABLE
-    instance.Get<Coap::CoapSecure>().GetRequestMessages().GetInfo(aBufferInfo->mCoapSecureMessages,
-                                                                  aBufferInfo->mCoapSecureBuffers);
-    instance.Get<Coap::CoapSecure>().GetCachedResponses().GetInfo(messages, buffers);
-    aBufferInfo->mCoapSecureMessages += messages;
-    aBufferInfo->mCoapSecureBuffers += buffers;
-#else
-    aBufferInfo->mCoapSecureMessages      = 0;
-    aBufferInfo->mCoapSecureBuffers       = 0;
-#endif
-
-#if OPENTHREAD_CONFIG_COAP_API_ENABLE
-    instance.GetApplicationCoap().GetRequestMessages().GetInfo(aBufferInfo->mApplicationCoapMessages,
-                                                               aBufferInfo->mApplicationCoapBuffers);
-    instance.GetApplicationCoap().GetCachedResponses().GetInfo(messages, buffers);
-    aBufferInfo->mApplicationCoapMessages += messages;
-    aBufferInfo->mApplicationCoapBuffers += buffers;
-#else
-    aBufferInfo->mApplicationCoapMessages = 0;
-    aBufferInfo->mApplicationCoapBuffers  = 0;
-#endif
+    AsCoreType(aInstance).GetBufferInfo(AsCoreType(aBufferInfo));
 }
 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
diff --git a/src/core/api/netdata_api.cpp b/src/core/api/netdata_api.cpp
index de24242..c28b987 100644
--- a/src/core/api/netdata_api.cpp
+++ b/src/core/api/netdata_api.cpp
@@ -42,7 +42,8 @@
 
 otError otNetDataGet(otInstance *aInstance, bool aStable, uint8_t *aData, uint8_t *aDataLength)
 {
-    return AsCoreType(aInstance).Get<NetworkData::Leader>().CopyNetworkData(aStable, aData, *aDataLength);
+    return AsCoreType(aInstance).Get<NetworkData::Leader>().CopyNetworkData(
+        aStable ? NetworkData::kStableSubset : NetworkData::kFullSet, aData, *aDataLength);
 }
 
 otError otNetDataGetNextOnMeshPrefix(otInstance *           aInstance,
@@ -59,6 +60,13 @@
     return error;
 }
 
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+bool otNetDataContainsOmrPrefix(otInstance *aInstance, const otIp6Prefix *aPrefix)
+{
+    return AsCoreType(aInstance).Get<NetworkData::Leader>().ContainsOmrPrefix(AsCoreType(aPrefix));
+}
+#endif
+
 otError otNetDataGetNextRoute(otInstance *aInstance, otNetworkDataIterator *aIterator, otExternalRouteConfig *aConfig)
 {
     Error error = kErrorNone;
@@ -85,12 +93,12 @@
 
 uint8_t otNetDataGetVersion(otInstance *aInstance)
 {
-    return AsCoreType(aInstance).Get<Mle::MleRouter>().GetLeaderData().GetDataVersion();
+    return AsCoreType(aInstance).Get<Mle::MleRouter>().GetLeaderData().GetDataVersion(NetworkData::kFullSet);
 }
 
 uint8_t otNetDataGetStableVersion(otInstance *aInstance)
 {
-    return AsCoreType(aInstance).Get<Mle::MleRouter>().GetLeaderData().GetStableDataVersion();
+    return AsCoreType(aInstance).Get<Mle::MleRouter>().GetLeaderData().GetDataVersion(NetworkData::kStableSubset);
 }
 
 otError otNetDataSteeringDataCheckJoiner(otInstance *aInstance, const otExtAddress *aEui64)
diff --git a/src/core/api/random_crypto_api.cpp b/src/core/api/random_crypto_api.cpp
index 08797e8..906a4a0 100644
--- a/src/core/api/random_crypto_api.cpp
+++ b/src/core/api/random_crypto_api.cpp
@@ -43,8 +43,3 @@
 {
     return Random::Crypto::FillBuffer(aBuffer, aSize);
 }
-
-mbedtls_ctr_drbg_context *otRandomCryptoMbedTlsContextGet(void)
-{
-    return Random::Crypto::MbedTlsContextGet();
-}
diff --git a/src/core/api/server_api.cpp b/src/core/api/server_api.cpp
index bf08e9c..b1712f1 100644
--- a/src/core/api/server_api.cpp
+++ b/src/core/api/server_api.cpp
@@ -44,7 +44,8 @@
 
 otError otServerGetNetDataLocal(otInstance *aInstance, bool aStable, uint8_t *aData, uint8_t *aDataLength)
 {
-    return AsCoreType(aInstance).Get<NetworkData::Local>().CopyNetworkData(aStable, aData, *aDataLength);
+    return AsCoreType(aInstance).Get<NetworkData::Local>().CopyNetworkData(
+        aStable ? NetworkData::kStableSubset : NetworkData::kFullSet, aData, *aDataLength);
 }
 
 otError otServerAddService(otInstance *aInstance, const otServiceConfig *aConfig)
diff --git a/src/core/api/srp_client_api.cpp b/src/core/api/srp_client_api.cpp
index 304a2fe..3ec356f 100644
--- a/src/core/api/srp_client_api.cpp
+++ b/src/core/api/srp_client_api.cpp
@@ -84,6 +84,16 @@
 }
 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
 
+uint32_t otSrpClientGetTtl(otInstance *aInstance)
+{
+    return AsCoreType(aInstance).Get<Srp::Client>().GetTtl();
+}
+
+void otSrpClientSetTtl(otInstance *aInstance, uint32_t aTtl)
+{
+    return AsCoreType(aInstance).Get<Srp::Client>().SetTtl(aTtl);
+}
+
 uint32_t otSrpClientGetLeaseInterval(otInstance *aInstance)
 {
     return AsCoreType(aInstance).Get<Srp::Client>().GetLeaseInterval();
@@ -114,6 +124,11 @@
     return AsCoreType(aInstance).Get<Srp::Client>().SetHostName(aName);
 }
 
+otError otSrpClientEnableAutoHostAddress(otInstance *aInstance)
+{
+    return AsCoreType(aInstance).Get<Srp::Client>().EnableAutoHostAddress();
+}
+
 otError otSrpClientSetHostAddresses(otInstance *aInstance, const otIp6Address *aIp6Addresses, uint8_t aNumAddresses)
 {
     return AsCoreType(aInstance).Get<Srp::Client>().SetHostAddresses(AsCoreTypePtr(aIp6Addresses), aNumAddresses);
diff --git a/src/core/api/srp_server_api.cpp b/src/core/api/srp_server_api.cpp
index 8c59319..f9d4367 100644
--- a/src/core/api/srp_server_api.cpp
+++ b/src/core/api/srp_server_api.cpp
@@ -57,6 +57,11 @@
     return MapEnum(AsCoreType(aInstance).Get<Srp::Server>().GetState());
 }
 
+uint16_t otSrpServerGetPort(otInstance *aInstance)
+{
+    return AsCoreType(aInstance).Get<Srp::Server>().GetPort();
+}
+
 otSrpServerAddressMode otSrpServerGetAddressMode(otInstance *aInstance)
 {
     return MapEnum(AsCoreType(aInstance).Get<Srp::Server>().GetAddressMode());
@@ -82,6 +87,16 @@
     AsCoreType(aInstance).Get<Srp::Server>().SetEnabled(aEnabled);
 }
 
+void otSrpServerGetTtlConfig(otInstance *aInstance, otSrpServerTtlConfig *aTtlConfig)
+{
+    AsCoreType(aInstance).Get<Srp::Server>().GetTtlConfig(AsCoreType(aTtlConfig));
+}
+
+otError otSrpServerSetTtlConfig(otInstance *aInstance, const otSrpServerTtlConfig *aTtlConfig)
+{
+    return AsCoreType(aInstance).Get<Srp::Server>().SetTtlConfig(AsCoreType(aTtlConfig));
+}
+
 void otSrpServerGetLeaseConfig(otInstance *aInstance, otSrpServerLeaseConfig *aLeaseConfig)
 {
     AsCoreType(aInstance).Get<Srp::Server>().GetLeaseConfig(AsCoreType(aLeaseConfig));
@@ -109,6 +124,11 @@
     return AsCoreType(aInstance).Get<Srp::Server>().GetNextHost(AsCoreTypePtr(aHost));
 }
 
+const otSrpServerResponseCounters *otSrpServerGetResponseCounters(otInstance *aInstance)
+{
+    return AsCoreType(aInstance).Get<Srp::Server>().GetResponseCounters();
+}
+
 bool otSrpServerHostIsDeleted(const otSrpServerHost *aHost)
 {
     return AsCoreType(aHost).IsDeleted();
@@ -124,6 +144,16 @@
     return AsCoreType(aHost).GetAddresses(*aAddressesNum);
 }
 
+void otSrpServerHostGetLeaseInfo(const otSrpServerHost *aHost, otSrpServerLeaseInfo *aLeaseInfo)
+{
+    AsCoreType(aHost).GetLeaseInfo(*aLeaseInfo);
+}
+
+uint32_t otSrpServerHostGetKeyLease(const otSrpServerHost *aHost)
+{
+    return AsCoreType(aHost).GetKeyLease();
+}
+
 const otSrpServerService *otSrpServerHostGetNextService(const otSrpServerHost *   aHost,
                                                         const otSrpServerService *aService)
 {
@@ -184,6 +214,11 @@
     return AsCoreType(aService).GetPriority();
 }
 
+uint32_t otSrpServerServiceGetTtl(const otSrpServerService *aService)
+{
+    return AsCoreType(aService).GetTtl();
+}
+
 const uint8_t *otSrpServerServiceGetTxtData(const otSrpServerService *aService, uint16_t *aDataLength)
 {
     *aDataLength = AsCoreType(aService).GetTxtDataLength();
@@ -196,4 +231,9 @@
     return &AsCoreType(aService).GetHost();
 }
 
+void otSrpServerServiceGetLeaseInfo(const otSrpServerService *aService, otSrpServerLeaseInfo *aLeaseInfo)
+{
+    AsCoreType(aService).GetLeaseInfo(*aLeaseInfo);
+}
+
 #endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
diff --git a/src/core/api/tasklet_api.cpp b/src/core/api/tasklet_api.cpp
index 6f8a0de..e5213c8 100644
--- a/src/core/api/tasklet_api.cpp
+++ b/src/core/api/tasklet_api.cpp
@@ -38,7 +38,6 @@
 #include "common/as_core_type.hpp"
 #include "common/code_utils.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
 
 using namespace ot;
 
diff --git a/src/core/api/tcp_api.cpp b/src/core/api/tcp_api.cpp
index 62a1de5..896aac6 100644
--- a/src/core/api/tcp_api.cpp
+++ b/src/core/api/tcp_api.cpp
@@ -42,7 +42,9 @@
 
 using namespace ot;
 
-otError otTcpEndpointInitialize(otInstance *aInstance, otTcpEndpoint *aEndpoint, otTcpEndpointInitializeArgs *aArgs)
+otError otTcpEndpointInitialize(otInstance *                       aInstance,
+                                otTcpEndpoint *                    aEndpoint,
+                                const otTcpEndpointInitializeArgs *aArgs)
 {
     return AsCoreType(aEndpoint).Initialize(AsCoreType(aInstance), *aArgs);
 }
@@ -87,7 +89,7 @@
     return AsCoreType(aEndpoint).SendByExtension(aNumBytes, aFlags);
 }
 
-otError otTcpReceiveByReference(const otTcpEndpoint *aEndpoint, const otLinkedBuffer **aBuffer)
+otError otTcpReceiveByReference(otTcpEndpoint *aEndpoint, const otLinkedBuffer **aBuffer)
 {
     return AsCoreType(aEndpoint).ReceiveByReference(*aBuffer);
 }
@@ -117,7 +119,9 @@
     return AsCoreType(aEndpoint).Deinitialize();
 }
 
-otError otTcpListenerInitialize(otInstance *aInstance, otTcpListener *aListener, otTcpListenerInitializeArgs *aArgs)
+otError otTcpListenerInitialize(otInstance *                       aInstance,
+                                otTcpListener *                    aListener,
+                                const otTcpListenerInitializeArgs *aArgs)
 {
     return AsCoreType(aListener).Initialize(AsCoreType(aInstance), *aArgs);
 }
diff --git a/src/core/api/thread_api.cpp b/src/core/api/thread_api.cpp
index 9ebafa9..bec8c06 100644
--- a/src/core/api/thread_api.cpp
+++ b/src/core/api/thread_api.cpp
@@ -55,25 +55,21 @@
 
 const otExtendedPanId *otThreadGetExtendedPanId(otInstance *aInstance)
 {
-    return &AsCoreType(aInstance).Get<Mac::Mac>().GetExtendedPanId();
+    return &AsCoreType(aInstance).Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId();
 }
 
 otError otThreadSetExtendedPanId(otInstance *aInstance, const otExtendedPanId *aExtendedPanId)
 {
-    Error                     error    = kErrorNone;
-    Instance &                instance = AsCoreType(aInstance);
-    const Mac::ExtendedPanId &extPanId = AsCoreType(aExtendedPanId);
-    Mle::MeshLocalPrefix      prefix;
+    Error                         error    = kErrorNone;
+    Instance &                    instance = AsCoreType(aInstance);
+    const MeshCoP::ExtendedPanId &extPanId = AsCoreType(aExtendedPanId);
 
     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
 
-    instance.Get<Mac::Mac>().SetExtendedPanId(extPanId);
+    instance.Get<MeshCoP::ExtendedPanIdManager>().SetExtPanId(extPanId);
 
-    prefix.SetFromExtendedPanId(extPanId);
-    instance.Get<Mle::MleRouter>().SetMeshLocalPrefix(prefix);
-
-    instance.Get<MeshCoP::ActiveDataset>().Clear();
-    instance.Get<MeshCoP::PendingDataset>().Clear();
+    instance.Get<MeshCoP::ActiveDatasetManager>().Clear();
+    instance.Get<MeshCoP::PendingDatasetManager>().Clear();
 
 exit:
     return error;
@@ -123,8 +119,8 @@
 
     instance.Get<KeyManager>().SetNetworkKey(AsCoreType(aKey));
 
-    instance.Get<MeshCoP::ActiveDataset>().Clear();
-    instance.Get<MeshCoP::PendingDataset>().Clear();
+    instance.Get<MeshCoP::ActiveDatasetManager>().Clear();
+    instance.Get<MeshCoP::PendingDatasetManager>().Clear();
 
 exit:
     return error;
@@ -141,8 +137,8 @@
     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
 
     instance.Get<KeyManager>().SetNetworkKeyRef((aKeyRef));
-    instance.Get<MeshCoP::ActiveDataset>().Clear();
-    instance.Get<MeshCoP::PendingDataset>().Clear();
+    instance.Get<MeshCoP::ActiveDatasetManager>().Clear();
+    instance.Get<MeshCoP::PendingDatasetManager>().Clear();
 
 exit:
     return error;
@@ -171,8 +167,8 @@
     VerifyOrExit(AsCoreType(aInstance).Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
 
     AsCoreType(aInstance).Get<Mle::MleRouter>().SetMeshLocalPrefix(AsCoreType(aMeshLocalPrefix));
-    AsCoreType(aInstance).Get<MeshCoP::ActiveDataset>().Clear();
-    AsCoreType(aInstance).Get<MeshCoP::PendingDataset>().Clear();
+    AsCoreType(aInstance).Get<MeshCoP::ActiveDatasetManager>().Clear();
+    AsCoreType(aInstance).Get<MeshCoP::PendingDatasetManager>().Clear();
 
 exit:
     return error;
@@ -200,7 +196,7 @@
 
 const char *otThreadGetNetworkName(otInstance *aInstance)
 {
-    return AsCoreType(aInstance).Get<Mac::Mac>().GetNetworkName().GetAsCString();
+    return AsCoreType(aInstance).Get<MeshCoP::NetworkNameManager>().GetNetworkName().GetAsCString();
 }
 
 otError otThreadSetNetworkName(otInstance *aInstance, const char *aNetworkName)
@@ -209,9 +205,9 @@
 
     VerifyOrExit(AsCoreType(aInstance).Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
 
-    error = AsCoreType(aInstance).Get<Mac::Mac>().SetNetworkName(aNetworkName);
-    AsCoreType(aInstance).Get<MeshCoP::ActiveDataset>().Clear();
-    AsCoreType(aInstance).Get<MeshCoP::PendingDataset>().Clear();
+    error = AsCoreType(aInstance).Get<MeshCoP::NetworkNameManager>().SetNetworkName(aNetworkName);
+    AsCoreType(aInstance).Get<MeshCoP::ActiveDatasetManager>().Clear();
+    AsCoreType(aInstance).Get<MeshCoP::PendingDatasetManager>().Clear();
 
 exit:
     return error;
@@ -220,7 +216,7 @@
 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
 const char *otThreadGetDomainName(otInstance *aInstance)
 {
-    return AsCoreType(aInstance).Get<Mac::Mac>().GetDomainName().GetAsCString();
+    return AsCoreType(aInstance).Get<MeshCoP::NetworkNameManager>().GetDomainName().GetAsCString();
 }
 
 otError otThreadSetDomainName(otInstance *aInstance, const char *aDomainName)
@@ -229,7 +225,7 @@
 
     VerifyOrExit(AsCoreType(aInstance).Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
 
-    error = AsCoreType(aInstance).Get<Mac::Mac>().SetDomainName(aDomainName);
+    error = AsCoreType(aInstance).Get<MeshCoP::NetworkNameManager>().SetDomainName(aDomainName);
 
 exit:
     return error;
@@ -295,7 +291,7 @@
 
 otError otThreadBecomeChild(otInstance *aInstance)
 {
-    return AsCoreType(aInstance).Get<Mle::MleRouter>().BecomeChild(Mle::kAttachAny);
+    return AsCoreType(aInstance).Get<Mle::MleRouter>().BecomeChild();
 }
 
 otError otThreadGetNextNeighborInfo(otInstance *aInstance, otNeighborInfoIterator *aIterator, otNeighborInfo *aInfo)
@@ -501,4 +497,9 @@
 }
 #endif
 
+otError otThreadDetachGracefully(otInstance *aInstance, otDetachGracefullyCallback aCallback, void *aContext)
+{
+    return AsCoreType(aInstance).Get<Mle::MleRouter>().DetachGracefully(aCallback, aContext);
+}
+
 #endif // OPENTHREAD_FTD || OPENTHREAD_MTD
diff --git a/src/core/api/thread_ftd_api.cpp b/src/core/api/thread_ftd_api.cpp
index d96c11f..e8d3a4b 100644
--- a/src/core/api/thread_ftd_api.cpp
+++ b/src/core/api/thread_ftd_api.cpp
@@ -296,8 +296,8 @@
     VerifyOrExit(AsCoreType(aInstance).Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
 
     AsCoreType(aInstance).Get<KeyManager>().SetPskc(AsCoreType(aPskc));
-    AsCoreType(aInstance).Get<MeshCoP::ActiveDataset>().Clear();
-    AsCoreType(aInstance).Get<MeshCoP::PendingDataset>().Clear();
+    AsCoreType(aInstance).Get<MeshCoP::ActiveDatasetManager>().Clear();
+    AsCoreType(aInstance).Get<MeshCoP::PendingDatasetManager>().Clear();
 
 exit:
     return error;
@@ -313,8 +313,8 @@
     VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
 
     instance.Get<KeyManager>().SetPskcRef(aKeyRef);
-    instance.Get<MeshCoP::ActiveDataset>().Clear();
-    instance.Get<MeshCoP::PendingDataset>().Clear();
+    instance.Get<MeshCoP::ActiveDatasetManager>().Clear();
+    instance.Get<MeshCoP::PendingDatasetManager>().Clear();
 
 exit:
     return error;
@@ -368,6 +368,23 @@
 {
     AsCoreType(aInstance).Get<Mle::MleRouter>().SetCcmEnabled(aEnabled);
 }
+
+void otThreadSetThreadVersionCheckEnabled(otInstance *aInstance, bool aEnabled)
+{
+    AsCoreType(aInstance).Get<Mle::MleRouter>().SetThreadVersionCheckEnabled(aEnabled);
+}
+#endif
+
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+void otThreadGetRouterIdRange(otInstance *aInstance, uint8_t *aMinRouterId, uint8_t *aMaxRouterId)
+{
+    AsCoreType(aInstance).Get<RouterTable>().GetRouterIdRange(*aMinRouterId, *aMaxRouterId);
+}
+
+otError otThreadSetRouterIdRange(otInstance *aInstance, uint8_t aMinRouterId, uint8_t aMaxRouterId)
+{
+    return AsCoreType(aInstance).Get<RouterTable>().SetRouterIdRange(aMinRouterId, aMaxRouterId);
+}
 #endif
 
 #endif // OPENTHREAD_FTD
diff --git a/src/core/api/trel_api.cpp b/src/core/api/trel_api.cpp
new file mode 100644
index 0000000..01feb25
--- /dev/null
+++ b/src/core/api/trel_api.cpp
@@ -0,0 +1,81 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file implements the OpenThread TREL (Thread Radio Encapsulation Link) APIs for Thread Over Infrastructure.
+ */
+
+#include "openthread-core-config.h"
+
+#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
+
+#include <openthread/trel.h>
+
+#include "common/as_core_type.hpp"
+#include "common/code_utils.hpp"
+#include "common/instance.hpp"
+
+using namespace ot;
+
+void otTrelEnable(otInstance *aInstance)
+{
+    AsCoreType(aInstance).Get<Trel::Interface>().Enable();
+}
+
+void otTrelDisable(otInstance *aInstance)
+{
+    AsCoreType(aInstance).Get<Trel::Interface>().Disable();
+}
+
+bool otTrelIsEnabled(otInstance *aInstance)
+{
+    return AsCoreType(aInstance).Get<Trel::Interface>().IsEnabled();
+}
+
+void otTrelInitPeerIterator(otInstance *aInstance, otTrelPeerIterator *aIterator)
+{
+    AsCoreType(aInstance).Get<Trel::Interface>().InitIterator(*aIterator);
+}
+
+const otTrelPeer *otTrelGetNextPeer(otInstance *aInstance, otTrelPeerIterator *aIterator)
+{
+    return AsCoreType(aInstance).Get<Trel::Interface>().GetNextPeer(*aIterator);
+}
+
+void otTrelSetFilterEnabled(otInstance *aInstance, bool aEnable)
+{
+    AsCoreType(aInstance).Get<Trel::Interface>().SetFilterEnabled(aEnable);
+}
+
+bool otTrelIsFilterEnabled(otInstance *aInstance)
+{
+    return AsCoreType(aInstance).Get<Trel::Interface>().IsFilterEnabled();
+}
+
+#endif // OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
diff --git a/src/core/backbone_router/backbone_tmf.cpp b/src/core/backbone_router/backbone_tmf.cpp
index cde9d46..293793f 100644
--- a/src/core/backbone_router/backbone_tmf.cpp
+++ b/src/core/backbone_router/backbone_tmf.cpp
@@ -36,11 +36,13 @@
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
 
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 
 namespace ot {
 namespace BackboneRouter {
 
+RegisterLogModule("Bbr");
+
 Error BackboneTmfAgent::Start(void)
 {
     Error error = kErrorNone;
@@ -77,20 +79,31 @@
 
 void BackboneTmfAgent::SubscribeMulticast(const Ip6::Address &aAddress)
 {
-    Error error;
+    Error error = mSocket.JoinNetifMulticastGroup(OT_NETIF_BACKBONE, aAddress);
 
-    error = mSocket.JoinNetifMulticastGroup(OT_NETIF_BACKBONE, aAddress);
-
-    otLogResultBbr(error, "Backbone TMF subscribes %s", aAddress.ToString().AsCString());
+    LogError("Backbone TMF subscribes", aAddress, error);
 }
 
 void BackboneTmfAgent::UnsubscribeMulticast(const Ip6::Address &aAddress)
 {
-    Error error;
+    Error error = mSocket.LeaveNetifMulticastGroup(OT_NETIF_BACKBONE, aAddress);
 
-    error = mSocket.LeaveNetifMulticastGroup(OT_NETIF_BACKBONE, aAddress);
+    LogError("Backbone TMF unsubscribes", aAddress, error);
+}
 
-    otLogResultBbr(error, "Backbone TMF unsubscribes %s", aAddress.ToString().AsCString());
+void BackboneTmfAgent::LogError(const char *aText, const Ip6::Address &aAddress, Error aError) const
+{
+    OT_UNUSED_VARIABLE(aText);
+    OT_UNUSED_VARIABLE(aAddress);
+
+    if (aError == kErrorNone)
+    {
+        LogInfo("%s %s: %s", aText, aAddress.ToString().AsCString(), ErrorToString(aError));
+    }
+    else
+    {
+        LogWarn("%s %s: %s", aText, aAddress.ToString().AsCString(), ErrorToString(aError));
+    }
 }
 
 } // namespace BackboneRouter
diff --git a/src/core/backbone_router/backbone_tmf.hpp b/src/core/backbone_router/backbone_tmf.hpp
index 31d6ce6..0720f05 100644
--- a/src/core/backbone_router/backbone_tmf.hpp
+++ b/src/core/backbone_router/backbone_tmf.hpp
@@ -99,6 +99,7 @@
     void UnsubscribeMulticast(const Ip6::Address &aAddress);
 
 private:
+    void         LogError(const char *aText, const Ip6::Address &aAddress, Error aError) const;
     static Error Filter(const ot::Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext);
 };
 
diff --git a/src/core/backbone_router/bbr_leader.cpp b/src/core/backbone_router/bbr_leader.cpp
index 282073a..4b64fff 100644
--- a/src/core/backbone_router/bbr_leader.cpp
+++ b/src/core/backbone_router/bbr_leader.cpp
@@ -37,11 +37,12 @@
 
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
 
 namespace ot {
 namespace BackboneRouter {
 
+RegisterLogModule("BbrLeader");
+
 Leader::Leader(Instance &aInstance)
     : InstanceLocator(aInstance)
 {
@@ -81,92 +82,67 @@
     return error;
 }
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_BBR == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
+
 void Leader::LogBackboneRouterPrimary(State aState, const BackboneRouterConfig &aConfig) const
 {
     OT_UNUSED_VARIABLE(aConfig);
 
-    otLogInfoBbr("PBBR state: %s", StateToString(aState));
+    LogInfo("PBBR state: %s", StateToString(aState));
 
     if (aState != kStateRemoved && aState != kStateNone)
     {
-        otLogInfoBbr("Rloc16: 0x%4X, seqno: %d, delay: %d, timeout %d", aConfig.mServer16, aConfig.mSequenceNumber,
-                     aConfig.mReregistrationDelay, aConfig.mMlrTimeout);
+        LogInfo("Rloc16: 0x%4X, seqno: %d, delay: %d, timeout %d", aConfig.mServer16, aConfig.mSequenceNumber,
+                aConfig.mReregistrationDelay, aConfig.mMlrTimeout);
     }
 }
 
 void Leader::LogDomainPrefix(DomainPrefixState aState, const Ip6::Prefix &aPrefix) const
 {
-    otLogInfoBbr("Domain Prefix: %s, state: %s", aPrefix.ToString().AsCString(), DomainPrefixStateToString(aState));
+    LogInfo("Domain Prefix: %s, state: %s", aPrefix.ToString().AsCString(), DomainPrefixStateToString(aState));
 }
 
 const char *Leader::StateToString(State aState)
 {
-    const char *logString = "Unknown";
+    static const char *const kStateStrings[] = {
+        "None",            //  (0) kStateNone
+        "Added",           //  (1) kStateAdded
+        "Removed",         //  (2) kStateRemoved
+        "Rereg triggered", //  (3) kStateToTriggerRereg
+        "Refreshed",       //  (4) kStateRefreshed
+        "Unchanged",       //  (5) kStateUnchanged
+    };
 
-    switch (aState)
-    {
-    case kStateNone:
-        logString = "None";
-        break;
+    static_assert(0 == kStateNone, "kStateNone value is incorrect");
+    static_assert(1 == kStateAdded, "kStateAdded value is incorrect");
+    static_assert(2 == kStateRemoved, "kStateRemoved value is incorrect");
+    static_assert(3 == kStateToTriggerRereg, "kStateToTriggerRereg value is incorrect");
+    static_assert(4 == kStateRefreshed, "kStateRefreshed value is incorrect");
+    static_assert(5 == kStateUnchanged, "kStateUnchanged value is incorrect");
 
-    case kStateAdded:
-        logString = "Added";
-        break;
-
-    case kStateRemoved:
-        logString = "Removed";
-        break;
-
-    case kStateToTriggerRereg:
-        logString = "Rereg triggered";
-        break;
-
-    case kStateRefreshed:
-        logString = "Refreshed";
-        break;
-
-    case kStateUnchanged:
-        logString = "Unchanged";
-        break;
-
-    default:
-        break;
-    }
-
-    return logString;
+    return kStateStrings[aState];
 }
 
 const char *Leader::DomainPrefixStateToString(DomainPrefixState aState)
 {
-    const char *logString = "Unknown";
+    static const char *const kPrefixStateStrings[] = {
+        "None",      // (0) kDomainPrefixNone
+        "Added",     // (1) kDomainPrefixAdded
+        "Removed",   // (2) kDomainPrefixRemoved
+        "Refreshed", // (3) kDomainPrefixRefreshed
+        "Unchanged", // (4) kDomainPrefixUnchanged
+    };
 
-    switch (aState)
-    {
-    case kDomainPrefixNone:
-        logString = "None";
-        break;
+    static_assert(0 == kDomainPrefixNone, "kDomainPrefixNone value is incorrect");
+    static_assert(1 == kDomainPrefixAdded, "kDomainPrefixAdded value is incorrect");
+    static_assert(2 == kDomainPrefixRemoved, "kDomainPrefixRemoved value is incorrect");
+    static_assert(3 == kDomainPrefixRefreshed, "kDomainPrefixRefreshed value is incorrect");
+    static_assert(4 == kDomainPrefixUnchanged, "kDomainPrefixUnchanged value is incorrect");
 
-    case kDomainPrefixAdded:
-        logString = "Added";
-        break;
-
-    case kDomainPrefixRemoved:
-        logString = "Removed";
-        break;
-
-    case kDomainPrefixRefreshed:
-        logString = "Refreshed";
-        break;
-
-    case kDomainPrefixUnchanged:
-        logString = "Unchanged";
-        break;
-    }
-
-    return logString;
+    return kPrefixStateStrings[aState];
 }
-#endif
+
+#endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
 void Leader::Update(void)
 {
@@ -229,7 +205,7 @@
 
         if (config.mMlrTimeout != origMlrTimeout)
         {
-            otLogNoteBbr("Leader MLR Timeout is normalized from %u to %u", origMlrTimeout, config.mMlrTimeout);
+            LogNote("Leader MLR Timeout is normalized from %u to %u", origMlrTimeout, config.mMlrTimeout);
         }
     }
 
diff --git a/src/core/backbone_router/bbr_leader.hpp b/src/core/backbone_router/bbr_leader.hpp
index 823d619..6266d02 100644
--- a/src/core/backbone_router/bbr_leader.hpp
+++ b/src/core/backbone_router/bbr_leader.hpp
@@ -44,6 +44,7 @@
 #include "coap/coap.hpp"
 #include "coap/coap_message.hpp"
 #include "common/locator.hpp"
+#include "common/log.hpp"
 #include "common/non_copyable.hpp"
 #include "net/ip6_address.hpp"
 
@@ -175,7 +176,7 @@
 private:
     void UpdateBackboneRouterPrimary(void);
     void UpdateDomainPrefixConfig(void);
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_BBR == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
     void               LogBackboneRouterPrimary(State aState, const BackboneRouterConfig &aConfig) const;
     void               LogDomainPrefix(DomainPrefixState aState, const Ip6::Prefix &aPrefix) const;
     static const char *StateToString(State aState);
diff --git a/src/core/backbone_router/bbr_local.cpp b/src/core/backbone_router/bbr_local.cpp
index b21f7c9..4c7945a 100644
--- a/src/core/backbone_router/bbr_local.cpp
+++ b/src/core/backbone_router/bbr_local.cpp
@@ -38,7 +38,7 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/random.hpp"
 #include "thread/mle_types.hpp"
 #include "thread/thread_netif.hpp"
@@ -47,12 +47,14 @@
 
 namespace BackboneRouter {
 
+RegisterLogModule("BbrLocal");
+
 Local::Local(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mState(OT_BACKBONE_ROUTER_STATE_DISABLED)
     , mMlrTimeout(Mle::kMlrTimeoutDefault)
     , mReregistrationDelay(Mle::kRegistrationDelayDefault)
-    , mSequenceNumber(Random::NonCrypto::GetUint8())
+    , mSequenceNumber(Random::NonCrypto::GetUint8() % 127)
     , mRegistrationJitter(Mle::kBackboneRouterRegistrationJitter)
     , mIsServiceAdded(false)
     , mDomainPrefixCallback(nullptr)
@@ -109,7 +111,7 @@
     if (mState == OT_BACKBONE_ROUTER_STATE_PRIMARY)
     {
         // Increase sequence number when changing from Primary to Secondary.
-        mSequenceNumber++;
+        SequenceNumberIncrease();
         Get<Notifier>().Signal(kEventThreadBackboneRouterLocalChanged);
         SetState(OT_BACKBONE_ROUTER_STATE_SECONDARY);
     }
@@ -130,8 +132,10 @@
     Error error  = kErrorNone;
     bool  update = false;
 
+#if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
     VerifyOrExit(aConfig.mMlrTimeout >= Mle::kMlrTimeoutMin && aConfig.mMlrTimeout <= Mle::kMlrTimeoutMax,
                  error = kErrorInvalidArgs);
+#endif
     // Validate configuration according to Thread 1.2.1 Specification 5.21.3.3:
     // "The Reregistration Delay in seconds MUST be lower than (0.5 * MLR Timeout). It MUST be at least 1."
     VerifyOrExit(aConfig.mReregistrationDelay >= 1, error = kErrorInvalidArgs);
@@ -265,9 +269,10 @@
     {
         // Here original PBBR restores its Backbone Router Service from Thread Network,
         // Intentionally skips the state update as PBBR will refresh its service.
-        mSequenceNumber      = aConfig.mSequenceNumber + 1;
+        mSequenceNumber      = aConfig.mSequenceNumber;
         mReregistrationDelay = aConfig.mReregistrationDelay;
         mMlrTimeout          = aConfig.mMlrTimeout;
+        SequenceNumberIncrease();
         Get<Notifier>().Signal(kEventThreadBackboneRouterLocalChanged);
         if (AddService(true /* Force registration to refresh and restore Primary state */) == kErrorNone)
         {
@@ -410,6 +415,24 @@
     LogDomainPrefix("Remove", error);
 }
 
+void Local::SequenceNumberIncrease(void)
+{
+    switch (mSequenceNumber)
+    {
+    case 126:
+    case 127:
+        mSequenceNumber = 0;
+        break;
+    case 254:
+    case 255:
+        mSequenceNumber = 128;
+        break;
+    default:
+        mSequenceNumber++;
+        break;
+    }
+}
+
 void Local::AddDomainPrefixToNetworkData(void)
 {
     Error error = kErrorNotFound; // only used for logging.
@@ -422,17 +445,17 @@
     LogDomainPrefix("Add", error);
 }
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_BBR == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 void Local::LogDomainPrefix(const char *aAction, Error aError)
 {
-    otLogInfoBbr("%s Domain Prefix: %s, %s", aAction, mDomainPrefixConfig.GetPrefix().ToString().AsCString(),
-                 ErrorToString(aError));
+    LogInfo("%s Domain Prefix: %s, %s", aAction, mDomainPrefixConfig.GetPrefix().ToString().AsCString(),
+            ErrorToString(aError));
 }
 
 void Local::LogBackboneRouterService(const char *aAction, Error aError)
 {
-    otLogInfoBbr("%s BBR Service: seqno (%d), delay (%ds), timeout (%ds), %s", aAction, mSequenceNumber,
-                 mReregistrationDelay, mMlrTimeout, ErrorToString(aError));
+    LogInfo("%s BBR Service: seqno (%d), delay (%ds), timeout (%ds), %s", aAction, mSequenceNumber,
+            mReregistrationDelay, mMlrTimeout, ErrorToString(aError));
 }
 #endif
 
diff --git a/src/core/backbone_router/bbr_local.hpp b/src/core/backbone_router/bbr_local.hpp
index 9587969..b7a76f3 100644
--- a/src/core/backbone_router/bbr_local.hpp
+++ b/src/core/backbone_router/bbr_local.hpp
@@ -55,6 +55,7 @@
 
 #include "backbone_router/bbr_leader.hpp"
 #include "common/locator.hpp"
+#include "common/log.hpp"
 #include "common/non_copyable.hpp"
 #include "net/netif.hpp"
 #include "thread/network_data.hpp"
@@ -259,7 +260,8 @@
     void RemoveService(void);
     void AddDomainPrefixToNetworkData(void);
     void RemoveDomainPrefixFromNetworkData(void);
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_BBR == 1)
+    void SequenceNumberIncrease(void);
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
     void LogBackboneRouterService(const char *aAction, Error aError);
     void LogDomainPrefix(const char *aAction, Error aError);
 #else
diff --git a/src/core/backbone_router/bbr_manager.cpp b/src/core/backbone_router/bbr_manager.cpp
index f5c3c60..2de2f6f 100644
--- a/src/core/backbone_router/bbr_manager.cpp
+++ b/src/core/backbone_router/bbr_manager.cpp
@@ -39,7 +39,7 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/random.hpp"
 #include "thread/mle_types.hpp"
 #include "thread/thread_netif.hpp"
@@ -50,6 +50,8 @@
 
 namespace BackboneRouter {
 
+RegisterLogModule("BbrManager");
+
 Manager::Manager(Instance &aInstance)
     : InstanceLocator(aInstance)
 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
@@ -108,11 +110,11 @@
 
             if (error != kErrorNone)
             {
-                otLogWarnBbr("Stop Backbone TMF agent: %s", ErrorToString(error));
+                LogWarn("Stop Backbone TMF agent: %s", ErrorToString(error));
             }
             else
             {
-                otLogInfoBbr("Stop Backbone TMF agent: %s", ErrorToString(error));
+                LogInfo("Stop Backbone TMF agent: %s", ErrorToString(error));
             }
         }
         else
@@ -130,7 +132,7 @@
 
             error = mBackboneTmfAgent.Start();
 
-            otLogResultBbr(error, "Start Backbone TMF agent");
+            LogError("Start Backbone TMF agent", error);
         }
     }
 }
@@ -163,7 +165,7 @@
 
     uint16_t     addressesOffset, addressesLength;
     Ip6::Address address;
-    Ip6::Address addresses[kIp6AddressesNumMax];
+    Ip6::Address addresses[Ip6AddressesTlv::kMaxAddresses];
     uint8_t      failedAddressNum  = 0;
     uint8_t      successAddressNum = 0;
     TimeMilli    expireTime;
@@ -189,9 +191,8 @@
 
     if (Tlv::Find<ThreadCommissionerSessionIdTlv>(aMessage, commissionerSessionId) == kErrorNone)
     {
-        const MeshCoP::CommissionerSessionIdTlv *commissionerSessionIdTlv =
-            static_cast<const MeshCoP::CommissionerSessionIdTlv *>(
-                Get<NetworkData::Leader>().GetCommissioningDataSubTlv(MeshCoP::Tlv::kCommissionerSessionId));
+        const MeshCoP::CommissionerSessionIdTlv *commissionerSessionIdTlv = As<MeshCoP::CommissionerSessionIdTlv>(
+            Get<NetworkData::Leader>().GetCommissioningDataSubTlv(MeshCoP::Tlv::kCommissionerSessionId));
 
         VerifyOrExit(commissionerSessionIdTlv != nullptr &&
                          commissionerSessionIdTlv->GetCommissionerSessionId() == commissionerSessionId,
@@ -206,7 +207,7 @@
                      kErrorNone,
                  error = kErrorParse);
     VerifyOrExit(addressesLength % sizeof(Ip6::Address) == 0, status = ThreadStatusTlv::kMlrGeneralFailure);
-    VerifyOrExit(addressesLength / sizeof(Ip6::Address) <= kIp6AddressesNumMax,
+    VerifyOrExit(addressesLength / sizeof(Ip6::Address) <= Ip6AddressesTlv::kMaxAddresses,
                  status = ThreadStatusTlv::kMlrGeneralFailure);
 
     if (!processTimeoutTlv)
@@ -224,11 +225,10 @@
             uint32_t origTimeout = timeout;
 
             timeout = OT_MIN(timeout, static_cast<uint32_t>(Mle::kMlrTimeoutMax));
-            timeout = OT_MAX(timeout, static_cast<uint32_t>(Mle::kMlrTimeoutMin));
 
             if (timeout != origTimeout)
             {
-                otLogNoteBbr("MLR.req: MLR timeout is normalized from %u to %u", origTimeout, timeout);
+                LogNote("MLR.req: MLR timeout is normalized from %u to %u", origTimeout, timeout);
             }
         }
     }
@@ -242,6 +242,9 @@
         if (timeout == 0)
         {
             mMulticastListenersTable.Remove(address);
+
+            // Put successfully de-registered addresses at the end of `addresses`.
+            addresses[Ip6AddressesTlv::kMaxAddresses - (++successAddressNum)] = address;
         }
         else
         {
@@ -275,7 +278,7 @@
             else
             {
                 // Put successfully registered addresses at the end of `addresses`.
-                addresses[kIp6AddressesNumMax - (++successAddressNum)] = address;
+                addresses[Ip6AddressesTlv::kMaxAddresses - (++successAddressNum)] = address;
             }
         }
     }
@@ -288,7 +291,7 @@
 
     if (successAddressNum > 0)
     {
-        SendBackboneMulticastListenerRegistration(&addresses[kIp6AddressesNumMax - successAddressNum],
+        SendBackboneMulticastListenerRegistration(&addresses[Ip6AddressesTlv::kMaxAddresses - successAddressNum],
                                                   successAddressNum, timeout);
     }
 }
@@ -299,13 +302,11 @@
                                                         Ip6::Address *             aFailedAddresses,
                                                         uint8_t                    aFailedAddressNum)
 {
-    Error          error   = kErrorNone;
-    Coap::Message *message = nullptr;
+    Error          error = kErrorNone;
+    Coap::Message *message;
 
-    VerifyOrExit((message = Get<Tmf::Agent>().NewMessage()) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(message->SetDefaultResponseHeader(aMessage));
-    SuccessOrExit(message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewResponseMessage(aMessage);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(Tlv::Append<ThreadStatusTlv>(*message, aStatus));
 
@@ -327,7 +328,7 @@
 
 exit:
     FreeMessageOnError(message, error);
-    otLogInfoBbr("Sent MLR.rsp (status=%d): %s", aStatus, ErrorToString(error));
+    LogInfo("Sent MLR.rsp (status=%d): %s", aStatus, ErrorToString(error));
 }
 
 void Manager::SendBackboneMulticastListenerRegistration(const Ip6::Address *aAddresses,
@@ -340,12 +341,10 @@
     Ip6AddressesTlv   addressesTlv;
     BackboneTmfAgent &backboneTmf = Get<BackboneRouter::BackboneTmfAgent>();
 
-    OT_ASSERT(aAddressNum >= kIp6AddressesNumMin && aAddressNum <= kIp6AddressesNumMax);
+    OT_ASSERT(aAddressNum >= Ip6AddressesTlv::kMinAddresses && aAddressNum <= Ip6AddressesTlv::kMaxAddresses);
 
-    VerifyOrExit((message = backboneTmf.NewMessage()) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->InitAsNonConfirmablePost(UriPath::kBackboneMlr));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = backboneTmf.NewNonConfirmablePostMessage(UriPath::kBackboneMlr);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     addressesTlv.Init();
     addressesTlv.SetLength(sizeof(Ip6::Address) * aAddressNum);
@@ -364,7 +363,7 @@
 
 exit:
     FreeMessageOnError(message, error);
-    otLogInfoBbr("Sent BMLR.ntf: %s", ErrorToString(error));
+    LogInfo("Sent BMLR.ntf: %s", ErrorToString(error));
 }
 #endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
 
@@ -429,7 +428,7 @@
     }
 
 exit:
-    otLogInfoBbr("Received DUA.req on %s: %s", (isPrimary ? "PBBR" : "SBBR"), ErrorToString(error));
+    LogInfo("Received DUA.req on %s: %s", (isPrimary ? "PBBR" : "SBBR"), ErrorToString(error));
 
     if (error == kErrorNone)
     {
@@ -451,13 +450,11 @@
                                           const Ip6::Address &       aTarget,
                                           ThreadStatusTlv::DuaStatus aStatus)
 {
-    Error          error   = kErrorNone;
-    Coap::Message *message = nullptr;
+    Error          error = kErrorNone;
+    Coap::Message *message;
 
-    VerifyOrExit((message = Get<Tmf::Agent>().NewMessage()) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(message->SetDefaultResponseHeader(aMessage));
-    SuccessOrExit(message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewResponseMessage(aMessage);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(Tlv::Append<ThreadStatusTlv>(*message, aStatus));
     SuccessOrExit(Tlv::Append<ThreadTargetTlv>(*message, aTarget));
@@ -466,8 +463,7 @@
 
 exit:
     FreeMessageOnError(message, error);
-    otLogInfoBbr("Sent DUA.rsp for DUA %s, status %d %s", aTarget.ToString().AsCString(), aStatus,
-                 ErrorToString(error));
+    LogInfo("Sent DUA.rsp for DUA %s, status %d %s", aTarget.ToString().AsCString(), aStatus, ErrorToString(error));
 }
 #endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
 
@@ -507,19 +503,18 @@
 
 bool Manager::ShouldForwardDuaToBackbone(const Ip6::Address &aAddress)
 {
-    bool              forwardToBackbone = false;
-    Mac::ShortAddress rloc16;
-    Error             error;
+    bool forwardToBackbone = false;
 
     VerifyOrExit(Get<Local>().IsPrimary());
     VerifyOrExit(Get<Leader>().IsDomainUnicast(aAddress));
 
+    // Do not forward to Backbone if the DUA is registered on PBBR
     VerifyOrExit(!mNdProxyTable.IsRegistered(aAddress.GetIid()));
+    // Do not forward to Backbone if the DUA belongs to a MTD Child (which may have failed in DUA registration)
+    VerifyOrExit(Get<NeighborTable>().FindNeighbor(aAddress) == nullptr);
+    // Forward to Backbone only if the DUA is resolved to the PBBR's RLOC16
+    VerifyOrExit(Get<AddressResolver>().LookUp(aAddress) == Get<Mle::MleRouter>().GetRloc16());
 
-    error = Get<AddressResolver>().Resolve(aAddress, rloc16, /* aAllowAddressQuery */ false);
-    VerifyOrExit(error != kErrorNone || rloc16 == Get<Mle::MleRouter>().GetRloc16());
-
-    // TODO: check if the DUA is an address of any Child?
     forwardToBackbone = true;
 
 exit:
@@ -534,10 +529,8 @@
 
     VerifyOrExit(Get<Local>().IsPrimary(), error = kErrorInvalidState);
 
-    VerifyOrExit((message = mBackboneTmfAgent.NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->InitAsNonConfirmablePost(UriPath::kBackboneQuery));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = mBackboneTmfAgent.NewPriorityNonConfirmablePostMessage(UriPath::kBackboneQuery);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = Tlv::Append<ThreadTargetTlv>(*message, aDua));
 
@@ -555,8 +548,7 @@
     error = mBackboneTmfAgent.SendMessage(*message, messageInfo);
 
 exit:
-    otLogInfoBbr("SendBackboneQuery for %s (rloc16=%04x): %s", aDua.ToString().AsCString(), aRloc16,
-                 ErrorToString(error));
+    LogInfo("SendBackboneQuery for %s (rloc16=%04x): %s", aDua.ToString().AsCString(), aRloc16, ErrorToString(error));
     FreeMessageOnError(message, error);
     return error;
 }
@@ -583,8 +575,8 @@
     error = Tlv::Find<ThreadRloc16Tlv>(aMessage, rloc16);
     VerifyOrExit(error == kErrorNone || error == kErrorNotFound);
 
-    otLogInfoBbr("Received BB.qry from %s for %s (rloc16=%04x)", aMessageInfo.GetPeerAddr().ToString().AsCString(),
-                 dua.ToString().AsCString(), rloc16);
+    LogInfo("Received BB.qry from %s for %s (rloc16=%04x)", aMessageInfo.GetPeerAddr().ToString().AsCString(),
+            dua.ToString().AsCString(), rloc16);
 
     ndProxy = mNdProxyTable.ResolveDua(dua);
     VerifyOrExit(ndProxy != nullptr && !ndProxy->GetDadFlag(), error = kErrorNotFound);
@@ -592,7 +584,7 @@
     error = SendBackboneAnswer(aMessageInfo, dua, rloc16, *ndProxy);
 
 exit:
-    otLogInfoBbr("HandleBackboneQuery: %s", ErrorToString(error));
+    LogInfo("HandleBackboneQuery: %s", ErrorToString(error));
 }
 
 void Manager::HandleBackboneAnswer(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
@@ -643,7 +635,7 @@
     SuccessOrExit(error = mBackboneTmfAgent.SendEmptyAck(aMessage, aMessageInfo));
 
 exit:
-    otLogInfoBbr("HandleBackboneAnswer: %s", ErrorToString(error));
+    LogInfo("HandleBackboneAnswer: %s", ErrorToString(error));
 }
 
 Error Manager::SendProactiveBackboneNotification(const Ip6::Address &            aDua,
@@ -687,7 +679,7 @@
     SuccessOrExit(error = Tlv::Append<ThreadLastTransactionTimeTlv>(*message, aTimeSinceLastTransaction));
 
     {
-        const Mac::NameData nameData = Get<Mac::Mac>().GetNetworkName().GetAsData();
+        const MeshCoP::NameData nameData = Get<MeshCoP::NetworkNameManager>().GetNetworkName().GetAsData();
 
         SuccessOrExit(error = Tlv::Append<ThreadNetworkNameTlv>(*message, nameData.GetBuffer(), nameData.GetLength()));
     }
@@ -706,8 +698,8 @@
     error = mBackboneTmfAgent.SendMessage(*message, messageInfo);
 
 exit:
-    otLogInfoBbr("Send %s for %s (rloc16=%04x): %s", proactive ? "PRO_BB.ntf" : "BB.ans", aDua.ToString().AsCString(),
-                 aSrcRloc16, ErrorToString(error));
+    LogInfo("Send %s for %s (rloc16=%04x): %s", proactive ? "PRO_BB.ntf" : "BB.ans", aDua.ToString().AsCString(),
+            aSrcRloc16, ErrorToString(error));
 
     FreeMessageOnError(message, error);
     return error;
@@ -736,8 +728,8 @@
     ot::BackboneRouter::NdProxyTable::NotifyDadComplete(*ndProxy, duplicate);
 
 exit:
-    otLogInfoBbr("HandleDadBackboneAnswer: %s, target=%s, mliid=%s, duplicate=%s", ErrorToString(error),
-                 aDua.ToString().AsCString(), aMeshLocalIid.ToString().AsCString(), duplicate ? "Y" : "N");
+    LogInfo("HandleDadBackboneAnswer: %s, target=%s, mliid=%s, duplicate=%s", ErrorToString(error),
+            aDua.ToString().AsCString(), aMeshLocalIid.ToString().AsCString(), duplicate ? "Y" : "N");
 }
 
 void Manager::HandleExtendedBackboneAnswer(const Ip6::Address &            aDua,
@@ -750,9 +742,8 @@
     dest.SetToRoutingLocator(Get<Mle::MleRouter>().GetMeshLocalPrefix(), aSrcRloc16);
     Get<AddressResolver>().SendAddressQueryResponse(aDua, aMeshLocalIid, &aTimeSinceLastTransaction, dest);
 
-    otLogInfoBbr("HandleExtendedBackboneAnswer: target=%s, mliid=%s, LTT=%lds, rloc16=%04x",
-                 aDua.ToString().AsCString(), aMeshLocalIid.ToString().AsCString(), aTimeSinceLastTransaction,
-                 aSrcRloc16);
+    LogInfo("HandleExtendedBackboneAnswer: target=%s, mliid=%s, LTT=%lds, rloc16=%04x", aDua.ToString().AsCString(),
+            aMeshLocalIid.ToString().AsCString(), aTimeSinceLastTransaction, aSrcRloc16);
 }
 
 void Manager::HandleProactiveBackboneNotification(const Ip6::Address &            aDua,
@@ -788,11 +779,25 @@
     }
 
 exit:
-    otLogInfoBbr("HandleProactiveBackboneNotification: %s, target=%s, mliid=%s, LTT=%lds", ErrorToString(error),
-                 aDua.ToString().AsCString(), aMeshLocalIid.ToString().AsCString(), aTimeSinceLastTransaction);
+    LogInfo("HandleProactiveBackboneNotification: %s, target=%s, mliid=%s, LTT=%lds", ErrorToString(error),
+            aDua.ToString().AsCString(), aMeshLocalIid.ToString().AsCString(), aTimeSinceLastTransaction);
 }
 #endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
 
+void Manager::LogError(const char *aText, Error aError) const
+{
+    OT_UNUSED_VARIABLE(aText);
+
+    if (aError == kErrorNone)
+    {
+        LogInfo("%s: %s", aText, ErrorToString(aError));
+    }
+    else
+    {
+        LogWarn("%s: %s", aText, ErrorToString(aError));
+    }
+}
+
 } // namespace BackboneRouter
 
 } // namespace ot
diff --git a/src/core/backbone_router/bbr_manager.hpp b/src/core/backbone_router/bbr_manager.hpp
index b7f83bd..e5f1705 100644
--- a/src/core/backbone_router/bbr_manager.hpp
+++ b/src/core/backbone_router/bbr_manager.hpp
@@ -88,7 +88,7 @@
      * Note: available only when `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is enabled.
      *       Only used for test and certification.
      *
-     * @param[in] aMlIid    A pointer to the Mesh Local IID. If nullptr, respond with @p aStatus for any
+     * @param[in] aMlIid    A pointer to the Mesh Local IID. If `nullptr`, respond with @p aStatus for any
      *                      coming DUA.req, otherwise only respond the one with matching @p aMlIid.
      * @param[in] aStatus   The status to respond.
      *
@@ -229,6 +229,8 @@
     static void HandleTimer(Timer &aTimer);
     void        HandleTimer(void);
 
+    void LogError(const char *aText, Error aError) const;
+
 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
     Coap::Resource mMulticastListenerRegistration;
 #endif
diff --git a/src/core/backbone_router/multicast_listeners_table.cpp b/src/core/backbone_router/multicast_listeners_table.cpp
index bf9b51e..35a4972 100644
--- a/src/core/backbone_router/multicast_listeners_table.cpp
+++ b/src/core/backbone_router/multicast_listeners_table.cpp
@@ -35,10 +35,11 @@
 
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
 
+#include "common/array.hpp"
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/random.hpp"
 #include "thread/mle_types.hpp"
 #include "thread/thread_netif.hpp"
@@ -48,6 +49,8 @@
 
 namespace BackboneRouter {
 
+RegisterLogModule("BbrMlt");
+
 Error MulticastListenersTable::Add(const Ip6::Address &aAddress, Time aExpireTime)
 {
     Error error = kErrorNone;
@@ -66,7 +69,7 @@
         }
     }
 
-    VerifyOrExit(mNumValidListeners < OT_ARRAY_LENGTH(mListeners), error = kErrorNoBufs);
+    VerifyOrExit(mNumValidListeners < GetArrayLength(mListeners), error = kErrorNoBufs);
 
     mListeners[mNumValidListeners].SetAddress(aAddress);
     mListeners[mNumValidListeners].SetExpireTime(aExpireTime);
@@ -154,8 +157,8 @@
     OT_UNUSED_VARIABLE(aExpireTime);
     OT_UNUSED_VARIABLE(aError);
 
-    otLogDebgBbr("MulticastListenersTable: %s %s expire %u: %s", aAction, aAddress.ToString().AsCString(),
-                 aExpireTime.GetValue(), ErrorToString(aError));
+    LogDebg("%s %s expire %u: %s", aAction, aAddress.ToString().AsCString(), aExpireTime.GetValue(),
+            ErrorToString(aError));
 }
 
 void MulticastListenersTable::FixHeap(uint16_t aIndex)
diff --git a/src/core/backbone_router/ndproxy_table.cpp b/src/core/backbone_router/ndproxy_table.cpp
index f680daa..89c0442 100644
--- a/src/core/backbone_router/ndproxy_table.cpp
+++ b/src/core/backbone_router/ndproxy_table.cpp
@@ -35,13 +35,16 @@
 
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
 
+#include "common/array.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 
 namespace ot {
 
 namespace BackboneRouter {
 
+RegisterLogModule("BbrNdProxy");
+
 void NdProxyTable::NdProxy::Init(const Ip6::InterfaceIdentifier &aAddressIid,
                                  const Ip6::InterfaceIdentifier &aMeshLocalIid,
                                  uint16_t                        aRloc16,
@@ -107,7 +110,7 @@
     : InstanceLocator(aInstance)
 {
     NdProxyTable &table = GetInstance().Get<BackboneRouter::NdProxyTable>();
-    mItem               = OT_ARRAY_END(table.mProxies);
+    mItem               = GetArrayEnd(table.mProxies);
 }
 
 void NdProxyTable::Iterator::Advance(void)
@@ -117,7 +120,7 @@
     do
     {
         mItem++;
-    } while (mItem < OT_ARRAY_END(table.mProxies) && !MatchesFilter(*mItem, mFilter));
+    } while (mItem < GetArrayEnd(table.mProxies) && !MatchesFilter(*mItem, mFilter));
 }
 
 void NdProxyTable::Erase(NdProxy &aNdProxy)
@@ -146,7 +149,7 @@
         mCallback(mCallbackContext, OT_BACKBONE_ROUTER_NDPROXY_CLEARED, nullptr);
     }
 
-    otLogNoteBbr("NdProxyTable::Clear!");
+    LogInfo("NdProxyTable::Clear!");
 }
 
 Error NdProxyTable::Register(const Ip6::InterfaceIdentifier &aAddressIid,
@@ -185,8 +188,8 @@
     mIsAnyDadInProcess = true;
 
 exit:
-    otLogInfoBbr("NdProxyTable::Register %s MLIID %s RLOC16 %04x LTT %u => %s", aAddressIid.ToString().AsCString(),
-                 aMeshLocalIid.ToString().AsCString(), aRloc16, timeSinceLastTransaction, ErrorToString(error));
+    LogInfo("NdProxyTable::Register %s MLIID %s RLOC16 %04x LTT %u => %s", aAddressIid.ToString().AsCString(),
+            aMeshLocalIid.ToString().AsCString(), aRloc16, timeSinceLastTransaction, ErrorToString(error));
     return error;
 }
 
@@ -203,8 +206,8 @@
     }
 
 exit:
-    otLogDebgBbr("NdProxyTable::FindByAddressIid(%s) => %s", aAddressIid.ToString().AsCString(),
-                 found ? found->mMeshLocalIid.ToString().AsCString() : "NOT_FOUND");
+    LogDebg("NdProxyTable::FindByAddressIid(%s) => %s", aAddressIid.ToString().AsCString(),
+            found ? found->mMeshLocalIid.ToString().AsCString() : "NOT_FOUND");
     return found;
 }
 
@@ -221,8 +224,8 @@
     }
 
 exit:
-    otLogDebgBbr("NdProxyTable::FindByMeshLocalIid(%s) => %s", aMeshLocalIid.ToString().AsCString(),
-                 found ? found->mAddressIid.ToString().AsCString() : "NOT_FOUND");
+    LogDebg("NdProxyTable::FindByMeshLocalIid(%s) => %s", aMeshLocalIid.ToString().AsCString(),
+            found ? found->mAddressIid.ToString().AsCString() : "NOT_FOUND");
     return found;
 }
 
@@ -236,7 +239,7 @@
     }
 
 exit:
-    otLogDebgBbr("NdProxyTable::FindInvalid() => %s", found ? "OK" : "NOT_FOUND");
+    LogDebg("NdProxyTable::FindInvalid() => %s", found ? "OK" : "NOT_FOUND");
     return found;
 }
 
@@ -248,7 +251,7 @@
 
     for (NdProxy &proxy : Iterate(kFilterDadInProcess))
     {
-        if (proxy.IsDadAttamptsComplete())
+        if (proxy.IsDadAttemptsComplete())
         {
             proxy.mDadFlag = false;
             NotifyDuaRegistrationOnBackboneLink(proxy, /* aIsRenew */ false);
@@ -259,7 +262,7 @@
 
             if (Get<BackboneRouter::Manager>().SendBackboneQuery(GetDua(proxy)) == kErrorNone)
             {
-                proxy.IncreaseDadAttampts();
+                proxy.IncreaseDadAttempts();
             }
         }
     }
diff --git a/src/core/backbone_router/ndproxy_table.hpp b/src/core/backbone_router/ndproxy_table.hpp
index b4cf716..097a6d3 100644
--- a/src/core/backbone_router/ndproxy_table.hpp
+++ b/src/core/backbone_router/ndproxy_table.hpp
@@ -111,8 +111,8 @@
                   uint32_t                        aTimeSinceLastTransaction);
 
         void Update(uint16_t aRloc16, uint32_t aTimeSinceLastTransaction);
-        void IncreaseDadAttampts(void) { mDadAttempts++; }
-        bool IsDadAttamptsComplete() const { return mDadAttempts == Mle::kDuaDadRepeats; }
+        void IncreaseDadAttempts(void) { mDadAttempts++; }
+        bool IsDadAttemptsComplete() const { return mDadAttempts == Mle::kDuaDadRepeats; }
 
         Ip6::InterfaceIdentifier mAddressIid;
         Ip6::InterfaceIdentifier mMeshLocalIid;
diff --git a/src/core/border_router/infra_if.cpp b/src/core/border_router/infra_if.cpp
new file mode 100644
index 0000000..7fe20c9
--- /dev/null
+++ b/src/core/border_router/infra_if.cpp
@@ -0,0 +1,162 @@
+/*
+ *    Copyright (c) 2022, The OpenThread Authors.
+ *    All rights reserved.
+ *
+ *    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, 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
+ *   This file implements infrastructure network interface.
+ */
+
+#include "infra_if.hpp"
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+
+#include "border_router/routing_manager.hpp"
+#include "common/as_core_type.hpp"
+#include "common/instance.hpp"
+#include "common/locator_getters.hpp"
+#include "common/logging.hpp"
+#include "net/icmp6.hpp"
+
+namespace ot {
+namespace BorderRouter {
+
+RegisterLogModule("InfraIf");
+
+InfraIf::InfraIf(Instance &aInstance)
+    : InstanceLocator(aInstance)
+    , mInitialized(false)
+    , mIsRunning(false)
+    , mIfIndex(0)
+{
+}
+
+Error InfraIf::Init(uint32_t aIfIndex)
+{
+    Error error = kErrorNone;
+
+    VerifyOrExit(!mInitialized, error = kErrorInvalidState);
+    VerifyOrExit(aIfIndex > 0, error = kErrorInvalidArgs);
+
+    mIfIndex     = aIfIndex;
+    mInitialized = true;
+
+    LogInfo("Init %s", ToString().AsCString());
+
+exit:
+    return error;
+}
+
+void InfraIf::Deinit(void)
+{
+    mInitialized = false;
+    mIsRunning   = false;
+    mIfIndex     = 0;
+
+    LogInfo("Deinit");
+}
+
+bool InfraIf::HasAddress(const Ip6::Address &aAddress)
+{
+    OT_ASSERT(mInitialized);
+
+    return otPlatInfraIfHasAddress(mIfIndex, &aAddress);
+}
+
+Error InfraIf::Send(const Icmp6Packet &aPacket, const Ip6::Address &aDestination)
+{
+    OT_ASSERT(mInitialized);
+
+    return otPlatInfraIfSendIcmp6Nd(mIfIndex, &aDestination, aPacket.GetBytes(), aPacket.GetLength());
+}
+
+void InfraIf::HandledReceived(uint32_t aIfIndex, const Ip6::Address &aSource, const Icmp6Packet &aPacket)
+{
+    Error error = kErrorNone;
+
+    VerifyOrExit(mInitialized && mIsRunning, error = kErrorInvalidState);
+    VerifyOrExit(aIfIndex == mIfIndex, error = kErrorDrop);
+    VerifyOrExit(aPacket.GetBytes() != nullptr, error = kErrorInvalidArgs);
+    VerifyOrExit(aPacket.GetLength() >= sizeof(Ip6::Icmp::Header), error = kErrorParse);
+
+    Get<RoutingManager>().HandleReceived(aPacket, aSource);
+
+exit:
+    if (error != kErrorNone)
+    {
+        LogDebg("Dropped ICMPv6 message: %s", ErrorToString(error));
+    }
+}
+
+Error InfraIf::HandleStateChanged(uint32_t aIfIndex, bool aIsRunning)
+{
+    Error error = kErrorNone;
+
+    VerifyOrExit(mInitialized, error = kErrorInvalidState);
+    VerifyOrExit(aIfIndex == mIfIndex, error = kErrorInvalidArgs);
+
+    VerifyOrExit(aIsRunning != mIsRunning);
+    LogInfo("State changed: %sRUNNING -> %sRUNNING", mIsRunning ? "" : "NOT ", aIsRunning ? "" : "NOT ");
+
+    mIsRunning = aIsRunning;
+
+    Get<RoutingManager>().HandleInfraIfStateChanged();
+
+exit:
+    return error;
+}
+
+InfraIf::InfoString InfraIf::ToString(void) const
+{
+    InfoString string;
+
+    string.Append("infra netif %u", mIfIndex);
+    return string;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+
+extern "C" void otPlatInfraIfRecvIcmp6Nd(otInstance *        aInstance,
+                                         uint32_t            aInfraIfIndex,
+                                         const otIp6Address *aSrcAddress,
+                                         const uint8_t *     aBuffer,
+                                         uint16_t            aBufferLength)
+{
+    InfraIf::Icmp6Packet packet;
+
+    packet.Init(aBuffer, aBufferLength);
+    AsCoreType(aInstance).Get<InfraIf>().HandledReceived(aInfraIfIndex, AsCoreType(aSrcAddress), packet);
+}
+
+extern "C" otError otPlatInfraIfStateChanged(otInstance *aInstance, uint32_t aInfraIfIndex, bool aIsRunning)
+{
+    return AsCoreType(aInstance).Get<InfraIf>().HandleStateChanged(aInfraIfIndex, aIsRunning);
+}
+
+} // namespace BorderRouter
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
diff --git a/src/core/border_router/infra_if.hpp b/src/core/border_router/infra_if.hpp
new file mode 100644
index 0000000..b67009e
--- /dev/null
+++ b/src/core/border_router/infra_if.hpp
@@ -0,0 +1,186 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes definitions for infrastructure network interface.
+ *
+ */
+
+#ifndef INFRA_IF_HPP_
+#define INFRA_IF_HPP_
+
+#include "openthread-core-config.h"
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+
+#include <openthread/platform/infra_if.h>
+
+#include "common/data.hpp"
+#include "common/error.hpp"
+#include "common/locator.hpp"
+#include "common/string.hpp"
+#include "net/ip6.hpp"
+
+namespace ot {
+namespace BorderRouter {
+
+/**
+ * This class represents the infrastructure network interface on a border router.
+ *
+ */
+class InfraIf : public InstanceLocator
+{
+public:
+    static constexpr uint16_t kInfoStringSize = 20; ///< Max chars for the info string (`ToString()`).
+
+    typedef String<kInfoStringSize> InfoString;  ///< String type returned from `ToString()`.
+    typedef Data<kWithUint16Length> Icmp6Packet; ///< An IMCPv6 packet (data containing the IP payload)
+
+    /**
+     * This constructor initializes the `InfraIf`.
+     *
+     * @param[in]  aInstance  A OpenThread instance.
+     *
+     */
+    explicit InfraIf(Instance &aInstance);
+
+    /**
+     * This method initializes the `InfraIf`.
+     *
+     * @param[in]  aIfIndex        The infrastructure interface index.
+     *
+     * @retval  kErrorNone         Successfully initialized the `InfraIf`.
+     * @retval  kErrorInvalidArgs  The index of the infra interface is not valid.
+     * @retval  kErrorInvalidState The `InfraIf` is already initialized.
+     *
+     */
+    Error Init(uint32_t aIfIndex);
+
+    /**
+     * This method deinitilaizes the `InfraIf`.
+     *
+     */
+    void Deinit(void);
+
+    /**
+     * This method indicates whether or not the `InfraIf` is initialized.
+     *
+     * @retval TRUE    The `InfraIf` is initialized.
+     * @retval FALSE   The `InfraIf` is not initialized.
+     *
+     */
+    bool IsInitialized(void) const { return mInitialized; }
+
+    /**
+     * This method indicates whether or not the infra interface is running.
+     *
+     * @retval TRUE   The infrastructure interface is running.
+     * @retval FALSE  The infrastructure interface is not running.
+     *
+     */
+    bool IsRunning(void) const { return mIsRunning; }
+
+    /**
+     * This method returns the infrastructure interface index.
+     *
+     * @returns The interface index or zero if not initialized.
+     *
+     */
+    uint32_t GetIfIndex(void) const { return mIfIndex; }
+
+    /**
+     * This method indicates whether or not the infra interface has the given IPv6 address assigned.
+     *
+     * This method MUST be used when interface is initialized.
+     *
+     * @param[in]  aAddress       The IPv6 address.
+     *
+     * @retval TRUE   The infrastructure interface has @p aAddress.
+     * @retval FALSE  The infrastructure interface does not have @p aAddress.
+     *
+     */
+    bool HasAddress(const Ip6::Address &aAddress);
+
+    /**
+     * This method sends an ICMPv6 Neighbor Discovery packet on the infrastructure interface.
+     *
+     * This method MUST be used when interface is initialized.
+     *
+     * @param[in]  aPacket        The ICMPv6 packet to send.
+     * @param[in]  aDestination   The destination address.
+     *
+     * @retval kErrorNone    Successfully sent the ICMPv6 message.
+     * @retval kErrorFailed  Failed to send the ICMPv6 message.
+     *
+     */
+    Error Send(const Icmp6Packet &aPacket, const Ip6::Address &aDestination);
+
+    /**
+     * This method processes a received ICMPv6 Neighbor Discovery packet from an infrastructure interface.
+     *
+     * @param[in]  aIfIndex       The infrastructure interface index on which the ICMPv6 message is received.
+     * @param[in]  aSource        The IPv6 source address.
+     * @param[in]  aPacket        The ICMPv6 packet.
+     *
+     */
+    void HandledReceived(uint32_t aIfIndex, const Ip6::Address &aSource, const Icmp6Packet &aPacket);
+
+    /**
+     * This method handles infrastructure interface state changes.
+     *
+     * @param[in]  aIfIndex         The infrastructure interface index.
+     * @param[in]  aIsRunning       A boolean that indicates whether the infrastructure interface is running.
+     *
+     * @retval  kErrorNone          Successfully updated the infra interface status.
+     * @retval  kErrorInvalidState  The `InfraIf` is not initialized.
+     * @retval  kErrorInvalidArgs   The @p IfIndex does not match the interface index of `InfraIf`.
+     *
+     */
+    Error HandleStateChanged(uint32_t aIfIndex, bool aIsRunning);
+
+    /**
+     * This method converts the `InfraIf` to a human-readable string.
+     *
+     * @returns The string representation of `InfraIf`.
+     *
+     */
+    InfoString ToString(void) const;
+
+private:
+    bool     mInitialized : 1;
+    bool     mIsRunning : 1;
+    uint32_t mIfIndex;
+};
+
+} // namespace BorderRouter
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+
+#endif // INFRA_IF_HPP_
diff --git a/src/core/border_router/infra_if_platform.cpp b/src/core/border_router/infra_if_platform.cpp
deleted file mode 100644
index 33e0c4c..0000000
--- a/src/core/border_router/infra_if_platform.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *    Copyright (c) 2020, The OpenThread Authors.
- *    All rights reserved.
- *
- *    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, 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
- *   This file implements infrastructure interface platform APIs.
- */
-
-#include "openthread-core-config.h"
-
-#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
-
-#include <openthread/platform/infra_if.h>
-
-#include "border_router/routing_manager.hpp"
-#include "common/as_core_type.hpp"
-#include "common/instance.hpp"
-
-using namespace ot;
-
-extern "C" void otPlatInfraIfRecvIcmp6Nd(otInstance *        aInstance,
-                                         uint32_t            aInfraIfIndex,
-                                         const otIp6Address *aSrcAddress,
-                                         const uint8_t *     aBuffer,
-                                         uint16_t            aBufferLength)
-{
-    AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().RecvIcmp6Message(aInfraIfIndex, AsCoreType(aSrcAddress),
-                                                                               aBuffer, aBufferLength);
-}
-
-extern "C" otError otPlatInfraIfStateChanged(otInstance *aInstance, uint32_t aInfraIfIndex, bool aIsRunning)
-{
-    return AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().HandleInfraIfStateChanged(aInfraIfIndex,
-                                                                                               aIsRunning);
-}
-
-#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
diff --git a/src/core/border_router/router_advertisement.cpp b/src/core/border_router/router_advertisement.cpp
deleted file mode 100644
index 66dbdd5..0000000
--- a/src/core/border_router/router_advertisement.cpp
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- *  Copyright (c) 2020, The OpenThread Authors.
- *  All rights reserved.
- *
- *  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, 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
- *   This file includes implementations for ICMPv6 Router Advertisement.
- *
- */
-
-#include "border_router/router_advertisement.hpp"
-
-#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
-
-#include "common/as_core_type.hpp"
-#include "common/code_utils.hpp"
-
-namespace ot {
-
-namespace BorderRouter {
-
-namespace RouterAdv {
-
-const Option *Option::GetNextOption(const Option *aCurOption, const uint8_t *aBuffer, uint16_t aBufferLength)
-{
-    const uint8_t *nextOption = nullptr;
-    const uint8_t *bufferEnd  = aBuffer + aBufferLength;
-
-    VerifyOrExit(aBuffer != nullptr, nextOption = nullptr);
-
-    if (aCurOption == nullptr)
-    {
-        nextOption = aBuffer;
-    }
-    else
-    {
-        nextOption = reinterpret_cast<const uint8_t *>(aCurOption) + aCurOption->GetSize();
-    }
-
-    VerifyOrExit(nextOption + sizeof(Option) <= bufferEnd, nextOption = nullptr);
-    VerifyOrExit(reinterpret_cast<const Option *>(nextOption)->GetSize() > 0, nextOption = nullptr);
-    VerifyOrExit(nextOption + reinterpret_cast<const Option *>(nextOption)->GetSize() <= bufferEnd,
-                 nextOption = nullptr);
-
-exit:
-    return reinterpret_cast<const Option *>(nextOption);
-}
-
-PrefixInfoOption::PrefixInfoOption(void)
-    : Option(Type::kPrefixInfo, sizeof(*this) / kLengthUnit)
-    , mPrefixLength(0)
-    , mReserved1(0)
-    , mValidLifetime(0)
-    , mPreferredLifetime(0)
-    , mReserved2(0)
-{
-    OT_UNUSED_VARIABLE(mReserved2);
-
-    mPrefix.Clear();
-}
-
-void PrefixInfoOption::SetOnLink(bool aOnLink)
-{
-    if (aOnLink)
-    {
-        mReserved1 |= kOnLinkFlagMask;
-    }
-    else
-    {
-        mReserved1 &= ~kOnLinkFlagMask;
-    }
-}
-
-void PrefixInfoOption::SetAutoAddrConfig(bool aAutoAddrConfig)
-{
-    if (aAutoAddrConfig)
-    {
-        mReserved1 |= kAutoConfigFlagMask;
-    }
-    else
-    {
-        mReserved1 &= ~kAutoConfigFlagMask;
-    }
-}
-
-void PrefixInfoOption::SetPrefix(const Ip6::Prefix &aPrefix)
-{
-    mPrefixLength = aPrefix.mLength;
-    mPrefix       = AsCoreType(&aPrefix.mPrefix);
-}
-
-Ip6::Prefix PrefixInfoOption::GetPrefix(void) const
-{
-    Ip6::Prefix prefix;
-
-    prefix.Set(mPrefix.GetBytes(), mPrefixLength);
-    return prefix;
-}
-
-RouteInfoOption::RouteInfoOption(void)
-    : Option(Type::kRouteInfo, 0)
-    , mPrefixLength(0)
-    , mReserved(0)
-    , mRouteLifetime(0)
-{
-    OT_UNUSED_VARIABLE(mReserved);
-
-    mPrefix.Clear();
-}
-
-void RouteInfoOption::SetPreference(RoutePreference aPreference)
-{
-    mReserved &= ~kPreferenceMask;
-    mReserved |= (NetworkData::RoutePreferenceToValue(aPreference) << kPreferenceOffset) & kPreferenceMask;
-}
-
-RouteInfoOption::RoutePreference RouteInfoOption::GetPreference(void) const
-{
-    return NetworkData::RoutePreferenceFromValue((mReserved & kPreferenceMask) >> kPreferenceOffset);
-}
-
-void RouteInfoOption::SetPrefix(const Ip6::Prefix &aPrefix)
-{
-    // The total length (in bytes) of a Router Information Option
-    // is: (8 bytes fixed option header) + (0, 8, or 16 bytes prefix).
-    // Because the length of the option must be padded with 8 bytes,
-    // the length of the prefix (in bits) must be padded with 64 bits.
-    SetLength((aPrefix.mLength + kLengthUnit * CHAR_BIT - 1) / (kLengthUnit * CHAR_BIT) + 1);
-
-    mPrefixLength = aPrefix.mLength;
-    mPrefix       = AsCoreType(&aPrefix.mPrefix);
-}
-
-Ip6::Prefix RouteInfoOption::GetPrefix(void) const
-{
-    Ip6::Prefix prefix;
-
-    prefix.Set(mPrefix.GetBytes(), mPrefixLength);
-    return prefix;
-}
-
-bool RouteInfoOption::IsValid(void) const
-{
-    return (GetLength() == 1 || GetLength() == 2 || GetLength() == 3) &&
-           (mPrefixLength <= OT_IP6_ADDRESS_SIZE * CHAR_BIT) && NetworkData::IsRoutePreferenceValid(GetPreference());
-}
-
-void RouterAdvMessage::SetToDefault(void)
-{
-    mHeader.Clear();
-    mHeader.SetType(Ip6::Icmp::Header::kTypeRouterAdvert);
-    mReachableTime = 0;
-    mRetransTimer  = 0;
-}
-
-const RouterAdvMessage &RouterAdvMessage::operator=(const RouterAdvMessage &aOther)
-{
-    mHeader = aOther.mHeader;
-
-    // Set zero value and let platform do the calculation.
-    mHeader.SetChecksum(0);
-
-    mReachableTime = aOther.mReachableTime;
-    mRetransTimer  = aOther.mRetransTimer;
-
-    return *this;
-}
-
-bool RouterAdvMessage::operator==(const RouterAdvMessage &aOther) const
-{
-    return memcmp(&mHeader.mData, &aOther.mHeader.mData, sizeof(mHeader.mData)) == 0 &&
-           mReachableTime == aOther.mReachableTime && mRetransTimer == aOther.mRetransTimer;
-}
-
-RouterSolicitMessage::RouterSolicitMessage(void)
-{
-    mHeader.Clear();
-    mHeader.SetType(Ip6::Icmp::Header::kTypeRouterSolicit);
-}
-
-} // namespace RouterAdv
-
-} // namespace BorderRouter
-
-} // namespace ot
-
-#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
diff --git a/src/core/border_router/router_advertisement.hpp b/src/core/border_router/router_advertisement.hpp
deleted file mode 100644
index ada13eb..0000000
--- a/src/core/border_router/router_advertisement.hpp
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
- *  Copyright (c) 2020, The OpenThread Authors.
- *  All rights reserved.
- *
- *  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, 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
- *   This file includes definitions for IPv6 Router Advertisement.
- *
- * See RFC 4861: Neighbor Discovery for IP version 6 (https://tools.ietf.org/html/rfc4861).
- *
- */
-
-#ifndef ROUTER_ADVERTISEMENT_HPP_
-#define ROUTER_ADVERTISEMENT_HPP_
-
-#include "openthread-core-config.h"
-
-#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
-
-#include <stdint.h>
-
-#include <openthread/netdata.h>
-#include <openthread/platform/toolchain.h>
-
-#include "common/encoding.hpp"
-#include "common/equatable.hpp"
-#include "net/icmp6.hpp"
-#include "net/ip6.hpp"
-#include "thread/network_data_types.hpp"
-
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
-
-namespace ot {
-
-namespace BorderRouter {
-
-namespace RouterAdv {
-
-/**
- * This class represents the variable length options in Neighbor
- * Discovery messages.
- *
- * @sa PrefixInfoOption
- * @sa RouteInfoOption
- *
- */
-OT_TOOL_PACKED_BEGIN
-class Option
-{
-public:
-    enum class Type : uint8_t
-    {
-        kPrefixInfo = 3,  ///< Prefix Information Option.
-        kRouteInfo  = 24, ///< Route Information Option.
-    };
-
-    static constexpr uint8_t kLengthUnit = 8; ///< The unit of length in octets.
-
-    /**
-     * This constructor initializes the option with given type and length.
-     *
-     * @param[in]  aType    The type of this option.
-     * @param[in]  aLength  The length of this option in unit of 8 octets.
-     *
-     */
-    explicit Option(Type aType, uint8_t aLength = 0)
-        : mType(aType)
-        , mLength(aLength)
-    {
-    }
-
-    /**
-     * This method returns the type of this option.
-     *
-     * @returns  The option type.
-     *
-     */
-    Type GetType(void) const { return mType; }
-
-    /**
-     * This method sets the size of the option (in bytes).
-     *
-     * Since the option must end on their natural 64-bits boundaries,
-     * the actual length set to the option is padded to (aSize + 7) / 8 * 8.
-     *
-     * @param[in]  aSize  The size of the option in unit of 1 byte.
-     *
-     */
-    void SetSize(uint16_t aSize) { mLength = static_cast<uint8_t>((aSize + kLengthUnit - 1) / kLengthUnit); }
-
-    /**
-     * This method returns the size of the option (in bytes).
-     *
-     * @returns  The size of the option in unit of 1 byte.
-     *
-     */
-    uint16_t GetSize(void) const { return mLength * kLengthUnit; }
-
-    /**
-     * This method sets the length of the option (in unit of 8 bytes).
-     *
-     * @param[in]  aLength  The length of the option in unit of 8 bytes.
-     *
-     */
-    void SetLength(uint8_t aLength) { mLength = aLength; }
-
-    /**
-     * This method returns the length of the option (in unit of 8 bytes).
-     *
-     * @returns  The length of the option in unit of 8 bytes.
-     *
-     */
-    uint16_t GetLength(void) const { return mLength; }
-
-    /**
-     * This helper method returns a pointer to the next valid option in the buffer.
-     *
-     * @param[in]  aCurOption     The current option. Use nullptr to get the first option.
-     * @param[in]  aBuffer        The buffer within which the options are held.
-     * @param[in]  aBufferLength  The length of the buffer.
-     *
-     * @returns  A pointer to the next option if there are a valid one. Otherwise, nullptr.
-     *
-     */
-    static const Option *GetNextOption(const Option *aCurOption, const uint8_t *aBuffer, uint16_t aBufferLength);
-
-    /**
-     * This method tells whether this option is valid.
-     *
-     * @return  A boolean that indicates whether this option is valid.
-     *
-     */
-    bool IsValid(void) const { return mLength > 0; }
-
-private:
-    Type    mType;   // Type of the option.
-    uint8_t mLength; // Length of the option in unit of 8 octets,
-                     // including the `type` and `length` fields.
-} OT_TOOL_PACKED_END;
-
-/**
- * This class represents the Prefix Information Option.
- *
- * See section 4.6.2 of RFC 4861 for definition of this option.
- * https://tools.ietf.org/html/rfc4861#section-4.6.2
- *
- */
-OT_TOOL_PACKED_BEGIN
-class PrefixInfoOption : public Option
-{
-public:
-    /**
-     * This constructor initializes this option with zero prefix
-     * length, valid lifetime and preferred lifetime.
-     *
-     */
-    PrefixInfoOption(void);
-
-    /**
-     * This method returns the on-link flag.
-     *
-     * @returns  A boolean which indicates whether the on-link flag is set.
-     *
-     */
-    bool GetOnLink(void) const { return (mReserved1 & kOnLinkFlagMask) != 0; }
-
-    /**
-     * This method sets the on-link (L) flag.
-     *
-     * @param[in]  aOnLink  A boolean indicates whether the prefix is on-link or off-link.
-     *
-     */
-    void SetOnLink(bool aOnLink);
-
-    /**
-     * This method returns the autonomous address-configuration (A) flag.
-     *
-     * @returns  A boolean which indicates whether the A flag is set.
-     *
-     */
-    bool GetAutoAddrConfig(void) const { return (mReserved1 & kAutoConfigFlagMask) != 0; }
-
-    /**
-     * This method sets the autonomous address-configuration (A) flag.
-     *
-     * @param[in]  aAutoAddrConfig  A boolean indicates whether this prefix can be used
-     *                              for SLAAC.
-     *
-     */
-    void SetAutoAddrConfig(bool aAutoAddrConfig);
-
-    /**
-     * This method set the valid lifetime of the prefix in seconds.
-     *
-     * @param[in]  aValidLifetime  The valid lifetime in seconds.
-     *
-     */
-    void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = HostSwap32(aValidLifetime); }
-
-    /**
-     * THis method returns the valid lifetime of the prefix in seconds.
-     *
-     * @returns  The valid lifetime in seconds.
-     *
-     */
-    uint32_t GetValidLifetime(void) const { return HostSwap32(mValidLifetime); }
-
-    /**
-     * This method sets the preferred lifetime of the prefix in seconds.
-     *
-     * @param[in]  aPreferredLifetime  The preferred lifetime in seconds.
-     *
-     */
-    void SetPreferredLifetime(uint32_t aPreferredLifetime) { mPreferredLifetime = HostSwap32(aPreferredLifetime); }
-
-    /**
-     * THis method returns the preferred lifetime of the prefix in seconds.
-     *
-     * @returns  The preferred lifetime in seconds.
-     *
-     */
-    uint32_t GetPreferredLifetime(void) const { return HostSwap32(mPreferredLifetime); }
-
-    /**
-     * This method sets the prefix.
-     *
-     * @param[in]  aPrefix  The prefix contained in this option.
-     *
-     */
-    void SetPrefix(const Ip6::Prefix &aPrefix);
-
-    /**
-     * This method returns the prefix in this option.
-     *
-     * @returns  The IPv6 prefix in this option.
-     *
-     */
-    Ip6::Prefix GetPrefix(void) const;
-
-    /**
-     * This method tells whether this option is valid.
-     *
-     * @returns  A boolean indicates whether this option is valid.
-     *
-     */
-    bool IsValid(void) const
-    {
-        return (GetSize() == sizeof(*this)) && (mPrefixLength <= OT_IP6_ADDRESS_SIZE * CHAR_BIT) &&
-               (GetPreferredLifetime() <= GetValidLifetime());
-    }
-
-private:
-    static constexpr uint8_t kAutoConfigFlagMask = 0x40; // Bit mask of the Automatic Address Configure flag.
-    static constexpr uint8_t kOnLinkFlagMask     = 0x80; // Bit mask of the On-link flag.
-
-    uint8_t      mPrefixLength;      // The prefix length in bits.
-    uint8_t      mReserved1;         // The reserved field.
-    uint32_t     mValidLifetime;     // The valid lifetime of the prefix.
-    uint32_t     mPreferredLifetime; // The preferred lifetime of the prefix.
-    uint32_t     mReserved2;         // The reserved field.
-    Ip6::Address mPrefix;            // The prefix.
-} OT_TOOL_PACKED_END;
-
-static_assert(sizeof(PrefixInfoOption) == 32, "invalid PrefixInfoOption structure");
-
-/**
- * This class represents the Route Information Option.
- *
- * See section 2.3 of RFC 4191 for definition of this option.
- * https://tools.ietf.org/html/rfc4191#section-2.3
- *
- */
-OT_TOOL_PACKED_BEGIN
-class RouteInfoOption : public Option
-{
-public:
-    /**
-     * This type represents a route preference.
-     *
-     */
-    typedef NetworkData::RoutePreference RoutePreference;
-
-    /**
-     * This constructor initializes this option with zero prefix length.
-     *
-     */
-    RouteInfoOption(void);
-
-    /**
-     * This method sets the route preference.
-     *
-     * @param[in]  aPreference  The route preference.
-     *
-     */
-    void SetPreference(RoutePreference aPreference);
-
-    /**
-     * This method returns the route preference.
-     *
-     * @returns  The route preference.
-     *
-     */
-    RoutePreference GetPreference(void) const;
-
-    /**
-     * This method sets the lifetime of the route in seconds.
-     *
-     * @param[in]  aLifetime  The lifetime of the route in seconds.
-     *
-     */
-    void SetRouteLifetime(uint32_t aLifetime) { mRouteLifetime = HostSwap32(aLifetime); }
-
-    /**
-     * This method returns Route Lifetime in seconds.
-     *
-     * @returns  The Route Lifetime in seconds.
-     *
-     */
-    uint32_t GetRouteLifetime(void) const { return HostSwap32(mRouteLifetime); }
-
-    /**
-     * This method sets the prefix.
-     *
-     * @param[in]  aPrefix  The prefix contained in this option.
-     *
-     */
-    void SetPrefix(const Ip6::Prefix &aPrefix);
-
-    /**
-     * This method returns the prefix in this option.
-     *
-     * @returns  The IPv6 prefix in this option.
-     *
-     */
-    Ip6::Prefix GetPrefix(void) const;
-
-    /**
-     * This method tells whether this option is valid.
-     *
-     * @returns  A boolean indicates whether this option is valid.
-     *
-     */
-    bool IsValid(void) const;
-
-private:
-    static constexpr uint8_t kPreferenceOffset = 3;
-    static constexpr uint8_t kPreferenceMask   = 3 << kPreferenceOffset;
-
-    uint8_t      mPrefixLength;  // The prefix length in bits.
-    uint8_t      mReserved;      // The reserved field.
-    uint32_t     mRouteLifetime; // The lifetime in seconds.
-    Ip6::Address mPrefix;        // The prefix.
-} OT_TOOL_PACKED_END;
-
-static_assert(sizeof(RouteInfoOption) == 24, "invalid RouteInfoOption structure");
-
-/**
- * This class implements the Router Advertisement message.
- *
- * See section 4.2 of RFC 4861 for definition of this message.
- * https://tools.ietf.org/html/rfc4861#section-4.2
- *
- */
-OT_TOOL_PACKED_BEGIN
-class RouterAdvMessage : public Unequatable<RouterAdvMessage>
-{
-public:
-    /**
-     * This constructor initializes the Router Advertisement message with
-     * zero router lifetime, reachable time and retransmission timer.
-     *
-     */
-    RouterAdvMessage(void) { SetToDefault(); }
-
-    /**
-     * This method sets the RA message to default values.
-     *
-     */
-    void SetToDefault(void);
-
-    /**
-     * This method sets the checksum value.
-     *
-     * @param[in]  aChecksum  The checksum value.
-     *
-     */
-    void SetChecksum(uint16_t aChecksum) { mHeader.SetChecksum(aChecksum); }
-
-    /**
-     * This method sets the Router Lifetime in seconds.
-     *
-     * Zero Router Lifetime means we are not a default router.
-     *
-     * @param[in]  aRouterLifetime  The router lifetime in seconds.
-     *
-     */
-    void SetRouterLifetime(uint16_t aRouterLifetime)
-    {
-        mHeader.mData.m16[kRouteLifetimeIdx] = HostSwap16(aRouterLifetime);
-    }
-
-    /**
-     * This method returns the Router Lifetime.
-     *
-     * Zero Router Lifetime means we are not a default router.
-     *
-     * @returns  The router lifetime in seconds.
-     *
-     */
-    uint16_t GetRouterLifetime(void) const { return HostSwap16(mHeader.mData.m16[kRouteLifetimeIdx]); }
-
-    /**
-     * This method returns the Managed Address Configuration ('m') flag.
-     *
-     * @returns  A boolean which indicates whether the 'm' flag is set.
-     *
-     */
-    bool GetManagedAddrConfig(void) const { return (mHeader.mData.m8[kReservedIdx] & kManagedAddressConfigMask) != 0; }
-
-    /**
-     * This method overloads the assignment operator.
-     *
-     */
-    const RouterAdvMessage &operator=(const RouterAdvMessage &aOther);
-
-    /**
-     * This method overloads operator `==` to evaluate whether or not
-     * two instances of `RouterAdvMessage` are equal.
-     *
-     * @param[in]  aOther  The other `RouterAdvMessage` instance to compare with.
-     *
-     * @retval TRUE   If the two `RouterAdvMessage` instances are equal.
-     * @retval FALSE  If the two `RouterAdvMessage` instances are not equal.
-     *
-     */
-    bool operator==(const RouterAdvMessage &aOther) const;
-
-private:
-    // The index of Route Lifetime in ICMPv6 Header Data. In unit of 2 octets.
-    static constexpr uint8_t kRouteLifetimeIdx = 1;
-
-    // The index of Reserved byte in ICMPv6 Header Data. In unit of 1 octet.
-    static constexpr uint8_t kReservedIdx = 1;
-
-    // The bitmask of the Managed Address Configuration ('m') flag.
-    static constexpr uint8_t kManagedAddressConfigMask = 0x80;
-
-    Ip6::Icmp::Header mHeader;        // The common ICMPv6 header.
-    uint32_t          mReachableTime; // The reachable time. In milliseconds.
-    uint32_t          mRetransTimer;  // The retransmission timer. In milliseconds.
-} OT_TOOL_PACKED_END;
-
-static_assert(sizeof(RouterAdvMessage) == 16, "invalid RouterAdvMessage structure");
-
-/**
- * This class implements the Router Solicitation message.
- *
- * See section 4.1 of RFC 4861 for definition of this message.
- * https://tools.ietf.org/html/rfc4861#section-4.1
- *
- */
-OT_TOOL_PACKED_BEGIN
-class RouterSolicitMessage
-{
-public:
-    /**
-     * This constructor initializes the Router Solicitation message.
-     *
-     */
-    RouterSolicitMessage(void);
-
-private:
-    Ip6::Icmp::Header mHeader; // The common ICMPv6 header.
-} OT_TOOL_PACKED_END;
-
-static_assert(sizeof(RouterSolicitMessage) == 8, "invalid RouterSolicitMessage structure");
-
-} // namespace RouterAdv
-
-} // namespace BorderRouter
-
-} // namespace ot
-
-#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
-
-#endif // ROUTER_ADVERTISEMENT_HPP_
diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp
index 85ba1e8..c7f213f 100644
--- a/src/core/border_router/routing_manager.cpp
+++ b/src/core/border_router/routing_manager.cpp
@@ -44,9 +44,10 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/random.hpp"
 #include "common/settings.hpp"
+#include "meshcop/extended_panid.hpp"
 #include "net/ip6.hpp"
 #include "thread/network_data_leader.hpp"
 #include "thread/network_data_local.hpp"
@@ -56,49 +57,58 @@
 
 namespace BorderRouter {
 
+RegisterLogModule("BorderRouter");
+
 RoutingManager::RoutingManager(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mIsRunning(false)
     , mIsEnabled(false)
-    , mInfraIfIsRunning(false)
-    , mInfraIfIndex(0)
+    , mInfraIf(aInstance)
+    , mLocalOmrPrefix(aInstance)
+    , mRouteInfoOptionPreference(NetworkData::kRoutePreferenceMedium)
     , mIsAdvertisingLocalOnLinkPrefix(false)
     , mOnLinkPrefixDeprecateTimer(aInstance, HandleOnLinkPrefixDeprecateTimer)
+    , mIsAdvertisingLocalNat64Prefix(false)
+    , mDiscoveredPrefixTable(aInstance)
     , mTimeRouterAdvMessageLastUpdate(TimerMilli::GetNow())
-    , mDiscoveredPrefixInvalidTimer(aInstance, HandleDiscoveredPrefixInvalidTimer)
+    , mLearntRouterAdvMessageFromHost(false)
     , mDiscoveredPrefixStaleTimer(aInstance, HandleDiscoveredPrefixStaleTimer)
-    , mRouterAdvertisementTimer(aInstance, HandleRouterAdvertisementTimer)
     , mRouterAdvertisementCount(0)
-    , mVicariousRouterSolicitTimer(aInstance, HandleVicariousRouterSolicitTimer)
+    , mLastRouterAdvertisementSendTime(TimerMilli::GetNow() - kMinDelayBetweenRtrAdvs)
     , mRouterSolicitTimer(aInstance, HandleRouterSolicitTimer)
     , mRouterSolicitCount(0)
     , mRoutingPolicyTimer(aInstance, HandleRoutingPolicyTimer)
 {
-    mLocalOmrPrefix.Clear();
+    mFavoredDiscoveredOnLinkPrefix.Clear();
+
+    mBrUlaPrefix.Clear();
 
     mLocalOnLinkPrefix.Clear();
+
+    mLocalNat64Prefix.Clear();
 }
 
 Error RoutingManager::Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning)
 {
     Error error;
 
-    VerifyOrExit(!IsInitialized(), error = kErrorInvalidState);
-    VerifyOrExit(aInfraIfIndex > 0, error = kErrorInvalidArgs);
+    SuccessOrExit(error = mInfraIf.Init(aInfraIfIndex));
 
-    SuccessOrExit(error = LoadOrGenerateRandomOmrPrefix());
-    SuccessOrExit(error = LoadOrGenerateRandomOnLinkPrefix());
+    SuccessOrExit(error = LoadOrGenerateRandomBrUlaPrefix());
+    mLocalOmrPrefix.GenerateFrom(mBrUlaPrefix);
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
+    GenerateNat64Prefix();
+#endif
+    GenerateOnLinkPrefix();
 
-    mInfraIfIndex = aInfraIfIndex;
-
-    // Initialize the infra interface status.
-    SuccessOrExit(error = HandleInfraIfStateChanged(mInfraIfIndex, aInfraIfIsRunning));
+    error = mInfraIf.HandleStateChanged(mInfraIf.GetIfIndex(), aInfraIfIsRunning);
 
 exit:
     if (error != kErrorNone)
     {
-        mInfraIfIndex = 0;
+        mInfraIf.Deinit();
     }
+
     return error;
 }
 
@@ -117,12 +127,37 @@
     return error;
 }
 
+void RoutingManager::SetRouteInfoOptionPreference(RoutePreference aPreference)
+{
+    VerifyOrExit(mRouteInfoOptionPreference != aPreference);
+
+    mRouteInfoOptionPreference = aPreference;
+
+    VerifyOrExit(mIsRunning);
+    StartRoutingPolicyEvaluationJitter(kRoutingPolicyEvaluationJitter);
+
+exit:
+    return;
+}
+
 Error RoutingManager::GetOmrPrefix(Ip6::Prefix &aPrefix)
 {
     Error error = kErrorNone;
 
     VerifyOrExit(IsInitialized(), error = kErrorInvalidState);
-    aPrefix = mLocalOmrPrefix;
+    aPrefix = mLocalOmrPrefix.GetPrefix();
+
+exit:
+    return error;
+}
+
+Error RoutingManager::GetFavoredOmrPrefix(Ip6::Prefix &aPrefix, RoutePreference &aPreference)
+{
+    Error error = kErrorNone;
+
+    VerifyOrExit(IsInitialized(), error = kErrorInvalidState);
+    aPrefix     = mFavoredOmrPrefix.GetPrefix();
+    aPreference = mFavoredOmrPrefix.GetPreference();
 
 exit:
     return error;
@@ -139,63 +174,81 @@
     return error;
 }
 
-Error RoutingManager::LoadOrGenerateRandomOmrPrefix(void)
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
+Error RoutingManager::GetNat64Prefix(Ip6::Prefix &aPrefix)
 {
     Error error = kErrorNone;
 
-    if (Get<Settings>().Read<Settings::OmrPrefix>(mLocalOmrPrefix) != kErrorNone || !IsValidOmrPrefix(mLocalOmrPrefix))
-    {
-        Ip6::NetworkPrefix randomOmrPrefix;
-
-        otLogNoteBr("No valid OMR prefix found in settings, generating new one");
-
-        error = randomOmrPrefix.GenerateRandomUla();
-        if (error != kErrorNone)
-        {
-            otLogCritBr("Failed to generate random OMR prefix");
-            ExitNow();
-        }
-
-        mLocalOmrPrefix.Set(randomOmrPrefix);
-        IgnoreError(Get<Settings>().Save<Settings::OmrPrefix>(mLocalOmrPrefix));
-    }
+    VerifyOrExit(IsInitialized(), error = kErrorInvalidState);
+    aPrefix = mLocalNat64Prefix;
 
 exit:
     return error;
 }
+#endif
 
-Error RoutingManager::LoadOrGenerateRandomOnLinkPrefix(void)
+Error RoutingManager::LoadOrGenerateRandomBrUlaPrefix(void)
 {
-    Error error = kErrorNone;
+    Error error     = kErrorNone;
+    bool  generated = false;
 
-    if (Get<Settings>().Read<Settings::OnLinkPrefix>(mLocalOnLinkPrefix) != kErrorNone ||
-        !mLocalOnLinkPrefix.IsUniqueLocal())
+    if (Get<Settings>().Read<Settings::BrUlaPrefix>(mBrUlaPrefix) != kErrorNone || !IsValidBrUlaPrefix(mBrUlaPrefix))
     {
-        Ip6::NetworkPrefix randomOnLinkPrefix;
+        Ip6::NetworkPrefix randomUlaPrefix;
 
-        otLogNoteBr("No valid on-link prefix found in settings, generating new one");
+        LogNote("No valid /48 BR ULA prefix found in settings, generating new one");
 
-        error = randomOnLinkPrefix.GenerateRandomUla();
-        if (error != kErrorNone)
-        {
-            otLogCritBr("Failed to generate random on-link prefix");
-            ExitNow();
-        }
+        SuccessOrExit(error = randomUlaPrefix.GenerateRandomUla());
 
-        randomOnLinkPrefix.m8[6] = 0;
-        randomOnLinkPrefix.m8[7] = 0;
-        mLocalOnLinkPrefix.Set(randomOnLinkPrefix);
+        mBrUlaPrefix.Set(randomUlaPrefix);
+        mBrUlaPrefix.SetSubnetId(0);
+        mBrUlaPrefix.SetLength(kBrUlaPrefixLength);
 
-        IgnoreError(Get<Settings>().Save<Settings::OnLinkPrefix>(mLocalOnLinkPrefix));
+        IgnoreError(Get<Settings>().Save<Settings::BrUlaPrefix>(mBrUlaPrefix));
+        generated = true;
     }
 
+    OT_UNUSED_VARIABLE(generated);
+
+    LogNote("BR ULA prefix: %s (%s)", mBrUlaPrefix.ToString().AsCString(), generated ? "generated" : "loaded");
+
 exit:
+    if (error != kErrorNone)
+    {
+        LogCrit("Failed to generate random /48 BR ULA prefix");
+    }
     return error;
 }
 
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
+void RoutingManager::GenerateNat64Prefix(void)
+{
+    mLocalNat64Prefix = mBrUlaPrefix;
+    mLocalNat64Prefix.SetSubnetId(kNat64PrefixSubnetId);
+    mLocalNat64Prefix.mPrefix.mFields.m32[2] = 0;
+    mLocalNat64Prefix.SetLength(kNat64PrefixLength);
+
+    LogInfo("Generated NAT64 prefix: %s", mLocalNat64Prefix.ToString().AsCString());
+}
+#endif
+
+void RoutingManager::GenerateOnLinkPrefix(void)
+{
+    MeshCoP::ExtendedPanId extPanId = Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId();
+
+    mLocalOnLinkPrefix.mPrefix.mFields.m8[0] = 0xfd;
+    // Global ID: 40 most significant bits of Extended PAN ID
+    memcpy(mLocalOnLinkPrefix.mPrefix.mFields.m8 + 1, extPanId.m8, 5);
+    // Subnet ID: 16 least significant bits of Extended PAN ID
+    memcpy(mLocalOnLinkPrefix.mPrefix.mFields.m8 + 6, extPanId.m8 + 6, 2);
+    mLocalOnLinkPrefix.SetLength(kOnLinkPrefixLength);
+
+    LogNote("Local on-link prefix: %s", mLocalOnLinkPrefix.ToString().AsCString());
+}
+
 void RoutingManager::EvaluateState(void)
 {
-    if (mIsEnabled && Get<Mle::MleRouter>().IsAttached() && mInfraIfIsRunning)
+    if (mIsEnabled && Get<Mle::MleRouter>().IsAttached() && mInfraIf.IsRunning())
     {
         Start();
     }
@@ -209,9 +262,10 @@
 {
     if (!mIsRunning)
     {
-        otLogInfoBr("Border Routing manager started");
+        LogInfo("Border Routing manager started");
 
         mIsRunning = true;
+        UpdateDiscoveredPrefixTableOnNetDataChange();
         StartRouterSolicitationDelay();
     }
 }
@@ -220,39 +274,43 @@
 {
     VerifyOrExit(mIsRunning);
 
-    UnpublishLocalOmrPrefix();
+    mLocalOmrPrefix.RemoveFromNetData();
+    mFavoredOmrPrefix.Clear();
+
+    mFavoredDiscoveredOnLinkPrefix.Clear();
 
     if (mIsAdvertisingLocalOnLinkPrefix)
     {
-        RemoveExternalRoute(mLocalOnLinkPrefix);
+        UnpublishExternalRoute(mLocalOnLinkPrefix);
 
         // Start deprecating the local on-link prefix to send a PIO
         // with zero preferred lifetime in `SendRouterAdvertisement`.
         DeprecateOnLinkPrefix();
     }
 
-    // Use empty OMR & on-link prefixes to invalidate possible advertised prefixes.
-    SendRouterAdvertisement(OmrPrefixArray(), nullptr);
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
+    if (mIsAdvertisingLocalNat64Prefix)
+    {
+        UnpublishExternalRoute(mLocalNat64Prefix);
+        mIsAdvertisingLocalNat64Prefix = false;
+    }
+#endif
+    SendRouterAdvertisement(kInvalidateAllPrevPrefixes);
 
-    mAdvertisedOmrPrefixes.Clear();
-    mIsAdvertisingLocalOnLinkPrefix = false;
+    mAdvertisedPrefixes.Clear();
     mOnLinkPrefixDeprecateTimer.Stop();
 
-    InvalidateAllDiscoveredPrefixes();
-    mDiscoveredPrefixes.Clear();
-    mDiscoveredPrefixInvalidTimer.Stop();
+    mDiscoveredPrefixTable.RemoveAllEntries();
     mDiscoveredPrefixStaleTimer.Stop();
 
-    mRouterAdvertisementTimer.Stop();
     mRouterAdvertisementCount = 0;
 
-    mVicariousRouterSolicitTimer.Stop();
     mRouterSolicitTimer.Stop();
     mRouterSolicitCount = 0;
 
     mRoutingPolicyTimer.Stop();
 
-    otLogInfoBr("Border Routing manager stopped");
+    LogInfo("Border Routing manager stopped");
 
     mIsRunning = false;
 
@@ -260,55 +318,28 @@
     return;
 }
 
-void RoutingManager::RecvIcmp6Message(uint32_t            aInfraIfIndex,
-                                      const Ip6::Address &aSrcAddress,
-                                      const uint8_t *     aBuffer,
-                                      uint16_t            aBufferLength)
+void RoutingManager::HandleReceived(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress)
 {
-    Error                    error = kErrorNone;
     const Ip6::Icmp::Header *icmp6Header;
 
-    VerifyOrExit(IsInitialized() && mIsRunning, error = kErrorDrop);
-    VerifyOrExit(aInfraIfIndex == mInfraIfIndex, error = kErrorDrop);
-    VerifyOrExit(aBuffer != nullptr && aBufferLength >= sizeof(*icmp6Header), error = kErrorParse);
+    VerifyOrExit(mIsRunning);
 
-    icmp6Header = reinterpret_cast<const Ip6::Icmp::Header *>(aBuffer);
+    icmp6Header = reinterpret_cast<const Ip6::Icmp::Header *>(aPacket.GetBytes());
 
     switch (icmp6Header->GetType())
     {
     case Ip6::Icmp::Header::kTypeRouterAdvert:
-        HandleRouterAdvertisement(aSrcAddress, aBuffer, aBufferLength);
+        HandleRouterAdvertisement(aPacket, aSrcAddress);
         break;
     case Ip6::Icmp::Header::kTypeRouterSolicit:
-        HandleRouterSolicit(aSrcAddress, aBuffer, aBufferLength);
+        HandleRouterSolicit(aPacket, aSrcAddress);
         break;
     default:
         break;
     }
 
 exit:
-    if (error != kErrorNone)
-    {
-        otLogDebgBr("Dropped ICMPv6 message: %s", ErrorToString(error));
-    }
-}
-
-Error RoutingManager::HandleInfraIfStateChanged(uint32_t aInfraIfIndex, bool aIsRunning)
-{
-    Error error = kErrorNone;
-
-    VerifyOrExit(IsInitialized(), error = kErrorInvalidState);
-    VerifyOrExit(aInfraIfIndex == mInfraIfIndex, error = kErrorInvalidArgs);
-    VerifyOrExit(aIsRunning != mInfraIfIsRunning);
-
-    otLogInfoBr("Infra interface (%u) state changed: %sRUNNING -> %sRUNNING", aInfraIfIndex,
-                (mInfraIfIsRunning ? "" : "NOT "), (aIsRunning ? "" : "NOT "));
-
-    mInfraIfIsRunning = aIsRunning;
-    EvaluateState();
-
-exit:
-    return error;
+    return;
 }
 
 void RoutingManager::HandleNotifierEvents(Events aEvents)
@@ -322,134 +353,122 @@
 
     if (mIsRunning && aEvents.Contains(kEventThreadNetdataChanged))
     {
-        StartRoutingPolicyEvaluationDelay();
+        UpdateDiscoveredPrefixTableOnNetDataChange();
+        StartRoutingPolicyEvaluationJitter(kRoutingPolicyEvaluationJitter);
+    }
+
+    if (aEvents.Contains(kEventThreadExtPanIdChanged))
+    {
+        if (mIsAdvertisingLocalOnLinkPrefix)
+        {
+            UnpublishExternalRoute(mLocalOnLinkPrefix);
+            // TODO: consider deprecating/invalidating existing
+            // on-link prefix
+            mIsAdvertisingLocalOnLinkPrefix = false;
+        }
+
+        GenerateOnLinkPrefix();
+
+        if (mIsRunning)
+        {
+            StartRoutingPolicyEvaluationJitter(kRoutingPolicyEvaluationJitter);
+        }
     }
 
 exit:
     return;
 }
 
-void RoutingManager::EvaluateOmrPrefix(OmrPrefixArray &aNewOmrPrefixes)
+void RoutingManager::UpdateDiscoveredPrefixTableOnNetDataChange(void)
+{
+    NetworkData::Iterator           iterator = NetworkData::kIteratorInit;
+    NetworkData::OnMeshPrefixConfig prefixConfig;
+    bool                            foundDefRouteOmrPrefix = false;
+
+    // Remove all OMR prefixes in Network Data from the
+    // discovered prefix table. Also check if we have
+    // an OMR prefix with default route flag.
+
+    while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNone)
+    {
+        if (!IsValidOmrPrefix(prefixConfig))
+        {
+            continue;
+        }
+
+        mDiscoveredPrefixTable.RemoveRoutePrefix(prefixConfig.GetPrefix(),
+                                                 DiscoveredPrefixTable::kUnpublishFromNetData);
+
+        if (prefixConfig.mDefaultRoute)
+        {
+            foundDefRouteOmrPrefix = true;
+        }
+    }
+
+    // If we find an OMR prefix with default route flag, it indicates
+    // that this prefix can be used with default route (routable beyond
+    // infra link).
+    //
+    // `DiscoveredPrefixTable` will always track which routers provide
+    // default route when processing received RA messages, but only
+    // if we see an OMR prefix with default route flag, we allow it
+    // to publish the discovered default route (as ::/0 external
+    // route) in Network Data.
+
+    mDiscoveredPrefixTable.SetAllowDefaultRouteInNetData(foundDefRouteOmrPrefix);
+}
+
+void RoutingManager::EvaluateOmrPrefix(void)
 {
     NetworkData::Iterator           iterator = NetworkData::kIteratorInit;
     NetworkData::OnMeshPrefixConfig onMeshPrefixConfig;
-    Ip6::Prefix *                   smallestOmrPrefix       = nullptr;
-    Ip6::Prefix *                   publishedLocalOmrPrefix = nullptr;
 
     OT_ASSERT(mIsRunning);
 
+    mFavoredOmrPrefix.Clear();
+
     while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, onMeshPrefixConfig) == kErrorNone)
     {
-        const Ip6::Prefix &prefix = onMeshPrefixConfig.GetPrefix();
-
-        if (!IsValidOmrPrefix(onMeshPrefixConfig))
+        if (!IsValidOmrPrefix(onMeshPrefixConfig) || !onMeshPrefixConfig.mPreferred)
         {
             continue;
         }
 
-        if (aNewOmrPrefixes.Contains(prefix))
+        if (mFavoredOmrPrefix.IsEmpty() || !mFavoredOmrPrefix.IsFavoredOver(onMeshPrefixConfig))
         {
-            // Ignore duplicate prefixes.
-            continue;
-        }
-
-        if (aNewOmrPrefixes.PushBack(prefix) != kErrorNone)
-        {
-            otLogWarnBr("EvaluateOmrPrefix: Too many OMR prefixes, ignoring prefix %s", prefix.ToString().AsCString());
-            continue;
-        }
-
-        if (smallestOmrPrefix == nullptr || (prefix < *smallestOmrPrefix))
-        {
-            smallestOmrPrefix = aNewOmrPrefixes.Back();
-        }
-
-        if (prefix == mLocalOmrPrefix)
-        {
-            publishedLocalOmrPrefix = aNewOmrPrefixes.Back();
+            mFavoredOmrPrefix.SetFrom(onMeshPrefixConfig);
         }
     }
 
     // Decide if we need to add or remove our local OMR prefix.
 
-    if (aNewOmrPrefixes.IsEmpty())
+    if (mFavoredOmrPrefix.IsEmpty())
     {
-        otLogInfoBr("EvaluateOmrPrefix: No valid OMR prefixes found in Thread network");
+        LogInfo("EvaluateOmrPrefix: No preferred OMR prefix found in Thread network");
 
-        if (PublishLocalOmrPrefix() == kErrorNone)
-        {
-            IgnoreError(aNewOmrPrefixes.PushBack(mLocalOmrPrefix));
-        }
-
-        // The `aNewOmrPrefixes` remains empty if we fail to publish
+        // The `aNewPrefixes` remains empty if we fail to publish
         // the local OMR prefix.
+        SuccessOrExit(mLocalOmrPrefix.AddToNetData());
+
+        mFavoredOmrPrefix.SetFrom(mLocalOmrPrefix);
     }
-    else if (publishedLocalOmrPrefix != nullptr && smallestOmrPrefix != publishedLocalOmrPrefix)
+    else if (mFavoredOmrPrefix.GetPrefix() == mLocalOmrPrefix.GetPrefix())
     {
-        otLogInfoBr("EvaluateOmrPrefix: There is already a smaller OMR prefix %s in the Thread network",
-                    smallestOmrPrefix->ToString().AsCString());
-
-        UnpublishLocalOmrPrefix();
-
-        // Remove the local OMR prefix from the list by overwriting it
-        // with the last element and then popping it from the list.
-
-        *publishedLocalOmrPrefix = *aNewOmrPrefixes.Back();
-        aNewOmrPrefixes.PopBack();
+        IgnoreError(mLocalOmrPrefix.AddToNetData());
     }
-}
-
-Error RoutingManager::PublishLocalOmrPrefix(void)
-{
-    Error                           error = kErrorNone;
-    NetworkData::OnMeshPrefixConfig omrPrefixConfig;
-
-    OT_ASSERT(mIsRunning);
-
-    omrPrefixConfig.Clear();
-    omrPrefixConfig.mPrefix       = mLocalOmrPrefix;
-    omrPrefixConfig.mStable       = true;
-    omrPrefixConfig.mSlaac        = true;
-    omrPrefixConfig.mPreferred    = true;
-    omrPrefixConfig.mOnMesh       = true;
-    omrPrefixConfig.mDefaultRoute = false;
-    omrPrefixConfig.mPreference   = NetworkData::kRoutePreferenceMedium;
-
-    error = Get<NetworkData::Local>().AddOnMeshPrefix(omrPrefixConfig);
-    if (error != kErrorNone)
+    else if (mLocalOmrPrefix.IsAddedInNetData())
     {
-        otLogWarnBr("Failed to publish local OMR prefix %s in Thread network: %s",
-                    mLocalOmrPrefix.ToString().AsCString(), ErrorToString(error));
+        LogInfo("EvaluateOmrPrefix: There is already a preferred OMR prefix %s in the Thread network",
+                mFavoredOmrPrefix.GetPrefix().ToString().AsCString());
+
+        mLocalOmrPrefix.RemoveFromNetData();
     }
-    else
-    {
-        Get<NetworkData::Notifier>().HandleServerDataUpdated();
-        otLogInfoBr("Published local OMR prefix %s in Thread network", mLocalOmrPrefix.ToString().AsCString());
-    }
-
-    return error;
-}
-
-void RoutingManager::UnpublishLocalOmrPrefix(void)
-{
-    Error error = kErrorNone;
-
-    VerifyOrExit(mIsRunning);
-
-    SuccessOrExit(error = Get<NetworkData::Local>().RemoveOnMeshPrefix(mLocalOmrPrefix));
-
-    Get<NetworkData::Notifier>().HandleServerDataUpdated();
-    otLogInfoBr("Unpublished local OMR prefix %s from Thread network", mLocalOmrPrefix.ToString().AsCString());
 
 exit:
-    if (error != kErrorNone)
-    {
-        otLogWarnBr("Failed to unpublish local OMR prefix %s from Thread network: %s",
-                    mLocalOmrPrefix.ToString().AsCString(), ErrorToString(error));
-    }
+    return;
 }
 
-Error RoutingManager::AddExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aRoutePreference)
+Error RoutingManager::PublishExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aRoutePreference, bool aNat64)
 {
     Error                            error;
     NetworkData::ExternalRouteConfig routeConfig;
@@ -459,93 +478,81 @@
     routeConfig.Clear();
     routeConfig.SetPrefix(aPrefix);
     routeConfig.mStable     = true;
+    routeConfig.mNat64      = aNat64;
     routeConfig.mPreference = aRoutePreference;
 
-    error = Get<NetworkData::Local>().AddHasRoutePrefix(routeConfig);
+    error = Get<NetworkData::Publisher>().PublishExternalRoute(routeConfig);
+
     if (error != kErrorNone)
     {
-        otLogWarnBr("Failed to add external route %s: %s", aPrefix.ToString().AsCString(), ErrorToString(error));
-    }
-    else
-    {
-        Get<NetworkData::Notifier>().HandleServerDataUpdated();
-        otLogInfoBr("Added external route %s", aPrefix.ToString().AsCString());
+        LogWarn("Failed to publish external route %s: %s", aPrefix.ToString().AsCString(), ErrorToString(error));
     }
 
     return error;
 }
 
-void RoutingManager::RemoveExternalRoute(const Ip6::Prefix &aPrefix)
+void RoutingManager::UnpublishExternalRoute(const Ip6::Prefix &aPrefix)
 {
-    Error error = kErrorNone;
-
     VerifyOrExit(mIsRunning);
-
-    SuccessOrExit(error = Get<NetworkData::Local>().RemoveHasRoutePrefix(aPrefix));
-
-    Get<NetworkData::Notifier>().HandleServerDataUpdated();
-    otLogInfoBr("Removed external route %s", aPrefix.ToString().AsCString());
+    IgnoreError(Get<NetworkData::Publisher>().UnpublishPrefix(aPrefix));
 
 exit:
-    if (error != kErrorNone)
-    {
-        otLogWarnBr("Failed to remove external route %s: %s", aPrefix.ToString().AsCString(), ErrorToString(error));
-    }
+    return;
 }
 
-const Ip6::Prefix *RoutingManager::EvaluateOnLinkPrefix(void)
+void RoutingManager::EvaluateOnLinkPrefix(void)
 {
-    const Ip6::Prefix *newOnLinkPrefix      = nullptr;
-    const Ip6::Prefix *smallestOnLinkPrefix = nullptr;
+    VerifyOrExit(!IsRouterSolicitationInProgress());
 
-    // We don't evaluate on-link prefix if we are doing Router Solicitation.
-    VerifyOrExit(!mRouterSolicitTimer.IsRunning(),
-                 newOnLinkPrefix = (mIsAdvertisingLocalOnLinkPrefix ? &mLocalOnLinkPrefix : nullptr));
+    mDiscoveredPrefixTable.FindFavoredOnLinkPrefix(mFavoredDiscoveredOnLinkPrefix);
 
-    for (const ExternalPrefix &prefix : mDiscoveredPrefixes)
+    if (mFavoredDiscoveredOnLinkPrefix.GetLength() == 0)
     {
-        if (!prefix.mIsOnLinkPrefix || prefix.IsDeprecated())
-        {
-            continue;
-        }
-
-        if (smallestOnLinkPrefix == nullptr || (prefix.mPrefix < *smallestOnLinkPrefix))
-        {
-            smallestOnLinkPrefix = &prefix.mPrefix;
-        }
-    }
-
-    // We start advertising our local on-link prefix if there is no existing one.
-    if (smallestOnLinkPrefix == nullptr)
-    {
-        if (mIsAdvertisingLocalOnLinkPrefix ||
-            (AddExternalRoute(mLocalOnLinkPrefix, NetworkData::kRoutePreferenceMedium) == kErrorNone))
-        {
-            newOnLinkPrefix = &mLocalOnLinkPrefix;
-        }
+        // We need to advertise our local on-link prefix since there is
+        // no discovered on-link prefix.
 
         mOnLinkPrefixDeprecateTimer.Stop();
+        VerifyOrExit(!mIsAdvertisingLocalOnLinkPrefix);
+
+        SuccessOrExit(PublishExternalRoute(mLocalOnLinkPrefix, NetworkData::kRoutePreferenceMedium));
+
+        mIsAdvertisingLocalOnLinkPrefix = true;
+        LogInfo("Start advertising on-link prefix %s on %s", mLocalOnLinkPrefix.ToString().AsCString(),
+                mInfraIf.ToString().AsCString());
+
+        // We remove the local on-link prefix from discovered prefix
+        // table, in case it was previously discovered and included in
+        // the table (now as a deprecating entry). We remove it with
+        // `kKeepInNetData` flag to ensure that the prefix is not
+        // unpublished from network data.
+        //
+        // Note that `ShouldProcessPrefixInfoOption()` will also check
+        // not allow the local on-link prefix to be added in the prefix
+        // table while we are advertising it.
+
+        mDiscoveredPrefixTable.RemoveOnLinkPrefix(mLocalOnLinkPrefix, DiscoveredPrefixTable::kKeepInNetData);
     }
-    // When an application-specific on-link prefix is received and it is bigger than the
-    // advertised prefix, we will not remove the advertised prefix. In this case, there
-    // will be two on-link prefixes on the infra link. But all BRs will still converge to
-    // the same smallest on-link prefix and the application-specific prefix is not used.
-    else if (mIsAdvertisingLocalOnLinkPrefix)
+    else
     {
-        if (mLocalOnLinkPrefix < *smallestOnLinkPrefix)
+        VerifyOrExit(mIsAdvertisingLocalOnLinkPrefix);
+
+        // When an application-specific on-link prefix is received and
+        // it is larger than the local prefix, we will not remove the
+        // advertised local prefix. In this case, there will be two
+        // on-link prefixes on the infra link. But all BRs will still
+        // converge to the same smallest/favored on-link prefix and the
+        // application-specific prefix is not used.
+
+        if (!(mLocalOnLinkPrefix < mFavoredDiscoveredOnLinkPrefix))
         {
-            newOnLinkPrefix = &mLocalOnLinkPrefix;
-        }
-        else
-        {
-            otLogInfoBr("EvaluateOnLinkPrefix: There is already smaller on-link prefix %s on interface %u",
-                        smallestOnLinkPrefix->ToString().AsCString(), mInfraIfIndex);
+            LogInfo("EvaluateOnLinkPrefix: There is already favored on-link prefix %s on %s",
+                    mFavoredDiscoveredOnLinkPrefix.ToString().AsCString(), mInfraIf.ToString().AsCString());
             DeprecateOnLinkPrefix();
         }
     }
 
 exit:
-    return newOnLinkPrefix;
+    return;
 }
 
 void RoutingManager::HandleOnLinkPrefixDeprecateTimer(Timer &aTimer)
@@ -555,79 +562,130 @@
 
 void RoutingManager::HandleOnLinkPrefixDeprecateTimer(void)
 {
-    otLogInfoBr("Local on-link prefix %s expired", mLocalOnLinkPrefix.ToString().AsCString());
-    RemoveExternalRoute(mLocalOnLinkPrefix);
+    OT_ASSERT(!mIsAdvertisingLocalOnLinkPrefix);
+
+    LogInfo("Local on-link prefix %s expired", mLocalOnLinkPrefix.ToString().AsCString());
+
+    if (!mDiscoveredPrefixTable.ContainsOnLinkPrefix(mLocalOnLinkPrefix))
+    {
+        UnpublishExternalRoute(mLocalOnLinkPrefix);
+    }
 }
 
 void RoutingManager::DeprecateOnLinkPrefix(void)
 {
     OT_ASSERT(mIsAdvertisingLocalOnLinkPrefix);
 
-    otLogInfoBr("Deprecate local on-link prefix %s", mLocalOnLinkPrefix.ToString().AsCString());
+    mIsAdvertisingLocalOnLinkPrefix = false;
+
+    LogInfo("Deprecate local on-link prefix %s", mLocalOnLinkPrefix.ToString().AsCString());
     mOnLinkPrefixDeprecateTimer.StartAt(mTimeAdvertisedOnLinkPrefix,
                                         TimeMilli::SecToMsec(kDefaultOnLinkPrefixLifetime));
 }
 
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
+void RoutingManager::EvaluateNat64Prefix(void)
+{
+    OT_ASSERT(mIsRunning);
+
+    NetworkData::Iterator            iterator = NetworkData::kIteratorInit;
+    NetworkData::ExternalRouteConfig config;
+    Ip6::Prefix                      smallestNat64Prefix;
+
+    LogInfo("Evaluating NAT64 prefix");
+
+    smallestNat64Prefix.Clear();
+    while (Get<NetworkData::Leader>().GetNextExternalRoute(iterator, config) == kErrorNone)
+    {
+        const Ip6::Prefix &prefix = config.GetPrefix();
+
+        if (config.mNat64 && prefix.IsValidNat64())
+        {
+            if (smallestNat64Prefix.GetLength() == 0 || prefix < smallestNat64Prefix)
+            {
+                smallestNat64Prefix = prefix;
+            }
+        }
+    }
+
+    if (smallestNat64Prefix.GetLength() == 0 || smallestNat64Prefix == mLocalNat64Prefix)
+    {
+        LogInfo("No NAT64 prefix in Network Data is smaller than the local NAT64 prefix %s",
+                mLocalNat64Prefix.ToString().AsCString());
+
+        // Advertise local NAT64 prefix.
+        if (!mIsAdvertisingLocalNat64Prefix &&
+            PublishExternalRoute(mLocalNat64Prefix, NetworkData::kRoutePreferenceLow, /* aNat64= */ true) == kErrorNone)
+        {
+            mIsAdvertisingLocalNat64Prefix = true;
+        }
+    }
+    else if (mIsAdvertisingLocalNat64Prefix && smallestNat64Prefix < mLocalNat64Prefix)
+    {
+        // Withdraw local NAT64 prefix if it's not the smallest one in Network Data.
+        // TODO: remove the prefix with lower preference after discovering upstream NAT64 prefix is supported
+        LogNote("Withdrawing local NAT64 prefix since a smaller one %s exists.",
+                smallestNat64Prefix.ToString().AsCString());
+
+        UnpublishExternalRoute(mLocalNat64Prefix);
+        mIsAdvertisingLocalNat64Prefix = false;
+    }
+}
+#endif
+
 // This method evaluate the routing policy depends on prefix and route
 // information on Thread Network and infra link. As a result, this
 // method May send RA messages on infra link and publish/unpublish
-// OMR prefix in the Thread network.
+// OMR and NAT64 prefix in the Thread network.
 void RoutingManager::EvaluateRoutingPolicy(void)
 {
     OT_ASSERT(mIsRunning);
 
-    const Ip6::Prefix *newOnLinkPrefix = nullptr;
-    OmrPrefixArray     newOmrPrefixes;
+    LogInfo("Evaluating routing policy");
 
-    otLogInfoBr("Evaluating routing policy");
-
-    // 0. Evaluate on-link & OMR prefixes.
-    newOnLinkPrefix = EvaluateOnLinkPrefix();
-    EvaluateOmrPrefix(newOmrPrefixes);
+    // 0. Evaluate on-link, OMR and NAT64 prefixes.
+    EvaluateOnLinkPrefix();
+    EvaluateOmrPrefix();
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
+    EvaluateNat64Prefix();
+#endif
 
     // 1. Send Router Advertisement message if necessary.
-    SendRouterAdvertisement(newOmrPrefixes, newOnLinkPrefix);
+    SendRouterAdvertisement(kAdvPrefixesFromNetData);
 
-    if (newOmrPrefixes.IsEmpty())
+    // 2. Schedule routing policy timer with random interval for the next Router Advertisement.
     {
-        // This is the very exceptional case and happens only when we failed to publish
-        // our local OMR prefix to the Thread network. We schedule the Router Advertisement
-        // timer to re-evaluate our routing policy in the future.
+        uint32_t nextSendDelay;
 
-        otLogWarnBr("No OMR prefix advertised! Start Router Advertisement timer for future evaluation");
-    }
+        nextSendDelay = Random::NonCrypto::GetUint32InRange(kMinRtrAdvInterval, kMaxRtrAdvInterval);
 
-    // 2. Schedule Router Advertisement timer with random interval.
-    {
-        uint32_t nextSendTime;
-
-        nextSendTime = Random::NonCrypto::GetUint32InRange(kMinRtrAdvInterval, kMaxRtrAdvInterval);
-
-        if (mRouterAdvertisementCount <= kMaxInitRtrAdvertisements && nextSendTime > kMaxInitRtrAdvInterval)
+        if (mRouterAdvertisementCount <= kMaxInitRtrAdvertisements && nextSendDelay > kMaxInitRtrAdvInterval)
         {
-            nextSendTime = kMaxInitRtrAdvInterval;
+            nextSendDelay = kMaxInitRtrAdvInterval;
         }
 
-        otLogInfoBr("Router advertisement scheduled in %u seconds", nextSendTime);
-        mRouterAdvertisementTimer.Start(Time::SecToMsec(nextSendTime));
+        StartRoutingPolicyEvaluationDelay(Time::SecToMsec(nextSendDelay));
     }
-
-    // 3. Update advertised on-link & OMR prefixes information.
-    mIsAdvertisingLocalOnLinkPrefix = (newOnLinkPrefix == &mLocalOnLinkPrefix);
-    mAdvertisedOmrPrefixes          = newOmrPrefixes;
 }
 
-void RoutingManager::StartRoutingPolicyEvaluationDelay(void)
+void RoutingManager::StartRoutingPolicyEvaluationJitter(uint32_t aJitterMilli)
 {
     OT_ASSERT(mIsRunning);
 
-    uint32_t randomDelay;
+    StartRoutingPolicyEvaluationDelay(Random::NonCrypto::GetUint32InRange(0, aJitterMilli));
+}
 
-    static_assert(kMaxRoutingPolicyDelay > 0, "invalid maximum routing policy evaluation delay");
-    randomDelay = Random::NonCrypto::GetUint32InRange(0, Time::SecToMsec(kMaxRoutingPolicyDelay));
+void RoutingManager::StartRoutingPolicyEvaluationDelay(uint32_t aDelayMilli)
+{
+    TimeMilli now          = TimerMilli::GetNow();
+    TimeMilli evaluateTime = now + aDelayMilli;
+    TimeMilli earliestTime = mLastRouterAdvertisementSendTime + kMinDelayBetweenRtrAdvs;
 
-    otLogInfoBr("Start evaluating routing policy, scheduled in %u milliseconds", randomDelay);
-    mRoutingPolicyTimer.Start(randomDelay);
+    evaluateTime = OT_MAX(evaluateTime, earliestTime);
+
+    LogInfo("Start evaluating routing policy, scheduled in %u milliseconds", evaluateTime - now);
+
+    mRoutingPolicyTimer.FireAtIfEarlier(evaluateTime);
 }
 
 // starts sending Router Solicitations in random delay
@@ -636,14 +694,14 @@
 {
     uint32_t randomDelay;
 
-    VerifyOrExit(!mRouterSolicitTimer.IsRunning() && mRouterSolicitCount == 0);
+    VerifyOrExit(!IsRouterSolicitationInProgress());
 
-    mVicariousRouterSolicitTimer.Stop();
+    OT_ASSERT(mRouterSolicitCount == 0);
 
     static_assert(kMaxRtrSolicitationDelay > 0, "invalid maximum Router Solicitation delay");
     randomDelay = Random::NonCrypto::GetUint32InRange(0, Time::SecToMsec(kMaxRtrSolicitationDelay));
 
-    otLogInfoBr("Start Router Solicitation, scheduled in %u milliseconds", randomDelay);
+    LogInfo("Start Router Solicitation, scheduled in %u milliseconds", randomDelay);
     mTimeRouterSolicitStart = TimerMilli::GetNow();
     mRouterSolicitTimer.Start(randomDelay);
 
@@ -651,117 +709,179 @@
     return;
 }
 
+bool RoutingManager::IsRouterSolicitationInProgress(void) const
+{
+    return mRouterSolicitTimer.IsRunning() || mRouterSolicitCount > 0;
+}
+
 Error RoutingManager::SendRouterSolicitation(void)
 {
-    Ip6::Address                    destAddress;
-    RouterAdv::RouterSolicitMessage routerSolicit;
+    Ip6::Address                  destAddress;
+    Ip6::Nd::RouterSolicitMessage routerSolicit;
+    InfraIf::Icmp6Packet          packet;
 
     OT_ASSERT(IsInitialized());
 
+    packet.InitFrom(routerSolicit);
     destAddress.SetToLinkLocalAllRoutersMulticast();
-    return otPlatInfraIfSendIcmp6Nd(mInfraIfIndex, &destAddress, reinterpret_cast<const uint8_t *>(&routerSolicit),
-                                    sizeof(routerSolicit));
+
+    return mInfraIf.Send(packet, destAddress);
 }
 
-// This method sends Router Advertisement messages to advertise on-link prefix and route for OMR prefix.
-// @param[in]  aNewOmrPrefixes   An array of the new OMR prefixes to be advertised.
-//                               Empty array means we should stop advertising OMR prefixes.
-// @param[in]  aOnLinkPrefix     A pointer to the new on-link prefix to be advertised.
-//                               nullptr means we should stop advertising on-link prefix.
-void RoutingManager::SendRouterAdvertisement(const OmrPrefixArray &aNewOmrPrefixes, const Ip6::Prefix *aNewOnLinkPrefix)
+void RoutingManager::SendRouterAdvertisement(RouterAdvTxMode aRaTxMode)
 {
-    uint8_t  buffer[kMaxRouterAdvMessageLength];
-    uint16_t bufferLength = 0;
+    // RA message max length is derived to accommodate:
+    //
+    // - The RA header,
+    // - At most one PIO (for local on-link prefix),
+    // - At most twice `kMaxOnMeshPrefixes` RIO for on-mesh prefixes.
+    //   Factor two is used for RIO to account for entries invalidating
+    //   previous prefixes while adding new ones.
 
-    static_assert(sizeof(mRouterAdvMessage) <= sizeof(buffer), "RA buffer too small");
-    memcpy(buffer, &mRouterAdvMessage, sizeof(mRouterAdvMessage));
-    bufferLength += sizeof(mRouterAdvMessage);
+    static constexpr uint16_t kMaxRaLength =
+        sizeof(Ip6::Nd::RouterAdvertMessage::Header) + sizeof(Ip6::Nd::PrefixInfoOption) +
+        2 * kMaxOnMeshPrefixes * (sizeof(Ip6::Nd::RouteInfoOption) + sizeof(Ip6::Prefix));
 
-    if (aNewOnLinkPrefix != nullptr)
+    uint8_t                         buffer[kMaxRaLength];
+    Ip6::Nd::RouterAdvertMessage    raMsg(mRouterAdvertHeader, buffer);
+    NetworkData::Iterator           iterator;
+    NetworkData::OnMeshPrefixConfig prefixConfig;
+
+    // Append PIO for local on-link prefix. Ensure it is either being
+    // advertised or deprecated.
+
+    if (mIsAdvertisingLocalOnLinkPrefix || mOnLinkPrefixDeprecateTimer.IsRunning())
     {
-        OT_ASSERT(aNewOnLinkPrefix == &mLocalOnLinkPrefix);
+        uint32_t validLifetime     = kDefaultOnLinkPrefixLifetime;
+        uint32_t preferredLifetime = kDefaultOnLinkPrefixLifetime;
 
-        RouterAdv::PrefixInfoOption pio;
-
-        pio.SetOnLink(true);
-        pio.SetAutoAddrConfig(true);
-        pio.SetValidLifetime(kDefaultOnLinkPrefixLifetime);
-        pio.SetPreferredLifetime(kDefaultOnLinkPrefixLifetime);
-        pio.SetPrefix(*aNewOnLinkPrefix);
-
-        OT_ASSERT(bufferLength + pio.GetSize() <= sizeof(buffer));
-        memcpy(buffer + bufferLength, &pio, pio.GetSize());
-        bufferLength += pio.GetSize();
-
-        if (!mIsAdvertisingLocalOnLinkPrefix)
+        if (mOnLinkPrefixDeprecateTimer.IsRunning())
         {
-            otLogInfoBr("Start advertising new on-link prefix %s on interface %u",
-                        aNewOnLinkPrefix->ToString().AsCString(), mInfraIfIndex);
+            validLifetime     = TimeMilli::MsecToSec(mOnLinkPrefixDeprecateTimer.GetFireTime() - TimerMilli::GetNow());
+            preferredLifetime = 0;
         }
 
-        otLogInfoBr("Send on-link prefix %s in PIO (preferred lifetime = %u seconds, valid lifetime = %u seconds)",
-                    aNewOnLinkPrefix->ToString().AsCString(), pio.GetPreferredLifetime(), pio.GetValidLifetime());
+        SuccessOrAssert(raMsg.AppendPrefixInfoOption(mLocalOnLinkPrefix, validLifetime, preferredLifetime));
 
-        mTimeAdvertisedOnLinkPrefix = TimerMilli::GetNow();
-    }
-    else if (mOnLinkPrefixDeprecateTimer.IsRunning())
-    {
-        RouterAdv::PrefixInfoOption pio;
-
-        pio.SetOnLink(true);
-        pio.SetAutoAddrConfig(true);
-        pio.SetValidLifetime(TimeMilli::MsecToSec(mOnLinkPrefixDeprecateTimer.GetFireTime() - TimerMilli::GetNow()));
-
-        // Set zero preferred lifetime to immediately deprecate the advertised on-link prefix.
-        pio.SetPreferredLifetime(0);
-        pio.SetPrefix(mLocalOnLinkPrefix);
-
-        OT_ASSERT(bufferLength + pio.GetSize() <= sizeof(buffer));
-        memcpy(buffer + bufferLength, &pio, pio.GetSize());
-        bufferLength += pio.GetSize();
-
-        otLogInfoBr("Send on-link prefix %s in PIO (preferred lifetime = %u seconds, valid lifetime = %u seconds)",
-                    mLocalOnLinkPrefix.ToString().AsCString(), pio.GetPreferredLifetime(), pio.GetValidLifetime());
-    }
-
-    // Invalidate the advertised OMR prefixes if they are no longer in the new OMR prefix array.
-
-    for (const Ip6::Prefix &advertisedOmrPrefix : mAdvertisedOmrPrefixes)
-    {
-        if (!aNewOmrPrefixes.Contains(advertisedOmrPrefix))
+        if (mIsAdvertisingLocalOnLinkPrefix)
         {
-            RouterAdv::RouteInfoOption rio;
+            mTimeAdvertisedOnLinkPrefix = TimerMilli::GetNow();
+        }
 
-            // Set zero route lifetime to immediately invalidate the advertised OMR prefix.
-            rio.SetRouteLifetime(0);
-            rio.SetPrefix(advertisedOmrPrefix);
+        LogInfo("RouterAdvert: Added PIO for %s (valid=%u, preferred=%u)", mLocalOnLinkPrefix.ToString().AsCString(),
+                validLifetime, preferredLifetime);
+    }
 
-            OT_ASSERT(bufferLength + rio.GetSize() <= sizeof(buffer));
-            memcpy(buffer + bufferLength, &rio, rio.GetSize());
-            bufferLength += rio.GetSize();
+    // Determine which previously advertised prefixes need to be
+    // invalidated. Under `kInvalidateAllPrevPrefixes` mode we need
+    // to invalidate all. Under `kAdvPrefixesFromNetData` mode, we
+    // check Network Data entries and invalidate any previously
+    // advertised prefix that is no longer present in the Network
+    // Data. We go through all Network Data prefixes and mark the
+    // ones we find in `mAdvertisedPrefixes` as deleted by setting
+    // the prefix length to zero). By the end, the remaining entries
+    // in the array with a non-zero prefix length are invalidated.
 
-            otLogInfoBr("Stop advertising OMR prefix %s on interface %u", advertisedOmrPrefix.ToString().AsCString(),
-                        mInfraIfIndex);
+    if (aRaTxMode != kInvalidateAllPrevPrefixes)
+    {
+        iterator = NetworkData::kIteratorInit;
+
+        while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNone)
+        {
+            if (!prefixConfig.mOnMesh || prefixConfig.mDp || (prefixConfig.GetPrefix() == mLocalOmrPrefix.GetPrefix()))
+            {
+                continue;
+            }
+
+            mAdvertisedPrefixes.MarkAsDeleted(prefixConfig.GetPrefix());
+        }
+
+        if (mLocalOmrPrefix.IsAddedInNetData())
+        {
+            mAdvertisedPrefixes.MarkAsDeleted(mLocalOmrPrefix.GetPrefix());
         }
     }
 
-    for (const Ip6::Prefix &newOmrPrefix : aNewOmrPrefixes)
+    for (const OnMeshPrefix &prefix : mAdvertisedPrefixes)
     {
-        RouterAdv::RouteInfoOption rio;
+        if (prefix.GetLength() != 0)
+        {
+            SuccessOrAssert(raMsg.AppendRouteInfoOption(prefix, /* aRouteLifetime */ 0, mRouteInfoOptionPreference));
+            LogInfo("RouterAdvert: Added RIO for %s (lifetime=0)", prefix.ToString().AsCString());
+        }
+    }
 
-        rio.SetRouteLifetime(kDefaultOmrPrefixLifetime);
-        rio.SetPrefix(newOmrPrefix);
+    // Discover and add prefixes from Network Data to advertise as
+    // RIO in the Router Advertisement message.
 
-        OT_ASSERT(bufferLength + rio.GetSize() <= sizeof(buffer));
-        memcpy(buffer + bufferLength, &rio, rio.GetSize());
-        bufferLength += rio.GetSize();
+    mAdvertisedPrefixes.Clear();
 
-        otLogInfoBr("Send OMR prefix %s in RIO (valid lifetime = %u seconds)", newOmrPrefix.ToString().AsCString(),
+    if (aRaTxMode == kAdvPrefixesFromNetData)
+    {
+        // `mAdvertisedPrefixes` array has a limited size. We add more
+        // important prefixes first in the array to ensure they are
+        // advertised in the RA message. Note that `Add()` method
+        // will ensure to add a prefix only once (will check if
+        // prefix is already present in the array).
+
+        // (1) Local OMR prefix.
+
+        if (mLocalOmrPrefix.IsAddedInNetData())
+        {
+            mAdvertisedPrefixes.Add(mLocalOmrPrefix.GetPrefix());
+        }
+
+        // (2) Favored OMR prefix.
+
+        if (!mFavoredOmrPrefix.IsEmpty())
+        {
+            mAdvertisedPrefixes.Add(mFavoredOmrPrefix.GetPrefix());
+        }
+
+        // (3) All other OMR prefixes.
+
+        iterator = NetworkData::kIteratorInit;
+
+        while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNone)
+        {
+            // Local OMR prefix is added to the array depending on
+            // `mLocalOmrPrefix.IsAddedInNetData()` at step (1). As
+            // we iterate through the Network Data prefixes, we skip
+            // over entries matching the local OMR prefix. This
+            // ensures that we stop including it in emitted RA
+            // message as soon as we decide to remove it from Network
+            // Data. Note that upon requesting it to be removed from
+            // Network Data the change needs to be registered with
+            // leader and can take some time to be updated in Network
+            // Data.
+
+            if (IsValidOmrPrefix(prefixConfig) && (prefixConfig.GetPrefix() != mLocalOmrPrefix.GetPrefix()))
+            {
+                mAdvertisedPrefixes.Add(prefixConfig.GetPrefix());
+            }
+        }
+
+        // (4) All other on-mesh prefixes (excluding Domain Prefix).
+
+        iterator = NetworkData::kIteratorInit;
+
+        while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNone)
+        {
+            if (prefixConfig.mOnMesh && !prefixConfig.mDp && !IsValidOmrPrefix(prefixConfig))
+            {
+                mAdvertisedPrefixes.Add(prefixConfig.GetPrefix());
+            }
+        }
+
+        for (const OnMeshPrefix &prefix : mAdvertisedPrefixes)
+        {
+            SuccessOrAssert(raMsg.AppendRouteInfoOption(prefix, kDefaultOmrPrefixLifetime, mRouteInfoOptionPreference));
+            LogInfo("RouterAdvert: Added RIO for %s (lifetime=%u)", prefix.ToString().AsCString(),
                     kDefaultOmrPrefixLifetime);
+        }
     }
 
-    // Send the message only when there are options.
-    if (bufferLength > sizeof(mRouterAdvMessage))
+    if (raMsg.ContainsAnyOptions())
     {
         Error        error;
         Ip6::Address destAddress;
@@ -769,23 +889,95 @@
         ++mRouterAdvertisementCount;
 
         destAddress.SetToLinkLocalAllNodesMulticast();
-        error = otPlatInfraIfSendIcmp6Nd(mInfraIfIndex, &destAddress, buffer, bufferLength);
+
+        error = mInfraIf.Send(raMsg.GetAsPacket(), destAddress);
 
         if (error == kErrorNone)
         {
-            otLogInfoBr("Sent Router Advertisement on interface %u", mInfraIfIndex);
-            otDumpDebgBr("[BR-CERT] direction=send | type=RA |", buffer, bufferLength);
+            mLastRouterAdvertisementSendTime = TimerMilli::GetNow();
+            LogInfo("Sent Router Advertisement on %s", mInfraIf.ToString().AsCString());
+            DumpDebg("[BR-CERT] direction=send | type=RA |", raMsg.GetAsPacket().GetBytes(),
+                     raMsg.GetAsPacket().GetLength());
         }
         else
         {
-            otLogWarnBr("Failed to send Router Advertisement on interface %u: %s", mInfraIfIndex, ErrorToString(error));
+            LogWarn("Failed to send Router Advertisement on %s: %s", mInfraIf.ToString().AsCString(),
+                    ErrorToString(error));
         }
     }
 }
 
+bool RoutingManager::IsReceivedRouterAdvertFromManager(const Ip6::Nd::RouterAdvertMessage &aRaMessage) const
+{
+    // Determines whether or not a received RA message was prepared by
+    // by `RoutingManager` itself.
+
+    bool        isFromManager = false;
+    uint16_t    rioCount      = 0;
+    Ip6::Prefix prefix;
+
+    VerifyOrExit(aRaMessage.ContainsAnyOptions());
+
+    for (const Ip6::Nd::Option &option : aRaMessage)
+    {
+        switch (option.GetType())
+        {
+        case Ip6::Nd::Option::kTypePrefixInfo:
+        {
+            // PIO should match `mLocalOnLinkPrefix`.
+
+            const Ip6::Nd::PrefixInfoOption &pio = static_cast<const Ip6::Nd::PrefixInfoOption &>(option);
+
+            VerifyOrExit(pio.IsValid());
+            pio.GetPrefix(prefix);
+
+            VerifyOrExit(prefix == mLocalOnLinkPrefix);
+            break;
+        }
+
+        case Ip6::Nd::Option::kTypeRouteInfo:
+        {
+            // RIO (with non-zero lifetime) should match entries from
+            // `mAdvertisedPrefixes`. We keep track of the number
+            // of matched RIOs and check after the loop ends that all
+            // entries were seen.
+
+            const Ip6::Nd::RouteInfoOption &rio = static_cast<const Ip6::Nd::RouteInfoOption &>(option);
+
+            VerifyOrExit(rio.IsValid());
+            rio.GetPrefix(prefix);
+
+            if (rio.GetRouteLifetime() != 0)
+            {
+                VerifyOrExit(mAdvertisedPrefixes.Contains(prefix));
+                rioCount++;
+            }
+
+            break;
+        }
+
+        default:
+            ExitNow();
+        }
+    }
+
+    VerifyOrExit(rioCount == mAdvertisedPrefixes.GetLength());
+
+    isFromManager = true;
+
+exit:
+    return isFromManager;
+}
+
+bool RoutingManager::IsValidBrUlaPrefix(const Ip6::Prefix &aBrUlaPrefix)
+{
+    return aBrUlaPrefix.mLength == kBrUlaPrefixLength && aBrUlaPrefix.mPrefix.mFields.m8[0] == 0xfd;
+}
+
 bool RoutingManager::IsValidOmrPrefix(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig)
 {
-    return IsValidOmrPrefix(aOnMeshPrefixConfig.GetPrefix()) && aOnMeshPrefixConfig.mSlaac && !aOnMeshPrefixConfig.mDp;
+    return IsValidOmrPrefix(aOnMeshPrefixConfig.GetPrefix()) && aOnMeshPrefixConfig.mOnMesh &&
+           aOnMeshPrefixConfig.mSlaac && aOnMeshPrefixConfig.mStable && !aOnMeshPrefixConfig.mDp;
 }
 
 bool RoutingManager::IsValidOmrPrefix(const Ip6::Prefix &aOmrPrefix)
@@ -795,46 +987,19 @@
            (aOmrPrefix.mLength >= 3 && (aOmrPrefix.GetBytes()[0] & 0xE0) == 0x20);
 }
 
-bool RoutingManager::IsValidOnLinkPrefix(const RouterAdv::PrefixInfoOption &aPio, bool aManagedAddrConfig)
+bool RoutingManager::IsValidOnLinkPrefix(const Ip6::Nd::PrefixInfoOption &aPio)
 {
-    return IsValidOnLinkPrefix(aPio.GetPrefix()) && aPio.GetOnLink() &&
-           (aPio.GetAutoAddrConfig() || aManagedAddrConfig);
+    Ip6::Prefix prefix;
+
+    aPio.GetPrefix(prefix);
+
+    return IsValidOnLinkPrefix(prefix) && aPio.IsOnLinkFlagSet() && aPio.IsAutoAddrConfigFlagSet();
 }
 
 bool RoutingManager::IsValidOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix)
 {
-    return !aOnLinkPrefix.IsLinkLocal() && !aOnLinkPrefix.IsMulticast();
-}
-
-void RoutingManager::HandleRouterAdvertisementTimer(Timer &aTimer)
-{
-    aTimer.Get<RoutingManager>().HandleRouterAdvertisementTimer();
-}
-
-void RoutingManager::HandleRouterAdvertisementTimer(void)
-{
-    otLogInfoBr("Router advertisement timer triggered");
-
-    EvaluateRoutingPolicy();
-}
-
-void RoutingManager::HandleVicariousRouterSolicitTimer(Timer &aTimer)
-{
-    aTimer.Get<RoutingManager>().HandleVicariousRouterSolicitTimer();
-}
-
-void RoutingManager::HandleVicariousRouterSolicitTimer(void)
-{
-    otLogInfoBr("Vicarious router solicitation time out");
-
-    for (const ExternalPrefix &prefix : mDiscoveredPrefixes)
-    {
-        if (prefix.mTimeLastUpdate <= mTimeVicariousRouterSolicitStart)
-        {
-            StartRouterSolicitationDelay();
-            break;
-        }
-    }
+    return aOnLinkPrefix.IsValid() && (aOnLinkPrefix.GetLength() > 0) && !aOnLinkPrefix.IsLinkLocal() &&
+           !aOnLinkPrefix.IsMulticast();
 }
 
 void RoutingManager::HandleRouterSolicitTimer(Timer &aTimer)
@@ -844,7 +1009,7 @@
 
 void RoutingManager::HandleRouterSolicitTimer(void)
 {
-    otLogInfoBr("Router solicitation times out");
+    LogInfo("Router solicitation times out");
 
     if (mRouterSolicitCount < kMaxRtrSolicitations)
     {
@@ -855,14 +1020,14 @@
 
         if (error == kErrorNone)
         {
-            otLogDebgBr("Successfully sent %uth Router Solicitation", mRouterSolicitCount);
+            LogDebg("Successfully sent %uth Router Solicitation", mRouterSolicitCount);
             ++mRouterSolicitCount;
             nextSolicitationDelay =
                 (mRouterSolicitCount == kMaxRtrSolicitations) ? kMaxRtrSolicitationDelay : kRtrSolicitationInterval;
         }
         else
         {
-            otLogCritBr("Failed to send %uth Router Solicitation: %s", mRouterSolicitCount, ErrorToString(error));
+            LogCrit("Failed to send %uth Router Solicitation: %s", mRouterSolicitCount, ErrorToString(error));
 
             // It's unexpected that RS will fail and we will retry sending RS messages in 60 seconds.
             // Notice that `mRouterSolicitCount` is not incremented for failed RS and thus we will
@@ -872,36 +1037,25 @@
             mRouterSolicitCount   = 0;
         }
 
-        otLogDebgBr("Router solicitation timer scheduled in %u seconds", nextSolicitationDelay);
+        LogDebg("Router solicitation timer scheduled in %u seconds", nextSolicitationDelay);
         mRouterSolicitTimer.Start(Time::SecToMsec(nextSolicitationDelay));
     }
     else
     {
-        // Invalidate/deprecate all OMR/on-link prefixes that are not refreshed during Router Solicitation.
-        for (ExternalPrefix &prefix : mDiscoveredPrefixes)
-        {
-            if (prefix.mTimeLastUpdate <= mTimeRouterSolicitStart)
-            {
-                if (prefix.mIsOnLinkPrefix)
-                {
-                    prefix.mPreferredLifetime = 0;
-                }
-                else
-                {
-                    InvalidateDiscoveredPrefixes(&prefix.mPrefix, prefix.mIsOnLinkPrefix);
-                }
-            }
-        }
+        // Remove route prefixes and deprecate on-link prefixes that
+        // are not refreshed during Router Solicitation.
+        mDiscoveredPrefixTable.RemoveOrDeprecateOldEntries(mTimeRouterSolicitStart);
 
         // Invalidate the learned RA message if it is not refreshed during Router Solicitation.
         if (mTimeRouterAdvMessageLastUpdate <= mTimeRouterSolicitStart)
         {
-            UpdateRouterAdvMessage(/* aRouterAdvMessage */ nullptr);
+            UpdateRouterAdvertHeader(/* aRouterAdvertMessage */ nullptr);
         }
 
-        // Re-evaluate our routing policy and send Router Advertisement if necessary.
-        EvaluateRoutingPolicy();
         mRouterSolicitCount = 0;
+
+        // Re-evaluate our routing policy and send Router Advertisement if necessary.
+        StartRoutingPolicyEvaluationDelay(/* aDelayJitter */ 0);
     }
 }
 
@@ -912,55 +1066,942 @@
 
 void RoutingManager::HandleDiscoveredPrefixStaleTimer(void)
 {
-    otLogInfoBr("All on-link prefixes are stale");
+    LogInfo("Stale On-Link or OMR Prefixes or RA messages are detected");
     StartRouterSolicitationDelay();
 }
 
-void RoutingManager::HandleDiscoveredPrefixInvalidTimer(Timer &aTimer)
-{
-    aTimer.Get<RoutingManager>().HandleDiscoveredPrefixInvalidTimer();
-}
-
-void RoutingManager::HandleDiscoveredPrefixInvalidTimer(void)
-{
-    InvalidateDiscoveredPrefixes();
-}
-
 void RoutingManager::HandleRoutingPolicyTimer(Timer &aTimer)
 {
     aTimer.Get<RoutingManager>().EvaluateRoutingPolicy();
 }
 
-void RoutingManager::HandleRouterSolicit(const Ip6::Address &aSrcAddress,
-                                         const uint8_t *     aBuffer,
-                                         uint16_t            aBufferLength)
+void RoutingManager::HandleRouterSolicit(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress)
 {
-    uint32_t randomDelay;
-
+    OT_UNUSED_VARIABLE(aPacket);
     OT_UNUSED_VARIABLE(aSrcAddress);
-    OT_UNUSED_VARIABLE(aBuffer);
-    OT_UNUSED_VARIABLE(aBufferLength);
 
-    VerifyOrExit(!mRouterSolicitTimer.IsRunning());
-    otLogInfoBr("Received Router Solicitation from %s on interface %u", aSrcAddress.ToString().AsCString(),
-                mInfraIfIndex);
+    LogInfo("Received Router Solicitation from %s on %s", aSrcAddress.ToString().AsCString(),
+            mInfraIf.ToString().AsCString());
 
-    if (!mVicariousRouterSolicitTimer.IsRunning())
+    // Schedule routing policy evaluation with random jitter to respond with Router Advertisement.
+    StartRoutingPolicyEvaluationJitter(kRaReplyJitter);
+}
+
+void RoutingManager::HandleRouterAdvertisement(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress)
+{
+    Ip6::Nd::RouterAdvertMessage routerAdvMessage(aPacket);
+
+    OT_ASSERT(mIsRunning);
+
+    VerifyOrExit(routerAdvMessage.IsValid());
+
+    LogInfo("Received Router Advertisement from %s on %s", aSrcAddress.ToString().AsCString(),
+            mInfraIf.ToString().AsCString());
+    DumpDebg("[BR-CERT] direction=recv | type=RA |", aPacket.GetBytes(), aPacket.GetLength());
+
+    mDiscoveredPrefixTable.ProcessRouterAdvertMessage(routerAdvMessage, aSrcAddress);
+
+    // Remember the header and parameters of RA messages which are
+    // initiated from the infra interface.
+    if (mInfraIf.HasAddress(aSrcAddress))
     {
-        mTimeVicariousRouterSolicitStart = TimerMilli::GetNow();
-        mVicariousRouterSolicitTimer.Start(Time::SecToMsec(kVicariousSolicitationTime));
+        UpdateRouterAdvertHeader(&routerAdvMessage);
     }
 
-    // Schedule Router Advertisements with random delay.
-    randomDelay = Random::NonCrypto::GetUint32InRange(0, kMaxRaDelayTime);
-    otLogInfoBr("Router Advertisement scheduled in %u milliseconds", randomDelay);
-    mRouterAdvertisementTimer.Start(randomDelay);
-
 exit:
     return;
 }
 
-uint32_t RoutingManager::ExternalPrefix::GetPrefixExpireDelay(uint32_t aValidLifetime)
+bool RoutingManager::ShouldProcessPrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio, const Ip6::Prefix &aPrefix)
+{
+    // Indicate whether to process or skip a given prefix
+    // from a PIO (from received RA message).
+
+    bool shouldProcess = false;
+
+    VerifyOrExit(mIsRunning);
+
+    if (!IsValidOnLinkPrefix(aPio))
+    {
+        LogInfo("Ignore invalid on-link prefix in PIO: %s", aPrefix.ToString().AsCString());
+        ExitNow();
+    }
+
+    if (mIsAdvertisingLocalOnLinkPrefix)
+    {
+        VerifyOrExit(aPrefix != mLocalOnLinkPrefix);
+    }
+
+    shouldProcess = true;
+
+exit:
+    return shouldProcess;
+}
+
+bool RoutingManager::ShouldProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption &aRio, const Ip6::Prefix &aPrefix)
+{
+    // Indicate whether to process or skip a given prefix
+    // from a RIO (from received RA message).
+
+    OT_UNUSED_VARIABLE(aRio);
+
+    bool shouldProcess = false;
+
+    VerifyOrExit(mIsRunning);
+
+    if (aPrefix.GetLength() == 0)
+    {
+        // Always process default route ::/0 prefix.
+        ExitNow(shouldProcess = true);
+    }
+
+    if (!IsValidOmrPrefix(aPrefix))
+    {
+        LogInfo("Ignore RIO prefix %s since not a valid OMR prefix", aPrefix.ToString().AsCString());
+        ExitNow();
+    }
+
+    VerifyOrExit(mLocalOmrPrefix.GetPrefix() != aPrefix);
+
+    // Ignore OMR prefixes advertised by ourselves or in current Thread Network Data.
+    // The `mAdvertisedPrefixes` and the OMR prefix set in Network Data should eventually
+    // be equal, but there is time that they are not synchronized immediately:
+    // 1. Network Data could contain more OMR prefixes than `mAdvertisedPrefixes` because
+    //    we added random delay before Evaluating routing policy when Network Data is changed.
+    // 2. `mAdvertisedPrefixes` could contain more OMR prefixes than Network Data because
+    //    it takes time to sync a new OMR prefix into Network Data (multicast loopback RA
+    //    messages are usually faster than Thread Network Data propagation).
+    // They are the reasons why we need both the checks.
+
+    VerifyOrExit(!mAdvertisedPrefixes.Contains(aPrefix));
+    VerifyOrExit(!Get<RoutingManager>().NetworkDataContainsOmrPrefix(aPrefix));
+
+    shouldProcess = true;
+
+exit:
+    return shouldProcess;
+}
+
+void RoutingManager::HandleDiscoveredPrefixTableChanged(void)
+{
+    // This is a callback from `mDiscoveredPrefixTable` indicating that
+    // there has been a change in the table. If the favored on-link
+    // prefix has changed, we trigger a re-evaluation of the routing
+    // policy.
+
+    Ip6::Prefix newFavoredPrefix;
+
+    VerifyOrExit(mIsRunning);
+
+    ResetDiscoveredPrefixStaleTimer();
+
+    mDiscoveredPrefixTable.FindFavoredOnLinkPrefix(newFavoredPrefix);
+
+    if (newFavoredPrefix != mFavoredDiscoveredOnLinkPrefix)
+    {
+        StartRoutingPolicyEvaluationJitter(kRoutingPolicyEvaluationJitter);
+    }
+
+exit:
+    return;
+}
+
+bool RoutingManager::NetworkDataContainsOmrPrefix(const Ip6::Prefix &aPrefix) const
+{
+    NetworkData::Iterator           iterator = NetworkData::kIteratorInit;
+    NetworkData::OnMeshPrefixConfig onMeshPrefixConfig;
+    bool                            contain = false;
+
+    while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, onMeshPrefixConfig) == kErrorNone)
+    {
+        if (IsValidOmrPrefix(onMeshPrefixConfig) && onMeshPrefixConfig.GetPrefix() == aPrefix)
+        {
+            contain = true;
+            break;
+        }
+    }
+
+    return contain;
+}
+
+void RoutingManager::UpdateRouterAdvertHeader(const Ip6::Nd::RouterAdvertMessage *aRouterAdvertMessage)
+{
+    // Updates the `mRouterAdvertHeader` from the given RA message.
+
+    Ip6::Nd::RouterAdvertMessage::Header oldHeader;
+
+    if (aRouterAdvertMessage != nullptr)
+    {
+        // We skip and do not update RA header if the received RA message
+        // was not prepared and sent by `RoutingManager` itself.
+
+        VerifyOrExit(!IsReceivedRouterAdvertFromManager(*aRouterAdvertMessage));
+    }
+
+    oldHeader                       = mRouterAdvertHeader;
+    mTimeRouterAdvMessageLastUpdate = TimerMilli::GetNow();
+
+    if (aRouterAdvertMessage == nullptr || aRouterAdvertMessage->GetHeader().GetRouterLifetime() == 0)
+    {
+        mRouterAdvertHeader.SetToDefault();
+        mLearntRouterAdvMessageFromHost = false;
+    }
+    else
+    {
+        // The checksum is set to zero in `mRouterAdvertHeader`
+        // which indicates to platform that it needs to do the
+        // calculation and update it.
+
+        mRouterAdvertHeader = aRouterAdvertMessage->GetHeader();
+        mRouterAdvertHeader.SetChecksum(0);
+        mLearntRouterAdvMessageFromHost = true;
+    }
+
+    ResetDiscoveredPrefixStaleTimer();
+
+    if (mRouterAdvertHeader != oldHeader)
+    {
+        // If there was a change to the header, start timer to
+        // reevaluate routing policy and send RA message with new
+        // header.
+
+        StartRoutingPolicyEvaluationJitter(kRoutingPolicyEvaluationJitter);
+    }
+
+exit:
+    return;
+}
+
+void RoutingManager::ResetDiscoveredPrefixStaleTimer(void)
+{
+    TimeMilli now = TimerMilli::GetNow();
+    TimeMilli nextStaleTime;
+
+    OT_ASSERT(mIsRunning);
+
+    // The stale timer triggers sending RS to check the state of
+    // discovered prefixes and host RA messages.
+
+    nextStaleTime = mDiscoveredPrefixTable.CalculateNextStaleTime(now);
+
+    // Check for stale Router Advertisement Message if learnt from Host.
+    if (mLearntRouterAdvMessageFromHost)
+    {
+        TimeMilli raStaleTime = OT_MAX(now, mTimeRouterAdvMessageLastUpdate + Time::SecToMsec(kRtrAdvStaleTime));
+
+        nextStaleTime = OT_MIN(nextStaleTime, raStaleTime);
+    }
+
+    if (nextStaleTime == now.GetDistantFuture())
+    {
+        if (mDiscoveredPrefixStaleTimer.IsRunning())
+        {
+            LogDebg("Prefix stale timer stopped");
+        }
+
+        mDiscoveredPrefixStaleTimer.Stop();
+    }
+    else
+    {
+        mDiscoveredPrefixStaleTimer.FireAt(nextStaleTime);
+        LogDebg("Prefix stale timer scheduled in %lu ms", nextStaleTime - now);
+    }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+// DiscoveredPrefixTable
+
+RoutingManager::DiscoveredPrefixTable::DiscoveredPrefixTable(Instance &aInstance)
+    : InstanceLocator(aInstance)
+    , mTimer(aInstance, HandleTimer)
+    , mSignalTask(aInstance, HandleSignalTask)
+    , mAllowDefaultRouteInNetData(false)
+{
+}
+
+void RoutingManager::DiscoveredPrefixTable::ProcessRouterAdvertMessage(const Ip6::Nd::RouterAdvertMessage &aRaMessage,
+                                                                       const Ip6::Address &                aSrcAddress)
+{
+    // Process a received RA message and update the prefix table.
+
+    Router *router = mRouters.FindMatching(aSrcAddress);
+
+    if (router == nullptr)
+    {
+        router = mRouters.PushBack();
+
+        if (router == nullptr)
+        {
+            LogWarn("Received RA from too many routers, ignore RA from %s", aSrcAddress.ToString().AsCString());
+            ExitNow();
+        }
+
+        router->mAddress = aSrcAddress;
+        router->mEntries.Clear();
+    }
+
+    // RA message can indicate router provides default route in the RA
+    // message header and can also include an RIO for `::/0`. When
+    // processing an RA message, the preference and lifetime values
+    // in a `::/0` RIO override the preference and lifetime values in
+    // the RA header (per RFC 4191 section 3.1).
+
+    ProcessDefaultRoute(aRaMessage.GetHeader(), *router);
+
+    for (const Ip6::Nd::Option &option : aRaMessage)
+    {
+        switch (option.GetType())
+        {
+        case Ip6::Nd::Option::kTypePrefixInfo:
+            ProcessPrefixInfoOption(static_cast<const Ip6::Nd::PrefixInfoOption &>(option), *router);
+            break;
+
+        case Ip6::Nd::Option::kTypeRouteInfo:
+            ProcessRouteInfoOption(static_cast<const Ip6::Nd::RouteInfoOption &>(option), *router);
+            break;
+
+        default:
+            break;
+        }
+    }
+
+    RemoveRoutersWithNoEntries();
+
+exit:
+    return;
+}
+
+void RoutingManager::DiscoveredPrefixTable::ProcessDefaultRoute(const Ip6::Nd::RouterAdvertMessage::Header &aRaHeader,
+                                                                Router &                                    aRouter)
+{
+    Entry *     entry;
+    Ip6::Prefix prefix;
+
+    prefix.Clear();
+    entry = aRouter.mEntries.FindMatching(Entry::Matcher(prefix, Entry::kTypeRoute));
+
+    if (entry == nullptr)
+    {
+        VerifyOrExit(aRaHeader.GetRouterLifetime() != 0);
+
+        entry = AllocateEntry();
+
+        if (entry == nullptr)
+        {
+            LogWarn("Discovered too many prefixes, ignore default route from RA header");
+            ExitNow();
+        }
+
+        entry->SetFrom(aRaHeader);
+        aRouter.mEntries.Push(*entry);
+    }
+    else
+    {
+        entry->SetFrom(aRaHeader);
+    }
+
+    UpdateNetworkDataOnChangeTo(*entry);
+    mTimer.FireAtIfEarlier(entry->GetExpireTime());
+    SignalTableChanged();
+
+exit:
+    return;
+}
+
+void RoutingManager::DiscoveredPrefixTable::ProcessPrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio,
+                                                                    Router &                         aRouter)
+{
+    Ip6::Prefix prefix;
+    Entry *     entry;
+
+    VerifyOrExit(aPio.IsValid());
+    aPio.GetPrefix(prefix);
+
+    VerifyOrExit(Get<RoutingManager>().ShouldProcessPrefixInfoOption(aPio, prefix));
+
+    LogInfo("Processing PIO (%s, %u seconds)", prefix.ToString().AsCString(), aPio.GetValidLifetime());
+
+    entry = aRouter.mEntries.FindMatching(Entry::Matcher(prefix, Entry::kTypeOnLink));
+
+    if (entry == nullptr)
+    {
+        VerifyOrExit(aPio.GetValidLifetime() != 0);
+
+        entry = AllocateEntry();
+
+        if (entry == nullptr)
+        {
+            LogWarn("Discovered too many prefixes, ignore on-link prefix %s", prefix.ToString().AsCString());
+            ExitNow();
+        }
+
+        entry->SetFrom(aPio);
+        aRouter.mEntries.Push(*entry);
+    }
+    else
+    {
+        Entry newEntry;
+
+        newEntry.SetFrom(aPio);
+        entry->AdoptValidAndPreferredLiftimesFrom(newEntry);
+    }
+
+    UpdateNetworkDataOnChangeTo(*entry);
+    mTimer.FireAtIfEarlier(entry->GetExpireTime());
+    SignalTableChanged();
+
+exit:
+    return;
+}
+
+void RoutingManager::DiscoveredPrefixTable::ProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption &aRio,
+                                                                   Router &                        aRouter)
+{
+    Ip6::Prefix prefix;
+    Entry *     entry;
+
+    VerifyOrExit(aRio.IsValid());
+    aRio.GetPrefix(prefix);
+
+    VerifyOrExit(Get<RoutingManager>().ShouldProcessRouteInfoOption(aRio, prefix));
+
+    LogInfo("Processing RIO (%s, %u seconds)", prefix.ToString().AsCString(), aRio.GetRouteLifetime());
+
+    entry = aRouter.mEntries.FindMatching(Entry::Matcher(prefix, Entry::kTypeRoute));
+
+    if (entry == nullptr)
+    {
+        VerifyOrExit(aRio.GetRouteLifetime() != 0);
+
+        entry = AllocateEntry();
+
+        if (entry == nullptr)
+        {
+            LogWarn("Discovered too many prefixes, ignore route prefix %s", prefix.ToString().AsCString());
+            ExitNow();
+        }
+
+        entry->SetFrom(aRio);
+        aRouter.mEntries.Push(*entry);
+    }
+    else
+    {
+        entry->SetFrom(aRio);
+    }
+
+    UpdateNetworkDataOnChangeTo(*entry);
+    mTimer.FireAtIfEarlier(entry->GetExpireTime());
+    SignalTableChanged();
+
+exit:
+    return;
+}
+
+void RoutingManager::DiscoveredPrefixTable::SetAllowDefaultRouteInNetData(bool aAllow)
+{
+    Entry *     favoredEntry;
+    Ip6::Prefix prefix;
+
+    VerifyOrExit(aAllow != mAllowDefaultRouteInNetData);
+
+    LogInfo("Allow default route in netdata: %s -> %s", ToYesNo(mAllowDefaultRouteInNetData), ToYesNo(aAllow));
+
+    mAllowDefaultRouteInNetData = aAllow;
+
+    prefix.Clear();
+    favoredEntry = FindFavoredEntryToPublish(prefix);
+    VerifyOrExit(favoredEntry != nullptr);
+
+    if (mAllowDefaultRouteInNetData)
+    {
+        PublishEntry(*favoredEntry);
+    }
+    else
+    {
+        UnpublishEntry(*favoredEntry);
+    }
+
+exit:
+    return;
+}
+
+void RoutingManager::DiscoveredPrefixTable::FindFavoredOnLinkPrefix(Ip6::Prefix &aPrefix) const
+{
+    // Find the smallest preferred on-link prefix entry in the table
+    // and return it in `aPrefix`. If there is none, `aPrefix` is
+    // cleared (prefix length is set to zero).
+
+    aPrefix.Clear();
+
+    for (const Router &router : mRouters)
+    {
+        for (const Entry &entry : router.mEntries)
+        {
+            if (!entry.IsOnLinkPrefix() || entry.IsDeprecated())
+            {
+                continue;
+            }
+
+            if ((aPrefix.GetLength() == 0) || (entry.GetPrefix() < aPrefix))
+            {
+                aPrefix = entry.GetPrefix();
+            }
+        }
+    }
+}
+
+bool RoutingManager::DiscoveredPrefixTable::ContainsOnLinkPrefix(const Ip6::Prefix &aPrefix) const
+{
+    return ContainsPrefix(Entry::Matcher(aPrefix, Entry::kTypeOnLink));
+}
+
+bool RoutingManager::DiscoveredPrefixTable::ContainsRoutePrefix(const Ip6::Prefix &aPrefix) const
+{
+    return ContainsPrefix(Entry::Matcher(aPrefix, Entry::kTypeRoute));
+}
+
+bool RoutingManager::DiscoveredPrefixTable::ContainsPrefix(const Entry::Matcher &aMatcher) const
+{
+    bool contains = false;
+
+    for (const Router &router : mRouters)
+    {
+        if (router.mEntries.ContainsMatching(aMatcher))
+        {
+            contains = true;
+            break;
+        }
+    }
+
+    return contains;
+}
+
+void RoutingManager::DiscoveredPrefixTable::RemoveOnLinkPrefix(const Ip6::Prefix &aPrefix, NetDataMode aNetDataMode)
+{
+    RemovePrefix(Entry::Matcher(aPrefix, Entry::kTypeOnLink), aNetDataMode);
+}
+
+void RoutingManager::DiscoveredPrefixTable::RemoveRoutePrefix(const Ip6::Prefix &aPrefix, NetDataMode aNetDataMode)
+{
+    RemovePrefix(Entry::Matcher(aPrefix, Entry::kTypeRoute), aNetDataMode);
+}
+
+void RoutingManager::DiscoveredPrefixTable::RemovePrefix(const Entry::Matcher &aMatcher, NetDataMode aNetDataMode)
+{
+    // Removes all entries matching a given prefix from the table.
+    // `aNetDataMode` specifies behavior when a match is found and
+    // removed. It indicates whether or not to unpublish it from
+    // Network Data.
+
+    LinkedList<Entry> removedEntries;
+
+    for (Router &router : mRouters)
+    {
+        router.mEntries.RemoveAllMatching(aMatcher, removedEntries);
+    }
+
+    VerifyOrExit(!removedEntries.IsEmpty());
+
+    if (aNetDataMode == kUnpublishFromNetData)
+    {
+        UnpublishEntry(*removedEntries.GetHead());
+    }
+
+    FreeEntries(removedEntries);
+    RemoveRoutersWithNoEntries();
+
+    SignalTableChanged();
+
+exit:
+    return;
+}
+
+void RoutingManager::DiscoveredPrefixTable::RemoveAllEntries(void)
+{
+    // Remove all entries from the table and unpublish them
+    // from Network Data.
+
+    for (Router &router : mRouters)
+    {
+        Entry *entry;
+
+        while ((entry = router.mEntries.Pop()) != nullptr)
+        {
+            UnpublishEntry(*entry);
+            FreeEntry(*entry);
+            SignalTableChanged();
+        }
+    }
+
+    RemoveRoutersWithNoEntries();
+    mTimer.Stop();
+}
+
+void RoutingManager::DiscoveredPrefixTable::RemoveOrDeprecateOldEntries(TimeMilli aTimeThreshold)
+{
+    // Remove route prefix entries and deprecate on-link entries in
+    // the table that are old (not updated since `aTimeThreshold`).
+
+    for (Router &router : mRouters)
+    {
+        for (Entry &entry : router.mEntries)
+        {
+            if (entry.GetLastUpdateTime() <= aTimeThreshold)
+            {
+                if (entry.IsOnLinkPrefix())
+                {
+                    entry.ClearPreferredLifetime();
+                }
+                else
+                {
+                    entry.ClearValidLifetime();
+                }
+
+                SignalTableChanged();
+            }
+        }
+    }
+
+    RemoveExpiredEntries();
+}
+
+TimeMilli RoutingManager::DiscoveredPrefixTable::CalculateNextStaleTime(TimeMilli aNow) const
+{
+    TimeMilli onLinkStaleTime = aNow;
+    TimeMilli routeStaleTime  = aNow.GetDistantFuture();
+    bool      foundOnLink     = false;
+
+    // For on-link prefixes, we consider stale time as when all on-link
+    // prefixes become stale (the latest stale time) but for route
+    // prefixes we consider the earliest stale time.
+
+    for (const Router &router : mRouters)
+    {
+        for (const Entry &entry : router.mEntries)
+        {
+            TimeMilli entryStaleTime = OT_MAX(aNow, entry.GetStaleTime());
+
+            if (entry.IsOnLinkPrefix() && !entry.IsDeprecated())
+            {
+                onLinkStaleTime = OT_MAX(onLinkStaleTime, entryStaleTime);
+                foundOnLink     = true;
+            }
+
+            if (!entry.IsOnLinkPrefix())
+            {
+                routeStaleTime = OT_MIN(routeStaleTime, entryStaleTime);
+            }
+        }
+    }
+
+    return foundOnLink ? OT_MIN(onLinkStaleTime, routeStaleTime) : routeStaleTime;
+}
+
+void RoutingManager::DiscoveredPrefixTable::RemoveRoutersWithNoEntries(void)
+{
+    mRouters.RemoveAllMatching(Router::kContainsNoEntries);
+}
+
+void RoutingManager::DiscoveredPrefixTable::FreeEntries(LinkedList<Entry> &aEntries)
+{
+    // Frees all entries in the given list `aEntries` (put them back
+    // in the entry pool).
+
+    Entry *entry;
+
+    while ((entry = aEntries.Pop()) != nullptr)
+    {
+        FreeEntry(*entry);
+    }
+}
+
+RoutingManager::DiscoveredPrefixTable::Entry *RoutingManager::DiscoveredPrefixTable::FindFavoredEntryToPublish(
+    const Ip6::Prefix &aPrefix)
+{
+    // Finds the favored entry matching a given `aPrefix` in the table
+    // to publish in the Network Data. We can have multiple entries
+    // in the table matching the same `aPrefix` from different
+    // routers and potentially with different preference values. We
+    // select the one with the highest preference as the favored
+    // entry to publish.
+
+    Entry *favoredEntry = nullptr;
+
+    for (Router &router : mRouters)
+    {
+        for (Entry &entry : router.mEntries)
+        {
+            if (entry.GetPrefix() != aPrefix)
+            {
+                continue;
+            }
+
+            if ((favoredEntry == nullptr) || (entry.GetPreference() > favoredEntry->GetPreference()))
+            {
+                favoredEntry = &entry;
+            }
+        }
+    }
+
+    return favoredEntry;
+}
+
+void RoutingManager::DiscoveredPrefixTable::UpdateNetworkDataOnChangeTo(Entry &aEntry)
+{
+    // Updates Network Data when there is a change to `aEntry` which
+    // can be a newly added entry or an existing entry that is
+    // modified due to processing of a received RA message.
+
+    Entry *favoredEntry;
+
+    if (aEntry.GetPrefix().GetLength() == 0)
+    {
+        // If the change is to default route ::/0 prefix, make sure we
+        // are allowed to publish default route in Network Data.
+
+        VerifyOrExit(mAllowDefaultRouteInNetData);
+    }
+
+    favoredEntry = FindFavoredEntryToPublish(aEntry.GetPrefix());
+
+    OT_ASSERT(favoredEntry != nullptr);
+    PublishEntry(*favoredEntry);
+
+exit:
+    return;
+}
+
+void RoutingManager::DiscoveredPrefixTable::PublishEntry(const Entry &aEntry)
+{
+    IgnoreError(Get<RoutingManager>().PublishExternalRoute(aEntry.GetPrefix(), aEntry.GetPreference()));
+}
+
+void RoutingManager::DiscoveredPrefixTable::UnpublishEntry(const Entry &aEntry)
+{
+    Get<RoutingManager>().UnpublishExternalRoute(aEntry.GetPrefix());
+}
+
+void RoutingManager::DiscoveredPrefixTable::HandleTimer(Timer &aTimer)
+{
+    aTimer.Get<RoutingManager>().mDiscoveredPrefixTable.HandleTimer();
+}
+
+void RoutingManager::DiscoveredPrefixTable::HandleTimer(void)
+{
+    RemoveExpiredEntries();
+}
+
+void RoutingManager::DiscoveredPrefixTable::RemoveExpiredEntries(void)
+{
+    TimeMilli         now            = TimerMilli::GetNow();
+    TimeMilli         nextExpireTime = now.GetDistantFuture();
+    LinkedList<Entry> expiredEntries;
+
+    for (Router &router : mRouters)
+    {
+        router.mEntries.RemoveAllMatching(Entry::ExpirationChecker(now), expiredEntries);
+    }
+
+    RemoveRoutersWithNoEntries();
+
+    // Determine if we need to publish/unpublish any prefixes in
+    // the Network Data.
+
+    for (const Entry &expiredEntry : expiredEntries)
+    {
+        Entry *favoredEntry = FindFavoredEntryToPublish(expiredEntry.GetPrefix());
+
+        if (favoredEntry == nullptr)
+        {
+            UnpublishEntry(expiredEntry);
+        }
+        else
+        {
+            PublishEntry(*favoredEntry);
+        }
+    }
+
+    if (!expiredEntries.IsEmpty())
+    {
+        SignalTableChanged();
+    }
+
+    FreeEntries(expiredEntries);
+
+    // Determine the next expire time and schedule timer.
+
+    for (const Router &router : mRouters)
+    {
+        for (const Entry &entry : router.mEntries)
+        {
+            nextExpireTime = OT_MIN(nextExpireTime, entry.GetExpireTime());
+        }
+    }
+
+    if (nextExpireTime != now.GetDistantFuture())
+    {
+        mTimer.FireAt(nextExpireTime);
+    }
+}
+
+void RoutingManager::DiscoveredPrefixTable::SignalTableChanged(void)
+{
+    mSignalTask.Post();
+}
+
+void RoutingManager::DiscoveredPrefixTable::HandleSignalTask(Tasklet &aTasklet)
+{
+    aTasklet.Get<RoutingManager>().HandleDiscoveredPrefixTableChanged();
+}
+
+void RoutingManager::DiscoveredPrefixTable::InitIterator(PrefixTableIterator &aIterator) const
+{
+    Iterator &iterator = static_cast<Iterator &>(aIterator);
+
+    iterator.SetInitTime();
+    iterator.SetRouter(mRouters.Front());
+    iterator.SetEntry(mRouters.IsEmpty() ? nullptr : mRouters[0].mEntries.GetHead());
+}
+
+Error RoutingManager::DiscoveredPrefixTable::GetNextEntry(PrefixTableIterator &aIterator,
+                                                          PrefixTableEntry &   aEntry) const
+{
+    Error     error    = kErrorNone;
+    Iterator &iterator = static_cast<Iterator &>(aIterator);
+
+    VerifyOrExit(iterator.GetRouter() != nullptr, error = kErrorNotFound);
+    OT_ASSERT(iterator.GetEntry() != nullptr);
+
+    aEntry.mRouterAddress       = iterator.GetRouter()->mAddress;
+    aEntry.mPrefix              = iterator.GetEntry()->GetPrefix();
+    aEntry.mIsOnLink            = iterator.GetEntry()->IsOnLinkPrefix();
+    aEntry.mMsecSinceLastUpdate = iterator.GetInitTime() - iterator.GetEntry()->GetLastUpdateTime();
+    aEntry.mValidLifetime       = iterator.GetEntry()->GetValidLifetime();
+    aEntry.mPreferredLifetime   = aEntry.mIsOnLink ? iterator.GetEntry()->GetPreferredLifetime() : 0;
+    aEntry.mRoutePreference =
+        static_cast<otRoutePreference>(aEntry.mIsOnLink ? 0 : iterator.GetEntry()->GetRoutePreference());
+
+    // Advance the iterator
+    iterator.SetEntry(iterator.GetEntry()->GetNext());
+
+    if (iterator.GetEntry() == nullptr)
+    {
+        if (iterator.GetRouter() != mRouters.Back())
+        {
+            iterator.SetRouter(iterator.GetRouter() + 1);
+            iterator.SetEntry(iterator.GetRouter()->mEntries.GetHead());
+        }
+        else
+        {
+            iterator.SetRouter(nullptr);
+        }
+    }
+
+exit:
+    return error;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+// DiscoveredPrefixTable::Entry
+
+void RoutingManager::DiscoveredPrefixTable::Entry::SetFrom(const Ip6::Nd::RouterAdvertMessage::Header &aRaHeader)
+{
+    mPrefix.Clear();
+    mType                    = kTypeRoute;
+    mValidLifetime           = aRaHeader.GetRouterLifetime();
+    mShared.mRoutePreference = aRaHeader.GetDefaultRouterPreference();
+    mLastUpdateTime          = TimerMilli::GetNow();
+}
+
+void RoutingManager::DiscoveredPrefixTable::Entry::SetFrom(const Ip6::Nd::PrefixInfoOption &aPio)
+{
+    aPio.GetPrefix(mPrefix);
+    mType                      = kTypeOnLink;
+    mValidLifetime             = aPio.GetValidLifetime();
+    mShared.mPreferredLifetime = aPio.GetPreferredLifetime();
+    mLastUpdateTime            = TimerMilli::GetNow();
+}
+
+void RoutingManager::DiscoveredPrefixTable::Entry::SetFrom(const Ip6::Nd::RouteInfoOption &aRio)
+{
+    aRio.GetPrefix(mPrefix);
+    mType                    = kTypeRoute;
+    mValidLifetime           = aRio.GetRouteLifetime();
+    mShared.mRoutePreference = aRio.GetPreference();
+    mLastUpdateTime          = TimerMilli::GetNow();
+}
+
+bool RoutingManager::DiscoveredPrefixTable::Entry::operator==(const Entry &aOther) const
+{
+    return (mType == aOther.mType) && (mPrefix == aOther.mPrefix);
+}
+
+bool RoutingManager::DiscoveredPrefixTable::Entry::Matches(const Matcher &aMatcher) const
+{
+    return (mType == aMatcher.mType) && (mPrefix == aMatcher.mPrefix);
+}
+
+bool RoutingManager::DiscoveredPrefixTable::Entry::Matches(const ExpirationChecker &aCheker) const
+{
+    return GetExpireTime() <= aCheker.mNow;
+}
+
+TimeMilli RoutingManager::DiscoveredPrefixTable::Entry::GetExpireTime(void) const
+{
+    return mLastUpdateTime + CalculateExpireDelay(mValidLifetime);
+}
+
+TimeMilli RoutingManager::DiscoveredPrefixTable::Entry::GetStaleTime(void) const
+{
+    uint32_t delay = OT_MIN(kRtrAdvStaleTime, IsOnLinkPrefix() ? GetPreferredLifetime() : mValidLifetime);
+
+    return mLastUpdateTime + TimeMilli::SecToMsec(delay);
+}
+
+bool RoutingManager::DiscoveredPrefixTable::Entry::IsDeprecated(void) const
+{
+    OT_ASSERT(IsOnLinkPrefix());
+
+    return mLastUpdateTime + TimeMilli::SecToMsec(GetPreferredLifetime()) <= TimerMilli::GetNow();
+}
+
+RoutingManager::RoutePreference RoutingManager::DiscoveredPrefixTable::Entry::GetPreference(void) const
+{
+    // Returns the preference level to use when we publish
+    // the prefix entry in Network Data.
+
+    return IsOnLinkPrefix() ? NetworkData::kRoutePreferenceMedium : GetRoutePreference();
+}
+
+void RoutingManager::DiscoveredPrefixTable::Entry::AdoptValidAndPreferredLiftimesFrom(const Entry &aEntry)
+{
+    constexpr uint32_t kTwoHoursInSeconds = 2 * 3600;
+
+    // Per RFC 4862 section 5.5.3.e:
+    //
+    // 1.  If the received Valid Lifetime is greater than 2 hours or
+    //     greater than RemainingLifetime, set the valid lifetime of the
+    //     corresponding address to the advertised Valid Lifetime.
+    // 2.  If RemainingLifetime is less than or equal to 2 hours, ignore
+    //     the Prefix Information option with regards to the valid
+    //     lifetime, unless ...
+    // 3.  Otherwise, reset the valid lifetime of the corresponding
+    //     address to 2 hours.
+
+    if (aEntry.mValidLifetime > kTwoHoursInSeconds || aEntry.GetExpireTime() > GetExpireTime())
+    {
+        mValidLifetime = aEntry.mValidLifetime;
+    }
+    else if (GetExpireTime() > TimerMilli::GetNow() + TimeMilli::SecToMsec(kTwoHoursInSeconds))
+    {
+        mValidLifetime = kTwoHoursInSeconds;
+    }
+
+    mShared.mPreferredLifetime = aEntry.GetPreferredLifetime();
+    mLastUpdateTime            = aEntry.GetLastUpdateTime();
+}
+
+uint32_t RoutingManager::DiscoveredPrefixTable::Entry::CalculateExpireDelay(uint32_t aValidLifetime)
 {
     uint32_t delay;
 
@@ -976,349 +2017,148 @@
     return delay;
 }
 
-void RoutingManager::HandleRouterAdvertisement(const Ip6::Address &aSrcAddress,
-                                               const uint8_t *     aBuffer,
-                                               uint16_t            aBufferLength)
+//---------------------------------------------------------------------------------------------------------------------
+// OmrPrefix
+
+void RoutingManager::OmrPrefix::SetFrom(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig)
 {
-    OT_ASSERT(mIsRunning);
-    OT_UNUSED_VARIABLE(aSrcAddress);
+    mPrefix     = aOnMeshPrefixConfig.GetPrefix();
+    mPreference = aOnMeshPrefixConfig.GetPreference();
+}
 
-    using RouterAdv::Option;
-    using RouterAdv::PrefixInfoOption;
-    using RouterAdv::RouteInfoOption;
-    using RouterAdv::RouterAdvMessage;
+void RoutingManager::OmrPrefix::SetFrom(const LocalOmrPrefix &aLocalOmrPrefix)
+{
+    mPrefix     = aLocalOmrPrefix.GetPrefix();
+    mPreference = aLocalOmrPrefix.GetPreference();
+}
 
-    bool                    needReevaluate = false;
-    const uint8_t *         optionsBegin;
-    uint16_t                optionsLength;
-    const Option *          option;
-    const RouterAdvMessage *routerAdvMessage;
+bool RoutingManager::OmrPrefix::IsFavoredOver(const NetworkData::OnMeshPrefixConfig &aOmrPrefixConfig) const
+{
+    // This method determines whether this OMR prefix is favored
+    // over another prefix. A prefix with higher preference is
+    // favored. If the preference is the same, then the smaller
+    // prefix (in the sense defined by `Ip6::Prefix`) is favored.
 
-    VerifyOrExit(aBufferLength >= sizeof(RouterAdvMessage));
+    bool isFavored = (mPreference > aOmrPrefixConfig.GetPreference());
 
-    otLogInfoBr("Received Router Advertisement from %s on interface %u", aSrcAddress.ToString().AsCString(),
-                mInfraIfIndex);
-    otDumpDebgBr("[BR-CERT] direction=recv | type=RA |", aBuffer, aBufferLength);
+    OT_ASSERT(IsValidOmrPrefix(aOmrPrefixConfig));
 
-    routerAdvMessage = reinterpret_cast<const RouterAdvMessage *>(aBuffer);
-    optionsBegin     = aBuffer + sizeof(RouterAdvMessage);
-    optionsLength    = aBufferLength - sizeof(RouterAdvMessage);
-
-    option = nullptr;
-    while ((option = Option::GetNextOption(option, optionsBegin, optionsLength)) != nullptr)
+    if (mPreference == aOmrPrefixConfig.GetPreference())
     {
-        switch (option->GetType())
-        {
-        case Option::Type::kPrefixInfo:
-        {
-            const PrefixInfoOption *pio = static_cast<const PrefixInfoOption *>(option);
-
-            if (pio->IsValid())
-            {
-                needReevaluate |= UpdateDiscoveredPrefixes(*pio, routerAdvMessage->GetManagedAddrConfig());
-            }
-        }
-        break;
-
-        case Option::Type::kRouteInfo:
-        {
-            const RouteInfoOption *rio = static_cast<const RouteInfoOption *>(option);
-
-            if (rio->IsValid())
-            {
-                needReevaluate |= UpdateDiscoveredPrefixes(*rio);
-            }
-        }
-        break;
-
-        default:
-            break;
-        }
+        isFavored = (mPrefix < aOmrPrefixConfig.GetPrefix());
     }
 
-    // Remember the header and parameters of RA messages which are
-    // initiated from the infra interface.
-    if (otPlatInfraIfHasAddress(mInfraIfIndex, &aSrcAddress))
+    return isFavored;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+// LocalOmrPrefix
+
+RoutingManager::LocalOmrPrefix::LocalOmrPrefix(Instance &aInstance)
+    : InstanceLocator(aInstance)
+    , mIsAddedInNetData(false)
+{
+}
+
+void RoutingManager::LocalOmrPrefix::GenerateFrom(const Ip6::Prefix &aBrUlaPrefix)
+{
+    mPrefix = aBrUlaPrefix;
+    mPrefix.SetSubnetId(kOmrPrefixSubnetId);
+    mPrefix.SetLength(kOmrPrefixLength);
+
+    LogInfo("Generated OMR prefix: %s", mPrefix.ToString().AsCString());
+}
+
+Error RoutingManager::LocalOmrPrefix::AddToNetData(void)
+{
+    Error                           error = kErrorNone;
+    NetworkData::OnMeshPrefixConfig config;
+
+    VerifyOrExit(!mIsAddedInNetData);
+
+    config.Clear();
+    config.mPrefix       = mPrefix;
+    config.mStable       = true;
+    config.mSlaac        = true;
+    config.mPreferred    = true;
+    config.mOnMesh       = true;
+    config.mDefaultRoute = false;
+    config.mPreference   = GetPreference();
+
+    error = Get<NetworkData::Local>().AddOnMeshPrefix(config);
+
+    if (error != kErrorNone)
     {
-        needReevaluate |= UpdateRouterAdvMessage(routerAdvMessage);
+        LogWarn("Failed to add local OMR prefix %s in Thread Network Data: %s", mPrefix.ToString().AsCString(),
+                ErrorToString(error));
+        ExitNow();
     }
 
-    if (needReevaluate)
+    mIsAddedInNetData = true;
+    Get<NetworkData::Notifier>().HandleServerDataUpdated();
+    LogInfo("Added local OMR prefix %s in Thread Network Data", mPrefix.ToString().AsCString());
+
+exit:
+    return error;
+}
+
+void RoutingManager::LocalOmrPrefix::RemoveFromNetData(void)
+{
+    Error error = kErrorNone;
+
+    VerifyOrExit(mIsAddedInNetData);
+
+    error = Get<NetworkData::Local>().RemoveOnMeshPrefix(mPrefix);
+
+    if (error != kErrorNone)
     {
-        StartRoutingPolicyEvaluationDelay();
+        LogWarn("Failed to remove local OMR prefix %s from Thread Network Data: %s", mPrefix.ToString().AsCString(),
+                ErrorToString(error));
+        ExitNow();
+    }
+
+    mIsAddedInNetData = false;
+    Get<NetworkData::Notifier>().HandleServerDataUpdated();
+    LogInfo("Removed local OMR prefix %s from Thread Network Data", mPrefix.ToString().AsCString());
+
+exit:
+    return;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+// OnMeshPrefixArray
+
+void RoutingManager::OnMeshPrefixArray::Add(const OnMeshPrefix &aPrefix)
+{
+    // Checks if `aPrefix` is already present in the array and if not
+    // adds it as new entry.
+
+    Error error;
+
+    VerifyOrExit(!Contains(aPrefix));
+
+    error = PushBack(aPrefix);
+
+    if (error != kErrorNone)
+    {
+        LogWarn("Too many on-mesh prefixes in net data, ignoring prefix %s", aPrefix.ToString().AsCString());
     }
 
 exit:
     return;
 }
 
-bool RoutingManager::UpdateDiscoveredPrefixes(const RouterAdv::PrefixInfoOption &aPio, bool aManagedAddrConfig)
+void RoutingManager::OnMeshPrefixArray::MarkAsDeleted(const OnMeshPrefix &aPrefix)
 {
-    Ip6::Prefix     prefix         = aPio.GetPrefix();
-    bool            needReevaluate = false;
-    TimeMilli       staleTime;
-    ExternalPrefix  onLinkPrefix;
-    ExternalPrefix *existingPrefix = nullptr;
+    // Searches for a matching entry to `aPrefix` and if found marks
+    // it as deleted by setting prefix length to zero.
 
-    if (!IsValidOnLinkPrefix(aPio, aManagedAddrConfig))
+    OnMeshPrefix *entry = Find(aPrefix);
+
+    if (entry != nullptr)
     {
-        otLogInfoBr("Ignore invalid on-link prefix in PIO: %s", prefix.ToString().AsCString());
-        ExitNow();
+        entry->SetLength(0);
     }
-
-    VerifyOrExit(!mIsAdvertisingLocalOnLinkPrefix || prefix != mLocalOnLinkPrefix);
-
-    otLogInfoBr("Discovered on-link prefix (%s, %u seconds) from interface %u", prefix.ToString().AsCString(),
-                aPio.GetValidLifetime(), mInfraIfIndex);
-
-    onLinkPrefix.mIsOnLinkPrefix    = true;
-    onLinkPrefix.mPrefix            = prefix;
-    onLinkPrefix.mValidLifetime     = aPio.GetValidLifetime();
-    onLinkPrefix.mPreferredLifetime = aPio.GetPreferredLifetime();
-    onLinkPrefix.mTimeLastUpdate    = TimerMilli::GetNow();
-
-    staleTime = TimerMilli::GetNow();
-
-    for (ExternalPrefix &externalPrefix : mDiscoveredPrefixes)
-    {
-        if (externalPrefix == onLinkPrefix)
-        {
-            existingPrefix = &externalPrefix;
-        }
-
-        staleTime = OT_MAX(staleTime, externalPrefix.GetStaleTime());
-    }
-
-    if (existingPrefix == nullptr)
-    {
-        if (onLinkPrefix.mValidLifetime == 0)
-        {
-            ExitNow();
-        }
-
-        if (!mDiscoveredPrefixes.IsFull())
-        {
-            SuccessOrExit(AddExternalRoute(prefix, NetworkData::kRoutePreferenceMedium));
-            existingPrefix  = mDiscoveredPrefixes.PushBack();
-            *existingPrefix = onLinkPrefix;
-            needReevaluate  = true;
-        }
-        else
-        {
-            otLogWarnBr("Discovered too many prefixes, ignore new on-link prefix %s", prefix.ToString().AsCString());
-            ExitNow();
-        }
-    }
-    else
-    {
-        constexpr uint32_t kTwoHoursInSeconds = 2 * 3600;
-
-        // Per RFC 4862 section 5.5.3.e:
-        // 1.  If the received Valid Lifetime is greater than 2 hours or
-        //     greater than RemainingLifetime, set the valid lifetime of the
-        //     corresponding address to the advertised Valid Lifetime.
-        // 2.  If RemainingLifetime is less than or equal to 2 hours, ignore
-        //     the Prefix Information option with regards to the valid
-        //     lifetime, unless ...
-        // 3.  Otherwise, reset the valid lifetime of the corresponding
-        //     address to 2 hours.
-
-        if (onLinkPrefix.mValidLifetime > kTwoHoursInSeconds ||
-            onLinkPrefix.GetExpireTime() > existingPrefix->GetExpireTime())
-        {
-            existingPrefix->mValidLifetime = onLinkPrefix.mValidLifetime;
-        }
-        else if (existingPrefix->GetExpireTime() > TimerMilli::GetNow() + TimeMilli::SecToMsec(kTwoHoursInSeconds))
-        {
-            existingPrefix->mValidLifetime = kTwoHoursInSeconds;
-        }
-
-        existingPrefix->mPreferredLifetime = onLinkPrefix.mPreferredLifetime;
-        existingPrefix->mTimeLastUpdate    = onLinkPrefix.mTimeLastUpdate;
-        needReevaluate                     = (existingPrefix->mPreferredLifetime == 0);
-    }
-
-    mDiscoveredPrefixInvalidTimer.FireAtIfEarlier(existingPrefix->GetExpireTime());
-    staleTime = OT_MAX(staleTime, existingPrefix->GetStaleTime());
-    mDiscoveredPrefixStaleTimer.FireAtIfEarlier(staleTime);
-
-exit:
-    return needReevaluate;
-}
-
-bool RoutingManager::UpdateDiscoveredPrefixes(const RouterAdv::RouteInfoOption &aRio)
-{
-    Ip6::Prefix     prefix         = aRio.GetPrefix();
-    bool            needReevaluate = false;
-    ExternalPrefix  omrPrefix;
-    ExternalPrefix *existingPrefix = nullptr;
-
-    if (!IsValidOmrPrefix(prefix))
-    {
-        otLogInfoBr("Ignore invalid OMR prefix in RIO: %s", prefix.ToString().AsCString());
-        ExitNow();
-    }
-
-    // Ignore OMR prefixes advertised by ourselves or in current Thread Network Data.
-    // The `mAdvertisedOmrPrefixes` and the OMR prefix set in Network Data should eventually
-    // be equal, but there is time that they are not synchronized immediately:
-    // 1. Network Data could contain more OMR prefixes than `mAdvertisedOmrPrefixes` because
-    //    we added random delay before Evaluating routing policy when Network Data is changed.
-    // 2. `mAdvertisedOmrPrefixes` could contain more OMR prefixes than Network Data because
-    //    it takes time to sync a new OMR prefix into Network Data (multicast loopback RA
-    //    messages are usually faster than Thread Network Data propagation).
-    // They are the reasons why we need both the checks.
-
-    VerifyOrExit(!mAdvertisedOmrPrefixes.Contains(prefix));
-    VerifyOrExit(!NetworkDataContainsOmrPrefix(prefix));
-
-    otLogInfoBr("Discovered OMR prefix (%s, %u seconds) from interface %u", prefix.ToString().AsCString(),
-                aRio.GetRouteLifetime(), mInfraIfIndex);
-
-    if (aRio.GetRouteLifetime() == 0)
-    {
-        needReevaluate = InvalidateDiscoveredPrefixes(&prefix, /* aIsOnLinkPrefix */ false);
-        ExitNow();
-    }
-
-    omrPrefix.mIsOnLinkPrefix  = false;
-    omrPrefix.mPrefix          = prefix;
-    omrPrefix.mValidLifetime   = aRio.GetRouteLifetime();
-    omrPrefix.mRoutePreference = aRio.GetPreference();
-    omrPrefix.mTimeLastUpdate  = TimerMilli::GetNow();
-
-    for (ExternalPrefix &externalPrefix : mDiscoveredPrefixes)
-    {
-        if (externalPrefix == omrPrefix)
-        {
-            existingPrefix = &externalPrefix;
-        }
-
-        mDiscoveredPrefixStaleTimer.FireAtIfEarlier(externalPrefix.GetStaleTime());
-    }
-
-    if (existingPrefix == nullptr)
-    {
-        if (omrPrefix.mValidLifetime == 0)
-        {
-            ExitNow();
-        }
-
-        if (!mDiscoveredPrefixes.IsFull())
-        {
-            SuccessOrExit(AddExternalRoute(prefix, omrPrefix.mRoutePreference));
-            existingPrefix = mDiscoveredPrefixes.PushBack();
-            needReevaluate = true;
-        }
-        else
-        {
-            otLogWarnBr("Discovered too many prefixes, ignore new prefix %s", prefix.ToString().AsCString());
-            ExitNow();
-        }
-    }
-
-    *existingPrefix = omrPrefix;
-
-    mDiscoveredPrefixInvalidTimer.FireAtIfEarlier(existingPrefix->GetExpireTime());
-    mDiscoveredPrefixStaleTimer.FireAtIfEarlier(existingPrefix->GetStaleTime());
-
-exit:
-    return needReevaluate;
-}
-
-bool RoutingManager::InvalidateDiscoveredPrefixes(const Ip6::Prefix *aPrefix, bool aIsOnLinkPrefix)
-{
-    bool                didRemove                = false;
-    TimeMilli           now                      = TimerMilli::GetNow();
-    uint8_t             remainingOnLinkPrefixNum = 0;
-    ExternalPrefixArray remainingPrefixes;
-
-    mDiscoveredPrefixInvalidTimer.Stop();
-
-    for (const ExternalPrefix &prefix : mDiscoveredPrefixes)
-    {
-        if ((aPrefix != nullptr && prefix.mPrefix == *aPrefix && prefix.mIsOnLinkPrefix == aIsOnLinkPrefix) ||
-            (prefix.GetExpireTime() <= now))
-        {
-            RemoveExternalRoute(prefix.mPrefix);
-            didRemove = true;
-        }
-        else
-        {
-            mDiscoveredPrefixInvalidTimer.FireAtIfEarlier(prefix.GetExpireTime());
-
-            IgnoreError(remainingPrefixes.PushBack(prefix));
-
-            if (prefix.mIsOnLinkPrefix)
-            {
-                ++remainingOnLinkPrefixNum;
-            }
-        }
-    }
-
-    mDiscoveredPrefixes = remainingPrefixes;
-
-    if (remainingOnLinkPrefixNum == 0 && !mIsAdvertisingLocalOnLinkPrefix)
-    {
-        // There are no valid on-link prefixes on infra link now, start Router Solicitation
-        // To discover more on-link prefixes or timeout to advertise my local on-link prefix.
-        StartRouterSolicitationDelay();
-    }
-
-    return didRemove; // If anything was removed we need to reevaluate.
-}
-
-void RoutingManager::InvalidateAllDiscoveredPrefixes(void)
-{
-    for (ExternalPrefix &prefix : mDiscoveredPrefixes)
-    {
-        prefix.mValidLifetime = 0;
-    }
-
-    InvalidateDiscoveredPrefixes();
-
-    OT_ASSERT(mDiscoveredPrefixes.IsEmpty());
-}
-
-bool RoutingManager::NetworkDataContainsOmrPrefix(const Ip6::Prefix &aPrefix) const
-{
-    NetworkData::Iterator           iterator = NetworkData::kIteratorInit;
-    NetworkData::OnMeshPrefixConfig onMeshPrefixConfig;
-    bool                            contain = false;
-
-    while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, onMeshPrefixConfig) == OT_ERROR_NONE)
-    {
-        if (IsValidOmrPrefix(onMeshPrefixConfig) && onMeshPrefixConfig.GetPrefix() == aPrefix)
-        {
-            contain = true;
-            break;
-        }
-    }
-
-    return contain;
-}
-
-// Update the `mRouterAdvMessage` with given Router Advertisement message.
-// Returns a boolean which indicates whether there are changes of `mRouterAdvMessage`.
-bool RoutingManager::UpdateRouterAdvMessage(const RouterAdv::RouterAdvMessage *aRouterAdvMessage)
-{
-    RouterAdv::RouterAdvMessage oldRouterAdvMessage;
-
-    oldRouterAdvMessage = mRouterAdvMessage;
-
-    mTimeRouterAdvMessageLastUpdate = TimerMilli::GetNow();
-    if (aRouterAdvMessage == nullptr || aRouterAdvMessage->GetRouterLifetime() == 0)
-    {
-        mRouterAdvMessage.SetToDefault();
-    }
-    else
-    {
-        mRouterAdvMessage = *aRouterAdvMessage;
-        mDiscoveredPrefixStaleTimer.FireAtIfEarlier(mTimeRouterAdvMessageLastUpdate +
-                                                    Time::SecToMsec(kRtrAdvStaleTime));
-    }
-
-    return (mRouterAdvMessage != oldRouterAdvMessage);
 }
 
 } // namespace BorderRouter
diff --git a/src/core/border_router/routing_manager.hpp b/src/core/border_router/routing_manager.hpp
index 4d26d26..fcc07c4 100644
--- a/src/core/border_router/routing_manager.hpp
+++ b/src/core/border_router/routing_manager.hpp
@@ -48,15 +48,18 @@
 #endif
 
 #include <openthread/netdata.h>
-#include <openthread/platform/infra_if.h>
 
-#include "border_router/router_advertisement.hpp"
+#include "border_router/infra_if.hpp"
 #include "common/array.hpp"
 #include "common/error.hpp"
+#include "common/linked_list.hpp"
 #include "common/locator.hpp"
 #include "common/notifier.hpp"
+#include "common/pool.hpp"
+#include "common/string.hpp"
 #include "common/timer.hpp"
 #include "net/ip6.hpp"
+#include "net/nd6.hpp"
 #include "thread/network_data.hpp"
 
 namespace ot {
@@ -73,8 +76,13 @@
 class RoutingManager : public InstanceLocator
 {
     friend class ot::Notifier;
+    friend class ot::Instance;
 
 public:
+    typedef NetworkData::RoutePreference       RoutePreference;     ///< Route preference (high, medium, low).
+    typedef otBorderRoutingPrefixTableIterator PrefixTableIterator; ///< Prefix Table Iterator.
+    typedef otBorderRoutingPrefixTableEntry    PrefixTableEntry;    ///< Prefix Table Entry.
+
     /**
      * This constructor initializes the routing manager.
      *
@@ -110,10 +118,33 @@
     Error SetEnabled(bool aEnabled);
 
     /**
-     * This method returns the off-mesh-routable (OMR) prefix.
+     * This method gets the preference used when advertising Route Info Options (e.g., for discovered OMR prefixes) in
+     * Router Advertisement messages sent over the infrastructure link.
      *
-     * The randomly generated 64-bit prefix will be published
-     * in the Thread network if there isn't already an OMR prefix.
+     * @returns The Route Info Option preference.
+     *
+     */
+    RoutePreference GetRouteInfoOptionPreference(void) const { return mRouteInfoOptionPreference; }
+
+    /**
+     * This method sets the preference to use when advertising Route Info Options (e.g., for discovered OMR prefixes)
+     * in Router Advertisement messages sent over the infrastructure link.
+     *
+     * By default BR will use 'medium' preference level but this method allows the default value to be changed. As an
+     * example, it can be set to 'low' preference in the case where device is a temporary BR (a mobile BR or a
+     * battery-powered BR) to indicate that other BRs (if any) should be preferred over this BR on the infrastructure
+     * link.
+     *
+     * @param[in] aPreference   The route preference to use.
+     *
+     */
+    void SetRouteInfoOptionPreference(RoutePreference aPreference);
+
+    /**
+     * This method returns the local off-mesh-routable (OMR) prefix.
+     *
+     * The randomly generated 64-bit prefix will be added to the Thread Network Data if there isn't already an OMR
+     * prefix.
      *
      * @param[out]  aPrefix  A reference to where the prefix will be output to.
      *
@@ -124,6 +155,23 @@
     Error GetOmrPrefix(Ip6::Prefix &aPrefix);
 
     /**
+     * This method returns the currently favored off-mesh-routable (OMR) prefix.
+     *
+     * The favored OMR prefix can be discovered from Network Data or can be our local OMR prefix.
+     *
+     * An OMR prefix with higher preference is favored. If the preference is the same, then the smaller prefix (in the
+     * sense defined by `Ip6::Prefix`) is favored.
+     *
+     * @param[out] aPrefix         A reference to output the favored prefix.
+     * @param[out] aPreference     A reference to output the preference associated with the favored OMR prefix.
+     *
+     * @retval  kErrorInvalidState  The Border Routing Manager is not initialized yet.
+     * @retval  kErrorNone          Successfully retrieved the OMR prefix.
+     *
+     */
+    Error GetFavoredOmrPrefix(Ip6::Prefix &aPrefix, RoutePreference &aPreference);
+
+    /**
      * This method returns the on-link prefix for the adjacent  infrastructure link.
      *
      * The randomly generated 64-bit prefix will be advertised
@@ -138,50 +186,99 @@
      */
     Error GetOnLinkPrefix(Ip6::Prefix &aPrefix);
 
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
     /**
-     * This method receives an ICMPv6 message on the infrastructure interface.
+     * This method returns the local NAT64 prefix.
+     *
+     * The local NAT64 prefix will be published in the Thread network
+     * if none exists.
+     *
+     * @param[out]  aPrefix  A reference to where the prefix will be output to.
+     *
+     * @retval  kErrorInvalidState  The Border Routing Manager is not initialized yet.
+     * @retval  kErrorNone          Successfully retrieved the NAT64 prefix.
+     *
+     */
+    Error GetNat64Prefix(Ip6::Prefix &aPrefix);
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
+
+    /**
+     * This method processes a received ICMPv6 message from the infrastructure interface.
      *
      * Malformed or undesired messages are dropped silently.
      *
-     * @param[in]  aInfraIfIndex  The infrastructure interface index.
+     * @param[in]  aPacket        The received ICMPv6 packet.
      * @param[in]  aSrcAddress    The source address this message is sent from.
-     * @param[in]  aBuffer        THe ICMPv6 message buffer.
-     * @param[in]  aLength        The length of the ICMPv6 message buffer.
      *
      */
-    void RecvIcmp6Message(uint32_t            aInfraIfIndex,
-                          const Ip6::Address &aSrcAddress,
-                          const uint8_t *     aBuffer,
-                          uint16_t            aBufferLength);
+    void HandleReceived(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress);
 
     /**
      * This method handles infrastructure interface state changes.
      *
-     * @param[in]  aInfraIfIndex  The index of the infrastructure interface.
-     * @param[in]  aIsRunning     A boolean that indicates whether the infrastructure
-     *                            interface is running.
+     */
+    void HandleInfraIfStateChanged(void) { EvaluateState(); }
+
+    /**
+     * This method checks if the on-mesh prefix configuration is a valid OMR prefix.
      *
-     * @retval  kErrorNone          Successfully updated the infra interface status.
-     * @retval  kErrorInvalidState  The Routing Manager is not initialized.
-     * @retval  kErrorInvalidArgs   The @p aInfraIfIndex doesn't match the infra interface
-     *                              the Routing Manager is initialized with.
+     * @param[in] aOnMeshPrefixConfig  The on-mesh prefix configuration to check.
+     *
+     * @returns  Whether the on-mesh prefix configuration is a valid OMR prefix.
      *
      */
-    Error HandleInfraIfStateChanged(uint32_t aInfraIfIndex, bool aIsRunning);
+    static bool IsValidOmrPrefix(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig);
+
+    /**
+     * This method checks if the OMR prefix is valid (i.e. GUA/ULA prefix with length being 64).
+     *
+     * @param[in]  aOmrPrefix  The OMR prefix to check.
+     * @returns    Whether the OMR prefix is valid.
+     *
+     */
+    static bool IsValidOmrPrefix(const Ip6::Prefix &aOmrPrefix);
+
+    /**
+     * This method initializes a `PrefixTableIterator`.
+     *
+     * An iterator can be initialized again to start from the beginning of the table.
+     *
+     * When iterating over entries in the table, to ensure the entry update times are consistent, they are given
+     * relative to the time the iterator was initialized.
+     *
+     * @param[out] aIterator  The iterator to initialize.
+     *
+     */
+    void InitPrefixTableIterator(PrefixTableIterator &aIterator) const
+    {
+        mDiscoveredPrefixTable.InitIterator(aIterator);
+    }
+
+    /**
+     * This method iterates over entries in the discovered prefix table.
+     *
+     * @param[in,out] aIterator  An iterator.
+     * @param[out]    aEntry     A reference to the entry to populate.
+     *
+     * @retval kErrorNone        Got the next entry, @p aEntry is updated and @p aIterator is advanced.
+     * @retval kErrorNotFound    No more entries in the table.
+     *
+     */
+    Error GetNextPrefixTableEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const
+    {
+        return mDiscoveredPrefixTable.GetNextEntry(aIterator, aEntry);
+    }
 
 private:
-    typedef NetworkData::RoutePreference RoutePreference;
-
-    static constexpr uint16_t kMaxRouterAdvMessageLength = 256; // The maximum RA message length we can handle.
-
-    // The maximum number of the OMR prefixes to advertise.
-    static constexpr uint8_t kMaxOmrPrefixNum = OPENTHREAD_CONFIG_IP6_SLAAC_NUM_ADDRESSES;
-
-    // The maximum number of prefixes to discover on the infra link.
-    static constexpr uint8_t kMaxDiscoveredPrefixNum = 8;
+    static constexpr uint8_t kMaxOnMeshPrefixes = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_ON_MESH_PREFIXES;
 
     static constexpr uint8_t kOmrPrefixLength    = OT_IP6_PREFIX_BITSIZE; // The length of an OMR prefix. In bits.
     static constexpr uint8_t kOnLinkPrefixLength = OT_IP6_PREFIX_BITSIZE; // The length of an On-link prefix. In bits.
+    static constexpr uint8_t kBrUlaPrefixLength  = 48;                    // The length of a BR ULA prefix. In bits.
+    static constexpr uint8_t kNat64PrefixLength  = 96;                    // The length of a NAT64 prefix. In bits.
+
+    static constexpr uint16_t kOmrPrefixSubnetId   = 1; // The subnet ID of an OMR prefix within a BR ULA prefix.
+    static constexpr uint16_t kNat64PrefixSubnetId = 2; // The subnet ID of a NAT64 prefix within a BR ULA prefix.
 
     // The maximum number of initial Router Advertisements.
     static constexpr uint32_t kMaxInitRtrAdvertisements = 3;
@@ -194,11 +291,13 @@
     static constexpr uint32_t kMaxRtrAdvInterval           = 600;  // Max Router Advertisement Interval. In sec.
     static constexpr uint32_t kMinRtrAdvInterval           = kMaxRtrAdvInterval / 3; // Min RA Interval. In sec.
     static constexpr uint32_t kMaxInitRtrAdvInterval       = 16;                     // Max Initial RA Interval. In sec.
-    static constexpr uint32_t kMaxRaDelayTime              = 500; // Max delay of sending RA after rx RS. In msec.
-    static constexpr uint32_t kRtrSolicitationInterval     = 4;   // Interval between RSs. In sec.
-    static constexpr uint32_t kMaxRtrSolicitationDelay     = 1;   // Max delay for initial solicitation. In sec.
-    static constexpr uint32_t kMaxRoutingPolicyDelay       = 1;   // Max delay for routing policy evaluation. In sec.
-    static constexpr uint32_t kRtrSolicitationRetryDelay   = 60;  // The delay before retrying failed RS tx. In Sec.
+    static constexpr uint32_t kRaReplyJitter               = 500;    // Jitter for sending RA after rx RS. In msec.
+    static constexpr uint32_t kRtrSolicitationInterval     = 4;      // Interval between RSs. In sec.
+    static constexpr uint32_t kMaxRtrSolicitationDelay     = 1;      // Max delay for initial solicitation. In sec.
+    static constexpr uint32_t kRoutingPolicyEvaluationJitter = 1000; // Jitter for routing policy evaluation. In msec.
+    static constexpr uint32_t kRtrSolicitationRetryDelay =
+        kRtrSolicitationInterval;                             // The delay before retrying failed RS tx. In Sec.
+    static constexpr uint32_t kMinDelayBetweenRtrAdvs = 3000; // Min delay (msec) between consecutive RAs.
 
     // The STALE_RA_TIME in seconds. The Routing Manager will consider the prefixes
     // and learned RA parameters STALE when they are not refreshed in STALE_RA_TIME
@@ -208,91 +307,266 @@
     // The value is chosen in range of [`kMaxRtrAdvInterval` upper bound (1800s), `kDefaultOnLinkPrefixLifetime`].
     static constexpr uint32_t kRtrAdvStaleTime = 1800;
 
-    // The VICARIOUS_SOLICIT_TIME in seconds. The Routing Manager will consider
-    // the discovered prefixes invalid if they are not refreshed after receiving
-    // a Router Solicitation message.
-    // The value is equal to Router Solicitation timeout.
-    static constexpr uint32_t kVicariousSolicitationTime =
-        kRtrSolicitationInterval * (kMaxRtrSolicitations - 1) + kMaxRtrSolicitationDelay;
-
     static_assert(kMinRtrAdvInterval <= 3 * kMaxRtrAdvInterval / 4, "invalid RA intervals");
     static_assert(kDefaultOmrPrefixLifetime >= kMaxRtrAdvInterval, "invalid default OMR prefix lifetime");
     static_assert(kDefaultOnLinkPrefixLifetime >= kMaxRtrAdvInterval, "invalid default on-link prefix lifetime");
     static_assert(kRtrAdvStaleTime >= 1800 && kRtrAdvStaleTime <= kDefaultOnLinkPrefixLifetime,
                   "invalid RA STALE time");
 
-    // This struct represents an external prefix which is
-    // discovered on the infrastructure interface.
-    struct ExternalPrefix : public Clearable<ExternalPrefix>, public Unequatable<ExternalPrefix>
+    enum RouterAdvTxMode : uint8_t // Used in `SendRouterAdvertisement()`
     {
-        Ip6::Prefix mPrefix;
-        uint32_t    mValidLifetime;
-
-        union
-        {
-            // Preferred Lifetime of on-link prefix, available
-            // only when `mIsOnLinkPrefix` is TRUE.
-            uint32_t mPreferredLifetime;
-
-            // The preference of this route, available
-            // only when `mIsOnLinkPrefix` is FALSE.
-            RoutePreference mRoutePreference;
-        };
-        TimeMilli mTimeLastUpdate;
-        bool      mIsOnLinkPrefix;
-
-        bool operator==(const ExternalPrefix &aPrefix) const
-        {
-            return mPrefix == aPrefix.mPrefix && mIsOnLinkPrefix == aPrefix.mIsOnLinkPrefix;
-        }
-
-        bool IsDeprecated(void) const
-        {
-            OT_ASSERT(mIsOnLinkPrefix);
-
-            return mTimeLastUpdate + TimeMilli::SecToMsec(mPreferredLifetime) <= TimerMilli::GetNow();
-        }
-
-        TimeMilli GetExpireTime(void) const { return mTimeLastUpdate + GetPrefixExpireDelay(mValidLifetime); }
-        TimeMilli GetStaleTime(void) const
-        {
-            uint32_t delay = OT_MIN(kRtrAdvStaleTime, mIsOnLinkPrefix ? mPreferredLifetime : mValidLifetime);
-
-            return mTimeLastUpdate + TimeMilli::SecToMsec(delay);
-        }
-
-        static uint32_t GetPrefixExpireDelay(uint32_t aValidLifetime);
+        kInvalidateAllPrevPrefixes,
+        kAdvPrefixesFromNetData,
     };
 
-    typedef Array<Ip6::Prefix, kMaxOmrPrefixNum>           OmrPrefixArray;
-    typedef Array<ExternalPrefix, kMaxDiscoveredPrefixNum> ExternalPrefixArray;
+    class DiscoveredPrefixTable : public InstanceLocator
+    {
+        // This class maintains the discovered on-link and route prefixes
+        // from the received RA messages by processing PIO and RIO options
+        // from the message. It takes care of processing the RA message but
+        // delegates the decision whether to include or exclude a prefix to
+        // `RoutingManager` by calling its `ShouldProcessPrefixInfoOption()`
+        // and `ShouldProcessRouteInfoOption()` methods.
+        //
+        // It manages the lifetime of the discovered entries and publishes
+        // and unpublishes the prefixes in the Network Data (as external
+        // route) as they are added or removed.
+        //
+        // When there is any change in the table (an entry is added, removed,
+        // or modified), it signals the change to `RoutingManager` by calling
+        // `HandleDiscoveredPrefixTableChanged()` callback. A `Tasklet` is
+        // used for signalling which ensures that if there are multiple
+        // changes within the same flow of execution, the callback is
+        // invoked after all the changes are processed.
+
+    public:
+        enum NetDataMode : uint8_t // Used in `Remove{}` methods
+        {
+            kUnpublishFromNetData, // Unpublish the entry from Network Data if previously published.
+            kKeepInNetData,        // Keep entry in Network Data if previously published.
+        };
+
+        explicit DiscoveredPrefixTable(Instance &aInstance);
+
+        void ProcessRouterAdvertMessage(const Ip6::Nd::RouterAdvertMessage &aRaMessage,
+                                        const Ip6::Address &                aSrcAddress);
+
+        void SetAllowDefaultRouteInNetData(bool aAllow);
+
+        void FindFavoredOnLinkPrefix(Ip6::Prefix &aPrefix) const;
+        bool ContainsOnLinkPrefix(const Ip6::Prefix &aPrefix) const;
+        void RemoveOnLinkPrefix(const Ip6::Prefix &aPrefix, NetDataMode aNetDataMode);
+
+        bool ContainsRoutePrefix(const Ip6::Prefix &aPrefix) const;
+        void RemoveRoutePrefix(const Ip6::Prefix &aPrefix, NetDataMode aNetDataMode);
+
+        void RemoveAllEntries(void);
+        void RemoveOrDeprecateOldEntries(TimeMilli aTimeThreshold);
+
+        TimeMilli CalculateNextStaleTime(TimeMilli aNow) const;
+
+        void  InitIterator(PrefixTableIterator &aIterator) const;
+        Error GetNextEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const;
+
+    private:
+        static constexpr uint16_t kMaxRouters = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS;
+        static constexpr uint16_t kMaxEntries = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES;
+
+        class Entry : public LinkedListEntry<Entry>, public Unequatable<Entry>, private Clearable<Entry>
+        {
+            friend class LinkedListEntry<Entry>;
+
+        public:
+            enum Type : uint8_t
+            {
+                kTypeOnLink,
+                kTypeRoute,
+            };
+
+            struct Matcher
+            {
+                Matcher(const Ip6::Prefix &aPrefix, Type aType)
+                    : mPrefix(aPrefix)
+                    , mType(aType)
+                {
+                }
+
+                const Ip6::Prefix &mPrefix;
+                bool               mType;
+            };
+
+            struct ExpirationChecker
+            {
+                explicit ExpirationChecker(TimeMilli aNow)
+                    : mNow(aNow)
+                {
+                }
+
+                TimeMilli mNow;
+            };
+
+            void               SetFrom(const Ip6::Nd::RouterAdvertMessage::Header &aRaHeader);
+            void               SetFrom(const Ip6::Nd::PrefixInfoOption &aPio);
+            void               SetFrom(const Ip6::Nd::RouteInfoOption &aRio);
+            Type               GetType(void) const { return mType; }
+            bool               IsOnLinkPrefix(void) const { return (mType == kTypeOnLink); }
+            const Ip6::Prefix &GetPrefix(void) const { return mPrefix; }
+            const TimeMilli &  GetLastUpdateTime(void) const { return mLastUpdateTime; }
+            uint32_t           GetValidLifetime(void) const { return mValidLifetime; }
+            void               ClearValidLifetime(void) { mValidLifetime = 0; }
+            TimeMilli          GetExpireTime(void) const;
+            TimeMilli          GetStaleTime(void) const;
+            RoutePreference    GetPreference(void) const;
+            bool               operator==(const Entry &aOther) const;
+            bool               Matches(const Matcher &aMatcher) const;
+            bool               Matches(const ExpirationChecker &aCheker) const;
+
+            // Methods to use when `IsOnLinkPrefix()`
+            uint32_t GetPreferredLifetime(void) const { return mShared.mPreferredLifetime; }
+            void     ClearPreferredLifetime(void) { mShared.mPreferredLifetime = 0; }
+            bool     IsDeprecated(void) const;
+            void     AdoptValidAndPreferredLiftimesFrom(const Entry &aEntry);
+
+            // Method to use when `!IsOnlinkPrefix()`
+            RoutePreference GetRoutePreference(void) const { return mShared.mRoutePreference; }
+
+        private:
+            static uint32_t CalculateExpireDelay(uint32_t aValidLifetime);
+
+            Entry *     mNext;
+            Ip6::Prefix mPrefix;
+            Type        mType;
+            TimeMilli   mLastUpdateTime;
+            uint32_t    mValidLifetime;
+            union
+            {
+                uint32_t        mPreferredLifetime; // Applicable when prefix is on-link.
+                RoutePreference mRoutePreference;   // Applicable when prefix is not on-link
+            } mShared;
+        };
+
+        struct Router
+        {
+            enum EmptyChecker : uint8_t
+            {
+                kContainsNoEntries
+            };
+
+            bool Matches(const Ip6::Address &aAddress) const { return aAddress == mAddress; }
+            bool Matches(EmptyChecker) const { return mEntries.IsEmpty(); }
+
+            Ip6::Address      mAddress;
+            LinkedList<Entry> mEntries;
+        };
+
+        class Iterator : public PrefixTableIterator
+        {
+        public:
+            const Router *GetRouter(void) const { return static_cast<const Router *>(mPtr1); }
+            void          SetRouter(const Router *aRouter) { mPtr1 = aRouter; }
+            const Entry * GetEntry(void) const { return static_cast<const Entry *>(mPtr2); }
+            void          SetEntry(const Entry *aEntry) { mPtr2 = aEntry; }
+            TimeMilli     GetInitTime(void) const { return TimeMilli(mData32); }
+            void          SetInitTime(void) { mData32 = TimerMilli::GetNow().GetValue(); }
+        };
+
+        void        ProcessDefaultRoute(const Ip6::Nd::RouterAdvertMessage::Header &aRaHeader, Router &aRouter);
+        void        ProcessPrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio, Router &aRouter);
+        void        ProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption &aRio, Router &aRouter);
+        bool        ContainsPrefix(const Entry::Matcher &aMatcher) const;
+        void        RemovePrefix(const Entry::Matcher &aMatcher, NetDataMode aNetDataMode);
+        void        RemoveRoutersWithNoEntries(void);
+        Entry *     AllocateEntry(void) { return mEntryPool.Allocate(); }
+        void        FreeEntry(Entry &aEntry) { mEntryPool.Free(aEntry); }
+        void        FreeEntries(LinkedList<Entry> &aEntries);
+        void        UpdateNetworkDataOnChangeTo(Entry &aEntry);
+        Entry *     FindFavoredEntryToPublish(const Ip6::Prefix &aPrefix);
+        void        PublishEntry(const Entry &aEntry);
+        void        UnpublishEntry(const Entry &aEntry);
+        static void HandleTimer(Timer &aTimer);
+        void        HandleTimer(void);
+        void        RemoveExpiredEntries(void);
+        void        SignalTableChanged(void);
+        static void HandleSignalTask(Tasklet &aTasklet);
+
+        Array<Router, kMaxRouters> mRouters;
+        Pool<Entry, kMaxEntries>   mEntryPool;
+        TimerMilli                 mTimer;
+        Tasklet                    mSignalTask;
+        bool                       mAllowDefaultRouteInNetData;
+    };
+
+    class LocalOmrPrefix;
+
+    class OmrPrefix : public Clearable<OmrPrefix>
+    {
+    public:
+        OmrPrefix(void) { Clear(); }
+
+        bool               IsEmpty(void) const { return (mPrefix.GetLength() == 0); }
+        void               SetFrom(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig);
+        void               SetFrom(const LocalOmrPrefix &aLocalOmrPrefix);
+        const Ip6::Prefix &GetPrefix(void) const { return mPrefix; }
+        RoutePreference    GetPreference(void) const { return mPreference; }
+        bool               IsFavoredOver(const NetworkData::OnMeshPrefixConfig &aOmrPrefixConfig) const;
+
+    private:
+        Ip6::Prefix     mPrefix;
+        RoutePreference mPreference;
+    };
+
+    class LocalOmrPrefix : InstanceLocator
+    {
+    public:
+        explicit LocalOmrPrefix(Instance &aInstance);
+        void               GenerateFrom(const Ip6::Prefix &aBrUlaPrefix);
+        const Ip6::Prefix &GetPrefix(void) const { return mPrefix; }
+        RoutePreference    GetPreference(void) const { return NetworkData::kRoutePreferenceLow; }
+        Error              AddToNetData(void);
+        void               RemoveFromNetData(void);
+        bool               IsAddedInNetData(void) const { return mIsAddedInNetData; }
+
+    private:
+        Ip6::Prefix mPrefix;
+        bool        mIsAddedInNetData;
+    };
+
+    typedef Ip6::Prefix OnMeshPrefix;
+
+    class OnMeshPrefixArray : public Array<OnMeshPrefix, kMaxOnMeshPrefixes>
+    {
+    public:
+        void Add(const OnMeshPrefix &aPrefix);
+        void MarkAsDeleted(const OnMeshPrefix &aPrefix);
+    };
 
     void  EvaluateState(void);
     void  Start(void);
     void  Stop(void);
     void  HandleNotifierEvents(Events aEvents);
-    bool  IsInitialized(void) const { return mInfraIfIndex != 0; }
+    bool  IsInitialized(void) const { return mInfraIf.IsInitialized(); }
     bool  IsEnabled(void) const { return mIsEnabled; }
-    Error LoadOrGenerateRandomOmrPrefix(void);
-    Error LoadOrGenerateRandomOnLinkPrefix(void);
+    Error LoadOrGenerateRandomBrUlaPrefix(void);
+    void  GenerateOnLinkPrefix(void);
 
-    const Ip6::Prefix *EvaluateOnLinkPrefix(void);
+    void EvaluateOnLinkPrefix(void);
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
+    void GenerateNat64Prefix(void);
+    void EvaluateNat64Prefix(void);
+#endif
 
     void  EvaluateRoutingPolicy(void);
-    void  StartRoutingPolicyEvaluationDelay(void);
-    void  EvaluateOmrPrefix(OmrPrefixArray &aNewOmrPrefixes);
-    Error PublishLocalOmrPrefix(void);
-    void  UnpublishLocalOmrPrefix(void);
-    Error AddExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aRoutePreference);
-    void  RemoveExternalRoute(const Ip6::Prefix &aPrefix);
+    void  StartRoutingPolicyEvaluationJitter(uint32_t aJitterMilli);
+    void  StartRoutingPolicyEvaluationDelay(uint32_t aDelayMilli);
+    void  EvaluateOmrPrefix(void);
+    Error PublishExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aRoutePreference, bool aNat64 = false);
+    void  UnpublishExternalRoute(const Ip6::Prefix &aPrefix);
     void  StartRouterSolicitationDelay(void);
     Error SendRouterSolicitation(void);
-    void  SendRouterAdvertisement(const OmrPrefixArray &aNewOmrPrefixes, const Ip6::Prefix *aNewOnLinkPrefix);
+    void  SendRouterAdvertisement(RouterAdvTxMode aRaTxMode);
+    bool  IsRouterSolicitationInProgress(void) const;
 
-    static void HandleRouterAdvertisementTimer(Timer &aTimer);
-    void        HandleRouterAdvertisementTimer(void);
-    static void HandleVicariousRouterSolicitTimer(Timer &aTimer);
-    void        HandleVicariousRouterSolicitTimer(void);
     static void HandleRouterSolicitTimer(Timer &aTimer);
     void        HandleRouterSolicitTimer(void);
     static void HandleDiscoveredPrefixInvalidTimer(Timer &aTimer);
@@ -304,18 +578,19 @@
     static void HandleOnLinkPrefixDeprecateTimer(Timer &aTimer);
 
     void DeprecateOnLinkPrefix(void);
-    void HandleRouterSolicit(const Ip6::Address &aSrcAddress, const uint8_t *aBuffer, uint16_t aBufferLength);
-    void HandleRouterAdvertisement(const Ip6::Address &aSrcAddress, const uint8_t *aBuffer, uint16_t aBufferLength);
-    bool UpdateDiscoveredPrefixes(const RouterAdv::PrefixInfoOption &aPio, bool aManagedAddrConfig);
-    bool UpdateDiscoveredPrefixes(const RouterAdv::RouteInfoOption &aRio);
-    bool InvalidateDiscoveredPrefixes(const Ip6::Prefix *aPrefix = nullptr, bool aIsOnLinkPrefix = true);
-    void InvalidateAllDiscoveredPrefixes(void);
+    void HandleRouterSolicit(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress);
+    void HandleRouterAdvertisement(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress);
+    bool ShouldProcessPrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio, const Ip6::Prefix &aPrefix);
+    bool ShouldProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption &aRio, const Ip6::Prefix &aPrefix);
+    void UpdateDiscoveredPrefixTableOnNetDataChange(void);
+    void HandleDiscoveredPrefixTableChanged(void);
     bool NetworkDataContainsOmrPrefix(const Ip6::Prefix &aPrefix) const;
-    bool UpdateRouterAdvMessage(const RouterAdv::RouterAdvMessage *aRouterAdvMessage);
+    void UpdateRouterAdvertHeader(const Ip6::Nd::RouterAdvertMessage *aRouterAdvertMessage);
+    bool IsReceivedRouterAdvertFromManager(const Ip6::Nd::RouterAdvertMessage &aRaMessage) const;
+    void ResetDiscoveredPrefixStaleTimer(void);
 
-    static bool IsValidOmrPrefix(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig);
-    static bool IsValidOmrPrefix(const Ip6::Prefix &aOmrPrefix);
-    static bool IsValidOnLinkPrefix(const RouterAdv::PrefixInfoOption &aPio, bool aManagedAddrConfig);
+    static bool IsValidBrUlaPrefix(const Ip6::Prefix &aBrUlaPrefix);
+    static bool IsValidOnLinkPrefix(const Ip6::Nd::PrefixInfoOption &aPio);
     static bool IsValidOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix);
 
     // Indicates whether the Routing Manager is running (started).
@@ -325,25 +600,24 @@
     // Manager will be stopped if we are disabled.
     bool mIsEnabled;
 
-    // Indicates whether the infra interface is running. The Routing
-    // Manager will be stopped when the Infra interface is not running.
-    bool mInfraIfIsRunning;
+    InfraIf mInfraIf;
 
-    // The index of the infra interface on which Router Advertisement
-    // messages will be sent.
-    uint32_t mInfraIfIndex;
+    // The /48 BR ULA prefix loaded from local persistent storage or
+    // randomly generated if none is found in persistent storage.
+    Ip6::Prefix mBrUlaPrefix;
 
-    // The OMR prefix loaded from local persistent storage or randomly
-    // generated if non is found in persistent storage.
-    Ip6::Prefix mLocalOmrPrefix;
+    LocalOmrPrefix mLocalOmrPrefix;
+    OmrPrefix      mFavoredOmrPrefix;
 
-    // The advertised OMR prefixes. For a stable Thread network without
-    // manually configured OMR prefixes, there should be a single OMR
-    // prefix that is being advertised because each BRs will converge to
-    // the smallest OMR prefix sorted by method IsPrefixSmallerThan. If
-    // manually configured OMR prefixes exist, they will also be
-    // advertised on infra link.
-    OmrPrefixArray mAdvertisedOmrPrefixes;
+    // List of on-mesh prefixes (discovered from Network Data) which
+    // were advertised as RIO in the last sent RA message.
+    OnMeshPrefixArray mAdvertisedPrefixes;
+
+    RoutePreference mRouteInfoOptionPreference;
+
+    // The currently favored (smallest) discovered on-link prefix.
+    // Prefix length of zero indicates there is none.
+    Ip6::Prefix mFavoredDiscoveredOnLinkPrefix;
 
     // The on-link prefix loaded from local persistent storage or
     // randomly generated if non is found in persistent storage.
@@ -356,26 +630,26 @@
     TimeMilli  mTimeAdvertisedOnLinkPrefix;
     TimerMilli mOnLinkPrefixDeprecateTimer;
 
-    // The array of prefixes discovered on the infra link. Those
-    // prefixes consist of on-link prefix(es) and OMR prefixes
-    // advertised by BRs in another Thread Network which is connected to
-    // the same infra link.
-    ExternalPrefixArray mDiscoveredPrefixes;
+    // The NAT64 prefix allocated from the /48 BR ULA prefix.
+    Ip6::Prefix mLocalNat64Prefix;
+
+    // True if the local NAT64 prefix is advertised in Thread network.
+    bool mIsAdvertisingLocalNat64Prefix;
+
+    DiscoveredPrefixTable mDiscoveredPrefixTable;
 
     // The RA header and parameters for the infra interface.
     // This value is initialized with `RouterAdvMessage::SetToDefault`
     // and updated with RA messages initiated from infra interface.
-    RouterAdv::RouterAdvMessage mRouterAdvMessage;
-    TimeMilli                   mTimeRouterAdvMessageLastUpdate;
+    Ip6::Nd::RouterAdvertMessage::Header mRouterAdvertHeader;
+    TimeMilli                            mTimeRouterAdvMessageLastUpdate;
+    bool                                 mLearntRouterAdvMessageFromHost;
 
-    TimerMilli mDiscoveredPrefixInvalidTimer;
     TimerMilli mDiscoveredPrefixStaleTimer;
 
-    TimerMilli mRouterAdvertisementTimer;
-    uint32_t   mRouterAdvertisementCount;
+    uint32_t  mRouterAdvertisementCount;
+    TimeMilli mLastRouterAdvertisementSendTime;
 
-    TimerMilli mVicariousRouterSolicitTimer;
-    TimeMilli  mTimeVicariousRouterSolicitStart;
     TimerMilli mRouterSolicitTimer;
     TimeMilli  mTimeRouterSolicitStart;
     uint8_t    mRouterSolicitCount;
diff --git a/src/core/coap/coap.cpp b/src/core/coap/coap.cpp
index 37ceff9..f0b966d 100644
--- a/src/core/coap/coap.cpp
+++ b/src/core/coap/coap.cpp
@@ -28,12 +28,13 @@
 
 #include "coap.hpp"
 
+#include "common/array.hpp"
 #include "common/as_core_type.hpp"
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/random.hpp"
 #include "net/ip6.hpp"
 #include "net/udp6.hpp"
@@ -47,6 +48,8 @@
 namespace ot {
 namespace Coap {
 
+RegisterLogModule("Coap");
+
 CoapBase::CoapBase(Instance &aInstance, Sender aSender)
     : InstanceLocator(aInstance)
     , mMessageId(Random::NonCrypto::GetUint16())
@@ -76,18 +79,15 @@
 
 void CoapBase::ClearRequests(const Ip6::Address *aAddress)
 {
-    Message *nextMessage;
-
-    for (Message *message = mPendingRequests.GetHead(); message != nullptr; message = nextMessage)
+    for (Message &message : mPendingRequests)
     {
         Metadata metadata;
 
-        nextMessage = message->GetNextCoapMessage();
-        metadata.ReadFrom(*message);
+        metadata.ReadFrom(message);
 
         if ((aAddress == nullptr) || (metadata.mSourceAddress == *aAddress))
         {
-            FinalizeCoapTransaction(*message, metadata, nullptr, nullptr, kErrorAbort);
+            FinalizeCoapTransaction(message, metadata, nullptr, nullptr, kErrorAbort);
         }
     }
 }
@@ -139,6 +139,64 @@
     return message;
 }
 
+Message *CoapBase::NewPriorityConfirmablePostMessage(const char *aUriPath)
+{
+    return InitMessage(NewPriorityMessage(), kTypeConfirmable, aUriPath);
+}
+
+Message *CoapBase::NewConfirmablePostMessage(const char *aUriPath)
+{
+    return InitMessage(NewMessage(), kTypeConfirmable, aUriPath);
+}
+
+Message *CoapBase::NewPriorityNonConfirmablePostMessage(const char *aUriPath)
+{
+    return InitMessage(NewPriorityMessage(), kTypeNonConfirmable, aUriPath);
+}
+
+Message *CoapBase::NewNonConfirmablePostMessage(const char *aUriPath)
+{
+    return InitMessage(NewMessage(), kTypeNonConfirmable, aUriPath);
+}
+
+Message *CoapBase::NewPriorityResponseMessage(const Message &aRequest)
+{
+    return InitResponse(NewPriorityMessage(), aRequest);
+}
+
+Message *CoapBase::NewResponseMessage(const Message &aRequest)
+{
+    return InitResponse(NewMessage(), aRequest);
+}
+
+Message *CoapBase::InitMessage(Message *aMessage, Type aType, const char *aUriPath)
+{
+    Error error = kErrorNone;
+
+    VerifyOrExit(aMessage != nullptr);
+
+    SuccessOrExit(error = aMessage->Init(aType, kCodePost, aUriPath));
+    SuccessOrExit(error = aMessage->SetPayloadMarker());
+
+exit:
+    FreeAndNullMessageOnError(aMessage, error);
+    return aMessage;
+}
+
+Message *CoapBase::InitResponse(Message *aMessage, const Message &aResponse)
+{
+    Error error = kErrorNone;
+
+    VerifyOrExit(aMessage != nullptr);
+
+    SuccessOrExit(error = aMessage->SetDefaultResponseHeader(aResponse));
+    SuccessOrExit(error = aMessage->SetPayloadMarker());
+
+exit:
+    FreeAndNullMessageOnError(aMessage, error);
+    return aMessage;
+}
+
 Error CoapBase::Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
 {
     Error error;
@@ -418,19 +476,16 @@
     TimeMilli        now      = TimerMilli::GetNow();
     TimeMilli        nextTime = now.GetDistantFuture();
     Metadata         metadata;
-    Message *        nextMessage;
     Ip6::MessageInfo messageInfo;
 
-    for (Message *message = mPendingRequests.GetHead(); message != nullptr; message = nextMessage)
+    for (Message &message : mPendingRequests)
     {
-        nextMessage = message->GetNextCoapMessage();
-
-        metadata.ReadFrom(*message);
+        metadata.ReadFrom(message);
 
         if (now >= metadata.mNextTimerShot)
         {
 #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
-            if (message->IsRequest() && metadata.mObserve && metadata.mAcknowledged)
+            if (message.IsRequest() && metadata.mObserve && metadata.mAcknowledged)
             {
                 // This is a RFC7641 subscription.  Do not time out.
                 continue;
@@ -440,7 +495,7 @@
             if (!metadata.mConfirmable || (metadata.mRetransmissionsRemaining == 0))
             {
                 // No expected response or acknowledgment.
-                FinalizeCoapTransaction(*message, metadata, nullptr, nullptr, kErrorResponseTimeout);
+                FinalizeCoapTransaction(message, metadata, nullptr, nullptr, kErrorResponseTimeout);
                 continue;
             }
 
@@ -448,7 +503,7 @@
             metadata.mRetransmissionsRemaining--;
             metadata.mRetransmissionTimeout *= 2;
             metadata.mNextTimerShot = now + metadata.mRetransmissionTimeout;
-            metadata.UpdateIn(*message);
+            metadata.UpdateIn(message);
 
             // Retransmit
             if (!metadata.mAcknowledged)
@@ -462,7 +517,7 @@
 #endif
                 messageInfo.SetMulticastLoop(metadata.mMulticastLoop);
 
-                SendCopy(*message, messageInfo);
+                SendCopy(message, messageInfo);
             }
         }
 
@@ -495,17 +550,15 @@
 Error CoapBase::AbortTransaction(ResponseHandler aHandler, void *aContext)
 {
     Error    error = kErrorNotFound;
-    Message *nextMessage;
     Metadata metadata;
 
-    for (Message *message = mPendingRequests.GetHead(); message != nullptr; message = nextMessage)
+    for (Message &message : mPendingRequests)
     {
-        nextMessage = message->GetNextCoapMessage();
-        metadata.ReadFrom(*message);
+        metadata.ReadFrom(message);
 
         if (metadata.mResponseHandler == aHandler && metadata.mResponseContext == aContext)
         {
-            FinalizeCoapTransaction(*message, metadata, nullptr, nullptr, kErrorAbort);
+            FinalizeCoapTransaction(message, metadata, nullptr, nullptr, kErrorAbort);
             error = kErrorNone;
         }
     }
@@ -676,8 +729,8 @@
 
     DequeueMessage(aRequest);
 
-    otLogInfoCoap("Send Block1 Nr. %d, Size: %d bytes, More Blocks Flag: %d", request->GetBlockWiseBlockNumber(),
-                  otCoapBlockSizeFromExponent(request->GetBlockWiseBlockSize()), request->IsMoreBlocksFlagSet());
+    LogInfo("Send Block1 Nr. %d, Size: %d bytes, More Blocks Flag: %d", request->GetBlockWiseBlockNumber(),
+            otCoapBlockSizeFromExponent(request->GetBlockWiseBlockSize()), request->IsMoreBlocksFlagSet());
 
     SuccessOrExit(error = SendMessage(*request, aMessageInfo, TxParameters::GetDefault(),
                                       aCoapMetadata.mResponseHandler, aCoapMetadata.mResponseContext,
@@ -718,8 +771,8 @@
                                                     bufLen, aMessage.IsMoreBlocksFlagSet(), aTotalLength));
 
     // CoAP Block-Wise Transfer continues
-    otLogInfoCoap("Received Block2 Nr. %d , Size: %d bytes, More Blocks Flag: %d", aMessage.GetBlockWiseBlockNumber(),
-                  otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()), aMessage.IsMoreBlocksFlagSet());
+    LogInfo("Received Block2 Nr. %d , Size: %d bytes, More Blocks Flag: %d", aMessage.GetBlockWiseBlockNumber(),
+            otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()), aMessage.IsMoreBlocksFlagSet());
 
     // Conclude block-wise transfer if last block has been received
     if (!aMessage.IsMoreBlocksFlagSet())
@@ -738,8 +791,8 @@
         DequeueMessage(aRequest);
     }
 
-    otLogInfoCoap("Request Block2 Nr. %d, Size: %d bytes", request->GetBlockWiseBlockNumber(),
-                  otCoapBlockSizeFromExponent(request->GetBlockWiseBlockSize()));
+    LogInfo("Request Block2 Nr. %d, Size: %d bytes", request->GetBlockWiseBlockNumber(),
+            otCoapBlockSizeFromExponent(request->GetBlockWiseBlockSize()));
 
     SuccessOrExit(error =
                       SendMessage(*request, aMessageInfo, TxParameters::GetDefault(), aCoapMetadata.mResponseHandler,
@@ -789,8 +842,8 @@
 
         SuccessOrExit(error = CacheLastBlockResponse(response));
 
-        otLogInfoCoap("Acknowledge Block1 Nr. %d, Size: %d bytes", response->GetBlockWiseBlockNumber(),
-                      otCoapBlockSizeFromExponent(response->GetBlockWiseBlockSize()));
+        LogInfo("Acknowledge Block1 Nr. %d, Size: %d bytes", response->GetBlockWiseBlockNumber(),
+                otCoapBlockSizeFromExponent(response->GetBlockWiseBlockSize()));
 
         SuccessOrExit(error = SendMessage(*response, aMessageInfo));
 
@@ -826,8 +879,8 @@
 
     SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock2));
 
-    otLogInfoCoap("Request for Block2 Nr. %d, Size: %d bytes received", aMessage.GetBlockWiseBlockNumber(),
-                  otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()));
+    LogInfo("Request for Block2 Nr. %d, Size: %d bytes received", aMessage.GetBlockWiseBlockNumber(),
+            otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()));
 
     if (aMessage.GetBlockWiseBlockNumber() == 0)
     {
@@ -926,8 +979,8 @@
         FreeLastBlockResponse();
     }
 
-    otLogInfoCoap("Send Block2 Nr. %d, Size: %d bytes, More Blocks Flag %d", response->GetBlockWiseBlockNumber(),
-                  otCoapBlockSizeFromExponent(response->GetBlockWiseBlockSize()), response->IsMoreBlocksFlagSet());
+    LogInfo("Send Block2 Nr. %d, Size: %d bytes, More Blocks Flag %d", response->GetBlockWiseBlockNumber(),
+            otCoapBlockSizeFromExponent(response->GetBlockWiseBlockSize()), response->IsMoreBlocksFlagSet());
 
     SuccessOrExit(error = SendMessage(*response, aMessageInfo));
 
@@ -953,7 +1006,7 @@
 
     if (error != kErrorNone)
     {
-        otLogWarnCoap("Failed to send copy: %s", ErrorToString(error));
+        LogWarn("Failed to send copy: %s", ErrorToString(error));
         FreeMessage(messageCopy);
     }
 }
@@ -962,11 +1015,11 @@
                                       const Ip6::MessageInfo &aMessageInfo,
                                       Metadata &              aMetadata)
 {
-    Message *message;
+    Message *request = nullptr;
 
-    for (message = mPendingRequests.GetHead(); message != nullptr; message = message->GetNextCoapMessage())
+    for (Message &message : mPendingRequests)
     {
-        aMetadata.ReadFrom(*message);
+        aMetadata.ReadFrom(message);
 
         if (((aMetadata.mDestinationAddress == aMessageInfo.GetPeerAddr()) ||
              aMetadata.mDestinationAddress.IsMulticast() ||
@@ -977,8 +1030,9 @@
             {
             case kTypeReset:
             case kTypeAck:
-                if (aResponse.GetMessageId() == message->GetMessageId())
+                if (aResponse.GetMessageId() == message.GetMessageId())
                 {
+                    request = &message;
                     ExitNow();
                 }
 
@@ -986,8 +1040,9 @@
 
             case kTypeConfirmable:
             case kTypeNonConfirmable:
-                if (aResponse.IsTokenEqual(*message))
+                if (aResponse.IsTokenEqual(message))
                 {
+                    request = &message;
                     ExitNow();
                 }
 
@@ -997,7 +1052,7 @@
     }
 
 exit:
-    return message;
+    return request;
 }
 
 void CoapBase::Receive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
@@ -1006,7 +1061,7 @@
 
     if (message.ParseHeader() != kErrorNone)
     {
-        otLogDebgCoap("Failed to parse CoAP header");
+        LogDebg("Failed to parse CoAP header");
 
         if (!aMessageInfo.GetSockAddr().IsMulticast() && message.IsConfirmable())
         {
@@ -1289,7 +1344,7 @@
                 *curUriPath++ = '/';
             }
 
-            VerifyOrExit(curUriPath + iterator.GetOption()->GetLength() < OT_ARRAY_END(uriPath), error = kErrorParse);
+            VerifyOrExit(curUriPath + iterator.GetOption()->GetLength() < GetArrayEnd(uriPath), error = kErrorParse);
 
             IgnoreError(iterator.ReadOptionValue(curUriPath));
             curUriPath += iterator.GetOption()->GetLength();
@@ -1398,7 +1453,7 @@
 
     if (error != kErrorNone)
     {
-        otLogInfoCoap("Failed to process request: %s", ErrorToString(error));
+        LogInfo("Failed to process request: %s", ErrorToString(error));
 
         if (error == kErrorNotFound && !aMessageInfo.GetSockAddr().IsMulticast())
         {
@@ -1446,25 +1501,26 @@
 
 const Message *ResponsesQueue::FindMatchedResponse(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) const
 {
-    Message *message;
+    const Message *response = nullptr;
 
-    for (message = mQueue.GetHead(); message != nullptr; message = message->GetNextCoapMessage())
+    for (const Message &message : mQueue)
     {
-        if (message->GetMessageId() == aRequest.GetMessageId())
+        if (message.GetMessageId() == aRequest.GetMessageId())
         {
             ResponseMetadata metadata;
 
-            metadata.ReadFrom(*message);
+            metadata.ReadFrom(message);
 
             if ((metadata.mMessageInfo.GetPeerPort() == aMessageInfo.GetPeerPort()) &&
                 (metadata.mMessageInfo.GetPeerAddr() == aMessageInfo.GetPeerAddr()))
             {
+                response = &message;
                 break;
             }
         }
     }
 
-    return message;
+    return response;
 }
 
 void ResponsesQueue::EnqueueResponse(Message &               aMessage,
@@ -1503,15 +1559,15 @@
     // `kMaxCachedResponses` remove the one with earliest dequeue
     // time.
 
-    for (Message *message = mQueue.GetHead(); message != nullptr; message = message->GetNextCoapMessage())
+    for (Message &message : mQueue)
     {
         ResponseMetadata metadata;
 
-        metadata.ReadFrom(*message);
+        metadata.ReadFrom(message);
 
         if ((earliestMsg == nullptr) || (metadata.mDequeueTime < earliestDequeueTime))
         {
-            earliestMsg         = message;
+            earliestMsg         = &message;
             earliestDequeueTime = metadata.mDequeueTime;
         }
 
@@ -1543,19 +1599,16 @@
 {
     TimeMilli now             = TimerMilli::GetNow();
     TimeMilli nextDequeueTime = now.GetDistantFuture();
-    Message * nextMessage;
 
-    for (Message *message = mQueue.GetHead(); message != nullptr; message = nextMessage)
+    for (Message &message : mQueue)
     {
         ResponseMetadata metadata;
 
-        nextMessage = message->GetNextCoapMessage();
-
-        metadata.ReadFrom(*message);
+        metadata.ReadFrom(message);
 
         if (now >= metadata.mDequeueTime)
         {
-            DequeueResponse(*message);
+            DequeueResponse(message);
             continue;
         }
 
diff --git a/src/core/coap/coap.hpp b/src/core/coap/coap.hpp
index 8ab2e3c..aea240e 100644
--- a/src/core/coap/coap.hpp
+++ b/src/core/coap/coap.hpp
@@ -34,6 +34,7 @@
 #include <openthread/coap.h>
 
 #include "coap/coap_message.hpp"
+#include "common/as_core_type.hpp"
 #include "common/debug.hpp"
 #include "common/linked_list.hpp"
 #include "common/locator.hpp"
@@ -90,12 +91,12 @@
     /**
      * This static method coverts a pointer to `otCoapTxParameters` to `Coap::TxParamters`
      *
-     * If the pointer is nullptr, the default parameters are used instead.
+     * If the pointer is `nullptr`, the default parameters are used instead.
      *
      * @param[in] aTxParameters   A pointer to tx parameter.
      *
-     * @returns A reference to corresponding `TxParamters` if  @p aTxParameters is not nullptr, otherwise the default tx
-     * parameters.
+     * @returns A reference to corresponding `TxParamters` if  @p aTxParameters is not `nullptr`, otherwise the default
+     *          tx parameters.
      *
      */
     static const TxParameters &From(const otCoapTxParameters *aTxParameters)
@@ -225,7 +226,7 @@
     /**
      * This method gets the next entry in the linked list.
      *
-     * @returns A pointer to the next entry in the linked list or nullptr if at the end of the list.
+     * @returns A pointer to the next entry in the linked list or `nullptr` if at the end of the list.
      *
      */
     const ResourceBlockWise *GetNext(void) const
@@ -236,7 +237,7 @@
     /**
      * This method gets the next entry in the linked list.
      *
-     * @returns A pointer to the next entry in the linked list or nullptr if at the end of the list.
+     * @returns A pointer to the next entry in the linked list or `nullptr` if at the end of the list.
      *
      */
     ResourceBlockWise *GetNext(void)
@@ -428,25 +429,25 @@
     /* This method sets the default handler for unhandled CoAP requests.
      *
      * @param[in]  aHandler   A function pointer that shall be called when an unhandled request arrives.
-     * @param[in]  aContext   A pointer to arbitrary context information. May be nullptr if not used.
+     * @param[in]  aContext   A pointer to arbitrary context information. May be `nullptr` if not used.
      *
      */
     void SetDefaultHandler(RequestHandler aHandler, void *aContext);
 
     /**
-     * This method creates a new message with a CoAP header.
+     * This method allocates a new message with a CoAP header.
      *
      * @param[in]  aSettings  The message settings.
      *
-     * @returns A pointer to the message or nullptr if failed to allocate message.
+     * @returns A pointer to the message or `nullptr` if failed to allocate message.
      *
      */
     Message *NewMessage(const Message::Settings &aSettings = Message::Settings::GetDefault());
 
     /**
-     * This method creates a new message with a CoAP header that has Network Control priority level.
+     * This method allocates a new message with a CoAP header that has Network Control priority level.
      *
-     * @returns A pointer to the message or nullptr if failed to allocate message.
+     * @returns A pointer to the message or `nullptr` if failed to allocate message.
      *
      */
     Message *NewPriorityMessage(void)
@@ -454,6 +455,95 @@
         return NewMessage(Message::Settings(Message::kWithLinkSecurity, Message::kPriorityNet));
     }
 
+    /**
+     * This method allocates and initializes a new CoAP Confirmable Post message with Network Control priority level.
+     *
+     * The CoAP header is initialized as `kTypeConfirmable` and `kCodePost` with a given URI path and a randomly
+     * generated token (of default length). This method also sets the payload marker (`SetPayloadMarker()` on message.
+     * Even if message has no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and
+     * remove the payload marker when there is no payload.
+     *
+     * @param[in] aUriPath   The URI path string.
+     *
+     * @returns A pointer to the message or `nullptr` if failed to allocate message.
+     *
+     */
+    Message *NewPriorityConfirmablePostMessage(const char *aUriPath);
+
+    /**
+     * This method allocates and initializes a new CoAP Confirmable Post message with normal priority level.
+     *
+     * The CoAP header is initialized as `kTypeConfirmable` and `kCodePost` with a given URI path and a randomly
+     * generated token (of default length). This method also sets the payload marker (calling `SetPayloadMarker()`).
+     * Even if message has no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and
+     * remove the payload marker when there is no payload.
+     *
+     * @param[in] aUriPath   The URI path string.
+     *
+     * @returns A pointer to the message or `nullptr` if failed to allocate message.
+     *
+     */
+    Message *NewConfirmablePostMessage(const char *aUriPath);
+
+    /**
+     * This method allocates and initializes a new CoAP Non-confirmable Post message with Network Control priority
+     * level.
+     *
+     * The CoAP header is initialized as `kTypeNonConfirmable` and `kCodePost` with a given URI path and a randomly
+     * generated token (of default length). This method also sets the payload marker (calling `SetPayloadMarker()`).
+     * Even if message has no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and
+     * remove the payload marker when there is no payload.
+     *
+     * @param[in] aUriPath   The URI path string.
+     *
+     * @returns A pointer to the message or `nullptr` if failed to allocate message.
+     *
+     */
+    Message *NewPriorityNonConfirmablePostMessage(const char *aUriPath);
+
+    /**
+     * This method allocates and initializes a new CoAP Non-confirmable Post message with normal priority level.
+     *
+     * The CoAP header is initialized as `kTypeNonConfirmable` and `kCodePost` with a given URI path and a randomly
+     * generated token (of default length). This method also sets the payload marker (calling `SetPayloadMarker()`).
+     * Even if message has no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and
+     * remove the payload marker when there is no payload.
+     *
+     * @param[in] aUriPath   The URI path string.
+     *
+     * @returns A pointer to the message or `nullptr` if failed to allocate message.
+     *
+     */
+    Message *NewNonConfirmablePostMessage(const char *aUriPath);
+
+    /**
+     * This method allocates and initializes a new CoAP response message with Network Control priority level for a
+     * given request message.
+     *
+     * The CoAP header is initialized as `kTypeAck` with `kCodeChanged`. The token and message ID is copied from
+     * @p aRequest. This method also sets the payload marker (calling `SetPayloadMarker()`). Even if message has
+     * no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and remove the payload
+     * marker when there is no payload.
+     *
+     * @returns A pointer to the message or `nullptr` if failed to allocate message.
+     *
+     */
+    Message *NewPriorityResponseMessage(const Message &aRequest);
+
+    /**
+     * This method allocates and initializes a new CoAP response message with regular priority level for a given
+     * request message.
+     *
+     * The CoAP header is initialized as `kTypeAck` with `kCodeChanged`. The token and message ID is copied from
+     * @p aRequest. This method also sets the payload marker (calling `SetPayloadMarker()`). Even if message has
+     * no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and remove the payload
+     * marker when there is no payload.
+     *
+     * @returns A pointer to the message or `nullptr` if failed to allocate message.
+     *
+     */
+    Message *NewResponseMessage(const Message &aRequest);
+
 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
     /**
      * This method sends a CoAP message block-wise with custom transmission parameters.
@@ -487,7 +577,7 @@
      * This method sends a CoAP message with custom transmission parameters.
      *
      * If a response for a request is expected, respective function and context information should be provided.
-     * If no response is expected, these arguments should be nullptr pointers.
+     * If no response is expected, these arguments should be `nullptr` pointers.
      * If Message Id was not set in the header (equal to 0), this function will assign unique Message Id to the message.
      *
      * @param[in]  aMessage      A reference to the message to send.
@@ -511,7 +601,7 @@
      * This method sends a CoAP message with default transmission parameters.
      *
      * If a response for a request is expected, respective function and context information should be provided.
-     * If no response is expected, these arguments should be nullptr pointers.
+     * If no response is expected, these arguments should be `nullptr` pointers.
      * If Message Id was not set in the header (equal to 0), this function will assign unique Message Id to the message.
      *
      * @param[in]  aMessage      A reference to the message to send.
@@ -717,6 +807,9 @@
 #endif
     };
 
+    Message *InitMessage(Message *aMessage, Type aType, const char *aUriPath);
+    Message *InitResponse(Message *aMessage, const Message &aResponse);
+
     static void HandleRetransmissionTimer(Timer &aTimer);
     void        HandleRetransmissionTimer(void);
 
@@ -834,6 +927,13 @@
 };
 
 } // namespace Coap
+
+DefineCoreType(otCoapTxParameters, Coap::TxParameters);
+DefineCoreType(otCoapResource, Coap::Resource);
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+DefineCoreType(otCoapBlockwiseResource, Coap::ResourceBlockWise);
+#endif
+
 } // namespace ot
 
 #endif // COAP_HPP_
diff --git a/src/core/coap/coap_message.cpp b/src/core/coap/coap_message.cpp
index 5753bf7..bd1c152 100644
--- a/src/core/coap/coap_message.cpp
+++ b/src/core/coap/coap_message.cpp
@@ -34,6 +34,7 @@
 #include "coap_message.hpp"
 
 #include "coap/coap.hpp"
+#include "common/array.hpp"
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
 #include "common/encoding.hpp"
@@ -78,26 +79,6 @@
     return error;
 }
 
-void Message::InitAsConfirmablePost(void)
-{
-    Init(kTypeConfirmable, kCodePost);
-}
-
-void Message::InitAsNonConfirmablePost(void)
-{
-    Init(kTypeNonConfirmable, kCodePost);
-}
-
-Error Message::InitAsConfirmablePost(const char *aUriPath)
-{
-    return Init(kTypeConfirmable, kCodePost, aUriPath);
-}
-
-Error Message::InitAsNonConfirmablePost(const char *aUriPath)
-{
-    return Init(kTypeNonConfirmable, kCodePost, aUriPath);
-}
-
 Error Message::InitAsPost(const Ip6::Address &aDestination, const char *aUriPath)
 {
     return Init(aDestination.IsMulticast() ? kTypeNonConfirmable : kTypeConfirmable, kCodePost, aUriPath);
@@ -259,7 +240,7 @@
             *curUriPath++ = '/';
         }
 
-        VerifyOrExit(curUriPath + optionLength < OT_ARRAY_END(aUriPath), error = kErrorParse);
+        VerifyOrExit(curUriPath + optionLength < GetArrayEnd(aUriPath), error = kErrorParse);
 
         IgnoreError(iterator.ReadOptionValue(curUriPath));
         curUriPath += optionLength;
@@ -438,103 +419,53 @@
 #if OPENTHREAD_CONFIG_COAP_API_ENABLE
 const char *Message::CodeToString(void) const
 {
-    const char *string;
+    static constexpr Stringify::Entry kCodeTable[] = {
+        {kCodeEmpty, "Empty"},
+        {kCodeGet, "Get"},
+        {kCodePost, "Post"},
+        {kCodePut, "Put"},
+        {kCodeDelete, "Delete"},
+        {kCodeCreated, "Created"},
+        {kCodeDeleted, "Deleted"},
+        {kCodeValid, "Valid"},
+        {kCodeChanged, "Changed"},
+        {kCodeContent, "Content"},
+        {kCodeContinue, "Continue"},
+        {kCodeBadRequest, "BadRequest"},
+        {kCodeUnauthorized, "Unauthorized"},
+        {kCodeBadOption, "BadOption"},
+        {kCodeForbidden, "Forbidden"},
+        {kCodeNotFound, "NotFound"},
+        {kCodeMethodNotAllowed, "MethodNotAllowed"},
+        {kCodeNotAcceptable, "NotAcceptable"},
+        {kCodeRequestIncomplete, "RequestIncomplete"},
+        {kCodePreconditionFailed, "PreconditionFailed"},
+        {kCodeRequestTooLarge, "RequestTooLarge"},
+        {kCodeUnsupportedFormat, "UnsupportedFormat"},
+        {kCodeInternalError, "InternalError"},
+        {kCodeNotImplemented, "NotImplemented"},
+        {kCodeBadGateway, "BadGateway"},
+        {kCodeServiceUnavailable, "ServiceUnavailable"},
+        {kCodeGatewayTimeout, "GatewayTimeout"},
+        {kCodeProxyNotSupported, "ProxyNotSupported"},
+    };
 
-    switch (GetCode())
-    {
-    case kCodeEmpty:
-        string = "Empty";
-        break;
-    case kCodeGet:
-        string = "Get";
-        break;
-    case kCodePost:
-        string = "Post";
-        break;
-    case kCodePut:
-        string = "Put";
-        break;
-    case kCodeDelete:
-        string = "Delete";
-        break;
-    case kCodeCreated:
-        string = "Created";
-        break;
-    case kCodeDeleted:
-        string = "Deleted";
-        break;
-    case kCodeValid:
-        string = "Valid";
-        break;
-    case kCodeChanged:
-        string = "Changed";
-        break;
-    case kCodeContent:
-        string = "Content";
-        break;
-    case kCodeContinue:
-        string = "Continue";
-        break;
-    case kCodeBadRequest:
-        string = "BadRequest";
-        break;
-    case kCodeUnauthorized:
-        string = "Unauthorized";
-        break;
-    case kCodeBadOption:
-        string = "BadOption";
-        break;
-    case kCodeForbidden:
-        string = "Forbidden";
-        break;
-    case kCodeNotFound:
-        string = "NotFound";
-        break;
-    case kCodeMethodNotAllowed:
-        string = "MethodNotAllowed";
-        break;
-    case kCodeNotAcceptable:
-        string = "NotAcceptable";
-        break;
-    case kCodeRequestIncomplete:
-        string = "RequestIncomplete";
-        break;
-    case kCodePreconditionFailed:
-        string = "PreconditionFailed";
-        break;
-    case kCodeRequestTooLarge:
-        string = "RequestTooLarge";
-        break;
-    case kCodeUnsupportedFormat:
-        string = "UnsupportedFormat";
-        break;
-    case kCodeInternalError:
-        string = "InternalError";
-        break;
-    case kCodeNotImplemented:
-        string = "NotImplemented";
-        break;
-    case kCodeBadGateway:
-        string = "BadGateway";
-        break;
-    case kCodeServiceUnavailable:
-        string = "ServiceUnavailable";
-        break;
-    case kCodeGatewayTimeout:
-        string = "GatewayTimeout";
-        break;
-    case kCodeProxyNotSupported:
-        string = "ProxyNotSupported";
-        break;
-    default:
-        string = "Unknown";
-        break;
-    }
+    static_assert(Stringify::IsSorted(kCodeTable), "kCodeTable is not sorted");
 
-    return string;
+    return Stringify::Lookup(GetCode(), kCodeTable, "Unknown");
 }
 #endif // OPENTHREAD_CONFIG_COAP_API_ENABLE
 
+Message::Iterator MessageQueue::begin(void)
+{
+    return Message::Iterator(GetHead());
+}
+
+Message::ConstIterator MessageQueue::begin(void) const
+{
+    return Message::ConstIterator(GetHead());
+}
+
 Error Option::Iterator::Init(const Message &aMessage)
 {
     Error    error  = kErrorParse;
diff --git a/src/core/coap/coap_message.hpp b/src/core/coap/coap_message.hpp
index db7e1bd..1f4a86b 100644
--- a/src/core/coap/coap_message.hpp
+++ b/src/core/coap/coap_message.hpp
@@ -38,6 +38,7 @@
 
 #include <openthread/coap.h>
 
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/code_utils.hpp"
 #include "common/const_cast.hpp"
@@ -165,6 +166,7 @@
 class Message : public ot::Message
 {
     friend class Option;
+    friend class MessageQueue;
 
 public:
     static constexpr uint8_t kDefaultTokenLength = OT_COAP_DEFAULT_TOKEN_LENGTH; ///< Default token length.
@@ -202,18 +204,6 @@
     void Init(Type aType, Code aCode);
 
     /**
-     * This method initializes the CoAP header as `kTypeConfirmable` and `kCodePost`.
-     *
-     */
-    void InitAsConfirmablePost(void);
-
-    /**
-     * This method initializes the CoAP header as `kTypeNonConfirmable` and `kCodePost`.
-     *
-     */
-    void InitAsNonConfirmablePost(void);
-
-    /**
      * This method initializes the CoAP header with specific Type and Code.
      *
      * @param[in]  aType              The Type value.
@@ -227,28 +217,6 @@
     Error Init(Type aType, Code aCode, const char *aUriPath);
 
     /**
-     * This method initializes the CoAP header as `kTypeConfirmable` and `kCodePost` with a given URI Path.
-     *
-     * @param[in]  aUriPath           A pointer to a null-terminated string.
-     *
-     * @retval kErrorNone         Successfully appended the option.
-     * @retval kErrorNoBufs       The option length exceeds the buffer size.
-     *
-     */
-    Error InitAsConfirmablePost(const char *aUriPath);
-
-    /**
-     * This method initializes the CoAP header as `kTypeNonConfirmable` and `kCodePost` with a given URI Path.
-     *
-     * @param[in]  aUriPath           A pointer to a null-terminated string.
-     *
-     * @retval kErrorNone         Successfully appended the option.
-     * @retval kErrorNoBufs       The option length exceeds the buffer size.
-     *
-     */
-    Error InitAsNonConfirmablePost(const char *aUriPath);
-
-    /**
      * This method initializes the CoAP header as `kCodePost` with a given URI Path with its type determined from a
      * given destination IPv6 address.
      *
@@ -809,7 +777,7 @@
      *
      * @param[in] aLength  Number of payload bytes to copy.
      *
-     * @returns A pointer to the message or nullptr if insufficient message buffers are available.
+     * @returns A pointer to the message or `nullptr` if insufficient message buffers are available.
      *
      */
     Message *Clone(uint16_t aLength) const;
@@ -821,7 +789,7 @@
      * `Type`, `SubType`, `LinkSecurity`, `Offset`, `InterfaceId`, and `Priority` fields on the cloned message are also
      * copied from the original one.
      *
-     * @returns A pointer to the message or nullptr if insufficient message buffers are available.
+     * @returns A pointer to the message or `nullptr` if insufficient message buffers are available.
      *
      */
     Message *Clone(void) const { return Clone(GetLength()); }
@@ -838,7 +806,7 @@
      * This method should be used when the message is in a `Coap::MessageQueue` (i.e., a queue containing only CoAP
      * messages).
      *
-     * @returns A pointer to the next message in the queue or nullptr if at the end of the queue.
+     * @returns A pointer to the next message in the queue or `nullptr` if at the end of the queue.
      *
      */
     Message *GetNextCoapMessage(void) { return static_cast<Message *>(GetNext()); }
@@ -849,7 +817,7 @@
      * This method should be used when the message is in a `Coap::MessageQueue` (i.e., a queue containing only CoAP
      * messages).
      *
-     * @returns A pointer to the next message in the queue or nullptr if at the end of the queue.
+     * @returns A pointer to the next message in the queue or `nullptr` if at the end of the queue.
      *
      */
     const Message *GetNextCoapMessage(void) const { return static_cast<const Message *>(GetNext()); }
@@ -955,6 +923,27 @@
 #endif
     };
 
+    class ConstIterator : public ot::Message::ConstIterator
+    {
+    public:
+        using ot::Message::ConstIterator::ConstIterator;
+
+        const Message &operator*(void) { return static_cast<const Message &>(ot::Message::ConstIterator::operator*()); }
+        const Message *operator->(void)
+        {
+            return static_cast<const Message *>(ot::Message::ConstIterator::operator->());
+        }
+    };
+
+    class Iterator : public ot::Message::Iterator
+    {
+    public:
+        using ot::Message::Iterator::Iterator;
+
+        Message &operator*(void) { return static_cast<Message &>(ot::Message::Iterator::operator*()); }
+        Message *operator->(void) { return static_cast<Message *>(ot::Message::Iterator::operator->()); }
+    };
+
     static_assert(sizeof(HelpData) <= sizeof(Ip6::Header) + sizeof(Ip6::HopByHopHeader) + sizeof(Ip6::OptionMpl) +
                                           sizeof(Ip6::Udp::Header),
                   "HelpData size exceeds the size of the reserved region in the message");
@@ -999,7 +988,15 @@
      * @returns A pointer to the first message.
      *
      */
-    Message *GetHead(void) const { return static_cast<Message *>(ot::MessageQueue::GetHead()); }
+    Message *GetHead(void) { return static_cast<Message *>(ot::MessageQueue::GetHead()); }
+
+    /**
+     * This method returns a pointer to the first message.
+     *
+     * @returns A pointer to the first message.
+     *
+     */
+    const Message *GetHead(void) const { return static_cast<const Message *>(ot::MessageQueue::GetHead()); }
 
     /**
      * This method adds a message to the end of the queue.
@@ -1033,6 +1030,17 @@
      *
      */
     void DequeueAndFree(Message &aMessage) { ot::MessageQueue::DequeueAndFree(aMessage); }
+
+    // The following methods are intended to support range-based `for`
+    // loop iteration over the queue entries and should not be used
+    // directly. The range-based `for` works correctly even if the
+    // current entry is removed from the queue during iteration.
+
+    Message::Iterator begin(void);
+    Message::Iterator end(void) { return Message::Iterator(); }
+
+    Message::ConstIterator begin(void) const;
+    Message::ConstIterator end(void) const { return Message::ConstIterator(); }
 };
 
 /**
@@ -1140,7 +1148,7 @@
         /**
          * This methods gets a pointer to the current CoAP Option to which the iterator is currently pointing.
          *
-         * @returns A pointer to the current CoAP Option, or nullptr if iterator is done (or there was an earlier
+         * @returns A pointer to the current CoAP Option, or `nullptr` if iterator is done (or there was an earlier
          *          parse error).
          *
          */
@@ -1218,6 +1226,64 @@
  */
 
 } // namespace Coap
+
+DefineCoreType(otCoapOption, Coap::Option);
+DefineCoreType(otCoapOptionIterator, Coap::Option::Iterator);
+DefineMapEnum(otCoapType, Coap::Type);
+DefineMapEnum(otCoapCode, Coap::Code);
+
+/**
+ * This method casts an `otMessage` pointer to a `Coap::Message` reference.
+ *
+ * @param[in] aMessage   A pointer to an `otMessage`.
+ *
+ * @returns A reference to `Coap::Message` matching @p aMessage.
+ *
+ */
+inline Coap::Message &AsCoapMessage(otMessage *aMessage)
+{
+    return *static_cast<Coap::Message *>(aMessage);
+}
+
+/**
+ * This method casts an `otMessage` pointer to a `Coap::Message` reference.
+ *
+ * @param[in] aMessage   A pointer to an `otMessage`.
+ *
+ * @returns A reference to `Coap::Message` matching @p aMessage.
+ *
+ */
+inline Coap::Message *AsCoapMessagePtr(otMessage *aMessage)
+{
+    return static_cast<Coap::Message *>(aMessage);
+}
+
+/**
+ * This method casts an `otMessage` pointer to a `Coap::Message` pointer.
+ *
+ * @param[in] aMessage   A pointer to an `otMessage`.
+ *
+ * @returns A pointer to `Coap::Message` matching @p aMessage.
+ *
+ */
+inline const Coap::Message &AsCoapMessage(const otMessage *aMessage)
+{
+    return *static_cast<const Coap::Message *>(aMessage);
+}
+
+/**
+ * This method casts an `otMessage` pointer to a `Coap::Message` reference.
+ *
+ * @param[in] aMessage   A pointer to an `otMessage`.
+ *
+ * @returns A pointer to `Coap::Message` matching @p aMessage.
+ *
+ */
+inline const Coap::Message *AsCoapMessagePtr(const otMessage *aMessage)
+{
+    return static_cast<const Coap::Message *>(aMessage);
+}
+
 } // namespace ot
 
 #endif // COAP_HEADER_HPP_
diff --git a/src/core/coap/coap_secure.cpp b/src/core/coap/coap_secure.cpp
index d6bbada..d158731 100644
--- a/src/core/coap/coap_secure.cpp
+++ b/src/core/coap/coap_secure.cpp
@@ -32,7 +32,7 @@
 
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/new.hpp"
 #include "meshcop/dtls.hpp"
 #include "thread/thread_netif.hpp"
@@ -45,6 +45,8 @@
 namespace ot {
 namespace Coap {
 
+RegisterLogModule("CoapSecure");
+
 CoapSecure::CoapSecure(Instance &aInstance, bool aLayerTwoSecurity)
     : CoapBase(aInstance, &CoapSecure::Send)
     , mDtls(aInstance, aLayerTwoSecurity)
@@ -189,7 +191,7 @@
 {
     ot::Message *message = nullptr;
 
-    VerifyOrExit((message = Get<MessagePool>().New(Message::kTypeIp6, Message::GetHelpDataReserved())) != nullptr);
+    VerifyOrExit((message = Get<MessagePool>().Allocate(Message::kTypeIp6, Message::GetHelpDataReserved())) != nullptr);
     SuccessOrExit(message->AppendBytes(aBuf, aLength));
 
     CoapBase::Receive(*message, mDtls.GetMessageInfo());
@@ -221,12 +223,12 @@
 exit:
     if (error != kErrorNone)
     {
-        otLogNoteMeshCoP("CoapSecure Transmit: %s", ErrorToString(error));
+        LogNote("Transmit: %s", ErrorToString(error));
         message->Free();
     }
     else
     {
-        otLogDebgMeshCoP("CoapSecure Transmit: %s", ErrorToString(error));
+        LogDebg("Transmit: %s", ErrorToString(error));
     }
 }
 
diff --git a/src/core/coap/coap_secure.hpp b/src/core/coap/coap_secure.hpp
index cd01ada..be8caf6 100644
--- a/src/core/coap/coap_secure.hpp
+++ b/src/core/coap/coap_secure.hpp
@@ -209,8 +209,8 @@
      *
      * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
      *
-     * @param[in]  aX509Certificate   A pointer to the PEM formatted X509 PEM certificate.
-     * @param[in]  aX509CertLength    The length of certificate.
+     * @param[in]  aX509Cert          A pointer to the PEM formatted X509 PEM certificate.
+     * @param[in]  aX509Length        The length of certificate.
      * @param[in]  aPrivateKey        A pointer to the PEM formatted private key.
      * @param[in]  aPrivateKeyLength  The length of the private key.
      *
diff --git a/src/core/common/appender.cpp b/src/core/common/appender.cpp
new file mode 100644
index 0000000..caa46e0
--- /dev/null
+++ b/src/core/common/appender.cpp
@@ -0,0 +1,92 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file implements the `Appender` class.
+ */
+
+#include "appender.hpp"
+
+namespace ot {
+
+Appender::Appender(Message &aMessage)
+    : mType(kMessage)
+{
+    mShared.mMessage.mMessage     = &aMessage;
+    mShared.mMessage.mStartOffset = aMessage.GetLength();
+}
+
+Appender::Appender(uint8_t *aBuffer, uint16_t aSize)
+    : mType(kBuffer)
+{
+    mShared.mFrameBuilder.Init(aBuffer, aSize);
+}
+
+Error Appender::AppendBytes(const void *aBuffer, uint16_t aLength)
+{
+    Error error = kErrorNone;
+
+    switch (mType)
+    {
+    case kMessage:
+        error = mShared.mMessage.mMessage->AppendBytes(aBuffer, aLength);
+        break;
+
+    case kBuffer:
+        error = mShared.mFrameBuilder.AppendBytes(aBuffer, aLength);
+        break;
+    }
+
+    return error;
+}
+
+uint16_t Appender::GetAppendedLength(void) const
+{
+    uint16_t length = 0;
+
+    switch (mType)
+    {
+    case kMessage:
+        length = mShared.mMessage.mMessage->GetLength() - mShared.mMessage.mStartOffset;
+        break;
+
+    case kBuffer:
+        length = mShared.mFrameBuilder.GetLength();
+        break;
+    }
+
+    return length;
+}
+
+void Appender::GetAsData(Data<kWithUint16Length> &aData)
+{
+    aData.Init(mShared.mFrameBuilder.GetBytes(), mShared.mFrameBuilder.GetLength());
+}
+
+} // namespace ot
diff --git a/src/core/common/appender.hpp b/src/core/common/appender.hpp
new file mode 100644
index 0000000..9154c53
--- /dev/null
+++ b/src/core/common/appender.hpp
@@ -0,0 +1,183 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *  This file defines OpenThread `Appender` class.
+ */
+
+#ifndef APPENDER_HPP_
+#define APPENDER_HPP_
+
+#include "openthread-core-config.h"
+
+#include "common/const_cast.hpp"
+#include "common/data.hpp"
+#include "common/frame_builder.hpp"
+#include "common/message.hpp"
+#include "common/type_traits.hpp"
+
+namespace ot {
+
+/**
+ * The `Appender` class acts as a wrapper over either a `Message` or a data buffer and provides different flavors of
+ * `Append()` method.
+ *
+ * This class helps in construction of message content where the destination can be either a `Message` or a buffer.
+ *
+ */
+class Appender
+{
+public:
+    /**
+     * This enumeration represent the `Appender` Type (whether appending to a `Message` or data buffer).
+     *
+     */
+    enum Type : uint8_t
+    {
+        kMessage, ///< `Appender` appends to a `Message`
+        kBuffer,  ///< `Appender` appends to a buffer.
+    };
+
+    /**
+     * This constructor initializes the `Appender` to append to a `Message`.
+     *
+     * New content is appended to the end of @p aMessage, growing its length.
+     *
+     * @param[in] aMessage   The message to append to.
+     *
+     */
+    explicit Appender(Message &aMessage);
+
+    /**
+     * This constructor initializes the `Appender` to append in a given a buffer
+     *
+     * New content is append in the buffer starting from @p aBuffer up to is size @p aSize. `Appender` does not allow
+     * content to be appended beyond the size of the buffer.
+     *
+     * @param[in] aBuffer  A pointer to start of buffer.
+     * @param[in] aSize    The maximum size of @p aBuffer (number of available bytes in buffer).
+     *
+     */
+    Appender(uint8_t *aBuffer, uint16_t aSize);
+
+    /**
+     * This method indicates the `Appender` type (whether appending to a `Message` or data buffer).
+     *
+     * @returns The type of `Appender`.
+     *
+     */
+    Type GetType(void) const { return mType; }
+
+    /**
+     * This method appends bytes to the `Appender` object
+     *
+     * @param[in] aBuffer  A pointer to a data buffer (MUST NOT be `nullptr`) to append.
+     * @param[in] aLength  The number of bytes to append.
+     *
+     * @retval kErrorNone    Successfully appended the bytes.
+     * @retval kErrorNoBufs  Insufficient available buffers.
+     *
+     */
+    Error AppendBytes(const void *aBuffer, uint16_t aLength);
+
+    /**
+     * This method appends an object to the end of the `Appender` object.
+     *
+     * @tparam    ObjectType   The object type to append to the message.
+     *
+     * @param[in] aObject      A reference to the object to append to the message.
+     *
+     * @retval kErrorNone    Successfully appended the object.
+     * @retval kErrorNoBufs  Insufficient available buffers to append @p aObject.
+     *
+     */
+    template <typename ObjectType> Error Append(const ObjectType &aObject)
+    {
+        static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
+
+        return AppendBytes(&aObject, sizeof(ObjectType));
+    }
+
+    /**
+     * This method returns the number of bytes appended so far using `Appender` methods.
+     *
+     * This method can be used independent of the `Type` of `Appender`.
+     *
+     * @returns The number of byes appended so far.
+     *
+     */
+    uint16_t GetAppendedLength(void) const;
+
+    /**
+     * This method returns the `Message` associated with `Appender`.
+     *
+     * This method MUST be used when `GetType() == kMessage`. Otherwise its behavior is undefined.
+     *
+     * @returns The `Message` instance associated with `Appender`.
+     *
+     */
+    Message &GetMessage(void) { return *mShared.mMessage.mMessage; }
+
+    /**
+     * This method returns a pointer to the start of the data buffer associated with `Appender`.
+     *
+     * This method MUST be used when `GetType() == kBuffer`. Otherwise its behavior is undefined.
+     *
+     * @returns A pointer to the start of the data buffer associated with `Appender`.
+     *
+     */
+    uint8_t *GetBufferStart(void) { return AsNonConst(mShared.mFrameBuilder.GetBytes()); }
+
+    /**
+     * This method gets the data buffer associated with `Appender` as a `Data`.
+     *
+     * This method MUST be used when `GetType() == kBuffer`. Otherwise its behavior is undefined.
+     *
+     * @pram[out] aData  A reference to a `Data` to output the data buffer.
+     *
+     */
+    void GetAsData(Data<kWithUint16Length> &aData);
+
+private:
+    Type mType;
+    union
+    {
+        struct
+        {
+            Message *mMessage;
+            uint16_t mStartOffset;
+        } mMessage;
+
+        FrameBuilder mFrameBuilder;
+    } mShared;
+};
+
+} // namespace ot
+
+#endif // APPENDER_HPP_
diff --git a/src/core/common/array.hpp b/src/core/common/array.hpp
index 3f5ee10..2afb4fd 100644
--- a/src/core/common/array.hpp
+++ b/src/core/common/array.hpp
@@ -45,6 +45,61 @@
 namespace ot {
 
 /**
+ * This function returns the length of a given array (number of elements in the array).
+ *
+ * This template function is `constexpr`. The template arguments are expected to be deduced by the compiler allowing
+ * callers to simply use `GetArrayLength(aArray)`.
+ *
+ * @tparam  Type          The array element type.
+ * @tparam  kArrayLength  The array length.
+ *
+ * @returns The array length (number of elements in the array).
+ *
+ */
+template <typename Type, uint16_t kArrayLength> constexpr inline uint16_t GetArrayLength(const Type (&)[kArrayLength])
+{
+    return kArrayLength;
+}
+
+/**
+ * This function returns a pointer to end of a given array (pointing to the past-the-end element).
+ *
+ * Note that the past-the-end element is a theoretical element that would follow the last element in the array. It does
+ * not point to an actual element in array, and thus should not be dereferenced.
+ *
+ * @tparam  Type          The array element type.
+ * @tparam  kArrayLength  The array length.
+ *
+ * @param[in] aArray   A reference to the array.
+ *
+ * @returns Pointer to the past-the-end element.
+ *
+ */
+template <typename Type, uint16_t kArrayLength> inline Type *GetArrayEnd(Type (&aArray)[kArrayLength])
+{
+    return &aArray[kArrayLength];
+}
+
+/**
+ * This function returns a pointer to end of a given array (pointing to the past-the-end element).
+ *
+ * Note that the past-the-end element is a theoretical element that would follow the last element in the array. It does
+ * not point to an actual element in array, and thus should not be dereferenced.
+ *
+ * @tparam  Type          The array element type.
+ * @tparam  kArrayLength  The array length.
+ *
+ * @param[in] aArray   A reference to the array.
+ *
+ * @returns Pointer to the past-the-end element.
+ *
+ */
+template <typename Type, uint16_t kArrayLength> inline const Type *GetArrayEnd(const Type (&aArray)[kArrayLength])
+{
+    return &aArray[kArrayLength];
+}
+
+/**
  * This template class represents an array of elements with a fixed max size.
  *
  * @tparam Type        The array element type.
@@ -256,6 +311,27 @@
     IndexType IndexOf(const Type &aElement) const { return static_cast<IndexType>(&aElement - &mElements[0]); }
 
     /**
+     * This method removes an element from the array.
+     *
+     * The @p aElement MUST be from the array, otherwise the behavior of this method is undefined.
+     *
+     * To remove @p aElement, it is replaced by the last element in array, so the order of items in the array can
+     * change after a call to this method.
+     *
+     * The method uses assignment `=` operator on `Type` to copy the last element in place of @p aElement.
+     *
+     */
+    void Remove(Type &aElement)
+    {
+        Type *lastElement = PopBack();
+
+        if (lastElement != &aElement)
+        {
+            aElement = *lastElement;
+        }
+    }
+
+    /**
      * This method finds the first match of a given entry in the array.
      *
      * This method uses `==` operator on `Type` to compare the array element with @p aEntry.
@@ -317,7 +393,7 @@
      *
      * @param[in]  aIndicator  An indicator to match with elements in the array.
      *
-     * @returns A pointer to the matched array element, or nullptr if a match could not be found.
+     * @returns A pointer to the matched array element, or `nullptr` if a match could not be found.
      *
      */
     template <typename Indicator> Type *FindMatching(const Indicator &aIndicator)
@@ -336,7 +412,7 @@
      *
      * @param[in]  aIndicator  An indicator to match with elements in the array.
      *
-     * @returns A pointer to the matched array element, or nullptr if a match could not be found.
+     * @returns A pointer to the matched array element, or `nullptr` if a match could not be found.
      *
      */
     template <typename Indicator> const Type *FindMatching(const Indicator &aIndicator) const
@@ -376,6 +452,68 @@
     }
 
     /**
+     * This template method removes the first element in the array matching a given indicator.
+     *
+     * This method behaves similar to `Remove()`, i.e., the matched element (if found) is replaced with the last element
+     * in the array (using `=` operator on `Type`). So the order of items in the array can change after a call to this
+     * method.
+     *
+     * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against elements
+     * in the array. To check that an element matches the given indicator, the `Matches()` method is invoked on each
+     * `Type` element in the array. The `Matches()` method should be provided by `Type` class accordingly:
+     *
+     *     bool Type::Matches(const Indicator &aIndicator) const
+     *
+     * @param[in]  aIndicator  An indicator to match with elements in the array.
+     *
+     */
+    template <typename Indicator> void RemoveMatching(const Indicator &aIndicator)
+    {
+        Type *entry = FindMatching(aIndicator);
+
+        if (entry != nullptr)
+        {
+            Remove(*entry);
+        }
+    }
+
+    /**
+     * This template method removes all elements in the array matching a given indicator.
+     *
+     * This method behaves similar to `Remove()`, i.e., a matched element is replaced with the last element in the
+     * array (using `=` operator on `Type`). So the order of items in the array can change after a call to this method.
+     *
+     * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against elements
+     * in the array. To check that an element matches the given indicator, the `Matches()` method is invoked on each
+     * `Type` element in the array. The `Matches()` method should be provided by `Type` class accordingly:
+     *
+     *     bool Type::Matches(const Indicator &aIndicator) const
+     *
+     * @param[in]  aIndicator  An indicator to match with elements in the array.
+     *
+     */
+    template <typename Indicator> void RemoveAllMatching(const Indicator &aIndicator)
+    {
+        for (IndexType index = 0; index < GetLength();)
+        {
+            Type &entry = mElements[index];
+
+            if (entry.Matches(aIndicator))
+            {
+                Remove(entry);
+
+                // When the entry is removed from the array it is
+                // replaced with the last element. In this case, we do
+                // not increment `index`.
+            }
+            else
+            {
+                index++;
+            }
+        }
+    }
+
+    /**
      * This method overloads assignment `=` operator to copy elements from another array into the array.
      *
      * The method uses assignment `=` operator on `Type` to copy each element from @p aOtherArray into the elements of
diff --git a/src/core/common/as_core_type.hpp b/src/core/common/as_core_type.hpp
index 0020894..e5ad9bc 100644
--- a/src/core/common/as_core_type.hpp
+++ b/src/core/common/as_core_type.hpp
@@ -36,11 +36,6 @@
 
 #include "openthread-core-config.h"
 
-#include "common/instance.hpp"
-#include "crypto/sha256.hpp"
-#include "mac/mac_filter.hpp"
-#include "net/dns_types.hpp"
-
 namespace ot {
 
 /**
@@ -116,62 +111,6 @@
     return static_cast<const typename CoreType<Type>::Type *>(aObject);
 }
 
-#if OPENTHREAD_FTD || OPENTHREAD_MTD
-
-/**
- * This method casts an `otMessage` pointer to a `Coap::Message` reference.
- *
- * @param[in] aMessage   A pointer to an `otMessage`.
- *
- * @returns A reference to `Coap::Message` matching @p aMessage.
- *
- */
-inline Coap::Message &AsCoapMessage(otMessage *aMessage)
-{
-    return *static_cast<Coap::Message *>(aMessage);
-}
-
-/**
- * This method casts an `otMessage` pointer to a `Coap::Message` reference.
- *
- * @param[in] aMessage   A pointer to an `otMessage`.
- *
- * @returns A reference to `Coap::Message` matching @p aMessage.
- *
- */
-inline Coap::Message *AsCoapMessagePtr(otMessage *aMessage)
-{
-    return static_cast<Coap::Message *>(aMessage);
-}
-
-/**
- * This method casts an `otMessage` pointer to a `Coap::Message` pointer.
- *
- * @param[in] aMessage   A pointer to an `otMessage`.
- *
- * @returns A pointer to `Coap::Message` matching @p aMessage.
- *
- */
-inline const Coap::Message &AsCoapMessage(const otMessage *aMessage)
-{
-    return *static_cast<const Coap::Message *>(aMessage);
-}
-
-/**
- * This method casts an `otMessage` pointer to a `Coap::Message` reference.
- *
- * @param[in] aMessage   A pointer to an `otMessage`.
- *
- * @returns A pointer to `Coap::Message` matching @p aMessage.
- *
- */
-inline const Coap::Message *AsCoapMessagePtr(const otMessage *aMessage)
-{
-    return static_cast<const Coap::Message *>(aMessage);
-}
-
-#endif // #if OPENTHREAD_FTD || OPENTHREAD_MTD
-
 /**
  * This structure maps two enumeration types.
  *
@@ -198,9 +137,6 @@
     return static_cast<typename MappedEnum<EnumType>::Type>(aValue);
 }
 
-//---------------------------------------------------------------------------------------------------------------------
-// Private macros and definitions
-
 // Helper macro to define specialization of `CoreType` struct relating `BaseType` with `SubType`.
 #define DefineCoreType(BaseType, SubType) \
     template <> struct CoreType<BaseType> \
@@ -220,149 +156,6 @@
         using Type = FirstEnumType;                  \
     }
 
-DefineCoreType(otInstance, Instance);
-
-// Message
-DefineCoreType(otMessage, Message);
-DefineCoreType(otMessageSettings, Message::Settings);
-DefineCoreType(otMessageBuffer, Buffer);
-DefineCoreType(otMessageQueue, MessageQueue);
-
-// Mac
-DefineCoreType(otRadioFrame, Mac::Frame);
-DefineCoreType(otExtAddress, Mac::ExtAddress);
-DefineCoreType(otMacKey, Mac::Key);
-DefineCoreType(otExtendedPanId, Mac::ExtendedPanId);
-DefineCoreType(otNetworkName, Mac::NetworkName);
-#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
-DefineMapEnum(otMacFilterAddressMode, Mac::Filter::Mode);
-#endif
-
-DefineCoreType(otCryptoKey, Crypto::Key);
-DefineCoreType(otCryptoSha256Hash, Crypto::Sha256::Hash);
-
-#if OPENTHREAD_FTD || OPENTHREAD_MTD
-
-// Thread
-DefineCoreType(otThreadLinkInfo, ThreadLinkInfo);
-DefineCoreType(otSecurityPolicy, SecurityPolicy);
-DefineCoreType(otNetworkKey, NetworkKey);
-DefineCoreType(otPskc, Pskc);
-
-DefineCoreType(otNeighborInfo, Neighbor::Info);
-DefineCoreType(otRouterInfo, Router::Info);
-#if OPENTHREAD_FTD
-DefineCoreType(otChildInfo, Child::Info);
-#endif
-
-// Ip6
-DefineCoreType(otIp6Prefix, Ip6::Prefix);
-DefineCoreType(otIp6InterfaceIdentifier, Ip6::InterfaceIdentifier);
-DefineCoreType(otIp6Address, Ip6::Address);
-DefineCoreType(otMessageInfo, Ip6::MessageInfo);
-DefineCoreType(otSockAddr, Ip6::SockAddr);
-DefineCoreType(otNetifAddress, Ip6::Netif::UnicastAddress);
-DefineCoreType(otNetifMulticastAddress, Ip6::Netif::MulticastAddress);
-DefineCoreType(otIcmp6Header, Ip6::Icmp::Header);
-DefineCoreType(otIcmp6Handler, Ip6::Icmp::Handler);
-DefineCoreType(otUdpSocket, Ip6::Udp::SocketHandle);
-DefineCoreType(otUdpReceiver, Ip6::Udp::Receiver);
-DefineCoreType(otTcpEndpoint, Ip6::Tcp::Endpoint);
-DefineCoreType(otTcpListener, Ip6::Tcp::Listener);
-
-// Mle
-DefineCoreType(otMeshLocalPrefix, Mle::MeshLocalPrefix);
-DefineCoreType(otLeaderData, Mle::LeaderData);
-DefineMapEnum(otDeviceRole, Mle::DeviceRole);
-
-// LinkMetrics
-#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
-DefineCoreType(otLinkMetrics, LinkMetrics::Metrics);
-DefineCoreType(otLinkMetricsValues, LinkMetrics::MetricsValues);
-DefineMapEnum(otLinkMetricsEnhAckFlags, LinkMetrics::EnhAckFlags);
-#endif
-
-// NetworkData
-DefineCoreType(otBorderRouterConfig, NetworkData::OnMeshPrefixConfig);
-DefineCoreType(otExternalRouteConfig, NetworkData::ExternalRouteConfig);
-DefineCoreType(otServiceConfig, NetworkData::ServiceConfig);
-DefineCoreType(otServerConfig, NetworkData::ServiceConfig::ServerConfig);
-
-// MeshCoP
-DefineCoreType(otOperationalDatasetComponents, MeshCoP::Dataset::Components);
-DefineCoreType(otOperationalDataset, MeshCoP::Dataset::Info);
-DefineCoreType(otJoinerPskd, MeshCoP::JoinerPskd);
-DefineCoreType(otJoinerDiscerner, MeshCoP::JoinerDiscerner);
-DefineCoreType(otSteeringData, MeshCoP::SteeringData);
-#if OPENTHREAD_CONFIG_JOINER_ENABLE
-DefineMapEnum(otJoinerState, MeshCoP::Joiner::State);
-#endif
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
-DefineMapEnum(otCommissionerState, MeshCoP::Commissioner::State);
-#endif
-#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
-DefineMapEnum(otBorderAgentState, MeshCoP::BorderAgent::State);
-#endif
-
-// Coap
-DefineCoreType(otCoapTxParameters, Coap::TxParameters);
-DefineCoreType(otCoapResource, Coap::Resource);
-DefineCoreType(otCoapOption, Coap::Option);
-DefineCoreType(otCoapOptionIterator, Coap::Option::Iterator);
-DefineMapEnum(otCoapType, Coap::Type);
-DefineMapEnum(otCoapCode, Coap::Code);
-#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
-DefineCoreType(otCoapBlockwiseResource, Coap::ResourceBlockWise);
-#endif
-
-// Dns
-DefineCoreType(otDnsTxtEntry, Dns::TxtEntry);
-DefineCoreType(otDnsTxtEntryIterator, Dns::TxtEntry::Iterator);
-#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
-DefineCoreType(otDnsQueryConfig, Dns::Client::QueryConfig);
-DefineCoreType(otDnsAddressResponse, Dns::Client::AddressResponse);
-#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
-DefineCoreType(otDnsBrowseResponse, Dns::Client::BrowseResponse);
-DefineCoreType(otDnsServiceResponse, Dns::Client::ServiceResponse);
-DefineCoreType(otDnsServiceInfo, Dns::Client::ServiceInfo);
-#endif
-#endif
-#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
-DefineMapEnum(otDnssdQueryType, Dns::ServiceDiscovery::Server::DnsQueryType);
-#endif
-
-// Srp
-#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
-DefineCoreType(otSrpClientHostInfo, Srp::Client::HostInfo);
-DefineCoreType(otSrpClientService, Srp::Client::Service);
-DefineMapEnum(otSrpClientItemState, Srp::Client::ItemState);
-#endif
-#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
-DefineCoreType(otSrpServerLeaseConfig, Srp::Server::LeaseConfig);
-DefineCoreType(otSrpServerHost, Srp::Server::Host);
-DefineCoreType(otSrpServerService, Srp::Server::Service);
-DefineMapEnum(otSrpServerState, Srp::Server::State);
-DefineMapEnum(otSrpServerAddressMode, Srp::Server::AddressMode);
-#endif
-
-// Utils
-#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
-DefineCoreType(otHistoryTrackerIterator, Utils::HistoryTracker::Iterator);
-DefineCoreType(otHistoryTrackerNetworkInfo, Utils::HistoryTracker::NetworkInfo);
-DefineCoreType(otHistoryTrackerMessageInfo, Utils::HistoryTracker::MessageInfo);
-DefineCoreType(otHistoryTrackerNeighborInfo, Utils::HistoryTracker::NeighborInfo);
-#endif
-#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
-DefineCoreType(otPingSenderReply, Utils::PingSender::Reply);
-DefineCoreType(otPingSenderConfig, Utils::PingSender::Config);
-DefineCoreType(otPingSenderStatistics, Utils::PingSender::Statistics);
-#endif
-#if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE
-DefineCoreType(otSrpClientBuffersServiceEntry, Utils::SrpClientBuffers::ServiceEntry);
-#endif
-
-#endif // #if OPENTHREAD_FTD || OPENTHREAD_MTD
-
 } // namespace ot
 
 #endif // AS_CORE_TYPE_HPP_
diff --git a/src/core/utils/lookup_table.cpp b/src/core/common/binary_search.cpp
similarity index 68%
rename from src/core/utils/lookup_table.cpp
rename to src/core/common/binary_search.cpp
index e4e8dee..58256e0 100644
--- a/src/core/utils/lookup_table.cpp
+++ b/src/core/common/binary_search.cpp
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2020, The OpenThread Authors.
+ *  Copyright (c) 2022, The OpenThread Authors.
  *  All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -28,23 +28,20 @@
 
 /**
  * @file
- *   This file implements the lookup table (binary search) functionality.
+ *  This file implements a generic binary search.
  */
 
-#include <string.h>
-
-#include "lookup_table.hpp"
+#include "binary_search.hpp"
 
 #include "common/code_utils.hpp"
 
 namespace ot {
-namespace Utils {
 
-const void *LookupTable::Find(const char *aName,
-                              const void *aTable,
-                              uint16_t    aLength,
-                              uint16_t    aTableEntrySize,
-                              NameGetter  aNameGetter)
+const void *BinarySearch::Find(const void *aKey,
+                               const void *aTable,
+                               uint16_t    aLength,
+                               uint16_t    aEntrySize,
+                               Comparator  aComparator)
 {
     const void *entry;
     uint16_t    left  = 0;
@@ -56,17 +53,17 @@
         int      compare;
 
         // Note that `aTable` array entry type is not known here and
-        // only its size is given as `aTableEntrySize`. Based on this,
-        // we can calculate the pointer to the table entry at any index
+        // only its size is given as `aEntrySize`. Based on this, we
+        // can calculate the pointer to the table entry at any index
         // (such as `[middle]`) which is then passed to the given
-        // `aNameGetter` function which knows how to cast the void
-        // pointer to proper entry type and get the enclosed `mName`
-        // field. This model keeps the implementation generic and
-        // re-usable allowing it to be used with any entry type.
+        // `aComparator` function which knows how to cast the void
+        // pointer to proper entry type and compare it with `aKey`.
+        // This model keeps the implementation generic and reusable
+        // allowing it to be used with any entry type.
 
-        entry = reinterpret_cast<const uint8_t *>(aTable) + aTableEntrySize * middle;
+        entry = reinterpret_cast<const uint8_t *>(aTable) + aEntrySize * middle;
 
-        compare = strcmp(aName, aNameGetter(entry));
+        compare = aComparator(aKey, entry);
 
         if (compare == 0)
         {
@@ -88,5 +85,4 @@
     return entry;
 }
 
-} // namespace Utils
 } // namespace ot
diff --git a/src/core/common/binary_search.hpp b/src/core/common/binary_search.hpp
new file mode 100644
index 0000000..0e05ab5
--- /dev/null
+++ b/src/core/common/binary_search.hpp
@@ -0,0 +1,127 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *  This file provides a generic binary search and related helper functions.
+ */
+
+#ifndef BINARY_SEARCH_HPP_
+#define BINARY_SEARCH_HPP_
+
+#include "openthread-core-config.h"
+
+#include <stdint.h>
+
+namespace ot {
+
+class BinarySearch
+{
+public:
+    /**
+     * This template method performs binary search in a given sorted table array to find an entry matching a given key.
+     *
+     * @note This method requires the array to be sorted, otherwise its behavior is undefined.
+     *
+     * @tparam Key         The type of `Key` to search for.
+     * @tparam Entry       The table `Entry` type.
+     * @tparam kLength     The array length (number of entries in the array).
+     *
+     * The `Entry` class MUST provide the following method to compare the entry against a given key.
+     *
+     *    int Entry::Compare(const Key &aKey) const;
+     *
+     * The return value indicates the comparison result between @p aKey and the entry (similar to `strcmp()`), i.e.,
+     * zero means perfect match, positive (> 0) indicates @p aKey is larger than entry, and negative indicates @p aKey
+     * is smaller than entry.
+     *
+     * @note In the common use of this method as `Find(key, kTable)` where `kTable` is a fixed size array, the
+     * template types/parameters do not need to be explicitly specified and can be inferred from the passed-in argument.
+     *
+     * @param[in] aKey    The key to search for within the table.
+     * @param[in] aTable  A reference to an array of `kLength` entries of type `Entry`
+     *
+     * @returns A pointer to the entry in the table if a match is found, otherwise `nullptr` (no match in table).
+     *
+     */
+    template <typename Key, typename Entry, uint16_t kLength>
+    static const Entry *Find(const Key &aKey, const Entry (&aTable)[kLength])
+    {
+        return static_cast<const Entry *>(
+            Find(&aKey, &aTable[0], kLength, sizeof(aTable[0]), BinarySearch::Compare<Key, Entry>));
+    }
+
+    /**
+     * This template method indicates whether a given table array is sorted based or not.
+     *
+     * This method is `constexpr` and is intended for use in `static_assert`s to verify that a `constexpr` lookup table
+     * array is sorted. It is not recommended for use in other situations.
+     *
+     * @tparam Entry       The table entry type.
+     * @tparam kLength     The array length (number of entries in the array).
+     *
+     * The `Entry` class MUST provide the following `static` and `constexpr` method to compare two entries.
+     *
+     *    constexpr static bool Entry::AreInOrder(const Entry &aFirst, const Entry &aSecond);
+     *
+     * The return value MUST be TRUE if the entries are in order, i.e. `aFirst < aSecond` and FALSE otherwise.
+     *
+     * @param[in] aTable  A reference to an array of `kLength` entries on type `Entry`
+     *
+     * @retval TRUE   If the entries in @p aTable are sorted.
+     * @retval FALSE  If the entries in @p aTable are not sorted.
+     *
+     */
+    template <typename Entry, uint16_t kLength> static constexpr bool IsSorted(const Entry (&aTable)[kLength])
+    {
+        return IsSorted(&aTable[0], kLength);
+    }
+
+private:
+    typedef int (&Comparator)(const void *aKey, const void *aEntry);
+
+    template <typename Entry> static constexpr bool IsSorted(const Entry *aTable, uint16_t aLength)
+    {
+        return (aLength <= 1) ? true : Entry::AreInOrder(aTable[0], aTable[1]) && IsSorted(aTable + 1, aLength - 1);
+    }
+
+    template <typename Key, typename Entry> static int Compare(const void *aKey, const void *aEntry)
+    {
+        return static_cast<const Entry *>(aEntry)->Compare(*static_cast<const Key *>(aKey));
+    }
+
+    static const void *Find(const void *aKey,
+                            const void *aTable,
+                            uint16_t    aLength,
+                            uint16_t    aEntrySize,
+                            Comparator  aComparator);
+};
+
+} // namespace ot
+
+#endif // BINARY_SEARCH_HPP_
diff --git a/include/openthread/entropy.h b/src/core/common/data.cpp
similarity index 69%
copy from include/openthread/entropy.h
copy to src/core/common/data.cpp
index bc07c30..f7bec4e 100644
--- a/include/openthread/entropy.h
+++ b/src/core/common/data.cpp
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2019, The OpenThread Authors.
+ *  Copyright (c) 2021, The OpenThread Authors.
  *  All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -28,43 +28,33 @@
 
 /**
  * @file
- * @brief
- *  This file defines the OpenThread entropy source API.
+ *   This file implements `Data` related function
  */
 
-#ifndef OPENTHREAD_ENTROPY_H_
-#define OPENTHREAD_ENTROPY_H_
+#include "data.hpp"
 
-#include <mbedtls/entropy.h>
+namespace ot {
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+bool DataUtils::MatchBytes(const uint8_t *aFirstBuffer,
+                           const uint8_t *aSecondBuffer,
+                           uint16_t       aLength,
+                           ByteMatcher    aMatcher)
+{
+    bool matches = true;
 
-/**
- * @addtogroup api-entropy
- *
- * @brief
- *   This module includes functions that manages entropy source.
- *
- * @{
- *
- */
+    if (aMatcher == nullptr)
+    {
+        matches = (memcmp(aFirstBuffer, aSecondBuffer, aLength) == 0);
+        ExitNow();
+    }
 
-/**
- * This function returns initialized mbedtls_entropy_context.
- *
- * @returns  A pointer to initialized mbedtls_entropy_context.
- */
-mbedtls_entropy_context *otEntropyMbedTlsContextGet(void);
+    while (aLength-- != 0)
+    {
+        VerifyOrExit(aMatcher(*aFirstBuffer++, *aSecondBuffer++), matches = false);
+    }
 
-/**
- * @}
- *
- */
+exit:
+    return matches;
+}
 
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // OPENTHREAD_ENTROPY_H_
+} // namespace ot
diff --git a/src/core/common/data.hpp b/src/core/common/data.hpp
index c8e57da..59b37a3 100644
--- a/src/core/common/data.hpp
+++ b/src/core/common/data.hpp
@@ -59,6 +59,35 @@
     kWithUint16Length, ///< Use `uint16_t` for data length
 };
 
+/**
+ * This type specifies a function pointer which matches two given bytes.
+ *
+ * Such a function is used as a parameter in `Data::MatchesByteIn()` method. This can be used to relax the definition
+ * of a match when comparing data bytes, e.g., can be used for case-insensitive string comparison.
+ *
+ * @param[in] aFirst   A first byte.
+ * @param[in] aSecond  A second byte.
+ *
+ * @retval TRUE  if @p aFirst matches @p aSecond.
+ * @retval FALSE if @p aFirst does not match @p aSecond.
+ *
+ */
+typedef bool (*ByteMatcher)(uint8_t aFirst, uint8_t aSecond);
+
+/**
+ * This class implements common utility methods used by `Data` and `MutableData`.
+ *
+ */
+class DataUtils
+{
+protected:
+    DataUtils(void) = default;
+    static bool MatchBytes(const uint8_t *aFirstBuffer,
+                           const uint8_t *aSecondBuffer,
+                           uint16_t       aLength,
+                           ByteMatcher    aMatcher);
+};
+
 template <DataLengthType kDataLengthType> class MutableData;
 
 /**
@@ -76,7 +105,7 @@
  *
  */
 template <DataLengthType kDataLengthType>
-class Data : public Clearable<Data<kDataLengthType>>, public Unequatable<Data<kDataLengthType>>
+class Data : public Clearable<Data<kDataLengthType>>, public Unequatable<Data<kDataLengthType>>, private DataUtils
 {
     friend class MutableData<kDataLengthType>;
 
@@ -177,6 +206,23 @@
     bool MatchesBytesIn(const void *aBuffer) const { return memcmp(mBuffer, aBuffer, mLength) == 0; }
 
     /**
+     * This method compares the `Data` content with the bytes from a given buffer using a given `Matcher` function.
+     *
+     * It is up to the caller to ensure that @p aBuffer has enough bytes to compare with the current data length.
+     *
+     * @param[in] aBuffer   A pointer to a buffer to compare with the data.
+     * @param[in] aMatcher  A `ByteMatcher` function to match the bytes. If `nullptr`, bytes are compared directly.
+     *
+     * @retval TRUE   The `Data` content matches the bytes in @p aBuffer.
+     * @retval FALSE  The `Data` content does not match the byes in @p aBuffer.
+     *
+     */
+    bool MatchesBytesIn(const void *aBuffer, ByteMatcher aMatcher)
+    {
+        return MatchBytes(mBuffer, static_cast<const uint8_t *>(aBuffer), mLength, aMatcher);
+    }
+
+    /**
      * This method overloads operator `==` to compare the `Data` content with the content from another one.
      *
      * @param[in] aOtherData   The other `Data` to compare with.
diff --git a/src/core/common/error.cpp b/src/core/common/error.cpp
index 5d4a92c..ec15c4a 100644
--- a/src/core/common/error.cpp
+++ b/src/core/common/error.cpp
@@ -33,6 +33,7 @@
 
 #include "error.hpp"
 
+#include "common/array.hpp"
 #include "common/code_utils.hpp"
 
 namespace ot {
@@ -80,7 +81,7 @@
         "Rejected",                   // (37) kErrorRejected
     };
 
-    return aError < OT_ARRAY_LENGTH(kErrorStrings) ? kErrorStrings[aError] : "UnknownErrorType";
+    return aError < GetArrayLength(kErrorStrings) ? kErrorStrings[aError] : "UnknownErrorType";
 }
 
 } // namespace ot
diff --git a/src/core/common/frame_builder.cpp b/src/core/common/frame_builder.cpp
new file mode 100644
index 0000000..6d95d1a
--- /dev/null
+++ b/src/core/common/frame_builder.cpp
@@ -0,0 +1,99 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file implements the `FrameBuilder` class.
+ */
+
+#include "frame_builder.hpp"
+
+namespace ot {
+
+void FrameBuilder::Init(void *aBuffer, uint16_t aLength)
+{
+    mBuffer    = static_cast<uint8_t *>(aBuffer);
+    mLength    = 0;
+    mMaxLength = aLength;
+}
+
+Error FrameBuilder::AppendUint8(uint8_t aUint8)
+{
+    return Append<uint8_t>(aUint8);
+}
+
+Error FrameBuilder::AppendBigEndianUint16(uint16_t aUint16)
+{
+    return Append<uint16_t>(Encoding::BigEndian::HostSwap16(aUint16));
+}
+
+Error FrameBuilder::AppendBigEndianUint32(uint32_t aUint32)
+{
+    return Append<uint32_t>(Encoding::BigEndian::HostSwap32(aUint32));
+}
+
+Error FrameBuilder::AppendLittleEndianUint16(uint16_t aUint16)
+{
+    return Append<uint16_t>(Encoding::LittleEndian::HostSwap16(aUint16));
+}
+
+Error FrameBuilder::AppendLittleEndianUint32(uint32_t aUint32)
+{
+    return Append<uint32_t>(Encoding::LittleEndian::HostSwap32(aUint32));
+}
+
+Error FrameBuilder::AppendBytes(const void *aBuffer, uint16_t aLength)
+{
+    Error error = kErrorNone;
+
+    VerifyOrExit(CanAppend(aLength), error = kErrorNoBufs);
+    memcpy(mBuffer + mLength, aBuffer, aLength);
+    mLength += aLength;
+
+exit:
+    return error;
+}
+
+Error FrameBuilder::AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength)
+{
+    Error error = kErrorNone;
+
+    VerifyOrExit(CanAppend(aLength), error = kErrorNoBufs);
+    SuccessOrExit(error = aMessage.Read(aOffset, mBuffer + mLength, aLength));
+    mLength += aLength;
+
+exit:
+    return error;
+}
+
+void FrameBuilder::WriteBytes(uint16_t aOffset, const void *aBuffer, uint16_t aLength)
+{
+    memcpy(mBuffer + aOffset, aBuffer, aLength);
+}
+
+} // namespace ot
diff --git a/src/core/common/frame_builder.hpp b/src/core/common/frame_builder.hpp
new file mode 100644
index 0000000..8115045
--- /dev/null
+++ b/src/core/common/frame_builder.hpp
@@ -0,0 +1,238 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *  This file defines OpenThread `FrameBuilder` class.
+ */
+
+#ifndef FRAME_BUILDER_HPP_
+#define FRAME_BUILDER_HPP_
+
+#include "openthread-core-config.h"
+
+#include "common/error.hpp"
+#include "common/message.hpp"
+#include "common/type_traits.hpp"
+
+namespace ot {
+
+/**
+ * The `FrameBuilder` can be used to construct frame content in a given data buffer.
+ *
+ */
+class FrameBuilder
+{
+public:
+    /**
+     * This method initializes the `FrameBuilder` to use a given buffer.
+     *
+     * `FrameBuilder` MUST be initialized before its other methods are used.
+     *
+     * @param[in] aBuffer   A pointer to a buffer.
+     * @param[in] aLength   The data length (number of bytes in @p aBuffer).
+     *
+     */
+    void Init(void *aBuffer, uint16_t aLength);
+
+    /**
+     * This method returns a pointer to the start of `FrameBuilder` buffer.
+     *
+     * @returns A pointer to the frame buffer.
+     *
+     */
+    const uint8_t *GetBytes(void) const { return mBuffer; }
+
+    /**
+     * This method returns the current length of frame (number of bytes appended so far).
+     *
+     * @returns The current frame length.
+     *
+     */
+    uint16_t GetLength(void) const { return mLength; }
+
+    /**
+     * This method returns the maximum length of frame.
+     *
+     * @returns The maximum frame length (max number of bytes in the frame buffer).
+     *
+     */
+    uint16_t GetMaxLength(void) const { return mMaxLength; }
+
+    /**
+     * This method indicates whether or not there are enough bytes remaining in the `FrameBuilder` buffer to append a
+     * given number of bytes.
+     *
+     * @param[in] aLength   The append length.
+     *
+     * @retval TRUE   There are enough remaining bytes to append @p aLength bytes.
+     * @retval FALSE  There are not enough remaining bytes to append @p aLength bytes.
+     *
+     */
+    bool CanAppend(uint16_t aLength) const { return (static_cast<uint32_t>(mLength) + aLength) <= mMaxLength; }
+
+    /**
+     * This method appends an `uint8_t` value to the `FrameBuilder`.
+     *
+     * @param[in] aUint8     The `uint8_t` value to append.
+     *
+     * @retval kErrorNone    Successfully appended the value.
+     * @retval kErrorNoBufs  Insufficient available buffers.
+     *
+     */
+    Error AppendUint8(uint8_t aUint8);
+
+    /**
+     * This method appends an `uint16_t` value assuming big endian encoding to the `FrameBuilder`.
+     *
+     * @param[in] aUint16    The `uint16_t` value to append.
+     *
+     * @retval kErrorNone    Successfully appended the value.
+     * @retval kErrorNoBufs  Insufficient available buffers.
+     *
+     */
+    Error AppendBigEndianUint16(uint16_t aUint16);
+
+    /**
+     * This method appends an `uint32_t` value assuming big endian encoding to the `FrameBuilder`.
+     *
+     * @param[in] aUint32    The `uint32_t` value to append.
+     *
+     * @retval kErrorNone    Successfully appended the value.
+     * @retval kErrorNoBufs  Insufficient available buffers.
+     *
+     */
+    Error AppendBigEndianUint32(uint32_t aUint32);
+
+    /**
+     * This method appends an `uint16_t` value assuming little endian encoding to the `FrameBuilder`.
+     *
+     * @param[in] aUint16    The `uint16_t` value to append.
+     *
+     * @retval kErrorNone    Successfully appended the value.
+     * @retval kErrorNoBufs  Insufficient available buffers.
+     *
+     */
+    Error AppendLittleEndianUint16(uint16_t aUint16);
+
+    /**
+     * This method appends an `uint32_t` value assuming little endian encoding to the `FrameBuilder`.
+     *
+     * @param[in] aUint32    The `uint32_t` value to append.
+     *
+     * @retval kErrorNone    Successfully appended the value.
+     * @retval kErrorNoBufs  Insufficient available buffers.
+     *
+     */
+    Error AppendLittleEndianUint32(uint32_t aUint32);
+
+    /**
+     * This method appends bytes from a given buffer to the `FrameBuilder`.
+     *
+     * @param[in] aBuffer    A pointer to a data bytes to append.
+     * @param[in] aLength    Number of bytes in @p aBuffer.
+     *
+     * @retval kErrorNone    Successfully appended the bytes.
+     * @retval kErrorNoBufs  Insufficient available buffers.
+     *
+     */
+    Error AppendBytes(const void *aBuffer, uint16_t aLength);
+
+    /**
+     * This method appends bytes read from a given message to the `FrameBuilder`.
+     *
+     * @param[in] aMessage   The message to read the bytes from.
+     * @param[in] aOffset    The offset in @p aMessage to start reading the bytes from.
+     * @param[in] aLength    Number of bytes to read from @p aMessage and append.
+     *
+     * @retval kErrorNone    Successfully appended the bytes.
+     * @retval kErrorNoBufs  Insufficient available buffers to append the requested @p aLength bytes.
+     * @retval kErrorParse   Not enough bytes in @p aMessage to read @p aLength bytes from @p aOffset.
+     *
+     */
+    Error AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
+
+    /**
+     * This method appends an object to the `FrameBuilder`.
+     *
+     * @tparam    ObjectType  The object type to append.
+     *
+     * @param[in] aObject     A reference to the object to append.
+     *
+     * @retval kErrorNone    Successfully appended the object.
+     * @retval kErrorNoBufs  Insufficient available buffers to append @p aObject.
+     *
+     */
+    template <typename ObjectType> Error Append(const ObjectType &aObject)
+    {
+        static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
+
+        return AppendBytes(&aObject, sizeof(ObjectType));
+    }
+
+    /**
+     * This method writes bytes in `FrameBuilder` at a given offset overwriting the previously appended content.
+     *
+     * This method does not perform any bound checks. The caller MUST ensure that the given data length fits within the
+     * previously appended content. Otherwise the behavior of this method is undefined.
+     *
+     * @param[in] aOffset    The offset to begin writing.
+     * @param[in] aBuffer    A pointer to a data buffer to write.
+     * @param[in] aLength    Number of bytes in @p aBuffer.
+     *
+     */
+    void WriteBytes(uint16_t aOffset, const void *aBuffer, uint16_t aLength);
+
+    /**
+     * This methods writes an object to the `FrameBuilder` at a given offset overwriting previously appended content.
+     *
+     * This method does not perform any bound checks. The caller MUST ensure the given data length fits within the
+     * previously appended content. Otherwise the behavior of this method is undefined.
+     *
+     * @tparam     ObjectType   The object type to write.
+     *
+     * @param[in]  aOffset      The offset to begin writing.
+     * @param[in]  aObject      A reference to the object to write.
+     *
+     */
+    template <typename ObjectType> void Write(uint16_t aOffset, const ObjectType &aObject)
+    {
+        static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
+
+        WriteBytes(aOffset, &aObject, sizeof(ObjectType));
+    }
+
+private:
+    uint8_t *mBuffer;
+    uint16_t mLength;
+    uint16_t mMaxLength;
+};
+
+} // namespace ot
+
+#endif // FRAME_BUILDER_HPP_
diff --git a/src/core/common/frame_data.cpp b/src/core/common/frame_data.cpp
new file mode 100644
index 0000000..7607041
--- /dev/null
+++ b/src/core/common/frame_data.cpp
@@ -0,0 +1,107 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes implementation of `FrameData`.
+ */
+
+#include "frame_data.hpp"
+
+#include "common/code_utils.hpp"
+#include "common/encoding.hpp"
+
+namespace ot {
+
+Error FrameData::ReadUint8(uint8_t &aUint8)
+{
+    return ReadBytes(&aUint8, sizeof(uint8_t));
+}
+
+Error FrameData::ReadBigEndianUint16(uint16_t &aUint16)
+{
+    Error error;
+
+    SuccessOrExit(error = ReadBytes(&aUint16, sizeof(uint16_t)));
+    aUint16 = Encoding::BigEndian::HostSwap16(aUint16);
+
+exit:
+    return error;
+}
+
+Error FrameData::ReadBigEndianUint32(uint32_t &aUint32)
+{
+    Error error;
+
+    SuccessOrExit(error = ReadBytes(&aUint32, sizeof(uint32_t)));
+    aUint32 = Encoding::BigEndian::HostSwap32(aUint32);
+
+exit:
+    return error;
+}
+
+Error FrameData::ReadLittleEndianUint16(uint16_t &aUint16)
+{
+    Error error;
+
+    SuccessOrExit(error = ReadBytes(&aUint16, sizeof(uint16_t)));
+    aUint16 = Encoding::LittleEndian::HostSwap16(aUint16);
+
+exit:
+    return error;
+}
+
+Error FrameData::ReadLittleEndianUint32(uint32_t &aUint32)
+{
+    Error error;
+
+    SuccessOrExit(error = ReadBytes(&aUint32, sizeof(uint32_t)));
+    aUint32 = Encoding::LittleEndian::HostSwap32(aUint32);
+
+exit:
+    return error;
+}
+
+Error FrameData::ReadBytes(void *aBuffer, uint16_t aLength)
+{
+    Error error = kErrorNone;
+
+    VerifyOrExit(CanRead(aLength), error = kErrorParse);
+    memcpy(aBuffer, GetBytes(), aLength);
+    SkipOver(aLength);
+
+exit:
+    return error;
+}
+
+void FrameData::SkipOver(uint16_t aLength)
+{
+    Init(GetBytes() + aLength, GetLength() - aLength);
+}
+
+} // namespace ot
diff --git a/src/core/common/frame_data.hpp b/src/core/common/frame_data.hpp
new file mode 100644
index 0000000..336a782
--- /dev/null
+++ b/src/core/common/frame_data.hpp
@@ -0,0 +1,177 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes definitions for `FrameData`.
+ */
+
+#ifndef FRAME_DATA_HPP_
+#define FRAME_DATA_HPP_
+
+#include "openthread-core-config.h"
+
+#include "common/data.hpp"
+#include "common/type_traits.hpp"
+
+namespace ot {
+
+/**
+ * This class represents a frame `Data` which is simply a wrapper over a pointer to a buffer with a given frame length.
+ *
+ * It provide helper method to parse the content. As data is parsed and read, the `FrameData` is updated to skip over
+ * the read content.
+ *
+ */
+class FrameData : public Data<kWithUint16Length>
+{
+public:
+    /**
+     * This method indicates whether or not there are enough bytes remaining in the `FrameData` to read a given number
+     * of bytes.
+     *
+     * @param[in] aLength   The read length to check.
+     *
+     * @retval TRUE   There are enough remaining bytes to read @p aLength bytes.
+     * @retval FALSE  There are not enough remaining bytes to read @p aLength bytes.
+     *
+     */
+    bool CanRead(uint16_t aLength) const { return GetLength() >= aLength; }
+
+    /**
+     * This method reads an `uint8_t` value from the `FrameData`.
+     *
+     * If read successfully, the `FrameData` is updated to skip over the read content.
+     *
+     * @param[out] aUint8   A reference to an `uint8_t` to return the read value.
+     *
+     * @retval kErrorNone   Successfully read `uint8_t` value and skipped over it.
+     * @retval kErrorParse  Not enough bytes remaining to read.
+     *
+     */
+    Error ReadUint8(uint8_t &aUint8);
+
+    /**
+     * This method reads an `uint16_t` value assuming big endian encoding from the `FrameData`.
+     *
+     * If read successfully, the `FrameData` is updated to skip over the read content.
+     *
+     * @param[out] aUint16   A reference to an `uint16_t` to return the read value.
+     *
+     * @retval kErrorNone   Successfully read `uint16_t` value and skipped over it.
+     * @retval kErrorParse  Not enough bytes remaining to read.
+     *
+     */
+    Error ReadBigEndianUint16(uint16_t &aUint16);
+
+    /**
+     * This method reads an `uint32_t` value assuming big endian encoding from the `FrameData`.
+     *
+     * If read successfully, the `FrameData` is updated to skip over the read content.
+     *
+     * @param[out] aUint32   A reference to an `uint32_t` to return the read value.
+     *
+     * @retval kErrorNone   Successfully read `uint32_t` value and skipped over it.
+     * @retval kErrorParse  Not enough bytes remaining to read.
+     *
+     */
+    Error ReadBigEndianUint32(uint32_t &aUint32);
+
+    /**
+     * This method reads an `uint16_t` value assuming little endian encoding from the `FrameData`.
+     *
+     * If read successfully, the `FrameData` is updated to skip over the read content.
+     *
+     * @param[out] aUint16   A reference to an `uint16_t` to return the read value.
+     *
+     * @retval kErrorNone   Successfully read `uint16_t` value and skipped over it.
+     * @retval kErrorParse  Not enough bytes remaining to read.
+     *
+     */
+    Error ReadLittleEndianUint16(uint16_t &aUint16);
+
+    /**
+     * This method reads an `uint32_t` value assuming little endian encoding from the `FrameData`.
+     *
+     * If read successfully, the `FrameData` is updated to skip over the read content.
+     *
+     * @param[out] aUint32   A reference to an `uint32_t` to return the read value.
+     *
+     * @retval kErrorNone   Successfully read `uint32_t` value and skipped over it.
+     * @retval kErrorParse  Not enough bytes remaining to read.
+     *
+     */
+    Error ReadLittleEndianUint32(uint32_t &aUint32);
+
+    /**
+     * This method reads a given number of bytes from the `FrameData`.
+     *
+     * If read successfully, the `FrameData` is updated to skip over the read content.
+     *
+     * @param[out] aBuffer   The buffer to copy the read bytes into.
+     * @param[in]  aLength   Number of bytes to read.
+     *
+     * @retval kErrorNone   Successfully read @p aLength bytes into @p aBuffer and skipped over them.
+     * @retval kErrorParse  Not enough bytes remaining to read @p aLength.
+     *
+     */
+    Error ReadBytes(void *aBuffer, uint16_t aLength);
+
+    /**
+     * This template method reads an object from the `FrameData`.
+     *
+     * @tparam     ObjectType   The object type to read from the message.
+     *
+     * @param[out] aObject      A reference to the object to read into.
+     *
+     * @retval kErrorNone     Successfully read @p aObject and skipped over the read content.
+     * @retval kErrorParse    Not enough bytes remaining to read the entire object.
+     *
+     */
+    template <typename ObjectType> Error Read(ObjectType &aObject)
+    {
+        static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
+
+        return ReadBytes(&aObject, sizeof(ObjectType));
+    }
+
+    /**
+     * This method skips over a given number of bytes from `FrameData`.
+     *
+     * The caller MUST make sure that the @p aLength is smaller than current data length. Otherwise the behavior of
+     * this method is undefined.
+     *
+     * @param[in] aLength   The length (number of bytes) to skip over.
+     *
+     */
+    void SkipOver(uint16_t aLength);
+};
+
+} // namespace ot
+
+#endif // FRAME_DATA_HPP_
diff --git a/src/core/api/entropy_api.cpp b/src/core/common/heap.cpp
similarity index 71%
rename from src/core/api/entropy_api.cpp
rename to src/core/common/heap.cpp
index 469e55d..77a171a 100644
--- a/src/core/api/entropy_api.cpp
+++ b/src/core/common/heap.cpp
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2019, The OpenThread Authors.
+ *  Copyright (c) 2021, The OpenThread Authors.
  *  All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -28,16 +28,41 @@
 
 /**
  * @file
- *   This file implements the OpenThread entropy source management API.
+ *   This file implements the `Heap` API.
  */
 
-#include <openthread/entropy.h>
+#include "heap.hpp"
 
-#include "common/random_manager.hpp"
+#include "common/instance.hpp"
 
-using namespace ot;
+namespace ot {
+namespace Heap {
 
-mbedtls_entropy_context *otEntropyMbedTlsContextGet(void)
+#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+
+void *CAlloc(size_t aCount, size_t aSize)
 {
-    return RandomManager::GetMbedTlsEntropyContext();
+    return otPlatCAlloc(aCount, aSize);
 }
+
+void Free(void *aPointer)
+{
+    otPlatFree(aPointer);
+}
+
+#else
+
+void *CAlloc(size_t aCount, size_t aSize)
+{
+    return Instance::GetHeap().CAlloc(aCount, aSize);
+}
+
+void Free(void *aPointer)
+{
+    Instance::GetHeap().Free(aPointer);
+}
+
+#endif // OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+
+} // namespace Heap
+} // namespace ot
diff --git a/include/openthread/entropy.h b/src/core/common/heap.hpp
similarity index 64%
copy from include/openthread/entropy.h
copy to src/core/common/heap.hpp
index bc07c30..529f6f2 100644
--- a/include/openthread/entropy.h
+++ b/src/core/common/heap.hpp
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2019, The OpenThread Authors.
+ *  Copyright (c) 2021, The OpenThread Authors.
  *  All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -28,43 +28,42 @@
 
 /**
  * @file
- * @brief
- *  This file defines the OpenThread entropy source API.
+ *   This file includes definitions for `Heap`.
  */
 
-#ifndef OPENTHREAD_ENTROPY_H_
-#define OPENTHREAD_ENTROPY_H_
+#ifndef HEAP_HPP_
+#define HEAP_HPP_
 
-#include <mbedtls/entropy.h>
+#include "openthread-core-config.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include <stddef.h>
+#include <string.h>
+
+namespace ot {
+namespace Heap {
 
 /**
- * @addtogroup api-entropy
+ * This function allocates memory from heap for an array of given number of object of certain size.
  *
- * @brief
- *   This module includes functions that manages entropy source.
+ * @param[in] aCount   Number of objects.
+ * @param[in] aSize    Size of each object.
  *
- * @{
+ * @returns A pointer to the allocated buffer or `nullptr` if fails to allocate.
  *
  */
+void *CAlloc(size_t aCount, size_t aSize);
 
 /**
- * This function returns initialized mbedtls_entropy_context.
+ * This function frees a previously heap allocated buffer.
  *
- * @returns  A pointer to initialized mbedtls_entropy_context.
- */
-mbedtls_entropy_context *otEntropyMbedTlsContextGet(void);
-
-/**
- * @}
+ * A heap allocated buffer MUST be freed only once.
+ *
+ * @param[in] aPointer   A pointer to the previously heap allocated buffer. Can be `nullptr` which does nothing.
  *
  */
+void Free(void *aPointer);
 
-#ifdef __cplusplus
-} // extern "C"
-#endif
+} // namespace Heap
+} // namespace ot
 
-#endif // OPENTHREAD_ENTROPY_H_
+#endif // HEAP_HPP_
diff --git a/src/core/common/heap_allocatable.hpp b/src/core/common/heap_allocatable.hpp
new file mode 100644
index 0000000..1b88016
--- /dev/null
+++ b/src/core/common/heap_allocatable.hpp
@@ -0,0 +1,134 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes definitions for `Heap::Allocatable`.
+ */
+
+#ifndef HEAP_ALLOCATABLE_HPP_
+#define HEAP_ALLOCATABLE_HPP_
+
+#include "openthread-core-config.h"
+
+#include "common/code_utils.hpp"
+#include "common/error.hpp"
+#include "common/heap.hpp"
+#include "common/new.hpp"
+
+namespace ot {
+namespace Heap {
+
+/**
+ * This template class defines a `Heap::Allocatable` object.
+ *
+ * `Heap::Allocatable` provides methods to allocate and free instances of `Type` on heap.
+ *
+ * Users of this class should follow CRTP-style inheritance, i.e., the `Type` class itself should inherit from
+ * `Allocatable<Type>`.
+ *
+ * The `Type` class destructor is used when `Free()` is called. The destructor frees any heap allocated data members
+ * that are stored in a `Type` instance (e.g., `Heap::String`, `Heap::Data`, etc).
+ *
+ */
+template <class Type> class Allocatable
+{
+public:
+    /**
+     * This static method allocates a new instance of `Type` on heap and initializes it using `Type` constructor.
+     *
+     * The `Type` class MUST have a constructor `Type(Args...)` which is invoked upon allocation of new `Type` to
+     * initialize it.
+     *
+     * @param[in] aArgs   A set of arguments to pass to the `Type` constructor of the allocated `Type` instance.
+     *
+     * @returns A pointer to the newly allocated instance or `nullptr` if it fails to allocate.
+     *
+     */
+    template <typename... Args> static Type *Allocate(Args &&... aArgs)
+    {
+        void *buf = Heap::CAlloc(1, sizeof(Type));
+
+        return (buf != nullptr) ? new (buf) Type(static_cast<Args &&>(aArgs)...) : nullptr;
+    }
+
+    /**
+     * This static method allocates a new instance of `Type` on heap and initializes it using `Type::Init()` method.
+     *
+     * The `Type` class MUST have a default constructor (with no arguments) which is invoked upon allocation of new
+     * `Type` instance. It MUST also provide an `Error Init(Args...)` method to initialize the instance. If any `Error`
+     * other than `kErrorNone` is returned the initialization is considered failed.
+     *
+     * @param[in] aArgs   A set of arguments to initialize the allocated `Type` instance.
+     *
+     * @returns A pointer to the newly allocated instance or `nullptr` if it fails to allocate or initialize.
+     *
+     */
+    template <typename... Args> static Type *AllocateAndInit(Args &&... aArgs)
+    {
+        void *buf    = Heap::CAlloc(1, sizeof(Type));
+        Type *object = nullptr;
+
+        VerifyOrExit(buf != nullptr);
+
+        object = new (buf) Type();
+
+        if (object->Init(static_cast<Args &&>(aArgs)...) != kErrorNone)
+        {
+            object->Free();
+            object = nullptr;
+        }
+
+    exit:
+        return object;
+    }
+
+    /**
+     * This method frees the `Type` instance.
+     *
+     * The instance MUST be heap allocated using either `Allocate()` or `AllocateAndInit()`.
+     *
+     * The `Free()` method invokes the `Type` destructor before releasing the allocated heap buffer for the instance.
+     * This ensures that any heap allocated member variables in `Type` are freed before the `Type` instance itself is
+     * freed.
+     *
+     */
+    void Free(void)
+    {
+        static_cast<Type *>(this)->~Type();
+        Heap::Free(this);
+    }
+
+protected:
+    Allocatable(void) = default;
+};
+
+} // namespace Heap
+} // namespace ot
+
+#endif // HEAP_ALLOCATABLE_HPP_
diff --git a/src/core/common/heap_array.hpp b/src/core/common/heap_array.hpp
new file mode 100644
index 0000000..a4ede90
--- /dev/null
+++ b/src/core/common/heap_array.hpp
@@ -0,0 +1,549 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes definitions for `Heap::Array` (a heap allocated array of flexible length).
+ */
+
+#ifndef HEAP_ARRAY_HPP_
+#define HEAP_ARRAY_HPP_
+
+#include "openthread-core-config.h"
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include "common/array.hpp"
+#include "common/code_utils.hpp"
+#include "common/error.hpp"
+#include "common/heap.hpp"
+#include "common/new.hpp"
+
+namespace ot {
+namespace Heap {
+
+/**
+ * This class represents a heap allocated array.
+ *
+ * The buffer to store the elements is allocated from heap and is managed by the `Heap::Array` class itself. The `Array`
+ * implementation will automatically grow the buffer when new entries are added. The `Heap::Array` destructor will
+ * always free the allocated buffer.
+ *
+ * The `Type` class MUST provide a move constructor `Type(Type &&aOther)` (or a copy constructor if no move constructor
+ * is provided). This constructor is used to move existing elements when array buffer is grown (new buffer is
+ * allocated) to make room for new elements.
+ *
+ * @tparam  Type                  The array element type.
+ * @tparam  kCapacityIncrements   Number of elements to allocate at a time when updating the array buffer.
+ *
+ */
+template <typename Type, uint16_t kCapacityIncrements = 2> class Array
+{
+public:
+    using IndexType = uint16_t;
+
+    /**
+     * This constructor initializes the `Array` as empty.
+     *
+     */
+    Array(void)
+        : mArray(nullptr)
+        , mLength(0)
+        , mCapacity(0)
+    {
+    }
+
+    /**
+     * This is the destructor for `Array` object.
+     *
+     */
+    ~Array(void) { Free(); }
+
+    /**
+     * This method frees any buffer allocated by the `Array`.
+     *
+     * The `Array` destructor will automatically call `Free()`. This method allows caller to free buffer explicitly.
+     *
+     */
+    void Free(void)
+    {
+        Clear();
+        Heap::Free(mArray);
+        mArray    = nullptr;
+        mCapacity = 0;
+    }
+
+    /**
+     * This method clears the array.
+     *
+     * Note that `Clear()` method (unlike `Free()`) does not free the allocated buffer and therefore does not change
+     * the current capacity of the array.
+     *
+     * This method invokes `Type` destructor on all cleared existing elements of array.
+     *
+     */
+    void Clear(void)
+    {
+        for (Type &entry : *this)
+        {
+            entry.~Type();
+        }
+
+        mLength = 0;
+    }
+
+    /**
+     * This method returns the current array length (number of elements in the array).
+     *
+     * @returns The array length.
+     *
+     */
+    IndexType GetLength(void) const { return mLength; }
+
+    /**
+     * This method returns a raw pointer to the array buffer.
+     *
+     * The returned raw pointer is valid only while the `Array` remains unchanged.
+     *
+     * @returns A pointer to the array buffer or `nullptr` if the array is empty.
+     *
+     */
+    const Type *AsCArray(void) const { return (mLength != 0) ? mArray : nullptr; }
+
+    /**
+     * This method returns the current capacity of array (number of elements that can fit in current allocated buffer).
+     *
+     * The allocated buffer and array capacity are automatically increased (by the `Array` itself) when new elements
+     * are added to array. Removing elements does not change the buffer and the capacity. A desired capacity can be
+     * reserved using `ReserveCapacity()` method.
+     *
+     * @returns The current capacity of the array.
+     *
+     */
+    IndexType GetCapacity(void) const { return mCapacity; }
+
+    /**
+     * This method allocates buffer to reserve a given capacity for array.
+     *
+     * If the requested @p aCapacity is smaller than the current length of the array, capacity remains unchanged.
+     *
+     * @param[in] aCapacity   The target capacity for the array.
+     *
+     * @retval kErrorNone     Array was successfully updated to support @p aCapacity.
+     * @retval kErrorNoBufs   Could not allocate buffer.
+     *
+     */
+    Error ReserveCapacity(IndexType aCapacity) { return Allocate(aCapacity); }
+
+    /**
+     * This method sets the array by taking the buffer from another given array (using move semantics).
+     *
+     * @param[in] aOther    The other `Heap::Array` to take from (rvalue reference).
+     *
+     */
+    void TakeFrom(Array &&aOther)
+    {
+        Free();
+        mArray           = aOther.mArray;
+        mLength          = aOther.mLength;
+        mCapacity        = aOther.mCapacity;
+        aOther.mArray    = nullptr;
+        aOther.mLength   = 0;
+        aOther.mCapacity = 0;
+    }
+
+    /**
+     * This method overloads the `[]` operator to get the element at a given index.
+     *
+     * This method does not perform index bounds checking. Behavior is undefined if @p aIndex is not valid.
+     *
+     * @param[in] aIndex  The index to get.
+     *
+     * @returns A reference to the element in array at @p aIndex.
+     *
+     */
+    Type &operator[](IndexType aIndex) { return mArray[aIndex]; }
+
+    /**
+     * This method overloads the `[]` operator to get the element at a given index.
+     *
+     * This method does not perform index bounds checking. Behavior is undefined if @p aIndex is not valid.
+     *
+     * @param[in] aIndex  The index to get.
+     *
+     * @returns A reference to the element in array at @p aIndex.
+     *
+     */
+    const Type &operator[](IndexType aIndex) const { return mArray[aIndex]; }
+
+    /**
+     * This method gets a pointer to the element at a given index.
+     *
+     * Unlike `operator[]`, this method checks @p aIndex to be valid and within the current length. The returned
+     * pointer is valid only while the `Array` remains unchanged.
+     *
+     * @param[in] aIndex  The index to get.
+     *
+     * @returns A pointer to element in array at @p aIndex or `nullptr` if @p aIndex is not valid.
+     *
+     */
+    Type *At(IndexType aIndex) { return (aIndex < mLength) ? &mArray[aIndex] : nullptr; }
+
+    /**
+     * This method gets a pointer to the element at a given index.
+     *
+     * Unlike `operator[]`, this method checks @p aIndex to be valid and within the current length. The returned
+     * pointer is valid only while the `Array` remains unchanged.
+     *
+     * @param[in] aIndex  The index to get.
+     *
+     * @returns A pointer to element in array at @p aIndex or `nullptr` if @p aIndex is not valid.
+     *
+     */
+    const Type *At(IndexType aIndex) const { return (aIndex < mLength) ? &mArray[aIndex] : nullptr; }
+
+    /**
+     * This method gets a pointer to the element at the front of the array (first element).
+     *
+     * The returned pointer is valid only while the `Array` remains unchanged.
+     *
+     * @returns A pointer to the front element or `nullptr` if array is empty.
+     *
+     */
+    Type *Front(void) { return At(0); }
+
+    /**
+     * This method gets a pointer to the element at the front of the array (first element).
+     *
+     * The returned pointer is valid only while the `Array` remains unchanged.
+     *
+     * @returns A pointer to the front element or `nullptr` if array is empty.
+     *
+     */
+    const Type *Front(void) const { return At(0); }
+
+    /**
+     * This method gets a pointer to the element at the back of the array (last element).
+     *
+     * The returned pointer is valid only while the `Array` remains unchanged.
+     *
+     * @returns A pointer to the back element or `nullptr` if array is empty.
+     *
+     */
+    Type *Back(void) { return (mLength > 0) ? &mArray[mLength - 1] : nullptr; }
+
+    /**
+     * This method gets a pointer to the element at the back of the array (last element).
+     *
+     * The returned pointer is valid only while the `Array` remains unchanged.
+     *
+     * @returns A pointer to the back element or `nullptr` if array is empty.
+     *
+     */
+    const Type *Back(void) const { return (mLength > 0) ? &mArray[mLength - 1] : nullptr; }
+
+    /**
+     * This method appends a new entry to the end of the array.
+     *
+     * This method requires the `Type` to provide a copy constructor of format `Type(const Type &aOther)` to init the
+     * new element in the array from @p aEntry.
+     *
+     * @param[in] aEntry     The new entry to push back.
+     *
+     * @retval kErrorNone    Successfully pushed back @p aEntry to the end of the array.
+     * @retval kErrorNoBufs  Could not allocate buffer to grow the array.
+     *
+     */
+    Error PushBack(const Type &aEntry)
+    {
+        Error error = kErrorNone;
+
+        if (mLength == mCapacity)
+        {
+            SuccessOrExit(error = Allocate(mCapacity + kCapacityIncrements));
+        }
+
+        new (&mArray[mLength++]) Type(aEntry);
+
+    exit:
+        return error;
+    }
+
+    /**
+     * This method appends a new entry to the end of the array.
+     *
+     * This method requires the `Type` to provide a copy constructor of format `Type(Type &&aOther)` to init the
+     * new element in the array from @p aEntry.
+     *
+     * @param[in] aEntry     The new entry to push back (an rvalue reference)
+     *
+     * @retval kErrorNone    Successfully pushed back @p aEntry to the end of the array.
+     * @retval kErrorNoBufs  Could not allocate buffer to grow the array.
+     *
+     */
+    Error PushBack(Type &&aEntry)
+    {
+        Error error = kErrorNone;
+
+        if (mLength == mCapacity)
+        {
+            SuccessOrExit(error = Allocate(mCapacity + kCapacityIncrements));
+        }
+
+        new (&mArray[mLength++]) Type(static_cast<Type &&>(aEntry));
+
+    exit:
+        return error;
+    }
+
+    /**
+     * This method appends a new entry to the end of the array.
+     *
+     * On success, this method returns a pointer to the newly appended element in the array for the caller to
+     * initialize and use. This method uses the `Type(void)` default constructor on the newly appended element (if not
+     * `nullptr`).
+     *
+     * The returned pointer is valid only while the `Array` remains unchanged.
+     *
+     * @return A pointer to the newly appended element or `nullptr` if could not allocate buffer to grow the array
+     *
+     */
+    Type *PushBack(void)
+    {
+        Type *newEntry = nullptr;
+
+        if (mLength == mCapacity)
+        {
+            SuccessOrExit(Allocate(mCapacity + kCapacityIncrements));
+        }
+
+        newEntry = new (&mArray[mLength++]) Type();
+
+    exit:
+        return newEntry;
+    }
+
+    /**
+     * This method removes the last element in the array.
+     *
+     * This method will invoke the `Type` destructor on the removed element.
+     *
+     */
+    void PopBack(void)
+    {
+        if (mLength > 0)
+        {
+            mArray[mLength - 1].~Type();
+            mLength--;
+        }
+    }
+
+    /**
+     * This method returns the index of an element in the array.
+     *
+     * The @p aElement MUST be from the array, otherwise the behavior of this method is undefined.
+     *
+     * @param[in] aElement  A reference to an element in the array.
+     *
+     * @returns The index of @p aElement in the array.
+     *
+     */
+    IndexType IndexOf(const Type &aElement) const { return static_cast<IndexType>(&aElement - mArray); }
+
+    /**
+     * This method finds the first match of a given entry in the array.
+     *
+     * This method uses `==` operator on `Type` to compare the array element with @p aEntry. The returned pointer is
+     * valid only while the `Array` remains unchanged.
+     *
+     * @param[in] aEntry   The entry to search for within the array.
+     *
+     * @returns A pointer to matched array element, or `nullptr` if a match could not be found.
+     *
+     */
+    Type *Find(const Type &aEntry) { return AsNonConst(AsConst(this)->Find(aEntry)); }
+
+    /**
+     * This method finds the first match of a given entry in the array.
+     *
+     * This method uses `==` operator to compare the array elements with @p aEntry. The returned pointer is valid only
+     * while the `Array` remains unchanged.
+     *
+     * @param[in] aEntry   The entry to search for within the array.
+     *
+     * @returns A pointer to matched array element, or `nullptr` if a match could not be found.
+     *
+     */
+    const Type *Find(const Type &aEntry) const
+    {
+        const Type *matched = nullptr;
+
+        for (const Type &element : *this)
+        {
+            if (element == aEntry)
+            {
+                matched = &element;
+                break;
+            }
+        }
+
+        return matched;
+    }
+
+    /**
+     * This method indicates whether or not a match to given entry exists in the array.
+     *
+     * This method uses `==` operator on `Type` to compare the array elements with @p aEntry.
+     *
+     * @param[in] aEntry   The entry to search for within the array.
+     *
+     * @retval TRUE   The array contains a matching element with @p aEntry.
+     * @retval FALSE  The array does not contain a matching element with @p aEntry.
+     *
+     */
+    bool Contains(const Type &aEntry) const { return Find(aEntry) != nullptr; }
+
+    /**
+     * This template method finds the first element in the array matching a given indicator.
+     *
+     * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against elements
+     * in the array. To check that an element matches the given indicator, the `Matches()` method is invoked on each
+     * `Type` element in the array. The `Matches()` method should be provided by `Type` class accordingly:
+     *
+     *     bool Type::Matches(const Indicator &aIndicator) const
+     *
+     * The returned pointer is valid only while the `Array` remains unchanged.
+     *
+     * @param[in]  aIndicator  An indicator to match with elements in the array.
+     *
+     * @returns A pointer to the matched array element, or `nullptr` if a match could not be found.
+     *
+     */
+    template <typename Indicator> Type *FindMatching(const Indicator &aIndicator)
+    {
+        return AsNonConst(AsConst(this)->FindMatching(aIndicator));
+    }
+
+    /**
+     * This template method finds the first element in the array matching a given indicator.
+     *
+     * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against elements
+     * in the array. To check that an element matches the given indicator, the `Matches()` method is invoked on each
+     * `Type` element in the array. The `Matches()` method should be provided by `Type` class accordingly:
+     *
+     *     bool Type::Matches(const Indicator &aIndicator) const
+     *
+     * The returned pointer is valid only while the `Array` remains unchanged.
+     *
+     * @param[in]  aIndicator  An indicator to match with elements in the array.
+     *
+     * @returns A pointer to the matched array element, or `nullptr` if a match could not be found.
+     *
+     */
+    template <typename Indicator> const Type *FindMatching(const Indicator &aIndicator) const
+    {
+        const Type *matched = nullptr;
+
+        for (const Type &element : *this)
+        {
+            if (element.Matches(aIndicator))
+            {
+                matched = &element;
+                break;
+            }
+        }
+
+        return matched;
+    }
+
+    /**
+     * This template method indicates whether or not the array contains an element matching a given indicator.
+     *
+     * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against elements
+     * in the array. To check that an element matches the given indicator, the `Matches()` method is invoked on each
+     * `Type` element in the array. The `Matches()` method should be provided by `Type` class accordingly:
+     *
+     *     bool Type::Matches(const Indicator &aIndicator) const
+     *
+     * @param[in]  aIndicator  An indicator to match with elements in the array.
+     *
+     * @retval TRUE   The array contains a matching element with @p aIndicator.
+     * @retval FALSE  The array does not contain a matching element with @p aIndicator.
+     *
+     */
+    template <typename Indicator> bool ContainsMatching(const Indicator &aIndicator) const
+    {
+        return FindMatching(aIndicator) != nullptr;
+    }
+
+    // The following methods are intended to support range-based `for`
+    // loop iteration over the array elements and should not be used
+    // directly.
+
+    Type *      begin(void) { return (mLength > 0) ? mArray : nullptr; }
+    Type *      end(void) { return (mLength > 0) ? &mArray[mLength] : nullptr; }
+    const Type *begin(void) const { return (mLength > 0) ? mArray : nullptr; }
+    const Type *end(void) const { return (mLength > 0) ? &mArray[mLength] : nullptr; }
+
+    Array(const Array &) = delete;
+    Array &operator=(const Array &) = delete;
+
+private:
+    Error Allocate(IndexType aCapacity)
+    {
+        Error error = kErrorNone;
+        Type *newArray;
+
+        VerifyOrExit((aCapacity != mCapacity) && (aCapacity >= mLength));
+        newArray = static_cast<Type *>(Heap::CAlloc(aCapacity, sizeof(Type)));
+        VerifyOrExit(newArray != nullptr, error = kErrorNoBufs);
+
+        for (IndexType index = 0; index < mLength; index++)
+        {
+            new (&newArray[index]) Type(static_cast<Type &&>(mArray[index]));
+            mArray[index].~Type();
+        }
+
+        Heap::Free(mArray);
+        mArray    = newArray;
+        mCapacity = aCapacity;
+
+    exit:
+        return error;
+    }
+
+    Type *    mArray;
+    IndexType mLength;
+    IndexType mCapacity;
+};
+
+} // namespace Heap
+} // namespace ot
+
+#endif // HEAP_ARRAY_HPP_
diff --git a/src/core/common/heap_data.cpp b/src/core/common/heap_data.cpp
new file mode 100644
index 0000000..d12686e
--- /dev/null
+++ b/src/core/common/heap_data.cpp
@@ -0,0 +1,118 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file implements the `Heap::Data` (a heap allocated data).
+ */
+
+#include "heap_data.hpp"
+
+#include "common/code_utils.hpp"
+#include "common/debug.hpp"
+
+namespace ot {
+namespace Heap {
+
+Error Data::SetFrom(const uint8_t *aBuffer, uint16_t aLength)
+{
+    Error error;
+
+    SuccessOrExit(error = UpdateBuffer(aLength));
+    VerifyOrExit(aLength != 0);
+
+    SuccessOrAssert(mData.CopyBytesFrom(aBuffer, aLength));
+
+exit:
+    return error;
+}
+
+Error Data::SetFrom(const Message &aMessage)
+{
+    return SetFrom(aMessage, aMessage.GetOffset(), aMessage.GetLength() - aMessage.GetOffset());
+}
+
+Error Data::SetFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength)
+{
+    Error error;
+
+    VerifyOrExit(aOffset + aLength <= aMessage.GetLength(), error = kErrorParse);
+
+    SuccessOrExit(error = UpdateBuffer(aLength));
+    VerifyOrExit(aLength != 0);
+
+    SuccessOrAssert(aMessage.Read(aOffset, mData.GetBytes(), aLength));
+
+exit:
+    return error;
+}
+
+void Data::SetFrom(Data &&aData)
+{
+    Free();
+    TakeFrom(aData);
+}
+
+void Data::Free(void)
+{
+    Heap::Free(mData.GetBytes());
+    mData.Init(nullptr, 0);
+}
+
+Error Data::UpdateBuffer(uint16_t aNewLength)
+{
+    Error error = kErrorNone;
+
+    VerifyOrExit(aNewLength != mData.GetLength());
+
+    Heap::Free(mData.GetBytes());
+
+    if (aNewLength == 0)
+    {
+        mData.Init(nullptr, 0);
+    }
+    else
+    {
+        uint8_t *newBuffer = static_cast<uint8_t *>(Heap::CAlloc(aNewLength, sizeof(uint8_t)));
+
+        VerifyOrExit(newBuffer != nullptr, error = kErrorNoBufs);
+        mData.Init(newBuffer, aNewLength);
+    }
+
+exit:
+    return error;
+}
+
+void Data::TakeFrom(Data &aData)
+{
+    mData.Init(aData.mData.GetBytes(), aData.GetLength());
+    aData.mData.Init(nullptr, 0);
+}
+
+} // namespace Heap
+} // namespace ot
diff --git a/src/core/common/heap_data.hpp b/src/core/common/heap_data.hpp
new file mode 100644
index 0000000..041f539
--- /dev/null
+++ b/src/core/common/heap_data.hpp
@@ -0,0 +1,194 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes definitions for `Heap::Data` (heap allocated data).
+ */
+
+#ifndef HEAP_DATA_HPP_
+#define HEAP_DATA_HPP_
+
+#include "openthread-core-config.h"
+
+#include "common/data.hpp"
+#include "common/heap.hpp"
+#include "common/message.hpp"
+
+namespace ot {
+namespace Heap {
+
+/**
+ * This class represents a heap allocated data.
+ *
+ */
+class Data
+{
+public:
+    /**
+     * This constructor initializes the `Heap::Data` as empty.
+     *
+     */
+    Data(void) { mData.Init(nullptr, 0); }
+
+    /**
+     * This is the move constructor for `Heap::Data`.
+     *
+     * `Heap::Data` is non-copyable (copy constructor is deleted) but move constructor is provided to allow it to to be
+     * used as return type (return by value) from functions/methods (which will then use move semantics).
+     *
+     * @param[in] aData   An rvalue reference to another `Heap::Data` to move from.
+     *
+     */
+    Data(Data &&aData) { TakeFrom(aData); }
+
+    /**
+     * This is the destructor for `Heap::Data` object.
+     *
+     */
+    ~Data(void) { Free(); }
+
+    /**
+     * This method indicates whether or not the `Heap::Data` is null (i.e., it was never successfully set or it was
+     * freed).
+     *
+     * @retval TRUE  The `Heap::Data` is null.
+     * @retval FALSE The `Heap::Data` is not null.
+     *
+     */
+    bool IsNull(void) const { return (mData.GetBytes() == nullptr); }
+
+    /**
+     * This method returns a pointer to the `Heap::Data` bytes buffer.
+     *
+     * @returns A pointer to data buffer or `nullptr` if the `Heap::Data` is null (never set or freed).
+     *
+     */
+    const uint8_t *GetBytes(void) const { return mData.GetBytes(); }
+
+    /**
+     * This method returns the `Heap::Data` length.
+     *
+     * @returns The data length (number of bytes) or zero if the `HeadpData` is null.
+     *
+     */
+    uint16_t GetLength(void) const { return mData.GetLength(); }
+
+    /**
+     * This method sets the `Heap::Data` from the content of a given buffer.
+     *
+     * @param[in] aBuffer     The buffer to copy bytes from.
+     * @param[in] aLength     The buffer length (number of bytes).
+     *
+     * @retval kErrorNone     Successfully set the `Heap::Data`.
+     * @retval kErrorNoBufs   Failed to allocate buffer.
+     *
+     */
+    Error SetFrom(const uint8_t *aBuffer, uint16_t aLength);
+
+    /**
+     * This method sets the `Heap::Data` from the content of a given message.
+     *
+     * The bytes are copied from current offset in @p aMessage till the end of the message.
+     *
+     * @param[in] aMessage    The message to copy bytes from (starting from offset till the end of message).
+     *
+     * @retval kErrorNone     Successfully set the `Heap::Data`.
+     * @retval kErrorNoBufs   Failed to allocate buffer.
+     *
+     */
+    Error SetFrom(const Message &aMessage);
+
+    /**
+     * This method sets the `Heap::Data` from the content of a given message read at a given offset up to a given
+     * length.
+     *
+     * @param[in] aMessage    The message to read and copy bytes from.
+     * @param[in] aOffset     The offset into the message to start reading the bytes from.
+     * @param[in] aLength     The number of bytes to read from message. If @p aMessage contains fewer bytes than
+     *                        requested, then `Heap::Data` is cleared and this method returns `kErrorParse`.
+     *
+     * @retval kErrorNone     Successfully set the `Heap::Data`.
+     * @retval kErrorNoBufs   Failed to allocate buffer.
+     * @retval kErrorParse    Not enough bytes in @p aMessage to read the requested @p aLength bytes.
+     *
+     */
+    Error SetFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
+
+    /**
+     * This method sets the `Heap::Data` from another one (move semantics).
+     *
+     * @param[in] aData   The other `Heap::Data` to set from (rvalue reference).
+     *
+     */
+    void SetFrom(Data &&aData);
+
+    /**
+     * This method appends the bytes from `Heap::Data` to a given message.
+     *
+     * @param[in] aMessage   The message to append the bytes into.
+     *
+     * @retval kErrorNone     Successfully copied the bytes from `Heap::Data` into @p aMessage.
+     * @retval kErrorNoBufs   Failed to allocate buffer.
+     *
+     */
+    Error CopyBytesTo(Message &aMessage) const { return aMessage.AppendBytes(mData.GetBytes(), mData.GetLength()); }
+
+    /**
+     * This method copies the bytes from `Heap::Data` into a given buffer.
+     *
+     * It is up to the caller to ensure that @p aBuffer has enough space for the current data length.
+     *
+     * @param[in] aBuffer     A pointer to buffer to copy the bytes into.
+     *
+     */
+    void CopyBytesTo(uint8_t *aBuffer) const { return mData.CopyBytesTo(aBuffer); }
+
+    /**
+     * This method frees any buffer allocated by the `Heap::Data`.
+     *
+     * The `Heap::Data` destructor will automatically call `Free()`. This method allows caller to free the buffer
+     * explicitly.
+     *
+     */
+    void Free(void);
+
+    Data(const Data &) = delete;
+    Data &operator=(const Data &) = delete;
+
+private:
+    Error UpdateBuffer(uint16_t aNewLength);
+    void  TakeFrom(Data &aData);
+
+    MutableData<kWithUint16Length> mData;
+};
+
+} // namespace Heap
+} // namespace ot
+
+#endif // HEAP_DATA_HPP_
diff --git a/src/core/common/heap_string.cpp b/src/core/common/heap_string.cpp
index 4806f61..060bfa2 100644
--- a/src/core/common/heap_string.cpp
+++ b/src/core/common/heap_string.cpp
@@ -28,18 +28,18 @@
 
 /**
  * @file
- *   This file implements the `HeapString` (a heap allocated string).
+ *   This file implements the `Heap::String` (a heap allocated string).
  */
 
 #include "heap_string.hpp"
 
 #include "common/code_utils.hpp"
-#include "common/instance.hpp"
 #include "common/string.hpp"
 
 namespace ot {
+namespace Heap {
 
-Error HeapString::Set(const char *aCString)
+Error String::Set(const char *aCString)
 {
     Error  error = kErrorNone;
     size_t curSize;
@@ -52,11 +52,11 @@
 
     if (curSize != newSize)
     {
-        char *newBuffer = static_cast<char *>(Instance::HeapCAlloc(sizeof(char), newSize));
+        char *newBuffer = static_cast<char *>(Heap::CAlloc(sizeof(char), newSize));
 
         VerifyOrExit(newBuffer != nullptr, error = kErrorNoBufs);
 
-        Instance::HeapFree(mStringBuffer);
+        Heap::Free(mStringBuffer);
         mStringBuffer = newBuffer;
     }
 
@@ -66,11 +66,11 @@
     return error;
 }
 
-Error HeapString::Set(HeapString &&aString)
+Error String::Set(String &&aString)
 {
     VerifyOrExit(mStringBuffer != aString.mStringBuffer);
 
-    Instance::HeapFree(mStringBuffer);
+    Heap::Free(mStringBuffer);
     mStringBuffer         = aString.mStringBuffer;
     aString.mStringBuffer = nullptr;
 
@@ -78,13 +78,13 @@
     return kErrorNone;
 }
 
-void HeapString::Free(void)
+void String::Free(void)
 {
-    Instance::HeapFree(mStringBuffer);
+    Heap::Free(mStringBuffer);
     mStringBuffer = nullptr;
 }
 
-bool HeapString::operator==(const char *aCString) const
+bool String::operator==(const char *aCString) const
 {
     bool isEqual;
 
@@ -95,4 +95,5 @@
     return isEqual;
 }
 
+} // namespace Heap
 } // namespace ot
diff --git a/src/core/common/heap_string.hpp b/src/core/common/heap_string.hpp
index 7d1ecfa..c9a27fd 100644
--- a/src/core/common/heap_string.hpp
+++ b/src/core/common/heap_string.hpp
@@ -28,7 +28,7 @@
 
 /**
  * @file
- *   This file includes definitions for `HeapString` (a heap allocated string).
+ *   This file includes definitions for `Heap::String` (a heap allocated string).
  */
 
 #ifndef HEAP_STRING_HPP_
@@ -38,37 +38,39 @@
 
 #include "common/equatable.hpp"
 #include "common/error.hpp"
+#include "common/heap.hpp"
 
 namespace ot {
+namespace Heap {
 
 /**
  * This class represents a heap allocated string.
  *
- * The buffer to store the string is allocated from heap and is manged by the `HeapString` class itself, e.g., it may
- * be reused and/or freed and reallocated when the string is set. The `HeapString` destructor will always free the
+ * The buffer to store the string is allocated from heap and is manged by the `Heap::String` class itself, e.g., it may
+ * be reused and/or freed and reallocated when the string is set. The `Heap::String` destructor will always free the
  * allocated buffer.
  *
  */
-class HeapString : public Unequatable<HeapString>
+class String : public Unequatable<String>
 {
 public:
     /**
-     * This constructor initializes the `HeapString` as null (or empty).
+     * This constructor initializes the `String` as null (or empty).
      *
      */
-    HeapString(void)
+    String(void)
         : mStringBuffer(nullptr)
     {
     }
 
     /**
-     * This is the move constructor for `HeapString`.
+     * This is the move constructor for `String`.
      *
-     * `HeapString` is non-copyable (copy constructor is deleted) but move constructor is provided to allow it to to be
+     * `String` is non-copyable (copy constructor is deleted) but move constructor is provided to allow it to to be
      * used as return type (return by value) from functions/methods (which will then use move semantics).
      *
      */
-    HeapString(HeapString &&aString)
+    String(String &&aString)
         : mStringBuffer(aString.mStringBuffer)
     {
         aString.mStringBuffer = nullptr;
@@ -78,22 +80,22 @@
      * This is the destructor for `HealString` object
      *
      */
-    ~HeapString(void) { Free(); }
+    ~String(void) { Free(); }
 
     /**
-     * This method indicates whether or not the `HeapString` is null (i.e., it was never successfully set or it was
+     * This method indicates whether or not the `String` is null (i.e., it was never successfully set or it was
      * freed).
      *
-     * @retval TRUE  The `HeapString` is null.
-     * @retval FALSE The `HeapString` is not null.
+     * @retval TRUE  The `String` is null.
+     * @retval FALSE The `String` is not null.
      *
      */
     bool IsNull(void) const { return (mStringBuffer == nullptr); }
 
     /**
-     * This method returns the `HeapString` as a C string.
+     * This method returns the `String` as a C string.
      *
-     * @returns A pointer to C string buffer or `nullptr` if the `HeapString` is null (never set or freed).
+     * @returns A pointer to C string buffer or `nullptr` if the `String` is null (never set or freed).
      *
      */
     const char *AsCString(void) const { return mStringBuffer; }
@@ -101,7 +103,7 @@
     /**
      * This method sets the string from a given C string.
      *
-     * @param[in] aCString   A pointer to c string buffer. Can be `nullptr` which then frees the `HeapString`.
+     * @param[in] aCString   A pointer to c string buffer. Can be `nullptr` which then frees the `String`.
      *
      * @retval kErrorNone     Successfully set the string.
      * @retval kErrorNoBufs   Failed to allocate buffer for string.
@@ -110,40 +112,40 @@
     Error Set(const char *aCString);
 
     /**
-     * This method sets the string from another `HeapString`.
+     * This method sets the string from another `String`.
      *
-     * @param[in] aString   The other `HeapString` to set from.
+     * @param[in] aString   The other `String` to set from.
      *
      * @retval kErrorNone     Successfully set the string.
      * @retval kErrorNoBufs   Failed to allocate buffer for string.
      *
      */
-    Error Set(const HeapString &aString) { return Set(aString.AsCString()); }
+    Error Set(const String &aString) { return Set(aString.AsCString()); }
 
     /**
-     * This method sets the string from another `HeapString`.
+     * This method sets the string from another `String`.
      *
-     * @param[in] aString     The other `HeapString` to set from (rvalue reference using move semantics).
+     * @param[in] aString     The other `String` to set from (rvalue reference using move semantics).
      *
      * @retval kErrorNone     Successfully set the string.
      * @retval kErrorNoBufs   Failed to allocate buffer for string.
      *
      */
-    Error Set(HeapString &&aString);
+    Error Set(String &&aString);
 
     /**
-     * This method frees any buffer allocated by the `HeapString`.
+     * This method frees any buffer allocated by the `String`.
      *
-     * The `HeapString` destructor will automatically call `Free()`. This method allows caller to free buffer
+     * The `String` destructor will automatically call `Free()`. This method allows caller to free buffer
      * explicitly.
      *
      */
     void Free(void);
 
     /**
-     * This method overloads operator `==` to evaluate whether or not the `HeapString` is equal to a given C string.
+     * This method overloads operator `==` to evaluate whether or not the `String` is equal to a given C string.
      *
-     * @param[in]  aCString  A C string to compare with. Can be `nullptr` which then checks if `HeapString` is null.
+     * @param[in]  aCString  A C string to compare with. Can be `nullptr` which then checks if `String` is null.
      *
      * @retval TRUE   If the two strings are equal.
      * @retval FALSE  If the two strings are not equal.
@@ -152,9 +154,9 @@
     bool operator==(const char *aCString) const;
 
     /**
-     * This method overloads operator `!=` to evaluate whether or not the `HeapString` is unequal to a given C string.
+     * This method overloads operator `!=` to evaluate whether or not the `String` is unequal to a given C string.
      *
-     * @param[in]  aCString  A C string to compare with. Can be `nullptr` which then checks if `HeapString` is not null.
+     * @param[in]  aCString  A C string to compare with. Can be `nullptr` which then checks if `String` is not null.
      *
      * @retval TRUE   If the two strings are not equal.
      * @retval FALSE  If the two strings are equal.
@@ -163,7 +165,7 @@
     bool operator!=(const char *aCString) const { return !(*this == aCString); }
 
     /**
-     * This method overloads operator `==` to evaluate whether or not two `HeapString` are equal.
+     * This method overloads operator `==` to evaluate whether or not two `String` are equal.
      *
      * @param[in]  aString  The other string to compare with.
      *
@@ -171,15 +173,16 @@
      * @retval FALSE  If the two strings are not equal.
      *
      */
-    bool operator==(const HeapString &aString) const { return (*this == aString.AsCString()); }
+    bool operator==(const String &aString) const { return (*this == aString.AsCString()); }
 
-    HeapString(const HeapString &) = delete;
-    HeapString &operator=(const HeapString &) = delete;
+    String(const String &) = delete;
+    String &operator=(const String &) = delete;
 
 private:
     char *mStringBuffer;
 };
 
+} // namespace Heap
 } // namespace ot
 
 #endif // HEAP_STRING_HPP_
diff --git a/src/core/common/instance.cpp b/src/core/common/instance.cpp
index fb543e4..6aa1075 100644
--- a/src/core/common/instance.cpp
+++ b/src/core/common/instance.cpp
@@ -35,7 +35,6 @@
 
 #include <openthread/platform/misc.h>
 
-#include "common/logging.hpp"
 #include "common/new.hpp"
 #include "radio/trel_link.hpp"
 #include "utils/heap.hpp"
@@ -59,7 +58,7 @@
 #endif
 
 #if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
-otLogLevel Instance::sLogLevel = static_cast<otLogLevel>(OPENTHREAD_CONFIG_LOG_LEVEL_INIT);
+LogLevel Instance::sLogLevel = static_cast<LogLevel>(OPENTHREAD_CONFIG_LOG_LEVEL_INIT);
 #endif
 
 Instance::Instance(void)
@@ -79,6 +78,121 @@
     , mMessagePool(*this)
     , mIp6(*this)
     , mThreadNetif(*this)
+    , mTmfAgent(*this)
+#if OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
+    , mDhcp6Client(*this)
+#endif
+#if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
+    , mDhcp6Server(*this)
+#endif
+#if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
+    , mNeighborDiscoveryAgent(*this)
+#endif
+#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
+    , mSlaac(*this)
+#endif
+#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
+    , mDnsClient(*this)
+#endif
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+    , mSrpClient(*this)
+#endif
+#if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE
+    , mSrpClientBuffers(*this)
+#endif
+#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
+    , mDnssdServer(*this)
+#endif
+#if OPENTHREAD_CONFIG_DNS_DSO_ENABLE
+    , mDnsDso(*this)
+#endif
+#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
+    , mSntpClient(*this)
+#endif
+    , mActiveDataset(*this)
+    , mPendingDataset(*this)
+    , mExtendedPanIdManager(*this)
+    , mNetworkNameManager(*this)
+    , mIp6Filter(*this)
+    , mKeyManager(*this)
+    , mLowpan(*this)
+    , mMac(*this)
+    , mMeshForwarder(*this)
+    , mMleRouter(*this)
+    , mDiscoverScanner(*this)
+    , mAddressResolver(*this)
+#if OPENTHREAD_CONFIG_MULTI_RADIO
+    , mRadioSelector(*this)
+#endif
+#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
+    , mNetworkDataLocal(*this)
+#endif
+    , mNetworkDataLeader(*this)
+#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
+    , mNetworkDataNotifier(*this)
+#endif
+#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
+    , mNetworkDataPublisher(*this)
+#endif
+    , mNetworkDataServiceManager(*this)
+#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
+    , mNetworkDiagnostic(*this)
+#endif
+#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
+    , mBorderAgent(*this)
+#endif
+#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
+    , mCommissioner(*this)
+#endif
+#if OPENTHREAD_CONFIG_DTLS_ENABLE
+    , mCoapSecure(*this)
+#endif
+#if OPENTHREAD_CONFIG_JOINER_ENABLE
+    , mJoiner(*this)
+#endif
+#if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
+    , mJamDetector(*this)
+#endif
+#if OPENTHREAD_FTD
+    , mJoinerRouter(*this)
+    , mLeader(*this)
+#endif
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+    , mBackboneRouterLeader(*this)
+#endif
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
+    , mBackboneRouterLocal(*this)
+    , mBackboneRouterManager(*this)
+#endif
+#if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)
+    , mMlrManager(*this)
+#endif
+
+#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
+    , mDuaManager(*this)
+#endif
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+    , mSrpServer(*this)
+#endif
+
+#if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
+#if OPENTHREAD_FTD
+    , mChildSupervisor(*this)
+#endif
+    , mSupervisionListener(*this)
+#endif
+    , mAnnounceBegin(*this)
+    , mPanIdQuery(*this)
+    , mEnergyScan(*this)
+#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
+    , mAnycastLocator(*this)
+#endif
+#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+    , mTimeSync(*this)
+#endif
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
+    , mLinkMetrics(*this)
+#endif
 #if OPENTHREAD_CONFIG_COAP_API_ENABLE
     , mApplicationCoap(*this)
 #endif
@@ -190,7 +304,7 @@
     // Restore datasets and network information
 
     Get<Settings>().Init();
-    IgnoreError(Get<Mle::MleRouter>().Restore());
+    Get<Mle::MleRouter>().Restore();
 
 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
     Get<Trel::Link>().AfterInit();
@@ -234,6 +348,7 @@
 }
 
 #if OPENTHREAD_MTD || OPENTHREAD_FTD
+
 void Instance::FactoryReset(void)
 {
     Get<Settings>().Wipe();
@@ -251,6 +366,55 @@
     return error;
 }
 
+void Instance::GetBufferInfo(BufferInfo &aInfo)
+{
+    aInfo.Clear();
+
+    aInfo.mTotalBuffers = Get<MessagePool>().GetTotalBufferCount();
+    aInfo.mFreeBuffers  = Get<MessagePool>().GetFreeBufferCount();
+
+    Get<MeshForwarder>().GetSendQueue().GetInfo(aInfo.m6loSendQueue);
+    Get<MeshForwarder>().GetReassemblyQueue().GetInfo(aInfo.m6loReassemblyQueue);
+    Get<Ip6::Ip6>().GetSendQueue().GetInfo(aInfo.mIp6Queue);
+
+#if OPENTHREAD_FTD
+    Get<Ip6::Mpl>().GetBufferedMessageSet().GetInfo(aInfo.mMplQueue);
+#endif
+
+    Get<Mle::MleRouter>().GetMessageQueue().GetInfo(aInfo.mMleQueue);
+
+    Get<Tmf::Agent>().GetRequestMessages().GetInfo(aInfo.mCoapQueue);
+    Get<Tmf::Agent>().GetCachedResponses().GetInfo(aInfo.mCoapQueue);
+
+#if OPENTHREAD_CONFIG_DTLS_ENABLE
+    Get<Coap::CoapSecure>().GetRequestMessages().GetInfo(aInfo.mCoapSecureQueue);
+    Get<Coap::CoapSecure>().GetCachedResponses().GetInfo(aInfo.mCoapSecureQueue);
+#endif
+
+#if OPENTHREAD_CONFIG_COAP_API_ENABLE
+    GetApplicationCoap().GetRequestMessages().GetInfo(aInfo.mApplicationCoapQueue);
+    GetApplicationCoap().GetCachedResponses().GetInfo(aInfo.mApplicationCoapQueue);
+#endif
+}
+
 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
 
+#if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
+
+void Instance::SetLogLevel(LogLevel aLogLevel)
+{
+    if (aLogLevel != sLogLevel)
+    {
+        sLogLevel = aLogLevel;
+        otPlatLogHandleLevelChanged(sLogLevel);
+    }
+}
+
+extern "C" OT_TOOL_WEAK void otPlatLogHandleLevelChanged(otLogLevel aLogLevel)
+{
+    OT_UNUSED_VARIABLE(aLogLevel);
+}
+
+#endif
+
 } // namespace ot
diff --git a/src/core/common/instance.hpp b/src/core/common/instance.hpp
index 7436ca9..dd3e4e6 100644
--- a/src/core/common/instance.hpp
+++ b/src/core/common/instance.hpp
@@ -40,77 +40,96 @@
 #include <stdint.h>
 
 #include <openthread/heap.h>
-#include <openthread/platform/logging.h>
 #if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
 #include <openthread/platform/memory.h>
 #endif
 
+#include "common/array.hpp"
+#include "common/as_core_type.hpp"
 #include "common/error.hpp"
+#include "common/extension.hpp"
+#include "common/log.hpp"
+#include "common/message.hpp"
 #include "common/non_copyable.hpp"
-#include "common/random_manager.hpp"
+#include "common/random.hpp"
 #include "common/tasklet.hpp"
 #include "common/time_ticker.hpp"
 #include "common/timer.hpp"
 #include "common/uptime.hpp"
 #include "diags/factory_diags.hpp"
-#include "radio/radio.hpp"
-
-#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
-#include "common/message.hpp"
 #include "mac/link_raw.hpp"
-#endif
+#include "radio/radio.hpp"
+#include "utils/otns.hpp"
+
 #if OPENTHREAD_FTD || OPENTHREAD_MTD
+#include "backbone_router/backbone_tmf.hpp"
+#include "backbone_router/bbr_leader.hpp"
+#include "backbone_router/bbr_local.hpp"
+#include "backbone_router/bbr_manager.hpp"
+#include "border_router/routing_manager.hpp"
+#include "coap/coap_secure.hpp"
 #include "common/code_utils.hpp"
 #include "common/notifier.hpp"
 #include "common/settings.hpp"
 #include "crypto/mbedtls.hpp"
+#include "mac/mac.hpp"
 #include "meshcop/border_agent.hpp"
-#if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
+#include "meshcop/commissioner.hpp"
+#include "meshcop/dataset_manager.hpp"
 #include "meshcop/dataset_updater.hpp"
-#endif
+#include "meshcop/extended_panid.hpp"
+#include "meshcop/joiner.hpp"
+#include "meshcop/joiner_router.hpp"
+#include "meshcop/meshcop_leader.hpp"
+#include "meshcop/network_name.hpp"
+#include "net/dhcp6.hpp"
+#include "net/dhcp6_client.hpp"
+#include "net/dhcp6_server.hpp"
+#include "net/dns_client.hpp"
+#include "net/dns_dso.hpp"
+#include "net/dnssd_server.hpp"
 #include "net/ip6.hpp"
+#include "net/ip6_filter.hpp"
+#include "net/nd_agent.hpp"
+#include "net/netif.hpp"
+#include "net/sntp_client.hpp"
+#include "net/srp_client.hpp"
+#include "net/srp_server.hpp"
+#include "thread/address_resolver.hpp"
+#include "thread/announce_begin_server.hpp"
 #include "thread/announce_sender.hpp"
-#include "thread/link_quality.hpp"
-#include "thread/thread_netif.hpp"
-#include "thread/tmf.hpp"
-#include "utils/heap.hpp"
-#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
-#include "utils/ping_sender.hpp"
-#endif
-#if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE && OPENTHREAD_FTD
-#include "utils/channel_manager.hpp"
-#endif
-#if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
-#include "utils/channel_monitor.hpp"
-#endif
-#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
-#include "utils/history_tracker.hpp"
-#endif
-
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-#include "backbone_router/bbr_leader.hpp"
-
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
-#include "backbone_router/bbr_local.hpp"
-#endif
-
-#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
+#include "thread/anycast_locator.hpp"
+#include "thread/discover_scanner.hpp"
+#include "thread/dua_manager.hpp"
+#include "thread/energy_scan_server.hpp"
+#include "thread/key_manager.hpp"
 #include "thread/link_metrics.hpp"
-#endif
-
-#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-
-#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
-#include "border_router/routing_manager.hpp"
-#endif
-
+#include "thread/link_quality.hpp"
+#include "thread/mesh_forwarder.hpp"
+#include "thread/mle.hpp"
+#include "thread/mle_router.hpp"
+#include "thread/mlr_manager.hpp"
+#include "thread/network_data_local.hpp"
+#include "thread/network_data_notifier.hpp"
+#include "thread/network_data_publisher.hpp"
+#include "thread/network_data_service.hpp"
+#include "thread/network_diagnostic.hpp"
+#include "thread/panid_query_server.hpp"
+#include "thread/radio_selector.hpp"
+#include "thread/thread_netif.hpp"
+#include "thread/time_sync_service.hpp"
+#include "thread/tmf.hpp"
+#include "utils/channel_manager.hpp"
+#include "utils/channel_monitor.hpp"
+#include "utils/child_supervision.hpp"
+#include "utils/heap.hpp"
+#include "utils/history_tracker.hpp"
+#include "utils/jam_detector.hpp"
+#include "utils/ping_sender.hpp"
+#include "utils/slaac_address.hpp"
+#include "utils/srp_client_buffers.hpp"
 #endif // OPENTHREAD_FTD || OPENTHREAD_MTD
-#if OPENTHREAD_ENABLE_VENDOR_EXTENSION
-#include "common/extension.hpp"
-#endif
-#if OPENTHREAD_CONFIG_OTNS_ENABLE
-#include "utils/otns.hpp"
-#endif
+
 /**
  * @addtogroup core-instance
  *
@@ -140,15 +159,23 @@
 class Instance : public otInstance, private NonCopyable
 {
 public:
+    /**
+     * This type represents the message buffer information (number of messages/buffers in all OT stack message queues).
+     *
+     */
+    class BufferInfo : public otBufferInfo, public Clearable<BufferInfo>
+    {
+    };
+
 #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
     /**
       * This static method initializes the OpenThread instance.
       *
       * This function must be called before any other calls on OpenThread instance.
       *
-      * @param[in]    aBuffer      The buffer for OpenThread to use for allocating the Instance.
-      * @param[inout] aBufferSize  On input, the size of `aBuffer`. On output, if not enough space for `Instance`, the
-                                   number of bytes required for `Instance`.
+      * @param[in]     aBuffer      The buffer for OpenThread to use for allocating the Instance.
+      * @param[in,out] aBufferSize  On input, the size of `aBuffer`. On output, if not enough space for `Instance`, the
+                                    number of bytes required for `Instance`.
       *
       * @returns  A pointer to the new OpenThread instance.
       *
@@ -208,14 +235,14 @@
      * @returns The log level.
      *
      */
-    static otLogLevel GetLogLevel(void)
+    static LogLevel GetLogLevel(void)
 #if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
     {
         return sLogLevel;
     }
 #else
     {
-        return static_cast<otLogLevel>(OPENTHREAD_CONFIG_LOG_LEVEL);
+        return static_cast<LogLevel>(OPENTHREAD_CONFIG_LOG_LEVEL);
     }
 #endif
 
@@ -226,11 +253,7 @@
      * @param[in] aLogLevel  A log level.
      *
      */
-    static void SetLogLevel(otLogLevel aLogLevel)
-    {
-        OT_ASSERT(aLogLevel <= OT_LOG_LEVEL_DEBG && aLogLevel >= OT_LOG_LEVEL_NONE);
-        sLogLevel = aLogLevel;
-    }
+    static void SetLogLevel(LogLevel aLogLevel);
 #endif
 
     /**
@@ -259,21 +282,15 @@
      */
     Error ErasePersistentInfo(void);
 
-#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
-    static void  HeapFree(void *aPointer) { otPlatFree(aPointer); }
-    static void *HeapCAlloc(size_t aCount, size_t aSize) { return otPlatCAlloc(aCount, aSize); }
-#else
-    static void  HeapFree(void *aPointer) { sHeap.Free(aPointer); }
-    static void *HeapCAlloc(size_t aCount, size_t aSize) { return sHeap.CAlloc(aCount, aSize); }
-
+#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
     /**
      * This method returns a reference to the Heap object.
      *
      * @returns A reference to the Heap object.
      *
      */
-    Utils::Heap &GetHeap(void) { return sHeap; }
-#endif // OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+    static Utils::Heap &GetHeap(void) { return sHeap; }
+#endif
 
 #if OPENTHREAD_CONFIG_COAP_API_ENABLE
     /**
@@ -318,6 +335,14 @@
     static bool IsDnsNameCompressionEnabled(void) { return sDnsNameCompressionEnabled; }
 #endif
 
+    /**
+     * This method retrieves the the Message Buffer information.
+     *
+     * @param[out]  aInfo  A `BufferInfo` where information is written.
+     *
+     */
+    void GetBufferInfo(BufferInfo &aInfo);
+
 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
 
     /**
@@ -352,7 +377,7 @@
 #endif
 
 #if OPENTHREAD_MTD || OPENTHREAD_FTD
-    // RandomManager is initialized before other objects. Note that it
+    // Random::Manager is initialized before other objects. Note that it
     // requires MbedTls which itself may use Heap.
 #if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
     static Utils::Heap sHeap;
@@ -360,12 +385,13 @@
     Crypto::MbedTls mMbedTls;
 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
 
-    RandomManager mRandomManager;
+    Random::Manager mRandomManager;
 
     // Radio is initialized before other member variables
     // (particularly, SubMac and Mac) to allow them to use its methods
     // from their constructor.
     Radio mRadio;
+
 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
     Uptime mUptime;
 #endif
@@ -382,6 +408,153 @@
 
     Ip6::Ip6    mIp6;
     ThreadNetif mThreadNetif;
+    Tmf::Agent  mTmfAgent;
+
+#if OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
+    Dhcp6::Client mDhcp6Client;
+#endif
+
+#if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
+    Dhcp6::Server mDhcp6Server;
+#endif
+
+#if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
+    NeighborDiscovery::Agent mNeighborDiscoveryAgent;
+#endif
+
+#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
+    Utils::Slaac mSlaac;
+#endif
+
+#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
+    Dns::Client mDnsClient;
+#endif
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+    Srp::Client mSrpClient;
+#endif
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE
+    Utils::SrpClientBuffers mSrpClientBuffers;
+#endif
+
+#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
+    Dns::ServiceDiscovery::Server mDnssdServer;
+#endif
+
+#if OPENTHREAD_CONFIG_DNS_DSO_ENABLE
+    Dns::Dso mDnsDso;
+#endif
+
+#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
+    Sntp::Client mSntpClient;
+#endif
+
+    MeshCoP::ActiveDatasetManager  mActiveDataset;
+    MeshCoP::PendingDatasetManager mPendingDataset;
+    MeshCoP::ExtendedPanIdManager  mExtendedPanIdManager;
+    MeshCoP::NetworkNameManager    mNetworkNameManager;
+    Ip6::Filter                    mIp6Filter;
+    KeyManager                     mKeyManager;
+    Lowpan::Lowpan                 mLowpan;
+    Mac::Mac                       mMac;
+    MeshForwarder                  mMeshForwarder;
+    Mle::MleRouter                 mMleRouter;
+    Mle::DiscoverScanner           mDiscoverScanner;
+    AddressResolver                mAddressResolver;
+
+#if OPENTHREAD_CONFIG_MULTI_RADIO
+    RadioSelector mRadioSelector;
+#endif
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
+    NetworkData::Local mNetworkDataLocal;
+#endif
+
+    NetworkData::Leader mNetworkDataLeader;
+
+#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
+    NetworkData::Notifier mNetworkDataNotifier;
+#endif
+
+#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
+    NetworkData::Publisher mNetworkDataPublisher;
+#endif
+
+    NetworkData::Service::Manager mNetworkDataServiceManager;
+
+#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
+    NetworkDiagnostic::NetworkDiagnostic mNetworkDiagnostic;
+#endif
+
+#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
+    MeshCoP::BorderAgent mBorderAgent;
+#endif
+
+#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
+    MeshCoP::Commissioner mCommissioner;
+#endif
+
+#if OPENTHREAD_CONFIG_DTLS_ENABLE
+    Coap::CoapSecure mCoapSecure;
+#endif
+
+#if OPENTHREAD_CONFIG_JOINER_ENABLE
+    MeshCoP::Joiner mJoiner;
+#endif
+
+#if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
+    Utils::JamDetector mJamDetector;
+#endif
+
+#if OPENTHREAD_FTD
+    MeshCoP::JoinerRouter mJoinerRouter;
+    MeshCoP::Leader       mLeader;
+#endif
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+    BackboneRouter::Leader mBackboneRouterLeader;
+#endif
+
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
+    BackboneRouter::Local   mBackboneRouterLocal;
+    BackboneRouter::Manager mBackboneRouterManager;
+#endif
+
+#if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)
+    MlrManager mMlrManager;
+#endif
+
+#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
+    DuaManager mDuaManager;
+#endif
+
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+    Srp::Server mSrpServer;
+#endif
+
+#if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
+#if OPENTHREAD_FTD
+    Utils::ChildSupervisor mChildSupervisor;
+#endif
+    Utils::SupervisionListener mSupervisionListener;
+#endif
+
+    AnnounceBeginServer mAnnounceBegin;
+    PanIdQueryServer    mPanIdQuery;
+    EnergyScanServer    mEnergyScan;
+
+#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
+    AnycastLocator mAnycastLocator;
+#endif
+
+#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+    TimeSync mTimeSync;
+#endif
+
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
+    LinkMetrics::LinkMetrics mLinkMetrics;
+#endif
 
 #if OPENTHREAD_CONFIG_COAP_API_ENABLE
     Coap::Coap mApplicationCoap;
@@ -424,19 +597,23 @@
 #endif
 
 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
+
 #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
     Mac::LinkRaw mLinkRaw;
-#endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
+#endif
 
 #if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
-    static otLogLevel sLogLevel;
+    static LogLevel sLogLevel;
 #endif
+
 #if OPENTHREAD_ENABLE_VENDOR_EXTENSION
     Extension::ExtensionBase &mExtension;
 #endif
+
 #if OPENTHREAD_CONFIG_DIAG_ENABLE
     FactoryDiags::Diags mDiags;
 #endif
+
     bool mIsInitialized;
 
 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
@@ -444,8 +621,16 @@
 #endif
 };
 
+DefineCoreType(otInstance, Instance);
+DefineCoreType(otBufferInfo, Instance::BufferInfo);
+
 // Specializations of the `Get<Type>()` method.
 
+template <> inline Instance &Instance::Get(void)
+{
+    return *this;
+}
+
 template <> inline Radio &Instance::Get(void)
 {
     return mRadio;
@@ -486,45 +671,45 @@
 
 template <> inline MeshForwarder &Instance::Get(void)
 {
-    return mThreadNetif.mMeshForwarder;
+    return mMeshForwarder;
 }
 
 #if OPENTHREAD_CONFIG_MULTI_RADIO
 template <> inline RadioSelector &Instance::Get(void)
 {
-    return mThreadNetif.mRadioSelector;
+    return mRadioSelector;
 }
 #endif
 
 template <> inline Mle::Mle &Instance::Get(void)
 {
-    return mThreadNetif.mMleRouter;
+    return mMleRouter;
 }
 
 template <> inline Mle::MleRouter &Instance::Get(void)
 {
-    return mThreadNetif.mMleRouter;
+    return mMleRouter;
 }
 
 template <> inline Mle::DiscoverScanner &Instance::Get(void)
 {
-    return mThreadNetif.mDiscoverScanner;
+    return mDiscoverScanner;
 }
 
 template <> inline NeighborTable &Instance::Get(void)
 {
-    return mThreadNetif.mMleRouter.mNeighborTable;
+    return mMleRouter.mNeighborTable;
 }
 
 #if OPENTHREAD_FTD
 template <> inline ChildTable &Instance::Get(void)
 {
-    return mThreadNetif.mMleRouter.mChildTable;
+    return mMleRouter.mChildTable;
 }
 
 template <> inline RouterTable &Instance::Get(void)
 {
-    return mThreadNetif.mMleRouter.mRouterTable;
+    return mMleRouter.mRouterTable;
 }
 #endif
 
@@ -545,144 +730,144 @@
 
 template <> inline Mac::Mac &Instance::Get(void)
 {
-    return mThreadNetif.mMac;
+    return mMac;
 }
 
 template <> inline Mac::SubMac &Instance::Get(void)
 {
-    return mThreadNetif.mMac.mLinks.mSubMac;
+    return mMac.mLinks.mSubMac;
 }
 
 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
 template <> inline Trel::Link &Instance::Get(void)
 {
-    return mThreadNetif.mMac.mLinks.mTrel;
+    return mMac.mLinks.mTrel;
 }
 
 template <> inline Trel::Interface &Instance::Get(void)
 {
-    return mThreadNetif.mMac.mLinks.mTrel.mInterface;
+    return mMac.mLinks.mTrel.mInterface;
 }
 #endif
 
 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
 template <> inline Mac::Filter &Instance::Get(void)
 {
-    return mThreadNetif.mMac.mFilter;
+    return mMac.mFilter;
 }
 #endif
 
 template <> inline Lowpan::Lowpan &Instance::Get(void)
 {
-    return mThreadNetif.mLowpan;
+    return mLowpan;
 }
 
 template <> inline KeyManager &Instance::Get(void)
 {
-    return mThreadNetif.mKeyManager;
+    return mKeyManager;
 }
 
 template <> inline Ip6::Filter &Instance::Get(void)
 {
-    return mThreadNetif.mIp6Filter;
+    return mIp6Filter;
+}
+
+template <> inline AddressResolver &Instance::Get(void)
+{
+    return mAddressResolver;
 }
 
 #if OPENTHREAD_FTD
 
 template <> inline IndirectSender &Instance::Get(void)
 {
-    return mThreadNetif.mMeshForwarder.mIndirectSender;
+    return mMeshForwarder.mIndirectSender;
 }
 
 template <> inline SourceMatchController &Instance::Get(void)
 {
-    return mThreadNetif.mMeshForwarder.mIndirectSender.mSourceMatchController;
+    return mMeshForwarder.mIndirectSender.mSourceMatchController;
 }
 
 template <> inline DataPollHandler &Instance::Get(void)
 {
-    return mThreadNetif.mMeshForwarder.mIndirectSender.mDataPollHandler;
+    return mMeshForwarder.mIndirectSender.mDataPollHandler;
 }
 
 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
 template <> inline CslTxScheduler &Instance::Get(void)
 {
-    return mThreadNetif.mMeshForwarder.mIndirectSender.mCslTxScheduler;
+    return mMeshForwarder.mIndirectSender.mCslTxScheduler;
 }
 #endif
 
-template <> inline AddressResolver &Instance::Get(void)
-{
-    return mThreadNetif.mAddressResolver;
-}
-
 template <> inline MeshCoP::Leader &Instance::Get(void)
 {
-    return mThreadNetif.mLeader;
+    return mLeader;
 }
 
 template <> inline MeshCoP::JoinerRouter &Instance::Get(void)
 {
-    return mThreadNetif.mJoinerRouter;
+    return mJoinerRouter;
 }
 #endif // OPENTHREAD_FTD
 
 template <> inline AnnounceBeginServer &Instance::Get(void)
 {
-    return mThreadNetif.mAnnounceBegin;
+    return mAnnounceBegin;
 }
 
 template <> inline DataPollSender &Instance::Get(void)
 {
-    return mThreadNetif.mMeshForwarder.mDataPollSender;
+    return mMeshForwarder.mDataPollSender;
 }
 
 template <> inline EnergyScanServer &Instance::Get(void)
 {
-    return mThreadNetif.mEnergyScan;
+    return mEnergyScan;
 }
 
 template <> inline PanIdQueryServer &Instance::Get(void)
 {
-    return mThreadNetif.mPanIdQuery;
+    return mPanIdQuery;
 }
 
 #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
 template <> inline AnycastLocator &Instance::Get(void)
 {
-    return mThreadNetif.mAnycastLocator;
+    return mAnycastLocator;
 }
 #endif
 
 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
 template <> inline NetworkData::Local &Instance::Get(void)
 {
-    return mThreadNetif.mNetworkDataLocal;
+    return mNetworkDataLocal;
 }
 #endif
 
 template <> inline NetworkData::Leader &Instance::Get(void)
 {
-    return mThreadNetif.mNetworkDataLeader;
+    return mNetworkDataLeader;
 }
 
 #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
 template <> inline NetworkData::Notifier &Instance::Get(void)
 {
-    return mThreadNetif.mNetworkDataNotifier;
+    return mNetworkDataNotifier;
 }
 #endif
 
 #if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
 template <> inline NetworkData::Publisher &Instance::Get(void)
 {
-    return mThreadNetif.mNetworkDataPublisher;
+    return mNetworkDataPublisher;
 }
 #endif
 
 template <> inline NetworkData::Service::Manager &Instance::Get(void)
 {
-    return mThreadNetif.mNetworkDataServiceManager;
+    return mNetworkDataServiceManager;
 }
 
 #if OPENTHREAD_CONFIG_TCP_ENABLE
@@ -709,121 +894,138 @@
 
 template <> inline Tmf::Agent &Instance::Get(void)
 {
-    return mThreadNetif.mTmfAgent;
+    return mTmfAgent;
 }
 
 #if OPENTHREAD_CONFIG_DTLS_ENABLE
 template <> inline Coap::CoapSecure &Instance::Get(void)
 {
-    return mThreadNetif.mCoapSecure;
+    return mCoapSecure;
 }
 #endif
 
-template <> inline MeshCoP::ActiveDataset &Instance::Get(void)
+template <> inline MeshCoP::ExtendedPanIdManager &Instance::Get(void)
 {
-    return mThreadNetif.mActiveDataset;
+    return mExtendedPanIdManager;
 }
 
-template <> inline MeshCoP::PendingDataset &Instance::Get(void)
+template <> inline MeshCoP::NetworkNameManager &Instance::Get(void)
 {
-    return mThreadNetif.mPendingDataset;
+    return mNetworkNameManager;
+}
+
+template <> inline MeshCoP::ActiveDatasetManager &Instance::Get(void)
+{
+    return mActiveDataset;
+}
+
+template <> inline MeshCoP::PendingDatasetManager &Instance::Get(void)
+{
+    return mPendingDataset;
 }
 
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
 template <> inline TimeSync &Instance::Get(void)
 {
-    return mThreadNetif.mTimeSync;
+    return mTimeSync;
 }
 #endif
 
 #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
 template <> inline MeshCoP::Commissioner &Instance::Get(void)
 {
-    return mThreadNetif.mCommissioner;
+    return mCommissioner;
 }
 #endif
 
 #if OPENTHREAD_CONFIG_JOINER_ENABLE
 template <> inline MeshCoP::Joiner &Instance::Get(void)
 {
-    return mThreadNetif.mJoiner;
+    return mJoiner;
 }
 #endif
 
 #if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
 template <> inline Dns::Client &Instance::Get(void)
 {
-    return mThreadNetif.mDnsClient;
+    return mDnsClient;
 }
 #endif
 
 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
 template <> inline Srp::Client &Instance::Get(void)
 {
-    return mThreadNetif.mSrpClient;
+    return mSrpClient;
 }
 #endif
 
 #if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE
 template <> inline Utils::SrpClientBuffers &Instance::Get(void)
 {
-    return mThreadNetif.mSrpClientBuffers;
+    return mSrpClientBuffers;
 }
 #endif
 
 #if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
 template <> inline Dns::ServiceDiscovery::Server &Instance::Get(void)
 {
-    return mThreadNetif.mDnssdServer;
+    return mDnssdServer;
+}
+#endif
+
+#if OPENTHREAD_CONFIG_DNS_DSO_ENABLE
+template <> inline Dns::Dso &Instance::Get(void)
+{
+    return mDnsDso;
 }
 #endif
 
 #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
 template <> inline NetworkDiagnostic::NetworkDiagnostic &Instance::Get(void)
 {
-    return mThreadNetif.mNetworkDiagnostic;
+    return mNetworkDiagnostic;
 }
 #endif
 
 #if OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
 template <> inline Dhcp6::Client &Instance::Get(void)
 {
-    return mThreadNetif.mDhcp6Client;
+    return mDhcp6Client;
 }
 #endif
 
 #if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
 template <> inline Dhcp6::Server &Instance::Get(void)
 {
-    return mThreadNetif.mDhcp6Server;
+    return mDhcp6Server;
 }
 #endif
 
 #if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
 template <> inline NeighborDiscovery::Agent &Instance::Get(void)
 {
-    return mThreadNetif.mNeighborDiscoveryAgent;
+    return mNeighborDiscoveryAgent;
 }
 #endif
 
 #if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
 template <> inline Utils::Slaac &Instance::Get(void)
 {
-    return mThreadNetif.mSlaac;
+    return mSlaac;
 }
 #endif
 
 #if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
 template <> inline Utils::JamDetector &Instance::Get(void)
 {
-    return mThreadNetif.mJamDetector;
+    return mJamDetector;
 }
 #endif
 
 #if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
 template <> inline Sntp::Client &Instance::Get(void)
 {
-    return mThreadNetif.mSntpClient;
+    return mSntpClient;
 }
 #endif
 
@@ -831,12 +1033,12 @@
 #if OPENTHREAD_FTD
 template <> inline Utils::ChildSupervisor &Instance::Get(void)
 {
-    return mThreadNetif.mChildSupervisor;
+    return mChildSupervisor;
 }
 #endif
 template <> inline Utils::SupervisionListener &Instance::Get(void)
 {
-    return mThreadNetif.mSupervisionListener;
+    return mSupervisionListener;
 }
 #endif
 
@@ -878,7 +1080,7 @@
 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
 template <> inline MeshCoP::BorderAgent &Instance::Get(void)
 {
-    return mThreadNetif.mBorderAgent;
+    return mBorderAgent;
 }
 #endif
 
@@ -898,57 +1100,57 @@
 
 template <> inline BackboneRouter::Leader &Instance::Get(void)
 {
-    return mThreadNetif.mBackboneRouterLeader;
+    return mBackboneRouterLeader;
 }
 
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
 template <> inline BackboneRouter::Local &Instance::Get(void)
 {
-    return mThreadNetif.mBackboneRouterLocal;
+    return mBackboneRouterLocal;
 }
 template <> inline BackboneRouter::Manager &Instance::Get(void)
 {
-    return mThreadNetif.mBackboneRouterManager;
+    return mBackboneRouterManager;
 }
 
 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
 template <> inline BackboneRouter::MulticastListenersTable &Instance::Get(void)
 {
-    return mThreadNetif.mBackboneRouterManager.GetMulticastListenersTable();
+    return mBackboneRouterManager.GetMulticastListenersTable();
 }
 #endif
 
 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
 template <> inline BackboneRouter::NdProxyTable &Instance::Get(void)
 {
-    return mThreadNetif.mBackboneRouterManager.GetNdProxyTable();
+    return mBackboneRouterManager.GetNdProxyTable();
 }
 #endif
 
 template <> inline BackboneRouter::BackboneTmfAgent &Instance::Get(void)
 {
-    return mThreadNetif.mBackboneRouterManager.GetBackboneTmfAgent();
+    return mBackboneRouterManager.GetBackboneTmfAgent();
 }
 #endif
 
 #if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)
 template <> inline MlrManager &Instance::Get(void)
 {
-    return mThreadNetif.mMlrManager;
+    return mMlrManager;
 }
 #endif
 
 #if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
 template <> inline DuaManager &Instance::Get(void)
 {
-    return mThreadNetif.mDuaManager;
+    return mDuaManager;
 }
 #endif
 
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
 template <> inline LinkMetrics::LinkMetrics &Instance::Get(void)
 {
-    return mThreadNetif.mLinkMetrics;
+    return mLinkMetrics;
 }
 #endif
 
@@ -966,12 +1168,17 @@
 {
     return mRoutingManager;
 }
+
+template <> inline BorderRouter::InfraIf &Instance::Get(void)
+{
+    return mRoutingManager.mInfraIf;
+}
 #endif
 
 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
 template <> inline Srp::Server &Instance::Get(void)
 {
-    return mThreadNetif.mSrpServer;
+    return mSrpServer;
 }
 #endif
 
diff --git a/src/core/common/linked_list.hpp b/src/core/common/linked_list.hpp
index d7b2aae..b924877 100644
--- a/src/core/common/linked_list.hpp
+++ b/src/core/common/linked_list.hpp
@@ -72,7 +72,7 @@
     /**
      * This method gets the next entry in the linked list.
      *
-     * @returns A pointer to the next entry in the linked list or nullptr if at the end of the list.
+     * @returns A pointer to the next entry in the linked list or `nullptr` if at the end of the list.
      *
      */
     const Type *GetNext(void) const { return static_cast<const Type *>(static_cast<const Type *>(this)->mNext); }
@@ -80,7 +80,7 @@
     /**
      * This method gets the next entry in the linked list.
      *
-     * @returns A pointer to the next entry in the linked list or nullptr if at the end of the list.
+     * @returns A pointer to the next entry in the linked list or `nullptr` if at the end of the list.
      *
      */
     Type *GetNext(void) { return static_cast<Type *>(static_cast<Type *>(this)->mNext); }
@@ -119,7 +119,7 @@
     /**
      * This method returns the entry at the head of the linked list
      *
-     * @returns Pointer to the entry at the head of the linked list, or nullptr if the list is empty.
+     * @returns Pointer to the entry at the head of the linked list, or `nullptr` if the list is empty.
      *
      */
     Type *GetHead(void) { return mHead; }
@@ -127,7 +127,7 @@
     /**
      * This method returns the entry at the head of the linked list.
      *
-     * @returns Pointer to the entry at the head of the linked list, or nullptr if the list is empty.
+     * @returns Pointer to the entry at the head of the linked list, or `nullptr` if the list is empty.
      *
      */
     const Type *GetHead(void) const { return mHead; }
@@ -185,7 +185,7 @@
      *
      * @note This method does not change the popped entry itself, i.e., the popped entry next pointer stays as before.
      *
-     * @returns The entry that was popped if the list is not empty, or nullptr if the list is empty.
+     * @returns The entry that was popped if the list is not empty, or `nullptr` if the list is empty.
      *
      */
     Type *Pop(void)
@@ -205,10 +205,10 @@
      *
      * @note This method does not change the popped entry itself, i.e., the popped entry next pointer stays as before.
      *
-     * @param[in] aPrevEntry  A pointer to a previous entry. If it is not nullptr the entry after this will be popped,
-     *                        otherwise (if it is nullptr) the entry at the head of the list is popped.
+     * @param[in] aPrevEntry  A pointer to a previous entry. If it is not `nullptr` the entry after this will be popped,
+     *                        otherwise (if it is `nullptr`) the entry at the head of the list is popped.
      *
-     * @returns Pointer to the entry that was popped, or nullptr if there is no entry to pop.
+     * @returns Pointer to the entry that was popped, or `nullptr` if there is no entry to pop.
      *
      */
     Type *PopAfter(Type *aPrevEntry)
@@ -333,7 +333,8 @@
      *
      * @param[in] aIndicator   An entry indicator to match against entries in the list.
      *
-     * @returns A pointer to the removed matching entry if one could be found, or nullptr if no matching entry is found.
+     * @returns A pointer to the removed matching entry if one could be found, or `nullptr` if no matching entry is
+     *          found.
      *
      */
     template <typename Indicator> Type *RemoveMatching(const Indicator &aIndicator)
@@ -350,11 +351,50 @@
     }
 
     /**
+     * This template method removes all entries in the list matching a given entry indicator from the list and adds
+     * them to a new list.
+     *
+     * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries
+     * in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each
+     * `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly:
+     *
+     *     bool Type::Matches(const Indicator &aIndicator) const
+     *
+     * @param[in] aIndicator   An entry indicator to match against entries in the list.
+     * @param[in] aRemovedList The list to add the removed entries to.
+     *
+     */
+    template <typename Indicator> void RemoveAllMatching(const Indicator &aIndicator, LinkedList &aRemovedList)
+    {
+        Type *entry;
+        Type *prev;
+        Type *next;
+
+        for (prev = nullptr, entry = GetHead(); entry != nullptr; entry = next)
+        {
+            next = entry->GetNext();
+
+            if (entry->Matches(aIndicator))
+            {
+                PopAfter(prev);
+                aRemovedList.Push(*entry);
+
+                // When the entry is removed from the list
+                // we keep the `prev` pointer same as before.
+            }
+            else
+            {
+                prev = entry;
+            }
+        }
+    }
+
+    /**
      * This method searches within the linked list to find an entry and if found returns a pointer to previous entry.
      *
      * @param[in]  aEntry      A reference to an entry to find.
      * @param[out] aPrevEntry  A pointer to output the previous entry on success (when @p aEntry is found in the list).
-     *                         @p aPrevEntry is set to nullptr if @p aEntry is the head of the list. Otherwise it is
+     *                         @p aPrevEntry is set to `nullptr` if @p aEntry is the head of the list. Otherwise it is
      *                         updated to point to the previous entry before @p aEntry in the list.
      *
      * @retval kErrorNone      The entry was found in the list and @p aPrevEntry was updated successfully.
@@ -384,7 +424,7 @@
      *
      * @param[in]  aEntry      A reference to an entry to find.
      * @param[out] aPrevEntry  A pointer to output the previous entry on success (when @p aEntry is found in the list).
-     *                         @p aPrevEntry is set to nullptr if @p aEntry is the head of the list. Otherwise it is
+     *                         @p aPrevEntry is set to `nullptr` if @p aEntry is the head of the list. Otherwise it is
      *                         updated to point to the previous entry before @p aEntry in the list.
      *
      * @retval kErrorNone      The entry was found in the list and @p aPrevEntry was updated successfully.
@@ -407,13 +447,14 @@
      *     bool Type::Matches(const Indicator &aIndicator) const
      *
      * @param[in]  aBegin      A pointer to the begin of the range.
-     * @param[in]  aEnd        A pointer to the end of the range, or nullptr to search all entries after @p aBegin.
+     * @param[in]  aEnd        A pointer to the end of the range, or `nullptr` to search all entries after @p aBegin.
      * @param[in]  aIndicator  An indicator to match with entries in the list.
      * @param[out] aPrevEntry  A pointer to output the previous entry on success (when a match is found in the list).
-     *                         @p aPrevEntry is set to nullptr if the matching entry is the head of the list. Otherwise
-     *                         it is updated to point to the previous entry before the matching entry in the list.
+     *                         @p aPrevEntry is set to `nullptr` if the matching entry is the head of the list.
+     *                         Otherwise it is updated to point to the previous entry before the matching entry in the
+     *                         list.
      *
-     * @returns A pointer to the matching entry if one is found, or nullptr if no matching entry was found.
+     * @returns A pointer to the matching entry if one is found, or `nullptr` if no matching entry was found.
      *
      */
     template <typename Indicator>
@@ -448,13 +489,14 @@
      *     bool Type::Matches(const Indicator &aIndicator) const
      *
      * @param[in]  aBegin      A pointer to the begin of the range.
-     * @param[in]  aEnd        A pointer to the end of the range, or nullptr to search all entries after @p aBegin.
+     * @param[in]  aEnd        A pointer to the end of the range, or `nullptr` to search all entries after @p aBegin.
      * @param[in]  aIndicator  An indicator to match with entries in the list.
      * @param[out] aPrevEntry  A pointer to output the previous entry on success (when a match is found in the list).
-     *                         @p aPrevEntry is set to nullptr if the matching entry is the head of the list. Otherwise
-     *                         it is updated to point to the previous entry before the matching entry in the list.
+     *                         @p aPrevEntry is set to `nullptr` if the matching entry is the head of the list.
+     *                         Otherwise it is updated to point to the previous entry before the matching entry in the
+     *                         list.
      *
-     * @returns A pointer to the matching entry if one is found, or nullptr if no matching entry was found.
+     * @returns A pointer to the matching entry if one is found, or `nullptr` if no matching entry was found.
      *
      */
     template <typename Indicator>
@@ -474,10 +516,11 @@
      *
      * @param[in]  aIndicator  An indicator to match with entries in the list.
      * @param[out] aPrevEntry  A pointer to output the previous entry on success (when a match is found in the list).
-     *                         @p aPrevEntry is set to nullptr if the matching entry is the head of the list. Otherwise
-     *                         it is updated to point to the previous entry before the matching entry in the list.
+     *                         @p aPrevEntry is set to `nullptr` if the matching entry is the head of the list.
+     *                         Otherwise it is updated to point to the previous entry before the matching entry in the
+     *                         list.
      *
-     * @returns A pointer to the matching entry if one is found, or nullptr if no matching entry was found.
+     * @returns A pointer to the matching entry if one is found, or `nullptr` if no matching entry was found.
      *
      */
     template <typename Indicator> const Type *FindMatching(const Indicator &aIndicator, const Type *&aPrevEntry) const
@@ -497,10 +540,11 @@
      *
      * @param[in]  aIndicator  An indicator to match with entries in the list.
      * @param[out] aPrevEntry  A pointer to output the previous entry on success (when a match is found in the list).
-     *                         @p aPrevEntry is set to nullptr if the matching entry is the head of the list. Otherwise
-     *                         it is updated to point to the previous entry before the matching entry in the list.
+     *                         @p aPrevEntry is set to `nullptr` if the matching entry is the head of the list.
+     *                         Otherwise it is updated to point to the previous entry before the matching entry in the
+     *                         list.
      *
-     * @returns A pointer to the matching entry if one is found, or nullptr if no matching entry was found.
+     * @returns A pointer to the matching entry if one is found, or `nullptr` if no matching entry was found.
      *
      */
     template <typename Indicator> Type *FindMatching(const Indicator &aIndicator, Type *&aPrevEntry)
@@ -519,7 +563,7 @@
      *
      * @param[in]  aIndicator  An indicator to match with entries in the list.
      *
-     * @returns A pointer to the matching entry if one is found, or nullptr if no matching entry was found.
+     * @returns A pointer to the matching entry if one is found, or `nullptr` if no matching entry was found.
      *
      */
     template <typename Indicator> const Type *FindMatching(const Indicator &aIndicator) const
@@ -540,7 +584,7 @@
      *
      * @param[in]  aIndicator  An indicator to match with entries in the list.
      *
-     * @returns A pointer to the matching entry if one is found, or nullptr if no matching entry was found.
+     * @returns A pointer to the matching entry if one is found, or `nullptr` if no matching entry was found.
      *
      */
     template <typename Indicator> Type *FindMatching(const Indicator &aIndicator)
@@ -551,7 +595,7 @@
     /**
      * This method returns the tail of the linked list (i.e., the last entry in the list).
      *
-     * @returns A pointer to the tail entry in the linked list or nullptr if the list is empty.
+     * @returns A pointer to the tail entry in the linked list or `nullptr` if the list is empty.
      *
      */
     const Type *GetTail(void) const
@@ -572,7 +616,7 @@
     /**
      * This method returns the tail of the linked list (i.e., the last entry in the list).
      *
-     * @returns A pointer to the tail entry in the linked list or nullptr if the list is empty.
+     * @returns A pointer to the tail entry in the linked list or `nullptr` if the list is empty.
      *
      */
     Type *GetTail(void) { return AsNonConst(AsConst(this)->GetTail()); }
diff --git a/src/core/common/locator.hpp b/src/core/common/locator.hpp
index 927e1d8..7ed3625 100644
--- a/src/core/common/locator.hpp
+++ b/src/core/common/locator.hpp
@@ -59,6 +59,38 @@
  */
 
 /**
+ * This template class implements `Get<Type>()` method for different `Type` objects belonging to the OpenThread
+ * instance.
+ *
+ * Users of this class MUST follow CRTP-style inheritance, i.e., the class `Class` itself should publicly inherit
+ * from `GetProvider<Class>`.
+ *
+ * @tparam InstanceGetProvider   The template sub-lass used in CRTP style inheritance.
+ *                               `InstanceGetProvider` MUST provide a method with the following signature:
+ *                               `Instance &GetInstance(void) const`
+ *
+ */
+template <class InstanceGetProvider> class GetProvider
+{
+public:
+    /**
+     * This template method returns a reference to a given `Type` object belonging to the OpenThread instance.
+     *
+     * For example, `Get<MeshForwarder>()` returns a reference to the `MeshForwarder` object of the instance.
+     *
+     * Note that any `Type` for which the `Get<Type>` is defined MUST be uniquely accessible from the OpenThread
+     * `Instance` through the member variable property hierarchy.
+     *
+     * @returns A reference to the `Type` object of the instance.
+     *
+     */
+    template <typename Type> inline Type &Get(void) const; // Implemented in `locator_getters.hpp`.
+
+protected:
+    GetProvider(void) = default;
+};
+
+/**
  * This class implements a locator for an OpenThread Instance object.
  *
  * The `InstanceLocator` is used as base class of almost all other OpenThread classes. It provides a way for an object
@@ -69,7 +101,7 @@
  * single-instance case, this class becomes an empty base class.
  *
  */
-class InstanceLocator
+class InstanceLocator : public GetProvider<InstanceLocator>
 {
     friend class InstanceLocatorInit;
 
@@ -86,19 +118,6 @@
     Instance &GetInstance(void) const { return *reinterpret_cast<Instance *>(&gInstanceRaw); }
 #endif
 
-    /**
-     * This template method returns a reference to a given `Type` object belonging to the OpenThread instance.
-     *
-     * For example, `Get<MeshForwarder>()` returns a reference to the `MeshForwarder` object of the instance.
-     *
-     * Note that any `Type` for which the `Get<Type>` is defined MUST be uniquely accessible from the OpenThread
-     * `Instance` through the member variable property hierarchy.
-     *
-     * @returns A reference to the `Type` object of the instance.
-     *
-     */
-    template <typename Type> inline Type &Get(void) const; // Implemented in `locator_getters.hpp`.
-
 protected:
     /**
      * This constructor initializes the object.
diff --git a/src/core/common/locator_getters.hpp b/src/core/common/locator_getters.hpp
index dc87b40..e1c6885 100644
--- a/src/core/common/locator_getters.hpp
+++ b/src/core/common/locator_getters.hpp
@@ -42,25 +42,11 @@
 
 namespace ot {
 
-/**
- * This method returns a reference to the parent OpenThread Instance.
- *
- * This definition is a specialization of template `Get<Type>` for `Get<Instance>()`,
- *
- * @returns A reference to `Instance` object.
- *
- */
-template <> inline Instance &InstanceLocator::Get(void) const
+template <typename InstanceGetProvider>
+template <typename Type>
+inline Type &GetProvider<InstanceGetProvider>::Get(void) const
 {
-    return GetInstance();
-}
-
-template <typename Type> inline Type &InstanceLocator::Get(void) const
-{
-    // This method uses the `Instance` template method `Get<Type>`
-    // to get to the given `Type` from the single OpenThread
-    // instance.
-    return GetInstance().Get<Type>();
+    return static_cast<const InstanceGetProvider *>(this)->GetInstance().template Get<Type>();
 }
 
 } // namespace ot
diff --git a/src/core/common/log.cpp b/src/core/common/log.cpp
new file mode 100644
index 0000000..a0a126a
--- /dev/null
+++ b/src/core/common/log.cpp
@@ -0,0 +1,266 @@
+/*
+ *  Copyright (c) 2017-2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file implements the logging related functions.
+ */
+
+#include "log.hpp"
+
+#include <ctype.h>
+
+#include <openthread/platform/logging.h>
+
+#include "common/code_utils.hpp"
+#include "common/instance.hpp"
+#include "common/string.hpp"
+
+/*
+ * Verify debug UART dependency.
+ *
+ * It is reasonable to only enable the debug UART and not enable logs to the DEBUG UART.
+ */
+#if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_DEBUG_UART) && (!OPENTHREAD_CONFIG_ENABLE_DEBUG_UART)
+#error "OPENTHREAD_CONFIG_ENABLE_DEBUG_UART_LOG requires OPENTHREAD_CONFIG_ENABLE_DEBUG_UART"
+#endif
+
+#if OPENTHREAD_CONFIG_LOG_PREPEND_UPTIME && !OPENTHREAD_CONFIG_UPTIME_ENABLE
+#error "OPENTHREAD_CONFIG_LOG_PREPEND_UPTIME requires OPENTHREAD_CONFIG_UPTIME_ENABLE"
+#endif
+
+#if OPENTHREAD_CONFIG_LOG_PREPEND_UPTIME && OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
+#error "OPENTHREAD_CONFIG_LOG_PREPEND_UPTIME is not supported under OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE"
+#endif
+
+namespace ot {
+
+#if OT_SHOULD_LOG
+
+template <LogLevel kLogLevel> void Logger::LogAtLevel(const char *aModuleName, const char *aFormat, ...)
+{
+    va_list args;
+
+    va_start(args, aFormat);
+    LogVarArgs(aModuleName, kLogLevel, aFormat, args);
+    va_end(args);
+}
+
+// Explicit instantiations
+template void Logger::LogAtLevel<kLogLevelNone>(const char *aModuleName, const char *aFormat, ...);
+template void Logger::LogAtLevel<kLogLevelCrit>(const char *aModuleName, const char *aFormat, ...);
+template void Logger::LogAtLevel<kLogLevelWarn>(const char *aModuleName, const char *aFormat, ...);
+template void Logger::LogAtLevel<kLogLevelNote>(const char *aModuleName, const char *aFormat, ...);
+template void Logger::LogAtLevel<kLogLevelInfo>(const char *aModuleName, const char *aFormat, ...);
+template void Logger::LogAtLevel<kLogLevelDebg>(const char *aModuleName, const char *aFormat, ...);
+
+void Logger::LogInModule(const char *aModuleName, LogLevel aLogLevel, const char *aFormat, ...)
+{
+    va_list args;
+
+    va_start(args, aFormat);
+    LogVarArgs(aModuleName, aLogLevel, aFormat, args);
+    va_end(args);
+}
+
+void Logger::LogVarArgs(const char *aModuleName, LogLevel aLogLevel, const char *aFormat, va_list aArgs)
+{
+    static const char kModuleNamePadding[] = "--------------";
+
+    ot::String<OPENTHREAD_CONFIG_LOG_MAX_SIZE> logString;
+
+    static_assert(sizeof(kModuleNamePadding) == kMaxLogModuleNameLength + 1, "Padding string is not correct");
+
+#if OPENTHREAD_CONFIG_LOG_PREPEND_UPTIME
+    ot::Uptime::UptimeToString(ot::Instance::Get().Get<ot::Uptime>().GetUptime(), logString);
+    logString.Append(" ");
+#endif
+
+#if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
+    VerifyOrExit(Instance::GetLogLevel() >= aLogLevel);
+#endif
+
+#if OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL
+    {
+        static const char kLevelChars[] = {
+            '-', /* kLogLevelNone */
+            'C', /* kLogLevelCrit */
+            'W', /* kLogLevelWarn */
+            'N', /* kLogLevelNote */
+            'I', /* kLogLevelInfo */
+            'D', /* kLogLevelDebg */
+        };
+
+        logString.Append("[%c] ", kLevelChars[aLogLevel]);
+    }
+#endif
+
+    logString.Append("%.*s%s: ", kMaxLogModuleNameLength, aModuleName,
+                     &kModuleNamePadding[StringLength(aModuleName, kMaxLogModuleNameLength)]);
+
+    logString.AppendVarArgs(aFormat, aArgs);
+
+    logString.Append("%s", OPENTHREAD_CONFIG_LOG_SUFFIX);
+    otPlatLog(aLogLevel, OT_LOG_REGION_CORE, "%s", logString.AsCString());
+
+    ExitNow();
+
+exit:
+    return;
+}
+
+#if OPENTHREAD_CONFIG_LOG_PKT_DUMP
+
+template <LogLevel kLogLevel>
+void Logger::DumpAtLevel(const char *aModuleName, const char *aText, const void *aData, uint16_t aDataLength)
+{
+    DumpInModule(aModuleName, kLogLevel, aText, aData, aDataLength);
+}
+
+// Explicit instantiations
+template void Logger::DumpAtLevel<kLogLevelNone>(const char *aModuleName,
+                                                 const char *aText,
+                                                 const void *aData,
+                                                 uint16_t    aDataLength);
+template void Logger::DumpAtLevel<kLogLevelCrit>(const char *aModuleName,
+                                                 const char *aText,
+                                                 const void *aData,
+                                                 uint16_t    aDataLength);
+template void Logger::DumpAtLevel<kLogLevelWarn>(const char *aModuleName,
+                                                 const char *aText,
+                                                 const void *aData,
+                                                 uint16_t    aDataLength);
+template void Logger::DumpAtLevel<kLogLevelNote>(const char *aModuleName,
+                                                 const char *aText,
+                                                 const void *aData,
+                                                 uint16_t    aDataLength);
+template void Logger::DumpAtLevel<kLogLevelInfo>(const char *aModuleName,
+                                                 const char *aText,
+                                                 const void *aData,
+                                                 uint16_t    aDataLength);
+template void Logger::DumpAtLevel<kLogLevelDebg>(const char *aModuleName,
+                                                 const char *aText,
+                                                 const void *aData,
+                                                 uint16_t    aDataLength);
+
+void Logger::DumpLine(const char *aModuleName, LogLevel aLogLevel, const uint8_t *aData, const uint16_t aDataLength)
+{
+    ot::String<kStringLineLength> string;
+
+    string.Append("|");
+
+    for (uint8_t i = 0; i < kDumpBytesPerLine; i++)
+    {
+        if (i < aDataLength)
+        {
+            string.Append(" %02X", aData[i]);
+        }
+        else
+        {
+            string.Append(" ..");
+        }
+
+        if (!((i + 1) % 8))
+        {
+            string.Append(" |");
+        }
+    }
+
+    string.Append(" ");
+
+    for (uint8_t i = 0; i < kDumpBytesPerLine; i++)
+    {
+        char c = '.';
+
+        if (i < aDataLength)
+        {
+            char byteAsChar = static_cast<char>(0x7f & aData[i]);
+
+            if (isprint(byteAsChar))
+            {
+                c = byteAsChar;
+            }
+        }
+
+        string.Append("%c", c);
+    }
+
+    LogInModule(aModuleName, aLogLevel, "%s", string.AsCString());
+}
+
+void Logger::DumpInModule(const char *aModuleName,
+                          LogLevel    aLogLevel,
+                          const char *aText,
+                          const void *aData,
+                          uint16_t    aDataLength)
+{
+    constexpr uint16_t kWidth         = 72;
+    constexpr uint16_t kTextSuffixLen = sizeof("[ len=000]") - 1;
+
+    uint16_t                      txtLen = StringLength(aText, kWidth - kTextSuffixLen) + kTextSuffixLen;
+    ot::String<kStringLineLength> string;
+
+    VerifyOrExit(otLoggingGetLevel() >= aLogLevel);
+
+    for (uint16_t i = 0; i < static_cast<uint16_t>((kWidth - txtLen) / 2); i++)
+    {
+        string.Append("=");
+    }
+
+    string.Append("[%s len=%03u]", aText, aDataLength);
+
+    for (uint16_t i = 0; i < static_cast<uint16_t>(kWidth - txtLen - (kWidth - txtLen) / 2); i++)
+    {
+        string.Append("=");
+    }
+
+    LogInModule(aModuleName, aLogLevel, "%s", string.AsCString());
+
+    for (uint16_t i = 0; i < aDataLength; i += kDumpBytesPerLine)
+    {
+        DumpLine(aModuleName, aLogLevel, static_cast<const uint8_t *>(aData) + i,
+                 OT_MIN((aDataLength - i), kDumpBytesPerLine));
+    }
+
+    string.Clear();
+
+    for (uint16_t i = 0; i < kWidth; i++)
+    {
+        string.Append("-");
+    }
+
+    LogInModule(aModuleName, aLogLevel, "%s", string.AsCString());
+
+exit:
+    return;
+}
+#endif // OPENTHREAD_CONFIG_LOG_PKT_DUMP
+
+#endif // OT_SHOULD_LOG
+
+} // namespace ot
diff --git a/src/core/common/log.hpp b/src/core/common/log.hpp
new file mode 100644
index 0000000..0870e06
--- /dev/null
+++ b/src/core/common/log.hpp
@@ -0,0 +1,379 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes logging related  definitions.
+ */
+
+#ifndef LOG_HPP_
+#define LOG_HPP_
+
+#include "openthread-core-config.h"
+
+#include <openthread/logging.h>
+#include <openthread/platform/logging.h>
+#include <openthread/platform/toolchain.h>
+
+namespace ot {
+
+/**
+ * @def OT_SHOULD_LOG
+ *
+ * This definition indicates whether or not logging is enabled.
+ *
+ */
+#define OT_SHOULD_LOG (OPENTHREAD_CONFIG_LOG_OUTPUT != OPENTHREAD_CONFIG_LOG_OUTPUT_NONE)
+
+/**
+ * This macro indicates whether the OpenThread logging is enabled at a given log level.
+ *
+ * @param[in] aLevel   The log level to check.
+ *
+ * @returns TRUE if logging is enabled at @p aLevel, FALSE otherwise.
+ *
+ */
+#define OT_SHOULD_LOG_AT(aLevel) (OT_SHOULD_LOG && (OPENTHREAD_CONFIG_LOG_LEVEL >= (aLevel)))
+
+/**
+ * This enumeration represents the log level.
+ *
+ */
+enum LogLevel : uint8_t
+{
+    kLogLevelNone = OT_LOG_LEVEL_NONE, ///< None (disable logs)
+    kLogLevelCrit = OT_LOG_LEVEL_CRIT, ///< Critical log level
+    kLogLevelWarn = OT_LOG_LEVEL_WARN, ///< Warning log level
+    kLogLevelNote = OT_LOG_LEVEL_NOTE, ///< Note log level
+    kLogLevelInfo = OT_LOG_LEVEL_INFO, ///< Info log level
+    kLogLevelDebg = OT_LOG_LEVEL_DEBG, ///< Debug log level
+};
+
+constexpr uint8_t kMaxLogModuleNameLength = 14; ///< Maximum module name length
+
+#if OT_SHOULD_LOG && (OPENTHREAD_CONFIG_LOG_LEVEL != OT_LOG_LEVEL_NONE)
+/**
+ * This macro registers log module name.
+ *
+ * This macro is used in a `cpp` file to register the log module name for that file before using any other logging
+ * functions or macros (e.g., `LogInfo()` or `DumpInfo()`, ...) in the file.
+ *
+ * @param[in] aName  The log module name string (MUST be shorter than `kMaxLogModuleNameLength`).
+ *
+ */
+#define RegisterLogModule(aName)                                     \
+    constexpr char kLogModuleName[] = aName;                         \
+    namespace {                                                      \
+    /* Defining this type to silence "unused constant" warning/error \
+     * for `kLogModuleName` under any log level config.              \
+     */                                                              \
+    using DummyType = char[sizeof(kLogModuleName)];                  \
+    }                                                                \
+    static_assert(sizeof(kLogModuleName) <= kMaxLogModuleNameLength + 1, "Log module name is too long")
+
+#else
+#define RegisterLogModule(aName) static_assert(true, "Consume the required semi-colon at the end of macro")
+#endif
+
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_CRIT)
+/**
+ * This macro emits a log message at critical log level.
+ *
+ * @param[in]  ...   Arguments for the format specification.
+ *
+ */
+#define LogCrit(...) Logger::Log<kLogLevelCrit, kLogModuleName>(__VA_ARGS__)
+#else
+#define LogCrit(...)
+#endif
+
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
+/**
+ * This macro emits a log message at warning log level.
+ *
+ * @param[in]  ...   Arguments for the format specification.
+ *
+ */
+#define LogWarn(...) Logger::Log<kLogLevelWarn, kLogModuleName>(__VA_ARGS__)
+#else
+#define LogWarn(...)
+#endif
+
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
+/**
+ * This macro emits a log message at note log level.
+ *
+ * @param[in]  ...   Arguments for the format specification.
+ *
+ */
+#define LogNote(...) Logger::Log<kLogLevelNote, kLogModuleName>(__VA_ARGS__)
+#else
+#define LogNote(...)
+#endif
+
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
+/**
+ * This macro emits a log message at info log level.
+ *
+ * @param[in]  ...   Arguments for the format specification.
+ *
+ */
+#define LogInfo(...) Logger::Log<kLogLevelInfo, kLogModuleName>(__VA_ARGS__)
+#else
+#define LogInfo(...)
+#endif
+
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_DEBG)
+/**
+ * This macro emits a log message at debug log level.
+ *
+ * @param[in]  ...   Arguments for the format specification.
+ *
+ */
+#define LogDebg(...) Logger::Log<kLogLevelDebg, kLogModuleName>(__VA_ARGS__)
+#else
+#define LogDebg(...)
+#endif
+
+#if OT_SHOULD_LOG
+/**
+ * This macro emits a log message at a given log level.
+ *
+ * @param[in] aLogLevel  The log level to use.
+ * @param[in] ...        Argument for the format specification.
+ *
+ */
+#define LogAt(aLogLevel, ...) Logger::LogInModule(kLogModuleName, aLogLevel, __VA_ARGS__)
+#else
+#define LogAt(aLogLevel, ...)
+#endif
+
+#if OT_SHOULD_LOG
+/**
+ * This macro emits a log message independent of the configured log level.
+ *
+ * @param[in]  ...   Arguments for the format specification.
+ *
+ */
+#define LogAlways(...) Logger::LogInModule("", kLogLevelNone, __VA_ARGS__)
+#else
+#define LogAlways(...)
+#endif
+
+#if OT_SHOULD_LOG && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+/**
+ * This macro emit a log message for the certification test.
+ *
+ * @param[in]  ...  Arguments for the format specification.
+ *
+ */
+#define LogCert(...) LogAlways(__VA_ARGS__)
+#else
+#define LogCert(...)
+#endif
+
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_CRIT) && OPENTHREAD_CONFIG_LOG_PKT_DUMP
+/**
+ * This macro generates a memory dump at log level critical.
+ *
+ * @param[in]  aText         A string that is printed before the bytes.
+ * @param[in]  aData         A pointer to the data buffer.
+ * @param[in]  aDataLength   Number of bytes in @p aData.
+ *
+ */
+#define DumpCrit(aText, aData, aDataLength) Logger::Dump<kLogLevelCrit, kLogModuleName>(aText, aData, aDataLength)
+#else
+#define DumpCrit(aText, aData, aDataLength)
+#endif
+
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN) && OPENTHREAD_CONFIG_LOG_PKT_DUMP
+/**
+ * This macro generates a memory dump at log level warning.
+ *
+ * @param[in]  aText         A string that is printed before the bytes.
+ * @param[in]  aData         A pointer to the data buffer.
+ * @param[in]  aDataLength   Number of bytes in @p aData.
+ *
+ */
+#define DumpWarn(aText, aData, aDataLength) Logger::Dump<kLogLevelWarn, kLogModuleName>(aText, aData, aDataLength)
+#else
+#define DumpWarn(aText, aData, aDataLength)
+#endif
+
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE) && OPENTHREAD_CONFIG_LOG_PKT_DUMP
+/**
+ * This macro generates a memory dump at log level note.
+ *
+ * @param[in]  aText         A string that is printed before the bytes.
+ * @param[in]  aData         A pointer to the data buffer.
+ * @param[in]  aDataLength   Number of bytes in @p aData.
+ *
+ */
+#define DumpNote(aText, aData, aDataLength) Logger::Dump<kLogLevelNote, kLogModuleName>(aText, aData, aDataLength)
+#else
+#define DumpNote(aText, aData, aDataLength)
+#endif
+
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) && OPENTHREAD_CONFIG_LOG_PKT_DUMP
+/**
+ * This macro generates a memory dump at log level info.
+ *
+ * @param[in]  aText         A string that is printed before the bytes.
+ * @param[in]  aData         A pointer to the data buffer.
+ * @param[in]  aDataLength   Number of bytes in @p aData.
+ *
+ */
+#define DumpInfo(aText, aData, aDataLength) Logger::Dump<kLogLevelInfo, kLogModuleName>(aText, aData, aDataLength)
+#else
+#define DumpInfo(aText, aData, aDataLength)
+#endif
+
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_DEBG) && OPENTHREAD_CONFIG_LOG_PKT_DUMP
+/**
+ * This macro generates a memory dump at log level debug.
+ *
+ * @param[in]  aText         A string that is printed before the bytes.
+ * @param[in]  aData         A pointer to the data buffer.
+ * @param[in]  aDataLength   Number of bytes in @p aData.
+ *
+ */
+#define DumpDebg(aText, aData, aDataLength) Logger::Dump<kLogLevelDebg, kLogModuleName>(aText, aData, aDataLength)
+#else
+#define DumpDebg(aText, aData, aDataLength)
+#endif
+
+#if OT_SHOULD_LOG && OPENTHREAD_CONFIG_LOG_PKT_DUMP
+/**
+ * This macro generates a memory dump independent of the configured log level.
+ *
+ * @param[in]  aText         A string that is printed before the bytes.
+ * @param[in]  aData         A pointer to the data buffer.
+ * @param[in]  aDataLength   Number of bytes in @p aData.
+ *
+ */
+#define DumpAlways(aText, aData, aDataLength) Logger::DumpInModule("", kLogLevelNone, aText, aData, aDataLength)
+#endif
+
+#if OT_SHOULD_LOG && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE && OPENTHREAD_CONFIG_LOG_PKT_DUMP
+/**
+ * This macro generates a memory dump for certification test.
+ *
+ * @param[in]  aText         A string that is printed before the bytes.
+ * @param[in]  aData         A pointer to the data buffer.
+ * @param[in]  aDataLength   Number of bytes in @p aData.
+ *
+ */
+#define DumpCert(aText, aData, aDataLength) DumpAlways(aText, aData, aDataLength)
+#else
+#define DumpCert(aText, aData, aDataLength)
+#endif
+
+//----------------------------------------------------------------------------------------------------------------------
+
+#if OT_SHOULD_LOG
+
+class Logger
+{
+    // The `Logger` class implements the logging methods.
+    //
+    // The `Logger` methods are not intended to be directly used
+    // and instead the logging macros should be used.
+
+public:
+    template <LogLevel kLogLevel, const char *kModuleName, typename... Args>
+    static void Log(const char *aFormat, Args... aArgs)
+    {
+        LogAtLevel<kLogLevel>(kModuleName, aFormat, aArgs...);
+    }
+
+    static void LogInModule(const char *aModuleName, LogLevel aLogLevel, const char *aFormat, ...);
+
+    template <LogLevel kLogLevel> static void LogAtLevel(const char *aModuleName, const char *aFormat, ...);
+    static void LogVarArgs(const char *aModuleName, LogLevel aLogLevel, const char *aFormat, va_list aArgs);
+
+#if OPENTHREAD_CONFIG_LOG_PKT_DUMP
+    static constexpr uint8_t kStringLineLength = 80;
+    static constexpr uint8_t kDumpBytesPerLine = 16;
+
+    template <LogLevel kLogLevel, const char *kModuleName>
+    static void Dump(const char *aText, const void *aData, uint16_t aDataLength)
+    {
+        DumpAtLevel<kLogLevel>(kModuleName, aText, aData, aDataLength);
+    }
+
+    static void DumpInModule(const char *aModuleName,
+                             LogLevel    aLogLevel,
+                             const char *aText,
+                             const void *aData,
+                             uint16_t    aDataLength);
+
+    template <LogLevel kLogLevel>
+    static void DumpAtLevel(const char *aModuleName, const char *aText, const void *aData, uint16_t aDataLength);
+
+    static void DumpLine(const char *aModuleName, LogLevel aLogLevel, const uint8_t *aData, uint16_t aDataLength);
+#endif
+};
+
+extern template void Logger::LogAtLevel<kLogLevelNone>(const char *aModuleName, const char *aFormat, ...);
+extern template void Logger::LogAtLevel<kLogLevelCrit>(const char *aModuleName, const char *aFormat, ...);
+extern template void Logger::LogAtLevel<kLogLevelWarn>(const char *aModuleName, const char *aFormat, ...);
+extern template void Logger::LogAtLevel<kLogLevelNote>(const char *aModuleName, const char *aFormat, ...);
+extern template void Logger::LogAtLevel<kLogLevelInfo>(const char *aModuleName, const char *aFormat, ...);
+extern template void Logger::LogAtLevel<kLogLevelDebg>(const char *aModuleName, const char *aFormat, ...);
+
+#if OPENTHREAD_CONFIG_LOG_PKT_DUMP
+extern template void Logger::DumpAtLevel<kLogLevelNone>(const char *aModuleName,
+                                                        const char *aText,
+                                                        const void *aData,
+                                                        uint16_t    aDataLength);
+extern template void Logger::DumpAtLevel<kLogLevelCrit>(const char *aModuleName,
+                                                        const char *aText,
+                                                        const void *aData,
+                                                        uint16_t    aDataLength);
+extern template void Logger::DumpAtLevel<kLogLevelWarn>(const char *aModuleName,
+                                                        const char *aText,
+                                                        const void *aData,
+                                                        uint16_t    aDataLength);
+extern template void Logger::DumpAtLevel<kLogLevelNote>(const char *aModuleName,
+                                                        const char *aText,
+                                                        const void *aData,
+                                                        uint16_t    aDataLength);
+extern template void Logger::DumpAtLevel<kLogLevelInfo>(const char *aModuleName,
+                                                        const char *aText,
+                                                        const void *aData,
+                                                        uint16_t    aDataLength);
+extern template void Logger::DumpAtLevel<kLogLevelDebg>(const char *aModuleName,
+                                                        const char *aText,
+                                                        const void *aData,
+                                                        uint16_t    aDataLength);
+#endif // OPENTHREAD_CONFIG_LOG_PKT_DUMP
+#endif // OT_SHOULD_LOG
+
+} // namespace ot
+
+#endif // LOG_HPP_
diff --git a/src/core/common/logging.cpp b/src/core/common/logging.cpp
deleted file mode 100644
index 24df506..0000000
--- a/src/core/common/logging.cpp
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- *  Copyright (c) 2016, The OpenThread Authors.
- *  All rights reserved.
- *
- *  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, 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
- *   This file implements the logging related functions.
- */
-
-#include "logging.hpp"
-
-#include "common/code_utils.hpp"
-#include "common/instance.hpp"
-#include "common/string.hpp"
-
-/*
- * Verify debug uart dependency.
- *
- * It is reasonable to only enable the debug uart and not enable logs to the DEBUG uart.
- */
-#if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_DEBUG_UART) && (!OPENTHREAD_CONFIG_ENABLE_DEBUG_UART)
-#error "OPENTHREAD_CONFIG_ENABLE_DEBUG_UART_LOG requires OPENTHREAD_CONFIG_ENABLE_DEBUG_UART"
-#endif
-
-#if OPENTHREAD_CONFIG_LOG_PREPEND_UPTIME && !OPENTHREAD_CONFIG_UPTIME_ENABLE
-#error "OPENTHREAD_CONFIG_LOG_PREPEND_UPTIME requires OPENTHREAD_CONFIG_UPTIME_ENABLE"
-#endif
-
-#if OPENTHREAD_CONFIG_LOG_PREPEND_UPTIME && OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
-#error "OPENTHREAD_CONFIG_LOG_PREPEND_UPTIME is not supported under OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE"
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if !OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
-
-static void Log(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, va_list aArgs)
-{
-    ot::String<OPENTHREAD_CONFIG_LOG_MAX_SIZE> logString;
-
-#if OPENTHREAD_CONFIG_LOG_PREPEND_UPTIME
-    ot::Uptime::UptimeToString(ot::Instance::Get().Get<ot::Uptime>().GetUptime(), logString);
-    logString.Append(" ");
-#endif
-
-#if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
-    VerifyOrExit(otLoggingGetLevel() >= aLogLevel);
-#endif
-
-#if OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL
-    logString.Append("%s", otLogLevelToPrefixString(aLogLevel));
-#endif
-
-#if OPENTHREAD_CONFIG_LOG_PREPEND_REGION
-    {
-        static const char *const kRegionPrefixStrings[] = {
-            _OT_REGION_SUFFIX,          _OT_REGION_API_PREFIX,      _OT_REGION_MLE_PREFIX,  _OT_REGION_ARP_PREFIX,
-            _OT_REGION_NET_DATA_PREFIX, _OT_REGION_ICMP_PREFIX,     _OT_REGION_IP6_PREFIX,  _OT_REGION_TCP_PREFIX,
-            _OT_REGION_MAC_PREFIX,      _OT_REGION_MEM_PREFIX,      _OT_REGION_NCP_PREFIX,  _OT_REGION_MESH_COP_PREFIX,
-            _OT_REGION_NET_DIAG_PREFIX, _OT_REGION_PLATFORM_PREFIX, _OT_REGION_COAP_PREFIX, _OT_REGION_CLI_PREFIX,
-            _OT_REGION_CORE_PREFIX,     _OT_REGION_UTIL_PREFIX,     _OT_REGION_BBR_PREFIX,  _OT_REGION_MLR_PREFIX,
-            _OT_REGION_DUA_PREFIX,      _OT_REGION_BR_PREFIX,       _OT_REGION_SRP_PREFIX,  _OT_REGION_DNS_PREFIX,
-        };
-
-        if (aLogRegion < OT_ARRAY_LENGTH(kRegionPrefixStrings))
-        {
-            logString.Append("%s", kRegionPrefixStrings[aLogRegion]);
-        }
-        else
-        {
-            logString.Append("%s", _OT_REGION_SUFFIX);
-        }
-    }
-#else
-    logString.Append("%s", _OT_REGION_SUFFIX);
-#endif
-
-    logString.AppendVarArgs(aFormat, aArgs);
-    otPlatLog(aLogLevel, aLogRegion, "%s" OPENTHREAD_CONFIG_LOG_SUFFIX, logString.AsCString());
-
-#if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
-exit:
-    return;
-#endif
-}
-
-#if OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_CRIT
-void _otLogCrit(otLogRegion aRegion, const char *aFormat, ...)
-{
-    va_list args;
-
-    va_start(args, aFormat);
-    Log(OT_LOG_LEVEL_CRIT, aRegion, aFormat, args);
-    va_end(args);
-}
-#endif
-
-#if OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN
-void _otLogWarn(otLogRegion aRegion, const char *aFormat, ...)
-{
-    va_list args;
-
-    va_start(args, aFormat);
-    Log(OT_LOG_LEVEL_WARN, aRegion, aFormat, args);
-    va_end(args);
-}
-#endif
-
-#if OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE
-void _otLogNote(otLogRegion aRegion, const char *aFormat, ...)
-{
-    va_list args;
-
-    va_start(args, aFormat);
-    Log(OT_LOG_LEVEL_NOTE, aRegion, aFormat, args);
-    va_end(args);
-}
-#endif
-
-#if OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO
-void _otLogInfo(otLogRegion aRegion, const char *aFormat, ...)
-{
-    va_list args;
-
-    va_start(args, aFormat);
-    Log(OT_LOG_LEVEL_INFO, aRegion, aFormat, args);
-    va_end(args);
-}
-#endif
-
-#if OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_DEBG
-void _otLogDebg(otLogRegion aRegion, const char *aFormat, ...)
-{
-    va_list args;
-
-    va_start(args, aFormat);
-    Log(OT_LOG_LEVEL_DEBG, aRegion, aFormat, args);
-    va_end(args);
-}
-#endif
-
-#if OPENTHREAD_CONFIG_LOG_MAC
-void otLogMac(otLogLevel aLogLevel, const char *aFormat, ...)
-{
-    va_list args;
-
-    VerifyOrExit(otLoggingGetLevel() >= aLogLevel);
-
-    va_start(args, aFormat);
-    Log(aLogLevel, OT_LOG_REGION_MAC, aFormat, args);
-    va_end(args);
-
-exit:
-    return;
-}
-
-void otDumpMacFrame(otLogLevel aLogLevel, const char *aId, const void *aBuf, const size_t aLength)
-{
-    constexpr uint8_t kFixedStringPart = 10; // strlen(" seqno=000")
-    constexpr uint8_t kSeqnoIdx        = 2;  // index of the sequence number within aBuf
-
-    size_t idLength = strlen(aId) + kFixedStringPart + 1; // allow for the '\0' character
-    char   newId[25];
-
-    VerifyOrExit(idLength <= sizeof(newId));
-    snprintf(newId, idLength, "%s seqno=%03u", aId, static_cast<const uint8_t *>(aBuf)[kSeqnoIdx]);
-    otDump(aLogLevel, OT_LOG_REGION_MAC, newId, aBuf, aLength);
-exit:
-    return;
-}
-#endif
-
-#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-void otLogCertMeshCoP(const char *aFormat, ...)
-{
-    va_list args;
-
-    va_start(args, aFormat);
-    Log(OT_LOG_LEVEL_NONE, OT_LOG_REGION_MESH_COP, aFormat, args);
-    va_end(args);
-}
-#endif
-
-#if OPENTHREAD_CONFIG_OTNS_ENABLE
-void otLogOtns(const char *aFormat, ...)
-{
-    va_list args;
-
-    va_start(args, aFormat);
-    Log(OT_LOG_LEVEL_NONE, OT_LOG_REGION_CORE, aFormat, args);
-    va_end(args);
-}
-#endif
-
-#endif // #if !OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
-
-#if OPENTHREAD_CONFIG_LOG_PKT_DUMP
-
-#if OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
-#define otLogDump(aLogLevel, aLogRegion, aFormat, ...) \
-    _otDynamicLog(aLogLevel, aLogRegion, aFormat OPENTHREAD_CONFIG_LOG_SUFFIX, __VA_ARGS__)
-#else
-static void otLogDump(otLogLevel aLogLevel, otLogRegion aRegion, const char *aFormat, ...)
-{
-    va_list args;
-
-    VerifyOrExit(otLoggingGetLevel() >= aLogLevel);
-
-    va_start(args, aFormat);
-    Log(aLogLevel, aRegion, aFormat, args);
-    va_end(args);
-
-exit:
-    return;
-}
-#endif
-
-static constexpr uint8_t kStringLineLength = 80;
-static constexpr uint8_t kDumpBytesPerLine = 16;
-
-static void DumpLine(otLogLevel aLogLevel, otLogRegion aLogRegion, const uint8_t *aBytes, const size_t aLength)
-{
-    ot::String<kStringLineLength> string;
-
-    string.Append("|");
-
-    for (uint8_t i = 0; i < kDumpBytesPerLine; i++)
-    {
-        if (i < aLength)
-        {
-            string.Append(" %02X", aBytes[i]);
-        }
-        else
-        {
-            string.Append(" ..");
-        }
-
-        if (!((i + 1) % 8))
-        {
-            string.Append(" |");
-        }
-    }
-
-    string.Append(" ");
-
-    for (uint8_t i = 0; i < kDumpBytesPerLine; i++)
-    {
-        char c = '.';
-
-        if (i < aLength)
-        {
-            char byteAsChar = static_cast<char>(0x7f & aBytes[i]);
-
-            if (isprint(byteAsChar))
-            {
-                c = byteAsChar;
-            }
-        }
-
-        string.Append("%c", c);
-    }
-
-    otLogDump(aLogLevel, aLogRegion, "%s", string.AsCString());
-}
-
-void otDump(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aId, const void *aBuf, const size_t aLength)
-{
-    constexpr uint8_t kWidth           = 72;
-    constexpr uint8_t kFixedStringPart = 10; // strlen("[ len=000]")
-
-    size_t                        idLen = strlen(aId) + kFixedStringPart;
-    ot::String<kStringLineLength> string;
-
-    for (size_t i = 0; i < (kWidth - idLen) / 2; i++)
-    {
-        string.Append("=");
-    }
-
-    string.Append("[%s len=%03u]", aId, static_cast<unsigned>(aLength));
-
-    for (size_t i = 0; i < kWidth - idLen - (kWidth - idLen) / 2; i++)
-    {
-        string.Append("=");
-    }
-
-    otLogDump(aLogLevel, aLogRegion, "%s", string.AsCString());
-
-    for (size_t i = 0; i < aLength; i += kDumpBytesPerLine)
-    {
-        DumpLine(aLogLevel, aLogRegion, static_cast<const uint8_t *>(aBuf) + i,
-                 OT_MIN((aLength - i), static_cast<size_t>(kDumpBytesPerLine)));
-    }
-
-    string.Clear();
-
-    for (size_t i = 0; i < kWidth; i++)
-    {
-        string.Append("-");
-    }
-
-    otLogDump(aLogLevel, aLogRegion, "%s", string.AsCString());
-}
-#else  // OPENTHREAD_CONFIG_LOG_PKT_DUMP
-void otDump(otLogLevel, otLogRegion, const char *, const void *, const size_t)
-{
-}
-#endif // OPENTHREAD_CONFIG_LOG_PKT_DUMP
-
-#if OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY || OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL
-
-const char *otLogLevelToPrefixString(otLogLevel aLogLevel)
-{
-    static const char *const kLevelStrings[] = {
-        _OT_LEVEL_NONE_PREFIX, _OT_LEVEL_CRIT_PREFIX, _OT_LEVEL_WARN_PREFIX,
-        _OT_LEVEL_NOTE_PREFIX, _OT_LEVEL_INFO_PREFIX, _OT_LEVEL_DEBG_PREFIX,
-    };
-
-    return ((aLogLevel >= 0) && (aLogLevel < static_cast<int>(OT_ARRAY_LENGTH(kLevelStrings))))
-               ? kLevelStrings[aLogLevel]
-               : "";
-}
-#endif
-
-#if OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_NONE
-/* this provides a stub, in case something uses the function */
-void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
-{
-    OT_UNUSED_VARIABLE(aLogLevel);
-    OT_UNUSED_VARIABLE(aLogRegion);
-    OT_UNUSED_VARIABLE(aFormat);
-}
-#endif
-
-OT_TOOL_WEAK void otPlatLogLine(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aLogLine)
-{
-    otPlatLog(aLogLevel, aLogRegion, "%s", aLogLine);
-}
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/src/core/common/logging.hpp b/src/core/common/logging.hpp
index 21243df..56016bc 100644
--- a/src/core/common/logging.hpp
+++ b/src/core/common/logging.hpp
@@ -36,2759 +36,7 @@
 
 #include "openthread-core-config.h"
 
-#include <ctype.h>
-#include <stdio.h>
-
 #include <openthread/logging.h>
 #include <openthread/platform/logging.h>
 
-#include "common/arg_macros.hpp"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Log level prefix string definitions.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL
-#define _OT_LEVEL_NONE_PREFIX "[NONE]"
-#define _OT_LEVEL_CRIT_PREFIX "[CRIT]"
-#define _OT_LEVEL_WARN_PREFIX "[WARN]"
-#define _OT_LEVEL_NOTE_PREFIX "[NOTE]"
-#define _OT_LEVEL_INFO_PREFIX "[INFO]"
-#define _OT_LEVEL_DEBG_PREFIX "[DEBG]"
-#define _OT_REGION_SUFFIX ": "
-#else
-#define _OT_LEVEL_NONE_PREFIX ""
-#define _OT_LEVEL_CRIT_PREFIX ""
-#define _OT_LEVEL_WARN_PREFIX ""
-#define _OT_LEVEL_NOTE_PREFIX ""
-#define _OT_LEVEL_INFO_PREFIX ""
-#define _OT_LEVEL_DEBG_PREFIX ""
-#define _OT_REGION_SUFFIX ""
-#endif
-
-/**
- * Log region prefix string definitions.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_PREPEND_REGION
-#define _OT_REGION_API_PREFIX "-API-----: "
-#define _OT_REGION_MLE_PREFIX "-MLE-----: "
-#define _OT_REGION_ARP_PREFIX "-ARP-----: "
-#define _OT_REGION_NET_DATA_PREFIX "-N-DATA--: "
-#define _OT_REGION_ICMP_PREFIX "-ICMP----: "
-#define _OT_REGION_IP6_PREFIX "-IP6-----: "
-#define _OT_REGION_TCP_PREFIX "-TCP-----: "
-#define _OT_REGION_MAC_PREFIX "-MAC-----: "
-#define _OT_REGION_MEM_PREFIX "-MEM-----: "
-#define _OT_REGION_NCP_PREFIX "-NCP-----: "
-#define _OT_REGION_MESH_COP_PREFIX "-MESH-CP-: "
-#define _OT_REGION_NET_DIAG_PREFIX "-DIAG----: "
-#define _OT_REGION_PLATFORM_PREFIX "-PLAT----: "
-#define _OT_REGION_COAP_PREFIX "-COAP----: "
-#define _OT_REGION_CLI_PREFIX "-CLI-----: "
-#define _OT_REGION_CORE_PREFIX "-CORE----: "
-#define _OT_REGION_UTIL_PREFIX "-UTIL----: "
-#define _OT_REGION_BBR_PREFIX "-BBR-----: "
-#define _OT_REGION_MLR_PREFIX "-MLR-----: "
-#define _OT_REGION_DUA_PREFIX "-DUA-----: "
-#define _OT_REGION_BR_PREFIX "-BR------: "
-#define _OT_REGION_SRP_PREFIX "-SRP-----: "
-#define _OT_REGION_DNS_PREFIX "-DNS-----: "
-
-// When adding a new log region, please ensure to update the array
-// `kRegionPrefixStrings[]` in `Log()` function in `logging.cpp`.
-
-#else
-#define _OT_REGION_API_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_MLE_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_ARP_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_NET_DATA_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_ICMP_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_IP6_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_TCP_PREFIX _OT_REGION_PREFIX
-#define _OT_REGION_MAC_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_MEM_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_NCP_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_MESH_COP_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_NET_DIAG_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_PLATFORM_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_COAP_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_CLI_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_CORE_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_UTIL_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_BBR_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_MLR_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_DUA_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_BR_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_SRP_PREFIX _OT_REGION_SUFFIX
-#define _OT_REGION_DNS_PREFIX _OT_REGION_SUFFIX
-#endif
-
-/**
- * @def otLogCrit
- *
- * Logging at log level critical.
- *
- * @param[in]  aRegion   The log region.
- * @param[in]  ...       Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_LEVEL < OT_LOG_LEVEL_CRIT
-#define otLogCrit(aRegion, aRegionPrefix, ...)
-#elif OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
-#define otLogCrit(aRegion, aRegionPrefix, ...) \
-    _otLogFormatter(OT_LOG_LEVEL_CRIT, aRegion, _OT_LEVEL_CRIT_PREFIX aRegionPrefix __VA_ARGS__)
-#else
-#define otLogCrit(aRegion, aRegionPrefix, ...) _otLogCrit(aRegion, __VA_ARGS__)
-void _otLogCrit(otLogRegion aRegion, const char *aFormat, ...);
-#endif
-
-/**
- * @def otLogWarn
- *
- * Logging at log level warning.
- *
- * @param[in]  aRegion   The log region.
- * @param[in]  ...       Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_LEVEL < OT_LOG_LEVEL_WARN
-#define otLogWarn(aRegion, aRegionPrefix, ...)
-#elif OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
-#define otLogWarn(aRegion, aRegionPrefix, ...) \
-    _otLogFormatter(OT_LOG_LEVEL_WARN, aRegion, _OT_LEVEL_WARN_PREFIX aRegionPrefix __VA_ARGS__)
-#else
-#define otLogWarn(aRegion, aRegionPrefix, ...) _otLogWarn(aRegion, __VA_ARGS__)
-void _otLogWarn(otLogRegion aRegion, const char *aFormat, ...);
-#endif
-
-/**
- * @def otLogNote
- *
- * Logging at log level note
- *
- * @param[in]  aRegion   The log region.
- * @param[in]  ...       Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_LEVEL < OT_LOG_LEVEL_NOTE
-#define otLogNote(aRegion, aRegionPrefix, ...)
-#elif OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
-#define otLogNote(aRegion, aRegionPrefix, ...) \
-    _otLogFormatter(OT_LOG_LEVEL_NOTE, aRegion, _OT_LEVEL_NOTE_PREFIX aRegionPrefix __VA_ARGS__)
-#else
-#define otLogNote(aRegion, aRegionPrefix, ...) _otLogNote(aRegion, __VA_ARGS__)
-void _otLogNote(otLogRegion aRegion, const char *aFormat, ...);
-#endif
-
-/**
- * @def otLogInfo
- *
- * Logging at log level info.
- *
- * @param[in]  aRegion   The log region.
- * @param[in]  ...       Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_LEVEL < OT_LOG_LEVEL_INFO
-#define otLogInfo(aRegion, aRegionPrefix, ...)
-#elif OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
-#define otLogInfo(aRegion, aRegionPrefix, ...) \
-    _otLogFormatter(OT_LOG_LEVEL_INFO, aRegion, _OT_LEVEL_INFO_PREFIX aRegionPrefix __VA_ARGS__)
-#else
-#define otLogInfo(aRegion, aRegionPrefix, ...) _otLogInfo(aRegion, __VA_ARGS__)
-void _otLogInfo(otLogRegion aRegion, const char *aFormat, ...);
-#endif
-
-/**
- * @def otLogDebg
- *
- * Logging at log level debug.
- *
- * @param[in]  aRegion   The log region.
- * @param[in]  ...       Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_LEVEL < OT_LOG_LEVEL_DEBG
-#define otLogDebg(aRegion, aRegionPrefix, ...)
-#elif OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
-#define otLogDebg(aRegion, aRegionPrefix, ...) \
-    _otLogFormatter(OT_LOG_LEVEL_DEBG, aRegion, _OT_LEVEL_DEBG_PREFIX aRegionPrefix __VA_ARGS__)
-#else
-#define otLogDebg(aRegion, aRegionPrefix, ...) _otLogDebg(aRegion, __VA_ARGS__)
-void _otLogDebg(otLogRegion aRegion, const char *aFormat, ...);
-#endif
-
-/**
- * @def otLogCritApi
- *
- * This function generates a log with level critical for the API region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnApi
- *
- * This function generates a log with level warning for the API region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteApi
- *
- * This function generates a log with level note for the API region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoApi
- *
- * This function generates a log with level info for the API region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgApi
- *
- * This function generates a log with level debug for the API region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_API
-#define otLogCritApi(...) otLogCrit(OT_LOG_REGION_API, _OT_REGION_API_PREFIX, __VA_ARGS__)
-#define otLogWarnApi(...) otLogWarn(OT_LOG_REGION_API, _OT_REGION_API_PREFIX, __VA_ARGS__)
-#define otLogNoteApi(...) otLogNote(OT_LOG_REGION_API, _OT_REGION_API_PREFIX, __VA_ARGS__)
-#define otLogInfoApi(...) otLogInfo(OT_LOG_REGION_API, _OT_REGION_API_PREFIX, __VA_ARGS__)
-#define otLogDebgApi(...) otLogDebg(OT_LOG_REGION_API, _OT_REGION_API_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritApi(...)
-#define otLogWarnApi(...)
-#define otLogNoteApi(...)
-#define otLogInfoApi(...)
-#define otLogDebgApi(...)
-#endif
-
-/**
- * @def otLogCritMeshCoP
- *
- * This function generates a log with level critical for the MeshCoP region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- *
- */
-
-/**
- * @def otLogWarnMeshCoP
- *
- * This function generates a log with level warning for the MeshCoP region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteMeshCoP
- *
- * This function generates a log with level note for the MeshCoP region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoMeshCoP
- *
- * This function generates a log with level info for the MeshCoP region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgMeshCoP
- *
- * This function generates a log with level debug for the MeshCoP region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_MESHCOP
-#define otLogCritMeshCoP(...) otLogCrit(OT_LOG_REGION_MESH_COP, _OT_REGION_MESH_COP_PREFIX, __VA_ARGS__)
-#define otLogWarnMeshCoP(...) otLogWarn(OT_LOG_REGION_MESH_COP, _OT_REGION_MESH_COP_PREFIX, __VA_ARGS__)
-#define otLogNoteMeshCoP(...) otLogNote(OT_LOG_REGION_MESH_COP, _OT_REGION_MESH_COP_PREFIX, __VA_ARGS__)
-#define otLogInfoMeshCoP(...) otLogInfo(OT_LOG_REGION_MESH_COP, _OT_REGION_MESH_COP_PREFIX, __VA_ARGS__)
-#define otLogDebgMeshCoP(...) otLogDebg(OT_LOG_REGION_MESH_COP, _OT_REGION_MESH_COP_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritMeshCoP(...)
-#define otLogWarnMeshCoP(...)
-#define otLogNoteMeshCoP(...)
-#define otLogInfoMeshCoP(...)
-#define otLogDebgMeshCoP(...)
-#endif
-
-#define otLogCritMbedTls(...) otLogCritMeshCoP(__VA_ARGS__)
-#define otLogWarnMbedTls(...) otLogWarnMeshCoP(__VA_ARGS__)
-#define otLogNoteMbedTls(...) otLogNoteMeshCoP(__VA_ARGS__)
-#define otLogInfoMbedTls(...) otLogInfoMeshCoP(__VA_ARGS__)
-#define otLogDebgMbedTls(...) otLogDebgMeshCoP(__VA_ARGS__)
-
-/**
- * @def otLogCritBr
- *
- * This function generates a log with level critical for the BR region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnBr
- *
- * This function generates a log with level warning for the BR region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteBr
- *
- * This function generates a log with level note for the BR region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoBr
- *
- * This function generates a log with level info for the BR region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgBr
- *
- * This function generates a log with level debug for the BR region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_BR
-#define otLogCritBr(...) otLogCrit(OT_LOG_REGION_BR, _OT_REGION_BR_PREFIX, __VA_ARGS__)
-#define otLogWarnBr(...) otLogWarn(OT_LOG_REGION_BR, _OT_REGION_BR_PREFIX, __VA_ARGS__)
-#define otLogNoteBr(...) otLogNote(OT_LOG_REGION_BR, _OT_REGION_BR_PREFIX, __VA_ARGS__)
-#define otLogInfoBr(...) otLogInfo(OT_LOG_REGION_BR, _OT_REGION_BR_PREFIX, __VA_ARGS__)
-#define otLogDebgBr(...) otLogDebg(OT_LOG_REGION_BR, _OT_REGION_BR_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritBr(...)
-#define otLogWarnBr(...)
-#define otLogNoteBr(...)
-#define otLogInfoBr(...)
-#define otLogDebgBr(...)
-#endif
-
-/**
- * @def otLogCritMle
- *
- * This function generates a log with level critical for the MLE region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnMle
- *
- * This function generates a log with level warning for the MLE region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteMle
- *
- * This function generates a log with level note for the MLE region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoMle
- *
- * This function generates a log with level info for the MLE region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgMle
- *
- * This function generates a log with level debug for the MLE region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- *
- */
-#if OPENTHREAD_CONFIG_LOG_MLE
-#define otLogCritMle(...) otLogCrit(OT_LOG_REGION_MLE, _OT_REGION_MLE_PREFIX, __VA_ARGS__)
-#define otLogWarnMle(...) otLogWarn(OT_LOG_REGION_MLE, _OT_REGION_MLE_PREFIX, __VA_ARGS__)
-#define otLogNoteMle(...) otLogNote(OT_LOG_REGION_MLE, _OT_REGION_MLE_PREFIX, __VA_ARGS__)
-#define otLogInfoMle(...) otLogInfo(OT_LOG_REGION_MLE, _OT_REGION_MLE_PREFIX, __VA_ARGS__)
-#define otLogDebgMle(...) otLogDebg(OT_LOG_REGION_MLE, _OT_REGION_MLE_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritMle(...)
-#define otLogWarnMle(...)
-#define otLogNoteMle(...)
-#define otLogInfoMle(...)
-#define otLogDebgMle(...)
-#endif
-
-/**
- * @def otLogCritArp
- *
- * This function generates a log with level critical for the EID-to-RLOC mapping region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnArp
- *
- * This function generates a log with level warning for the EID-to-RLOC mapping region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteArp
- *
- * This function generates a log with level note for the EID-to-RLOC mapping region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoArp
- *
- * This function generates a log with level info for the EID-to-RLOC mapping region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgArp
- *
- * This function generates a log with level debug for the EID-to-RLOC mapping region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_ARP
-#define otLogCritArp(...) otLogCrit(OT_LOG_REGION_ARP, _OT_REGION_ARP_PREFIX, __VA_ARGS__)
-#define otLogWarnArp(...) otLogWarn(OT_LOG_REGION_ARP, _OT_REGION_ARP_PREFIX, __VA_ARGS__)
-#define otLogNoteArp(...) otLogNote(OT_LOG_REGION_ARP, _OT_REGION_ARP_PREFIX, __VA_ARGS__)
-#define otLogInfoArp(...) otLogInfo(OT_LOG_REGION_ARP, _OT_REGION_ARP_PREFIX, __VA_ARGS__)
-#define otLogDebgArp(...) otLogDebg(OT_LOG_REGION_ARP, _OT_REGION_ARP_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritArp(...)
-#define otLogWarnArp(...)
-#define otLogNoteArp(...)
-#define otLogInfoArp(...)
-#define otLogDebgArp(...)
-#endif
-
-/**
- * @def otLogCritBbr
- *
- * This function generates a log with level critical for the Backbone Router (BBR) region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnBbr
- *
- * This function generates a log with level warning for the Backbone Router (BBR) region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteBbr
- *
- * This function generates a log with level note for the Backbone Router (BBR) region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoBbr
- *
- * This function generates a log with level info for the Backbone Router (BBR) region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgBbr
- *
- * This function generates a log with level debug for the Backbone Router (BBR) region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_BBR
-#define otLogCritBbr(...) otLogCrit(OT_LOG_REGION_BBR, _OT_REGION_BBR_PREFIX, __VA_ARGS__)
-#define otLogWarnBbr(...) otLogWarn(OT_LOG_REGION_BBR, _OT_REGION_BBR_PREFIX, __VA_ARGS__)
-#define otLogNoteBbr(...) otLogNote(OT_LOG_REGION_BBR, _OT_REGION_BBR_PREFIX, __VA_ARGS__)
-#define otLogInfoBbr(...) otLogInfo(OT_LOG_REGION_BBR, _OT_REGION_BBR_PREFIX, __VA_ARGS__)
-#define otLogDebgBbr(...) otLogDebg(OT_LOG_REGION_BBR, _OT_REGION_BBR_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritBbr(...)
-#define otLogWarnBbr(...)
-#define otLogNoteBbr(...)
-#define otLogInfoBbr(...)
-#define otLogDebgBbr(...)
-#endif
-
-/**
- * @def otLogCritMlr
- *
- * This function generates a log with level critical for the Multicast Listener Registration (MLR) region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnMlr
- *
- * This function generates a log with level warning for the Multicast Listener Registration (MLR) region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteMlr
- *
- * This function generates a log with level note for the Multicast Listener Registration (MLR) region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoMlr
- *
- * This function generates a log with level info for the Multicast Listener Registration (MLR) region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgMlr
- *
- * This function generates a log with level debug for the Multicast Listener Registration (MLR) region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_MLR
-#define otLogCritMlr(...) otLogCrit(OT_LOG_REGION_MLR, _OT_REGION_MLR_PREFIX, __VA_ARGS__)
-#define otLogWarnMlr(...) otLogWarn(OT_LOG_REGION_MLR, _OT_REGION_MLR_PREFIX, __VA_ARGS__)
-#define otLogNoteMlr(...) otLogNote(OT_LOG_REGION_MLR, _OT_REGION_MLR_PREFIX, __VA_ARGS__)
-#define otLogInfoMlr(...) otLogInfo(OT_LOG_REGION_MLR, _OT_REGION_MLR_PREFIX, __VA_ARGS__)
-#define otLogDebgMlr(...) otLogDebg(OT_LOG_REGION_MLR, _OT_REGION_MLR_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritMlr(...)
-#define otLogWarnMlr(...)
-#define otLogNoteMlr(...)
-#define otLogInfoMlr(...)
-#define otLogDebgMlr(...)
-#endif
-
-/**
- * @def otLogCritNetData
- *
- * This function generates a log with level critical for the Network Data region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnNetData
- *
- * This function generates a log with level warning for the Network Data region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteNetData
- *
- * This function generates a log with level note for the Network Data region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoNetData
- *
- * This function generates a log with level info for the Network Data region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgNetData
- *
- * This function generates a log with level debug for the Network Data region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_NETDATA
-#define otLogCritNetData(...) otLogCrit(OT_LOG_REGION_NET_DATA, _OT_REGION_NET_DATA_PREFIX, __VA_ARGS__)
-#define otLogWarnNetData(...) otLogWarn(OT_LOG_REGION_NET_DATA, _OT_REGION_NET_DATA_PREFIX, __VA_ARGS__)
-#define otLogNoteNetData(...) otLogNote(OT_LOG_REGION_NET_DATA, _OT_REGION_NET_DATA_PREFIX, __VA_ARGS__)
-#define otLogInfoNetData(...) otLogInfo(OT_LOG_REGION_NET_DATA, _OT_REGION_NET_DATA_PREFIX, __VA_ARGS__)
-#define otLogDebgNetData(...) otLogDebg(OT_LOG_REGION_NET_DATA, _OT_REGION_NET_DATA_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritNetData(...)
-#define otLogWarnNetData(...)
-#define otLogNoteNetData(...)
-#define otLogInfoNetData(...)
-#define otLogDebgNetData(...)
-#endif
-
-/**
- * @def otLogCritIcmp
- *
- * This function generates a log with level critical for the ICMPv6 region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnIcmp
- *
- * This function generates a log with level warning for the ICMPv6 region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteIcmp
- *
- * This function generates a log with level note for the ICMPv6 region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoIcmp
- *
- * This function generates a log with level info for the ICMPv6 region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgIcmp
- *
- * This function generates a log with level debug for the ICMPv6 region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_ICMP
-#define otLogCritIcmp(...) otLogCrit(OT_LOG_REGION_ICMP, _OT_REGION_ICMP_PREFIX, __VA_ARGS__)
-#define otLogWarnIcmp(...) otLogWarn(OT_LOG_REGION_ICMP, _OT_REGION_ICMP_PREFIX, __VA_ARGS__)
-#define otLogNoteIcmp(...) otLogNote(OT_LOG_REGION_ICMP, _OT_REGION_ICMP_PREFIX, __VA_ARGS__)
-#define otLogInfoIcmp(...) otLogInfo(OT_LOG_REGION_ICMP, _OT_REGION_ICMP_PREFIX, __VA_ARGS__)
-#define otLogDebgIcmp(...) otLogDebg(OT_LOG_REGION_ICMP, _OT_REGION_ICMP_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritIcmp(...)
-#define otLogWarnIcmp(...)
-#define otLogNoteIcmp(...)
-#define otLogInfoIcmp(...)
-#define otLogDebgIcmp(...)
-#endif
-
-/**
- * @def otLogCritIp6
- *
- * This function generates a log with level critical for the IPv6 region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnIp6
- *
- * This function generates a log with level warning for the IPv6 region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteIp6
- *
- * This function generates a log with level note for the IPv6 region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoIp6
- *
- * This function generates a log with level info for the IPv6 region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgIp6
- *
- * This function generates a log with level debug for the IPv6 region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_IP6
-#define otLogCritIp6(...) otLogCrit(OT_LOG_REGION_IP6, _OT_REGION_IP6_PREFIX, __VA_ARGS__)
-#define otLogWarnIp6(...) otLogWarn(OT_LOG_REGION_IP6, _OT_REGION_IP6_PREFIX, __VA_ARGS__)
-#define otLogNoteIp6(...) otLogNote(OT_LOG_REGION_IP6, _OT_REGION_IP6_PREFIX, __VA_ARGS__)
-#define otLogInfoIp6(...) otLogInfo(OT_LOG_REGION_IP6, _OT_REGION_IP6_PREFIX, __VA_ARGS__)
-#define otLogDebgIp6(...) otLogDebg(OT_LOG_REGION_IP6, _OT_REGION_IP6_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritIp6(...)
-#define otLogWarnIp6(...)
-#define otLogNoteIp6(...)
-#define otLogInfoIp6(...)
-#define otLogDebgIp6(...)
-#endif
-
-/**
- * @def otLogCritTcp
- *
- * This function generates a log with level critical for the TCP region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnTcp
- *
- * This function generates a log with level warning for the TCP region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteTcp
- *
- * This function generates a log with level note for the TCP region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoTcp
- *
- * This function generates a log with level info for the TCP region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgTcp
- *
- * This function generates a log with level debug for the TCP region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_TCP
-#define otLogCritTcp(...) otLogCrit(OT_LOG_REGION_TCP, _OT_REGION_TCP_PREFIX, __VA_ARGS__)
-#define otLogWarnTcp(...) otLogWarn(OT_LOG_REGION_TCP, _OT_REGION_TCP_PREFIX, __VA_ARGS__)
-#define otLogNoteTcp(...) otLogNote(OT_LOG_REGION_TCP, _OT_REGION_TCP_PREFIX, __VA_ARGS__)
-#define otLogInfoTcp(...) otLogInfo(OT_LOG_REGION_TCP, _OT_REGION_TCP_PREFIX, __VA_ARGS__)
-#define otLogDebgTcp(...) otLogDebg(OT_LOG_REGION_TCP, _OT_REGION_TCP_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritTcp(...)
-#define otLogWarnTcp(...)
-#define otLogNoteTcp(...)
-#define otLogInfoTcp(...)
-#define otLogDebgTcp(...)
-#endif
-
-/**
- * @def otLogCritMac
- *
- * This function generates a log with level critical for the MAC region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnMac
- *
- * This function generates a log with level warning for the MAC region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteMac
- *
- * This function generates a log with level note for the MAC region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoMac
- *
- * This function generates a log with level info for the MAC region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgMac
- *
- * This function generates a log with level debug for the MAC region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogMac
- *
- * This function generates a log with a given log level for the MAC region.
- *
- * @param[in]  aLogLevel  A log level.
- * @param[in]  aFormat    A pointer to the format string.
- * @param[in]  ...        Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_MAC
-#define otLogCritMac(...) otLogCrit(OT_LOG_REGION_MAC, _OT_REGION_MAC_PREFIX, __VA_ARGS__)
-#define otLogWarnMac(...) otLogWarn(OT_LOG_REGION_MAC, _OT_REGION_MAC_PREFIX, __VA_ARGS__)
-#define otLogNoteMac(...) otLogNote(OT_LOG_REGION_MAC, _OT_REGION_MAC_PREFIX, __VA_ARGS__)
-#define otLogInfoMac(...) otLogInfo(OT_LOG_REGION_MAC, _OT_REGION_MAC_PREFIX, __VA_ARGS__)
-#define otLogDebgMac(...) otLogDebg(OT_LOG_REGION_MAC, _OT_REGION_MAC_PREFIX, __VA_ARGS__)
-#if OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
-#define otLogMac(aLogLevel, aFormat, ...)                                                     \
-    do                                                                                        \
-    {                                                                                         \
-        if (otLoggingGetLevel() >= aLogLevel)                                                 \
-        {                                                                                     \
-            _otLogFormatter(aLogLevel, OT_LOG_REGION_MAC, "%s" _OT_REGION_MAC_PREFIX aFormat, \
-                            otLogLevelToPrefixString(aLogLevel), __VA_ARGS__);                \
-        }                                                                                     \
-    } while (false)
-#else
-void otLogMac(otLogLevel aLogLevel, const char *aFormat, ...);
-#endif
-#else
-#define otLogCritMac(...)
-#define otLogWarnMac(...)
-#define otLogNoteMac(...)
-#define otLogInfoMac(...)
-#define otLogDebgMac(...)
-#define otLogMac(aLogLevel, ...)
-#endif
-
-/**
- * @def otLogCritCore
- *
- * This function generates a log with level critical for the Core region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnCore
- *
- * This function generates a log with level warning for the Core region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteCore
- *
- * This function generates a log with level note for the Core region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoCore
- *
- * This function generates a log with level info for the Core region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgCore
- *
- * This function generates a log with level debug for the Core region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_CORE
-#define otLogCritCore(...) otLogCrit(OT_LOG_REGION_CORE, _OT_REGION_CORE_PREFIX, __VA_ARGS__)
-#define otLogWarnCore(...) otLogWarn(OT_LOG_REGION_CORE, _OT_REGION_CORE_PREFIX, __VA_ARGS__)
-#define otLogNoteCore(...) otLogNote(OT_LOG_REGION_CORE, _OT_REGION_CORE_PREFIX, __VA_ARGS__)
-#define otLogInfoCore(...) otLogInfo(OT_LOG_REGION_CORE, _OT_REGION_CORE_PREFIX, __VA_ARGS__)
-#define otLogDebgCore(...) otLogDebg(OT_LOG_REGION_CORE, _OT_REGION_CORE_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritCore(...)
-#define otLogWarnCore(...)
-#define otLogInfoCore(...)
-#define otLogDebgCore(...)
-#endif
-
-/**
- * @def otLogCritMem
- *
- * This function generates a log with level critical for the memory region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnMem
- *
- * This function generates a log with level warning for the memory region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteMem
- *
- * This function generates a log with level note for the memory region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoMem
- *
- * This function generates a log with level info for the memory region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgMem
- *
- * This function generates a log with level debug for the memory region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_MEM
-#define otLogCritMem(...) otLogCrit(OT_LOG_REGION_MEM, _OT_REGION_MEM_PREFIX, __VA_ARGS__)
-#define otLogWarnMem(...) otLogWarn(OT_LOG_REGION_MEM, _OT_REGION_MEM_PREFIX, __VA_ARGS__)
-#define otLogNoteMem(...) otLogNote(OT_LOG_REGION_MEM, _OT_REGION_MEM_PREFIX, __VA_ARGS__)
-#define otLogInfoMem(...) otLogInfo(OT_LOG_REGION_MEM, _OT_REGION_MEM_PREFIX, __VA_ARGS__)
-#define otLogDebgMem(...) otLogDebg(OT_LOG_REGION_MEM, _OT_REGION_MEM_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritMem(...)
-#define otLogWarnMem(...)
-#define otLogNoteMem(...)
-#define otLogInfoMem(...)
-#define otLogDebgMem(...)
-#endif
-
-/**
- * @def otLogCritUtil
- *
- * This function generates a log with level critical for the Util region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnUtil
- *
- * This function generates a log with level warning for the Util region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteUtil
- *
- * This function generates a log with level note for the Util region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoUtil
- *
- * This function generates a log with level info for the Util region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgUtil
- *
- * This function generates a log with level debug for the Util region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_UTIL
-#define otLogCritUtil(...) otLogCrit(OT_LOG_REGION_UTIL, _OT_REGION_UTIL_PREFIX, __VA_ARGS__)
-#define otLogWarnUtil(...) otLogWarn(OT_LOG_REGION_UTIL, _OT_REGION_UTIL_PREFIX, __VA_ARGS__)
-#define otLogNoteUtil(...) otLogNote(OT_LOG_REGION_UTIL, _OT_REGION_UTIL_PREFIX, __VA_ARGS__)
-#define otLogInfoUtil(...) otLogInfo(OT_LOG_REGION_UTIL, _OT_REGION_UTIL_PREFIX, __VA_ARGS__)
-#define otLogDebgUtil(...) otLogDebg(OT_LOG_REGION_UTIL, _OT_REGION_UTIL_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritUtil(...)
-#define otLogWarnUtil(...)
-#define otLogNoteUtil(...)
-#define otLogInfoUtil(...)
-#define otLogDebgUtil(...)
-#endif
-
-/**
- * @def otLogCritNetDiag
- *
- * This function generates a log with level critical for the NETDIAG region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnNetDiag
- *
- * This function generates a log with level warning for the NETDIAG region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteNetDiag
- *
- * This function generates a log with level note for the NETDIAG region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoNetDiag
- *
- * This function generates a log with level info for the NETDIAG region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgNetDiag
- *
- * This function generates a log with level debug for the NETDIAG region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_NETDIAG
-#define otLogCritNetDiag(...) otLogCrit(OT_LOG_REGION_NET_DIAG, _OT_REGION_NET_DIAG_PREFIX, __VA_ARGS__)
-#define otLogWarnNetDiag(...) otLogWarn(OT_LOG_REGION_NET_DIAG, _OT_REGION_NET_DIAG_PREFIX, __VA_ARGS__)
-#define otLogNoteNetDiag(...) otLogNote(OT_LOG_REGION_NET_DIAG, _OT_REGION_NET_DIAG_PREFIX, __VA_ARGS__)
-#define otLogInfoNetDiag(...) otLogInfo(OT_LOG_REGION_NET_DIAG, _OT_REGION_NET_DIAG_PREFIX, __VA_ARGS__)
-#define otLogDebgNetDiag(...) otLogDebg(OT_LOG_REGION_NET_DIAG, _OT_REGION_NET_DIAG_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritNetDiag(...)
-#define otLogWarnNetDiag(...)
-#define otLogNoteNetDiag(...)
-#define otLogInfoNetDiag(...)
-#define otLogDebgNetDiag(...)
-#endif
-
-/**
- * @def otLogCert
- *
- * This function generates a log with level none for the certification test.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- *
- */
-#if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-#define otLogCertMeshCoP(...)
-#elif OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
-#define otLogCertMeshCoP(...) _otLogFormatter(OT_LOG_LEVEL_NONE, OT_LOG_REGION_MESH_COP, __VA_ARGS__)
-#else
-void otLogCertMeshCoP(const char *aFormat, ...);
-#endif
-
-/**
- * @def otLogCritCli
- *
- * This function generates a log with level critical for the CLI region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnCli
- *
- * This function generates a log with level warning for the CLI region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteCli
- *
- * This function generates a log with level note for the CLI region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoCli
- *
- * This function generates a log with level info for the CLI region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgCli
- *
- * This function generates a log with level debug for the CLI region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_CLI
-
-#define otLogCritCli(...) otLogCrit(OT_LOG_REGION_CLI, _OT_REGION_CLI_PREFIX, __VA_ARGS__)
-#define otLogWarnCli(...) otLogWarn(OT_LOG_REGION_CLI, _OT_REGION_CLI_PREFIX, __VA_ARGS__)
-#define otLogNoteCli(...) otLogNote(OT_LOG_REGION_CLI, _OT_REGION_CLI_PREFIX, __VA_ARGS__)
-#define otLogInfoCli(...) otLogInfo(OT_LOG_REGION_CLI, _OT_REGION_CLI_PREFIX, __VA_ARGS__)
-#define otLogDebgCli(...) otLogDebg(OT_LOG_REGION_CLI, _OT_REGION_CLI_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritCli(...)
-#define otLogWarnCli(...)
-#define otLogNoteCli(...)
-#define otLogInfoCli(...)
-#define otLogDebgCli(...)
-#endif
-
-/**
- * @def otLogCritCoap
- *
- * This function generates a log with level critical for the CoAP region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnCoap
- *
- * This function generates a log with level warning for the CoAP region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteCoap
- *
- * This function generates a log with level note for the CoAP region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoCoap
- *
- * This function generates a log with level info for the CoAP region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgCoap
- *
- * This function generates a log with level debug for the CoAP region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_COAP
-#define otLogCritCoap(...) otLogCrit(OT_LOG_REGION_COAP, _OT_REGION_COAP_PREFIX, __VA_ARGS__)
-#define otLogWarnCoap(...) otLogWarn(OT_LOG_REGION_COAP, _OT_REGION_COAP_PREFIX, __VA_ARGS__)
-#define otLogNoteCoap(...) otLogNote(OT_LOG_REGION_COAP, _OT_REGION_COAP_PREFIX, __VA_ARGS__)
-#define otLogInfoCoap(...) otLogInfo(OT_LOG_REGION_COAP, _OT_REGION_COAP_PREFIX, __VA_ARGS__)
-#define otLogDebgCoap(...) otLogDebg(OT_LOG_REGION_COAP, _OT_REGION_COAP_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritCoap(...)
-#define otLogWarnCoap(...)
-#define otLogNoteCoap(...)
-#define otLogInfoCoap(...)
-#define otLogDebgCoap(...)
-#endif
-
-/**
- * @def otLogCritDua
- *
- * This function generates a log with level critical for the Domain Unicast Address region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnDua
- *
- * This function generates a log with level warning for the Domain Unicast Address region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteDua
- *
- * This function generates a log with level note for the Domain Unicast Address region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoDua
- *
- * This function generates a log with level info for the Domain Unicast Address region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgDua
- *
- * This function generates a log with level debug for the Domain Unicast Address region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_DUA
-#define otLogCritDua(...) otLogCrit(OT_LOG_REGION_DUA, _OT_REGION_DUA_PREFIX, __VA_ARGS__)
-#define otLogWarnDua(...) otLogWarn(OT_LOG_REGION_DUA, _OT_REGION_DUA_PREFIX, __VA_ARGS__)
-#define otLogNoteDua(...) otLogNote(OT_LOG_REGION_DUA, _OT_REGION_DUA_PREFIX, __VA_ARGS__)
-#define otLogInfoDua(...) otLogInfo(OT_LOG_REGION_DUA, _OT_REGION_DUA_PREFIX, __VA_ARGS__)
-#define otLogDebgDua(...) otLogDebg(OT_LOG_REGION_DUA, _OT_REGION_DUA_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritDua(...)
-#define otLogWarnDua(...)
-#define otLogNoteDua(...)
-#define otLogInfoDua(...)
-#define otLogDebgDua(...)
-#endif
-
-/**
- * @def otLogCritSrp
- *
- * This function generates a log with level critical for the Service Registration Protocol (SRP) region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnSrp
- *
- * This function generates a log with level warning for the Service Registration Protocol (SRP) region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteSrp
- *
- * This function generates a log with level note for the Service Registration Protocol (SRP) region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoSrp
- *
- * This function generates a log with level info for the Service Registration Protocol (SRP) region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgSrp
- *
- * This function generates a log with level debug for the Service Registration Protocol (SRP) region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_SRP
-#define otLogCritSrp(...) otLogCrit(OT_LOG_REGION_SRP, _OT_REGION_SRP_PREFIX, __VA_ARGS__)
-#define otLogWarnSrp(...) otLogWarn(OT_LOG_REGION_SRP, _OT_REGION_SRP_PREFIX, __VA_ARGS__)
-#define otLogNoteSrp(...) otLogNote(OT_LOG_REGION_SRP, _OT_REGION_SRP_PREFIX, __VA_ARGS__)
-#define otLogInfoSrp(...) otLogInfo(OT_LOG_REGION_SRP, _OT_REGION_SRP_PREFIX, __VA_ARGS__)
-#define otLogDebgSrp(...) otLogDebg(OT_LOG_REGION_SRP, _OT_REGION_SRP_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritSrp(...)
-#define otLogWarnSrp(...)
-#define otLogNoteSrp(...)
-#define otLogInfoSrp(...)
-#define otLogDebgSrp(...)
-#endif
-
-/**
- * @def otLogCritDns
- *
- * This function generates a log with level critical for the DNS region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnDns
- *
- * This function generates a log with level warning for the DNS region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNoteDns
- *
- * This function generates a log with level note for the DNS region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoDns
- *
- * This function generates a log with level info for the DNS region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgDns
- *
- * This function generates a log with level debug for the DNS region.
- *
- * @param[in]  ...  Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_DNS
-#define otLogCritDns(...) otLogCrit(OT_LOG_REGION_DNS, _OT_REGION_DNS_PREFIX, __VA_ARGS__)
-#define otLogWarnDns(...) otLogWarn(OT_LOG_REGION_DNS, _OT_REGION_DNS_PREFIX, __VA_ARGS__)
-#define otLogNoteDns(...) otLogNote(OT_LOG_REGION_DNS, _OT_REGION_DNS_PREFIX, __VA_ARGS__)
-#define otLogInfoDns(...) otLogInfo(OT_LOG_REGION_DNS, _OT_REGION_DNS_PREFIX, __VA_ARGS__)
-#define otLogDebgDns(...) otLogDebg(OT_LOG_REGION_DNS, _OT_REGION_DNS_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritDns(...)
-#define otLogWarnDns(...)
-#define otLogNoteDns(...)
-#define otLogInfoDns(...)
-#define otLogDebgDns(...)
-#endif
-
-/**
- * @def otLogCritPlat
- *
- * This function generates a log with level critical for the Platform region.
- *
- * @param[in]  ...       Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogWarnPlat
- *
- * This function generates a log with level warning for the Platform region.
- *
- * @param[in]  ...       Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogNotePlat
- *
- * This function generates a log with level note for the Platform region.
- *
- * @param[in]  ...       Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogInfoPlat
- *
- * This function generates a log with level info for the Platform region.
- *
- * @param[in]  ...       Arguments for the format specification.
- *
- */
-
-/**
- * @def otLogDebgPlat
- *
- * This function generates a log with level debug for the Platform region.
- *
- * @param[in]  ...       Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_PLATFORM
-#define otLogCritPlat(...) otLogCrit(OT_LOG_REGION_PLATFORM, _OT_REGION_PLATFORM_PREFIX, __VA_ARGS__)
-#define otLogWarnPlat(...) otLogWarn(OT_LOG_REGION_PLATFORM, _OT_REGION_PLATFORM_PREFIX, __VA_ARGS__)
-#define otLogNotePlat(...) otLogNote(OT_LOG_REGION_PLATFORM, _OT_REGION_PLATFORM_PREFIX, __VA_ARGS__)
-#define otLogInfoPlat(...) otLogInfo(OT_LOG_REGION_PLATFORM, _OT_REGION_PLATFORM_PREFIX, __VA_ARGS__)
-#define otLogDebgPlat(...) otLogDebg(OT_LOG_REGION_PLATFORM, _OT_REGION_PLATFORM_PREFIX, __VA_ARGS__)
-#else
-#define otLogCritPlat(...)
-#define otLogWarnPlat(...)
-#define otLogNotePlat(...)
-#define otLogInfoPlat(...)
-#define otLogDebgPlat(...)
-#endif
-
-/**
- * @def otLogOtns
- *
- * This function generates a log with level none for the Core region,
- * and is specifically for OTNS visualization use.
- *
- * @param[in]  ...       Arguments for the format specification.
- *
- */
-#if OPENTHREAD_CONFIG_OTNS_ENABLE
-#if OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
-#define otLogOtns(...) _otLogFormatter(OT_LOG_LEVEL_NONE, OT_LOG_REGION_CORE, _OT_LEVEL_NONE_PREFIX __VA_ARGS__)
-#else
-void otLogOtns(const char *aFormat, ...);
-#endif
-#endif
-
-/**
- * @def otDumpCrit
- *
- * This function generates a memory dump with log level critical.
- *
- * @param[in]  aRegion      The log region.
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_CRIT
-#define otDumpCrit(aRegion, aId, aBuf, aLength) otDump(OT_LOG_LEVEL_CRIT, aRegion, aId, aBuf, aLength)
-#else
-#define otDumpCrit(aRegion, aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpWarn
- *
- * This function generates a memory dump with log level warning.
- *
- * @param[in]  aRegion      The log region.
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN
-#define otDumpWarn(aRegion, aId, aBuf, aLength) otDump(OT_LOG_LEVEL_WARN, aRegion, aId, aBuf, aLength)
-#else
-#define otDumpWarn(aRegion, aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpNote
- *
- * This function generates a memory dump with log level note.
- *
- * @param[in]  aRegion      The log region.
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE
-#define otDumpNote(aRegion, aId, aBuf, aLength) otDump(OT_LOG_LEVEL_NOTE, aRegion, aId, aBuf, aLength)
-#else
-#define otDumpNote(aRegion, aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpInfo
- *
- * This function generates a memory dump with log level info.
- *
- * @param[in]  aRegion      The log region.
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO
-#define otDumpInfo(aRegion, aId, aBuf, aLength) otDump(OT_LOG_LEVEL_INFO, aRegion, aId, aBuf, aLength)
-#else
-#define otDumpInfo(aRegion, aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpDebg
- *
- * This function generates a memory dump with log level debug.
- *
- * @param[in]  aRegion      The log region.
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_DEBG
-#define otDumpDebg(aRegion, aId, aBuf, aLength) otDump(OT_LOG_LEVEL_DEBG, aRegion, aId, aBuf, aLength)
-#else
-#define otDumpDebg(aRegion, aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpCritNetData
- *
- * This function generates a memory dump with log level debug and region Network Data.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpWarnNetData
- *
- * This function generates a memory dump with log level warning and region Network Data.
- *
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpNoteNetData
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpInfoNetData
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpDebgNetData
- *
- * This function generates a memory dump with log level debug and region Network Data.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_NETDATA
-#define otDumpCritNetData(aId, aBuf, aLength) otDumpCrit(OT_LOG_REGION_NET_DATA, aId, aBuf, aLength)
-#define otDumpWarnNetData(aId, aBuf, aLength) otDumpWarn(OT_LOG_REGION_NET_DATA, aId, aBuf, aLength)
-#define otDumpNoteNetData(aId, aBuf, aLength) otDumpNote(OT_LOG_REGION_NET_DATA, aId, aBuf, aLength)
-#define otDumpInfoNetData(aId, aBuf, aLength) otDumpInfo(OT_LOG_REGION_NET_DATA, aId, aBuf, aLength)
-#define otDumpDebgNetData(aId, aBuf, aLength) otDumpDebg(OT_LOG_REGION_NET_DATA, aId, aBuf, aLength)
-#else
-#define otDumpCritNetData(aId, aBuf, aLength)
-#define otDumpWarnNetData(aId, aBuf, aLength)
-#define otDumpNoteNetData(aId, aBuf, aLength)
-#define otDumpInfoNetData(aId, aBuf, aLength)
-#define otDumpDebgNetData(aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpCritMle
- *
- * This function generates a memory dump with log level debug and region MLE.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpWarnMle
- *
- * This function generates a memory dump with log level warning and region MLE.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpNoteMle
- *
- * This function generates a memory dump with log level note and region MLE.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpInfoMle
- *
- * This function generates a memory dump with log level info and region MLE.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpDebgMle
- *
- * This function generates a memory dump with log level debug and region MLE.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_MLE
-#define otDumpCritMle(aId, aBuf, aLength) otDumpCrit(OT_LOG_REGION_MLE, aId, aBuf, aLength)
-#define otDumpWarnMle(aId, aBuf, aLength) otDumpWarn(OT_LOG_REGION_MLE, aId, aBuf, aLength)
-#define otDumpNoteMle(aId, aBuf, aLength) otDumpNote(OT_LOG_REGION_MLE, aId, aBuf, aLength)
-#define otDumpInfoMle(aId, aBuf, aLength) otDumpInfo(OT_LOG_REGION_MLE, aId, aBuf, aLength)
-#define otDumpDebgMle(aId, aBuf, aLength) otDumpDebg(OT_LOG_REGION_MLE, aId, aBuf, aLength)
-#else
-#define otDumpCritMle(aId, aBuf, aLength)
-#define otDumpWarnMle(aId, aBuf, aLength)
-#define otDumpNoteMle(aId, aBuf, aLength)
-#define otDumpInfoMle(aId, aBuf, aLength)
-#define otDumpDebgMle(aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpCritArp
- *
- * This function generates a memory dump with log level debug and region EID-to-RLOC mapping.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpWarnArp
- *
- * This function generates a memory dump with log level warning and region EID-to-RLOC mapping.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpNoteArp
- *
- * This function generates a memory dump with log level note and region EID-to-RLOC mapping.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpInfoArp
- *
- * This function generates a memory dump with log level info and region EID-to-RLOC mapping.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpDebgArp
- *
- * This function generates a memory dump with log level debug and region EID-to-RLOC mapping.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_ARP
-#define otDumpCritArp(aId, aBuf, aLength) otDumpCrit(OT_LOG_REGION_ARP, aId, aBuf, aLength)
-#define otDumpWarnArp(aId, aBuf, aLength) otDumpWarn(OT_LOG_REGION_ARP, aId, aBuf, aLength)
-#define otDumpNoteArp(aId, aBuf, aLength) otDumpNote(OT_LOG_REGION_ARP, aId, aBuf, aLength)
-#define otDumpInfoArp(aId, aBuf, aLength) otDumpInfo(OT_LOG_REGION_ARP, aId, aBuf, aLength)
-#define otDumpDebgArp(aId, aBuf, aLength) otDumpDebg(OT_LOG_REGION_ARP, aId, aBuf, aLength)
-#else
-#define otDumpCritArp(aId, aBuf, aLength)
-#define otDumpWarnArp(aId, aBuf, aLength)
-#define otDumpNoteArp(aId, aBuf, aLength)
-#define otDumpInfoArp(aId, aBuf, aLength)
-#define otDumpDebgArp(aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpCritBbr
- *
- * This function generates a memory dump with log level critical and region Backbone Router (BBR).
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpWarnBbr
- *
- * This function generates a memory dump with log level warning and region Backbone Router (BBR).
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpNoteBbr
- *
- * This function generates a memory dump with log level note and region Backbone Router (BBR).
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpInfoBbr
- *
- * This function generates a memory dump with log level info and region Backbone Router (BBR).
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpDebgBbr
- *
- * This function generates a memory dump with log level debug and region Backbone Router (BBR).
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_BBR
-#define otDumpCritBbr(aId, aBuf, aLength) otDumpCrit(OT_LOG_REGION_BBR, aId, aBuf, aLength)
-#define otDumpWarnBbr(aId, aBuf, aLength) otDumpWarn(OT_LOG_REGION_BBR, aId, aBuf, aLength)
-#define otDumpNoteBbr(aId, aBuf, aLength) otDumpNote(OT_LOG_REGION_BBR, aId, aBuf, aLength)
-#define otDumpInfoBbr(aId, aBuf, aLength) otDumpInfo(OT_LOG_REGION_BBR, aId, aBuf, aLength)
-#define otDumpDebgBbr(aId, aBuf, aLength) otDumpDebg(OT_LOG_REGION_BBR, aId, aBuf, aLength)
-#else
-#define otDumpCritBbr(aId, aBuf, aLength)
-#define otDumpWarnBbr(aId, aBuf, aLength)
-#define otDumpNoteBbr(aId, aBuf, aLength)
-#define otDumpInfoBbr(aId, aBuf, aLength)
-#define otDumpDebgBbr(aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpCritMlr
- *
- * This function generates a memory dump with log level critical and region Multicast Listener Registration (MLR).
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpWarnMlr
- *
- * This function generates a memory dump with log level warning and region Multicast Listener Registration (MLR).
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpNoteMlr
- *
- * This function generates a memory dump with log level note and region Multicast Listener Registration (MLR).
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpInfoMlr
- *
- * This function generates a memory dump with log level info and region Multicast Listener Registration (MLR).
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpDebgMlr
- *
- * This function generates a memory dump with log level debug and region Multicast Listener Registration (MLR).
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_MLR
-#define otDumpCritMlr(aId, aBuf, aLength) otDumpCrit(OT_LOG_REGION_MLR, aId, aBuf, aLength)
-#define otDumpWarnMlr(aId, aBuf, aLength) otDumpWarn(OT_LOG_REGION_MLR, aId, aBuf, aLength)
-#define otDumpNoteMlr(aId, aBuf, aLength) otDumpNote(OT_LOG_REGION_MLR, aId, aBuf, aLength)
-#define otDumpInfoMlr(aId, aBuf, aLength) otDumpInfo(OT_LOG_REGION_MLR, aId, aBuf, aLength)
-#define otDumpDebgMlr(aId, aBuf, aLength) otDumpDebg(OT_LOG_REGION_MLR, aId, aBuf, aLength)
-#else
-#define otDumpCritMlr(aId, aBuf, aLength)
-#define otDumpWarnMlr(aId, aBuf, aLength)
-#define otDumpNoteMlr(aId, aBuf, aLength)
-#define otDumpInfoMlr(aId, aBuf, aLength)
-#define otDumpDebgMlr(aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpCritIcmp
- *
- * This function generates a memory dump with log level debug and region ICMPv6.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpWarnIcmp
- *
- * This function generates a memory dump with log level warning and region ICMPv6.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpNoteIcmp
- *
- * This function generates a memory dump with log level note and region ICMPv6.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpInfoIcmp
- *
- * This function generates a memory dump with log level info and region ICMPv6.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpDebgIcmp
- *
- * This function generates a memory dump with log level debug and region ICMPv6.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_ICMP
-#define otDumpCritIcmp(aId, aBuf, aLength) otDumpCrit(OT_LOG_REGION_ICMP, aId, aBuf, aLength)
-#define otDumpWarnIcmp(aId, aBuf, aLength) otDumpWarn(OT_LOG_REGION_ICMP, aId, aBuf, aLength)
-#define otDumpNoteIcmp(aId, aBuf, aLength) otDumpNote(OT_LOG_REGION_ICMP, aId, aBuf, aLength)
-#define otDumpInfoIcmp(aId, aBuf, aLength) otDumpInfo(OT_LOG_REGION_ICMP, aId, aBuf, aLength)
-#define otDumpDebgIcmp(aId, aBuf, aLength) otDumpDebg(OT_LOG_REGION_ICMP, aId, aBuf, aLength)
-#else
-#define otDumpCritIcmp(aId, aBuf, aLength)
-#define otDumpWarnIcmp(aId, aBuf, aLength)
-#define otDumpNoteIcmp(aId, aBuf, aLength)
-#define otDumpInfoIcmp(aId, aBuf, aLength)
-#define otDumpDebgIcmp(aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpCritIp6
- *
- * This function generates a memory dump with log level debug and region IPv6.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpWarnIp6
- *
- * This function generates a memory dump with log level warning and region IPv6.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpNoteIp6
- *
- * This function generates a memory dump with log level note and region IPv6.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpInfoIp6
- *
- * This function generates a memory dump with log level info and region IPv6.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpDebgIp6
- *
- * This function generates a memory dump with log level debug and region IPv6.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_IP6
-#define otDumpCritIp6(aId, aBuf, aLength) otDumpCrit(OT_LOG_REGION_IP6, aId, aBuf, aLength)
-#define otDumpWarnIp6(aId, aBuf, aLength) otDumpWarn(OT_LOG_REGION_IP6, aId, aBuf, aLength)
-#define otDumpNoteIp6(aId, aBuf, aLength) otDumpNote(OT_LOG_REGION_IP6, aId, aBuf, aLength)
-#define otDumpInfoIp6(aId, aBuf, aLength) otDumpInfo(OT_LOG_REGION_IP6, aId, aBuf, aLength)
-#define otDumpDebgIp6(aId, aBuf, aLength) otDumpDebg(OT_LOG_REGION_IP6, aId, aBuf, aLength)
-#else
-#define otDumpCritIp6(aId, aBuf, aLength)
-#define otDumpWarnIp6(aId, aBuf, aLength)
-#define otDumpNoteIp6(aId, aBuf, aLength)
-#define otDumpInfoIp6(aId, aBuf, aLength)
-#define otDumpDebgIp6(aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpCritTcp
- *
- * This function generates a memory dump with log level debug and region TCP.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpWartTcp
- *
- * This function generates a memory dump with log level warning and region TCP.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpNottTcp
- *
- * This function generates a memory dump with log level note and region TCP.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpInftTcp
- *
- * This function generates a memory dump with log level info and region TCP.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpDebtTcp
- *
- * This function generates a memory dump with log level debug and region TCP.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_TCP
-#define otDumpCritTcp(aId, aBuf, aLength) otDumpCrit(OT_LOG_REGION_TCP, aId, aBuf, aLength)
-#define otDumpWarnTcp(aId, aBuf, aLength) otDumpWarn(OT_LOG_REGION_TCP, aId, aBuf, aLength)
-#define otDumpNoteTcp(aId, aBuf, aLength) otDumpNote(OT_LOG_REGION_TCP, aId, aBuf, aLength)
-#define otDumpInfoTcp(aId, aBuf, aLength) otDumpInfo(OT_LOG_REGION_TCP, aId, aBuf, aLength)
-#define otDumpDebgTcp(aId, aBuf, aLength) otDumpDebg(OT_LOG_REGION_TCP, aId, aBuf, aLength)
-#else
-#define otDumpCritTcp(aId, aBuf, aLength)
-#define otDumpWarnTcp(aId, aBuf, aLength)
-#define otDumpNoteTcp(aId, aBuf, aLength)
-#define otDumpInfoTcp(aId, aBuf, aLength)
-#define otDumpDebgTcp(aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpCritMac
- *
- * This function generates a memory dump with log level debug and region MAC.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpWarnMac
- *
- * This function generates a memory dump with log level warning and region MAC.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpNoteMac
- *
- * This function generates a memory dump with log level note and region MAC.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpInfoMac
- *
- * This function generates a memory dump with log level info and region MAC.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpDebgMac
- *
- * This function generates a memory dump with log level debug and region MAC.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_MAC
-void otDumpMacFrame(otLogLevel aLogLevel, const char *aId, const void *aBuf, size_t aLength);
-#define otDumpCritMac(aId, aBuf, aLength) otDumpMacFrame(OT_LOG_LEVEL_CRIT, aId, aBuf, aLength)
-#define otDumpWarnMac(aId, aBuf, aLength) otDumpMacFrame(OT_LOG_LEVEL_WARN, aId, aBuf, aLength)
-#define otDumpNoteMac(aId, aBuf, aLength) otDumpMacFrame(OT_LOG_LEVEL_NOTE, aId, aBuf, aLength)
-#define otDumpInfoMac(aId, aBuf, aLength) otDumpMacFrame(OT_LOG_LEVEL_INFO, aId, aBuf, aLength)
-#define otDumpDebgMac(aId, aBuf, aLength) otDumpMacFrame(OT_LOG_LEVEL_DEBG, aId, aBuf, aLength)
-#else
-#define otDumpCritMac(aId, aBuf, aLength)
-#define otDumpWarnMac(aId, aBuf, aLength)
-#define otDumpNoteMac(aId, aBuf, aLength)
-#define otDumpInfoMac(aId, aBuf, aLength)
-#define otDumpDebgMac(aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpCritCore
- *
- * This function generates a memory dump with log level debug and region Core.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpWarnCore
- *
- * This function generates a memory dump with log level warning and region Core.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpNoteCore
- *
- * This function generates a memory dump with log level note and region Core.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpInfoCore
- *
- * This function generates a memory dump with log level info and region Core.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpDebgCore
- *
- * This function generates a memory dump with log level debug and region Core.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_CORE
-#define otDumpCritCore(aId, aBuf, aLength) otDumpCrit(OT_LOG_REGION_CORE, aId, aBuf, aLength)
-#define otDumpWarnCore(aId, aBuf, aLength) otDumpWarn(OT_LOG_REGION_CORE, aId, aBuf, aLength)
-#define otDumpNoteCore(aId, aBuf, aLength) otDumpNote(OT_LOG_REGION_CORE, aId, aBuf, aLength)
-#define otDumpInfoCore(aId, aBuf, aLength) otDumpInfo(OT_LOG_REGION_CORE, aId, aBuf, aLength)
-#define otDumpDebgCore(aId, aBuf, aLength) otDumpDebg(OT_LOG_REGION_CORE, aId, aBuf, aLength)
-#else
-#define otDumpCritCore(aId, aBuf, aLength)
-#define otDumpWarnCore(aId, aBuf, aLength)
-#define otDumpNoteCore(aId, aBuf, aLength)
-#define otDumpInfoCore(aId, aBuf, aLength)
-#define otDumpDebgCore(aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpCritDua
- *
- * This function generates a memory dump with log level critical and region Domain Unicast Address.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpWarnDua
- *
- * This function generates a memory dump with log level warning and region Domain Unicast Address.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpNoteDua
- *
- * This function generates a memory dump with log level note and region Domain Unicast Address.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpInfoDua
- *
- * This function generates a memory dump with log level info and region Domain Unicast Address.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpDebgDua
- *
- * This function generates a memory dump with log level debug and region Domain Unicast Address.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_DUA
-#define otDumpCritDua(aId, aBuf, aLength) otDumpCrit(OT_LOG_REGION_DUA, aId, aBuf, aLength)
-#define otDumpWarnDua(aId, aBuf, aLength) otDumpWarn(OT_LOG_REGION_DUA, aId, aBuf, aLength)
-#define otDumpNoteDua(aId, aBuf, aLength) otDumpNote(OT_LOG_REGION_DUA, aId, aBuf, aLength)
-#define otDumpInfoDua(aId, aBuf, aLength) otDumpInfo(OT_LOG_REGION_DUA, aId, aBuf, aLength)
-#define otDumpDebgDua(aId, aBuf, aLength) otDumpDebg(OT_LOG_REGION_DUA, aId, aBuf, aLength)
-#else
-#define otDumpCritDua(aId, aBuf, aLength)
-#define otDumpWarnDua(aId, aBuf, aLength)
-#define otDumpNoteDua(aId, aBuf, aLength)
-#define otDumpInfoDua(aId, aBuf, aLength)
-#define otDumpDebgDua(aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpCritSrp
- *
- * This function generates a memory dump with log level critical and region Service Registration Protocol (SRP).
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpWarnSrp
- *
- * This function generates a memory dump with log level warning and region Service Registration Protocol (SRP).
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpNoteSrp
- *
- * This function generates a memory dump with log level note and region Service Registration Protocol (SRP).
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpInfoSrp
- *
- * This function generates a memory dump with log level info and region Service Registration Protocol (SRP).
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpDebgSrp
- *
- * This function generates a memory dump with log level debug and region Service Registration Protocol (SRP).
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_SRP
-#define otDumpCritSrp(aId, aBuf, aLength) otDumpCrit(OT_LOG_REGION_SRP, aId, aBuf, aLength)
-#define otDumpWarnSrp(aId, aBuf, aLength) otDumpWarn(OT_LOG_REGION_SRP, aId, aBuf, aLength)
-#define otDumpNoteSrp(aId, aBuf, aLength) otDumpNote(OT_LOG_REGION_SRP, aId, aBuf, aLength)
-#define otDumpInfoSrp(aId, aBuf, aLength) otDumpInfo(OT_LOG_REGION_SRP, aId, aBuf, aLength)
-#define otDumpDebgSrp(aId, aBuf, aLength) otDumpDebg(OT_LOG_REGION_SRP, aId, aBuf, aLength)
-#else
-#define otDumpCritSrp(aId, aBuf, aLength)
-#define otDumpWarnSrp(aId, aBuf, aLength)
-#define otDumpNoteSrp(aId, aBuf, aLength)
-#define otDumpInfoSrp(aId, aBuf, aLength)
-#define otDumpDebgSrp(aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpCritBr
- *
- * This function generates a memory dump with log level critical and region Border Routing.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpWarnBr
- *
- * This function generates a memory dump with log level warning and region Border Routing.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpNoteBr
- *
- * This function generates a memory dump with log level note and region Border Routing.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpInfoBr
- *
- * This function generates a memory dump with log level info and region Border Routing.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpDebgBr
- *
- * This function generates a memory dump with log level debug and region Border Routing.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_BR
-#define otDumpCritBr(aId, aBuf, aLength) otDumpCrit(OT_LOG_REGION_BR, aId, aBuf, aLength)
-#define otDumpWarnBr(aId, aBuf, aLength) otDumpWarn(OT_LOG_REGION_BR, aId, aBuf, aLength)
-#define otDumpNoteBr(aId, aBuf, aLength) otDumpNote(OT_LOG_REGION_BR, aId, aBuf, aLength)
-#define otDumpInfoBr(aId, aBuf, aLength) otDumpInfo(OT_LOG_REGION_BR, aId, aBuf, aLength)
-#define otDumpDebgBr(aId, aBuf, aLength) otDumpDebg(OT_LOG_REGION_BR, aId, aBuf, aLength)
-#else
-#define otDumpCritBr(aId, aBuf, aLength)
-#define otDumpWarnBr(aId, aBuf, aLength)
-#define otDumpNoteBr(aId, aBuf, aLength)
-#define otDumpInfoBr(aId, aBuf, aLength)
-#define otDumpDebgBr(aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpCritDns
- *
- * This function generates a memory dump with log level critical and region DNS.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpWarnDns
- *
- * This function generates a memory dump with log level warning and region DNS.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpNoteDns
- *
- * This function generates a memory dump with log level note and region DNS.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpInfoDns
- *
- * This function generates a memory dump with log level info and region DNS.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpDebgDns
- *
- * This function generates a memory dump with log level debug and region DNS.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_SRP
-#define otDumpCritDns(aId, aBuf, aLength) otDumpCrit(OT_LOG_REGION_SRP, aId, aBuf, aLength)
-#define otDumpWarnDns(aId, aBuf, aLength) otDumpWarn(OT_LOG_REGION_SRP, aId, aBuf, aLength)
-#define otDumpNoteDns(aId, aBuf, aLength) otDumpNote(OT_LOG_REGION_SRP, aId, aBuf, aLength)
-#define otDumpInfoDns(aId, aBuf, aLength) otDumpInfo(OT_LOG_REGION_SRP, aId, aBuf, aLength)
-#define otDumpDebgDns(aId, aBuf, aLength) otDumpDebg(OT_LOG_REGION_SRP, aId, aBuf, aLength)
-#else
-#define otDumpCritDns(aId, aBuf, aLength)
-#define otDumpWarnDns(aId, aBuf, aLength)
-#define otDumpNoteDns(aId, aBuf, aLength)
-#define otDumpInfoDns(aId, aBuf, aLength)
-#define otDumpDebgDns(aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpCritMem
- *
- * This function generates a memory dump with log level debug and region memory.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpWarnMem
- *
- * This function generates a memory dump with log level warning and region memory.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpNoteMem
- *
- * This function generates a memory dump with log level note and region memory.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpInfoMem
- *
- * This function generates a memory dump with log level info and region memory.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-
-/**
- * @def otDumpDebgMem
- *
- * This function generates a memory dump with log level debug and region memory.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_LOG_MEM
-#define otDumpCritMem(aId, aBuf, aLength) otDumpCrit(OT_LOG_REGION_MEM, aId, aBuf, aLength)
-#define otDumpWarnMem(aId, aBuf, aLength) otDumpWarn(OT_LOG_REGION_MEM, aId, aBuf, aLength)
-#define otDumpNoteMem(aId, aBuf, aLength) otDumpNote(OT_LOG_REGION_MEM, aId, aBuf, aLength)
-#define otDumpInfoMem(aId, aBuf, aLength) otDumpInfo(OT_LOG_REGION_MEM, aId, aBuf, aLength)
-#define otDumpDebgMem(aId, aBuf, aLength) otDumpDebg(OT_LOG_REGION_MEM, aId, aBuf, aLength)
-#else
-#define otDumpCritMem(aId, aBuf, aLength)
-#define otDumpWarnMem(aId, aBuf, aLength)
-#define otDumpNoteMem(aId, aBuf, aLength)
-#define otDumpInfoMem(aId, aBuf, aLength)
-#define otDumpDebgMem(aId, aBuf, aLength)
-#endif
-
-/**
- * @def otDumpCertMeshCoP
- *
- * This function generates a memory dump with log level none for the certification test.
- *
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-#define otDumpCertMeshCoP(aId, aBuf, aLength) otDump(OT_LOG_LEVEL_NONE, OT_LOG_REGION_MESH_COP, aId, aBuf, aLength)
-#else
-#define otDumpCertMeshCoP(aId, aBuf, aLength)
-#endif
-
-/**
- * This function dumps bytes to the log in a human-readable fashion.
- *
- * @param[in]  aLogLevel    The log level.
- * @param[in]  aLogRegion   The log region.
- * @param[in]  aId          A pointer to a NULL-terminated string that is printed before the bytes.
- * @param[in]  aBuf         A pointer to the buffer.
- * @param[in]  aLength      Number of bytes to print.
- *
- */
-void otDump(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aId, const void *aBuf, size_t aLength);
-
-#if OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY || OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL
-/**
- * This function converts a log level to a prefix string for appending to log message.
- *
- * @param[in]  aLogLevel    A log level.
- *
- * @returns A C string representing the log level.
- *
- */
-const char *otLogLevelToPrefixString(otLogLevel aLogLevel);
-#endif
-
-#if OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
-
-/**
- * Local/private macro to format the log message
- */
-#define _otLogFormatter(aLogLevel, aRegion, ...) \
-    _otDynamicLog(aLogLevel, aRegion, OT_FIRST_ARG(__VA_ARGS__) OPENTHREAD_CONFIG_LOG_SUFFIX OT_REST_ARGS(__VA_ARGS__))
-
-#if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
-
-#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
-#error "Dynamic log level is not supported along with multiple OT instance feature"
-#endif
-
-/**
- * Local/private macro to dynamically filter log level.
- */
-#define _otDynamicLog(aLogLevel, aRegion, ...)           \
-    do                                                   \
-    {                                                    \
-        if (otLoggingGetLevel() >= aLogLevel)            \
-            _otPlatLog(aLogLevel, aRegion, __VA_ARGS__); \
-    } while (false)
-
-#else // OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
-
-#define _otDynamicLog(aLogLevel, aRegion, ...) _otPlatLog(aLogLevel, aRegion, __VA_ARGS__)
-
-#endif // OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
-
-/**
- * `OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME` is a configuration parameter (see `config/logging.h`) which specifies the
- * function/macro to be used for logging in OpenThread. By default it is set to `otPlatLog()`.
- *
- */
-#define _otPlatLog(aLogLevel, aRegion, ...) OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME(aLogLevel, aRegion, __VA_ARGS__)
-
-#endif // OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
-
-#define _otLogResult(aRegion, aError, ...)                                                 \
-    do                                                                                     \
-    {                                                                                      \
-        otError _err = (aError);                                                           \
-                                                                                           \
-        if (_err == OT_ERROR_NONE)                                                         \
-        {                                                                                  \
-            otLogInfo##aRegion(OT_FIRST_ARG(__VA_ARGS__) ": %s" OT_REST_ARGS(__VA_ARGS__), \
-                               otThreadErrorToString(_err));                               \
-        }                                                                                  \
-        else                                                                               \
-        {                                                                                  \
-            otLogWarn##aRegion(OT_FIRST_ARG(__VA_ARGS__) ": %s" OT_REST_ARGS(__VA_ARGS__), \
-                               otThreadErrorToString(_err));                               \
-        }                                                                                  \
-    } while (false)
-
-/**
- * @def otLogResultPlat
- *
- * This function generates a log for the Plat region according to the error result. If @p aError is `kErrorNone`, the
- * log level is info. Otherwise the log level is warn.
- *
- * @param[in]  aError    The error result.
- * @param[in]  ...       Arguments for the format specification.
- *
- */
-#define otLogResultPlat(aError, ...) _otLogResult(Plat, aError, __VA_ARGS__)
-
-/**
- * @def otLogResultBbr
- *
- * This function generates a log for the BBR region according to the error result. If @p aError is `OT_ERROR_NONE`, the
- * log level is info. Otherwise the log level is warn.
- *
- * @param[in]  aError    The error result.
- * @param[in]  ...       Arguments for the format specification.
- *
- */
-#define otLogResultBbr(aError, ...) _otLogResult(Bbr, aError, __VA_ARGS__)
-
-#ifdef __cplusplus
-}
-#endif
-
 #endif // LOGGING_HPP_
diff --git a/src/core/common/message.cpp b/src/core/common/message.cpp
index a60f4b6..4847aac 100644
--- a/src/core/common/message.cpp
+++ b/src/core/common/message.cpp
@@ -36,9 +36,11 @@
 #include "common/as_core_type.hpp"
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
+#include "common/heap.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
+#include "common/numeric_limits.hpp"
 #include "net/checksum.hpp"
 #include "net/ip6.hpp"
 
@@ -54,6 +56,8 @@
 
 namespace ot {
 
+RegisterLogModule("Message");
+
 //---------------------------------------------------------------------------------------------------------------------
 // MessagePool
 
@@ -68,20 +72,20 @@
 #endif
 }
 
-Message *MessagePool::New(Message::Type aType, uint16_t aReserveHeader, Message::Priority aPriority)
+Message *MessagePool::Allocate(Message::Type aType, uint16_t aReserveHeader, const Message::Settings &aSettings)
 {
     Error    error = kErrorNone;
     Message *message;
 
-    VerifyOrExit((message = static_cast<Message *>(NewBuffer(aPriority))) != nullptr);
+    VerifyOrExit((message = static_cast<Message *>(NewBuffer(aSettings.GetPriority()))) != nullptr);
 
     memset(message, 0, sizeof(*message));
     message->SetMessagePool(this);
     message->SetType(aType);
     message->SetReserved(aReserveHeader);
-    message->SetLinkSecurityEnabled(true);
+    message->SetLinkSecurityEnabled(aSettings.IsLinkSecurityEnabled());
 
-    SuccessOrExit(error = message->SetPriority(aPriority));
+    SuccessOrExit(error = message->SetPriority(aSettings.GetPriority()));
     SuccessOrExit(error = message->SetLength(0));
 
 exit:
@@ -94,18 +98,6 @@
     return message;
 }
 
-Message *MessagePool::New(Message::Type aType, uint16_t aReserveHeader, const Message::Settings &aSettings)
-{
-    Message *message = New(aType, aReserveHeader, aSettings.GetPriority());
-
-    if (message)
-    {
-        message->SetLinkSecurityEnabled(aSettings.IsLinkSecurityEnabled());
-    }
-
-    return message;
-}
-
 void MessagePool::Free(Message *aMessage)
 {
     OT_ASSERT(aMessage->Next() == nullptr && aMessage->Prev() == nullptr);
@@ -119,7 +111,7 @@
 
     while ((
 #if OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE
-               buffer = static_cast<Buffer *>(Instance::HeapCAlloc(1, sizeof(Buffer)))
+               buffer = static_cast<Buffer *>(Heap::CAlloc(1, sizeof(Buffer)))
 #elif OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT
                buffer = static_cast<Buffer *>(otPlatMessagePoolNew(&GetInstance()))
 #else
@@ -139,7 +131,7 @@
 exit:
     if (buffer == nullptr)
     {
-        otLogInfoMem("No available message buffer");
+        LogInfo("No available message buffer");
     }
 
     return buffer;
@@ -151,7 +143,7 @@
     {
         Buffer *next = aBuffer->GetNextBuffer();
 #if OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE
-        Instance::HeapFree(aBuffer);
+        Heap::Free(aBuffer);
 #elif OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT
         otPlatMessagePoolFree(&GetInstance(), aBuffer);
 #else
@@ -172,7 +164,11 @@
     uint16_t rval;
 
 #if OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE
-    rval = static_cast<uint16_t>(GetInstance().GetHeap().GetFreeSize() / sizeof(Buffer));
+#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+    rval = static_cast<uint16_t>(Instance::GetHeap().GetFreeSize() / sizeof(Buffer));
+#else
+    rval = NumericLimits<uint16_t>::kMax;
+#endif
 #elif OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT
     rval = otPlatMessagePoolNumFreeBuffers(&GetInstance());
 #else
@@ -184,11 +180,19 @@
 
 uint16_t MessagePool::GetTotalBufferCount(void) const
 {
+    uint16_t rval;
+
 #if OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE
-    return static_cast<uint16_t>(GetInstance().GetHeap().GetCapacity() / sizeof(Buffer));
+#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+    rval = static_cast<uint16_t>(Instance::GetHeap().GetCapacity() / sizeof(Buffer));
 #else
-    return OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS;
+    rval = NumericLimits<uint16_t>::kMax;
 #endif
+#else
+    rval = OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS;
+#endif
+
+    return rval;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -208,6 +212,15 @@
 }
 
 //---------------------------------------------------------------------------------------------------------------------
+// Message::Iterator
+
+void Message::Iterator::Advance(void)
+{
+    mItem = mNext;
+    mNext = NextMessage(mNext);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
 // Message
 
 Error Message::ResizeMessage(uint16_t aLength)
@@ -346,6 +359,8 @@
     uint8_t        priority = static_cast<uint8_t>(aPriority);
     PriorityQueue *priorityQueue;
 
+    static_assert(kNumPriorities <= 4, "`Metadata::mPriority` as a 2-bit field cannot fit all `Priority` values");
+
     VerifyOrExit(priority < kNumPriorities, error = kErrorInvalidArgs);
 
     VerifyOrExit(IsInAQueue(), GetMetadata().mPriority = priority);
@@ -577,7 +592,7 @@
     return (ReadBytes(aOffset, aBuf, aLength) == aLength) ? kErrorNone : kErrorParse;
 }
 
-bool Message::CompareBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength) const
+bool Message::CompareBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength, ByteMatcher aMatcher) const
 {
     uint16_t       bytesToCompare = aLength;
     const uint8_t *bufPtr         = reinterpret_cast<const uint8_t *>(aBuf);
@@ -587,7 +602,7 @@
 
     while (chunk.GetLength() > 0)
     {
-        VerifyOrExit(chunk.MatchesBytesIn(bufPtr));
+        VerifyOrExit(chunk.MatchesBytesIn(bufPtr, aMatcher));
         bufPtr += chunk.GetLength();
         bytesToCompare -= chunk.GetLength();
         GetNextChunk(aLength, chunk);
@@ -600,7 +615,8 @@
 bool Message::CompareBytes(uint16_t       aOffset,
                            const Message &aOtherMessage,
                            uint16_t       aOtherOffset,
-                           uint16_t       aLength) const
+                           uint16_t       aLength,
+                           ByteMatcher    aMatcher) const
 {
     uint16_t bytesToCompare = aLength;
     Chunk    chunk;
@@ -609,7 +625,7 @@
 
     while (chunk.GetLength() > 0)
     {
-        VerifyOrExit(aOtherMessage.CompareBytes(aOtherOffset, chunk.GetBytes(), chunk.GetLength()));
+        VerifyOrExit(aOtherMessage.CompareBytes(aOtherOffset, chunk.GetBytes(), chunk.GetLength(), aMatcher));
         aOtherOffset += chunk.GetLength();
         bytesToCompare -= chunk.GetLength();
         GetNextChunk(aLength, chunk);
@@ -665,10 +681,11 @@
 {
     Error    error = kErrorNone;
     Message *messageCopy;
+    Settings settings(IsLinkSecurityEnabled() ? kWithLinkSecurity : kNoLinkSecurity, GetPriority());
     uint16_t offset;
 
-    VerifyOrExit((messageCopy = GetMessagePool()->New(GetType(), GetReserved(), GetPriority())) != nullptr,
-                 error = kErrorNoBufs);
+    messageCopy = GetMessagePool()->Allocate(GetType(), GetReserved(), settings);
+    VerifyOrExit(messageCopy != nullptr, error = kErrorNoBufs);
     SuccessOrExit(error = messageCopy->SetLength(aLength));
     CopyTo(0, 0, aLength, *messageCopy);
 
@@ -677,7 +694,6 @@
     messageCopy->SetOffset(offset);
 
     messageCopy->SetSubType(GetSubType());
-    messageCopy->SetLinkSecurityEnabled(IsLinkSecurityEnabled());
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
     messageCopy->SetTimeSync(IsTimeSync());
 #endif
@@ -748,16 +764,6 @@
 //---------------------------------------------------------------------------------------------------------------------
 // MessageQueue
 
-MessageQueue::MessageQueue(void)
-{
-    SetTail(nullptr);
-}
-
-Message *MessageQueue::GetHead(void) const
-{
-    return (GetTail() == nullptr) ? nullptr : GetTail()->Next();
-}
-
 void MessageQueue::Enqueue(Message &aMessage, QueuePosition aPosition)
 {
     OT_ASSERT(!aMessage.IsInAQueue());
@@ -829,37 +835,37 @@
     }
 }
 
-void MessageQueue::GetInfo(uint16_t &aMessageCount, uint16_t &aBufferCount) const
+Message::Iterator MessageQueue::begin(void)
 {
-    aMessageCount = 0;
-    aBufferCount  = 0;
+    return Message::Iterator(GetHead());
+}
 
-    for (const Message *message = GetHead(); message != nullptr; message = message->GetNext())
+Message::ConstIterator MessageQueue::begin(void) const
+{
+    return Message::ConstIterator(GetHead());
+}
+
+void MessageQueue::GetInfo(Info &aInfo) const
+{
+    for (const Message &message : *this)
     {
-        aMessageCount++;
-        aBufferCount += message->GetBufferCount();
+        aInfo.mNumMessages++;
+        aInfo.mNumBuffers += message.GetBufferCount();
+        aInfo.mTotalBytes += message.GetLength();
     }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 // PriorityQueue
 
-PriorityQueue::PriorityQueue(void)
+const Message *PriorityQueue::FindFirstNonNullTail(Message::Priority aStartPriorityLevel) const
 {
-    for (Message *&tail : mTails)
-    {
-        tail = nullptr;
-    }
-}
-
-Message *PriorityQueue::FindFirstNonNullTail(Message::Priority aStartPriorityLevel) const
-{
-    // Find the first non-nullptr tail starting from the given priority
+    // Find the first non-`nullptr` tail starting from the given priority
     // level and moving forward (wrapping from priority value
     // `kNumPriorities` -1 back to 0).
 
-    Message *tail = nullptr;
-    uint8_t  priority;
+    const Message *tail = nullptr;
+    uint8_t        priority;
 
     priority = static_cast<uint8_t>(aStartPriorityLevel);
 
@@ -877,19 +883,15 @@
     return tail;
 }
 
-Message *PriorityQueue::GetHead(void) const
+const Message *PriorityQueue::GetHead(void) const
 {
-    Message *tail;
-
-    tail = FindFirstNonNullTail(Message::kPriorityLow);
-
-    return (tail == nullptr) ? nullptr : tail->Next();
+    return Message::NextOf(FindFirstNonNullTail(Message::kPriorityLow));
 }
 
-Message *PriorityQueue::GetHeadForPriority(Message::Priority aPriority) const
+const Message *PriorityQueue::GetHeadForPriority(Message::Priority aPriority) const
 {
-    Message *head;
-    Message *previousTail;
+    const Message *head;
+    const Message *previousTail;
 
     if (mTails[aPriority] != nullptr)
     {
@@ -907,7 +909,7 @@
     return head;
 }
 
-Message *PriorityQueue::GetTail(void) const
+const Message *PriorityQueue::GetTail(void) const
 {
     return FindFirstNonNullTail(Message::kPriorityLow);
 }
@@ -991,15 +993,23 @@
     }
 }
 
-void PriorityQueue::GetInfo(uint16_t &aMessageCount, uint16_t &aBufferCount) const
+Message::Iterator PriorityQueue::begin(void)
 {
-    aMessageCount = 0;
-    aBufferCount  = 0;
+    return Message::Iterator(GetHead());
+}
 
-    for (const Message *message = GetHead(); message != nullptr; message = message->GetNext())
+Message::ConstIterator PriorityQueue::begin(void) const
+{
+    return Message::ConstIterator(GetHead());
+}
+
+void PriorityQueue::GetInfo(Info &aInfo) const
+{
+    for (const Message &message : *this)
     {
-        aMessageCount++;
-        aBufferCount += message->GetBufferCount();
+        aInfo.mNumMessages++;
+        aInfo.mNumBuffers += message.GetBufferCount();
+        aInfo.mTotalBytes += message.GetLength();
     }
 }
 
diff --git a/src/core/common/message.hpp b/src/core/common/message.hpp
index e9e419d..78adcee 100644
--- a/src/core/common/message.hpp
+++ b/src/core/common/message.hpp
@@ -41,14 +41,18 @@
 #include <openthread/message.h>
 #include <openthread/platform/messagepool.h>
 
+#include "common/as_core_type.hpp"
+#include "common/clearable.hpp"
 #include "common/code_utils.hpp"
 #include "common/const_cast.hpp"
 #include "common/data.hpp"
 #include "common/encoding.hpp"
+#include "common/iterator_utils.hpp"
 #include "common/linked_list.hpp"
 #include "common/locator.hpp"
 #include "common/non_copyable.hpp"
 #include "common/pool.hpp"
+#include "common/timer.hpp"
 #include "common/type_traits.hpp"
 #include "mac/mac_types.hpp"
 #include "thread/child_mask.hpp"
@@ -66,6 +70,7 @@
 
 namespace Crypto {
 
+class AesCcm;
 class Sha256;
 class HmacSha256;
 
@@ -82,14 +87,14 @@
  */
 
 /**
- * This macro frees a given message buffer if not nullptr.
+ * This macro frees a given message buffer if not `nullptr`.
  *
  * This macro and the ones that follow contain small but common code patterns used in many of the core modules. They
  * are intentionally defined as macros instead of inline methods/functions to ensure that they are fully inlined.
  * Note that an `inline` method/function is not necessarily always inlined by the toolchain and not inlining such
  * small implementations can add a rather large code-size overhead.
  *
- * @param[in] aMessage    A pointer to a `Message` to free (can be nullptr).
+ * @param[in] aMessage    A pointer to a `Message` to free (can be `nullptr`).
  *
  */
 #define FreeMessage(aMessage)      \
@@ -104,9 +109,9 @@
 /**
  * This macro frees a given message buffer if a given `Error` indicates an error.
  *
- * The parameter @p aMessage can be nullptr in which case this macro does nothing.
+ * The parameter @p aMessage can be `nullptr` in which case this macro does nothing.
  *
- * @param[in] aMessage    A pointer to a `Message` to free (can be nullptr).
+ * @param[in] aMessage    A pointer to a `Message` to free (can be `nullptr`).
  * @param[in] aError      The `Error` to check.
  *
  */
@@ -122,7 +127,7 @@
 /**
  * This macro frees a given message buffer if a given `Error` indicates an error and sets the `aMessage` to `nullptr`.
  *
- * @param[in] aMessage    A pointer to a `Message` to free (can be nullptr).
+ * @param[in] aMessage    A pointer to a `Message` to free (can be `nullptr`).
  * @param[in] aError      The `Error` to check.
  *
  */
@@ -186,28 +191,29 @@
         MessagePool *mMessagePool; // Message pool for this message.
         void *       mQueue;       // The queue where message is queued (if any). Queue type from `mInPriorityQ`.
         uint32_t     mDatagramTag; // The datagram tag used for 6LoWPAN frags or IPv6fragmentation.
+        TimeMilli    mTimestamp;   // The message timestamp.
         uint16_t     mReserved;    // Number of reserved bytes (for header).
         uint16_t     mLength;      // Current message length (number of bytes).
         uint16_t     mOffset;      // A byte offset within the message.
         uint16_t     mMeshDest;    // Used for unicast non-link-local messages.
         uint16_t     mPanId;       // PAN ID (used for MLE Discover Request and Response).
         uint8_t      mChannel;     // The message channel (used for MLE Announce).
-        uint8_t      mTimeout;     // Seconds remaining before dropping the message.
         RssAverager  mRssAverager; // The averager maintaining the received signal strength (RSS) average.
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
         LqiAverager mLqiAverager; // The averager maintaining the Link quality indicator (LQI) average.
 #endif
         ChildMask mChildMask; // ChildMask to indicate which sleepy children need to receive this.
 
-        uint8_t mType : 3;          // The message type.
-        uint8_t mSubType : 4;       // The message sub type.
-        bool    mDirectTx : 1;      // Whether a direct transmission is required.
-        bool    mLinkSecurity : 1;  // Whether link security is enabled.
-        uint8_t mPriority : 2;      // The message priority level (higher value is higher priority).
-        bool    mInPriorityQ : 1;   // Whether the message is queued in normal or priority queue.
-        bool    mTxSuccess : 1;     // Whether the direct tx of the message was successful.
-        bool    mDoNotEvict : 1;    // Whether this message may be evicted.
-        bool    mMulticastLoop : 1; // Whether this multicast message may be looped back.
+        uint8_t mType : 3;             // The message type.
+        uint8_t mSubType : 4;          // The message sub type.
+        bool    mDirectTx : 1;         // Whether a direct transmission is required.
+        bool    mLinkSecurity : 1;     // Whether link security is enabled.
+        uint8_t mPriority : 2;         // The message priority level (higher value is higher priority).
+        bool    mInPriorityQ : 1;      // Whether the message is queued in normal or priority queue.
+        bool    mTxSuccess : 1;        // Whether the direct tx of the message was successful.
+        bool    mDoNotEvict : 1;       // Whether this message may be evicted.
+        bool    mMulticastLoop : 1;    // Whether this multicast message may be looped back.
+        bool    mResolvingAddress : 1; // Whether the message is pending an address query resolution.
 #if OPENTHREAD_CONFIG_MULTI_RADIO
         uint8_t mRadioType : 2;      // The radio link type the message was received on, or should be sent on.
         bool    mIsRadioTypeSet : 1; // Whether the radio type is set.
@@ -252,11 +258,12 @@
  * This class represents a message.
  *
  */
-class Message : public otMessage, public Buffer
+class Message : public otMessage, public Buffer, public GetProvider<Message>
 {
     friend class Checksum;
     friend class Crypto::HmacSha256;
     friend class Crypto::Sha256;
+    friend class Crypto::AesCcm;
     friend class MessagePool;
     friend class MessageQueue;
     friend class PriorityQueue;
@@ -345,7 +352,7 @@
     {
     public:
         /**
-         * This constructor initializes the Settings object.
+         * This constructor initializes the `Settings` object.
          *
          * @param[in]  aSecurityMode  A link security mode.
          * @param[in]  aPriority      A message priority.
@@ -354,6 +361,17 @@
         Settings(LinkSecurityMode aSecurityMode, Priority aPriority);
 
         /**
+         * This constructor initializes the `Settings` with a given message priority and link security enabled.
+         *
+         * @param[in]  aPriority      A message priority.
+         *
+         */
+        explicit Settings(Priority aPriority)
+            : Settings(kWithLinkSecurity, aPriority)
+        {
+        }
+
+        /**
          * This method gets the message priority.
          *
          * @returns The message priority.
@@ -393,6 +411,14 @@
     };
 
     /**
+     * This method returns a reference to the OpenThread Instance which owns the `Message`.
+     *
+     * @returns A reference to the `Instance`.
+     *
+     */
+    Instance &GetInstance(void) const;
+
+    /**
      * This method frees this message buffer.
      *
      */
@@ -401,7 +427,7 @@
     /**
      * This method returns a pointer to the next message.
      *
-     * @returns A pointer to the next message in the list or nullptr if at the end of the list.
+     * @returns A pointer to the next message in the list or `nullptr` if at the end of the list.
      *
      */
     Message *GetNext(void) const;
@@ -637,6 +663,24 @@
     }
 
     /**
+     * This method appends bytes from a given `Data` instance to the end of the message.
+     *
+     * On success, this method grows the message by the size of the appended data.
+     *
+     * @tparam    kDataLengthType   Determines the data length type (`uint8_t` or `uint16_t`).
+     *
+     * @param[in] aData      A reference to `Data` to append to the message.
+     *
+     * @retval kErrorNone    Successfully appended the bytes from @p aData.
+     * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
+     *
+     */
+    template <DataLengthType kDataLengthType> Error AppendData(const Data<kDataLengthType> &aData)
+    {
+        return AppendBytes(aData.GetBytes(), aData.GetLength());
+    }
+
+    /**
      * This method reads bytes from the message.
      *
      * @param[in]  aOffset  Byte offset within the message to begin reading.
@@ -696,12 +740,14 @@
      * @param[in]  aOffset    Byte offset within the message to read from for the comparison.
      * @param[in]  aBuf       A pointer to a data buffer to compare with the bytes from message.
      * @param[in]  aLength    Number of bytes in @p aBuf.
+     * @param[in]  aMatcher   A `ByteMatcher` function pointer to match the bytes. If `nullptr` then bytes are directly
+     *                        compared.
      *
      * @returns TRUE if there are enough bytes available in @p aMessage and they match the bytes from @p aBuf,
      *          FALSE otherwise.
      *
      */
-    bool CompareBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength) const;
+    bool CompareBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength, ByteMatcher aMatcher = nullptr) const;
 
     /**
      * This method compares the bytes in the message at a given offset with bytes read from another message.
@@ -713,11 +759,17 @@
      * @param[in]  aOtherMessage  The other message to compare with.
      * @param[in]  aOtherOffset   Byte offset within @p aOtherMessage to read from for the comparison.
      * @param[in]  aLength        Number of bytes to compare.
+     * @param[in]  aMatcher       A `ByteMatcher` function pointer to match the bytes. If `nullptr` then bytes are
+     *                            directly compared.
      *
      * @returns TRUE if there are enough bytes available in both messages and they all match. FALSE otherwise.
      *
      */
-    bool CompareBytes(uint16_t aOffset, const Message &aOtherMessage, uint16_t aOtherOffset, uint16_t aLength) const;
+    bool CompareBytes(uint16_t       aOffset,
+                      const Message &aOtherMessage,
+                      uint16_t       aOtherOffset,
+                      uint16_t       aLength,
+                      ByteMatcher    aMatcher = nullptr) const;
 
     /**
      * This method compares the bytes in the message at a given offset with an object.
@@ -774,6 +826,23 @@
     }
 
     /**
+     * This method writes bytes from a given `Data` instance to the message.
+     *
+     * This method will not resize the message. The given data to write MUST fit within the existing message buffer
+     * (from the given offset @p aOffset up to the message's length).
+     *
+     * @tparam     kDataLengthType   Determines the data length type (`uint8_t` or `uint16_t`).
+     *
+     * @param[in]  aOffset    Byte offset within the message to begin writing.
+     * @param[in]  aData      The `Data` to write to the message.
+     *
+     */
+    template <DataLengthType kDataLengthType> void WriteData(uint16_t aOffset, const Data<kDataLengthType> &aData)
+    {
+        WriteBytes(aOffset, aData.GetBytes(), aData.GetLength());
+    }
+
+    /**
      * This method copies bytes from one message to another.
      *
      * If source and destination messages are the same, `CopyTo()` can be used to perform a backward copy, but
@@ -811,7 +880,7 @@
      * `Type`, `SubType`, `LinkSecurity`, `Offset`, `InterfaceId`, and `Priority` fields on the cloned message are also
      * copied from the original one.
      *
-     * @returns A pointer to the message or nullptr if insufficient message buffers are available.
+     * @returns A pointer to the message or `nullptr` if insufficient message buffers are available.
      *
      */
     Message *Clone(void) const { return Clone(GetLength()); }
@@ -930,26 +999,26 @@
     void SetChannel(uint8_t aChannel) { GetMetadata().mChannel = aChannel; }
 
     /**
-     * This method returns the timeout used for 6LoWPAN reassembly.
+     * This method returns the message timestamp.
      *
-     * @returns The time remaining in seconds.
+     * @returns The message timestamp.
      *
      */
-    uint8_t GetTimeout(void) const { return GetMetadata().mTimeout; }
+    TimeMilli GetTimestamp(void) const { return GetMetadata().mTimestamp; }
 
     /**
-     * This method sets the timeout used for 6LoWPAN reassembly.
+     * This method sets the message timestamp to a given time.
      *
-     * @param[in]  aTimeout  The timeout value.
+     * @param[in] aTimestamp   The timestamp value.
      *
      */
-    void SetTimeout(uint8_t aTimeout) { GetMetadata().mTimeout = aTimeout; }
+    void SetTimestamp(TimeMilli aTimestamp) { GetMetadata().mTimestamp = aTimestamp; }
 
     /**
-     * This method decrements the timeout.
+     * This method sets the message timestamp to the current time.
      *
      */
-    void DecrementTimeout(void) { GetMetadata().mTimeout--; }
+    void SetTimestampToNow(void) { SetTimestamp(TimerMilli::GetNow()); }
 
     /**
      * This method returns whether or not message forwarding is scheduled for direct transmission.
@@ -958,7 +1027,7 @@
      * @retval FALSE  If message forwarding is not scheduled for direct transmission.
      *
      */
-    bool GetDirectTransmission(void) const { return GetMetadata().mDirectTx; }
+    bool IsDirectTransmission(void) const { return GetMetadata().mDirectTx; }
 
     /**
      * This method unschedules forwarding using direct transmission.
@@ -1008,6 +1077,23 @@
     void SetDoNotEvict(bool aDoNotEvict) { GetMetadata().mDoNotEvict = aDoNotEvict; }
 
     /**
+     * This method indicates whether the message is waiting for an address query resolution.
+     *
+     * @retval TRUE   If the message is waiting for address query resolution.
+     * @retval FALSE  If the message is not waiting for address query resolution.
+     *
+     */
+    bool IsResolvingAddress(void) const { return GetMetadata().mResolvingAddress; }
+
+    /**
+     * This method sets whether the message is waiting for an address query resolution.
+     *
+     * @param[in] aResolvingAddress    TRUE if message is waiting for address resolution, FALSE otherwise.
+     *
+     */
+    void SetResolvingAddress(bool aResolvingAddress) { GetMetadata().mResolvingAddress = aResolvingAddress; }
+
+    /**
      * This method indicates whether or not link security is enabled for the message.
      *
      * @retval TRUE   If link security is enabled.
@@ -1057,7 +1143,7 @@
      * The given LQI value would be added to the average. Note that a message can be composed of multiple 802.15.4
      * frame fragments each received with a different signal strength.
      *
-     * @param[in] aLQI A new LQI value (has no unit) to be added to average.
+     * @param[in] aLqi A new LQI value (has no unit) to be added to average.
      *
      */
     void AddLqi(uint8_t aLqi) { GetMetadata().mLqiAverager.Add(aLqi); }
@@ -1090,7 +1176,7 @@
     /**
      * This method returns a pointer to the message queue (if any) where this message is queued.
      *
-     * @returns A pointer to the message queue or nullptr if not in any message queue.
+     * @returns A pointer to the message queue or `nullptr` if not in any message queue.
      *
      */
     MessageQueue *GetMessageQueue(void) const
@@ -1101,7 +1187,7 @@
     /**
      * This method returns a pointer to the priority message queue (if any) where this message is queued.
      *
-     * @returns A pointer to the priority queue or nullptr if not in any priority queue.
+     * @returns A pointer to the priority queue or `nullptr` if not in any priority queue.
      *
      */
     PriorityQueue *GetPriorityQueue(void) const
@@ -1205,6 +1291,45 @@
 #endif // #if OPENTHREAD_CONFIG_MULTI_RADIO
 
 protected:
+    class ConstIterator : public ItemPtrIterator<const Message, ConstIterator>
+    {
+        friend class ItemPtrIterator<const Message, ConstIterator>;
+
+    public:
+        ConstIterator(void) = default;
+
+        explicit ConstIterator(const Message *aMessage)
+            : ItemPtrIterator(aMessage)
+        {
+        }
+
+    private:
+        void Advance(void) { mItem = mItem->GetNext(); }
+    };
+
+    class Iterator : public ItemPtrIterator<Message, Iterator>
+    {
+        friend class ItemPtrIterator<Message, Iterator>;
+
+    public:
+        Iterator(void)
+            : mNext(nullptr)
+        {
+        }
+
+        explicit Iterator(Message *aMessage)
+            : ItemPtrIterator(aMessage)
+            , mNext(NextMessage(aMessage))
+        {
+        }
+
+    private:
+        void            Advance(void);
+        static Message *NextMessage(Message *aMessage) { return (aMessage != nullptr) ? aMessage->GetNext() : nullptr; }
+
+        Message *mNext;
+    };
+
     uint16_t GetReserved(void) const { return GetMetadata().mReserved; }
     void     SetReserved(uint16_t aReservedHeader) { GetMetadata().mReserved = aReservedHeader; }
 
@@ -1249,6 +1374,9 @@
     Message *const &Next(void) const { return GetMetadata().mNext; }
     Message *&      Prev(void) { return GetMetadata().mPrev; }
 
+    static Message *      NextOf(Message *aMessage) { return (aMessage != nullptr) ? aMessage->Next() : nullptr; }
+    static const Message *NextOf(const Message *aMessage) { return (aMessage != nullptr) ? aMessage->Next() : nullptr; }
+
     Error ResizeMessage(uint16_t aLength);
 };
 
@@ -1262,6 +1390,8 @@
     friend class PriorityQueue;
 
 public:
+    typedef otMessageQueueInfo Info; ///< This struct represents info (number of messages/buffers) about a queue.
+
     /**
      * This enumeration represents a position (head or tail) in the queue. This is used to specify where a new message
      * should be added in the queue.
@@ -1277,7 +1407,7 @@
      * This constructor initializes the message queue.
      *
      */
-    MessageQueue(void);
+    MessageQueue(void) { SetTail(nullptr); }
 
     /**
      * This method returns a pointer to the first message.
@@ -1285,7 +1415,15 @@
      * @returns A pointer to the first message.
      *
      */
-    Message *GetHead(void) const;
+    Message *GetHead(void) { return Message::NextOf(GetTail()); }
+
+    /**
+     * This method returns a pointer to the first message.
+     *
+     * @returns A pointer to the first message.
+     *
+     */
+    const Message *GetHead(void) const { return Message::NextOf(GetTail()); }
 
     /**
      * This method adds a message to the end of the list.
@@ -1327,35 +1465,53 @@
     void DequeueAndFreeAll(void);
 
     /**
-     * This method returns the number of messages and buffers enqueued.
+     * This method gets the information about number of messages and buffers in the queue.
      *
-     * @param[out]  aMessageCount  Returns the number of messages enqueued.
-     * @param[out]  aBufferCount   Returns the number of buffers enqueued.
+     * This method updates `aInfo` and adds number of message/buffers in the message queue to the corresponding member
+     * variable in `aInfo`. The caller needs to make sure `aInfo` is initialized before calling this method (e.g.,
+     * clearing `aInfo`). Same `aInfo` can be passed in multiple calls of `GetInfo(aInfo)` on different queues to add
+     * up the number of messages/buffers on different queues.
+     *
+     * @param[out] aInfo  A reference to `Info` structure to update.ni
      *
      */
-    void GetInfo(uint16_t &aMessageCount, uint16_t &aBufferCount) const;
+    void GetInfo(Info &aInfo) const;
+
+    // The following methods are intended to support range-based `for`
+    // loop iteration over the queue entries and should not be used
+    // directly. The range-based `for` works correctly even if the
+    // current entry is removed from the queue during iteration.
+
+    Message::Iterator begin(void);
+    Message::Iterator end(void) { return Message::Iterator(); }
+
+    Message::ConstIterator begin(void) const;
+    Message::ConstIterator end(void) const { return Message::ConstIterator(); }
 
 private:
-    Message *GetTail(void) const { return static_cast<Message *>(mData); }
-    void     SetTail(Message *aMessage) { mData = aMessage; }
+    Message *      GetTail(void) { return static_cast<Message *>(mData); }
+    const Message *GetTail(void) const { return static_cast<const Message *>(mData); }
+    void           SetTail(Message *aMessage) { mData = aMessage; }
 };
 
 /**
  * This class implements a priority queue.
  *
  */
-class PriorityQueue
+class PriorityQueue : private Clearable<PriorityQueue>
 {
     friend class Message;
     friend class MessageQueue;
     friend class MessagePool;
 
 public:
+    typedef otMessageQueueInfo Info; ///< This struct represents info (number of messages/buffers) about a queue.
+
     /**
      * This constructor initializes the priority queue.
      *
      */
-    PriorityQueue(void);
+    PriorityQueue(void) { Clear(); }
 
     /**
      * This method returns a pointer to the first message.
@@ -1363,18 +1519,40 @@
      * @returns A pointer to the first message.
      *
      */
-    Message *GetHead(void) const;
+    Message *GetHead(void) { return AsNonConst(AsConst(this)->GetHead()); }
+
+    /**
+     * This method returns a pointer to the first message.
+     *
+     * @returns A pointer to the first message.
+     *
+     */
+    const Message *GetHead(void) const;
 
     /**
      * This method returns a pointer to the first message for a given priority level.
      *
      * @param[in] aPriority   Priority level.
      *
-     * @returns A pointer to the first message with given priority level or nullptr if there is no messages with
+     * @returns A pointer to the first message with given priority level or `nullptr` if there is no messages with
      *          this priority level.
      *
      */
-    Message *GetHeadForPriority(Message::Priority aPriority) const;
+    Message *GetHeadForPriority(Message::Priority aPriority)
+    {
+        return AsNonConst(AsConst(this)->GetHeadForPriority(aPriority));
+    }
+
+    /**
+     * This method returns a pointer to the first message for a given priority level.
+     *
+     * @param[in] aPriority   Priority level.
+     *
+     * @returns A pointer to the first message with given priority level or `nullptr` if there is no messages with
+     *          this priority level.
+     *
+     */
+    const Message *GetHeadForPriority(Message::Priority aPriority) const;
 
     /**
      * This method adds a message to the queue.
@@ -1407,21 +1585,44 @@
     void DequeueAndFreeAll(void);
 
     /**
-     * This method returns the number of messages and buffers enqueued.
-     *
-     * @param[out]  aMessageCount  Returns the number of messages enqueued.
-     * @param[out]  aBufferCount   Returns the number of buffers enqueued.
-     *
-     */
-    void GetInfo(uint16_t &aMessageCount, uint16_t &aBufferCount) const;
-
-    /**
-     * This method returns the tail of the list (last message in the list)
+     * This method returns the tail of the list (last message in the list).
      *
      * @returns A pointer to the tail of the list.
      *
      */
-    Message *GetTail(void) const;
+    Message *GetTail(void) { return AsNonConst(AsConst(this)->GetTail()); }
+
+    /**
+     * This method returns the tail of the list (last message in the list).
+     *
+     * @returns A pointer to the tail of the list.
+     *
+     */
+    const Message *GetTail(void) const;
+
+    /**
+     * This method gets the information about number of messages and buffers in the priority queue.
+     *
+     * This method updates `aInfo` array and adds number of message/buffers in the message queue to the corresponding
+     * member variable in `aInfo`. The caller needs to make sure `aInfo` is initialized before calling this method
+     * (e.g., clearing `aInfo`). Same `aInfo` can be passed in multiple calls of `GetInfo(aInfo)` on different queues
+     * to add up the number of messages/buffers on different queues.
+     *
+     * @param[out] aInfo  A reference to an `Info` structure to update.
+     *
+     */
+    void GetInfo(Info &aInfo) const;
+
+    // The following methods are intended to support range-based `for`
+    // loop iteration over the queue entries and should not be used
+    // directly. The range-based `for` works correctly even if the
+    // current entry is removed from the queue during iteration.
+
+    Message::Iterator begin(void);
+    Message::Iterator end(void) { return Message::Iterator(); }
+
+    Message::ConstIterator begin(void) const;
+    Message::ConstIterator end(void) const { return Message::ConstIterator(); }
 
 private:
     uint8_t PrevPriority(uint8_t aPriority) const
@@ -1429,7 +1630,12 @@
         return (aPriority == Message::kNumPriorities - 1) ? 0 : (aPriority + 1);
     }
 
-    Message *FindFirstNonNullTail(Message::Priority aStartPriorityLevel) const;
+    const Message *FindFirstNonNullTail(Message::Priority aStartPriorityLevel) const;
+
+    Message *FindFirstNonNullTail(Message::Priority aStartPriorityLevel)
+    {
+        return AsNonConst(AsConst(this)->FindFirstNonNullTail(aStartPriorityLevel));
+    }
 
     Message *mTails[Message::kNumPriorities]; // Tail pointers associated with different priority levels.
 };
@@ -1452,32 +1658,18 @@
     explicit MessagePool(Instance &aInstance);
 
     /**
-     * This method is used to obtain a new message.
-     *
-     * The link security is enabled by default on the newly obtained message.
-     *
-     * @param[in]  aType           The message type.
-     * @param[in]  aReserveHeader  The number of header bytes to reserve.
-     * @param[in]  aPriority       The priority level of the message.
-     *
-     * @returns A pointer to the message or nullptr if no message buffers are available.
-     *
-     */
-    Message *New(Message::Type aType, uint16_t aReserveHeader, Message::Priority aPriority);
-
-    /**
-     * This method is used to obtain a new message with specified settings.
+     * This method allocates a new message with specified settings.
      *
      * @param[in]  aType           The message type.
      * @param[in]  aReserveHeader  The number of header bytes to reserve.
      * @param[in]  aSettings       The message settings.
      *
-     * @returns A pointer to the message or nullptr if no message buffers are available.
+     * @returns A pointer to the message or `nullptr` if no message buffers are available.
      *
      */
-    Message *New(Message::Type            aType,
-                 uint16_t                 aReserveHeader,
-                 const Message::Settings &aSettings = Message::Settings::GetDefault());
+    Message *Allocate(Message::Type            aType,
+                      uint16_t                 aReserveHeader = 0,
+                      const Message::Settings &aSettings      = Message::Settings::GetDefault());
 
     /**
      * This method is used to free a message and return all message buffers to the buffer pool.
@@ -1490,7 +1682,7 @@
     /**
      * This method returns the number of free buffers.
      *
-     * @returns The number of free buffers.
+     * @returns The number of free buffers, or 0xffff (UINT16_MAX) if number is unknown.
      *
      */
     uint16_t GetFreeBufferCount(void) const;
@@ -1498,7 +1690,7 @@
     /**
      * This method returns the total number of buffers.
      *
-     * @returns The total number of buffers.
+     * @returns The total number of buffers, or 0xffff (UINT16_MAX) if number is unknown.
      *
      */
     uint16_t GetTotalBufferCount(void) const;
@@ -1514,11 +1706,21 @@
 #endif
 };
 
+inline Instance &Message::GetInstance(void) const
+{
+    return GetMessagePool()->GetInstance();
+}
+
 /**
  * @}
  *
  */
 
+DefineCoreType(otMessageBuffer, Buffer);
+DefineCoreType(otMessageSettings, Message::Settings);
+DefineCoreType(otMessage, Message);
+DefineCoreType(otMessageQueue, MessageQueue);
+
 } // namespace ot
 
 #endif // MESSAGE_HPP_
diff --git a/src/core/common/notifier.cpp b/src/core/common/notifier.cpp
index a77660a..7fd2831 100644
--- a/src/core/common/notifier.cpp
+++ b/src/core/common/notifier.cpp
@@ -34,13 +34,16 @@
 #include "notifier.hpp"
 
 #include "border_router/routing_manager.hpp"
+#include "common/array.hpp"
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 
 namespace ot {
 
+RegisterLogModule("Notifier");
+
 Notifier::Notifier(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mTask(aInstance, Notifier::EmitEvents)
@@ -165,6 +168,9 @@
 #if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
     Get<DuaManager>().HandleNotifierEvents(events);
 #endif
+#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
+    Get<Trel::Link>().HandleNotifierEvents(events);
+#endif
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
     Get<TimeSync>().HandleNotifierEvents(events);
 #endif
@@ -210,7 +216,7 @@
 
 // LCOV_EXCL_START
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_CORE == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
 void Notifier::LogEvents(Events aEvents) const
 {
@@ -227,8 +233,8 @@
         {
             if (string.GetLength() >= kFlagsStringLineLimit)
             {
-                otLogInfoCore("Notifier: StateChanged (0x%08x) %s%s ...", aEvents.GetAsFlags(), didLog ? "... " : "[",
-                              string.AsCString());
+                LogInfo("StateChanged (0x%08x) %s%s ...", aEvents.GetAsFlags(), didLog ? "... " : "[",
+                        string.AsCString());
                 string.Clear();
                 didLog   = true;
                 addSpace = false;
@@ -242,8 +248,7 @@
     }
 
 exit:
-    otLogInfoCore("Notifier: StateChanged (0x%08x) %s%s]", aEvents.GetAsFlags(), didLog ? "... " : "[",
-                  string.AsCString());
+    LogInfo("StateChanged (0x%08x) %s%s]", aEvents.GetAsFlags(), didLog ? "... " : "[", string.AsCString());
 }
 
 const char *Notifier::EventToString(Event aEvent) const
@@ -286,7 +291,7 @@
         "PndDset",           // kEventPendingDatasetChanged            (1 << 29)
     };
 
-    for (uint8_t index = 0; index < OT_ARRAY_LENGTH(kEventStrings); index++)
+    for (uint8_t index = 0; index < GetArrayLength(kEventStrings); index++)
     {
         if (static_cast<uint32_t>(aEvent) == (1U << index))
         {
@@ -298,7 +303,7 @@
     return retval;
 }
 
-#else // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_CORE == 1)
+#else // #if OT_SHOULD_LOG_AT( OT_LOG_LEVEL_INFO)
 
 void Notifier::LogEvents(Events) const
 {
@@ -309,7 +314,7 @@
     return "";
 }
 
-#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_CORE == 1)
+#endif // #if OT_SHOULD_LOG_AT( OT_LOG_LEVEL_INFO)
 
 // LCOV_EXCL_STOP
 
diff --git a/src/core/common/notifier.hpp b/src/core/common/notifier.hpp
index 96494ac..8887671 100644
--- a/src/core/common/notifier.hpp
+++ b/src/core/common/notifier.hpp
@@ -222,7 +222,7 @@
      * This method removes/unregisters a previously registered `otStateChangedCallback` handler.
      *
      * @param[in]  aCallback     A pointer to the callback function pointer.
-     * @param[in]  aContex       A pointer to arbitrary context information.
+     * @param[in]  aContext      A pointer to arbitrary context information.
      *
      */
     void RemoveCallback(otStateChangedCallback aCallback, void *aContext);
@@ -270,9 +270,9 @@
      *
      * The template `Type` should support comparison operator `==` and assignment operator `=`.
      *
-     * @param[inout] aVariable    A reference to the variable to update.
-     * @param[in]    aNewValue    The new value.
-     * @param[in]    aEvent       The event to signal.
+     * @param[in,out] aVariable    A reference to the variable to update.
+     * @param[in]     aNewValue    The new value.
+     * @param[in]     aEvent       The event to signal.
      *
      * @retval kErrorNone      The variable was update successfully and @p aEvent was signaled.
      * @retval kErrorAlready   The variable was already set to the same value.
diff --git a/src/core/common/owned_ptr.hpp b/src/core/common/owned_ptr.hpp
new file mode 100644
index 0000000..ab98fd3
--- /dev/null
+++ b/src/core/common/owned_ptr.hpp
@@ -0,0 +1,190 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes definitions for an owned smart pointer.
+ */
+
+#ifndef OWNED_PTR_HPP_
+#define OWNED_PTR_HPP_
+
+#include "openthread-core-config.h"
+
+#include "common/ptr_wrapper.hpp"
+
+namespace ot {
+
+/**
+ * This template class represents an owned smart pointer.
+ *
+ * `OwnedPtr` acts as sole owner of the object it manages. An `OwnedPtr` is non-copyable (copy constructor is deleted)
+ * but the ownership can be transferred from one `OwnedPtr` to another using move semantics.
+ *
+ * The `Type` class MUST provide `Free()` method which frees the instance.
+ *
+ * @tparam Type  The pointer type.
+ *
+ */
+template <class Type> class OwnedPtr : public Ptr<Type>
+{
+    using Ptr<Type>::mPointer;
+
+public:
+    /**
+     * This is the default constructor for `OwnedPtr` initializing it as null.
+     *
+     */
+    OwnedPtr(void) = default;
+
+    /**
+     * This constructor initializes the `OwnedPtr` with a given pointer.
+     *
+     * The `OwnedPtr` takes the ownership of the object at @p aPointer.
+     *
+     * @param[in] aPointer  A pointer to object to initialize with.
+     *
+     */
+    explicit OwnedPtr(Type *aPointer)
+        : Ptr<Type>(aPointer)
+    {
+    }
+
+    /**
+     * This constructor initializes the `OwnedPtr` from another `OwnedPtr` using move semantics.
+     *
+     * The `OwnedPtr` takes over the ownership of the object from @p aOther. After this call, @p aOther will be null.
+     *
+     * @param[in] aOther   An rvalue reference to another `OwnedPtr`.
+     *
+     */
+    OwnedPtr(OwnedPtr &&aOther)
+    {
+        mPointer        = aOther.mPointer;
+        aOther.mPointer = nullptr;
+    }
+
+    /**
+     * This is the destructor for `OwnedPtr`.
+     *
+     * Upon destruction, the `OwnedPtr` invokes `Free()` method on its managed object (if any).
+     *
+     */
+    ~OwnedPtr(void) { Delete(); }
+
+    /**
+     * This method frees the owned object (if any).
+     *
+     * This method invokes `Free()` method on the `Type` object owned by `OwnedPtr` (if any). It will also set the
+     * `OwnedPtr` to null.
+     *
+     */
+    void Free(void)
+    {
+        Delete();
+        mPointer = nullptr;
+    }
+
+    /**
+     * This method frees the current object owned by `OwnedPtr` (if any) and replaces it with a new one.
+     *
+     * The method will `Free()` the current object managed by `OwnedPtr` (if different from @p aPointer) before taking
+     * the ownership of the object at @p aPointer. The method correctly handles a self `Reset()` (i.e., @p aPointer
+     * being the same pointer as the one currently managed by `OwnedPtr`).
+     *
+     * @param[in] aPointer   A pointer to the new object to replace with.
+     *
+     */
+    void Reset(Type *aPointer = nullptr)
+    {
+        if (mPointer != aPointer)
+        {
+            Delete();
+            mPointer = aPointer;
+        }
+    }
+
+    /**
+     * This method releases the ownership of the current object in `OwnedPtr` (if any).
+     *
+     * After this call, the `OwnedPtr` will be null.
+     *
+     * @returns The pointer to the object owned by `OwnedPtr` or `nullptr` if `OwnedPtr` was null.
+     *
+     */
+    Type *Release(void)
+    {
+        Type *pointer = mPointer;
+        mPointer      = nullptr;
+        return pointer;
+    }
+
+    /**
+     * This method allows passing of the ownership to another `OwnedPtr` using move semantics.
+     *
+     * @returns An rvalue reference of the pointer to move from.
+     *
+     */
+    OwnedPtr &&PassOwnership(void) { return static_cast<OwnedPtr &&>(*this); }
+
+    /**
+     * This method overload the assignment operator `=` to replace the object owned by the `OwnedPtr` with another one
+     * using move semantics.
+     *
+     * The `OwnedPtr` first frees its current owned object (if there is any and it is different from @p aOther) before
+     * taking over the ownership of the object from @p aOther. This method correctly handles a self assignment (i.e.,
+     * assigning the pointer to itself).
+     *
+     * @param[in] aOther   An rvalue reference to an `OwnedPtr` to move from.
+     *
+     * @returns A reference to this `OwnedPtr`.
+     *
+     */
+    OwnedPtr &operator=(OwnedPtr &&aOther)
+    {
+        Reset(aOther.Release());
+        return *this;
+    }
+
+    OwnedPtr(const OwnedPtr &) = delete;
+    OwnedPtr(OwnedPtr &)       = delete;
+    OwnedPtr &operator=(const OwnedPtr &) = delete;
+
+private:
+    void Delete(void)
+    {
+        if (mPointer != nullptr)
+        {
+            mPointer->Free();
+        }
+    }
+};
+
+} // namespace ot
+
+#endif // OWNED_PTR_HPP_
diff --git a/src/core/common/owning_list.hpp b/src/core/common/owning_list.hpp
new file mode 100644
index 0000000..3b73fe6
--- /dev/null
+++ b/src/core/common/owning_list.hpp
@@ -0,0 +1,156 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes definitions for a singly linked list which owns its entries and frees them upon destruction of
+ *   the list.
+ */
+
+#ifndef OWNING_LIST_HPP_
+#define OWNING_LIST_HPP_
+
+#include "openthread-core-config.h"
+
+#include "common/linked_list.hpp"
+#include "common/owned_ptr.hpp"
+
+namespace ot {
+
+/**
+ * This template class represents a singly linked list which owns its entries and frees them upon destruction of the
+ * list.
+ *
+ */
+template <typename Type> class OwningList : public LinkedList<Type>
+{
+    class Iterator;
+    class ConstIterator;
+
+public:
+    /**
+     * This is the default constructor for `OwningList`
+     *
+     */
+    OwningList(void) = default;
+
+    /**
+     * This is the destructor for `OwningList`.
+     *
+     * On destruction, all existing entries in the list are freed.
+     *
+     */
+    ~OwningList(void) { Free(); }
+
+    /**
+     * This method clears the list and frees all existing entries in it.
+     *
+     */
+    void Free(void)
+    {
+        while (!Pop().IsNull())
+        {
+        }
+    }
+
+    /**
+     * This method clears the list and frees all existing entries in it.
+     *
+     */
+    void Clear(void) { Free(); }
+
+    /**
+     * This method pops an entry from head of the linked list and return an `OwnedPtr` to it.
+     *
+     * @note This method does not change the popped entry itself, i.e., the popped entry next pointer stays as before.
+     *
+     * @returns An `OwnedPtr` to the entry that was popped (set to null if list of empty).
+     *
+     */
+    OwnedPtr<Type> Pop(void) { return OwnedPtr<Type>(LinkedList<Type>::Pop()); }
+
+    /**
+     * This method pops an entry after a given previous entry.
+     *
+     * @note This method does not change the popped entry itself, i.e., the popped entry next pointer stays as before.
+     *
+     * @param[in] aPrevEntry  A pointer to a previous entry. If it is not `nullptr` the entry after this will be popped,
+     *                        otherwise (if it is `nullptr`) the entry at the head of the list is popped.
+     *
+     * @returns An `OwnedPtr` to the entry that was popped (set to null if there is no entry to pop).
+     *
+     */
+    OwnedPtr<Type> PopAfter(Type *aPrevEntry) { return OwnedPtr<Type>(LinkedList<Type>::PopAfter(aPrevEntry)); }
+
+    /**
+     * This template method removes an entry matching a given entry indicator from the linked list.
+     *
+     * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries
+     * in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each
+     * `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly:
+     *
+     *     bool Type::Matches(const Indicator &aIndicator) const
+     *
+     * @note This method does not change the removed entry itself (which is returned in case of success), i.e., the
+     * entry next pointer stays as before.
+     *
+     * @param[in] aIndicator   An entry indicator to match against entries in the list.
+     *
+     * @returns An `OwnedPtr` to the entry that was removed (set to null if there is no matching entry to remove).
+     *
+     */
+    template <typename Indicator> OwnedPtr<Type> RemoveMatching(const Indicator &aIndicator)
+    {
+        return OwnedPtr<Type>(LinkedList<Type>::RemoveMatching(aIndicator));
+    }
+
+    /**
+     * This template method removes all entries in the list matching a given entry indicator from the list and adds
+     * them to a new list.
+     *
+     * The template type `Indicator` specifies the type of @p aIndicator object which is used to match against entries
+     * in the list. To check that an entry matches the given indicator, the `Matches()` method is invoked on each
+     * `Type` entry in the list. The `Matches()` method should be provided by `Type` class accordingly:
+     *
+     *     bool Type::Matches(const Indicator &aIndicator) const
+     *
+     * The ownership of the removed entries is transferred from the original list to the @p aRemovedList.
+     *
+     * @param[in] aIndicator   An entry indicator to match against entries in the list.
+     * @param[in] aRemovedList The list to add the removed entries to.
+     *
+     */
+    template <typename Indicator> void RemoveAllMatching(const Indicator &aIndicator, OwningList &aRemovedList)
+    {
+        LinkedList<Type>::RemoveAllMatching(aIndicator, aRemovedList);
+    }
+};
+
+} // namespace ot
+
+#endif // OWNING_LIST_HPP_
diff --git a/src/core/common/pool.hpp b/src/core/common/pool.hpp
index 66e8c71..279655f 100644
--- a/src/core/common/pool.hpp
+++ b/src/core/common/pool.hpp
@@ -36,6 +36,7 @@
 
 #include "openthread-core-config.h"
 
+#include "common/array.hpp"
 #include "common/linked_list.hpp"
 #include "common/non_copyable.hpp"
 
@@ -99,7 +100,8 @@
     /**
      * This method allocates a new object from the pool.
      *
-     * @returns A pointer to the newly allocated object, or nullptr if all entries from the pool are already allocated.
+     * @returns A pointer to the newly allocated object, or `nullptr` if all entries from the pool are already
+     *          allocated.
      *
      */
     Type *Allocate(void) { return mFreeList.Pop(); }
@@ -146,7 +148,7 @@
      * @retval FALSE if @p aObject is not from the pool.
      *
      */
-    bool IsPoolEntry(const Type &aObject) const { return (&mPool[0] <= &aObject) && (&aObject < OT_ARRAY_END(mPool)); }
+    bool IsPoolEntry(const Type &aObject) const { return (&mPool[0] <= &aObject) && (&aObject < GetArrayEnd(mPool)); }
 
     /**
      * This method returns the associated index of a given entry from the pool.
diff --git a/src/core/common/ptr_wrapper.hpp b/src/core/common/ptr_wrapper.hpp
new file mode 100644
index 0000000..1a65543
--- /dev/null
+++ b/src/core/common/ptr_wrapper.hpp
@@ -0,0 +1,186 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes definitions for a pointer wrapper.
+ */
+
+#ifndef PTR_WRAPPER_HPP_
+#define PTR_WRAPPER_HPP_
+
+#include "openthread-core-config.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+
+namespace ot {
+
+/**
+ * This template class represents a wrapper over a pointer.
+ *
+ * This is intended as base class of `OwnedPtr` or `RetainPtr` providing common simple methods.
+ *
+ * @tparam Type  The pointer type.
+ *
+ */
+template <class Type> class Ptr
+{
+public:
+    /**
+     * This is the default constructor for `Ptr` initializing it as null.
+     *
+     */
+    Ptr(void)
+        : mPointer(nullptr)
+    {
+    }
+
+    /**
+     * This constructor initializes the `Ptr` with a given pointer.
+     *
+     * @param[in] aPointer  A pointer to initialize with.
+     *
+     */
+    explicit Ptr(Type *aPointer)
+        : mPointer(aPointer)
+    {
+    }
+
+    /**
+     * This method indicates whether the `Ptr` is null or not.
+     *
+     * @retval TRUE   The `Ptr` is null.
+     * @retval FALSE  The `Ptr` is not null.
+     *
+     */
+    bool IsNull(void) const { return (mPointer == nullptr); }
+
+    /**
+     * This method gets the wrapped pointer.
+     *
+     * @returns The wrapped pointer.
+     *
+     */
+    Type *Get(void) { return mPointer; }
+
+    /**
+     * This method gets the wrapped pointer.
+     *
+     * @returns The wrapped pointer.
+     *
+     */
+    const Type *Get(void) const { return mPointer; }
+
+    /**
+     * This method overloads the `->` dereference operator and returns the pointer.
+     *
+     * @returns The wrapped pointer.
+     *
+     */
+    Type *operator->(void) { return mPointer; }
+
+    /**
+     * This method overloads the `->` dereference operator and returns the pointer.
+     *
+     * @returns The wrapped pointer.
+     *
+     */
+    const Type *operator->(void)const { return mPointer; }
+
+    /**
+     * This method overloads the `*` dereference operator and returns a reference to the pointed object.
+     *
+     * The behavior is undefined if `IsNull() == true`.
+     *
+     * @returns A reference to the pointed object.
+     *
+     */
+    Type &operator*(void) { return *mPointer; }
+
+    /**
+     * This method overloads the `*` dereference operator and returns a reference to the pointed object.
+     *
+     * The behavior is undefined if `IsNull() == true`.
+     *
+     * @returns A reference to the pointed object.
+     *
+     */
+    const Type &operator*(void)const { return *mPointer; }
+
+    /**
+     * This method overloads the operator `==` to compare the `Ptr` with a given pointer.
+     *
+     * @param[in] aPointer   The pointer to compare with.
+     *
+     * @retval TRUE   If `Ptr` is equal to @p aPointer.
+     * @retval FALSE  If `Ptr` is not equal to @p aPointer.
+     *
+     */
+    bool operator==(const Type *aPointer) const { return (mPointer == aPointer); }
+
+    /**
+     * This method overloads the operator `!=` to compare the `Ptr` with a given pointer.
+     *
+     * @param[in] aPointer   The pointer to compare with.
+     *
+     * @retval TRUE   If `Ptr` is not equal to @p aPointer.
+     * @retval FALSE  If `Ptr` is equal to @p aPointer.
+     *
+     */
+    bool operator!=(const Type *aPointer) const { return (mPointer != aPointer); }
+
+    /**
+     * This method overloads the operator `==` to compare the `Ptr` with another `Ptr`.
+     *
+     * @param[in] aOther   The other `Ptr` to compare with.
+     *
+     * @retval TRUE   If `Ptr` is equal to @p aOther.
+     * @retval FALSE  If `Ptr` is not equal to @p aOther.
+     *
+     */
+    bool operator==(const Ptr &aOther) const { return (mPointer == aOther.mPointer); }
+
+    /**
+     * This method overloads the operator `!=` to compare the `Ptr` with another `Ptr`.
+     *
+     * @param[in] aOther   The other `Ptr` to compare with.
+     *
+     * @retval TRUE   If `Ptr` is not equal to @p aOther.
+     * @retval FALSE  If `Ptr` is equal to @p aOther.
+     *
+     */
+    bool operator!=(const Ptr &aOther) const { return (mPointer != aOther.mPointer); }
+
+protected:
+    Type *mPointer;
+};
+
+} // namespace ot
+
+#endif // PTR_WRAPPER_HPP_
diff --git a/src/core/common/random.cpp b/src/core/common/random.cpp
new file mode 100644
index 0000000..482d68d
--- /dev/null
+++ b/src/core/common/random.cpp
@@ -0,0 +1,168 @@
+/*
+ *  Copyright (c) 2019, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file provides an implementation of OpenThread random number generation manager class.
+ */
+
+#include "random.hpp"
+
+#include <openthread/platform/entropy.h>
+
+#include "common/code_utils.hpp"
+#include "common/debug.hpp"
+
+namespace ot {
+namespace Random {
+
+uint16_t               Manager::sInitCount = 0;
+Manager::NonCryptoPrng Manager::sPrng;
+
+Manager::Manager(void)
+{
+    uint32_t seed;
+
+    OT_ASSERT(sInitCount < 0xffff);
+
+    VerifyOrExit(sInitCount == 0);
+
+#if !OPENTHREAD_RADIO
+    otPlatCryptoRandomInit();
+    SuccessOrAssert(Random::Crypto::FillBuffer(reinterpret_cast<uint8_t *>(&seed), sizeof(seed)));
+#else
+    SuccessOrAssert(otPlatEntropyGet(reinterpret_cast<uint8_t *>(&seed), sizeof(seed)));
+#endif
+
+    sPrng.Init(seed);
+
+exit:
+    sInitCount++;
+}
+
+Manager::~Manager(void)
+{
+    OT_ASSERT(sInitCount > 0);
+
+    sInitCount--;
+    VerifyOrExit(sInitCount == 0);
+
+#if !OPENTHREAD_RADIO
+    otPlatCryptoRandomDeinit();
+#endif
+
+exit:
+    return;
+}
+
+uint32_t Manager::NonCryptoGetUint32(void)
+{
+    OT_ASSERT(sInitCount > 0);
+
+    return sPrng.GetNext();
+}
+
+//-------------------------------------------------------------------
+// NonCryptoPrng
+
+void Manager::NonCryptoPrng::Init(uint32_t aSeed)
+{
+    // The PRNG has a cycle of length 1 for the below two initial
+    // seeds. For all other seed values the cycle is ~2^31 long.
+
+    if ((aSeed == 0) || (aSeed == 0x7fffffff))
+    {
+        aSeed = 0x1;
+    }
+
+    mState = aSeed;
+}
+
+uint32_t Manager::NonCryptoPrng::GetNext(void)
+{
+    uint32_t mlcg, p, q;
+    uint64_t tmpstate;
+
+    tmpstate = static_cast<uint64_t>(33614) * static_cast<uint64_t>(mState);
+    q        = tmpstate & 0xffffffff;
+    q        = q >> 1;
+    p        = tmpstate >> 32;
+    mlcg     = p + q;
+
+    if (mlcg & 0x80000000)
+    {
+        mlcg &= 0x7fffffff;
+        mlcg++;
+    }
+
+    mState = mlcg;
+
+    return mlcg;
+}
+
+//-------------------------------------------------------------------
+
+namespace NonCrypto {
+
+uint8_t GetUint8InRange(uint8_t aMin, uint8_t aMax)
+{
+    OT_ASSERT(aMax > aMin);
+
+    return (aMin + (GetUint8() % (aMax - aMin)));
+}
+
+uint16_t GetUint16InRange(uint16_t aMin, uint16_t aMax)
+{
+    OT_ASSERT(aMax > aMin);
+    return (aMin + (GetUint16() % (aMax - aMin)));
+}
+
+uint32_t GetUint32InRange(uint32_t aMin, uint32_t aMax)
+{
+    OT_ASSERT(aMax > aMin);
+    return (aMin + (GetUint32() % (aMax - aMin)));
+}
+
+void FillBuffer(uint8_t *aBuffer, uint16_t aSize)
+{
+    while (aSize-- != 0)
+    {
+        *aBuffer++ = GetUint8();
+    }
+}
+
+uint32_t AddJitter(uint32_t aValue, uint16_t aJitter)
+{
+    aJitter = (aJitter <= aValue) ? aJitter : static_cast<uint16_t>(aValue);
+
+    return aValue + GetUint32InRange(0, 2 * aJitter + 1) - aJitter;
+}
+
+} // namespace NonCrypto
+} // namespace Random
+} // namespace ot
diff --git a/src/core/common/random.hpp b/src/core/common/random.hpp
index da00281..d3b75d0 100644
--- a/src/core/common/random.hpp
+++ b/src/core/common/random.hpp
@@ -38,12 +38,70 @@
 
 #include <stdint.h>
 
+#include <openthread/platform/crypto.h>
+
 #include "common/debug.hpp"
 #include "common/error.hpp"
-#include "common/random_manager.hpp"
+#include "common/non_copyable.hpp"
 
 namespace ot {
 namespace Random {
+
+/**
+ * This class manages random number generator initialization/deinitialization.
+ *
+ */
+class Manager : private NonCopyable
+{
+public:
+    /**
+     * This constructor initializes the object.
+     *
+     */
+    Manager(void);
+
+    /**
+     * This destructor deinitializes the object.
+     *
+     */
+    ~Manager(void);
+
+    /**
+     * This static method generates and returns a random value using a non-crypto Pseudo Random Number Generator.
+     *
+     * @returns    A random `uint32_t` value.
+     *
+     */
+    static uint32_t NonCryptoGetUint32(void);
+
+#if !OPENTHREAD_RADIO
+    /**
+     * This static method fills a given buffer with cryptographically secure random bytes.
+     *
+     * @param[out] aBuffer  A pointer to a buffer to fill with the random bytes.
+     * @param[in]  aSize    Size of buffer (number of bytes to fill).
+     *
+     * @retval kErrorNone    Successfully filled buffer with random values.
+     *
+     */
+    static Error CryptoFillBuffer(uint8_t *aBuffer, uint16_t aSize) { return otPlatCryptoRandomGet(aBuffer, aSize); }
+#endif
+
+private:
+    class NonCryptoPrng // A non-crypto Pseudo Random Number Generator (PRNG)
+    {
+    public:
+        void     Init(uint32_t aSeed);
+        uint32_t GetNext(void);
+
+    private:
+        uint32_t mState;
+    };
+
+    static uint16_t      sInitCount;
+    static NonCryptoPrng sPrng;
+};
+
 namespace NonCrypto {
 
 /**
@@ -54,7 +112,7 @@
  */
 inline uint32_t GetUint32(void)
 {
-    return ot::RandomManager::NonCryptoGetUint32();
+    return Manager::NonCryptoGetUint32();
 }
 
 /**
@@ -86,12 +144,9 @@
  * @param[in]  aMax  A maximum value (this value is excluded from returned random result).
  *
  * @returns    A random `uint8_t` value in the given range (i.e., aMin <= random value < aMax).
+ *
  */
-inline uint8_t GetUint8InRange(uint8_t aMin, uint8_t aMax)
-{
-    OT_ASSERT(aMax > aMin);
-    return (aMin + (GetUint8() % (aMax - aMin)));
-}
+uint8_t GetUint8InRange(uint8_t aMin, uint8_t aMax);
 
 /**
  * This function generates and returns a random `uint16_t` value within a given range `[aMin, aMax)`.
@@ -102,12 +157,9 @@
  * @param[in]  aMax  A maximum value (this value is excluded from returned random result).
  *
  * @returns    A random `uint16_t` value in the given range (i.e., aMin <= random value < aMax).
+ *
  */
-inline uint16_t GetUint16InRange(uint16_t aMin, uint16_t aMax)
-{
-    OT_ASSERT(aMax > aMin);
-    return (aMin + (GetUint16() % (aMax - aMin)));
-}
+uint16_t GetUint16InRange(uint16_t aMin, uint16_t aMax);
 
 /**
  * This function generates and returns a random `uint32_t` value within a given range `[aMin, aMax)`.
@@ -120,11 +172,7 @@
  * @returns    A random `uint32_t` value in the given range (i.e., aMin <= random value < aMax).
  *
  */
-inline uint32_t GetUint32InRange(uint32_t aMin, uint32_t aMax)
-{
-    OT_ASSERT(aMax > aMin);
-    return (aMin + (GetUint32() % (aMax - aMin)));
-}
+uint32_t GetUint32InRange(uint32_t aMin, uint32_t aMax);
 
 /**
  * This function fills a given buffer with random bytes.
@@ -133,13 +181,7 @@
  * @param[in]  aSize    Size of buffer (number of bytes to fill).
  *
  */
-inline void FillBuffer(uint8_t *aBuffer, uint16_t aSize)
-{
-    while (aSize-- != 0)
-    {
-        *aBuffer++ = GetUint8();
-    }
-}
+void FillBuffer(uint8_t *aBuffer, uint16_t aSize);
 
 /**
  * This function adds a random jitter within a given range to a given value.
@@ -150,12 +192,7 @@
  * @returns    The given value with an added random jitter.
  *
  */
-inline uint32_t AddJitter(uint32_t aValue, uint16_t aJitter)
-{
-    aJitter = (aJitter <= aValue) ? aJitter : static_cast<uint16_t>(aValue);
-
-    return aValue + GetUint32InRange(0, 2 * aJitter + 1) - aJitter;
-}
+uint32_t AddJitter(uint32_t aValue, uint16_t aJitter);
 
 } // namespace NonCrypto
 
@@ -174,18 +211,7 @@
  */
 inline Error FillBuffer(uint8_t *aBuffer, uint16_t aSize)
 {
-    return RandomManager::CryptoFillBuffer(aBuffer, aSize);
-}
-
-/**
- * This function returns initialized mbedtls_ctr_drbg_context.
- *
- * @returns  A pointer to initialized mbedtls_ctr_drbg_context.
- *
- */
-inline mbedtls_ctr_drbg_context *MbedTlsContextGet(void)
-{
-    return RandomManager::GetMbedTlsCtrDrbgContext();
+    return Manager::CryptoFillBuffer(aBuffer, aSize);
 }
 
 } // namespace Crypto
diff --git a/src/core/common/random_manager.cpp b/src/core/common/random_manager.cpp
deleted file mode 100644
index 4caf226..0000000
--- a/src/core/common/random_manager.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- *  Copyright (c) 2019, The OpenThread Authors.
- *  All rights reserved.
- *
- *  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, 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
- *   This file provides an implementation of OpenThread random number generation manager class.
- */
-
-#include "random_manager.hpp"
-
-#include <openthread/platform/entropy.h>
-
-#include "common/code_utils.hpp"
-#include "common/debug.hpp"
-#include "common/logging.hpp"
-#include "common/random.hpp"
-#include "crypto/mbedtls.hpp"
-
-namespace ot {
-
-uint16_t                     RandomManager::sInitCount = 0;
-RandomManager::NonCryptoPrng RandomManager::sPrng;
-
-#if !OPENTHREAD_RADIO
-RandomManager::Entropy       RandomManager::sEntropy;
-RandomManager::CryptoCtrDrbg RandomManager::sCtrDrbg;
-#endif
-
-RandomManager::RandomManager(void)
-{
-    uint32_t seed;
-
-    OT_ASSERT(sInitCount < 0xffff);
-
-    VerifyOrExit(sInitCount == 0);
-
-#if !OPENTHREAD_RADIO
-    sEntropy.Init();
-    sCtrDrbg.Init();
-
-    SuccessOrAssert(Random::Crypto::FillBuffer(reinterpret_cast<uint8_t *>(&seed), sizeof(seed)));
-#else
-    SuccessOrAssert(otPlatEntropyGet(reinterpret_cast<uint8_t *>(&seed), sizeof(seed)));
-#endif
-
-    sPrng.Init(seed);
-
-exit:
-    sInitCount++;
-}
-
-RandomManager::~RandomManager(void)
-{
-    OT_ASSERT(sInitCount > 0);
-
-    sInitCount--;
-    VerifyOrExit(sInitCount == 0);
-
-#if !OPENTHREAD_RADIO
-    sCtrDrbg.Deinit();
-    sEntropy.Deinit();
-#endif
-
-exit:
-    return;
-}
-
-uint32_t RandomManager::NonCryptoGetUint32(void)
-{
-    OT_ASSERT(sInitCount > 0);
-
-    return sPrng.GetNext();
-}
-
-//-------------------------------------------------------------------
-// NonCryptoPrng
-
-void RandomManager::NonCryptoPrng::Init(uint32_t aSeed)
-{
-    // The PRNG has a cycle of length 1 for the below two initial
-    // seeds. For all other seed values the cycle is ~2^31 long.
-
-    if ((aSeed == 0) || (aSeed == 0x7fffffff))
-    {
-        aSeed = 0x1;
-    }
-
-    mState = aSeed;
-}
-
-uint32_t RandomManager::NonCryptoPrng::GetNext(void)
-{
-    uint32_t mlcg, p, q;
-    uint64_t tmpstate;
-
-    tmpstate = static_cast<uint64_t>(33614) * static_cast<uint64_t>(mState);
-    q        = tmpstate & 0xffffffff;
-    q        = q >> 1;
-    p        = tmpstate >> 32;
-    mlcg     = p + q;
-
-    if (mlcg & 0x80000000)
-    {
-        mlcg &= 0x7fffffff;
-        mlcg++;
-    }
-
-    mState = mlcg;
-
-    return mlcg;
-}
-
-#if !OPENTHREAD_RADIO
-
-//-------------------------------------------------------------------
-// Entropy
-
-void RandomManager::Entropy::Init(void)
-{
-    mbedtls_entropy_init(&mEntropyContext);
-
-#ifndef OT_MBEDTLS_STRONG_DEFAULT_ENTROPY_PRESENT
-    mbedtls_entropy_add_source(&mEntropyContext, &RandomManager::Entropy::HandleMbedtlsEntropyPoll, nullptr,
-                               kEntropyMinThreshold, MBEDTLS_ENTROPY_SOURCE_STRONG);
-#endif // OT_MBEDTLS_STRONG_DEFAULT_ENTROPY_PRESENT
-}
-
-void RandomManager::Entropy::Deinit(void)
-{
-    mbedtls_entropy_free(&mEntropyContext);
-}
-
-#ifndef OT_MBEDTLS_STRONG_DEFAULT_ENTROPY_PRESENT
-
-int RandomManager::Entropy::HandleMbedtlsEntropyPoll(void *         aData,
-                                                     unsigned char *aOutput,
-                                                     size_t         aInLen,
-                                                     size_t *       aOutLen)
-{
-    int rval = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
-
-    SuccessOrExit(otPlatEntropyGet(reinterpret_cast<uint8_t *>(aOutput), static_cast<uint16_t>(aInLen)));
-    rval = 0;
-
-    VerifyOrExit(aOutLen != nullptr);
-    *aOutLen = aInLen;
-
-exit:
-    OT_UNUSED_VARIABLE(aData);
-    return rval;
-}
-
-#endif // OT_MBEDTLS_STRONG_DEFAULT_ENTROPY_PRESENT
-
-//-------------------------------------------------------------------
-// CryptoCtrDrbg
-
-void RandomManager::CryptoCtrDrbg::Init(void)
-{
-    int rval;
-
-    mbedtls_ctr_drbg_init(&mCtrDrbg);
-
-    rval =
-        mbedtls_ctr_drbg_seed(&mCtrDrbg, mbedtls_entropy_func, RandomManager::GetMbedTlsEntropyContext(), nullptr, 0);
-
-    if (rval != 0)
-    {
-        otLogCritMbedTls("Failed to seed the CTR DRBG");
-    }
-
-    OT_ASSERT(rval == 0);
-}
-
-void RandomManager::CryptoCtrDrbg::Deinit(void)
-{
-    mbedtls_ctr_drbg_free(&mCtrDrbg);
-}
-
-Error RandomManager::CryptoCtrDrbg::FillBuffer(uint8_t *aBuffer, uint16_t aSize)
-{
-    return ot::Crypto::MbedTls::MapError(
-        mbedtls_ctr_drbg_random(&mCtrDrbg, static_cast<unsigned char *>(aBuffer), static_cast<size_t>(aSize)));
-}
-
-#endif // #if !OPENTHREAD_RADIO
-
-} // namespace ot
diff --git a/src/core/common/random_manager.hpp b/src/core/common/random_manager.hpp
deleted file mode 100644
index 42e7767..0000000
--- a/src/core/common/random_manager.hpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- *  Copyright (c) 2019, The OpenThread Authors.
- *  All rights reserved.
- *
- *  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, 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
- *  This file includes definitions for OpenThread random number generation manager class.
- */
-
-#ifndef RANDOM_MANAGER_HPP_
-#define RANDOM_MANAGER_HPP_
-
-#include "openthread-core-config.h"
-
-#include <stdint.h>
-
-#if !OPENTHREAD_RADIO
-#include <mbedtls/ctr_drbg.h>
-#include <mbedtls/entropy.h>
-#endif
-
-#include "common/error.hpp"
-#include "common/non_copyable.hpp"
-
-#if (!defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) && \
-     (!defined(MBEDTLS_NO_PLATFORM_ENTROPY) || defined(MBEDTLS_HAVEGE_C) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT)))
-#define OT_MBEDTLS_STRONG_DEFAULT_ENTROPY_PRESENT
-#endif
-
-namespace ot {
-
-/**
- * This class manages random number generator initialization/deinitialization.
- *
- */
-class RandomManager : private NonCopyable
-{
-public:
-    /**
-     * This constructor initializes the object.
-     *
-     */
-    RandomManager(void);
-
-    /**
-     * This destructor deinitializes the object.
-     *
-     */
-    ~RandomManager(void);
-
-    /**
-     * This static method generates and returns a random value using a non-crypto Pseudo Random Number Generator.
-     *
-     * @returns    A random `uint32_t` value.
-     *
-     */
-    static uint32_t NonCryptoGetUint32(void);
-
-#if !OPENTHREAD_RADIO
-    /**
-     * This static method returns the initialized mbedtls_entropy_context.
-     *
-     * @returns  A pointer to initialized mbedtls_entropy_context.
-     */
-    static mbedtls_entropy_context *GetMbedTlsEntropyContext(void) { return sEntropy.GetContext(); }
-
-    /**
-     * This static method fills a given buffer with cryptographically secure random bytes.
-     *
-     * @param[out] aBuffer  A pointer to a buffer to fill with the random bytes.
-     * @param[in]  aSize    Size of buffer (number of bytes to fill).
-     *
-     * @retval kErrorNone    Successfully filled buffer with random values.
-     *
-     */
-    static Error CryptoFillBuffer(uint8_t *aBuffer, uint16_t aSize) { return sCtrDrbg.FillBuffer(aBuffer, aSize); }
-
-    /**
-     * This static method returns the initialized mbedtls_ctr_drbg_context.
-     *
-     * @returns  A pointer to the initialized mbedtls_ctr_drbg_context.
-     *
-     */
-    static mbedtls_ctr_drbg_context *GetMbedTlsCtrDrbgContext(void) { return sCtrDrbg.GetContext(); }
-#endif
-
-private:
-    class NonCryptoPrng // A non-crypto Pseudo Random Number Generator (PRNG)
-    {
-    public:
-        void     Init(uint32_t aSeed);
-        uint32_t GetNext(void);
-
-    private:
-        uint32_t mState;
-    };
-
-#if !OPENTHREAD_RADIO
-    class Entropy
-    {
-    public:
-        void Init(void);
-        void Deinit(void);
-
-        mbedtls_entropy_context *GetContext(void) { return &mEntropyContext; }
-
-    private:
-#ifndef OT_MBEDTLS_STRONG_DEFAULT_ENTROPY_PRESENT
-        static int HandleMbedtlsEntropyPoll(void *aData, unsigned char *aOutput, size_t aInLen, size_t *aOutLen);
-#endif // OT_MBEDTLS_STRONG_DEFAULT_ENTROPY_PRESENT
-
-        static constexpr size_t kEntropyMinThreshold = 32;
-
-        mbedtls_entropy_context mEntropyContext;
-    };
-
-    class CryptoCtrDrbg
-    {
-    public:
-        void  Init(void);
-        void  Deinit(void);
-        Error FillBuffer(uint8_t *aBuffer, uint16_t aSize);
-
-        mbedtls_ctr_drbg_context *GetContext(void) { return &mCtrDrbg; }
-
-    private:
-        mbedtls_ctr_drbg_context mCtrDrbg;
-    };
-#endif
-
-    static uint16_t      sInitCount;
-    static NonCryptoPrng sPrng;
-#if !OPENTHREAD_RADIO
-    static Entropy       sEntropy;
-    static CryptoCtrDrbg sCtrDrbg;
-#endif
-};
-
-} // namespace ot
-
-#endif // RANDOM_MANAGER_HPP_
diff --git a/src/core/common/retain_ptr.hpp b/src/core/common/retain_ptr.hpp
new file mode 100644
index 0000000..5605ced
--- /dev/null
+++ b/src/core/common/retain_ptr.hpp
@@ -0,0 +1,221 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes definitions for a retain (reference counted) smart pointer.
+ */
+
+#ifndef RETAIN_PTR_HPP_
+#define RETAIN_PTR_HPP_
+
+#include "openthread-core-config.h"
+
+#include "common/ptr_wrapper.hpp"
+
+namespace ot {
+
+/**
+ * This template class represents a retain (reference counted) smart pointer.
+ *
+ * The `Type` class MUST provide mechanism to track its current retain count. It MUST provide the following three
+ * methods:
+ *
+ *   - void      IncrementRetainCount(void);  (Increment the retain count).
+ *   - uint16_t  DecrementRetainCount(void);  (Decrement the retain count and return the value after decrement).
+ *   - void      Free(void);                  (Free the `Type` instance).
+ *
+ * The `Type` can inherit from `RetainCountable` which provides the retain counting methods.
+ *
+ * @tparam Type  The pointer type.
+ *
+ */
+template <class Type> class RetainPtr : public Ptr<Type>
+{
+    using Ptr<Type>::mPointer;
+
+public:
+    /**
+     * This is the default constructor for `RetainPtr` initializing it as null.
+     *
+     */
+    RetainPtr(void) = default;
+
+    /**
+     * This constructor initializes the `RetainPtr` with a given pointer.
+     *
+     * Upon construction the `RetainPtr` will increment the retain count on @p aPointer (if not null).
+     *
+     * @param[in] aPointer  A pointer to object to initialize with.
+     *
+     */
+    explicit RetainPtr(Type *aPointer)
+        : Ptr<Type>(aPointer)
+    {
+        IncrementRetainCount();
+    }
+
+    /**
+     * This constructor initializes the `RetainPtr` from another `RetainPtr`.
+     *
+     * @param[in] aOther   Another `RetainPtr`.
+     *
+     */
+    RetainPtr(const RetainPtr &aOther)
+        : Ptr<Type>(aOther.mPointer)
+    {
+        IncrementRetainCount();
+    }
+
+    /**
+     * This is the destructor for `RetainPtr`.
+     *
+     * Upon destruction, the `RetainPtr` will decrement the retain count on the managed object (if not null) and
+     * free the object if its retain count reaches zero.
+     *
+     */
+    ~RetainPtr(void) { DecrementRetainCount(); }
+
+    /**
+     * This method replaces the managed object by `RetainPtr` with a new one.
+     *
+     * The method correctly handles a self `Reset()` (i.e., @p aPointer being the same pointer as the one currently
+     * managed by `RetainPtr`).
+     *
+     * @param[in] aPointer   A pointer to a new object to replace with.
+     *
+     */
+    void Reset(Type *aPointer = nullptr)
+    {
+        if (aPointer != mPointer)
+        {
+            DecrementRetainCount();
+            mPointer = aPointer;
+            IncrementRetainCount();
+        }
+    }
+
+    /**
+     * This method releases the ownership of the current pointer in `RetainPtr` (if any) without changing its retain
+     * count.
+     *
+     * After this call, the `RetainPtr` will be null.
+     *
+     * @returns The pointer to the object managed by `RetainPtr` or `nullptr` if `RetainPtr` was null.
+     *
+     */
+    Type *Release(void)
+    {
+        Type *pointer = mPointer;
+        mPointer      = nullptr;
+        return pointer;
+    }
+
+    /**
+     * This method overloads the assignment operator `=`.
+     *
+     * The `RetainPtr` first frees its current managed object (if there is any and it is different from @p aOther)
+     * before taking over the ownership of the object from @p aOther. This method correctly handles a self assignment
+     * (i.e., assigning the pointer to itself).
+     *
+     * @param[in] aOther   A reference to another `RetainPtr`.
+     *
+     * @returns A reference to this `RetainPtr`.
+     *
+     */
+    RetainPtr &operator=(const RetainPtr &aOther)
+    {
+        Reset(aOther.mPointer);
+        return *this;
+    }
+
+private:
+    void IncrementRetainCount(void)
+    {
+        if (mPointer != nullptr)
+        {
+            mPointer->IncrementRetainCount();
+        }
+    }
+
+    void DecrementRetainCount(void)
+    {
+        if ((mPointer != nullptr) && (mPointer->DecrementRetainCount() == 0))
+        {
+            mPointer->Free();
+        }
+    }
+};
+
+/**
+ * This class provides mechanism to track retain count.
+ *
+ */
+class RetainCountable
+{
+    template <class Type> friend class RetainPtr;
+
+protected:
+    /**
+     * This constrictor initializes the object starting with retain count of zero.
+     *
+     */
+    RetainCountable(void)
+        : mRetainCount(0)
+    {
+    }
+
+    /**
+     * This method returns the current retain count.
+     *
+     * @returns The current retain count.
+     *
+     */
+    uint16_t GetRetainCount(void) const { return mRetainCount; }
+
+    /**
+     * This method increments the retain count.
+     *
+     */
+    void IncrementRetainCount(void) { ++mRetainCount; }
+
+    /**
+     * This method decrements the retain count.
+     *
+     * @returns The retain count value after decrementing it.
+     *
+     */
+    uint16_t DecrementRetainCount(void) { return --mRetainCount; }
+
+private:
+    uint16_t mRetainCount;
+};
+
+} // namespace ot
+
+#endif // RETAIN_PTR_HPP_
diff --git a/src/core/common/serial_number.hpp b/src/core/common/serial_number.hpp
new file mode 100644
index 0000000..39f1166
--- /dev/null
+++ b/src/core/common/serial_number.hpp
@@ -0,0 +1,100 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes definitions for serial number comparison similar to RFC-1982.
+ */
+
+#ifndef SERIAL_NUMBER_HPP_
+#define SERIAL_NUMBER_HPP_
+
+#include "openthread-core-config.h"
+
+#include <stdint.h>
+
+#include "common/numeric_limits.hpp"
+#include "common/type_traits.hpp"
+
+namespace ot {
+
+class SerialNumber
+{
+public:
+    /**
+     * This static method indicates whether or not a first serial number is strictly less than a second serial number.
+     *
+     * The comparison takes into account the wrapping of serial number values (similar to RFC-1982). It is semantically
+     * equivalent to `aFirst < aSecond`.
+     *
+     * @tparam UintType    The unsigned integer type.
+     *
+     * @param[in] aFirst   The first serial number.
+     * @param[in] aSecond  The second serial number.
+     *
+     * @retval TRUE  If @p aFirst is less than @p aSecond.
+     * @retval FALSE If @p aFirst is not less than @p aSecond.
+     *
+     */
+    template <typename UintType> static bool IsLess(UintType aFirst, UintType aSecond)
+    {
+        static_assert(TypeTraits::IsSame<UintType, uint8_t>::kValue || TypeTraits::IsSame<UintType, uint16_t>::kValue ||
+                          TypeTraits::IsSame<UintType, uint32_t>::kValue ||
+                          TypeTraits::IsSame<UintType, uint64_t>::kValue,
+                      "UintType MUST be an 8, 16, 32, or 64 bit `uint` type");
+
+        static constexpr UintType kNegativeMask = (NumericLimits<UintType>::kMax >> 1) + 1;
+
+        return ((aFirst - aSecond) & kNegativeMask) != 0;
+    }
+
+    /**
+     * This static method indicates whether or not a first serial number is strictly greater than a second serial
+     * number.
+     *
+     * The comparison takes into account the wrapping of serial number values (similar to RFC-1982). It is semantically
+     * equivalent to `aFirst > aSecond`.
+     *
+     * @tparam UintType    The unsigned integer type.
+     *
+     * @param[in] aFirst   The first serial number.
+     * @param[in] aSecond  The second serial number.
+     *
+     * @retval TRUE  If @p aFirst is greater than @p aSecond.
+     * @retval FALSE If @p aFirst is not greater than @p aSecond.
+     *
+     */
+    template <typename UintType> static bool IsGreater(UintType aFirst, UintType aSecond)
+    {
+        return IsLess(aSecond, aFirst);
+    }
+};
+
+} // namespace ot
+
+#endif // SERIAL_NUMBER_HPP_
diff --git a/src/core/common/settings.cpp b/src/core/common/settings.cpp
index d120f37..67f76e2 100644
--- a/src/core/common/settings.cpp
+++ b/src/core/common/settings.cpp
@@ -33,81 +33,81 @@
 
 #include "settings.hpp"
 
+#include "common/array.hpp"
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
 #include "meshcop/dataset.hpp"
 #include "thread/mle.hpp"
 
 namespace ot {
 
+RegisterLogModule("Settings");
+
 //---------------------------------------------------------------------------------------------------------------------
 // SettingsBase
 
 // LCOV_EXCL_START
 
-#if OPENTHREAD_CONFIG_LOG_UTIL && (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
 void SettingsBase::NetworkInfo::Log(Action aAction) const
 {
-    otLogInfoCore(
-        "[settings] %s NetworkInfo {rloc:0x%04x, extaddr:%s, role:%s, mode:0x%02x, version:%hu, keyseq:0x%x, ...",
-        ActionToString(aAction), GetRloc16(), GetExtAddress().ToString().AsCString(),
-        Mle::Mle::RoleToString(static_cast<Mle::DeviceRole>(GetRole())), GetDeviceMode(), GetVersion(),
-        GetKeySequence());
+    LogInfo("%s NetworkInfo {rloc:0x%04x, extaddr:%s, role:%s, mode:0x%02x, version:%hu, keyseq:0x%x, ...",
+            ActionToString(aAction), GetRloc16(), GetExtAddress().ToString().AsCString(),
+            Mle::Mle::RoleToString(static_cast<Mle::DeviceRole>(GetRole())), GetDeviceMode(), GetVersion(),
+            GetKeySequence());
 
-    otLogInfoCore("[settings] ... pid:0x%x, mlecntr:0x%x, maccntr:0x%x, mliid:%s}", GetPreviousPartitionId(),
-                  GetMleFrameCounter(), GetMacFrameCounter(), GetMeshLocalIid().ToString().AsCString());
+    LogInfo("... pid:0x%x, mlecntr:0x%x, maccntr:0x%x, mliid:%s}", GetPreviousPartitionId(), GetMleFrameCounter(),
+            GetMacFrameCounter(), GetMeshLocalIid().ToString().AsCString());
 }
 
 void SettingsBase::ParentInfo::Log(Action aAction) const
 {
-    otLogInfoCore("[settings] %s ParentInfo {extaddr:%s, version:%hu}", ActionToString(aAction),
-                  GetExtAddress().ToString().AsCString(), GetVersion());
+    LogInfo("%s ParentInfo {extaddr:%s, version:%hu}", ActionToString(aAction), GetExtAddress().ToString().AsCString(),
+            GetVersion());
 }
 
 #if OPENTHREAD_FTD
 void SettingsBase::ChildInfo::Log(Action aAction) const
 {
-    otLogInfoCore("[settings] %s ChildInfo {rloc:0x%04x, extaddr:%s, timeout:%u, mode:0x%02x, version:%hu}",
-                  ActionToString(aAction), GetRloc16(), GetExtAddress().ToString().AsCString(), GetTimeout(), GetMode(),
-                  GetVersion());
+    LogInfo("%s ChildInfo {rloc:0x%04x, extaddr:%s, timeout:%u, mode:0x%02x, version:%hu}", ActionToString(aAction),
+            GetRloc16(), GetExtAddress().ToString().AsCString(), GetTimeout(), GetMode(), GetVersion());
 }
 #endif
 
 #if OPENTHREAD_CONFIG_DUA_ENABLE
 void SettingsBase::DadInfo::Log(Action aAction) const
 {
-    otLogInfoCore("[settings] %s DadInfo {DadCounter:%2d}", ActionToString(aAction), GetDadCounter());
+    LogInfo("%s DadInfo {DadCounter:%2d}", ActionToString(aAction), GetDadCounter());
 }
 #endif
 
 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
 void SettingsBase::LogPrefix(Action aAction, Key aKey, const Ip6::Prefix &aPrefix)
 {
-    otLogInfoCore("[settings] %s %s %s", ActionToString(aAction), KeyToString(aKey), aPrefix.ToString().AsCString());
+    LogInfo("%s %s %s", ActionToString(aAction), KeyToString(aKey), aPrefix.ToString().AsCString());
 }
 #endif
 
 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE && OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
 void SettingsBase::SrpClientInfo::Log(Action aAction) const
 {
-    otLogInfoCore("[settings] %s SrpClientInfo {Server:[%s]:%u}", ActionToString(aAction),
-                  GetServerAddress().ToString().AsCString(), GetServerPort());
+    LogInfo("%s SrpClientInfo {Server:[%s]:%u}", ActionToString(aAction), GetServerAddress().ToString().AsCString(),
+            GetServerPort());
 }
 #endif
 
 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE && OPENTHREAD_CONFIG_SRP_SERVER_PORT_SWITCH_ENABLE
 void SettingsBase::SrpServerInfo::Log(Action aAction) const
 {
-    otLogInfoCore("[settings] %s SrpServerInfo {port:%u}", ActionToString(aAction), GetPort());
+    LogInfo("%s SrpServerInfo {port:%u}", ActionToString(aAction), GetPort());
 }
 #endif
 
-#endif // OPENTHREAD_CONFIG_LOG_UTIL && (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO)
+#endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
-#if OPENTHREAD_CONFIG_LOG_UTIL && (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 const char *SettingsBase::ActionToString(Action aAction)
 {
     static const char *const kActionStrings[] = {
@@ -134,9 +134,9 @@
 
     return kActionStrings[aAction];
 }
-#endif // OPENTHREAD_CONFIG_LOG_UTIL && (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO)
+#endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
-#if OPENTHREAD_CONFIG_LOG_UTIL && (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
 const char *SettingsBase::KeyToString(Key aKey)
 {
     static const char *const kKeyStrings[] = {
@@ -146,14 +146,16 @@
         "NetworkInfo",       // (3)  kKeyNetworkInfo
         "ParentInfo",        // (4)  kKeyParentInfo
         "ChildInfo",         // (5)  kKeyChildInfo
-        "",                  // (6)  kKeyReserved
+        "",                  // (6)  Removed (previously auto-start).
         "SlaacIidSecretKey", // (7)  kKeySlaacIidSecretKey
         "DadInfo",           // (8)  kKeyDadInfo
-        "OmrPrefix",         // (9)  kKeyOmrPrefix
-        "OnLinkPrefix",      // (10) kKeyOnLinkPrefix
+        "",                  // (9)  Removed (previously OMR prefix).
+        "",                  // (10) Removed (previously on-link prefix).
         "SrpEcdsaKey",       // (11) kKeySrpEcdsaKey
         "SrpClientInfo",     // (12) kKeySrpClientInfo
         "SrpServerInfo",     // (13) kKeySrpServerInfo
+        "",                  // (14) Removed (previously NAT64 prefix)
+        "BrUlaPrefix",       // (15) kKeyBrUlaPrefix
     };
 
     static_assert(1 == kKeyActiveDataset, "kKeyActiveDataset value is incorrect");
@@ -161,30 +163,28 @@
     static_assert(3 == kKeyNetworkInfo, "kKeyNetworkInfo value is incorrect");
     static_assert(4 == kKeyParentInfo, "kKeyParentInfo value is incorrect");
     static_assert(5 == kKeyChildInfo, "kKeyChildInfo value is incorrect");
-    static_assert(6 == kKeyReserved, "kKeyReserved value is incorrect");
     static_assert(7 == kKeySlaacIidSecretKey, "kKeySlaacIidSecretKey value is incorrect");
     static_assert(8 == kKeyDadInfo, "kKeyDadInfo value is incorrect");
-    static_assert(9 == kKeyOmrPrefix, "kKeyOmrPrefix value is incorrect");
-    static_assert(10 == kKeyOnLinkPrefix, "kKeyOnLinkPrefix value is incorrect");
     static_assert(11 == kKeySrpEcdsaKey, "kKeySrpEcdsaKey value is incorrect");
     static_assert(12 == kKeySrpClientInfo, "kKeySrpClientInfo value is incorrect");
     static_assert(13 == kKeySrpServerInfo, "kKeySrpServerInfo value is incorrect");
+    static_assert(15 == kKeyBrUlaPrefix, "kKeyBrUlaPrefix value is incorrect");
 
-    static_assert(kLastKey == kKeySrpServerInfo, "kLastKey is not valid");
+    static_assert(kLastKey == kKeyBrUlaPrefix, "kLastKey is not valid");
 
     OT_ASSERT(aKey <= kLastKey);
 
     return kKeyStrings[aKey];
 }
-#endif // OPENTHREAD_CONFIG_LOG_UTIL && (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN)
+#endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
 
 // LCOV_EXCL_STOP
 
 //---------------------------------------------------------------------------------------------------------------------
 // Settings
 
-// This array contains critical keys that should be stored in the secure area.
-const uint16_t Settings::kCriticalKeys[] = {
+// This array contains sensitive keys that should be stored in the secure area.
+const uint16_t Settings::kSensitiveKeys[] = {
     SettingsBase::kKeyActiveDataset,
     SettingsBase::kKeyPendingDataset,
     SettingsBase::kKeySrpEcdsaKey,
@@ -192,8 +192,7 @@
 
 void Settings::Init(void)
 {
-    Get<SettingsDriver>().Init();
-    Get<SettingsDriver>().SetCriticalKeys(kCriticalKeys, OT_ARRAY_LENGTH(kCriticalKeys));
+    Get<SettingsDriver>().Init(kSensitiveKeys, GetArrayLength(kSensitiveKeys));
 }
 
 void Settings::Deinit(void)
@@ -204,12 +203,17 @@
 void Settings::Wipe(void)
 {
     Get<SettingsDriver>().Wipe();
-    otLogInfoCore("[settings] Wiped all info");
+    LogInfo("Wiped all info");
 }
 
-Error Settings::SaveOperationalDataset(bool aIsActive, const MeshCoP::Dataset &aDataset)
+Settings::Key Settings::KeyForDatasetType(MeshCoP::Dataset::Type aType)
 {
-    Key   key   = (aIsActive ? kKeyActiveDataset : kKeyPendingDataset);
+    return (aType == MeshCoP::Dataset::kActive) ? kKeyActiveDataset : kKeyPendingDataset;
+}
+
+Error Settings::SaveOperationalDataset(MeshCoP::Dataset::Type aType, const MeshCoP::Dataset &aDataset)
+{
+    Key   key   = KeyForDatasetType(aType);
     Error error = Get<SettingsDriver>().Set(key, aDataset.GetBytes(), aDataset.GetSize());
 
     Log(kActionSave, error, key);
@@ -217,13 +221,12 @@
     return error;
 }
 
-Error Settings::ReadOperationalDataset(bool aIsActive, MeshCoP::Dataset &aDataset) const
+Error Settings::ReadOperationalDataset(MeshCoP::Dataset::Type aType, MeshCoP::Dataset &aDataset) const
 {
     Error    error  = kErrorNone;
     uint16_t length = MeshCoP::Dataset::kMaxSize;
 
-    SuccessOrExit(error = Get<SettingsDriver>().Get(aIsActive ? kKeyActiveDataset : kKeyPendingDataset,
-                                                    aDataset.GetBytes(), &length));
+    SuccessOrExit(error = Get<SettingsDriver>().Get(KeyForDatasetType(aType), aDataset.GetBytes(), &length));
     VerifyOrExit(length <= MeshCoP::Dataset::kMaxSize, error = kErrorNotFound);
 
     aDataset.SetSize(length);
@@ -232,9 +235,9 @@
     return error;
 }
 
-Error Settings::DeleteOperationalDataset(bool aIsActive)
+Error Settings::DeleteOperationalDataset(MeshCoP::Dataset::Type aType)
 {
-    Key   key   = (aIsActive ? kKeyActiveDataset : kKeyPendingDataset);
+    Key   key   = KeyForDatasetType(aType);
     Error error = Get<SettingsDriver>().Delete(key);
 
     Log(kActionDelete, error, key);
@@ -353,13 +356,11 @@
     OT_UNUSED_VARIABLE(aError);
     OT_UNUSED_VARIABLE(aValue);
 
-#if OPENTHREAD_CONFIG_LOG_UTIL
-
     if (aError != kErrorNone)
     {
         // Log error if log level is at "warn" or higher.
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
         const char *actionText = "";
 
         switch (aAction)
@@ -393,9 +394,9 @@
             ExitNow();
         }
 
-        otLogWarnCore("[settings] Error %s %s %s", ErrorToString(aError), actionText, KeyToString(aKey));
+        LogWarn("Error %s %s %s", ErrorToString(aError), actionText, KeyToString(aKey));
 
-#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN)
+#endif // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
 
         ExitNow();
     }
@@ -403,7 +404,7 @@
     // We reach here when `aError` is `kErrorNone`.
     // Log success if log level is at "info" or higher.
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
     if (aValue != nullptr)
     {
         switch (aKey)
@@ -429,8 +430,7 @@
 #endif
 
 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
-        case kKeyOmrPrefix:
-        case kKeyOnLinkPrefix:
+        case kKeyBrUlaPrefix:
             LogPrefix(aAction, aKey, *reinterpret_cast<const Ip6::Prefix *>(aValue));
             break;
 #endif
@@ -459,13 +459,11 @@
 
     if (aValue == nullptr)
     {
-        otLogInfoCore("[settings] %s %s", ActionToString(aAction), KeyToString(aKey));
+        LogInfo("%s %s", ActionToString(aAction), KeyToString(aKey));
     }
-#endif // (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO)
+#endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
 exit:
-
-#endif // OPENTHREAD_CONFIG_LOG_UTIL
     return;
 }
 
diff --git a/src/core/common/settings.hpp b/src/core/common/settings.hpp
index 19f90f4..6db4a02 100644
--- a/src/core/common/settings.hpp
+++ b/src/core/common/settings.hpp
@@ -42,24 +42,18 @@
 #include "common/encoding.hpp"
 #include "common/equatable.hpp"
 #include "common/locator.hpp"
+#include "common/log.hpp"
 #include "common/non_copyable.hpp"
 #include "common/settings_driver.hpp"
+#include "crypto/ecdsa.hpp"
 #include "mac/mac_types.hpp"
+#include "meshcop/dataset.hpp"
 #include "net/ip6_address.hpp"
 #include "utils/flash.hpp"
-#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
 #include "utils/slaac_address.hpp"
-#endif
-#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
-#include "crypto/ecdsa.hpp"
-#endif
 
 namespace ot {
 
-namespace MeshCoP {
-class Dataset;
-}
-
 class Settings;
 
 /**
@@ -118,17 +112,17 @@
         kKeyNetworkInfo       = OT_SETTINGS_KEY_NETWORK_INFO,
         kKeyParentInfo        = OT_SETTINGS_KEY_PARENT_INFO,
         kKeyChildInfo         = OT_SETTINGS_KEY_CHILD_INFO,
-        kKeyReserved          = OT_SETTINGS_KEY_RESERVED,
         kKeySlaacIidSecretKey = OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY,
         kKeyDadInfo           = OT_SETTINGS_KEY_DAD_INFO,
-        kKeyOmrPrefix         = OT_SETTINGS_KEY_OMR_PREFIX,
-        kKeyOnLinkPrefix      = OT_SETTINGS_KEY_ON_LINK_PREFIX,
         kKeySrpEcdsaKey       = OT_SETTINGS_KEY_SRP_ECDSA_KEY,
         kKeySrpClientInfo     = OT_SETTINGS_KEY_SRP_CLIENT_INFO,
         kKeySrpServerInfo     = OT_SETTINGS_KEY_SRP_SERVER_INFO,
+        kKeyBrUlaPrefix       = OT_SETTINGS_KEY_BR_ULA_PREFIX,
     };
 
-    static constexpr Key kLastKey = kKeySrpServerInfo; ///< The last (numerically) enumerator value in `Key`.
+    static constexpr Key kLastKey = kKeyBrUlaPrefix; ///< The last (numerically) enumerator value in `Key`.
+    static_assert(static_cast<uint16_t>(kLastKey) < static_cast<uint16_t>(OT_SETTINGS_KEY_VENDOR_RESERVED_MIN),
+                  "Core settings keys overlap with vendor reserved keys");
 
     /**
      * This structure represents the device's own network information for settings storage.
@@ -479,7 +473,7 @@
         /**
          * This method sets the Thread device mode.
          *
-         * @param[in] aRloc16  The Thread device mode.
+         * @param[in] aMode  The Thread device mode.
          *
          */
         void SetMode(uint8_t aMode) { mMode = aMode; }
@@ -572,35 +566,20 @@
 
 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
     /**
-     * This class defines constants and types for OMR prefix settings.
+     * This class defines constants and types for BR ULA prefix settings.
      *
      */
-    class OmrPrefix
+    class BrUlaPrefix
     {
     public:
-        static constexpr Key kKey = kKeyOmrPrefix; ///< The associated key.
+        static constexpr Key kKey = kKeyBrUlaPrefix; ///< The associated key.
 
         typedef Ip6::Prefix ValueType; ///< The associated value type.
 
     private:
-        OmrPrefix(void) = default;
+        BrUlaPrefix(void) = default;
     };
-
-    /**
-     * This class defines constants and types for on-link prefix settings.
-     *
-     */
-    class OnLinkPrefix
-    {
-    public:
-        static constexpr Key kKey = kKeyOnLinkPrefix; ///< The associated key.
-
-        typedef Ip6::Prefix ValueType; ///< The associated value type.
-
-    private:
-        OnLinkPrefix(void) = default;
-    };
-#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+#endif
 
 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
     /**
@@ -730,10 +709,10 @@
     static void LogPrefix(Action aAction, Key aKey, const Ip6::Prefix &aPrefix);
 #endif
 
-#if OPENTHREAD_CONFIG_LOG_UTIL && (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
     static const char *KeyToString(Key aKey);
 #endif
-#if OPENTHREAD_CONFIG_LOG_UTIL && (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
     static const char *ActionToString(Action aAction);
 #endif
 };
@@ -783,38 +762,38 @@
     /**
      * This method saves the Operational Dataset (active or pending).
      *
-     * @param[in]   aIsActive   Indicates whether Dataset is active or pending.
+     * @param[in]   aType       The Dataset type (active or pending) to save.
      * @param[in]   aDataset    A reference to a `Dataset` object to be saved.
      *
      * @retval kErrorNone             Successfully saved the Dataset.
      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
      *
      */
-    Error SaveOperationalDataset(bool aIsActive, const MeshCoP::Dataset &aDataset);
+    Error SaveOperationalDataset(MeshCoP::Dataset::Type aType, const MeshCoP::Dataset &aDataset);
 
     /**
      * This method reads the Operational Dataset (active or pending).
      *
-     * @param[in]   aIsActive             Indicates whether Dataset is active or pending.
-     * @param[out]  aDataset              A reference to a `Dataset` object to output the read content.
+     * @param[in]   aType            The Dataset type (active or pending) to read.
+     * @param[out]  aDataset         A reference to a `Dataset` object to output the read content.
      *
      * @retval kErrorNone             Successfully read the Dataset.
      * @retval kErrorNotFound         No corresponding value in the setting store.
      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
      *
      */
-    Error ReadOperationalDataset(bool aIsActive, MeshCoP::Dataset &aDataset) const;
+    Error ReadOperationalDataset(MeshCoP::Dataset::Type aType, MeshCoP::Dataset &aDataset) const;
 
     /**
      * This method deletes the Operational Dataset (active/pending) from settings.
      *
-     * @param[in]   aIsActive            Indicates whether Dataset is active or pending.
+     * @param[in]   aType            The Dataset type (active or pending) to delete.
      *
      * @retval kErrorNone            Successfully deleted the Dataset.
      * @retval kErrorNotImplemented  The platform does not implement settings functionality.
      *
      */
-    Error DeleteOperationalDataset(bool aIsActive);
+    Error DeleteOperationalDataset(MeshCoP::Dataset::Type aType);
 
     /**
      * This template method reads a specified settings entry.
@@ -852,7 +831,7 @@
      *  - It must provide a nested type `EntryType::ValueType` to specify the associated entry value type.
      *
      * This version of `Read<EntryType>` is intended for use with entries that have a simple entry value type (which can
-     * be represented by an existing type), e.g., `OmrPrefx` (using `Ip6::Prefix` as the value type).
+     * be represented by an existing type), e.g., `OmrPrefix` (using `Ip6::Prefix` as the value type).
      *
      * @tparam EntryType              The settings entry type.
      *
@@ -902,11 +881,11 @@
      *  - It must provide a nested type `EntryType::ValueType` to specify the associated entry value type.
      *
      * This version of `Save<EntryType>` is intended for use with entries that have a simple entry value type (which can
-     * be represented by an existing type), e.g., `OmrPrefx` (using `Ip6::Prefix` as the value type).
+     * be represented by an existing type), e.g., `OmrPrefix` (using `Ip6::Prefix` as the value type).
      *
      * @tparam EntryType              The settings entry type.
      *
-     * @param[in] aEntry              The entry value to be saved.
+     * @param[in] aValue              The entry value to be saved.
      *
      * @retval kErrorNone             Successfully saved Network Info in settings.
      * @retval kErrorNotImplemented   The platform does not implement settings functionality.
@@ -1098,13 +1077,15 @@
     };
 #endif
 
+    static Key KeyForDatasetType(MeshCoP::Dataset::Type aType);
+
     Error ReadEntry(Key aKey, void *aValue, uint16_t aMaxLength) const;
     Error SaveEntry(Key aKey, const void *aValue, void *aPrev, uint16_t aLength);
     Error DeleteEntry(Key aKey);
 
     static void Log(Action aAction, Error aError, Key aKey, const void *aValue = nullptr);
 
-    static const uint16_t kCriticalKeys[];
+    static const uint16_t kSensitiveKeys[];
 };
 
 } // namespace ot
diff --git a/src/core/common/settings_driver.hpp b/src/core/common/settings_driver.hpp
index c4a8d54..f7851a2 100644
--- a/src/core/common/settings_driver.hpp
+++ b/src/core/common/settings_driver.hpp
@@ -66,13 +66,19 @@
     /**
      * This method initializes the settings storage driver.
      *
+     * @param[in]  aSensitiveKeys        A pointer to an array containing the list of sensitive keys.
+     * @param[in]  aSensitiveKeysLength  The number of entries in the @p aSensitiveKeys array.
+     *
      */
-    void Init(void)
+    void Init(const uint16_t *aSensitiveKeys, uint16_t aSensitiveKeysLength)
     {
 #if OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE
+        OT_UNUSED_VARIABLE(aSensitiveKeys);
+        OT_UNUSED_VARIABLE(aSensitiveKeysLength);
+
         mFlash.Init();
 #else
-        otPlatSettingsInit(GetInstancePtr());
+        otPlatSettingsInit(GetInstancePtr(), aSensitiveKeys, aSensitiveKeysLength);
 #endif
     }
 
@@ -88,28 +94,11 @@
     }
 
     /**
-     * This method sets the critical keys that should be stored in a secure area.
-     *
-     * @param[in]  aKeys        A pointer to an array containing the list of critical keys.
-     * @param[in]  aKeysLength  The number of entries in the @p aKeys array.
-     *
-     */
-    void SetCriticalKeys(const uint16_t *aKeys, uint16_t aKeysLength)
-    {
-#if OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE
-        OT_UNUSED_VARIABLE(aKeys);
-        OT_UNUSED_VARIABLE(aKeysLength);
-#else
-        otPlatSettingsSetCriticalKeys(GetInstancePtr(), aKeys, aKeysLength);
-#endif
-    }
-
-    /**
      * This method adds a value to @p aKey.
      *
      * @param[in]  aKey          The key associated with the value.
      * @param[in]  aValue        A pointer to where the new value of the setting should be read from.
-     *                           MUST NOT be nullptr if @p aValueLength is non-zero.
+     *                           MUST NOT be `nullptr` if @p aValueLength is non-zero.
      * @param[in]  aValueLength  The length of the data pointed to by @p aValue. May be zero.
      *
      * @retval kErrorNone     The value was added.
@@ -155,15 +144,15 @@
     /**
      * This method fetches the value identified by @p aKey at a given @p aIndex.
      *
-     * @param[in]     aKey          The key associated with the requested value.
-     * @param[in]     aIndex        The index of the specific item to get.
-     * @param[out]    aValue        A pointer to where the value of the setting should be written.
-     *                              May be nullptr if just testing for the presence or length of a key.
-     * @param[inout]  aValueLength  A pointer to the length of the value.
-     *                              When called, this should point to an integer containing the maximum bytes that
-     *                              can be written to @p aValue.
-     *                              At return, the actual length of the setting is written.
-     *                              May be nullptr if performing a presence check.
+     * @param[in]      aKey          The key associated with the requested value.
+     * @param[in]      aIndex        The index of the specific item to get.
+     * @param[out]     aValue        A pointer to where the value of the setting should be written.
+     *                               May be `nullptr` if just testing for the presence or length of a key.
+     * @param[in,out]  aValueLength  A pointer to the length of the value.
+     *                               When called, this should point to an integer containing the maximum bytes that
+     *                               can be written to @p aValue.
+     *                               At return, the actual length of the setting is written.
+     *                               May be `nullptr` if performing a presence check.
      *
      * @retval kErrorNone        The value was fetched successfully.
      * @retval kErrorNotFound    The key was not found.
@@ -185,14 +174,14 @@
     /**
      * This method fetches the value identified by @p aKey.
      *
-     * @param[in]     aKey          The key associated with the requested value.
-     * @param[out]    aValue        A pointer to where the value of the setting should be written.
-     *                              May be nullptr if just testing for the presence or length of a key.
-     * @param[inout]  aValueLength  A pointer to the length of the value.
-     *                              When called, this should point to an integer containing the maximum bytes that
-     *                              can be written to @p aValue.
-     *                              At return, the actual length of the setting is written.
-     *                              May be nullptr if performing a presence check.
+     * @param[in]      aKey          The key associated with the requested value.
+     * @param[out]     aValue        A pointer to where the value of the setting should be written.
+     *                               May be `nullptr` if just testing for the presence or length of a key.
+     * @param[in,out]  aValueLength  A pointer to the length of the value.
+     *                               When called, this should point to an integer containing the maximum bytes that
+     *                               can be written to @p aValue.
+     *                               At return, the actual length of the setting is written.
+     *                               May be `nullptr` if performing a presence check.
      *
      * @retval kErrorNone        The value was fetched successfully.
      * @retval kErrorNotFound    The key was not found.
@@ -208,7 +197,7 @@
      *
      * @param[in]  aKey          The key associated with the value.
      * @param[in]  aValue        A pointer to where the new value of the setting should be read from.
-     *                           MUST NOT be nullptr if @p aValueLength is non-zero.
+     *                           MUST NOT be `nullptr` if @p aValueLength is non-zero.
      * @param[in]  aValueLength  The length of the data pointed to by @p aValue. May be zero.
      *
      * @retval kErrorNone     The value was changed.
diff --git a/src/core/common/string.cpp b/src/core/common/string.cpp
index 612054f..4940076 100644
--- a/src/core/common/string.cpp
+++ b/src/core/common/string.cpp
@@ -28,7 +28,7 @@
 
 /**
  * @file
- *  This file implements OpenThread String class.
+ *  This file implements OpenThread String class and functions.
  */
 
 #include "string.hpp"
@@ -38,11 +38,60 @@
 
 namespace ot {
 
+namespace {
+
+// The definitions below are included in an unnamed namespace
+// to limit their scope to this translation unit (this file).
+
+enum MatchType : uint8_t
+{
+    kNoMatch,
+    kPrefixMatch,
+    kFullMatch,
+};
+
+MatchType Match(const char *aString, const char *aPrefixString, StringMatchMode aMode)
+{
+    // This is file private function that is used by other functions.
+    // It matches @p aString with @p aPrefixString using match @ aMode.
+    //
+    // If @p aString and @p aPrefixString match and have the
+    // same length `kFullMatch` is returned. If @p aString starts
+    // with @p aPrefixString but contains more characters, then
+    // `kPrefixMatch` is returned. Otherwise `kNoMatch` is returned.
+
+    MatchType match = kNoMatch;
+
+    switch (aMode)
+    {
+    case kStringExactMatch:
+        while (*aPrefixString != kNullChar)
+        {
+            VerifyOrExit(*aString++ == *aPrefixString++);
+        }
+        break;
+
+    case kStringCaseInsensitiveMatch:
+        while (*aPrefixString != kNullChar)
+        {
+            VerifyOrExit(ToLowercase(*aString++) == ToLowercase(*aPrefixString++));
+        }
+        break;
+    }
+
+    match = (*aString == kNullChar) ? kFullMatch : kPrefixMatch;
+
+exit:
+    return match;
+}
+
+} // namespace
+
 uint16_t StringLength(const char *aString, uint16_t aMaxLength)
 {
     uint16_t ret;
 
-    for (ret = 0; (ret < aMaxLength) && (aString[ret] != 0); ret++)
+    for (ret = 0; (ret < aMaxLength) && (aString[ret] != kNullChar); ret++)
     {
         // Empty loop.
     }
@@ -54,7 +103,7 @@
 {
     const char *ret = nullptr;
 
-    for (; *aString != '\0'; aString++)
+    for (; *aString != kNullChar; aString++)
     {
         if (*aString == aChar)
         {
@@ -66,7 +115,7 @@
     return ret;
 }
 
-const char *StringFind(const char *aString, const char *aSubString)
+const char *StringFind(const char *aString, const char *aSubString, StringMatchMode aMode)
 {
     const char *ret    = nullptr;
     size_t      len    = strlen(aString);
@@ -76,7 +125,7 @@
 
     for (size_t index = 0; index <= static_cast<size_t>(len - subLen); index++)
     {
-        if (memcmp(&aString[index], aSubString, subLen) == 0)
+        if (Match(&aString[index], aSubString, aMode) != kNoMatch)
         {
             ExitNow(ret = &aString[index]);
         }
@@ -86,19 +135,72 @@
     return ret;
 }
 
+bool StringStartsWith(const char *aString, const char *aPrefixString, StringMatchMode aMode)
+{
+    return Match(aString, aPrefixString, aMode) != kNoMatch;
+}
+
 bool StringEndsWith(const char *aString, char aChar)
 {
     size_t len = strlen(aString);
 
-    return len > 0 && aString[len - 1] == aChar;
+    return (len > 0) && (aString[len - 1] == aChar);
 }
 
-bool StringEndsWith(const char *aString, const char *aSubString)
+bool StringEndsWith(const char *aString, const char *aSubString, StringMatchMode aMode)
 {
     size_t len    = strlen(aString);
     size_t subLen = strlen(aSubString);
 
-    return (subLen > 0) && (len >= subLen) && (memcmp(aSubString, &aString[len - subLen], subLen) == 0);
+    return (subLen > 0) && (len >= subLen) && (Match(&aString[len - subLen], aSubString, aMode) != kNoMatch);
+}
+
+bool StringMatch(const char *aFirstString, const char *aSecondString, StringMatchMode aMode)
+{
+    return Match(aFirstString, aSecondString, aMode) == kFullMatch;
+}
+
+void StringConvertToLowercase(char *aString)
+{
+    for (; *aString != kNullChar; aString++)
+    {
+        *aString = ToLowercase(*aString);
+    }
+}
+
+void StringConvertToUppercase(char *aString)
+{
+    for (; *aString != kNullChar; aString++)
+    {
+        *aString = ToUppercase(*aString);
+    }
+}
+
+char ToLowercase(char aChar)
+{
+    if ((aChar >= 'A') && (aChar <= 'Z'))
+    {
+        aChar += 'a' - 'A';
+    }
+
+    return aChar;
+}
+
+char ToUppercase(char aChar)
+{
+    if ((aChar >= 'a') && (aChar <= 'z'))
+    {
+        aChar -= 'a' - 'A';
+    }
+
+    return aChar;
+}
+
+const char *ToYesNo(bool aBool)
+{
+    static const char *const kYesNoStrings[] = {"no", "yes"};
+
+    return kYesNoStrings[aBool];
 }
 
 StringWriter::StringWriter(char *aBuffer, uint16_t aSize)
@@ -106,12 +208,12 @@
     , mLength(0)
     , mSize(aSize)
 {
-    mBuffer[0] = '\0';
+    mBuffer[0] = kNullChar;
 }
 
 StringWriter &StringWriter::Clear(void)
 {
-    mBuffer[0] = '\0';
+    mBuffer[0] = kNullChar;
     mLength    = 0;
     return *this;
 }
@@ -137,7 +239,7 @@
 
     if (IsTruncated())
     {
-        mBuffer[mSize - 1] = '\0';
+        mBuffer[mSize - 1] = kNullChar;
     }
 
     return *this;
diff --git a/src/core/common/string.hpp b/src/core/common/string.hpp
index 3070793..a2ab1aa 100644
--- a/src/core/common/string.hpp
+++ b/src/core/common/string.hpp
@@ -40,6 +40,7 @@
 #include <stdint.h>
 #include <stdio.h>
 
+#include "common/binary_search.hpp"
 #include "common/code_utils.hpp"
 #include "common/error.hpp"
 
@@ -56,13 +57,25 @@
  */
 
 /**
- * This function returns the number of characters that precede the terminating nullptr character.
+ * This enumeration represents comparison mode when matching strings.
+ *
+ */
+enum StringMatchMode : uint8_t
+{
+    kStringExactMatch,           ///< Exact match of characters.
+    kStringCaseInsensitiveMatch, ///< Case insensitive match (uppercase and lowercase characters are treated as equal).
+};
+
+static constexpr char kNullChar = '\0'; ///< null character.
+
+/**
+ * This function returns the number of characters that precede the terminating null character.
  *
  * @param[in] aString      A pointer to the string.
  * @param[in] aMaxLength   The maximum length in bytes.
  *
- * @returns The number of characters that precede the terminating nullptr character or @p aMaxLength, whichever is
- * smaller.
+ * @returns The number of characters that precede the terminating null character or @p aMaxLength, whichever is
+ *          smaller.
  *
  */
 uint16_t StringLength(const char *aString, uint16_t aMaxLength);
@@ -73,7 +86,7 @@
  * @param[in] aString     A pointer to the string.
  * @param[in] aChar       A char to search for in the string.
  *
- * @returns The pointer to first occurrence of the @p aChar in @p aString, or nullptr if cannot be found.
+ * @returns The pointer to first occurrence of the @p aChar in @p aString, or `nullptr` if cannot be found.
  *
  */
 const char *StringFind(const char *aString, char aChar);
@@ -83,11 +96,26 @@
  *
  * @param[in] aString     A pointer to the string.
  * @param[in] aSubString  A sub-string to search for.
+ * @param[in] aMode       The string comparison mode, exact match or case insensitive match.
  *
- * @returns The pointer to first occurrence of the @p aSubString in @p aString, or nullptr if cannot be found.
+ * @returns The pointer to first match of the @p aSubString in @p aString (using comparison @p aMode), or `nullptr` if
+ *          cannot be found.
  *
  */
-const char *StringFind(const char *aString, const char *aSubString);
+const char *StringFind(const char *aString, const char *aSubString, StringMatchMode aMode = kStringExactMatch);
+
+/**
+ * This function checks whether a null-terminated string starts with a given prefix string.
+ *
+ * @param[in] aString         A pointer to the string.
+ * @param[in] aPrefixString   A prefix string.
+ * @param[in] aMode           The string comparison mode, exact match or case insensitive match.
+ *
+ * @retval TRUE   If @p aString starts with @p aPrefixString.
+ * @retval FALSE  If @p aString does not start with @p aPrefixString.
+ *
+ */
+bool StringStartsWith(const char *aString, const char *aPrefixString, StringMatchMode aMode = kStringExactMatch);
 
 /**
  * This function checks whether a null-terminated string ends with a given character.
@@ -105,13 +133,122 @@
  * This function checks whether a null-terminated string ends with a given sub-string.
  *
  * @param[in] aString      A pointer to the string.
- * @param[in] aSubString   A sun-string to check against.
+ * @param[in] aSubString   A sub-string to check against.
+ * @param[in] aMode        The string comparison mode, exact match or case insensitive match.
  *
  * @retval TRUE   If @p aString ends with sub-string @p aSubString.
  * @retval FALSE  If @p aString does not end with sub-string @p aSubString.
  *
  */
-bool StringEndsWith(const char *aString, const char *aSubString);
+bool StringEndsWith(const char *aString, const char *aSubString, StringMatchMode aMode = kStringExactMatch);
+
+/**
+ * This method checks whether or not two null-terminated strings match.
+ *
+ * @param[in] aFirstString   A pointer to the first string.
+ * @param[in] aSecondString  A pointer to the second string.
+ * @param[in] aMode          The string comparison mode, exact match or case insensitive match.
+ *
+ * @retval TRUE   If @p aFirstString matches @p aSecondString using match mode @p aMode.
+ * @retval FALSE  If @p aFirstString does not match @p aSecondString using match mode @p aMode.
+ *
+ */
+bool StringMatch(const char *aFirstString, const char *aSecondString, StringMatchMode aMode = kStringExactMatch);
+
+/**
+ * This function converts all uppercase letter characters in a given string to lowercase.
+ *
+ * @param[in,out] aString   A pointer to the string to convert.
+ *
+ */
+void StringConvertToLowercase(char *aString);
+
+/**
+ * This function converts all lowercase letter characters in a given string to uppercase.
+ *
+ * @param[in,out] aString   A pointer to the string to convert.
+ *
+ */
+void StringConvertToUppercase(char *aString);
+
+/**
+ * This function converts an uppercase letter character to lowercase.
+ *
+ * If @p aChar is uppercase letter it is converted lowercase. Otherwise, it remains unchanged.
+ *
+ * @param[in] aChar   The character to convert
+ *
+ * @returns The character converted to lowercase.
+ *
+ */
+char ToLowercase(char aChar);
+
+/**
+ * This function converts a lowercase letter character to uppercase.
+ *
+ * If @p aChar is lowercase letter it is converted uppercase. Otherwise, it remains unchanged.
+ *
+ * @param[in] aChar   The character to convert
+ *
+ * @returns The character converted to uppercase.
+ *
+ */
+char ToUppercase(char aChar);
+
+/**
+ * This function coverts a boolean to "yes" or "no" string.
+ *
+ * @param[in] aBool  A boolean value to convert.
+ *
+ * @returns The converted string representation of @p aBool ("yes" for TRUE and "no" for FALSE).
+ *
+ */
+const char *ToYesNo(bool aBool);
+
+/**
+ * This function validates whether a given byte sequence (string) follows UTF-8 encoding.
+ * Control characters are not allowed.
+ *
+ * @param[in]  aString  A null-terminated byte sequence.
+ *
+ * @retval TRUE   The sequence is a valid UTF-8 string.
+ * @retval FALSE  The sequence is not a valid UTF-8 string.
+ *
+ */
+bool IsValidUtf8String(const char *aString);
+
+/**
+ * This function validates whether a given byte sequence (string) follows UTF-8 encoding.
+ * Control characters are not allowed.
+ *
+ * @param[in]  aString  A byte sequence.
+ * @param[in]  aLength  Length of the sequence.
+ *
+ * @retval TRUE   The sequence is a valid UTF-8 string.
+ * @retval FALSE  The sequence is not a valid UTF-8 string.
+ *
+ */
+bool IsValidUtf8String(const char *aString, size_t aLength);
+
+/**
+ * This `constexpr` function checks whether two given C strings are in order (alphabetical order).
+ *
+ * This is intended for use from `static_assert`, e.g., checking if a lookup table entries are sorted. It is not
+ * recommended to use this function in other situations as it uses recursion so that it can be `constexpr`.
+ *
+ * @param[in] aFirst    The first string.
+ * @param[in] aSecond   The second string.
+ *
+ * @retval TRUE  If first string is strictly before second string (alphabetical order).
+ * @retval FALSE If first string is not strictly before second string (alphabetical order).
+ *
+ */
+inline constexpr bool AreStringsInOrder(const char *aFirst, const char *aSecond)
+{
+    return (*aFirst < *aSecond)
+               ? true
+               : ((*aFirst > *aSecond) || (*aFirst == '\0') ? false : AreStringsInOrder(aFirst + 1, aSecond + 1));
+}
 
 /**
  * This class implements writing to a string buffer.
@@ -199,6 +336,18 @@
      */
     StringWriter &AppendHexBytes(const uint8_t *aBytes, uint16_t aLength);
 
+    /**
+     * This method converts all uppercase letter characters in the string to lowercase.
+     *
+     */
+    void ConvertToLowercase(void) { StringConvertToLowercase(mBuffer); }
+
+    /**
+     * This method converts all lowercase letter characters in the string to uppercase.
+     *
+     */
+    void ConvertToUppercase(void) { StringConvertToUppercase(mBuffer); }
+
 private:
     char *         mBuffer;
     uint16_t       mLength;
@@ -236,29 +385,59 @@
 };
 
 /**
- * This function validates whether a given byte sequence (string) follows UTF-8 encoding.
- * Control characters are not allowed.
- *
- * @param[in]  aString  A null-terminated byte sequence.
- *
- * @retval TRUE   The sequence is a valid UTF-8 string.
- * @retval FALSE  The sequence is not a valid UTF-8 string.
+ * This class provides helper methods to convert from a set of `uint16_t` values (e.g., a non-sequential `enum`) to
+ * string using binary search in a lookup table.
  *
  */
-bool IsValidUtf8String(const char *aString);
+class Stringify : public BinarySearch
+{
+public:
+    /**
+     * This class represents a entry in the lookup table.
+     *
+     */
+    class Entry
+    {
+        friend class BinarySearch;
 
-/**
- * This function validates whether a given byte sequence (string) follows UTF-8 encoding.
- * Control characters are not allowed.
- *
- * @param[in]  aString  A byte sequence.
- * @param[in]  aLength  Length of the sequence.
- *
- * @retval TRUE   The sequence is a valid UTF-8 string.
- * @retval FALSE  The sequence is not a valid UTF-8 string.
- *
- */
-bool IsValidUtf8String(const char *aString, size_t aLength);
+    public:
+        uint16_t    mKey;    ///< The key value.
+        const char *mString; ///< The associated string.
+
+    private:
+        int Compare(uint16_t aKey) const { return (aKey == mKey) ? 0 : ((aKey > mKey) ? 1 : -1); }
+
+        constexpr static bool AreInOrder(const Entry &aFirst, const Entry &aSecond)
+        {
+            return aFirst.mKey < aSecond.mKey;
+        }
+    };
+
+    /**
+     * This static method looks up a key in a given sorted table array (using binary search) and return the associated
+     * strings with the key.
+     *
+     * @note This method requires the array to be sorted, otherwise its behavior is undefined.
+     *
+     * @tparam kLength     The array length (number of entries in the array).
+     *
+     * @param[in] aKey       The key to search for within the table.
+     * @param[in] aTable     A reference to an array of `kLength` entries.
+     * @param[in] aNotFound  A C string to return if @p aKey was not found in the table.
+     *
+     * @returns The associated string with @p aKey in @p aTable if found, or @p aNotFound otherwise.
+     *
+     */
+    template <uint16_t kLength>
+    static const char *Lookup(uint16_t aKey, const Entry (&aTable)[kLength], const char *aNotFound = "unknown")
+    {
+        const Entry *entry = BinarySearch::Find(aKey, aTable);
+
+        return (entry != nullptr) ? entry->mString : aNotFound;
+    }
+
+    Stringify(void) = delete;
+};
 
 /**
  * @}
diff --git a/src/core/common/tasklet.cpp b/src/core/common/tasklet.cpp
index a7dc136..b2c4512 100644
--- a/src/core/common/tasklet.cpp
+++ b/src/core/common/tasklet.cpp
@@ -70,9 +70,9 @@
 
     // This method processes all tasklets queued when this is called. We
     // keep a copy the current list and then clear the main list by
-    // setting `mTail` to nullptr. A newly posted tasklet while processing
-    // the currently queued tasklets will then trigger a call to
-    // `otTaskletsSignalPending()`.
+    // setting `mTail` to `nullptr`. A newly posted tasklet while
+    // processing the currently queued tasklets will then trigger a call
+    // to `otTaskletsSignalPending()`.
 
     mTail = nullptr;
 
diff --git a/src/core/common/time.hpp b/src/core/common/time.hpp
index 9e83587..6c07fa3 100644
--- a/src/core/common/time.hpp
+++ b/src/core/common/time.hpp
@@ -40,6 +40,7 @@
 #include <stdint.h>
 
 #include "common/equatable.hpp"
+#include "common/serial_number.hpp"
 
 namespace ot {
 
@@ -60,6 +61,11 @@
 class Time : public Unequatable<Time>
 {
 public:
+    static constexpr uint32_t kOneSecondInMsec = 1000u;                 ///< One second interval in msec.
+    static constexpr uint32_t kOneMinuteInMsec = kOneSecondInMsec * 60; ///< One minute interval in msec.
+    static constexpr uint32_t kOneHourInMsec   = kOneMinuteInMsec * 60; ///< One hour interval in msec.
+    static constexpr uint32_t kOneDayInMsec    = kOneHourInMsec * 24;   ///< One day interval in msec.
+
     /**
      * This constant defines a maximum time duration ensured to be longer than any other duration.
      *
@@ -173,7 +179,7 @@
      * @retval FALSE   This `Time` instance is not strictly before @p aOther.
      *
      */
-    bool operator<(const Time &aOther) const { return ((mValue - aOther.mValue) & (1UL << 31)) != 0; }
+    bool operator<(const Time &aOther) const { return SerialNumber::IsLess(mValue, aOther.mValue); }
 
     /**
      * This method indicates whether this `Time` instance is after or equal to another one.
@@ -235,18 +241,22 @@
     /**
      * This static method converts a given number of seconds to milliseconds.
      *
+     * @param[in] aSeconds   The seconds value to convert to milliseconds.
+     *
      * @returns The number of milliseconds.
      *
      */
-    static uint32_t SecToMsec(uint32_t aSeconds) { return aSeconds * 1000u; }
+    static uint32_t constexpr SecToMsec(uint32_t aSeconds) { return aSeconds * 1000u; }
 
     /**
      * This static method converts a given number of milliseconds to seconds.
      *
+     * @param[in] aMilliseconds  The milliseconds value to convert to seconds.
+     *
      * @returns The number of seconds.
      *
      */
-    static uint32_t MsecToSec(uint32_t aMilliseconds) { return aMilliseconds / 1000u; }
+    static uint32_t constexpr MsecToSec(uint32_t aMilliseconds) { return aMilliseconds / 1000u; }
 
 private:
     static constexpr uint32_t kDistantFuture = (1UL << 31);
diff --git a/src/core/common/time_ticker.cpp b/src/core/common/time_ticker.cpp
index c770275..2bfb130 100644
--- a/src/core/common/time_ticker.cpp
+++ b/src/core/common/time_ticker.cpp
@@ -94,6 +94,13 @@
         Get<AddressResolver>().HandleTimeTick();
     }
 
+#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
+    if (mReceivers & Mask(kNetworkDataNotifier))
+    {
+        Get<NetworkData::Notifier>().HandleTimeTick();
+    }
+#endif
+
 #if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
     if (mReceivers & Mask(kChildSupervisor))
     {
diff --git a/src/core/common/time_ticker.hpp b/src/core/common/time_ticker.hpp
index 8f5d272..a89f3e3 100644
--- a/src/core/common/time_ticker.hpp
+++ b/src/core/common/time_ticker.hpp
@@ -71,6 +71,7 @@
         kIp6FragmentReassembler, ///< `Ip6::Ip6` (handling of fragmented messages)
         kDuaManager,             ///< `DuaManager`
         kMlrManager,             ///< `MlrManager`
+        kNetworkDataNotifier,    ///< `NetworkData::Notifier`
 
         kNumReceivers, ///< Number of receivers.
     };
@@ -109,8 +110,8 @@
     bool IsReceiverRegistered(Receiver aReceiver) const { return (mReceivers & Mask(aReceiver)) != 0; }
 
 private:
-    static constexpr uint32_t kTickInterval  = 1000; // in msec.
-    static constexpr uint32_t kRestartJitter = 4;    // in msec, jitter added when restarting the timer [-4,+4] ms.
+    static constexpr uint32_t kTickInterval  = Time::kOneSecondInMsec;
+    static constexpr uint32_t kRestartJitter = 4; // in msec, jitter added when restarting the timer [-4,+4] ms.
 
     constexpr static uint32_t Mask(Receiver aReceiver) { return static_cast<uint32_t>(1U) << aReceiver; }
 
diff --git a/src/core/common/timer.cpp b/src/core/common/timer.cpp
index 803f054..66de06d 100644
--- a/src/core/common/timer.cpp
+++ b/src/core/common/timer.cpp
@@ -38,7 +38,6 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
 
 namespace ot {
 
diff --git a/src/core/common/timer.hpp b/src/core/common/timer.hpp
index 6489961..3faf09f 100644
--- a/src/core/common/timer.hpp
+++ b/src/core/common/timer.hpp
@@ -85,21 +85,6 @@
     typedef void (&Handler)(Timer &aTimer);
 
     /**
-     * This constructor creates a timer instance.
-     *
-     * @param[in]  aInstance   A reference to the OpenThread instance.
-     * @param[in]  aHandler    A pointer to a function that is called when the timer expires.
-     *
-     */
-    Timer(Instance &aInstance, Handler aHandler)
-        : InstanceLocator(aInstance)
-        , mHandler(aHandler)
-        , mFireTime()
-        , mNext(this)
-    {
-    }
-
-    /**
      * This method returns the fire time of the timer.
      *
      * @returns The fire time.
@@ -143,6 +128,13 @@
         LinkedList<Timer> mTimerList;
     };
 
+    Timer(Instance &aInstance, Handler aHandler)
+        : InstanceLocator(aInstance)
+        , mHandler(aHandler)
+        , mNext(this)
+    {
+    }
+
     bool DoesFireBefore(const Timer &aSecondTimer, Time aNow) const;
     void Fired(void) { mHandler(*this); }
 
diff --git a/src/core/common/tlvs.cpp b/src/core/common/tlvs.cpp
index 12edf4d..c045db6 100644
--- a/src/core/common/tlvs.cpp
+++ b/src/core/common/tlvs.cpp
@@ -41,8 +41,7 @@
 
 uint32_t Tlv::GetSize(void) const
 {
-    return IsExtended() ? sizeof(ExtendedTlv) + static_cast<const ExtendedTlv *>(this)->GetLength()
-                        : sizeof(Tlv) + GetLength();
+    return IsExtended() ? sizeof(ExtendedTlv) + As<ExtendedTlv>(this)->GetLength() : sizeof(Tlv) + GetLength();
 }
 
 uint8_t *Tlv::GetValue(void)
diff --git a/src/core/common/tlvs.hpp b/src/core/common/tlvs.hpp
index 7d07b34..4dd55f4 100644
--- a/src/core/common/tlvs.hpp
+++ b/src/core/common/tlvs.hpp
@@ -331,7 +331,6 @@
      * @tparam       SimpleTlvType   The simple TLV type to find (must be a sub-class of `SimpleTlvInfo`)
      *
      * @param[in]    aMessage        A reference to the message.
-     * @param[in]    aType           The TLV type to search for.
      * @param[out]   aValue          A reference to the value object to output the read value.
      *
      * @retval kErrorNone         The TLV was found and read successfully. @p aValue is updated.
@@ -469,6 +468,66 @@
 } OT_TOOL_PACKED_END;
 
 /**
+ * This template method casts a `Tlv` pointer to a given subclass `TlvType` pointer.
+ *
+ * @tparam TlvType  The TLV type to cast into. MUST be a subclass of `Tlv`.
+ *
+ * @param[in] aTlv   A pointer to a `Tlv` to convert/cast to a `TlvType`.
+ *
+ * @returns A `TlvType` pointer to `aTlv`.
+ *
+ */
+template <class TlvType> TlvType *As(Tlv *aTlv)
+{
+    return static_cast<TlvType *>(aTlv);
+}
+
+/**
+ * This template method casts a `Tlv` pointer to a given subclass `TlvType` pointer.
+ *
+ * @tparam TlvType  The TLV type to cast into. MUST be a subclass of `Tlv`.
+ *
+ * @param[in] aTlv   A pointer to a `Tlv` to convert/cast to a `TlvType`.
+ *
+ * @returns A `TlvType` pointer to `aTlv`.
+ *
+ */
+template <class TlvType> const TlvType *As(const Tlv *aTlv)
+{
+    return static_cast<const TlvType *>(aTlv);
+}
+
+/**
+ * This template method casts a `Tlv` reference to a given subclass `TlvType` reference.
+ *
+ * @tparam TlvType  The TLV type to cast into. MUST be a subclass of `Tlv`.
+ *
+ * @param[in] aTlv   A reference to a `Tlv` to convert/cast to a `TlvType`.
+ *
+ * @returns A `TlvType` reference to `aTlv`.
+ *
+ */
+template <class TlvType> TlvType &As(Tlv &aTlv)
+{
+    return static_cast<TlvType &>(aTlv);
+}
+
+/**
+ * This template method casts a `Tlv` reference to a given subclass `TlvType` reference.
+ *
+ * @tparam TlvType  The TLV type to cast into. MUST be a subclass of `Tlv`.
+ *
+ * @param[in] aTlv   A reference to a `Tlv` to convert/cast to a `TlvType`.
+ *
+ * @returns A `TlvType` reference to `aTlv`.
+ *
+ */
+template <class TlvType> const TlvType &As(const Tlv &aTlv)
+{
+    return static_cast<const TlvType &>(aTlv);
+}
+
+/**
  * This class defines constants for a TLV.
  *
  * @tparam kTlvTypeValue   The TLV Type value.
diff --git a/src/core/common/uptime.cpp b/src/core/common/uptime.cpp
index 9bac0f3..1c3c74c 100644
--- a/src/core/common/uptime.cpp
+++ b/src/core/common/uptime.cpp
@@ -117,7 +117,7 @@
 
 void Uptime::UptimeToString(uint64_t aUptime, StringWriter &aWriter)
 {
-    uint64_t days = aUptime / kOneDayInMsec;
+    uint64_t days = aUptime / Time::kOneDayInMsec;
     uint32_t remainder;
     uint32_t hours;
     uint32_t minutes;
@@ -126,13 +126,13 @@
     if (days > 0)
     {
         aWriter.Append("%lud.", days);
-        aUptime -= days * kOneDayInMsec;
+        aUptime -= days * Time::kOneDayInMsec;
     }
 
     remainder = static_cast<uint32_t>(aUptime);
-    hours     = DivideAndGetRemainder(remainder, kOneHourInMsec);
-    minutes   = DivideAndGetRemainder(remainder, kOneMinuteInMsec);
-    seconds   = DivideAndGetRemainder(remainder, kOneSecondInMsec);
+    hours     = DivideAndGetRemainder(remainder, Time::kOneHourInMsec);
+    minutes   = DivideAndGetRemainder(remainder, Time::kOneMinuteInMsec);
+    seconds   = DivideAndGetRemainder(remainder, Time::kOneSecondInMsec);
 
     aWriter.Append("%02u:%02u:%02u.%03u", hours, minutes, seconds, remainder);
 }
diff --git a/src/core/common/uptime.hpp b/src/core/common/uptime.hpp
index 35a5c91..d6cab3c 100644
--- a/src/core/common/uptime.hpp
+++ b/src/core/common/uptime.hpp
@@ -92,18 +92,14 @@
      * The string follows the format "<hh>:<mm>:<ss>.<mmmm>" for hours, minutes, seconds and millisecond (if uptime is
      * shorter than one day) or "<dd>d.<hh>:<mm>:<ss>.<mmmm>" (if longer than a day).
      *
-     * @param[in]    aUptime  The uptime to convert.
-     * @param[inout] aWriter  A `StringWriter` to append the converted string to.
+     * @param[in]     aUptime  The uptime to convert.
+     * @param[in,out] aWriter  A `StringWriter` to append the converted string to.
      *
      */
     static void UptimeToString(uint64_t aUptime, StringWriter &aWriter);
 
 private:
-    static constexpr uint32_t kTimerInterval   = (1 << 30);
-    static constexpr uint32_t kOneSecondInMsec = 1000;
-    static constexpr uint32_t kOneMinuteInMsec = 60 * kOneSecondInMsec;
-    static constexpr uint32_t kOneHourInMsec   = 60 * kOneMinuteInMsec;
-    static constexpr uint32_t kOneDayInMsec    = 24 * kOneHourInMsec;
+    static constexpr uint32_t kTimerInterval = (1 << 30);
 
     static_assert(static_cast<uint32_t>(4 * kTimerInterval) == 0, "kTimerInterval is not correct");
 
diff --git a/src/core/config/border_router.h b/src/core/config/border_router.h
index da57425..ec1792a 100644
--- a/src/core/config/border_router.h
+++ b/src/core/config/border_router.h
@@ -56,6 +56,32 @@
 #endif
 
 /**
+ * @def OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
+ *
+ * Define to 1 to enable mechanism on a Border Router which provides IP connectivity to request router role upgrade.
+ *
+ * This config is applicable on an `OPENTHREAD_FTD` build and when `OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE` is also
+ * enabled.
+ *
+ * A Border Router is considered to provide external IP connectivity if at least one of the below conditions hold:
+ *
+ * - It has added at least one external route entry.
+ * - It has added at least one prefix entry with default-route and on-mesh flags set.
+ * - It has added at least one domain prefix (domain and on-mesh flags set).
+ *
+ * A Border Router which provides IP connectivity and is acting as a REED is eligible to request a router role upgrade
+ * by sending an "Address Solicit" request to leader with status reason `BorderRouterRequest`. This reason is used when
+ * the number of active routers in the Thread mesh is above the threshold, and only if the number of existing eligible
+ * BRs (determined from the Thread Network Data) that are acting as router is less than two. This mechanism allows up
+ * to two eligible Border Routers to request router role upgrade when the number of routers is already above the
+ * threshold.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
+#define OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE 1
+#endif
+
+/**
  * @def OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
  *
  * Define to 1 to enable Border Routing support.
@@ -66,6 +92,47 @@
 #endif
 
 /**
+ * @def OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS
+ *
+ * Specifies maximum number of routers (on infra link) to track by routing manager.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS
+#define OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS 16
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES
+ *
+ * Specifies maximum number of discovered prefixes (on-link prefixes on the infra link) maintained by routing manager.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES
+#define OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES 64
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_ON_MESH_PREFIXES
+ *
+ * Specified maximum number of on-mesh prefixes (discovered from Thread Network Data) that are included as Route Info
+ * Option in emitted Router Advertisement messages.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_ON_MESH_PREFIXES
+#define OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_ON_MESH_PREFIXES 16
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
+ *
+ * Define to 1 to enable Border Routing NAT64 support.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
+#define OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE 0
+#endif
+
+/**
  * @def OPENTHREAD_CONFIG_BORDER_AGENT_UDP_PORT
  *
  * Specifies the Border Agent UDP port, and use 0 for ephemeral port.
diff --git a/src/core/config/dns_dso.h b/src/core/config/dns_dso.h
new file mode 100644
index 0000000..65a7171
--- /dev/null
+++ b/src/core/config/dns_dso.h
@@ -0,0 +1,78 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes compile-time configurations for the DNS Stateful Operations (DSO).
+ *
+ */
+
+#ifndef CONFIG_DNS_DSO_H_
+#define CONFIG_DNS_DSO_H_
+
+/**
+ * @def OPENTHREAD_CONFIG_DNS_DSO_ENABLE
+ *
+ * Define to 1 to enable DSO support.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DNS_DSO_ENABLE
+#define OPENTHREAD_CONFIG_DNS_DSO_ENABLE 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_DNS_DSO_CONNECTING_TIMEOUT
+ *
+ * Specifies the maximum time (in msec) waiting for a connection to be established by DSO platform layer.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DNS_DSO_CONNECTING_TIMEOUT
+#define OPENTHREAD_CONFIG_DNS_DSO_CONNECTING_TIMEOUT (45 * 1000)
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_DNS_DSO_RESPONSE_TIMEOUT
+ *
+ * Specifies the maximum time (in msec) waiting for a response to a request.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DNS_DSO_RESPONSE_TIMEOUT
+#define OPENTHREAD_CONFIG_DNS_DSO_RESPONSE_TIMEOUT (30 * 1000)
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_DNS_DSO_MAX_PENDING_REQUESTS
+ *
+ * Specifies the maximum number of pending requests per DSO session.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DNS_DSO_MAX_PENDING_REQUESTS
+#define OPENTHREAD_CONFIG_DNS_DSO_MAX_PENDING_REQUESTS 3
+#endif
+
+#endif // CONFIG_DNS_DSO_H_
diff --git a/src/core/config/history_tracker.h b/src/core/config/history_tracker.h
index 7cf6574..32da285 100644
--- a/src/core/config/history_tracker.h
+++ b/src/core/config/history_tracker.h
@@ -127,4 +127,28 @@
 #define OPENTHREAD_CONFIG_HISTORY_TRACKER_NEIGHBOR_LIST_SIZE 64
 #endif
 
+/**
+ * @def OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_MESH_PREFIX_LIST_SIZE
+ *
+ * Specifies the maximum number of entries in Network Data On Mesh Prefix history list.
+ *
+ * Can be set to zero to configure History Tracker module not to collect prefix info.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_MESH_PREFIX_LIST_SIZE
+#define OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_MESH_PREFIX_LIST_SIZE 32
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_HISTORY_TRACKER_EXTERNAL_ROUTE_LIST_SIZE
+ *
+ * Specifies the maximum number of entries in Network Data External Route history list.
+ *
+ * Can be set to zero to configure History Tracker module not to collect route info.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_HISTORY_TRACKER_EXTERNAL_ROUTE_LIST_SIZE
+#define OPENTHREAD_CONFIG_HISTORY_TRACKER_EXTERNAL_ROUTE_LIST_SIZE 32
+#endif
+
 #endif // CONFIG_HISTORY_TRACKER_H_
diff --git a/src/core/config/ip6.h b/src/core/config/ip6.h
index 4eb5ac3..b84918f 100644
--- a/src/core/config/ip6.h
+++ b/src/core/config/ip6.h
@@ -161,23 +161,6 @@
 #endif
 
 /**
- * @def OPENTHREAD_CONFIG_UNSECURE_TRAFFIC_MANAGED_BY_STACK_ENABLE
- *
- * Define as 1 to enable dynamic unsecure port management
- *
- * If this feature is enabled, OpenThread will automaitically disable link-level
- * security for packets sent with unsecure source ports. Once we receive a secure
- * packet sent to the unsecure port, this port will be removed from the unsecure
- * port list.
- *
- * Enable only if you know well about its behavior.
- *
- */
-#ifndef OPENTHREAD_CONFIG_UNSECURE_TRAFFIC_MANAGED_BY_STACK_ENABLE
-#define OPENTHREAD_CONFIG_UNSECURE_TRAFFIC_MANAGED_BY_STACK_ENABLE 0
-#endif
-
-/**
  * @def OPENTHREAD_CONFIG_TCP_ENABLE
  *
  * Define as 1 to enable TCP.
@@ -187,4 +170,14 @@
 #define OPENTHREAD_CONFIG_TCP_ENABLE 1
 #endif
 
+/**
+ * @def OPENTHREAD_CONFIG_IP6_ALLOW_LOOP_BACK_HOST_DATAGRAMS
+ *
+ * Define as 1 to allow IPv6 datagrams from Host to be looped back to Host.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_IP6_ALLOW_LOOP_BACK_HOST_DATAGRAMS
+#define OPENTHREAD_CONFIG_IP6_ALLOW_LOOP_BACK_HOST_DATAGRAMS 1
+#endif
+
 #endif // CONFIG_IP6_H_
diff --git a/src/core/config/logging.h b/src/core/config/logging.h
index 509bb73..aacec69 100644
--- a/src/core/config/logging.h
+++ b/src/core/config/logging.h
@@ -104,109 +104,9 @@
 #endif
 
 /**
- * @def OPENTHREAD_CONFIG_LOG_API
- *
- * Define to enable OpenThread API logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_API
-#define OPENTHREAD_CONFIG_LOG_API 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_MLE
- *
- * Define to enable MLE logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_MLE
-#define OPENTHREAD_CONFIG_LOG_MLE 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_MESHCOP
- *
- * Define to enable MeshCoP logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_MESHCOP
-#define OPENTHREAD_CONFIG_LOG_MESHCOP 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_ARP
- *
- * Define to enable EID-to-RLOC map logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_ARP
-#define OPENTHREAD_CONFIG_LOG_ARP 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_NETDATA
- *
- * Define to enable Network Data logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_NETDATA
-#define OPENTHREAD_CONFIG_LOG_NETDATA 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_ICMP
- *
- * Define to enable ICMPv6 logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_ICMP
-#define OPENTHREAD_CONFIG_LOG_ICMP 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_IP6
- *
- * Define to enable IPv6 logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_IP6
-#define OPENTHREAD_CONFIG_LOG_IP6 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_TCP
- *
- * Define to enable IPv6 logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_TCP
-#define OPENTHREAD_CONFIG_LOG_TCP 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_MAC
- *
- * Define to enable IEEE 802.15.4 MAC logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_MAC
-#define OPENTHREAD_CONFIG_LOG_MAC 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_MEM
- *
- * Define to enable memory logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_MEM
-#define OPENTHREAD_CONFIG_LOG_MEM 1
-#endif
-
-/**
  * @def OPENTHREAD_CONFIG_LOG_PKT_DUMP
  *
- * Define to enable log content of packets.
+ * Define to enable dump logs (of packets).
  *
  */
 #ifndef OPENTHREAD_CONFIG_LOG_PKT_DUMP
@@ -214,29 +114,9 @@
 #endif
 
 /**
- * @def OPENTHREAD_CONFIG_LOG_NETDIAG
- *
- * Define to enable network diagnostic logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_NETDIAG
-#define OPENTHREAD_CONFIG_LOG_NETDIAG 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_PLATFORM
- *
- * Define to enable platform region logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_PLATFORM
-#define OPENTHREAD_CONFIG_LOG_PLATFORM 1
-#endif
-
-/**
  * @def OPENTHREAD_CONFIG_LOG_CLI
  *
- * Define to enable CLI logging.
+ * Define to enable CLI logging and `otLogCli()` OT function.
  *
  */
 #ifndef OPENTHREAD_CONFIG_LOG_CLI
@@ -244,99 +124,13 @@
 #endif
 
 /**
- * @def OPENTHREAD_CONFIG_LOG_COAP
+ * @def OPENTHREAD_CONFIG_LOG_PLATFORM
  *
- * Define to enable COAP logging.
+ * Define to enable platform logging and `otLog{Level}Plat()` OT functions.
  *
  */
-#ifndef OPENTHREAD_CONFIG_LOG_COAP
-#define OPENTHREAD_CONFIG_LOG_COAP 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_CORE
- *
- * Define to enable OpenThread Core logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_CORE
-#define OPENTHREAD_CONFIG_LOG_CORE 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_UTIL
- *
- * Define to enable OpenThread Utility module logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_UTIL
-#define OPENTHREAD_CONFIG_LOG_UTIL 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_BBR
- *
- * Note: available since Thread 1.2.
- *
- * Define to enable Backbone Router (BBR) region logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_BBR
-#define OPENTHREAD_CONFIG_LOG_BBR 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_MLR
- *
- * Note: available since Thread 1.2.
- *
- * Define to enable Multicast Listener Registration (MLR) region logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_MLR
-#define OPENTHREAD_CONFIG_LOG_MLR 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_DUA
- *
- * Note: available since Thread 1.2.
- *
- * Define to enable Domain Unicast Address (DUA) region logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_DUA
-#define OPENTHREAD_CONFIG_LOG_DUA 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_BR
- *
- * Define to Border Router (BR) region logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_BR
-#define OPENTHREAD_CONFIG_LOG_BR 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_SRP
- *
- * Define to enable Service Registration Protocol (SRP) region logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_SRP
-#define OPENTHREAD_CONFIG_LOG_SRP 1
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_LOG_DNS
- *
- * Define to enable DNS region logging.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_DNS
-#define OPENTHREAD_CONFIG_LOG_DNS 1
+#ifndef OPENTHREAD_CONFIG_LOG_PLATFORM
+#define OPENTHREAD_CONFIG_LOG_PLATFORM 1
 #endif
 
 /**
@@ -360,16 +154,6 @@
 #endif
 
 /**
- * @def OPENTHREAD_CONFIG_LOG_PREPEND_REGION
- *
- * Define to prepend the log region to all log messages.
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_PREPEND_REGION
-#define OPENTHREAD_CONFIG_LOG_PREPEND_REGION 1
-#endif
-
-/**
  * @def OPENTHREAD_CONFIG_LOG_SUFFIX
  *
  * Define suffix to append at the end of logs.
@@ -391,31 +175,6 @@
 #endif
 
 /**
- * @def OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
- *
- * Set to 1 to require all the logging related definition to user macro only (up to the call to the platform log API).
- * Otherwise the logging implementation uses functions (which is preferred and recommended model).
- *
- * This is intended for special platform requirements where the logging needs to be defined a macro (e.g., for log
- * tokenization or similar features).
- *
- */
-#ifndef OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
-#define OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY 0
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME
- *
- * Defines the name of macro used for logging inside OpenThread, by default it is set to `otPlatLog()`. This is used
- * and applicable only when `OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY` is set to 1.
- *
- */
-#ifndef OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME
-#define OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME otPlatLog
-#endif
-
-/**
  * @def OPENTHREAD_CONFIG_LOG_MAX_SIZE
  *
  * The maximum log string size (number of chars).
diff --git a/src/core/config/mac.h b/src/core/config/mac.h
index e244425..d44ff11 100644
--- a/src/core/config/mac.h
+++ b/src/core/config/mac.h
@@ -86,6 +86,66 @@
 #endif
 
 /**
+ * @def OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
+ *
+ * Define as 1 to add random backoff delay in between frame transmission retries when the previous attempt resulted in
+ * no-ack error.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
+#define OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY 1
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_RETX_DELAY_MIN_BACKOFF_EXPONENT
+ *
+ * Specifies the minimum backoff exponent to start with when adding random delay in between frame transmission
+ * retries on no-ack error. It is applicable only when `OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY`
+ * is enabled.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_RETX_DELAY_MIN_BACKOFF_EXPONENT
+#define OPENTHREAD_CONFIG_MAC_RETX_DELAY_MIN_BACKOFF_EXPONENT 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_RETX_DELAY_MAX_BACKOFF_EXPONENT
+ *
+ * Specifies the maximum backoff exponent when adding random delay in between frame transmission retries on no-ack
+ * error. It is applicable only when `OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY` is enabled.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_RETX_DELAY_MAX_BACKOFF_EXPONENT
+#define OPENTHREAD_CONFIG_MAC_RETX_DELAY_MAX_BACKOFF_EXPONENT 5
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
+ *
+ * Define as 1 to enable collision avoidance delay feature, which adds a delay wait time after a successful frame tx
+ * to a neighbor which is expected to forward the frame. This delay is applied before the next direct frame tx (towards
+ * any neighbor) on an FTD.
+ *
+ * The delay interval is specified by `OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_INTERVAL` (in milliseconds).
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
+#define OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE 1
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_INTERVAL
+ *
+ * Specifies the collision avoidance delay interval in milliseconds. This is added after a successful frame tx to a
+ * neighbor that is expected to forward the frame (when `OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE` is
+ * enabled).
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_INTERVAL
+#define OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_INTERVAL 8
+#endif
+
+/**
  * @def OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
  *
  * Define to 1 to enable MAC retry packets histogram analysis.
@@ -439,4 +499,26 @@
 #define OPENTHREAD_CONFIG_MAC_SCAN_DURATION 300
 #endif
 
+/**
+ * @def OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE
+ *
+ * This setting configures if the beacon payload parsing needs to be enabled in MAC. This is optional and is disabled by
+ * default because Thread 1.2.1 has removed support for beacon payloads.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE
+#define OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE
+ *
+ * This setting configures if the beacon payload needs to be enabled in outgoing beacon frames. This is optional and is
+ * disabled by default because Thread 1.2.1 has removed support for beacon payloads.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE
+#define OPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE 0
+#endif
+
 #endif // CONFIG_MAC_H_
diff --git a/src/core/config/openthread-core-default-config.h b/src/core/config/misc.h
similarity index 82%
rename from src/core/config/openthread-core-default-config.h
rename to src/core/config/misc.h
index c73c7f6..3070bb0 100644
--- a/src/core/config/openthread-core-default-config.h
+++ b/src/core/config/misc.h
@@ -28,12 +28,11 @@
 
 /**
  * @file
- *   This file includes default compile-time configuration constants
- *   for OpenThread.
+ *   This file includes miscellaneous compile-time configuration constants for OpenThread.
  */
 
-#ifndef OPENTHREAD_CORE_DEFAULT_CONFIG_H_
-#define OPENTHREAD_CORE_DEFAULT_CONFIG_H_
+#ifndef CONFIG_MISC_H_
+#define CONFIG_MISC_H_
 
 #include "config/coap.h"
 #include "config/srp_server.h"
@@ -423,6 +422,84 @@
 #endif
 
 /**
+ * @def OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+ *
+ * Define to 1 to enable delay-aware queue management for the send queue.
+ *
+ * When enabled device will monitor time-in-queue of messages in the direct tx queue and if the wait time is lager than
+ * specified thresholds it may update ECN flag (if message indicates it is ECN-capable) or drop the message.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+#define OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE \
+    (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_3)
+#endif
+
+/**
+ * @OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_MARK_ECN_INTERVAL
+ *
+ * Specifies the time-in-queue threshold interval in milliseconds to mark ECN on a message if it is ECN-capable or
+ * drop the message if not ECN-capable.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_MARK_ECN_INTERVAL
+#define OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_MARK_ECN_INTERVAL 500
+#endif
+
+/**
+ * @OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_DROP_MSG_INTERVAL
+ *
+ * Specifies the time-in-queue threshold interval in milliseconds to drop a message.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_DROP_MSG_INTERVAL
+#define OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_DROP_MSG_INTERVAL 1000
+#endif
+
+/**
+ * OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_FRAG_TAG_RETAIN_TIME
+ *
+ * Specifies the max retain time in seconds of a mesh header fragmentation tag entry in the list.
+ *
+ * The entry in list is used to track whether an earlier fragment of same message was dropped by the router and if so
+ * the next fragments are also dropped. The entry is removed once last fragment is processed or after the retain time
+ * specified by this config parameter expires.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_FRAG_TAG_RETAIN_TIME
+#define OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_FRAG_TAG_RETAIN_TIME (4 * 60) // 4 minutes
+#endif
+
+/**
+ * OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_FRAG_TAG_ENTRY_LIST_SIZE
+ *
+ * Specifies the number of mesh header fragmentation tag entries in the list for delay-aware queue management.
+ *
+ * The list is used to track whether an earlier fragment of same message was dropped by the router and if so the next
+ * fragments are also dropped.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_FRAG_TAG_ENTRY_LIST_SIZE
+#define OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_FRAG_TAG_ENTRY_LIST_SIZE 16
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE
+ *
+ * Specifies the maximum number of frames in direct tx queue before new direct tx messages are dropped.
+ *
+ * If set to zero then the behavior is disabled, i.e., no check is performed on tx queue length.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_3)
+#define OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE 100
+#else
+#define OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE 0
+#endif
+#endif
+
+/**
  * @def OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_SUPPORT
  *
  * Define to 1 to support proprietary radio configurations defined by platform.
@@ -527,4 +604,4 @@
 #define OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE 0
 #endif
 
-#endif // OPENTHREAD_CORE_DEFAULT_CONFIG_H_
+#endif // CONFIG_MISC_H_
diff --git a/src/core/config/mle.h b/src/core/config/mle.h
index 068ca76..872e1a7 100644
--- a/src/core/config/mle.h
+++ b/src/core/config/mle.h
@@ -287,7 +287,7 @@
  *
  */
 #ifndef OPENTHREAD_CONFIG_MLE_LINK_METRICS_MAX_SERIES_SUPPORTED
-#define OPENTHREAD_CONFIG_MLE_LINK_METRICS_MAX_SERIES_SUPPORTED 10
+#define OPENTHREAD_CONFIG_MLE_LINK_METRICS_MAX_SERIES_SUPPORTED OPENTHREAD_CONFIG_MLE_MAX_CHILDREN
 #endif
 
 #endif // CONFIG_MLE_H_
diff --git a/src/core/config/netdata_publisher.h b/src/core/config/netdata_publisher.h
index 7f9fe07..bd3ef8f 100644
--- a/src/core/config/netdata_publisher.h
+++ b/src/core/config/netdata_publisher.h
@@ -35,6 +35,7 @@
 #ifndef CONFIG_NETDATA_PUBLISHER_H_
 #define CONFIG_NETDATA_PUBLISHER_H_
 
+#include "config/border_router.h"
 #include "config/srp_server.h"
 
 /**
@@ -48,7 +49,8 @@
  *
  */
 #ifndef OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
-#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE \
+    (OPENTHREAD_CONFIG_SRP_SERVER_ENABLE || OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE)
 #endif
 
 /**
@@ -149,7 +151,13 @@
  *
  */
 #ifndef OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES \
+    (OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES + 5)
+#else
 #define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES 3
 #endif
+#endif
 
 #endif // CONFIG_NETDATA_PUBLISHER_H_
diff --git a/src/core/config/openthread-core-config-check.h b/src/core/config/openthread-core-config-check.h
index 7d3e927..4cf7121 100644
--- a/src/core/config/openthread-core-config-check.h
+++ b/src/core/config/openthread-core-config-check.h
@@ -478,11 +478,6 @@
 #error "OPENTHREAD_CONFIG_LOG_OUTPUT_NCP_SPINEL is removed, use OPENTHREAD_CONFIG_LOG_OUTPUT_APP instead"
 #endif
 
-#ifdef OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION
-#error "OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION was replaced by OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME " \
-       "(and OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY)"
-#endif
-
 #ifdef OPENTHREAD_CONFIG_DNS_RESPONSE_TIMEOUT
 #error "OPENTHREAD_CONFIG_DNS_RESPONSE_TIMEOUT was replaced by OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_RESPONSE_TIMEOUT"
 #endif
@@ -519,4 +514,122 @@
        " and OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE"
 #endif
 
+#ifdef OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
+#error "OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME
+#error "OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION
+#error "OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_UNSECURE_TRAFFIC_MANAGED_BY_STACK_ENABLE
+#error "OPENTHREAD_CONFIG_UNSECURE_TRAFFIC_MANAGED_BY_STACK_ENABLE was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_API
+#error "OPENTHREAD_CONFIG_LOG_API was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_MLE
+#error "OPENTHREAD_CONFIG_LOG_MLE was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_MESHCOP
+#error "OPENTHREAD_CONFIG_LOG_MESHCOP was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_ARP
+#error "OPENTHREAD_CONFIG_LOG_ARP was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_NETDATA
+#error "OPENTHREAD_CONFIG_LOG_NETDATA was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_ICMP
+#error "OPENTHREAD_CONFIG_LOG_ICMP was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_IP6
+#error "OPENTHREAD_CONFIG_LOG_IP6 was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_TCP
+#error "OPENTHREAD_CONFIG_LOG_TCP was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_MAC
+#error "OPENTHREAD_CONFIG_LOG_MAC was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_MEM
+#error "OPENTHREAD_CONFIG_LOG_MEM was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_NETDIAG
+#error "OPENTHREAD_CONFIG_LOG_NETDIAG was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_COAP
+#error "OPENTHREAD_CONFIG_LOG_COAP was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_CORE
+#error "OPENTHREAD_CONFIG_LOG_CORE was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_UTIL
+#error "OPENTHREAD_CONFIG_LOG_UTIL was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_BBR
+#error "OPENTHREAD_CONFIG_LOG_BBR was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_MLR
+#error "OPENTHREAD_CONFIG_LOG_MLR was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_DUA
+#error "OPENTHREAD_CONFIG_LOG_DUA was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_BR
+#error "OPENTHREAD_CONFIG_LOG_BR was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_SRP
+#error "OPENTHREAD_CONFIG_LOG_SRP was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_DNS
+#error "OPENTHREAD_CONFIG_LOG_DNS was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_LOG_PREPEND_REGION
+#error "OPENTHREAD_CONFIG_LOG_PREPEND_REGION was removed and not longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_SRP_SERVER_MAX_ADDRESSES_NUM
+#error "OPENTHREAD_CONFIG_SRP_SERVER_MAX_ADDRESSES_NUM was removed. "\
+       "SRP host uses dynamic heap array to store addresses so no need for config on max number of addresses".
+#endif
+
+#ifdef OPENTHREAD_CONFIG_PLATFORM_CSL_UNCERT
+#error "OPENTHREAD_CONFIG_PLATFORM_CSL_UNCERT was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_BORDER_ROUTING_VICARIOUS_RS_ENABLE
+#error "OPENTHREAD_CONFIG_BORDER_ROUTING_VICARIOUS_RS_ENABLE was removed and no longer supported"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_DELAY
+#error "OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_DELAY was replaced with "\
+        "OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY and OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MAX_DELAY"
+#endif
+
 #endif // OPENTHREAD_CORE_CONFIG_CHECK_H_
diff --git a/src/core/config/platform.h b/src/core/config/platform.h
index 83581fe..ca132db 100644
--- a/src/core/config/platform.h
+++ b/src/core/config/platform.h
@@ -148,6 +148,16 @@
 #define OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE 0
 #endif
 
+/**
+ * @def OPENTHREAD_CONFIG_PLATFORM_MAC_KEYS_EXPORTABLE_ENABLE
+ *
+ * Define to 1 if you want to make MAC keys exportable.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_PLATFORM_MAC_KEYS_EXPORTABLE_ENABLE
+#define OPENTHREAD_CONFIG_PLATFORM_MAC_KEYS_EXPORTABLE_ENABLE 0
+#endif
+
 #if OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_SUPPORT
 #if (!defined(OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_PAGE) || \
      !defined(OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_MIN) ||  \
@@ -166,14 +176,4 @@
 #endif
 #endif
 
-/**
- * @def OPENTHREAD_CONFIG_PLATFORM_CSL_UNCERT
- *
- * The Uncertainty of the scheduling CSL of transmission by the parent, in ±10 us units.
- *
- */
-#ifndef OPENTHREAD_CONFIG_PLATFORM_CSL_UNCERT
-#define OPENTHREAD_CONFIG_PLATFORM_CSL_UNCERT UINT8_MAX
-#endif
-
 #endif // CONFIG_PLATFORM_H_
diff --git a/src/core/config/radio_link.h b/src/core/config/radio_link.h
index 1179261..e82ea96 100644
--- a/src/core/config/radio_link.h
+++ b/src/core/config/radio_link.h
@@ -72,4 +72,14 @@
 #define OPENTHREAD_CONFIG_MULTI_RADIO 0
 #endif
 
+/**
+ * @def OPENTHREAD_CONFIG_MULTI_RADIO_FRAG_TAG_TIMEOUT
+ *
+ * Specifies the fragment tag timeout interval in milliseconds.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MULTI_RADIO_FRAG_TAG_TIMEOUT
+#define OPENTHREAD_CONFIG_MULTI_RADIO_FRAG_TAG_TIMEOUT (20 * 1000)
+#endif
+
 #endif // CONFIG_RADIO_LINK_H_
diff --git a/src/core/config/srp_client.h b/src/core/config/srp_client.h
index e13ed7d..4bef258 100644
--- a/src/core/config/srp_client.h
+++ b/src/core/config/srp_client.h
@@ -214,9 +214,11 @@
 #endif
 
 /**
- * @def OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_DELAY
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY
  *
- * Specifies the (short) delay (in msec) after an update is required before SRP client sends the update message.
+ * Specifies the minimum value (in msec) for the short random delay wait time before sending an update message.
+ *
+ * The random delay is chosen uniformly from the min up to max value `OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MAX_DELAY`.
  *
  * When there is a change (e.g., a new service is added/removed) that requires an update, the SRP client will wait for
  * a short delay before preparing and sending an SRP update message to server. This allows user to provide more change
@@ -225,8 +227,22 @@
  * delay timer.
  *
  */
-#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_DELAY
-#define OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_DELAY 10
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY
+#define OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY 10
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY
+ *
+ * Specifies the maximum value (in msec) for the short random delay wait time before sending an update message.
+ *
+ * The random delay is chosen uniformly from the min `OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY` up to max value.
+ *
+ * See `OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY` for more details.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MAX_DELAY
+#define OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MAX_DELAY 700
 #endif
 
 /**
diff --git a/src/core/config/srp_server.h b/src/core/config/srp_server.h
index 7bc5aef..aeffbdf 100644
--- a/src/core/config/srp_server.h
+++ b/src/core/config/srp_server.h
@@ -109,14 +109,4 @@
 #define OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_UPDATE_TIMEOUT ((4 * 250u) + 250u)
 #endif
 
-/**
- * @def OPENTHREAD_CONFIG_SRP_SERVER_MAX_ADDRESSES_NUM
- *
- * Specifies the maximum number of addresses the SRP server can handle for a host.
- *
- */
-#ifndef OPENTHREAD_CONFIG_SRP_SERVER_MAX_ADDRESSES_NUM
-#define OPENTHREAD_CONFIG_SRP_SERVER_MAX_ADDRESSES_NUM 2
-#endif
-
 #endif // CONFIG_SRP_SERVER_H_
diff --git a/src/core/config/tmf.h b/src/core/config/tmf.h
index cf3c062..538ccaf 100644
--- a/src/core/config/tmf.h
+++ b/src/core/config/tmf.h
@@ -213,6 +213,7 @@
 #endif
 
 /**
+ * @def OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
  *
  * This setting configures the Multicast Listener Registration parent proxing in Thread 1.2.
  *
diff --git a/src/core/crypto/aes_ccm.cpp b/src/core/crypto/aes_ccm.cpp
index a3ed5e5..49c42f2 100644
--- a/src/core/crypto/aes_ccm.cpp
+++ b/src/core/crypto/aes_ccm.cpp
@@ -248,6 +248,21 @@
     }
 }
 
+#if !OPENTHREAD_RADIO
+void AesCcm::Payload(Message &aMessage, uint16_t aOffset, uint16_t aLength, Mode aMode)
+{
+    Message::MutableChunk chunk;
+
+    aMessage.GetFirstChunk(aOffset, aLength, chunk);
+
+    while (chunk.GetLength() > 0)
+    {
+        Payload(chunk.GetBytes(), chunk.GetBytes(), chunk.GetLength(), aMode);
+        aMessage.GetNextChunk(aLength, chunk);
+    }
+}
+#endif
+
 void AesCcm::Finalize(void *aTag)
 {
     uint8_t *tagBytes = reinterpret_cast<uint8_t *>(aTag);
diff --git a/src/core/crypto/aes_ccm.hpp b/src/core/crypto/aes_ccm.hpp
index 34e50f7..0234243 100644
--- a/src/core/crypto/aes_ccm.hpp
+++ b/src/core/crypto/aes_ccm.hpp
@@ -40,6 +40,8 @@
 
 #include <openthread/platform/crypto.h>
 #include "common/error.hpp"
+#include "common/message.hpp"
+#include "common/type_traits.hpp"
 #include "crypto/aes_ecb.hpp"
 #include "crypto/storage.hpp"
 #include "mac/mac_types.hpp"
@@ -126,16 +128,46 @@
     void Header(const void *aHeader, uint32_t aHeaderLength);
 
     /**
+     * This method processes the header.
+     *
+     * @tparam    ObjectType   The object type.
+     *
+     * @param[in] aObject      A reference to the object to add to header.
+     *
+     */
+    template <typename ObjectType> void Header(const ObjectType &aObject)
+    {
+        static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
+
+        Header(&aObject, sizeof(ObjectType));
+    }
+
+    /**
      * This method processes the payload.
      *
-     * @param[inout]  aPlainText   A pointer to the plaintext.
-     * @param[inout]  aCipherText  A pointer to the ciphertext.
-     * @param[in]     aLength      Payload length in bytes.
-     * @param[in]     aMode        Mode to indicate whether to encrypt (`kEncrypt`) or decrypt (`kDecrypt`).
+     * @param[in,out]  aPlainText   A pointer to the plaintext.
+     * @param[in,out]  aCipherText  A pointer to the ciphertext.
+     * @param[in]      aLength      Payload length in bytes.
+     * @param[in]      aMode        Mode to indicate whether to encrypt (`kEncrypt`) or decrypt (`kDecrypt`).
      *
      */
     void Payload(void *aPlainText, void *aCipherText, uint32_t aLength, Mode aMode);
 
+#if !OPENTHREAD_RADIO
+    /**
+     * This method processes the payload within a given message.
+     *
+     * This method encrypts/decrypts the payload content in place within the @p aMessage.
+     *
+     * @param[in,out]  aMessage     The message to read from and update.
+     * @param[in]      aOffset      The offset in @p aMessage to start of payload.
+     * @param[in]      aLength      Payload length in bytes.
+     * @param[in]      aMode        Mode to indicate whether to encrypt (`kEncrypt`) or decrypt (`kDecrypt`).
+     *
+     */
+    void Payload(Message &aMessage, uint16_t aOffset, uint16_t aLength, Mode aMode);
+#endif
+
     /**
      * This method returns the tag length in bytes.
      *
diff --git a/src/core/crypto/crypto_platform.cpp b/src/core/crypto/crypto_platform.cpp
index d49f1a6..7b3a770 100644
--- a/src/core/crypto/crypto_platform.cpp
+++ b/src/core/crypto/crypto_platform.cpp
@@ -33,11 +33,14 @@
 #include "openthread-core-config.h"
 
 #include <mbedtls/aes.h>
+#include <mbedtls/ctr_drbg.h>
+#include <mbedtls/entropy.h>
 #include <mbedtls/md.h>
 #include <mbedtls/sha256.h>
 
 #include <openthread/instance.h>
 #include <openthread/platform/crypto.h>
+#include <openthread/platform/entropy.h>
 #include <openthread/platform/time.h>
 
 #include "common/code_utils.hpp"
@@ -51,12 +54,27 @@
 using namespace ot;
 using namespace Crypto;
 
+#if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_MBEDTLS
+
 //---------------------------------------------------------------------------------------------------------------------
 // Default/weak implementation of crypto platform APIs
 
-OT_TOOL_WEAK otError otPlatCryptoInit(void)
+#if (!defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) && \
+     (!defined(MBEDTLS_NO_PLATFORM_ENTROPY) || defined(MBEDTLS_HAVEGE_C) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT)))
+#define OT_MBEDTLS_STRONG_DEFAULT_ENTROPY_PRESENT
+#endif
+
+#if !OPENTHREAD_RADIO
+static mbedtls_ctr_drbg_context sCtrDrbgContext;
+static mbedtls_entropy_context  sEntropyContext;
+#ifndef OT_MBEDTLS_STRONG_DEFAULT_ENTROPY_PRESENT
+static constexpr uint16_t kEntropyMinThreshold = 16;
+#endif
+#endif
+
+OT_TOOL_WEAK void otPlatCryptoInit(void)
 {
-    return kErrorNone;
+    // Intentionally empty.
 }
 
 // AES  Implementation
@@ -419,4 +437,53 @@
     return error;
 }
 
+#ifndef OT_MBEDTLS_STRONG_DEFAULT_ENTROPY_PRESENT
+
+static int handleMbedtlsEntropyPoll(void *aData, unsigned char *aOutput, size_t aInLen, size_t *aOutLen)
+{
+    int rval = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+
+    SuccessOrExit(otPlatEntropyGet(reinterpret_cast<uint8_t *>(aOutput), static_cast<uint16_t>(aInLen)));
+    rval = 0;
+
+    VerifyOrExit(aOutLen != nullptr);
+    *aOutLen = aInLen;
+
+exit:
+    OT_UNUSED_VARIABLE(aData);
+    return rval;
+}
+
+#endif // OT_MBEDTLS_STRONG_DEFAULT_ENTROPY_PRESENT
+
+OT_TOOL_WEAK void otPlatCryptoRandomInit(void)
+{
+    mbedtls_entropy_init(&sEntropyContext);
+
+#ifndef OT_MBEDTLS_STRONG_DEFAULT_ENTROPY_PRESENT
+    mbedtls_entropy_add_source(&sEntropyContext, handleMbedtlsEntropyPoll, nullptr, kEntropyMinThreshold,
+                               MBEDTLS_ENTROPY_SOURCE_STRONG);
+#endif
+
+    mbedtls_ctr_drbg_init(&sCtrDrbgContext);
+
+    int rval = mbedtls_ctr_drbg_seed(&sCtrDrbgContext, mbedtls_entropy_func, &sEntropyContext, nullptr, 0);
+    OT_ASSERT(rval == 0);
+    OT_UNUSED_VARIABLE(rval);
+}
+
+OT_TOOL_WEAK void otPlatCryptoRandomDeinit(void)
+{
+    mbedtls_entropy_free(&sEntropyContext);
+    mbedtls_ctr_drbg_free(&sCtrDrbgContext);
+}
+
+OT_TOOL_WEAK otError otPlatCryptoRandomGet(uint8_t *aBuffer, uint16_t aSize)
+{
+    return ot::Crypto::MbedTls::MapError(
+        mbedtls_ctr_drbg_random(&sCtrDrbgContext, static_cast<unsigned char *>(aBuffer), static_cast<size_t>(aSize)));
+}
+
 #endif // #if !OPENTHREAD_RADIO
+
+#endif // #if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_MBEDTLS
diff --git a/src/core/crypto/ecdsa.cpp b/src/core/crypto/ecdsa.cpp
index 373169b..b91e4e1 100644
--- a/src/core/crypto/ecdsa.cpp
+++ b/src/core/crypto/ecdsa.cpp
@@ -35,6 +35,8 @@
 
 #if OPENTHREAD_CONFIG_ECDSA_ENABLE
 
+#ifndef MBEDTLS_USE_TINYCRYPT
+
 #include <string.h>
 
 #include <mbedtls/ctr_drbg.h>
@@ -61,8 +63,7 @@
     ret = mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
     VerifyOrExit(ret == 0);
 
-    ret = mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, mbedtls_pk_ec(pk), mbedtls_ctr_drbg_random,
-                              Random::Crypto::MbedTlsContextGet());
+    ret = mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, mbedtls_pk_ec(pk), MbedTls::CryptoSecurePrng, nullptr);
     VerifyOrExit(ret == 0);
 
     ret = mbedtls_pk_write_key_der(&pk, mDerBytes, sizeof(mDerBytes));
@@ -87,8 +88,7 @@
 
     VerifyOrExit(mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)) == 0, error = kErrorFailed);
 #if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
-    VerifyOrExit(mbedtls_pk_parse_key(pk, mDerBytes, mDerLength, nullptr, 0, mbedtls_ctr_drbg_random,
-                                      Random::Crypto::MbedTlsContextGet()) == 0,
+    VerifyOrExit(mbedtls_pk_parse_key(pk, mDerBytes, mDerLength, nullptr, 0, MbedTls::CryptoSecurePrng, nullptr) == 0,
                  error = kErrorParse);
 #else
     VerifyOrExit(mbedtls_pk_parse_key(pk, mDerBytes, mDerLength, nullptr, 0) == 0, error = kErrorParse);
@@ -144,8 +144,7 @@
 
 #if (MBEDTLS_VERSION_NUMBER >= 0x02130000)
     ret = mbedtls_ecdsa_sign_det_ext(&ecdsa.MBEDTLS_PRIVATE(grp), &r, &s, &ecdsa.MBEDTLS_PRIVATE(d), aHash.GetBytes(),
-                                     Sha256::Hash::kSize, MBEDTLS_MD_SHA256, mbedtls_ctr_drbg_random,
-                                     Random::Crypto::MbedTlsContextGet());
+                                     Sha256::Hash::kSize, MBEDTLS_MD_SHA256, MbedTls::CryptoSecurePrng, nullptr);
 #else
     ret = mbedtls_ecdsa_sign_det(&ecdsa.MBEDTLS_PRIVATE(grp), &r, &s, &ecdsa.MBEDTLS_PRIVATE(d), aHash.GetBytes(),
                                  Sha256::Hash::kSize, MBEDTLS_MD_SHA256);
@@ -230,8 +229,8 @@
 
     // Parse a private key in PEM format.
 #if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
-    VerifyOrExit(mbedtls_pk_parse_key(&pkCtx, aPrivateKey, aPrivateKeyLength, nullptr, 0, mbedtls_ctr_drbg_random,
-                                      Random::Crypto::MbedTlsContextGet()) == 0,
+    VerifyOrExit(mbedtls_pk_parse_key(&pkCtx, aPrivateKey, aPrivateKeyLength, nullptr, 0, MbedTls::CryptoSecurePrng,
+                                      nullptr) == 0,
                  error = kErrorInvalidArgs);
 #else
     VerifyOrExit(mbedtls_pk_parse_key(&pkCtx, aPrivateKey, aPrivateKeyLength, nullptr, 0) == 0,
@@ -246,8 +245,7 @@
 
     // Sign using ECDSA.
     VerifyOrExit(mbedtls_ecdsa_sign(&ctx.MBEDTLS_PRIVATE(grp), &rMpi, &sMpi, &ctx.MBEDTLS_PRIVATE(d), aInputHash,
-                                    aInputHashLength, mbedtls_ctr_drbg_random,
-                                    Random::Crypto::MbedTlsContextGet()) == 0,
+                                    aInputHashLength, MbedTls::CryptoSecurePrng, nullptr) == 0,
                  error = kErrorFailed);
     VerifyOrExit(mbedtls_mpi_size(&rMpi) + mbedtls_mpi_size(&sMpi) <= aOutputLength, error = kErrorNoBufs);
 
@@ -272,4 +270,5 @@
 } // namespace Crypto
 } // namespace ot
 
+#endif // MBEDTLS_USE_TINYCRYPT
 #endif // OPENTHREAD_CONFIG_ECDSA_ENABLE
diff --git a/src/core/crypto/ecdsa.hpp b/src/core/crypto/ecdsa.hpp
index 7111363..98b439b 100644
--- a/src/core/crypto/ecdsa.hpp
+++ b/src/core/crypto/ecdsa.hpp
@@ -228,7 +228,7 @@
      *
      */
     OT_TOOL_PACKED_BEGIN
-    class PublicKey
+    class PublicKey : public Equatable<PublicKey>
     {
         friend class KeyPair;
 
@@ -265,12 +265,12 @@
 /**
  * This function creates an ECDSA signature.
  *
- * @param[out]    aOutput            An output buffer where ECDSA sign should be stored.
- * @param[inout]  aOutputLength      The length of the @p aOutput buffer.
- * @param[in]     aInputHash         An input hash.
- * @param[in]     aInputHashLength   The length of the @p aInputHash buffer.
- * @param[in]     aPrivateKey        A private key in PEM format.
- * @param[in]     aPrivateKeyLength  The length of the @p aPrivateKey buffer.
+ * @param[out]     aOutput            An output buffer where ECDSA sign should be stored.
+ * @param[in,out]  aOutputLength      The length of the @p aOutput buffer.
+ * @param[in]      aInputHash         An input hash.
+ * @param[in]      aInputHashLength   The length of the @p aInputHash buffer.
+ * @param[in]      aPrivateKey        A private key in PEM format.
+ * @param[in]      aPrivateKeyLength  The length of the @p aPrivateKey buffer.
  *
  * @retval  kErrorNone         ECDSA sign has been created successfully.
  * @retval  kErrorNoBufs       Output buffer is too small.
diff --git a/src/core/crypto/ecdsa_tinycrypt.cpp b/src/core/crypto/ecdsa_tinycrypt.cpp
new file mode 100644
index 0000000..ea75a2d
--- /dev/null
+++ b/src/core/crypto/ecdsa_tinycrypt.cpp
@@ -0,0 +1,211 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file implements ECDSA signing using TinyCrypt library.
+ */
+
+#include "ecdsa.hpp"
+
+#if OPENTHREAD_CONFIG_ECDSA_ENABLE
+
+#ifdef MBEDTLS_USE_TINYCRYPT
+
+#include <string.h>
+
+#include <mbedtls/pk.h>
+#include <mbedtls/version.h>
+
+#include <tinycrypt/ecc.h>
+#include <tinycrypt/ecc_dh.h>
+#include <tinycrypt/ecc_dsa.h>
+
+#include "common/code_utils.hpp"
+#include "common/debug.hpp"
+#include "common/random.hpp"
+#include "crypto/mbedtls.hpp"
+
+namespace ot {
+namespace Crypto {
+namespace Ecdsa {
+
+Error P256::KeyPair::Generate(void)
+{
+    mbedtls_pk_context    pk;
+    mbedtls_uecc_keypair *keypair;
+    int                   ret;
+
+    mbedtls_pk_init(&pk);
+
+    ret = mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
+    VerifyOrExit(ret == 0);
+
+    keypair = mbedtls_pk_uecc(pk);
+
+    ret = uECC_make_key(keypair->public_key, keypair->private_key);
+    VerifyOrExit(ret == UECC_SUCCESS);
+
+    ret = mbedtls_pk_write_key_der(&pk, mDerBytes, sizeof(mDerBytes));
+    VerifyOrExit(ret > 0);
+
+    mDerLength = static_cast<uint8_t>(ret);
+
+    memmove(mDerBytes, mDerBytes + sizeof(mDerBytes) - mDerLength, mDerLength);
+
+exit:
+    mbedtls_pk_free(&pk);
+
+    return (ret >= 0) ? kErrorNone : MbedTls::MapError(ret);
+}
+
+Error P256::KeyPair::Parse(void *aContext) const
+{
+    Error               error = kErrorNone;
+    mbedtls_pk_context *pk    = reinterpret_cast<mbedtls_pk_context *>(aContext);
+
+    mbedtls_pk_init(pk);
+
+    VerifyOrExit(mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)) == 0, error = kErrorFailed);
+#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
+    VerifyOrExit(mbedtls_pk_parse_key(pk, mDerBytes, mDerLength, nullptr, 0, MbedTls::CryptoSecurePrng, nullptr) == 0,
+                 error = kErrorParse);
+#else
+    VerifyOrExit(mbedtls_pk_parse_key(pk, mDerBytes, mDerLength, nullptr, 0) == 0, error = kErrorParse);
+#endif
+
+exit:
+    return error;
+}
+
+Error P256::KeyPair::GetPublicKey(PublicKey &aPublicKey) const
+{
+    Error                 error;
+    mbedtls_pk_context    pk;
+    mbedtls_uecc_keypair *keyPair;
+    int                   ret;
+
+    SuccessOrExit(error = Parse(&pk));
+
+    keyPair = mbedtls_pk_uecc(pk);
+
+    memcpy(aPublicKey.mData, keyPair->public_key, kMpiSize);
+    memcpy(aPublicKey.mData + kMpiSize, keyPair->public_key + kMpiSize, kMpiSize);
+
+exit:
+    mbedtls_pk_free(&pk);
+
+    return error;
+}
+
+Error P256::KeyPair::Sign(const Sha256::Hash &aHash, Signature &aSignature) const
+{
+    Error                 error;
+    mbedtls_pk_context    pk;
+    mbedtls_uecc_keypair *keypair;
+    int                   ret;
+    uint8_t               sig[2 * kMpiSize];
+
+    SuccessOrExit(error = Parse(&pk));
+
+    keypair = mbedtls_pk_uecc(pk);
+
+    ret = uECC_sign(keypair->private_key, aHash.GetBytes(), Sha256::Hash::kSize, sig);
+    VerifyOrExit(ret == UECC_SUCCESS, error = MbedTls::MapError(ret));
+
+    memcpy(aSignature.mShared.mMpis.mR, sig, kMpiSize);
+    memcpy(aSignature.mShared.mMpis.mS, sig + kMpiSize, kMpiSize);
+
+exit:
+    mbedtls_pk_free(&pk);
+
+    return error;
+}
+
+Error P256::PublicKey::Verify(const Sha256::Hash &aHash, const Signature &aSignature) const
+{
+    Error   error = kErrorNone;
+    int     ret;
+    uint8_t public_key[2 * kMpiSize];
+    uint8_t sig[2 * kMpiSize];
+
+    memcpy(public_key, GetBytes(), 2 * kMpiSize);
+
+    memcpy(sig, aSignature.mShared.mMpis.mR, kMpiSize);
+    memcpy(sig + kMpiSize, aSignature.mShared.mMpis.mS, kMpiSize);
+
+    ret = uECC_verify(public_key, aHash.GetBytes(), Sha256::Hash::kSize, sig);
+    VerifyOrExit(ret == UECC_SUCCESS, error = kErrorSecurity);
+
+exit:
+    return error;
+}
+
+Error Sign(uint8_t *      aOutput,
+           uint16_t &     aOutputLength,
+           const uint8_t *aInputHash,
+           uint16_t       aInputHashLength,
+           const uint8_t *aPrivateKey,
+           uint16_t       aPrivateKeyLength)
+{
+    Error                 error = kErrorNone;
+    mbedtls_pk_context    pkCtx;
+    mbedtls_uecc_keypair *keypair;
+    uint8_t               sig[2 * NUM_ECC_BYTES];
+
+    mbedtls_pk_init(&pkCtx);
+
+    // Parse a private key in PEM format.
+    VerifyOrExit(mbedtls_pk_parse_key(&pkCtx, aPrivateKey, aPrivateKeyLength, nullptr, 0) == 0,
+                 error = kErrorInvalidArgs);
+    VerifyOrExit(mbedtls_pk_get_type(&pkCtx) == MBEDTLS_PK_ECKEY, error = kErrorInvalidArgs);
+
+    keypair = mbedtls_pk_uecc(pkCtx);
+    OT_ASSERT(keypair != nullptr);
+
+    // Sign using ECDSA.
+    VerifyOrExit(uECC_sign(keypair->private_key, aInputHash, aInputHashLength, sig) == UECC_SUCCESS,
+                 error = kErrorFailed);
+    VerifyOrExit(2 * NUM_ECC_BYTES <= aOutputLength, error = kErrorNoBufs);
+
+    // Concatenate the two octet sequences in the order R and then S.
+    memcpy(aOutput, sig, 2 * NUM_ECC_BYTES);
+    aOutputLength = 2 * NUM_ECC_BYTES;
+
+exit:
+    mbedtls_pk_free(&pkCtx);
+
+    return error;
+}
+
+} // namespace Ecdsa
+} // namespace Crypto
+} // namespace ot
+
+#endif // MBEDTLS_USE_TINYCRYPT
+#endif // OPENTHREAD_CONFIG_ECDSA_ENABLE
diff --git a/src/core/crypto/mbedtls.cpp b/src/core/crypto/mbedtls.cpp
index 7be4d0d..f8c1c53 100644
--- a/src/core/crypto/mbedtls.cpp
+++ b/src/core/crypto/mbedtls.cpp
@@ -43,8 +43,10 @@
 #include <mbedtls/pem.h>
 #endif
 
+#include "common/code_utils.hpp"
 #include "common/error.hpp"
-#include "common/instance.hpp"
+#include "common/heap.hpp"
+#include "common/random.hpp"
 
 namespace ot {
 namespace Crypto {
@@ -56,7 +58,7 @@
     // mbedTLS's debug level is almost the same as OpenThread's
     mbedtls_debug_set_threshold(OPENTHREAD_CONFIG_LOG_LEVEL);
 #endif
-    mbedtls_platform_set_calloc_free(Instance::HeapCAlloc, Instance::HeapFree);
+    mbedtls_platform_set_calloc_free(Heap::CAlloc, Heap::Free);
 #endif // OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS_MANAGEMENT
 }
 
@@ -168,5 +170,16 @@
     return error;
 }
 
+#if !OPENTHREAD_RADIO
+
+int MbedTls::CryptoSecurePrng(void *, unsigned char *aBuffer, size_t aSize)
+{
+    IgnoreError(ot::Random::Crypto::FillBuffer(aBuffer, static_cast<uint16_t>(aSize)));
+
+    return 0;
+}
+
+#endif // !OPENTHREAD_RADIO
+
 } // namespace Crypto
 } // namespace ot
diff --git a/src/core/crypto/mbedtls.hpp b/src/core/crypto/mbedtls.hpp
index 2be5cfc..a5fd869 100644
--- a/src/core/crypto/mbedtls.hpp
+++ b/src/core/crypto/mbedtls.hpp
@@ -89,6 +89,20 @@
      *
      */
     static Error MapError(int aMbedTlsError);
+
+#if !OPENTHREAD_RADIO
+    /**
+     * This function fills a given buffer with cryptographically secure random bytes.
+     *
+     * @param[in]  aContext A pointer to arbitrary context.
+     * @param[out] aBuffer  A pointer to a buffer to fill with the random bytes.
+     * @param[in]  aSize    Size of buffer (number of bytes to fill).
+     *
+     * @retval kErrorNone   Successfully filled buffer with random values.
+     *
+     */
+    static int CryptoSecurePrng(void *aContext, unsigned char *aBuffer, size_t aSize);
+#endif
 };
 
 /**
diff --git a/src/core/crypto/sha256.hpp b/src/core/crypto/sha256.hpp
index 99027d2..f895c8e 100644
--- a/src/core/crypto/sha256.hpp
+++ b/src/core/crypto/sha256.hpp
@@ -41,6 +41,7 @@
 #include <openthread/crypto.h>
 #include <openthread/platform/crypto.h>
 
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/code_utils.hpp"
 #include "common/equatable.hpp"
@@ -155,6 +156,9 @@
  */
 
 } // namespace Crypto
+
+DefineCoreType(otCryptoSha256Hash, Crypto::Sha256::Hash);
+
 } // namespace ot
 
 #endif // SHA256_HPP_
diff --git a/src/core/crypto/storage.hpp b/src/core/crypto/storage.hpp
index bb08f78..725ab27 100644
--- a/src/core/crypto/storage.hpp
+++ b/src/core/crypto/storage.hpp
@@ -38,6 +38,7 @@
 
 #include <openthread/platform/crypto.h>
 
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/code_utils.hpp"
 #include "common/error.hpp"
@@ -94,7 +95,13 @@
  */
 typedef otCryptoKeyRef KeyRef;
 
-constexpr KeyRef kInvalidKeyRef = 0x80000000; ///< Invalid `KeyRef` value (PSA_KEY_ID_VENDOR_MAX + 1).
+constexpr KeyRef kInvalidKeyRef               = 0x80000000; ///< Invalid `KeyRef` value (PSA_KEY_ID_VENDOR_MAX + 1).
+constexpr KeyRef kNetworkKeyRef               = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 1;
+constexpr KeyRef kPskcRef                     = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 2;
+constexpr KeyRef kActiveDatasetNetworkKeyRef  = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 3;
+constexpr KeyRef kActiveDatasetPskcRef        = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 4;
+constexpr KeyRef kPendingDatasetNetworkKeyRef = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 5;
+constexpr KeyRef kPendingDatasetPskcRef       = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 6;
 
 /**
  * Determine if a given `KeyRef` is valid or not.
@@ -113,17 +120,17 @@
 /**
  * Import a key into PSA ITS.
  *
- * @param[inout] aKeyRef           Reference to the key ref to be used for crypto operations.
- * @param[in]    aKeyType          Key Type encoding for the key.
- * @param[in]    aKeyAlgorithm     Key algorithm encoding for the key.
- * @param[in]    aKeyUsage         Key Usage encoding for the key.
- * @param[in]    aStorageType      Key storage type.
- * @param[in]    aKey              Actual key to be imported.
- * @param[in]    aKeyLen           Length of the key to be imported.
+ * @param[in,out] aKeyRef          Reference to the key ref to be used for crypto operations.
+ * @param[in]     aKeyType         Key Type encoding for the key.
+ * @param[in]     aKeyAlgorithm    Key algorithm encoding for the key.
+ * @param[in]     aKeyUsage        Key Usage encoding for the key.
+ * @param[in]     aStorageType     Key storage type.
+ * @param[in]     aKey             Actual key to be imported.
+ * @param[in]     aKeyLen          Length of the key to be imported.
  *
  * @retval kErrorNone          Successfully imported the key.
  * @retval kErrorFailed        Failed to import the key.
- * @retval kErrorInvalidArgs   @p aKey was set to nullptr.
+ * @retval kErrorInvalidArgs   @p aKey was set to `nullptr`.
  *
  */
 inline Error ImportKey(KeyRef &       aKeyRef,
@@ -149,7 +156,7 @@
  *
  * @retval kErrorNone          Successfully exported  @p aKeyRef.
  * @retval kErrorFailed        Failed to export @p aKeyRef.
- * @retval kErrorInvalidArgs   @p aBuffer was nullptr.
+ * @retval kErrorInvalidArgs   @p aBuffer was `nullptr`.
  *
  */
 inline Error ExportKey(KeyRef aKeyRef, uint8_t *aBuffer, size_t aBufferLen, size_t &aKeyLen)
@@ -273,9 +280,9 @@
      *
      * This method MUST be used when `IsKeyRef()` returns `true`.
      *
-     * @param[out]    aKeyBuffer  Pointer to a byte array buffer to place the extracted key.
-     * @param[inout]  aKeyLength  On input, the size of @p aKeyBuffer.
-     *                            On exit, returns the key length (number of bytes written in @p aKeyBuffer).
+     * @param[out]     aKeyBuffer  Pointer to a byte array buffer to place the extracted key.
+     * @param[in,out]  aKeyLength  On input, the size of @p aKeyBuffer.
+     *                             On exit, returns the key length (number of bytes written in @p aKeyBuffer).
      *
      * @retval kErrorNone    Successfully extracted the key, @p aKeyBuffer and @p aKeyLength are updated.
      * @retval kErrorNoBufs  Key does not fit in @p aKeyBuffer (extracted key length is larger than @p aKeyLength).
@@ -330,6 +337,9 @@
 };
 
 } // namespace Crypto
+
+DefineCoreType(otCryptoKey, Crypto::Key);
+
 } // namespace ot
 
 #endif // STORAGE_HPP_
diff --git a/src/core/diags/README.md b/src/core/diags/README.md
index ba2a9ec..090aa03 100644
--- a/src/core/diags/README.md
+++ b/src/core/diags/README.md
@@ -171,3 +171,63 @@
 stop diagnostics mode
 status 0x00
 ```
+
+### diag rcp
+
+RCP-related diagnostics commands. These commands are used for debugging and testing only.
+
+#### diag rcp start
+
+Start RCP diagnostics mode.
+
+```bash
+> diag rcp start
+Done
+```
+
+#### diag rcp stop
+
+Stop RCP diagnostics mode.
+
+```bash
+> diag rcp stop
+Done
+```
+
+#### diag rcp channel \<channel\>
+
+Set the RCP IEEE 802.15.4 Channel value for diagnostics module.
+
+```bash
+> diag rcp channel 11
+Done
+```
+
+#### diag rcp power \<power\>
+
+Set the RCP tx power value(dBm) for diagnostics module.
+
+```bash
+> diag rcp power 0
+Done
+```
+
+#### diag rcp echo \<message\>
+
+RCP echoes the given message.
+
+```bash
+> diag rcp echo 0123456789
+0123456789
+Done
+```
+
+#### diag rcp echo -n \<number\>
+
+RCP echoes the message with the given number of bytes.
+
+```bash
+> diag rcp echo -n 20
+01234567890123456789
+Done
+```
diff --git a/src/core/diags/factory_diags.cpp b/src/core/diags/factory_diags.cpp
index 0612494..6410421 100644
--- a/src/core/diags/factory_diags.cpp
+++ b/src/core/diags/factory_diags.cpp
@@ -70,10 +70,8 @@
 #if OPENTHREAD_RADIO && !OPENTHREAD_RADIO_CLI
 
 const struct Diags::Command Diags::sCommands[] = {
-    {"channel", &Diags::ProcessChannel},
-    {"power", &Diags::ProcessPower},
-    {"start", &Diags::ProcessStart},
-    {"stop", &Diags::ProcessStop},
+    {"channel", &Diags::ProcessChannel}, {"echo", &Diags::ProcessEcho}, {"power", &Diags::ProcessPower},
+    {"start", &Diags::ProcessStart},     {"stop", &Diags::ProcessStop},
 };
 
 Diags::Diags(Instance &aInstance)
@@ -114,6 +112,43 @@
     return error;
 }
 
+Error Diags::ProcessEcho(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
+{
+    Error error = kErrorNone;
+
+    if (aArgsLength == 1)
+    {
+        snprintf(aOutput, aOutputMaxLen, "%s\r\n", aArgs[0]);
+    }
+    else if ((aArgsLength == 2) && (strcmp(aArgs[0], "-n") == 0))
+    {
+        const uint8_t kReservedLen = 3; // 1 byte '\r', 1 byte '\n' and 1 byte '\0'
+        uint32_t      outputMaxLen = static_cast<uint32_t>(aOutputMaxLen) - kReservedLen;
+        long          value;
+        uint32_t      i;
+        uint32_t      number;
+
+        SuccessOrExit(error = ParseLong(aArgs[1], value));
+        number = static_cast<uint32_t>(value);
+        number = (number < outputMaxLen) ? number : outputMaxLen;
+
+        for (i = 0; i < number; i++)
+        {
+            aOutput[i] = '0' + i % 10;
+        }
+
+        snprintf(&aOutput[i], aOutputMaxLen - i, "\r\n");
+    }
+    else
+    {
+        error = kErrorInvalidArgs;
+    }
+
+exit:
+    AppendErrorResult(error, aOutput, aOutputMaxLen);
+    return error;
+}
+
 Error Diags::ProcessStart(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
 {
     OT_UNUSED_VARIABLE(aArgsLength);
@@ -160,6 +195,7 @@
     , mTxPower(0)
     , mTxLen(0)
     , mRepeatActive(false)
+    , mDiagSendOn(false)
 {
     mStats.Clear();
 }
@@ -378,6 +414,7 @@
         mTxPacket->mPsdu[i] = i;
     }
 
+    mDiagSendOn = true;
     IgnoreError(Get<Radio>().Transmit(*static_cast<Mac::TxFrame *>(mTxPacket)));
 }
 
@@ -480,6 +517,9 @@
 
 void Diags::TransmitDone(Error aError)
 {
+    VerifyOrExit(mDiagSendOn);
+    mDiagSendOn = false;
+
     if (aError == kErrorNone)
     {
         mStats.mSentPackets++;
diff --git a/src/core/diags/factory_diags.hpp b/src/core/diags/factory_diags.hpp
index 7081bff..26ccd9e 100644
--- a/src/core/diags/factory_diags.hpp
+++ b/src/core/diags/factory_diags.hpp
@@ -103,7 +103,7 @@
     /**
      * The radio driver calls this method to notify OpenThread diagnostics module of a received frame.
      *
-     * @param[in]  aFrame  A pointer to the received frame or nullptr if the receive operation failed.
+     * @param[in]  aFrame  A pointer to the received frame or `nullptr` if the receive operation failed.
      * @param[in]  aError  kErrorNone when successfully received a frame,
      *                     kErrorAbort when reception was aborted and a frame was not received,
      *                     kErrorNoBufs when a frame could not be received due to lack of rx buffer space.
@@ -151,6 +151,9 @@
     Error ProcessStart(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
     Error ProcessStats(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
     Error ProcessStop(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
+#if OPENTHREAD_RADIO && !OPENTHREAD_RADIO_CLI
+    Error ProcessEcho(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
+#endif
 
     void TransmitPacket(void);
 
@@ -169,6 +172,7 @@
     int8_t        mTxPower;
     uint8_t       mTxLen;
     bool          mRepeatActive;
+    bool          mDiagSendOn;
 #endif
 };
 
diff --git a/src/core/ftd.cmake b/src/core/ftd.cmake
index e0c692b..0100a1f 100644
--- a/src/core/ftd.cmake
+++ b/src/core/ftd.cmake
@@ -43,6 +43,9 @@
 target_link_libraries(openthread-ftd
     PRIVATE
         ${OT_MBEDTLS}
-        tcplp
         ot-config
 )
+
+if(NOT OT_EXCLUDE_TCPLP_LIB)
+    target_link_libraries(openthread-ftd PRIVATE tcplp)
+endif()
diff --git a/src/core/mac/channel_mask.hpp b/src/core/mac/channel_mask.hpp
index e92eca1..200ab5b 100644
--- a/src/core/mac/channel_mask.hpp
+++ b/src/core/mac/channel_mask.hpp
@@ -200,7 +200,7 @@
      * This method can be used to iterate over all channels in the channel mask. To get the first channel (channel with
      * lowest number) in the mask the @p aChannel should be set to `kChannelIteratorFirst`.
      *
-     * @param[inout] aChannel        A reference to a `uint8_t`.
+     * @param[in,out] aChannel       A reference to a `uint8_t`.
      *                               On entry it should contain the previous channel or `kChannelIteratorFirst`.
      *                               On exit it contains the next channel.
      *
diff --git a/src/core/mac/data_poll_handler.cpp b/src/core/mac/data_poll_handler.cpp
index 8703ab0..c1d78e3 100644
--- a/src/core/mac/data_poll_handler.cpp
+++ b/src/core/mac/data_poll_handler.cpp
@@ -38,10 +38,12 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 
 namespace ot {
 
+RegisterLogModule("DataPollHandlr");
+
 DataPollHandler::Callbacks::Callbacks(Instance &aInstance)
     : InstanceLocator(aInstance)
 {
@@ -144,8 +146,8 @@
 
     indirectMsgCount = child->GetIndirectMessageCount();
 
-    otLogInfoMac("Rx data poll, src:0x%04x, qed_msgs:%d, rss:%d, ack-fp:%d", child->GetRloc16(), indirectMsgCount,
-                 aFrame.GetRssi(), aFrame.IsAckedWithFramePending());
+    LogInfo("Rx data poll, src:0x%04x, qed_msgs:%d, rss:%d, ack-fp:%d", child->GetRloc16(), indirectMsgCount,
+            aFrame.GetRssi(), aFrame.IsAckedWithFramePending());
 
     if (!aFrame.IsAckedWithFramePending())
     {
@@ -245,8 +247,8 @@
         OT_ASSERT(!aFrame.GetSecurityEnabled() || aFrame.IsHeaderUpdated());
 
         aChild.IncrementIndirectTxAttempts();
-        otLogInfoMac("Indirect tx to child %04x failed, attempt %d/%d", aChild.GetRloc16(),
-                     aChild.GetIndirectTxAttempts(), kMaxPollTriggeredTxAttempts);
+        LogInfo("Indirect tx to child %04x failed, attempt %d/%d", aChild.GetRloc16(), aChild.GetIndirectTxAttempts(),
+                kMaxPollTriggeredTxAttempts);
 
         OT_FALL_THROUGH;
 
diff --git a/src/core/mac/data_poll_handler.hpp b/src/core/mac/data_poll_handler.hpp
index 29e9f23..37532c4 100644
--- a/src/core/mac/data_poll_handler.hpp
+++ b/src/core/mac/data_poll_handler.hpp
@@ -278,7 +278,7 @@
 
     // In the current implementation of `DataPollHandler`, we can have a
     // single indirect tx operation active at MAC layer at each point of
-    // time. `mIndirectTxChild` indicates the child being handled (nullptr
+    // time. `mIndirectTxChild` indicates the child being handled (`nullptr`
     // indicates no active indirect tx). `mFrameContext` tracks the
     // context for the prepared frame for the current indirect tx.
 
diff --git a/src/core/mac/data_poll_sender.cpp b/src/core/mac/data_poll_sender.cpp
index 512d50a..2c5b089 100644
--- a/src/core/mac/data_poll_sender.cpp
+++ b/src/core/mac/data_poll_sender.cpp
@@ -36,7 +36,7 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/message.hpp"
 #include "net/ip6.hpp"
 #include "net/netif.hpp"
@@ -46,6 +46,8 @@
 
 namespace ot {
 
+RegisterLogModule("DataPollSender");
+
 DataPollSender::DataPollSender(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mTimerStartTime(0)
@@ -112,22 +114,17 @@
     switch (error)
     {
     case kErrorNone:
-        otLogDebgMac("Sending data poll");
+        LogDebg("Sending data poll");
         ScheduleNextPoll(kUsePreviousPollPeriod);
         break;
 
     case kErrorInvalidState:
-        otLogWarnMac("Data poll tx requested while data polling was not enabled!");
+        LogWarn("Data poll tx requested while data polling was not enabled!");
         StopPolling();
         break;
 
-    case kErrorAlready:
-        otLogDebgMac("Data poll tx requested when a previous data request still in send queue.");
-        ScheduleNextPoll(kUsePreviousPollPeriod);
-        break;
-
     default:
-        otLogWarnMac("Unexpected error %s requesting data poll", ErrorToString(error));
+        LogWarn("Unexpected error %s requesting data poll", ErrorToString(error));
         ScheduleNextPoll(kRecalculatePollPeriod);
         break;
     }
@@ -216,7 +213,7 @@
     if (!aFrame.IsEmpty())
     {
         IgnoreError(aFrame.GetDstAddr(macDest));
-        Get<MeshForwarder>().UpdateNeighborOnSentFrame(aFrame, aError, macDest);
+        Get<MeshForwarder>().UpdateNeighborOnSentFrame(aFrame, aError, macDest, /* aIsDataPoll */ true);
     }
 
     if (GetParent().IsStateInvalid())
@@ -259,8 +256,14 @@
     default:
         mPollTxFailureCounter++;
 
-        otLogInfoMac("Failed to send data poll, error:%s, retx:%d/%d", ErrorToString(aError), mPollTxFailureCounter,
-                     kMaxPollRetxAttempts);
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+        LogInfo("Failed to send data poll, error:%s, retx:%d/%d", ErrorToString(aError), mPollTxFailureCounter,
+                (aFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) != nullptr) ? kMaxCslPollRetxAttempts
+                                                                         : kMaxPollRetxAttempts);
+#else
+        LogInfo("Failed to send data poll, error:%s, retx:%d/%d", ErrorToString(aError), mPollTxFailureCounter,
+                kMaxPollRetxAttempts);
+#endif
 
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
         if (mPollTxFailureCounter <
@@ -304,7 +307,7 @@
 
     mPollTimeoutCounter++;
 
-    otLogInfoMac("Data poll timeout, retry:%d/%d", mPollTimeoutCounter, kQuickPollsAfterTimeout);
+    LogInfo("Data poll timeout, retry:%d/%d", mPollTimeoutCounter, kQuickPollsAfterTimeout);
 
     if (mPollTimeoutCounter < kQuickPollsAfterTimeout)
     {
@@ -542,7 +545,8 @@
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE && OPENTHREAD_CONFIG_MAC_CSL_AUTO_SYNC_ENABLE
     if (Get<Mac::Mac>().IsCslEnabled())
     {
-        period = OT_MIN(period, Time::SecToMsec(Get<Mle::MleRouter>().GetCslTimeout()));
+        period    = OT_MIN(period, Time::SecToMsec(Get<Mle::MleRouter>().GetCslTimeout()));
+        pollAhead = static_cast<uint32_t>(kRetxPollPeriod);
     }
 #endif
 
diff --git a/src/core/mac/data_poll_sender.hpp b/src/core/mac/data_poll_sender.hpp
index e66657b..a30f563 100644
--- a/src/core/mac/data_poll_sender.hpp
+++ b/src/core/mac/data_poll_sender.hpp
@@ -163,7 +163,7 @@
      * This method informs the data poll sender to process a transmitted MAC frame.
      *
      * @param[in]  aFrame      A reference to the frame that was transmitted.
-     * @param[in]  aAckFrame   A pointer to the ACK frame, nullptr if no ACK was received.
+     * @param[in]  aAckFrame   A pointer to the ACK frame, `nullptr` if no ACK was received.
      * @param[in]  aError      kErrorNone when the frame was transmitted successfully,
      *                         kErrorNoAck when the frame was transmitted but no ACK was received,
      *                         kErrorChannelAccessFailure when the tx failed due to activity on the channel,
@@ -271,7 +271,7 @@
     static constexpr uint32_t kRetxPollPeriod       = OPENTHREAD_CONFIG_MAC_RETX_POLL_PERIOD;
     static constexpr uint32_t kFastPollPeriod       = 188;
     static constexpr uint32_t kMinPollPeriod        = OPENTHREAD_CONFIG_MAC_MINIMUM_POLL_PERIOD;
-    static constexpr uint32_t kMaxExternalPeriod    = ((1 << 26) - 1); //< ~18.6 hours.
+    static constexpr uint32_t kMaxExternalPeriod    = ((1 << 26) - 1); // ~18.6 hours.
 
     void            ScheduleNextPoll(PollPeriodSelector aPollPeriodSelector);
     uint32_t        CalculatePollPeriod(void) const;
@@ -285,17 +285,17 @@
 
     TimeMilli mTimerStartTime;
     uint32_t  mPollPeriod;
-    uint32_t  mExternalPollPeriod : 26; //< In milliseconds.
-    uint8_t   mFastPollsUsers : 6;      //< Number of callers which request fast polls.
+    uint32_t  mExternalPollPeriod : 26; // In milliseconds.
+    uint8_t   mFastPollsUsers : 6;      // Number of callers which request fast polls.
 
     TimerMilli mTimer;
 
-    bool    mEnabled : 1;              //< Indicates whether data polling is enabled/started.
-    bool    mAttachMode : 1;           //< Indicates whether in attach mode (to use attach poll period).
-    bool    mRetxMode : 1;             //< Indicates whether last poll tx failed at mac/radio layer (poll retx mode).
-    uint8_t mPollTimeoutCounter : 4;   //< Poll timeouts counter (0 to `kQuickPollsAfterTimout`).
-    uint8_t mPollTxFailureCounter : 4; //< Poll tx failure counter (0 to `kMaxPollRetxAttempts`).
-    uint8_t mRemainingFastPolls : 4;   //< Number of remaining fast polls when in transient fast polling mode.
+    bool    mEnabled : 1;              // Indicates whether data polling is enabled/started.
+    bool    mAttachMode : 1;           // Indicates whether in attach mode (to use attach poll period).
+    bool    mRetxMode : 1;             // Indicates whether last poll tx failed at mac/radio layer (poll retx mode).
+    uint8_t mPollTimeoutCounter : 4;   // Poll timeouts counter (0 to `kQuickPollsAfterTimout`).
+    uint8_t mPollTxFailureCounter : 4; // Poll tx failure counter (0 to `kMaxPollRetxAttempts`).
+    uint8_t mRemainingFastPolls : 4;   // Number of remaining fast polls when in transient fast polling mode.
 };
 
 /**
diff --git a/src/core/mac/link_raw.cpp b/src/core/mac/link_raw.cpp
index 155708f..bbce9f2 100644
--- a/src/core/mac/link_raw.cpp
+++ b/src/core/mac/link_raw.cpp
@@ -42,13 +42,15 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/random.hpp"
 #include "mac/mac_frame.hpp"
 
 namespace ot {
 namespace Mac {
 
+RegisterLogModule("LinkRaw");
+
 LinkRaw::LinkRaw(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mReceiveChannel(OPENTHREAD_CONFIG_DEFAULT_CHANNEL)
@@ -84,7 +86,7 @@
     Error error  = kErrorNone;
     bool  enable = aCallback != nullptr;
 
-    otLogDebgMac("LinkRaw::Enabled(%s)", (enable ? "true" : "false"));
+    LogDebg("Enabled(%s)", (enable ? "true" : "false"));
 
 #if OPENTHREAD_MTD || OPENTHREAD_FTD
     VerifyOrExit(!Get<ThreadNetif>().IsUp(), error = kErrorInvalidState);
@@ -179,8 +181,7 @@
 
 void LinkRaw::InvokeReceiveDone(RxFrame *aFrame, Error aError)
 {
-    otLogDebgMac("LinkRaw::ReceiveDone(%d bytes), error:%s", (aFrame != nullptr) ? aFrame->mLength : 0,
-                 ErrorToString(aError));
+    LogDebg("ReceiveDone(%d bytes), error:%s", (aFrame != nullptr) ? aFrame->mLength : 0, ErrorToString(aError));
 
     if (mReceiveDoneCallback && (aError == kErrorNone))
     {
@@ -203,7 +204,7 @@
 
 void LinkRaw::InvokeTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError)
 {
-    otLogDebgMac("LinkRaw::TransmitDone(%d bytes), error:%s", aFrame.mLength, ErrorToString(aError));
+    LogDebg("TransmitDone(%d bytes), error:%s", aFrame.mLength, ErrorToString(aError));
 
     if (mTransmitDoneCallback)
     {
@@ -270,7 +271,7 @@
 
 // LCOV_EXCL_START
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
 void LinkRaw::RecordFrameTransmitStatus(const TxFrame &aFrame,
                                         const RxFrame *aAckFrame,
@@ -283,8 +284,8 @@
 
     if (aError != kErrorNone)
     {
-        otLogInfoMac("Frame tx failed, error:%s, retries:%d/%d, %s", ErrorToString(aError), aRetryCount,
-                     aFrame.GetMaxFrameRetries(), aFrame.ToInfoString().AsCString());
+        LogInfo("Frame tx failed, error:%s, retries:%d/%d, %s", ErrorToString(aError), aRetryCount,
+                aFrame.GetMaxFrameRetries(), aFrame.ToInfoString().AsCString());
     }
 }
 
diff --git a/src/core/mac/link_raw.hpp b/src/core/mac/link_raw.hpp
index 2018bb9..e0a66c9 100644
--- a/src/core/mac/link_raw.hpp
+++ b/src/core/mac/link_raw.hpp
@@ -41,6 +41,7 @@
 #include <openthread/link_raw.h>
 
 #include "common/locator.hpp"
+#include "common/log.hpp"
 #include "common/non_copyable.hpp"
 #include "mac/mac_frame.hpp"
 #include "mac/sub_mac.hpp"
@@ -82,7 +83,7 @@
     /**
      * This method enables/disables the raw link-layer.
      *
-     * @param[in]  aCallback  A pointer to a function called on receipt of a IEEE 802.15.4 frame, nullptr to disable
+     * @param[in]  aCallback  A pointer to a function called on receipt of a IEEE 802.15.4 frame, `nullptr` to disable
      *                        raw link-layer.
      *
      *
@@ -113,7 +114,7 @@
     /**
      * This method invokes the mReceiveDoneCallback, if set.
      *
-     * @param[in]  aFrame    A pointer to the received frame or nullptr if the receive operation failed.
+     * @param[in]  aFrame    A pointer to the received frame or `nullptr` if the receive operation failed.
      * @param[in]  aError    kErrorNone when successfully received a frame,
      *                       kErrorAbort when reception was aborted and a frame was not received,
      *                       kErrorNoBufs when a frame could not be received due to lack of rx buffer space.
@@ -146,7 +147,7 @@
      * This method invokes the mTransmitDoneCallback, if set.
      *
      * @param[in]  aFrame     The transmitted frame.
-     * @param[in]  aAckFrame  A pointer to the ACK frame, nullptr if no ACK was received.
+     * @param[in]  aAckFrame  A pointer to the ACK frame, `nullptr` if no ACK was received.
      * @param[in]  aError     kErrorNone when the frame was transmitted,
      *                        kErrorNoAck when the frame was transmitted but no ACK was received,
      *                        kErrorChannelAccessFailure tx failed due to activity on the channel,
@@ -163,6 +164,7 @@
      * @param[in]  aCallback        A pointer to a function called on completion of a scanned channel.
      *
      * @retval kErrorNone            Successfully started scanning the channel.
+     * @retval kErrorBusy            The radio is performing energy scanning.
      * @retval kErrorNotImplemented  The radio doesn't support energy scanning.
      * @retval kErrorInvalidState    If the raw link-layer isn't enabled.
      *
@@ -277,6 +279,7 @@
      */
     Error SetMacFrameCounter(uint32_t aMacFrameCounter);
 
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
     /**
      * This method records the status of a frame transmission attempt and is mainly used for logging failures.
      *
@@ -284,7 +287,7 @@
      * of a frame transmission request, this method is invoked on all frame transmission attempts.
      *
      * @param[in] aFrame      The transmitted frame.
-     * @param[in] aAckFrame   A pointer to the ACK frame, or nullptr if no ACK was received.
+     * @param[in] aAckFrame   A pointer to the ACK frame, or `nullptr` if no ACK was received.
      * @param[in] aError      kErrorNone when the frame was transmitted successfully,
      *                        kErrorNoAck when the frame was transmitted but no ACK was received,
      *                        kErrorChannelAccessFailure tx failed due to activity on the channel,
@@ -294,7 +297,6 @@
      *                        when there was an error in transmission (i.e., `aError` is not NONE).
      *
      */
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
     void RecordFrameTransmitStatus(const TxFrame &aFrame,
                                    const RxFrame *aAckFrame,
                                    Error          aError,
diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp
index b203f9e..8ad0518 100644
--- a/src/core/mac/mac.cpp
+++ b/src/core/mac/mac.cpp
@@ -35,13 +35,13 @@
 
 #include <stdio.h>
 
+#include "common/array.hpp"
 #include "common/as_core_type.hpp"
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
 #include "common/random.hpp"
 #include "common/string.hpp"
 #include "crypto/aes_ccm.hpp"
@@ -57,35 +57,15 @@
 namespace ot {
 namespace Mac {
 
+RegisterLogModule("Mac");
+
 const otExtAddress Mac::sMode2ExtAddress = {
     {0x35, 0x06, 0xfe, 0xb8, 0x23, 0xd4, 0x87, 0x12},
 };
 
-const otExtendedPanId Mac::sExtendedPanidInit = {
-    {0xde, 0xad, 0x00, 0xbe, 0xef, 0x00, 0xca, 0xfe},
-};
-
-const char Mac::sNetworkNameInit[] = "OpenThread";
-
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-const char Mac::sDomainNameInit[] = "DefaultDomain";
-#endif
-
 Mac::Mac(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mEnabled(false)
-    , mPendingActiveScan(false)
-    , mPendingEnergyScan(false)
-    , mPendingTransmitBeacon(false)
-    , mPendingTransmitDataDirect(false)
-#if OPENTHREAD_FTD
-    , mPendingTransmitDataIndirect(false)
-#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
-    , mPendingTransmitDataCsl(false)
-#endif
-#endif
-    , mPendingTransmitPoll(false)
-    , mPendingWaitingForData(false)
     , mShouldTxPollBeforeData(false)
     , mRxOnWhenIdle(false)
     , mPromiscuous(false)
@@ -96,6 +76,7 @@
     , mDelayingSleep(false)
 #endif
     , mOperation(kOperationIdle)
+    , mPendingOperations(0)
     , mBeaconSequence(Random::NonCrypto::GetUint8())
     , mDataSequence(Random::NonCrypto::GetUint8())
     , mBroadcastTransmitCount(0)
@@ -111,6 +92,10 @@
 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
     , mCslTxFireTime(TimeMilli::kMaxDuration)
 #endif
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+    , mCslChannel(0)
+    , mCslPeriod(0)
+#endif
 #endif
     , mActiveScanHandler(nullptr) // Initialize `mActiveScanHandler` and `mEnergyScanHandler` union
     , mScanHandlerContext(nullptr)
@@ -132,17 +117,11 @@
 
     mCcaSuccessRateTracker.Clear();
     ResetCounters();
-    mExtendedPanId.Clear();
 
     SetEnabled(true);
     mLinks.Enable();
 
     Get<KeyManager>().UpdateKeyMaterial();
-    SetExtendedPanId(AsCoreType(&sExtendedPanidInit));
-    IgnoreError(SetNetworkName(sNetworkNameInit));
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-    IgnoreError(SetDomainName(sDomainNameInit));
-#endif
     SetPanId(mPanId);
     SetExtAddress(randomExtAddress);
     SetShortAddress(GetShortAddress());
@@ -233,11 +212,13 @@
 
 Error Mac::ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveScanResult &aResult)
 {
-    Error                error = kErrorNone;
-    Address              address;
-    const Beacon *       beacon        = nullptr;
+    Error   error = kErrorNone;
+    Address address;
+#if OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE
     const BeaconPayload *beaconPayload = nullptr;
+    const Beacon *       beacon        = nullptr;
     uint16_t             payloadLength;
+#endif
 
     memset(&aResult, 0, sizeof(ActiveScanResult));
 
@@ -257,6 +238,7 @@
     aResult.mRssi    = aBeaconFrame->GetRssi();
     aResult.mLqi     = aBeaconFrame->GetLqi();
 
+#if OPENTHREAD_CONFIG_MAC_BEACON_PAYLOAD_PARSING_ENABLE
     payloadLength = aBeaconFrame->GetPayloadLength();
 
     beacon        = reinterpret_cast<const Beacon *>(aBeaconFrame->GetPayload());
@@ -271,8 +253,9 @@
         VerifyOrExit(IsValidUtf8String(aResult.mNetworkName.m8), error = kErrorParse);
         aResult.mExtendedPanId = beaconPayload->GetExtendedPanId();
     }
+#endif
 
-    LogBeacon("Received", *beaconPayload);
+    LogBeacon("Received");
 
 exit:
     return error;
@@ -394,10 +377,10 @@
 
     if (mRxOnWhenIdle)
     {
-        if (mPendingWaitingForData)
+        if (IsPending(kOperationWaitingForData))
         {
             mTimer.Stop();
-            mPendingWaitingForData = false;
+            ClearPending(kOperationWaitingForData);
         }
 
         if (mOperation == kOperationWaitingForData)
@@ -434,6 +417,10 @@
 
     mRadioChannel = mPanChannel;
 
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+    UpdateCsl();
+#endif
+
     UpdateIdleMode();
 
 exit:
@@ -473,52 +460,6 @@
     IgnoreError(Get<Notifier>().Update(mSupportedChannelMask, newMask, kEventSupportedChannelMaskChanged));
 }
 
-Error Mac::SetNetworkName(const char *aNameString)
-{
-    return SignalNetworkNameChange(mNetworkName.Set(aNameString));
-}
-
-Error Mac::SetNetworkName(const NameData &aNameData)
-{
-    return SignalNetworkNameChange(mNetworkName.Set(aNameData));
-}
-
-Error Mac::SignalNetworkNameChange(Error aError)
-{
-    switch (aError)
-    {
-    case kErrorNone:
-        Get<Notifier>().Signal(kEventThreadNetworkNameChanged);
-        break;
-
-    case kErrorAlready:
-        Get<Notifier>().SignalIfFirst(kEventThreadNetworkNameChanged);
-        aError = kErrorNone;
-        break;
-
-    default:
-        break;
-    }
-
-    return aError;
-}
-
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-Error Mac::SetDomainName(const char *aNameString)
-{
-    Error error = mDomainName.Set(aNameString);
-
-    return (error == kErrorAlready) ? kErrorNone : error;
-}
-
-Error Mac::SetDomainName(const NameData &aNameData)
-{
-    Error error = mDomainName.Set(aNameData);
-
-    return (error == kErrorAlready) ? kErrorNone : error;
-}
-#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-
 void Mac::SetPanId(PanId aPanId)
 {
     SuccessOrExit(Get<Notifier>().Update(mPanId, aPanId, kEventThreadPanIdChanged));
@@ -528,15 +469,10 @@
     return;
 }
 
-void Mac::SetExtendedPanId(const ExtendedPanId &aExtendedPanId)
-{
-    IgnoreError(Get<Notifier>().Update(mExtendedPanId, aExtendedPanId, kEventThreadExtPanIdChanged));
-}
-
 void Mac::RequestDirectFrameTransmission(void)
 {
     VerifyOrExit(IsEnabled());
-    VerifyOrExit(!mPendingTransmitDataDirect && (mOperation != kOperationTransmitDataDirect));
+    VerifyOrExit(!IsActiveOrPending(kOperationTransmitDataDirect));
 
     StartOperation(kOperationTransmitDataDirect);
 
@@ -548,7 +484,7 @@
 void Mac::RequestIndirectFrameTransmission(void)
 {
     VerifyOrExit(IsEnabled());
-    VerifyOrExit(!mPendingTransmitDataIndirect && (mOperation != kOperationTransmitDataIndirect));
+    VerifyOrExit(!IsActiveOrPending(kOperationTransmitDataIndirect));
 
     StartOperation(kOperationTransmitDataIndirect);
 
@@ -576,13 +512,13 @@
     Error error = kErrorNone;
 
     VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
-    VerifyOrExit(!mPendingTransmitPoll && (mOperation != kOperationTransmitPoll), error = kErrorAlready);
+    VerifyOrExit(!IsActiveOrPending(kOperationTransmitPoll));
 
     // We ensure data frame and data poll tx requests are handled in the
     // order they are requested. So if we have a pending direct data frame
     // tx request, it should be sent before the poll frame.
 
-    mShouldTxPollBeforeData = !mPendingTransmitDataDirect;
+    mShouldTxPollBeforeData = !IsPending(kOperationTransmitDataDirect);
 
     StartOperation(kOperationTransmitPoll);
 
@@ -604,7 +540,7 @@
             mTimer.Start(kSleepDelay);
             mShouldDelaySleep = false;
             mDelayingSleep    = true;
-            otLogDebgMac("Idle mode: Sleep delayed");
+            LogDebg("Idle mode: Sleep delayed");
         }
 
         if (mDelayingSleep)
@@ -614,7 +550,7 @@
 #endif
     }
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
-    else if (mPendingTransmitDataCsl)
+    else if (IsPending(kOperationTransmitDataCsl))
     {
         mTimer.FireAt(mCslTxFireTime);
     }
@@ -625,33 +561,40 @@
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
         if (IsCslEnabled())
         {
-            mLinks.CslSample(mRadioChannel);
+            mLinks.CslSample();
             ExitNow();
         }
 #endif
         mLinks.Sleep();
-        otLogDebgMac("Idle mode: Radio sleeping");
+        LogDebg("Idle mode: Radio sleeping");
     }
     else
     {
         mLinks.Receive(mRadioChannel);
-        otLogDebgMac("Idle mode: Radio receiving on channel %d", mRadioChannel);
+        LogDebg("Idle mode: Radio receiving on channel %d", mRadioChannel);
     }
 
 exit:
     return;
 }
 
+bool Mac::IsActiveOrPending(Operation aOperation) const
+{
+    return (mOperation == aOperation) || IsPending(aOperation);
+}
+
 void Mac::StartOperation(Operation aOperation)
 {
     if (aOperation != kOperationIdle)
     {
-        otLogDebgMac("Request to start operation \"%s\"", OperationToString(aOperation));
+        SetPending(aOperation);
+
+        LogDebg("Request to start operation \"%s\"", OperationToString(aOperation));
 
 #if OPENTHREAD_CONFIG_MAC_STAY_AWAKE_BETWEEN_FRAGMENTS
         if (mDelayingSleep)
         {
-            otLogDebgMac("Canceling sleep delay");
+            LogDebg("Canceling sleep delay");
             mTimer.Stop();
             mDelayingSleep    = false;
             mShouldDelaySleep = false;
@@ -659,48 +602,6 @@
 #endif
     }
 
-    switch (aOperation)
-    {
-    case kOperationIdle:
-        break;
-
-    case kOperationActiveScan:
-        mPendingActiveScan = true;
-        break;
-
-    case kOperationEnergyScan:
-        mPendingEnergyScan = true;
-        break;
-
-    case kOperationTransmitBeacon:
-        mPendingTransmitBeacon = true;
-        break;
-
-    case kOperationTransmitDataDirect:
-        mPendingTransmitDataDirect = true;
-        break;
-
-#if OPENTHREAD_FTD
-    case kOperationTransmitDataIndirect:
-        mPendingTransmitDataIndirect = true;
-        break;
-
-#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
-    case kOperationTransmitDataCsl:
-        mPendingTransmitDataCsl = true;
-        break;
-#endif
-#endif
-
-    case kOperationTransmitPoll:
-        mPendingTransmitPoll = true;
-        break;
-
-    case kOperationWaitingForData:
-        mPendingWaitingForData = true;
-        break;
-    }
-
     if (mOperation == kOperationIdle)
     {
         mOperationTask.Post();
@@ -718,18 +619,7 @@
 
     if (!IsEnabled())
     {
-        mPendingWaitingForData     = false;
-        mPendingActiveScan         = false;
-        mPendingEnergyScan         = false;
-        mPendingTransmitBeacon     = false;
-        mPendingTransmitDataDirect = false;
-#if OPENTHREAD_FTD
-        mPendingTransmitDataIndirect = false;
-#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
-        mPendingTransmitDataCsl = false;
-#endif
-#endif
-        mPendingTransmitPoll = false;
+        mPendingOperations = 0;
         mTimer.Stop();
 #if OPENTHREAD_CONFIG_MAC_STAY_AWAKE_BETWEEN_FRAGMENTS
         mDelayingSleep    = false;
@@ -741,51 +631,43 @@
     // `WaitingForData` should be checked before any other pending
     // operations since radio should remain in receive mode after
     // a data poll ack indicating a pending frame from parent.
-    if (mPendingWaitingForData)
+    if (IsPending(kOperationWaitingForData))
     {
-        mPendingWaitingForData = false;
-        mOperation             = kOperationWaitingForData;
+        mOperation = kOperationWaitingForData;
     }
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
-    else if (mPendingTransmitDataCsl && TimerMilli::GetNow() >= mCslTxFireTime)
+    else if (IsPending(kOperationTransmitDataCsl) && TimerMilli::GetNow() >= mCslTxFireTime)
     {
-        mPendingTransmitDataCsl = false;
-        mOperation              = kOperationTransmitDataCsl;
+        mOperation = kOperationTransmitDataCsl;
     }
 #endif
-    else if (mPendingActiveScan)
+    else if (IsPending(kOperationActiveScan))
     {
-        mPendingActiveScan = false;
-        mOperation         = kOperationActiveScan;
+        mOperation = kOperationActiveScan;
     }
-    else if (mPendingEnergyScan)
+    else if (IsPending(kOperationEnergyScan))
     {
-        mPendingEnergyScan = false;
-        mOperation         = kOperationEnergyScan;
+        mOperation = kOperationEnergyScan;
     }
-    else if (mPendingTransmitBeacon)
+    else if (IsPending(kOperationTransmitBeacon))
     {
-        mPendingTransmitBeacon = false;
-        mOperation             = kOperationTransmitBeacon;
+        mOperation = kOperationTransmitBeacon;
     }
 #if OPENTHREAD_FTD
-    else if (mPendingTransmitDataIndirect)
+    else if (IsPending(kOperationTransmitDataIndirect))
     {
-        mPendingTransmitDataIndirect = false;
-        mOperation                   = kOperationTransmitDataIndirect;
+        mOperation = kOperationTransmitDataIndirect;
     }
 #endif // OPENTHREAD_FTD
-    else if (mPendingTransmitPoll && (!mPendingTransmitDataDirect || mShouldTxPollBeforeData))
+    else if (IsPending(kOperationTransmitPoll) && (!IsPending(kOperationTransmitDataDirect) || mShouldTxPollBeforeData))
     {
-        mPendingTransmitPoll = false;
-        mOperation           = kOperationTransmitPoll;
+        mOperation = kOperationTransmitPoll;
     }
-    else if (mPendingTransmitDataDirect)
+    else if (IsPending(kOperationTransmitDataDirect))
     {
-        mPendingTransmitDataDirect = false;
-        mOperation                 = kOperationTransmitDataDirect;
+        mOperation = kOperationTransmitDataDirect;
 
-        if (mPendingTransmitPoll)
+        if (IsPending(kOperationTransmitPoll))
         {
             // Ensure that a pending "transmit poll" operation request
             // is prioritized over any future "transmit data" requests.
@@ -795,7 +677,8 @@
 
     if (mOperation != kOperationIdle)
     {
-        otLogDebgMac("Starting operation \"%s\"", OperationToString(mOperation));
+        ClearPending(mOperation);
+        LogDebg("Starting operation \"%s\"", OperationToString(mOperation));
         mTimer.Stop(); // Stop the timer before any non-idle operation, have the operation itself be responsible to
                        // start the timer (if it wants to).
     }
@@ -838,7 +721,7 @@
 
 void Mac::FinishOperation(void)
 {
-    otLogDebgMac("Finishing operation \"%s\"", OperationToString(mOperation));
+    LogDebg("Finishing operation \"%s\"", OperationToString(mOperation));
     mOperation = kOperationIdle;
 }
 
@@ -852,18 +735,20 @@
     frame.SetDstAddr(kShortAddrBroadcast);
     IgnoreError(frame.SetCommandId(Frame::kMacCmdBeaconRequest));
 
-    otLogInfoMac("Sending Beacon Request");
+    LogInfo("Sending Beacon Request");
 
     return &frame;
 }
 
 TxFrame *Mac::PrepareBeacon(void)
 {
-    TxFrame *      frame;
+    TxFrame *frame;
+    uint16_t fcf;
+    Beacon * beacon = nullptr;
+#if OPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE
     uint8_t        beaconLength;
-    uint16_t       fcf;
-    Beacon *       beacon        = nullptr;
     BeaconPayload *beaconPayload = nullptr;
+#endif
 
 #if OPENTHREAD_CONFIG_MULTI_RADIO
     OT_ASSERT(!mTxBeaconRadioLinks.IsEmpty());
@@ -880,32 +765,32 @@
 
     beacon = reinterpret_cast<Beacon *>(frame->GetPayload());
     beacon->Init();
+
+#if OPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE
     beaconLength = sizeof(*beacon);
 
     beaconPayload = reinterpret_cast<BeaconPayload *>(beacon->GetPayload());
 
-    if (Get<KeyManager>().GetSecurityPolicy().mBeaconsEnabled)
+    beaconPayload->Init();
+
+    if (IsJoinable())
     {
-        beaconPayload->Init();
-
-        if (IsJoinable())
-        {
-            beaconPayload->SetJoiningPermitted();
-        }
-        else
-        {
-            beaconPayload->ClearJoiningPermitted();
-        }
-
-        beaconPayload->SetNetworkName(mNetworkName.GetAsData());
-        beaconPayload->SetExtendedPanId(mExtendedPanId);
-
-        beaconLength += sizeof(*beaconPayload);
+        beaconPayload->SetJoiningPermitted();
+    }
+    else
+    {
+        beaconPayload->ClearJoiningPermitted();
     }
 
-    frame->SetPayloadLength(beaconLength);
+    beaconPayload->SetNetworkName(Get<MeshCoP::NetworkNameManager>().GetNetworkName().GetAsData());
+    beaconPayload->SetExtendedPanId(Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId());
 
-    LogBeacon("Sending", *beaconPayload);
+    beaconLength += sizeof(*beaconPayload);
+
+    frame->SetPayloadLength(beaconLength);
+#endif
+
+    LogBeacon("Sending");
 
     return frame;
 }
@@ -1015,7 +900,6 @@
 
     default:
         OT_ASSERT(false);
-        OT_UNREACHABLE_CODE(break);
     }
 
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
@@ -1126,7 +1010,6 @@
 
     default:
         OT_ASSERT(false);
-        OT_UNREACHABLE_CODE(break);
     }
 
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
@@ -1150,7 +1033,7 @@
         // copy the frame into correct `TxFrame` for each radio type
         // (if it is not already prepared).
 
-        for (uint8_t index = 0; index < OT_ARRAY_LENGTH(RadioTypes::kAllRadioTypes); index++)
+        for (uint8_t index = 0; index < GetArrayLength(RadioTypes::kAllRadioTypes); index++)
         {
             RadioType radio = RadioTypes::kAllRadioTypes[index];
 
@@ -1169,7 +1052,7 @@
         // process security for each radio type separately. This
         // allows radio links to handle security differently, e.g.,
         // with different keys or link frame counters.
-        for (uint8_t index = 0; index < OT_ARRAY_LENGTH(RadioTypes::kAllRadioTypes); index++)
+        for (uint8_t index = 0; index < GetArrayLength(RadioTypes::kAllRadioTypes); index++)
         {
             RadioType radio = RadioTypes::kAllRadioTypes[index];
 
@@ -1205,7 +1088,7 @@
     if (!mRxOnWhenIdle && !mPromiscuous)
     {
         mShouldDelaySleep = frame->GetFramePending();
-        otLogDebgMac("Delay sleep for pending tx");
+        LogDebg("Delay sleep for pending tx");
     }
 #endif
 
@@ -1298,7 +1181,7 @@
     if (aError != kErrorNone)
     {
         LogFrameTxFailure(aFrame, aError, aRetryCount, aWillRetx);
-        otDumpDebgMac("TX ERR", aFrame.GetHeader(), 16);
+        DumpDebg("TX ERR", aFrame.GetHeader(), 16);
 
         if (aWillRetx)
         {
@@ -1451,8 +1334,8 @@
 
             if (requriedRadios.Contains(radio) && (aError != kErrorNone))
             {
-                otLogDebgMac("Frame tx failed on required radio link %s with error %s", RadioTypeToString(radio),
-                             ErrorToString(aError));
+                LogDebg("Frame tx failed on required radio link %s with error %s", RadioTypeToString(radio),
+                        ErrorToString(aError));
 
                 mTxError = aError;
             }
@@ -1466,7 +1349,7 @@
 
         aError = mTxError;
     }
-#endif
+#endif // OPENTHREAD_CONFIG_MULTI_RADIO
 
     // Determine next action based on current operation.
 
@@ -1495,7 +1378,7 @@
                 StartOperation(kOperationWaitingForData);
             }
 
-            otLogInfoMac("Sent data poll, fp:%s", framePending ? "yes" : "no");
+            LogInfo("Sent data poll, fp:%s", ToYesNo(framePending));
         }
 
         mCounters.mTxDataPoll++;
@@ -1518,7 +1401,7 @@
         }
 #endif
 
-        otDumpDebgMac("TX", aFrame.GetHeader(), aFrame.GetLength());
+        DumpDebg("TX", aFrame.GetHeader(), aFrame.GetLength());
         FinishOperation();
         Get<MeshForwarder>().HandleSentFrame(aFrame, aError);
 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
@@ -1532,7 +1415,7 @@
     case kOperationTransmitDataCsl:
         mCounters.mTxData++;
 
-        otDumpDebgMac("TX", aFrame.GetHeader(), aFrame.GetLength());
+        DumpDebg("TX", aFrame.GetHeader(), aFrame.GetLength());
         FinishOperation();
         Get<CslTxScheduler>().HandleSentFrame(aFrame, aError);
         PerformNextOperation();
@@ -1553,19 +1436,19 @@
         }
 #endif
 
-        otDumpDebgMac("TX", aFrame.GetHeader(), aFrame.GetLength());
+        DumpDebg("TX", aFrame.GetHeader(), aFrame.GetLength());
         FinishOperation();
         Get<DataPollHandler>().HandleSentFrame(aFrame, aError);
         PerformNextOperation();
         break;
-#endif
+#endif // OPENTHREAD_FTD
 
     default:
         OT_ASSERT(false);
-        OT_UNREACHABLE_CODE(ExitNow()); // Added to suppress "unused label exit" warning (in TREL radio only).
-        OT_UNREACHABLE_CODE(break);
     }
 
+    ExitNow(); // Added to suppress "unused label exit" warning (in TREL radio only).
+
 exit:
     return;
 }
@@ -1584,7 +1467,7 @@
         break;
 
     case kOperationWaitingForData:
-        otLogDebgMac("Data poll timeout");
+        LogDebg("Data poll timeout");
         FinishOperation();
         Get<DataPollSender>().HandlePollTimeout();
         PerformNextOperation();
@@ -1596,14 +1479,14 @@
 #if OPENTHREAD_CONFIG_MAC_STAY_AWAKE_BETWEEN_FRAGMENTS
             if (mDelayingSleep)
             {
-                otLogDebgMac("Sleep delay timeout expired");
+                LogDebg("Sleep delay timeout expired");
                 mDelayingSleep = false;
                 UpdateIdleMode();
             }
 #endif
         }
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
-        else if (mPendingTransmitDataCsl)
+        else if (IsPending(kOperationTransmitDataCsl))
         {
             PerformNextOperation();
         }
@@ -1612,7 +1495,6 @@
 
     default:
         OT_ASSERT(false);
-        OT_UNREACHABLE_CODE(break);
     }
 }
 
@@ -1634,7 +1516,7 @@
     VerifyOrExit(securityLevel == Frame::kSecEncMic32);
 
     IgnoreError(aFrame.GetFrameCounter(frameCounter));
-    otLogDebgMac("Rx security - frame counter %u", frameCounter);
+    LogDebg("Rx security - frame counter %u", frameCounter);
 
     IgnoreError(aFrame.GetKeyIdMode(keyIdMode));
 
@@ -1708,7 +1590,6 @@
 
     default:
         ExitNow();
-        OT_UNREACHABLE_CODE(break);
     }
 
     SuccessOrExit(aFrame.ProcessReceiveAesCcm(*extAddress, *macKey));
@@ -1781,7 +1662,7 @@
     VerifyOrExit(txKeyId == ackKeyId);
 
     IgnoreError(aAckFrame.GetFrameCounter(frameCounter));
-    otLogDebgMac("Rx security - Ack frame counter %u", frameCounter);
+    LogDebg("Rx security - Ack frame counter %u", frameCounter);
 
     IgnoreError(aAckFrame.GetSrcAddr(srcAddr));
 
@@ -1842,7 +1723,7 @@
 exit:
     if (error != kErrorNone)
     {
-        otLogInfoMac("Frame tx attempt failed, error: Enh-ACK security check fail");
+        LogInfo("Frame tx attempt failed, error: Enh-ACK security check fail");
     }
 
     return error;
@@ -1909,7 +1790,7 @@
         break;
 
     case Address::kTypeShort:
-        otLogDebgMac("Received frame from short address 0x%04x", srcaddr.GetShort());
+        LogDebg("Received frame from short address 0x%04x", srcaddr.GetShort());
 
         VerifyOrExit(neighbor != nullptr, error = kErrorUnknownNeighbor);
 
@@ -2072,7 +1953,7 @@
             if (!mRxOnWhenIdle && !mPromiscuous && aFrame->GetFramePending())
             {
                 mShouldDelaySleep = true;
-                otLogDebgMac("Delay sleep for pending rx");
+                LogDebg("Delay sleep for pending rx");
             }
 #endif
             FinishOperation();
@@ -2110,7 +1991,7 @@
         ExitNow();
     }
 
-    otDumpDebgMac("RX", aFrame->GetHeader(), aFrame->GetLength());
+    DumpDebg("RX", aFrame->GetHeader(), aFrame->GetLength());
     Get<MeshForwarder>().HandleReceivedFrame(*aFrame);
 
     UpdateIdleMode();
@@ -2173,7 +2054,7 @@
     {
     case Frame::kMacCmdBeaconRequest:
         mCounters.mRxBeaconRequest++;
-        otLogInfoMac("Received Beacon Request");
+        LogInfo("Received Beacon Request");
 
         if (ShouldSendBeacon())
         {
@@ -2255,7 +2136,7 @@
 
 // LCOV_EXCL_START
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
 const char *Mac::OperationToString(Operation aOperation)
 {
@@ -2294,28 +2175,29 @@
 
 void Mac::LogFrameRxFailure(const RxFrame *aFrame, Error aError) const
 {
-    otLogLevel logLevel;
+    LogLevel logLevel;
 
     switch (aError)
     {
     case kErrorAbort:
     case kErrorNoFrameReceived:
+    case kErrorAddressFiltered:
     case kErrorDestinationAddressFiltered:
-        logLevel = OT_LOG_LEVEL_DEBG;
+        logLevel = kLogLevelDebg;
         break;
 
     default:
-        logLevel = OT_LOG_LEVEL_INFO;
+        logLevel = kLogLevelInfo;
         break;
     }
 
     if (aFrame == nullptr)
     {
-        otLogMac(logLevel, "Frame rx failed, error:%s", ErrorToString(aError));
+        LogAt(logLevel, "Frame rx failed, error:%s", ErrorToString(aError));
     }
     else
     {
-        otLogMac(logLevel, "Frame rx failed, error:%s, %s", ErrorToString(aError), aFrame->ToInfoString().AsCString());
+        LogAt(logLevel, "Frame rx failed, error:%s, %s", ErrorToString(aError), aFrame->ToInfoString().AsCString());
     }
 }
 
@@ -2332,27 +2214,27 @@
         uint8_t maxAttempts = aFrame.GetMaxFrameRetries() + 1;
         uint8_t curAttempt  = aWillRetx ? (aRetryCount + 1) : maxAttempts;
 
-        otLogInfoMac("Frame tx attempt %d/%d failed, error:%s, %s", curAttempt, maxAttempts, ErrorToString(aError),
-                     aFrame.ToInfoString().AsCString());
+        LogInfo("Frame tx attempt %d/%d failed, error:%s, %s", curAttempt, maxAttempts, ErrorToString(aError),
+                aFrame.ToInfoString().AsCString());
     }
     else
     {
-        otLogInfoMac("Frame tx failed, error:%s, %s", ErrorToString(aError), aFrame.ToInfoString().AsCString());
+        LogInfo("Frame tx failed, error:%s, %s", ErrorToString(aError), aFrame.ToInfoString().AsCString());
     }
 }
 
-void Mac::LogBeacon(const char *aActionText, const BeaconPayload &aBeaconPayload) const
+void Mac::LogBeacon(const char *aActionText) const
 {
-    otLogInfoMac("%s Beacon, %s", aActionText, aBeaconPayload.ToInfoString().AsCString());
+    LogInfo("%s Beacon", aActionText);
 }
 
-#else // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
+#else // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
 void Mac::LogFrameRxFailure(const RxFrame *, Error) const
 {
 }
 
-void Mac::LogBeacon(const char *, const BeaconPayload &) const
+void Mac::LogBeacon(const char *) const
 {
 }
 
@@ -2360,7 +2242,7 @@
 {
 }
 
-#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
+#endif // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
 // LCOV_EXCL_STOP
 
@@ -2383,52 +2265,54 @@
 #endif
 
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+void Mac::UpdateCsl(void)
+{
+    uint16_t period  = IsCslEnabled() ? GetCslPeriod() : 0;
+    uint8_t  channel = GetCslChannel() ? GetCslChannel() : mRadioChannel;
+
+    if (mLinks.UpdateCsl(period, channel, Get<Mle::Mle>().GetParent().GetRloc16(),
+                         &Get<Mle::Mle>().GetParent().GetExtAddress()))
+    {
+        if (Get<Mle::Mle>().IsChild())
+        {
+            Get<DataPollSender>().RecalculatePollPeriod();
+
+            if (period != 0)
+            {
+                Get<Mle::Mle>().ScheduleChildUpdateRequest();
+            }
+        }
+
+        UpdateIdleMode();
+    }
+}
+
 void Mac::SetCslChannel(uint8_t aChannel)
 {
-    VerifyOrExit(GetCslChannel() != aChannel);
-
-    mLinks.GetSubMac().SetCslChannel(aChannel);
-    mLinks.GetSubMac().SetCslChannelSpecified(aChannel != 0);
-
-    if (IsCslEnabled())
-    {
-        Get<Mle::Mle>().ScheduleChildUpdateRequest();
-    }
-exit:
-    return;
+    mCslChannel = aChannel;
+    UpdateCsl();
 }
 
 void Mac::SetCslPeriod(uint16_t aPeriod)
 {
-    mLinks.GetSubMac().SetCslPeriod(aPeriod);
-
-    Get<DataPollSender>().RecalculatePollPeriod();
-
-    if ((GetCslPeriod() == 0) || IsCslEnabled())
-    {
-        IgnoreError(Get<Radio>().EnableCsl(GetCslPeriod(), Get<Mle::Mle>().GetParent().GetRloc16(),
-                                           &Get<Mle::Mle>().GetParent().GetExtAddress()));
-    }
-
-    if (IsCslEnabled())
-    {
-        Get<Mle::Mle>().ScheduleChildUpdateRequest();
-    }
-
-    UpdateIdleMode();
+    mCslPeriod = aPeriod;
+    UpdateCsl();
 }
 
 bool Mac::IsCslEnabled(void) const
 {
-    return !GetRxOnWhenIdle() && IsCslCapable();
+    return !Get<Mle::Mle>().IsRxOnWhenIdle() && IsCslCapable();
 }
 
 bool Mac::IsCslCapable(void) const
 {
-    return (GetCslPeriod() > 0) && Get<Mle::MleRouter>().IsChild() &&
-           Get<Mle::Mle>().GetParent().IsEnhancedKeepAliveSupported();
+    return (GetCslPeriod() > 0) && IsCslSupported();
 }
 
+bool Mac::IsCslSupported(void) const
+{
+    return Get<Mle::MleRouter>().IsChild() && Get<Mle::Mle>().GetParent().IsEnhancedKeepAliveSupported();
+}
 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
 
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
@@ -2448,9 +2332,9 @@
     child->SetCslSynchronized(true);
     child->SetCslLastHeard(TimerMilli::GetNow());
     child->SetLastRxTimestamp(aFrame.GetTimestamp());
-    otLogDebgMac("Timestamp=%u Sequence=%u CslPeriod=%hu CslPhase=%hu TransmitPhase=%hu",
-                 static_cast<uint32_t>(aFrame.GetTimestamp()), aFrame.GetSequence(), csl->GetPeriod(), csl->GetPhase(),
-                 child->GetCslPhase());
+    LogDebg("Timestamp=%u Sequence=%u CslPeriod=%hu CslPhase=%hu TransmitPhase=%hu",
+            static_cast<uint32_t>(aFrame.GetTimestamp()), aFrame.GetSequence(), csl->GetPeriod(), csl->GetPhase(),
+            child->GetCslPhase());
 
     Get<CslTxScheduler>().Update();
 
@@ -2481,5 +2365,13 @@
 }
 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
 
+#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
+void Mac::SetRadioFilterEnabled(bool aFilterEnabled)
+{
+    mLinks.GetSubMac().SetRadioFilterEnabled(aFilterEnabled);
+    UpdateIdleMode();
+}
+#endif
+
 } // namespace Mac
 } // namespace ot
diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp
index 7746909..babdbbf 100644
--- a/src/core/mac/mac.hpp
+++ b/src/core/mac/mac.hpp
@@ -40,6 +40,7 @@
 #include <openthread/platform/time.h>
 
 #include "common/locator.hpp"
+#include "common/log.hpp"
 #include "common/non_copyable.hpp"
 #include "common/tasklet.hpp"
 #include "common/time.hpp"
@@ -227,7 +228,6 @@
      * This method requests transmission of a data poll (MAC Data Request) frame.
      *
      * @retval kErrorNone          Data poll transmission request is scheduled successfully.
-     * @retval kErrorAlready       MAC is busy sending earlier poll transmission request.
      * @retval kErrorInvalidState  The MAC layer is not enabled.
      *
      */
@@ -323,68 +323,6 @@
     void SetSupportedChannelMask(const ChannelMask &aMask);
 
     /**
-     * This method returns the IEEE 802.15.4 Network Name.
-     *
-     * @returns The IEEE 802.15.4 Network Name.
-     *
-     */
-    const NetworkName &GetNetworkName(void) const { return mNetworkName; }
-
-    /**
-     * This method sets the IEEE 802.15.4 Network Name.
-     *
-     * @param[in]  aNameString   A pointer to a string character array. Must be null terminated.
-     *
-     * @retval kErrorNone          Successfully set the IEEE 802.15.4 Network Name.
-     * @retval kErrorInvalidArgs   Given name is too long.
-     *
-     */
-    Error SetNetworkName(const char *aNameString);
-
-    /**
-     * This method sets the IEEE 802.15.4 Network Name.
-     *
-     * @param[in]  aNameData     A name data (pointer to char buffer and length).
-     *
-     * @retval kErrorNone          Successfully set the IEEE 802.15.4 Network Name.
-     * @retval kErrorInvalidArgs   Given name is too long.
-     *
-     */
-    Error SetNetworkName(const NameData &aNameData);
-
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-    /**
-     * This method returns the Thread Domain Name.
-     *
-     * @returns The Thread Domain Name.
-     *
-     */
-    const DomainName &GetDomainName(void) const { return mDomainName; }
-
-    /**
-     * This method sets the Thread Domain Name.
-     *
-     * @param[in]  aNameString   A pointer to a string character array. Must be null terminated.
-     *
-     * @retval kErrorNone          Successfully set the Thread Domain Name.
-     * @retval kErrorInvalidArgs   Given name is too long.
-     *
-     */
-    Error SetDomainName(const char *aNameString);
-
-    /**
-     * This method sets the Thread Domain Name.
-     *
-     * @param[in]  aNameData     A name data (pointer to char buffer and length).
-     *
-     * @retval kErrorNone          Successfully set the Thread Domain Name.
-     * @retval kErrorInvalidArgs   Given name is too long.
-     *
-     */
-    Error SetDomainName(const NameData &aNameData);
-#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-
-    /**
      * This method returns the IEEE 802.15.4 PAN ID.
      *
      * @returns The IEEE 802.15.4 PAN ID.
@@ -401,22 +339,6 @@
     void SetPanId(PanId aPanId);
 
     /**
-     * This method returns the IEEE 802.15.4 Extended PAN Identifier.
-     *
-     * @returns The IEEE 802.15.4 Extended PAN Identifier.
-     *
-     */
-    const ExtendedPanId &GetExtendedPanId(void) const { return mExtendedPanId; }
-
-    /**
-     * This method sets the IEEE 802.15.4 Extended PAN Identifier.
-     *
-     * @param[in]  aExtendedPanId  The IEEE 802.15.4 Extended PAN Identifier.
-     *
-     */
-    void SetExtendedPanId(const ExtendedPanId &aExtendedPanId);
-
-    /**
      * This method returns the maximum number of frame retries during direct transmission.
      *
      * @returns The maximum number of retries during direct transmission.
@@ -456,7 +378,7 @@
     /**
      * This method is called to handle a received frame.
      *
-     * @param[in]  aFrame  A pointer to the received frame, or nullptr if the receive operation was aborted.
+     * @param[in]  aFrame  A pointer to the received frame, or `nullptr` if the receive operation was aborted.
      * @param[in]  aError  kErrorNone when successfully received a frame,
      *                     kErrorAbort when reception was aborted and a frame was not received.
      *
@@ -479,7 +401,7 @@
      * of a frame transmission request, this method is invoked on all frame transmission attempts.
      *
      * @param[in] aFrame      The transmitted frame.
-     * @param[in] aAckFrame   A pointer to the ACK frame, or nullptr if no ACK was received.
+     * @param[in] aAckFrame   A pointer to the ACK frame, or `nullptr` if no ACK was received.
      * @param[in] aError      kErrorNone when the frame was transmitted successfully,
      *                        kErrorNoAck when the frame was transmitted but no ACK was received,
      *                        kErrorChannelAccessFailure tx failed due to activity on the channel,
@@ -499,7 +421,7 @@
      * This method is called to handle transmit events.
      *
      * @param[in]  aFrame      The frame that was transmitted.
-     * @param[in]  aAckFrame   A pointer to the ACK frame, nullptr if no ACK was received.
+     * @param[in]  aAckFrame   A pointer to the ACK frame, `nullptr` if no ACK was received.
      * @param[in]  aError      kErrorNone when the frame was transmitted successfully,
      *                         kErrorNoAck when the frame was transmitted but no ACK was received,
      *                         kErrorChannelAccessFailure when the tx failed due to activity on the channel,
@@ -512,13 +434,13 @@
      * This method returns if an active scan is in progress.
      *
      */
-    bool IsActiveScanInProgress(void) const { return (mOperation == kOperationActiveScan) || (mPendingActiveScan); }
+    bool IsActiveScanInProgress(void) const { return IsActiveOrPending(kOperationActiveScan); }
 
     /**
      * This method returns if an energy scan is in progress.
      *
      */
-    bool IsEnergyScanInProgress(void) const { return (mOperation == kOperationEnergyScan) || (mPendingEnergyScan); }
+    bool IsEnergyScanInProgress(void) const { return IsActiveOrPending(kOperationEnergyScan); }
 
 #if OPENTHREAD_FTD
     /**
@@ -544,7 +466,7 @@
      * This method registers a callback to provide received raw IEEE 802.15.4 frames.
      *
      * @param[in]  aPcapCallback     A pointer to a function that is called when receiving an IEEE 802.15.4 link frame
-     * or nullptr to disable the callback.
+     *                               or `nullptr` to disable the callback.
      * @param[in]  aCallbackContext  A pointer to application-specific context.
      *
      */
@@ -661,7 +583,7 @@
      * @returns CSL channel.
      *
      */
-    uint8_t GetCslChannel(void) const { return mLinks.GetSubMac().GetCslChannel(); }
+    uint8_t GetCslChannel(void) const { return mCslChannel; }
 
     /**
      * This method sets the CSL channel.
@@ -672,12 +594,10 @@
     void SetCslChannel(uint8_t aChannel);
 
     /**
-     * This method indicates if CSL channel has been explicitly specified by the upper layer.
-     *
-     * @returns If CSL channel has been specified.
+     * This method centralizes CSL state switching conditions evaluating, configuring SubMac accordingly.
      *
      */
-    bool IsCslChannelSpecified(void) const { return mLinks.GetSubMac().IsCslChannelSpecified(); }
+    void UpdateCsl(void);
 
     /**
      * This method gets the CSL period.
@@ -685,7 +605,7 @@
      * @returns CSL period in units of 10 symbols.
      *
      */
-    uint16_t GetCslPeriod(void) const { return mLinks.GetSubMac().GetCslPeriod(); }
+    uint16_t GetCslPeriod(void) const { return mCslPeriod; }
 
     /**
      * This method sets the CSL period.
@@ -714,6 +634,15 @@
     bool IsCslCapable(void) const;
 
     /**
+     * This method indicates whether the device is connected to a parent which supports CSL.
+     *
+     * @retval TRUE   If parent supports CSL.
+     * @retval FALSE  If parent does not support CSL.
+     *
+     */
+    bool IsCslSupported(void) const;
+
+    /**
      * This method returns CSL parent clock accuracy, in ± ppm.
      *
      * @retval CSL parent clock accuracy, in ± ppm.
@@ -752,6 +681,29 @@
     }
 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
 
+#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
+    /**
+     * This method enables/disables the 802.15.4 radio filter.
+     *
+     * When radio filter is enabled, radio is put to sleep instead of receive (to ensure device does not receive any
+     * frame and/or potentially send ack). Also the frame transmission requests return immediately without sending the
+     * frame over the air (return "no ack" error if ack is requested, otherwise return success).
+     *
+     * @param[in] aFilterEnabled    TRUE to enable radio filter, FALSE to disable.
+     *
+     */
+    void SetRadioFilterEnabled(bool aFilterEnabled);
+
+    /**
+     * This method indicates whether the 802.15.4 radio filter is enabled or not.
+     *
+     * @retval TRUE   If the radio filter is enabled.
+     * @retval FALSE  If the radio filter is disabled.
+     *
+     */
+    bool IsRadioFilterEnabled(void) const { return mLinks.GetSubMac().IsRadioFilterEnabled(); }
+#endif
+
 private:
     static constexpr int8_t   kInvalidRssiValue  = SubMac::kInvalidRssiValue;
     static constexpr uint16_t kMaxCcaSampleCount = OPENTHREAD_CONFIG_CCA_FAILURE_RATE_AVERAGING_WINDOW;
@@ -803,6 +755,10 @@
 #endif
 
     void     UpdateIdleMode(void);
+    bool     IsPending(Operation aOperation) const { return mPendingOperations & (1U << aOperation); }
+    bool     IsActiveOrPending(Operation aOperation) const;
+    void     SetPending(Operation aOperation) { mPendingOperations |= (1U << aOperation); }
+    void     ClearPending(Operation aOperation) { mPendingOperations &= ~(1U << aOperation); }
     void     StartOperation(Operation aOperation);
     void     FinishOperation(void);
     void     PerformNextOperation(void);
@@ -824,11 +780,10 @@
     Error ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveScanResult &aResult);
     void  PerformEnergyScan(void);
     void  ReportEnergyScanResult(int8_t aRssi);
-    Error SignalNetworkNameChange(Error aError);
 
     void LogFrameRxFailure(const RxFrame *aFrame, Error aError) const;
     void LogFrameTxFailure(const TxFrame &aFrame, Error aError, uint8_t aRetryCount, bool aWillRetx) const;
-    void LogBeacon(const char *aActionText, const BeaconPayload &aBeaconPayload) const;
+    void LogBeacon(const char *aActionText) const;
 
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
     uint8_t GetTimeIeOffset(const Frame &aFrame);
@@ -842,24 +797,9 @@
 #endif
     static const char *OperationToString(Operation aOperation);
 
-    static const otExtAddress    sMode2ExtAddress;
-    static const otExtendedPanId sExtendedPanidInit;
-    static const char            sNetworkNameInit[];
-    static const char            sDomainNameInit[];
+    static const otExtAddress sMode2ExtAddress;
 
     bool mEnabled : 1;
-    bool mPendingActiveScan : 1;
-    bool mPendingEnergyScan : 1;
-    bool mPendingTransmitBeacon : 1;
-    bool mPendingTransmitDataDirect : 1;
-#if OPENTHREAD_FTD
-    bool mPendingTransmitDataIndirect : 1;
-#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
-    bool mPendingTransmitDataCsl : 1;
-#endif
-#endif
-    bool mPendingTransmitPoll : 1;
-    bool mPendingWaitingForData : 1;
     bool mShouldTxPollBeforeData : 1;
     bool mRxOnWhenIdle : 1;
     bool mPromiscuous : 1;
@@ -869,20 +809,15 @@
     bool mShouldDelaySleep : 1;
     bool mDelayingSleep : 1;
 #endif
-
-    Operation     mOperation;
-    uint8_t       mBeaconSequence;
-    uint8_t       mDataSequence;
-    uint8_t       mBroadcastTransmitCount;
-    PanId         mPanId;
-    uint8_t       mPanChannel;
-    uint8_t       mRadioChannel;
-    ChannelMask   mSupportedChannelMask;
-    ExtendedPanId mExtendedPanId;
-    NetworkName   mNetworkName;
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-    DomainName mDomainName;
-#endif
+    Operation   mOperation;
+    uint16_t    mPendingOperations;
+    uint8_t     mBeaconSequence;
+    uint8_t     mDataSequence;
+    uint8_t     mBroadcastTransmitCount;
+    PanId       mPanId;
+    uint8_t     mPanChannel;
+    uint8_t     mRadioChannel;
+    ChannelMask mSupportedChannelMask;
     uint8_t     mScanChannel;
     uint16_t    mScanDuration;
     ChannelMask mScanChannelMask;
@@ -893,6 +828,11 @@
     TimeMilli mCslTxFireTime;
 #endif
 #endif
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+    // When Mac::mCslChannel is 0, it indicates that CSL channel has not been specified by the upper layer.
+    uint8_t  mCslChannel;
+    uint16_t mCslPeriod;
+#endif
 
     union
     {
@@ -921,7 +861,7 @@
 
 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
     Filter mFilter;
-#endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
+#endif
 
     KeyMaterial mMode2KeyMaterial;
 };
diff --git a/src/core/mac/mac_filter.cpp b/src/core/mac/mac_filter.cpp
index d05a221..c119c42 100644
--- a/src/core/mac/mac_filter.cpp
+++ b/src/core/mac/mac_filter.cpp
@@ -35,6 +35,7 @@
 
 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
 
+#include "common/array.hpp"
 #include "common/as_core_type.hpp"
 #include "common/code_utils.hpp"
 
@@ -123,7 +124,7 @@
 {
     Error error = kErrorNotFound;
 
-    for (; aIterator < OT_ARRAY_LENGTH(mFilterEntries); aIterator++)
+    for (; aIterator < GetArrayLength(mFilterEntries); aIterator++)
     {
         const FilterEntry &entry = mFilterEntries[aIterator];
 
@@ -185,7 +186,7 @@
 {
     Error error = kErrorNotFound;
 
-    for (; aIterator < OT_ARRAY_LENGTH(mFilterEntries); aIterator++)
+    for (; aIterator < GetArrayLength(mFilterEntries); aIterator++)
     {
         FilterEntry &entry = mFilterEntries[aIterator];
 
@@ -200,7 +201,7 @@
     }
 
     // Return the default RssIn at the end of list
-    if ((aIterator == OT_ARRAY_LENGTH(mFilterEntries)) && (mDefaultRssIn != kFixedRssDisabled))
+    if ((aIterator == GetArrayLength(mFilterEntries)) && (mDefaultRssIn != kFixedRssDisabled))
     {
         AsCoreType(&aEntry.mExtAddress).Fill(0xff);
         aEntry.mRssIn = mDefaultRssIn;
diff --git a/src/core/mac/mac_filter.hpp b/src/core/mac/mac_filter.hpp
index 7597e5f..2eaef71 100644
--- a/src/core/mac/mac_filter.hpp
+++ b/src/core/mac/mac_filter.hpp
@@ -40,6 +40,7 @@
 
 #include <stdint.h>
 
+#include "common/as_core_type.hpp"
 #include "common/non_copyable.hpp"
 #include "mac/mac_frame.hpp"
 
@@ -139,9 +140,9 @@
     /**
      * This method iterates through filter entries.
      *
-     * @param[inout]  aIterator  A reference to the MAC filter iterator context.
-     *                           To get the first in-use address filter, set it to OT_MAC_FILTER_ITERATOR_INIT.
-     * @param[out]     aEntry    A reference to where the information is placed.
+     * @param[in,out]  aIterator  A reference to the MAC filter iterator context.
+     *                            To get the first in-use address filter, set it to OT_MAC_FILTER_ITERATOR_INIT.
+     * @param[out]     aEntry     A reference to where the information is placed.
      *
      * @retval kErrorNone      Successfully retrieved the next address filter entry.
      * @retval kErrorNotFound  No subsequent entry exists.
@@ -197,11 +198,11 @@
     /**
      * This method iterates through RssIn filter entry.
      *
-     * @param[inout]  aIterator  A reference to the MAC filter iterator context. To get the first in-use RssIn
-     *                           filter entry, it should be set to OT_MAC_FILTER_ITERATOR_INIT.
-     * @param[out]    aEntry     A reference to where the information is placed. The last entry would have the
-     *                           Extended Address as all 0xff to indicate the default received signal strength
-     *                           if it was set.
+     * @param[in,out]  aIterator  A reference to the MAC filter iterator context. To get the first in-use RssIn
+     *                            filter entry, it should be set to OT_MAC_FILTER_ITERATOR_INIT.
+     * @param[out]     aEntry     A reference to where the information is placed. The last entry would have the
+     *                            Extended Address as all 0xff to indicate the default received signal strength
+     *                            if it was set.
      *
      * @retval kErrorNone      Successfully retrieved the next RssIn filter entry.
      * @retval kErrorNotFound  No subsequent entry exists.
@@ -247,6 +248,9 @@
  */
 
 } // namespace Mac
+
+DefineMapEnum(otMacFilterAddressMode, Mac::Filter::Mode);
+
 } // namespace ot
 
 #endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
diff --git a/src/core/mac/mac_frame.cpp b/src/core/mac/mac_frame.cpp
index adc50df..2f0b1d1 100644
--- a/src/core/mac/mac_frame.cpp
+++ b/src/core/mac/mac_frame.cpp
@@ -37,6 +37,7 @@
 
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
+#include "common/log.hpp"
 #include "radio/trel_link.hpp"
 #if !OPENTHREAD_RADIO || OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE
 #include "crypto/aes_ccm.hpp"
@@ -1379,7 +1380,7 @@
 
 // LCOV_EXCL_START
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
 
 Frame::InfoString Frame::ToInfoString(void) const
 {
@@ -1437,7 +1438,7 @@
     IgnoreError(GetDstAddr(dst));
 
     string.Append(", src:%s, dst:%s, sec:%s, ackreq:%s", src.ToString().AsCString(), dst.ToString().AsCString(),
-                  GetSecurityEnabled() ? "yes" : "no", GetAckRequest() ? "yes" : "no");
+                  ToYesNo(GetSecurityEnabled()), ToYesNo(GetAckRequest()));
 
 #if OPENTHREAD_CONFIG_MULTI_RADIO
     string.Append(", radio:%s", RadioTypeToString(GetRadioType()));
@@ -1446,20 +1447,7 @@
     return string;
 }
 
-BeaconPayload::InfoString BeaconPayload::ToInfoString(void) const
-{
-    NetworkName name;
-    InfoString  string;
-
-    IgnoreError(name.Set(GetNetworkName()));
-
-    string.Append("name:%s, xpanid:%s, id:%d, ver:%d, joinable:%s, native:%s", name.GetAsCString(),
-                  mExtendedPanId.ToString().AsCString(), GetProtocolId(), GetProtocolVersion(),
-                  IsJoiningPermitted() ? "yes" : "no", IsNative() ? "yes" : "no");
-    return string;
-}
-
-#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
+#endif // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
 
 // LCOV_EXCL_STOP
 
diff --git a/src/core/mac/mac_frame.hpp b/src/core/mac/mac_frame.hpp
index fbe1314..9ffe2d5 100644
--- a/src/core/mac/mac_frame.hpp
+++ b/src/core/mac/mac_frame.hpp
@@ -39,9 +39,11 @@
 #include <limits.h>
 #include <stdint.h>
 
+#include "common/as_core_type.hpp"
 #include "common/const_cast.hpp"
 #include "common/encoding.hpp"
 #include "mac/mac_types.hpp"
+#include "meshcop/network_name.hpp"
 
 namespace ot {
 namespace Mac {
@@ -92,7 +94,7 @@
     /**
      * This method sets the IE Element Id.
      *
-     * @param[in]  aID  The IE Element Id.
+     * @param[in]  aId  The IE Element Id.
      *
      */
     void SetId(uint16_t aId)
@@ -154,7 +156,7 @@
     /**
      * This method returns the Vendor OUI.
      *
-     * @returns the Vendor OUI.
+     * @returns The Vendor OUI.
      *
      */
     uint32_t GetVendorOui(void) const { return ReadUint24(mOui); }
@@ -170,7 +172,7 @@
     /**
      * This method returns the Vendor IE sub-type.
      *
-     * @returns the Vendor IE sub-type.
+     * @returns The Vendor IE sub-type.
      *
      */
     uint8_t GetSubType(void) const { return mSubType; }
@@ -178,7 +180,7 @@
     /**
      * This method sets the Vendor IE sub-type.
      *
-     * @param[in] the Vendor IE sub-type.
+     * @param[in]  aSubType  The Vendor IE sub-type.
      *
      */
     void SetSubType(uint8_t aSubType) { mSubType = aSubType; }
@@ -363,8 +365,8 @@
     /**
      * This method initializes the MAC header.
      *
-     * @param[in]  aFcf          The Frame Control field.
-     * @param[in]  aSecurityCtl  The Security Control field.
+     * @param[in]  aFcf              The Frame Control field.
+     * @param[in]  aSecurityControl  The Security Control field.
      *
      */
     void InitMacHeader(uint16_t aFcf, uint8_t aSecurityControl);
@@ -662,7 +664,7 @@
     /**
      * This method gets the Key Identifier Mode.
      *
-     * @param[out]  aSecurityLevel  The Key Identifier Mode.
+     * @param[out]  aKeyIdMode  The Key Identifier Mode.
      *
      * @retval kErrorNone  Successfully retrieved the Key Identifier Mode.
      *
@@ -898,7 +900,7 @@
     /**
      * This method returns a pointer to the vendor specific Time IE.
      *
-     * @returns A pointer to the Time IE, nullptr if not found.
+     * @returns A pointer to the Time IE, `nullptr` if not found.
      *
      */
     TimeIe *GetTimeIe(void) { return AsNonConst(AsConst(this)->GetTimeIe()); }
@@ -906,7 +908,7 @@
     /**
      * This method returns a pointer to the vendor specific Time IE.
      *
-     * @returns A pointer to the Time IE, nullptr if not found.
+     * @returns A pointer to the Time IE, `nullptr` if not found.
      *
      */
     const TimeIe *GetTimeIe(void) const;
@@ -936,7 +938,7 @@
      *
      * @param[in] aIeId  The Element Id of the Header IE.
      *
-     * @returns A pointer to the Header IE, nullptr if not found.
+     * @returns A pointer to the Header IE, `nullptr` if not found.
      *
      */
     uint8_t *GetHeaderIe(uint8_t aIeId) { return AsNonConst(AsConst(this)->GetHeaderIe(aIeId)); }
@@ -946,7 +948,7 @@
      *
      * @param[in] aIeId  The Element Id of the Header IE.
      *
-     * @returns A pointer to the Header IE, nullptr if not found.
+     * @returns A pointer to the Header IE, `nullptr` if not found.
      *
      */
     const uint8_t *GetHeaderIe(uint8_t aIeId) const;
@@ -958,7 +960,7 @@
      *
      * @param[in] aSubType  The sub type of the Thread IE.
      *
-     * @returns A pointer to the Thread IE, nullptr if not found.
+     * @returns A pointer to the Thread IE, `nullptr` if not found.
      *
      */
     uint8_t *GetThreadIe(uint8_t aSubType) { return AsNonConst(AsConst(this)->GetThreadIe(aSubType)); }
@@ -970,7 +972,7 @@
      *
      * @param[in] aSubType  The sub type of the Thread IE.
      *
-     * @returns A pointer to the Thread IE, nullptr if not found.
+     * @returns A pointer to the Thread IE, `nullptr` if not found.
      *
      */
     const uint8_t *GetThreadIe(uint8_t aSubType) const;
@@ -1496,14 +1498,6 @@
     static constexpr uint8_t kNativeFlag      = 1 << 3;                ///< Native Commissioner flag.
     static constexpr uint8_t kJoiningFlag     = 1 << 0;                ///< Joining Permitted flag.
 
-    static constexpr uint16_t kInfoStringSize = 92; ///< Max chars for the info string (@sa ToInfoString()).
-
-    /**
-     * This type defines the fixed-length `String` object returned from `ToInfoString()` method.
-     *
-     */
-    typedef String<kInfoStringSize> InfoString;
-
     /**
      * This method initializes the Beacon Payload.
      *
@@ -1595,7 +1589,7 @@
      * @returns The Network Name field as `NameData`.
      *
      */
-    NameData GetNetworkName(void) const { return NameData(mNetworkName, sizeof(mNetworkName)); }
+    MeshCoP::NameData GetNetworkName(void) const { return MeshCoP::NameData(mNetworkName, sizeof(mNetworkName)); }
 
     /**
      * This method sets the Network Name field.
@@ -1603,7 +1597,7 @@
      * @param[in]  aNameData  The Network Name (as a `NameData`).
      *
      */
-    void SetNetworkName(const NameData &aNameData) { aNameData.CopyTo(mNetworkName, sizeof(mNetworkName)); }
+    void SetNetworkName(const MeshCoP::NameData &aNameData) { aNameData.CopyTo(mNetworkName, sizeof(mNetworkName)); }
 
     /**
      * This method returns the Extended PAN ID field.
@@ -1611,7 +1605,7 @@
      * @returns The Extended PAN ID field.
      *
      */
-    const ExtendedPanId &GetExtendedPanId(void) const { return mExtendedPanId; }
+    const otExtendedPanId &GetExtendedPanId(void) const { return mExtendedPanId; }
 
     /**
      * This method sets the Extended PAN ID field.
@@ -1619,21 +1613,13 @@
      * @param[in]  aExtPanId  An Extended PAN ID.
      *
      */
-    void SetExtendedPanId(const ExtendedPanId &aExtPanId) { mExtendedPanId = aExtPanId; }
-
-    /**
-     * This method returns information about the Beacon as a `InfoString`.
-     *
-     * @returns An `InfoString` representing the beacon payload.
-     *
-     */
-    InfoString ToInfoString(void) const;
+    void SetExtendedPanId(const otExtendedPanId &aExtPanId) { mExtendedPanId = aExtPanId; }
 
 private:
-    uint8_t       mProtocolId;
-    uint8_t       mFlags;
-    char          mNetworkName[NetworkName::kMaxSize];
-    ExtendedPanId mExtendedPanId;
+    uint8_t         mProtocolId;
+    uint8_t         mFlags;
+    char            mNetworkName[MeshCoP::NetworkName::kMaxSize];
+    otExtendedPanId mExtendedPanId;
 } OT_TOOL_PACKED_END;
 
 /**
diff --git a/src/core/mac/mac_links.hpp b/src/core/mac/mac_links.hpp
index ff6821c..99406f7 100644
--- a/src/core/mac/mac_links.hpp
+++ b/src/core/mac/mac_links.hpp
@@ -457,18 +457,42 @@
 
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
     /**
-     * This method transitions all radios link to CSL sample state.
+     * This method configures CSL parameters in all radios.
      *
-     * CSL sample state is only applicable and used for 15.4 radio link. Other link are transitioned to sleep state.
+     * @param[in]  aPeriod    The CSL period.
+     * @param[in]  aChannel   The CSL channel.
+     * @param[in]  aShortAddr The short source address of CSL receiver's peer.
+     * @param[in]  aExtAddr   The extended source address of CSL receiver's peer.
      *
-     * @param[in]  aPanChannel  The current phy channel used by the device. This param will only take effect when CSL
-     *                          channel hasn't been explicitly specified.
+     * @retval  TRUE if CSL Period or CSL Channel changed.
+     * @retval  FALSE if CSL Period and CSL Channel did not change.
+     *
      */
-    void CslSample(uint8_t aPanChannel)
+    bool UpdateCsl(uint16_t aPeriod, uint8_t aChannel, otShortAddress aShortAddr, const otExtAddress *aExtAddr)
     {
-        OT_UNUSED_VARIABLE(aPanChannel);
+        bool retval = false;
+
+        OT_UNUSED_VARIABLE(aPeriod);
+        OT_UNUSED_VARIABLE(aChannel);
+        OT_UNUSED_VARIABLE(aShortAddr);
+        OT_UNUSED_VARIABLE(aExtAddr);
 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
-        IgnoreError(mSubMac.CslSample(aPanChannel));
+        retval = mSubMac.UpdateCsl(aPeriod, aChannel, aShortAddr, aExtAddr);
+#endif
+        return retval;
+    }
+
+    /**
+     * This method transitions all radios link to CSL sample state, given that a non-zero CSL period is configured.
+     *
+     * CSL sample state is only applicable and used for 15.4 radio link. Other link are transitioned to sleep state
+     * when CSL period is non-zero.
+     *
+     */
+    void CslSample(void)
+    {
+#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
+        mSubMac.CslSample();
 #endif
 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
         mTrel.Sleep();
@@ -572,6 +596,7 @@
      * @param[in] aScanDuration  The duration, in milliseconds, for the channel to be scanned.
      *
      * @retval kErrorNone            Successfully started scanning the channel.
+     * @retval kErrorBusy            The radio is performing energy scanning.
      * @retval kErrorInvalidState    The radio was disabled or transmitting.
      * @retval kErrorNotImplemented  Energy scan is not supported by radio link.
      *
diff --git a/src/core/mac/mac_types.cpp b/src/core/mac/mac_types.cpp
index af1a680..83fab4b 100644
--- a/src/core/mac/mac_types.cpp
+++ b/src/core/mac/mac_types.cpp
@@ -28,7 +28,7 @@
 
 /**
  * @file
- *   This file implements MAC types such as Address, Extended PAN Identifier, Network Name, etc.
+ *   This file implements MAC types.
  */
 
 #include "mac_types.hpp"
@@ -110,80 +110,6 @@
     return string;
 }
 
-ExtendedPanId::InfoString ExtendedPanId::ToString(void) const
-{
-    InfoString string;
-
-    string.AppendHexBytes(m8, sizeof(ExtendedPanId));
-
-    return string;
-}
-
-uint8_t NameData::CopyTo(char *aBuffer, uint8_t aMaxSize) const
-{
-    MutableData<kWithUint8Length> destData;
-
-    destData.Init(aBuffer, aMaxSize);
-    destData.ClearBytes();
-    IgnoreError(destData.CopyBytesFrom(*this));
-
-    return destData.GetLength();
-}
-
-NameData NetworkName::GetAsData(void) const
-{
-    return NameData(m8, static_cast<uint8_t>(StringLength(m8, kMaxSize + 1)));
-}
-
-Error NetworkName::Set(const char *aNameString)
-{
-    // When setting `NetworkName` from a string, we treat it as `NameData`
-    // with `kMaxSize + 1` chars. `NetworkName::Set(data)` will look
-    // for null char in the data (within its given size) to calculate
-    // the name's length and ensure that the name fits in `kMaxSize`
-    // chars. The `+ 1` ensures that a `aNameString` with length
-    // longer than `kMaxSize` is correctly rejected (returning error
-    // `kErrorInvalidArgs`).
-
-    Error    error;
-    NameData data(aNameString, kMaxSize + 1);
-
-    VerifyOrExit(IsValidUtf8String(aNameString), error = kErrorInvalidArgs);
-
-    error = Set(data);
-
-exit:
-    return error;
-}
-
-Error NetworkName::Set(const NameData &aNameData)
-{
-    Error    error  = kErrorNone;
-    NameData data   = aNameData;
-    uint8_t  newLen = static_cast<uint8_t>(StringLength(data.GetBuffer(), data.GetLength()));
-
-    VerifyOrExit((0 < newLen) && (newLen <= kMaxSize), error = kErrorInvalidArgs);
-
-    data.SetLength(newLen);
-
-    // Ensure the new name does not match the current one.
-    if (data.MatchesBytesIn(m8) && m8[newLen] == '\0')
-    {
-        ExitNow(error = kErrorAlready);
-    }
-
-    data.CopyBytesTo(m8);
-    m8[newLen] = '\0';
-
-exit:
-    return error;
-}
-
-bool NetworkName::operator==(const NetworkName &aOther) const
-{
-    return GetAsData() == aOther.GetAsData();
-}
-
 #if OPENTHREAD_CONFIG_MULTI_RADIO
 
 const RadioType RadioTypes::kAllRadioTypes[kNumRadioTypes] = {
diff --git a/src/core/mac/mac_types.hpp b/src/core/mac/mac_types.hpp
index d7fd1f0..483a5b9 100644
--- a/src/core/mac/mac_types.hpp
+++ b/src/core/mac/mac_types.hpp
@@ -28,7 +28,7 @@
 
 /**
  * @file
- *   This file includes definitions for MAC types such as Address, Extended PAN Identifier, Network Name, etc.
+ *   This file includes definitions for MAC types.
  */
 
 #ifndef MAC_TYPES_HPP_
@@ -42,6 +42,7 @@
 #include <openthread/link.h>
 #include <openthread/thread.h>
 
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/data.hpp"
 #include "common/equatable.hpp"
@@ -468,6 +469,8 @@
      *
      */
     KeyMaterial &operator=(const KeyMaterial &aOther);
+
+    KeyMaterial(const KeyMaterial &) = delete;
 #endif
 
     /**
@@ -522,7 +525,7 @@
     /**
      * This method converts `KeyMaterial` to a `Crypto::Key`.
      *
-     * @param[out]  A reference to a `Crypto::Key` to populate.
+     * @param[out]  aCryptoKey  A reference to a `Crypto::Key` to populate.
      *
      */
     void ConvertToCryptoKey(Crypto::Key &aCryptoKey) const;
@@ -538,8 +541,6 @@
      */
     bool operator==(const KeyMaterial &aOther) const;
 
-    KeyMaterial(const KeyMaterial &) = delete;
-
 private:
 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
     static constexpr KeyRef kInvalidKeyRef = Crypto::Storage::kInvalidKeyRef;
@@ -551,165 +552,6 @@
     void SetKey(const Key &aKey) { mKeyMaterial.mKey = aKey; }
 };
 
-/**
- * This structure represents an IEEE 802.15.4 Extended PAN Identifier.
- *
- */
-OT_TOOL_PACKED_BEGIN
-class ExtendedPanId : public otExtendedPanId, public Equatable<ExtendedPanId>, public Clearable<ExtendedPanId>
-{
-public:
-    static constexpr uint16_t kInfoStringSize = 17; ///< Max chars for the info string (`ToString()`).
-
-    /**
-     * This type defines the fixed-length `String` object returned from `ToString()`.
-     *
-     */
-    typedef String<kInfoStringSize> InfoString;
-
-    /**
-     * This method converts an address to a string.
-     *
-     * @returns An `InfoString` containing the string representation of the Extended PAN Identifier.
-     *
-     */
-    InfoString ToString(void) const;
-
-} OT_TOOL_PACKED_END;
-
-/**
- * This class represents a name string as data (pointer to a char buffer along with a length).
- *
- * @note The char array does NOT need to be null terminated.
- *
- */
-class NameData : private Data<kWithUint8Length>
-{
-    friend class NetworkName;
-
-public:
-    /**
-     * This constructor initializes the NameData object.
-     *
-     * @param[in] aBuffer   A pointer to a `char` buffer (does not need to be null terminated).
-     * @param[in] aLength   The length (number of chars) in the buffer.
-     *
-     */
-    NameData(const char *aBuffer, uint8_t aLength) { Init(aBuffer, aLength); }
-
-    /**
-     * This method returns the pointer to char buffer (not necessarily null terminated).
-     *
-     * @returns The pointer to the char buffer.
-     *
-     */
-    const char *GetBuffer(void) const { return reinterpret_cast<const char *>(GetBytes()); }
-
-    /**
-     * This method returns the length (number of chars in buffer).
-     *
-     * @returns The name length.
-     *
-     */
-    uint8_t GetLength(void) const { return Data<kWithUint8Length>::GetLength(); }
-
-    /**
-     * This method copies the name data into a given char buffer with a given size.
-     *
-     * The given buffer is cleared (`memset` to zero) before copying the name into it. The copied string
-     * in @p aBuffer is NOT necessarily null terminated.
-     *
-     * @param[out] aBuffer   A pointer to a buffer where to copy the name into.
-     * @param[in]  aMaxSize  Size of @p aBuffer (maximum number of chars to write into @p aBuffer).
-     *
-     * @returns The actual number of chars copied into @p aBuffer.
-     *
-     */
-    uint8_t CopyTo(char *aBuffer, uint8_t aMaxSize) const;
-};
-
-/**
- * This structure represents an IEEE802.15.4 Network Name.
- *
- */
-class NetworkName : public otNetworkName, public Unequatable<NetworkName>
-{
-public:
-    /**
-     * This constant specified the maximum number of chars in Network Name (excludes null char).
-     *
-     */
-    static constexpr uint8_t kMaxSize = OT_NETWORK_NAME_MAX_SIZE;
-
-    /**
-     * This constructor initializes the IEEE802.15.4 Network Name as an empty string.
-     *
-     */
-    NetworkName(void) { m8[0] = '\0'; }
-
-    /**
-     * This method gets the IEEE802.15.4 Network Name as a null terminated C string.
-     *
-     * @returns The Network Name as a null terminated C string array.
-     *
-     */
-    const char *GetAsCString(void) const { return m8; }
-
-    /**
-     * This method gets the IEEE802.15.4 Network Name as NameData.
-     *
-     * @returns The Network Name as NameData.
-     *
-     */
-    NameData GetAsData(void) const;
-
-    /**
-     * This method sets the IEEE 802.15.4 Network Name from a given null terminated C string.
-     *
-     * This method also validates that the given @p aNameString follows UTF-8 encoding and can fit in `kMaxSize`
-     * chars.
-     *
-     * @param[in] aNameString      A name C string.
-     *
-     * @retval kErrorNone          Successfully set the IEEE 802.15.4 Network Name.
-     * @retval kErrorAlready       The name is already set to the same string.
-     * @retval kErrorInvalidArgs   Given name is invalid (too long or does not follow UTF-8 encoding).
-     *
-     */
-    Error Set(const char *aNameString);
-
-    /**
-     * This method sets the IEEE 802.15.4 Network Name.
-     *
-     * @param[in]  aNameData           A reference to name data.
-     *
-     * @retval kErrorNone          Successfully set the IEEE 802.15.4 Network Name.
-     * @retval kErrorAlready       The name is already set to the same string.
-     * @retval kErrorInvalidArgs   Given name is too long.
-     *
-     */
-    Error Set(const NameData &aNameData);
-
-    /**
-     * This method overloads operator `==` to evaluate whether or not two given `NetworkName` objects are equal.
-     *
-     * @param[in]  aOther  The other `NetworkName` to compare with.
-     *
-     * @retval TRUE   If the two are equal.
-     * @retval FALSE  If the two are not equal.
-     *
-     */
-    bool operator==(const NetworkName &aOther) const;
-};
-
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-/**
- * This type represents a Thread Domain Name.
- *
- */
-typedef NetworkName DomainName;
-#endif
-
 #if OPENTHREAD_CONFIG_MULTI_RADIO
 
 /**
@@ -1020,6 +862,10 @@
  */
 
 } // namespace Mac
+
+DefineCoreType(otExtAddress, Mac::ExtAddress);
+DefineCoreType(otMacKey, Mac::Key);
+
 } // namespace ot
 
 #endif // MAC_TYPES_HPP_
diff --git a/src/core/mac/sub_mac.cpp b/src/core/mac/sub_mac.cpp
index 85b9064..7d5cccd 100644
--- a/src/core/mac/sub_mac.cpp
+++ b/src/core/mac/sub_mac.cpp
@@ -41,7 +41,7 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/random.hpp"
 #include "common/time.hpp"
 #include "mac/mac_frame.hpp"
@@ -49,6 +49,8 @@
 namespace ot {
 namespace Mac {
 
+RegisterLogModule("SubMac");
+
 SubMac::SubMac(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mRadioCaps(Get<Radio>().GetCaps())
@@ -76,6 +78,13 @@
     mRxOnWhenBackoff   = true;
     mEnergyScanMaxRssi = kInvalidRssiValue;
     mEnergyScanEndTime = Time{0};
+#if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
+    mRetxDelayBackOffExponent = kRetxDelayMinBackoffExponent;
+#endif
+
+#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
+    mRadioFilterEnabled = false;
+#endif
 
     mPrevKey.Clear();
     mCurrKey.Clear();
@@ -86,12 +95,12 @@
     mTimer.Stop();
 
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-    mCslPeriod             = 0;
-    mCslChannel            = 0;
-    mIsCslChannelSpecified = false;
-    mCslSampleTime         = TimeMicro{0};
-    mCslLastSync           = TimeMicro{0};
-    mCslState              = kCslIdle;
+    mCslPeriod     = 0;
+    mCslChannel    = 0;
+    mCslPeerShort  = 0;
+    mIsCslSampling = false;
+    mCslSampleTime = TimeMicro{0};
+    mCslLastSync   = TimeMicro{0};
     mCslTimer.Stop();
 #endif
 }
@@ -143,14 +152,14 @@
 void SubMac::SetPanId(PanId aPanId)
 {
     Get<Radio>().SetPanId(aPanId);
-    otLogDebgMac("RadioPanId: 0x%04x", aPanId);
+    LogDebg("RadioPanId: 0x%04x", aPanId);
 }
 
 void SubMac::SetShortAddress(ShortAddress aShortAddress)
 {
     mShortAddress = aShortAddress;
     Get<Radio>().SetShortAddress(mShortAddress);
-    otLogDebgMac("RadioShortAddress: 0x%04x", mShortAddress);
+    LogDebg("RadioShortAddress: 0x%04x", mShortAddress);
 }
 
 void SubMac::SetExtAddress(const ExtAddress &aExtAddress)
@@ -163,7 +172,7 @@
     address.Set(aExtAddress.m8, ExtAddress::kReverseByteOrder);
     Get<Radio>().SetExtendedAddress(address);
 
-    otLogDebgMac("RadioExtAddress: %s", mExtAddress.ToString().AsCString());
+    LogDebg("RadioExtAddress: %s", mExtAddress.ToString().AsCString());
 }
 
 void SubMac::SetPcapCallback(otLinkPcapCallback aPcapCallback, void *aCallbackContext)
@@ -192,6 +201,10 @@
 {
     Error error;
 
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+    mCslTimer.Stop();
+#endif
+
     mTimer.Stop();
     SuccessOrExit(error = Get<Radio>().Sleep());
     SuccessOrExit(error = Get<Radio>().Disable());
@@ -207,7 +220,7 @@
 
     if (error != kErrorNone)
     {
-        otLogWarnMac("RadioSleep() failed, error: %s", ErrorToString(error));
+        LogWarn("RadioSleep() failed, error: %s", ErrorToString(error));
         ExitNow();
     }
 
@@ -219,11 +232,22 @@
 
 Error SubMac::Receive(uint8_t aChannel)
 {
-    Error error = Get<Radio>().Receive(aChannel);
+    Error error;
+
+#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
+    if (mRadioFilterEnabled)
+    {
+        error = Get<Radio>().Sleep();
+    }
+    else
+#endif
+    {
+        error = Get<Radio>().Receive(aChannel);
+    }
 
     if (error != kErrorNone)
     {
-        otLogWarnMac("RadioReceive() failed, error: %s", ErrorToString(error));
+        LogWarn("RadioReceive() failed, error: %s", ErrorToString(error));
         ExitNow();
     }
 
@@ -234,42 +258,29 @@
 }
 
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-Error SubMac::CslSample(uint8_t aPanChannel)
+void SubMac::CslSample(void)
 {
-    Error error = kErrorNone;
-
-    if (!IsCslChannelSpecified())
-    {
-        mCslChannel = aPanChannel;
-    }
-
-    switch (mCslState)
-    {
-    case kCslSample:
-        error = Get<Radio>().Receive(mCslChannel);
-        break;
-    case kCslSleep:
-#if !OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE
-        error = Get<Radio>().Sleep(); // Don't actually sleep for debugging
+#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
+    VerifyOrExit(!mRadioFilterEnabled, IgnoreError(Get<Radio>().Sleep()));
 #endif
-        break;
-    case kCslIdle:
-        ExitNow(error = kErrorInvalidState);
-    default:
-        OT_ASSERT(false);
-    }
 
     SetState(kStateCslSample);
 
-exit:
-    if (error != kErrorNone)
+    if (mIsCslSampling && !RadioSupportsReceiveTiming())
     {
-        otLogWarnMac("CslSample() failed, error: %s", ErrorToString(error));
+        IgnoreError(Get<Radio>().Receive(mCslChannel));
+        ExitNow();
     }
-    return error;
-}
+
+#if !OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE
+    IgnoreError(Get<Radio>().Sleep()); // Don't actually sleep for debugging
 #endif
 
+exit:
+    return;
+}
+#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+
 void SubMac::HandleReceiveDone(RxFrame *aFrame, Error aError)
 {
     if (mPcapCallback && (aFrame != nullptr) && (aError == kErrorNone))
@@ -293,15 +304,20 @@
 
 #if OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE
         // Split the log into two lines for RTT to output
-        otLogDebgMac("Received frame in state (SubMac %s, CSL %s), timestamp %u", StateToString(mState),
-                     CslStateToString(mCslState), static_cast<uint32_t>(aFrame->mInfo.mRxInfo.mTimestamp));
-        otLogDebgMac("Target sample start time %u, time drift %d", mCslSampleTime.GetValue(),
-                     static_cast<uint32_t>(aFrame->mInfo.mRxInfo.mTimestamp) - mCslSampleTime.GetValue());
+        LogDebg("Received frame in state (SubMac %s, CSL %s), timestamp %u", StateToString(mState),
+                mIsCslSampling ? "CslSample" : "CslSleep", static_cast<uint32_t>(aFrame->mInfo.mRxInfo.mTimestamp));
+        LogDebg("Target sample start time %u, time drift %d", mCslSampleTime.GetValue(),
+                static_cast<uint32_t>(aFrame->mInfo.mRxInfo.mTimestamp) - mCslSampleTime.GetValue());
 #endif
     }
-#endif
+#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
 
-    mCallbacks.ReceiveDone(aFrame, aError);
+#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
+    if (!mRadioFilterEnabled)
+#endif
+    {
+        mCallbacks.ReceiveDone(aFrame, aError);
+    }
 }
 
 Error SubMac::Send(void)
@@ -316,6 +332,9 @@
     case kStateCslTransmit:
 #endif
     case kStateTransmit:
+#if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
+    case kStateDelayBeforeRetx:
+#endif
     case kStateEnergyScan:
         ExitNow(error = kErrorInvalidState);
         OT_UNREACHABLE_CODE(break);
@@ -328,9 +347,23 @@
         break;
     }
 
+#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
+    if (mRadioFilterEnabled)
+    {
+        mCallbacks.TransmitDone(mTransmitFrame, nullptr, mTransmitFrame.GetAckRequest() ? kErrorNoAck : kErrorNone);
+        ExitNow();
+    }
+#endif
+
     ProcessTransmitSecurity();
+
     mCsmaBackoffs    = 0;
     mTransmitRetries = 0;
+
+#if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
+    mRetxDelayBackOffExponent = kRetxDelayMinBackoffExponent;
+#endif
+
     StartCsmaBackoff();
 
 exit:
@@ -380,8 +413,7 @@
 
 void SubMac::StartCsmaBackoff(void)
 {
-    uint32_t backoff;
-    uint32_t backoffExponent = kMinBE + mTransmitRetries + mCsmaBackoffs;
+    uint8_t backoffExponent = kCsmaMinBe + mCsmaBackoffs;
 
 #if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
     if (mTransmitFrame.mInfo.mTxInfo.mTxDelay != 0)
@@ -410,17 +442,28 @@
         ExitNow();
     }
 #endif // !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+
     SetState(kStateCsmaBackoff);
 
     VerifyOrExit(ShouldHandleCsmaBackOff(), BeginTransmit());
 
-    if (backoffExponent > kMaxBE)
+    if (backoffExponent > kCsmaMaxBe)
     {
-        backoffExponent = kMaxBE;
+        backoffExponent = kCsmaMaxBe;
     }
 
-    backoff = Random::NonCrypto::GetUint32InRange(0, static_cast<uint32_t>(1UL << backoffExponent));
-    backoff *= (kUnitBackoffPeriod * OT_RADIO_SYMBOL_TIME);
+    StartTimerForBackoff(backoffExponent);
+
+exit:
+    return;
+}
+
+void SubMac::StartTimerForBackoff(uint8_t aBackoffExponent)
+{
+    uint32_t backoff;
+
+    backoff = Random::NonCrypto::GetUint32InRange(0, static_cast<uint32_t>(1UL << aBackoffExponent));
+    backoff *= (kUnitBackoffPeriod * Radio::kSymbolTime);
 
     if (mRxOnWhenBackoff)
     {
@@ -437,16 +480,18 @@
     mTimer.Start(backoff / 1000UL);
 #endif
 
-exit:
-    return;
+#if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
+    if (mState == kStateDelayBeforeRetx)
+    {
+        LogDebg("Delaying retx for %u usec (be=%d)", backoff, aBackoffExponent);
+    }
+#endif
 }
 
 void SubMac::BeginTransmit(void)
 {
     Error error;
 
-    OT_UNUSED_VARIABLE(error);
-
 #if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
     VerifyOrExit(mState == kStateCsmaBackoff || mState == kStateCslTransmit);
 #else
@@ -466,12 +511,14 @@
     }
 
     error = Get<Radio>().Transmit(mTransmitFrame);
+
     if (error == kErrorInvalidState && mTransmitFrame.mInfo.mTxInfo.mTxDelay > 0)
     {
         // Platform `transmit_at` fails and we send the frame directly.
         mTransmitFrame.mInfo.mTxInfo.mTxDelay         = 0;
         mTransmitFrame.mInfo.mTxInfo.mTxDelayBaseTime = 0;
-        error                                         = Get<Radio>().Transmit(mTransmitFrame);
+
+        error = Get<Radio>().Transmit(mTransmitFrame);
     }
 
     SuccessOrAssert(error);
@@ -559,6 +606,17 @@
     {
         mTransmitRetries++;
         aFrame.SetIsARetransmission(true);
+
+#if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
+        if (aError == kErrorNoAck)
+        {
+            SetState(kStateDelayBeforeRetx);
+            StartTimerForBackoff(mRetxDelayBackOffExponent);
+            mRetxDelayBackOffExponent = OT_MIN(mRetxDelayBackOffExponent + 1, kRetxDelayMaxBackoffExponent);
+            ExitNow();
+        }
+#endif
+
         StartCsmaBackoff();
         ExitNow();
     }
@@ -606,7 +664,20 @@
 
 int8_t SubMac::GetRssi(void) const
 {
-    return Get<Radio>().GetRssi();
+    int8_t rssi;
+
+#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
+    if (mRadioFilterEnabled)
+    {
+        rssi = kInvalidRssiValue;
+    }
+    else
+#endif
+    {
+        rssi = Get<Radio>().GetRssi();
+    }
+
+    return rssi;
 }
 
 int8_t SubMac::GetNoiseFloor(void)
@@ -626,6 +697,9 @@
 #if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
     case kStateCslTransmit:
 #endif
+#if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
+    case kStateDelayBeforeRetx:
+#endif
     case kStateEnergyScan:
         ExitNow(error = kErrorInvalidState);
 
@@ -637,6 +711,10 @@
         break;
     }
 
+#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
+    VerifyOrExit(!mRadioFilterEnabled, HandleEnergyScanDone(kInvalidRssiValue));
+#endif
+
     if (RadioSupportsEnergyScan())
     {
         IgnoreError(Get<Radio>().EnergyScan(aScanChannel, aScanDuration));
@@ -713,11 +791,17 @@
         break;
 
     case kStateTransmit:
-        otLogDebgMac("Ack timer timed out");
+        LogDebg("Ack timer timed out");
         IgnoreError(Get<Radio>().Receive(mTransmitFrame.GetChannel()));
         HandleTransmitDone(mTransmitFrame, nullptr, kErrorNoAck);
         break;
 
+#if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
+    case kStateDelayBeforeRetx:
+        StartCsmaBackoff();
+        break;
+#endif
+
     case kStateEnergyScan:
         SampleRssi();
         break;
@@ -839,7 +923,7 @@
 {
     if (mState != aState)
     {
-        otLogDebgMac("RadioState: %s -> %s", StateToString(mState), StateToString(aState));
+        LogDebg("RadioState: %s -> %s", StateToString(mState), StateToString(aState));
         mState = aState;
     }
 }
@@ -917,11 +1001,14 @@
         "CsmaBackoff", // (3) kStateCsmaBackoff
         "Transmit",    // (4) kStateTransmit
         "EnergyScan",  // (5) kStateEnergyScan
+#if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
+        "DelayBeforeRetx", // (6) kStateDelayBeforeRetx
+#endif
 #if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
-        "CslTransmit", // (6) kStateCslTransmit
+        "CslTransmit", // (7) kStateCslTransmit
 #endif
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-        "CslSample", // (7) kStateCslSample
+        "CslSample", // (8) kStateCslSample
 #endif
     };
 
@@ -931,77 +1018,61 @@
     static_assert(kStateCsmaBackoff == 3, "kStateCsmaBackoff value is not correct");
     static_assert(kStateTransmit == 4, "kStateTransmit value is not correct");
     static_assert(kStateEnergyScan == 5, "kStateEnergyScan value is not correct");
+
+#if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
+    static_assert(kStateDelayBeforeRetx == 6, "kStateDelayBeforeRetx value is not correct");
 #if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+    static_assert(kStateCslTransmit == 7, "kStateCslTransmit value is not correct");
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+    static_assert(kStateCslSample == 8, "kStateCslSample value is not correct");
+#endif
+#elif OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+    static_assert(kStateCslSample == 7, "kStateCslSample value is not correct");
+#endif
+
+#elif !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
     static_assert(kStateCslTransmit == 6, "kStateCslTransmit value is not correct");
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
     static_assert(kStateCslSample == 7, "kStateCslSample value is not correct");
 #endif
-#else
-#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+#elif OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
     static_assert(kStateCslSample == 6, "kStateCslSample value is not correct");
 #endif
-#endif
 
     return kStateStrings[aState];
 }
 
-#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-const char *SubMac::CslStateToString(CslState aCslState)
-{
-    static const char *const kCslStateStrings[] = {
-        "CslIdle",   // (0) kCslIdle
-        "CslSample", // (1) kCslSample
-        "CslSleep",  // (2) kCslSleep
-    };
-
-    static_assert(kCslIdle == 0, "kCslIdle value is incorrect");
-    static_assert(kCslSample == 1, "kCslSample value is incorrect");
-    static_assert(kCslSleep == 2, "kCslSleep value is incorrect");
-
-    return kCslStateStrings[aCslState];
-}
-#endif
-
 // LCOV_EXCL_STOP
 
 //---------------------------------------------------------------------------------------------------------------------
 // CSL Receiver methods
 
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-void SubMac::SetCslChannel(uint8_t aChannel)
+bool SubMac::UpdateCsl(uint16_t aPeriod, uint8_t aChannel, otShortAddress aShortAddr, const otExtAddress *aExtAddr)
 {
+    bool diffPeriod  = aPeriod != mCslPeriod;
+    bool diffChannel = aChannel != mCslChannel;
+    bool diffPeer    = aShortAddr != mCslPeerShort;
+    bool retval      = diffPeriod || diffChannel || diffPeer;
+
+    VerifyOrExit(retval);
     mCslChannel = aChannel;
-}
 
-void SubMac::SetCslPeriod(uint16_t aPeriod)
-{
-    VerifyOrExit(mCslPeriod != aPeriod);
-
-    mCslPeriod = aPeriod;
+    VerifyOrExit(diffPeriod || diffPeer);
+    mCslPeriod    = aPeriod;
+    mCslPeerShort = aShortAddr;
+    IgnoreError(Get<Radio>().EnableCsl(aPeriod, aShortAddr, aExtAddr));
 
     mCslTimer.Stop();
-
     if (mCslPeriod > 0)
     {
         mCslSampleTime = TimeMicro(static_cast<uint32_t>(otPlatRadioGetNow(&GetInstance())));
-        mCslState      = kCslSleep;
+        mIsCslSampling = false;
         HandleCslTimer();
     }
-    else
-    {
-        mCslState = kCslIdle;
-
-        if (mState == kStateCslSample)
-        {
-            IgnoreError(Get<Radio>().Sleep());
-            SetState(kStateSleep);
-        }
-    }
-
-    otLogDebgMac("CSL Period: %u", mCslPeriod);
 
 exit:
-    return;
+    return retval;
 }
 
 void SubMac::HandleCslTimer(Timer &aTimer)
@@ -1025,81 +1096,63 @@
 
     GetCslWindowEdges(timeAhead, timeAfter);
 
-    switch (mCslState)
+    if (mIsCslSampling)
     {
-    case kCslSample:
-        mCslState = kCslSleep;
-
+        mIsCslSampling = false;
         mCslTimer.FireAt(mCslSampleTime - timeAhead);
         if (mState == kStateCslSample)
         {
 #if !OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE
             IgnoreError(Get<Radio>().Sleep()); // Don't actually sleep for debugging
 #endif
-            otLogDebgMac("CSL sleep %u", mCslTimer.GetNow().GetValue());
+            LogDebg("CSL sleep %u", mCslTimer.GetNow().GetValue());
         }
-        break;
-
-    case kCslSleep:
-        mCslSampleTime += periodUs;
-
+    }
+    else
+    {
         if (RadioSupportsReceiveTiming())
         {
+            mCslSampleTime += periodUs;
             mCslTimer.FireAt(mCslSampleTime - timeAhead);
             timeAhead -= kCslReceiveTimeAhead;
         }
         else
         {
             mCslTimer.FireAt(mCslSampleTime + timeAfter);
-            mCslState = kCslSample;
+            mIsCslSampling = true;
+            mCslSampleTime += periodUs;
         }
 
         Get<Radio>().UpdateCslSampleTime(mCslSampleTime.GetValue());
-        if (mState == kStateCslSample)
+
+        if (RadioSupportsReceiveTiming() && (mState != kStateDisabled))
         {
-            if (RadioSupportsReceiveTiming())
-            {
-                IgnoreError(Get<Radio>().ReceiveAt(mCslChannel, mCslSampleTime.GetValue() - periodUs - timeAhead,
-                                                   timeAhead + timeAfter));
-            }
-            else
-            {
-                IgnoreError(Get<Radio>().Receive(mCslChannel));
-                otLogDebgMac("CSL sample %u, duration %u", mCslTimer.GetNow().GetValue(), timeAhead + timeAfter);
-            }
+            IgnoreError(Get<Radio>().ReceiveAt(mCslChannel, mCslSampleTime.GetValue() - periodUs - timeAhead,
+                                               timeAhead + timeAfter));
         }
-        break;
-
-    case kCslIdle:
-        break;
-
-    default:
-        OT_ASSERT(false);
-        break;
+        else if (mState == kStateCslSample)
+        {
+            IgnoreError(Get<Radio>().Receive(mCslChannel));
+            LogDebg("CSL sample %u, duration %u", mCslTimer.GetNow().GetValue(), timeAhead + timeAfter);
+        }
     }
 }
 
-void SubMac::GetCslWindowEdges(uint32_t &ahead, uint32_t &after)
+void SubMac::GetCslWindowEdges(uint32_t &aAhead, uint32_t &aAfter)
 {
     uint32_t semiPeriod = mCslPeriod * kUsPerTenSymbols / 2;
-    uint64_t curTime    = otPlatRadioGetNow(&GetInstance());
-    uint64_t elapsed;
+    uint32_t curTime    = static_cast<uint32_t>(otPlatRadioGetNow(&GetInstance()));
+    uint32_t elapsed;
     uint32_t semiWindow;
 
-    if (mCslLastSync.GetValue() > curTime)
-    {
-        elapsed = UINT64_MAX - mCslLastSync.GetValue() + curTime;
-    }
-    else
-    {
-        elapsed = curTime - mCslLastSync.GetValue();
-    }
+    elapsed = curTime - mCslLastSync.GetValue();
 
-    semiWindow = static_cast<uint32_t>(elapsed * (Get<Radio>().GetCslAccuracy() + mCslParentAccuracy) / 1000000);
+    semiWindow = static_cast<uint32_t>(static_cast<uint64_t>(elapsed) *
+                                       (Get<Radio>().GetCslAccuracy() + mCslParentAccuracy) / 1000000);
     semiWindow += mCslParentUncert * kUsPerUncertUnit;
 
-    ahead = (semiWindow + kCslReceiveTimeAhead > semiPeriod) ? semiPeriod : semiWindow + kCslReceiveTimeAhead;
-    after = (semiWindow + kMinCslWindow > semiPeriod) ? semiPeriod : semiWindow + kMinCslWindow;
+    aAhead = (semiWindow + kCslReceiveTimeAhead > semiPeriod) ? semiPeriod : semiWindow + kCslReceiveTimeAhead;
+    aAfter = (semiWindow + kMinCslWindow > semiPeriod) ? semiPeriod : semiWindow + kMinCslWindow;
 }
 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
 
diff --git a/src/core/mac/sub_mac.hpp b/src/core/mac/sub_mac.hpp
index 64b7a3a..8eccfe9 100644
--- a/src/core/mac/sub_mac.hpp
+++ b/src/core/mac/sub_mac.hpp
@@ -128,7 +128,7 @@
         /**
          * This method notifies user of `SubMac` of a received frame.
          *
-         * @param[in]  aFrame    A pointer to the received frame or nullptr if the receive operation failed.
+         * @param[in]  aFrame    A pointer to the received frame or `nullptr` if the receive operation failed.
          * @param[in]  aError    kErrorNone when successfully received a frame,
          *                       kErrorAbort when reception was aborted and a frame was not received,
          *                       kErrorNoBufs when a frame could not be received due to lack of rx buffer space.
@@ -156,7 +156,7 @@
          * of a frame transmission, this method is invoked on all frame transmission attempts.
          *
          * @param[in] aFrame      The transmitted frame.
-         * @param[in] aAckFrame   A pointer to the ACK frame, or nullptr if no ACK was received.
+         * @param[in] aAckFrame   A pointer to the ACK frame, or `nullptr` if no ACK was received.
          * @param[in] aError      kErrorNone when the frame was transmitted successfully,
          *                        kErrorNoAck when the frame was transmitted but no ACK was received,
          *                        kErrorChannelAccessFailure tx failed due to activity on the channel,
@@ -177,7 +177,7 @@
          * the received ACK frame.
          *
          * @param[in]  aFrame     The transmitted frame.
-         * @param[in]  aAckFrame  A pointer to the ACK frame, nullptr if no ACK was received.
+         * @param[in]  aAckFrame  A pointer to the ACK frame, `nullptr` if no ACK was received.
          * @param[in]  aError     kErrorNone when the frame was transmitted,
          *                        kErrorNoAck when the frame was transmitted but no ACK was received,
          *                        kErrorChannelAccessFailure tx failed due to activity on the channel,
@@ -274,7 +274,7 @@
      * This method registers a callback to provide received packet capture for IEEE 802.15.4 frames.
      *
      * @param[in]  aPcapCallback     A pointer to a function that is called when receiving an IEEE 802.15.4 link frame
-     *                                or nullptr to disable the callback.
+     *                               or `nullptr` to disable the callback.
      * @param[in]  aCallbackContext  A pointer to application-specific context.
      *
      */
@@ -379,6 +379,7 @@
      * @param[in] aScanDuration  The duration, in milliseconds, for the channel to be scanned.
      *
      * @retval kErrorNone            Successfully started scanning the channel.
+     * @retval kErrorBusy            The radio is performing energy scanning.
      * @retval kErrorInvalidState    The radio was disabled or transmitting.
      * @retval kErrorNotImplemented  Energy scan is not supported (applicable in link-raw/radio mode only).
      *
@@ -394,69 +395,27 @@
     int8_t GetNoiseFloor(void);
 
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-
     /**
-     * This method lets `SubMac` start CSL sample.
+     * This method configures CSL parameters in 'SubMac'.
      *
-     * `SubMac` would switch the radio state between `Receive` and `Sleep` according the CSL timer. When CslSample is
-     * started, `mState` will become `kStateCslSample`. But it could be doing `Sleep` or `Receive` at this moment
-     * (depending on `mCslState`).
+     * @param[in]  aPeriod    The CSL period.
+     * @param[in]  aChannel   The CSL channel.
+     * @param[in]  aShortAddr The short source address of CSL receiver's peer.
+     * @param[in]  aExtAddr   The extended source address of CSL receiver's peer.
      *
-     * @param[in]  aPanChannel  The current phy channel used by the device. This param will only take effect when CSL
-     *                          channel hasn't been explicitly specified.
-     *
-     * @retval kErrorNone          Successfully entered CSL operation (sleep or receive according to CSL timer).
-     * @retval kErrorBusy          The radio was transmitting.
-     * @retval kErrorInvalidState  The radio was disabled.
+     * @retval  TRUE if CSL Period or CSL Channel changed.
+     * @retval  FALSE if CSL Period and CSL Channel did not change.
      *
      */
-    Error CslSample(uint8_t aPanChannel);
+    bool UpdateCsl(uint16_t aPeriod, uint8_t aChannel, otShortAddress aShortAddr, const otExtAddress *aExtAddr);
 
     /**
-     * This method gets the CSL channel.
+     * This method lets `SubMac` start CSL sample mode given a configured non-zero CSL period.
      *
-     * @returns CSL channel.
+     * `SubMac` would switch the radio state between `Receive` and `Sleep` according the CSL timer.
      *
      */
-    uint8_t GetCslChannel(void) const { return mCslChannel; }
-
-    /**
-     * This method sets the CSL channel.
-     *
-     * @param[in]  aChannel  The CSL channel. `0` to set CSL Channel unspecified.
-     *
-     */
-    void SetCslChannel(uint8_t aChannel);
-
-    /**
-     * This method indicates if CSL channel has been explicitly specified by the upper layer.
-     *
-     * @returns If CSL channel has been specified.
-     *
-     */
-    bool IsCslChannelSpecified(void) const { return mIsCslChannelSpecified; }
-
-    /**
-     * This method sets the flag representing if CSL channel has been specified.
-     *
-     */
-    void SetCslChannelSpecified(bool aIsSpecified) { mIsCslChannelSpecified = aIsSpecified; }
-
-    /**
-     * This method gets the CSL period.
-     *
-     * @returns CSL period.
-     *
-     */
-    uint16_t GetCslPeriod(void) const { return mCslPeriod; }
-
-    /**
-     * This method sets the CSL period.
-     *
-     * @param[in]  aPeriod  The CSL period in 10 symbols.
-     *
-     */
-    void SetCslPeriod(uint16_t aPeriod);
+    void CslSample(void);
 
     /**
      * This method returns CSL parent clock accuracy, in ± ppm.
@@ -548,19 +507,47 @@
      */
     void SetFrameCounter(uint32_t aFrameCounter);
 
+#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
+    /**
+     * This method enables/disables the radio filter.
+     *
+     * When radio filter is enabled, radio is put to sleep instead of receive (to ensure device does not receive any
+     * frame and/or potentially send ack). Also the frame transmission requests return immediately without sending the
+     * frame over the air (return "no ack" error if ack is requested, otherwise return success).
+     *
+     * @param[in] aFilterEnabled    TRUE to enable radio filter, FALSE to disable.
+     *
+     */
+    void SetRadioFilterEnabled(bool aFilterEnabled) { mRadioFilterEnabled = aFilterEnabled; }
+
+    /**
+     * This method indicates whether the radio filter is enabled or not.
+     *
+     * @retval TRUE   If the radio filter is enabled.
+     * @retval FALSE  If the radio filter is disabled.
+     *
+     */
+    bool IsRadioFilterEnabled(void) const { return mRadioFilterEnabled; }
+#endif
+
 private:
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
     static void HandleCslTimer(Timer &aTimer);
     void        HandleCslTimer(void);
-    void        GetCslWindowEdges(uint32_t &ahead, uint32_t &after);
+    void        GetCslWindowEdges(uint32_t &aAhead, uint32_t &aAfter);
 #endif
 
-    static constexpr uint8_t  kMinBE             = 3;   // macMinBE (IEEE 802.15.4-2006).
-    static constexpr uint8_t  kMaxBE             = 5;   // macMaxBE (IEEE 802.15.4-2006).
+    static constexpr uint8_t  kCsmaMinBe         = 3;   // macMinBE (IEEE 802.15.4-2006).
+    static constexpr uint8_t  kCsmaMaxBe         = 5;   // macMaxBE (IEEE 802.15.4-2006).
     static constexpr uint32_t kUnitBackoffPeriod = 20;  // Number of symbols (IEEE 802.15.4-2006).
     static constexpr uint32_t kAckTimeout        = 16;  // Timeout for waiting on an ACK (in msec).
     static constexpr uint32_t kCcaSampleInterval = 128; // CCA sample interval, 128 usec.
 
+#if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
+    static constexpr uint8_t kRetxDelayMinBackoffExponent = OPENTHREAD_CONFIG_MAC_RETX_DELAY_MIN_BACKOFF_EXPONENT;
+    static constexpr uint8_t kRetxDelayMaxBackoffExponent = OPENTHREAD_CONFIG_MAC_RETX_DELAY_MAX_BACKOFF_EXPONENT;
+#endif
+
 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
     static constexpr uint32_t kEnergyScanRssiSampleInterval = 128; // RSSI sample interval for energy scan, 128 usec
 #else
@@ -575,6 +562,9 @@
         kStateCsmaBackoff, // CSMA backoff before transmission.
         kStateTransmit,    // Radio is transmitting.
         kStateEnergyScan,  // Energy scan.
+#if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
+        kStateDelayBeforeRetx, // Delay before retx
+#endif
 #if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
         kStateCslTransmit, // CSL transmission.
 #endif
@@ -591,12 +581,6 @@
     // CSL receivers would wake up `kCslReceiveTimeAhead` earlier
     // than expected sample window. The value is in usec.
     static constexpr uint32_t kCslReceiveTimeAhead = OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD;
-
-    enum CslState : uint8_t{
-        kCslIdle,   // CSL receiver is not started.
-        kCslSample, // Sampling CSL channel.
-        kCslSleep,  // Radio in sleep.
-    };
 #endif
 
     /**
@@ -627,6 +611,7 @@
     void ProcessTransmitSecurity(void);
     void SignalFrameCounterUsed(uint32_t aFrameCounter);
     void StartCsmaBackoff(void);
+    void StartTimerForBackoff(uint8_t aBackoffExponent);
     void BeginTransmit(void);
     void SampleRssi(void);
 
@@ -641,17 +626,17 @@
 
     void               SetState(State aState);
     static const char *StateToString(State aState);
-#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-    static const char *CslStateToString(CslState aCslState);
-#endif
 
-    otRadioCaps        mRadioCaps;
-    State              mState;
-    uint8_t            mCsmaBackoffs;
-    uint8_t            mTransmitRetries;
-    ShortAddress       mShortAddress;
-    ExtAddress         mExtAddress;
-    bool               mRxOnWhenBackoff;
+    otRadioCaps  mRadioCaps;
+    State        mState;
+    uint8_t      mCsmaBackoffs;
+    uint8_t      mTransmitRetries;
+    ShortAddress mShortAddress;
+    ExtAddress   mExtAddress;
+    bool         mRxOnWhenBackoff : 1;
+#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
+    bool mRadioFilterEnabled : 1;
+#endif
     int8_t             mEnergyScanMaxRssi;
     TimeMilli          mEnergyScanEndTime;
     TxFrame &          mTransmitFrame;
@@ -663,6 +648,9 @@
     KeyMaterial        mNextKey;
     uint32_t           mFrameCounter;
     uint8_t            mKeyId;
+#if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
+    uint8_t mRetxDelayBackOffExponent;
+#endif
 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
     TimerMicro mTimer;
 #else
@@ -670,14 +658,15 @@
 #endif
 
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-    uint16_t   mCslPeriod;                 // The CSL sample period, in units of 10 symbols (160 microseconds).
-    uint8_t    mCslChannel : 7;            // The CSL sample channel (only when `mIsCslChannelSpecified` is `true`).
-    uint8_t    mIsCslChannelSpecified : 1; // Whether the CSL channel was explicitly set
-    TimeMicro  mCslSampleTime;             // The CSL sample time of the current period.
-    TimeMicro  mCslLastSync;               // The timestamp of the last successful CSL synchronization.
-    uint8_t    mCslParentAccuracy;         // Drift of timer used for scheduling CSL tx by the parent, in ± ppm.
-    uint8_t    mCslParentUncert;           // Uncertainty of the scheduling CSL of tx by the parent, in ±10 us units.
-    CslState   mCslState;
+    uint16_t mCslPeriod;      // The CSL sample period, in units of 10 symbols (160 microseconds).
+    uint8_t  mCslChannel : 7; // The CSL sample channel.
+    bool mIsCslSampling : 1;  // Indicates that the radio is receiving in CSL state for platforms not supporting delayed
+                              // reception.
+    uint16_t   mCslPeerShort; // The CSL peer short address.
+    TimeMicro  mCslSampleTime;     // The CSL sample time of the current period.
+    TimeMicro  mCslLastSync;       // The timestamp of the last successful CSL synchronization.
+    uint8_t    mCslParentAccuracy; // Drift of timer used for scheduling CSL tx by the parent, in ± ppm.
+    uint8_t    mCslParentUncert;   // Uncertainty of the scheduling CSL of tx by the parent, in ±10 us units.
     TimerMicro mCslTimer;
 #endif
 };
diff --git a/src/core/meshcop/announce_begin_client.cpp b/src/core/meshcop/announce_begin_client.cpp
index 8b707d2..b1bb699 100644
--- a/src/core/meshcop/announce_begin_client.cpp
+++ b/src/core/meshcop/announce_begin_client.cpp
@@ -40,7 +40,7 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "meshcop/meshcop.hpp"
 #include "meshcop/meshcop_tlvs.hpp"
 #include "thread/thread_netif.hpp"
@@ -48,6 +48,8 @@
 
 namespace ot {
 
+RegisterLogModule("MeshCoP");
+
 AnnounceBeginClient::AnnounceBeginClient(Instance &aInstance)
     : InstanceLocator(aInstance)
 {
@@ -60,11 +62,11 @@
 {
     Error                   error = kErrorNone;
     MeshCoP::ChannelMaskTlv channelMask;
-    Ip6::MessageInfo        messageInfo;
+    Tmf::MessageInfo        messageInfo(GetInstance());
     Coap::Message *         message = nullptr;
 
     VerifyOrExit(Get<MeshCoP::Commissioner>().IsActive(), error = kErrorInvalidState);
-    VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
+    VerifyOrExit((message = Get<Tmf::Agent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = message->InitAsPost(aAddress, UriPath::kAnnounceBegin));
     SuccessOrExit(error = message->SetPayloadMarker());
@@ -79,13 +81,11 @@
     SuccessOrExit(error = Tlv::Append<MeshCoP::CountTlv>(*message, aCount));
     SuccessOrExit(error = Tlv::Append<MeshCoP::PeriodTlv>(*message, aPeriod));
 
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.SetPeerAddr(aAddress);
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
+    messageInfo.SetSockAddrToRlocPeerAddrTo(aAddress);
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
 
-    otLogInfoMeshCoP("sent announce begin query");
+    LogInfo("sent announce begin query");
 
 exit:
     FreeMessageOnError(message, error);
diff --git a/src/core/meshcop/border_agent.cpp b/src/core/meshcop/border_agent.cpp
index 3f5f60a..e10a79d 100644
--- a/src/core/meshcop/border_agent.cpp
+++ b/src/core/meshcop/border_agent.cpp
@@ -37,9 +37,10 @@
 
 #include "coap/coap_message.hpp"
 #include "common/as_core_type.hpp"
+#include "common/heap.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "meshcop/meshcop.hpp"
 #include "meshcop/meshcop_tlvs.hpp"
 #include "thread/thread_netif.hpp"
@@ -49,6 +50,8 @@
 namespace ot {
 namespace MeshCoP {
 
+RegisterLogModule("BorderAgent");
+
 namespace {
 constexpr uint16_t kBorderAgentUdpPort = OPENTHREAD_CONFIG_BORDER_AGENT_UDP_PORT; ///< UDP port of border agent service.
 }
@@ -114,7 +117,7 @@
     Coap::CoapSecure &coaps   = Get<Coap::CoapSecure>();
     Coap::Message *   message = nullptr;
 
-    VerifyOrExit((message = NewMeshCoPMessage(coaps)) != nullptr, error = kErrorNoBufs);
+    VerifyOrExit((message = coaps.NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
     SuccessOrExit(error = aForwardContext.ToHeader(*message, CoapCodeFromError(aError)));
     SuccessOrExit(error = coaps.SendMessage(*message, coaps.GetMessageInfo()));
 
@@ -129,7 +132,7 @@
     Coap::CoapSecure &coaps   = Get<Coap::CoapSecure>();
     Coap::Message *   message = nullptr;
 
-    VerifyOrExit((message = NewMeshCoPMessage(coaps)) != nullptr, error = kErrorNoBufs);
+    VerifyOrExit((message = coaps.NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
 
     if (aRequest.IsNonConfirmable() || aSeparate)
     {
@@ -172,7 +175,7 @@
     Error          error;
 
     SuccessOrExit(error = aResult);
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Coap::CoapSecure>())) != nullptr, error = kErrorNoBufs);
+    VerifyOrExit((message = Get<Coap::CoapSecure>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
 
     if (aForwardContext.IsPetition() && aResponse->GetCode() == Coap::kCodeChanged)
     {
@@ -190,8 +193,8 @@
             Get<ThreadNetif>().AddUnicastAddress(mCommissionerAloc);
             IgnoreError(Get<Ip6::Udp>().AddReceiver(mUdpReceiver));
 
-            otLogInfoMeshCoP("commissioner accepted: session ID=%d, ALOC=%s", sessionId,
-                             mCommissionerAloc.GetAddress().ToString().AsCString());
+            LogInfo("commissioner accepted: session ID=%d, ALOC=%s", sessionId,
+                    mCommissionerAloc.GetAddress().ToString().AsCString());
         }
     }
 
@@ -210,12 +213,12 @@
     {
         FreeMessage(message);
 
-        otLogWarnMeshCoP("Commissioner request[%hu] failed: %s", aForwardContext.GetMessageId(), ErrorToString(error));
+        LogWarn("Commissioner request[%hu] failed: %s", aForwardContext.GetMessageId(), ErrorToString(error));
 
         SendErrorMessage(aForwardContext, error);
     }
 
-    Instance::HeapFree(&aForwardContext);
+    Heap::Free(&aForwardContext);
 }
 
 template <Coap::Resource BorderAgent::*aResource>
@@ -300,7 +303,7 @@
     VerifyOrExit(aEvents.ContainsAny(kEventThreadRoleChanged | kEventCommissionerStateChanged));
 
 #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
-    VerifyOrExit(Get<MeshCoP::Commissioner>().IsDisabled());
+    VerifyOrExit(Get<Commissioner>().IsDisabled());
 #endif
 
     if (Get<Mle::MleRouter>().IsAttached())
@@ -342,7 +345,7 @@
     SuccessOrExit(error = Get<Ip6::Udp>().SendDatagram(*message, messageInfo, Ip6::kProtoUdp));
     mUdpProxyPort = tlv.GetSourcePort();
 
-    otLogInfoMeshCoP("Proxy transmit sent to %s", messageInfo.GetPeerAddr().ToString().AsCString());
+    LogInfo("Proxy transmit sent to %s", messageInfo.GetPeerAddr().ToString().AsCString());
 
 exit:
     FreeMessageOnError(message, error);
@@ -359,11 +362,8 @@
 
     VerifyOrExit(aMessage.GetLength() > 0, error = kErrorNone);
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Coap::CoapSecure>())) != nullptr, error = kErrorNoBufs);
-
-    message->InitAsNonConfirmablePost();
-    SuccessOrExit(error = message->AppendUriPathOptions(UriPath::kProxyRx));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Coap::CoapSecure>().NewPriorityNonConfirmablePostMessage(UriPath::kProxyRx);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     {
         UdpEncapsulationTlv tlv;
@@ -385,7 +385,7 @@
 
     SuccessOrExit(error = Get<Coap::CoapSecure>().SendMessage(*message, Get<Coap::CoapSecure>().GetMessageInfo()));
 
-    otLogInfoMeshCoP("Sent to commissioner on %s", UriPath::kProxyRx);
+    LogInfo("Sent to commissioner on %s", UriPath::kProxyRx);
 
 exit:
     FreeMessageOnError(message, error);
@@ -400,18 +400,12 @@
     Error          error;
 
     VerifyOrExit(aMessage.IsNonConfirmablePostRequest(), error = kErrorDrop);
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Coap::CoapSecure>())) != nullptr, error = kErrorNoBufs);
 
-    message->InitAsNonConfirmablePost();
-    SuccessOrExit(error = message->AppendUriPathOptions(UriPath::kRelayRx));
-
-    if (aMessage.GetLength() > aMessage.GetOffset())
-    {
-        SuccessOrExit(error = message->SetPayloadMarker());
-    }
+    message = Get<Coap::CoapSecure>().NewPriorityNonConfirmablePostMessage(UriPath::kRelayRx);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = ForwardToCommissioner(*message, aMessage));
-    otLogInfoMeshCoP("Sent to commissioner on %s", UriPath::kRelayRx);
+    LogInfo("Sent to commissioner on %s", UriPath::kRelayRx);
 
 exit:
     FreeMessageOnError(message, error);
@@ -429,7 +423,7 @@
     SuccessOrExit(error =
                       Get<Coap::CoapSecure>().SendMessage(aForwardMessage, Get<Coap::CoapSecure>().GetMessageInfo()));
 
-    otLogInfoMeshCoP("Sent to commissioner");
+    LogInfo("Sent to commissioner");
 
 exit:
     LogError("send to commissioner", error);
@@ -453,31 +447,26 @@
     Error            error = kErrorNone;
     uint16_t         joinerRouterRloc;
     Coap::Message *  message = nullptr;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
     uint16_t         offset = 0;
 
     VerifyOrExit(aMessage.IsNonConfirmablePostRequest());
 
     SuccessOrExit(error = Tlv::Find<JoinerRouterLocatorTlv>(aMessage, joinerRouterRloc));
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->InitAsNonConfirmablePost(UriPath::kRelayTx));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityNonConfirmablePostMessage(UriPath::kRelayTx);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     offset = message->GetLength();
     SuccessOrExit(error = message->SetLength(offset + aMessage.GetLength() - aMessage.GetOffset()));
     aMessage.CopyTo(aMessage.GetOffset(), offset, aMessage.GetLength() - aMessage.GetOffset(), *message);
 
-    messageInfo.SetSockPort(Tmf::kUdpPort);
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
-    messageInfo.SetPeerAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.GetPeerAddr().GetIid().SetLocator(joinerRouterRloc);
+    messageInfo.SetSockAddrToRlocPeerAddrTo(joinerRouterRloc);
+    messageInfo.SetSockPortToTmf();
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
 
-    otLogInfoMeshCoP("Sent to joiner router request on %s", UriPath::kRelayTx);
+    LogInfo("Sent to joiner router request on %s", UriPath::kRelayTx);
 
 exit:
     FreeMessageOnError(message, error);
@@ -492,45 +481,36 @@
 {
     Error            error          = kErrorNone;
     ForwardContext * forwardContext = nullptr;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
     Coap::Message *  message = nullptr;
     uint16_t         offset  = 0;
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-
     if (aSeparate)
     {
         SuccessOrExit(error = Get<Coap::CoapSecure>().SendAck(aMessage, aMessageInfo));
     }
 
-    forwardContext = static_cast<ForwardContext *>(Instance::HeapCAlloc(1, sizeof(ForwardContext)));
+    forwardContext = static_cast<ForwardContext *>(Heap::CAlloc(1, sizeof(ForwardContext)));
     VerifyOrExit(forwardContext != nullptr, error = kErrorNoBufs);
 
     forwardContext->Init(GetInstance(), aMessage, aPetition, aSeparate);
 
-    SuccessOrExit(error = message->InitAsConfirmablePost(aPath));
-
-    // Payload of c/cg may be empty
-    if (aMessage.GetLength() - aMessage.GetOffset() > 0)
-    {
-        SuccessOrExit(error = message->SetPayloadMarker());
-    }
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(aPath);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     offset = message->GetLength();
     SuccessOrExit(error = message->SetLength(offset + aMessage.GetLength() - aMessage.GetOffset()));
     aMessage.CopyTo(aMessage.GetOffset(), offset, aMessage.GetLength() - aMessage.GetOffset(), *message);
 
-    SuccessOrExit(error = Get<Mle::MleRouter>().GetLeaderAloc(messageInfo.GetPeerAddr()));
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.SetSockPort(Tmf::kUdpPort);
+    SuccessOrExit(error = messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc());
+    messageInfo.SetSockPortToTmf();
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, HandleCoapResponse, forwardContext));
 
     // HandleCoapResponse is responsible to free this forward context.
     forwardContext = nullptr;
 
-    otLogInfoMeshCoP("Forwarded request to leader on %s", aPath);
+    LogInfo("Forwarded request to leader on %s", aPath);
 
 exit:
     LogError("forward to leader", error);
@@ -539,7 +519,7 @@
     {
         if (forwardContext != nullptr)
         {
-            Instance::HeapFree(forwardContext);
+            Heap::Free(forwardContext);
         }
 
         FreeMessage(message);
@@ -558,13 +538,13 @@
 {
     if (aConnected)
     {
-        otLogInfoMeshCoP("Commissioner connected");
+        LogInfo("Commissioner connected");
         mState = kStateActive;
         mTimer.Start(kKeepAliveTimeout);
     }
     else
     {
-        otLogInfoMeshCoP("Commissioner disconnected");
+        LogInfo("Commissioner disconnected");
         IgnoreError(Get<Ip6::Udp>().RemoveReceiver(mUdpReceiver));
         Get<ThreadNetif>().RemoveUnicastAddress(mCommissionerAloc);
         mState        = kStateStarted;
@@ -583,7 +563,7 @@
     Coap::CoapSecure &coaps = Get<Coap::CoapSecure>();
     Pskc              pskc;
 
-    VerifyOrExit(mState == kStateStopped, error = kErrorAlready);
+    VerifyOrExit(mState == kStateStopped, error = kErrorNone);
 
     Get<KeyManager>().GetPskc(pskc);
     SuccessOrExit(error = coaps.Start(kBorderAgentUdpPort));
@@ -608,12 +588,12 @@
     mState        = kStateStarted;
     mUdpProxyPort = 0;
 
-    otLogInfoMeshCoP("Border Agent start listening on port %d", kBorderAgentUdpPort);
+    LogInfo("Border Agent start listening on port %u", GetUdpPort());
 
 exit:
     if (error != kErrorNone)
     {
-        otLogWarnMeshCoP("failed to start Border Agent on port %d: %s", kBorderAgentUdpPort, ErrorToString(error));
+        LogWarn("failed to start Border Agent on port %d: %s", kBorderAgentUdpPort, ErrorToString(error));
     }
 }
 
@@ -627,7 +607,7 @@
     if (Get<Coap::CoapSecure>().IsConnected())
     {
         Get<Coap::CoapSecure>().Disconnect();
-        otLogWarnMeshCoP("Reset commissioner session");
+        LogWarn("Reset commissioner session");
     }
 }
 
@@ -657,7 +637,7 @@
     mState        = kStateStopped;
     mUdpProxyPort = 0;
 
-    otLogInfoMeshCoP("Border Agent stopped");
+    LogInfo("Border Agent stopped");
 
 exit:
     return;
diff --git a/src/core/meshcop/border_agent.hpp b/src/core/meshcop/border_agent.hpp
index 157d069..6f6bc45 100644
--- a/src/core/meshcop/border_agent.hpp
+++ b/src/core/meshcop/border_agent.hpp
@@ -41,6 +41,7 @@
 #include <openthread/border_agent.h>
 
 #include "coap/coap.hpp"
+#include "common/as_core_type.hpp"
 #include "common/locator.hpp"
 #include "common/non_copyable.hpp"
 #include "common/notifier.hpp"
@@ -168,8 +169,7 @@
     void        HandleProxyTransmit(const Coap::Message &aMessage);
     static bool HandleUdpReceive(void *aContext, const otMessage *aMessage, const otMessageInfo *aMessageInfo)
     {
-        return static_cast<BorderAgent *>(aContext)->HandleUdpReceive(
-            *static_cast<const Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
+        return static_cast<BorderAgent *>(aContext)->HandleUdpReceive(AsCoreType(aMessage), AsCoreType(aMessageInfo));
     }
     bool HandleUdpReceive(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
 
@@ -198,6 +198,9 @@
 };
 
 } // namespace MeshCoP
+
+DefineMapEnum(otBorderAgentState, MeshCoP::BorderAgent::State);
+
 } // namespace ot
 
 #endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
diff --git a/src/core/meshcop/commissioner.cpp b/src/core/meshcop/commissioner.cpp
index d20e25a..c1c73eb 100644
--- a/src/core/meshcop/commissioner.cpp
+++ b/src/core/meshcop/commissioner.cpp
@@ -38,11 +38,11 @@
 #include <stdio.h>
 
 #include "coap/coap_message.hpp"
+#include "common/array.hpp"
 #include "common/as_core_type.hpp"
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
 #include "common/string.hpp"
 #include "meshcop/joiner.hpp"
 #include "meshcop/joiner_router.hpp"
@@ -55,6 +55,8 @@
 namespace ot {
 namespace MeshCoP {
 
+RegisterLogModule("Commissioner");
+
 Commissioner::Commissioner(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mActiveJoiner(nullptr)
@@ -84,6 +86,8 @@
     mCommissionerAloc.mScopeOverride      = Ip6::Address::kRealmLocalScope;
     mCommissionerAloc.mScopeOverrideValid = true;
 
+    IgnoreError(SetId("OpenThread Commissioner"));
+
     mProvisioningUrl[0] = '\0';
 }
 
@@ -95,7 +99,7 @@
 
     SuccessOrExit(Get<Notifier>().Update(mState, aState, kEventCommissionerStateChanged));
 
-    otLogInfoMeshCoP("CommissionerState: %s -> %s", StateToString(oldState), StateToString(aState));
+    LogInfo("State: %s -> %s", StateToString(oldState), StateToString(aState));
 
     if (mStateCallback)
     {
@@ -129,8 +133,7 @@
         noJoinerId = true;
     }
 
-    mJoinerCallback(static_cast<otCommissionerJoinerEvent>(aEvent), &joinerInfo, noJoinerId ? nullptr : &joinerId,
-                    mCallbackContext);
+    mJoinerCallback(MapEnum(aEvent), &joinerInfo, noJoinerId ? nullptr : &joinerId, mCallbackContext);
 
 exit:
     return;
@@ -295,9 +298,7 @@
     SignalJoinerEvent(kJoinerEventRemoved, &joinerCopy);
 }
 
-Error Commissioner::Start(otCommissionerStateCallback  aStateCallback,
-                          otCommissionerJoinerCallback aJoinerCallback,
-                          void *                       aCallbackContext)
+Error Commissioner::Start(StateCallback aStateCallback, JoinerCallback aJoinerCallback, void *aCallbackContext)
 {
     Error error = kErrorNone;
 
@@ -305,7 +306,7 @@
     VerifyOrExit(mState == kStateDisabled, error = kErrorAlready);
 
 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
-    Get<MeshCoP::BorderAgent>().Stop();
+    Get<BorderAgent>().Stop();
 #endif
 
     SuccessOrExit(error = Get<Coap::CoapSecure>().Start(SendRelayTransmit, this));
@@ -319,6 +320,8 @@
     SuccessOrExit(error = SendPetition());
     SetState(kStatePetition);
 
+    LogInfo("start commissioner %s", mCommissionerId);
+
 exit:
     if ((error != kErrorNone) && (error != kErrorAlready))
     {
@@ -329,7 +332,7 @@
     return error;
 }
 
-Error Commissioner::Stop(bool aResign)
+Error Commissioner::Stop(ResignMode aResignMode)
 {
     Error error      = kErrorNone;
     bool  needResign = false;
@@ -354,13 +357,13 @@
 
     SetState(kStateDisabled);
 
-    if (needResign && aResign)
+    if (needResign && (aResignMode == kSendKeepAliveToResign))
     {
         SendKeepAlive();
     }
 
 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
-    Get<MeshCoP::BorderAgent>().Start();
+    Get<BorderAgent>().Start();
 #endif
 
 exit:
@@ -368,6 +371,28 @@
     return error;
 }
 
+Error Commissioner::SetId(const char *aId)
+{
+    Error   error = kErrorNone;
+    uint8_t len;
+
+    VerifyOrExit(IsDisabled(), error = kErrorInvalidState);
+    VerifyOrExit(aId != nullptr);
+    VerifyOrExit(IsValidUtf8String(aId), error = kErrorInvalidArgs);
+
+    len = static_cast<uint8_t>(StringLength(aId, sizeof(mCommissionerId)));
+
+    // CommissionerIdTlv::SetCommissionerId trims the string to the maximum array size.
+    // Prevent this from happening returning an error.
+    VerifyOrExit(len < CommissionerIdTlv::kMaxLength, error = kErrorInvalidArgs);
+
+    memcpy(mCommissionerId, aId, len);
+    mCommissionerId[len] = '\0';
+
+exit:
+    return error;
+}
+
 void Commissioner::ComputeBloomFilter(SteeringData &aSteeringData) const
 {
     Mac::ExtAddress joinerId;
@@ -402,18 +427,15 @@
 
 void Commissioner::SendCommissionerSet(void)
 {
-    Error                  error = kErrorNone;
-    otCommissioningDataset dataset;
+    Error   error = kErrorNone;
+    Dataset dataset;
 
     VerifyOrExit(mState == kStateActive, error = kErrorInvalidState);
 
-    memset(&dataset, 0, sizeof(dataset));
+    dataset.Clear();
 
-    dataset.mSessionId      = mSessionId;
-    dataset.mIsSessionIdSet = true;
-
-    ComputeBloomFilter(AsCoreType(&dataset.mSteeringData));
-    dataset.mIsSteeringDataSet = true;
+    dataset.SetSessionId(mSessionId);
+    ComputeBloomFilter(dataset.UpdateSteeringData());
 
     error = SendMgmtCommissionerSetRequest(dataset, nullptr, 0);
 
@@ -522,7 +544,7 @@
 {
     Error error = kErrorNone;
 
-    while (aIterator < OT_ARRAY_LENGTH(mJoiners))
+    while (aIterator < GetArrayLength(mJoiners))
     {
         const Joiner &joiner = mJoiners[aIterator++];
 
@@ -646,7 +668,7 @@
 
         if (joiner.mExpirationTime <= now)
         {
-            otLogDebgMeshCoP("removing joiner due to timeout or successfully joined");
+            LogDebg("removing joiner due to timeout or successfully joined");
             RemoveJoinerEntry(joiner);
         }
     }
@@ -690,33 +712,25 @@
 {
     Error            error = kErrorNone;
     Coap::Message *  message;
-    Ip6::MessageInfo messageInfo;
-    MeshCoP::Tlv     tlv;
+    Tmf::MessageInfo messageInfo(GetInstance());
+    Tlv              tlv;
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kCommissionerGet));
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(UriPath::kCommissionerGet);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     if (aLength > 0)
     {
-        SuccessOrExit(error = message->SetPayloadMarker());
-    }
-
-    if (aLength > 0)
-    {
-        tlv.SetType(MeshCoP::Tlv::kGet);
+        tlv.SetType(Tlv::kGet);
         tlv.SetLength(aLength);
         SuccessOrExit(error = message->Append(tlv));
         SuccessOrExit(error = message->AppendBytes(aTlvs, aLength));
     }
 
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    SuccessOrExit(error = Get<Mle::MleRouter>().GetLeaderAloc(messageInfo.GetPeerAddr()));
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
+    SuccessOrExit(error = messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc());
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo,
                                                         Commissioner::HandleMgmtCommissionerGetResponse, this));
 
-    otLogInfoMeshCoP("sent MGMT_COMMISSIONER_GET.req to leader");
+    LogInfo("sent MGMT_COMMISSIONER_GET.req to leader");
 
 exit:
     FreeMessageOnError(message, error);
@@ -739,44 +753,41 @@
     OT_UNUSED_VARIABLE(aMessageInfo);
 
     VerifyOrExit(aResult == kErrorNone && aMessage->GetCode() == Coap::kCodeChanged);
-    otLogInfoMeshCoP("received MGMT_COMMISSIONER_GET response");
+    LogInfo("received MGMT_COMMISSIONER_GET response");
 
 exit:
     return;
 }
 
-Error Commissioner::SendMgmtCommissionerSetRequest(const otCommissioningDataset &aDataset,
-                                                   const uint8_t *               aTlvs,
-                                                   uint8_t                       aLength)
+Error Commissioner::SendMgmtCommissionerSetRequest(const Dataset &aDataset, const uint8_t *aTlvs, uint8_t aLength)
 {
     Error            error = kErrorNone;
     Coap::Message *  message;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(UriPath::kCommissionerSet);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
-    SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kCommissionerSet));
-    SuccessOrExit(error = message->SetPayloadMarker());
-
-    if (aDataset.mIsLocatorSet)
+    if (aDataset.IsLocatorSet())
     {
-        SuccessOrExit(error = Tlv::Append<MeshCoP::BorderAgentLocatorTlv>(*message, aDataset.mLocator));
+        SuccessOrExit(error = Tlv::Append<BorderAgentLocatorTlv>(*message, aDataset.GetLocator()));
     }
 
-    if (aDataset.mIsSessionIdSet)
+    if (aDataset.IsSessionIdSet())
     {
-        SuccessOrExit(error = Tlv::Append<MeshCoP::CommissionerSessionIdTlv>(*message, aDataset.mSessionId));
+        SuccessOrExit(error = Tlv::Append<CommissionerSessionIdTlv>(*message, aDataset.GetSessionId()));
     }
 
-    if (aDataset.mIsSteeringDataSet)
+    if (aDataset.IsSteeringDataSet())
     {
-        SuccessOrExit(
-            error = Tlv::Append<SteeringDataTlv>(*message, aDataset.mSteeringData.m8, aDataset.mSteeringData.mLength));
+        const SteeringData &steeringData = aDataset.GetSteeringData();
+
+        SuccessOrExit(error = Tlv::Append<SteeringDataTlv>(*message, steeringData.GetData(), steeringData.GetLength()));
     }
 
-    if (aDataset.mIsJoinerUdpPortSet)
+    if (aDataset.IsJoinerUdpPortSet())
     {
-        SuccessOrExit(error = Tlv::Append<JoinerUdpPortTlv>(*message, aDataset.mJoinerUdpPort));
+        SuccessOrExit(error = Tlv::Append<JoinerUdpPortTlv>(*message, aDataset.GetJoinerUdpPort()));
     }
 
     if (aLength > 0)
@@ -784,13 +795,11 @@
         SuccessOrExit(error = message->AppendBytes(aTlvs, aLength));
     }
 
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    SuccessOrExit(error = Get<Mle::MleRouter>().GetLeaderAloc(messageInfo.GetPeerAddr()));
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
+    SuccessOrExit(error = messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc());
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo,
                                                         Commissioner::HandleMgmtCommissionerSetResponse, this));
 
-    otLogInfoMeshCoP("sent MGMT_COMMISSIONER_SET.req to leader");
+    LogInfo("sent MGMT_COMMISSIONER_SET.req to leader");
 
 exit:
     FreeMessageOnError(message, error);
@@ -813,7 +822,7 @@
     OT_UNUSED_VARIABLE(aMessageInfo);
 
     VerifyOrExit(aResult == kErrorNone && aMessage->GetCode() == Coap::kCodeChanged);
-    otLogInfoMeshCoP("received MGMT_COMMISSIONER_SET response");
+    LogInfo("received MGMT_COMMISSIONER_SET response");
 
 exit:
     return;
@@ -823,28 +832,23 @@
 {
     Error             error   = kErrorNone;
     Coap::Message *   message = nullptr;
-    Ip6::MessageInfo  messageInfo;
-    CommissionerIdTlv commissionerId;
+    Tmf::MessageInfo  messageInfo(GetInstance());
+    CommissionerIdTlv commissionerIdTlv;
 
     mTransmitAttempts++;
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(UriPath::kLeaderPetition);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
-    SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kLeaderPetition));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    commissionerIdTlv.Init();
+    commissionerIdTlv.SetCommissionerId(mCommissionerId);
 
-    commissionerId.Init();
-    commissionerId.SetCommissionerId("OpenThread Commissioner");
-
-    SuccessOrExit(error = commissionerId.AppendTo(*message));
-
-    SuccessOrExit(error = Get<Mle::MleRouter>().GetLeaderAloc(messageInfo.GetPeerAddr()));
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
+    SuccessOrExit(error = commissionerIdTlv.AppendTo(*message));
+    SuccessOrExit(error = messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc());
     SuccessOrExit(
         error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, Commissioner::HandleLeaderPetitionResponse, this));
 
-    otLogInfoMeshCoP("sent petition");
+    LogInfo("sent petition");
 
 exit:
     FreeMessageOnError(message, error);
@@ -873,10 +877,10 @@
     VerifyOrExit(aResult == kErrorNone && aMessage->GetCode() == Coap::kCodeChanged,
                  retransmit = (mState == kStatePetition));
 
-    otLogInfoMeshCoP("received Leader Petition response");
+    LogInfo("received Leader Petition response");
 
     SuccessOrExit(Tlv::Find<StateTlv>(*aMessage, state));
-    VerifyOrExit(state == StateTlv::kAccept, IgnoreError(Stop(/* aResign */ false)));
+    VerifyOrExit(state == StateTlv::kAccept, IgnoreError(Stop(kDoNotSendKeepAlive)));
 
     SuccessOrExit(Tlv::Find<CommissionerSessionIdTlv>(*aMessage, mSessionId));
 
@@ -903,7 +907,7 @@
     {
         if (mTransmitAttempts >= kPetitionRetryCount)
         {
-            IgnoreError(Stop(/* aResign */ false));
+            IgnoreError(Stop(kDoNotSendKeepAlive));
         }
         else
         {
@@ -921,25 +925,21 @@
 {
     Error            error   = kErrorNone;
     Coap::Message *  message = nullptr;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kLeaderKeepAlive));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(UriPath::kLeaderKeepAlive);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(
         error = Tlv::Append<StateTlv>(*message, (mState == kStateActive) ? StateTlv::kAccept : StateTlv::kReject));
 
     SuccessOrExit(error = Tlv::Append<CommissionerSessionIdTlv>(*message, aSessionId));
 
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    SuccessOrExit(error = Get<Mle::MleRouter>().GetLeaderAloc(messageInfo.GetPeerAddr()));
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
+    SuccessOrExit(error = messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc());
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo,
                                                         Commissioner::HandleLeaderKeepAliveResponse, this));
 
-    otLogInfoMeshCoP("sent keep alive");
+    LogInfo("sent keep alive");
 
 exit:
     FreeMessageOnError(message, error);
@@ -965,12 +965,12 @@
 
     VerifyOrExit(mState == kStateActive);
     VerifyOrExit(aResult == kErrorNone && aMessage->GetCode() == Coap::kCodeChanged,
-                 IgnoreError(Stop(/* aResign */ false)));
+                 IgnoreError(Stop(kDoNotSendKeepAlive)));
 
-    otLogInfoMeshCoP("received Leader keep-alive response");
+    LogInfo("received Leader keep-alive response");
 
     SuccessOrExit(Tlv::Find<StateTlv>(*aMessage, state));
-    VerifyOrExit(state == StateTlv::kAccept, IgnoreError(Stop(/* aResign */ false)));
+    VerifyOrExit(state == StateTlv::kAccept, IgnoreError(Stop(kDoNotSendKeepAlive)));
 
     mTimer.Start(Time::SecToMsec(kKeepAliveTimeout) / 2);
 
@@ -1031,7 +1031,7 @@
     mJoinerPort = joinerPort;
     mJoinerRloc = joinerRloc;
 
-    otLogInfoMeshCoP("Received Relay Receive (%s, 0x%04x)", mJoinerIid.ToString().AsCString(), mJoinerRloc);
+    LogInfo("Received Relay Receive (%s, 0x%04x)", mJoinerIid.ToString().AsCString(), mJoinerRloc);
 
     aMessage.SetOffset(offset);
     SuccessOrExit(error = aMessage.SetLength(offset + length));
@@ -1055,11 +1055,11 @@
 {
     VerifyOrExit(aMessage.IsConfirmablePostRequest());
 
-    otLogInfoMeshCoP("received dataset changed");
+    LogInfo("received dataset changed");
 
     SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMessage, aMessageInfo));
 
-    otLogInfoMeshCoP("sent dataset changed acknowledgment");
+    LogInfo("sent dataset changed acknowledgment");
 
 exit:
     return;
@@ -1077,7 +1077,7 @@
     StateTlv::State    state = StateTlv::kAccept;
     ProvisioningUrlTlv provisioningUrl;
 
-    otLogInfoMeshCoP("received joiner finalize");
+    LogInfo("received joiner finalize");
 
     if (Tlv::FindTlv(aMessage, provisioningUrl) == kErrorNone)
     {
@@ -1096,8 +1096,7 @@
         uint8_t buf[OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE];
 
         aMessage.ReadBytes(aMessage.GetOffset(), buf, aMessage.GetLength() - aMessage.GetOffset());
-        otDumpCertMeshCoP("[THCI] direction=recv | type=JOIN_FIN.req |", buf,
-                          aMessage.GetLength() - aMessage.GetOffset());
+        DumpCert("[THCI] direction=recv | type=JOIN_FIN.req |", buf, aMessage.GetLength() - aMessage.GetOffset());
     }
 #endif
 
@@ -1110,10 +1109,9 @@
     Ip6::MessageInfo joinerMessageInfo;
     Coap::Message *  message;
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Coap::CoapSecure>())) != nullptr, error = kErrorNoBufs);
+    message = Get<Coap::CoapSecure>().NewPriorityResponseMessage(aRequest);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
-    SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
-    SuccessOrExit(error = message->SetPayloadMarker());
     message->SetOffset(message->GetLength());
     message->SetSubType(Message::kSubTypeJoinerFinalizeResponse);
 
@@ -1128,7 +1126,7 @@
 
     VerifyOrExit(message->GetLength() <= sizeof(buf));
     message->ReadBytes(message->GetOffset(), buf, message->GetLength() - message->GetOffset());
-    otDumpCertMeshCoP("[THCI] direction=send | type=JOIN_FIN.rsp |", buf, message->GetLength() - message->GetOffset());
+    DumpCert("[THCI] direction=send | type=JOIN_FIN.rsp |", buf, message->GetLength() - message->GetOffset());
 #endif
 
     SuccessOrExit(error = Get<Coap::CoapSecure>().SendMessage(*message, joinerMessageInfo));
@@ -1141,7 +1139,7 @@
         RemoveJoiner(*mActiveJoiner, kRemoveJoinerDelay);
     }
 
-    otLogInfoMeshCoP("sent joiner finalize response");
+    LogInfo("sent joiner finalize response");
 
 exit:
     FreeMessageOnError(message, error);
@@ -1160,16 +1158,13 @@
     ExtendedTlv      tlv;
     Coap::Message *  message;
     uint16_t         offset;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
     Kek              kek;
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-
     Get<KeyManager>().ExtractKek(kek);
 
-    message->InitAsNonConfirmablePost();
-    SuccessOrExit(error = message->AppendUriPathOptions(UriPath::kRelayTx));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityNonConfirmablePostMessage(UriPath::kRelayTx);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = Tlv::Append<JoinerUdpPortTlv>(*message, mJoinerPort));
     SuccessOrExit(error = Tlv::Append<JoinerIidTlv>(*message, mJoinerIid));
@@ -1187,10 +1182,7 @@
     SuccessOrExit(error = message->SetLength(offset + aMessage.GetLength()));
     aMessage.CopyTo(0, offset, aMessage.GetLength(), *message);
 
-    messageInfo.SetPeerAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.GetPeerAddr().GetIid().SetLocator(mJoinerRloc);
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
+    messageInfo.SetSockAddrToRlocPeerAddrTo(mJoinerRloc);
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
 
@@ -1215,7 +1207,7 @@
 
 // LCOV_EXCL_START
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MESHCOP == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
 const char *Commissioner::StateToString(State aState)
 {
@@ -1240,17 +1232,17 @@
         break;
 
     case Joiner::kTypeAny:
-        otLogInfoMeshCoP("%s Joiner (any, %s)", aAction, aJoiner.mPskd.GetAsCString());
+        LogInfo("%s Joiner (any, %s)", aAction, aJoiner.mPskd.GetAsCString());
         break;
 
     case Joiner::kTypeEui64:
-        otLogInfoMeshCoP("%s Joiner (eui64:%s, %s)", aAction, aJoiner.mSharedId.mEui64.ToString().AsCString(),
-                         aJoiner.mPskd.GetAsCString());
+        LogInfo("%s Joiner (eui64:%s, %s)", aAction, aJoiner.mSharedId.mEui64.ToString().AsCString(),
+                aJoiner.mPskd.GetAsCString());
         break;
 
     case Joiner::kTypeDiscerner:
-        otLogInfoMeshCoP("%s Joiner (disc:%s, %s)", aAction, aJoiner.mSharedId.mDiscerner.ToString().AsCString(),
-                         aJoiner.mPskd.GetAsCString());
+        LogInfo("%s Joiner (disc:%s, %s)", aAction, aJoiner.mSharedId.mDiscerner.ToString().AsCString(),
+                aJoiner.mPskd.GetAsCString());
         break;
     }
 }
@@ -1261,7 +1253,7 @@
 {
 }
 
-#endif // (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MESHCOP == 1)
+#endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
 // LCOV_EXCL_STOP
 
diff --git a/src/core/meshcop/commissioner.hpp b/src/core/meshcop/commissioner.hpp
index 01bf0a7..4c1d190 100644
--- a/src/core/meshcop/commissioner.hpp
+++ b/src/core/meshcop/commissioner.hpp
@@ -42,7 +42,10 @@
 
 #include "coap/coap.hpp"
 #include "coap/coap_secure.hpp"
+#include "common/as_core_type.hpp"
+#include "common/clearable.hpp"
 #include "common/locator.hpp"
+#include "common/log.hpp"
 #include "common/non_copyable.hpp"
 #include "common/timer.hpp"
 #include "mac/mac_types.hpp"
@@ -74,6 +77,150 @@
     };
 
     /**
+     * This enumeration type represents Joiner Event.
+     *
+     */
+    enum JoinerEvent : uint8_t
+    {
+        kJoinerEventStart     = OT_COMMISSIONER_JOINER_START,
+        kJoinerEventConnected = OT_COMMISSIONER_JOINER_CONNECTED,
+        kJoinerEventFinalize  = OT_COMMISSIONER_JOINER_FINALIZE,
+        kJoinerEventEnd       = OT_COMMISSIONER_JOINER_END,
+        kJoinerEventRemoved   = OT_COMMISSIONER_JOINER_REMOVED,
+    };
+
+    typedef otCommissionerStateCallback  StateCallback;  ///< State change callback function pointer type.
+    typedef otCommissionerJoinerCallback JoinerCallback; ///< Joiner state change callback function pointer type.
+
+    /**
+     * This type represents a Commissioning Dataset.
+     *
+     */
+    class Dataset : public otCommissioningDataset, public Clearable<Dataset>
+    {
+    public:
+        /**
+         * This method indicates whether or not the Border Router RLOC16 Locator is set in the Dataset.
+         *
+         * @returns TRUE if Border Router RLOC16 Locator is set, FALSE otherwise.
+         *
+         */
+        bool IsLocatorSet(void) const { return mIsLocatorSet; }
+
+        /**
+         * This method gets the Border Router RLOC16 Locator in the Dataset.
+         *
+         * This method MUST be used when Locator is set in the Dataset, otherwise its behavior is undefined.
+         *
+         * @returns The Border Router RLOC16 Locator in the Dataset.
+         *
+         */
+        uint16_t GetLocator(void) const { return mLocator; }
+
+        /**
+         * This method sets the Border Router RLOCG16 Locator in the Dataset.
+         *
+         * @param[in] aLocator  A Locator.
+         *
+         */
+        void SetLocator(uint16_t aLocator)
+        {
+            mIsLocatorSet = true;
+            mLocator      = aLocator;
+        }
+
+        /**
+         * This method indicates whether or not the Session ID is set in the Dataset.
+         *
+         * @returns TRUE if Session ID is set, FALSE otherwise.
+         *
+         */
+        bool IsSessionIdSet(void) const { return mIsSessionIdSet; }
+
+        /**
+         * This method gets the Session ID in the Dataset.
+         *
+         * This method MUST be used when Session ID is set in the Dataset, otherwise its behavior is undefined.
+         *
+         * @returns The Session ID in the Dataset.
+         *
+         */
+        uint16_t GetSessionId(void) const { return mSessionId; }
+
+        /**
+         * This method sets the Session ID in the Dataset.
+         *
+         * @param[in] aSessionId  The Session ID.
+         *
+         */
+        void SetSessionId(uint16_t aSessionId)
+        {
+            mIsSessionIdSet = true;
+            mSessionId      = aSessionId;
+        }
+
+        /**
+         * This method indicates whether or not the Steering Data is set in the Dataset.
+         *
+         * @returns TRUE if Steering Data is set, FALSE otherwise.
+         *
+         */
+        bool IsSteeringDataSet(void) const { return mIsSteeringDataSet; }
+
+        /**
+         * This method gets the Steering Data in the Dataset.
+         *
+         * This method MUST be used when Steering Data is set in the Dataset, otherwise its behavior is undefined.
+         *
+         * @returns The Steering Data in the Dataset.
+         *
+         */
+        const SteeringData &GetSteeringData(void) const { return AsCoreType(&mSteeringData); }
+
+        /**
+         * This method returns a reference to the Steering Data in the Dataset to be updated by caller.
+         *
+         * @returns A reference to the Steering Data in the Dataset.
+         *
+         */
+        SteeringData &UpdateSteeringData(void)
+        {
+            mIsSteeringDataSet = true;
+            return AsCoreType(&mSteeringData);
+        }
+
+        /**
+         * This method indicates whether or not the Joiner UDP port is set in the Dataset.
+         *
+         * @returns TRUE if Joiner UDP port is set, FALSE otherwise.
+         *
+         */
+        bool IsJoinerUdpPortSet(void) const { return mIsJoinerUdpPortSet; }
+
+        /**
+         * This method gets the Joiner UDP port in the Dataset.
+         *
+         * This method MUST be used when Joiner UDP port is set in the Dataset, otherwise its behavior is undefined.
+         *
+         * @returns The Joiner UDP port in the Dataset.
+         *
+         */
+        uint16_t GetJoinerUdpPort(void) const { return mJoinerUdpPort; }
+
+        /**
+         * This method sets the Joiner UDP Port in the Dataset.
+         *
+         * @param[in] aJoinerUdpPort  The Joiner UDP Port.
+         *
+         */
+        void SetJoinerUdpPort(uint16_t aJoinerUdpPort)
+        {
+            mIsJoinerUdpPortSet = true;
+            mJoinerUdpPort      = aJoinerUdpPort;
+        }
+    };
+
+    /**
      * This constructor initializes the Commissioner object.
      *
      * @param[in]  aInstance     A reference to the OpenThread instance.
@@ -93,20 +240,36 @@
      * @retval kErrorInvalidState   Device is not currently attached to a network.
      *
      */
-    Error Start(otCommissionerStateCallback  aStateCallback,
-                otCommissionerJoinerCallback aJoinerCallback,
-                void *                       aCallbackContext);
+    Error Start(StateCallback aStateCallback, JoinerCallback aJoinerCallback, void *aCallbackContext);
 
     /**
      * This method stops the Commissioner service.
      *
-     * @param[in]  aResign      Whether send LEAD_KA.req to resign as Commissioner
-     *
      * @retval kErrorNone     Successfully stopped the Commissioner service.
      * @retval kErrorAlready  Commissioner is already stopped.
      *
      */
-    Error Stop(bool aResign);
+    Error Stop(void) { return Stop(kSendKeepAliveToResign); }
+
+    /**
+     * This method returns the Commissioner Id.
+     *
+     * @returns The Commissioner Id.
+     *
+     */
+    const char *GetId(void) const { return mCommissionerId; }
+
+    /**
+     * This method sets the Commissioner Id.
+     *
+     * @param[in]  aId   A pointer to a string character array. Must be null terminated.
+     *
+     * @retval kErrorNone           Successfully set the Commissioner Id.
+     * @retval kErrorInvalidArgs    Given name is too long.
+     * @retval kErrorInvalidState   The commissioner is active and id cannot be changed.
+     *
+     */
+    Error SetId(const char *aId);
 
     /**
      * This method clears all Joiner entries.
@@ -164,7 +327,7 @@
     /**
      * This method get joiner info at aIterator position.
      *
-     * @param[inout]    aIterator   A iterator to the index of the joiner.
+     * @param[in,out]   aIterator   A iterator to the index of the joiner.
      * @param[out]      aJoiner     A reference to Joiner info.
      *
      * @retval kErrorNone       Successfully get the Joiner info.
@@ -228,7 +391,7 @@
     /**
      * This method sets the Provisioning URL.
      *
-     * @param[in]  aProvisioningUrl  A pointer to the Provisioning URL (may be nullptr to set URL to empty string).
+     * @param[in]  aProvisioningUrl  A pointer to the Provisioning URL (may be `nullptr` to set URL to empty string).
      *
      * @retval kErrorNone         Successfully set the Provisioning URL.
      * @retval kErrorInvalidArgs  @p aProvisioningUrl is invalid (too long).
@@ -293,7 +456,7 @@
      * @retval kErrorInvalidState  Commissioner service is not started.
      *
      */
-    Error SendMgmtCommissionerSetRequest(const otCommissioningDataset &aDataset, const uint8_t *aTlvs, uint8_t aLength);
+    Error SendMgmtCommissionerSetRequest(const Dataset &aDataset, const uint8_t *aTlvs, uint8_t aLength);
 
     /**
      * This method returns a reference to the AnnounceBeginClient instance.
@@ -332,13 +495,10 @@
     static constexpr uint32_t kKeepAliveTimeout     = 50; // TIMEOUT_COMM_PET (seconds)
     static constexpr uint32_t kRemoveJoinerDelay    = 20; // Delay to remove successfully joined joiner
 
-    enum JoinerEvent : uint8_t
+    enum ResignMode : uint8_t
     {
-        kJoinerEventStart     = OT_COMMISSIONER_JOINER_START,
-        kJoinerEventConnected = OT_COMMISSIONER_JOINER_CONNECTED,
-        kJoinerEventFinalize  = OT_COMMISSIONER_JOINER_FINALIZE,
-        kJoinerEventEnd       = OT_COMMISSIONER_JOINER_END,
-        kJoinerEventRemoved   = OT_COMMISSIONER_JOINER_REMOVED,
+        kSendKeepAliveToResign,
+        kDoNotSendKeepAlive,
     };
 
     struct Joiner
@@ -365,6 +525,7 @@
         void CopyToJoinerInfo(otJoinerInfo &aJoiner) const;
     };
 
+    Error   Stop(ResignMode aResignMode);
     Joiner *GetUnusedJoinerEntry(void);
     Joiner *FindJoinerEntry(const Mac::ExtAddress *aEui64);
     Joiner *FindJoinerEntry(const JoinerDiscerner &aDiscerner);
@@ -465,15 +626,21 @@
     Ip6::Netif::UnicastAddress mCommissionerAloc;
 
     char mProvisioningUrl[OT_PROVISIONING_URL_MAX_SIZE + 1]; // + 1 is for null char at end of string.
+    char mCommissionerId[CommissionerIdTlv::kMaxLength + 1];
 
     State mState;
 
-    otCommissionerStateCallback  mStateCallback;
-    otCommissionerJoinerCallback mJoinerCallback;
-    void *                       mCallbackContext;
+    StateCallback  mStateCallback;
+    JoinerCallback mJoinerCallback;
+    void *         mCallbackContext;
 };
 
 } // namespace MeshCoP
+
+DefineMapEnum(otCommissionerState, MeshCoP::Commissioner::State);
+DefineMapEnum(otCommissionerJoinerEvent, MeshCoP::Commissioner::JoinerEvent);
+DefineCoreType(otCommissioningDataset, MeshCoP::Commissioner::Dataset);
+
 } // namespace ot
 
 #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
diff --git a/src/core/meshcop/dataset.cpp b/src/core/meshcop/dataset.cpp
index ea78a49..0478085 100644
--- a/src/core/meshcop/dataset.cpp
+++ b/src/core/meshcop/dataset.cpp
@@ -40,14 +40,17 @@
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "mac/mac_types.hpp"
 #include "meshcop/meshcop_tlvs.hpp"
+#include "meshcop/timestamp.hpp"
 #include "thread/mle_tlvs.hpp"
 
 namespace ot {
 namespace MeshCoP {
 
+RegisterLogModule("Dataset");
+
 Error Dataset::Info::GenerateRandom(Instance &aInstance)
 {
     Error            error;
@@ -67,16 +70,18 @@
 
     Clear();
 
-    mActiveTimestamp = 1;
-    mChannel         = preferredChannels.ChooseRandomChannel();
-    mChannelMask     = supportedChannels.GetMask();
-    mPanId           = Mac::GenerateRandomPanId();
-    static_cast<SecurityPolicy &>(mSecurityPolicy).SetToDefault();
+    mActiveTimestamp.mSeconds       = 1;
+    mActiveTimestamp.mTicks         = 0;
+    mActiveTimestamp.mAuthoritative = false;
+    mChannel                        = preferredChannels.ChooseRandomChannel();
+    mChannelMask                    = supportedChannels.GetMask();
+    mPanId                          = Mac::GenerateRandomPanId();
+    AsCoreType(&mSecurityPolicy).SetToDefault();
 
-    SuccessOrExit(error = static_cast<NetworkKey &>(mNetworkKey).GenerateRandom());
-    SuccessOrExit(error = static_cast<Pskc &>(mPskc).GenerateRandom());
+    SuccessOrExit(error = AsCoreType(&mNetworkKey).GenerateRandom());
+    SuccessOrExit(error = AsCoreType(&mPskc).GenerateRandom());
     SuccessOrExit(error = Random::Crypto::FillBuffer(mExtendedPanId.m8, sizeof(mExtendedPanId.m8)));
-    SuccessOrExit(error = static_cast<Ip6::NetworkPrefix &>(mMeshLocalPrefix).GenerateRandomUla());
+    SuccessOrExit(error = AsCoreType(&mMeshLocalPrefix).GenerateRandomUla());
 
     snprintf(mNetworkName.m8, sizeof(mNetworkName), "OpenThread-%04x", mPanId);
 
@@ -191,16 +196,16 @@
         switch (cur->GetType())
         {
         case Tlv::kActiveTimestamp:
-            aDatasetInfo.SetActiveTimestamp(static_cast<const ActiveTimestampTlv *>(cur)->GetTimestamp().GetSeconds());
+            aDatasetInfo.SetActiveTimestamp(As<ActiveTimestampTlv>(cur)->GetTimestamp());
             break;
 
         case Tlv::kChannel:
-            aDatasetInfo.SetChannel(static_cast<const ChannelTlv *>(cur)->GetChannel());
+            aDatasetInfo.SetChannel(As<ChannelTlv>(cur)->GetChannel());
             break;
 
         case Tlv::kChannelMask:
         {
-            uint32_t mask = static_cast<const ChannelMaskTlv *>(cur)->GetChannelMask();
+            uint32_t mask = As<ChannelMaskTlv>(cur)->GetChannelMask();
 
             if (mask != 0)
             {
@@ -211,45 +216,40 @@
         }
 
         case Tlv::kDelayTimer:
-            aDatasetInfo.SetDelay(static_cast<const DelayTimerTlv *>(cur)->GetDelayTimer());
+            aDatasetInfo.SetDelay(As<DelayTimerTlv>(cur)->GetDelayTimer());
             break;
 
         case Tlv::kExtendedPanId:
-            aDatasetInfo.SetExtendedPanId(static_cast<const ExtendedPanIdTlv *>(cur)->GetExtendedPanId());
+            aDatasetInfo.SetExtendedPanId(As<ExtendedPanIdTlv>(cur)->GetExtendedPanId());
             break;
 
         case Tlv::kMeshLocalPrefix:
-            aDatasetInfo.SetMeshLocalPrefix(static_cast<const MeshLocalPrefixTlv *>(cur)->GetMeshLocalPrefix());
+            aDatasetInfo.SetMeshLocalPrefix(As<MeshLocalPrefixTlv>(cur)->GetMeshLocalPrefix());
             break;
 
         case Tlv::kNetworkKey:
-            aDatasetInfo.SetNetworkKey(static_cast<const NetworkKeyTlv *>(cur)->GetNetworkKey());
+            aDatasetInfo.SetNetworkKey(As<NetworkKeyTlv>(cur)->GetNetworkKey());
             break;
 
         case Tlv::kNetworkName:
-            aDatasetInfo.SetNetworkName(static_cast<const NetworkNameTlv *>(cur)->GetNetworkName());
+            aDatasetInfo.SetNetworkName(As<NetworkNameTlv>(cur)->GetNetworkName());
             break;
 
         case Tlv::kPanId:
-            aDatasetInfo.SetPanId(static_cast<const PanIdTlv *>(cur)->GetPanId());
+            aDatasetInfo.SetPanId(As<PanIdTlv>(cur)->GetPanId());
             break;
 
         case Tlv::kPendingTimestamp:
-            aDatasetInfo.SetPendingTimestamp(
-                static_cast<const PendingTimestampTlv *>(cur)->GetTimestamp().GetSeconds());
+            aDatasetInfo.SetPendingTimestamp(As<PendingTimestampTlv>(cur)->GetTimestamp());
             break;
 
         case Tlv::kPskc:
-            aDatasetInfo.SetPskc(static_cast<const PskcTlv *>(cur)->GetPskc());
+            aDatasetInfo.SetPskc(As<PskcTlv>(cur)->GetPskc());
             break;
 
         case Tlv::kSecurityPolicy:
-        {
-            const SecurityPolicyTlv *tlv = static_cast<const SecurityPolicyTlv *>(cur);
-
-            aDatasetInfo.SetSecurityPolicy(tlv->GetSecurityPolicy());
+            aDatasetInfo.SetSecurityPolicy(As<SecurityPolicyTlv>(cur)->GetSecurityPolicy());
             break;
-        }
 
         default:
             break;
@@ -289,20 +289,18 @@
 
     if (aDatasetInfo.IsActiveTimestampPresent())
     {
-        Timestamp timestamp;
+        Timestamp activeTimestamp;
 
-        timestamp.Clear();
-        timestamp.SetSeconds(aDatasetInfo.GetActiveTimestamp());
-        IgnoreError(SetTlv(Tlv::kActiveTimestamp, timestamp));
+        aDatasetInfo.GetActiveTimestamp(activeTimestamp);
+        IgnoreError(SetTlv(Tlv::kActiveTimestamp, activeTimestamp));
     }
 
     if (aDatasetInfo.IsPendingTimestampPresent())
     {
-        Timestamp timestamp;
+        Timestamp pendingTimestamp;
 
-        timestamp.Clear();
-        timestamp.SetSeconds(aDatasetInfo.GetPendingTimestamp());
-        IgnoreError(SetTlv(Tlv::kPendingTimestamp, timestamp));
+        aDatasetInfo.GetPendingTimestamp(pendingTimestamp);
+        IgnoreError(SetTlv(Tlv::kPendingTimestamp, pendingTimestamp));
     }
 
     if (aDatasetInfo.IsDelayPresent())
@@ -343,7 +341,7 @@
 
     if (aDatasetInfo.IsNetworkNamePresent())
     {
-        Mac::NameData nameData = aDatasetInfo.GetNetworkName().GetAsData();
+        NameData nameData = aDatasetInfo.GetNetworkName().GetAsData();
 
         IgnoreError(SetTlv(Tlv::kNetworkName, nameData.GetBuffer(), nameData.GetLength()));
     }
@@ -438,13 +436,15 @@
     return SetTlv(aTlv.GetType(), aTlv.GetValue(), aTlv.GetLength());
 }
 
-Error Dataset::Set(const Message &aMessage, uint16_t aOffset, uint8_t aLength)
+Error Dataset::ReadFromMessage(const Message &aMessage, uint16_t aOffset, uint8_t aLength)
 {
-    Error error = kErrorInvalidArgs;
+    Error error = kErrorParse;
 
     SuccessOrExit(aMessage.Read(aOffset, mTlvs, aLength));
     mLength = aLength;
 
+    VerifyOrExit(IsValid(), error = kErrorParse);
+
     mUpdateTime = TimerMilli::GetNow();
     error       = kErrorNone;
 
@@ -486,8 +486,8 @@
         }
         else if (cur->GetType() == Tlv::kDelayTimer)
         {
-            uint32_t      elapsed = TimerMilli::GetNow() - mUpdateTime;
-            DelayTimerTlv delayTimer(static_cast<const DelayTimerTlv &>(*cur));
+            uint32_t      elapsed    = TimerMilli::GetNow() - mUpdateTime;
+            DelayTimerTlv delayTimer = *As<DelayTimerTlv>(cur);
 
             if (delayTimer.GetDelayTimer() > elapsed)
             {
@@ -538,14 +538,13 @@
         {
         case Tlv::kChannel:
         {
-            uint8_t channel = static_cast<uint8_t>(static_cast<const ChannelTlv *>(cur)->GetChannel());
+            uint8_t channel = static_cast<uint8_t>(As<ChannelTlv>(cur)->GetChannel());
 
             error = mac.SetPanChannel(channel);
 
             if (error != kErrorNone)
             {
-                otLogWarnMeshCoP("DatasetManager::ApplyConfiguration() Failed to set channel to %d (%s)", channel,
-                                 ErrorToString(error));
+                LogWarn("ApplyConfiguration() Failed to set channel to %d (%s)", channel, ErrorToString(error));
                 ExitNow();
             }
 
@@ -553,20 +552,20 @@
         }
 
         case Tlv::kPanId:
-            mac.SetPanId(static_cast<const PanIdTlv *>(cur)->GetPanId());
+            mac.SetPanId(As<PanIdTlv>(cur)->GetPanId());
             break;
 
         case Tlv::kExtendedPanId:
-            mac.SetExtendedPanId(static_cast<const ExtendedPanIdTlv *>(cur)->GetExtendedPanId());
+            aInstance.Get<ExtendedPanIdManager>().SetExtPanId(As<ExtendedPanIdTlv>(cur)->GetExtendedPanId());
             break;
 
         case Tlv::kNetworkName:
-            IgnoreError(mac.SetNetworkName(static_cast<const NetworkNameTlv *>(cur)->GetNetworkName()));
+            IgnoreError(aInstance.Get<NetworkNameManager>().SetNetworkName(As<NetworkNameTlv>(cur)->GetNetworkName()));
             break;
 
         case Tlv::kNetworkKey:
         {
-            const NetworkKeyTlv *key = static_cast<const NetworkKeyTlv *>(cur);
+            const NetworkKeyTlv *key = As<NetworkKeyTlv>(cur);
             NetworkKey           networkKey;
 
             keyManager.GetNetworkKey(networkKey);
@@ -583,22 +582,18 @@
 #if OPENTHREAD_FTD
 
         case Tlv::kPskc:
-            keyManager.SetPskc(static_cast<const PskcTlv *>(cur)->GetPskc());
+            keyManager.SetPskc(As<PskcTlv>(cur)->GetPskc());
             break;
 
 #endif
 
         case Tlv::kMeshLocalPrefix:
-            aInstance.Get<Mle::MleRouter>().SetMeshLocalPrefix(
-                static_cast<const MeshLocalPrefixTlv *>(cur)->GetMeshLocalPrefix());
+            aInstance.Get<Mle::MleRouter>().SetMeshLocalPrefix(As<MeshLocalPrefixTlv>(cur)->GetMeshLocalPrefix());
             break;
 
         case Tlv::kSecurityPolicy:
-        {
-            const SecurityPolicyTlv *securityPolicy = static_cast<const SecurityPolicyTlv *>(cur);
-            keyManager.SetSecurityPolicy(securityPolicy->GetSecurityPolicy());
+            keyManager.SetSecurityPolicy(As<SecurityPolicyTlv>(cur)->GetSecurityPolicy());
             break;
-        }
 
         default:
             break;
diff --git a/src/core/meshcop/dataset.hpp b/src/core/meshcop/dataset.hpp
index 8b51134..3809513 100644
--- a/src/core/meshcop/dataset.hpp
+++ b/src/core/meshcop/dataset.hpp
@@ -39,6 +39,7 @@
 
 #include <openthread/dataset.h>
 
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/const_cast.hpp"
 #include "common/locator.hpp"
@@ -202,7 +203,7 @@
          * @returns The Active Timestamp in the Dataset.
          *
          */
-        uint64_t GetActiveTimestamp(void) const { return mActiveTimestamp; }
+        void GetActiveTimestamp(Timestamp &aTimestamp) const { aTimestamp.SetFromTimestamp(mActiveTimestamp); }
 
         /**
          * This method sets the Active Timestamp in the Dataset.
@@ -210,9 +211,9 @@
          * @param[in] aTimestamp   A Timestamp value.
          *
          */
-        void SetActiveTimestamp(uint64_t aTimestamp)
+        void SetActiveTimestamp(const Timestamp &aTimestamp)
         {
-            mActiveTimestamp                      = aTimestamp;
+            aTimestamp.ConvertTo(mActiveTimestamp);
             mComponents.mIsActiveTimestampPresent = true;
         }
 
@@ -233,7 +234,7 @@
          * @returns The Pending Timestamp in the Dataset.
          *
          */
-        uint64_t GetPendingTimestamp(void) const { return mPendingTimestamp; }
+        void GetPendingTimestamp(Timestamp &aTimestamp) const { aTimestamp.SetFromTimestamp(mPendingTimestamp); }
 
         /**
          * This method sets the Pending Timestamp in the Dataset.
@@ -241,9 +242,9 @@
          * @param[in] aTimestamp   A Timestamp value.
          *
          */
-        void SetPendingTimestamp(uint64_t aTimestamp)
+        void SetPendingTimestamp(const Timestamp &aTimestamp)
         {
-            mPendingTimestamp                      = aTimestamp;
+            aTimestamp.ConvertTo(mPendingTimestamp);
             mComponents.mIsPendingTimestampPresent = true;
         }
 
@@ -264,7 +265,7 @@
          * @returns The Network Key in the Dataset.
          *
          */
-        const NetworkKey &GetNetworkKey(void) const { return static_cast<const NetworkKey &>(mNetworkKey); }
+        const NetworkKey &GetNetworkKey(void) const { return AsCoreType(&mNetworkKey); }
 
         /**
          * This method sets the Network Key in the Dataset.
@@ -287,7 +288,7 @@
         NetworkKey &UpdateNetworkKey(void)
         {
             mComponents.mIsNetworkKeyPresent = true;
-            return static_cast<NetworkKey &>(mNetworkKey);
+            return AsCoreType(&mNetworkKey);
         }
 
         /**
@@ -307,10 +308,7 @@
          * @returns The Network Name in the Dataset.
          *
          */
-        const Mac::NetworkName &GetNetworkName(void) const
-        {
-            return static_cast<const Mac::NetworkName &>(mNetworkName);
-        }
+        const NetworkName &GetNetworkName(void) const { return AsCoreType(&mNetworkName); }
 
         /**
          * This method sets the Network Name in the Dataset.
@@ -318,9 +316,9 @@
          * @param[in] aNetworkNameData   A Network Name Data.
          *
          */
-        void SetNetworkName(const Mac::NameData &aNetworkNameData)
+        void SetNetworkName(const NameData &aNetworkNameData)
         {
-            IgnoreError(static_cast<Mac::NetworkName &>(mNetworkName).Set(aNetworkNameData));
+            IgnoreError(AsCoreType(&mNetworkName).Set(aNetworkNameData));
             mComponents.mIsNetworkNamePresent = true;
         }
 
@@ -341,10 +339,7 @@
          * @returns The Extended PAN ID in the Dataset.
          *
          */
-        const Mac::ExtendedPanId &GetExtendedPanId(void) const
-        {
-            return static_cast<const Mac::ExtendedPanId &>(mExtendedPanId);
-        }
+        const ExtendedPanId &GetExtendedPanId(void) const { return AsCoreType(&mExtendedPanId); }
 
         /**
          * This method sets the Extended PAN ID in the Dataset.
@@ -352,7 +347,7 @@
          * @param[in] aExtendedPanId   An Extended PAN ID.
          *
          */
-        void SetExtendedPanId(const Mac::ExtendedPanId &aExtendedPanId)
+        void SetExtendedPanId(const ExtendedPanId &aExtendedPanId)
         {
             mExtendedPanId                      = aExtendedPanId;
             mComponents.mIsExtendedPanIdPresent = true;
@@ -375,9 +370,9 @@
          * @returns The Mesh Local Prefix in the Dataset.
          *
          */
-        const Mle::MeshLocalPrefix &GetMeshLocalPrefix(void) const
+        const Ip6::NetworkPrefix &GetMeshLocalPrefix(void) const
         {
-            return static_cast<const Mle::MeshLocalPrefix &>(mMeshLocalPrefix);
+            return static_cast<const Ip6::NetworkPrefix &>(mMeshLocalPrefix);
         }
 
         /**
@@ -386,7 +381,7 @@
          * @param[in] aMeshLocalPrefix   A Mesh Local Prefix.
          *
          */
-        void SetMeshLocalPrefix(const Mle::MeshLocalPrefix &aMeshLocalPrefix)
+        void SetMeshLocalPrefix(const Ip6::NetworkPrefix &aMeshLocalPrefix)
         {
             mMeshLocalPrefix                      = aMeshLocalPrefix;
             mComponents.mIsMeshLocalPrefixPresent = true;
@@ -414,7 +409,7 @@
         /**
          * This method sets the Delay Timer in the Dataset.
          *
-         * @param[in] aDely   A Delay value.
+         * @param[in] aDelay  A Delay value.
          *
          */
         void SetDelay(uint32_t aDelay)
@@ -501,7 +496,7 @@
          * @returns The PSKc in the Dataset.
          *
          */
-        const Pskc &GetPskc(void) const { return static_cast<const Pskc &>(mPskc); }
+        const Pskc &GetPskc(void) const { return AsCoreType(&mPskc); }
 
         /**
          * This method set the PSKc in the Dataset.
@@ -532,10 +527,7 @@
          * @returns The Security Policy in the Dataset.
          *
          */
-        const SecurityPolicy &GetSecurityPolicy(void) const
-        {
-            return static_cast<const SecurityPolicy &>(mSecurityPolicy);
-        }
+        const SecurityPolicy &GetSecurityPolicy(void) const { return AsCoreType(&mSecurityPolicy); }
 
         /**
          * This method sets the Security Policy in the Dataset.
@@ -635,7 +627,7 @@
      *
      * @param[in] aType  A TLV type.
      *
-     * @returns A pointer to the TLV or nullptr if none is found.
+     * @returns A pointer to the TLV or `nullptr` if none is found.
      *
      */
     Tlv *GetTlv(Tlv::Type aType) { return AsNonConst(AsConst(this)->GetTlv(aType)); }
@@ -645,7 +637,7 @@
      *
      * @param[in] aType  The TLV type.
      *
-     * @returns A pointer to the TLV or nullptr if none is found.
+     * @returns A pointer to the TLV or `nullptr` if none is found.
      *
      */
     const Tlv *GetTlv(Tlv::Type aType) const;
@@ -653,23 +645,23 @@
     /**
      * This template method returns a pointer to the TLV with a given template type `TlvType`
      *
-     * @returns A pointer to the TLV or nullptr if none is found.
+     * @returns A pointer to the TLV or `nullptr` if none is found.
      *
      */
     template <typename TlvType> TlvType *GetTlv(void)
     {
-        return static_cast<TlvType *>(GetTlv(static_cast<Tlv::Type>(TlvType::kType)));
+        return As<TlvType>(GetTlv(static_cast<Tlv::Type>(TlvType::kType)));
     }
 
     /**
      * This template method returns a pointer to the TLV with a given template type `TlvType`
      *
-     * @returns A pointer to the TLV or nullptr if none is found.
+     * @returns A pointer to the TLV or `nullptr` if none is found.
      *
      */
     template <typename TlvType> const TlvType *GetTlv(void) const
     {
-        return static_cast<const TlvType *>(GetTlv(static_cast<Tlv::Type>(TlvType::kType)));
+        return As<TlvType>(GetTlv(static_cast<Tlv::Type>(TlvType::kType)));
     }
 
     /**
@@ -793,17 +785,17 @@
     }
 
     /**
-     * This method sets the Dataset using TLVs stored in a message buffer.
+     * This method reads the Dataset from a given message and checks that it is well-formed and valid.
      *
-     * @param[in]  aMessage  The message buffer.
-     * @param[in]  aOffset   The message buffer offset where the dataset starts.
-     * @param[in]  aLength   The TLVs length in the message buffer in bytes.
+     * @param[in]  aMessage  The message to read from.
+     * @param[in]  aOffset   The offset in @p aMessage to start reading the Dataset TLVs.
+     * @param[in]  aLength   The dataset length in bytes.
      *
-     * @retval kErrorNone         Successfully set the Dataset.
-     * @retval kErrorInvalidArgs  The values of @p aOffset and @p aLength are not valid for @p aMessage.
+     * @retval kErrorNone    Successfully read and validated the Dataset.
+     * @retval kErrorParse   Could not read or parse the dataset from @p aMessage.
      *
      */
-    Error Set(const Message &aMessage, uint16_t aOffset, uint8_t aLength);
+    Error ReadFromMessage(const Message &aMessage, uint16_t aOffset, uint8_t aLength);
 
     /**
      * This method sets the Dataset using an existing Dataset.
@@ -963,6 +955,10 @@
 }
 
 } // namespace MeshCoP
+
+DefineCoreType(otOperationalDatasetComponents, MeshCoP::Dataset::Components);
+DefineCoreType(otOperationalDataset, MeshCoP::Dataset::Info);
+
 } // namespace ot
 
 #endif // MESHCOP_DATASET_HPP_
diff --git a/src/core/meshcop/dataset_local.cpp b/src/core/meshcop/dataset_local.cpp
index 6ed5018..dfcb077 100644
--- a/src/core/meshcop/dataset_local.cpp
+++ b/src/core/meshcop/dataset_local.cpp
@@ -39,8 +39,9 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/settings.hpp"
+#include "crypto/storage.hpp"
 #include "meshcop/dataset.hpp"
 #include "meshcop/meshcop_tlvs.hpp"
 #include "thread/mle_tlvs.hpp"
@@ -48,6 +49,8 @@
 namespace ot {
 namespace MeshCoP {
 
+RegisterLogModule("DatasetLocal");
+
 DatasetLocal::DatasetLocal(Instance &aInstance, Dataset::Type aType)
     : InstanceLocator(aInstance)
     , mUpdateTime(0)
@@ -60,7 +63,10 @@
 
 void DatasetLocal::Clear(void)
 {
-    IgnoreError(Get<Settings>().DeleteOperationalDataset(IsActive()));
+#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+    DestroySecurelyStoredKeys();
+#endif
+    IgnoreError(Get<Settings>().DeleteOperationalDataset(mType));
     mTimestamp.Clear();
     mTimestampPresent = false;
     mSaved            = false;
@@ -88,9 +94,13 @@
     uint32_t       elapsed;
     Error          error;
 
-    error = Get<Settings>().ReadOperationalDataset(IsActive(), aDataset);
+    error = Get<Settings>().ReadOperationalDataset(mType, aDataset);
     VerifyOrExit(error == kErrorNone, aDataset.mLength = 0);
 
+#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+    EmplaceSecurelyStoredKeys(aDataset);
+#endif
+
     if (mType == Dataset::kActive)
     {
         aDataset.RemoveTlv(Tlv::kPendingTimestamp);
@@ -172,18 +182,32 @@
 {
     Error error = kErrorNone;
 
+#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+    DestroySecurelyStoredKeys();
+#endif
+
     if (aDataset.GetSize() == 0)
     {
         // do not propagate error back
-        IgnoreError(Get<Settings>().DeleteOperationalDataset(IsActive()));
+        IgnoreError(Get<Settings>().DeleteOperationalDataset(mType));
         mSaved = false;
-        otLogInfoMeshCoP("%s dataset deleted", Dataset::TypeToString(mType));
+        LogInfo("%s dataset deleted", Dataset::TypeToString(mType));
     }
     else
     {
-        SuccessOrExit(error = Get<Settings>().SaveOperationalDataset(IsActive(), aDataset));
+#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+        // Store the network key and PSKC in the secure storage instead of settings.
+        Dataset dataset;
+
+        dataset.Set(GetType(), aDataset);
+        MoveKeysToSecureStorage(dataset);
+        SuccessOrExit(error = Get<Settings>().SaveOperationalDataset(mType, dataset));
+#else
+        SuccessOrExit(error = Get<Settings>().SaveOperationalDataset(mType, aDataset));
+#endif
+
         mSaved = true;
-        otLogInfoMeshCoP("%s dataset set", Dataset::TypeToString(mType));
+        LogInfo("%s dataset set", Dataset::TypeToString(mType));
     }
 
     mTimestampPresent = (aDataset.GetTimestamp(mType, mTimestamp) == kErrorNone);
@@ -193,5 +217,113 @@
     return error;
 }
 
+#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+void DatasetLocal::DestroySecurelyStoredKeys(void) const
+{
+    using namespace Crypto::Storage;
+
+    KeyRef networkKeyRef = IsActive() ? kActiveDatasetNetworkKeyRef : kPendingDatasetNetworkKeyRef;
+    KeyRef pskcRef       = IsActive() ? kActiveDatasetPskcRef : kPendingDatasetPskcRef;
+
+    // Destroy securely stored keys associated with the given operational dataset type.
+    DestroyKey(networkKeyRef);
+    DestroyKey(pskcRef);
+}
+
+void DatasetLocal::MoveKeysToSecureStorage(Dataset &aDataset) const
+{
+    using namespace Crypto::Storage;
+
+    KeyRef         networkKeyRef = IsActive() ? kActiveDatasetNetworkKeyRef : kPendingDatasetNetworkKeyRef;
+    KeyRef         pskcRef       = IsActive() ? kActiveDatasetPskcRef : kPendingDatasetPskcRef;
+    NetworkKeyTlv *networkKeyTlv = aDataset.GetTlv<NetworkKeyTlv>();
+    PskcTlv *      pskcTlv       = aDataset.GetTlv<PskcTlv>();
+
+    if (networkKeyTlv != nullptr)
+    {
+        // If the dataset contains a network key, put it in the secure storage
+        // and zero the corresponding TLV element.
+        NetworkKey networkKey;
+        SuccessOrAssert(ImportKey(networkKeyRef, kKeyTypeRaw, kKeyAlgorithmVendor, kUsageExport, kTypePersistent,
+                                  networkKeyTlv->GetNetworkKey().m8, NetworkKey::kSize));
+        networkKey.Clear();
+        networkKeyTlv->SetNetworkKey(networkKey);
+    }
+
+    if (pskcTlv != nullptr)
+    {
+        // If the dataset contains a PSKC, put it in the secure storage and zero
+        // the corresponding TLV element.
+        Pskc pskc;
+        SuccessOrAssert(ImportKey(pskcRef, kKeyTypeRaw, kKeyAlgorithmVendor, kUsageExport, kTypePersistent,
+                                  pskcTlv->GetPskc().m8, Pskc::kSize));
+        pskc.Clear();
+        pskcTlv->SetPskc(pskc);
+    }
+}
+
+void DatasetLocal::EmplaceSecurelyStoredKeys(Dataset &aDataset) const
+{
+    using namespace Crypto::Storage;
+
+    KeyRef         networkKeyRef = IsActive() ? kActiveDatasetNetworkKeyRef : kPendingDatasetNetworkKeyRef;
+    KeyRef         pskcRef       = IsActive() ? kActiveDatasetPskcRef : kPendingDatasetPskcRef;
+    NetworkKeyTlv *networkKeyTlv = aDataset.GetTlv<NetworkKeyTlv>();
+    PskcTlv *      pskcTlv       = aDataset.GetTlv<PskcTlv>();
+    bool           moveKeys      = false;
+    size_t         keyLen;
+    Error          error;
+
+    if (networkKeyTlv != nullptr)
+    {
+        // If the dataset contains a network key, its real value must have been moved to
+        // the secure storage upon saving the dataset, so restore it back now.
+        NetworkKey networkKey;
+        error = ExportKey(networkKeyRef, networkKey.m8, NetworkKey::kSize, keyLen);
+
+        if (error != kErrorNone)
+        {
+            // If ExportKey fails, key is not in secure storage and is stored in settings
+            moveKeys = true;
+        }
+        else
+        {
+            OT_ASSERT(keyLen == NetworkKey::kSize);
+            networkKeyTlv->SetNetworkKey(networkKey);
+        }
+    }
+
+    if (pskcTlv != nullptr)
+    {
+        // If the dataset contains a PSKC, its real value must have been moved to
+        // the secure storage upon saving the dataset, so restore it back now.
+        Pskc pskc;
+        error = ExportKey(pskcRef, pskc.m8, Pskc::kSize, keyLen);
+
+        if (error != kErrorNone)
+        {
+            // If ExportKey fails, key is not in secure storage and is stored in settings
+            moveKeys = true;
+        }
+        else
+        {
+            OT_ASSERT(keyLen == Pskc::kSize);
+            pskcTlv->SetPskc(pskc);
+        }
+    }
+
+    if (moveKeys)
+    {
+        // Clear the networkkey and Pskc stored in the settings and move them to secure storage.
+        // Store the network key and PSKC in the secure storage instead of settings.
+        Dataset dataset;
+
+        dataset.Set(GetType(), aDataset);
+        MoveKeysToSecureStorage(dataset);
+        SuccessOrAssert(error = Get<Settings>().SaveOperationalDataset(mType, dataset));
+    }
+}
+#endif
+
 } // namespace MeshCoP
 } // namespace ot
diff --git a/src/core/meshcop/dataset_local.hpp b/src/core/meshcop/dataset_local.hpp
index 6af9f29..c91c11e 100644
--- a/src/core/meshcop/dataset_local.hpp
+++ b/src/core/meshcop/dataset_local.hpp
@@ -186,6 +186,11 @@
 private:
     bool IsActive(void) const { return (mType == Dataset::kActive); }
     void SetTimestamp(const Dataset &aDataset);
+#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+    void MoveKeysToSecureStorage(Dataset &aDataset) const;
+    void DestroySecurelyStoredKeys(void) const;
+    void EmplaceSecurelyStoredKeys(Dataset &aDataset) const;
+#endif
 
     Timestamp     mTimestamp;            ///< Active or Pending Timestamp
     TimeMilli     mUpdateTime;           ///< Local time last updated
diff --git a/src/core/meshcop/dataset_manager.cpp b/src/core/meshcop/dataset_manager.cpp
index 89b1f1c..355c4b0 100644
--- a/src/core/meshcop/dataset_manager.cpp
+++ b/src/core/meshcop/dataset_manager.cpp
@@ -39,7 +39,7 @@
 #include "common/as_core_type.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/notifier.hpp"
 #include "meshcop/meshcop.hpp"
 #include "meshcop/meshcop_tlvs.hpp"
@@ -51,6 +51,8 @@
 namespace ot {
 namespace MeshCoP {
 
+RegisterLogModule("DatasetManager");
+
 DatasetManager::DatasetManager(Instance &aInstance, Dataset::Type aType, Timer::Handler aTimerHandler)
     : InstanceLocator(aInstance)
     , mLocal(aInstance, aType)
@@ -138,7 +140,7 @@
 
     if (isNetworkkeyUpdated || compare > 0)
     {
-        IgnoreError(mLocal.Save(aDataset));
+        SuccessOrExit(error = mLocal.Save(aDataset));
 
 #if OPENTHREAD_FTD
         Get<NetworkData::Leader>().IncrementVersionAndStableVersion();
@@ -225,10 +227,10 @@
 
 Error DatasetManager::GetChannelMask(Mac::ChannelMask &aChannelMask) const
 {
-    Error                          error;
-    const MeshCoP::ChannelMaskTlv *channelMaskTlv;
-    uint32_t                       mask;
-    Dataset                        dataset;
+    Error                 error;
+    const ChannelMaskTlv *channelMaskTlv;
+    uint32_t              mask;
+    Dataset               dataset;
 
     SuccessOrExit(error = Read(dataset));
 
@@ -253,20 +255,20 @@
 {
     Error            error;
     Coap::Message *  message = nullptr;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
     Dataset          dataset;
 
     VerifyOrExit(!mMgmtPending, error = kErrorBusy);
     VerifyOrExit(Get<Mle::MleRouter>().IsChild() || Get<Mle::MleRouter>().IsRouter(), error = kErrorInvalidState);
 
-    VerifyOrExit(Timestamp::Compare(GetTimestamp(), mLocal.GetTimestamp()) < 0, error = kErrorInvalidState);
+    VerifyOrExit(Timestamp::Compare(GetTimestamp(), mLocal.GetTimestamp()) < 0, error = kErrorAlready);
 
     if (IsActiveDataset())
     {
         Dataset   pendingDataset;
         Timestamp timestamp;
 
-        IgnoreError(Get<PendingDataset>().Read(pendingDataset));
+        IgnoreError(Get<PendingDatasetManager>().Read(pendingDataset));
 
         if ((pendingDataset.GetTimestamp(Dataset::kActive, timestamp) == kErrorNone) &&
             (Timestamp::Compare(&timestamp, mLocal.GetTimestamp()) == 0))
@@ -276,22 +278,18 @@
         }
     }
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error =
-                      message->InitAsConfirmablePost(IsActiveDataset() ? UriPath::kActiveSet : UriPath::kPendingSet));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(IsActiveDataset() ? UriPath::kActiveSet
+                                                                                    : UriPath::kPendingSet);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     IgnoreError(Read(dataset));
     SuccessOrExit(error = message->AppendBytes(dataset.GetBytes(), dataset.GetSize()));
 
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    IgnoreError(Get<Mle::MleRouter>().GetLeaderAloc(messageInfo.GetPeerAddr()));
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
+    IgnoreError(messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc());
     SuccessOrExit(
         error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, &DatasetManager::HandleMgmtSetResponse, this));
 
-    otLogInfoMeshCoP("Sent %s set to leader", Dataset::TypeToString(GetType()));
+    LogInfo("Sent %s set to leader", Dataset::TypeToString(GetType()));
 
 exit:
 
@@ -345,7 +343,7 @@
     }
 
 exit:
-    otLogInfoMeshCoP("MGMT_SET finished: %s", ErrorToString(error));
+    LogInfo("MGMT_SET finished: %s", ErrorToString(error));
 
     mMgmtPending = false;
 
@@ -372,7 +370,7 @@
 
     while (offset < aMessage.GetLength())
     {
-        IgnoreError(aMessage.Read(offset, tlv));
+        SuccessOrExit(aMessage.Read(offset, tlv));
 
         if (tlv.GetType() == Tlv::kGet)
         {
@@ -419,10 +417,8 @@
 
     IgnoreError(Read(dataset));
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityResponseMessage(aRequest);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     if (aLength == 0)
     {
@@ -454,8 +450,8 @@
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, aMessageInfo));
 
-    otLogInfoMeshCoP("sent %s dataset get response to %s", (GetType() == Dataset::kActive ? "active" : "pending"),
-                     aMessageInfo.GetPeerAddr().ToString().AsCString());
+    LogInfo("sent %s dataset get response to %s", (GetType() == Dataset::kActive ? "active" : "pending"),
+            aMessageInfo.GetPeerAddr().ToString().AsCString());
 
 exit:
     FreeMessageOnError(message, error);
@@ -481,15 +477,13 @@
 {
     Error            error   = kErrorNone;
     Coap::Message *  message = nullptr;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
 
     VerifyOrExit(!mMgmtPending, error = kErrorBusy);
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error =
-                      message->InitAsConfirmablePost(IsActiveDataset() ? UriPath::kActiveSet : UriPath::kPendingSet));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(IsActiveDataset() ? UriPath::kActiveSet
+                                                                                    : UriPath::kPendingSet);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
 #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
 
@@ -524,16 +518,14 @@
         SuccessOrExit(error = message->AppendBytes(aTlvs, aLength));
     }
 
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    IgnoreError(Get<Mle::MleRouter>().GetLeaderAloc(messageInfo.GetPeerAddr()));
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
+    IgnoreError(messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc());
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, HandleMgmtSetResponse, this));
     mMgmtSetCallback        = aCallback;
     mMgmtSetCallbackContext = aContext;
     mMgmtPending            = true;
 
-    otLogInfoMeshCoP("sent dataset set request to leader");
+    LogInfo("sent dataset set request to leader");
 
 exit:
     FreeMessageOnError(message, error);
@@ -547,7 +539,7 @@
 {
     Error            error = kErrorNone;
     Coap::Message *  message;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
     Tlv              tlv;
     uint8_t          datasetTlvs[kMaxDatasetTlvs];
     uint8_t          length;
@@ -614,15 +606,9 @@
         datasetTlvs[length++] = Tlv::kChannelMask;
     }
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error =
-                      message->InitAsConfirmablePost(IsActiveDataset() ? UriPath::kActiveGet : UriPath::kPendingGet));
-
-    if (aLength + length > 0)
-    {
-        SuccessOrExit(error = message->SetPayloadMarker());
-    }
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(IsActiveDataset() ? UriPath::kActiveGet
+                                                                                    : UriPath::kPendingGet);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     if (aLength + length > 0)
     {
@@ -641,42 +627,39 @@
         }
     }
 
+    IgnoreError(messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc());
+
     if (aAddress != nullptr)
     {
+        // Use leader ALOC if `aAddress` is `nullptr`.
         messageInfo.SetPeerAddr(AsCoreType(aAddress));
     }
-    else
-    {
-        IgnoreError(Get<Mle::MleRouter>().GetLeaderAloc(messageInfo.GetPeerAddr()));
-    }
 
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
 
-    otLogInfoMeshCoP("sent dataset get request");
+    LogInfo("sent dataset get request");
 
 exit:
     FreeMessageOnError(message, error);
     return error;
 }
 
-ActiveDataset::ActiveDataset(Instance &aInstance)
-    : DatasetManager(aInstance, Dataset::kActive, ActiveDataset::HandleTimer)
-    , mResourceGet(UriPath::kActiveGet, &ActiveDataset::HandleGet, this)
+ActiveDatasetManager::ActiveDatasetManager(Instance &aInstance)
+    : DatasetManager(aInstance, Dataset::kActive, ActiveDatasetManager::HandleTimer)
+    , mResourceGet(UriPath::kActiveGet, &ActiveDatasetManager::HandleGet, this)
 #if OPENTHREAD_FTD
-    , mResourceSet(UriPath::kActiveSet, &ActiveDataset::HandleSet, this)
+    , mResourceSet(UriPath::kActiveSet, &ActiveDatasetManager::HandleSet, this)
 #endif
 {
     Get<Tmf::Agent>().AddResource(mResourceGet);
 }
 
-bool ActiveDataset::IsPartiallyComplete(void) const
+bool ActiveDatasetManager::IsPartiallyComplete(void) const
 {
     return mLocal.IsSaved() && !mTimestampValid;
 }
 
-bool ActiveDataset::IsCommissioned(void) const
+bool ActiveDatasetManager::IsCommissioned(void) const
 {
     Dataset::Info datasetInfo;
     bool          isValid = false;
@@ -690,52 +673,55 @@
     return isValid;
 }
 
-Error ActiveDataset::Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength)
+Error ActiveDatasetManager::Save(const Timestamp &aTimestamp,
+                                 const Message &  aMessage,
+                                 uint16_t         aOffset,
+                                 uint8_t          aLength)
 {
     Error   error = kErrorNone;
     Dataset dataset;
 
-    SuccessOrExit(error = dataset.Set(aMessage, aOffset, aLength));
+    SuccessOrExit(error = dataset.ReadFromMessage(aMessage, aOffset, aLength));
     dataset.SetTimestamp(Dataset::kActive, aTimestamp);
-    IgnoreError(DatasetManager::Save(dataset));
+    error = DatasetManager::Save(dataset);
 
 exit:
     return error;
 }
 
-void ActiveDataset::HandleGet(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
+void ActiveDatasetManager::HandleGet(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
 {
-    static_cast<ActiveDataset *>(aContext)->HandleGet(AsCoapMessage(aMessage), AsCoreType(aMessageInfo));
+    static_cast<ActiveDatasetManager *>(aContext)->HandleGet(AsCoapMessage(aMessage), AsCoreType(aMessageInfo));
 }
 
-void ActiveDataset::HandleGet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const
+void ActiveDatasetManager::HandleGet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const
 {
     DatasetManager::HandleGet(aMessage, aMessageInfo);
 }
 
-void ActiveDataset::HandleTimer(Timer &aTimer)
+void ActiveDatasetManager::HandleTimer(Timer &aTimer)
 {
-    aTimer.Get<ActiveDataset>().HandleTimer();
+    aTimer.Get<ActiveDatasetManager>().HandleTimer();
 }
 
-PendingDataset::PendingDataset(Instance &aInstance)
-    : DatasetManager(aInstance, Dataset::kPending, PendingDataset::HandleTimer)
-    , mDelayTimer(aInstance, PendingDataset::HandleDelayTimer)
-    , mResourceGet(UriPath::kPendingGet, &PendingDataset::HandleGet, this)
+PendingDatasetManager::PendingDatasetManager(Instance &aInstance)
+    : DatasetManager(aInstance, Dataset::kPending, PendingDatasetManager::HandleTimer)
+    , mDelayTimer(aInstance, PendingDatasetManager::HandleDelayTimer)
+    , mResourceGet(UriPath::kPendingGet, &PendingDatasetManager::HandleGet, this)
 #if OPENTHREAD_FTD
-    , mResourceSet(UriPath::kPendingSet, &PendingDataset::HandleSet, this)
+    , mResourceSet(UriPath::kPendingSet, &PendingDatasetManager::HandleSet, this)
 #endif
 {
     Get<Tmf::Agent>().AddResource(mResourceGet);
 }
 
-void PendingDataset::Clear(void)
+void PendingDatasetManager::Clear(void)
 {
     DatasetManager::Clear();
     mDelayTimer.Stop();
 }
 
-void PendingDataset::ClearNetwork(void)
+void PendingDatasetManager::ClearNetwork(void)
 {
     Dataset dataset;
 
@@ -744,7 +730,7 @@
     IgnoreError(DatasetManager::Save(dataset));
 }
 
-Error PendingDataset::Save(const Dataset::Info &aDatasetInfo)
+Error PendingDatasetManager::Save(const Dataset::Info &aDatasetInfo)
 {
     Error error;
 
@@ -755,7 +741,7 @@
     return error;
 }
 
-Error PendingDataset::Save(const otOperationalDatasetTlvs &aDataset)
+Error PendingDatasetManager::Save(const otOperationalDatasetTlvs &aDataset)
 {
     Error error;
 
@@ -766,7 +752,7 @@
     return error;
 }
 
-Error PendingDataset::Save(const Dataset &aDataset)
+Error PendingDatasetManager::Save(const Dataset &aDataset)
 {
     Error error;
 
@@ -777,21 +763,24 @@
     return error;
 }
 
-Error PendingDataset::Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength)
+Error PendingDatasetManager::Save(const Timestamp &aTimestamp,
+                                  const Message &  aMessage,
+                                  uint16_t         aOffset,
+                                  uint8_t          aLength)
 {
     Error   error = kErrorNone;
     Dataset dataset;
 
-    SuccessOrExit(error = dataset.Set(aMessage, aOffset, aLength));
+    SuccessOrExit(error = dataset.ReadFromMessage(aMessage, aOffset, aLength));
     dataset.SetTimestamp(Dataset::kPending, aTimestamp);
-    IgnoreError(DatasetManager::Save(dataset));
+    SuccessOrExit(error = DatasetManager::Save(dataset));
     StartDelayTimer();
 
 exit:
     return error;
 }
 
-void PendingDataset::StartDelayTimer(void)
+void PendingDatasetManager::StartDelayTimer(void)
 {
     DelayTimerTlv *delayTimer;
     Dataset        dataset;
@@ -811,16 +800,16 @@
         }
 
         mDelayTimer.StartAt(dataset.GetUpdateTime(), delay);
-        otLogInfoMeshCoP("delay timer started %d", delay);
+        LogInfo("delay timer started %d", delay);
     }
 }
 
-void PendingDataset::HandleDelayTimer(Timer &aTimer)
+void PendingDatasetManager::HandleDelayTimer(Timer &aTimer)
 {
-    aTimer.Get<PendingDataset>().HandleDelayTimer();
+    aTimer.Get<PendingDatasetManager>().HandleDelayTimer();
 }
 
-void PendingDataset::HandleDelayTimer(void)
+void PendingDatasetManager::HandleDelayTimer(void)
 {
     DelayTimerTlv *delayTimer;
     Dataset        dataset;
@@ -841,11 +830,11 @@
         }
     }
 
-    otLogInfoMeshCoP("pending delay timer expired");
+    LogInfo("pending delay timer expired");
 
     dataset.ConvertToActive();
 
-    Get<ActiveDataset>().Save(dataset);
+    Get<ActiveDatasetManager>().Save(dataset);
 
     Clear();
 
@@ -853,19 +842,19 @@
     return;
 }
 
-void PendingDataset::HandleGet(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
+void PendingDatasetManager::HandleGet(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
 {
-    static_cast<PendingDataset *>(aContext)->HandleGet(AsCoapMessage(aMessage), AsCoreType(aMessageInfo));
+    static_cast<PendingDatasetManager *>(aContext)->HandleGet(AsCoapMessage(aMessage), AsCoreType(aMessageInfo));
 }
 
-void PendingDataset::HandleGet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const
+void PendingDatasetManager::HandleGet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const
 {
     DatasetManager::HandleGet(aMessage, aMessageInfo);
 }
 
-void PendingDataset::HandleTimer(Timer &aTimer)
+void PendingDatasetManager::HandleTimer(Timer &aTimer)
 {
-    aTimer.Get<PendingDataset>().HandleTimer();
+    aTimer.Get<PendingDatasetManager>().HandleTimer();
 }
 
 } // namespace MeshCoP
diff --git a/src/core/meshcop/dataset_manager.hpp b/src/core/meshcop/dataset_manager.hpp
index 75ee9f7..9d54874 100644
--- a/src/core/meshcop/dataset_manager.hpp
+++ b/src/core/meshcop/dataset_manager.hpp
@@ -272,6 +272,9 @@
      * @param[in]  aOffset     The offset where the Operational Dataset begins.
      * @param[in]  aLength     The length of the Operational Dataset.
      *
+     * @retval kErrorNone     Successfully parsed the Dataset from the @p aMessage and saved it.
+     * @retval kErrorParse    Could not parse the Dataset from @p aMessage.
+     *
      */
     Error Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength);
 
@@ -360,16 +363,16 @@
     void *                   mMgmtSetCallbackContext;
 };
 
-class ActiveDataset : public DatasetManager, private NonCopyable
+class ActiveDatasetManager : public DatasetManager, private NonCopyable
 {
 public:
     /**
-     * This constructor initializes the ActiveDataset object.
+     * This constructor initializes the ActiveDatasetManager object.
      *
      * @param[in]  aInstance  A reference to the OpenThread instance.
      *
      */
-    explicit ActiveDataset(Instance &aInstance);
+    explicit ActiveDatasetManager(Instance &aInstance);
 
     /**
      * This method indicates whether the Active Dataset is partially complete.
@@ -419,6 +422,9 @@
      * @param[in]  aOffset     The offset where the Operational Dataset begins.
      * @param[in]  aLength     The length of the Operational Dataset.
      *
+     * @retval kErrorNone     Successfully parsed the Dataset from the @p aMessage and saved it.
+     * @retval kErrorParse    Could not parse the Dataset from @p aMessage.
+     *
      */
     Error Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength);
 
@@ -499,16 +505,16 @@
 #endif
 };
 
-class PendingDataset : public DatasetManager, private NonCopyable
+class PendingDatasetManager : public DatasetManager, private NonCopyable
 {
 public:
     /**
-     * This constructor initializes the PendingDataset object.
+     * This constructor initializes the PendingDatasetManager object.
      *
      * @param[in]  aInstance     A reference to the OpenThread instance.
      *
      */
-    explicit PendingDataset(Instance &aInstance);
+    explicit PendingDatasetManager(Instance &aInstance);
 
     /**
      * This method clears the Pending Operational Dataset.
diff --git a/src/core/meshcop/dataset_manager_ftd.cpp b/src/core/meshcop/dataset_manager_ftd.cpp
index 68a8515..4face84 100644
--- a/src/core/meshcop/dataset_manager_ftd.cpp
+++ b/src/core/meshcop/dataset_manager_ftd.cpp
@@ -46,7 +46,7 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/random.hpp"
 #include "common/timer.hpp"
 #include "meshcop/dataset.hpp"
@@ -60,6 +60,8 @@
 namespace ot {
 namespace MeshCoP {
 
+RegisterLogModule("DatasetManager");
+
 Error DatasetManager::AppendMleDatasetTlv(Message &aMessage) const
 {
     Dataset dataset;
@@ -71,20 +73,20 @@
 
 Error DatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
 {
-    Tlv                  tlv;
-    uint16_t             offset                   = aMessage.GetOffset();
-    bool                 isUpdateFromCommissioner = false;
-    bool                 doesAffectConnectivity   = false;
-    bool                 doesAffectNetworkKey     = false;
-    bool                 hasNetworkKey            = false;
-    StateTlv::State      state                    = StateTlv::kReject;
-    Dataset              dataset;
-    Timestamp            activeTimestamp;
-    ChannelTlv           channel;
-    uint16_t             sessionId;
-    Mle::MeshLocalPrefix meshLocalPrefix;
-    NetworkKey           networkKey;
-    uint16_t             panId;
+    Tlv                tlv;
+    uint16_t           offset                   = aMessage.GetOffset();
+    bool               isUpdateFromCommissioner = false;
+    bool               doesAffectConnectivity   = false;
+    bool               doesAffectNetworkKey     = false;
+    bool               hasNetworkKey            = false;
+    StateTlv::State    state                    = StateTlv::kReject;
+    Dataset            dataset;
+    Timestamp          activeTimestamp;
+    ChannelTlv         channel;
+    uint16_t           sessionId;
+    Ip6::NetworkPrefix meshLocalPrefix;
+    NetworkKey         networkKey;
+    uint16_t           panId;
 
     VerifyOrExit(Get<Mle::MleRouter>().IsLeader());
 
@@ -157,7 +159,7 @@
     if (GetType() == Dataset::kPending && (!hasNetworkKey || !doesAffectNetworkKey))
     {
         // no change to network key, active timestamp must be ahead
-        const Timestamp *localActiveTimestamp = Get<ActiveDataset>().GetTimestamp();
+        const Timestamp *localActiveTimestamp = Get<ActiveDatasetManager>().GetTimestamp();
 
         VerifyOrExit(Timestamp::Compare(&activeTimestamp, localActiveTimestamp) > 0);
     }
@@ -169,7 +171,7 @@
 
         isUpdateFromCommissioner = true;
 
-        localId = static_cast<const CommissionerSessionIdTlv *>(
+        localId = As<CommissionerSessionIdTlv>(
             Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kCommissionerSessionId));
 
         VerifyOrExit(localId != nullptr && localId->GetCommissionerSessionId() == sessionId);
@@ -182,7 +184,7 @@
     {
         // Thread specification allows partial dataset changes for MGMT_ACTIVE_SET.req/MGMT_PENDING_SET.req
         // from Commissioner based on existing active dataset.
-        IgnoreError(Get<ActiveDataset>().Read(dataset));
+        IgnoreError(Get<ActiveDatasetManager>().Read(dataset));
     }
 
     if (GetType() == Dataset::kPending || !doesAffectConnectivity)
@@ -203,7 +205,7 @@
 
             case Tlv::kDelayTimer:
             {
-                DelayTimerTlv &delayTimerTlv = static_cast<DelayTimerTlv &>(static_cast<Tlv &>(datasetTlv));
+                DelayTimerTlv &delayTimerTlv = As<DelayTimerTlv>(datasetTlv);
 
                 if (doesAffectNetworkKey && delayTimerTlv.GetDelayTimer() < DelayTimerTlv::kDelayTimerDefault)
                 {
@@ -230,7 +232,7 @@
     }
     else
     {
-        Get<PendingDataset>().ApplyActiveDataset(activeTimestamp, aMessage);
+        Get<PendingDatasetManager>().ApplyActiveDataset(activeTimestamp, aMessage);
     }
 
     state = StateTlv::kAccept;
@@ -241,7 +243,7 @@
         const CommissionerSessionIdTlv *localSessionId;
         Ip6::Address                    destination;
 
-        localSessionId = static_cast<const CommissionerSessionIdTlv *>(
+        localSessionId = As<CommissionerSessionIdTlv>(
             Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kCommissionerSessionId));
         VerifyOrExit(localSessionId != nullptr);
 
@@ -268,16 +270,14 @@
     Error          error = kErrorNone;
     Coap::Message *message;
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityResponseMessage(aRequest);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = Tlv::Append<StateTlv>(*message, aState));
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, aMessageInfo));
 
-    otLogInfoMeshCoP("sent dataset set response");
+    LogInfo("sent dataset set response");
 
 exit:
     FreeMessageOnError(message, error);
@@ -296,7 +296,7 @@
     return error;
 }
 
-Error ActiveDataset::GenerateLocal(void)
+Error ActiveDatasetManager::GenerateLocal(void)
 {
     Error   error = kErrorNone;
     Dataset dataset;
@@ -332,7 +332,7 @@
 
     if (dataset.GetTlv<ExtendedPanIdTlv>() == nullptr)
     {
-        IgnoreError(dataset.SetTlv(Tlv::kExtendedPanId, Get<Mac::Mac>().GetExtendedPanId()));
+        IgnoreError(dataset.SetTlv(Tlv::kExtendedPanId, Get<ExtendedPanIdManager>().GetExtPanId()));
     }
 
     if (dataset.GetTlv<MeshLocalPrefixTlv>() == nullptr)
@@ -350,7 +350,7 @@
 
     if (dataset.GetTlv<NetworkNameTlv>() == nullptr)
     {
-        Mac::NameData nameData = Get<Mac::Mac>().GetNetworkName().GetAsData();
+        NameData nameData = Get<NetworkNameManager>().GetNetworkName().GetAsData();
 
         IgnoreError(dataset.SetTlv(Tlv::kNetworkName, nameData.GetBuffer(), nameData.GetLength()));
     }
@@ -388,29 +388,29 @@
     SuccessOrExit(error = mLocal.Save(dataset));
     IgnoreError(Restore());
 
-    otLogInfoMeshCoP("Generated local dataset");
+    LogInfo("Generated local dataset");
 
 exit:
     return error;
 }
 
-void ActiveDataset::StartLeader(void)
+void ActiveDatasetManager::StartLeader(void)
 {
     IgnoreError(GenerateLocal());
     Get<Tmf::Agent>().AddResource(mResourceSet);
 }
 
-void ActiveDataset::StopLeader(void)
+void ActiveDatasetManager::StopLeader(void)
 {
     Get<Tmf::Agent>().RemoveResource(mResourceSet);
 }
 
-void ActiveDataset::HandleSet(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
+void ActiveDatasetManager::HandleSet(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
 {
-    static_cast<ActiveDataset *>(aContext)->HandleSet(AsCoapMessage(aMessage), AsCoreType(aMessageInfo));
+    static_cast<ActiveDatasetManager *>(aContext)->HandleSet(AsCoapMessage(aMessage), AsCoreType(aMessageInfo));
 }
 
-void ActiveDataset::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+void ActiveDatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
 {
     SuccessOrExit(DatasetManager::HandleSet(aMessage, aMessageInfo));
     IgnoreError(ApplyConfiguration());
@@ -419,23 +419,23 @@
     return;
 }
 
-void PendingDataset::StartLeader(void)
+void PendingDatasetManager::StartLeader(void)
 {
     StartDelayTimer();
     Get<Tmf::Agent>().AddResource(mResourceSet);
 }
 
-void PendingDataset::StopLeader(void)
+void PendingDatasetManager::StopLeader(void)
 {
     Get<Tmf::Agent>().RemoveResource(mResourceSet);
 }
 
-void PendingDataset::HandleSet(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
+void PendingDatasetManager::HandleSet(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
 {
-    static_cast<PendingDataset *>(aContext)->HandleSet(AsCoapMessage(aMessage), AsCoreType(aMessageInfo));
+    static_cast<PendingDatasetManager *>(aContext)->HandleSet(AsCoapMessage(aMessage), AsCoreType(aMessageInfo));
 }
 
-void PendingDataset::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+void PendingDatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
 {
     SuccessOrExit(DatasetManager::HandleSet(aMessage, aMessageInfo));
     StartDelayTimer();
@@ -444,7 +444,7 @@
     return;
 }
 
-void PendingDataset::ApplyActiveDataset(const Timestamp &aTimestamp, Coap::Message &aMessage)
+void PendingDatasetManager::ApplyActiveDataset(const Timestamp &aTimestamp, Coap::Message &aMessage)
 {
     uint16_t offset = aMessage.GetOffset();
     Dataset  dataset;
diff --git a/src/core/meshcop/dataset_updater.cpp b/src/core/meshcop/dataset_updater.cpp
index 8185457..36d63d7 100644
--- a/src/core/meshcop/dataset_updater.cpp
+++ b/src/core/meshcop/dataset_updater.cpp
@@ -39,8 +39,9 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/random.hpp"
+#include "meshcop/timestamp.hpp"
 
 namespace ot {
 namespace MeshCoP {
@@ -54,7 +55,7 @@
 {
 }
 
-Error DatasetUpdater::RequestUpdate(const MeshCoP::Dataset::Info &aDataset, Callback aCallback, void *aContext)
+Error DatasetUpdater::RequestUpdate(const Dataset::Info &aDataset, Callback aCallback, void *aContext)
 {
     Error    error   = kErrorNone;
     Message *message = nullptr;
@@ -65,7 +66,7 @@
     VerifyOrExit(!aDataset.IsActiveTimestampPresent() && !aDataset.IsPendingTimestampPresent(),
                  error = kErrorInvalidArgs);
 
-    message = Get<MessagePool>().New(Message::kTypeOther, 0);
+    message = Get<MessagePool>().Allocate(Message::kTypeOther);
     VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = message->Append(aDataset));
@@ -105,15 +106,15 @@
 
 void DatasetUpdater::PreparePendingDataset(void)
 {
-    Dataset                dataset;
-    MeshCoP::Dataset::Info requestedDataset;
-    Error                  error;
+    Dataset       dataset;
+    Dataset::Info requestedDataset;
+    Error         error;
 
     VerifyOrExit(!Get<Mle::Mle>().IsDisabled(), error = kErrorInvalidState);
 
     IgnoreError(mDataset->Read(0, requestedDataset));
 
-    error = Get<ActiveDataset>().Read(dataset);
+    error = Get<ActiveDatasetManager>().Read(dataset);
 
     if (error != kErrorNone)
     {
@@ -139,9 +140,9 @@
     {
         Timestamp timestamp;
 
-        if (Get<PendingDataset>().GetTimestamp() != nullptr)
+        if (Get<PendingDatasetManager>().GetTimestamp() != nullptr)
         {
-            timestamp = *Get<PendingDataset>().GetTimestamp();
+            timestamp = *Get<PendingDatasetManager>().GetTimestamp();
         }
 
         timestamp.AdvanceRandomTicks();
@@ -154,7 +155,7 @@
         tlv->GetTimestamp().AdvanceRandomTicks();
     }
 
-    SuccessOrExit(error = Get<PendingDataset>().Save(dataset));
+    SuccessOrExit(error = Get<PendingDatasetManager>().Save(dataset));
 
 exit:
     if (error != kErrorNone)
@@ -178,8 +179,8 @@
 
 void DatasetUpdater::HandleNotifierEvents(Events aEvents)
 {
-    MeshCoP::Dataset::Info requestedDataset;
-    MeshCoP::Dataset::Info dataset;
+    Dataset::Info requestedDataset;
+    Dataset::Info dataset;
 
     VerifyOrExit(mDataset != nullptr);
 
@@ -187,19 +188,27 @@
 
     IgnoreError(mDataset->Read(0, requestedDataset));
 
-    if (aEvents.Contains(kEventActiveDatasetChanged) && Get<MeshCoP::ActiveDataset>().Read(dataset) == kErrorNone)
+    if (aEvents.Contains(kEventActiveDatasetChanged) && Get<ActiveDatasetManager>().Read(dataset) == kErrorNone)
     {
         if (requestedDataset.IsSubsetOf(dataset))
         {
             Finish(kErrorNone);
         }
-        else if (requestedDataset.GetActiveTimestamp() <= dataset.GetActiveTimestamp())
+        else
         {
-            Finish(kErrorAlready);
+            Timestamp requestedDatasetTimestamp;
+            Timestamp activeDatasetTimestamp;
+
+            requestedDataset.GetActiveTimestamp(requestedDatasetTimestamp);
+            dataset.GetActiveTimestamp(activeDatasetTimestamp);
+            if (Timestamp::Compare(requestedDatasetTimestamp, activeDatasetTimestamp) <= 0)
+            {
+                Finish(kErrorAlready);
+            }
         }
     }
 
-    if (aEvents.Contains(kEventPendingDatasetChanged) && Get<MeshCoP::PendingDataset>().Read(dataset) == kErrorNone)
+    if (aEvents.Contains(kEventPendingDatasetChanged) && Get<PendingDatasetManager>().Read(dataset) == kErrorNone)
     {
         if (!requestedDataset.IsSubsetOf(dataset))
         {
diff --git a/src/core/meshcop/dataset_updater.hpp b/src/core/meshcop/dataset_updater.hpp
index c72c644..b3b94c0 100644
--- a/src/core/meshcop/dataset_updater.hpp
+++ b/src/core/meshcop/dataset_updater.hpp
@@ -74,13 +74,6 @@
      *
      * The function pointer has the syntax `void (*Callback)(Error aError, void *aContext)`.
      *
-     * @param[in] aError   The error status.
-     *                     kErrorNone           indicates Dataset update successfully finished.
-     *                     kErrorInvalidState   indicates failure due invalid state (MLE being disabled).
-     *                     kErrorAlready        indicates failure due to another device within network requesting a
-     *                                          conflicting Dataset update.
-     * @param[in] aContext A pointer to the arbitrary context provided by the user.
-     *
      */
     typedef otDatasetUpdaterCallback Callback;
 
@@ -101,7 +94,7 @@
      * @retval kErrorNoBufs         Could not allocated buffer to save Dataset.
      *
      */
-    Error RequestUpdate(const MeshCoP::Dataset::Info &aDataset, Callback aCallback, void *aContext);
+    Error RequestUpdate(const Dataset::Info &aDataset, Callback aCallback, void *aContext);
 
     /**
      * This method cancels an ongoing (if any) Operational Dataset update request.
diff --git a/src/core/meshcop/dtls.cpp b/src/core/meshcop/dtls.cpp
index 3ef65d5..7a558aa 100644
--- a/src/core/meshcop/dtls.cpp
+++ b/src/core/meshcop/dtls.cpp
@@ -40,12 +40,13 @@
 
 #include <openthread/platform/radio.h>
 
+#include "common/as_core_type.hpp"
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/timer.hpp"
 #include "crypto/mbedtls.hpp"
 #include "crypto/sha256.hpp"
@@ -56,7 +57,14 @@
 namespace ot {
 namespace MeshCoP {
 
+RegisterLogModule("Dtls");
+
+#if (MBEDTLS_VERSION_NUMBER >= 0x03010000)
+const uint16_t Dtls::sGroups[] = {MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, MBEDTLS_SSL_IANA_TLS_GROUP_NONE};
+#else
 const mbedtls_ecp_group_id Dtls::sCurves[] = {MBEDTLS_ECP_DP_SECP256R1, MBEDTLS_ECP_DP_NONE};
+#endif
+
 #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
 const int Dtls::sHashes[] = {MBEDTLS_MD_SHA256, MBEDTLS_MD_NONE};
 #endif
@@ -161,18 +169,17 @@
 
 void Dtls::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
 {
-    static_cast<Dtls *>(aContext)->HandleUdpReceive(*static_cast<Message *>(aMessage),
-                                                    *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
+    static_cast<Dtls *>(aContext)->HandleUdpReceive(AsCoreType(aMessage), AsCoreType(aMessageInfo));
 }
 
 void Dtls::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
 {
     switch (mState)
     {
-    case MeshCoP::Dtls::kStateClosed:
+    case Dtls::kStateClosed:
         ExitNow();
 
-    case MeshCoP::Dtls::kStateOpen:
+    case Dtls::kStateOpen:
         IgnoreError(mSocket.Connect(Ip6::SockAddr(aMessageInfo.GetPeerAddr(), aMessageInfo.GetPeerPort())));
 
         mMessageInfo.SetPeerAddr(aMessageInfo.GetPeerAddr());
@@ -197,7 +204,7 @@
     }
 
 #ifdef MBEDTLS_SSL_SRV_C
-    if (mState == MeshCoP::Dtls::kStateConnecting)
+    if (mState == Dtls::kStateConnecting)
     {
         IgnoreError(SetClientId(mMessageInfo.GetPeerAddr().mFields.m8, sizeof(mMessageInfo.GetPeerAddr().mFields)));
     }
@@ -281,7 +288,7 @@
     OT_UNUSED_VARIABLE(mVerifyPeerCertificate);
 #endif
 
-    mbedtls_ssl_conf_rng(&mConf, mbedtls_ctr_drbg_random, Random::Crypto::MbedTlsContextGet());
+    mbedtls_ssl_conf_rng(&mConf, Crypto::MbedTls::CryptoSecurePrng, nullptr);
     mbedtls_ssl_conf_min_version(&mConf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
     mbedtls_ssl_conf_max_version(&mConf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
 
@@ -289,7 +296,11 @@
     mbedtls_ssl_conf_ciphersuites(&mConf, mCipherSuites);
     if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
     {
+#if (MBEDTLS_VERSION_NUMBER >= 0x03010000)
+        mbedtls_ssl_conf_groups(&mConf, sGroups);
+#else
         mbedtls_ssl_conf_curves(&mConf, sCurves);
+#endif
 #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
         mbedtls_ssl_conf_sig_hashes(&mConf, sHashes);
 #endif
@@ -307,7 +318,7 @@
 #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
     if (!aClient)
     {
-        rval = mbedtls_ssl_cookie_setup(&mCookieCtx, mbedtls_ctr_drbg_random, Random::Crypto::MbedTlsContextGet());
+        rval = mbedtls_ssl_cookie_setup(&mCookieCtx, Crypto::MbedTls::CryptoSecurePrng, nullptr);
         VerifyOrExit(rval == 0);
 
         mbedtls_ssl_conf_dtls_cookies(&mConf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &mCookieCtx);
@@ -338,12 +349,12 @@
 
     if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
     {
-        otLogInfoMeshCoP("DTLS started");
+        LogInfo("DTLS started");
     }
 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
     else
     {
-        otLogInfoCoap("Application Coap Secure DTLS started");
+        LogInfo("Application Coap Secure DTLS started");
     }
 #endif
 
@@ -386,8 +397,8 @@
 
 #if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
             rval = mbedtls_pk_parse_key(&mPrivateKey, static_cast<const unsigned char *>(mPrivateKeySrc),
-                                        static_cast<size_t>(mPrivateKeyLength), nullptr, 0, mbedtls_ctr_drbg_random,
-                                        Random::Crypto::MbedTlsContextGet());
+                                        static_cast<size_t>(mPrivateKeyLength), nullptr, 0,
+                                        Crypto::MbedTls::CryptoSecurePrng, nullptr);
 #else
             rval = mbedtls_pk_parse_key(&mPrivateKey, static_cast<const unsigned char *>(mPrivateKeySrc),
                                         static_cast<size_t>(mPrivateKeyLength), nullptr, 0);
@@ -408,7 +419,7 @@
         break;
 
     default:
-        otLogCritCoap("Application Coap Secure DTLS: Not supported cipher.");
+        LogCrit("Application Coap Secure: Not supported cipher.");
         rval = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
         ExitNow();
         break;
@@ -524,12 +535,19 @@
 
     VerifyOrExit(mState == kStateConnected, error = kErrorInvalidState);
 
+#if (MBEDTLS_VERSION_NUMBER >= 0x03010000)
+    VerifyOrExit(mbedtls_base64_encode(aPeerCert, aCertBufferSize, aCertLength,
+                                       mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.p,
+                                       mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.len) == 0,
+                 error = kErrorNoBufs);
+#else
     VerifyOrExit(
         mbedtls_base64_encode(
             aPeerCert, aCertBufferSize, aCertLength,
             mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p),
             mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len)) == 0,
         error = kErrorNoBufs);
+#endif
 
 exit:
     return error;
@@ -590,12 +608,12 @@
 
     if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
     {
-        otLogDebgMeshCoP("Dtls::HandleMbedtlsTransmit");
+        LogDebg("HandleMbedtlsTransmit");
     }
 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
     else
     {
-        otLogDebgCoap("Dtls::ApplicationCoapSecure HandleMbedtlsTransmit");
+        LogDebg("ApplicationCoapSecure HandleMbedtlsTransmit");
     }
 #endif
 
@@ -615,7 +633,7 @@
         break;
 
     default:
-        otLogWarnMeshCoP("Dtls::HandleMbedtlsTransmit: %s error", ErrorToString(error));
+        LogWarn("HandleMbedtlsTransmit: %s error", ErrorToString(error));
         rval = MBEDTLS_ERR_NET_SEND_FAILED;
         break;
     }
@@ -634,12 +652,12 @@
 
     if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
     {
-        otLogDebgMeshCoP("Dtls::HandleMbedtlsReceive");
+        LogDebg("HandleMbedtlsReceive");
     }
 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
     else
     {
-        otLogDebgCoap("Dtls:: ApplicationCoapSecure HandleMbedtlsReceive");
+        LogDebg("ApplicationCoapSecure HandleMbedtlsReceive");
     }
 #endif
 
@@ -669,12 +687,12 @@
 
     if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
     {
-        otLogDebgMeshCoP("Dtls::HandleMbedtlsGetTimer");
+        LogDebg("HandleMbedtlsGetTimer");
     }
 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
     else
     {
-        otLogDebgCoap("Dtls:: ApplicationCoapSecure HandleMbedtlsGetTimer");
+        LogDebg("ApplicationCoapSecure HandleMbedtlsGetTimer");
     }
 #endif
 
@@ -707,12 +725,12 @@
 {
     if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
     {
-        otLogDebgMeshCoP("Dtls::SetTimer");
+        LogDebg("SetTimer");
     }
 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
     else
     {
-        otLogDebgCoap("Dtls::ApplicationCoapSecure SetTimer");
+        LogDebg("ApplicationCoapSecure SetTimer");
     }
 #endif
 
@@ -769,7 +787,7 @@
     sha256.Update(keyBlock, kDtlsKeyBlockSize);
     sha256.Finish(kek);
 
-    otLogDebgMeshCoP("Generated KEK");
+    LogDebg("Generated KEK");
     Get<KeyManager>().SetKek(kek.GetBytes());
 
 exit:
@@ -778,12 +796,12 @@
 
 #else
 
-int Dtls::HandleMbedtlsExportKeys(void *aContext,
+int Dtls::HandleMbedtlsExportKeys(void *               aContext,
                                   const unsigned char *aMasterSecret,
                                   const unsigned char *aKeyBlock,
-                                  size_t aMacLength,
-                                  size_t aKeyLength,
-                                  size_t aIvLength)
+                                  size_t               aMacLength,
+                                  size_t               aKeyLength,
+                                  size_t               aIvLength)
 {
     return static_cast<Dtls *>(aContext)->HandleMbedtlsExportKeys(aMasterSecret, aKeyBlock, aMacLength, aKeyLength,
                                                                   aIvLength);
@@ -791,14 +809,14 @@
 
 int Dtls::HandleMbedtlsExportKeys(const unsigned char *aMasterSecret,
                                   const unsigned char *aKeyBlock,
-                                  size_t aMacLength,
-                                  size_t aKeyLength,
-                                  size_t aIvLength)
+                                  size_t               aMacLength,
+                                  size_t               aKeyLength,
+                                  size_t               aIvLength)
 {
     OT_UNUSED_VARIABLE(aMasterSecret);
 
     Crypto::Sha256::Hash kek;
-    Crypto::Sha256 sha256;
+    Crypto::Sha256       sha256;
 
     VerifyOrExit(mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8);
 
@@ -806,7 +824,7 @@
     sha256.Update(aKeyBlock, 2 * static_cast<uint16_t>(aMacLength + aKeyLength + aIvLength));
     sha256.Finish(kek);
 
-    otLogDebgMeshCoP("Generated KEK");
+    LogDebg("Generated KEK");
     Get<KeyManager>().SetKek(kek.GetBytes());
 
 exit:
@@ -952,20 +970,20 @@
     switch (aLevel)
     {
     case 1:
-        otLogCritMbedTls("[%hu] %s", mSocket.GetSockName().mPort, aStr);
+        LogCrit("[%hu] %s", mSocket.GetSockName().mPort, aStr);
         break;
 
     case 2:
-        otLogWarnMbedTls("[%hu] %s", mSocket.GetSockName().mPort, aStr);
+        LogWarn("[%hu] %s", mSocket.GetSockName().mPort, aStr);
         break;
 
     case 3:
-        otLogInfoMbedTls("[%hu] %s", mSocket.GetSockName().mPort, aStr);
+        LogInfo("[%hu] %s", mSocket.GetSockName().mPort, aStr);
         break;
 
     case 4:
     default:
-        otLogDebgMbedTls("[%hu] %s", mSocket.GetSockName().mPort, aStr);
+        LogDebg("[%hu] %s", mSocket.GetSockName().mPort, aStr);
         break;
     }
 }
diff --git a/src/core/meshcop/dtls.hpp b/src/core/meshcop/dtls.hpp
index 40db551..0f809de 100644
--- a/src/core/meshcop/dtls.hpp
+++ b/src/core/meshcop/dtls.hpp
@@ -72,7 +72,7 @@
     /**
      * This constructor initializes the DTLS object.
      *
-     * @param[in]  aNetif               A reference to the Thread network interface.
+     * @param[in]  aInstance            A reference to the OpenThread instance.
      * @param[in]  aLayerTwoSecurity    Specifies whether to use layer two security or not.
      *
      */
@@ -357,7 +357,7 @@
 #if !OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
     static constexpr uint16_t kApplicationDataMaxLength = 1152;
 #else
-    static constexpr uint16_t kApplicationDataMaxLength = OPENTHREAD_CONFIG_DTLS_APPLICATION_DATA_MAX_LENGTH;
+    static constexpr uint16_t         kApplicationDataMaxLength = OPENTHREAD_CONFIG_DTLS_APPLICATION_DATA_MAX_LENGTH;
 #endif
 
     static constexpr size_t kDtlsKeyBlockSize     = 40;
@@ -442,7 +442,12 @@
     uint8_t mPsk[kPskMaxLength];
     uint8_t mPskLength;
 
+#if (MBEDTLS_VERSION_NUMBER >= 0x03010000)
+    static const uint16_t sGroups[];
+#else
     static const mbedtls_ecp_group_id sCurves[];
+#endif
+
 #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
     static const int sHashes[];
 #endif
diff --git a/src/core/meshcop/energy_scan_client.cpp b/src/core/meshcop/energy_scan_client.cpp
index f0f8e10..09e8fbd 100644
--- a/src/core/meshcop/energy_scan_client.cpp
+++ b/src/core/meshcop/energy_scan_client.cpp
@@ -42,7 +42,7 @@
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "meshcop/meshcop.hpp"
 #include "meshcop/meshcop_tlvs.hpp"
 #include "thread/thread_netif.hpp"
@@ -50,6 +50,8 @@
 
 namespace ot {
 
+RegisterLogModule("EnergyScanClnt");
+
 EnergyScanClient::EnergyScanClient(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mCallback(nullptr)
@@ -69,11 +71,11 @@
 {
     Error                   error = kErrorNone;
     MeshCoP::ChannelMaskTlv channelMask;
-    Ip6::MessageInfo        messageInfo;
+    Tmf::MessageInfo        messageInfo(GetInstance());
     Coap::Message *         message = nullptr;
 
     VerifyOrExit(Get<MeshCoP::Commissioner>().IsActive(), error = kErrorInvalidState);
-    VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
+    VerifyOrExit((message = Get<Tmf::Agent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = message->InitAsPost(aAddress, UriPath::kEnergyScan));
     SuccessOrExit(error = message->SetPayloadMarker());
@@ -89,12 +91,10 @@
     SuccessOrExit(error = Tlv::Append<MeshCoP::PeriodTlv>(*message, aPeriod));
     SuccessOrExit(error = Tlv::Append<MeshCoP::ScanDurationTlv>(*message, aScanDuration));
 
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.SetPeerAddr(aAddress);
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
+    messageInfo.SetSockAddrToRlocPeerAddrTo(aAddress);
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
 
-    otLogInfoMeshCoP("sent energy scan query");
+    LogInfo("sent query");
 
     mCallback = aCallback;
     mContext  = aContext;
@@ -122,7 +122,7 @@
 
     VerifyOrExit(aMessage.IsConfirmablePostRequest());
 
-    otLogInfoMeshCoP("received energy scan report");
+    LogInfo("received report");
 
     VerifyOrExit((mask = MeshCoP::ChannelMaskTlv::GetChannelMask(aMessage)) != 0);
 
@@ -136,7 +136,7 @@
 
     SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMessage, aMessageInfo));
 
-    otLogInfoMeshCoP("sent energy scan report response");
+    LogInfo("sent report response");
 
 exit:
     return;
diff --git a/include/openthread/entropy.h b/src/core/meshcop/extended_panid.cpp
similarity index 62%
copy from include/openthread/entropy.h
copy to src/core/meshcop/extended_panid.cpp
index bc07c30..b90301a 100644
--- a/include/openthread/entropy.h
+++ b/src/core/meshcop/extended_panid.cpp
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2019, The OpenThread Authors.
+ *  Copyright (c) 2022, The OpenThread Authors.
  *  All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -28,43 +28,42 @@
 
 /**
  * @file
- * @brief
- *  This file defines the OpenThread entropy source API.
- */
-
-#ifndef OPENTHREAD_ENTROPY_H_
-#define OPENTHREAD_ENTROPY_H_
-
-#include <mbedtls/entropy.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @addtogroup api-entropy
- *
- * @brief
- *   This module includes functions that manages entropy source.
- *
- * @{
+ *   This file implements Extended PAN ID management.
  *
  */
 
-/**
- * This function returns initialized mbedtls_entropy_context.
- *
- * @returns  A pointer to initialized mbedtls_entropy_context.
- */
-mbedtls_entropy_context *otEntropyMbedTlsContextGet(void);
+#include "extended_panid.hpp"
 
-/**
- * @}
- *
- */
+#include "common/locator_getters.hpp"
+#include "common/notifier.hpp"
 
-#ifdef __cplusplus
-} // extern "C"
-#endif
+namespace ot {
+namespace MeshCoP {
 
-#endif // OPENTHREAD_ENTROPY_H_
+const otExtendedPanId ExtendedPanIdManager::sExtendedPanidInit = {
+    {0xde, 0xad, 0x00, 0xbe, 0xef, 0x00, 0xca, 0xfe},
+};
+
+ExtendedPanId::InfoString ExtendedPanId::ToString(void) const
+{
+    InfoString string;
+
+    string.AppendHexBytes(m8, sizeof(ExtendedPanId));
+
+    return string;
+}
+
+ExtendedPanIdManager::ExtendedPanIdManager(Instance &aInstance)
+    : InstanceLocator(aInstance)
+{
+    mExtendedPanId.Clear();
+    SetExtPanId(AsCoreType(&sExtendedPanidInit));
+}
+
+void ExtendedPanIdManager::SetExtPanId(const ExtendedPanId &aExtendedPanId)
+{
+    IgnoreError(Get<Notifier>().Update(mExtendedPanId, aExtendedPanId, kEventThreadExtPanIdChanged));
+}
+
+} // namespace MeshCoP
+} // namespace ot
diff --git a/src/core/meshcop/extended_panid.hpp b/src/core/meshcop/extended_panid.hpp
new file mode 100644
index 0000000..9bf5cf9
--- /dev/null
+++ b/src/core/meshcop/extended_panid.hpp
@@ -0,0 +1,117 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes definitions for managing the Extended PAN ID.
+ *
+ */
+
+#ifndef MESHCOP_EXTENDED_PANID_HPP_
+#define MESHCOP_EXTENDED_PANID_HPP_
+
+#include "openthread-core-config.h"
+
+#include <openthread/dataset.h>
+
+#include "common/as_core_type.hpp"
+#include "common/clearable.hpp"
+#include "common/equatable.hpp"
+#include "common/locator.hpp"
+#include "common/non_copyable.hpp"
+#include "common/string.hpp"
+
+namespace ot {
+namespace MeshCoP {
+
+/**
+ * This class represents an Extended PAN Identifier.
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class ExtendedPanId : public otExtendedPanId, public Equatable<ExtendedPanId>, public Clearable<ExtendedPanId>
+{
+public:
+    static constexpr uint16_t kInfoStringSize = 17; ///< Max chars for the info string (`ToString()`).
+
+    /**
+     * This type defines the fixed-length `String` object returned from `ToString()`.
+     *
+     */
+    typedef String<kInfoStringSize> InfoString;
+
+    /**
+     * This method converts an address to a string.
+     *
+     * @returns An `InfoString` containing the string representation of the Extended PAN Identifier.
+     *
+     */
+    InfoString ToString(void) const;
+
+} OT_TOOL_PACKED_END;
+
+class ExtendedPanIdManager : public InstanceLocator, private NonCopyable
+{
+public:
+    /**
+     * Constructor.
+     *
+     * @param[in]  aInstance  A reference to the OpenThread instance.
+     *
+     */
+    explicit ExtendedPanIdManager(Instance &aInstance);
+
+    /**
+     * This method returns the Extended PAN Identifier.
+     *
+     * @returns The Extended PAN Identifier.
+     *
+     */
+    const ExtendedPanId &GetExtPanId(void) const { return mExtendedPanId; }
+
+    /**
+     * This method sets the Extended PAN Identifier.
+     *
+     * @param[in]  aExtendedPanId  The Extended PAN Identifier.
+     *
+     */
+    void SetExtPanId(const ExtendedPanId &aExtendedPanId);
+
+private:
+    static const otExtendedPanId sExtendedPanidInit;
+
+    ExtendedPanId mExtendedPanId;
+};
+
+} // namespace MeshCoP
+
+DefineCoreType(otExtendedPanId, MeshCoP::ExtendedPanId);
+
+} // namespace ot
+
+#endif // MESHCOP_EXTENDED_PANID_HPP_
diff --git a/src/core/meshcop/joiner.cpp b/src/core/meshcop/joiner.cpp
index b90d2fc..4c48316 100644
--- a/src/core/meshcop/joiner.cpp
+++ b/src/core/meshcop/joiner.cpp
@@ -37,13 +37,14 @@
 
 #include <stdio.h>
 
+#include "common/array.hpp"
 #include "common/as_core_type.hpp"
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/string.hpp"
 #include "meshcop/meshcop.hpp"
 #include "radio/radio.hpp"
@@ -54,6 +55,8 @@
 namespace ot {
 namespace MeshCoP {
 
+RegisterLogModule("Joiner");
+
 Joiner::Joiner(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mId()
@@ -120,7 +123,7 @@
 
     SuccessOrExit(Get<Notifier>().Update(mState, aState, kEventJoinerStateChanged));
 
-    otLogInfoMeshCoP("JoinerState: %s -> %s", StateToString(oldState), StateToString(aState));
+    LogInfo("JoinerState: %s -> %s", StateToString(oldState), StateToString(aState));
 exit:
     return;
 }
@@ -139,7 +142,7 @@
     Mac::ExtAddress              randomAddress;
     SteeringData::HashBitIndexes filterIndexes;
 
-    otLogInfoMeshCoP("Joiner starting");
+    LogInfo("Joiner starting");
 
     VerifyOrExit(aProvisioningUrl == nullptr || IsValidUtf8String(aProvisioningUrl), error = kErrorInvalidArgs);
     VerifyOrExit(aVendorName == nullptr || IsValidUtf8String(aVendorName), error = kErrorInvalidArgs);
@@ -196,7 +199,7 @@
 
 void Joiner::Stop(void)
 {
-    otLogInfoMeshCoP("Joiner stopped");
+    LogInfo("Joiner stopped");
 
     // Callback is set to `nullptr` to skip calling it from `Finish()`
     mCallback = nullptr;
@@ -302,14 +305,14 @@
 {
     uint8_t       priority;
     bool          doesAllowAny;
-    JoinerRouter *end = OT_ARRAY_END(mJoinerRouters);
+    JoinerRouter *end = GetArrayEnd(mJoinerRouters);
     JoinerRouter *entry;
 
     doesAllowAny = AsCoreType(&aResult.mSteeringData).PermitsAllJoiners();
 
-    otLogInfoMeshCoP("Joiner discover network: %s, pan:0x%04x, port:%d, chan:%d, rssi:%d, allow-any:%s",
-                     AsCoreType(&aResult.mExtAddress).ToString().AsCString(), aResult.mPanId, aResult.mJoinerUdpPort,
-                     aResult.mChannel, aResult.mRssi, doesAllowAny ? "yes" : "no");
+    LogInfo("Joiner discover network: %s, pan:0x%04x, port:%d, chan:%d, rssi:%d, allow-any:%s",
+            AsCoreType(&aResult.mExtAddress).ToString().AsCString(), aResult.mPanId, aResult.mJoinerUdpPort,
+            aResult.mChannel, aResult.mRssi, ToYesNo(doesAllowAny));
 
     priority = CalculatePriority(aResult.mRssi, doesAllowAny);
 
@@ -342,7 +345,7 @@
 
 void Joiner::TryNextJoinerRouter(Error aPrevError)
 {
-    for (; mJoinerRouterIndex < OT_ARRAY_LENGTH(mJoinerRouters); mJoinerRouterIndex++)
+    for (; mJoinerRouterIndex < GetArrayLength(mJoinerRouters); mJoinerRouterIndex++)
     {
         JoinerRouter &router = mJoinerRouters[mJoinerRouterIndex];
         Error         error;
@@ -384,8 +387,8 @@
     Error         error = kErrorNotFound;
     Ip6::SockAddr sockAddr(aRouter.mJoinerUdpPort);
 
-    otLogInfoMeshCoP("Joiner connecting to %s, pan:0x%04x, chan:%d", aRouter.mExtAddr.ToString().AsCString(),
-                     aRouter.mPanId, aRouter.mChannel);
+    LogInfo("Joiner connecting to %s, pan:0x%04x, chan:%d", aRouter.mExtAddr.ToString().AsCString(), aRouter.mPanId,
+            aRouter.mChannel);
 
     Get<Mac::Mac>().SetPanId(aRouter.mPanId);
     SuccessOrExit(error = Get<Mac::Mac>().SetPanChannel(aRouter.mChannel));
@@ -439,11 +442,9 @@
     VendorStackVersionTlv vendorStackVersionTlv;
     ProvisioningUrlTlv    provisioningUrlTlv;
 
-    VerifyOrExit((mFinalizeMessage = NewMeshCoPMessage(Get<Coap::CoapSecure>())) != nullptr, error = kErrorNoBufs);
+    mFinalizeMessage = Get<Coap::CoapSecure>().NewPriorityConfirmablePostMessage(UriPath::kJoinerFinalize);
+    VerifyOrExit(mFinalizeMessage != nullptr, error = kErrorNoBufs);
 
-    mFinalizeMessage->InitAsConfirmablePost();
-    SuccessOrExit(error = mFinalizeMessage->AppendUriPathOptions(UriPath::kJoinerFinalize));
-    SuccessOrExit(error = mFinalizeMessage->SetPayloadMarker());
     mFinalizeMessage->SetOffset(mFinalizeMessage->GetLength());
 
     SuccessOrExit(error = Tlv::Append<StateTlv>(*mFinalizeMessage, StateTlv::kAccept));
@@ -514,7 +515,7 @@
     SuccessOrExit(Get<Coap::CoapSecure>().SendMessage(*mFinalizeMessage, Joiner::HandleJoinerFinalizeResponse, this));
     mFinalizeMessage = nullptr;
 
-    otLogInfoMeshCoP("Joiner sent finalize");
+    LogInfo("Joiner sent finalize");
 
 exit:
     return;
@@ -545,7 +546,7 @@
     SetState(kStateEntrust);
     mTimer.Start(kReponseTimeout);
 
-    otLogInfoMeshCoP("Joiner received finalize response %d", state);
+    LogInfo("Joiner received finalize response %d", state);
 
 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
     LogCertMessage("[THCI] direction=recv | type=JOIN_FIN.rsp |", *aMessage);
@@ -568,8 +569,8 @@
 
     VerifyOrExit(mState == kStateEntrust && aMessage.IsConfirmablePostRequest(), error = kErrorDrop);
 
-    otLogInfoMeshCoP("Joiner received entrust");
-    otLogCertMeshCoP("[THCI] direction=recv | type=JOIN_ENT.ntf");
+    LogInfo("Joiner received entrust");
+    LogCert("[THCI] direction=recv | type=JOIN_ENT.ntf");
 
     datasetInfo.Clear();
 
@@ -578,9 +579,9 @@
     datasetInfo.SetChannel(Get<Mac::Mac>().GetPanChannel());
     datasetInfo.SetPanId(Get<Mac::Mac>().GetPanId());
 
-    IgnoreError(Get<MeshCoP::ActiveDataset>().Save(datasetInfo));
+    IgnoreError(Get<ActiveDatasetManager>().Save(datasetInfo));
 
-    otLogInfoMeshCoP("Joiner successful!");
+    LogInfo("Joiner successful!");
 
     SendJoinerEntrustResponse(aMessage, aMessageInfo);
 
@@ -597,8 +598,9 @@
     Coap::Message *  message;
     Ip6::MessageInfo responseInfo(aRequestInfo);
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-    SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
+    message = Get<Tmf::Agent>().NewPriorityResponseMessage(aRequest);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
+
     message->SetSubType(Message::kSubTypeJoinerEntrust);
 
     responseInfo.GetSockAddr().Clear();
@@ -606,8 +608,8 @@
 
     SetState(kStateJoined);
 
-    otLogInfoMeshCoP("Joiner sent entrust response");
-    otLogCertMeshCoP("[THCI] direction=send | type=JOIN_ENT.rsp");
+    LogInfo("Joiner sent entrust response");
+    LogCert("[THCI] direction=send | type=JOIN_ENT.rsp");
 
 exit:
     FreeMessageOnError(message, error);
@@ -675,12 +677,14 @@
 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
 void Joiner::LogCertMessage(const char *aText, const Coap::Message &aMessage) const
 {
+    OT_UNUSED_VARIABLE(aText);
+
     uint8_t buf[OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE];
 
     VerifyOrExit(aMessage.GetLength() <= sizeof(buf));
     aMessage.ReadBytes(aMessage.GetOffset(), buf, aMessage.GetLength() - aMessage.GetOffset());
 
-    otDumpCertMeshCoP(aText, buf, aMessage.GetLength() - aMessage.GetOffset());
+    DumpCert(aText, buf, aMessage.GetLength() - aMessage.GetOffset());
 
 exit:
     return;
diff --git a/src/core/meshcop/joiner.hpp b/src/core/meshcop/joiner.hpp
index a3668a6..ac894e9 100644
--- a/src/core/meshcop/joiner.hpp
+++ b/src/core/meshcop/joiner.hpp
@@ -43,8 +43,9 @@
 #include "coap/coap.hpp"
 #include "coap/coap_message.hpp"
 #include "coap/coap_secure.hpp"
+#include "common/as_core_type.hpp"
 #include "common/locator.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/message.hpp"
 #include "common/non_copyable.hpp"
 #include "mac/mac_types.hpp"
@@ -86,11 +87,11 @@
      * This method starts the Joiner service.
      *
      * @param[in]  aPskd             A pointer to the PSKd.
-     * @param[in]  aProvisioningUrl  A pointer to the Provisioning URL (may be nullptr).
-     * @param[in]  aVendorName       A pointer to the Vendor Name (may be nullptr).
-     * @param[in]  aVendorModel      A pointer to the Vendor Model (may be nullptr).
-     * @param[in]  aVendorSwVersion  A pointer to the Vendor SW Version (may be nullptr).
-     * @param[in]  aVendorData       A pointer to the Vendor Data (may be nullptr).
+     * @param[in]  aProvisioningUrl  A pointer to the Provisioning URL (may be `nullptr`).
+     * @param[in]  aVendorName       A pointer to the Vendor Name (may be `nullptr`).
+     * @param[in]  aVendorModel      A pointer to the Vendor Model (may be `nullptr`).
+     * @param[in]  aVendorSwVersion  A pointer to the Vendor SW Version (may be `nullptr`).
+     * @param[in]  aVendorData       A pointer to the Vendor Data (may be `nullptr`).
      * @param[in]  aCallback         A pointer to a function that is called when the join operation completes.
      * @param[in]  aContext          A pointer to application-specific context.
      *
@@ -167,6 +168,16 @@
      */
     Error ClearDiscerner(void);
 
+    /**
+     * This method converts a given Joiner state to its human-readable string representation.
+     *
+     * @param[in] aState  The Joiner state to convert.
+     *
+     * @returns A human-readable string representation of @p aState.
+     *
+     */
+    static const char *StateToString(State aState);
+
 private:
     static constexpr uint16_t kJoinerUdpPort = OPENTHREAD_CONFIG_JOINER_UDP_PORT;
 
@@ -200,8 +211,6 @@
     static void HandleTimer(Timer &aTimer);
     void        HandleTimer(void);
 
-    static const char *StateToString(State aState);
-
     void    SetState(State aState);
     void    SetIdFromIeeeEui64(void);
     void    SaveDiscoveredJoinerRouter(const Mle::DiscoverScanner::ScanResult &aResult);
@@ -241,6 +250,9 @@
 };
 
 } // namespace MeshCoP
+
+DefineMapEnum(otJoinerState, MeshCoP::Joiner::State);
+
 } // namespace ot
 
 #endif // OPENTHREAD_CONFIG_JOINER_ENABLE
diff --git a/src/core/meshcop/joiner_router.cpp b/src/core/meshcop/joiner_router.cpp
index ebe1c78..679ae81 100644
--- a/src/core/meshcop/joiner_router.cpp
+++ b/src/core/meshcop/joiner_router.cpp
@@ -42,7 +42,7 @@
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "meshcop/meshcop.hpp"
 #include "meshcop/meshcop_tlvs.hpp"
 #include "thread/mle.hpp"
@@ -52,6 +52,8 @@
 namespace ot {
 namespace MeshCoP {
 
+RegisterLogModule("JoinerRouter");
+
 JoinerRouter::JoinerRouter(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mSocket(aInstance)
@@ -84,7 +86,7 @@
         IgnoreError(mSocket.Open(&JoinerRouter::HandleUdpReceive, this));
         IgnoreError(mSocket.Bind(port));
         IgnoreError(Get<Ip6::Filter>().AddUnsecurePort(port));
-        otLogInfoMeshCoP("Joiner Router: start");
+        LogInfo("Joiner Router: start");
     }
     else
     {
@@ -106,8 +108,7 @@
 
     VerifyOrExit(!mIsJoinerPortConfigured, rval = mJoinerUdpPort);
 
-    joinerUdpPort = static_cast<const JoinerUdpPortTlv *>(
-        Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kJoinerUdpPort));
+    joinerUdpPort = As<JoinerUdpPortTlv>(Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kJoinerUdpPort));
     VerifyOrExit(joinerUdpPort != nullptr);
 
     rval = joinerUdpPort->GetUdpPort();
@@ -132,19 +133,17 @@
 {
     Error            error;
     Coap::Message *  message = nullptr;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
     ExtendedTlv      tlv;
     uint16_t         borderAgentRloc;
     uint16_t         offset;
 
-    otLogInfoMeshCoP("JoinerRouter::HandleUdpReceive");
+    LogInfo("JoinerRouter::HandleUdpReceive");
 
     SuccessOrExit(error = GetBorderAgentRloc(Get<ThreadNetif>(), borderAgentRloc));
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->InitAsNonConfirmablePost(UriPath::kRelayRx));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityNonConfirmablePostMessage(UriPath::kRelayRx);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = Tlv::Append<JoinerUdpPortTlv>(*message, aMessageInfo.GetPeerPort()));
     SuccessOrExit(error = Tlv::Append<JoinerIidTlv>(*message, aMessageInfo.GetPeerAddr().GetIid()));
@@ -157,14 +156,11 @@
     SuccessOrExit(error = message->SetLength(offset + tlv.GetLength()));
     aMessage.CopyTo(aMessage.GetOffset(), offset, tlv.GetLength(), *message);
 
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.SetPeerAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.GetPeerAddr().GetIid().SetLocator(borderAgentRloc);
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
+    messageInfo.SetSockAddrToRlocPeerAddrTo(borderAgentRloc);
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
 
-    otLogInfoMeshCoP("Sent relay rx");
+    LogInfo("Sent relay rx");
 
 exit:
     FreeMessageOnError(message, error);
@@ -191,7 +187,7 @@
 
     VerifyOrExit(aMessage.IsNonConfirmablePostRequest(), error = kErrorDrop);
 
-    otLogInfoMeshCoP("Received relay transmit");
+    LogInfo("Received relay transmit");
 
     SuccessOrExit(error = Tlv::Find<JoinerUdpPortTlv>(aMessage, joinerPort));
     SuccessOrExit(error = Tlv::Find<JoinerIidTlv>(aMessage, joinerIid));
@@ -210,7 +206,7 @@
 
     if (Tlv::Find<JoinerRouterKekTlv>(aMessage, kek) == kErrorNone)
     {
-        otLogInfoMeshCoP("Received kek");
+        LogInfo("Received kek");
 
         DelaySendingJoinerEntrust(messageInfo, kek);
     }
@@ -222,7 +218,7 @@
 void JoinerRouter::DelaySendingJoinerEntrust(const Ip6::MessageInfo &aMessageInfo, const Kek &aKek)
 {
     Error                 error   = kErrorNone;
-    Message *             message = Get<MessagePool>().New(Message::kTypeOther, 0);
+    Message *             message = Get<MessagePool>().Allocate(Message::kTypeOther);
     JoinerEntrustMetadata metadata;
 
     VerifyOrExit(message != nullptr, error = kErrorNoBufs);
@@ -296,12 +292,12 @@
 
     IgnoreError(Get<Tmf::Agent>().AbortTransaction(&JoinerRouter::HandleJoinerEntrustResponse, this));
 
-    otLogInfoMeshCoP("Sending JOIN_ENT.ntf");
+    LogInfo("Sending JOIN_ENT.ntf");
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, aMessageInfo,
                                                         &JoinerRouter::HandleJoinerEntrustResponse, this));
 
-    otLogInfoMeshCoP("Sent joiner entrust length = %d", message->GetLength());
-    otLogCertMeshCoP("[THCI] direction=send | type=JOIN_ENT.ntf");
+    LogInfo("Sent joiner entrust length = %d", message->GetLength());
+    LogCert("[THCI] direction=send | type=JOIN_ENT.ntf");
 
 exit:
     FreeMessageOnError(message, error);
@@ -317,23 +313,21 @@
     const Tlv *    tlv;
     NetworkKey     networkKey;
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(UriPath::kJoinerEntrust);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
-    message->InitAsConfirmablePost();
-    SuccessOrExit(error = message->AppendUriPathOptions(UriPath::kJoinerEntrust));
-    SuccessOrExit(error = message->SetPayloadMarker());
     message->SetSubType(Message::kSubTypeJoinerEntrust);
 
     Get<KeyManager>().GetNetworkKey(networkKey);
     SuccessOrExit(error = Tlv::Append<NetworkKeyTlv>(*message, networkKey));
     SuccessOrExit(error = Tlv::Append<MeshLocalPrefixTlv>(*message, Get<Mle::MleRouter>().GetMeshLocalPrefix()));
-    SuccessOrExit(error = Tlv::Append<ExtendedPanIdTlv>(*message, Get<Mac::Mac>().GetExtendedPanId()));
+    SuccessOrExit(error = Tlv::Append<ExtendedPanIdTlv>(*message, Get<ExtendedPanIdManager>().GetExtPanId()));
 
     networkName.Init();
-    networkName.SetNetworkName(Get<Mac::Mac>().GetNetworkName().GetAsData());
+    networkName.SetNetworkName(Get<NetworkNameManager>().GetNetworkName().GetAsData());
     SuccessOrExit(error = networkName.AppendTo(*message));
 
-    IgnoreError(Get<ActiveDataset>().Read(dataset));
+    IgnoreError(Get<ActiveDatasetManager>().Read(dataset));
 
     if ((tlv = dataset.GetTlv<ActiveTimestampTlv>()) != nullptr)
     {
@@ -407,8 +401,8 @@
 
     VerifyOrExit(aMessage->GetCode() == Coap::kCodeChanged);
 
-    otLogInfoMeshCoP("Receive joiner entrust response");
-    otLogCertMeshCoP("[THCI] direction=recv | type=JOIN_ENT.rsp");
+    LogInfo("Receive joiner entrust response");
+    LogCert("[THCI] direction=recv | type=JOIN_ENT.rsp");
 
 exit:
     return;
diff --git a/src/core/meshcop/joiner_router.hpp b/src/core/meshcop/joiner_router.hpp
index 206972b..e8c6116 100644
--- a/src/core/meshcop/joiner_router.hpp
+++ b/src/core/meshcop/joiner_router.hpp
@@ -78,7 +78,7 @@
     /**
      * This method sets the Joiner UDP Port.
      *
-     * @param[in]  The Joiner UDP Port number.
+     * @param[in]  aJoinerUdpPort  The Joiner UDP Port number.
      *
      */
     void SetJoinerUdpPort(uint16_t aJoinerUdpPort);
diff --git a/src/core/meshcop/meshcop.cpp b/src/core/meshcop/meshcop.cpp
index ac206e8..a61b0ae 100644
--- a/src/core/meshcop/meshcop.cpp
+++ b/src/core/meshcop/meshcop.cpp
@@ -36,7 +36,6 @@
 #include "common/crc16.hpp"
 #include "common/debug.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
 #include "common/string.hpp"
 #include "crypto/pbkdf2_cmac.hpp"
 #include "crypto/sha256.hpp"
@@ -44,6 +43,9 @@
 #include "thread/thread_netif.hpp"
 
 namespace ot {
+
+RegisterLogModule("MeshCoP");
+
 namespace MeshCoP {
 
 Error JoinerPskd::SetFrom(const char *aPskdString)
@@ -303,7 +305,7 @@
     Error                        error = kErrorNone;
     const BorderAgentLocatorTlv *borderAgentLocator;
 
-    borderAgentLocator = static_cast<const BorderAgentLocatorTlv *>(
+    borderAgentLocator = As<BorderAgentLocatorTlv>(
         aNetif.Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kBorderAgentLocator));
     VerifyOrExit(borderAgentLocator != nullptr, error = kErrorNotFound);
 
@@ -314,10 +316,10 @@
 }
 
 #if OPENTHREAD_FTD
-Error GeneratePskc(const char *              aPassPhrase,
-                   const Mac::NetworkName &  aNetworkName,
-                   const Mac::ExtendedPanId &aExtPanId,
-                   Pskc &                    aPskc)
+Error GeneratePskc(const char *         aPassPhrase,
+                   const NetworkName &  aNetworkName,
+                   const ExtendedPanId &aExtPanId,
+                   Pskc &               aPskc)
 {
     Error      error        = kErrorNone;
     const char saltPrefix[] = "Thread";
@@ -354,12 +356,12 @@
 }
 #endif // OPENTHREAD_FTD
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN) && (OPENTHREAD_CONFIG_LOG_MESHCOP == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
 void LogError(const char *aActionText, Error aError)
 {
-    if (aError != kErrorNone)
+    if (aError != kErrorNone && aError != kErrorAlready)
     {
-        otLogWarnMeshCoP("Failed to %s: %s", aActionText, ErrorToString(aError));
+        LogWarn("Failed to %s: %s", aActionText, ErrorToString(aError));
     }
 }
 #endif
diff --git a/src/core/meshcop/meshcop.hpp b/src/core/meshcop/meshcop.hpp
index 41477f2..0de1047 100644
--- a/src/core/meshcop/meshcop.hpp
+++ b/src/core/meshcop/meshcop.hpp
@@ -44,8 +44,10 @@
 #include <openthread/joiner.h>
 
 #include "coap/coap.hpp"
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/equatable.hpp"
+#include "common/log.hpp"
 #include "common/message.hpp"
 #include "common/string.hpp"
 #include "mac/mac_types.hpp"
@@ -203,7 +205,7 @@
     /**
      * This method indicates whether a given Joiner ID matches the Discerner.
      *
-     * @param[in] aJoiner  A Joiner ID to match with the Discerner.
+     * @param[in] aJoinerId  A Joiner ID to match with the Discerner.
      *
      * @returns TRUE if the Joiner ID matches the Discerner, FALSE otherwise.
      *
@@ -405,15 +407,6 @@
 };
 
 /**
- * This function creates Message for MeshCoP.
- *
- */
-inline Coap::Message *NewMeshCoPMessage(Coap::CoapBase &aCoap)
-{
-    return aCoap.NewMessage(Message::Settings(Message::kWithLinkSecurity, Message::kPriorityNet));
-}
-
-/**
  * This function generates PSKc.
  *
  * PSKc is used to establish the Commissioner Session.
@@ -427,10 +420,10 @@
  * @retval kErrorInvalidArgs   If the length of passphrase is out of range.
  *
  */
-Error GeneratePskc(const char *              aPassPhrase,
-                   const Mac::NetworkName &  aNetworkName,
-                   const Mac::ExtendedPanId &aExtPanId,
-                   Pskc &                    aPskc);
+Error GeneratePskc(const char *         aPassPhrase,
+                   const NetworkName &  aNetworkName,
+                   const ExtendedPanId &aExtPanId,
+                   Pskc &               aPskc);
 
 /**
  * This function computes the Joiner ID from a factory-assigned IEEE EUI-64.
@@ -444,7 +437,7 @@
 /**
  * This function gets the border agent RLOC.
  *
- * @param[in]   aNetif  A reference to the thread interface.
+ * @param[in]   aNetIf  A reference to the thread interface.
  * @param[out]  aRloc   Border agent RLOC.
  *
  * @retval kErrorNone       Successfully got the Border Agent Rloc.
@@ -453,7 +446,7 @@
  */
 Error GetBorderAgentRloc(ThreadNetif &aNetIf, uint16_t &aRloc);
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN) && (OPENTHREAD_CONFIG_LOG_MESHCOP == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
 /**
  * This function emits a log message indicating an error during a MeshCoP action.
  *
@@ -473,6 +466,10 @@
 
 } // namespace MeshCoP
 
+DefineCoreType(otJoinerPskd, MeshCoP::JoinerPskd);
+DefineCoreType(otJoinerDiscerner, MeshCoP::JoinerDiscerner);
+DefineCoreType(otSteeringData, MeshCoP::SteeringData);
+
 } // namespace ot
 
 #endif // MESHCOP_HPP_
diff --git a/src/core/meshcop/meshcop_leader.cpp b/src/core/meshcop/meshcop_leader.cpp
index ecf5de4..a072026 100644
--- a/src/core/meshcop/meshcop_leader.cpp
+++ b/src/core/meshcop/meshcop_leader.cpp
@@ -42,7 +42,7 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/random.hpp"
 #include "meshcop/meshcop.hpp"
 #include "meshcop/meshcop_tlvs.hpp"
@@ -53,6 +53,8 @@
 namespace ot {
 namespace MeshCoP {
 
+RegisterLogModule("MeshCoPLeader");
+
 Leader::Leader(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mPetition(UriPath::kLeaderPetition, Leader::HandlePetition, this)
@@ -78,7 +80,7 @@
     CommissionerIdTlv commissionerId;
     StateTlv::State   state = StateTlv::kReject;
 
-    otLogInfoMeshCoP("received petition");
+    LogInfo("received petition");
 
     VerifyOrExit(Get<Mle::MleRouter>().IsRoutingLocator(aMessageInfo.GetPeerAddr()));
     SuccessOrExit(Tlv::FindTlv(aMessage, commissionerId));
@@ -126,10 +128,8 @@
     Error          error = kErrorNone;
     Coap::Message *message;
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityResponseMessage(aRequest);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = Tlv::Append<StateTlv>(*message, aState));
 
@@ -145,7 +145,7 @@
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, aMessageInfo));
 
-    otLogInfoMeshCoP("sent petition response");
+    LogInfo("sent petition response");
 
 exit:
     FreeMessageOnError(message, error);
@@ -164,14 +164,14 @@
     BorderAgentLocatorTlv *borderAgentLocator;
     StateTlv::State        responseState;
 
-    otLogInfoMeshCoP("received keep alive");
+    LogInfo("received keep alive");
 
     SuccessOrExit(Tlv::Find<StateTlv>(aMessage, state));
 
     SuccessOrExit(Tlv::Find<CommissionerSessionIdTlv>(aMessage, sessionId));
 
-    borderAgentLocator = static_cast<BorderAgentLocatorTlv *>(
-        Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kBorderAgentLocator));
+    borderAgentLocator =
+        As<BorderAgentLocatorTlv>(Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kBorderAgentLocator));
 
     if ((borderAgentLocator == nullptr) || (sessionId != mSessionId))
     {
@@ -209,16 +209,14 @@
     Error          error = kErrorNone;
     Coap::Message *message;
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityResponseMessage(aRequest);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = Tlv::Append<StateTlv>(*message, aState));
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, aMessageInfo));
 
-    otLogInfoMeshCoP("sent keep alive response");
+    LogInfo("sent keep alive response");
 
 exit:
     FreeMessageOnError(message, error);
@@ -228,19 +226,16 @@
 void Leader::SendDatasetChanged(const Ip6::Address &aAddress)
 {
     Error            error = kErrorNone;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
     Coap::Message *  message;
 
-    VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(UriPath::kDatasetChanged);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
-    SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kDatasetChanged));
-
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.SetPeerAddr(aAddress);
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
+    messageInfo.SetSockAddrToRlocPeerAddrTo(aAddress);
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
 
-    otLogInfoMeshCoP("sent dataset changed");
+    LogInfo("sent dataset changed");
 
 exit:
     FreeMessageOnError(message, error);
@@ -294,7 +289,7 @@
     mTimer.Stop();
     SetEmptyCommissionerData();
 
-    otLogInfoMeshCoP("commissioner inactive");
+    LogInfo("commissioner inactive");
 }
 
 } // namespace MeshCoP
diff --git a/src/core/meshcop/meshcop_tlvs.cpp b/src/core/meshcop/meshcop_tlvs.cpp
index f2c72b2..c047ed9 100644
--- a/src/core/meshcop/meshcop_tlvs.cpp
+++ b/src/core/meshcop/meshcop_tlvs.cpp
@@ -48,39 +48,39 @@
     switch (aTlv.GetType())
     {
     case Tlv::kChannel:
-        rval = static_cast<const ChannelTlv &>(aTlv).IsValid();
+        rval = As<ChannelTlv>(aTlv).IsValid();
         break;
 
     case Tlv::kPanId:
-        rval = static_cast<const PanIdTlv &>(aTlv).IsValid();
+        rval = As<PanIdTlv>(aTlv).IsValid();
         break;
 
     case Tlv::kExtendedPanId:
-        rval = static_cast<const ExtendedPanIdTlv &>(aTlv).IsValid();
+        rval = As<ExtendedPanIdTlv>(aTlv).IsValid();
         break;
 
     case Tlv::kNetworkName:
-        rval = static_cast<const NetworkNameTlv &>(aTlv).IsValid();
+        rval = As<NetworkNameTlv>(aTlv).IsValid();
         break;
 
     case Tlv::kNetworkKey:
-        rval = static_cast<const NetworkKeyTlv &>(aTlv).IsValid();
+        rval = As<NetworkKeyTlv>(aTlv).IsValid();
         break;
 
     case Tlv::kPskc:
-        rval = static_cast<const PskcTlv &>(aTlv).IsValid();
+        rval = As<PskcTlv>(aTlv).IsValid();
         break;
 
     case Tlv::kMeshLocalPrefix:
-        rval = static_cast<const MeshLocalPrefixTlv &>(aTlv).IsValid();
+        rval = As<MeshLocalPrefixTlv>(aTlv).IsValid();
         break;
 
     case Tlv::kSecurityPolicy:
-        rval = static_cast<const SecurityPolicyTlv &>(aTlv).IsValid();
+        rval = As<SecurityPolicyTlv>(aTlv).IsValid();
         break;
 
     case Tlv::kChannelMask:
-        rval = static_cast<const ChannelMaskTlv &>(aTlv).IsValid();
+        rval = As<ChannelMaskTlv>(aTlv).IsValid();
         break;
 
     default:
@@ -115,7 +115,7 @@
     return tlv;
 }
 
-Mac::NameData NetworkNameTlv::GetNetworkName(void) const
+NameData NetworkNameTlv::GetNetworkName(void) const
 {
     uint8_t len = GetLength();
 
@@ -124,10 +124,10 @@
         len = sizeof(mNetworkName);
     }
 
-    return Mac::NameData(mNetworkName, len);
+    return NameData(mNetworkName, len);
 }
 
-void NetworkNameTlv::SetNetworkName(const Mac::NameData &aNameData)
+void NetworkNameTlv::SetNetworkName(const NameData &aNameData)
 {
     uint8_t len;
 
@@ -148,8 +148,7 @@
 
 bool SecurityPolicyTlv::IsValid(void) const
 {
-    return GetLength() >= sizeof(mRotationTime) && GetRotationTime() >= SecurityPolicy::kMinKeyRotationTime &&
-           GetFlagsLength() >= kThread11FlagsLength;
+    return GetLength() >= sizeof(mRotationTime) && GetFlagsLength() >= kThread11FlagsLength;
 }
 
 SecurityPolicy SecurityPolicyTlv::GetSecurityPolicy(void) const
@@ -281,9 +280,9 @@
         entry->SetChannelPage(OT_RADIO_CHANNEL_PAGE_2);
         entry->SetMask(aChannelMask & OT_RADIO_915MHZ_OQPSK_CHANNEL_MASK);
 
-        length += sizeof(MeshCoP::ChannelMaskEntry);
+        length += sizeof(ChannelMaskEntry);
 
-        entry = static_cast<MeshCoP::ChannelMaskEntry *>(entry->GetNext());
+        entry = static_cast<ChannelMaskEntry *>(entry->GetNext());
     }
 #endif
 
@@ -295,7 +294,7 @@
         entry->SetChannelPage(OT_RADIO_CHANNEL_PAGE_0);
         entry->SetMask(aChannelMask & OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MASK);
 
-        length += sizeof(MeshCoP::ChannelMaskEntry);
+        length += sizeof(ChannelMaskEntry);
     }
 #endif
 
@@ -307,7 +306,7 @@
         entry->SetChannelPage(OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_PAGE);
         entry->SetMask(aChannelMask & OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_CHANNEL_MASK);
 
-        length += sizeof(MeshCoP::ChannelMaskEntry);
+        length += sizeof(ChannelMaskEntry);
     }
 #endif
 
diff --git a/src/core/meshcop/meshcop_tlvs.hpp b/src/core/meshcop/meshcop_tlvs.hpp
index e3048ea..c21e799 100644
--- a/src/core/meshcop/meshcop_tlvs.hpp
+++ b/src/core/meshcop/meshcop_tlvs.hpp
@@ -47,6 +47,8 @@
 #include "common/string.hpp"
 #include "common/tlvs.hpp"
 #include "mac/mac_types.hpp"
+#include "meshcop/extended_panid.hpp"
+#include "meshcop/network_name.hpp"
 #include "meshcop/timestamp.hpp"
 #include "net/ip6_address.hpp"
 #include "radio/radio.hpp"
@@ -139,7 +141,7 @@
      * @returns A pointer to the next TLV.
      *
      */
-    Tlv *GetNext(void) { return static_cast<Tlv *>(ot::Tlv::GetNext()); }
+    Tlv *GetNext(void) { return As<Tlv>(ot::Tlv::GetNext()); }
 
     /**
      * This method returns a pointer to the next TLV.
@@ -147,7 +149,7 @@
      * @returns A pointer to the next TLV.
      *
      */
-    const Tlv *GetNext(void) const { return static_cast<const Tlv *>(ot::Tlv::GetNext()); }
+    const Tlv *GetNext(void) const { return As<Tlv>(ot::Tlv::GetNext()); }
 
     /**
      * This static method reads the requested TLV out of @p aMessage.
@@ -203,7 +205,7 @@
      * @param[in]  aTlvsLength The length (number of bytes) in TLV sequence.
      * @param[in]  aType       The TLV Type to search for.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     static Tlv *FindTlv(uint8_t *aTlvsStart, uint16_t aTlvsLength, Type aType)
@@ -218,7 +220,7 @@
      * @param[in]  aTlvsLength The length (number of bytes) in TLV sequence.
      * @param[in]  aType       The TLV Type to search for.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     static const Tlv *FindTlv(const uint8_t *aTlvsStart, uint16_t aTlvsLength, Type aType);
@@ -230,12 +232,12 @@
      * @param[in]  aTlvsStart  A pointer to the start of the sequence of TLVs to search within.
      * @param[in]  aTlvsLength The length (number of bytes) in TLV sequence.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     template <typename TlvType> static TlvType *FindTlv(uint8_t *aTlvsStart, uint16_t aTlvsLength)
     {
-        return static_cast<TlvType *>(FindTlv(aTlvsStart, aTlvsLength, static_cast<Tlv::Type>(TlvType::kType)));
+        return As<TlvType>(FindTlv(aTlvsStart, aTlvsLength, static_cast<Tlv::Type>(TlvType::kType)));
     }
 
     /**
@@ -245,12 +247,12 @@
      * @param[in]  aTlvsStart  A pointer to the start of the sequence of TLVs to search within.
      * @param[in]  aTlvsLength The length (number of bytes) in TLV sequence.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     template <typename TlvType> static const TlvType *FindTlv(const uint8_t *aTlvsStart, uint16_t aTlvsLength)
     {
-        return static_cast<const TlvType *>(FindTlv(aTlvsStart, aTlvsLength, static_cast<Tlv::Type>(TlvType::kType)));
+        return As<TlvType>(FindTlv(aTlvsStart, aTlvsLength, static_cast<Tlv::Type>(TlvType::kType)));
     }
 
 } OT_TOOL_PACKED_END;
@@ -445,7 +447,7 @@
  *
  */
 OT_TOOL_PACKED_BEGIN
-class ExtendedPanIdTlv : public Tlv, public SimpleTlvInfo<Tlv::kExtendedPanId, Mac::ExtendedPanId>
+class ExtendedPanIdTlv : public Tlv, public SimpleTlvInfo<Tlv::kExtendedPanId, ExtendedPanId>
 {
 public:
     /**
@@ -473,7 +475,7 @@
      * @returns The Extended PAN ID value.
      *
      */
-    const Mac::ExtendedPanId &GetExtendedPanId(void) const { return mExtendedPanId; }
+    const ExtendedPanId &GetExtendedPanId(void) const { return mExtendedPanId; }
 
     /**
      * This method sets the Extended PAN ID value.
@@ -481,10 +483,10 @@
      * @param[in]  aExtendedPanId  An Extended PAN ID value.
      *
      */
-    void SetExtendedPanId(const Mac::ExtendedPanId &aExtendedPanId) { mExtendedPanId = aExtendedPanId; }
+    void SetExtendedPanId(const ExtendedPanId &aExtendedPanId) { mExtendedPanId = aExtendedPanId; }
 
 private:
-    Mac::ExtendedPanId mExtendedPanId;
+    ExtendedPanId mExtendedPanId;
 } OT_TOOL_PACKED_END;
 
 /**
@@ -520,7 +522,7 @@
      * @returns The Network Name value (as `NameData`).
      *
      */
-    Mac::NameData GetNetworkName(void) const;
+    NameData GetNetworkName(void) const;
 
     /**
      * This method sets the Network Name value.
@@ -528,10 +530,10 @@
      * @param[in] aNameData   A Network Name value (as `NameData`).
      *
      */
-    void SetNetworkName(const Mac::NameData &aNameData);
+    void SetNetworkName(const NameData &aNameData);
 
 private:
-    char mNetworkName[Mac::NetworkName::kMaxSize];
+    char mNetworkName[NetworkName::kMaxSize];
 } OT_TOOL_PACKED_END;
 
 /**
@@ -680,7 +682,7 @@
  *
  */
 OT_TOOL_PACKED_BEGIN
-class MeshLocalPrefixTlv : public Tlv, public SimpleTlvInfo<Tlv::kMeshLocalPrefix, Mle::MeshLocalPrefix>
+class MeshLocalPrefixTlv : public Tlv, public SimpleTlvInfo<Tlv::kMeshLocalPrefix, Ip6::NetworkPrefix>
 {
 public:
     /**
@@ -716,7 +718,7 @@
      * @returns The Mesh Local Prefix value.
      *
      */
-    const Mle::MeshLocalPrefix &GetMeshLocalPrefix(void) const { return mMeshLocalPrefix; }
+    const Ip6::NetworkPrefix &GetMeshLocalPrefix(void) const { return mMeshLocalPrefix; }
 
     /**
      * This method sets the Mesh Local Prefix value.
@@ -724,10 +726,10 @@
      * @param[in]  aMeshLocalPrefix  A pointer to the Mesh Local Prefix value.
      *
      */
-    void SetMeshLocalPrefix(const Mle::MeshLocalPrefix &aMeshLocalPrefix) { mMeshLocalPrefix = aMeshLocalPrefix; }
+    void SetMeshLocalPrefix(const Ip6::NetworkPrefix &aMeshLocalPrefix) { mMeshLocalPrefix = aMeshLocalPrefix; }
 
 private:
-    Mle::MeshLocalPrefix mMeshLocalPrefix;
+    Ip6::NetworkPrefix mMeshLocalPrefix;
 } OT_TOOL_PACKED_END;
 
 class SteeringData;
@@ -827,7 +829,7 @@
     /**
      * This method sets the Border Agent Locator value.
      *
-     * @param[in]  aBorderAgentLocator  The Border Agent Locator value.
+     * @param[in]  aLocator  The Border Agent Locator value.
      *
      */
     void SetBorderAgentLocator(uint16_t aLocator) { mLocator = HostSwap16(aLocator); }
@@ -930,7 +932,7 @@
     /**
      * This method sets the Commissioner Session ID value.
      *
-     * @param[in]  aCommissionerSessionId  The Commissioner Session ID value.
+     * @param[in]  aSessionId  The Commissioner Session ID value.
      *
      */
     void SetCommissionerSessionId(uint16_t aSessionId) { mSessionId = HostSwap16(aSessionId); }
@@ -1464,7 +1466,7 @@
     /**
      * This method gets the first Channel Mask Entry in the Channel Mask TLV.
      *
-     * @returns A pointer to first Channel Mask Entry or nullptr if not found.
+     * @returns A pointer to first Channel Mask Entry or `nullptr` if not found.
      *
      */
     const ChannelMaskEntryBase *GetFirstEntry(void) const;
@@ -1472,7 +1474,7 @@
     /**
      * This method gets the first Channel Mask Entry in the Channel Mask TLV.
      *
-     * @returns A pointer to first Channel Mask Entry or nullptr if not found.
+     * @returns A pointer to first Channel Mask Entry or `nullptr` if not found.
      *
      */
     ChannelMaskEntryBase *GetFirstEntry(void);
@@ -1500,7 +1502,7 @@
     /**
      * This method sets the Channel Mask Entries.
      *
-     * @param[in]  aMask  The Channel Mask value.
+     * @param[in]  aChannelMask  The Channel Mask value.
      *
      */
     void SetChannelMask(uint32_t aChannelMask);
diff --git a/src/core/meshcop/network_name.cpp b/src/core/meshcop/network_name.cpp
new file mode 100644
index 0000000..e4ae562
--- /dev/null
+++ b/src/core/meshcop/network_name.cpp
@@ -0,0 +1,171 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file implements Network Name management.
+ *
+ */
+
+#include "network_name.hpp"
+
+#include "common/locator_getters.hpp"
+#include "common/notifier.hpp"
+
+namespace ot {
+namespace MeshCoP {
+
+const char NetworkNameManager::sNetworkNameInit[] = "OpenThread";
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+const char NetworkNameManager::sDomainNameInit[] = "DefaultDomain";
+#endif
+
+uint8_t NameData::CopyTo(char *aBuffer, uint8_t aMaxSize) const
+{
+    MutableData<kWithUint8Length> destData;
+
+    destData.Init(aBuffer, aMaxSize);
+    destData.ClearBytes();
+    IgnoreError(destData.CopyBytesFrom(*this));
+
+    return destData.GetLength();
+}
+
+NameData NetworkName::GetAsData(void) const
+{
+    return NameData(m8, static_cast<uint8_t>(StringLength(m8, kMaxSize + 1)));
+}
+
+Error NetworkName::Set(const char *aNameString)
+{
+    // When setting `NetworkName` from a string, we treat it as `NameData`
+    // with `kMaxSize + 1` chars. `NetworkName::Set(data)` will look
+    // for null char in the data (within its given size) to calculate
+    // the name's length and ensure that the name fits in `kMaxSize`
+    // chars. The `+ 1` ensures that a `aNameString` with length
+    // longer than `kMaxSize` is correctly rejected (returning error
+    // `kErrorInvalidArgs`).
+
+    Error    error;
+    NameData data(aNameString, kMaxSize + 1);
+
+    VerifyOrExit(IsValidUtf8String(aNameString), error = kErrorInvalidArgs);
+
+    error = Set(data);
+
+exit:
+    return error;
+}
+
+Error NetworkName::Set(const NameData &aNameData)
+{
+    Error    error  = kErrorNone;
+    NameData data   = aNameData;
+    uint8_t  newLen = static_cast<uint8_t>(StringLength(data.GetBuffer(), data.GetLength()));
+
+    VerifyOrExit((0 < newLen) && (newLen <= kMaxSize), error = kErrorInvalidArgs);
+
+    data.SetLength(newLen);
+
+    // Ensure the new name does not match the current one.
+    if (data.MatchesBytesIn(m8) && m8[newLen] == '\0')
+    {
+        ExitNow(error = kErrorAlready);
+    }
+
+    data.CopyBytesTo(m8);
+    m8[newLen] = '\0';
+
+exit:
+    return error;
+}
+
+bool NetworkName::operator==(const NetworkName &aOther) const
+{
+    return GetAsData() == aOther.GetAsData();
+}
+
+NetworkNameManager::NetworkNameManager(Instance &aInstance)
+    : InstanceLocator(aInstance)
+{
+    IgnoreError(SetNetworkName(sNetworkNameInit));
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+    IgnoreError(SetDomainName(sDomainNameInit));
+#endif
+}
+
+Error NetworkNameManager::SetNetworkName(const char *aNameString)
+{
+    return SignalNetworkNameChange(mNetworkName.Set(aNameString));
+}
+
+Error NetworkNameManager::SetNetworkName(const NameData &aNameData)
+{
+    return SignalNetworkNameChange(mNetworkName.Set(aNameData));
+}
+
+Error NetworkNameManager::SignalNetworkNameChange(Error aError)
+{
+    switch (aError)
+    {
+    case kErrorNone:
+        Get<Notifier>().Signal(kEventThreadNetworkNameChanged);
+        break;
+
+    case kErrorAlready:
+        Get<Notifier>().SignalIfFirst(kEventThreadNetworkNameChanged);
+        aError = kErrorNone;
+        break;
+
+    default:
+        break;
+    }
+
+    return aError;
+}
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+Error NetworkNameManager::SetDomainName(const char *aNameString)
+{
+    Error error = mDomainName.Set(aNameString);
+
+    return (error == kErrorAlready) ? kErrorNone : error;
+}
+
+Error NetworkNameManager::SetDomainName(const NameData &aNameData)
+{
+    Error error = mDomainName.Set(aNameData);
+
+    return (error == kErrorAlready) ? kErrorNone : error;
+}
+#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+
+} // namespace MeshCoP
+} // namespace ot
diff --git a/src/core/meshcop/network_name.hpp b/src/core/meshcop/network_name.hpp
new file mode 100644
index 0000000..1f6d847
--- /dev/null
+++ b/src/core/meshcop/network_name.hpp
@@ -0,0 +1,281 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes definitions for managing the Network Name.
+ *
+ */
+
+#ifndef MESHCOP_NETWORK_NAME_HPP_
+#define MESHCOP_NETWORK_NAME_HPP_
+
+#include "openthread-core-config.h"
+
+#include <openthread/dataset.h>
+
+#include "common/as_core_type.hpp"
+#include "common/data.hpp"
+#include "common/equatable.hpp"
+#include "common/locator.hpp"
+#include "common/non_copyable.hpp"
+#include "common/string.hpp"
+
+namespace ot {
+namespace MeshCoP {
+
+/**
+ * This class represents a name string as data (pointer to a char buffer along with a length).
+ *
+ * @note The char array does NOT need to be null terminated.
+ *
+ */
+class NameData : private Data<kWithUint8Length>
+{
+    friend class NetworkName;
+
+public:
+    /**
+     * This constructor initializes the NameData object.
+     *
+     * @param[in] aBuffer   A pointer to a `char` buffer (does not need to be null terminated).
+     * @param[in] aLength   The length (number of chars) in the buffer.
+     *
+     */
+    NameData(const char *aBuffer, uint8_t aLength) { Init(aBuffer, aLength); }
+
+    /**
+     * This method returns the pointer to char buffer (not necessarily null terminated).
+     *
+     * @returns The pointer to the char buffer.
+     *
+     */
+    const char *GetBuffer(void) const { return reinterpret_cast<const char *>(GetBytes()); }
+
+    /**
+     * This method returns the length (number of chars in buffer).
+     *
+     * @returns The name length.
+     *
+     */
+    uint8_t GetLength(void) const { return Data<kWithUint8Length>::GetLength(); }
+
+    /**
+     * This method copies the name data into a given char buffer with a given size.
+     *
+     * The given buffer is cleared (`memset` to zero) before copying the name into it. The copied string
+     * in @p aBuffer is NOT necessarily null terminated.
+     *
+     * @param[out] aBuffer   A pointer to a buffer where to copy the name into.
+     * @param[in]  aMaxSize  Size of @p aBuffer (maximum number of chars to write into @p aBuffer).
+     *
+     * @returns The actual number of chars copied into @p aBuffer.
+     *
+     */
+    uint8_t CopyTo(char *aBuffer, uint8_t aMaxSize) const;
+};
+
+/**
+ * This structure represents an Network Name.
+ *
+ */
+class NetworkName : public otNetworkName, public Unequatable<NetworkName>
+{
+public:
+    /**
+     * This constant specified the maximum number of chars in Network Name (excludes null char).
+     *
+     */
+    static constexpr uint8_t kMaxSize = OT_NETWORK_NAME_MAX_SIZE;
+
+    /**
+     * This constructor initializes the Network Name as an empty string.
+     *
+     */
+    NetworkName(void) { m8[0] = '\0'; }
+
+    /**
+     * This method gets the Network Name as a null terminated C string.
+     *
+     * @returns The Network Name as a null terminated C string array.
+     *
+     */
+    const char *GetAsCString(void) const { return m8; }
+
+    /**
+     * This method gets the Network Name as NameData.
+     *
+     * @returns The Network Name as NameData.
+     *
+     */
+    NameData GetAsData(void) const;
+
+    /**
+     * This method sets the Network Name from a given null terminated C string.
+     *
+     * This method also validates that the given @p aNameString follows UTF-8 encoding and can fit in `kMaxSize`
+     * chars.
+     *
+     * @param[in] aNameString      A name C string.
+     *
+     * @retval kErrorNone          Successfully set the Network Name.
+     * @retval kErrorAlready       The name is already set to the same string.
+     * @retval kErrorInvalidArgs   Given name is invalid (too long or does not follow UTF-8 encoding).
+     *
+     */
+    Error Set(const char *aNameString);
+
+    /**
+     * This method sets the Network Name.
+     *
+     * @param[in]  aNameData           A reference to name data.
+     *
+     * @retval kErrorNone          Successfully set the Network Name.
+     * @retval kErrorAlready       The name is already set to the same string.
+     * @retval kErrorInvalidArgs   Given name is too long.
+     *
+     */
+    Error Set(const NameData &aNameData);
+
+    /**
+     * This method overloads operator `==` to evaluate whether or not two given `NetworkName` objects are equal.
+     *
+     * @param[in]  aOther  The other `NetworkName` to compare with.
+     *
+     * @retval TRUE   If the two are equal.
+     * @retval FALSE  If the two are not equal.
+     *
+     */
+    bool operator==(const NetworkName &aOther) const;
+};
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+/**
+ * This type represents a Thread Domain Name.
+ *
+ */
+typedef NetworkName DomainName;
+#endif
+
+/**
+ * This class manages the Network Name value.
+ *
+ */
+class NetworkNameManager : public InstanceLocator, private NonCopyable
+{
+public:
+    /**
+     * Constructor.
+     *
+     * @param[in]  aInstance  A reference to the OpenThread instance.
+     *
+     */
+    explicit NetworkNameManager(Instance &aInstance);
+
+    /**
+     * This method returns the Network Name.
+     *
+     * @returns The Network Name.
+     *
+     */
+    const NetworkName &GetNetworkName(void) const { return mNetworkName; }
+
+    /**
+     * This method sets the Network Name.
+     *
+     * @param[in]  aNameString   A pointer to a string character array. Must be null terminated.
+     *
+     * @retval kErrorNone          Successfully set the Network Name.
+     * @retval kErrorInvalidArgs   Given name is too long.
+     *
+     */
+    Error SetNetworkName(const char *aNameString);
+
+    /**
+     * This method sets the Network Name.
+     *
+     * @param[in]  aNameData     A name data (pointer to char buffer and length).
+     *
+     * @retval kErrorNone          Successfully set the Network Name.
+     * @retval kErrorInvalidArgs   Given name is too long.
+     *
+     */
+    Error SetNetworkName(const NameData &aNameData);
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+    /**
+     * This method returns the Thread Domain Name.
+     *
+     * @returns The Thread Domain Name.
+     *
+     */
+    const DomainName &GetDomainName(void) const { return mDomainName; }
+
+    /**
+     * This method sets the Thread Domain Name.
+     *
+     * @param[in]  aNameString   A pointer to a string character array. Must be null terminated.
+     *
+     * @retval kErrorNone          Successfully set the Thread Domain Name.
+     * @retval kErrorInvalidArgs   Given name is too long.
+     *
+     */
+    Error SetDomainName(const char *aNameString);
+
+    /**
+     * This method sets the Thread Domain Name.
+     *
+     * @param[in]  aNameData     A name data (pointer to char buffer and length).
+     *
+     * @retval kErrorNone          Successfully set the Thread Domain Name.
+     * @retval kErrorInvalidArgs   Given name is too long.
+     *
+     */
+    Error SetDomainName(const NameData &aNameData);
+#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+
+private:
+    Error SignalNetworkNameChange(Error aError);
+
+    static const char sNetworkNameInit[];
+    static const char sDomainNameInit[];
+
+    NetworkName mNetworkName;
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+    DomainName mDomainName;
+#endif
+};
+
+} // namespace MeshCoP
+
+DefineCoreType(otNetworkName, MeshCoP::NetworkName);
+
+} // namespace ot
+
+#endif // MESHCOP_EXTENDED_PANID_HPP_
diff --git a/src/core/meshcop/panid_query_client.cpp b/src/core/meshcop/panid_query_client.cpp
index a36f985..7bacc80 100644
--- a/src/core/meshcop/panid_query_client.cpp
+++ b/src/core/meshcop/panid_query_client.cpp
@@ -41,7 +41,7 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "meshcop/meshcop.hpp"
 #include "meshcop/meshcop_tlvs.hpp"
 #include "thread/thread_netif.hpp"
@@ -49,6 +49,8 @@
 
 namespace ot {
 
+RegisterLogModule("PanIdQueryClnt");
+
 PanIdQueryClient::PanIdQueryClient(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mCallback(nullptr)
@@ -66,11 +68,11 @@
 {
     Error                   error = kErrorNone;
     MeshCoP::ChannelMaskTlv channelMask;
-    Ip6::MessageInfo        messageInfo;
+    Tmf::MessageInfo        messageInfo(GetInstance());
     Coap::Message *         message = nullptr;
 
     VerifyOrExit(Get<MeshCoP::Commissioner>().IsActive(), error = kErrorInvalidState);
-    VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
+    VerifyOrExit((message = Get<Tmf::Agent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = message->InitAsPost(aAddress, UriPath::kPanIdQuery));
     SuccessOrExit(error = message->SetPayloadMarker());
@@ -84,12 +86,10 @@
 
     SuccessOrExit(error = Tlv::Append<MeshCoP::PanIdTlv>(*message, aPanId));
 
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.SetPeerAddr(aAddress);
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
+    messageInfo.SetSockAddrToRlocPeerAddrTo(aAddress);
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
 
-    otLogInfoMeshCoP("sent panid query");
+    LogInfo("sent panid query");
 
     mCallback = aCallback;
     mContext  = aContext;
@@ -112,7 +112,7 @@
 
     VerifyOrExit(aMessage.IsConfirmablePostRequest());
 
-    otLogInfoMeshCoP("received panid conflict");
+    LogInfo("received panid conflict");
 
     SuccessOrExit(Tlv::Find<MeshCoP::PanIdTlv>(aMessage, panId));
 
@@ -125,7 +125,7 @@
 
     SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMessage, responseInfo));
 
-    otLogInfoMeshCoP("sent panid query conflict response");
+    LogInfo("sent panid query conflict response");
 
 exit:
     return;
diff --git a/src/core/meshcop/timestamp.cpp b/src/core/meshcop/timestamp.cpp
index 5d8f59b..08ed36b 100644
--- a/src/core/meshcop/timestamp.cpp
+++ b/src/core/meshcop/timestamp.cpp
@@ -38,13 +38,23 @@
 namespace ot {
 namespace MeshCoP {
 
+void Timestamp::ConvertTo(otTimestamp &aTimestamp) const
+{
+    aTimestamp.mSeconds       = GetSeconds();
+    aTimestamp.mTicks         = GetTicks();
+    aTimestamp.mAuthoritative = GetAuthoritative();
+}
+
+void Timestamp::SetFromTimestamp(const otTimestamp &aTimestamp)
+{
+    SetSeconds(aTimestamp.mSeconds);
+    SetTicks(aTimestamp.mTicks);
+    SetAuthoritative(aTimestamp.mAuthoritative);
+}
+
 int Timestamp::Compare(const Timestamp *aFirst, const Timestamp *aSecond)
 {
-    int      rval;
-    uint64_t firstSeconds;
-    uint64_t secondSeconds;
-    uint16_t firstTicks;
-    uint16_t secondTicks;
+    int rval;
 
     if (aFirst == nullptr)
     {
@@ -62,22 +72,46 @@
 
     // Both are non-null.
 
-    firstSeconds  = aFirst->GetSeconds();
-    secondSeconds = aSecond->GetSeconds();
+    rval = Compare(*aFirst, *aSecond);
+
+exit:
+    return rval;
+}
+
+int Timestamp::Compare(const Timestamp &aFirst, const Timestamp &aSecond)
+{
+    int      rval;
+    uint64_t firstSeconds;
+    uint64_t secondSeconds;
+    uint16_t firstTicks;
+    uint16_t secondTicks;
+    bool     firstAuthoritative;
+    bool     secondAuthoritative;
+
+    firstSeconds  = aFirst.GetSeconds();
+    secondSeconds = aSecond.GetSeconds();
 
     if (firstSeconds != secondSeconds)
     {
         ExitNow(rval = (firstSeconds > secondSeconds) ? 1 : -1);
     }
 
-    firstTicks  = aFirst->GetTicks();
-    secondTicks = aSecond->GetTicks();
+    firstTicks  = aFirst.GetTicks();
+    secondTicks = aSecond.GetTicks();
 
     if (firstTicks != secondTicks)
     {
         ExitNow(rval = (firstTicks > secondTicks) ? 1 : -1);
     }
 
+    firstAuthoritative  = aFirst.GetAuthoritative();
+    secondAuthoritative = aSecond.GetAuthoritative();
+
+    if (firstAuthoritative != secondAuthoritative)
+    {
+        ExitNow(rval = firstAuthoritative ? 1 : -1);
+    }
+
     rval = 0;
 
 exit:
diff --git a/src/core/meshcop/timestamp.hpp b/src/core/meshcop/timestamp.hpp
index ea3b115..1eace25 100644
--- a/src/core/meshcop/timestamp.hpp
+++ b/src/core/meshcop/timestamp.hpp
@@ -39,6 +39,7 @@
 
 #include <string.h>
 
+#include <openthread/dataset.h>
 #include <openthread/platform/toolchain.h>
 
 #include "common/clearable.hpp"
@@ -60,6 +61,18 @@
 {
 public:
     /**
+     * This method converts the timestamp to `otTimestamp`.
+     *
+     */
+    void ConvertTo(otTimestamp &aTimestamp) const;
+
+    /**
+     * This method sets the timestamp from `otTimestamp`.
+     *
+     */
+    void SetFromTimestamp(const otTimestamp &aTimestamp);
+
+    /**
      * This method returns the Seconds value.
      *
      * @returns The Seconds value.
@@ -128,6 +141,15 @@
     void AdvanceRandomTicks(void);
 
     /**
+     * This method indicates whether the timestamp indicates an MLE Orphan Announce message.
+     *
+     * @retval TRUE   The timestamp indicates an Orphan Announce message.
+     * @retval FALSE  If the timestamp does not indicate an Orphan Announce message.
+     *
+     */
+    bool IsOrphanTimestamp(void) const { return GetSeconds() == 0 && GetTicks() == 0 && GetAuthoritative(); }
+
+    /**
      * This static method compares two timestamps.
      *
      * Either one or both @p aFirst or @p aSecond can be `nullptr`. A non-null timestamp is considered greater than
@@ -143,6 +165,19 @@
      */
     static int Compare(const Timestamp *aFirst, const Timestamp *aSecond);
 
+    /**
+     * This static method compares two timestamps.
+     *
+     * @param[in]  aFirst   A reference to the first timestamp to compare.
+     * @param[in]  aSecond  A reference to the second timestamp to compare.
+     *
+     * @retval -1  if @p aFirst is less than @p aSecond (`aFirst < aSecond`).
+     * @retval  0  if @p aFirst is equal to @p aSecond (`aFirst == aSecond`).
+     * @retval  1  if @p aFirst is greater than @p aSecond (`aFirst > aSecond`).
+     *
+     */
+    static int Compare(const Timestamp &aFirst, const Timestamp &aSecond);
+
 private:
     static constexpr uint8_t  kTicksOffset         = 1;
     static constexpr uint16_t kTicksMask           = 0x7fff << kTicksOffset;
diff --git a/src/core/mtd.cmake b/src/core/mtd.cmake
index 7526f18..7d6f0ef 100644
--- a/src/core/mtd.cmake
+++ b/src/core/mtd.cmake
@@ -43,6 +43,9 @@
 target_link_libraries(openthread-mtd
     PRIVATE
         ${OT_MBEDTLS}
-        tcplp
         ot-config
 )
+
+if(NOT OT_EXCLUDE_TCPLP_LIB)
+    target_link_libraries(openthread-mtd PRIVATE tcplp)
+endif()
diff --git a/src/core/net/checksum.cpp b/src/core/net/checksum.cpp
index 7c532ff..16860cb 100644
--- a/src/core/net/checksum.cpp
+++ b/src/core/net/checksum.cpp
@@ -36,6 +36,7 @@
 #include "common/code_utils.hpp"
 #include "common/message.hpp"
 #include "net/icmp6.hpp"
+#include "net/ip4_types.hpp"
 #include "net/tcp6.hpp"
 #include "net/udp6.hpp"
 
@@ -115,6 +116,35 @@
     }
 }
 
+void Checksum::Calculate(const Ip4::Address &aSource,
+                         const Ip4::Address &aDestination,
+                         uint8_t             aIpProto,
+                         const Message &     aMessage)
+{
+    Message::Chunk chunk;
+    uint16_t       length = aMessage.GetLength() - aMessage.GetOffset();
+
+    // Pseudo-header for checksum calculation (RFC-768/792/793).
+    // Note: ICMP checksum won't count the presudo header like TCP and UDP.
+    if (aIpProto != Ip4::kProtoIcmp)
+    {
+        AddData(aSource.GetBytes(), sizeof(Ip4::Address));
+        AddData(aDestination.GetBytes(), sizeof(Ip4::Address));
+        AddUint16(static_cast<uint16_t>(aIpProto));
+        AddUint16(length);
+    }
+
+    // Add message content (from offset to the end) to checksum.
+
+    aMessage.GetFirstChunk(aMessage.GetOffset(), length, chunk);
+
+    while (chunk.GetLength() > 0)
+    {
+        AddData(chunk.GetBytes(), chunk.GetLength());
+        aMessage.GetNextChunk(length, chunk);
+    }
+}
+
 Error Checksum::VerifyMessageChecksum(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, uint8_t aIpProto)
 {
     Checksum checksum;
@@ -150,6 +180,8 @@
         ExitNow();
     }
 
+    // Clear the checksum before calculating it.
+    aMessage.Write<uint16_t>(aMessage.GetOffset() + headerOffset, 0);
     checksum.Calculate(aSource, aDestination, aIpProto, aMessage);
     checksum.WriteToMessage(aMessage.GetOffset() + headerOffset, aMessage);
 
@@ -157,4 +189,48 @@
     return;
 }
 
+void Checksum::UpdateMessageChecksum(Message &           aMessage,
+                                     const Ip4::Address &aSource,
+                                     const Ip4::Address &aDestination,
+                                     uint8_t             aIpProto)
+{
+    uint16_t headerOffset;
+    Checksum checksum;
+
+    switch (aIpProto)
+    {
+    case Ip4::kProtoTcp:
+        headerOffset = Ip4::Tcp::Header::kChecksumFieldOffset;
+        break;
+
+    case Ip4::kProtoUdp:
+        headerOffset = Ip4::Udp::Header::kChecksumFieldOffset;
+        break;
+
+    case Ip4::kProtoIcmp:
+        headerOffset = Ip4::Icmp::Header::kChecksumFieldOffset;
+        break;
+
+    default:
+        ExitNow();
+    }
+
+    // Clear the checksum before calculating it.
+    aMessage.Write<uint16_t>(aMessage.GetOffset() + headerOffset, 0);
+    checksum.Calculate(aSource, aDestination, aIpProto, aMessage);
+    checksum.WriteToMessage(aMessage.GetOffset() + headerOffset, aMessage);
+
+exit:
+    return;
+}
+
+void Checksum::UpdateIp4HeaderChecksum(Ip4::Header &aHeader)
+{
+    Checksum checksum;
+
+    aHeader.SetChecksum(0);
+    checksum.AddData(reinterpret_cast<const uint8_t *>(&aHeader), sizeof(aHeader));
+    aHeader.SetChecksum(~checksum.GetValue());
+}
+
 } // namespace ot
diff --git a/src/core/net/checksum.hpp b/src/core/net/checksum.hpp
index e56dc2f..f335785 100644
--- a/src/core/net/checksum.hpp
+++ b/src/core/net/checksum.hpp
@@ -39,6 +39,7 @@
 #include <stdint.h>
 
 #include "common/message.hpp"
+#include "net/ip4_types.hpp"
 #include "net/ip6_address.hpp"
 #include "net/ip6_headers.hpp"
 #include "net/socket.hpp"
@@ -69,11 +70,11 @@
     static Error VerifyMessageChecksum(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, uint8_t aIpProto);
 
     /**
-     * This static method calculates and then updates the checksum in a given message (if UDP/ICMP6).
+     * This static method calculates and then updates the checksum in a given message (if TCP/UDP/ICMPv6).
      *
-     * @param[inout] aMessage   The message to update the checksum in. The `aMessage.GetOffset()` should point to start
-     *                          of the UDP/ICMP6 header. On exit the checksum field in UDP/ICMP6 header in the message
-     *                          is updated.
+     * @param[in,out] aMessage  The message to update the checksum in. The `aMessage.GetOffset()` should point to start
+     *                          of the TCP/UDP/ICMPv6 header. On exit the checksum field in TCP/UDP/ICMPv6 header in the
+     *                          message is updated.
      * @param[in] aSource       The source address.
      * @param[in] aDestination  The destination address.
      * @param[in] aIpProto      The Internet Protocol value.
@@ -84,6 +85,30 @@
                                       const Ip6::Address &aDestination,
                                       uint8_t             aIpProto);
 
+    /**
+     * This static method calculates and then updates the checksum in a given IPv4 message (if TCP/UDP/ICMP(v4)).
+     *
+     * @param[in,out] aMessage  The message to update the checksum in. The `aMessage.GetOffset()` should point to start
+     *                          of the TCP/UDP/ICMP(v4) header. On exit the checksum field in TCP/UDP/ICMP(v4) header in
+     *                          the message is updated.
+     * @param[in] aSource       The source address.
+     * @param[in] aDestination  The destination address.
+     * @param[in] aIpProto      The Internet Protocol value.
+     *
+     */
+    static void UpdateMessageChecksum(Message &           aMessage,
+                                      const Ip4::Address &aSource,
+                                      const Ip4::Address &aDestination,
+                                      uint8_t             aIpProto);
+
+    /**
+     * This static method calculates and then updates the checksum field in the IPv4 header.
+     *
+     * @param[in,out] aHeader The IPv4 header to update the checksum in.
+     *
+     */
+    static void UpdateIp4HeaderChecksum(Ip4::Header &aHeader);
+
 private:
     Checksum(void)
         : mValue(0)
@@ -100,6 +125,10 @@
                        const Ip6::Address &aDestination,
                        uint8_t             aIpProto,
                        const Message &     aMessage);
+    void     Calculate(const Ip4::Address &aSource,
+                       const Ip4::Address &aDestination,
+                       uint8_t             aIpProto,
+                       const Message &     aMessage);
 
     static constexpr uint16_t kValidRxChecksum = 0xffff;
 
diff --git a/src/core/net/dhcp6.hpp b/src/core/net/dhcp6.hpp
index 5cfec52..6a1f3da 100644
--- a/src/core/net/dhcp6.hpp
+++ b/src/core/net/dhcp6.hpp
@@ -36,6 +36,8 @@
 
 #include "openthread-core-config.h"
 
+#if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE || OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
+
 #include "common/clearable.hpp"
 #include "common/equatable.hpp"
 #include "common/message.hpp"
@@ -309,7 +311,7 @@
     /**
      * This method sets the client LinkLayerAddress.
      *
-     * @param[in]  aLinkLayerAddress The client LinkLayerAddress.
+     * @param[in]  aDuidLinkLayerAddress  The client LinkLayerAddress.
      *
      */
     void SetDuidLinkLayerAddress(const Mac::ExtAddress &aDuidLinkLayerAddress)
@@ -380,7 +382,7 @@
     /**
      * This method sets the server LinkLayerAddress.
      *
-     * @param[in]  aLinkLayerAddress The server LinkLayerAddress.
+     * @param[in]  aDuidLinkLayerAddress  The server LinkLayerAddress.
      *
      */
     void SetDuidLinkLayerAddress(const Mac::ExtAddress &aDuidLinkLayerAddress)
@@ -426,7 +428,7 @@
     /**
      * This method sets the client IAID.
      *
-     * @param[in]  aIaId  The client IAID.
+     * @param[in]  aIaid  The client IAID.
      *
      */
     void SetIaid(uint32_t aIaid) { mIaid = HostSwap32(aIaid); }
@@ -668,4 +670,6 @@
 } // namespace Dhcp6
 } // namespace ot
 
+#endif // #if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE || OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
+
 #endif // DHCP6_HPP_
diff --git a/src/core/net/dhcp6_client.cpp b/src/core/net/dhcp6_client.cpp
index eed2a27..9c3e772 100644
--- a/src/core/net/dhcp6_client.cpp
+++ b/src/core/net/dhcp6_client.cpp
@@ -40,7 +40,7 @@
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "mac/mac.hpp"
 #include "net/dhcp6.hpp"
 #include "thread/thread_netif.hpp"
@@ -48,6 +48,8 @@
 namespace ot {
 namespace Dhcp6 {
 
+RegisterLogModule("Dhcp6Client");
+
 Client::Client(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mSocket(aInstance)
@@ -146,7 +148,7 @@
             }
             else
             {
-                otLogWarnIp6("Insufficient memory for new DHCP prefix");
+                LogWarn("Insufficient memory for new DHCP prefix");
                 continue;
             }
         }
@@ -283,13 +285,13 @@
     messageInfo.mPeerPort = kDhcpServerPort;
 
     SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));
-    otLogInfoIp6("solicit");
+    LogInfo("solicit");
 
 exit:
     if (error != kErrorNone)
     {
         FreeMessage(message);
-        otLogWarnIp6("Failed to send DHCPv6 Solicit: %s", ErrorToString(error));
+        LogWarn("Failed to send DHCPv6 Solicit: %s", ErrorToString(error));
     }
 }
 
diff --git a/src/core/net/dhcp6_server.cpp b/src/core/net/dhcp6_server.cpp
index 805144d..eaab1b4 100644
--- a/src/core/net/dhcp6_server.cpp
+++ b/src/core/net/dhcp6_server.cpp
@@ -35,18 +35,21 @@
 
 #if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
 
+#include "common/array.hpp"
 #include "common/as_core_type.hpp"
 #include "common/code_utils.hpp"
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "thread/mle.hpp"
 #include "thread/thread_netif.hpp"
 
 namespace ot {
 namespace Dhcp6 {
 
+RegisterLogModule("Dhcp6Server");
+
 Server::Server(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mSocket(aInstance)
@@ -175,7 +178,7 @@
 
     if (error != kErrorNone)
     {
-        otLogNoteIp6("Failed to add DHCPv6 prefix agent: %s", ErrorToString(error));
+        LogNote("Failed to add DHCPv6 prefix agent: %s", ErrorToString(error));
     }
 }
 
@@ -317,7 +320,7 @@
     VerifyOrExit(option.GetLength() == sizeof(option) - sizeof(Option), error = kErrorParse);
 
     // mask matching prefix
-    for (uint16_t i = 0; i < OT_ARRAY_LENGTH(mPrefixAgents); i++)
+    for (uint16_t i = 0; i < GetArrayLength(mPrefixAgents); i++)
     {
         if (mPrefixAgents[i].IsValid() && mPrefixAgents[i].IsPrefixMatch(option.GetAddress()))
         {
@@ -397,7 +400,7 @@
 
     if (mPrefixAgentsMask)
     {
-        for (uint16_t i = 0; i < OT_ARRAY_LENGTH(mPrefixAgents); i++)
+        for (uint16_t i = 0; i < GetArrayLength(mPrefixAgents); i++)
         {
             if (mPrefixAgentsMask & (1 << i))
             {
@@ -437,7 +440,7 @@
     if (mPrefixAgentsMask)
     {
         // if specified, only apply specified prefixes
-        for (uint16_t i = 0; i < OT_ARRAY_LENGTH(mPrefixAgents); i++)
+        for (uint16_t i = 0; i < GetArrayLength(mPrefixAgents); i++)
         {
             if (mPrefixAgentsMask & (1 << i))
             {
diff --git a/src/core/net/dhcp6_server.hpp b/src/core/net/dhcp6_server.hpp
index 01e0c5b..8fa7db3 100644
--- a/src/core/net/dhcp6_server.hpp
+++ b/src/core/net/dhcp6_server.hpp
@@ -167,7 +167,7 @@
          * @param[in]  aContextId        The 6LoWPAN Context ID.
          *
          */
-        void Set(const Ip6::Prefix &aPrefix, const Mle::MeshLocalPrefix &aMeshLocalPrefix, uint8_t aContextId)
+        void Set(const Ip6::Prefix &aPrefix, const Ip6::NetworkPrefix &aMeshLocalPrefix, uint8_t aContextId)
         {
             mPrefix = aPrefix;
 
diff --git a/src/core/net/dns_client.cpp b/src/core/net/dns_client.cpp
index 52d1d8d..bb33d70 100644
--- a/src/core/net/dns_client.cpp
+++ b/src/core/net/dns_client.cpp
@@ -30,12 +30,13 @@
 
 #if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
 
+#include "common/array.hpp"
 #include "common/as_core_type.hpp"
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "net/udp6.hpp"
 #include "thread/network_data_types.hpp"
 #include "thread/thread_netif.hpp"
@@ -48,6 +49,8 @@
 namespace ot {
 namespace Dns {
 
+RegisterLogModule("DnsClient");
+
 //---------------------------------------------------------------------------------------------------------------------
 // Client::QueryConfig
 
@@ -325,16 +328,17 @@
 
     if ((info.mQueryType == kIp4AddressQuery) || mIp6QueryResponseRequiresNat64)
     {
-        Section     section;
-        ARecord     aRecord;
-        Ip6::Prefix nat64Prefix;
+        Section                          section;
+        ARecord                          aRecord;
+        NetworkData::ExternalRouteConfig nat64Prefix;
 
-        SuccessOrExit(error = GetNat64Prefix(nat64Prefix));
+        VerifyOrExit(mInstance->Get<NetworkData::Leader>().GetPreferredNat64Prefix(nat64Prefix) == kErrorNone,
+                     error = kErrorInvalidState);
 
         section = (info.mQueryType == kIp4AddressQuery) ? kAnswerSection : kAdditionalDataSection;
         SuccessOrExit(error = FindARecord(section, name, aIndex, aRecord));
 
-        aAddress.SynthesizeFromIp4Address(nat64Prefix, aRecord.GetAddress());
+        aAddress.SynthesizeFromIp4Address(nat64Prefix.GetPrefix(), aRecord.GetAddress());
         aTtl = aRecord.GetTtl();
 
         ExitNow();
@@ -348,37 +352,6 @@
     return error;
 }
 
-#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
-
-Error Client::AddressResponse::GetNat64Prefix(Ip6::Prefix &aPrefix) const
-{
-    Error                            error      = kErrorNotFound;
-    NetworkData::Iterator            iterator   = NetworkData::kIteratorInit;
-    signed int                       preference = NetworkData::kRoutePreferenceLow;
-    NetworkData::ExternalRouteConfig config;
-
-    aPrefix.Clear();
-
-    while (mInstance->Get<NetworkData::Leader>().GetNextExternalRoute(iterator, config) == kErrorNone)
-    {
-        if (!config.mNat64 || !config.GetPrefix().IsValidNat64())
-        {
-            continue;
-        }
-
-        if ((aPrefix.GetLength() == 0) || (config.mPreference > preference))
-        {
-            aPrefix    = config.GetPrefix();
-            preference = config.mPreference;
-            error      = kErrorNone;
-        }
-    }
-
-    return error;
-}
-
-#endif // OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
-
 #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -533,13 +506,13 @@
 #endif
 
 const uint8_t Client::kQuestionCount[] = {
-    /* kIp6AddressQuery -> */ OT_ARRAY_LENGTH(kIp6AddressQueryRecordTypes), // AAAA records
+    /* kIp6AddressQuery -> */ GetArrayLength(kIp6AddressQueryRecordTypes), // AAAA records
 #if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
-    /* kIp4AddressQuery -> */ OT_ARRAY_LENGTH(kIp4AddressQueryRecordTypes), // A records
+    /* kIp4AddressQuery -> */ GetArrayLength(kIp4AddressQueryRecordTypes), // A records
 #endif
 #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
-    /* kBrowseQuery  -> */ OT_ARRAY_LENGTH(kBrowseQueryRecordTypes),  // PTR records
-    /* kServiceQuery -> */ OT_ARRAY_LENGTH(kServiceQueryRecordTypes), // SRV and TXT records
+    /* kBrowseQuery  -> */ GetArrayLength(kBrowseQueryRecordTypes),  // PTR records
+    /* kServiceQuery -> */ GetArrayLength(kServiceQueryRecordTypes), // SRV and TXT records
 #endif
 };
 
@@ -648,6 +621,22 @@
     return StartQuery(info, aConfig, nullptr, aHostName, aContext);
 }
 
+#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
+Error Client::ResolveIp4Address(const char *       aHostName,
+                                AddressCallback    aCallback,
+                                void *             aContext,
+                                const QueryConfig *aConfig)
+{
+    QueryInfo info;
+
+    info.Clear();
+    info.mQueryType                 = kIp4AddressQuery;
+    info.mCallback.mAddressCallback = aCallback;
+
+    return StartQuery(info, aConfig, nullptr, aHostName, aContext);
+}
+#endif
+
 #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
 
 Error Client::Browse(const char *aServiceName, BrowseCallback aCallback, void *aContext, const QueryConfig *aConfig)
@@ -715,6 +704,17 @@
 
     aInfo.mCallbackContext = aContext;
 
+#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
+    if (aInfo.mQueryType == kIp4AddressQuery)
+    {
+        NetworkData::ExternalRouteConfig nat64Prefix;
+
+        VerifyOrExit(aInfo.mConfig.GetNat64Mode() == QueryConfig::kNat64Allow, error = kErrorInvalidArgs);
+        VerifyOrExit(Get<NetworkData::Leader>().GetPreferredNat64Prefix(nat64Prefix) == kErrorNone,
+                     error = kErrorInvalidState);
+    }
+#endif
+
     SuccessOrExit(error = AllocateQuery(aInfo, aLabel, aName, query));
     mQueries.Enqueue(*query);
 
@@ -728,7 +728,7 @@
 {
     Error error = kErrorNone;
 
-    aQuery = Get<MessagePool>().New(Message::kTypeOther, /* aReserveHeader */ 0);
+    aQuery = Get<MessagePool>().Allocate(Message::kTypeOther);
     VerifyOrExit(aQuery != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = aQuery->Append(aInfo));
@@ -905,20 +905,21 @@
 
 Client::Query *Client::FindQueryById(uint16_t aMessageId)
 {
-    Query *   query;
+    Query *   matchedQuery = nullptr;
     QueryInfo info;
 
-    for (query = mQueries.GetHead(); query != nullptr; query = query->GetNext())
+    for (Query &query : mQueries)
     {
-        info.ReadFrom(*query);
+        info.ReadFrom(query);
 
         if (info.mMessageId == aMessageId)
         {
+            matchedQuery = &query;
             break;
         }
     }
 
-    return query;
+    return matchedQuery;
 }
 
 void Client::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMsgInfo)
@@ -975,12 +976,18 @@
 
     // Check the Question Section
 
-    VerifyOrExit(header.GetQuestionCount() == kQuestionCount[aType], error = kErrorParse);
-
-    for (uint8_t num = 0; num < kQuestionCount[aType]; num++)
+    if (header.GetQuestionCount() == kQuestionCount[aType])
     {
-        SuccessOrExit(error = Name::CompareName(message, offset, queryName));
-        offset += sizeof(Question);
+        for (uint8_t num = 0; num < kQuestionCount[aType]; num++)
+        {
+            SuccessOrExit(error = Name::CompareName(message, offset, queryName));
+            offset += sizeof(Question);
+        }
+    }
+    else
+    {
+        VerifyOrExit((header.GetResponseCode() != Header::kResponseSuccess) && (header.GetQuestionCount() == 0),
+                     error = kErrorParse);
     }
 
     // Check the answer, authority and additional record sections
@@ -1049,7 +1056,7 @@
 exit:
     if (error != kErrorNone)
     {
-        otLogInfoDns("Failed to parse response %s", ErrorToString(error));
+        LogInfo("Failed to parse response %s", ErrorToString(error));
     }
 
     return error;
@@ -1064,24 +1071,21 @@
 {
     TimeMilli now      = TimerMilli::GetNow();
     TimeMilli nextTime = now.GetDistantFuture();
-    Query *   nextQuery;
     QueryInfo info;
 
-    for (Query *query = mQueries.GetHead(); query != nullptr; query = nextQuery)
+    for (Query &query : mQueries)
     {
-        nextQuery = query->GetNext();
-
-        info.ReadFrom(*query);
+        info.ReadFrom(query);
 
         if (now >= info.mRetransmissionTime)
         {
             if (info.mTransmissionCount >= info.mConfig.GetMaxTxAttempts())
             {
-                FinalizeQuery(*query, kErrorResponseTimeout);
+                FinalizeQuery(query, kErrorResponseTimeout);
                 continue;
             }
 
-            SendQuery(*query, info, /* aUpdateTimer */ false);
+            SendQuery(query, info, /* aUpdateTimer */ false);
         }
 
         if (nextTime > info.mRetransmissionTime)
diff --git a/src/core/net/dns_client.hpp b/src/core/net/dns_client.hpp
index b29b34d..de9afca 100644
--- a/src/core/net/dns_client.hpp
+++ b/src/core/net/dns_client.hpp
@@ -35,6 +35,7 @@
 
 #include <openthread/dns_client.h>
 
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/message.hpp"
 #include "common/non_copyable.hpp"
@@ -210,7 +211,7 @@
 
         explicit QueryConfig(InitMode aMode);
 
-        Ip6::SockAddr &GetServerSockAddr(void) { return static_cast<Ip6::SockAddr &>(mServerSockAddr); }
+        Ip6::SockAddr &GetServerSockAddr(void) { return AsCoreType(&mServerSockAddr); }
 
         void SetResponseTimeout(uint32_t aResponseTimeout) { mResponseTimeout = aResponseTimeout; }
         void SetMaxTxAttempts(uint8_t aMaxTxAttempts) { mMaxTxAttempts = aMaxTxAttempts; }
@@ -330,9 +331,10 @@
          * @param[out] aAddress      A reference to an IPv6 address to output the address.
          * @param[out] aTtl          A reference to a `uint32_t` to output TTL for the address.
          *
-         * @retval kErrorNone       The address was read successfully.
-         * @retval kErrorNotFound   No address record at @p aIndex.
-         * @retval kErrorParse      Could not parse the records.
+         * @retval kErrorNone          The address was read successfully.
+         * @retval kErrorNotFound      No address record at @p aIndex.
+         * @retval kErrorParse         Could not parse the records.
+         * @retval kErrorInvalidState  No NAT64 prefix (applicable only when NAT64 is allowed).
          *
          */
         Error GetAddress(uint16_t aIndex, Ip6::Address &aAddress, uint32_t &aTtl) const;
@@ -389,7 +391,6 @@
          * Note that this method gets the service instance label and not the full service instance name which is of the
          * form `<Instance>.<Service>.<Domain>`.
          *
-         * @param[in]  aResponse          A pointer to a response.
          * @param[in]  aIndex             The service instance record index to retrieve.
          * @param[out] aLabelBuffer       A char array to output the service instance label (MUST NOT be NULL).
          * @param[in]  aLabelBufferSize   The size of @p aLabelBuffer.
@@ -608,6 +609,34 @@
                          void *             aContext,
                          const QueryConfig *aConfig = nullptr);
 
+#if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE
+    /**
+     * This method sends an address resolution DNS query for A (IPv4) record for a given host name.
+     *
+     * When a successful response is received, the addresses are returned from @p aCallback as NAT64 IPv6 translated
+     * versions of the IPv4 addresses from the query response.
+     *
+     * The @p aConfig can be nullptr. In this case the default config (from `GetDefaultConfig()`) will be used as
+     * the config for this query. In a non-nullptr @p aConfig, some of the fields can be left unspecified (value zero).
+     * The unspecified fields are then replaced by the values from the default config.
+     *
+     * @param[in]  aHostName        The host name for which to query the address (MUST NOT be `nullptr`).
+     * @param[in]  aCallback        A callback function pointer to report the result of query.
+     * @param[in]  aContext         A pointer to arbitrary context information passed to @p aCallback.
+     * @param[in]  aConfig          The config to use for this query.
+     *
+     * @retval kErrorNone           Successfully sent DNS query.
+     * @retval kErrorNoBufs         Failed to allocate retransmission data.
+     * @retval kErrorInvalidArgs    The host name is not valid format or NAT64 is not enabled in config.
+     * @retval kErrorInvalidState   Cannot send query since Thread interface is not up, or there is no NAT64 prefix.
+     *
+     */
+    Error ResolveIp4Address(const char *       aHostName,
+                            AddressCallback    aCallback,
+                            void *             aContext,
+                            const QueryConfig *aConfig = nullptr);
+#endif
+
 #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
 
     /**
@@ -634,11 +663,10 @@
     /**
      * This method sends a DNS service instance resolution query for a given service instance.
      *
-     * The @p aConfig can be nullptr. In this case the default config (from `GetDefaultConfig()`) will be used as
-     * the config for this query. In a non-nullptr @p aConfig, some of the fields can be left unspecified (value zero).
-     * The unspecified fields are then replaced by the values from the default config.
+     * The @p aConfig can be `nullptr`. In this case the default config (from `GetDefaultConfig()`) will be used as
+     * the config for this query. In a non-`nullptr` @p aConfig, some of the fields can be left unspecified (value
+     * zero). The unspecified fields are then replaced by the values from the default config.
      *
-     * @param[in]  aServerSockAddr    The server socket address.
      * @param[in]  aInstanceLabel     The service instance label.
      * @param[in]  aServiceName       The service name (together with @p aInstanceLabel form full instance name).
      * @param[in]  aCallback          A function pointer that shall be called on response reception or time-out.
@@ -746,6 +774,15 @@
 };
 
 } // namespace Dns
+
+DefineCoreType(otDnsQueryConfig, Dns::Client::QueryConfig);
+DefineCoreType(otDnsAddressResponse, Dns::Client::AddressResponse);
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+DefineCoreType(otDnsBrowseResponse, Dns::Client::BrowseResponse);
+DefineCoreType(otDnsServiceResponse, Dns::Client::ServiceResponse);
+DefineCoreType(otDnsServiceInfo, Dns::Client::ServiceInfo);
+#endif
+
 } // namespace ot
 
 #endif // OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
diff --git a/src/core/net/dns_dso.cpp b/src/core/net/dns_dso.cpp
new file mode 100644
index 0000000..a18b459
--- /dev/null
+++ b/src/core/net/dns_dso.cpp
@@ -0,0 +1,1523 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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 "dns_dso.hpp"
+
+#if OPENTHREAD_CONFIG_DNS_DSO_ENABLE
+
+#include "common/array.hpp"
+#include "common/as_core_type.hpp"
+#include "common/code_utils.hpp"
+#include "common/debug.hpp"
+#include "common/instance.hpp"
+#include "common/locator_getters.hpp"
+#include "common/log.hpp"
+#include "common/random.hpp"
+
+/**
+ * @file
+ *   This file implements the DNS Stateful Operations (DSO) per RFC 8490.
+ */
+
+namespace ot {
+namespace Dns {
+
+RegisterLogModule("DnsDso");
+
+//---------------------------------------------------------------------------------------------------------------------
+// otPlatDso transport callbacks
+
+extern "C" otInstance *otPlatDsoGetInstance(otPlatDsoConnection *aConnection)
+{
+    return &AsCoreType(aConnection).GetInstance();
+}
+
+extern "C" otPlatDsoConnection *otPlatDsoAccept(otInstance *aInstance, const otSockAddr *aPeerSockAddr)
+{
+    return AsCoreType(aInstance).Get<Dso>().AcceptConnection(AsCoreType(aPeerSockAddr));
+}
+
+extern "C" void otPlatDsoHandleConnected(otPlatDsoConnection *aConnection)
+{
+    AsCoreType(aConnection).HandleConnected();
+}
+
+extern "C" void otPlatDsoHandleReceive(otPlatDsoConnection *aConnection, otMessage *aMessage)
+{
+    AsCoreType(aConnection).HandleReceive(AsCoreType(aMessage));
+}
+
+extern "C" void otPlatDsoHandleDisconnected(otPlatDsoConnection *aConnection, otPlatDsoDisconnectMode aMode)
+{
+    AsCoreType(aConnection).HandleDisconnected(MapEnum(aMode));
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+// Dso::Connection
+
+Dso::Connection::Connection(Instance &           aInstance,
+                            const Ip6::SockAddr &aPeerSockAddr,
+                            Callbacks &          aCallbacks,
+                            uint32_t             aInactivityTimeout,
+                            uint32_t             aKeepAliveInterval)
+    : InstanceLocator(aInstance)
+    , mNext(nullptr)
+    , mCallbacks(aCallbacks)
+    , mPeerSockAddr(aPeerSockAddr)
+    , mState(kStateDisconnected)
+    , mIsServer(false)
+    , mInactivity(aInactivityTimeout)
+    , mKeepAlive(aKeepAliveInterval)
+{
+    OT_ASSERT(aKeepAliveInterval >= kMinKeepAliveInterval);
+    Init(/* aIsServer */ false);
+}
+
+void Dso::Connection::Init(bool aIsServer)
+{
+    mNextMessageId       = 1;
+    mIsServer            = aIsServer;
+    mStateDidChange      = false;
+    mLongLivedOperation  = false;
+    mRetryDelay          = 0;
+    mRetryDelayErrorCode = Dns::Header::kResponseSuccess;
+    mDisconnectReason    = kReasonUnknown;
+}
+
+void Dso::Connection::SetState(State aState)
+{
+    VerifyOrExit(mState != aState);
+
+    LogInfo("State: %s -> %s on connection with %s", StateToString(mState), StateToString(aState),
+            mPeerSockAddr.ToString().AsCString());
+
+    mState          = aState;
+    mStateDidChange = true;
+
+exit:
+    return;
+}
+
+void Dso::Connection::SignalAnyStateChange(void)
+{
+    VerifyOrExit(mStateDidChange);
+    mStateDidChange = false;
+
+    switch (mState)
+    {
+    case kStateDisconnected:
+        mCallbacks.mHandleDisconnected(*this);
+        break;
+
+    case kStateConnectedButSessionless:
+        mCallbacks.mHandleConnected(*this);
+        break;
+
+    case kStateSessionEstablished:
+        mCallbacks.mHandleSessionEstablished(*this);
+        break;
+
+    case kStateConnecting:
+    case kStateEstablishingSession:
+        break;
+    };
+
+exit:
+    return;
+}
+
+Message *Dso::Connection::NewMessage(void)
+{
+    return Get<MessagePool>().Allocate(Message::kTypeOther, sizeof(Dns::Header),
+                                       Message::Settings(Message::kPriorityNormal));
+}
+
+void Dso::Connection::Connect(void)
+{
+    OT_ASSERT(mState == kStateDisconnected);
+
+    Init(/* aIsServer */ false);
+    Get<Dso>().mClientConnections.Push(*this);
+    MarkAsConnecting();
+    otPlatDsoConnect(this, &mPeerSockAddr);
+}
+
+void Dso::Connection::Accept(void)
+{
+    OT_ASSERT(mState == kStateDisconnected);
+
+    Init(/* aIsServer */ true);
+    Get<Dso>().mServerConnections.Push(*this);
+    MarkAsConnecting();
+}
+
+void Dso::Connection::MarkAsConnecting(void)
+{
+    SetState(kStateConnecting);
+
+    // While in `kStateConnecting` state we use the `mKeepAlive` to
+    // track the `kConnectingTimeout` (if connection is not established
+    // within the timeout, we consider it as failure and close it).
+
+    mKeepAlive.SetExpirationTime(TimerMilli::GetNow() + kConnectingTimeout);
+    Get<Dso>().mTimer.FireAtIfEarlier(mKeepAlive.GetExpirationTime());
+
+    // Wait for `HandleConnected()` or `HandleDisconnected()` callbacks
+    // or timeout.
+}
+
+void Dso::Connection::HandleConnected(void)
+{
+    OT_ASSERT(mState == kStateConnecting);
+
+    SetState(kStateConnectedButSessionless);
+    ResetTimeouts(/* aIsKeepAliveMessage */ false);
+
+    SignalAnyStateChange();
+}
+
+void Dso::Connection::Disconnect(DisconnectMode aMode, DisconnectReason aReason)
+{
+    VerifyOrExit(mState != kStateDisconnected);
+
+    mDisconnectReason = aReason;
+    MarkAsDisconnected();
+
+    otPlatDsoDisconnect(this, MapEnum(aMode));
+
+exit:
+    return;
+}
+
+void Dso::Connection::HandleDisconnected(DisconnectMode aMode)
+{
+    VerifyOrExit(mState != kStateDisconnected);
+
+    if (mState == kStateConnecting)
+    {
+        mDisconnectReason = kReasonFailedToConnect;
+    }
+    else
+    {
+        switch (aMode)
+        {
+        case kGracefullyClose:
+            mDisconnectReason = kReasonPeerClosed;
+            break;
+
+        case kForciblyAbort:
+            mDisconnectReason = kReasonPeerAborted;
+        }
+    }
+
+    MarkAsDisconnected();
+    SignalAnyStateChange();
+
+exit:
+    return;
+}
+
+void Dso::Connection::MarkAsDisconnected(void)
+{
+    if (IsClient())
+    {
+        IgnoreError(Get<Dso>().mClientConnections.Remove(*this));
+    }
+    else
+    {
+        IgnoreError(Get<Dso>().mServerConnections.Remove(*this));
+    }
+
+    mPendingRequests.Clear();
+    SetState(kStateDisconnected);
+
+    LogInfo("Disconnect reason: %s", DisconnectReasonToString(mDisconnectReason));
+}
+
+void Dso::Connection::MarkSessionEstablished(void)
+{
+    switch (mState)
+    {
+    case kStateConnectedButSessionless:
+    case kStateEstablishingSession:
+    case kStateSessionEstablished:
+        break;
+
+    case kStateDisconnected:
+    case kStateConnecting:
+        OT_ASSERT(false);
+    }
+
+    SetState(kStateSessionEstablished);
+}
+
+Error Dso::Connection::SendRequestMessage(Message &aMessage, MessageId &aMessageId, uint32_t aResponseTimeout)
+{
+    return SendMessage(aMessage, kRequestMessage, aMessageId, Dns::Header::kResponseSuccess, aResponseTimeout);
+}
+
+Error Dso::Connection::SendUnidirectionalMessage(Message &aMessage)
+{
+    MessageId messageId = 0;
+
+    return SendMessage(aMessage, kUnidirectionalMessage, messageId);
+}
+
+Error Dso::Connection::SendResponseMessage(Message &aMessage, MessageId aResponseId)
+{
+    return SendMessage(aMessage, kResponseMessage, aResponseId);
+}
+
+void Dso::Connection::SetLongLivedOperation(bool aLongLivedOperation)
+{
+    VerifyOrExit(mLongLivedOperation != aLongLivedOperation);
+
+    mLongLivedOperation = aLongLivedOperation;
+
+    LogInfo("Long-lived operation %s", mLongLivedOperation ? "started" : "stopped");
+
+    if (!mLongLivedOperation)
+    {
+        TimeMilli now = TimerMilli::GetNow();
+        TimeMilli nextTime;
+
+        nextTime = GetNextFireTime(now);
+
+        if (nextTime != now.GetDistantFuture())
+        {
+            Get<Dso>().mTimer.FireAtIfEarlier(nextTime);
+        }
+    }
+
+exit:
+    return;
+}
+
+Error Dso::Connection::SendRetryDelayMessage(uint32_t aDelay, Dns::Header::Response aResponseCode)
+{
+    Error         error   = kErrorNone;
+    Message *     message = nullptr;
+    RetryDelayTlv retryDelayTlv;
+    MessageId     messageId;
+
+    switch (mState)
+    {
+    case kStateSessionEstablished:
+        OT_ASSERT(IsServer());
+        break;
+
+    case kStateConnectedButSessionless:
+    case kStateEstablishingSession:
+    case kStateDisconnected:
+    case kStateConnecting:
+        OT_ASSERT(false);
+    }
+
+    message = NewMessage();
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
+
+    retryDelayTlv.Init();
+    retryDelayTlv.SetRetryDelay(aDelay);
+    SuccessOrExit(error = message->Append(retryDelayTlv));
+    error = SendMessage(*message, kUnidirectionalMessage, messageId, aResponseCode);
+
+exit:
+    FreeMessageOnError(message, error);
+    return error;
+}
+
+Error Dso::Connection::SetTimeouts(uint32_t aInactivityTimeout, uint32_t aKeepAliveInterval)
+{
+    Error error = kErrorNone;
+
+    VerifyOrExit(aKeepAliveInterval >= kMinKeepAliveInterval, error = kErrorInvalidArgs);
+
+    // If acting as server, the timeout values are the ones we grant
+    // to a connecting clients. If acting as client, the timeout
+    // values are what to request when sending Keep Alive message.
+    // If in `kStateDisconnected` we set both (since we don't know
+    // yet whether we are going to connect as client or server).
+
+    if ((mState == kStateDisconnected) || IsServer())
+    {
+        mKeepAlive.SetInterval(aKeepAliveInterval);
+        AdjustInactivityTimeout(aInactivityTimeout);
+    }
+
+    if ((mState == kStateDisconnected) || IsClient())
+    {
+        mKeepAlive.SetRequestInterval(aKeepAliveInterval);
+        mInactivity.SetRequestInterval(aInactivityTimeout);
+    }
+
+    switch (mState)
+    {
+    case kStateDisconnected:
+    case kStateConnecting:
+        break;
+
+    case kStateConnectedButSessionless:
+    case kStateEstablishingSession:
+        if (IsServer())
+        {
+            break;
+        }
+
+        OT_FALL_THROUGH;
+
+    case kStateSessionEstablished:
+        error = SendKeepAliveMessage();
+    }
+
+exit:
+    return error;
+}
+
+Error Dso::Connection::SendKeepAliveMessage(void)
+{
+    return SendKeepAliveMessage(IsServer() ? kUnidirectionalMessage : kRequestMessage, 0);
+}
+
+Error Dso::Connection::SendKeepAliveMessage(MessageType aMessageType, MessageId aResponseId)
+{
+    // Sends a Keep Alive message of a given type. This is a common
+    // method used by both client and server. `aResponseId` is
+    // applicable and used only when the message type is
+    // `kResponseMessage`.
+
+    Error        error   = kErrorNone;
+    Message *    message = nullptr;
+    KeepAliveTlv keepAliveTlv;
+
+    switch (mState)
+    {
+    case kStateConnectedButSessionless:
+    case kStateEstablishingSession:
+        if (IsServer())
+        {
+            // While session is being established, server is only allowed
+            // to send a Keep Alive response to a request from client.
+            OT_ASSERT(aMessageType == kResponseMessage);
+        }
+        break;
+
+    case kStateSessionEstablished:
+        break;
+
+    case kStateDisconnected:
+    case kStateConnecting:
+        OT_ASSERT(false);
+    }
+
+    // Server can send Keep Alive response (to a request from client)
+    // or a unidirectional Keep Alive message. Client can send
+    // KeepAlive request message.
+
+    if (IsServer())
+    {
+        if (aMessageType == kResponseMessage)
+        {
+            OT_ASSERT(aResponseId != 0);
+        }
+        else
+        {
+            OT_ASSERT(aMessageType == kUnidirectionalMessage);
+        }
+    }
+    else
+    {
+        OT_ASSERT(aMessageType == kRequestMessage);
+    }
+
+    message = NewMessage();
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
+
+    keepAliveTlv.Init();
+
+    if (IsServer())
+    {
+        keepAliveTlv.SetInactivityTimeout(mInactivity.GetInterval());
+        keepAliveTlv.SetKeepAliveInterval(mKeepAlive.GetInterval());
+    }
+    else
+    {
+        keepAliveTlv.SetInactivityTimeout(mInactivity.GetRequestInterval());
+        keepAliveTlv.SetKeepAliveInterval(mKeepAlive.GetRequestInterval());
+    }
+
+    SuccessOrExit(error = message->Append(keepAliveTlv));
+
+    error = SendMessage(*message, aMessageType, aResponseId);
+
+exit:
+    FreeMessageOnError(message, error);
+    return error;
+}
+
+Error Dso::Connection::SendMessage(Message &             aMessage,
+                                   MessageType           aMessageType,
+                                   MessageId &           aMessageId,
+                                   Dns::Header::Response aResponseCode,
+                                   uint32_t              aResponseTimeout)
+{
+    Error       error          = kErrorNone;
+    Tlv::Type   primaryTlvType = Tlv::kReservedType;
+    Dns::Header header;
+
+    switch (mState)
+    {
+    case kStateConnectedButSessionless:
+        // To establish session, client MUST send a request message.
+        // Server is not allowed to send any messages. Unidirectional
+        // messages are not allowed before session is established.
+        OT_ASSERT(IsClient());
+        OT_ASSERT(aMessageType == kRequestMessage);
+        break;
+
+    case kStateEstablishingSession:
+        // During session establishment, client is allowed to send
+        // additional request messages, server is only allowed to
+        // send response.
+        if (IsClient())
+        {
+            OT_ASSERT(aMessageType == kRequestMessage);
+        }
+        else
+        {
+            OT_ASSERT(aMessageType == kResponseMessage);
+        }
+        break;
+
+    case kStateSessionEstablished:
+        // All message types are allowed.
+        break;
+
+    case kStateDisconnected:
+    case kStateConnecting:
+        OT_ASSERT(false);
+    }
+
+    // A DSO request or unidirectional message MUST contain at
+    // least one TLV. The first TLV is the "Primary TLV" and
+    // determines the nature of the operation being performed.
+    // A DSO response message may contain no TLVs, or may contain
+    // one or more TLVs. Response Primary TLV(s) MUST appear first
+    // in a DSO response message.
+
+    aMessage.SetOffset(0);
+    IgnoreError(ReadPrimaryTlv(aMessage, primaryTlvType));
+
+    switch (aMessageType)
+    {
+    case kResponseMessage:
+        break;
+    case kRequestMessage:
+    case kUnidirectionalMessage:
+        OT_ASSERT(primaryTlvType != Tlv::kReservedType);
+    }
+
+    // `header` is cleared from its constructor call so all fields
+    // start as zero.
+
+    switch (aMessageType)
+    {
+    case kRequestMessage:
+        header.SetType(Dns::Header::kTypeQuery);
+        aMessageId = mNextMessageId;
+        break;
+
+    case kResponseMessage:
+        header.SetType(Dns::Header::kTypeResponse);
+        break;
+
+    case kUnidirectionalMessage:
+        header.SetType(Dns::Header::kTypeQuery);
+        aMessageId = 0;
+        break;
+    }
+
+    header.SetMessageId(aMessageId);
+    header.SetQueryType(Dns::Header::kQueryTypeDso);
+    header.SetResponseCode(aResponseCode);
+    SuccessOrExit(error = aMessage.Prepend(header));
+
+    SuccessOrExit(error = AppendPadding(aMessage));
+
+    // Update `mPendingRequests` list with the new request info
+
+    if (aMessageType == kRequestMessage)
+    {
+        SuccessOrExit(
+            error = mPendingRequests.Add(mNextMessageId, primaryTlvType, TimerMilli::GetNow() + aResponseTimeout));
+
+        if (++mNextMessageId == 0)
+        {
+            mNextMessageId = 1;
+        }
+    }
+
+    LogInfo("Sending %s message with id %u to %s", MessageTypeToString(aMessageType), aMessageId,
+            mPeerSockAddr.ToString().AsCString());
+
+    switch (mState)
+    {
+    case kStateConnectedButSessionless:
+        // On client we transition from "connected" state to
+        // "establishing session" state on successfully sending a
+        // request message.
+        if (IsClient())
+        {
+            SetState(kStateEstablishingSession);
+        }
+        break;
+
+    case kStateEstablishingSession:
+        // On server we transition from "establishing session" state
+        // to "established" on sending a response with success
+        // response code.
+        if (IsServer() && (aResponseCode == Dns::Header::kResponseSuccess))
+        {
+            SetState(kStateSessionEstablished);
+        }
+
+    default:
+        break;
+    }
+
+    ResetTimeouts(/* aIsKeepAliveMessage*/ (primaryTlvType == KeepAliveTlv::kType));
+
+    otPlatDsoSend(this, &aMessage);
+
+    // Signal any state changes. This is done at the very end when the
+    // `SendMessage()` is fully processed (all state and local
+    // variables are updated) to ensure that we do not have any
+    // reentrancy issues (e.g., if the callback signalling state
+    // change triggers another tx).
+
+    SignalAnyStateChange();
+
+exit:
+    return error;
+}
+
+Error Dso::Connection::AppendPadding(Message &aMessage)
+{
+    // This method appends Encryption Padding TLV to a DSO message.
+    // It uses the padding policy "Random-Block-Length Padding" from
+    // RFC 8467.
+
+    static const uint16_t kBlockLengths[] = {8, 11, 17, 21};
+
+    Error                error = kErrorNone;
+    uint16_t             blockLength;
+    EncryptionPaddingTlv paddingTlv;
+
+    // We pick a random block length. The random selection can be
+    // based on a "weak" source of randomness (so the use of
+    // `NonCrypto` is fine). We add padding to the message such
+    // that its padded length is a multiple of the chosen block
+    // length.
+
+    blockLength = kBlockLengths[Random::NonCrypto::GetUint8InRange(0, GetArrayLength(kBlockLengths))];
+
+    paddingTlv.Init((blockLength - ((aMessage.GetLength() + sizeof(Tlv)) % blockLength)) % blockLength);
+
+    SuccessOrExit(error = aMessage.Append(paddingTlv));
+
+    for (uint16_t len = paddingTlv.GetLength(); len > 0; len--)
+    {
+        SuccessOrExit(error = aMessage.Append<uint8_t>(0));
+    }
+
+exit:
+    return error;
+}
+
+void Dso::Connection::HandleReceive(Message &aMessage)
+{
+    Error       error          = kErrorAbort;
+    Tlv::Type   primaryTlvType = Tlv::kReservedType;
+    Dns::Header header;
+
+    SuccessOrExit(aMessage.Read(0, header));
+
+    if (header.GetQueryType() != Dns::Header::kQueryTypeDso)
+    {
+        if (header.GetType() == Dns::Header::kTypeQuery)
+        {
+            SendErrorResponse(header, Dns::Header::kResponseNotImplemented);
+            error = kErrorNone;
+        }
+
+        ExitNow();
+    }
+
+    switch (mState)
+    {
+    case kStateConnectedButSessionless:
+        // After connection is established, client should initiate
+        // establishing session (by sending a request). So no rx is
+        // allowed before this. On server, we allow rx of a request
+        // message only.
+        VerifyOrExit(IsServer() && (header.GetType() == Dns::Header::kTypeQuery) && (header.GetMessageId() != 0));
+        break;
+
+    case kStateEstablishingSession:
+        // Unidirectional message are allowed after session is
+        // established. While session is being established, on client,
+        // we allow rx on response message. On server we can rx
+        // request or response.
+
+        VerifyOrExit(header.GetMessageId() != 0);
+
+        if (IsClient())
+        {
+            VerifyOrExit(header.GetType() == Dns::Header::kTypeResponse);
+        }
+        break;
+
+    case kStateSessionEstablished:
+        // All message types are allowed.
+        break;
+
+    case kStateDisconnected:
+    case kStateConnecting:
+        ExitNow();
+    }
+
+    // All count fields MUST be set to zero in the header.
+    VerifyOrExit((header.GetQuestionCount() == 0) && (header.GetAnswerCount() == 0) &&
+                 (header.GetAuthorityRecordCount() == 0) && (header.GetAdditionalRecordCount() == 0));
+
+    aMessage.SetOffset(sizeof(header));
+
+    switch (ReadPrimaryTlv(aMessage, primaryTlvType))
+    {
+    case kErrorNone:
+        VerifyOrExit(primaryTlvType != Tlv::kReservedType);
+        break;
+
+    case kErrorNotFound:
+        // The `primaryTlvType` is set to `Tlv::kReservedType`
+        // (value zero) to indicate that there is no primary TLV.
+        break;
+
+    default:
+        ExitNow();
+    }
+
+    switch (header.GetType())
+    {
+    case Dns::Header::kTypeQuery:
+        error = ProcessRequestOrUnidirectionalMessage(header, aMessage, primaryTlvType);
+        break;
+
+    case Dns::Header::kTypeResponse:
+        error = ProcessResponseMessage(header, aMessage, primaryTlvType);
+        break;
+    }
+
+exit:
+    aMessage.Free();
+
+    if (error == kErrorNone)
+    {
+        ResetTimeouts(/* aIsKeepAliveMessage */ (primaryTlvType == KeepAliveTlv::kType));
+    }
+    else
+    {
+        Disconnect(kForciblyAbort, kReasonPeerMisbehavior);
+    }
+
+    // We signal any state change at the very end when the received
+    // message is fully processed (all state and local variables are
+    // updated) to ensure that we do not have any reentrancy issues
+    // (e.g., if a `Connection` method happens to be called from the
+    // callback).
+
+    SignalAnyStateChange();
+}
+
+Error Dso::Connection::ReadPrimaryTlv(const Message &aMessage, Tlv::Type &aPrimaryTlvType) const
+{
+    // Read and validate the primary TLV (first TLV  after the header).
+    // The `aMessage.GetOffset()` must point to the first TLV. If no
+    // TLV then `kErrorNotFound` is returned. If TLV in message is not
+    // well-formed `kErrorParse` is returned. The read TLV type is
+    // returned in `aPrimaryTlvType` (set to `Tlv::kReservedType`
+    // (value zero) when `kErrorNotFound`).
+
+    Error error = kErrorNotFound;
+    Tlv   tlv;
+
+    aPrimaryTlvType = Tlv::kReservedType;
+
+    SuccessOrExit(aMessage.Read(aMessage.GetOffset(), tlv));
+    VerifyOrExit(aMessage.GetOffset() + tlv.GetSize() <= aMessage.GetLength(), error = kErrorParse);
+    aPrimaryTlvType = tlv.GetType();
+    error           = kErrorNone;
+
+exit:
+    return error;
+}
+
+Error Dso::Connection::ProcessRequestOrUnidirectionalMessage(const Dns::Header &aHeader,
+                                                             const Message &    aMessage,
+                                                             Tlv::Type          aPrimaryTlvType)
+{
+    Error error = kErrorAbort;
+
+    if (IsServer() && (mState == kStateConnectedButSessionless))
+    {
+        SetState(kStateEstablishingSession);
+    }
+
+    // A DSO request or unidirectional message MUST contain at
+    // least one TLV which is the "Primary TLV" and determines
+    // the nature of the operation being performed.
+
+    switch (aPrimaryTlvType)
+    {
+    case KeepAliveTlv::kType:
+        error = ProcessKeepAliveMessage(aHeader, aMessage);
+        break;
+
+    case RetryDelayTlv::kType:
+        error = ProcessRetryDelayMessage(aHeader, aMessage);
+        break;
+
+    case Tlv::kReservedType:
+    case EncryptionPaddingTlv::kType:
+        // Misbehavior by peer.
+        break;
+
+    default:
+        if (aHeader.GetMessageId() == 0)
+        {
+            LogInfo("Received unidirectional message from %s", mPeerSockAddr.ToString().AsCString());
+
+            error = mCallbacks.mProcessUnidirectionalMessage(*this, aMessage, aPrimaryTlvType);
+        }
+        else
+        {
+            MessageId messageId = aHeader.GetMessageId();
+
+            LogInfo("Received request message with id %u from %s", messageId, mPeerSockAddr.ToString().AsCString());
+
+            error = mCallbacks.mProcessRequestMessage(*this, messageId, aMessage, aPrimaryTlvType);
+
+            // `kErrorNotFound` indicates that TLV type is not known.
+
+            if (error == kErrorNotFound)
+            {
+                SendErrorResponse(aHeader, Dns::Header::kDsoTypeNotImplemented);
+                error = kErrorNone;
+            }
+        }
+        break;
+    }
+
+    return error;
+}
+
+Error Dso::Connection::ProcessResponseMessage(const Dns::Header &aHeader,
+                                              const Message &    aMessage,
+                                              Tlv::Type          aPrimaryTlvType)
+{
+    Error     error = kErrorAbort;
+    Tlv::Type requestPrimaryTlvType;
+
+    // If a client or server receives a response where the message
+    // ID is zero, or is any other value that does not match the
+    // message ID of any of its outstanding operations, this is a
+    // fatal error and the recipient MUST forcibly abort the
+    // connection immediately.
+
+    VerifyOrExit(aHeader.GetMessageId() != 0);
+    VerifyOrExit(mPendingRequests.Contains(aHeader.GetMessageId(), requestPrimaryTlvType));
+
+    // If the response has no error and contains a primary TLV, it
+    // MUST match the request primary TLV.
+
+    if ((aHeader.GetResponseCode() == Dns::Header::kResponseSuccess) && (aPrimaryTlvType != Tlv::kReservedType))
+    {
+        VerifyOrExit(aPrimaryTlvType == requestPrimaryTlvType);
+    }
+
+    mPendingRequests.Remove(aHeader.GetMessageId());
+
+    switch (requestPrimaryTlvType)
+    {
+    case KeepAliveTlv::kType:
+        SuccessOrExit(error = ProcessKeepAliveMessage(aHeader, aMessage));
+        break;
+
+    default:
+        SuccessOrExit(error = mCallbacks.mProcessResponseMessage(*this, aHeader, aMessage, aPrimaryTlvType,
+                                                                 requestPrimaryTlvType));
+        break;
+    }
+
+    // DSO session is established when client sends a request message
+    // and receives a response from server with no error code.
+
+    if (IsClient() && (mState == kStateEstablishingSession) &&
+        (aHeader.GetResponseCode() == Dns::Header::kResponseSuccess))
+    {
+        SetState(kStateSessionEstablished);
+    }
+
+exit:
+    return error;
+}
+
+Error Dso::Connection::ProcessKeepAliveMessage(const Dns::Header &aHeader, const Message &aMessage)
+{
+    Error        error  = kErrorAbort;
+    uint16_t     offset = aMessage.GetOffset();
+    Tlv          tlv;
+    KeepAliveTlv keepAliveTlv;
+
+    if (aHeader.GetType() == Dns::Header::kTypeResponse)
+    {
+        // A Keep Alive response message is allowed on a client from a sever.
+
+        VerifyOrExit(IsClient());
+
+        if (aHeader.GetResponseCode() != Dns::Header::kResponseSuccess)
+        {
+            // We got an error response code from server for our
+            // Keep Alive request message. If this happens while
+            // establishing the DSO session, it indicates that server
+            // does not support DSO, so we close the connection. If
+            // this happens while session is already established, it
+            // is a misbehavior (fatal error) by server.
+
+            if (mState == kStateEstablishingSession)
+            {
+                Disconnect(kGracefullyClose, kReasonPeerDoesNotSupportDso);
+                error = kErrorNone;
+            }
+
+            ExitNow();
+        }
+    }
+
+    // Parse and validate the Keep Alive Message
+
+    SuccessOrExit(aMessage.Read(offset, keepAliveTlv));
+    offset += keepAliveTlv.GetSize();
+
+    VerifyOrExit((keepAliveTlv.GetType() == KeepAliveTlv::kType) && keepAliveTlv.IsValid());
+
+    // Keep Alive message MUST contain only one Keep Alive TLV.
+
+    while (offset < aMessage.GetLength())
+    {
+        SuccessOrExit(aMessage.Read(offset, tlv));
+        offset += tlv.GetSize();
+
+        VerifyOrExit((tlv.GetType() != KeepAliveTlv::kType) && (tlv.GetType() != RetryDelayTlv::kType));
+    }
+
+    VerifyOrExit(offset == aMessage.GetLength());
+
+    if (aHeader.GetType() == Dns::Header::kTypeQuery)
+    {
+        if (IsServer())
+        {
+            // Received a Keep Alive message from client. It MUST
+            // be a request message (not unidirectional). We prepare
+            // and send a Keep Alive response.
+
+            VerifyOrExit(aHeader.GetMessageId() != 0);
+
+            LogInfo("Received KeepAlive request message from client %s", mPeerSockAddr.ToString().AsCString());
+
+            IgnoreError(SendKeepAliveMessage(kResponseMessage, aHeader.GetMessageId()));
+            error = kErrorNone;
+            ExitNow();
+        }
+
+        // Received a Keep Alive message on client from server. Server
+        // Keep Alive message MUST be unidirectional (message ID
+        // zero).
+
+        VerifyOrExit(aHeader.GetMessageId() == 0);
+    }
+
+    LogInfo("Received Keep Alive %s message from server %s",
+            (aHeader.GetMessageId() == 0) ? "unidirectional" : "response", mPeerSockAddr.ToString().AsCString());
+
+    // Receiving a Keep Alive interval value from server less than the
+    // minimum (ten seconds) is a fatal error and client MUST then
+    // abort the connection.
+
+    VerifyOrExit(keepAliveTlv.GetKeepAliveInterval() >= kMinKeepAliveInterval);
+
+    // Update the timeout intervals on the connection from
+    // the new values we got from the server. The receive
+    // of the Keep Alive message does not itself reset the
+    // inactivity timer. So we use `AdjustInactivityTimeout`
+    // which takes into account the time elapsed since the
+    // last activity.
+
+    AdjustInactivityTimeout(keepAliveTlv.GetInactivityTimeout());
+    mKeepAlive.SetInterval(keepAliveTlv.GetKeepAliveInterval());
+
+    LogInfo("Timeouts Inactivity:%u, KeepAlive:%u", mInactivity.GetInterval(), mKeepAlive.GetInterval());
+
+    error = kErrorNone;
+
+exit:
+    return error;
+}
+
+Error Dso::Connection::ProcessRetryDelayMessage(const Dns::Header &aHeader, const Message &aMessage)
+
+{
+    Error         error = kErrorAbort;
+    RetryDelayTlv retryDelayTlv;
+
+    // Retry Delay TLV can be used as the Primary TLV only in
+    // a unidirectional message sent from server to client.
+    // It is used by the server to instruct the client to
+    // close the session and its underlying connection, and not
+    // to reconnect for the indicated time interval.
+
+    VerifyOrExit(IsClient() && (aHeader.GetMessageId() == 0));
+
+    SuccessOrExit(aMessage.Read(aMessage.GetOffset(), retryDelayTlv));
+    VerifyOrExit(retryDelayTlv.IsValid());
+
+    mRetryDelayErrorCode = aHeader.GetResponseCode();
+    mRetryDelay          = retryDelayTlv.GetRetryDelay();
+
+    LogInfo("Received Retry Delay message from server %s", mPeerSockAddr.ToString().AsCString());
+    LogInfo("   RetryDelay:%u ms, ResponseCode:%d", mRetryDelay, mRetryDelayErrorCode);
+
+    Disconnect(kGracefullyClose, kReasonServerRetryDelayRequest);
+
+exit:
+    return error;
+}
+
+void Dso::Connection::SendErrorResponse(const Dns::Header &aHeader, Dns::Header::Response aResponseCode)
+{
+    Message *   response = NewMessage();
+    Dns::Header header;
+
+    VerifyOrExit(response != nullptr);
+
+    header.SetMessageId(aHeader.GetMessageId());
+    header.SetType(Dns::Header::kTypeResponse);
+    header.SetQueryType(aHeader.GetQueryType());
+    header.SetResponseCode(aResponseCode);
+
+    SuccessOrExit(response->Prepend(header));
+
+    otPlatDsoSend(this, response);
+    response = nullptr;
+
+exit:
+    FreeMessage(response);
+}
+
+void Dso::Connection::AdjustInactivityTimeout(uint32_t aNewTimeout)
+{
+    // This method sets the inactivity timeout interval to a new value
+    // and updates the expiration time based on the new timeout value.
+    //
+    // On client, it is called on receiving a Keep Alive response or
+    // unidirectional message from server. Note that the receive of
+    // the Keep Alive message does not itself reset the inactivity
+    // timer. So the time elapsed since the last activity should be
+    // taken into account with the new inactivity timeout value.
+    //
+    // On server this method is called from `SetTimeouts()` when a new
+    // inactivity timeout value is set.
+
+    TimeMilli now = TimerMilli::GetNow();
+    TimeMilli start;
+    TimeMilli newExpiration;
+
+    if (mState == kStateDisconnected)
+    {
+        mInactivity.SetInterval(aNewTimeout);
+        ExitNow();
+    }
+
+    VerifyOrExit(aNewTimeout != mInactivity.GetInterval());
+
+    // Calculate the start time (i.e., the last time inactivity timer
+    // was cleared). If the previous inactivity time is set to
+    // `kInfinite` value (`IsUsed()` returns `false`) then
+    // `GetExpirationTime()` returns the start time. Otherwise, we
+    // calculate it going back from the current expiration time with
+    // the current wait interval.
+
+    if (!mInactivity.IsUsed())
+    {
+        start = mInactivity.GetExpirationTime();
+    }
+    else if (IsClient())
+    {
+        start = mInactivity.GetExpirationTime() - mInactivity.GetInterval();
+    }
+    else
+    {
+        start = mInactivity.GetExpirationTime() - CalculateServerInactivityWaitTime();
+    }
+
+    mInactivity.SetInterval(aNewTimeout);
+
+    if (!mInactivity.IsUsed())
+    {
+        newExpiration = start;
+    }
+    else if (IsClient())
+    {
+        newExpiration = start + aNewTimeout;
+
+        if (newExpiration < now)
+        {
+            newExpiration = now;
+        }
+    }
+    else
+    {
+        newExpiration = start + CalculateServerInactivityWaitTime();
+
+        if (newExpiration < now)
+        {
+            // If the server abruptly reduces the inactivity timeout
+            // such that current elapsed time is already more than
+            // twice the new inactivity timeout, then the client is
+            // immediately considered delinquent (server can forcibly
+            // abort the connection). So to give the client time to
+            // close the connection gracefully, the server SHOULD
+            // give the client an additional grace period of either
+            // five seconds or one quarter of the new inactivity
+            // timeout, whichever is greater [RFC 8490 - 7.1.1].
+
+            newExpiration = now + OT_MAX(kMinServerInactivityWaitTime, aNewTimeout / 4);
+        }
+    }
+
+    mInactivity.SetExpirationTime(newExpiration);
+
+exit:
+    return;
+}
+
+uint32_t Dso::Connection::CalculateServerInactivityWaitTime(void) const
+{
+    // A server will abort an idle session after five seconds
+    // (`kMinServerInactivityWaitTime`) or twice the inactivity
+    // timeout value, whichever is greater [RFC 8490 - 6.4.1].
+
+    OT_ASSERT(mInactivity.IsUsed());
+
+    return OT_MAX(mInactivity.GetInterval() * 2, kMinServerInactivityWaitTime);
+}
+
+void Dso::Connection::ResetTimeouts(bool aIsKeepAliveMessage)
+{
+    TimeMilli now = TimerMilli::GetNow();
+    TimeMilli nextTime;
+
+    // At both servers and clients, the generation or reception of any
+    // complete DNS message resets both timers for that DSO
+    // session, with the one exception being that a DSO Keep Alive
+    // message resets only the keep alive timer, not the inactivity
+    // timeout timer [RFC 8490 - 6.3]
+
+    if (mKeepAlive.IsUsed())
+    {
+        // On client, we wait for the Keep Alive interval but on server
+        // we wait for twice the interval before considering Keep Alive
+        // timeout.
+        //
+        // Note that we limit the interval to `Timeout::kMaxInterval`
+        // (which is ~12 days). This max limit ensures that even twice
+        // the interval is less than max OpenThread timer duration so
+        // that the expiration time calculations below stay within the
+        // `TimerMilli` range.
+
+        mKeepAlive.SetExpirationTime(now + mKeepAlive.GetInterval() * (IsServer() ? 2 : 1));
+    }
+
+    if (!aIsKeepAliveMessage)
+    {
+        if (mInactivity.IsUsed())
+        {
+            mInactivity.SetExpirationTime(
+                now + (IsServer() ? CalculateServerInactivityWaitTime() : mInactivity.GetInterval()));
+        }
+        else
+        {
+            // When Inactivity timeout is not used (i.e., interval is set
+            // to the special `kInfinite` value), we still need to track
+            // the time so that if/when later the inactivity interval
+            // gets changed, we can adjust the remaining time correctly
+            // from `AdjustInactivityTimeout()`. In this case, we just
+            // track the current time as "expiration time".
+
+            mInactivity.SetExpirationTime(now);
+        }
+    }
+
+    nextTime = GetNextFireTime(now);
+
+    if (nextTime != now.GetDistantFuture())
+    {
+        Get<Dso>().mTimer.FireAtIfEarlier(nextTime);
+    }
+}
+
+TimeMilli Dso::Connection::GetNextFireTime(TimeMilli aNow) const
+{
+    TimeMilli nextTime = aNow.GetDistantFuture();
+
+    switch (mState)
+    {
+    case kStateDisconnected:
+        break;
+
+    case kStateConnecting:
+        // While in `kStateConnecting`, Keep Alive timer is
+        // used for `kConnectingTimeout`.
+        VerifyOrExit(mKeepAlive.GetExpirationTime() > aNow, nextTime = aNow);
+        nextTime = mKeepAlive.GetExpirationTime();
+        break;
+
+    case kStateConnectedButSessionless:
+    case kStateEstablishingSession:
+    case kStateSessionEstablished:
+        nextTime = OT_MIN(nextTime, mPendingRequests.GetNextFireTime(aNow));
+
+        if (mKeepAlive.IsUsed())
+        {
+            VerifyOrExit(mKeepAlive.GetExpirationTime() > aNow, nextTime = aNow);
+            nextTime = OT_MIN(nextTime, mKeepAlive.GetExpirationTime());
+        }
+
+        if (mInactivity.IsUsed() && mPendingRequests.IsEmpty() && !mLongLivedOperation)
+        {
+            // An operation being active on a DSO Session includes
+            // a request message waiting for a response, or an
+            // active long-lived operation.
+
+            VerifyOrExit(mInactivity.GetExpirationTime() > aNow, nextTime = aNow);
+            nextTime = OT_MIN(nextTime, mInactivity.GetExpirationTime());
+        }
+
+        break;
+    }
+
+exit:
+    return nextTime;
+}
+
+void Dso::Connection::HandleTimer(TimeMilli aNow, TimeMilli &aNextTime)
+{
+    switch (mState)
+    {
+    case kStateDisconnected:
+        break;
+
+    case kStateConnecting:
+        if (mKeepAlive.IsExpired(aNow))
+        {
+            Disconnect(kGracefullyClose, kReasonFailedToConnect);
+        }
+        break;
+
+    case kStateConnectedButSessionless:
+    case kStateEstablishingSession:
+    case kStateSessionEstablished:
+        if (mPendingRequests.HasAnyTimedOut(aNow))
+        {
+            // If server sends no response to a request, client
+            // waits for 30 seconds (`kResponseTimeout`) after which
+            // client MUST forcibly abort the connection.
+            Disconnect(kForciblyAbort, kReasonResponseTimeout);
+            ExitNow();
+        }
+
+        // The inactivity timer is kept clear, while an operation is
+        // active on the session (which includes a request waiting for
+        // response or an active long-lived operation).
+
+        if (mInactivity.IsUsed() && mPendingRequests.IsEmpty() && !mLongLivedOperation && mInactivity.IsExpired(aNow))
+        {
+            // On client, if the inactivity timeout is reached, the
+            // connection is closed gracefully. On server, if too much
+            // time (`CalculateServerInactivityWaitTime()`, i.e., five
+            // seconds or twice the current inactivity timeout interval,
+            // whichever is grater) elapses server MUST consider the
+            // client delinquent and MUST forcibly abort the connection.
+
+            Disconnect(IsClient() ? kGracefullyClose : kForciblyAbort, kReasonInactivityTimeout);
+            ExitNow();
+        }
+
+        if (mKeepAlive.IsUsed() && mKeepAlive.IsExpired(aNow))
+        {
+            // On client, if the Keep Alive interval elapses without any
+            // DNS messages being sent or received, the client MUST take
+            // action and send a DSO Keep Alive message.
+            //
+            // On server, if twice the Keep Alive interval value elapses
+            // without any messages being sent or received, the server
+            // considers the client delinquent and aborts the connection.
+
+            if (IsClient())
+            {
+                IgnoreError(SendKeepAliveMessage());
+            }
+            else
+            {
+                Disconnect(kForciblyAbort, kReasonKeepAliveTimeout);
+                ExitNow();
+            }
+        }
+        break;
+    }
+
+exit:
+    aNextTime = OT_MIN(aNextTime, GetNextFireTime(aNow));
+    SignalAnyStateChange();
+}
+
+const char *Dso::Connection::StateToString(State aState)
+{
+    static const char *const kStateStrings[] = {
+        "Disconnected",            // (0) kStateDisconnected,
+        "Connecting",              // (1) kStateConnecting,
+        "ConnectedButSessionless", // (2) kStateConnectedButSessionless,
+        "EstablishingSession",     // (3) kStateEstablishingSession,
+        "SessionEstablished",      // (4) kStateSessionEstablished,
+    };
+
+    static_assert(0 == kStateDisconnected, "kStateDisconnected value is incorrect");
+    static_assert(1 == kStateConnecting, "kStateConnecting value is incorrect");
+    static_assert(2 == kStateConnectedButSessionless, "kStateConnectedButSessionless value is incorrect");
+    static_assert(3 == kStateEstablishingSession, "kStateEstablishingSession value is incorrect");
+    static_assert(4 == kStateSessionEstablished, "kStateSessionEstablished value is incorrect");
+
+    return kStateStrings[aState];
+}
+
+const char *Dso::Connection::MessageTypeToString(MessageType aMessageType)
+{
+    static const char *const kMessageTypeStrings[] = {
+        "Request",        // (0) kRequestMessage
+        "Response",       // (1) kResponseMessage
+        "Unidirectional", // (2) kUnidirectionalMessage
+    };
+
+    static_assert(0 == kRequestMessage, "kRequestMessage value is incorrect");
+    static_assert(1 == kResponseMessage, "kResponseMessage value is incorrect");
+    static_assert(2 == kUnidirectionalMessage, "kUnidirectionalMessage value is incorrect");
+
+    return kMessageTypeStrings[aMessageType];
+}
+
+const char *Dso::Connection::DisconnectReasonToString(DisconnectReason aReason)
+{
+    static const char *const kDisconnectReasonStrings[] = {
+        "FailedToConnect",         // (0) kReasonFailedToConnect
+        "ResponseTimeout",         // (1) kReasonResponseTimeout
+        "PeerDoesNotSupportDso",   // (2) kReasonPeerDoesNotSupportDso
+        "PeerClosed",              // (3) kReasonPeerClosed
+        "PeerAborted",             // (4) kReasonPeerAborted
+        "InactivityTimeout",       // (5) kReasonInactivityTimeout
+        "KeepAliveTimeout",        // (6) kReasonKeepAliveTimeout
+        "ServerRetryDelayRequest", // (7) kReasonServerRetryDelayRequest
+        "PeerMisbehavior",         // (8) kReasonPeerMisbehavior
+        "Unknown",                 // (9) kReasonUnknown
+    };
+
+    static_assert(0 == kReasonFailedToConnect, "kReasonFailedToConnect value is incorrect");
+    static_assert(1 == kReasonResponseTimeout, "kReasonResponseTimeout value is incorrect");
+    static_assert(2 == kReasonPeerDoesNotSupportDso, "kReasonPeerDoesNotSupportDso value is incorrect");
+    static_assert(3 == kReasonPeerClosed, "kReasonPeerClosed value is incorrect");
+    static_assert(4 == kReasonPeerAborted, "kReasonPeerAborted value is incorrect");
+    static_assert(5 == kReasonInactivityTimeout, "kReasonInactivityTimeout value is incorrect");
+    static_assert(6 == kReasonKeepAliveTimeout, "kReasonKeepAliveTimeout value is incorrect");
+    static_assert(7 == kReasonServerRetryDelayRequest, "kReasonServerRetryDelayRequest value is incorrect");
+    static_assert(8 == kReasonPeerMisbehavior, "kReasonPeerMisbehavior value is incorrect");
+    static_assert(9 == kReasonUnknown, "kReasonUnknown value is incorrect");
+
+    return kDisconnectReasonStrings[aReason];
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+// Dso::Connection::PendingRequests
+
+bool Dso::Connection::PendingRequests::Contains(MessageId aMessageId, Tlv::Type &aPrimaryTlvType) const
+{
+    bool         contains = true;
+    const Entry *entry    = mRequests.FindMatching(aMessageId);
+
+    VerifyOrExit(entry != nullptr, contains = false);
+    aPrimaryTlvType = entry->mPrimaryTlvType;
+
+exit:
+    return contains;
+}
+
+Error Dso::Connection::PendingRequests::Add(MessageId aMessageId, Tlv::Type aPrimaryTlvType, TimeMilli aResponseTimeout)
+{
+    Error  error = kErrorNone;
+    Entry *entry = mRequests.PushBack();
+
+    VerifyOrExit(entry != nullptr, error = kErrorNoBufs);
+    entry->mMessageId      = aMessageId;
+    entry->mPrimaryTlvType = aPrimaryTlvType;
+    entry->mTimeout        = aResponseTimeout;
+
+exit:
+    return error;
+}
+
+void Dso::Connection::PendingRequests::Remove(MessageId aMessageId)
+{
+    mRequests.RemoveMatching(aMessageId);
+}
+
+bool Dso::Connection::PendingRequests::HasAnyTimedOut(TimeMilli aNow) const
+{
+    bool timedOut = false;
+
+    for (const Entry &entry : mRequests)
+    {
+        if (entry.mTimeout <= aNow)
+        {
+            timedOut = true;
+            break;
+        }
+    }
+
+    return timedOut;
+}
+
+TimeMilli Dso::Connection::PendingRequests::GetNextFireTime(TimeMilli aNow) const
+{
+    TimeMilli nextTime = aNow.GetDistantFuture();
+
+    for (const Entry &entry : mRequests)
+    {
+        VerifyOrExit(entry.mTimeout > aNow, nextTime = aNow);
+        nextTime = OT_MIN(entry.mTimeout, nextTime);
+    }
+
+exit:
+    return nextTime;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+// Dso
+
+Dso::Dso(Instance &aInstance)
+    : InstanceLocator(aInstance)
+    , mAcceptHandler(nullptr)
+    , mTimer(aInstance, HandleTimer)
+{
+}
+
+void Dso::StartListening(AcceptHandler aAcceptHandler)
+{
+    mAcceptHandler = aAcceptHandler;
+    otPlatDsoEnableListening(&GetInstance(), true);
+}
+
+void Dso::StopListening(void)
+{
+    otPlatDsoEnableListening(&GetInstance(), false);
+}
+
+Dso::Connection *Dso::FindClientConnection(const Ip6::SockAddr &aPeerSockAddr)
+{
+    return mClientConnections.FindMatching(aPeerSockAddr);
+}
+
+Dso::Connection *Dso::FindServerConnection(const Ip6::SockAddr &aPeerSockAddr)
+{
+    return mServerConnections.FindMatching(aPeerSockAddr);
+}
+
+Dso::Connection *Dso::AcceptConnection(const Ip6::SockAddr &aPeerSockAddr)
+{
+    Connection *connection = nullptr;
+
+    VerifyOrExit(mAcceptHandler != nullptr);
+    connection = mAcceptHandler(GetInstance(), aPeerSockAddr);
+
+    VerifyOrExit(connection != nullptr);
+    connection->Accept();
+
+exit:
+    return connection;
+}
+
+void Dso::HandleTimer(Timer &aTimer)
+{
+    aTimer.Get<Dso>().HandleTimer();
+}
+
+void Dso::HandleTimer(void)
+{
+    TimeMilli   now      = TimerMilli::GetNow();
+    TimeMilli   nextTime = now.GetDistantFuture();
+    Connection *conn;
+    Connection *next;
+
+    for (conn = mClientConnections.GetHead(); conn != nullptr; conn = next)
+    {
+        next = conn->GetNext();
+        conn->HandleTimer(now, nextTime);
+    }
+
+    for (conn = mServerConnections.GetHead(); conn != nullptr; conn = next)
+    {
+        next = conn->GetNext();
+        conn->HandleTimer(now, nextTime);
+    }
+
+    if (nextTime != now.GetDistantFuture())
+    {
+        mTimer.FireAtIfEarlier(nextTime);
+    }
+}
+
+} // namespace Dns
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_DNS_DSO_ENABLE
diff --git a/src/core/net/dns_dso.hpp b/src/core/net/dns_dso.hpp
new file mode 100644
index 0000000..d9ff458
--- /dev/null
+++ b/src/core/net/dns_dso.hpp
@@ -0,0 +1,973 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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 DNS_DSO_HPP_
+#define DNS_DSO_HPP_
+
+#include "openthread-core-config.h"
+
+#if OPENTHREAD_CONFIG_DNS_DSO_ENABLE
+
+#include <openthread/platform/dso_transport.h>
+
+#include "common/array.hpp"
+#include "common/as_core_type.hpp"
+#include "common/const_cast.hpp"
+#include "common/encoding.hpp"
+#include "common/linked_list.hpp"
+#include "common/locator.hpp"
+#include "common/message.hpp"
+#include "common/non_copyable.hpp"
+#include "common/timer.hpp"
+#include "net/dns_types.hpp"
+#include "net/socket.hpp"
+
+/**
+ * @file
+ *   This file includes definitions for the DNS Stateful Operations (DSO) per RFC-8490.
+ */
+
+struct otPlatDsoConnection
+{
+};
+
+namespace ot {
+namespace Dns {
+
+using ot::Encoding::BigEndian::HostSwap16;
+using ot::Encoding::BigEndian::HostSwap32;
+
+extern "C" otPlatDsoConnection *otPlatDsoAccept(otInstance *aInstance, const otSockAddr *aPeerSockAddr);
+
+extern "C" void otPlatDsoHandleConnected(otPlatDsoConnection *aConnection);
+extern "C" void otPlatDsoHandleReceive(otPlatDsoConnection *aConnection, otMessage *aMessage);
+extern "C" void otPlatDsoHandleDisconnected(otPlatDsoConnection *aConnection, otPlatDsoDisconnectMode aMode);
+
+/**
+ * This class implements DNS Stateful Operations (DSO).
+ *
+ */
+class Dso : public InstanceLocator, private NonCopyable
+{
+    friend otPlatDsoConnection *otPlatDsoAccept(otInstance *aInstance, const otSockAddr *aPeerSockAddr);
+
+public:
+    /**
+     * Infinite Keep Alive or Inactivity timeout value.
+     *
+     * This value can be used for either Keep Alive or Inactivity timeout interval. It practically disables the
+     * timeout.
+     *
+     */
+    static constexpr uint32_t kInfiniteTimeout = 0xffffffff;
+
+    /**
+     * Default Keep Alive or Inactivity timeout value (in msec).
+     *
+     * On a new DSO session, if no explicit DSO Keep Alive message exchange has taken place, the default value for both
+     * timeouts is 15 seconds [RFC 8490 - 6.2].
+     *
+     */
+    static constexpr uint32_t kDefaultTimeout = TimeMilli::SecToMsec(15);
+
+    /**
+     * The minimum allowed Keep Alive interval (in msec).
+     *
+     * Any value less than ten seconds is invalid [RFC 8490 - 6.5.2].
+     *
+     */
+    static constexpr uint32_t kMinKeepAliveInterval = TimeMilli::SecToMsec(10);
+
+    /**
+     * The maximum wait time for a DSO response to a DSO request (in msec).
+     *
+     */
+    static constexpr uint32_t kResponseTimeout = OPENTHREAD_CONFIG_DNS_DSO_RESPONSE_TIMEOUT;
+
+    /**
+     * The maximum wait time for a connection to be established (in msec).
+     *
+     */
+    static constexpr uint32_t kConnectingTimeout = OPENTHREAD_CONFIG_DNS_DSO_CONNECTING_TIMEOUT;
+
+    /**
+     * The minimum Inactivity wait time on a server before closing a connection.
+     *
+     * A server will abort an idle session after five seconds or twice the inactivity timeout value, whichever is
+     * greater [RFC 8490 - 6.4.1].
+     *
+     */
+    static constexpr uint32_t kMinServerInactivityWaitTime = TimeMilli::SecToMsec(5);
+
+    /**
+     * This class represents a DSO TLV.
+     *
+     */
+    OT_TOOL_PACKED_BEGIN
+    class Tlv
+    {
+    public:
+        typedef uint16_t Type; ///< DSO TLV type.
+
+        static constexpr Type kReservedType          = 0; ///< Reserved TLV type.
+        static constexpr Type kKeepAliveType         = 1; ///< Keep Alive TLV type.
+        static constexpr Type kRetryDelayType        = 2; ///< Retry Delay TLV type.
+        static constexpr Type kEncryptionPaddingType = 3; ///< Encryption Padding TLV type.
+
+        /**
+         * This method initializes the `Tlv` instance with a given type and length.
+         *
+         * @param[in] aType    The TLV type.
+         * @param[in] aLength  The TLV length.
+         *
+         */
+        void Init(Type aType, uint16_t aLength)
+        {
+            mType   = HostSwap16(aType);
+            mLength = HostSwap16(aLength);
+        }
+
+        /**
+         * This method gets the TLV type.
+         *
+         * @returns The TLV type.
+         *
+         */
+        Type GetType(void) const { return HostSwap16(mType); }
+
+        /**
+         * This method gets the TLV length.
+         *
+         * @returns The TLV length (in bytes).
+         *
+         */
+        uint16_t GetLength(void) const { return HostSwap16(mLength); }
+
+        /**
+         * This method returns the total size of the TLV (including the type and length fields).
+         *
+         * @returns The total size (number of bytes) of the TLV.
+         *
+         */
+        uint32_t GetSize(void) const { return sizeof(Tlv) + static_cast<uint32_t>(GetLength()); }
+
+    private:
+        Type     mType;
+        uint16_t mLength;
+    } OT_TOOL_PACKED_END;
+
+    /**
+     * This class represents a DSO connection to a peer.
+     *
+     */
+    class Connection : public otPlatDsoConnection,
+                       public InstanceLocator,
+                       public LinkedListEntry<Connection>,
+                       private NonCopyable
+    {
+        friend class Dso;
+        friend class LinkedList<Connection>;
+        friend class LinkedListEntry<Connection>;
+        friend void otPlatDsoHandleConnected(otPlatDsoConnection *aConnection);
+        friend void otPlatDsoHandleReceive(otPlatDsoConnection *aConnection, otMessage *aMessage);
+        friend void otPlatDsoHandleDisconnected(otPlatDsoConnection *aConnection, otPlatDsoDisconnectMode aMode);
+
+    public:
+        typedef uint16_t MessageId; ///< This type represents a DSO Message Identifier.
+
+        /**
+         * This enumeration defines the `Connection` states.
+         *
+         */
+        enum State : uint8_t
+        {
+            kStateDisconnected,            ///< Disconnected.
+            kStateConnecting,              ///< Connecting to peer.
+            kStateConnectedButSessionless, ///< Connected but DSO session is not yet established.
+            kStateEstablishingSession,     ///< Establishing DSO session.
+            kStateSessionEstablished,      ///< DSO session is established.
+        };
+
+        /**
+         * This enumeration defines the disconnect modes.
+         *
+         */
+        enum DisconnectMode : uint8_t
+        {
+            kGracefullyClose = OT_PLAT_DSO_DISCONNECT_MODE_GRACEFULLY_CLOSE, ///< Close the connection gracefully.
+            kForciblyAbort   = OT_PLAT_DSO_DISCONNECT_MODE_FORCIBLY_ABORT,   ///< Forcibly abort the connection.
+        };
+
+        /**
+         * This enumeration defines the disconnect reason.
+         *
+         */
+        enum DisconnectReason : uint8_t
+        {
+            kReasonFailedToConnect,         ///< Failed to connect (e.g., peer did not accept or timed out).
+            kReasonResponseTimeout,         ///< Response timeout (no response from peer after `kResponseTimeout`).
+            kReasonPeerDoesNotSupportDso,   ///< Peer does not support DSO.
+            kReasonPeerClosed,              ///< Peer closed the connection gracefully.
+            kReasonPeerAborted,             ///< Peer forcibly aborted the connection.
+            kReasonInactivityTimeout,       ///< Connection closed or aborted due to Inactivity timeout.
+            kReasonKeepAliveTimeout,        ///< Connection closed due to Keep Alive timeout.
+            kReasonServerRetryDelayRequest, ///< Connection closed due to server requesting retry delay.
+            kReasonPeerMisbehavior,         ///< Aborted due to peer misbehavior (fatal error).
+            kReasonUnknown,                 ///< Unknown reason.
+        };
+
+        /**
+         * This class defines the callback functions used by a `Connection`.
+         *
+         */
+        class Callbacks
+        {
+            friend class Connection;
+
+        public:
+            /**
+             * This callback signals that the connection is established (entering `kStateConnectedButSessionless`).
+             *
+             * On a client, this callback can be used to send the first DSO request to start establishing the session.
+             *
+             * @param[in] aConnection   A reference to the connection.
+             *
+             */
+            typedef void (&HandleConnected)(Connection &aConnection);
+
+            /**
+             * This callback signals that the DSO session is established (entering `kStateSessionEstablished`).
+             *
+             * @param[in] aConnection   A reference to the connection.
+             *
+             */
+            typedef void (&HandleSessionEstablished)(Connection &aConnection);
+
+            /**
+             * This callback signals that the DSO session is disconnected by DSO module or the peer.
+             *
+             * After this callback is invoked the DSO module will no longer track the related `Connection` instance. It
+             * can be reclaimed by the caller, e.g., freed if it was heap allocated.
+             *
+             * The `Connection::GetDisconnectReason()` can be used the get the disconnect reason.
+             *
+             * @param[in] aConnection   A reference to the connection.
+             *
+             */
+            typedef void (&HandleDisconnected)(Connection &aConnection);
+
+            /**
+             * This callback requests processing of a received DSO request message.
+             *
+             * If the processing is successful a response can be sent using `Connection::SendResponseMessage()` method.
+             *
+             * Note that @p aMessage is a `const` so the ownership of the message is not passed in this callback.
+             * The message will be freed by the `Connection` after returning from this callback, so if it needs to be
+             * persisted the callback implementation needs to create its own copy.
+             *
+             * The offset in @p aMessage is set to point to the start of the DSO TLVs. DSO module only reads and
+             * validates the first TLV (primary TLV) from the message. It is up to the callback implementation to parse
+             * and validate the rest of the TLVs in the message.
+             *
+             * @param[in] aConnection      A reference to the connection.
+             * @param[in] aMessageId       The message ID of the received request.
+             * @param[in] aMessage         The received message. Message offset is set to the start of the TLVs.
+             * @param[in] aPrimaryTlvType  The primary TLV type.
+             *
+             * @retval kErrorSuccess   The request message was processed successfully.
+             * @retval kErrorNotFound  The @p aPrimaryTlvType is not known (not supported). This error triggers a DNS
+             *                         response with error code 11 "DSO TLV TYPE not implemented" to be sent.
+             * @retval kErrorAbort     Fatal error (misbehavior by peer). This triggers aborting of the connection.
+             *
+             */
+            typedef Error (&ProcessRequestMessage)(Connection &   aConnection,
+                                                   MessageId      aMessageId,
+                                                   const Message &aMessage,
+                                                   Tlv::Type      aPrimaryTlvType);
+
+            /**
+             * This callback requests processing of a received DSO unidirectional message.
+             *
+             * Similar to `ProcessRequestMessage()` the ownership of @p aMessage is not passed in this callback.
+             *
+             * The offset in @p aMessage is set to point to the start of the DSO TLVs. DSO module only reads and
+             * validates the first TLV (primary TLV) from the message. It is up to the callback implementation to parse
+             * and validate the rest of the TLVs in the message.
+             *
+             * @param[in] aConnection      A reference to the connection.
+             * @param[in] aMessage         The received message. Message offset is set to the start of the TLVs.
+             * @param[in] aPrimaryTlvType  The primary TLV type.
+             *
+             * @retval kErrorSuccess  The unidirectional message was processed successfully.
+             * @retval kErrorAbort    Fatal error (misbehavior by peer). This triggers aborting of the connection. If
+             *                        @p aPrimaryTlvType is not known in a unidirectional message, it is a fatal error.
+             *
+             */
+            typedef Error (&ProcessUnidirectionalMessage)(Connection &   aConnection,
+                                                          const Message &aMessage,
+                                                          Tlv::Type      aPrimaryTlvType);
+
+            /**
+             * This callback requests processing of a received DSO response message.
+             *
+             * Before invoking this callback, the `Connection` implementation already verifies that:
+             *
+             *  (1) this response is for a pending previously sent request (based on the message ID),
+             *  (2) if no error response code in DNS @p aHeader and the response contains a response primary TLV, the
+             *      the response primary TLV matches the request primary TLV.
+             *
+             * Similar to `ProcessRequestMessage()` the ownership of @p aMessage is not passed in this callback.
+             *
+             * The offset in @p aMessage is set to point to the start of the DSO TLVs. DSO module only reads and
+             * validates the first TLV (primary TLV) from the message. It is up to the callback implementation to parse
+             * and validate the rest of the TLVs in the message.
+             *
+             * @param[in] aConnection        A reference to the connection.
+             * @param[in] aHeader            The DNS header of the received response.
+             * @param[in] aMessage           The received message. Message offset is set to the start of the TLVs.
+             * @param[in] aResponseTlvType   The primary TLV type in the response message, or `Tlv::kReservedType` if
+             *                               the response contains no TLV.
+             * @param[in] aRequestTlvType    The primary TLV type of the corresponding request message.
+             *
+             * @retval kErrorSuccess  The message was processed successfully.
+             * @retval kErrorAbort    Fatal error (misbehavior by peer). This triggers aborting of the connection.
+             *
+             */
+            typedef Error (&ProcessResponseMessage)(Connection &       aConnection,
+                                                    const Dns::Header &aHeader,
+                                                    const Message &    aMessage,
+                                                    Tlv::Type          aResponseTlvType,
+                                                    Tlv::Type          aRequestTlvType);
+            /**
+             * This constructor initializes a `Callbacks` object setting all the callback functions.
+             *
+             * @param[in] aHandleConnected               The `HandleConnected` callback.
+             * @param[in] aHandleSessionEstablished      The `HandleSessionEstablished` callback.
+             * @param[in] aHandleDisconnected            The `HandleDisconnected` callback.
+             * @param[in] aProcessRequestMessage         The `ProcessRequestMessage` callback.
+             * @param[in] aProcessUnidirectionalMessage  The `ProcessUnidirectionalMessage` callback.
+             * @param[in] aProcessResponseMessage        The `ProcessResponseMessage` callback.
+             *
+             */
+            Callbacks(HandleConnected              aHandleConnected,
+                      HandleSessionEstablished     aHandleSessionEstablished,
+                      HandleDisconnected           aHandleDisconnected,
+                      ProcessRequestMessage        aProcessRequestMessage,
+                      ProcessUnidirectionalMessage aProcessUnidirectionalMessage,
+                      ProcessResponseMessage       aProcessResponseMessage)
+                : mHandleConnected(aHandleConnected)
+                , mHandleSessionEstablished(aHandleSessionEstablished)
+                , mHandleDisconnected(aHandleDisconnected)
+                , mProcessRequestMessage(aProcessRequestMessage)
+                , mProcessUnidirectionalMessage(aProcessUnidirectionalMessage)
+                , mProcessResponseMessage(aProcessResponseMessage)
+            {
+            }
+
+        private:
+            HandleConnected              mHandleConnected;
+            HandleSessionEstablished     mHandleSessionEstablished;
+            HandleDisconnected           mHandleDisconnected;
+            ProcessRequestMessage        mProcessRequestMessage;
+            ProcessUnidirectionalMessage mProcessUnidirectionalMessage;
+            ProcessResponseMessage       mProcessResponseMessage;
+        };
+
+        /**
+         * This constructor initializes a `Connection` instance.
+         *
+         * The `kDefaultTimeout` will be used for @p aInactivityTimeout and @p aKeepAliveInterval. The
+         * @p aKeepAliveInterval MUST NOT be less than `kMinKeepAliveInterval`.
+         *
+         * @param[in] aInstance           The OpenThread instance.
+         * @param[in] aPeerSockAddr       The peer socket address.
+         * @param[in] aCallbacks          A reference to the `Callbacks` instance used by the `Connection`.
+         * @param[in] aInactivityTimeout  The Inactivity timeout interval (in msec).
+         * @param[in] aKeepAliveInterval  The Keep Alive timeout interval (in msec).
+         *
+         */
+        Connection(Instance &           aInstance,
+                   const Ip6::SockAddr &aPeerSockAddr,
+                   Callbacks &          aCallbacks,
+                   uint32_t             aInactivityTimeout = kDefaultTimeout,
+                   uint32_t             aKeepAliveInterval = kDefaultTimeout);
+
+        /**
+         * This method gets the current state of the `Connection`.
+         *
+         * @returns The `Connection` state.
+         *
+         */
+        State GetState(void) const { return mState; }
+
+        /**
+         * This method returns the `Connection` peer socket address.
+         *
+         * @returns The peer socket address.
+         *
+         */
+        const Ip6::SockAddr &GetPeerSockAddr(void) const { return mPeerSockAddr; }
+
+        /**
+         * This method indicates whether or not the device is acting as a DSO server on this `Connection`.
+         *
+         * Server is the software entity with a listening socket, awaiting incoming connection requests.
+         *
+         * @retval TRUE    Device is acting as a server on this connection.
+         * @retval FALSE   Device is acting as a client on this connection.
+         *
+         */
+        bool IsServer(void) const { return mIsServer; }
+
+        /**
+         * This method indicates whether or not the device is acting as a DSO client on this `Connection`.
+         *
+         * Client is the software entity that initiates a connection to the server's listening socket.
+         *
+         * @retval TRUE    Device is acting as a client on this connection.
+         * @retval FALSE   Device is acting as a server on this connection.
+         *
+         */
+        bool IsClient(void) const { return !mIsServer; }
+
+        /**
+         * This method allocates a new DSO message.
+         *
+         * @returns A pointer to the allocated message or `nullptr` if out of message buffers.
+         *
+         */
+        Message *NewMessage(void);
+
+        /**
+         * This method requests the device to initiate a connection (connect as a client) to the peer (acting as a
+         * server).
+         *
+         * This method MUST be called when `Connection` is `kStateDisconnected` state.
+         *
+         * After calling `Connect()`, either
+         * - `Callbacks::HandleConnected()` is invoked when connection is successfully established, or
+         * - `Callbacks::HandleDisconnected()` is invoked if the connection cannot be established (e.g., peer does not
+         *   accept it or we time out waiting for it). The disconnect reason is set to `kReasonFailedToConnect`.
+         *
+         * Calling `Connect()` passes the control and ownership of the `Connection` instance to the DSO module (which
+         * adds the `Connection` into a list of client connections - see `Dso::FindClientConnection()`). The ownership
+         * is passed back to the caller when the `Connection` gets disconnected, i.e., when either
+         *  - the user requests a disconnect by an explicit call to `Disconnect()` method, or,
+         *  - when `HandleDisconnected()` callback is invoked (after its is closed by DSO module itself or by peer).
+         *
+         */
+        void Connect(void);
+
+        /**
+         * This method requests the connection to be disconnected.
+         *
+         * Note that calling `Disconnect()` does not trigger the `Callbacks::HandleDisconnected()` to be invoked (as
+         * this callback is used when DSO module itself or the peer disconnects the connections).
+         *
+         * After the call to `Disconnect()` the caller can take back ownership of the `Connection` (e.g., can free the
+         * `Connection` instance if it was heap allocated).
+         *
+         * @param[in] aMode    Determines whether to close the connection gracefully or forcibly abort the connection.
+         * @param[in] aReason  The disconnect reason.
+         *
+         */
+        void Disconnect(DisconnectMode aMode, DisconnectReason aReason);
+
+        /**
+         * This method returns the last disconnect reason.
+         *
+         * @returns The last disconnect reason.
+         *
+         */
+        DisconnectReason GetDisconnectReason(void) const { return mDisconnectReason; }
+
+        /**
+         * This method implicitly marks the DSO session as established (set state to `kStateSessionEstablished`).
+         *
+         * This method MUST be called when `Connection is in `kStateConnectedButSessionless` state.
+         *
+         * The DSO module itself will mark the session as established after the first successful DSO message exchange
+         * (sending a request message from client and receiving a response from server).
+         *
+         * This method is intended for implicit DSO session establishment where it may be known in advance by some
+         * external means that both client and server support DSO and then the session may be established as soon as
+         * the connection is established.
+         *
+         */
+        void MarkSessionEstablished(void);
+
+        /**
+         * This method sends a DSO request message.
+         *
+         * This method MUST be called when `Connection` is in certain states depending on whether it is acting as a
+         * client or server:
+         * - On client, a request message can be sent after connection is established (`kStateConnectedButSessionless`).
+         *   The first request is used to establish the DSO session. While in `kStateEstablishingSession` or
+         *   `kStateSessionEstablished` other DSO request messages can be sent to the server.
+         * - On server, a request can be sent only after DSO session is established (`kStateSessionEstablished`).
+         *
+         * The prepared message needs to contain the DSO TLVs. The DNS header will be added by the DSO module itself.
+         * Also there is no need to append the "Encryption Padding TLV" to the message as it will be added by the DSO
+         * module before sending the message to the transport layer.
+         *
+         * On success (when this method returns `kErrorNone`) it takes the ownership of the @p aMessage. On failure the
+         * caller still owns the message and may need to free it.
+         *
+         * @param[in]  aMessage          The DSO request message to send.
+         * @param[out] aMessageId        A reference to output the message ID used for the transmission (may be used by
+         *                               the caller to track the response from `Callbacks::ProcessResponseMessage()`).
+         * @param[in]  aResponseTimeout  The response timeout in msec (default value is `kResponseTimeout`)
+         *
+         * @retval  kErrorNone      Successfully sent the DSO request message and updated @p aMessageId.
+         * @retval  kErrorNoBufs    Failed to allocate new buffer to prepare the message (append header or padding).
+         *
+         */
+        Error SendRequestMessage(Message &  aMessage,
+                                 MessageId &aMessageId,
+                                 uint32_t   aResponseTimeout = kResponseTimeout);
+
+        /**
+         * This method sends a DSO unidirectional message.
+         *
+         * This method MUST be called when session is established (in `kStateSessionEstablished` state).
+         *
+         * Similar to `SendRequestMessage()` method, only TLV(s) need to be included in the message. The DNS header and
+         * Encryption Padding TLV will be added by the DSO module.
+         *
+         * On success (when this method returns `kErrorNone`) it takes the ownership of the @p aMessage. On failure the
+         * caller still owns the message and may need to free it.
+         *
+         * @param[in] aMessage      The DSO unidirectional message to send.
+         *
+         * @retval  kErrorNone      Successfully sent the DSO message.
+         * @retval  kErrorNoBufs    Failed to allocate new buffer to prepare the message (append header or padding).
+         *
+         */
+        Error SendUnidirectionalMessage(Message &aMessage);
+
+        /**
+         * This method sends a DSO response message for a received request message.
+         *
+         * Similar to `SendRequestMessage()` method, only TLV(s) need to be included in the message. The DNS header and
+         * Encryption Padding TLV will be added by DSO module.
+         *
+         * On success (when this method returns `kErrorNone`) it takes the ownership of the @p aMessage. On failure the
+         * caller still owns the message and may need to free it.
+         *
+         * @param[in] aMessage      The DSO response message to send.
+         * @param[in] aResponseId   The message ID to use for the response.
+         *
+         * @retval  kErrorNone      Successfully sent the DSO response message.
+         * @retval  kErrorNoBufs    Failed to allocate new buffer to prepare the message (append header or padding).
+         *
+         */
+        Error SendResponseMessage(Message &aMessage, MessageId aResponseId);
+
+        /**
+         * This method returns the Keep Alive timeout interval (in msec).
+         *
+         * On client, this indicates the value granted by server, on server the value to grant.
+         *
+         * @returns The keep alive timeout interval (in msec).
+         *
+         */
+        uint32_t GetKeepAliveInterval(void) const { return mKeepAlive.GetInterval(); }
+
+        /**
+         * This method returns the Inactivity timeout interval (in msec).
+         *
+         * On client, this indicates the value granted by server, on server the value to grant.
+         *
+         * @returns The inactivity timeout interval (in msec).
+         *
+         */
+        uint32_t GetInactivityTimeout(void) const { return mInactivity.GetInterval(); }
+
+        /**
+         * This method sends a Keep Alive message.
+         *
+         * This method MUST be called when `Connection` is in certain states depending on whether it is acting as a
+         * client or server:
+         * - On client, it can be called in any state after the connection is established. Sending Keep Alive message
+         *   can be used to initiate establishing DSO session.
+         * - On server, it can be used only after session is established (`kStateSessionEstablished`).
+         *
+         * On a client, the Keep Alive message is sent as a request message. On server it is sent as a unidirectional
+         * message.
+         *
+         * @retval  kErrorNone     Successfully prepared and sent a Keep Alive message.
+         * @retval  kErrorNoBufs   Failed to allocate message to send.
+         *
+         */
+        Error SendKeepAliveMessage(void);
+
+        /**
+         * This method sets the Inactivity and Keep Alive timeout intervals.
+         *
+         * On client, the specified timeout intervals are used in Keep Alive request message, i.e., they are the values
+         * that client would wish to get. On server, the given timeout intervals specify the values that server would
+         * grant to a client upon receiving a Keep Alive request from it.
+         *
+         * This method can be called in any `Connection` state. If current state allows, calling this method will also
+         * trigger sending of a Keep Alive message (as if `SendKeepAliveMessage()` is also called). For states which
+         * trigger the tx, see `SendKeepAliveMessage()`.
+         *
+         * The special value `kInfiniteTimeout` can be used for either Inactivity or Keep Alive interval which disables
+         * the corresponding timer. The Keep Alive interval should be larger than or equal to minimum
+         * `kMinKeepAliveInterval`, otherwise `kErrorInvalidArgs` is returned.
+         *
+         * @param[in] aInactivityTimeout  The Inactivity timeout (in msec).
+         * @param[in] aKeepAliveInterval  The Keep Alive interval (in msec).
+         *
+         * @retval kErrorNone          Successfully set the timeouts and sent a Keep Alive message.
+         * @retval kErrorInvalidArgs   The given timeouts are not valid.
+         * @retval kErrorNoBufs        Failed to allocate message to send.
+         *
+         */
+        Error SetTimeouts(uint32_t aInactivityTimeout, uint32_t aKeepAliveInterval);
+
+        /**
+         * This method enables/disables long-lived operation on the session.
+         *
+         * When a long-lived operation is active, the Inactivity timeout is always cleared, i.e., the DSO session stays
+         * connected even if no messages are exchanged.
+         *
+         * @param[in] aLongLivedOperation    A boolean indicating whether or not a long-lived operation is active.
+         *
+         */
+        void SetLongLivedOperation(bool aLongLivedOperation);
+
+        /**
+         * This method sends a unidirectional Retry Delay message from server to client.
+         *
+         * This method MUST be used on a server only and when DSO session is already established, i.e., in state
+         * `kStateSessionEstablished`. It sends a unidirectional Retry Delay message to client requesting it to close
+         * the connection and not connect again for at least the specified delay amount.
+         *
+         * Note that calling `SendRetryDelayMessage()` does not by itself close the connection on server side. It is
+         * up to the user of the DSO module to implement a wait time delay before deciding to close/abort the connection
+         * from server side, in case the client does not close it upon receiving the Retry Delay message.
+         *
+         * @param[in] aDelay          The retry delay interval (in msec).
+         * @param[in] aResponseCode   The DNS RCODE to include in the Retry Delay message.
+         *
+         * @retval  kErrorNone        Successfully prepared and sent a Retry Delay message to client.
+         * @retval  kErrorNoBufs      Failed to allocate message to send.
+         *
+         */
+        Error SendRetryDelayMessage(uint32_t              aDelay,
+                                    Dns::Header::Response aResponseCode = Dns::Header::kResponseSuccess);
+
+        /**
+         * This method returns the requested retry delay interval (in msec) by server.
+         *
+         * This method MUST be used after a `HandleDisconnected()` callback with `kReasonServerRetryDelayRequest`
+         *
+         * @returns The retry delay interval requested by server.
+         *
+         */
+        uint32_t GetRetryDelay(void) const { return mRetryDelay; }
+
+        /**
+         * This method returns the DNS error code in the last retry delay message received on client from server.
+         *
+         * This method MUST be used after a `HandleDisconnected()` callback with `kReasonServerRetryDelayRequest`
+         *
+         * @returns The DNS error code in the last Retry Delay message received on client from server.
+         *
+         */
+        Dns::Header::Response GetRetryDelayErrorCode(void) const { return mRetryDelayErrorCode; }
+
+    private:
+        enum MessageType : uint8_t
+        {
+            kRequestMessage,
+            kResponseMessage,
+            kUnidirectionalMessage,
+        };
+
+        // Info about pending request messages (message ID, primary TLV type, and response timeout).
+        class PendingRequests
+        {
+        public:
+            static constexpr uint8_t kMaxPendingRequests = OPENTHREAD_CONFIG_DNS_DSO_MAX_PENDING_REQUESTS;
+
+            void      Clear(void) { mRequests.Clear(); }
+            bool      IsEmpty(void) const { return mRequests.IsEmpty(); }
+            bool      Contains(MessageId aMessageId, Tlv::Type &aPrimaryTlvType) const;
+            Error     Add(MessageId aMessageId, Tlv::Type aPrimaryTlvType, TimeMilli aResponseTimeout);
+            void      Remove(MessageId aMessageId);
+            bool      HasAnyTimedOut(TimeMilli aNow) const;
+            TimeMilli GetNextFireTime(TimeMilli aNow) const;
+
+        private:
+            struct Entry
+            {
+                bool Matches(MessageId aMessageId) const { return mMessageId == aMessageId; }
+
+                MessageId mMessageId;
+                Tlv::Type mPrimaryTlvType;
+                TimeMilli mTimeout; // Latest time by which a response is expected.
+            };
+
+            Array<Entry, kMaxPendingRequests> mRequests;
+        };
+
+        // Inactivity or KeepAlive timeout
+        class Timeout
+        {
+        public:
+            static constexpr uint32_t kInfinite = kInfiniteTimeout;
+            static constexpr uint32_t kDefault  = kDefaultTimeout;
+
+            explicit Timeout(uint32_t aInterval)
+                : mInterval(aInterval)
+                , mRequest(aInterval)
+            {
+            }
+
+            // On client, timeout value granted by server. On server, value to grant.
+            uint32_t GetInterval(void) const { return mInterval; }
+            void     SetInterval(uint32_t aInterval) { mInterval = LimitInterval(aInterval); }
+
+            // On client, timeout value to request. Not used on server.
+            uint32_t GetRequestInterval(void) const { return mRequest; }
+            void     SetRequestInterval(uint32_t aInterval) { mRequest = LimitInterval(aInterval); }
+
+            TimeMilli GetExpirationTime(void) const { return mExpirationTime; }
+            void      SetExpirationTime(TimeMilli aTime) { mExpirationTime = aTime; }
+
+            bool IsUsed(void) const { return (mInterval != kInfinite); }
+            bool IsExpired(TimeMilli aNow) const { return (mExpirationTime <= aNow); }
+
+        private:
+            static constexpr uint32_t kMaxInterval = TimerMilli::kMaxDelay / 2;
+
+            uint32_t LimitInterval(uint32_t aInterval) const
+            {
+                // If it is not infinite, limit the interval to `kMaxInterval`.
+                // The max limit ensures that even twice the interval is less
+                // than max OpenThread timer duration.
+                return (aInterval == kInfinite) ? aInterval : OT_MIN(aInterval, kMaxInterval);
+            }
+
+            uint32_t  mInterval;
+            uint32_t  mRequest;
+            TimeMilli mExpirationTime;
+        };
+
+        void Init(bool aIsServer);
+        void SetState(State aState);
+        void SignalAnyStateChange(void);
+        void Accept(void);
+        void MarkAsConnecting(void);
+        void HandleConnected(void);
+        void HandleDisconnected(DisconnectMode aMode);
+        void MarkAsDisconnected(void);
+
+        Error SendKeepAliveMessage(MessageType aMessageType, MessageId aResponseId);
+        Error SendMessage(Message &             aMessage,
+                          MessageType           aMessageType,
+                          MessageId &           aMessageId,
+                          Dns::Header::Response aResponseCode    = Dns::Header::kResponseSuccess,
+                          uint32_t              aResponseTimeout = kResponseTimeout);
+        void  HandleReceive(Message &aMessage);
+        Error ReadPrimaryTlv(const Message &aMessage, Tlv::Type &aPrimaryTlvType) const;
+        Error ProcessRequestOrUnidirectionalMessage(const Dns::Header &aHeader,
+                                                    const Message &    aMessage,
+                                                    Tlv::Type          aPrimaryTlvType);
+        Error ProcessResponseMessage(const Dns::Header &aHeader, const Message &aMessage, Tlv::Type aPrimaryTlvType);
+        Error ProcessKeepAliveMessage(const Dns::Header &aHeader, const Message &aMessage);
+        Error ProcessRetryDelayMessage(const Dns::Header &aHeader, const Message &aMessage);
+        void  SendErrorResponse(const Dns::Header &aHeader, Dns::Header::Response aResponseCode);
+        Error AppendPadding(Message &aMessage);
+
+        void      AdjustInactivityTimeout(uint32_t aNewTimeout);
+        uint32_t  CalculateServerInactivityWaitTime(void) const;
+        void      ResetTimeouts(bool aIsKeepAliveMessage);
+        TimeMilli GetNextFireTime(TimeMilli aNow) const;
+        void      HandleTimer(TimeMilli aNow, TimeMilli &aNextTime);
+
+        bool Matches(const Ip6::SockAddr &aPeerSockAddr) const { return mPeerSockAddr == aPeerSockAddr; }
+
+        static const char *StateToString(State aState);
+        static const char *MessageTypeToString(MessageType aMessageType);
+        static const char *DisconnectReasonToString(DisconnectReason aReason);
+
+        Connection *          mNext;
+        Callbacks &           mCallbacks;
+        Ip6::SockAddr         mPeerSockAddr;
+        State                 mState;
+        MessageId             mNextMessageId;
+        PendingRequests       mPendingRequests;
+        bool                  mIsServer : 1;
+        bool                  mStateDidChange : 1;
+        bool                  mLongLivedOperation : 1;
+        Timeout               mInactivity;
+        Timeout               mKeepAlive;
+        uint32_t              mRetryDelay;
+        Dns::Header::Response mRetryDelayErrorCode;
+        DisconnectReason      mDisconnectReason;
+    };
+
+    /**
+     * This callback function is used by DSO module to determine whether or not to accept a connection request from a
+     * peer.
+     *
+     * The function MUST return a non-null `Connection` pointer if the request is to be accepted. The returned
+     * `Connection` instance MUST be in `kStateDisconnected`. The DSO module will take the ownership of the `Connection`
+     * instance (adds it into a list of server connections - see `FindServerConnection()`). The ownership is passed
+     * back to the caller when the `Connection` gets disconnected, i.e., when either the user requests a disconnect by
+     * an explicit call to the method `Connection::Disconnect()`, or, if `HandleDisconnected()` callback is invoked
+     * (after connection is closed by the DSO module itself or by the peer).
+     *
+     * @param[in] aInstance      The OpenThread instance.
+     * @param[in] aPeerSockAddr  The peer socket address.
+     *
+     * @returns A pointer to the `Connection` to use if to accept, or `nullptr` if to reject the connection request.
+     *
+     */
+    typedef Connection *(*AcceptHandler)(Instance &aInstance, const Ip6::SockAddr &aPeerSockAddr);
+
+    /**
+     * This constructor initializes the `Dso` module.
+     *
+     */
+    explicit Dso(Instance &aInstance);
+
+    /**
+     * This method starts listening for DSO connection requests from peers.
+     *
+     * Once a connection request (from a peer) is received, the `Dso` module will invoke the `AcceptHandler` to
+     * determine whether to accept or reject the request.
+     *
+     * @param[in] aAcceptHandler   Accept handler callback.
+     *
+     */
+    void StartListening(AcceptHandler aAcceptHandler);
+
+    /**
+     * This method stops listening for DSO connection requests from peers.
+     *
+     */
+    void StopListening(void);
+
+    /**
+     * This method finds a client `Connection` instance (being currently managed by the `Dso` module) matching a given
+     * peer socket address.
+     *
+     * @param[in] aPeerSockAddr   The peer socket address.
+     *
+     * @returns A pointer to the matching `Connection` or `nullptr` if no match is found.
+     *
+     */
+    Connection *FindClientConnection(const Ip6::SockAddr &aPeerSockAddr);
+
+    /**
+     * This method finds a server `Connection` instance (being currently managed by the `Dso` module) matching a given
+     * peer socket address.
+     *
+     * @param[in] aPeerSockAddr   The peer socket address.
+     *
+     * @returns A pointer to the matching `Connection` or `nullptr` if no match is found.
+     *
+     */
+    Connection *FindServerConnection(const Ip6::SockAddr &aPeerSockAddr);
+
+private:
+    OT_TOOL_PACKED_BEGIN
+    class KeepAliveTlv : public Tlv
+    {
+    public:
+        static constexpr Type kType = kKeepAliveType;
+
+        void Init(void) { Tlv::Init(kType, sizeof(*this) - sizeof(Tlv)); }
+
+        bool IsValid(void) const { return GetSize() >= sizeof(*this); }
+
+        uint32_t GetInactivityTimeout(void) const { return HostSwap32(mInactivityTimeout); }
+        void     SetInactivityTimeout(uint32_t aTimeout) { mInactivityTimeout = HostSwap32(aTimeout); }
+
+        uint32_t GetKeepAliveInterval(void) const { return HostSwap32(mKeepAliveInterval); }
+        void     SetKeepAliveInterval(uint32_t aInterval) { mKeepAliveInterval = HostSwap32(aInterval); }
+
+    private:
+        uint32_t mInactivityTimeout; // In msec
+        uint32_t mKeepAliveInterval; // In msec
+    } OT_TOOL_PACKED_END;
+
+    OT_TOOL_PACKED_BEGIN
+    class RetryDelayTlv : public Tlv
+    {
+    public:
+        static constexpr Type kType = kRetryDelayType;
+
+        void Init(void) { Tlv::Init(kType, sizeof(*this) - sizeof(Tlv)); }
+
+        bool IsValid(void) const { return GetSize() >= sizeof(*this); }
+
+        uint32_t GetRetryDelay(void) const { return HostSwap32(mRetryDelay); }
+        void     SetRetryDelay(uint32_t aDelay) { mRetryDelay = HostSwap32(aDelay); }
+
+    private:
+        uint32_t mRetryDelay;
+    } OT_TOOL_PACKED_END;
+
+    OT_TOOL_PACKED_BEGIN
+    class EncryptionPaddingTlv : public Tlv
+    {
+    public:
+        static constexpr Type kType = kEncryptionPaddingType;
+
+        void Init(uint16_t aPaddingLength) { Tlv::Init(kType, aPaddingLength); }
+
+    private:
+        // Value is padding bytes (zero) based on the length.
+    } OT_TOOL_PACKED_END;
+
+    Connection *AcceptConnection(const Ip6::SockAddr &aPeerSockAddr);
+
+    static void HandleTimer(Timer &aTimer);
+    void        HandleTimer(void);
+
+    AcceptHandler          mAcceptHandler;
+    LinkedList<Connection> mClientConnections;
+    LinkedList<Connection> mServerConnections;
+    TimerMilli             mTimer;
+};
+
+} // namespace Dns
+
+DefineCoreType(otPlatDsoConnection, Dns::Dso::Connection);
+DefineMapEnum(otPlatDsoDisconnectMode, Dns::Dso::Connection::DisconnectMode);
+
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_DNS_DSO_ENABLE
+
+#endif // DNS_DSO_HPP_
diff --git a/src/core/net/dns_types.cpp b/src/core/net/dns_types.cpp
index 6ae3167..e65cd03 100644
--- a/src/core/net/dns_types.cpp
+++ b/src/core/net/dns_types.cpp
@@ -36,7 +36,6 @@
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
 #include "common/instance.hpp"
-#include "common/logging.hpp"
 #include "common/random.hpp"
 #include "common/string.hpp"
 
@@ -77,6 +76,7 @@
         break;
 
     case kResponseNotImplemented: // Server does not support the query type (OpCode).
+    case kDsoTypeNotImplemented:  // DSO TLV type is not implemented.
         error = kErrorNotImplemented;
         break;
 
@@ -368,7 +368,7 @@
     LabelIterator iterator(aMessage, aOffset);
 
     SuccessOrExit(error = iterator.GetNextLabel());
-    VerifyOrExit(iterator.CompareLabel(aLabel, /* aIsSingleLabel */ true), error = kErrorNotFound);
+    VerifyOrExit(iterator.CompareLabel(aLabel, kIsSingleLabel), error = kErrorNotFound);
     aOffset = iterator.mNextLabelOffset;
 
 exit:
@@ -394,7 +394,7 @@
         switch (error)
         {
         case kErrorNone:
-            if (matches && !iterator.CompareLabel(aName, /* aIsSingleLabel */ false))
+            if (matches && !iterator.CompareLabel(aName, !kIsSingleLabel))
             {
                 matches = false;
             }
@@ -564,6 +564,11 @@
     return error;
 }
 
+bool Name::LabelIterator::CaseInsensitiveMatch(uint8_t aFirst, uint8_t aSecond)
+{
+    return ToLowercase(static_cast<char>(aFirst)) == ToLowercase(static_cast<char>(aSecond));
+}
+
 bool Name::LabelIterator::CompareLabel(const char *&aName, bool aIsSingleLabel) const
 {
     // This method compares the current label in the iterator with the
@@ -577,7 +582,7 @@
     bool matches = false;
 
     VerifyOrExit(StringLength(aName, mLabelLength) == mLabelLength);
-    matches = mMessage.CompareBytes(mLabelStartOffset, aName, mLabelLength);
+    matches = mMessage.CompareBytes(mLabelStartOffset, aName, mLabelLength, CaseInsensitiveMatch);
 
     VerifyOrExit(matches);
 
@@ -606,7 +611,7 @@
 
     return (mLabelLength == aOtherIterator.mLabelLength) &&
            mMessage.CompareBytes(mLabelStartOffset, aOtherIterator.mMessage, aOtherIterator.mLabelStartOffset,
-                                 mLabelLength);
+                                 mLabelLength, CaseInsensitiveMatch);
 }
 
 Error Name::LabelIterator::AppendLabel(Message &aMessage) const
@@ -626,30 +631,53 @@
 
 bool Name::IsSubDomainOf(const char *aName, const char *aDomain)
 {
-    bool     match        = false;
-    uint16_t nameLength   = StringLength(aName, kMaxNameLength);
-    uint16_t domainLength = StringLength(aDomain, kMaxNameLength);
+    bool     match             = false;
+    bool     nameEndsWithDot   = false;
+    bool     domainEndsWithDot = false;
+    uint16_t nameLength        = StringLength(aName, kMaxNameLength);
+    uint16_t domainLength      = StringLength(aDomain, kMaxNameLength);
 
     if (nameLength > 0 && aName[nameLength - 1] == kLabelSeperatorChar)
     {
+        nameEndsWithDot = true;
         --nameLength;
     }
 
     if (domainLength > 0 && aDomain[domainLength - 1] == kLabelSeperatorChar)
     {
+        domainEndsWithDot = true;
         --domainLength;
     }
 
     VerifyOrExit(nameLength >= domainLength);
+
     aName += nameLength - domainLength;
 
     if (nameLength > domainLength)
     {
         VerifyOrExit(aName[-1] == kLabelSeperatorChar);
     }
-    VerifyOrExit(memcmp(aName, aDomain, domainLength) == 0);
 
-    match = true;
+    // This method allows either `aName` or `aDomain` to include or
+    // exclude the last `.` character. If both include it or if both
+    // do not, we do a full comparison using `StringMatch()`.
+    // Otherwise (i.e., when one includes and the other one does not)
+    // we use `StringStartWith()` to allow the extra `.` character.
+
+    if (nameEndsWithDot == domainEndsWithDot)
+    {
+        match = StringMatch(aName, aDomain, kStringCaseInsensitiveMatch);
+    }
+    else if (nameEndsWithDot)
+    {
+        // `aName` ends with dot, but `aDomain` does not.
+        match = StringStartsWith(aName, aDomain, kStringCaseInsensitiveMatch);
+    }
+    else
+    {
+        // `aDomain` ends with dot, but `aName` does not.
+        match = StringStartsWith(aDomain, aName, kStringCaseInsensitiveMatch);
+    }
 
 exit:
     return match;
@@ -957,6 +985,13 @@
 
 Error TxtEntry::AppendTo(Message &aMessage) const
 {
+    Appender appender(aMessage);
+
+    return AppendTo(appender);
+}
+
+Error TxtEntry::AppendTo(Appender &aAppender) const
+{
     Error    error = kErrorNone;
     uint16_t keyLength;
     char     separator = kKeyValueSeparator;
@@ -964,7 +999,7 @@
     if (mKey == nullptr)
     {
         VerifyOrExit((mValue != nullptr) && (mValueLength != 0));
-        error = aMessage.AppendBytes(mValue, mValueLength);
+        error = aAppender.AppendBytes(mValue, mValueLength);
         ExitNow();
     }
 
@@ -975,8 +1010,8 @@
     if (mValue == nullptr)
     {
         // Treat as a boolean attribute and encoded as "key" (with no `=`).
-        SuccessOrExit(error = aMessage.Append<uint8_t>(static_cast<uint8_t>(keyLength)));
-        error = aMessage.AppendBytes(mKey, keyLength);
+        SuccessOrExit(error = aAppender.Append<uint8_t>(static_cast<uint8_t>(keyLength)));
+        error = aAppender.AppendBytes(mKey, keyLength);
         ExitNow();
     }
 
@@ -984,10 +1019,10 @@
 
     VerifyOrExit(mValueLength + keyLength + sizeof(char) <= kMaxKeyValueEncodedSize, error = kErrorInvalidArgs);
 
-    SuccessOrExit(error = aMessage.Append<uint8_t>(static_cast<uint8_t>(keyLength + mValueLength + sizeof(char))));
-    SuccessOrExit(error = aMessage.AppendBytes(mKey, keyLength));
-    SuccessOrExit(error = aMessage.Append(separator));
-    error = aMessage.AppendBytes(mValue, mValueLength);
+    SuccessOrExit(error = aAppender.Append<uint8_t>(static_cast<uint8_t>(keyLength + mValueLength + sizeof(char))));
+    SuccessOrExit(error = aAppender.AppendBytes(mKey, keyLength));
+    SuccessOrExit(error = aAppender.Append(separator));
+    error = aAppender.AppendBytes(mValue, mValueLength);
 
 exit:
     return error;
@@ -995,17 +1030,35 @@
 
 Error TxtEntry::AppendEntries(const TxtEntry *aEntries, uint8_t aNumEntries, Message &aMessage)
 {
-    Error    error       = kErrorNone;
-    uint16_t startOffset = aMessage.GetLength();
+    Appender appender(aMessage);
+
+    return AppendEntries(aEntries, aNumEntries, appender);
+}
+
+Error TxtEntry::AppendEntries(const TxtEntry *aEntries, uint8_t aNumEntries, MutableData<kWithUint16Length> &aData)
+{
+    Error    error;
+    Appender appender(aData.GetBytes(), aData.GetLength());
+
+    SuccessOrExit(error = AppendEntries(aEntries, aNumEntries, appender));
+    appender.GetAsData(aData);
+
+exit:
+    return error;
+}
+
+Error TxtEntry::AppendEntries(const TxtEntry *aEntries, uint8_t aNumEntries, Appender &aAppender)
+{
+    Error error = kErrorNone;
 
     for (uint8_t index = 0; index < aNumEntries; index++)
     {
-        SuccessOrExit(error = aEntries[index].AppendTo(aMessage));
+        SuccessOrExit(error = aEntries[index].AppendTo(aAppender));
     }
 
-    if (aMessage.GetLength() == startOffset)
+    if (aAppender.GetAppendedLength() == 0)
     {
-        error = aMessage.Append<uint8_t>(0);
+        error = aAppender.Append<uint8_t>(0);
     }
 
 exit:
diff --git a/src/core/net/dns_types.hpp b/src/core/net/dns_types.hpp
index 12e922b..2fa3f1a 100644
--- a/src/core/net/dns_types.hpp
+++ b/src/core/net/dns_types.hpp
@@ -39,12 +39,14 @@
 #include <openthread/dns.h>
 #include <openthread/dns_client.h>
 
+#include "common/appender.hpp"
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/encoding.hpp"
 #include "common/equatable.hpp"
 #include "common/message.hpp"
 #include "crypto/ecdsa.hpp"
-#include "net/ip4_address.hpp"
+#include "net/ip4_types.hpp"
 #include "net/ip6_address.hpp"
 
 namespace ot {
@@ -149,7 +151,8 @@
         kQueryTypeInverse  = 1,
         kQueryTypeStatus   = 2,
         kQueryTypeNotify   = 4,
-        kQueryTypeUpdate   = 5
+        kQueryTypeUpdate   = 5,
+        kQueryTypeDso      = 6,
     };
 
     /**
@@ -271,6 +274,7 @@
         kResponseRecordNotExists = 8,  ///< Some RRset that ought to exist, does not exist.
         kResponseNotAuth         = 9,  ///< Service is not authoritative for zone.
         kResponseNotZone         = 10, ///< A name is not in the zone.
+        kDsoTypeNotImplemented   = 11, ///< DSO TLV TYPE is not implemented.
         kResponseBadName         = 20, ///< Bad name.
         kResponseBadAlg          = 21, ///< Bad algorithm.
         kResponseBadTruncation   = 22, ///< Bad truncation.
@@ -310,6 +314,7 @@
      * - kResponseRecordNotExists (8) : Some RRset that ought to exist, does not exist  -> kErrorNotFound
      * - kResponseNotAuth (9)         : Service is not authoritative for zone           -> kErrorSecurity
      * - kResponseNotZone (10)        : A name is not in the zone                       -> kErrorParse
+     * - kDsoTypeNotImplemented (11)  : DSO TLV Type is not implemented                 -> kErrorNotImplemented
      * - kResponseBadName (20)        : Bad name                                        -> kErrorParse
      * - kResponseBadAlg (21)         : Bad algorithm                                   -> kErrorSecurity
      * - kResponseBadTruncation (22)  : Bad truncation                                  -> kErrorParse
@@ -671,7 +676,7 @@
      * contain dot '.' character, which, for example, is useful for "Service Instance Names" where <Instance> portion
      * is a user-friendly name and can contain dot characters.
      *
-     * @param[in] aLabel              The label string to append. MUST NOT be nullptr.
+     * @param[in] aLabel              The label string to append. MUST NOT be `nullptr`.
      * @param[in] aMessage            The message to append to.
      *
      * @retval kErrorNone         Successfully encoded and appended the name label to @p aMessage.
@@ -690,7 +695,7 @@
      * whole label. This allows the label string to even contain dot '.' character, which, for example, is useful for
      * "Service Instance Names" where <Instance> portion is a user-friendly name and can contain dot characters.
      *
-     * @param[in] aLabel         The label string to append. MUST NOT be nullptr.
+     * @param[in] aLabel         The label string to append. MUST NOT be `nullptr`.
      * @param[in] aLength        The length of the label to append.
      * @param[in] aMessage       The message to append to.
      *
@@ -713,7 +718,7 @@
      * @note This method NEVER adds a label terminator (empty label) to the message, even in the case where @p aLabels
      * ends with a dot character, e.g., "host-1.test." is treated same as "host-1.test".
      *
-     * @param[in]  aLabels            A name label string. Can be nullptr (then treated as "").
+     * @param[in]  aLabels            A name label string. Can be `nullptr` (then treated as "").
      * @param[in]  aMessage           The message to which to append the encoded name.
      *
      * @retval kErrorNone         Successfully encoded and appended the name label(s) to @p aMessage.
@@ -739,7 +744,7 @@
      * @note This method NEVER adds a label terminator (empty label) to the message, even in the case where @p aLabels
      * ends with a dot character, e.g., "host-1.test." is treated same as "host-1.test".
      *
-     * @param[in]  aLabels            A name label string. Can be nullptr (then treated as "").
+     * @param[in]  aLabels            A name label string. Can be `nullptr` (then treated as "").
      * @param[in]  aLength            The max length of the name labels to encode.
      * @param[in]  aMessage           The message to which to append the encoded name.
      *
@@ -787,7 +792,7 @@
      * This method validates that the @p aName is a valid name format, i.e. no empty labels, and labels are
      * `kMaxLabelLength` (63) characters or less, and the name is `kMaxLength` (255) characters or less.
      *
-     * @param[in]  aName              A name string. Can be nullptr (then treated as "." or root).
+     * @param[in]  aName              A name string. Can be `nullptr` (then treated as "." or root).
      * @param[in]  aMessage           The message to append to.
      *
      * @retval kErrorNone         Successfully encoded and appended the name to @p aMessage.
@@ -800,9 +805,9 @@
     /**
      * This static method parses and skips over a full name in a message.
      *
-     * @param[in]    aMessage         The message to parse the name from. `aMessage.GetOffset()` MUST point to
+     * @param[in]     aMessage        The message to parse the name from. `aMessage.GetOffset()` MUST point to
      *                                the start of DNS header (this is used to handle compressed names).
-     * @param[inout] aOffset          On input the offset in @p aMessage pointing to the start of the name field.
+     * @param[in,out] aOffset         On input the offset in @p aMessage pointing to the start of the name field.
      *                                On exit (when parsed successfully), @p aOffset is updated to point to the byte
      *                                after the end of name field.
      *
@@ -824,13 +829,13 @@
      * Unlike `ReadName()` which requires and verifies that the read label to contain no dot '.' character, this method
      * allows the read label to include any character.
      *
-     * @param[in]    aMessage         The message to read the label from. `aMessage.GetOffset()` MUST point to
+     * @param[in]      aMessage       The message to read the label from. `aMessage.GetOffset()` MUST point to
      *                                the start of DNS header (this is used to handle compressed names).
-     * @param[inout] aOffset          On input, the offset in @p aMessage pointing to the start of the label to read.
+     * @param[in,out]  aOffset        On input, the offset in @p aMessage pointing to the start of the label to read.
      *                                On exit, when successfully read, @p aOffset is updated to point to the start of
      *                                the next label.
-     * @param[out]   aLabelBuffer     A pointer to a char array to output the read label as a null-terminated C string.
-     * @param[inout] aLabelLength     On input, the maximum number chars in @p aLabelBuffer array.
+     * @param[out]     aLabelBuffer   A pointer to a char array to output the read label as a null-terminated C string.
+     * @param[in,out]  aLabelLength   On input, the maximum number chars in @p aLabelBuffer array.
      *                                On output, when label is successfully read, @p aLabelLength is updated to return
      *                                the label's length (number of chars in the label string, excluding the null char).
      *
@@ -851,13 +856,13 @@
      * This method verifies that the read labels in message do not contain any dot character, otherwise it returns
      * `kErrorParse`).
      *
-     * @param[in]    aMessage         The message to read the name from. `aMessage.GetOffset()` MUST point to
-     *                                the start of DNS header (this is used to handle compressed names).
-     * @param[inout] aOffset          On input, the offset in @p aMessage pointing to the start of the name field.
-     *                                On exit (when parsed successfully), @p aOffset is updated to point to the byte
-     *                                after the end of name field.
-     * @param[out]   aNameBuffer      A pointer to a char array to output the read name as a null-terminated C string.
-     * @param[inout] aNameBufferSize  The maximum number of chars in @p aNameBuffer array.
+     * @param[in]     aMessage         The message to read the name from. `aMessage.GetOffset()` MUST point to
+     *                                 the start of DNS header (this is used to handle compressed names).
+     * @param[in,out] aOffset          On input, the offset in @p aMessage pointing to the start of the name field.
+     *                                 On exit (when parsed successfully), @p aOffset is updated to point to the byte
+     *                                 after the end of name field.
+     * @param[out]    aNameBuffer      A pointer to a char array to output the read name as a null-terminated C string.
+     * @param[in,out] aNameBufferSize  The maximum number of chars in @p aNameBuffer array.
      *
      * @retval kErrorNone         Successfully read the name, @p aNameBuffer and @p Offset are updated.
      * @retval kErrorParse        Name could not be parsed (invalid format).
@@ -870,18 +875,18 @@
      * This static method compares a single name label from a message with a given label string.
      *
      * This method can be used to compare labels one by one. It checks whether the label read from @p aMessage matches
-     * @p aLabel string.
+     * @p aLabel string (case-insensitive comparison).
      *
      * Unlike `CompareName()` which requires the labels in the the name string to contain no dot '.' character, this
      * method allows @p aLabel to include any character.
      *
-     * @param[in]    aMessage         The message to read the label from to compare. `aMessage.GetOffset()` MUST point
+     * @param[in]     aMessage        The message to read the label from to compare. `aMessage.GetOffset()` MUST point
      *                                to the start of DNS header (this is used to handle compressed names).
-     * @param[inout] aOffset          On input, the offset in @p aMessage pointing to the start of the label to read.
+     * @param[in,out] aOffset         On input, the offset in @p aMessage pointing to the start of the label to read.
      *                                On exit and only when label is successfully read and does match @p aLabel,
      *                                @p aOffset is updated to point to the start of the next label.
-     * @param[in]    aLabel           A pointer to a null terminated string containing the label to compare with.
-
+     * @param[in]     aLabel          A pointer to a null terminated string containing the label to compare with.
+     *
      * @retval kErrorNone          The label from @p aMessage matches @p aLabel. @p aOffset is updated.
      * @retval kErrorNotFound      The label from @p aMessage does not match @p aLabel (note that @p aOffset is not
      *                             updated in this case).
@@ -893,21 +898,22 @@
     /**
      * This static method parses and compares a full name from a message with a given name.
      *
-     * This method checks whether the encoded name in a message matches a given name string. It checks the name in
-     * the message in place and handles compressed names. If the name read from the message does not match @p aName, it
-     * returns `kErrorNotFound`. `kErrorNone` indicates that the name matches @p aName.
+     * This method checks whether the encoded name in a message matches a given name string (using case-insensitive
+     * comparison). It checks the name in the message in place and handles compressed names. If the name read from the
+     * message does not match @p aName, it returns `kErrorNotFound`. `kErrorNone` indicates that the name matches
+     * @p aName.
      *
      * The @p aName must follow  "<label1>.<label2>.<label3>", i.e., a sequence of labels separated by dot '.' char.
      * E.g., "example.com", "example.com." (same as previous one), "local.", "default.service.arpa", "." or "" (root).
      *
-     * @param[in]    aMessage         The message to read the name from and compare with @p aName.
+     * @param[in]     aMessage        The message to read the name from and compare with @p aName.
      *                                `aMessage.GetOffset()` MUST point to the start of DNS header (this is used to
      *                                handle compressed names).
-     * @param[inout] aOffset          On input, the offset in @p aMessage pointing to the start of the name field.
+     * @param[in,out] aOffset         On input, the offset in @p aMessage pointing to the start of the name field.
      *                                On exit (when parsed successfully independent of whether the read name matches
      *                                @p aName or not), @p aOffset is updated to point to the byte after the end of
      *                                the name field.
-     * @param[in]    aName            A pointer to a null terminated string containing the name to compare with.
+     * @param[in]     aName           A pointer to a null terminated string containing the name to compare with.
      *
      * @retval kErrorNone          The name from @p aMessage matches @p aName. @p aOffset is updated.
      * @retval kErrorNotFound      The name from @p aMessage does not match @p aName. @p aOffset is updated.
@@ -920,9 +926,10 @@
     /**
      * This static method parses and compares a full name from a message with a name from another message.
      *
-     * This method checks whether the encoded name in @p aMessage matches the name from @p aMessage2. It compares the
-     * names in both messages in place and handles compressed names. Note that this method works correctly even when
-     * the same message instance is used for both @p aMessage and @p aMessage2 (e.g., at different offsets).
+     * This method checks whether the encoded name in @p aMessage matches the name from @p aMessage2 (using
+     * case-insensitive comparison). It compares the names in both messages in place and handles compressed names. Note
+     * that this method works correctly even when the same message instance is used for both @p aMessage and
+     * @p aMessage2 (e.g., at different offsets).
      *
      * Only the name in @p aMessage is fully parsed and checked for parse errors. This method assumes that the name in
      * @p aMessage2 was previously parsed and validated before calling this method (if there is a parse error in
@@ -931,15 +938,15 @@
      * If the name in @p aMessage can be parsed fully (independent of whether the name matches or not with the name
      * from @p aMessage2), the @p aOffset is updated (note that @p aOffset2 for @p aMessage2 is not changed).
      *
-     * @param[in]    aMessage         The message to read the name from and compare. `aMessage.GetOffset()` MUST point
+     * @param[in]     aMessage        The message to read the name from and compare. `aMessage.GetOffset()` MUST point
      *                                to the start of DNS header (this is used to handle compressed names).
-     * @param[inout] aOffset          On input, the offset in @p aMessage pointing to the start of the name field.
+     * @param[in,out] aOffset         On input, the offset in @p aMessage pointing to the start of the name field.
      *                                On exit (when parsed successfully independent of whether the read name matches
      *                                or not), @p aOffset is updated to point to the byte after the end of the name
      *                                field.
-     * @param[in]    aMessage2        The second message to read the name from and compare with name from @p aMessage.
+     * @param[in]     aMessage2       The second message to read the name from and compare with name from @p aMessage.
      *                                `aMessage2.GetOffset()` MUST point to the start of DNS header.
-     * @param[in]    aOffset2         The offset in @p aMessage2 pointing to the start of the name field.
+     * @param[in]     aOffset2        The offset in @p aMessage2 pointing to the start of the name field.
      *
      * @retval kErrorNone       The name from @p aMessage matches the name from @p aMessage2. @p aOffset is updated.
      * @retval kErrorNotFound   The name from @p aMessage does not match the name from @p aMessage2. @p aOffset is
@@ -950,17 +957,18 @@
     static Error CompareName(const Message &aMessage, uint16_t &aOffset, const Message &aMessage2, uint16_t aOffset2);
 
     /**
-     * This static method parses and compares a full name from a message with a given name.
+     * This static method parses and compares a full name from a message with a given name (using case-insensitive
+     * comparison).
      *
      * If @p aName is empty (not specified), then any name in @p aMessage is considered a match to it.
      *
-     * @param[in]    aMessage         The message to read the name from and compare. `aMessage.GetOffset()` MUST point
+     * @param[in]     aMessage        The message to read the name from and compare. `aMessage.GetOffset()` MUST point
      *                                to the start of DNS header (this is used to handle compressed names).
-     * @param[inout] aOffset          On input, the offset in @p aMessage pointing to the start of the name field.
+     * @param[in,out] aOffset         On input, the offset in @p aMessage pointing to the start of the name field.
      *                                On exit (when parsed successfully independent of whether the read name matches
      *                                or not), @p aOffset is updated to point to the byte after the end of the name
      *                                field.
-     * @param[in]    aName            A reference to a name to compare with.
+     * @param[in]     aName           A reference to a name to compare with.
      *
      * @retval kErrorNone          The name from @p aMessage matches @p aName. @p aOffset is updated.
      * @retval kErrorNotFound      The name from @p aMessage does not match @p aName. @p aOffset is updated.
@@ -983,8 +991,6 @@
     static bool IsSubDomainOf(const char *aName, const char *aDomain);
 
 private:
-    static constexpr char kNullChar = '\0';
-
     // The first 2 bits of the encoded label specifies label type.
     //
     // - Value 00 indicates normal text label (lower 6-bits indicates the label length).
@@ -1000,6 +1006,8 @@
     static constexpr uint16_t kPointerLabelTypeUint16 = 0xc000; // Pointer label type mask (first 2 bits).
     static constexpr uint16_t kPointerLabelOffsetMask = 0x3fff; // Mask for offset in a pointer label (lower 14 bits).
 
+    static constexpr bool kIsSingleLabel = true; // Used in `LabelIterator::CompareLable()`.
+
     struct LabelIterator
     {
         static constexpr uint16_t kUnsetNameEndOffset = 0; // Special value indicating `mNameEndOffset` is not yet set.
@@ -1018,6 +1026,8 @@
         bool  CompareLabel(const LabelIterator &aOtherIterator) const;
         Error AppendLabel(Message &aMessage) const;
 
+        static bool CaseInsensitiveMatch(uint8_t aFirst, uint8_t aSecond);
+
         const Message &mMessage;          // Message to read labels from.
         uint16_t       mLabelStartOffset; // Offset in `mMessage` to the first char of current label text.
         uint8_t        mLabelLength;      // Length of current label (number of chars).
@@ -1127,7 +1137,17 @@
      * @param[in] aValueLength   Number of bytes in @p aValue buffer.
      *
      */
-    TxtEntry(const char *aKey, const uint8_t *aValue, uint8_t aValueLength)
+    TxtEntry(const char *aKey, const uint8_t *aValue, uint8_t aValueLength) { Init(aKey, aValue, aValueLength); }
+
+    /**
+     * This method initializes a `TxtEntry` object.
+     *
+     * @param[in] aKey           A pointer to the key string.
+     * @param[in] aValue         A pointer to a buffer containing the value.
+     * @param[in] aValueLength   Number of bytes in @p aValue buffer.
+     *
+     */
+    void Init(const char *aKey, const uint8_t *aValue, uint8_t aValueLength)
     {
         mKey         = aKey;
         mValue       = aValue;
@@ -1160,10 +1180,26 @@
      */
     static Error AppendEntries(const TxtEntry *aEntries, uint8_t aNumEntries, Message &aMessage);
 
+    /**
+     * This static method appends an array of `TxtEntry` items to a `MutableData` buffer.
+     *
+     * @param[in] aEntries     A pointer to array of `TxtEntry` items.
+     * @param[in] aNumEntries  The number of entries in @p aEntries array.
+     * @param[in] aData        The `MutableData` to append in.
+     *
+     * @retval kErrorNone          Entries appended successfully .
+     * @retval kErrorInvalidArgs   The `TxTEntry` info is not valid.
+     * @retval kErrorNoBufs        Insufficient available buffers.
+     *
+     */
+    static Error AppendEntries(const TxtEntry *aEntries, uint8_t aNumEntries, MutableData<kWithUint16Length> &aData);
+
 private:
+    Error        AppendTo(Appender &aAppender) const;
+    static Error AppendEntries(const TxtEntry *aEntries, uint8_t aNumEntries, Appender &aAppender);
+
     static constexpr uint8_t kMaxKeyValueEncodedSize = 255;
     static constexpr char    kKeyValueSeparator      = '=';
-    static constexpr char    kNullChar               = '\0';
 };
 
 /**
@@ -1300,12 +1336,12 @@
     /**
      * This static method parses and skips over a given number of resource records in a message from a given offset.
      *
-     * @param[in]    aMessage     The message from which to parse/read the resource records. `aMessage.GetOffset()`
-     *                            MUST point to the start of DNS header.
-     * @param[inout] aOffset      On input the offset in @p aMessage pointing to the start of the first record.
-     *                            On exit (when parsed successfully), @p aOffset is updated to point to the byte after
-     *                            the last parsed record.
-     * @param[in]    aNumRecords  Number of resource records to parse.
+     * @param[in]     aMessage     The message from which to parse/read the resource records. `aMessage.GetOffset()`
+     *                             MUST point to the start of DNS header.
+     * @param[in,out] aOffset      On input the offset in @p aMessage pointing to the start of the first record.
+     *                             On exit (when parsed successfully), @p aOffset is updated to point to the byte after
+     *                             the last parsed record.
+     * @param[in]     aNumRecords  Number of resource records to parse.
      *
      * @retval kErrorNone      Parsed records successfully. @p aOffset is updated.
      * @retval kErrorParse     Could not parse the records from @p aMessage (e.g., ran out of bytes in @p aMessage).
@@ -1316,17 +1352,17 @@
     /**
      * This static method searches in a given message to find the first resource record matching a given record name.
      *
-     * @param[in]    aMessage        The message in which to search for a matching resource record.
+     * @param[in]     aMessage       The message in which to search for a matching resource record.
      *                               `aMessage.GetOffset()` MUST point to the start of DNS header.
-     * @param[inout] aOffset         On input, the offset in @p aMessage pointing to the start of the first record.
+     * @param[in,out] aOffset        On input, the offset in @p aMessage pointing to the start of the first record.
      *                               On exit, if a matching record is found, @p aOffset is updated to point to the byte
      *                               after the record name.
      *                               If a matching record could not be found, @p aOffset is updated to point to the byte
      *                               after the last record that was checked.
-     * @param[inout] aNumRecords     On input, the maximum number of records to check (starting from @p aOffset).
+     * @param[in,out] aNumRecords    On input, the maximum number of records to check (starting from @p aOffset).
      *                               On exit and if a matching record is found, @p aNumRecords is updated to give the
      *                               number of remaining records after @p aOffset (excluding the matching record).
-     * @param[in]    aName           The record name to match against.
+     * @param[in]     aName          The record name to match against.
      *
      * @retval kErrorNone         A matching record was found. @p aOffset, @p aNumRecords are updated.
      * @retval kErrorNotFound     A matching record could not be found. @p aOffset and @p aNumRecords are updated.
@@ -1346,19 +1382,19 @@
      * to after the last byte read from the message and copied into @p aRecord. This allows the caller to read any
      * remaining fields in the record data.
      *
-     * @tparam       RecordType      The resource record type (i.e., a sub-class of `ResourceRecord`).
+     * @tparam        RecordType     The resource record type (i.e., a sub-class of `ResourceRecord`).
      *
-     * @param[in]    aMessage        The message to search within for matching resource records.
+     * @param[in]     aMessage       The message to search within for matching resource records.
      *                               `aMessage.GetOffset()` MUST point to the start of DNS header.
-     * @param[inout] aOffset         On input, the offset in @p aMessage pointing to the start of the first record.
+     * @param[in,out] aOffset        On input, the offset in @p aMessage pointing to the start of the first record.
      *                               On exit and only if a matching record is found, @p aOffset is updated to point to
      *                               the last read byte in the record (allowing caller to read any remaining fields in
      *                               the record data from the message).
-     * @param[in]    aNumRecords     The maximum number of records to check (starting from @p aOffset).
-     * @param[in]    aIndex          The matching record index to find. @p aIndex value of zero returns the first
+     * @param[in]     aNumRecords    The maximum number of records to check (starting from @p aOffset).
+     * @param[in]     aIndex         The matching record index to find. @p aIndex value of zero returns the first
      *                               matching record.
-     * @param[in]    aName           The record name to match against.
-     * @param[in]    aRecord         A reference to a record object to read a matching record into.
+     * @param[in]     aName          The record name to match against.
+     * @param[in]     aRecord        A reference to a record object to read a matching record into.
      *                               If a matching record is found, `sizeof(RecordType)` bytes from @p aMessage are
      *                               read and copied into @p aRecord.
      *
@@ -1396,15 +1432,15 @@
      * example, when reading a SRV record using `SrvRecord` type, @p aOffset would point to after the last field in
      * `SrvRecord`  which is the start of "target host domain name" field.
      *
-     * @tparam       RecordType      The resource record type (i.e., a sub-class of `ResourceRecord`).
+     * @tparam        RecordType     The resource record type (i.e., a sub-class of `ResourceRecord`).
      *
-     * @param[in]    aMessage        The message from which to read the record.
-     * @param[inout] aOffset         On input, the offset in @p aMessage pointing to the byte after the record name.
+     * @param[in]     aMessage       The message from which to read the record.
+     * @param[in,out] aOffset        On input, the offset in @p aMessage pointing to the byte after the record name.
      *                               On exit, if a matching record is read, @p aOffset is updated to point to the last
      *                               read byte in the record.
      *                               If a matching record could not be read, @p aOffset is updated to point to the byte
      *                               after the entire record (skipping over the record).
-     * @param[out]   aRecord         A reference to a record to read a matching record into.
+     * @param[out]    aRecord        A reference to a record to read a matching record into.
      *                               If a matching record is found, `sizeof(RecordType)` bytes from @p aMessage are
      *                               read and copied into @p aRecord.
      *
@@ -1523,14 +1559,14 @@
      * This method also verifies that the CNAME record is well-formed (e.g., the record data length `GetLength()`
      * matches the CNAME encoded name).
      *
-     * @param[in]     aMessage          The message to read from. `aMessage.GetOffset()` MUST point to the start of
+     * @param[in]      aMessage         The message to read from. `aMessage.GetOffset()` MUST point to the start of
      *                                  DNS header.
-     * @param[inout]  aOffset           On input, the offset in @p aMessage to start of CNAME name field.
+     * @param[in,out]  aOffset          On input, the offset in @p aMessage to start of CNAME name field.
      *                                  On exit when successfully read, @p aOffset is updated to point to the byte
      *                                  after the entire PTR record (skipping over the record).
-     * @param[out]    aNameBuffer       A pointer to a char array to output the read name as a null-terminated C string
-     *                                  (MUST NOT be nullptr).
-     * @param[in]     aNameBufferSize   The size of @p aNameBuffer.
+     * @param[out]     aNameBuffer      A pointer to a char array to output the read name as a null-terminated C string
+     *                                  (MUST NOT be `nullptr`).
+     * @param[in]      aNameBufferSize  The size of @p aNameBuffer.
      *
      * @retval kErrorNone           The CNAME name was read successfully. @p aOffset and @p aNameBuffer are updated.
      * @retval kErrorParse          The CNAME record in @p aMessage could not be parsed (invalid format).
@@ -1574,14 +1610,14 @@
      * This method also verifies that the PTR record is well-formed (e.g., the record data length `GetLength()` matches
      * the PTR encoded name).
      *
-     * @param[in]     aMessage          The message to read from.  `aMessage.GetOffset()` MUST point to the start of
+     * @param[in]      aMessage         The message to read from.  `aMessage.GetOffset()` MUST point to the start of
      *                                  DNS header.
-     * @param[inout]  aOffset           On input, the offset in @p aMessage to start of PTR name field.
+     * @param[in,out]  aOffset          On input, the offset in @p aMessage to start of PTR name field.
      *                                  On exit when successfully read, @p aOffset is updated to point to the byte
      *                                  after the entire PTR record (skipping over the record).
-     * @param[out]    aNameBuffer       A pointer to a char array to output the read name as a null-terminated C string
-     *                                  (MUST NOT be nullptr).
-     * @param[in]     aNameBufferSize   The size of @p aNameBuffer.
+     * @param[out]     aNameBuffer      A pointer to a char array to output the read name as a null-terminated C string
+     *                                  (MUST NOT be `nullptr`).
+     * @param[in]      aNameBufferSize  The size of @p aNameBuffer.
      *
      * @retval kErrorNone           The PTR name was read successfully. @p aOffset and @p aNameBuffer are updated.
      * @retval kErrorParse          The PTR record in @p aMessage could not be parsed (invalid format).
@@ -1607,17 +1643,17 @@
      * intended for "Service Instance Name" where first label (`<Instance>` portion) can be a user-friendly string and
      * can contain dot character.
      *
-     * @param[in]     aMessage          The message to read from. `aMessage.GetOffset()` MUST point to the start of
-     *                                  DNS header.
-     * @param[inout]  aOffset           On input, the offset in @p aMessage to the start of PTR name field.
-     *                                  On exit, when successfully read, @p aOffset is updated to point to the byte
-     *                                  after the entire PTR record (skipping over the record).
-     * @param[out]    aLabelBuffer      A pointer to a char array to output the first label as a null-terminated C
-     *                                  string (MUST NOT be nullptr).
-     * @param[in]     aLabelBufferSize  The size of @p aLabelBuffer.
-     * @param[out]    aNameBuffer       A pointer to a char array to output the rest of name (after first label). Can
-     *                                  be `nullptr` if caller is only interested in the first label.
-     * @param[in]     aNameBufferSize   The size of @p aNameBuffer.
+     * @param[in]      aMessage          The message to read from. `aMessage.GetOffset()` MUST point to the start of
+     *                                   DNS header.
+     * @param[in,out]  aOffset           On input, the offset in @p aMessage to the start of PTR name field.
+     *                                   On exit, when successfully read, @p aOffset is updated to point to the byte
+     *                                   after the entire PTR record (skipping over the record).
+     * @param[out]     aLabelBuffer      A pointer to a char array to output the first label as a null-terminated C
+     *                                   string (MUST NOT be `nullptr`).
+     * @param[in]      aLabelBufferSize  The size of @p aLabelBuffer.
+     * @param[out]     aNameBuffer       A pointer to a char array to output the rest of name (after first label). Can
+     *                                   be `nullptr` if caller is only interested in the first label.
+     * @param[in]      aNameBufferSize   The size of @p aNameBuffer.
      *
      * @retval kErrorNone    The PTR name was read successfully. @p aOffset, @aLabelBuffer and @aNameBuffer are updated.
      * @retval kErrorParse   The PTR record in @p aMessage could not be parsed (invalid format).
@@ -1658,12 +1694,12 @@
      *
      * This method also checks if the TXT data is well-formed by calling `VerifyTxtData()`.
      *
-     * @param[in]     aMessage          The message to read from.
-     * @param[inout]  aOffset           On input, the offset in @p aMessage to start of TXT record data.
+     * @param[in]      aMessage         The message to read from.
+     * @param[in,out]  aOffset          On input, the offset in @p aMessage to start of TXT record data.
      *                                  On exit when successfully read, @p aOffset is updated to point to the byte
      *                                  after the entire TXT record (skipping over the record).
-     * @param[out]    aTxtBuffer        A pointer to a byte array to output the read TXT data.
-     * @param[inout]  aTxtBufferSize    On input, the size of @p aTxtBuffer (max bytes that can be read).
+     * @param[out]     aTxtBuffer       A pointer to a byte array to output the read TXT data.
+     * @param[in,out]  aTxtBufferSize   On input, the size of @p aTxtBuffer (max bytes that can be read).
      *                                  On exit, @p aTxtBufferSize gives number of bytes written to @p aTxtBuffer.
      *
      * @retval kErrorNone           The TXT data was read successfully. @p aOffset, @p aTxtBuffer and @p aTxtBufferSize
@@ -1812,14 +1848,14 @@
      * This method also verifies that the SRV record is well-formed (e.g., the record data length `GetLength()` matches
      * the SRV encoded name).
      *
-     * @param[in]     aMessage          The message to read from. `aMessage.GetOffset()` MUST point to the start of
+     * @param[in]      aMessage         The message to read from. `aMessage.GetOffset()` MUST point to the start of
      *                                  DNS header.
-     * @param[inout]  aOffset           On input, the offset in @p aMessage to start of target host name field.
+     * @param[in,out]  aOffset          On input, the offset in @p aMessage to start of target host name field.
      *                                  On exit when successfully read, @p aOffset is updated to point to the byte
      *                                  after the entire SRV record (skipping over the record).
-     * @param[out]    aNameBuffer       A pointer to a char array to output the read name as a null-terminated C string
-     *                                  (MUST NOT be nullptr).
-     * @param[in]     aNameBufferSize   The size of @p aNameBuffer.
+     * @param[out]     aNameBuffer      A pointer to a char array to output the read name as a null-terminated C string
+     *                                  (MUST NOT be `nullptr`).
+     * @param[in]      aNameBufferSize  The size of @p aNameBuffer.
      *
      * @retval kErrorNone            The host name was read successfully. @p aOffset and @p aNameBuffer are updated.
      * @retval kErrorParse           The SRV record in @p aMessage could not be parsed (invalid format).
@@ -2215,14 +2251,14 @@
     /**
      * This method parses and reads the SIG signer name from a message.
      *
-     * @param[in]     aMessage          The message to read from. `aMessage.GetOffset()` MUST point to the start of DNS
+     * @param[in]      aMessage         The message to read from. `aMessage.GetOffset()` MUST point to the start of DNS
      *                                  header.
-     * @param[inout]  aOffset           On input, the offset in @p aMessage to start of signer name field.
+     * @param[in,out]  aOffset          On input, the offset in @p aMessage to start of signer name field.
      *                                  On exit when successfully read, @p aOffset is updated to point to the byte
      *                                  after the name field (i.e., start of signature field).
-     * @param[out]    aNameBuffer       A pointer to a char array to output the read name as a null-terminated C string
-     *                                  (MUST NOT be nullptr).
-     * @param[in]     aNameBufferSize   The size of @p aNameBuffer.
+     * @param[out]     aNameBuffer      A pointer to a char array to output the read name as a null-terminated C string
+     *                                  (MUST NOT be `nullptr`).
+     * @param[in]      aNameBufferSize  The size of @p aNameBuffer.
      *
      * @retval kErrorNone           The name was read successfully. @p aOffset and @p aNameBuffer are updated.
      * @retval kErrorParse          The SIG record in @p aMessage could not be parsed (invalid format).
@@ -2585,6 +2621,10 @@
  */
 
 } // namespace Dns
+
+DefineCoreType(otDnsTxtEntry, Dns::TxtEntry);
+DefineCoreType(otDnsTxtEntryIterator, Dns::TxtEntry::Iterator);
+
 } // namespace ot
 
 #endif // DNS_HEADER_HPP_
diff --git a/src/core/net/dnssd_server.cpp b/src/core/net/dnssd_server.cpp
index c3ac14d..c996c15 100644
--- a/src/core/net/dnssd_server.cpp
+++ b/src/core/net/dnssd_server.cpp
@@ -35,12 +35,14 @@
 
 #if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
 
+#include "common/array.hpp"
 #include "common/as_core_type.hpp"
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
+#include "common/string.hpp"
 #include "net/srp_server.hpp"
 #include "net/udp6.hpp"
 
@@ -48,8 +50,10 @@
 namespace Dns {
 namespace ServiceDiscovery {
 
-const char Server::kDnssdProtocolUdp[4] = {'_', 'u', 'd', 'p'};
-const char Server::kDnssdProtocolTcp[4] = {'_', 't', 'c', 'p'};
+RegisterLogModule("DnssdServer");
+
+const char Server::kDnssdProtocolUdp[]  = "_udp";
+const char Server::kDnssdProtocolTcp[]  = "_tcp";
 const char Server::kDnssdSubTypeLabel[] = "._sub.";
 const char Server::kDefaultDomainName[] = "default.service.arpa.";
 
@@ -61,6 +65,7 @@
     , mQueryUnsubscribe(nullptr)
     , mTimer(aInstance, Server::HandleTimer)
 {
+    mCounters.Clear();
 }
 
 Error Server::Start(void)
@@ -77,7 +82,7 @@
 #endif
 
 exit:
-    otLogInfoDns("[server] started: %s", ErrorToString(error));
+    LogInfo("started: %s", ErrorToString(error));
 
     if (error != kErrorNone)
     {
@@ -101,7 +106,7 @@
     mTimer.Stop();
 
     IgnoreError(mSocket.Close());
-    otLogInfoDns("[server] stopped");
+    LogInfo("stopped");
 
 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
     Get<Srp::Server>().HandleDnssdServerStateChange();
@@ -169,11 +174,19 @@
 #endif
 
     // Resolve the question using query callbacks if SRP server failed to resolve the questions.
-    if (responseHeader.GetAnswerCount() == 0 &&
-        kErrorNone == ResolveByQueryCallbacks(responseHeader, *responseMessage, compressInfo, aMessageInfo))
+    if (responseHeader.GetAnswerCount() == 0)
     {
-        resolveByQueryCallbacks = true;
+        if (kErrorNone == ResolveByQueryCallbacks(responseHeader, *responseMessage, compressInfo, aMessageInfo))
+        {
+            resolveByQueryCallbacks = true;
+        }
     }
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+    else
+    {
+        ++mCounters.mResolvedBySrp;
+    }
+#endif
 
 exit:
     if (error == kErrorNone && !resolveByQueryCallbacks)
@@ -194,7 +207,7 @@
 
     if (aResponseCode == Header::kResponseServerFailure)
     {
-        otLogWarnDns("[server] failed to handle DNS query due to server failure");
+        LogWarn("failed to handle DNS query due to server failure");
         aHeader.SetQuestionCount(0);
         aHeader.SetAnswerCount(0);
         aHeader.SetAdditionalRecordCount(0);
@@ -210,12 +223,14 @@
 
     if (error != kErrorNone)
     {
-        otLogWarnDns("[server] failed to send DNS-SD reply: %s", otThreadErrorToString(error));
+        LogWarn("failed to send DNS-SD reply: %s", ErrorToString(error));
     }
     else
     {
-        otLogInfoDns("[server] send DNS-SD reply: %s, RCODE=%d", otThreadErrorToString(error), aResponseCode);
+        LogInfo("send DNS-SD reply: %s, RCODE=%d", ErrorToString(error), aResponseCode);
     }
+
+    UpdateResponseCounters(aResponseCode);
 }
 
 Header::Response Server::AddQuestions(const Header &    aRequestHeader,
@@ -395,7 +410,7 @@
     const char *serviceName;
 
     // Check whether `aName` is a sub-type service name.
-    serviceName = StringFind(aName, kDnssdSubTypeLabel);
+    serviceName = StringFind(aName, kDnssdSubTypeLabel, kStringCaseInsensitiveMatch);
 
     if (serviceName != nullptr)
     {
@@ -488,17 +503,25 @@
                               uint32_t          aTtl,
                               NameCompressInfo &aCompressInfo)
 {
-    Error     error = kErrorNone;
-    TxtRecord txtRecord;
+    Error         error = kErrorNone;
+    TxtRecord     txtRecord;
+    const uint8_t kEmptyTxt = 0;
 
     SuccessOrExit(error = AppendInstanceName(aMessage, aInstanceName, aCompressInfo));
 
     txtRecord.Init();
     txtRecord.SetTtl(aTtl);
-    txtRecord.SetLength(aTxtLength);
+    txtRecord.SetLength(aTxtLength > 0 ? aTxtLength : sizeof(kEmptyTxt));
 
     SuccessOrExit(error = aMessage.Append(txtRecord));
-    error = aMessage.AppendBytes(aTxtData, aTxtLength);
+    if (aTxtLength > 0)
+    {
+        error = aMessage.AppendBytes(aTxtData, aTxtLength);
+    }
+    else
+    {
+        error = aMessage.Append(kEmptyTxt);
+    }
 
 exit:
     return error;
@@ -569,8 +592,8 @@
         VerifyOrExit(error == kErrorNone, error = (error == kErrorNotFound ? kErrorNone : error));
 
         if (labelEnd == labelBegin + kProtocolLabelLength &&
-            (memcmp(&aName[labelBegin], kDnssdProtocolUdp, kProtocolLabelLength) == 0 ||
-             memcmp(&aName[labelBegin], kDnssdProtocolTcp, kProtocolLabelLength) == 0))
+            (StringStartsWith(&aName[labelBegin], kDnssdProtocolUdp, kStringCaseInsensitiveMatch) ||
+             StringStartsWith(&aName[labelBegin], kDnssdProtocolTcp, kStringCaseInsensitiveMatch)))
         {
             // <Protocol> label found
             aInfo.mProtocolOffset = labelBegin;
@@ -591,7 +614,7 @@
     // Note that `kDnssdSubTypeLabel` is "._sub.". Here we get the
     // label only so we want to compare it with "_sub".
     if ((labelEnd == labelBegin + kSubTypeLabelLength) &&
-        (memcmp(&aName[labelBegin], kDnssdSubTypeLabel + 1, kSubTypeLabelLength) == 0))
+        StringStartsWith(&aName[labelBegin], kDnssdSubTypeLabel + 1, kStringCaseInsensitiveMatch))
     {
         SuccessOrExit(error = FindPreviousLabel(aName, labelBegin, labelEnd));
         VerifyOrExit(labelBegin == 0, error = kErrorInvalidArgs);
@@ -653,8 +676,8 @@
         response = ResolveQuestionBySrp(name, question, aResponseHeader, aResponseMessage, aCompressInfo,
                                         /* aAdditional */ false);
 
-        otLogInfoDns("[server] ANSWER: TRANSACTION=0x%04x, QUESTION=[%s %d %d], RCODE=%d",
-                     aResponseHeader.GetMessageId(), name, question.GetClass(), question.GetType(), response);
+        LogInfo("ANSWER: TRANSACTION=0x%04x, QUESTION=[%s %d %d], RCODE=%d", aResponseHeader.GetMessageId(), name,
+                question.GetClass(), question.GetType(), response);
     }
 
     // Answer the questions with additional RRs if required
@@ -672,8 +695,8 @@
                                                                                 /* aAdditional */ true),
                          response = Header::kResponseServerFailure);
 
-            otLogInfoDns("[server] ADDITIONAL: TRANSACTION=0x%04x, QUESTION=[%s %d %d], RCODE=%d",
-                         aResponseHeader.GetMessageId(), name, question.GetClass(), question.GetType(), response);
+            LogInfo("ADDITIONAL: TRANSACTION=0x%04x, QUESTION=[%s %d %d], RCODE=%d", aResponseHeader.GetMessageId(),
+                    name, question.GetClass(), question.GetType(), response);
         }
     }
 exit:
@@ -830,7 +853,7 @@
             continue;
         }
 
-        query.Init(aResponseHeader, aResponseMessage, aCompressInfo, aMessageInfo);
+        query.Init(aResponseHeader, aResponseMessage, aCompressInfo, aMessageInfo, GetInstance());
         ExitNow(newQuery = &query);
     }
 
@@ -856,10 +879,10 @@
     switch (sdType)
     {
     case kDnsQueryBrowse:
-        canAnswer = (strcmp(name, aServiceFullName) == 0);
+        canAnswer = StringMatch(name, aServiceFullName, kStringCaseInsensitiveMatch);
         break;
     case kDnsQueryResolve:
-        canAnswer = (strcmp(name, aInstanceInfo.mFullName) == 0);
+        canAnswer = StringMatch(name, aInstanceInfo.mFullName, kStringCaseInsensitiveMatch);
         break;
     default:
         break;
@@ -874,7 +897,7 @@
     DnsQueryType sdType;
 
     sdType = GetQueryTypeAndName(aQuery.GetResponseHeader(), aQuery.GetResponseMessage(), name);
-    return (sdType == kDnsQueryResolveHost) && (strcmp(name, aHostFullName) == 0);
+    return (sdType == kDnsQueryResolveHost) && StringMatch(name, aHostFullName, kStringCaseInsensitiveMatch);
 }
 
 void Server::AnswerQuery(QueryTransaction &                aQuery,
@@ -1013,7 +1036,7 @@
         cur = query + 1;
     }
 
-    for (; cur < OT_ARRAY_END(mQueryTransactions); cur++)
+    for (; cur < GetArrayEnd(mQueryTransactions); cur++)
     {
         if (cur->IsValid())
         {
@@ -1182,10 +1205,12 @@
 void Server::QueryTransaction::Init(const Header &          aResponseHeader,
                                     Message &               aResponseMessage,
                                     const NameCompressInfo &aCompressInfo,
-                                    const Ip6::MessageInfo &aMessageInfo)
+                                    const Ip6::MessageInfo &aMessageInfo,
+                                    Instance &              aInstance)
 {
     OT_ASSERT(mResponseMessage == nullptr);
 
+    InstanceLocatorInit::Init(aInstance);
     mResponseHeader  = aResponseHeader;
     mResponseMessage = &aResponseMessage;
     mCompressInfo    = aCompressInfo;
@@ -1197,10 +1222,35 @@
 {
     OT_ASSERT(mResponseMessage != nullptr);
 
-    SendResponse(mResponseHeader, aResponseMessage, *mResponseMessage, mMessageInfo, aSocket);
+    Get<Server>().SendResponse(mResponseHeader, aResponseMessage, *mResponseMessage, mMessageInfo, aSocket);
     mResponseMessage = nullptr;
 }
 
+void Server::UpdateResponseCounters(Header::Response aResponseCode)
+{
+    switch (aResponseCode)
+    {
+    case UpdateHeader::kResponseSuccess:
+        ++mCounters.mSuccessResponse;
+        break;
+    case UpdateHeader::kResponseServerFailure:
+        ++mCounters.mServerFailureResponse;
+        break;
+    case UpdateHeader::kResponseFormatError:
+        ++mCounters.mFormatErrorResponse;
+        break;
+    case UpdateHeader::kResponseNameError:
+        ++mCounters.mNameErrorResponse;
+        break;
+    case UpdateHeader::kResponseNotImplemented:
+        ++mCounters.mNotImplementedResponse;
+        break;
+    default:
+        ++mCounters.mOtherResponse;
+        break;
+    }
+}
+
 } // namespace ServiceDiscovery
 } // namespace Dns
 } // namespace ot
diff --git a/src/core/net/dnssd_server.hpp b/src/core/net/dnssd_server.hpp
index 527a1ca..de16c42 100644
--- a/src/core/net/dnssd_server.hpp
+++ b/src/core/net/dnssd_server.hpp
@@ -35,6 +35,7 @@
 
 #include <openthread/dnssd_server.h>
 
+#include "common/as_core_type.hpp"
 #include "common/message.hpp"
 #include "common/non_copyable.hpp"
 #include "common/timer.hpp"
@@ -67,6 +68,14 @@
 
 public:
     /**
+     * This class contains the counters of the DNS-SD server.
+     *
+     */
+    class Counters : public otDnssdCounters, public Clearable<Counters>
+    {
+    };
+
+    /**
      * This enumeration specifies a DNS-SD query type.
      *
      */
@@ -136,9 +145,9 @@
     /**
      * This method acquires the next query in the server.
      *
-     * @param[in] aQuery            The query pointer. Pass nullptr to get the first query.
+     * @param[in] aQuery            The query pointer. Pass `nullptr` to get the first query.
      *
-     * @returns  A pointer to the query or nullptr if no more queries.
+     * @returns  A pointer to the query or `nullptr` if no more queries.
      *
      */
     const otDnssdQuery *GetNextQuery(const otDnssdQuery *aQuery) const;
@@ -146,14 +155,22 @@
     /**
      * This method acquires the DNS-SD query type and name for a specific query.
      *
-     * @param[in]   aQuery            The query pointer.
-     * @param[out]  aNameOutput       The name output buffer.
+     * @param[in]   aQuery      The query pointer.
+     * @param[out]  aName       The name output buffer.
      *
      * @returns The DNS-SD query type.
      *
      */
     static DnsQueryType GetQueryTypeAndName(const otDnssdQuery *aQuery, char (&aName)[Name::kMaxNameSize]);
 
+    /**
+     * This method returns the counters of the DNS-SD server.
+     *
+     * @returns  A reference to the `Counters` instance.
+     *
+     */
+    const Counters &GetCounters(void) const { return mCounters; };
+
 private:
     class NameCompressInfo : public Clearable<NameCompressInfo>
     {
@@ -272,7 +289,7 @@
      * This class contains the compress information for a dns packet.
      *
      */
-    class QueryTransaction
+    class QueryTransaction : public InstanceLocatorInit
     {
     public:
         explicit QueryTransaction(void)
@@ -283,7 +300,8 @@
         void                    Init(const Header &          aResponseHeader,
                                      Message &               aResponseMessage,
                                      const NameCompressInfo &aCompressInfo,
-                                     const Ip6::MessageInfo &aMessageInfo);
+                                     const Ip6::MessageInfo &aMessageInfo,
+                                     Instance &              aInstance);
         bool                    IsValid(void) const { return mResponseMessage != nullptr; }
         const Ip6::MessageInfo &GetMessageInfo(void) const { return mMessageInfo; }
         const Header &          GetResponseHeader(void) const { return mResponseHeader; }
@@ -346,7 +364,7 @@
     static void             IncResourceRecordCount(Header &aHeader, bool aAdditional);
     static Error            FindNameComponents(const char *aName, const char *aDomain, NameComponentsOffsetInfo &aInfo);
     static Error            FindPreviousLabel(const char *aName, uint8_t &aStart, uint8_t &aStop);
-    static void             SendResponse(Header                  aHeader,
+    void                    SendResponse(Header                  aHeader,
                                          Header::Response        aResponseCode,
                                          Message &               aMessage,
                                          const Ip6::MessageInfo &aMessageInfo,
@@ -391,8 +409,10 @@
     void        HandleTimer(void);
     void        ResetTimer(void);
 
-    static const char kDnssdProtocolUdp[4];
-    static const char kDnssdProtocolTcp[4];
+    void UpdateResponseCounters(Header::Response aResponseCode);
+
+    static const char kDnssdProtocolUdp[];
+    static const char kDnssdProtocolTcp[];
     static const char kDnssdSubTypeLabel[];
     static const char kDefaultDomainName[];
     Ip6::Udp::Socket  mSocket;
@@ -402,10 +422,15 @@
     otDnssdQuerySubscribeCallback   mQuerySubscribe;
     otDnssdQueryUnsubscribeCallback mQueryUnsubscribe;
     TimerMilli                      mTimer;
+
+    Counters mCounters;
 };
 
 } // namespace ServiceDiscovery
 } // namespace Dns
+
+DefineMapEnum(otDnssdQueryType, Dns::ServiceDiscovery::Server::DnsQueryType);
+
 } // namespace ot
 
 #endif // OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
diff --git a/src/core/net/icmp6.cpp b/src/core/net/icmp6.cpp
index f417374..93542f6 100644
--- a/src/core/net/icmp6.cpp
+++ b/src/core/net/icmp6.cpp
@@ -37,7 +37,7 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/message.hpp"
 #include "net/checksum.hpp"
 #include "net/ip6.hpp"
@@ -45,6 +45,8 @@
 namespace ot {
 namespace Ip6 {
 
+RegisterLogModule("Icmp6");
+
 Icmp::Icmp(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mEchoSequence(1)
@@ -79,7 +81,7 @@
     aMessage.SetOffset(0);
     SuccessOrExit(error = Get<Ip6>().SendDatagram(aMessage, messageInfoLocal, kProtoIcmp6));
 
-    otLogInfoIcmp("Sent echo request: (seq = %d)", icmpHeader.GetSequence());
+    LogInfo("Sent echo request: (seq = %d)", icmpHeader.GetSequence());
 
 exit:
     return error;
@@ -87,36 +89,45 @@
 
 Error Icmp::SendError(Header::Type aType, Header::Code aCode, const MessageInfo &aMessageInfo, const Message &aMessage)
 {
+    Error   error;
+    Headers headers;
+
+    SuccessOrExit(error = headers.ParseFrom(aMessage));
+    error = SendError(aType, aCode, aMessageInfo, headers);
+
+exit:
+    return error;
+}
+
+Error Icmp::SendError(Header::Type aType, Header::Code aCode, const MessageInfo &aMessageInfo, const Headers &aHeaders)
+{
     Error             error = kErrorNone;
     MessageInfo       messageInfoLocal;
     Message *         message = nullptr;
     Header            icmp6Header;
-    ot::Ip6::Header   ip6Header;
     Message::Settings settings(Message::kWithLinkSecurity, Message::kPriorityNet);
 
-    SuccessOrExit(error = aMessage.Read(0, ip6Header));
-
-    if (ip6Header.GetNextHeader() == kProtoIcmp6)
+    if (aHeaders.GetIpProto() == kProtoIcmp6)
     {
-        SuccessOrExit(aMessage.Read(sizeof(ip6Header), icmp6Header));
-        VerifyOrExit(!icmp6Header.IsError());
+        VerifyOrExit(!aHeaders.GetIcmpHeader().IsError());
     }
 
     messageInfoLocal = aMessageInfo;
 
     VerifyOrExit((message = Get<Ip6>().NewMessage(0, settings)) != nullptr, error = kErrorNoBufs);
-    SuccessOrExit(error = message->SetLength(sizeof(icmp6Header) + sizeof(ip6Header)));
 
-    message->Write(sizeof(icmp6Header), ip6Header);
+    // Prepare the ICMPv6 error message. We only include the IPv6 header
+    // of the original message causing the error.
 
     icmp6Header.Clear();
     icmp6Header.SetType(aType);
     icmp6Header.SetCode(aCode);
-    message->Write(0, icmp6Header);
+    SuccessOrExit(error = message->Append(icmp6Header));
+    SuccessOrExit(error = message->Append(aHeaders.GetIp6Header()));
 
     SuccessOrExit(error = Get<Ip6>().SendDatagram(*message, messageInfoLocal, kProtoIcmp6));
 
-    otLogInfoIcmp("Sent ICMPv6 Error");
+    LogInfo("Sent ICMPv6 Error");
 
 exit:
     FreeMessageOnError(message, error);
@@ -182,14 +193,14 @@
     // always handle Echo Request destined for RLOC or ALOC
     VerifyOrExit(ShouldHandleEchoRequest(aMessageInfo) || aMessageInfo.GetSockAddr().GetIid().IsLocator());
 
-    otLogInfoIcmp("Received Echo Request");
+    LogInfo("Received Echo Request");
 
     icmp6Header.Clear();
     icmp6Header.SetType(Header::kTypeEchoReply);
 
     if ((replyMessage = Get<Ip6>().NewMessage(0)) == nullptr)
     {
-        otLogDebgIcmp("Failed to allocate a new message");
+        LogDebg("Failed to allocate a new message");
         ExitNow();
     }
 
@@ -210,7 +221,7 @@
     SuccessOrExit(error = Get<Ip6>().SendDatagram(*replyMessage, replyMessageInfo, kProtoIcmp6));
 
     IgnoreError(replyMessage->Read(replyMessage->GetOffset(), icmp6Header));
-    otLogInfoIcmp("Sent Echo Reply (seq = %d)", icmp6Header.GetSequence());
+    LogInfo("Sent Echo Reply (seq = %d)", icmp6Header.GetSequence());
 
 exit:
     FreeMessageOnError(replyMessage, error);
diff --git a/src/core/net/icmp6.hpp b/src/core/net/icmp6.hpp
index c23ba49..594da57 100644
--- a/src/core/net/icmp6.hpp
+++ b/src/core/net/icmp6.hpp
@@ -38,6 +38,7 @@
 
 #include <openthread/icmp6.h>
 
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/encoding.hpp"
 #include "common/linked_list.hpp"
@@ -60,6 +61,8 @@
  *
  */
 
+class Headers;
+
 /**
  * This class implements ICMPv6.
  *
@@ -239,7 +242,7 @@
      *
      * @param[in]  aReserved  The number of header bytes to reserve after the ICMP header.
      *
-     * @returns A pointer to the message or nullptr if no buffers are available.
+     * @returns A pointer to the message or `nullptr` if no buffers are available.
      *
      */
     Message *NewMessage(uint16_t aReserved);
@@ -284,6 +287,20 @@
     Error SendError(Header::Type aType, Header::Code aCode, const MessageInfo &aMessageInfo, const Message &aMessage);
 
     /**
+     * This method sends an ICMPv6 error message.
+     *
+     * @param[in]  aType         The ICMPv6 message type.
+     * @param[in]  aCode         The ICMPv6 message code.
+     * @param[in]  aMessageInfo  A reference to the message info.
+     * @param[in]  aHeaders      The parsed headers from the error-causing IPv6 message.
+     *
+     * @retval kErrorNone     Successfully enqueued the ICMPv6 error message.
+     * @retval kErrorNoBufs   Insufficient buffers available.
+     *
+     */
+    Error SendError(Header::Type aType, Header::Code aCode, const MessageInfo &aMessageInfo, const Headers &aHeaders);
+
+    /**
      * This method handles an ICMPv6 message.
      *
      * @param[in]  aMessage      A reference to the ICMPv6 message.
@@ -306,9 +323,9 @@
     otIcmp6EchoMode GetEchoMode(void) const { return mEchoMode; }
 
     /**
-     * This method sets whether or not ICMPv6 Echo processing is enabled.
+     * Sets the ICMPv6 echo mode.
      *
-     * @param[in]  aEnabled  TRUE to enable ICMPv6 Echo processing, FALSE otherwise.
+     * @param[in]  aMode  The ICMPv6 echo mode.
      *
      */
     void SetEchoMode(otIcmp6EchoMode aMode) { mEchoMode = aMode; }
@@ -345,6 +362,10 @@
  */
 
 } // namespace Ip6
+
+DefineCoreType(otIcmp6Header, Ip6::Icmp::Header);
+DefineCoreType(otIcmp6Handler, Ip6::Icmp::Handler);
+
 } // namespace ot
 
 #endif // ICMP6_HPP_
diff --git a/src/core/net/ip4_address.cpp b/src/core/net/ip4_address.cpp
deleted file mode 100644
index 6c9f322..0000000
--- a/src/core/net/ip4_address.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- *  Copyright (c) 2021, The OpenThread Authors.
- *  All rights reserved.
- *
- *  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, 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
- *   This file implements IPv4 address related functionality.
- */
-
-#include "ip4_address.hpp"
-
-#include "common/code_utils.hpp"
-#include "common/numeric_limits.hpp"
-
-namespace ot {
-namespace Ip4 {
-
-Error Address::FromString(const char *aString)
-{
-    constexpr char kSeperatorChar = '.';
-    constexpr char kNullChar      = '\0';
-
-    Error error = kErrorParse;
-
-    for (uint8_t index = 0;; index++)
-    {
-        uint16_t value         = 0;
-        uint8_t  hasFirstDigit = false;
-
-        for (char digitChar = *aString;; ++aString, digitChar = *aString)
-        {
-            if ((digitChar < '0') || (digitChar > '9'))
-            {
-                break;
-            }
-
-            value = static_cast<uint16_t>((value * 10) + static_cast<uint8_t>(digitChar - '0'));
-            VerifyOrExit(value <= NumericLimits<uint8_t>::kMax);
-            hasFirstDigit = true;
-        }
-
-        VerifyOrExit(hasFirstDigit);
-
-        mBytes[index] = static_cast<uint8_t>(value);
-
-        if (index == sizeof(Address) - 1)
-        {
-            break;
-        }
-
-        VerifyOrExit(*aString == kSeperatorChar);
-        aString++;
-    }
-
-    VerifyOrExit(*aString == kNullChar);
-    error = kErrorNone;
-
-exit:
-    return error;
-}
-
-Address::InfoString Address::ToString(void) const
-{
-    InfoString string;
-
-    string.Append("%d.%d.%d.%d", mBytes[0], mBytes[1], mBytes[2], mBytes[3]);
-
-    return string;
-}
-
-} // namespace Ip4
-} // namespace ot
diff --git a/src/core/net/ip4_address.hpp b/src/core/net/ip4_address.hpp
deleted file mode 100644
index fa1a013..0000000
--- a/src/core/net/ip4_address.hpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- *  Copyright (c) 2021, The OpenThread Authors.
- *  All rights reserved.
- *
- *  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, 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
- *   This file includes definitions for IPv4 addresses.
- */
-
-#ifndef IP4_ADDRESS_HPP_
-#define IP4_ADDRESS_HPP_
-
-#include "openthread-core-config.h"
-
-#include "common/clearable.hpp"
-#include "common/equatable.hpp"
-#include "common/error.hpp"
-#include "common/string.hpp"
-
-namespace ot {
-namespace Ip4 {
-
-/**
- * This class represents an IPv4 address.
- *
- */
-OT_TOOL_PACKED_BEGIN
-class Address : public Equatable<Address>, public Clearable<Address>
-{
-public:
-    static constexpr uint16_t kSize              = 4;  ///< Size of an IPv4 Address (in bytes).
-    static constexpr uint16_t kAddressStringSize = 17; ///< String size used by `ToString()`.
-
-    /**
-     * This type defines the fixed-length `String` object returned from `ToString()`.
-     *
-     */
-    typedef String<kAddressStringSize> InfoString;
-
-    /**
-     * This method gets the IPv4 address as a pointer to a byte array.
-     *
-     * @returns A pointer to a byte array containing the IPv4 address.
-     *
-     */
-    const uint8_t *GetBytes(void) const { return mBytes; }
-
-    /**
-     * This method sets the IPv4 address from a given byte array.
-     *
-     * @param[in] aBuffer    Pointer to an array containing the IPv4 address. `kSize` bytes from the buffer
-     *                       are copied to form the IPv4 address.
-     *
-     */
-    void SetBytes(const uint8_t *aBuffer) { memcpy(mBytes, aBuffer, kSize); }
-
-    /**
-     * This method parses an IPv4 address string.
-     *
-     * The string MUST follow the quad-dotted notation of four decimal values (ranging from 0 to 255 each). For
-     * example, "127.0.0.1"
-     *
-     * @param[in]  aString        A pointer to the null-terminated string.
-     *
-     * @retval kErrorNone         Successfully parsed the IPv4 address string.
-     * @retval kErrorParse        Failed to parse the IPv4 address string.
-     *
-     */
-    Error FromString(const char *aString);
-
-    /**
-     * This method converts the IPv4 address to a string.
-     *
-     * The string format uses quad-dotted notation of four bytes in the address (e.g., "127.0.0.1").
-     *
-     * @returns An `InfoString` representing the IPv4 address.
-     *
-     */
-    InfoString ToString(void) const;
-
-private:
-    uint8_t mBytes[kSize];
-} OT_TOOL_PACKED_END;
-
-} // namespace Ip4
-} // namespace ot
-
-#endif // IP4_ADDRESS_HPP_
diff --git a/src/core/net/ip4_types.cpp b/src/core/net/ip4_types.cpp
new file mode 100644
index 0000000..a23f51e
--- /dev/null
+++ b/src/core/net/ip4_types.cpp
@@ -0,0 +1,175 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file implements IP4 headers processing.
+ */
+
+#include "ip4_types.hpp"
+#include "ip6_address.hpp"
+
+namespace ot {
+namespace Ip4 {
+
+Error Address::FromString(const char *aString)
+{
+    constexpr char kSeperatorChar = '.';
+    constexpr char kNullChar      = '\0';
+
+    Error error = kErrorParse;
+
+    for (uint8_t index = 0;; index++)
+    {
+        uint16_t value         = 0;
+        uint8_t  hasFirstDigit = false;
+
+        for (char digitChar = *aString;; ++aString, digitChar = *aString)
+        {
+            if ((digitChar < '0') || (digitChar > '9'))
+            {
+                break;
+            }
+
+            value = static_cast<uint16_t>((value * 10) + static_cast<uint8_t>(digitChar - '0'));
+            VerifyOrExit(value <= NumericLimits<uint8_t>::kMax);
+            hasFirstDigit = true;
+        }
+
+        VerifyOrExit(hasFirstDigit);
+
+        mFields.m8[index] = static_cast<uint8_t>(value);
+
+        if (index == sizeof(Address) - 1)
+        {
+            break;
+        }
+
+        VerifyOrExit(*aString == kSeperatorChar);
+        aString++;
+    }
+
+    VerifyOrExit(*aString == kNullChar);
+    error = kErrorNone;
+
+exit:
+    return error;
+}
+
+void Address::ExtractFromIp6Address(uint8_t aPrefixLength, const Ip6::Address &aIp6Address)
+{
+    // The prefix length must be 32, 40, 48, 56, 64, 96. IPv4 bytes are added
+    // after the prefix, skipping over the bits 64 to 71 (byte at `kSkipIndex`)
+    // which must be set to zero. The suffix is set to zero (per RFC 6502).
+    //
+    //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+    //    |PL| 0-------------32--40--48--56--64--72--80--88--96--104---------|
+    //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+    //    |32|     prefix    |v4(32)         | u | suffix                    |
+    //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+    //    |40|     prefix        |v4(24)     | u |(8)| suffix                |
+    //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+    //    |48|     prefix            |v4(16) | u | (16)  | suffix            |
+    //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+    //    |56|     prefix                |(8)| u |  v4(24)   | suffix        |
+    //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+    //    |64|     prefix                    | u |   v4(32)      | suffix    |
+    //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+    //    |96|     prefix                                    |    v4(32)     |
+    //    +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+
+    constexpr uint8_t kSkipIndex = 8;
+
+    uint8_t ip6Index;
+
+    OT_ASSERT(Ip6::Prefix::IsValidNat64PrefixLength(aPrefixLength));
+
+    ip6Index = aPrefixLength / CHAR_BIT;
+
+    for (uint8_t i = 0; i < Ip4::Address::kSize; i++)
+    {
+        if (ip6Index == kSkipIndex)
+        {
+            ip6Index++;
+        }
+
+        mFields.m8[i] = aIp6Address.GetBytes()[ip6Index++];
+    }
+}
+
+void Address::SynthesizeFromCidrAndHost(const Cidr &aCidr, const uint32_t aHost)
+{
+    mFields.m32 = (aCidr.mAddress.mFields.m32 & aCidr.SubnetMask()) | (HostSwap32(aHost) & aCidr.HostMask());
+}
+
+Address::InfoString Address::ToString(void) const
+{
+    InfoString string;
+
+    string.Append("%d.%d.%d.%d", mFields.m8[0], mFields.m8[1], mFields.m8[2], mFields.m8[3]);
+
+    return string;
+}
+
+Cidr::InfoString Cidr::ToString(void) const
+{
+    InfoString string;
+
+    string.Append("%s/%d", AsCoreType(&mAddress).ToString().AsCString(), mLength);
+
+    return string;
+}
+
+bool Cidr::operator==(const Cidr &aOther) const
+{
+    return (mLength == aOther.mLength) &&
+           (Ip6::Prefix::MatchLength(GetBytes(), aOther.GetBytes(), Ip4::Address::kSize) >= mLength);
+}
+
+void Cidr::Set(const uint8_t *aAddress, uint8_t aLength)
+{
+    memcpy(mAddress.mFields.m8, aAddress, Ip4::Address::kSize);
+    mLength = aLength;
+}
+
+Error Header::ParseFrom(const Message &aMessage)
+{
+    Error error = kErrorParse;
+
+    SuccessOrExit(aMessage.Read(0, *this));
+    VerifyOrExit(IsValid());
+    VerifyOrExit(GetTotalLength() == aMessage.GetLength());
+
+    error = kErrorNone;
+
+exit:
+    return error;
+}
+
+} // namespace Ip4
+} // namespace ot
diff --git a/src/core/net/ip4_types.hpp b/src/core/net/ip4_types.hpp
new file mode 100644
index 0000000..042e4ca
--- /dev/null
+++ b/src/core/net/ip4_types.hpp
@@ -0,0 +1,672 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes definitions for IPv4 packet processing.
+ */
+
+#ifndef IP4_TYPES_HPP_
+#define IP4_TYPES_HPP_
+
+#include "openthread-core-config.h"
+
+#include <stddef.h>
+
+#include <openthread/nat64.h>
+
+#include "common/clearable.hpp"
+#include "common/encoding.hpp"
+#include "common/message.hpp"
+#include "net/ip6_types.hpp"
+#include "net/netif.hpp"
+#include "net/socket.hpp"
+#include "net/tcp6.hpp"
+#include "net/udp6.hpp"
+
+namespace ot {
+
+namespace Ip6 {
+// Forward declaration for ExtractFromIp4Address
+class Address;
+} // namespace Ip6
+
+/**
+ * @namespace ot::Ip4
+ *
+ * @brief
+ *   This namespace includes definitions for IPv4 networking used by NAT64.
+ *
+ */
+namespace Ip4 {
+
+using Encoding::BigEndian::HostSwap16;
+using Encoding::BigEndian::HostSwap32;
+
+using Ecn = Ip6::Ecn;
+
+/**
+ * @addtogroup core-ipv4
+ *
+ * @brief
+ *   This module includes definitions for the IPv4 network layer.
+ *
+ */
+
+/**
+ * @addtogroup core-ip4-ip4
+ *
+ * @brief
+ *   This module includes definitions for IPv4 networking used by NAT64.
+ *
+ * @{
+ *
+ */
+
+// Forward declaration for Address::SynthesizeFromCidrAndHost
+class Cidr;
+
+/**
+ * This class represents an IPv4 address.
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class Address : public otIp4Address, public Equatable<Address>, public Clearable<Address>
+{
+public:
+    static constexpr uint16_t kSize              = 4;  ///< Size of an IPv4 Address (in bytes).
+    static constexpr uint16_t kAddressStringSize = 17; ///< String size used by `ToString()`.
+
+    /**
+     * This type defines the fixed-length `String` object returned from `ToString()`.
+     *
+     */
+    typedef String<kAddressStringSize> InfoString;
+
+    /**
+     * This method gets the IPv4 address as a pointer to a byte array.
+     *
+     * @returns A pointer to a byte array containing the IPv4 address.
+     *
+     */
+    const uint8_t *GetBytes(void) const { return mFields.m8; }
+
+    /**
+     * This method sets the IPv4 address from a given byte array.
+     *
+     * @param[in] aBuffer    Pointer to an array containing the IPv4 address. `kSize` bytes from the buffer
+     *                       are copied to form the IPv4 address.
+     *
+     */
+    void SetBytes(const uint8_t *aBuffer) { memcpy(mFields.m8, aBuffer, kSize); }
+
+    /**
+     * This method sets the IPv4 address by performing NAT64 address translation from a given IPv6 address as specified
+     * in RFC 6052.
+     *
+     * The NAT64 @p aPrefixLength MUST be one of the following values: 32, 40, 48, 56, 64, or 96, otherwise the behavior
+     * of this method is undefined.
+     *
+     * @param[in] aPrefixLength      The prefix length to use for IPv4/IPv6 translation.
+     * @param[in] aIp6Address  The IPv6 address to translate to IPv4.
+     *
+     */
+    void ExtractFromIp6Address(uint8_t aPrefixLength, const Ip6::Address &aIp6Address);
+
+    /**
+     * This method sets the IPv4 address from the given CIDR and the host field.
+     *
+     * @param[in] aCidr The CIDR for the IPv4 address.
+     * @param[in] aHost The host bits of the IPv4 address in host byte order. The aHost will be masked by host mask.
+     *
+     */
+    void SynthesizeFromCidrAndHost(const Cidr &aCidr, uint32_t aHost);
+
+    /**
+     * This method parses an IPv4 address string.
+     *
+     * The string MUST follow the quad-dotted notation of four decimal values (ranging from 0 to 255 each). For
+     * example, "127.0.0.1"
+     *
+     * @param[in]  aString        A pointer to the null-terminated string.
+     *
+     * @retval kErrorNone         Successfully parsed the IPv4 address string.
+     * @retval kErrorParse        Failed to parse the IPv4 address string.
+     *
+     */
+    Error FromString(const char *aString);
+
+    /**
+     * This method converts the IPv4 address to a string.
+     *
+     * The string format uses quad-dotted notation of four bytes in the address (e.g., "127.0.0.1").
+     *
+     * @returns An `InfoString` representing the IPv4 address.
+     *
+     */
+    InfoString ToString(void) const;
+} OT_TOOL_PACKED_END;
+
+/**
+ * This class represents an IPv4 CIDR block.
+ *
+ */
+class Cidr : public otIp4Cidr, public Unequatable<Cidr>, public Clearable<Address>
+{
+    friend class Address;
+
+public:
+    static constexpr uint16_t kCidrSuffixSize = 3; ///< Suffix to represent CIDR (/dd).
+
+    /**
+     * This type defines the fixed-length `String` object returned from `ToString()`.
+     *
+     */
+    typedef String<Address::kAddressStringSize + kCidrSuffixSize> InfoString;
+
+    /**
+     * This method converts the IPv4 CIDR to a string.
+     *
+     * The string format uses quad-dotted notation of four bytes in the address with the length of prefix (e.g.,
+     * "127.0.0.1/32").
+     *
+     * @returns An `InfoString` representing the IPv4 cidr.
+     *
+     */
+    InfoString ToString(void) const;
+
+    /**
+     * This method gets the prefix as a pointer to a byte array.
+     *
+     * @returns A pointer to a byte array containing the Prefix.
+     *
+     */
+    const uint8_t *GetBytes(void) const { return mAddress.mFields.m8; }
+
+    /**
+     * This method overloads operator `==` to evaluate whether or not two prefixes are equal.
+     *
+     * @param[in]  aOther  The other prefix to compare with.
+     *
+     * @retval TRUE   If the two prefixes are equal.
+     * @retval FALSE  If the two prefixes are not equal.
+     *
+     */
+    bool operator==(const Cidr &aOther) const;
+
+    /**
+     * This method sets the CIDR.
+     *
+     * @param[in] aAddress  A pointer to buffer containing the CIDR bytes. The length of aAddress should be 4 bytes.
+     * @param[in] aLength   The length of CIDR in bits.
+     *
+     */
+    void Set(const uint8_t *aAddress, uint8_t aLength);
+
+private:
+    uint32_t HostMask(void) const
+    {
+        // Note: Using LL suffix to make it a uint64 since /32 is a valid CIDR, and right shifting 32 bits is undefined
+        // for uint32.
+        return HostSwap32(0xffffffffLL >> mLength);
+    }
+
+    uint32_t SubnetMask(void) const { return ~HostMask(); }
+};
+
+/**
+ * This class implements IPv4 header generation and parsing.
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class Header : public Clearable<Header>
+{
+public:
+    static constexpr uint8_t kVersionIhlOffset         = 0;
+    static constexpr uint8_t kTrafficClassOffset       = 1;
+    static constexpr uint8_t kTotalLengthOffset        = 2;
+    static constexpr uint8_t kIdenficationOffset       = 4;
+    static constexpr uint8_t kFlagsFragmentOffset      = 6;
+    static constexpr uint8_t kTtlOffset                = 8;
+    static constexpr uint8_t kProtocolOffset           = 9;
+    static constexpr uint8_t kHeaderChecksumOffset     = 10;
+    static constexpr uint8_t kSourceAddressOffset      = 12;
+    static constexpr uint8_t kDestinationAddressOffset = 16;
+
+    /**
+     * This method indicates whether or not the header appears to be well-formed.
+     *
+     * @retval TRUE    If the header appears to be well-formed.
+     * @retval FALSE   If the header does not appear to be well-formed.
+     *
+     */
+    bool IsValid(void) const { return IsVersion4(); }
+
+    /**
+     * This method initializes the Version to 4 and sets Traffic Class and Flow fields to zero.
+     *
+     * The other fields in the IPv4 header remain unchanged.
+     *
+     */
+    void InitVersionIhl(void) { SetVersionIhl(kVersIhlInit); }
+
+    /**
+     * This method sets the version and Ihl of the IPv4 header.
+     *
+     * @param[in] aVersionIhl The octet for the version and Ihl field.
+     *
+     */
+    void SetVersionIhl(uint8_t aVersionIhl) { mVersIhl = aVersionIhl; }
+
+    /**
+     * This method indicates whether or not the IPv4 Version is set to 6.
+     *
+     * @retval TRUE   If the IPv4 Version is set to 4.
+     * @retval FALSE  If the IPv4 Version is not set to 4.
+     *
+     */
+    bool IsVersion4(void) const { return (mVersIhl & kVersionMask) == kVersion4; }
+
+    /**
+     * This method returns the octet for DSCP + ECN.
+     *
+     * @retval The octet for DSCP and ECN.
+     *
+     */
+    uint8_t GetDscpEcn(void) const { return mDscpEcn; }
+
+    /**
+     * This method gets the 6-bit Differentiated Services Code Point (DSCP) from Traffic Class field.
+     *
+     * @returns The DSCP value.
+     *
+     */
+    uint8_t GetDscp(void) const { return (mDscpEcn & kDscpMask) >> kDscpOffset; }
+
+    /**
+     * This method sets 6-bit Differentiated Services Code Point (DSCP) in IPv4 header.
+     *
+     * @param[in]  aDscp  The DSCP value.
+     *
+     */
+    void SetDscp(uint8_t aDscp) { mDscpEcn = static_cast<uint8_t>((mDscpEcn & ~kDscpMask) | (aDscp << kDscpOffset)); }
+
+    /**
+     * This method gets the 2-bit Explicit Congestion Notification (ECN) from Traffic Class field.
+     *
+     * @returns The ECN value.
+     *
+     */
+    Ecn GetEcn(void) const { return static_cast<Ecn>(mDscpEcn & kEcnMask); }
+
+    /**
+     * This method sets the 2-bit Explicit Congestion Notification (ECN) in IPv4 header..
+     *
+     * @param[in]  aEcn  The ECN value.
+     *
+     */
+    void SetEcn(Ecn aEcn) { mDscpEcn = ((mDscpEcn & ~kEcnMask) | aEcn); }
+
+    /**
+     * This method returns the IPv4 Payload Length value.
+     *
+     * @returns The IPv4 Payload Length value.
+     *
+     */
+    uint16_t GetTotalLength(void) const { return HostSwap16(mTotalLength); }
+
+    /**
+     * This method sets the IPv4 Payload Length value.
+     *
+     * @param[in]  aLength  The IPv4 Payload Length value.
+     *
+     */
+    void SetTotalLength(uint16_t aLength) { mTotalLength = HostSwap16(aLength); }
+
+    /**
+     * This method returns the IPv4 payload protocol.
+     *
+     * @returns The IPv4 payload protocol value.
+     *
+     */
+    uint8_t GetProtocol(void) const { return mProtocol; }
+
+    /**
+     * This method sets the IPv4 payload protocol.
+     *
+     * @param[in]  aProtocol  The IPv4 payload protocol.
+     *
+     */
+    void SetProtocol(uint8_t aProtocol) { mProtocol = aProtocol; }
+
+    /**
+     * This method returns the IPv4 header checksum, the checksum is in host endian.
+     *
+     * @returns The checksum field in the IPv4 header.
+     *
+     */
+    uint16_t GetChecksum(void) const { return HostSwap16(mHeaderChecksum); }
+
+    /**
+     * This method sets the IPv4 header checksum, the checksum is in host endian.
+     *
+     * @param[in] aChecksum The checksum for the IPv4 header.
+     *
+     */
+    void SetChecksum(uint16_t aChecksum) { mHeaderChecksum = HostSwap16(aChecksum); }
+
+    /**
+     * This method returns the IPv4 Identification value.
+     *
+     * @returns The IPv4 Identification value.
+     *
+     */
+    uint16_t GetIdentification(void) const { return HostSwap16(mIdentification); }
+
+    /**
+     * This method sets the IPv4 Identification value.
+     *
+     * @param[in] aIdentification The IPv4 Identification value.
+     *
+     */
+    void SetIdentification(uint16_t aIdentification) { mIdentification = HostSwap16(aIdentification); }
+
+    /**
+     * This method returns the IPv4 Time-to-Live value.
+     *
+     * @returns The IPv4 Time-to-Live value.
+     *
+     */
+    uint8_t GetTtl(void) const { return mTtl; }
+
+    /**
+     * This method sets the IPv4 Time-to-Live value.
+     *
+     * @param[in]  aTtl  The IPv4 Time-to-Live value.
+     *
+     */
+    void SetTtl(uint8_t aTtl) { mTtl = aTtl; }
+
+    /**
+     * This method returns the IPv4 Source address.
+     *
+     * @returns A reference to the IPv4 Source address.
+     *
+     */
+    Address &GetSource(void) { return mSource; }
+
+    /**
+     * This method returns the IPv4 Source address.
+     *
+     * @returns A reference to the IPv4 Source address.
+     *
+     */
+    const Address &GetSource(void) const { return mSource; }
+
+    /**
+     * This method sets the IPv4 Source address.
+     *
+     * @param[in]  aSource  A reference to the IPv4 Source address.
+     *
+     */
+    void SetSource(const Address &aSource) { mSource = aSource; }
+
+    /**
+     * This method returns the IPv4 Destination address.
+     *
+     * @returns A reference to the IPv4 Destination address.
+     *
+     */
+    Address &GetDestination(void) { return mDestination; }
+
+    /**
+     * This method returns the IPv4 Destination address.
+     *
+     * @returns A reference to the IPv4 Destination address.
+     *
+     */
+    const Address &GetDestination(void) const { return mDestination; }
+
+    /**
+     * This method sets the IPv4 Destination address.
+     *
+     * @param[in]  aDestination  A reference to the IPv4 Destination address.
+     *
+     */
+    void SetDestination(const Address &aDestination) { mDestination = aDestination; }
+
+    /**
+     * This method parses and validates the IPv4 header from a given message.
+     *
+     * The header is read from @p aMessage at offset zero.
+     *
+     * @param[in]  aMessage  The IPv4 message.
+     *
+     * @retval kErrorNone   Successfully parsed the IPv4 header from @p aMessage.
+     * @retval kErrorParse  Malformed IPv4 header or message (e.g., message does not contained expected payload length).
+     *
+     */
+    Error ParseFrom(const Message &aMessage);
+
+    /**
+     * This method returns the Df flag in the IPv4 header.
+     *
+     * @returns Whether don't fragment flag is set.
+     *
+     */
+    bool GetDf(void) const { return HostSwap16(mFlagsFargmentOffset) & kFlagsDf; }
+
+    /**
+     * This method returns the Mf flag in the IPv4 header.
+     *
+     * @returns Whether more fragments flag is set.
+     *
+     */
+    bool GetMf(void) const { return HostSwap16(mFlagsFargmentOffset) & kFlagsMf; }
+
+    /**
+     * This method returns the fragment offset in the IPv4 header.
+     *
+     * @returns The fragment offset of the IPv4 packet.
+     *
+     */
+    uint16_t GetFragmentOffset(void) const { return HostSwap16(mFlagsFargmentOffset) & kFragmentOffsetMask; }
+
+private:
+    // IPv4 header
+    //
+    // +---------------+---------------+---------------+---------------+
+    // |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
+    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    // |Version|  IHL  |    DSCP   |ECN|         Total Length          |
+    // |        Identification         |Flags|    Fragment Offset      |
+    // |      TTL      |    Protocol   |        Header Checksum        |
+    // |                       Source IP Address                       |
+    // |                         Dest IP Address                       |
+    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+    static constexpr uint8_t  kVersion4           = 0x40;   // Use with `mVersIhl`
+    static constexpr uint8_t  kVersionMask        = 0xf0;   // Use with `mVersIhl`
+    static constexpr uint8_t  kIhlMask            = 0x0f;   // Use with `mVersIhl`
+    static constexpr uint8_t  kDscpOffset         = 2;      // Use with `mDscpEcn`
+    static constexpr uint16_t kDscpMask           = 0xfc;   // Use with `mDscpEcn`
+    static constexpr uint8_t  kEcnOffset          = 0;      // Use with `mDscpEcn`
+    static constexpr uint8_t  kEcnMask            = 0x03;   // Use with `mDscpEcn`
+    static constexpr uint16_t kFlagsMask          = 0xe000; // Use with `mFlagsFragmentOffset`
+    static constexpr uint16_t kFlagsDf            = 0x4000; // Use with `mFlagsFragmentOffset`
+    static constexpr uint16_t kFlagsMf            = 0x2000; // Use with `mFlagsFragmentOffset`
+    static constexpr uint16_t kFragmentOffsetMask = 0x1fff; // Use with `mFlagsFragmentOffset`
+    static constexpr uint32_t kVersIhlInit        = 0x45;   // Version 4, Header length = 5x8 bytes.
+
+    uint8_t  mVersIhl;
+    uint8_t  mDscpEcn;
+    uint16_t mTotalLength;
+    uint16_t mIdentification;
+    uint16_t mFlagsFargmentOffset;
+    uint8_t  mTtl;
+    uint8_t  mProtocol;
+    uint16_t mHeaderChecksum;
+    Address  mSource;
+    Address  mDestination;
+} OT_TOOL_PACKED_END;
+
+/**
+ * This class implements ICMP(v4).
+ * Note: ICMP(v4) messages will only be generated / handled by NAT64. So only header defination is required.
+ *
+ */
+class Icmp
+{
+public:
+    /**
+     * This class represents an IPv4 ICMP header.
+     *
+     */
+    OT_TOOL_PACKED_BEGIN
+    class Header : public Clearable<Header>
+    {
+    public:
+        static constexpr uint16_t kChecksumFieldOffset = 2;
+        // A few ICMP types, only the ICMP types work with NAT64 are listed here.
+        enum Type : uint8_t
+        {
+            kTypeEchoReply              = 0,
+            kTypeDestinationUnreachable = 3,
+            kTypeEchoRequest            = 8,
+            kTypeTimeExceeded           = 11,
+        };
+
+        enum Code : uint8_t
+        {
+            kCodeNone = 0,
+            // Destination Unreachable codes
+            kCodeNetworkUnreachable  = 0,
+            kCodeHostUnreachable     = 1,
+            kCodeProtocolUnreachable = 2,
+            kCodePortUnreachable     = 3,
+            kCodeSourceRouteFailed   = 5,
+            kCodeNetworkUnknown      = 6,
+            kCodeHostUnknown         = 7,
+        };
+
+        /**
+         * This method returns the type of the ICMP message.
+         *
+         * @returns The type field of the ICMP message.
+         *
+         */
+        uint8_t GetType(void) const { return mType; }
+
+        /**
+         * This method sets the type of the ICMP message.
+         *
+         * @param[in] aType The type of the ICMP message.
+         *
+         */
+        void SetType(uint8_t aType) { mType = aType; }
+
+        /**
+         * This method returns the code of the ICMP message.
+         *
+         * @returns The code field of the ICMP message.
+         *
+         */
+        uint8_t GetCode(void) const { return mCode; }
+
+        /**
+         * This method sets the code of the ICMP message.
+         *
+         * @param[in] aCode The code of the ICMP message.
+         *
+         */
+        void SetCode(uint8_t aCode) { mCode = aCode; }
+
+        /**
+         * This method sets the checksum field in the ICMP message.
+         *
+         * @returns The checksum of the ICMP message.
+         *
+         */
+        uint16_t GetChecksum(void) const { return HostSwap16(mChecksum); }
+
+        /**
+         * This method sets the checksum field in the ICMP message.
+         *
+         * @param[in] aChecksum The checksum of the ICMP message.
+         *
+         */
+        void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); }
+
+        /**
+         * This method returns the rest of header field in the ICMP message.
+         *
+         * @returns The rest of header field in the ICMP message. The returned buffer has 4 octets.
+         *
+         */
+        const uint8_t *GetRestOfHeader(void) const { return mRestOfHeader; }
+
+        /**
+         * This method sets the rest of header field in the ICMP message.
+         *
+         * @param[in] aRestOfHeader The rest of header field in the ICMP message. The buffer should have 4 octets.
+         *
+         */
+        void SetRestOfHeader(const uint8_t *aRestOfheader)
+        {
+            memcpy(mRestOfHeader, aRestOfheader, sizeof(mRestOfHeader));
+        }
+
+    private:
+        uint8_t  mType;
+        uint8_t  mCode;
+        uint16_t mChecksum;
+        uint8_t  mRestOfHeader[4];
+    } OT_TOOL_PACKED_END;
+};
+
+// Internet Protocol Numbers
+static constexpr uint8_t kProtoTcp  = Ip6::kProtoTcp; ///< Transmission Control Protocol
+static constexpr uint8_t kProtoUdp  = Ip6::kProtoUdp; ///< User Datagram
+static constexpr uint8_t kProtoIcmp = 1;              ///< ICMP for IPv4
+
+using Tcp = Ip6::Tcp; // TCP in IPv4 is the same as TCP in IPv6
+using Udp = Ip6::Udp; // UDP in IPv4 is the same as UDP in IPv6
+
+/**
+ * @}
+ *
+ */
+
+} // namespace Ip4
+
+DefineCoreType(otIp4Address, Ip4::Address);
+DefineCoreType(otIp4Cidr, Ip4::Cidr);
+
+} // namespace ot
+
+#endif // IP4_TYPES_HPP_
diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp
index d028ca2..bb3096f 100644
--- a/src/core/net/ip6.cpp
+++ b/src/core/net/ip6.cpp
@@ -40,7 +40,7 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/message.hpp"
 #include "common/random.hpp"
 #include "net/checksum.hpp"
@@ -62,6 +62,8 @@
 namespace ot {
 namespace Ip6 {
 
+RegisterLogModule("Ip6");
+
 Ip6::Ip6(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mForwardingEnabled(false)
@@ -80,13 +82,13 @@
 
 Message *Ip6::NewMessage(uint16_t aReserved, const Message::Settings &aSettings)
 {
-    return Get<MessagePool>().New(Message::kTypeIp6,
-                                  sizeof(Header) + sizeof(HopByHopHeader) + sizeof(OptionMpl) + aReserved, aSettings);
+    return Get<MessagePool>().Allocate(
+        Message::kTypeIp6, sizeof(Header) + sizeof(HopByHopHeader) + sizeof(OptionMpl) + aReserved, aSettings);
 }
 
 Message *Ip6::NewMessage(const uint8_t *aData, uint16_t aDataLength, const Message::Settings &aSettings)
 {
-    Message *message = Get<MessagePool>().New(Message::kTypeIp6, 0, aSettings);
+    Message *message = Get<MessagePool>().Allocate(Message::kTypeIp6, /* aReserveHeader */ 0, aSettings);
 
     VerifyOrExit(message != nullptr);
 
@@ -227,7 +229,7 @@
     // Use IP-in-IP encapsulation (RFC2473) and ALL_MPL_FORWARDERS address.
     messageInfo.GetPeerAddr().SetToRealmLocalAllMplForwarders();
 
-    tunnelHeader.Init();
+    tunnelHeader.InitVersionTrafficClassFlow();
     tunnelHeader.SetHopLimit(static_cast<uint8_t>(kDefaultHopLimit));
     tunnelHeader.SetPayloadLength(aHeader.GetPayloadLength() + sizeof(tunnelHeader));
     tunnelHeader.SetDestination(messageInfo.GetPeerAddr());
@@ -262,7 +264,7 @@
             OptionMpl      mplOption;
 
             // read existing hop-by-hop option header
-            IgnoreError(aMessage.Read(0, hbh));
+            SuccessOrExit(error = aMessage.Read(0, hbh));
             hbhLength = (hbh.GetLength() + 1) * 8;
 
             VerifyOrExit(hbhLength <= aHeader.GetPayloadLength(), error = kErrorParse);
@@ -307,12 +309,12 @@
 
             if ((messageCopy = aMessage.Clone()) != nullptr)
             {
-                IgnoreError(HandleDatagram(*messageCopy, nullptr, nullptr, true));
-                otLogInfoIp6("Message copy for indirect transmission to sleepy children");
+                IgnoreError(HandleDatagram(*messageCopy, nullptr, nullptr, /* aFromHost */ true));
+                LogInfo("Message copy for indirect transmission to sleepy children");
             }
             else
             {
-                otLogWarnIp6("No enough buffer for message copy for indirect transmission to sleepy children");
+                LogWarn("No enough buffer for message copy for indirect transmission to sleepy children");
             }
         }
 #endif
@@ -452,9 +454,9 @@
     Header   header;
     uint16_t payloadLength = aMessage.GetLength();
 
-    header.Init();
+    header.InitVersionTrafficClassFlow();
     header.SetDscp(PriorityToDscp(aMessage.GetPriority()));
-    header.SetEcn(aMessageInfo.mEcn);
+    header.SetEcn(aMessageInfo.GetEcn());
     header.SetPayloadLength(payloadLength);
     header.SetNextHeader(aIpProto);
 
@@ -499,12 +501,12 @@
 
             if (messageCopy != nullptr)
             {
-                otLogInfoIp6("Message copy for indirect transmission to sleepy children");
+                LogInfo("Message copy for indirect transmission to sleepy children");
                 EnqueueDatagram(*messageCopy);
             }
             else
             {
-                otLogWarnIp6("No enough buffer for message copy for indirect transmission to sleepy children");
+                LogWarn("No enough buffer for message copy for indirect transmission to sleepy children");
             }
         }
 #endif
@@ -540,7 +542,7 @@
     while ((message = mSendQueue.GetHead()) != nullptr)
     {
         mSendQueue.Dequeue(*message);
-        IgnoreError(HandleDatagram(*message, nullptr, nullptr, false));
+        IgnoreError(HandleDatagram(*message, nullptr, nullptr, /* aFromHost */ false));
     }
 }
 
@@ -637,7 +639,7 @@
             payloadFragment = payloadLeft;
             payloadLeft     = 0;
 
-            otLogDebgIp6("Last Fragment");
+            LogDebg("Last Fragment");
         }
         else
         {
@@ -649,6 +651,7 @@
         fragmentHeader.SetOffset(offset);
 
         VerifyOrExit((fragment = NewMessage(0)) != nullptr, error = kErrorNoBufs);
+        IgnoreError(fragment->SetPriority(aMessage.GetPriority()));
         SuccessOrExit(error = fragment->SetLength(aMessage.GetOffset() + sizeof(fragmentHeader) + payloadFragment));
 
         header.SetPayloadLength(payloadFragment + sizeof(fragmentHeader));
@@ -667,7 +670,7 @@
         fragmentCnt++;
         fragment = nullptr;
 
-        otLogInfoIp6("Fragment %d with %d bytes sent", fragmentCnt, payloadFragment);
+        LogInfo("Fragment %d with %d bytes sent", fragmentCnt, payloadFragment);
     }
 
     aMessage.Free();
@@ -676,14 +679,14 @@
 
     if (error == kErrorNoBufs)
     {
-        otLogWarnIp6("No buffer for Ip6 fragmentation");
+        LogWarn("No buffer for Ip6 fragmentation");
     }
 
     FreeMessageOnError(fragment, error);
     return error;
 }
 
-Error Ip6::HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromNcpHost)
+Error Ip6::HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromHost)
 {
     Error          error = kErrorNone;
     Header         header, headerBuffer;
@@ -706,13 +709,14 @@
         ExitNow();
     }
 
-    for (message = mReassemblyList.GetHead(); message; message = message->GetNext())
+    for (Message &msg : mReassemblyList)
     {
-        SuccessOrExit(error = message->Read(0, headerBuffer));
+        SuccessOrExit(error = msg.Read(0, headerBuffer));
 
-        if (message->GetDatagramTag() == fragmentHeader.GetIdentification() &&
+        if (msg.GetDatagramTag() == fragmentHeader.GetIdentification() &&
             headerBuffer.GetSource() == header.GetSource() && headerBuffer.GetDestination() == header.GetDestination())
         {
+            message = &msg;
             break;
         }
     }
@@ -720,23 +724,23 @@
     offset          = FragmentHeader::FragmentOffsetToBytes(fragmentHeader.GetOffset());
     payloadFragment = aMessage.GetLength() - aMessage.GetOffset() - sizeof(fragmentHeader);
 
-    otLogInfoIp6("Fragment with id %d received > %d bytes, offset %d", fragmentHeader.GetIdentification(),
-                 payloadFragment, offset);
+    LogInfo("Fragment with id %d received > %d bytes, offset %d", fragmentHeader.GetIdentification(), payloadFragment,
+            offset);
 
     if (offset + payloadFragment + aMessage.GetOffset() > kMaxAssembledDatagramLength)
     {
-        otLogWarnIp6("Packet too large for fragment buffer");
+        LogWarn("Packet too large for fragment buffer");
         ExitNow(error = kErrorNoBufs);
     }
 
     if (message == nullptr)
     {
-        otLogDebgIp6("start reassembly");
+        LogDebg("start reassembly");
         VerifyOrExit((message = NewMessage(0)) != nullptr, error = kErrorNoBufs);
         mReassemblyList.Enqueue(*message);
         SuccessOrExit(error = message->SetLength(aMessage.GetOffset()));
 
-        message->SetTimeout(kIp6ReassemblyTimeout);
+        message->SetTimestampToNow();
         message->SetOffset(0);
         message->SetDatagramTag(fragmentHeader.GetIdentification());
 
@@ -770,11 +774,11 @@
         header.SetNextHeader(fragmentHeader.GetNextHeader());
         message->Write(0, header);
 
-        otLogDebgIp6("Reassembly complete.");
+        LogDebg("Reassembly complete.");
 
         mReassemblyList.Dequeue(*message);
 
-        IgnoreError(HandleDatagram(*message, aNetif, aMessageInfo.mLinkInfo, aFromNcpHost));
+        IgnoreError(HandleDatagram(*message, aNetif, aMessageInfo.mLinkInfo, aFromHost));
     }
 
 exit:
@@ -785,7 +789,7 @@
             mReassemblyList.DequeueAndFree(*message);
         }
 
-        otLogWarnIp6("Reassembly failed: %s", ErrorToString(error));
+        LogWarn("Reassembly failed: %s", ErrorToString(error));
     }
 
     if (isFragmented)
@@ -814,22 +818,16 @@
 
 void Ip6::UpdateReassemblyList(void)
 {
-    Message *next;
+    TimeMilli now = TimerMilli::GetNow();
 
-    for (Message *message = mReassemblyList.GetHead(); message; message = next)
+    for (Message &message : mReassemblyList)
     {
-        next = message->GetNext();
-
-        if (message->GetTimeout() > 0)
+        if (now - message.GetTimestamp() >= TimeMilli::SecToMsec(kIp6ReassemblyTimeout))
         {
-            message->DecrementTimeout();
-        }
-        else
-        {
-            otLogNoteIp6("Reassembly timeout.");
-            SendIcmpError(*message, Icmp::Header::kTypeTimeExceeded, Icmp::Header::kCodeFragmReasTimeEx);
+            LogNote("Reassembly timeout.");
+            SendIcmpError(message, Icmp::Header::kTypeTimeExceeded, Icmp::Header::kCodeFragmReasTimeEx);
 
-            mReassemblyList.DequeueAndFree(*message);
+            mReassemblyList.DequeueAndFree(message);
         }
     }
 }
@@ -853,7 +851,7 @@
 
     if (error != kErrorNone)
     {
-        otLogWarnIp6("Failed to send ICMP error: %s", ErrorToString(error));
+        LogWarn("Failed to send ICMP error: %s", ErrorToString(error));
     }
 }
 
@@ -867,11 +865,11 @@
     return kErrorNone;
 }
 
-Error Ip6::HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromNcpHost)
+Error Ip6::HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromHost)
 {
     OT_UNUSED_VARIABLE(aNetif);
     OT_UNUSED_VARIABLE(aMessageInfo);
-    OT_UNUSED_VARIABLE(aFromNcpHost);
+    OT_UNUSED_VARIABLE(aFromHost);
 
     Error          error = kErrorNone;
     FragmentHeader fragmentHeader;
@@ -893,7 +891,7 @@
                                   Header &     aHeader,
                                   uint8_t &    aNextHeader,
                                   bool         aIsOutbound,
-                                  bool         aFromNcpHost,
+                                  bool         aFromHost,
                                   bool &       aReceive)
 {
     Error           error = kErrorNone;
@@ -910,11 +908,11 @@
             break;
 
         case kProtoFragment:
-            // Always forward IPv6 fragments to the Host.
-            IgnoreError(ProcessReceiveCallback(aMessage, aMessageInfo, aNextHeader, aFromNcpHost,
+#if !OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
+            IgnoreError(ProcessReceiveCallback(aMessage, aMessageInfo, aNextHeader, aFromHost,
                                                /* aAllowReceiveFilter */ false, Message::kCopyToUse));
-
-            SuccessOrExit(error = HandleFragment(aMessage, aNetif, aMessageInfo, aFromNcpHost));
+#endif
+            SuccessOrExit(error = HandleFragment(aMessage, aNetif, aMessageInfo, aFromHost));
             break;
 
         case kProtoDstOpts:
@@ -966,7 +964,7 @@
         error = mTcp.HandleMessage(aIp6Header, *message, aMessageInfo);
         if (error == kErrorDrop)
         {
-            otLogNoteIp6("Error TCP Checksum");
+            LogNote("Error TCP Checksum");
         }
         break;
 #endif
@@ -974,7 +972,7 @@
         error = mUdp.HandleMessage(*message, aMessageInfo);
         if (error == kErrorDrop)
         {
-            otLogNoteIp6("Error UDP Checksum");
+            LogNote("Error UDP Checksum");
         }
         break;
 
@@ -989,7 +987,7 @@
 exit:
     if (error != kErrorNone)
     {
-        otLogNoteIp6("Failed to handle payload: %s", ErrorToString(error));
+        LogNote("Failed to handle payload: %s", ErrorToString(error));
     }
 
     FreeMessage(message);
@@ -1000,14 +998,14 @@
 Error Ip6::ProcessReceiveCallback(Message &          aMessage,
                                   const MessageInfo &aMessageInfo,
                                   uint8_t            aIpProto,
-                                  bool               aFromNcpHost,
+                                  bool               aFromHost,
                                   bool               aAllowReceiveFilter,
                                   Message::Ownership aMessageOwnership)
 {
     Error    error   = kErrorNone;
     Message *message = &aMessage;
 
-    VerifyOrExit(!aFromNcpHost, error = kErrorNoRoute);
+    VerifyOrExit(!aFromHost, error = kErrorNoRoute);
     VerifyOrExit(mReceiveIp6DatagramCallback != nullptr, error = kErrorNoRoute);
 
     // Do not forward reassembled IPv6 packets.
@@ -1064,7 +1062,7 @@
 
         if (message == nullptr)
         {
-            otLogWarnIp6("No buff to clone msg (len: %d) to pass to host", aMessage.GetLength());
+            LogWarn("No buff to clone msg (len: %d) to pass to host", aMessage.GetLength());
             ExitNow(error = kErrorNoBufs);
         }
 
@@ -1084,14 +1082,14 @@
     return error;
 }
 
-Error Ip6::SendRaw(Message &aMessage)
+Error Ip6::SendRaw(Message &aMessage, bool aFromHost)
 {
     Error       error = kErrorNone;
     Header      header;
     MessageInfo messageInfo;
     bool        freed = false;
 
-    SuccessOrExit(error = header.Init(aMessage));
+    SuccessOrExit(error = header.ParseFrom(aMessage));
     VerifyOrExit(!header.GetSource().IsMulticast(), error = kErrorInvalidSourceAddress);
 
     messageInfo.SetPeerAddr(header.GetSource());
@@ -1103,7 +1101,7 @@
         SuccessOrExit(error = InsertMplOption(aMessage, header, messageInfo));
     }
 
-    error = HandleDatagram(aMessage, nullptr, nullptr, true);
+    error = HandleDatagram(aMessage, nullptr, nullptr, aFromHost);
     freed = true;
 
 exit:
@@ -1116,7 +1114,7 @@
     return error;
 }
 
-Error Ip6::HandleDatagram(Message &aMessage, Netif *aNetif, const void *aLinkMessageInfo, bool aFromNcpHost)
+Error Ip6::HandleDatagram(Message &aMessage, Netif *aNetif, const void *aLinkMessageInfo, bool aFromHost)
 {
     Error       error;
     MessageInfo messageInfo;
@@ -1133,12 +1131,13 @@
     forwardHost       = false;
     shouldFreeMessage = true;
 
-    SuccessOrExit(error = header.Init(aMessage));
+    SuccessOrExit(error = header.ParseFrom(aMessage));
 
     messageInfo.Clear();
     messageInfo.SetPeerAddr(header.GetSource());
     messageInfo.SetSockAddr(header.GetDestination());
     messageInfo.SetHopLimit(header.GetHopLimit());
+    messageInfo.SetEcn(header.GetEcn());
     messageInfo.SetLinkInfo(aLinkMessageInfo);
 
     // determine destination of packet
@@ -1192,7 +1191,7 @@
             forwardThread = true;
         }
 
-        if (forwardThread && !ShouldForwardToThread(messageInfo, aFromNcpHost))
+        if (forwardThread && !ShouldForwardToThread(messageInfo, aFromHost))
         {
             forwardThread = false;
             forwardHost   = true;
@@ -1204,7 +1203,7 @@
     // process IPv6 Extension Headers
     nextHeader = static_cast<uint8_t>(header.GetNextHeader());
     SuccessOrExit(error = HandleExtensionHeaders(aMessage, aNetif, messageInfo, header, nextHeader, aNetif == nullptr,
-                                                 aFromNcpHost, receive));
+                                                 aFromHost, receive));
 
     // process IPv6 Payload
     if (receive)
@@ -1213,26 +1212,11 @@
         {
             // Remove encapsulating header and start over.
             aMessage.RemoveHeader(aMessage.GetOffset());
+            Get<MeshForwarder>().LogMessage(MeshForwarder::kMessageReceive, aMessage);
             goto start;
         }
 
-#if OPENTHREAD_CONFIG_UNSECURE_TRAFFIC_MANAGED_BY_STACK_ENABLE
-        if (nextHeader == kProtoTcp || nextHeader == kProtoUdp)
-        {
-            uint16_t dstPort;
-
-            // TCP/UDP shares header uint16_t srcPort, uint16_t dstPort
-            SuccessOrExit(error = aMessage.Read(aMessage.GetOffset() + sizeof(uint16_t), dstPort));
-            dstPort = HostSwap16(dstPort);
-
-            if (aMessage.IsLinkSecurityEnabled() && Get<Filter>().IsUnsecurePort(dstPort))
-            {
-                IgnoreError(Get<Filter>().RemoveUnsecurePort(dstPort));
-            }
-        }
-#endif
-
-        error = ProcessReceiveCallback(aMessage, messageInfo, nextHeader, aFromNcpHost,
+        error = ProcessReceiveCallback(aMessage, messageInfo, nextHeader, aFromHost,
                                        /* aAllowReceiveFilter */ !forwardHost, Message::kCopyToUse);
 
         if ((error == kErrorNone || error == kErrorNoRoute) && forwardHost)
@@ -1248,7 +1232,7 @@
     if (forwardHost)
     {
         // try passing to host
-        error = ProcessReceiveCallback(aMessage, messageInfo, nextHeader, aFromNcpHost, /* aAllowReceiveFilter */ false,
+        error = ProcessReceiveCallback(aMessage, messageInfo, nextHeader, aFromHost, /* aAllowReceiveFilter */ false,
                                        forwardThread ? Message::kCopyToUse : Message::kTakeCustody);
         shouldFreeMessage = forwardThread;
     }
@@ -1268,7 +1252,7 @@
         hopLimit = header.GetHopLimit();
         aMessage.Write(Header::kHopLimitFieldOffset, hopLimit);
 
-        if (aFromNcpHost && nextHeader == kProtoIcmp6)
+        if (nextHeader == kProtoIcmp6)
         {
             uint8_t icmpType;
             bool    isAllowedType = false;
@@ -1284,35 +1268,21 @@
             }
             VerifyOrExit(isAllowedType, error = kErrorDrop);
         }
-        if (aFromNcpHost && (nextHeader == kProtoTcp || nextHeader == kProtoUdp))
-        {
-            uint16_t sourcePort, destPort;
-
-            SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), sourcePort));
-            SuccessOrExit(error = aMessage.Read(aMessage.GetOffset() + sizeof(sourcePort), destPort));
-            sourcePort = HostSwap16(sourcePort);
-            destPort   = HostSwap16(destPort);
 
 #if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+        if (aFromHost && (nextHeader == kProtoUdp))
+        {
+            uint16_t destPort;
+
+            SuccessOrExit(error = aMessage.Read(aMessage.GetOffset() + Udp::Header::kDestPortFieldOffset, destPort));
+            destPort = HostSwap16(destPort);
+
             if (nextHeader == kProtoUdp)
             {
                 VerifyOrExit(Get<Udp>().ShouldUsePlatformUdp(destPort), error = kErrorDrop);
             }
-#else
-            OT_UNUSED_VARIABLE(destPort);
-#endif
-
-#if OPENTHREAD_CONFIG_UNSECURE_TRAFFIC_MANAGED_BY_STACK_ENABLE
-            // check whether source port is an unsecure port
-            if (Get<Filter>().IsUnsecurePort(sourcePort))
-            {
-                aMessage.SetLinkSecurityEnabled(false);
-                otLogInfoIp6("Disabled link security for packet to %s", header.GetDestination().ToString().AsCString());
-            }
-#else
-            OT_UNUSED_VARIABLE(sourcePort);
-#endif
         }
+#endif
 
 #if OPENTHREAD_CONFIG_MULTI_RADIO
         // Since the message will be forwarded, we clear the radio
@@ -1337,45 +1307,31 @@
     return error;
 }
 
-bool Ip6::ShouldForwardToThread(const MessageInfo &aMessageInfo, bool aFromNcpHost) const
+bool Ip6::ShouldForwardToThread(const MessageInfo &aMessageInfo, bool aFromHost) const
 {
-    OT_UNUSED_VARIABLE(aFromNcpHost);
+    bool shouldForward = false;
 
-    bool rval = false;
-
-    if (aMessageInfo.GetSockAddr().IsMulticast())
+    if (aMessageInfo.GetSockAddr().IsMulticast() || aMessageInfo.GetSockAddr().IsLinkLocal())
     {
-        // multicast
-        ExitNow(rval = true);
-    }
-    else if (aMessageInfo.GetSockAddr().IsLinkLocal())
-    {
-        // on-link link-local address
-        ExitNow(rval = true);
+        shouldForward = true;
     }
     else if (IsOnLink(aMessageInfo.GetSockAddr()))
     {
-        // on-link global address
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
-        ExitNow(rval = (aFromNcpHost ||
-                        !Get<BackboneRouter::Manager>().ShouldForwardDuaToBackbone(aMessageInfo.GetSockAddr())));
+        shouldForward =
+            (aFromHost || !Get<BackboneRouter::Manager>().ShouldForwardDuaToBackbone(aMessageInfo.GetSockAddr()));
 #else
-        ExitNow(rval = true);
+        OT_UNUSED_VARIABLE(aFromHost);
+        shouldForward = true;
 #endif
     }
     else if (Get<ThreadNetif>().RouteLookup(aMessageInfo.GetPeerAddr(), aMessageInfo.GetSockAddr(), nullptr) ==
              kErrorNone)
     {
-        // route
-        ExitNow(rval = true);
-    }
-    else
-    {
-        ExitNow(rval = false);
+        shouldForward = true;
     }
 
-exit:
-    return rval;
+    return shouldForward;
 }
 
 const Netif::UnicastAddress *Ip6::SelectSourceAddress(MessageInfo &aMessageInfo)
@@ -1509,55 +1465,201 @@
 
 const char *Ip6::IpProtoToString(uint8_t aIpProto)
 {
-    const char *retval;
+    static constexpr Stringify::Entry kIpProtoTable[] = {
+        {kProtoHopOpts, "HopOpts"}, {kProtoTcp, "TCP"},         {kProtoUdp, "UDP"},
+        {kProtoIp6, "IP6"},         {kProtoRouting, "Routing"}, {kProtoFragment, "Frag"},
+        {kProtoIcmp6, "ICMP6"},     {kProtoNone, "None"},       {kProtoDstOpts, "DstOpts"},
+    };
 
-    switch (aIpProto)
-    {
-    case kProtoHopOpts:
-        retval = "HopOpts";
-        break;
+    static_assert(Stringify::IsSorted(kIpProtoTable), "kIpProtoTable is not sorted");
 
-    case kProtoTcp:
-        retval = "TCP";
-        break;
+    return Stringify::Lookup(aIpProto, kIpProtoTable, "Unknown");
+}
 
-    case kProtoUdp:
-        retval = "UDP";
-        break;
+const char *Ip6::EcnToString(Ecn aEcn)
+{
+    static const char *const kEcnStrings[] = {
+        "no", // (0) kEcnNotCapable
+        "e1", // (1) kEcnCapable1  (ECT1)
+        "e0", // (2) kEcnCapable0  (ECT0)
+        "ce", // (3) kEcnMarked    (Congestion Encountered)
+    };
 
-    case kProtoIp6:
-        retval = "IP6";
-        break;
+    static_assert(0 == kEcnNotCapable, "kEcnNotCapable value is incorrect");
+    static_assert(1 == kEcnCapable1, "kEcnCapable1 value is incorrect");
+    static_assert(2 == kEcnCapable0, "kEcnCapable0 value is incorrect");
+    static_assert(3 == kEcnMarked, "kEcnMarked value is incorrect");
 
-    case kProtoRouting:
-        retval = "Routing";
-        break;
-
-    case kProtoFragment:
-        retval = "Frag";
-        break;
-
-    case kProtoIcmp6:
-        retval = "ICMP6";
-        break;
-
-    case kProtoNone:
-        retval = "None";
-        break;
-
-    case kProtoDstOpts:
-        retval = "DstOpts";
-        break;
-
-    default:
-        retval = "Unknown";
-        break;
-    }
-
-    return retval;
+    return kEcnStrings[aEcn];
 }
 
 // LCOV_EXCL_STOP
 
+//---------------------------------------------------------------------------------------------------------------------
+// Headers
+
+Error Headers::ParseFrom(const Message &aMessage)
+{
+    Error error = kErrorParse;
+
+    Clear();
+
+    SuccessOrExit(mIp6Header.ParseFrom(aMessage));
+
+    switch (mIp6Header.GetNextHeader())
+    {
+    case kProtoUdp:
+        SuccessOrExit(aMessage.Read(sizeof(Header), mHeader.mUdp));
+        break;
+    case kProtoTcp:
+        SuccessOrExit(aMessage.Read(sizeof(Header), mHeader.mTcp));
+        break;
+    case kProtoIcmp6:
+        SuccessOrExit(aMessage.Read(sizeof(Header), mHeader.mIcmp));
+        break;
+    default:
+        break;
+    }
+
+    error = kErrorNone;
+
+exit:
+    return error;
+}
+
+Error Headers::DecompressFrom(const Message &     aMessage,
+                              uint16_t            aOffset,
+                              const Mac::Address &aMacSource,
+                              const Mac::Address &aMacDest)
+{
+    static constexpr uint16_t kReadLength = Lowpan::FragmentHeader::kSubsequentFragmentHeaderSize + sizeof(Headers);
+
+    uint8_t   frameBuffer[kReadLength];
+    uint16_t  frameLength;
+    FrameData frameData;
+
+    frameLength = aMessage.ReadBytes(aOffset, frameBuffer, sizeof(frameBuffer));
+    frameData.Init(frameBuffer, frameLength);
+
+    return DecompressFrom(frameData, aMacSource, aMacDest, aMessage.GetInstance());
+}
+
+Error Headers::DecompressFrom(const FrameData &   aFrameData,
+                              const Mac::Address &aMacSource,
+                              const Mac::Address &aMacDest,
+                              Instance &          aInstance)
+{
+    Error                  error     = kErrorNone;
+    FrameData              frameData = aFrameData;
+    Lowpan::FragmentHeader fragmentHeader;
+    bool                   nextHeaderCompressed;
+
+    if (fragmentHeader.ParseFrom(frameData) == kErrorNone)
+    {
+        // Only the first fragment header is followed by a LOWPAN_IPHC header
+        VerifyOrExit(fragmentHeader.GetDatagramOffset() == 0, error = kErrorNotFound);
+    }
+
+    VerifyOrExit(Lowpan::Lowpan::IsLowpanHc(frameData), error = kErrorNotFound);
+
+    SuccessOrExit(error = aInstance.Get<Lowpan::Lowpan>().DecompressBaseHeader(mIp6Header, nextHeaderCompressed,
+                                                                               aMacSource, aMacDest, frameData));
+
+    switch (mIp6Header.GetNextHeader())
+    {
+    case kProtoUdp:
+        if (nextHeaderCompressed)
+        {
+            SuccessOrExit(error = aInstance.Get<Lowpan::Lowpan>().DecompressUdpHeader(mHeader.mUdp, frameData));
+        }
+        else
+        {
+            SuccessOrExit(error = frameData.Read(mHeader.mUdp));
+        }
+        break;
+
+    case kProtoTcp:
+        SuccessOrExit(error = frameData.Read(mHeader.mTcp));
+        break;
+
+    case kProtoIcmp6:
+        SuccessOrExit(error = frameData.Read(mHeader.mIcmp));
+        break;
+
+    default:
+        break;
+    }
+
+exit:
+    return error;
+}
+
+uint16_t Headers::GetSourcePort(void) const
+{
+    uint16_t port = 0;
+
+    switch (GetIpProto())
+    {
+    case kProtoUdp:
+        port = mHeader.mUdp.GetSourcePort();
+        break;
+
+    case kProtoTcp:
+        port = mHeader.mTcp.GetSourcePort();
+        break;
+
+    default:
+        break;
+    }
+
+    return port;
+}
+
+uint16_t Headers::GetDestinationPort(void) const
+{
+    uint16_t port = 0;
+
+    switch (GetIpProto())
+    {
+    case kProtoUdp:
+        port = mHeader.mUdp.GetDestinationPort();
+        break;
+
+    case kProtoTcp:
+        port = mHeader.mTcp.GetDestinationPort();
+        break;
+
+    default:
+        break;
+    }
+
+    return port;
+}
+
+uint16_t Headers::GetChecksum(void) const
+{
+    uint16_t checksum = 0;
+
+    switch (GetIpProto())
+    {
+    case kProtoUdp:
+        checksum = mHeader.mUdp.GetChecksum();
+        break;
+
+    case kProtoTcp:
+        checksum = mHeader.mTcp.GetChecksum();
+        break;
+
+    case kProtoIcmp6:
+        checksum = mHeader.mIcmp.GetChecksum();
+        break;
+
+    default:
+        break;
+    }
+
+    return checksum;
+}
+
 } // namespace Ip6
 } // namespace ot
diff --git a/src/core/net/ip6.hpp b/src/core/net/ip6.hpp
index d538021..5e695cc 100644
--- a/src/core/net/ip6.hpp
+++ b/src/core/net/ip6.hpp
@@ -42,7 +42,9 @@
 #include <openthread/udp.h>
 
 #include "common/encoding.hpp"
+#include "common/frame_data.hpp"
 #include "common/locator.hpp"
+#include "common/log.hpp"
 #include "common/message.hpp"
 #include "common/non_copyable.hpp"
 #include "common/time_ticker.hpp"
@@ -51,6 +53,7 @@
 #include "net/ip6_address.hpp"
 #include "net/ip6_headers.hpp"
 #include "net/ip6_mpl.hpp"
+#include "net/ip6_types.hpp"
 #include "net/netif.hpp"
 #include "net/socket.hpp"
 #include "net/tcp6.hpp"
@@ -109,18 +112,6 @@
 
 public:
     /**
-     * The max datagram length (in bytes) of an IPv6 message.
-     *
-     */
-    static constexpr uint16_t kMaxDatagramLength = OPENTHREAD_CONFIG_IP6_MAX_DATAGRAM_LENGTH;
-
-    /**
-     * The max datagram length (in bytes) of an unfragmented IPv6 message.
-     *
-     */
-    static constexpr uint16_t kMaxAssembledDatagramLength = OPENTHREAD_CONFIG_IP6_MAX_ASSEMBLED_DATAGRAM;
-
-    /**
      * This constructor initializes the object.
      *
      * @param[in]  aInstance   A reference to the otInstance object.
@@ -134,7 +125,7 @@
      * @param[in]  aReserved  The number of header bytes to reserve following the IPv6 header.
      * @param[in]  aSettings  The message settings.
      *
-     * @returns A pointer to the message or nullptr if insufficient message buffers are available.
+     * @returns A pointer to the message or `nullptr` if insufficient message buffers are available.
      *
      */
     Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings = Message::Settings::GetDefault());
@@ -146,7 +137,7 @@
      * @param[in]  aDataLength  The size of the IPV6 datagram buffer pointed by @p aData.
      * @param[in]  aSettings    The message settings.
      *
-     * @returns A pointer to the message or nullptr if malformed IPv6 header or insufficient message buffers are
+     * @returns A pointer to the message or `nullptr` if malformed IPv6 header or insufficient message buffers are
      * available.
      *
      */
@@ -160,7 +151,7 @@
      * @param[in]  aData        A pointer to the IPv6 datagram buffer.
      * @param[in]  aDataLength  The size of the IPV6 datagram buffer pointed by @p aData.
      *
-     * @returns A pointer to the message or nullptr if malformed IPv6 header or insufficient message buffers are
+     * @returns A pointer to the message or `nullptr` if malformed IPv6 header or insufficient message buffers are
      * available.
      *
      */
@@ -196,6 +187,7 @@
      * processing is complete, including when a value other than `kErrorNone` is returned.
      *
      * @param[in]  aMessage          A reference to the message.
+     * @param[in]  aFromHost         TRUE if the message is originated from the host, FALSE otherwise.
      *
      * @retval kErrorNone     Successfully processed the message.
      * @retval kErrorDrop     Message was well-formed but not fully processed due to packet processing rules.
@@ -204,7 +196,7 @@
      * @retval kErrorParse    Encountered a malformed header when processing the message.
      *
      */
-    Error SendRaw(Message &aMessage);
+    Error SendRaw(Message &aMessage, bool aFromHost);
 
     /**
      * This method processes a received IPv6 datagram.
@@ -212,7 +204,7 @@
      * @param[in]  aMessage          A reference to the message.
      * @param[in]  aNetif            A pointer to the network interface that received the message.
      * @param[in]  aLinkMessageInfo  A pointer to link-specific message information.
-     * @param[in]  aFromNcpHost      TRUE if the message was submitted by the NCP host, FALSE otherwise.
+     * @param[in]  aFromHost         TRUE if the message is originated from the host, FALSE otherwise.
      *
      * @retval kErrorNone     Successfully processed the message.
      * @retval kErrorDrop     Message was well-formed but not fully processed due to packet processing rules.
@@ -221,7 +213,7 @@
      * @retval kErrorParse    Encountered a malformed header when processing the message.
      *
      */
-    Error HandleDatagram(Message &aMessage, Netif *aNetif, const void *aLinkMessageInfo, bool aFromNcpHost);
+    Error HandleDatagram(Message &aMessage, Netif *aNetif, const void *aLinkMessageInfo, bool aFromHost);
 
     /**
      * This method registers a callback to provide received raw IPv6 datagrams.
@@ -230,7 +222,7 @@
      * the Thread control traffic filter setting.
      *
      * @param[in]  aCallback         A pointer to a function that is called when an IPv6 datagram is received
-     *                               or nullptr to disable the callback.
+     *                               or `nullptr` to disable the callback.
      * @param[in]  aCallbackContext  A pointer to application-specific context.
      *
      * @sa IsReceiveIp6FilterEnabled
@@ -284,7 +276,7 @@
      *
      * @param[in]  aMessageInfo  A reference to the message information.
      *
-     * @returns A pointer to the selected IPv6 source address or nullptr if no source address was found.
+     * @returns A pointer to the selected IPv6 source address or `nullptr` if no source address was found.
      *
      */
     const Netif::UnicastAddress *SelectSourceAddress(MessageInfo &aMessageInfo);
@@ -300,21 +292,29 @@
     /**
      * This static method converts an IP protocol number to a string.
      *
-     * @param[in] aIpPorto  An IP protocol number.
+     * @param[in] aIpProto  An IP protocol number.
      *
      * @returns The string representation of @p aIpProto.
      *
      */
     static const char *IpProtoToString(uint8_t aIpProto);
 
+    /**
+     * This static method converts an IP header ECN value to a string.
+     *
+     * @param[in] aEcn   The 2-bit ECN value.
+     *
+     * @returns The string representation of @p aEcn.
+     *
+     */
+    static const char *EcnToString(Ecn aEcn);
+
 private:
     static constexpr uint8_t kDefaultHopLimit      = OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT;
     static constexpr uint8_t kIp6ReassemblyTimeout = OPENTHREAD_CONFIG_IP6_REASSEMBLY_TIMEOUT;
 
     static constexpr uint16_t kMinimalMtu = 1280;
 
-    static constexpr uint32_t kStateUpdatePeriod = 1000;
-
     static void HandleSendQueue(Tasklet &aTasklet);
     void        HandleSendQueue(void);
 
@@ -325,7 +325,7 @@
     Error ProcessReceiveCallback(Message &          aMessage,
                                  const MessageInfo &aMessageInfo,
                                  uint8_t            aIpProto,
-                                 bool               aFromNcpHost,
+                                 bool               aFromHost,
                                  bool               aAllowReceiveFilter,
                                  Message::Ownership aMessageOwnership);
     Error HandleExtensionHeaders(Message &    aMessage,
@@ -334,10 +334,10 @@
                                  Header &     aHeader,
                                  uint8_t &    aNextHeader,
                                  bool         aIsOutbound,
-                                 bool         aFromNcpHost,
+                                 bool         aFromHost,
                                  bool &       aReceive);
     Error FragmentDatagram(Message &aMessage, uint8_t aIpProto);
-    Error HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromNcpHost);
+    Error HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromHost);
 #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
     void CleanupFragmentationBuffer(void);
     void HandleTimeTick(void);
@@ -354,7 +354,7 @@
                         MessageInfo &      aMessageInfo,
                         uint8_t            aIpProto,
                         Message::Ownership aMessageOwnership);
-    bool  ShouldForwardToThread(const MessageInfo &aMessageInfo, bool aFromNcpHost) const;
+    bool  ShouldForwardToThread(const MessageInfo &aMessageInfo, bool aFromHost) const;
     bool  IsOnLink(const Address &aAddress) const;
 
     bool                 mForwardingEnabled;
@@ -379,6 +379,191 @@
 };
 
 /**
+ * This class represents parsed IPv6 header along with UDP/TCP/ICMP6 headers from a received message/frame.
+ *
+ */
+class Headers : private Clearable<Headers>
+{
+public:
+    /**
+     * This method parses the IPv6 and UDP/TCP/ICMP6 headers from a given message.
+     *
+     * @param[in] aMessage   The message to parse the headers from.
+     *
+     * @retval kErrorNone    The headers are parsed successfully.
+     * @retval kErrorParse   Failed to parse the headers.
+     *
+     */
+    Error ParseFrom(const Message &aMessage);
+
+    /**
+     * This method decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers.
+     *
+     * @param[in]  aMessage         The message from which to read the lowpan frame.
+     * @param[in]  aOffset          The offset in @p aMessage to start reading the frame.
+     * @param[in]  aMacSource       The MAC source address.
+     * @param[in]  aMacDest         The MAC destination address.
+     *
+     * @retval kErrorNone           Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers.
+     * @retval kErrorNotFound       Lowpan frame is a next fragment and does not contain IPv6 headers.
+     * @retval kErrorParse          Failed to parse the headers.
+     *
+     */
+    Error DecompressFrom(const Message &     aMessage,
+                         uint16_t            aOffset,
+                         const Mac::Address &aMacSource,
+                         const Mac::Address &aMacDest);
+
+    /**
+     * This method decompresses lowpan frame and parses the IPv6 and UDP/TCP/ICMP6 headers.
+     *
+     * @param[in]  aFrameData       The lowpan frame data.
+     * @param[in]  aMacSource       The MAC source address.
+     * @param[in]  aMacDest         The MAC destination address.
+     * @param[in]  aInstance        The OpenThread instance.
+     *
+     * @retval kErrorNone           Successfully decompressed and parsed IPv6 and UDP/TCP/ICMP6 headers.
+     * @retval kErrorNotFound       Lowpan frame is a next fragment and does not contain IPv6 headers.
+     * @retval kErrorParse          Failed to parse the headers.
+     *
+     */
+    Error DecompressFrom(const FrameData &   aFrameData,
+                         const Mac::Address &aMacSource,
+                         const Mac::Address &aMacDest,
+                         Instance &          aInstance);
+
+    /**
+     * This method returns the IPv6 header.
+     *
+     * @returns The IPv6 header.
+     *
+     */
+    const Header &GetIp6Header(void) const { return mIp6Header; }
+
+    /**
+     * This method returns the IP protocol number from IPv6 Next Header field.
+     *
+     * @returns The IP protocol number.
+     *
+     */
+    uint8_t GetIpProto(void) const { return mIp6Header.GetNextHeader(); }
+
+    /**
+     * This method returns the 2-bit Explicit Congestion Notification (ECN) from Traffic Class field from IPv6 header.
+     *
+     * @returns The ECN value.
+     *
+     */
+    Ecn GetEcn(void) const { return mIp6Header.GetEcn(); }
+
+    /**
+     * This method indicates if the protocol number from IPv6 header is UDP.
+     *
+     * @retval TRUE   If the protocol number in IPv6 header is UDP.
+     * @retval FALSE  If the protocol number in IPv6 header is not UDP.
+     *
+     */
+    bool IsUdp(void) const { return GetIpProto() == kProtoUdp; }
+
+    /**
+     * This method indicates if the protocol number from IPv6 header is TCP.
+     *
+     * @retval TRUE   If the protocol number in IPv6 header is TCP.
+     * @retval FALSE  If the protocol number in IPv6 header is not TCP.
+     *
+     */
+    bool IsTcp(void) const { return GetIpProto() == kProtoTcp; }
+
+    /**
+     * This method indicates if the protocol number from IPv6 header is ICMPv6.
+     *
+     * @retval TRUE   If the protocol number in IPv6 header is ICMPv6.
+     * @retval FALSE  If the protocol number in IPv6 header is not ICMPv6.
+     *
+     */
+    bool IsIcmp6(void) const { return GetIpProto() == kProtoIcmp6; }
+
+    /**
+     * This method returns the source IPv6 address from IPv6 header.
+     *
+     * @returns The source IPv6 address.
+     *
+     */
+    const Address &GetSourceAddress(void) const { return mIp6Header.GetSource(); }
+
+    /**
+     * This method returns the destination IPv6 address from IPv6 header.
+     *
+     * @returns The destination IPv6 address.
+     *
+     */
+    const Address &GetDestinationAddress(void) const { return mIp6Header.GetDestination(); }
+
+    /**
+     * This method returns the UDP header.
+     *
+     * This method MUST be used when `IsUdp() == true`. Otherwise its behavior is undefined
+     *
+     * @returns The UDP header.
+     *
+     */
+    const Udp::Header &GetUdpHeader(void) const { return mHeader.mUdp; }
+
+    /**
+     * This method returns the TCP header.
+     *
+     * This method MUST be used when `IsTcp() == true`. Otherwise its behavior is undefined
+     *
+     * @returns The TCP header.
+     *
+     */
+    const Tcp::Header &GetTcpHeader(void) const { return mHeader.mTcp; }
+
+    /**
+     * This method returns the ICMPv6 header.
+     *
+     * This method MUST be used when `IsIcmp6() == true`. Otherwise its behavior is undefined
+     *
+     * @returns The ICMPv6 header.
+     *
+     */
+    const Icmp::Header &GetIcmpHeader(void) const { return mHeader.mIcmp; }
+
+    /**
+     * This method returns the source port number if header is UDP or TCP, or zero otherwise
+     *
+     * @returns The source port number under UDP / TCP or zero.
+     *
+     */
+    uint16_t GetSourcePort(void) const;
+
+    /**
+     * This method returns the destination port number if header is UDP or TCP, or zero otherwise.
+     *
+     * @returns The destination port number under UDP / TCP or zero.
+     *
+     */
+    uint16_t GetDestinationPort(void) const;
+
+    /**
+     * This method returns the checksum values from corresponding UDP, TCP, or ICMPv6 header.
+     *
+     * @returns The checksum value.
+     *
+     */
+    uint16_t GetChecksum(void) const;
+
+private:
+    Header mIp6Header;
+    union
+    {
+        Udp::Header  mUdp;
+        Tcp::Header  mTcp;
+        Icmp::Header mIcmp;
+    } mHeader;
+};
+
+/**
  * @}
  *
  */
diff --git a/src/core/net/ip6_address.cpp b/src/core/net/ip6_address.cpp
index 27cc793..7f50c94 100644
--- a/src/core/net/ip6_address.cpp
+++ b/src/core/net/ip6_address.cpp
@@ -35,13 +35,14 @@
 
 #include <stdio.h>
 
+#include "common/array.hpp"
 #include "common/as_core_type.hpp"
 #include "common/code_utils.hpp"
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/numeric_limits.hpp"
 #include "common/random.hpp"
-#include "net/ip4_address.hpp"
+#include "net/ip4_types.hpp"
 #include "net/netif.hpp"
 
 using ot::Encoding::BigEndian::HostSwap32;
@@ -76,13 +77,17 @@
 bool Prefix::operator<(const Prefix &aOther) const
 {
     bool    isSmaller;
+    uint8_t minLength;
     uint8_t matchedLength;
 
-    VerifyOrExit(GetLength() == aOther.GetLength(), isSmaller = GetLength() < aOther.GetLength());
+    minLength     = OT_MIN(GetLength(), aOther.GetLength());
+    matchedLength = MatchLength(GetBytes(), aOther.GetBytes(), SizeForLength(minLength));
 
-    matchedLength = MatchLength(GetBytes(), aOther.GetBytes(), GetBytesSize());
-
-    VerifyOrExit(matchedLength < GetLength(), isSmaller = false);
+    if (matchedLength >= minLength)
+    {
+        isSmaller = (GetLength() < aOther.GetLength());
+        ExitNow();
+    }
 
     isSmaller = GetBytes()[matchedLength / CHAR_BIT] < aOther.GetBytes()[matchedLength / CHAR_BIT];
 
@@ -119,10 +124,10 @@
     return matchedLength;
 }
 
-bool Prefix::IsValidNat64(void) const
+bool Prefix::IsValidNat64PrefixLength(uint8_t aLength)
 {
-    return (mLength == 32) || (mLength == 40) || (mLength == 48) || (mLength == 56) || (mLength == 64) ||
-           (mLength == 96);
+    return (aLength == 32) || (aLength == 40) || (aLength == 48) || (aLength == 56) || (aLength == 64) ||
+           (aLength == 96);
 }
 
 Prefix::InfoString Prefix::ToString(void) const
@@ -613,7 +618,7 @@
         Ip4::Address ip4Addr;
 
         SuccessOrExit(error = ip4Addr.FromString(aString));
-        memcpy(OT_ARRAY_END(mFields.m8) - Ip4::Address::kSize, ip4Addr.GetBytes(), Ip4::Address::kSize);
+        memcpy(GetArrayEnd(mFields.m8) - Ip4::Address::kSize, ip4Addr.GetBytes(), Ip4::Address::kSize);
     }
 
     error = kErrorNone;
@@ -639,7 +644,7 @@
 
 void Address::ToString(StringWriter &aWriter) const
 {
-    AppendHexWords(aWriter, OT_ARRAY_LENGTH(mFields.m16));
+    AppendHexWords(aWriter, static_cast<uint8_t>(GetArrayLength(mFields.m16)));
 }
 
 void Address::AppendHexWords(StringWriter &aWriter, uint8_t aLength) const
diff --git a/src/core/net/ip6_address.hpp b/src/core/net/ip6_address.hpp
index 9139af7..064e282 100644
--- a/src/core/net/ip6_address.hpp
+++ b/src/core/net/ip6_address.hpp
@@ -40,16 +40,22 @@
 
 #include <openthread/ip6.h>
 
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/encoding.hpp"
 #include "common/equatable.hpp"
 #include "common/string.hpp"
 #include "mac/mac_types.hpp"
-#include "net/ip4_address.hpp"
 
 using ot::Encoding::BigEndian::HostSwap16;
 
 namespace ot {
+
+namespace Ip4 {
+// Forward declaration for SynthesizeFromIp4Address
+class Address;
+} // namespace Ip4
+
 namespace Ip6 {
 
 /**
@@ -110,6 +116,14 @@
     const uint8_t *GetBytes(void) const { return mPrefix.mFields.m8; }
 
     /**
+     * This method gets the subnet ID of the prefix.
+     *
+     * @returns The 16-bit subnet ID.
+     *
+     */
+    uint16_t GetSubnetId(void) const { return HostSwap16(mPrefix.mFields.m16[3]); }
+
+    /**
      * This method gets the prefix length (in bits).
      *
      * @returns The prefix length (in bits).
@@ -143,6 +157,14 @@
     void Set(const NetworkPrefix &aNetworkPrefix) { Set(aNetworkPrefix.m8, NetworkPrefix::kLength); }
 
     /**
+     * This method sets the subnet ID of the prefix.
+     *
+     * @param[in] aSubnetId  A 16-bit subnet ID.
+     *
+     */
+    void SetSubnetId(uint16_t aSubnetId) { mPrefix.mFields.m16[3] = HostSwap16(aSubnetId); }
+
+    /**
      * This method set the prefix length.
      *
      * @param[in] aLength  The new prefix length (in bits).
@@ -249,8 +271,10 @@
     /**
      * This method overloads operator `<` to compare two prefixes.
      *
-     * A prefix with shorter length is considered smaller than the one with longer length. If the prefix lengths are
-     * equal, then the prefix bytes are compared directly.
+     * If the two prefixes have the same length N, then the bytes are compared directly (as two big-endian N-bit
+     * numbers). If the two prefix have different lengths, the shorter prefix is padded by `0` bit up to the longer
+     * prefix length N before the bytes are compared (as big-endian N-bit numbers). If all bytes are equal, the prefix
+     * with shorter length is considered smaller.
      *
      * @param[in] aOther  The other prefix to compare against.
      *
@@ -283,6 +307,19 @@
     static uint8_t MatchLength(const uint8_t *aPrefixA, const uint8_t *aPrefixB, uint8_t aMaxSize);
 
     /**
+     * This method indicates whether or not a given prefix length is valid for use as a NAT64 prefix.
+     *
+     * A NAT64 prefix must have one of the following lengths: 32, 40, 48, 56, 64, or 96 (per RFC 6502).
+     *
+     * @param[in] aLength The length of the prefix.
+     *
+     * @retval TRUE   If the prefix has a valid length for use as a NAT64 prefix.
+     * @retval FALSE  If the prefix does not have a valid length for use as a NAT64 prefix.
+     *
+     */
+    static bool IsValidNat64PrefixLength(uint8_t aLength);
+
+    /**
      * This method indicates whether or not the prefix has a valid length for use as a NAT64 prefix.
      *
      * A NAT64 prefix must have one of the following lengths: 32, 40, 48, 56, 64, or 96 (per RFC 6502).
@@ -291,7 +328,7 @@
      * @retval FALSE  If the prefix does not have a valid length for use as a NAT64 prefix.
      *
      */
-    bool IsValidNat64(void) const;
+    bool IsValidNat64(void) const { return IsValidNat64PrefixLength(mLength); }
 
     /**
      * This method converts the prefix to a string.
@@ -311,7 +348,7 @@
      * If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be
      * truncated but the outputted string is always null-terminated.
      *
-     * @param[out] aBuffer   A pointer to a char array to output the string (MUST NOT be nullptr).
+     * @param[out] aBuffer   A pointer to a char array to output the string (MUST NOT be `nullptr`).
      * @param[in]  aSize     The size of @p aBuffer (in bytes).
      *
      */
@@ -952,7 +989,7 @@
      * If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be
      * truncated but the outputted string is always null-terminated.
      *
-     * @param[out] aBuffer   A pointer to a char array to output the string (MUST NOT be nullptr).
+     * @param[out] aBuffer   A pointer to a char array to output the string (MUST NOT be `nullptr`).
      * @param[in]  aSize     The size of @p aBuffer (in bytes).
      *
      */
@@ -991,6 +1028,12 @@
  */
 
 } // namespace Ip6
+
+DefineCoreType(otIp6NetworkPrefix, Ip6::NetworkPrefix);
+DefineCoreType(otIp6Prefix, Ip6::Prefix);
+DefineCoreType(otIp6InterfaceIdentifier, Ip6::InterfaceIdentifier);
+DefineCoreType(otIp6Address, Ip6::Address);
+
 } // namespace ot
 
 #endif // IP6_ADDRESS_HPP_
diff --git a/src/core/net/ip6_filter.cpp b/src/core/net/ip6_filter.cpp
index 5ea480a..0104fac 100644
--- a/src/core/net/ip6_filter.cpp
+++ b/src/core/net/ip6_filter.cpp
@@ -38,7 +38,7 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "meshcop/meshcop.hpp"
 #include "net/ip6.hpp"
 #include "net/tcp6.hpp"
@@ -48,19 +48,13 @@
 namespace ot {
 namespace Ip6 {
 
-Filter::Filter(Instance &aInstance)
-    : InstanceLocator(aInstance)
-{
-    memset(mUnsecurePorts, 0, sizeof(mUnsecurePorts));
-}
+RegisterLogModule("Ip6Filter");
 
 bool Filter::Accept(Message &aMessage) const
 {
-    bool        rval = false;
-    Header      ip6;
-    Udp::Header udp;
-    Tcp::Header tcp;
-    uint16_t    dstport;
+    bool     rval = false;
+    Headers  headers;
+    uint16_t dstPort;
 
     // Allow all received IPv6 datagrams with link security enabled
     if (aMessage.IsLinkSecurityEnabled())
@@ -68,11 +62,11 @@
         ExitNow(rval = true);
     }
 
-    // Read IPv6 header
-    SuccessOrExit(aMessage.Read(0, ip6));
+    SuccessOrExit(headers.ParseFrom(aMessage));
 
     // Allow only link-local unicast or multicast
-    VerifyOrExit(ip6.GetDestination().IsLinkLocal() || ip6.GetDestination().IsLinkLocalMulticast());
+    VerifyOrExit(headers.GetDestinationAddress().IsLinkLocal() ||
+                 headers.GetDestinationAddress().IsLinkLocalMulticast());
 
     // Allow all link-local IPv6 datagrams when Thread is not enabled
     if (Get<Mle::MleRouter>().GetRole() == Mle::kRoleDisabled)
@@ -80,16 +74,13 @@
         ExitNow(rval = true);
     }
 
-    switch (ip6.GetNextHeader())
+    dstPort = headers.GetDestinationPort();
+
+    switch (headers.GetIpProto())
     {
     case kProtoUdp:
-        // Read the UDP header and get the dst port
-        SuccessOrExit(aMessage.Read(sizeof(ip6), udp));
-
-        dstport = udp.GetDestinationPort();
-
         // Allow MLE traffic
-        if (dstport == Mle::kUdpPort)
+        if (dstPort == Mle::kUdpPort)
         {
             ExitNow(rval = true);
         }
@@ -97,7 +88,7 @@
 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
         // Allow native commissioner traffic
         if (Get<KeyManager>().GetSecurityPolicy().mNativeCommissioningEnabled &&
-            dstport == Get<MeshCoP::BorderAgent>().GetUdpPort())
+            dstPort == Get<MeshCoP::BorderAgent>().GetUdpPort())
         {
             ExitNow(rval = true);
         }
@@ -105,11 +96,6 @@
         break;
 
     case kProtoTcp:
-        // Read the TCP header and get the dst port
-        SuccessOrExit(aMessage.Read(sizeof(ip6), tcp));
-
-        dstport = tcp.GetDestinationPort();
-
         break;
 
     default:
@@ -118,111 +104,37 @@
     }
 
     // Check against allowed unsecure port list
-    for (uint16_t unsecurePort : mUnsecurePorts)
-    {
-        if (unsecurePort != 0 && unsecurePort == dstport)
-        {
-            ExitNow(rval = true);
-        }
-    }
+    rval = mUnsecurePorts.Contains(dstPort);
 
 exit:
     return rval;
 }
 
-Error Filter::AddUnsecurePort(uint16_t aPort)
+Error Filter::UpdateUnsecurePorts(Action aAction, uint16_t aPort)
 {
-    Error error = kErrorNone;
+    Error     error = kErrorNone;
+    uint16_t *entry;
 
     VerifyOrExit(aPort != 0, error = kErrorInvalidArgs);
 
-    for (uint16_t unsecurePort : mUnsecurePorts)
+    entry = mUnsecurePorts.Find(aPort);
+
+    if (aAction == kAdd)
     {
-        if (unsecurePort == aPort)
-        {
-            ExitNow();
-        }
+        VerifyOrExit(entry == nullptr);
+        SuccessOrExit(error = mUnsecurePorts.PushBack(aPort));
+    }
+    else
+    {
+        VerifyOrExit(entry != nullptr, error = kErrorNotFound);
+        mUnsecurePorts.Remove(*entry);
     }
 
-    for (uint16_t &unsecurePort : mUnsecurePorts)
-    {
-        if (unsecurePort == 0)
-        {
-            unsecurePort = aPort;
-            otLogInfoIp6("Added unsecure port %d", aPort);
-            ExitNow();
-        }
-    }
-
-    ExitNow(error = kErrorNoBufs);
+    LogInfo("%s unsecure port %d", (aAction == kAdd) ? "Added" : "Removed", aPort);
 
 exit:
     return error;
 }
 
-Error Filter::RemoveUnsecurePort(uint16_t aPort)
-{
-    Error error = kErrorNone;
-
-    VerifyOrExit(aPort != 0, error = kErrorInvalidArgs);
-
-    for (int i = 0; i < kMaxUnsecurePorts; i++)
-    {
-        if (mUnsecurePorts[i] == aPort)
-        {
-            // Shift all of the ports higher than this
-            // port down.
-            for (; i < kMaxUnsecurePorts - 1; i++)
-            {
-                mUnsecurePorts[i] = mUnsecurePorts[i + 1];
-            }
-
-            // Clear the last port entry.
-            mUnsecurePorts[i] = 0;
-            otLogInfoIp6("Removed unsecure port %d", aPort);
-            ExitNow();
-        }
-    }
-
-    ExitNow(error = kErrorNotFound);
-
-exit:
-    return error;
-}
-
-bool Filter::IsUnsecurePort(uint16_t aPort)
-{
-    bool found = false;
-
-    for (uint16_t unsecurePort : mUnsecurePorts)
-    {
-        if (unsecurePort == aPort)
-        {
-            found = true;
-            break;
-        }
-    }
-    return found;
-}
-
-void Filter::RemoveAllUnsecurePorts(void)
-{
-    memset(mUnsecurePorts, 0, sizeof(mUnsecurePorts));
-}
-
-const uint16_t *Filter::GetUnsecurePorts(uint8_t &aNumEntries) const
-{
-    // Count the number of unsecure ports.
-    for (aNumEntries = 0; aNumEntries < kMaxUnsecurePorts; aNumEntries++)
-    {
-        if (mUnsecurePorts[aNumEntries] == 0)
-        {
-            break;
-        }
-    }
-
-    return mUnsecurePorts;
-}
-
 } // namespace Ip6
 } // namespace ot
diff --git a/src/core/net/ip6_filter.hpp b/src/core/net/ip6_filter.hpp
index 86bdc4c..664aa0e 100644
--- a/src/core/net/ip6_filter.hpp
+++ b/src/core/net/ip6_filter.hpp
@@ -36,6 +36,7 @@
 
 #include "openthread-core-config.h"
 
+#include "common/array.hpp"
 #include "common/locator.hpp"
 #include "common/message.hpp"
 #include "common/non_copyable.hpp"
@@ -66,7 +67,10 @@
      * @param[in]  aInstance  A reference to the OpenThread instance.
      *
      */
-    explicit Filter(Instance &aInstance);
+    explicit Filter(Instance &aInstance)
+        : InstanceLocator(aInstance)
+    {
+    }
 
     /**
      * This method indicates whether or not the IPv6 datagram passes the filter.
@@ -89,7 +93,7 @@
      * @retval kErrorNoBufs       The unsecure port list is full.
      *
      */
-    Error AddUnsecurePort(uint16_t aPort);
+    Error AddUnsecurePort(uint16_t aPort) { return UpdateUnsecurePorts(kAdd, aPort); }
 
     /**
      * This method removes a port from the allowed unsecure port list.
@@ -101,7 +105,7 @@
      * @retval kErrorNotFound     The port was not found in the unsecure port list.
      *
      */
-    Error RemoveUnsecurePort(uint16_t aPort);
+    Error RemoveUnsecurePort(uint16_t aPort) { return UpdateUnsecurePorts(kRemove, aPort); }
 
     /**
      * This method checks whether a port is in the unsecure port list.
@@ -111,13 +115,13 @@
      * @returns Whether the given port is in the unsecure port list.
      *
      */
-    bool IsUnsecurePort(uint16_t aPort);
+    bool IsUnsecurePort(uint16_t aPort) { return mUnsecurePorts.Contains(aPort); }
 
     /**
      * This method removes all ports from the allowed unsecure port list.
      *
      */
-    void RemoveAllUnsecurePorts(void);
+    void RemoveAllUnsecurePorts(void) { mUnsecurePorts.Clear(); }
 
     /**
      * This method returns a pointer to the unsecure port list.
@@ -129,12 +133,25 @@
      * @returns A pointer to the unsecure port list.
      *
      */
-    const uint16_t *GetUnsecurePorts(uint8_t &aNumEntries) const;
+    const uint16_t *GetUnsecurePorts(uint8_t &aNumEntries) const
+    {
+        aNumEntries = mUnsecurePorts.GetLength();
+
+        return &mUnsecurePorts[0];
+    }
 
 private:
     static constexpr uint16_t kMaxUnsecurePorts = 2;
 
-    uint16_t mUnsecurePorts[kMaxUnsecurePorts];
+    enum Action : uint8_t
+    {
+        kAdd,
+        kRemove,
+    };
+
+    Error UpdateUnsecurePorts(Action aAction, uint16_t aPort);
+
+    Array<uint16_t, kMaxUnsecurePorts> mUnsecurePorts;
 };
 
 } // namespace Ip6
diff --git a/src/core/net/ip6_headers.cpp b/src/core/net/ip6_headers.cpp
index f545d2c..be72fb6 100644
--- a/src/core/net/ip6_headers.cpp
+++ b/src/core/net/ip6_headers.cpp
@@ -38,14 +38,15 @@
 namespace ot {
 namespace Ip6 {
 
-Error Header::Init(const Message &aMessage)
+Error Header::ParseFrom(const Message &aMessage)
 {
-    Error error = kErrorNone;
+    Error error = kErrorParse;
 
-    SuccessOrExit(error = aMessage.Read(0, *this));
+    SuccessOrExit(aMessage.Read(0, *this));
+    VerifyOrExit(IsValid());
+    VerifyOrExit(sizeof(Header) + GetPayloadLength() == aMessage.GetLength());
 
-    VerifyOrExit(IsValid(), error = kErrorParse);
-    VerifyOrExit((sizeof(*this) + GetPayloadLength()) == aMessage.GetLength(), error = kErrorParse);
+    error = kErrorNone;
 
 exit:
     return error;
@@ -53,20 +54,13 @@
 
 bool Header::IsValid(void) const
 {
-    bool ret = true;
-
-    // check Version
-    VerifyOrExit(IsVersion6(), ret = false);
-
-    // check Payload Length
 #if !OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
-    VerifyOrExit((sizeof(*this) + GetPayloadLength()) <= Ip6::kMaxDatagramLength, ret = false);
+    static constexpr uint32_t kMaxLength = kMaxDatagramLength;
 #else
-    VerifyOrExit((sizeof(*this) + GetPayloadLength()) <= Ip6::kMaxAssembledDatagramLength, ret = false);
+    static constexpr uint32_t kMaxLength = kMaxAssembledDatagramLength;
 #endif
 
-exit:
-    return ret;
+    return IsVersion6() && ((sizeof(Header) + GetPayloadLength()) <= kMaxLength);
 }
 
 } // namespace Ip6
diff --git a/src/core/net/ip6_headers.hpp b/src/core/net/ip6_headers.hpp
index 064c3e8..c6846a7 100644
--- a/src/core/net/ip6_headers.hpp
+++ b/src/core/net/ip6_headers.hpp
@@ -38,9 +38,11 @@
 
 #include <stddef.h>
 
+#include "common/clearable.hpp"
 #include "common/encoding.hpp"
 #include "common/message.hpp"
 #include "net/ip6_address.hpp"
+#include "net/ip6_types.hpp"
 #include "net/netif.hpp"
 #include "net/socket.hpp"
 
@@ -85,39 +87,12 @@
  *
  */
 
-// Internet Protocol Numbers
-static constexpr uint8_t kProtoHopOpts  = OT_IP6_PROTO_HOP_OPTS; ///< IPv6 Hop-by-Hop Option
-static constexpr uint8_t kProtoTcp      = OT_IP6_PROTO_TCP;      ///< Transmission Control Protocol
-static constexpr uint8_t kProtoUdp      = OT_IP6_PROTO_UDP;      ///< User Datagram
-static constexpr uint8_t kProtoIp6      = OT_IP6_PROTO_IP6;      ///< IPv6 encapsulation
-static constexpr uint8_t kProtoRouting  = OT_IP6_PROTO_ROUTING;  ///< Routing Header for IPv6
-static constexpr uint8_t kProtoFragment = OT_IP6_PROTO_FRAGMENT; ///< Fragment Header for IPv6
-static constexpr uint8_t kProtoIcmp6    = OT_IP6_PROTO_ICMP6;    ///< ICMP for IPv6
-static constexpr uint8_t kProtoNone     = OT_IP6_PROTO_NONE;     ///< No Next Header for IPv6
-static constexpr uint8_t kProtoDstOpts  = OT_IP6_PROTO_DST_OPTS; ///< Destination Options for IPv6
-
-/**
- * Class Selectors
- */
-enum IpDscpCs : uint8_t
-{
-    kDscpCs0    = 0,    ///< Class selector codepoint 0
-    kDscpCs1    = 8,    ///< Class selector codepoint 8
-    kDscpCs2    = 16,   ///< Class selector codepoint 16
-    kDscpCs3    = 24,   ///< Class selector codepoint 24
-    kDscpCs4    = 32,   ///< Class selector codepoint 32
-    kDscpCs5    = 40,   ///< Class selector codepoint 40
-    kDscpCs6    = 48,   ///< Class selector codepoint 48
-    kDscpCs7    = 56,   ///< Class selector codepoint 56
-    kDscpCsMask = 0x38, ///< Class selector mask
-};
-
 /**
  * This class implements IPv6 header generation and parsing.
  *
  */
 OT_TOOL_PACKED_BEGIN
-class Header
+class Header : public Clearable<Header>
 {
 public:
     static constexpr uint8_t kPayloadLengthFieldOffset = 4;  ///< Offset of Payload Length field in IPv6 header.
@@ -127,33 +102,18 @@
     static constexpr uint8_t kDestinationFieldOffset   = 24; ///< Offset of Destination Address field in IPv6 header.
 
     /**
-     * This method initializes the IPv6 header.
+     * This method initializes the Version to 6 and sets Traffic Class and Flow fields to zero.
+     *
+     * The other fields in the IPv6 header remain unchanged.
      *
      */
-    void Init(void) { mVersionClassFlow.m32 = HostSwap32(kVersionClassFlowInit); }
-
-    /**
-     * This method initializes the IPv6 header and sets Version, Traffic Control and Flow Label fields.
-     *
-     */
-    void Init(uint32_t aVersionClassFlow) { mVersionClassFlow.m32 = HostSwap32(aVersionClassFlow); }
-
-    /**
-     * This method reads the IPv6 header from @p aMessage.
-     *
-     * @param[in]  aMessage  The IPv6 datagram.
-     *
-     * @retval kErrorNone   Successfully read the IPv6 header.
-     * @retval kErrorParse  Malformed IPv6 header.
-     *
-     */
-    Error Init(const Message &aMessage);
+    void InitVersionTrafficClassFlow(void) { SetVerionTrafficClassFlow(kVersTcFlowInit); }
 
     /**
      * This method indicates whether or not the header appears to be well-formed.
      *
-     * @retval TRUE  if the header appears to be well-formed.
-     * @retval FALSE if the header does not appear to be well-formed.
+     * @retval TRUE    If the header appears to be well-formed.
+     * @retval FALSE   If the header does not appear to be well-formed.
      *
      */
     bool IsValid(void) const;
@@ -165,48 +125,103 @@
      * @retval FALSE  If the IPv6 Version is not set to 6.
      *
      */
-    bool IsVersion6(void) const { return (mVersionClassFlow.m8[0] & kVersionMask) == kVersion6; }
+    bool IsVersion6(void) const { return (mVerTcFlow.m8[0] & kVersionMask) == kVersion6; }
 
     /**
-     * This method returns the IPv6 DSCP value.
+     * This method gets the combination of Version, Traffic Class, and Flow fields as a 32-bit value.
      *
-     * @returns The IPv6 DSCP value.
+     * @returns The Version, Traffic Class, and Flow fields as a 32-bit value.
+     *
+     */
+    uint32_t GetVerionTrafficClassFlow(void) const { return HostSwap32(mVerTcFlow.m32); }
+
+    /**
+     * This method sets the combination of Version, Traffic Class, and Flow fields as a 32-bit value.
+     *
+     * @param[in] aVerTcFlow   The Version, Traffic Class, and Flow fields as a 32-bit value.
+     *
+     */
+    void SetVerionTrafficClassFlow(uint32_t aVerTcFlow) { mVerTcFlow.m32 = HostSwap32(aVerTcFlow); }
+
+    /**
+     * This method gets the Traffic Class field.
+     *
+     * @returns The Traffic Class field.
+     *
+     */
+    uint8_t GetTrafficClass(void) const
+    {
+        return static_cast<uint8_t>((HostSwap16(mVerTcFlow.m16[0]) & kTrafficClassMask) >> kTrafficClassOffset);
+    }
+
+    /**
+     * This method sets the Traffic Class filed.
+     *
+     * @param[in] aTc  The Traffic Class value.
+     *
+     */
+    void SetTrafficClass(uint8_t aTc)
+    {
+        mVerTcFlow.m16[0] = HostSwap16((HostSwap16(mVerTcFlow.m16[0]) & ~kTrafficClassMask) |
+                                       ((static_cast<uint16_t>(aTc) << kTrafficClassOffset) & kTrafficClassMask));
+    }
+
+    /**
+     * This method gets the 6-bit Differentiated Services Code Point (DSCP) from Traffic Class field.
+     *
+     * @returns The DSCP value.
      *
      */
     uint8_t GetDscp(void) const
     {
-        return static_cast<uint8_t>((HostSwap16(mVersionClassFlow.m16[0]) & kDscpMask) >> kDscpOffset);
+        return static_cast<uint8_t>((HostSwap16(mVerTcFlow.m16[0]) & kDscpMask) >> kDscpOffset);
     }
 
     /**
-     * This method sets the IPv6 DSCP value.
+     * This method sets 6-bit Differentiated Services Code Point (DSCP) in IPv6 header.
      *
-     * @param[in]  aDscp  The IPv6 DSCP value.
+     * @param[in]  aDscp  The DSCP value.
      *
      */
     void SetDscp(uint8_t aDscp)
     {
-        mVersionClassFlow.m16[0] = HostSwap16((HostSwap16(mVersionClassFlow.m16[0]) & ~kDscpMask) |
-                                              ((static_cast<uint16_t>(aDscp) << kDscpOffset) & kDscpMask));
+        mVerTcFlow.m16[0] = HostSwap16((HostSwap16(mVerTcFlow.m16[0]) & ~kDscpMask) |
+                                       ((static_cast<uint16_t>(aDscp) << kDscpOffset) & kDscpMask));
     }
 
     /**
-     * This method returns the IPv6 ECN value.
+     * This method gets the 2-bit Explicit Congestion Notification (ECN) from Traffic Class field.
      *
-     * @returns The IPv6 ECN value.
+     * @returns The ECN value.
      *
      */
-    uint8_t GetEcn(void) const { return (mVersionClassFlow.m8[1] & kEcnMask) >> kEcnOffset; }
+    Ecn GetEcn(void) const { return static_cast<Ecn>((mVerTcFlow.m8[1] & kEcnMask) >> kEcnOffset); }
 
     /**
-     * This method sets the Ipv6 ECN value.
+     * This method sets the 2-bit Explicit Congestion Notification (ECN) in IPv6 header..
      *
-     * @param[in]  aEcn  The Ipv6 ECN value.
+     * @param[in]  aEcn  The ECN value.
      *
      */
-    void SetEcn(uint8_t aEcn)
+    void SetEcn(Ecn aEcn) { mVerTcFlow.m8[1] = (mVerTcFlow.m8[1] & ~kEcnMask) | ((aEcn << kEcnOffset) & kEcnMask); }
+
+    /**
+     * This method gets the 20-bit Flow field.
+     *
+     * @returns  The Flow value.
+     *
+     */
+    uint32_t GetFlow(void) const { return HostSwap32(mVerTcFlow.m32) & kFlowMask; }
+
+    /**
+     * This method sets the 20-bit Flow field in IPv6 header.
+     *
+     * @param[in] aFlow  The Flow value.
+     *
+     */
+    void SetFlow(uint32_t aFlow)
     {
-        mVersionClassFlow.m8[1] = (mVersionClassFlow.m8[1] & ~kEcnMask) | ((aEcn << kEcnOffset) & kEcnMask);
+        mVerTcFlow.m32 = HostSwap32((HostSwap32(mVerTcFlow.m32) & ~kFlowMask) | (aFlow & kFlowMask));
     }
 
     /**
@@ -305,26 +320,48 @@
      */
     void SetDestination(const Address &aDestination) { mDestination = aDestination; }
 
-private:
-    static constexpr uint8_t  kVersion6             = 0x60;
-    static constexpr uint8_t  kVersionMask          = 0xf0;       // To use with `mVersionClassFlow.m8[0]`
-    static constexpr uint8_t  kDscpOffset           = 6;          // To use with `mVersionClassFlow.m16[0]`
-    static constexpr uint16_t kDscpMask             = 0x0fc0;     // To use with `mVersionClassFlow.m16[0]`
-    static constexpr uint8_t  kEcnOffset            = 4;          // To use with `mVersionClassFlow.m8[1]`
-    static constexpr uint8_t  kEcnMask              = 0x30;       // To use with `mVersionClassFlow.m8[1]`
-    static constexpr uint32_t kVersionClassFlowInit = 0x60000000; // Version 6, TC and flow zero.
+    /**
+     * This method parses and validates the IPv6 header from a given message.
+     *
+     * The header is read from @p aMessage at offset zero.
+     *
+     * @param[in]  aMessage  The IPv6 message.
+     *
+     * @retval kErrorNone   Successfully parsed the IPv6 header from @p aMessage.
+     * @retval kErrorParse  Malformed IPv6 header or message (e.g., message does not contained expected payload length).
+     *
+     */
+    Error ParseFrom(const Message &aMessage);
 
-    static constexpr uint8_t kEcnNotCapable = OT_ECN_NOT_CAPABLE; ///< Non-ECT
-    static constexpr uint8_t kEcnCapable0   = OT_ECN_CAPABLE_0;   ///< ECT(0)
-    static constexpr uint8_t kEcnCapable1   = OT_ECN_CAPABLE_1;   ///< ECT(1)
-    static constexpr uint8_t kEcnMarked     = OT_ECN_MARKED;      ///< Congestion encountered (CE)
+private:
+    // IPv6 header `mVerTcFlow` field:
+    //
+    // |             m16[0]            |            m16[1]             |
+    // |     m8[0]     |     m8[1]     |     m8[2]     |      m8[3]    |
+    // +---------------+---------------+---------------+---------------+
+    // |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
+    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    // |Version|    DSCP   |ECN|             Flow Label                |
+    // |       | Traffic Class |                                       |
+    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+    static constexpr uint8_t  kVersion6           = 0x60;       // Use with `mVerTcFlow.m8[0]`
+    static constexpr uint8_t  kVersionMask        = 0xf0;       // Use with `mVerTcFlow.m8[0]`
+    static constexpr uint8_t  kTrafficClassOffset = 4;          // Use with `mVerTcFlow.m16[0]`
+    static constexpr uint16_t kTrafficClassMask   = 0x0ff0;     // Use with `mVerTcFlow.m16[0]`
+    static constexpr uint8_t  kDscpOffset         = 6;          // Use with `mVerTcFlow.m16[0]`
+    static constexpr uint16_t kDscpMask           = 0x0fc0;     // Use with `mVerTcFlow.m16[0]`
+    static constexpr uint8_t  kEcnOffset          = 4;          // Use with `mVerTcFlow.m8[1]`
+    static constexpr uint8_t  kEcnMask            = 0x30;       // Use with `mVerTcFlow.m8[1]`
+    static constexpr uint32_t kFlowMask           = 0x000fffff; // Use with `mVerTcFlow.m32`
+    static constexpr uint32_t kVersTcFlowInit     = 0x60000000; // Version 6, TC and flow zero.
 
     union OT_TOOL_PACKED_FIELD
     {
         uint8_t  m8[sizeof(uint32_t) / sizeof(uint8_t)];
         uint16_t m16[sizeof(uint32_t) / sizeof(uint16_t)];
         uint32_t m32;
-    } mVersionClassFlow;
+    } mVerTcFlow;
     uint16_t mPayloadLength;
     uint8_t  mNextHeader;
     uint8_t  mHopLimit;
diff --git a/src/core/net/ip6_mpl.cpp b/src/core/net/ip6_mpl.cpp
index 7ed4a4c..3e0156a 100644
--- a/src/core/net/ip6_mpl.cpp
+++ b/src/core/net/ip6_mpl.cpp
@@ -38,6 +38,7 @@
 #include "common/locator_getters.hpp"
 #include "common/message.hpp"
 #include "common/random.hpp"
+#include "common/serial_number.hpp"
 #include "net/ip6.hpp"
 
 namespace ot {
@@ -187,14 +188,12 @@
         {
             // have existing entries for aSeedId
 
-            int8_t diff = static_cast<int8_t>(aSequence - mSeedSet[i].mSequence);
-
-            if (diff == 0)
+            if (aSequence == mSeedSet[i].mSequence)
             {
                 // already received, drop message
                 ExitNow(error = kErrorDrop);
             }
-            else if (insert == nullptr && diff < 0)
+            else if (insert == nullptr && SerialNumber::IsLess(aSequence, mSeedSet[i].mSequence))
             {
                 // insert in order of sequence
                 insert = &mSeedSet[i];
@@ -345,14 +344,10 @@
     TimeMilli now      = TimerMilli::GetNow();
     TimeMilli nextTime = now.GetDistantFuture();
     Metadata  metadata;
-    Message * message;
-    Message * nextMessage;
 
-    for (message = mBufferedMessageSet.GetHead(); message != nullptr; message = nextMessage)
+    for (Message &message : mBufferedMessageSet)
     {
-        nextMessage = message->GetNext();
-
-        metadata.ReadFrom(*message);
+        metadata.ReadFrom(message);
 
         if (now < metadata.mTransmissionTime)
         {
@@ -368,7 +363,7 @@
 
             if (metadata.mTransmissionCount < GetTimerExpirations())
             {
-                Message *messageCopy = message->Clone(message->GetLength() - sizeof(Metadata));
+                Message *messageCopy = message.Clone(message.GetLength() - sizeof(Metadata));
 
                 if (messageCopy != nullptr)
                 {
@@ -381,7 +376,7 @@
                 }
 
                 metadata.GenerateNextTransmissionTime(now, kDataMessageInterval);
-                metadata.UpdateIn(*message);
+                metadata.UpdateIn(message);
 
                 if (nextTime > metadata.mTransmissionTime)
                 {
@@ -390,22 +385,22 @@
             }
             else
             {
-                mBufferedMessageSet.Dequeue(*message);
+                mBufferedMessageSet.Dequeue(message);
 
                 if (metadata.mTransmissionCount == GetTimerExpirations())
                 {
                     if (metadata.mTransmissionCount > 1)
                     {
-                        message->SetSubType(Message::kSubTypeMplRetransmission);
+                        message.SetSubType(Message::kSubTypeMplRetransmission);
                     }
 
-                    metadata.RemoveFrom(*message);
-                    Get<Ip6>().EnqueueDatagram(*message);
+                    metadata.RemoveFrom(message);
+                    Get<Ip6>().EnqueueDatagram(message);
                 }
                 else
                 {
                     // Stop retransmitting if the number of timer expirations is already exceeded.
-                    message->Free();
+                    message.Free();
                 }
             }
         }
diff --git a/src/core/net/ip6_types.hpp b/src/core/net/ip6_types.hpp
new file mode 100644
index 0000000..06af126
--- /dev/null
+++ b/src/core/net/ip6_types.hpp
@@ -0,0 +1,115 @@
+/*
+ *  Copyright (c) 2016-2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes types and constants for IPv6 processing.
+ */
+
+#ifndef IP6_TYPES_HPP_
+#define IP6_TYPES_HPP_
+
+#include "openthread-core-config.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace ot {
+namespace Ip6 {
+
+/**
+ * @addtogroup core-ip6-ip6
+ *
+ * @brief
+ *   This module includes definitions for core IPv6 networking.
+ *
+ * @{
+ *
+ */
+
+// Internet Protocol Numbers
+static constexpr uint8_t kProtoHopOpts  = OT_IP6_PROTO_HOP_OPTS; ///< IPv6 Hop-by-Hop Option
+static constexpr uint8_t kProtoTcp      = OT_IP6_PROTO_TCP;      ///< Transmission Control Protocol
+static constexpr uint8_t kProtoUdp      = OT_IP6_PROTO_UDP;      ///< User Datagram
+static constexpr uint8_t kProtoIp6      = OT_IP6_PROTO_IP6;      ///< IPv6 encapsulation
+static constexpr uint8_t kProtoRouting  = OT_IP6_PROTO_ROUTING;  ///< Routing Header for IPv6
+static constexpr uint8_t kProtoFragment = OT_IP6_PROTO_FRAGMENT; ///< Fragment Header for IPv6
+static constexpr uint8_t kProtoIcmp6    = OT_IP6_PROTO_ICMP6;    ///< ICMP for IPv6
+static constexpr uint8_t kProtoNone     = OT_IP6_PROTO_NONE;     ///< No Next Header for IPv6
+static constexpr uint8_t kProtoDstOpts  = OT_IP6_PROTO_DST_OPTS; ///< Destination Options for IPv6
+
+/**
+ * The max datagram length (in bytes) of an IPv6 message.
+ *
+ */
+static constexpr uint16_t kMaxDatagramLength = OPENTHREAD_CONFIG_IP6_MAX_DATAGRAM_LENGTH;
+
+/**
+ * The max datagram length (in bytes) of an unfragmented IPv6 message.
+ *
+ */
+static constexpr uint16_t kMaxAssembledDatagramLength = OPENTHREAD_CONFIG_IP6_MAX_ASSEMBLED_DATAGRAM;
+
+/**
+ * 6-bit Differentiated Services Code Point (DSCP) values.
+ *
+ */
+enum IpDscpCs : uint8_t
+{
+    kDscpCs0    = 0,    ///< Class selector codepoint 0
+    kDscpCs1    = 8,    ///< Class selector codepoint 8
+    kDscpCs2    = 16,   ///< Class selector codepoint 16
+    kDscpCs3    = 24,   ///< Class selector codepoint 24
+    kDscpCs4    = 32,   ///< Class selector codepoint 32
+    kDscpCs5    = 40,   ///< Class selector codepoint 40
+    kDscpCs6    = 48,   ///< Class selector codepoint 48
+    kDscpCs7    = 56,   ///< Class selector codepoint 56
+    kDscpCsMask = 0x38, ///< Class selector mask
+};
+
+/**
+ * This enumeration represents the 2-bit Explicit Congestion Notification (ECN) values.
+ *
+ */
+enum Ecn : uint8_t
+{
+    kEcnNotCapable = OT_ECN_NOT_CAPABLE, ///< Non ECN-Capable Transport (ECT).
+    kEcnCapable0   = OT_ECN_CAPABLE_0,   ///< ECN Capable Transport, ECT(0).
+    kEcnCapable1   = OT_ECN_CAPABLE_1,   ///< ECN Capable Transport, ECT(1).
+    kEcnMarked     = OT_ECN_MARKED,      ///< Congestion encountered.
+};
+
+/**
+ * @}
+ *
+ */
+
+} // namespace Ip6
+} // namespace ot
+
+#endif // IP6_TYPES_HPP_
diff --git a/src/core/net/nd6.cpp b/src/core/net/nd6.cpp
new file mode 100644
index 0000000..5b57e1b
--- /dev/null
+++ b/src/core/net/nd6.cpp
@@ -0,0 +1,282 @@
+/*
+ *  Copyright (c) 2020, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes implementations for IPv6 Neighbor Discovery (ND6).
+ *
+ */
+
+#include "nd6.hpp"
+
+#include "common/as_core_type.hpp"
+#include "common/code_utils.hpp"
+
+namespace ot {
+namespace Ip6 {
+namespace Nd {
+
+//----------------------------------------------------------------------------------------------------------------------
+// Option::Iterator
+
+Option::Iterator::Iterator(void)
+    : mOption(nullptr)
+    , mEnd(nullptr)
+{
+    // An empty iterator (used to indicate `end()` of list).
+}
+
+Option::Iterator::Iterator(const void *aStart, const void *aEnd)
+    : mOption(nullptr)
+    , mEnd(reinterpret_cast<const Option *>(aEnd))
+{
+    // Note that `Validate()` uses `mEnd` so can only be called after
+    // `mEnd` is set.
+
+    mOption = Validate(reinterpret_cast<const Option *>(aStart));
+}
+
+const Option *Option::Iterator::Next(const Option *aOption)
+{
+    return reinterpret_cast<const Option *>(reinterpret_cast<const uint8_t *>(aOption) + aOption->GetSize());
+}
+
+void Option::Iterator::Advance(void)
+{
+    mOption = (mOption != nullptr) ? Validate(Next(mOption)) : nullptr;
+}
+
+const Option *Option::Iterator::Validate(const Option *aOption) const
+{
+    // Check if `aOption` is well-formed and fits in the range
+    // up to `mEnd`. Returns `aOption` if it is valid, `nullptr`
+    // otherwise.
+
+    return ((aOption != nullptr) && ((aOption + 1) <= mEnd) && aOption->IsValid() && (Next(aOption) <= mEnd)) ? aOption
+                                                                                                              : nullptr;
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+// PrefixInfoOption
+
+void PrefixInfoOption::Init(void)
+{
+    Clear();
+    SetType(kTypePrefixInfo);
+    SetSize(sizeof(PrefixInfoOption));
+
+    OT_UNUSED_VARIABLE(mReserved2);
+}
+
+void PrefixInfoOption::SetPrefix(const Prefix &aPrefix)
+{
+    mPrefixLength = aPrefix.mLength;
+    mPrefix       = AsCoreType(&aPrefix.mPrefix);
+}
+
+void PrefixInfoOption::GetPrefix(Prefix &aPrefix) const
+{
+    aPrefix.Set(mPrefix.GetBytes(), mPrefixLength);
+}
+
+bool PrefixInfoOption::IsValid(void) const
+{
+    return (GetSize() >= sizeof(*this)) && (mPrefixLength <= Prefix::kMaxLength) &&
+           (GetPreferredLifetime() <= GetValidLifetime());
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+// RouteInfoOption
+
+void RouteInfoOption::Init(void)
+{
+    Clear();
+    SetType(kTypeRouteInfo);
+}
+
+void RouteInfoOption::SetPreference(RoutePreference aPreference)
+{
+    mResvdPrf &= ~kPreferenceMask;
+    mResvdPrf |= (NetworkData::RoutePreferenceToValue(aPreference) << kPreferenceOffset) & kPreferenceMask;
+}
+
+RoutePreference RouteInfoOption::GetPreference(void) const
+{
+    return NetworkData::RoutePreferenceFromValue((mResvdPrf & kPreferenceMask) >> kPreferenceOffset);
+}
+
+void RouteInfoOption::SetPrefix(const Prefix &aPrefix)
+{
+    SetLength(OptionLengthForPrefix(aPrefix.mLength));
+    mPrefixLength = aPrefix.mLength;
+    memcpy(GetPrefixBytes(), aPrefix.GetBytes(), aPrefix.GetBytesSize());
+}
+
+void RouteInfoOption::GetPrefix(Prefix &aPrefix) const
+{
+    aPrefix.Set(GetPrefixBytes(), mPrefixLength);
+}
+
+bool RouteInfoOption::IsValid(void) const
+{
+    return (GetSize() >= kMinSize) && (mPrefixLength <= Prefix::kMaxLength) &&
+           (GetLength() >= OptionLengthForPrefix(mPrefixLength)) &&
+           NetworkData::IsRoutePreferenceValid(GetPreference());
+}
+
+uint8_t RouteInfoOption::OptionLengthForPrefix(uint8_t aPrefixLength)
+{
+    static constexpr uint8_t kMaxPrefixLenForOptionLen1 = 0;
+    static constexpr uint8_t kMaxPrefixLenForOptionLen2 = 64;
+
+    uint8_t length;
+
+    // The Option Length can be 1, 2, or 3 depending on the prefix
+    // length
+    //
+    // - 1 when prefix len is zero.
+    // - 2 when prefix len is less then or equal to 64.
+    // - 3 otherwise.
+
+    if (aPrefixLength == kMaxPrefixLenForOptionLen1)
+    {
+        length = 1;
+    }
+    else if (aPrefixLength <= kMaxPrefixLenForOptionLen2)
+    {
+        length = 2;
+    }
+    else
+    {
+        length = 3;
+    }
+
+    return length;
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+// RouterAdverMessage::Header
+
+void RouterAdvertMessage::Header::SetToDefault(void)
+{
+    OT_UNUSED_VARIABLE(mCode);
+    OT_UNUSED_VARIABLE(mCurHopLimit);
+    OT_UNUSED_VARIABLE(mReachableTime);
+    OT_UNUSED_VARIABLE(mRetransTimer);
+
+    Clear();
+    mType = Icmp::Header::kTypeRouterAdvert;
+}
+
+RoutePreference RouterAdvertMessage::Header::GetDefaultRouterPreference(void) const
+{
+    return NetworkData::RoutePreferenceFromValue((mFlags & kPreferenceMask) >> kPreferenceOffset);
+}
+
+void RouterAdvertMessage::Header::SetDefaultRouterPreference(RoutePreference aPreference)
+{
+    mFlags &= ~kPreferenceMask;
+    mFlags |= (NetworkData::RoutePreferenceToValue(aPreference) << kPreferenceOffset) & kPreferenceMask;
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+// RouterAdverMessage
+
+Option *RouterAdvertMessage::AppendOption(uint16_t aOptionSize)
+{
+    // This method appends an option with a given size to the RA
+    // message by reserving space in the data buffer if there is
+    // room. On success returns pointer to the option, on failure
+    // returns `nullptr`. The returned option needs to be
+    // initialized and populated by the caller.
+
+    Option * option    = nullptr;
+    uint32_t newLength = mData.GetLength();
+
+    newLength += aOptionSize;
+    VerifyOrExit(newLength <= mMaxLength);
+
+    option = reinterpret_cast<Option *>(AsNonConst(GetDataEnd()));
+    mData.SetLength(static_cast<uint16_t>(newLength));
+
+exit:
+    return option;
+}
+
+Error RouterAdvertMessage::AppendPrefixInfoOption(const Prefix &aPrefix,
+                                                  uint32_t      aValidLifetime,
+                                                  uint32_t      aPreferredLifetime)
+{
+    Error             error = kErrorNone;
+    PrefixInfoOption *pio;
+
+    pio = static_cast<PrefixInfoOption *>(AppendOption(sizeof(PrefixInfoOption)));
+    VerifyOrExit(pio != nullptr, error = kErrorNoBufs);
+
+    pio->Init();
+    pio->SetOnLinkFlag();
+    pio->SetAutoAddrConfigFlag();
+    pio->SetValidLifetime(aValidLifetime);
+    pio->SetPreferredLifetime(aPreferredLifetime);
+    pio->SetPrefix(aPrefix);
+
+exit:
+    return error;
+}
+
+Error RouterAdvertMessage::AppendRouteInfoOption(const Prefix &  aPrefix,
+                                                 uint32_t        aRouteLifetime,
+                                                 RoutePreference aPreference)
+{
+    Error            error = kErrorNone;
+    RouteInfoOption *rio;
+
+    rio = static_cast<RouteInfoOption *>(AppendOption(RouteInfoOption::OptionSizeForPrefix(aPrefix.GetLength())));
+    VerifyOrExit(rio != nullptr, error = kErrorNoBufs);
+
+    rio->Init();
+    rio->SetRouteLifetime(aRouteLifetime);
+    rio->SetPreference(aPreference);
+    rio->SetPrefix(aPrefix);
+
+exit:
+    return error;
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+// RouterAdvMessage
+
+RouterSolicitMessage::RouterSolicitMessage(void)
+{
+    mHeader.Clear();
+    mHeader.SetType(Icmp::Header::kTypeRouterSolicit);
+}
+
+} // namespace Nd
+} // namespace Ip6
+} // namespace ot
diff --git a/src/core/net/nd6.hpp b/src/core/net/nd6.hpp
new file mode 100644
index 0000000..0ec6146
--- /dev/null
+++ b/src/core/net/nd6.hpp
@@ -0,0 +1,699 @@
+/*
+ *  Copyright (c) 2020, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes definitions for IPv6 Neighbor Discovery (ND).
+ *
+ * See RFC 4861 (https://tools.ietf.org/html/rfc4861) and RFC 4191 (https://tools.ietf.org/html/rfc4191).
+ *
+ */
+
+#ifndef ND6_HPP_
+#define ND6_HPP_
+
+#include "openthread-core-config.h"
+
+#include <stdint.h>
+
+#include <openthread/netdata.h>
+#include <openthread/platform/toolchain.h>
+
+#include "common/const_cast.hpp"
+#include "common/encoding.hpp"
+#include "common/equatable.hpp"
+#include "net/icmp6.hpp"
+#include "net/ip6.hpp"
+#include "thread/network_data_types.hpp"
+
+using ot::Encoding::BigEndian::HostSwap16;
+using ot::Encoding::BigEndian::HostSwap32;
+
+namespace ot {
+namespace Ip6 {
+namespace Nd {
+
+typedef NetworkData::RoutePreference RoutePreference; ///< Route Preference
+
+/**
+ * This class represents the variable length options in Neighbor Discovery messages.
+ *
+ * @sa PrefixInfoOption
+ * @sa RouteInfoOption
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class Option
+{
+    friend class RouterAdvertMessage;
+
+public:
+    enum Type : uint8_t
+    {
+        kTypePrefixInfo = 3,  ///< Prefix Information Option.
+        kTypeRouteInfo  = 24, ///< Route Information Option.
+    };
+
+    static constexpr uint16_t kLengthUnit = 8; ///< The unit of length in octets.
+
+    /**
+     * This method gets the option type.
+     *
+     * @returns  The option type.
+     *
+     */
+    uint8_t GetType(void) const { return mType; }
+
+    /**
+     * This method sets the option type.
+     *
+     * @param[in] aType  The option type.
+     *
+     *
+     */
+    void SetType(Type aType) { mType = aType; }
+
+    /**
+     * This method sets the length based on a given total option size in bytes.
+     *
+     * Th option must end on a 64-bit boundary, so the length is derived as `(aSize + 7) / 8 * 8`.
+     *
+     * @param[in]  aSize  The size of option in bytes.
+     *
+     */
+    void SetSize(uint16_t aSize) { mLength = static_cast<uint8_t>((aSize + kLengthUnit - 1) / kLengthUnit); }
+
+    /**
+     * This method returns the size of the option in bytes.
+     *
+     * @returns  The size of the option in bytes.
+     *
+     */
+    uint16_t GetSize(void) const { return mLength * kLengthUnit; }
+
+    /**
+     * This method sets the length of the option (in unit of 8 bytes).
+     *
+     * @param[in]  aLength  The length of the option in unit of 8 bytes.
+     *
+     */
+    void SetLength(uint8_t aLength) { mLength = aLength; }
+
+    /**
+     * This method returns the length of the option (in unit of 8 bytes).
+     *
+     * @returns  The length of the option in unit of 8 bytes.
+     *
+     */
+    uint16_t GetLength(void) const { return mLength; }
+
+    /**
+     * This method indicates whether or not this option is valid.
+     *
+     * @retval TRUE   The option is valid.
+     * @retval FALSE  The option is not valid.
+     *
+     */
+    bool IsValid(void) const { return mLength > 0; }
+
+private:
+    class Iterator : public Unequatable<Iterator>
+    {
+    public:
+        Iterator(void);
+        Iterator(const void *aStart, const void *aEnd);
+
+        const Option &operator*(void) { return *mOption; }
+        void          operator++(void) { Advance(); }
+        void          operator++(int) { Advance(); }
+        bool          operator==(const Iterator &aOther) const { return mOption == aOther.mOption; }
+
+    private:
+        static const Option *Next(const Option *aOption);
+        void                 Advance(void);
+        const Option *       Validate(const Option *aOption) const;
+
+        const Option *mOption;
+        const Option *mEnd;
+    };
+
+    uint8_t mType;   // Type of the option.
+    uint8_t mLength; // Length of the option in unit of 8 octets, including the `mType` and `mLength` fields.
+} OT_TOOL_PACKED_END;
+
+/**
+ * This class represents the Prefix Information Option.
+ *
+ * See section 4.6.2 of RFC 4861 for definition of this option [https://tools.ietf.org/html/rfc4861#section-4.6.2]
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class PrefixInfoOption : public Option, private Clearable<PrefixInfoOption>
+{
+public:
+    static constexpr Type kType = kTypePrefixInfo; ///< Prefix Information Option Type.
+
+    /**
+     * This method initializes the Prefix Info option with proper type and length and sets all other fields to zero.
+     *
+     */
+    void Init(void);
+
+    /**
+     * This method indicates whether or not the on-link flag is set.
+     *
+     * @retval TRUE  The on-link flag is set.
+     * @retval FALSE The on-link flag is not set.
+     *
+     */
+    bool IsOnLinkFlagSet(void) const { return (mFlags & kOnLinkFlagMask) != 0; }
+
+    /**
+     * This method sets the on-link (L) flag.
+     *
+     */
+    void SetOnLinkFlag(void) { mFlags |= kOnLinkFlagMask; }
+
+    /**
+     * This method clears the on-link (L) flag.
+     *
+     */
+    void ClearOnLinkFlag(void) { mFlags &= ~kOnLinkFlagMask; }
+
+    /**
+     * This method indicates whether or not the autonomous address-configuration (A) flag is set.
+     *
+     * @retval TRUE  The auto address-config flag is set.
+     * @retval FALSE The auto address-config flag is not set.
+     *
+     */
+    bool IsAutoAddrConfigFlagSet(void) const { return (mFlags & kAutoConfigFlagMask) != 0; }
+
+    /**
+     * This method sets the autonomous address-configuration (A) flag.
+     *
+     */
+    void SetAutoAddrConfigFlag(void) { mFlags |= kAutoConfigFlagMask; }
+
+    /**
+     * This method clears the autonomous address-configuration (A) flag.
+     *
+     */
+    void ClearAutoAddrConfigFlag(void) { mFlags &= ~kAutoConfigFlagMask; }
+
+    /**
+     * This method sets the valid lifetime of the prefix in seconds.
+     *
+     * @param[in]  aValidLifetime  The valid lifetime in seconds.
+     *
+     */
+    void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = HostSwap32(aValidLifetime); }
+
+    /**
+     * THis method gets the valid lifetime of the prefix in seconds.
+     *
+     * @returns  The valid lifetime in seconds.
+     *
+     */
+    uint32_t GetValidLifetime(void) const { return HostSwap32(mValidLifetime); }
+
+    /**
+     * This method sets the preferred lifetime of the prefix in seconds.
+     *
+     * @param[in]  aPreferredLifetime  The preferred lifetime in seconds.
+     *
+     */
+    void SetPreferredLifetime(uint32_t aPreferredLifetime) { mPreferredLifetime = HostSwap32(aPreferredLifetime); }
+
+    /**
+     * THis method returns the preferred lifetime of the prefix in seconds.
+     *
+     * @returns  The preferred lifetime in seconds.
+     *
+     */
+    uint32_t GetPreferredLifetime(void) const { return HostSwap32(mPreferredLifetime); }
+
+    /**
+     * This method sets the prefix.
+     *
+     * @param[in]  aPrefix  The prefix contained in this option.
+     *
+     */
+    void SetPrefix(const Prefix &aPrefix);
+
+    /**
+     * This method gets the prefix in this option.
+     *
+     * @param[out] aPrefix   Reference to a `Prefix` to return the prefix.
+     *
+     */
+    void GetPrefix(Prefix &aPrefix) const;
+
+    /**
+     * This method indicates whether or not the option is valid.
+     *
+     * @retval TRUE  The option is valid
+     * @retval FALSE The option is not valid.
+     *
+     */
+    bool IsValid(void) const;
+
+    PrefixInfoOption(void) = delete;
+
+private:
+    // Prefix Information Option
+    //
+    //   0                   1                   2                   3
+    //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    //  |     Type      |    Length     | Prefix Length |L|A| Reserved1 |
+    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    //  |                         Valid Lifetime                        |
+    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    //  |                       Preferred Lifetime                      |
+    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    //  |                           Reserved2                           |
+    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    //  |                                                               |
+    //  +                                                               +
+    //  |                                                               |
+    //  +                            Prefix                             +
+    //  |                                                               |
+    //  +                                                               +
+    //  |                                                               |
+    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+    static constexpr uint8_t kAutoConfigFlagMask = 0x40; // Autonomous address-configuration flag.
+    static constexpr uint8_t kOnLinkFlagMask     = 0x80; // On-link flag.
+
+    uint8_t  mPrefixLength;      // The prefix length in bits.
+    uint8_t  mFlags;             // The flags field.
+    uint32_t mValidLifetime;     // The valid lifetime of the prefix.
+    uint32_t mPreferredLifetime; // The preferred lifetime of the prefix.
+    uint32_t mReserved2;         // The reserved field.
+    Address  mPrefix;            // The prefix.
+} OT_TOOL_PACKED_END;
+
+static_assert(sizeof(PrefixInfoOption) == 32, "invalid PrefixInfoOption structure");
+
+/**
+ * This class represents the Route Information Option.
+ *
+ * See section 2.3 of RFC 4191 for definition of this option. [https://tools.ietf.org/html/rfc4191#section-2.3]
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class RouteInfoOption : public Option, private Clearable<RouteInfoOption>
+{
+public:
+    static constexpr uint16_t kMinSize = kLengthUnit;    ///< Minimum size (in bytes) of a Route Info Option
+    static constexpr Type     kType    = kTypeRouteInfo; ///< Route Information Option Type.
+
+    /**
+     * This method initializes the option setting the type and clearing (setting to zero) all other fields.
+     *
+     */
+    void Init(void);
+
+    /**
+     * This method sets the route preference.
+     *
+     * @param[in]  aPreference  The route preference.
+     *
+     */
+    void SetPreference(RoutePreference aPreference);
+
+    /**
+     * This method gets the route preference.
+     *
+     * @returns  The route preference.
+     *
+     */
+    RoutePreference GetPreference(void) const;
+
+    /**
+     * This method sets the lifetime of the route in seconds.
+     *
+     * @param[in]  aLifetime  The lifetime of the route in seconds.
+     *
+     */
+    void SetRouteLifetime(uint32_t aLifetime) { mRouteLifetime = HostSwap32(aLifetime); }
+
+    /**
+     * This method gets Route Lifetime in seconds.
+     *
+     * @returns  The Route Lifetime in seconds.
+     *
+     */
+    uint32_t GetRouteLifetime(void) const { return HostSwap32(mRouteLifetime); }
+
+    /**
+     * This method sets the prefix and adjusts the option length based on the prefix length.
+     *
+     * @param[in]  aPrefix  The prefix contained in this option.
+     *
+     */
+    void SetPrefix(const Prefix &aPrefix);
+
+    /**
+     * This method gets the prefix in this option.
+     *
+     * @param[out] aPrefix   Reference to a `Prefix` to return the prefix.
+     *
+     */
+    void GetPrefix(Prefix &aPrefix) const;
+
+    /**
+     * This method tells whether this option is valid.
+     *
+     * @returns  A boolean indicates whether this option is valid.
+     *
+     */
+    bool IsValid(void) const;
+
+    /**
+     * This static method calculates the minimum option length for a given prefix length.
+     *
+     * The option length (which is in unit of 8 octets) can be 1, 2, or 3 depending on the prefix length. It can be 1
+     * for a zero prefix length, 2 if the prefix length is not greater than 64, and 3 otherwise.
+     *
+     * @param[in] aPrefixLength   The prefix length (in bits).
+     *
+     * @returns The option length (in unit of 8 octet) for @p aPrefixLength.
+     *
+     */
+    static uint8_t OptionLengthForPrefix(uint8_t aPrefixLength);
+
+    /**
+     * This static method calculates the minimum option size (in bytes) for a given prefix length.
+     *
+     * @param[in] aPrefixLength   The prefix length (in bits).
+     *
+     * @returns The option size (in bytes) for @p aPrefixLength.
+     *
+     */
+    static uint16_t OptionSizeForPrefix(uint8_t aPrefixLength)
+    {
+        return kLengthUnit * OptionLengthForPrefix(aPrefixLength);
+    }
+
+    RouteInfoOption(void) = delete;
+
+private:
+    // Route Information Option
+    //
+    //   0                   1                   2                   3
+    //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    //  |     Type      |    Length     | Prefix Length |Resvd|Prf|Resvd|
+    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    //  |                        Route Lifetime                         |
+    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+    //  |                   Prefix (Variable Length)                    |
+    //  .                                                               .
+    //  .                                                               .
+    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+    static constexpr uint8_t kPreferenceOffset = 3;
+    static constexpr uint8_t kPreferenceMask   = 3 << kPreferenceOffset;
+
+    uint8_t *      GetPrefixBytes(void) { return AsNonConst(AsConst(this)->GetPrefixBytes()); }
+    const uint8_t *GetPrefixBytes(void) const { return reinterpret_cast<const uint8_t *>(this) + sizeof(*this); }
+
+    uint8_t  mPrefixLength;  // The prefix length in bits.
+    uint8_t  mResvdPrf;      // The preference.
+    uint32_t mRouteLifetime; // The lifetime in seconds.
+    // Followed by prefix bytes (variable length).
+
+} OT_TOOL_PACKED_END;
+
+static_assert(sizeof(RouteInfoOption) == 8, "invalid RouteInfoOption structure");
+
+/**
+ * This class represents a Router Advertisement message.
+ *
+ */
+class RouterAdvertMessage
+{
+public:
+    /**
+     * This class implements the RA message header.
+     *
+     * See section 2.2 of RFC 4191 [https://datatracker.ietf.org/doc/html/rfc4191]
+     *
+     */
+    OT_TOOL_PACKED_BEGIN
+    class Header : public Equatable<Header>, private Clearable<Header>
+    {
+    public:
+        /**
+         * This constructor initializes the Router Advertisement message with
+         * zero router lifetime, reachable time and retransmission timer.
+         *
+         */
+        Header(void) { SetToDefault(); }
+
+        /**
+         * This method sets the RA message to default values.
+         *
+         */
+        void SetToDefault(void);
+
+        /**
+         * This method sets the checksum value.
+         *
+         * @param[in]  aChecksum  The checksum value.
+         *
+         */
+        void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); }
+
+        /**
+         * This method sets the Router Lifetime in seconds.
+         *
+         * @param[in]  aRouterLifetime  The router lifetime in seconds.
+         *
+         */
+        void SetRouterLifetime(uint16_t aRouterLifetime) { mRouterLifetime = HostSwap16(aRouterLifetime); }
+
+        /**
+         * This method gets the Router Lifetime (in seconds).
+         *
+         * Router Lifetime set to zero indicates that the sender is not a default router.
+         *
+         * @returns  The router lifetime in seconds.
+         *
+         */
+        uint16_t GetRouterLifetime(void) const { return HostSwap16(mRouterLifetime); }
+
+        /**
+         * This method sets the default router preference.
+         *
+         * @param[in]  aPreference  The router preference.
+         *
+         */
+        void SetDefaultRouterPreference(RoutePreference aPreference);
+
+        /**
+         * This method gets the default router preference.
+         *
+         * @returns  The router preference.
+         *
+         */
+        RoutePreference GetDefaultRouterPreference(void) const;
+
+    private:
+        // Router Advertisement Message
+        //
+        //   0                   1                   2                   3
+        //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+        //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        //  |     Type      |     Code      |          Checksum             |
+        //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        //  | Cur Hop Limit |M|O|H|Prf|Resvd|       Router Lifetime         |
+        //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        //  |                         Reachable Time                        |
+        //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        //  |                          Retrans Timer                        |
+        //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+        //  |   Options ...
+        //  +-+-+-+-+-+-+-+-+-+-+-+-
+
+        static constexpr uint8_t kPreferenceOffset = 3;
+        static constexpr uint8_t kPreferenceMask   = 3 << kPreferenceOffset;
+
+        uint8_t  mType;
+        uint8_t  mCode;
+        uint16_t mChecksum;
+        uint8_t  mCurHopLimit;
+        uint8_t  mFlags;
+        uint16_t mRouterLifetime;
+        uint32_t mReachableTime;
+        uint32_t mRetransTimer;
+    } OT_TOOL_PACKED_END;
+
+    static_assert(sizeof(Header) == 16, "Invalid RA `Header`");
+
+    typedef Data<kWithUint16Length> Icmp6Packet; ///< A data buffer containing an ICMPv6 packet.
+
+    /**
+     * This constructor initializes the RA message from a received packet data buffer.
+     *
+     * @param[in] aPacket   A received packet data.
+     *
+     */
+    explicit RouterAdvertMessage(const Icmp6Packet &aPacket)
+        : mData(aPacket)
+        , mMaxLength(0)
+    {
+    }
+
+    /**
+     * This template constructor initializes the RA message with a given header using a given buffer to store the RA
+     * message.
+     *
+     * @tparam kBufferSize   The size of the buffer used to store the RA message.
+     *
+     * @param[in] aHeader    The RA message header.
+     * @param[in] aBuffer    The data buffer to store the RA message in.
+     *
+     */
+    template <uint16_t kBufferSize>
+    RouterAdvertMessage(const Header &aHeader, uint8_t (&aBuffer)[kBufferSize])
+        : mMaxLength(kBufferSize)
+    {
+        static_assert(kBufferSize >= sizeof(Header), "Buffer for RA msg is too small");
+
+        memcpy(aBuffer, &aHeader, sizeof(Header));
+        mData.Init(aBuffer, sizeof(Header));
+    }
+
+    /**
+     * This method gets the RA message as an `Icmp6Packet`.
+     *
+     * @returns The RA message as an `Icmp6Packet`.
+     *
+     */
+    const Icmp6Packet &GetAsPacket(void) const { return mData; }
+
+    /**
+     * This method indicates whether or not the RA message is valid.
+     *
+     * @retval TRUE   If the RA message is valid.
+     * @retval FALSE  If the RA message is not valid.
+     *
+     */
+    bool IsValid(void) const { return (mData.GetBytes() != nullptr) && (mData.GetLength() >= sizeof(Header)); }
+
+    /**
+     * This method gets the RA message's header.
+     *
+     * @returns The RA message's header.
+     *
+     */
+    const Header &GetHeader(void) const { return *reinterpret_cast<const Header *>(mData.GetBytes()); }
+
+    /**
+     * This method appends a Prefix Info Option to the RA message.
+     *
+     * The appended Prefix Info Option will have both on-link (L) and autonomous address-configuration (A) flags set.
+     *
+     * @param[in] aPrefix             The prefix.
+     * @param[in] aValidLifetime      The valid lifetime in seconds.
+     * @param[in] aPreferredLifetime  The preferred lifetime in seconds.
+     *
+     * @retval kErrorNone    Option is appended successfully.
+     * @retval kErrorNoBufs  No more space in the buffer to append the option.
+     *
+     */
+    Error AppendPrefixInfoOption(const Prefix &aPrefix, uint32_t aValidLifetime, uint32_t aPreferredLifetime);
+
+    /**
+     * This method appends a Route Info Option to the RA message.
+     *
+     * @param[in] aPrefix             The prefix.
+     * @param[in] aRouteLifetime      The route lifetime in seconds.
+     * @param[in] aPreference         The route preference.
+     *
+     * @retval kErrorNone    Option is appended successfully.
+     * @retval kErrorNoBufs  No more space in the buffer to append the option.
+     *
+     */
+    Error AppendRouteInfoOption(const Prefix &aPrefix, uint32_t aRouteLifetime, RoutePreference aPreference);
+
+    /**
+     * This method indicates whether or not the RA message contains any options.
+     *
+     * @retval TRUE   If the RA message contains at least one option.
+     * @retval FALSE  If the RA message contains no options.
+     *
+     */
+    bool ContainsAnyOptions(void) const { return (mData.GetLength() > sizeof(Header)); }
+
+    // The following methods are intended to support range-based `for`
+    // loop iteration over `Option`s in the RA message.
+
+    Option::Iterator begin(void) const { return Option::Iterator(GetOptionStart(), GetDataEnd()); }
+    Option::Iterator end(void) const { return Option::Iterator(); }
+
+private:
+    const uint8_t *GetOptionStart(void) const { return (mData.GetBytes() + sizeof(Header)); }
+    const uint8_t *GetDataEnd(void) const { return mData.GetBytes() + mData.GetLength(); }
+    Option *       AppendOption(uint16_t aOptionSize);
+
+    Data<kWithUint16Length> mData;
+    uint16_t                mMaxLength;
+};
+
+/**
+ * This class implements the Router Solicitation message.
+ *
+ * See section 4.1 of RFC 4861 for definition of this message.
+ * https://tools.ietf.org/html/rfc4861#section-4.1
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class RouterSolicitMessage
+{
+public:
+    /**
+     * This constructor initializes the Router Solicitation message.
+     *
+     */
+    RouterSolicitMessage(void);
+
+private:
+    Icmp::Header mHeader; // The common ICMPv6 header.
+} OT_TOOL_PACKED_END;
+
+static_assert(sizeof(RouterSolicitMessage) == 8, "invalid RouterSolicitMessage structure");
+
+} // namespace Nd
+} // namespace Ip6
+} // namespace ot
+
+#endif // ND6_HPP_
diff --git a/src/core/net/netif.cpp b/src/core/net/netif.cpp
index 3f737e9..a55914f 100644
--- a/src/core/net/netif.cpp
+++ b/src/core/net/netif.cpp
@@ -71,7 +71,7 @@
  * Certain fixed multicast addresses are defined as a set of chained (linked-list) constant `otNetifMulticastAddress`
  * entries:
  *
- * LinkLocalAllRouters -> RealmLocalAllRouters -> LinkLocalAll -> RealmLocalAll -> RealmLocalAllMplForwarders -> nullptr
+ * LinkLocalAllRouters -> RealmLocalAllRouters -> LinkLocalAll -> RealmLocalAll -> RealmLocalAllMplForwarders.
  *
  * All or a portion of the chain is appended to the end of `mMulticastAddresses` linked-list. If the interface is
  * subscribed to all-routers multicast addresses (using `SubscribeAllRoutersMulticast()`) then all the five entries
@@ -399,7 +399,7 @@
 
     for (const MulticastAddress *cur = &linkLocalAllRoutersAddress; cur; cur = cur->GetNext())
     {
-        VerifyOrExit(cur->GetAddress() != aAddress, error = kErrorInvalidArgs);
+        VerifyOrExit(cur->GetAddress() != aAddress, error = kErrorRejected);
     }
 
     entry = mExtMulticastAddressPool.Allocate();
@@ -430,7 +430,7 @@
     entry = mMulticastAddresses.FindMatching(aAddress, prev);
     VerifyOrExit(entry != nullptr, error = kErrorNotFound);
 
-    VerifyOrExit(IsMulticastAddressExternal(*entry), error = kErrorInvalidArgs);
+    VerifyOrExit(IsMulticastAddressExternal(*entry), error = kErrorRejected);
 
     mMulticastAddresses.PopAfter(prev);
 
@@ -556,7 +556,7 @@
     entry = mUnicastAddresses.FindMatching(aAddress, prev);
     VerifyOrExit(entry != nullptr, error = kErrorNotFound);
 
-    VerifyOrExit(IsUnicastAddressExternal(*entry), error = kErrorInvalidArgs);
+    VerifyOrExit(IsUnicastAddressExternal(*entry), error = kErrorRejected);
 
     mUnicastAddresses.PopAfter(prev);
 
diff --git a/src/core/net/netif.hpp b/src/core/net/netif.hpp
index 61ff2c2..6501355 100644
--- a/src/core/net/netif.hpp
+++ b/src/core/net/netif.hpp
@@ -36,6 +36,7 @@
 
 #include "openthread-core-config.h"
 
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/code_utils.hpp"
 #include "common/const_cast.hpp"
@@ -149,7 +150,7 @@
          * @returns The unicast address.
          *
          */
-        const Address &GetAddress(void) const { return static_cast<const Address &>(mAddress); }
+        const Address &GetAddress(void) const { return AsCoreType(&mAddress); }
 
         /**
          * This method returns the unicast address.
@@ -157,7 +158,7 @@
          * @returns The unicast address.
          *
          */
-        Address &GetAddress(void) { return static_cast<Address &>(mAddress); }
+        Address &GetAddress(void) { return AsCoreType(&mAddress); }
 
         /**
          * This method returns the address's prefix length (in bits).
@@ -234,7 +235,7 @@
          * @returns The multicast address.
          *
          */
-        const Address &GetAddress(void) const { return static_cast<const Address &>(mAddress); }
+        const Address &GetAddress(void) const { return AsCoreType(&mAddress); }
 
         /**
          * This method returns the multicast address.
@@ -242,7 +243,7 @@
          * @returns The multicast address.
          *
          */
-        Address &GetAddress(void) { return static_cast<Address &>(mAddress); }
+        Address &GetAddress(void) { return AsCoreType(&mAddress); }
 
         /**
          * This method returns the next multicast address subscribed to the interface.
@@ -547,7 +548,8 @@
      *
      * @retval kErrorNone          Successfully subscribed to @p aAddress.
      * @retval kErrorAlready       The multicast address is already subscribed.
-     * @retval kErrorInvalidArgs   The address indicated by @p aAddress is an internal multicast address.
+     * @retval kErrorInvalidArgs   The IP Address indicated by @p aAddress is an invalid multicast address.
+     * @retval kErrorRejected      The IP Address indicated by @p aAddress is an internal multicast address.
      * @retval kErrorNoBufs        The maximum number of allowed external multicast addresses are already added.
      *
      */
@@ -559,7 +561,7 @@
      * @param[in]  aAddress  A reference to the multicast address.
      *
      * @retval kErrorNone         Successfully unsubscribed to the unicast address.
-     * @retval kErrorInvalidArgs  The address indicated by @p aAddress is an internal address.
+     * @retval kErrorRejected     The address indicated by @p aAddress is an internal address.
      * @retval kErrorNotFound     The multicast address was not found.
      *
      */
@@ -665,6 +667,10 @@
  */
 
 } // namespace Ip6
+
+DefineCoreType(otNetifAddress, Ip6::Netif::UnicastAddress);
+DefineCoreType(otNetifMulticastAddress, Ip6::Netif::MulticastAddress);
+
 } // namespace ot
 
 #endif // NET_NETIF_HPP_
diff --git a/src/core/net/sntp_client.cpp b/src/core/net/sntp_client.cpp
index 108370b..b2e82f2 100644
--- a/src/core/net/sntp_client.cpp
+++ b/src/core/net/sntp_client.cpp
@@ -36,7 +36,7 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "net/udp6.hpp"
 #include "thread/thread_netif.hpp"
 
@@ -48,6 +48,8 @@
 namespace ot {
 namespace Sntp {
 
+RegisterLogModule("SntpClnt");
+
 Header::Header(void)
     : mFlags(kNtpVersion << kVersionOffset | kModeClient << kModeOffset)
     , mStratum(0)
@@ -111,18 +113,12 @@
 
 Error Client::Stop(void)
 {
-    Message *     message = mPendingQueries.GetHead();
-    Message *     messageToRemove;
-    QueryMetadata queryMetadata;
-
-    // Remove all pending queries.
-    while (message != nullptr)
+    for (Message &message : mPendingQueries)
     {
-        messageToRemove = message;
-        message         = message->GetNext();
+        QueryMetadata queryMetadata;
 
-        queryMetadata.ReadFrom(*messageToRemove);
-        FinalizeSntpTransaction(*messageToRemove, queryMetadata, 0, kErrorAbort);
+        queryMetadata.ReadFrom(message);
+        FinalizeSntpTransaction(message, queryMetadata, 0, kErrorAbort);
     }
 
     return mSocket.Close();
@@ -237,30 +233,27 @@
     if (error != kErrorNone)
     {
         FreeMessage(messageCopy);
-        otLogWarnIp6("Failed to send SNTP request: %s", ErrorToString(error));
+        LogWarn("Failed to send SNTP request: %s", ErrorToString(error));
     }
 }
 
 Message *Client::FindRelatedQuery(const Header &aResponseHeader, QueryMetadata &aQueryMetadata)
 {
-    Header   header;
-    Message *message = mPendingQueries.GetHead();
+    Message *matchedMessage = nullptr;
 
-    while (message != nullptr)
+    for (Message &message : mPendingQueries)
     {
         // Read originate timestamp.
-        aQueryMetadata.ReadFrom(*message);
+        aQueryMetadata.ReadFrom(message);
 
         if (aQueryMetadata.mTransmitTimestamp == aResponseHeader.GetOriginateTimestampSeconds())
         {
-            ExitNow();
+            matchedMessage = &message;
+            break;
         }
-
-        message = message->GetNext();
     }
 
-exit:
-    return message;
+    return matchedMessage;
 }
 
 void Client::FinalizeSntpTransaction(Message &            aQuery,
@@ -286,36 +279,32 @@
     TimeMilli        now      = TimerMilli::GetNow();
     TimeMilli        nextTime = now.GetDistantFuture();
     QueryMetadata    queryMetadata;
-    Message *        message;
-    Message *        nextMessage;
     Ip6::MessageInfo messageInfo;
 
-    for (message = mPendingQueries.GetHead(); message != nullptr; message = nextMessage)
+    for (Message &message : mPendingQueries)
     {
-        nextMessage = message->GetNext();
-
-        queryMetadata.ReadFrom(*message);
+        queryMetadata.ReadFrom(message);
 
         if (now >= queryMetadata.mTransmissionTime)
         {
             if (queryMetadata.mRetransmissionCount >= kMaxRetransmit)
             {
                 // No expected response.
-                FinalizeSntpTransaction(*message, queryMetadata, 0, kErrorResponseTimeout);
+                FinalizeSntpTransaction(message, queryMetadata, 0, kErrorResponseTimeout);
                 continue;
             }
 
             // Increment retransmission counter and timer.
             queryMetadata.mRetransmissionCount++;
             queryMetadata.mTransmissionTime = now + kResponseTimeout;
-            queryMetadata.UpdateIn(*message);
+            queryMetadata.UpdateIn(message);
 
             // Retransmit
             messageInfo.SetPeerAddr(queryMetadata.mDestinationAddress);
             messageInfo.SetPeerPort(queryMetadata.mDestinationPort);
             messageInfo.SetSockAddr(queryMetadata.mSourceAddress);
 
-            SendCopy(*message, messageInfo);
+            SendCopy(message, messageInfo);
         }
 
         if (nextTime > queryMetadata.mTransmissionTime)
@@ -360,7 +349,7 @@
         memcpy(kissCode, responseHeader.GetKissCode(), Header::kKissCodeLength);
         kissCode[Header::kKissCodeLength] = 0;
 
-        otLogInfoIp6("SNTP response contains the Kiss-o'-death packet with %s code", kissCode);
+        LogInfo("SNTP response contains the Kiss-o'-death packet with %s code", kissCode);
         ExitNow(error = kErrorBusy);
     }
 
diff --git a/src/core/net/socket.hpp b/src/core/net/socket.hpp
index 8b1f3f3..fed22d1 100644
--- a/src/core/net/socket.hpp
+++ b/src/core/net/socket.hpp
@@ -39,6 +39,7 @@
 #include "common/clearable.hpp"
 #include "common/equatable.hpp"
 #include "net/ip6_address.hpp"
+#include "net/ip6_types.hpp"
 
 namespace ot {
 
@@ -72,7 +73,7 @@
      * @returns A reference to the local socket address.
      *
      */
-    Address &GetSockAddr(void) { return *static_cast<Address *>(&mSockAddr); }
+    Address &GetSockAddr(void) { return AsCoreType(&mSockAddr); }
 
     /**
      * This method returns a reference to the local socket address.
@@ -80,7 +81,7 @@
      * @returns A reference to the local socket address.
      *
      */
-    const Address &GetSockAddr(void) const { return *static_cast<const Address *>(&mSockAddr); }
+    const Address &GetSockAddr(void) const { return AsCoreType(&mSockAddr); }
 
     /**
      * This method sets the local socket address.
@@ -112,7 +113,7 @@
      * @returns A reference to the peer socket address.
      *
      */
-    Address &GetPeerAddr(void) { return *static_cast<Address *>(&mPeerAddr); }
+    Address &GetPeerAddr(void) { return AsCoreType(&mPeerAddr); }
 
     /**
      * This method returns a reference to the peer socket address.
@@ -120,7 +121,7 @@
      * @returns A reference to the peer socket address.
      *
      */
-    const Address &GetPeerAddr(void) const { return *static_cast<const Address *>(&mPeerAddr); }
+    const Address &GetPeerAddr(void) const { return AsCoreType(&mPeerAddr); }
 
     /**
      * This method sets the peer's socket address.
@@ -209,7 +210,7 @@
      * @returns The ECN status, as represented in the IP header.
      *
      */
-    uint8_t GetEcn(void) const { return mEcn; }
+    Ecn GetEcn(void) const { return static_cast<Ecn>(mEcn); }
 
     /**
      * This method sets the ECN status.
@@ -217,7 +218,7 @@
      * @param[in]  aEcn  The ECN status, as represented in the IP header.
      *
      */
-    void SetEcn(uint8_t aEcn) { mEcn = aEcn; }
+    void SetEcn(Ecn aEcn) { mEcn = aEcn; }
 
     /**
      * This method indicates whether peer is via the host interface.
@@ -298,7 +299,7 @@
      * @returns A reference to the IPv6 address.
      *
      */
-    Address &GetAddress(void) { return *static_cast<Address *>(&mAddress); }
+    Address &GetAddress(void) { return AsCoreType(&mAddress); }
 
     /**
      * This method returns a reference to the IPv6 address.
@@ -306,7 +307,7 @@
      * @returns A reference to the IPv6 address.
      *
      */
-    const Address &GetAddress(void) const { return *static_cast<const Address *>(&mAddress); }
+    const Address &GetAddress(void) const { return AsCoreType(&mAddress); }
 
     /**
      * This method sets the IPv6 address.
@@ -380,6 +381,10 @@
  */
 
 } // namespace Ip6
+
+DefineCoreType(otMessageInfo, Ip6::MessageInfo);
+DefineCoreType(otSockAddr, Ip6::SockAddr);
+
 } // namespace ot
 
 #endif // NET_SOCKET_HPP_
diff --git a/src/core/net/srp_client.cpp b/src/core/net/srp_client.cpp
index 2b34dba..5bf507b 100644
--- a/src/core/net/srp_client.cpp
+++ b/src/core/net/srp_client.cpp
@@ -35,12 +35,9 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
-#include "common/numeric_limits.hpp"
 #include "common/random.hpp"
 #include "common/settings.hpp"
 #include "common/string.hpp"
-#include "thread/network_data_service.hpp"
 
 /**
  * @file
@@ -50,6 +47,8 @@
 namespace ot {
 namespace Srp {
 
+RegisterLogModule("SrpClient");
+
 //---------------------------------------------------------------------
 // Client::HostInfo
 
@@ -72,21 +71,31 @@
 {
     if (aState != GetState())
     {
-        otLogInfoSrp("[client] HostInfo %s -> %s", ItemStateToString(GetState()), ItemStateToString(aState));
+        LogInfo("HostInfo %s -> %s", ItemStateToString(GetState()), ItemStateToString(aState));
         mState = MapEnum(aState);
     }
 }
 
+void Client::HostInfo::EnableAutoAddress(void)
+{
+    mAddresses    = nullptr;
+    mNumAddresses = 0;
+    mAutoAddress  = true;
+
+    LogInfo("HostInfo enabled auto address", GetNumAddresses());
+}
+
 void Client::HostInfo::SetAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses)
 {
     mAddresses    = aAddresses;
     mNumAddresses = aNumAddresses;
+    mAutoAddress  = false;
 
-    otLogInfoSrp("[client] HostInfo set %d addrs", GetNumAddresses());
+    LogInfo("HostInfo set %d addrs", GetNumAddresses());
 
     for (uint8_t index = 0; index < GetNumAddresses(); index++)
     {
-        otLogInfoSrp("[client] %s", GetAddress(index).ToString().AsCString());
+        LogInfo("%s", GetAddress(index).ToString().AsCString());
     }
 }
 
@@ -112,8 +121,8 @@
 {
     VerifyOrExit(GetState() != aState);
 
-    otLogInfoSrp("[client] Service %s -> %s, \"%s\" \"%s\"", ItemStateToString(GetState()), ItemStateToString(aState),
-                 GetInstanceName(), GetName());
+    LogInfo("Service %s -> %s, \"%s\" \"%s\"", ItemStateToString(GetState()), ItemStateToString(aState),
+            GetInstanceName(), GetName());
 
     if (aState == kToAdd)
     {
@@ -133,8 +142,8 @@
             }
         }
 
-        otLogInfoSrp("[client] subtypes:[%s] port:%d weight:%d prio:%d txts:%d", string.AsCString(), GetPort(),
-                     GetWeight(), GetPriority(), GetNumTxtEntries());
+        LogInfo("subtypes:[%s] port:%d weight:%d prio:%d txts:%d", string.AsCString(), GetPort(), GetWeight(),
+                GetPriority(), GetNumTxtEntries());
     }
 
     mState = MapEnum(aState);
@@ -154,6 +163,83 @@
 }
 
 //---------------------------------------------------------------------
+// Client::AutoStart
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+
+Client::AutoStart::AutoStart(void)
+{
+    Clear();
+    mState = kDefaultMode ? kSelectedNone : kDisabled;
+}
+
+bool Client::AutoStart::HasSelectedServer(void) const
+{
+    bool hasSelected = false;
+
+    switch (mState)
+    {
+    case kDisabled:
+    case kSelectedNone:
+        break;
+
+    case kSelectedUnicastPreferred:
+    case kSelectedUnicast:
+    case kSelectedAnycast:
+        hasSelected = true;
+        break;
+    }
+
+    return hasSelected;
+}
+
+void Client::AutoStart::SetState(State aState)
+{
+    if (mState != aState)
+    {
+        LogInfo("AutoStartState %s -> %s", StateToString(mState), StateToString(aState));
+        mState = aState;
+    }
+}
+
+void Client::AutoStart::SetCallback(AutoStartCallback aCallback, void *aContext)
+{
+    mCallback = aCallback;
+    mContext  = aContext;
+}
+
+void Client::AutoStart::InvokeCallback(const Ip6::SockAddr *aServerSockAddr) const
+{
+    if (mCallback != nullptr)
+    {
+        mCallback(aServerSockAddr, mContext);
+    }
+}
+
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
+const char *Client::AutoStart::StateToString(State aState)
+{
+    static const char *const kStateStrings[] = {
+        "Disabled",    // (0) kDisabled
+        "Idle",        // (1) kSelectedNone
+        "Unicast-prf", // (2) kSelectedUnicastPreferred
+        "Anycast",     // (3) kSelectedAnycast
+        "Unicast",     // (4) kSelectedUnicast
+    };
+
+    static_assert(0 == kDisabled, "kDisabled value is incorrect");
+    static_assert(1 == kSelectedNone, "kSelectedNone value is incorrect");
+    static_assert(2 == kSelectedUnicastPreferred, "kSelectedUnicastPreferred value is incorrect");
+    static_assert(3 == kSelectedAnycast, "kSelectedAnycast value is incorrect");
+    static_assert(4 == kSelectedUnicast, "kSelectedUnicast value is incorrect");
+
+    return kStateStrings[aState];
+}
+#endif
+
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+
+//---------------------------------------------------------------------
 // Client
 
 const char Client::kDefaultDomainName[] = "default.service.arpa";
@@ -163,30 +249,19 @@
     , mState(kStateStopped)
     , mTxFailureRetryCount(0)
     , mShouldRemoveKeyLease(false)
-#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
-    , mAutoStartModeEnabled(kAutoStartDefaultMode)
-    , mAutoStartDidSelectServer(false)
-    , mAutoStartIsUsingAnycastAddress(false)
-#endif
+    , mAutoHostAddressAddedMeshLocal(false)
 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
     , mServiceKeyRecordEnabled(false)
 #endif
     , mUpdateMessageId(0)
     , mRetryWaitInterval(kMinRetryWaitInterval)
     , mAcceptedLeaseInterval(0)
+    , mTtl(0)
     , mLeaseInterval(kDefaultLease)
     , mKeyLeaseInterval(kDefaultKeyLease)
     , mSocket(aInstance)
     , mCallback(nullptr)
     , mCallbackContext(nullptr)
-#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
-    , mAutoStartCallback(nullptr)
-    , mAutoStartContext(nullptr)
-    , mServerSequenceNumber(0)
-#if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
-    , mTimoutFailureCount(0)
-#endif
-#endif
     , mDomainName(kDefaultDomainName)
     , mTimer(aInstance, Client::HandleTimer)
 {
@@ -218,24 +293,18 @@
     SuccessOrExit(error = mSocket.Open(Client::HandleUdpReceive, this));
     SuccessOrExit(error = mSocket.Connect(aServerSockAddr));
 
-    otLogInfoSrp("[client] %starting, server %s", (aRequester == kRequesterUser) ? "S" : "Auto-s",
-                 aServerSockAddr.ToString().AsCString());
+    LogInfo("%starting, server %s", (aRequester == kRequesterUser) ? "S" : "Auto-s",
+            aServerSockAddr.ToString().AsCString());
 
     Resume();
 
 #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
-    mAutoStartDidSelectServer = (aRequester == kRequesterAuto);
-
-    if (mAutoStartDidSelectServer)
+    if (aRequester == kRequesterAuto)
     {
 #if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE && OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_ADDRESS_AUTO_SET_ENABLE
         Get<Dns::Client>().UpdateDefaultConfigAddress();
 #endif
-
-        if (mAutoStartCallback != nullptr)
-        {
-            mAutoStartCallback(&aServerSockAddr, mAutoStartContext);
-        }
+        mAutoStart.InvokeCallback(&aServerSockAddr);
     }
 #endif
 
@@ -266,6 +335,8 @@
 
     VerifyOrExit(GetState() != kStateStopped);
 
+    mSingleServiceMode.Disable();
+
     // State changes:
     //   kAdding     -> kToRefresh
     //   kRefreshing -> kToRefresh
@@ -288,14 +359,11 @@
 
 #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
 #if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
-    mTimoutFailureCount = 0;
+    mAutoStart.ResetTimoutFailureCount();
 #endif
-
-    mAutoStartDidSelectServer = false;
-
-    if ((aRequester == kRequesterAuto) && (mAutoStartCallback != nullptr))
+    if (aRequester == kRequesterAuto)
     {
-        mAutoStartCallback(nullptr, mAutoStartContext);
+        mAutoStart.InvokeCallback(nullptr);
     }
 #endif
 
@@ -337,6 +405,8 @@
         /* (7) kRemoved    -> */ kRemoved,
     };
 
+    mSingleServiceMode.Disable();
+
     // State changes:
     //   kAdding     -> kToRefresh
     //   kRefreshing -> kToRefresh
@@ -360,6 +430,22 @@
         ProcessAutoStart();
     }
 #endif
+
+    if (mHostInfo.IsAutoAddressEnabled())
+    {
+        Events::Flags eventFlags = (kEventIp6AddressAdded | kEventIp6AddressRemoved);
+
+        if (mAutoHostAddressAddedMeshLocal)
+        {
+            eventFlags |= kEventThreadMeshLocalAddrChanged;
+        }
+
+        if (aEvents.ContainsAny(eventFlags))
+        {
+            IgnoreError(UpdateHostInfoStateOnAddressChange());
+            UpdateState();
+        }
+    }
 }
 
 void Client::HandleRoleChanged(void)
@@ -387,7 +473,7 @@
     VerifyOrExit((mHostInfo.GetState() == kToAdd) || (mHostInfo.GetState() == kRemoved), error = kErrorInvalidState);
 
     mDomainName = (aName != nullptr) ? aName : kDefaultDomainName;
-    otLogInfoSrp("[client] Domain name \"%s\"", mDomainName);
+    LogInfo("Domain name \"%s\"", mDomainName);
 
 exit:
     return error;
@@ -402,7 +488,7 @@
 
     VerifyOrExit((mHostInfo.GetState() == kToAdd) || (mHostInfo.GetState() == kRemoved), error = kErrorInvalidState);
 
-    otLogInfoSrp("[client] Host name \"%s\"", aName);
+    LogInfo("Host name \"%s\"", aName);
     mHostInfo.SetName(aName);
     mHostInfo.SetState(kToAdd);
     UpdateState();
@@ -411,11 +497,37 @@
     return error;
 }
 
+Error Client::EnableAutoHostAddress(void)
+{
+    Error error = kErrorNone;
+
+    VerifyOrExit(!mHostInfo.IsAutoAddressEnabled());
+    SuccessOrExit(error = UpdateHostInfoStateOnAddressChange());
+
+    mHostInfo.EnableAutoAddress();
+    UpdateState();
+
+exit:
+    return error;
+}
+
 Error Client::SetHostAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses)
 {
     Error error = kErrorNone;
 
     VerifyOrExit((aAddresses != nullptr) && (aNumAddresses > 0), error = kErrorInvalidArgs);
+    SuccessOrExit(error = UpdateHostInfoStateOnAddressChange());
+
+    mHostInfo.SetAddresses(aAddresses, aNumAddresses);
+    UpdateState();
+
+exit:
+    return error;
+}
+
+Error Client::UpdateHostInfoStateOnAddressChange(void)
+{
+    Error error = kErrorNone;
 
     VerifyOrExit((mHostInfo.GetState() != kToRemove) && (mHostInfo.GetState() != kRemoving),
                  error = kErrorInvalidState);
@@ -429,9 +541,6 @@
         mHostInfo.SetState(kToRefresh);
     }
 
-    mHostInfo.SetAddresses(aAddresses, aNumAddresses);
-    UpdateState();
-
 exit:
     return error;
 }
@@ -506,7 +615,7 @@
 {
     Error error = kErrorNone;
 
-    otLogInfoSrp("[client] Remove host & services");
+    LogInfo("Remove host & services");
 
     VerifyOrExit(mHostInfo.GetState() != kRemoved, error = kErrorAlready);
 
@@ -542,7 +651,7 @@
 
 void Client::ClearHostAndServices(void)
 {
-    otLogInfoSrp("[client] Clear host & services");
+    LogInfo("Clear host & services");
 
     switch (GetState())
     {
@@ -569,7 +678,7 @@
 {
     VerifyOrExit(aState != mState);
 
-    otLogInfoSrp("[client] State %s -> %s", StateToString(mState), StateToString(aState));
+    LogInfo("State %s -> %s", StateToString(mState), StateToString(aState));
     mState = aState;
 
     switch (mState)
@@ -581,7 +690,7 @@
         break;
 
     case kStateToUpdate:
-        mTimer.Start(kUpdateTxDelay);
+        mTimer.Start(Random::NonCrypto::GetUint32InRange(kUpdateTxMinDelay, kUpdateTxMaxDelay));
         break;
 
     case kStateUpdating:
@@ -605,28 +714,38 @@
 
     for (Service &service : mServices)
     {
+        if (mSingleServiceMode.IsEnabled() && mSingleServiceMode.GetService() != &service)
+        {
+            continue;
+        }
+
         service.SetState(aNewStates[service.GetState()]);
     }
 
 #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE && OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
-    if (mAutoStartModeEnabled && mAutoStartDidSelectServer && (oldHostState != kRegistered) &&
-        (mHostInfo.GetState() == kRegistered))
+    if ((oldHostState != kRegistered) && (mHostInfo.GetState() == kRegistered))
     {
-        if (mAutoStartIsUsingAnycastAddress)
-        {
-            IgnoreError(Get<Settings>().Delete<Settings::SrpClientInfo>());
-        }
-        else
-        {
-            Settings::SrpClientInfo info;
+        Settings::SrpClientInfo info;
 
+        switch (mAutoStart.GetState())
+        {
+        case AutoStart::kDisabled:
+        case AutoStart::kSelectedNone:
+            break;
+
+        case AutoStart::kSelectedUnicastPreferred:
+        case AutoStart::kSelectedUnicast:
             info.SetServerAddress(GetServerAddress().GetAddress());
             info.SetServerPort(GetServerAddress().GetPort());
-
             IgnoreError(Get<Settings>().Save(info));
+            break;
+
+        case AutoStart::kSelectedAnycast:
+            IgnoreError(Get<Settings>().Delete<Settings::SrpClientInfo>());
+            break;
         }
     }
-#endif
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE && OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
 }
 
 void Client::InvokeCallback(Error aError) const
@@ -658,12 +777,24 @@
 
     Error    error   = kErrorNone;
     Message *message = mSocket.NewMessage(0);
+    uint32_t length;
 
     VerifyOrExit(message != nullptr, error = kErrorNoBufs);
     SuccessOrExit(error = PrepareUpdateMessage(*message));
+
+    length = message->GetLength() + sizeof(Ip6::Udp::Header) + sizeof(Ip6::Header);
+
+    if (length >= Ip6::kMaxDatagramLength)
+    {
+        LogInfo("Msg len %u is larger than MTU, enabling single service mode", length);
+        mSingleServiceMode.Enable();
+        IgnoreError(message->SetLength(0));
+        SuccessOrExit(error = PrepareUpdateMessage(*message));
+    }
+
     SuccessOrExit(error = mSocket.SendTo(*message, Ip6::MessageInfo()));
 
-    otLogInfoSrp("[client] Send update");
+    LogInfo("Send update");
 
     // State changes:
     //   kToAdd     -> kAdding
@@ -696,8 +827,9 @@
         // continue to retry using the `mRetryWaitInterval` (which keeps
         // growing on each failure).
 
-        otLogInfoSrp("[client] Failed to send update: %s", ErrorToString(error));
+        LogInfo("Failed to send update: %s", ErrorToString(error));
 
+        mSingleServiceMode.Disable();
         FreeMessage(message);
 
         SetState(kStateToRetry);
@@ -710,7 +842,7 @@
             interval = Random::NonCrypto::AddJitter(kTxFailureRetryInterval, kTxFailureRetryJitter);
             mTimer.Start(interval);
 
-            otLogInfoSrp("[client] Quick retry %d in %u msec", mTxFailureRetryCount, interval);
+            LogInfo("Quick retry %d in %u msec", mTxFailureRetryCount, interval);
 
             // Do not report message preparation errors to user
             // until `kMaxTxFailureRetries` are exhausted.
@@ -767,11 +899,16 @@
 
     // Prepare Update section
 
-    if (mHostInfo.GetState() != kToRemove)
+    if ((mHostInfo.GetState() != kToRemove) && (mHostInfo.GetState() != kRemoving))
     {
         for (Service &service : mServices)
         {
             SuccessOrExit(error = AppendServiceInstructions(service, aMessage, info));
+
+            if (mSingleServiceMode.IsEnabled() && (mSingleServiceMode.GetService() != nullptr))
+            {
+                break;
+            }
         }
     }
 
@@ -852,7 +989,7 @@
     // to NONE and TTL to zero (RFC 2136 - section 2.5.4).
 
     rr.Init(Dns::ResourceRecord::kTypePtr, removing ? Dns::PtrRecord::kClassNone : Dns::PtrRecord::kClassInternet);
-    rr.SetTtl(removing ? 0 : mLeaseInterval);
+    rr.SetTtl(removing ? 0 : GetTtl());
     offset = aMessage.GetLength();
     SuccessOrExit(error = aMessage.Append(rr));
 
@@ -864,7 +1001,7 @@
     UpdateRecordLengthInMessage(rr, offset, aMessage);
     aInfo.mRecordCount++;
 
-    if (aService.HasSubType())
+    if (aService.HasSubType() && !removing)
     {
         const char *subTypeLabel;
         uint16_t    subServiceNameOffset = 0;
@@ -886,7 +1023,7 @@
                 SuccessOrExit(error = Dns::Name::AppendPointerLabel(subServiceNameOffset, aMessage));
             }
 
-            // `rr` is already initialized as PTR (add or remove).
+            // `rr` is already initialized as PTR.
             offset = aMessage.GetLength();
             SuccessOrExit(error = aMessage.Append(rr));
 
@@ -911,7 +1048,7 @@
 
     SuccessOrExit(error = Dns::Name::AppendPointerLabel(instanceNameOffset, aMessage));
     srv.Init();
-    srv.SetTtl(mLeaseInterval);
+    srv.SetTtl(GetTtl());
     srv.SetPriority(aService.GetPriority());
     srv.SetWeight(aService.GetWeight());
     srv.SetPort(aService.GetPort());
@@ -944,14 +1081,18 @@
     }
 #endif
 
+    if (mSingleServiceMode.IsEnabled())
+    {
+        mSingleServiceMode.SetService(aService);
+    }
+
 exit:
     return error;
 }
 
-Error Client::AppendHostDescriptionInstruction(Message &aMessage, Info &aInfo) const
+Error Client::AppendHostDescriptionInstruction(Message &aMessage, Info &aInfo)
 {
-    Error               error = kErrorNone;
-    Dns::ResourceRecord rr;
+    Error error = kErrorNone;
 
     //----------------------------------
     // Host Description Instruction
@@ -964,16 +1105,37 @@
 
     // AAAA RRs
 
-    rr.Init(Dns::ResourceRecord::kTypeAaaa);
-    rr.SetTtl(mLeaseInterval);
-    rr.SetLength(sizeof(Ip6::Address));
-
-    for (uint8_t index = 0; index < mHostInfo.GetNumAddresses(); index++)
+    if (mHostInfo.IsAutoAddressEnabled())
     {
-        SuccessOrExit(error = AppendHostName(aMessage, aInfo));
-        SuccessOrExit(error = aMessage.Append(rr));
-        SuccessOrExit(error = aMessage.Append(mHostInfo.GetAddress(index)));
-        aInfo.mRecordCount++;
+        // Append all addresses on Thread netif excluding link-local and
+        // mesh-local addresses. If no address is appended, we include
+        // the mesh local address.
+
+        mAutoHostAddressAddedMeshLocal = true;
+
+        for (const Ip6::Netif::UnicastAddress &unicastAddress : Get<ThreadNetif>().GetUnicastAddresses())
+        {
+            if (unicastAddress.GetAddress().IsLinkLocal() ||
+                Get<Mle::Mle>().IsMeshLocalAddress(unicastAddress.GetAddress()))
+            {
+                continue;
+            }
+
+            SuccessOrExit(error = AppendAaaaRecord(unicastAddress.GetAddress(), aMessage, aInfo));
+            mAutoHostAddressAddedMeshLocal = false;
+        }
+
+        if (mAutoHostAddressAddedMeshLocal)
+        {
+            SuccessOrExit(error = AppendAaaaRecord(Get<Mle::Mle>().GetMeshLocal64(), aMessage, aInfo));
+        }
+    }
+    else
+    {
+        for (uint8_t index = 0; index < mHostInfo.GetNumAddresses(); index++)
+        {
+            SuccessOrExit(error = AppendAaaaRecord(mHostInfo.GetAddress(index), aMessage, aInfo));
+        }
     }
 
     // KEY RR
@@ -985,6 +1147,24 @@
     return error;
 }
 
+Error Client::AppendAaaaRecord(const Ip6::Address &aAddress, Message &aMessage, Info &aInfo) const
+{
+    Error               error;
+    Dns::ResourceRecord rr;
+
+    rr.Init(Dns::ResourceRecord::kTypeAaaa);
+    rr.SetTtl(GetTtl());
+    rr.SetLength(sizeof(Ip6::Address));
+
+    SuccessOrExit(error = AppendHostName(aMessage, aInfo));
+    SuccessOrExit(error = aMessage.Append(rr));
+    SuccessOrExit(error = aMessage.Append(aAddress));
+    aInfo.mRecordCount++;
+
+exit:
+    return error;
+}
+
 Error Client::AppendKeyRecord(Message &aMessage, Info &aInfo) const
 {
     Error                          error;
@@ -992,7 +1172,7 @@
     Crypto::Ecdsa::P256::PublicKey publicKey;
 
     key.Init();
-    key.SetTtl(mLeaseInterval);
+    key.SetTtl(GetTtl());
     key.SetFlags(Dns::KeyRecord::kAuthConfidPermitted, Dns::KeyRecord::kOwnerNonZone,
                  Dns::KeyRecord::kSignatoryFlagGeneral);
     key.SetProtocol(Dns::KeyRecord::kProtocolDnsSec);
@@ -1071,7 +1251,7 @@
 
     leaseOption.Init();
 
-    if (mHostInfo.GetState() == kToRemove)
+    if ((mHostInfo.GetState() == kToRemove) || (mHostInfo.GetState() == kRemoving))
     {
         leaseOption.SetLeaseInterval(0);
         leaseOption.SetKeyLeaseInterval(mShouldRemoveKeyLease ? 0 : mKeyLeaseInterval);
@@ -1206,17 +1386,17 @@
 
     // Response is for the earlier request message.
 
-    otLogInfoSrp("[client] Received response");
+    LogInfo("Received response");
 
 #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE && OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
-    mTimoutFailureCount = 0;
+    mAutoStart.ResetTimoutFailureCount();
 #endif
 
     error = Dns::Header::ResponseCodeToError(header.GetResponseCode());
 
     if (error != kErrorNone)
     {
-        otLogInfoSrp("[client] Server rejected %s code:%d", ErrorToString(error), header.GetResponseCode());
+        LogInfo("Server rejected %s code:%d", ErrorToString(error), header.GetResponseCode());
 
         if (mHostInfo.GetState() == kAdding)
         {
@@ -1325,6 +1505,7 @@
     //   kRemoving   -> kRemoved
 
     ChangeHostAndServiceStates(kNewStateOnUpdateDone);
+    mSingleServiceMode.Disable();
 
     HandleUpdateDone();
     UpdateState();
@@ -1332,7 +1513,7 @@
 exit:
     if (error != kErrorNone)
     {
-        otLogInfoSrp("[client] Failed to process response %s", ErrorToString(error));
+        LogInfo("Failed to process response %s", ErrorToString(error));
     }
 }
 
@@ -1355,27 +1536,7 @@
 
 void Client::GetRemovedServices(LinkedList<Service> &aRemovedServices)
 {
-    Service *service;
-    Service *prev;
-    Service *next;
-
-    for (prev = nullptr, service = mServices.GetHead(); service != nullptr; service = next)
-    {
-        next = service->GetNext();
-
-        if (service->GetState() == kRemoved)
-        {
-            mServices.PopAfter(prev);
-            aRemovedServices.Push(*service);
-
-            // When the service is removed from the list
-            // we keep the `prev` pointer same as before.
-        }
-        else
-        {
-            prev = service;
-        }
-    }
+    mServices.RemoveAllMatching(kRemoved, aRemovedServices);
 }
 
 Error Client::ReadResourceRecord(const Message &aMessage, uint16_t &aOffset, Dns::ResourceRecord &aRecord)
@@ -1479,7 +1640,7 @@
         // host address, otherwise no need to send SRP update message.
         // The exception is when removing host info where we allow
         // for empty service list.
-        VerifyOrExit(!mServices.IsEmpty() && (mHostInfo.GetNumAddresses() > 0));
+        VerifyOrExit(!mServices.IsEmpty() && (mHostInfo.IsAutoAddressEnabled() || (mHostInfo.GetNumAddresses() > 0)));
 
         // Fall through
 
@@ -1614,8 +1775,9 @@
         break;
 
     case kStateUpdating:
+        mSingleServiceMode.Disable();
         LogRetryWaitInterval();
-        otLogInfoSrp("[client] Timed out, no response");
+        LogInfo("Timed out, no response");
         GrowRetryWaitInterval();
         SetState(kStateToUpdate);
         InvokeCallback(kErrorResponseTimeout);
@@ -1627,12 +1789,9 @@
         // callback. It works correctly due to the guard check at the
         // top of `SelectNextServer()`.
 
-        if (mTimoutFailureCount < NumericLimits<uint8_t>::kMax)
-        {
-            mTimoutFailureCount++;
-        }
+        mAutoStart.IncrementTimoutFailureCount();
 
-        if (mTimoutFailureCount >= kMaxTimeoutFailuresToSwitchServer)
+        if (mAutoStart.GetTimoutFailureCount() >= kMaxTimeoutFailuresToSwitchServer)
         {
             SelectNextServer(kDisallowSwitchOnRegisteredHost);
         }
@@ -1649,11 +1808,11 @@
 
 void Client::EnableAutoStartMode(AutoStartCallback aCallback, void *aContext)
 {
-    mAutoStartCallback = aCallback;
-    mAutoStartContext  = aContext;
+    mAutoStart.SetCallback(aCallback, aContext);
 
-    VerifyOrExit(!mAutoStartModeEnabled);
-    mAutoStartModeEnabled = true;
+    VerifyOrExit(mAutoStart.GetState() == AutoStart::kDisabled);
+
+    mAutoStart.SetState(AutoStart::kSelectedNone);
     ProcessAutoStart();
 
 exit:
@@ -1662,130 +1821,174 @@
 
 void Client::ProcessAutoStart(void)
 {
-    Ip6::SockAddr                             serverSockAddr;
-    bool                                      serverIsAnycast = false;
-    NetworkData::Service::DnsSrpAnycast::Info anycastInfo;
-#if OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
-    Settings::SrpClientInfo savedInfo;
-    bool                    hasSavedServerInfo = false;
-#endif
+    Ip6::SockAddr       serverSockAddr;
+    DnsSrpAnycast::Info anycastInfo;
+    DnsSrpUnicast::Info unicastInfo;
+    bool                shouldRestart = false;
 
-    VerifyOrExit(mAutoStartModeEnabled);
+    // If auto start mode is enabled, we check the Network Data entries
+    // to discover and select the preferred SRP server to register with.
+    // If we currently have a selected server, we ensure that it is
+    // still present in the Network Data and is still the preferred one.
+
+    VerifyOrExit(mAutoStart.GetState() != AutoStart::kDisabled);
+
+    // If SRP client is running, we check to make sure that auto-start
+    // did select the current server, and server was not specified by
+    // user directly.
+
+    if (IsRunning())
+    {
+        VerifyOrExit(mAutoStart.GetState() != AutoStart::kSelectedNone);
+    }
+
+    // There are three types of entries in Network Data:
+    //
+    // 1) Preferred unicast entries with address included in service data.
+    // 2) Anycast entries (each having a seq number).
+    // 3) Unicast entries with address info included in server data.
 
     serverSockAddr.Clear();
 
-    // If the SRP client is not running and auto start mode is
-    // enabled, we check if we can find any SRP server info in the
-    // Thread Network Data. If it is already running and the server
-    // was chosen by the auto-start feature, then we ensure that the
-    // selected server is still present in the Network Data.
-    //
-    // Two types of "DNS/SRP Service" entries can be present in
-    // Network Data, "DNS/SRP Service Anycast Address" model and
-    // "DNS/SRP Service Unicast" model. The Anycast entries are
-    // preferred over the Unicast entries.
+    if (SelectUnicastEntry(DnsSrpUnicast::kFromServiceData, unicastInfo) == kErrorNone)
+    {
+        mAutoStart.SetState(AutoStart::kSelectedUnicastPreferred);
+        serverSockAddr = unicastInfo.mSockAddr;
+    }
+    else if (Get<NetworkData::Service::Manager>().FindPreferredDnsSrpAnycastInfo(anycastInfo) == kErrorNone)
+    {
+        serverSockAddr.SetAddress(anycastInfo.mAnycastAddress);
+        serverSockAddr.SetPort(kAnycastServerPort);
 
-    VerifyOrExit(!IsRunning() || mAutoStartDidSelectServer);
+        // We check if we are selecting an anycast entry for first
+        // time, or if the seq number has changed. Even if the
+        // anycast address remains the same as before, on a seq
+        // number change, the client still needs to restart to
+        // re-register its info.
 
-    // Now `IsRunning()` implies `mAutoStartDidSelectServer`.
+        if ((mAutoStart.GetState() != AutoStart::kSelectedAnycast) ||
+            (mAutoStart.GetAnycastSeqNum() != anycastInfo.mSequenceNumber))
+        {
+            shouldRestart = true;
+            mAutoStart.SetAnycastSeqNum(anycastInfo.mSequenceNumber);
+        }
 
+        mAutoStart.SetState(AutoStart::kSelectedAnycast);
+    }
+    else if (SelectUnicastEntry(DnsSrpUnicast::kFromServerData, unicastInfo) == kErrorNone)
+    {
+        mAutoStart.SetState(AutoStart::kSelectedUnicast);
+        serverSockAddr = unicastInfo.mSockAddr;
+    }
+
+    if (IsRunning())
+    {
+        VerifyOrExit((GetServerAddress() != serverSockAddr) || shouldRestart);
+        Stop(kRequesterAuto, kResetRetryInterval);
+    }
+
+    if (!serverSockAddr.GetAddress().IsUnspecified())
+    {
+        IgnoreError(Start(serverSockAddr, kRequesterAuto));
+    }
+    else
+    {
+        mAutoStart.SetState(AutoStart::kSelectedNone);
+    }
+
+exit:
+    return;
+}
+
+Error Client::SelectUnicastEntry(DnsSrpUnicast::Origin aOrigin, DnsSrpUnicast::Info &aInfo) const
+{
+    Error                                   error = kErrorNotFound;
+    DnsSrpUnicast::Info                     unicastInfo;
+    NetworkData::Service::Manager::Iterator iterator;
 #if OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
+    Settings::SrpClientInfo savedInfo;
+    bool                    hasSavedServerInfo = false;
+
     if (!IsRunning())
     {
         hasSavedServerInfo = (Get<Settings>().Read(savedInfo) == kErrorNone);
     }
 #endif
 
-    if (Get<NetworkData::Service::Manager>().FindPreferredDnsSrpAnycastInfo(anycastInfo) == kErrorNone)
+    while (Get<NetworkData::Service::Manager>().GetNextDnsSrpUnicastInfo(iterator, unicastInfo) == kErrorNone)
     {
-        if (IsRunning() && mAutoStartIsUsingAnycastAddress && (mServerSequenceNumber == anycastInfo.mSequenceNumber) &&
-            (GetServerAddress().GetAddress() == anycastInfo.mAnycastAddress))
+        if (unicastInfo.mOrigin != aOrigin)
         {
-            // Client is already using the same anycast address.
+            continue;
+        }
+
+        if (mAutoStart.HasSelectedServer() && (GetServerAddress() == unicastInfo.mSockAddr))
+        {
+            aInfo = unicastInfo;
+            error = kErrorNone;
             ExitNow();
         }
 
-        otLogInfoSrp("[client] Found anycast server %d", anycastInfo.mSequenceNumber);
-
-        serverSockAddr.SetAddress(anycastInfo.mAnycastAddress);
-        serverSockAddr.SetPort(kAnycastServerPort);
-        mServerSequenceNumber = anycastInfo.mSequenceNumber;
-        serverIsAnycast       = true;
-    }
-    else
-    {
-        uint16_t                                  numServers = 0;
-        NetworkData::Service::DnsSrpUnicast::Info unicastInfo;
-        NetworkData::Service::Manager::Iterator   iterator;
-
-        while (Get<NetworkData::Service::Manager>().GetNextDnsSrpUnicastInfo(iterator, unicastInfo) == kErrorNone)
-        {
-            if (IsRunning() && !mAutoStartIsUsingAnycastAddress && (GetServerAddress() == unicastInfo.mSockAddr))
-            {
-                ExitNow();
-            }
-
 #if OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
-            if (hasSavedServerInfo && (unicastInfo.mSockAddr.GetAddress() == savedInfo.GetServerAddress()) &&
-                (unicastInfo.mSockAddr.GetPort() == savedInfo.GetServerPort()))
-            {
-                // Stop the search if we see a match for the previously
-                // saved server info in the network data entries.
+        if (hasSavedServerInfo && (unicastInfo.mSockAddr.GetAddress() == savedInfo.GetServerAddress()) &&
+            (unicastInfo.mSockAddr.GetPort() == savedInfo.GetServerPort()))
+        {
+            // Stop the search if we see a match for the previously
+            // saved server info in the network data entries.
 
-                serverSockAddr  = unicastInfo.mSockAddr;
-                serverIsAnycast = false;
-                break;
-            }
+            aInfo = unicastInfo;
+            error = kErrorNone;
+            ExitNow();
+        }
 #endif
 
-            numServers++;
+        // Prefer the numerically lowest server address
 
-            // Choose a server randomly (with uniform distribution) from
-            // the list of servers. As we iterate through server entries,
-            // with probability `1/numServers`, we choose to switch the
-            // current selected server with the new entry. This approach
-            // results in a uniform/same probability of selection among
-            // all server entries.
-
-            if ((numServers == 1) || (Random::NonCrypto::GetUint16InRange(0, numServers) == 0))
-            {
-                serverSockAddr  = unicastInfo.mSockAddr;
-                serverIsAnycast = false;
-            }
+        if ((error == kErrorNotFound) || (unicastInfo.mSockAddr.GetAddress() < aInfo.mSockAddr.GetAddress()))
+        {
+            aInfo = unicastInfo;
+            error = kErrorNone;
         }
     }
 
-    if (IsRunning())
-    {
-        Stop(kRequesterAuto, kResetRetryInterval);
-    }
-
-    VerifyOrExit(!serverSockAddr.GetAddress().IsUnspecified());
-
-    mAutoStartIsUsingAnycastAddress = serverIsAnycast;
-    IgnoreError(Start(serverSockAddr, kRequesterAuto));
-
 exit:
-    return;
+    return error;
 }
 
 #if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
 void Client::SelectNextServer(bool aDisallowSwitchOnRegisteredHost)
 {
-    // This method tries to find the next server info entry in the
+    // This method tries to find the next unicast server info entry in the
     // Network Data after the current one selected. If found, it
     // restarts the client with the new server (keeping the retry wait
     // interval as before).
 
-    Ip6::SockAddr serverSockAddr;
-    bool          selectNext = false;
+    Ip6::SockAddr         serverSockAddr;
+    bool                  selectNext = false;
+    DnsSrpUnicast::Origin origin     = DnsSrpUnicast::kFromServiceData;
 
     serverSockAddr.Clear();
 
     // Ensure that client is running, auto-start is enabled and
-    // auto-start selected the server.
+    // auto-start selected the server and it is a unicast entry.
 
-    VerifyOrExit(IsRunning() && mAutoStartModeEnabled && mAutoStartDidSelectServer);
+    VerifyOrExit(IsRunning());
+
+    switch (mAutoStart.GetState())
+    {
+    case AutoStart::kSelectedUnicastPreferred:
+        origin = DnsSrpUnicast::kFromServiceData;
+        break;
+
+    case AutoStart::kSelectedUnicast:
+        origin = DnsSrpUnicast::kFromServerData;
+        break;
+
+    case AutoStart::kSelectedAnycast:
+    case AutoStart::kDisabled:
+    case AutoStart::kSelectedNone:
+        ExitNow();
+    }
 
     if (aDisallowSwitchOnRegisteredHost)
     {
@@ -1800,36 +2003,19 @@
 
     do
     {
-        NetworkData::Service::DnsSrpAnycast::Info anycastInfo;
-        NetworkData::Service::DnsSrpUnicast::Info unicastInfo;
-        NetworkData::Service::Manager::Iterator   iterator;
-
-        while (Get<NetworkData::Service::Manager>().GetNextDnsSrpAnycastInfo(iterator, anycastInfo) == kErrorNone)
-        {
-            if (selectNext)
-            {
-                serverSockAddr.SetAddress(anycastInfo.mAnycastAddress);
-                serverSockAddr.SetPort(kAnycastServerPort);
-                mServerSequenceNumber           = anycastInfo.mSequenceNumber;
-                mAutoStartIsUsingAnycastAddress = true;
-                ExitNow();
-            }
-
-            if (mAutoStartIsUsingAnycastAddress && (GetServerAddress().GetAddress() == anycastInfo.mAnycastAddress) &&
-                (GetServerAddress().GetPort() == kAnycastServerPort))
-            {
-                selectNext = true;
-            }
-        }
-
-        iterator.Reset();
+        DnsSrpUnicast::Info                     unicastInfo;
+        NetworkData::Service::Manager::Iterator iterator;
 
         while (Get<NetworkData::Service::Manager>().GetNextDnsSrpUnicastInfo(iterator, unicastInfo) == kErrorNone)
         {
+            if (unicastInfo.mOrigin != origin)
+            {
+                continue;
+            }
+
             if (selectNext)
             {
-                serverSockAddr                  = unicastInfo.mSockAddr;
-                mAutoStartIsUsingAnycastAddress = false;
+                serverSockAddr = unicastInfo.mSockAddr;
                 ExitNow();
             }
 
@@ -1886,7 +2072,7 @@
     return kItemStateStrings[aState];
 }
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_SRP == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
 const char *Client::StateToString(State aState)
 {
@@ -1915,11 +2101,11 @@
 
     uint32_t interval = GetRetryWaitInterval();
 
-    otLogInfoSrp("[client] Retry interval %u %s", (interval < kLogInMsecLimit) ? interval : Time::MsecToSec(interval),
-                 (interval < kLogInMsecLimit) ? "ms" : "sec");
+    LogInfo("Retry interval %u %s", (interval < kLogInMsecLimit) ? interval : Time::MsecToSec(interval),
+            (interval < kLogInMsecLimit) ? "ms" : "sec");
 }
 
-#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_SRP == 1)
+#endif // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
 } // namespace Srp
 } // namespace ot
diff --git a/src/core/net/srp_client.hpp b/src/core/net/srp_client.hpp
index df52718..46bdc33 100644
--- a/src/core/net/srp_client.hpp
+++ b/src/core/net/srp_client.hpp
@@ -35,17 +35,21 @@
 
 #include <openthread/srp_client.h>
 
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/linked_list.hpp"
 #include "common/locator.hpp"
+#include "common/log.hpp"
 #include "common/message.hpp"
 #include "common/non_copyable.hpp"
 #include "common/notifier.hpp"
+#include "common/numeric_limits.hpp"
 #include "common/timer.hpp"
 #include "crypto/ecdsa.hpp"
 #include "net/dns_types.hpp"
 #include "net/ip6.hpp"
 #include "net/udp6.hpp"
+#include "thread/network_data_service.hpp"
 
 /**
  * @file
@@ -67,6 +71,9 @@
 {
     friend class ot::Notifier;
 
+    using DnsSrpUnicast = NetworkData::Service::DnsSrpUnicast;
+    using DnsSrpAnycast = NetworkData::Service::DnsSrpAnycast;
+
 public:
     /**
      * This enumeration types represents an SRP client item (service or host info) state.
@@ -96,7 +103,7 @@
      * This type represents an SRP client host info.
      *
      */
-    class HostInfo : public otSrpClientHostInfo, public Clearable<HostInfo>
+    class HostInfo : public otSrpClientHostInfo, private Clearable<HostInfo>
     {
         friend class Client;
 
@@ -116,12 +123,21 @@
         /**
          * This method gets the host name (label) string.
          *
-         * @returns The host name (label) string, or nullptr if not yet set.
+         * @returns The host name (label) string, or `nullptr` if not yet set.
          *
          */
         const char *GetName(void) const { return mName; }
 
         /**
+         * This method indicates whether or not the host auto address mode is enabled.
+         *
+         * @retval TRUE  If the auto address mode is enabled.
+         * @retval FALSE If the auto address mode is disabled.
+         *
+         */
+        bool IsAutoAddressEnabled(void) const { return mAutoAddress; }
+
+        /**
          * This method gets the number of host IPv6 addresses.
          *
          * @returns The number of host IPv6 addresses.
@@ -137,10 +153,7 @@
          * @returns  The host IPv6 address at index @p aIndex.
          *
          */
-        const Ip6::Address &GetAddress(uint8_t aIndex) const
-        {
-            return static_cast<const Ip6::Address &>(mAddresses[aIndex]);
-        }
+        const Ip6::Address &GetAddress(uint8_t aIndex) const { return AsCoreType(&mAddresses[aIndex]); }
 
         /**
          * This method gets the state of `HostInfo`.
@@ -154,6 +167,7 @@
         void SetName(const char *aName) { mName = aName; }
         void SetState(ItemState aState);
         void SetAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses);
+        void EnableAutoAddress(void);
     };
 
     /**
@@ -243,7 +257,7 @@
          * @returns A pointer to an array of service TXT entries.
          *
          */
-        const Dns::TxtEntry *GetTxtEntries(void) const { return static_cast<const Dns::TxtEntry *>(mTxtEntries); }
+        const Dns::TxtEntry *GetTxtEntries(void) const { return AsCoreTypePtr(mTxtEntries); }
 
         /**
          * This method gets the number of entries in the service TXT entry array.
@@ -266,6 +280,7 @@
         TimeMilli GetLeaseRenewTime(void) const { return TimeMilli(mData); }
         void      SetLeaseRenewTime(TimeMilli aTime) { mData = aTime.GetValue(); }
         bool      Matches(const Service &aOther) const;
+        bool      Matches(ItemState aState) const { return GetState() == aState; }
     };
 
     /**
@@ -355,7 +370,7 @@
      * Note that a call to `Stop()` will also disable the auto-start mode.
      *
      */
-    void DisableAutoStartMode(void) { mAutoStartModeEnabled = false; }
+    void DisableAutoStartMode(void) { mAutoStart.SetState(AutoStart::kDisabled); }
 
     /**
      * This method indicates the current state of auto-start mode (enabled or disabled).
@@ -363,7 +378,7 @@
      * @returns TRUE if the auto-start mode is enabled, FALSE otherwise.
      *
      */
-    bool IsAutoStartModeEnabled(void) const { return mAutoStartModeEnabled; }
+    bool IsAutoStartModeEnabled(void) const { return mAutoStart.GetState() != AutoStart::kDisabled; }
 
     /**
      * This method indicates whether or not the current SRP server's address is selected by auto-start.
@@ -371,7 +386,7 @@
      * @returns TRUE if the SRP server's address is selected by auto-start, FALSE otherwise.
      *
      */
-    bool IsServerSelectedByAutoStart(void) const { return mAutoStartDidSelectServer; }
+    bool IsServerSelectedByAutoStart(void) const { return mAutoStart.HasSelectedServer(); }
 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
 
     /**
@@ -399,13 +414,38 @@
      * The SRP client allows a single callback to be registered. So consecutive calls to this method will overwrite any
      * previously set callback functions.
      *
-     * @param[in] aCallback        The callback to notify of events and changes. Can be nullptr if not needed.
+     * @param[in] aCallback        The callback to notify of events and changes. Can be `nullptr` if not needed.
      * @param[in] aContext         An arbitrary context used with @p aCallback.
      *
      */
     void SetCallback(Callback aCallback, void *aContext);
 
     /**
+     * This method gets the TTL used in SRP update requests.
+     *
+     * Note that this is the TTL requested by the SRP client. The server may choose to accept a different TTL.
+     *
+     * By default, the TTL will equal the lease interval. Passing 0 or a value larger than the lease interval via
+     * `otSrpClientSetTtl()` will also cause the TTL to equal the lease interval.
+     *
+     * @returns The TTL (in seconds).
+     *
+     */
+    uint32_t GetTtl(void) const { return (0 < mTtl && mTtl < mLeaseInterval) ? mTtl : mLeaseInterval; }
+
+    /**
+     * This method sets the TTL used in SRP update requests.
+     *
+     * Changing the TTL does not impact the TTL of already registered services/host-info.
+     * It only changes any future SRP update messages (i.e adding new services and/or refreshes of existing services).
+     *
+     * @param[in] aTtl  The TTL (in seconds). If value is zero or greater than lease interval, the TTL is set to the
+     *                  lease interval.
+     *
+     */
+    void SetTtl(uint32_t aTtl) { mTtl = aTtl; }
+
+    /**
      * This method gets the lease interval used in SRP update requests.
      *
      * Note that this is lease duration that would be requested by the SRP client. Server may choose to accept a
@@ -422,7 +462,7 @@
      * Changing the lease interval does not impact the accepted lease interval of already registered services/host-info.
      * It only changes any future SRP update messages (i.e adding new services and/or refreshes of existing services).
      *
-     * @param[in] The lease interval (in seconds). If zero, the default value `kDefaultLease` would be used.
+     * @param[in] aInterval  The lease interval (in seconds). If zero, the default value `kDefaultLease` would be used.
      *
      */
     void SetLeaseInterval(uint32_t aInterval) { mLeaseInterval = GetBoundedLeaseInterval(aInterval, kDefaultLease); }
@@ -441,7 +481,8 @@
      * Changing the lease interval does not impact the accepted lease interval of already registered services/host-info.
      * It only changes any future SRP update messages (i.e adding new services and/or refreshes of existing services).
      *
-     * @param[in] The key lease interval (in seconds). If zero, the default value `kDefaultKeyLease` would be used.
+     * @param[in] aInterval The key lease interval (in seconds). If zero, the default value `kDefaultKeyLease` would be
+     *                      used.
      *
      */
     void SetKeyLeaseInterval(uint32_t aInterval)
@@ -458,16 +499,16 @@
     const HostInfo &GetHostInfo(void) const { return mHostInfo; }
 
     /**
-     * This function sets the host name label.
+     * This method sets the host name label.
      *
-     * After a successful call to this function, `Callback` will be called to report the status of host info
+     * After a successful call to this method, `Callback` will be called to report the status of host info
      *  registration with SRP server.
      *
      * The host name can be set before client is started or after start but before host info is registered with server
      * (host info should be in either `kToAdd` or `kRemoved`).
      *
      * @param[in] aName       A pointer to host name label string (MUST NOT be NULL). Pointer the string buffer MUST
-     *                        persist and remain valid and constant after return from this function.
+     *                        persist and remain valid and constant after return from this method.
      *
      * @retval kErrorNone           The host name label was set successfully.
      * @retval kErrorInvalidArgs    The @p aName is NULL.
@@ -477,6 +518,27 @@
     Error SetHostName(const char *aName);
 
     /**
+     * This method enables auto host address mode.
+     *
+     * When enabled host IPv6 addresses are automatically set by SRP client using all the unicast addresses on Thread
+     * netif excluding the link-local and mesh-local addresses. If there is no valid address, then Mesh Local EID
+     * address is added. The SRP client will automatically re-register when/if addresses on Thread netif are updated
+     * (new addresses are added or existing addresses are removed).
+     *
+     * The auto host address mode can be enabled before start or during operation of SRP client except when the host
+     * info is being removed (client is busy handling a remove request from an call to `RemoveHostAndServices()` and
+     * host info still being in  either `kStateToRemove` or `kStateRemoving` states).
+     *
+     * After auto host address mode is enabled, it can be disabled by a call to `SetHostAddresses()` which then
+     * explicitly sets the host addresses.
+     *
+     * @retval kErrorNone          Successfully enabled auto host address mode.
+     * @retval kErrorInvalidState  Host is being removed and therefore cannot enable auto host address mode.
+     *
+     */
+    Error EnableAutoHostAddress(void);
+
+    /**
      * This method sets/updates the list of host IPv6 address.
      *
      * Host IPv6 addresses can be set/changed before start or even during operation of SRP client (e.g. to add/remove
@@ -487,6 +549,9 @@
      * After a successful call to this method, `Callback` will be called to report the status of the address
      * registration with SRP server.
      *
+     * Calling this method disables auto host address mode if it was previously enabled from a successful call to
+     * `EnableAutoHostAddress()`.
+     *
      * @param[in] aAddresses          A pointer to the an array containing the host IPv6 addresses.
      * @param[in] aNumAddresses       The number of addresses in the @p aAddresses array.
      *
@@ -576,9 +641,9 @@
      * any previously registered services with the server. In this case, caller can `SetHostName()` and then request
      * `RemoveHostAndServices()` with `aSendUnregToServer` as `true`.
      *
-     * @param[in] aRemoveKeyLease     A boolean indicating whether or not the host key lease should also be removed.
-     * @param[in] aSendUnregToServer   A boolean indicating whether to send update to server when host info is not
-     *                                registered.
+     * @param[in] aShouldRemoveKeyLease  A boolean indicating whether or not the host key lease should also be removed.
+     * @param[in] aSendUnregToServer     A boolean indicating whether to send update to server when host info is not
+     *                                   registered.
      *
      * @retval kErrorNone      The removal of host and services started successfully. The `Callback` will be called
      *                         to report the status.
@@ -668,7 +733,7 @@
         OPENTHREAD_CONFIG_SRP_CLIENT_MAX_TIMEOUT_FAILURES_TO_SWITCH_SERVER;
 #endif
 
-    static constexpr uint16_t kUdpPayloadSize = Ip6::Ip6::kMaxDatagramLength - sizeof(Ip6::Udp::Header);
+    static constexpr uint16_t kUdpPayloadSize = Ip6::kMaxDatagramLength - sizeof(Ip6::Udp::Header);
 
     // -------------------------------
     // Lease related constants
@@ -712,7 +777,8 @@
     // delay as specified by `kUpdateTxDelay` before sending an SRP
     // update to server. This allows the user to provide more change
     // that are then all sent in same update message.
-    static constexpr uint32_t kUpdateTxDelay = OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_DELAY; // in msec.
+    static constexpr uint32_t kUpdateTxMinDelay = OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY; // in msec.
+    static constexpr uint32_t kUpdateTxMaxDelay = OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MAX_DELAY; // in msec.
 
     // -------------------------------
     // Retry related constants
@@ -789,6 +855,74 @@
         kKeepRetryInterval,
     };
 
+    class SingleServiceMode
+    {
+    public:
+        SingleServiceMode(void)
+            : mEnabled(false)
+            , mService(nullptr)
+        {
+        }
+
+        void     Enable(void) { mEnabled = true, mService = nullptr; }
+        void     Disable(void) { mEnabled = false; }
+        bool     IsEnabled(void) const { return mEnabled; }
+        Service *GetService(void) { return mService; }
+        void     SetService(Service &aService) { mService = &aService; }
+
+    private:
+        bool     mEnabled;
+        Service *mService;
+    };
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+    class AutoStart : Clearable<AutoStart>
+    {
+    public:
+        enum State : uint8_t{
+            kDisabled,                 // AutoStart is disabled.
+            kSelectedNone,             // AutoStart is enabled but not yet selected any servers.
+            kSelectedUnicastPreferred, // AutoStart selected a preferred unicast entry (address in service data).
+            kSelectedAnycast,          // AutoStart selected an anycast entry with `mAnycastSeqNum`.
+            kSelectedUnicast,          // AutoStart selected a unicast entry (address in server data).
+        };
+
+        AutoStart(void);
+        bool    HasSelectedServer(void) const;
+        State   GetState(void) const { return mState; }
+        void    SetState(State aState);
+        uint8_t GetAnycastSeqNum(void) const { return mAnycastSeqNum; }
+        void    SetAnycastSeqNum(uint8_t aAnycastSeqNum) { mAnycastSeqNum = aAnycastSeqNum; }
+        void    SetCallback(AutoStartCallback aCallback, void *aContext);
+        void    InvokeCallback(const Ip6::SockAddr *aServerSockAddr) const;
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
+        uint8_t GetTimoutFailureCount(void) const { return mTimoutFailureCount; }
+        void    ResetTimoutFailureCount(void) { mTimoutFailureCount = 0; }
+        void    IncrementTimoutFailureCount(void)
+        {
+            if (mTimoutFailureCount < NumericLimits<uint8_t>::kMax)
+            {
+                mTimoutFailureCount++;
+            }
+        }
+#endif
+
+    private:
+        static constexpr bool kDefaultMode = OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE;
+
+        static const char *StateToString(State aState);
+
+        AutoStartCallback mCallback;
+        void *            mContext;
+        State             mState;
+        uint8_t           mAnycastSeqNum;
+#if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
+        uint8_t mTimoutFailureCount; // Number of no-response timeout failures with the currently selected server.
+#endif
+    };
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+
     struct Info : public Clearable<Info>
     {
         static constexpr uint16_t kUnknownOffset = 0; // Unknown offset value (used when offset is not yet set).
@@ -805,6 +939,7 @@
     void         Pause(void);
     void         HandleNotifierEvents(Events aEvents);
     void         HandleRoleChanged(void);
+    Error        UpdateHostInfoStateOnAddressChange(void);
     void         UpdateServiceStateToRemove(Service &aService);
     State        GetState(void) const { return mState; }
     void         SetState(State aState);
@@ -816,10 +951,11 @@
     Error        PrepareUpdateMessage(Message &aMessage);
     Error        ReadOrGenerateKey(Crypto::Ecdsa::P256::KeyPair &aKeyPair);
     Error        AppendServiceInstructions(Service &aService, Message &aMessage, Info &aInfo);
-    Error        AppendHostDescriptionInstruction(Message &aMessage, Info &aInfo) const;
+    Error        AppendHostDescriptionInstruction(Message &aMessage, Info &aInfo);
     Error        AppendKeyRecord(Message &aMessage, Info &aInfo) const;
     Error        AppendDeleteAllRrsets(Message &aMessage) const;
     Error        AppendHostName(Message &aMessage, Info &aInfo, bool aDoNotCompress = false) const;
+    Error        AppendAaaaRecord(const Ip6::Address &aAddress, Message &aMessage, Info &aInfo) const;
     Error        AppendUpdateLeaseOptRecord(Message &aMessage) const;
     Error        AppendSignature(Message &aMessage, Info &aInfo);
     void         UpdateRecordLengthInMessage(Dns::ResourceRecord &aRecord, uint16_t aOffset, Message &aMessage) const;
@@ -838,13 +974,14 @@
     static void  HandleTimer(Timer &aTimer);
     void         HandleTimer(void);
 #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
-    void ProcessAutoStart(void);
+    void  ProcessAutoStart(void);
+    Error SelectUnicastEntry(DnsSrpUnicast::Origin aOrigin, DnsSrpUnicast::Info &aInfo) const;
 #if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
     void SelectNextServer(bool aDisallowSwitchOnRegisteredHost);
 #endif
 #endif
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_SRP == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
     static const char *StateToString(State aState);
     void               LogRetryWaitInterval(void) const;
 #else
@@ -858,11 +995,7 @@
     State   mState;
     uint8_t mTxFailureRetryCount : 4;
     bool    mShouldRemoveKeyLease : 1;
-#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
-    bool mAutoStartModeEnabled : 1;
-    bool mAutoStartDidSelectServer : 1;
-    bool mAutoStartIsUsingAnycastAddress : 1;
-#endif
+    bool    mAutoHostAddressAddedMeshLocal : 1;
 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
     bool mServiceKeyRecordEnabled : 1;
 #endif
@@ -872,30 +1005,30 @@
 
     TimeMilli mLeaseRenewTime;
     uint32_t  mAcceptedLeaseInterval;
+    uint32_t  mTtl;
     uint32_t  mLeaseInterval;
     uint32_t  mKeyLeaseInterval;
 
     Ip6::Udp::Socket mSocket;
 
-    Callback mCallback;
-    void *   mCallbackContext;
-
-#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
-    AutoStartCallback mAutoStartCallback;
-    void *            mAutoStartContext;
-    uint8_t           mServerSequenceNumber;
-#if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
-    uint8_t mTimoutFailureCount;
-#endif
-#endif
-
+    Callback            mCallback;
+    void *              mCallbackContext;
     const char *        mDomainName;
     HostInfo            mHostInfo;
     LinkedList<Service> mServices;
+    SingleServiceMode   mSingleServiceMode;
     TimerMilli          mTimer;
+#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+    AutoStart mAutoStart;
+#endif
 };
 
 } // namespace Srp
+
+DefineCoreType(otSrpClientHostInfo, Srp::Client::HostInfo);
+DefineCoreType(otSrpClientService, Srp::Client::Service);
+DefineMapEnum(otSrpClientItemState, Srp::Client::ItemState);
+
 } // namespace ot
 
 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
diff --git a/src/core/net/srp_server.cpp b/src/core/net/srp_server.cpp
index 80b9adb..cdcee31 100644
--- a/src/core/net/srp_server.cpp
+++ b/src/core/net/srp_server.cpp
@@ -39,7 +39,7 @@
 #include "common/const_cast.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/new.hpp"
 #include "common/random.hpp"
 #include "net/dns_types.hpp"
@@ -48,6 +48,8 @@
 namespace ot {
 namespace Srp {
 
+RegisterLogModule("SrpServer");
+
 static const char kDefaultDomain[]       = "default.service.arpa.";
 static const char kServiceSubTypeLabel[] = "._sub.";
 
@@ -109,7 +111,7 @@
 
     VerifyOrExit(mState == kStateDisabled, error = kErrorInvalidState);
     VerifyOrExit(mAddressMode != aMode);
-    otLogInfoSrp("[server] Address Mode: %s -> %s", AddressModeToString(mAddressMode), AddressModeToString(aMode));
+    LogInfo("Address Mode: %s -> %s", AddressModeToString(mAddressMode), AddressModeToString(aMode));
     mAddressMode = aMode;
 
 exit:
@@ -123,7 +125,7 @@
     VerifyOrExit(mState == kStateDisabled, error = kErrorInvalidState);
     mAnycastSequenceNumber = aSequenceNumber;
 
-    otLogInfoSrp("[server] Set Anycast Address Mode Seq Number to %d", aSequenceNumber);
+    LogInfo("Set Anycast Address Mode Seq Number to %d", aSequenceNumber);
 
 exit:
     return error;
@@ -166,6 +168,30 @@
     return;
 }
 
+Server::TtlConfig::TtlConfig(void)
+{
+    mMinTtl = kDefaultMinTtl;
+    mMaxTtl = kDefaultMaxTtl;
+}
+
+Error Server::SetTtlConfig(const TtlConfig &aTtlConfig)
+{
+    Error error = kErrorNone;
+
+    VerifyOrExit(aTtlConfig.IsValid(), error = kErrorInvalidArgs);
+    mTtlConfig = aTtlConfig;
+
+exit:
+    return error;
+}
+
+uint32_t Server::TtlConfig::GrantTtl(uint32_t aLease, uint32_t aTtl) const
+{
+    OT_ASSERT(mMinTtl <= mMaxTtl);
+
+    return OT_MAX(mMinTtl, OT_MIN(OT_MIN(mMaxTtl, aLease), aTtl));
+}
+
 Server::LeaseConfig::LeaseConfig(void)
 {
     mMinLease    = kDefaultMinLease;
@@ -259,11 +285,12 @@
 // The caller MUST make sure that there is no existing host with the same hostname.
 void Server::AddHost(Host &aHost)
 {
+    LogInfo("Add new host %s", aHost.GetFullName());
+
     OT_ASSERT(mHosts.FindMatching(aHost.GetFullName()) == nullptr);
     IgnoreError(mHosts.Add(aHost));
 }
-
-void Server::RemoveHost(Host *aHost, bool aRetainName, bool aNotifyServiceHandler)
+void Server::RemoveHost(Host *aHost, RetainName aRetainName, NotifyMode aNotifyServiceHandler)
 {
     VerifyOrExit(aHost != nullptr);
 
@@ -272,18 +299,21 @@
 
     if (aRetainName)
     {
-        otLogInfoSrp("[server] remove host '%s' (but retain its name)", aHost->GetFullName());
+        LogInfo("Remove host %s (but retain its name)", aHost->GetFullName());
     }
     else
     {
         aHost->mKeyLease = 0;
         IgnoreError(mHosts.Remove(*aHost));
-        otLogInfoSrp("[server] fully remove host '%s'", aHost->GetFullName());
+        LogInfo("Fully remove host %s", aHost->GetFullName());
     }
 
     if (aNotifyServiceHandler && mServiceUpdateHandler != nullptr)
     {
-        mServiceUpdateHandler(AllocateId(), aHost, kDefaultEventsHandlerTimeout, mServiceUpdateHandlerContext);
+        uint32_t updateId = AllocateId();
+
+        LogInfo("SRP update handler is notified (updatedId = %u)", updateId);
+        mServiceUpdateHandler(updateId, aHost, kDefaultEventsHandlerTimeout, mServiceUpdateHandlerContext);
         // We don't wait for the reply from the service update handler,
         // but always remove the host (and its services) regardless of
         // host/service update result. Because removing a host should fail
@@ -305,22 +335,25 @@
     bool        hasConflicts = false;
     const Host *existingHost = mHosts.FindMatching(aHost.GetFullName());
 
-    if (existingHost != nullptr && *aHost.GetKey() != *existingHost->GetKey())
+    if (existingHost != nullptr && aHost.GetKeyRecord()->GetKey() != existingHost->GetKeyRecord()->GetKey())
     {
+        LogWarn("Name conflict: host name %s has already been allocated", aHost.GetFullName());
         ExitNow(hasConflicts = true);
     }
 
-    for (const Service::Description &desc : aHost.mServiceDescriptions)
+    for (const Service &service : aHost.mServices)
     {
-        // Check on all hosts for a matching service description with
-        // the same instance name and if found, verify that it has the
-        // same key.
+        // Check on all hosts for a matching service with the same
+        // instance name and if found, verify that it has the same
+        // key.
 
         for (const Host &host : mHosts)
         {
-            if (host.FindServiceDescription(desc.GetInstanceName()) != nullptr)
+            if (host.HasServiceInstance(service.GetInstanceName()) &&
+                aHost.GetKeyRecord()->GetKey() != host.GetKeyRecord()->GetKey())
             {
-                VerifyOrExit(*aHost.GetKey() == *host.GetKey(), hasConflicts = true);
+                LogWarn("Name conflict: service name %s has already been allocated", service.GetInstanceName());
+                ExitNow(hasConflicts = true);
             }
         }
     }
@@ -339,14 +372,16 @@
     }
     else
     {
-        otLogInfoSrp("[server] delayed SRP host update result, the SRP update has been committed (updateId = %u)", aId);
+        LogInfo("Delayed SRP host update result, the SRP update has been committed (updateId = %u)", aId);
     }
 }
 
 void Server::HandleServiceUpdateResult(UpdateMetadata *aUpdate, Error aError)
 {
+    LogInfo("Handler result of SRP update (id = %u) is received: %s", aUpdate->GetId(), ErrorToString(aError));
+
     IgnoreError(mOutstandingUpdates.Remove(*aUpdate));
-    CommitSrpUpdate(aError, aUpdate->GetDnsHeader(), aUpdate->GetHost(), aUpdate->GetMessageInfo());
+    CommitSrpUpdate(aError, *aUpdate);
     aUpdate->Free();
 
     if (mOutstandingUpdates.IsEmpty())
@@ -355,36 +390,55 @@
     }
     else
     {
-        mOutstandingUpdatesTimer.StartAt(mOutstandingUpdates.GetTail()->GetExpireTime(), 0);
+        mOutstandingUpdatesTimer.FireAt(mOutstandingUpdates.GetTail()->GetExpireTime());
     }
 }
 
+void Server::CommitSrpUpdate(Error aError, Host &aHost, const MessageMetadata &aMessageMetadata)
+{
+    CommitSrpUpdate(aError, aHost, aMessageMetadata.mDnsHeader, aMessageMetadata.mMessageInfo,
+                    aMessageMetadata.mTtlConfig, aMessageMetadata.mLeaseConfig);
+}
+
+void Server::CommitSrpUpdate(Error aError, UpdateMetadata &aUpdateMetadata)
+{
+    CommitSrpUpdate(aError, aUpdateMetadata.GetHost(), aUpdateMetadata.GetDnsHeader(),
+                    aUpdateMetadata.IsDirectRxFromClient() ? &aUpdateMetadata.GetMessageInfo() : nullptr,
+                    aUpdateMetadata.GetTtlConfig(), aUpdateMetadata.GetLeaseConfig());
+}
+
 void Server::CommitSrpUpdate(Error                    aError,
-                             const Dns::UpdateHeader &aDnsHeader,
                              Host &                   aHost,
-                             const Ip6::MessageInfo & aMessageInfo)
+                             const Dns::UpdateHeader &aDnsHeader,
+                             const Ip6::MessageInfo * aMessageInfo,
+                             const TtlConfig &        aTtlConfig,
+                             const LeaseConfig &      aLeaseConfig)
 {
     Host *   existingHost;
     uint32_t hostLease;
     uint32_t hostKeyLease;
     uint32_t grantedLease;
     uint32_t grantedKeyLease;
+    uint32_t grantedTtl;
     bool     shouldFreeHost = true;
 
     SuccessOrExit(aError);
 
     hostLease       = aHost.GetLease();
     hostKeyLease    = aHost.GetKeyLease();
-    grantedLease    = mLeaseConfig.GrantLease(hostLease);
-    grantedKeyLease = mLeaseConfig.GrantKeyLease(hostKeyLease);
+    grantedLease    = aLeaseConfig.GrantLease(hostLease);
+    grantedKeyLease = aLeaseConfig.GrantKeyLease(hostKeyLease);
+    grantedTtl      = aTtlConfig.GrantTtl(grantedLease, aHost.GetTtl());
 
     aHost.SetLease(grantedLease);
     aHost.SetKeyLease(grantedKeyLease);
+    aHost.SetTtl(grantedTtl);
 
-    for (Service::Description &desc : aHost.mServiceDescriptions)
+    for (Service &service : aHost.mServices)
     {
-        desc.mLease    = grantedLease;
-        desc.mKeyLease = grantedKeyLease;
+        service.mDescription->mLease    = grantedLease;
+        service.mDescription->mKeyLease = grantedKeyLease;
+        service.mDescription->mTtl      = grantedTtl;
     }
 
     existingHost = mHosts.FindMatching(aHost.GetFullName());
@@ -393,17 +447,17 @@
     {
         if (aHost.GetKeyLease() == 0)
         {
-            otLogInfoSrp("[server] remove key of host %s", aHost.GetFullName());
-            RemoveHost(existingHost, /* aRetainName */ false, /* aNotifyServiceHandler */ false);
+            LogInfo("Remove key of host %s", aHost.GetFullName());
+            RemoveHost(existingHost, kDeleteName, kDoNotNotifyServiceHandler);
         }
         else if (existingHost != nullptr)
         {
             existingHost->SetKeyLease(aHost.GetKeyLease());
-            RemoveHost(existingHost, /* aRetainName */ true, /* aNotifyServiceHandler */ false);
+            RemoveHost(existingHost, kRetainName, kDoNotNotifyServiceHandler);
 
             for (Service &service : existingHost->mServices)
             {
-                existingHost->RemoveService(&service, /* aRetainName */ true, /* aNotifyServiceHandler */ false);
+                existingHost->RemoveService(&service, kRetainName, kDoNotNotifyServiceHandler);
             }
         }
     }
@@ -413,7 +467,8 @@
     }
     else
     {
-        otLogInfoSrp("[server] add new host %s", aHost.GetFullName());
+        AddHost(aHost);
+        shouldFreeHost = false;
 
         for (Service &service : aHost.GetServices())
         {
@@ -421,9 +476,6 @@
             service.Log(Service::kAddNew);
         }
 
-        AddHost(aHost);
-        shouldFreeHost = false;
-
 #if OPENTHREAD_CONFIG_SRP_SERVER_PORT_SWITCH_ENABLE
         if (!mHasRegisteredAnyService && (mAddressMode == kAddressModeUnicast))
         {
@@ -440,13 +492,16 @@
     HandleLeaseTimer();
 
 exit:
-    if (aError == kErrorNone && !(grantedLease == hostLease && grantedKeyLease == hostKeyLease))
+    if (aMessageInfo != nullptr)
     {
-        SendResponse(aDnsHeader, grantedLease, grantedKeyLease, aMessageInfo);
-    }
-    else
-    {
-        SendResponse(aDnsHeader, ErrorToDnsResponseCode(aError), aMessageInfo);
+        if (aError == kErrorNone && !(grantedLease == hostLease && grantedKeyLease == hostKeyLease))
+        {
+            SendResponse(aDnsHeader, grantedLease, grantedKeyLease, *aMessageInfo);
+        }
+        else
+        {
+            SendResponse(aDnsHeader, ErrorToDnsResponseCode(aError), *aMessageInfo);
+        }
     }
 
     if (shouldFreeHost)
@@ -474,7 +529,7 @@
     }
 #endif
 
-    otLogInfoSrp("[server] selected port %u", mPort);
+    LogInfo("Selected port %u", mPort);
 }
 
 void Server::Start(void)
@@ -483,7 +538,7 @@
 
     mState = kStateRunning;
     PrepareSocket();
-    otLogInfoSrp("[server] start listening on port %u", mPort);
+    LogInfo("Start listening on port %u", mPort);
 
 exit:
     return;
@@ -514,7 +569,7 @@
 exit:
     if (error != kErrorNone)
     {
-        otLogCritSrp("[server] failed to prepare socket: %s", ErrorToString(error));
+        LogCrit("Failed to prepare socket: %s", ErrorToString(error));
         Stop();
     }
 }
@@ -577,7 +632,7 @@
 
     while (!mHosts.IsEmpty())
     {
-        RemoveHost(mHosts.GetHead(), /* aRetainName */ false, /* aNotifyServiceHandler */ true);
+        RemoveHost(mHosts.GetHead(), kDeleteName, kNotifyServiceHandler);
     }
 
     // TODO: We should cancel any outstanding service updates, but current
@@ -590,7 +645,7 @@
     mLeaseTimer.Stop();
     mOutstandingUpdatesTimer.Stop();
 
-    otLogInfoSrp("[server] stop listening on %u", mPort);
+    LogInfo("Stop listening on %u", mPort);
     IgnoreError(mSocket.Close());
     mHasRegisteredAnyService = false;
 
@@ -612,16 +667,17 @@
     }
 }
 
-const Server::UpdateMetadata *Server::FindOutstandingUpdate(const Ip6::MessageInfo &aMessageInfo,
-                                                            uint16_t                aDnsMessageId)
+const Server::UpdateMetadata *Server::FindOutstandingUpdate(const MessageMetadata &aMessageMetadata) const
 {
     const UpdateMetadata *ret = nullptr;
 
+    VerifyOrExit(aMessageMetadata.IsDirectRxFromClient());
+
     for (const UpdateMetadata &update : mOutstandingUpdates)
     {
-        if (aDnsMessageId == update.GetDnsHeader().GetMessageId() &&
-            aMessageInfo.GetPeerAddr() == update.GetMessageInfo().GetPeerAddr() &&
-            aMessageInfo.GetPeerPort() == update.GetMessageInfo().GetPeerPort())
+        if (aMessageMetadata.mDnsHeader.GetMessageId() == update.GetDnsHeader().GetMessageId() &&
+            aMessageMetadata.mMessageInfo->GetPeerAddr() == update.GetMessageInfo().GetPeerAddr() &&
+            aMessageMetadata.mMessageInfo->GetPeerPort() == update.GetMessageInfo().GetPeerPort())
         {
             ExitNow(ret = &update);
         }
@@ -631,22 +687,20 @@
     return ret;
 }
 
-void Server::ProcessDnsUpdate(Message &                aMessage,
-                              const Ip6::MessageInfo & aMessageInfo,
-                              const Dns::UpdateHeader &aDnsHeader,
-                              uint16_t                 aOffset)
+void Server::ProcessDnsUpdate(Message &aMessage, MessageMetadata &aMetadata)
 {
-    Error     error = kErrorNone;
-    Dns::Zone zone;
-    Host *    host = nullptr;
+    Error error = kErrorNone;
+    Host *host  = nullptr;
 
-    otLogInfoSrp("[server] receive DNS update from %s", aMessageInfo.GetPeerAddr().ToString().AsCString());
+    LogInfo("Received DNS update from %s", aMetadata.IsDirectRxFromClient()
+                                               ? aMetadata.mMessageInfo->GetPeerAddr().ToString().AsCString()
+                                               : "an SRPL Partner");
 
-    SuccessOrExit(error = ProcessZoneSection(aMessage, aDnsHeader, aOffset, zone));
+    SuccessOrExit(error = ProcessZoneSection(aMessage, aMetadata));
 
-    if (FindOutstandingUpdate(aMessageInfo, aDnsHeader.GetMessageId()) != nullptr)
+    if (FindOutstandingUpdate(aMetadata) != nullptr)
     {
-        otLogInfoSrp("[server] drop duplicated SRP update request: messageId=%hu", aDnsHeader.GetMessageId());
+        LogInfo("Drop duplicated SRP update request: MessageId=%hu", aMetadata.mDnsHeader.GetMessageId());
 
         // Silently drop duplicate requests.
         // This could rarely happen, because the outstanding SRP update timer should
@@ -655,16 +709,18 @@
     }
 
     // Per 2.3.2 of SRP draft 6, no prerequisites should be included in a SRP update.
-    VerifyOrExit(aDnsHeader.GetPrerequisiteRecordCount() == 0, error = kErrorFailed);
+    VerifyOrExit(aMetadata.mDnsHeader.GetPrerequisiteRecordCount() == 0, error = kErrorFailed);
 
-    host = Host::New(GetInstance());
+    host = Host::Allocate(GetInstance(), aMetadata.mRxTime);
     VerifyOrExit(host != nullptr, error = kErrorNoBufs);
-    SuccessOrExit(error = ProcessUpdateSection(*host, aMessage, aDnsHeader, zone, aOffset));
+    SuccessOrExit(error = ProcessUpdateSection(*host, aMessage, aMetadata));
 
     // Parse lease time and validate signature.
-    SuccessOrExit(error = ProcessAdditionalSection(host, aMessage, aDnsHeader, aOffset));
+    SuccessOrExit(error = ProcessAdditionalSection(host, aMessage, aMetadata));
 
-    HandleUpdate(aDnsHeader, *host, aMessageInfo);
+    SuccessOrExit(error = ValidateServiceSubTypes(*host, aMetadata));
+
+    HandleUpdate(*host, aMetadata);
 
 exit:
     if (error != kErrorNone)
@@ -674,39 +730,40 @@
             host->Free();
         }
 
-        SendResponse(aDnsHeader, ErrorToDnsResponseCode(error), aMessageInfo);
+        if (aMetadata.IsDirectRxFromClient())
+        {
+            SendResponse(aMetadata.mDnsHeader, ErrorToDnsResponseCode(error), *aMetadata.mMessageInfo);
+        }
     }
 }
 
-Error Server::ProcessZoneSection(const Message &          aMessage,
-                                 const Dns::UpdateHeader &aDnsHeader,
-                                 uint16_t &               aOffset,
-                                 Dns::Zone &              aZone) const
+Error Server::ProcessZoneSection(const Message &aMessage, MessageMetadata &aMetadata) const
 {
-    Error     error = kErrorNone;
-    char      name[Dns::Name::kMaxNameSize];
-    Dns::Zone zone;
+    Error    error = kErrorNone;
+    char     name[Dns::Name::kMaxNameSize];
+    uint16_t offset = aMetadata.mOffset;
 
-    VerifyOrExit(aDnsHeader.GetZoneRecordCount() == 1, error = kErrorParse);
+    VerifyOrExit(aMetadata.mDnsHeader.GetZoneRecordCount() == 1, error = kErrorParse);
 
-    SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, name, sizeof(name)));
+    SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name, sizeof(name)));
     // TODO: return `Dns::kResponseNotAuth` for not authorized zone names.
-    VerifyOrExit(strcmp(name, GetDomain()) == 0, error = kErrorSecurity);
-    SuccessOrExit(error = aMessage.Read(aOffset, zone));
-    aOffset += sizeof(zone);
+    VerifyOrExit(StringMatch(name, GetDomain(), kStringCaseInsensitiveMatch), error = kErrorSecurity);
+    SuccessOrExit(error = aMessage.Read(offset, aMetadata.mDnsZone));
+    offset += sizeof(Dns::Zone);
 
-    VerifyOrExit(zone.GetType() == Dns::ResourceRecord::kTypeSoa, error = kErrorParse);
-    aZone = zone;
+    VerifyOrExit(aMetadata.mDnsZone.GetType() == Dns::ResourceRecord::kTypeSoa, error = kErrorParse);
+    aMetadata.mOffset = offset;
 
 exit:
+    if (error != kErrorNone)
+    {
+        LogWarn("Failed to process DNS Zone section: %s", ErrorToString(error));
+    }
+
     return error;
 }
 
-Error Server::ProcessUpdateSection(Host &                   aHost,
-                                   const Message &          aMessage,
-                                   const Dns::UpdateHeader &aDnsHeader,
-                                   const Dns::Zone &        aZone,
-                                   uint16_t &               aOffset) const
+Error Server::ProcessUpdateSection(Host &aHost, const Message &aMessage, MessageMetadata &aMetadata) const
 {
     Error error = kErrorNone;
 
@@ -716,42 +773,43 @@
     // 0. Enumerate over all Service Discovery Instructions before processing any other records.
     // So that we will know whether a name is a hostname or service instance name when processing
     // a "Delete All RRsets from a name" record.
-    error = ProcessServiceDiscoveryInstructions(aHost, aMessage, aDnsHeader, aZone, aOffset);
-    SuccessOrExit(error);
+    SuccessOrExit(error = ProcessServiceDiscoveryInstructions(aHost, aMessage, aMetadata));
 
     // 1. Enumerate over all RRs to build the Host Description Instruction.
-    error = ProcessHostDescriptionInstruction(aHost, aMessage, aDnsHeader, aZone, aOffset);
-    SuccessOrExit(error);
+    SuccessOrExit(error = ProcessHostDescriptionInstruction(aHost, aMessage, aMetadata));
 
     // 2. Enumerate over all RRs to build the Service Description Instructions.
-    error = ProcessServiceDescriptionInstructions(aHost, aMessage, aDnsHeader, aZone, aOffset);
-    SuccessOrExit(error);
+    SuccessOrExit(error = ProcessServiceDescriptionInstructions(aHost, aMessage, aMetadata));
 
     // 3. Verify that there are no name conflicts.
     VerifyOrExit(!HasNameConflictsWith(aHost), error = kErrorDuplicated);
 
 exit:
+    if (error != kErrorNone)
+    {
+        LogWarn("Failed to process DNS Update section: %s", ErrorToString(error));
+    }
+
     return error;
 }
 
-Error Server::ProcessHostDescriptionInstruction(Host &                   aHost,
-                                                const Message &          aMessage,
-                                                const Dns::UpdateHeader &aDnsHeader,
-                                                const Dns::Zone &        aZone,
-                                                uint16_t                 aOffset) const
+Error Server::ProcessHostDescriptionInstruction(Host &                 aHost,
+                                                const Message &        aMessage,
+                                                const MessageMetadata &aMetadata) const
 {
-    Error error;
+    Error    error;
+    uint16_t offset = aMetadata.mOffset;
 
     OT_ASSERT(aHost.GetFullName() == nullptr);
 
-    for (uint16_t numRecords = aDnsHeader.GetUpdateRecordCount(); numRecords > 0; numRecords--)
+    for (uint16_t numRecords = aMetadata.mDnsHeader.GetUpdateRecordCount(); numRecords > 0; numRecords--)
     {
         char                name[Dns::Name::kMaxNameSize];
         Dns::ResourceRecord record;
 
-        SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, name, sizeof(name)));
+        SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name, sizeof(name)));
 
-        SuccessOrExit(error = aMessage.Read(aOffset, record));
+        SuccessOrExit(error = aMessage.Read(offset, record));
 
         if (record.GetClass() == Dns::ResourceRecord::kClassAny)
         {
@@ -760,7 +818,7 @@
 
             // A "Delete All RRsets from a name" RR can only apply to a Service or Host Description.
 
-            if (aHost.FindServiceDescription(name) == nullptr)
+            if (!aHost.HasServiceInstance(name))
             {
                 // If host name is already set to a different name, `SetFullName()`
                 // will return `kErrorFailed`.
@@ -772,11 +830,13 @@
         {
             Dns::AaaaRecord aaaaRecord;
 
-            VerifyOrExit(record.GetClass() == aZone.GetClass(), error = kErrorFailed);
+            VerifyOrExit(record.GetClass() == aMetadata.mDnsZone.GetClass(), error = kErrorFailed);
+
+            SuccessOrExit(error = aHost.ProcessTtl(record.GetTtl()));
 
             SuccessOrExit(error = aHost.SetFullName(name));
 
-            SuccessOrExit(error = aMessage.Read(aOffset, aaaaRecord));
+            SuccessOrExit(error = aMessage.Read(offset, aaaaRecord));
             VerifyOrExit(aaaaRecord.IsValid(), error = kErrorParse);
 
             // Tolerate kErrorDrop for AAAA Resources.
@@ -785,41 +845,48 @@
         else if (record.GetType() == Dns::ResourceRecord::kTypeKey)
         {
             // We currently support only ECDSA P-256.
-            Dns::Ecdsa256KeyRecord key;
+            Dns::Ecdsa256KeyRecord keyRecord;
 
-            VerifyOrExit(record.GetClass() == aZone.GetClass(), error = kErrorFailed);
-            SuccessOrExit(error = aMessage.Read(aOffset, key));
-            VerifyOrExit(key.IsValid(), error = kErrorParse);
+            VerifyOrExit(record.GetClass() == aMetadata.mDnsZone.GetClass(), error = kErrorFailed);
 
-            VerifyOrExit(aHost.GetKey() == nullptr || *aHost.GetKey() == key, error = kErrorSecurity);
-            aHost.SetKey(key);
+            SuccessOrExit(error = aHost.ProcessTtl(record.GetTtl()));
+
+            SuccessOrExit(error = aMessage.Read(offset, keyRecord));
+            VerifyOrExit(keyRecord.IsValid(), error = kErrorParse);
+
+            VerifyOrExit(aHost.GetKeyRecord() == nullptr || *aHost.GetKeyRecord() == keyRecord, error = kErrorSecurity);
+            aHost.SetKeyRecord(keyRecord);
         }
 
-        aOffset += record.GetSize();
+        offset += record.GetSize();
     }
 
     // Verify that we have a complete Host Description Instruction.
 
     VerifyOrExit(aHost.GetFullName() != nullptr, error = kErrorFailed);
-    VerifyOrExit(aHost.GetKey() != nullptr, error = kErrorFailed);
+    VerifyOrExit(aHost.GetKeyRecord() != nullptr, error = kErrorFailed);
 
     // We check the number of host addresses after processing of the
     // Lease Option in the Addition Section and determining whether
     // the host is being removed or registered.
 
 exit:
+    if (error != kErrorNone)
+    {
+        LogWarn("Failed to process Host Description instructions: %s", ErrorToString(error));
+    }
+
     return error;
 }
 
-Error Server::ProcessServiceDiscoveryInstructions(Host &                   aHost,
-                                                  const Message &          aMessage,
-                                                  const Dns::UpdateHeader &aDnsHeader,
-                                                  const Dns::Zone &        aZone,
-                                                  uint16_t                 aOffset) const
+Error Server::ProcessServiceDiscoveryInstructions(Host &                 aHost,
+                                                  const Message &        aMessage,
+                                                  const MessageMetadata &aMetadata) const
 {
-    Error error = kErrorNone;
+    Error    error  = kErrorNone;
+    uint16_t offset = aMetadata.mOffset;
 
-    for (uint16_t numRecords = aDnsHeader.GetUpdateRecordCount(); numRecords > 0; numRecords--)
+    for (uint16_t numRecords = aMetadata.mDnsHeader.GetUpdateRecordCount(); numRecords > 0; numRecords--)
     {
         char           serviceName[Dns::Name::kMaxNameSize];
         char           instanceName[Dns::Name::kMaxNameSize];
@@ -828,10 +895,10 @@
         Service *      service;
         bool           isSubType;
 
-        SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, serviceName, sizeof(serviceName)));
+        SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, serviceName, sizeof(serviceName)));
         VerifyOrExit(Dns::Name::IsSubDomainOf(serviceName, GetDomain()), error = kErrorSecurity);
 
-        error = Dns::ResourceRecord::ReadRecord(aMessage, aOffset, ptrRecord);
+        error = Dns::ResourceRecord::ReadRecord(aMessage, offset, ptrRecord);
 
         if (error == kErrorNotFound)
         {
@@ -843,16 +910,16 @@
 
         SuccessOrExit(error);
 
-        SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, instanceName, sizeof(instanceName)));
+        SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, instanceName, sizeof(instanceName)));
 
         VerifyOrExit(ptrRecord.GetClass() == Dns::ResourceRecord::kClassNone ||
-                         ptrRecord.GetClass() == aZone.GetClass(),
+                         ptrRecord.GetClass() == aMetadata.mDnsZone.GetClass(),
                      error = kErrorFailed);
 
         // Check if the `serviceName` is a subtype with the name
         // format: "<sub-label>._sub.<service-labels>.<domain>."
 
-        subServiceName = StringFind(serviceName, kServiceSubTypeLabel);
+        subServiceName = StringFind(serviceName, kServiceSubTypeLabel, kStringCaseInsensitiveMatch);
         isSubType      = (subServiceName != nullptr);
 
         if (isSubType)
@@ -864,39 +931,49 @@
 
         // Verify that instance name and service name are related.
 
-        VerifyOrExit(StringEndsWith(instanceName, isSubType ? subServiceName : serviceName), error = kErrorFailed);
+        VerifyOrExit(
+            StringEndsWith(instanceName, isSubType ? subServiceName : serviceName, kStringCaseInsensitiveMatch),
+            error = kErrorFailed);
 
         // Ensure the same service does not exist already.
         VerifyOrExit(aHost.FindService(serviceName, instanceName) == nullptr, error = kErrorFailed);
 
-        service = aHost.AddNewService(serviceName, instanceName, isSubType);
+        service = aHost.AddNewService(serviceName, instanceName, isSubType, aMetadata.mRxTime);
         VerifyOrExit(service != nullptr, error = kErrorNoBufs);
 
         // This RR is a "Delete an RR from an RRset" update when the CLASS is NONE.
         service->mIsDeleted = (ptrRecord.GetClass() == Dns::ResourceRecord::kClassNone);
+
+        if (!service->mIsDeleted)
+        {
+            SuccessOrExit(error = aHost.ProcessTtl(ptrRecord.GetTtl()));
+        }
     }
 
 exit:
+    if (error != kErrorNone)
+    {
+        LogWarn("Failed to process Service Discovery instructions: %s", ErrorToString(error));
+    }
+
     return error;
 }
 
-Error Server::ProcessServiceDescriptionInstructions(Host &                   aHost,
-                                                    const Message &          aMessage,
-                                                    const Dns::UpdateHeader &aDnsHeader,
-                                                    const Dns::Zone &        aZone,
-                                                    uint16_t &               aOffset) const
+Error Server::ProcessServiceDescriptionInstructions(Host &           aHost,
+                                                    const Message &  aMessage,
+                                                    MessageMetadata &aMetadata) const
 {
-    Error     error = kErrorNone;
-    TimeMilli now   = TimerMilli::GetNow();
+    Error    error  = kErrorNone;
+    uint16_t offset = aMetadata.mOffset;
 
-    for (uint16_t numRecords = aDnsHeader.GetUpdateRecordCount(); numRecords > 0; numRecords--)
+    for (uint16_t numRecords = aMetadata.mDnsHeader.GetUpdateRecordCount(); numRecords > 0; numRecords--)
     {
-        Service::Description *desc;
-        char                  name[Dns::Name::kMaxNameSize];
-        Dns::ResourceRecord   record;
+        RetainPtr<Service::Description> desc;
+        char                            name[Dns::Name::kMaxNameSize];
+        Dns::ResourceRecord             record;
 
-        SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, name, sizeof(name)));
-        SuccessOrExit(error = aMessage.Read(aOffset, record));
+        SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name, sizeof(name)));
+        SuccessOrExit(error = aMessage.Read(offset, record));
 
         if (record.GetClass() == Dns::ResourceRecord::kClassAny)
         {
@@ -908,10 +985,10 @@
             if (desc != nullptr)
             {
                 desc->ClearResources();
-                desc->mTimeLastUpdate = now;
+                desc->mUpdateTime = aMetadata.mRxTime;
             }
 
-            aOffset += record.GetSize();
+            offset += record.GetSize();
             continue;
         }
 
@@ -921,11 +998,14 @@
             char           hostName[Dns::Name::kMaxNameSize];
             uint16_t       hostNameLength = sizeof(hostName);
 
-            VerifyOrExit(record.GetClass() == aZone.GetClass(), error = kErrorFailed);
-            SuccessOrExit(error = aMessage.Read(aOffset, srvRecord));
-            aOffset += sizeof(srvRecord);
+            VerifyOrExit(record.GetClass() == aMetadata.mDnsZone.GetClass(), error = kErrorFailed);
 
-            SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, hostName, hostNameLength));
+            SuccessOrExit(error = aHost.ProcessTtl(record.GetTtl()));
+
+            SuccessOrExit(error = aMessage.Read(offset, srvRecord));
+            offset += sizeof(srvRecord);
+
+            SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, hostName, hostNameLength));
             VerifyOrExit(Dns::Name::IsSubDomainOf(name, GetDomain()), error = kErrorSecurity);
             VerifyOrExit(aHost.Matches(hostName), error = kErrorFailed);
 
@@ -934,44 +1014,55 @@
 
             // Make sure that this is the first SRV RR for this service description
             VerifyOrExit(desc->mPort == 0, error = kErrorFailed);
-            desc->mPriority       = srvRecord.GetPriority();
-            desc->mWeight         = srvRecord.GetWeight();
-            desc->mPort           = srvRecord.GetPort();
-            desc->mTimeLastUpdate = now;
+            desc->mTtl        = srvRecord.GetTtl();
+            desc->mPriority   = srvRecord.GetPriority();
+            desc->mWeight     = srvRecord.GetWeight();
+            desc->mPort       = srvRecord.GetPort();
+            desc->mUpdateTime = aMetadata.mRxTime;
         }
         else if (record.GetType() == Dns::ResourceRecord::kTypeTxt)
         {
-            VerifyOrExit(record.GetClass() == aZone.GetClass(), error = kErrorFailed);
+            VerifyOrExit(record.GetClass() == aMetadata.mDnsZone.GetClass(), error = kErrorFailed);
+
+            SuccessOrExit(error = aHost.ProcessTtl(record.GetTtl()));
 
             desc = aHost.FindServiceDescription(name);
             VerifyOrExit(desc != nullptr, error = kErrorFailed);
 
-            aOffset += sizeof(record);
-            SuccessOrExit(error = desc->SetTxtDataFromMessage(aMessage, aOffset, record.GetLength()));
-            aOffset += record.GetLength();
+            offset += sizeof(record);
+            SuccessOrExit(error = desc->SetTxtDataFromMessage(aMessage, offset, record.GetLength()));
+            offset += record.GetLength();
         }
         else
         {
-            aOffset += record.GetSize();
+            offset += record.GetSize();
         }
     }
 
     // Verify that all service descriptions on `aHost` are updated. Note
-    // that `mTimeLastUpdate` on a new `Service::Description` is set to
+    // that `mUpdateTime` on a new `Service::Description` is set to
     // `GetNow().GetDistantPast()`.
 
-    for (Service::Description &desc : aHost.mServiceDescriptions)
+    for (Service &service : aHost.mServices)
     {
-        VerifyOrExit(desc.mTimeLastUpdate == now, error = kErrorFailed);
+        VerifyOrExit(service.mDescription->mUpdateTime == aMetadata.mRxTime, error = kErrorFailed);
 
         // Check that either both `mPort` and `mTxtData` are set
         // (i.e., we saw both SRV and TXT record) or both are default
         // (cleared) value (i.e., we saw neither of them).
 
-        VerifyOrExit((desc.mPort == 0) == (desc.mTxtData == nullptr), error = kErrorFailed);
+        VerifyOrExit((service.mDescription->mPort == 0) == service.mDescription->mTxtData.IsNull(),
+                     error = kErrorFailed);
     }
 
+    aMetadata.mOffset = offset;
+
 exit:
+    if (error != kErrorNone)
+    {
+        LogWarn("Failed to process Service Description instructions: %s", ErrorToString(error));
+    }
+
     return error;
 }
 
@@ -981,32 +1072,30 @@
            aRecord.GetTtl() == 0 && aRecord.GetLength() == 0;
 }
 
-Error Server::ProcessAdditionalSection(Host *                   aHost,
-                                       const Message &          aMessage,
-                                       const Dns::UpdateHeader &aDnsHeader,
-                                       uint16_t &               aOffset) const
+Error Server::ProcessAdditionalSection(Host *aHost, const Message &aMessage, MessageMetadata &aMetadata) const
 {
     Error            error = kErrorNone;
     Dns::OptRecord   optRecord;
     Dns::LeaseOption leaseOption;
     Dns::SigRecord   sigRecord;
     char             name[2]; // The root domain name (".") is expected.
+    uint16_t         offset = aMetadata.mOffset;
     uint16_t         sigOffset;
     uint16_t         sigRdataOffset;
     char             signerName[Dns::Name::kMaxNameSize];
     uint16_t         signatureLength;
 
-    VerifyOrExit(aDnsHeader.GetAdditionalRecordCount() == 2, error = kErrorFailed);
+    VerifyOrExit(aMetadata.mDnsHeader.GetAdditionalRecordCount() == 2, error = kErrorFailed);
 
     // EDNS(0) Update Lease Option.
 
-    SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, name, sizeof(name)));
-    SuccessOrExit(error = aMessage.Read(aOffset, optRecord));
-    SuccessOrExit(error = aMessage.Read(aOffset + sizeof(optRecord), leaseOption));
+    SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name, sizeof(name)));
+    SuccessOrExit(error = aMessage.Read(offset, optRecord));
+    SuccessOrExit(error = aMessage.Read(offset + sizeof(optRecord), leaseOption));
     VerifyOrExit(leaseOption.IsValid(), error = kErrorFailed);
     VerifyOrExit(optRecord.GetSize() == sizeof(optRecord) + sizeof(leaseOption), error = kErrorParse);
 
-    aOffset += optRecord.GetSize();
+    offset += optRecord.GetSize();
 
     aHost->SetLease(leaseOption.GetLeaseInterval());
     aHost->SetKeyLease(leaseOption.GetKeyLeaseInterval());
@@ -1023,22 +1112,22 @@
 
     // SIG(0).
 
-    sigOffset = aOffset;
-    SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, name, sizeof(name)));
-    SuccessOrExit(error = aMessage.Read(aOffset, sigRecord));
+    sigOffset = offset;
+    SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, name, sizeof(name)));
+    SuccessOrExit(error = aMessage.Read(offset, sigRecord));
     VerifyOrExit(sigRecord.IsValid(), error = kErrorParse);
 
-    sigRdataOffset = aOffset + sizeof(Dns::ResourceRecord);
-    aOffset += sizeof(sigRecord);
+    sigRdataOffset = offset + sizeof(Dns::ResourceRecord);
+    offset += sizeof(sigRecord);
 
     // TODO: Verify that the signature doesn't expire. This is not
     // implemented because the end device may not be able to get
     // the synchronized date/time.
 
-    SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, signerName, sizeof(signerName)));
+    SuccessOrExit(error = Dns::Name::ReadName(aMessage, offset, signerName, sizeof(signerName)));
 
-    signatureLength = sigRecord.GetLength() - (aOffset - sigRdataOffset);
-    aOffset += signatureLength;
+    signatureLength = sigRecord.GetLength() - (offset - sigRdataOffset);
+    offset += signatureLength;
 
     // Verify the signature. Currently supports only ECDSA.
 
@@ -1046,14 +1135,21 @@
     VerifyOrExit(sigRecord.GetTypeCovered() == 0, error = kErrorFailed);
     VerifyOrExit(signatureLength == Crypto::Ecdsa::P256::Signature::kSize, error = kErrorParse);
 
-    SuccessOrExit(error = VerifySignature(*aHost->GetKey(), aMessage, aDnsHeader, sigOffset, sigRdataOffset,
-                                          sigRecord.GetLength(), signerName));
+    SuccessOrExit(error = VerifySignature(*aHost->GetKeyRecord(), aMessage, aMetadata.mDnsHeader, sigOffset,
+                                          sigRdataOffset, sigRecord.GetLength(), signerName));
+
+    aMetadata.mOffset = offset;
 
 exit:
+    if (error != kErrorNone)
+    {
+        LogWarn("Failed to process DNS Additional section: %s", ErrorToString(error));
+    }
+
     return error;
 }
 
-Error Server::VerifySignature(const Dns::Ecdsa256KeyRecord &aKey,
+Error Server::VerifySignature(const Dns::Ecdsa256KeyRecord &aKeyRecord,
                               const Message &               aMessage,
                               Dns::UpdateHeader             aDnsHeader,
                               uint16_t                      aSigOffset,
@@ -1093,14 +1189,81 @@
     signatureOffset = aSigRdataOffset + aSigRdataLength - Crypto::Ecdsa::P256::Signature::kSize;
     SuccessOrExit(error = aMessage.Read(signatureOffset, signature));
 
-    error = aKey.GetKey().Verify(hash, signature);
+    error = aKeyRecord.GetKey().Verify(hash, signature);
 
 exit:
+    if (error != kErrorNone)
+    {
+        LogWarn("Failed to verify message signature: %s", ErrorToString(error));
+    }
+
     FreeMessage(signerNameMessage);
     return error;
 }
 
-void Server::HandleUpdate(const Dns::UpdateHeader &aDnsHeader, Host &aHost, const Ip6::MessageInfo &aMessageInfo)
+Error Server::ValidateServiceSubTypes(Host &aHost, const MessageMetadata &aMetadata)
+{
+    Error error = kErrorNone;
+    Host *existingHost;
+
+    // Verify that there is a matching base type service for all
+    // sub-type services in `aHost` (which is from the received
+    // and parsed SRP Update message).
+
+    for (const Service &service : aHost.GetServices())
+    {
+        if (service.IsSubType() && (aHost.FindBaseService(service.GetInstanceName()) == nullptr))
+        {
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
+            char subLabel[Dns::Name::kMaxLabelSize];
+
+            IgnoreError(service.GetServiceSubTypeLabel(subLabel, sizeof(subLabel)));
+            LogWarn("Message contains instance %s with subtype %s without base type", service.GetInstanceName(),
+                    subLabel);
+#endif
+
+            ExitNow(error = kErrorParse);
+        }
+    }
+
+    // SRP server must treat the update instructions for a service type
+    // and all its sub-types as atomic, i.e., when a service and its
+    // sub-types are being updated, whatever information appears in the
+    // SRP Update is the entirety of information about that service and
+    // its sub-types. Any previously registered sub-type that does not
+    // appear in a new SRP Update, must be removed.
+    //
+    // We go though the list of registered services for the same host
+    // and if the base service is included in the new SRP Update
+    // message, we add any previously registered service sub-type that
+    // does not appear in new Update message as "deleted".
+
+    existingHost = mHosts.FindMatching(aHost.GetFullName());
+    VerifyOrExit(existingHost != nullptr);
+
+    for (const Service &baseService : existingHost->GetServices())
+    {
+        if (baseService.IsSubType() || (aHost.FindBaseService(baseService.GetInstanceName()) == nullptr))
+        {
+            continue;
+        }
+
+        for (const Service &subService : existingHost->GetServices())
+        {
+            if (!subService.IsSubType() || !subService.MatchesInstanceName(baseService.GetInstanceName()))
+            {
+                continue;
+            }
+
+            SuccessOrExit(error = aHost.AddCopyOfServiceAsDeletedIfNotPresent(subService, aMetadata.mRxTime));
+        }
+    }
+
+exit:
+    return error;
+}
+
+void Server::HandleUpdate(Host &aHost, const MessageMetadata &aMetadata)
 {
     Error error = kErrorNone;
     Host *existingHost;
@@ -1125,35 +1288,36 @@
             continue;
         }
 
-        if (aHost.FindService(service.GetServiceName(), service.GetInstanceName()) == nullptr)
-        {
-            Service *newService =
-                aHost.AddNewService(service.GetServiceName(), service.GetInstanceName(), service.IsSubType());
-
-            VerifyOrExit(newService != nullptr, error = kErrorNoBufs);
-            newService->mDescription.mTimeLastUpdate = TimerMilli::GetNow();
-            newService->mIsDeleted                   = true;
-        }
+        SuccessOrExit(error = aHost.AddCopyOfServiceAsDeletedIfNotPresent(service, aMetadata.mRxTime));
     }
 
 exit:
-    if (error != kErrorNone)
-    {
-        CommitSrpUpdate(error, aDnsHeader, aHost, aMessageInfo);
-    }
-    else if (mServiceUpdateHandler != nullptr)
-    {
-        UpdateMetadata *update = UpdateMetadata::New(GetInstance(), aDnsHeader, &aHost, aMessageInfo);
+    InformUpdateHandlerOrCommit(error, aHost, aMetadata);
+}
 
-        IgnoreError(mOutstandingUpdates.Add(*update));
-        mOutstandingUpdatesTimer.StartAt(mOutstandingUpdates.GetTail()->GetExpireTime(), 0);
-
-        mServiceUpdateHandler(update->GetId(), &aHost, kDefaultEventsHandlerTimeout, mServiceUpdateHandlerContext);
-    }
-    else
+void Server::InformUpdateHandlerOrCommit(Error aError, Host &aHost, const MessageMetadata &aMetadata)
+{
+    if ((aError == kErrorNone) && (mServiceUpdateHandler != nullptr))
     {
-        CommitSrpUpdate(kErrorNone, aDnsHeader, aHost, aMessageInfo);
+        UpdateMetadata *update = UpdateMetadata::Allocate(GetInstance(), aHost, aMetadata);
+
+        if (update != nullptr)
+        {
+            mOutstandingUpdates.Push(*update);
+            mOutstandingUpdatesTimer.FireAtIfEarlier(update->GetExpireTime());
+
+            LogInfo("SRP update handler is notified (updatedId = %u)", update->GetId());
+            mServiceUpdateHandler(update->GetId(), &aHost, kDefaultEventsHandlerTimeout, mServiceUpdateHandlerContext);
+            ExitNow();
+        }
+
+        aError = kErrorNoBufs;
     }
+
+    CommitSrpUpdate(aError, aHost, aMetadata);
+
+exit:
+    return;
 }
 
 void Server::SendResponse(const Dns::UpdateHeader &   aHeader,
@@ -1177,17 +1341,19 @@
 
     if (aResponseCode != Dns::UpdateHeader::kResponseSuccess)
     {
-        otLogInfoSrp("[server] send fail response: %d", aResponseCode);
+        LogWarn("Send fail response: %d", aResponseCode);
     }
     else
     {
-        otLogInfoSrp("[server] send success response");
+        LogInfo("Send success response");
     }
 
+    UpdateResponseCounters(aResponseCode);
+
 exit:
     if (error != kErrorNone)
     {
-        otLogWarnSrp("[server] failed to send response: %s", ErrorToString(error));
+        LogWarn("Failed to send response: %s", ErrorToString(error));
         FreeMessage(response);
     }
 }
@@ -1229,12 +1395,14 @@
 
     SuccessOrExit(error = GetSocket().SendTo(*response, aMessageInfo));
 
-    otLogInfoSrp("[server] send response with granted lease: %u and key lease: %u", aLease, aKeyLease);
+    LogInfo("Send success response with granted lease: %u and key lease: %u", aLease, aKeyLease);
+
+    UpdateResponseCounters(Dns::UpdateHeader::kResponseSuccess);
 
 exit:
     if (error != kErrorNone)
     {
-        otLogWarnSrp("[server] failed to send response: %s", ErrorToString(error));
+        LogWarn("Failed to send response: %s", ErrorToString(error));
         FreeMessage(response);
     }
 }
@@ -1250,31 +1418,37 @@
 
     if (error != kErrorNone)
     {
-        otLogInfoSrp("[server] failed to handle DNS message: %s", ErrorToString(error));
+        LogInfo("Failed to handle DNS message: %s", ErrorToString(error));
     }
 }
 
 Error Server::ProcessMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
 {
-    Error             error;
-    Dns::UpdateHeader dnsHeader;
-    uint16_t          offset = aMessage.GetOffset();
+    return ProcessMessage(aMessage, TimerMilli::GetNow(), mTtlConfig, mLeaseConfig, &aMessageInfo);
+}
 
-    SuccessOrExit(error = aMessage.Read(offset, dnsHeader));
-    offset += sizeof(dnsHeader);
+Error Server::ProcessMessage(Message &               aMessage,
+                             TimeMilli               aRxTime,
+                             const TtlConfig &       aTtlConfig,
+                             const LeaseConfig &     aLeaseConfig,
+                             const Ip6::MessageInfo *aMessageInfo)
+{
+    Error           error;
+    MessageMetadata metadata;
 
-    // Handles only queries.
-    VerifyOrExit(dnsHeader.GetType() == Dns::UpdateHeader::Type::kTypeQuery, error = kErrorDrop);
+    metadata.mOffset      = aMessage.GetOffset();
+    metadata.mRxTime      = aRxTime;
+    metadata.mTtlConfig   = aTtlConfig;
+    metadata.mLeaseConfig = aLeaseConfig;
+    metadata.mMessageInfo = aMessageInfo;
 
-    switch (dnsHeader.GetQueryType())
-    {
-    case Dns::UpdateHeader::kQueryTypeUpdate:
-        ProcessDnsUpdate(aMessage, aMessageInfo, dnsHeader, offset);
-        break;
-    default:
-        error = kErrorDrop;
-        break;
-    }
+    SuccessOrExit(error = aMessage.Read(metadata.mOffset, metadata.mDnsHeader));
+    metadata.mOffset += sizeof(Dns::UpdateHeader);
+
+    VerifyOrExit(metadata.mDnsHeader.GetType() == Dns::UpdateHeader::Type::kTypeQuery, error = kErrorDrop);
+    VerifyOrExit(metadata.mDnsHeader.GetQueryType() == Dns::UpdateHeader::kQueryTypeUpdate, error = kErrorDrop);
+
+    ProcessDnsUpdate(aMessage, metadata);
 
 exit:
     return error;
@@ -1297,10 +1471,10 @@
 
         if (host->GetKeyExpireTime() <= now)
         {
-            otLogInfoSrp("[server] KEY LEASE of host %s expired", host->GetFullName());
+            LogInfo("KEY LEASE of host %s expired", host->GetFullName());
 
             // Removes the whole host and all services if the KEY RR expired.
-            RemoveHost(host, /* aRetainName */ false, /* aNotifyServiceHandler */ true);
+            RemoveHost(host, kDeleteName, kNotifyServiceHandler);
         }
         else if (host->IsDeleted())
         {
@@ -1320,7 +1494,7 @@
                 if (service->GetKeyExpireTime() <= now)
                 {
                     service->Log(Service::kKeyLeaseExpired);
-                    host->RemoveService(service, /* aRetainName */ false, /* aNotifyServiceHandler */ true);
+                    host->RemoveService(service, kDeleteName, kNotifyServiceHandler);
                 }
                 else
                 {
@@ -1330,16 +1504,16 @@
         }
         else if (host->GetExpireTime() <= now)
         {
-            otLogInfoSrp("[server] LEASE of host %s expired", host->GetFullName());
+            LogInfo("LEASE of host %s expired", host->GetFullName());
 
             // If the host expired, delete all resources of this host and its services.
             for (Service &service : host->mServices)
             {
                 // Don't need to notify the service handler as `RemoveHost` at below will do.
-                host->RemoveService(&service, /* aRetainName */ true, /* aNotifyServiceHandler */ false);
+                host->RemoveService(&service, kRetainName, kDoNotNotifyServiceHandler);
             }
 
-            RemoveHost(host, /* aRetainName */ true, /* aNotifyServiceHandler */ true);
+            RemoveHost(host, kRetainName, kNotifyServiceHandler);
 
             earliestExpireTime = OT_MIN(earliestExpireTime, host->GetKeyExpireTime());
         }
@@ -1360,7 +1534,7 @@
                 if (service->GetKeyExpireTime() <= now)
                 {
                     service->Log(Service::kKeyLeaseExpired);
-                    host->RemoveService(service, /* aRetainName */ false, /* aNotifyServiceHandler */ true);
+                    host->RemoveService(service, kDeleteName, kNotifyServiceHandler);
                 }
                 else if (service->mIsDeleted)
                 {
@@ -1372,7 +1546,7 @@
                     service->Log(Service::kLeaseExpired);
 
                     // The service is expired, delete it.
-                    host->RemoveService(service, /* aRetainName */ true, /* aNotifyServiceHandler */ true);
+                    host->RemoveService(service, kRetainName, kNotifyServiceHandler);
                     earliestExpireTime = OT_MIN(earliestExpireTime, service->GetKeyExpireTime());
                 }
                 else
@@ -1388,13 +1562,13 @@
         OT_ASSERT(earliestExpireTime >= now);
         if (!mLeaseTimer.IsRunning() || earliestExpireTime <= mLeaseTimer.GetFireTime())
         {
-            otLogInfoSrp("[server] lease timer is scheduled for %u seconds", Time::MsecToSec(earliestExpireTime - now));
+            LogInfo("Lease timer is scheduled for %u seconds", Time::MsecToSec(earliestExpireTime - now));
             mLeaseTimer.StartAt(earliestExpireTime, 0);
         }
     }
     else
     {
-        otLogInfoSrp("[server] lease timer is stopped");
+        LogInfo("Lease timer is stopped");
         mLeaseTimer.Stop();
     }
 }
@@ -1408,8 +1582,7 @@
 {
     while (!mOutstandingUpdates.IsEmpty() && mOutstandingUpdates.GetTail()->GetExpireTime() <= TimerMilli::GetNow())
     {
-        otLogInfoSrp("[server] outstanding service update timeout (updateId = %u)",
-                     mOutstandingUpdates.GetTail()->GetId());
+        LogInfo("Outstanding service update timeout (updateId = %u)", mOutstandingUpdates.GetTail()->GetId());
         HandleServiceUpdateResult(mOutstandingUpdates.GetTail(), kErrorResponseTimeout);
     }
 }
@@ -1427,42 +1600,44 @@
     return kAddressModeStrings[aMode];
 }
 
+void Server::UpdateResponseCounters(Dns::UpdateHeader::Response aResponseCode)
+{
+    switch (aResponseCode)
+    {
+    case Dns::UpdateHeader::kResponseSuccess:
+        ++mResponseCounters.mSuccess;
+        break;
+    case Dns::UpdateHeader::kResponseServerFailure:
+        ++mResponseCounters.mServerFailure;
+        break;
+    case Dns::UpdateHeader::kResponseFormatError:
+        ++mResponseCounters.mFormatError;
+        break;
+    case Dns::UpdateHeader::kResponseNameExists:
+        ++mResponseCounters.mNameExists;
+        break;
+    case Dns::UpdateHeader::kResponseRefused:
+        ++mResponseCounters.mRefused;
+        break;
+    default:
+        ++mResponseCounters.mOther;
+        break;
+    }
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 // Server::Service
 
-Server::Service *Server::Service::New(const char *aServiceName, Description &aDescription, bool aIsSubType)
+Error Server::Service::Init(const char *aServiceName, Description &aDescription, bool aIsSubType, TimeMilli aUpdateTime)
 {
-    void *   buf;
-    Service *service = nullptr;
+    mDescription.Reset(&aDescription);
+    mNext        = nullptr;
+    mUpdateTime  = aUpdateTime;
+    mIsDeleted   = false;
+    mIsSubType   = aIsSubType;
+    mIsCommitted = false;
 
-    buf = Instance::HeapCAlloc(1, sizeof(Service));
-    VerifyOrExit(buf != nullptr);
-
-    service = new (buf) Service(aDescription, aIsSubType);
-
-    if (service->mServiceName.Set(aServiceName) != kErrorNone)
-    {
-        service->Free();
-        service = nullptr;
-    }
-
-exit:
-    return service;
-}
-
-void Server::Service::Free(void)
-{
-    Instance::HeapFree(this);
-}
-
-Server::Service::Service(Description &aDescription, bool aIsSubType)
-    : mDescription(aDescription)
-    , mNext(nullptr)
-    , mTimeLastUpdate(TimerMilli::GetNow())
-    , mIsDeleted(false)
-    , mIsSubType(aIsSubType)
-    , mIsCommitted(false)
-{
+    return mServiceName.Set(aServiceName);
 }
 
 Error Server::Service::GetServiceSubTypeLabel(char *aLabel, uint8_t aMaxSize) const
@@ -1476,7 +1651,7 @@
 
     VerifyOrExit(IsSubType(), error = kErrorInvalidArgs);
 
-    subServiceName = StringFind(serviceName, kServiceSubTypeLabel);
+    subServiceName = StringFind(serviceName, kServiceSubTypeLabel, kStringCaseInsensitiveMatch);
     OT_ASSERT(subServiceName != nullptr);
 
     if (subServiceName - serviceName < aMaxSize)
@@ -1500,12 +1675,34 @@
     OT_ASSERT(!mIsDeleted);
     OT_ASSERT(!GetHost().IsDeleted());
 
-    return mTimeLastUpdate + Time::SecToMsec(mDescription.mLease);
+    return mUpdateTime + Time::SecToMsec(mDescription->mLease);
 }
 
 TimeMilli Server::Service::GetKeyExpireTime(void) const
 {
-    return mTimeLastUpdate + Time::SecToMsec(mDescription.mKeyLease);
+    return mUpdateTime + Time::SecToMsec(mDescription->mKeyLease);
+}
+
+void Server::Service::GetLeaseInfo(LeaseInfo &aLeaseInfo) const
+{
+    TimeMilli now           = TimerMilli::GetNow();
+    TimeMilli expireTime    = GetExpireTime();
+    TimeMilli keyExpireTime = GetKeyExpireTime();
+
+    aLeaseInfo.mLease             = Time::SecToMsec(GetLease());
+    aLeaseInfo.mKeyLease          = Time::SecToMsec(GetKeyLease());
+    aLeaseInfo.mRemainingLease    = (now <= expireTime) ? (expireTime - now) : 0;
+    aLeaseInfo.mRemainingKeyLease = (now <= keyExpireTime) ? (keyExpireTime - now) : 0;
+}
+
+bool Server::Service::MatchesInstanceName(const char *aInstanceName) const
+{
+    return StringMatch(mDescription->mInstanceName.AsCString(), aInstanceName, kStringCaseInsensitiveMatch);
+}
+
+bool Server::Service::MatchesServiceName(const char *aServiceName) const
+{
+    return StringMatch(mServiceName.AsCString(), aServiceName, kStringCaseInsensitiveMatch);
 }
 
 bool Server::Service::MatchesFlags(Flags aFlags) const
@@ -1536,14 +1733,14 @@
     return matches;
 }
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && OPENTHREAD_CONFIG_LOG_SRP
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 void Server::Service::Log(Action aAction) const
 {
     static const char *const kActionStrings[] = {
-        "add new",                   // (0) kAddNew
-        "update existing",           // (1) kUpdateExisting
-        "remove but retain name of", // (2) kRemoveButRetainName
-        "full remove",               // (3) kFullyRemove
+        "Add new",                   // (0) kAddNew
+        "Update existing",           // (1) kUpdateExisting
+        "Remove but retain name of", // (2) kRemoveButRetainName
+        "Fully remove",              // (3) kFullyRemove
         "LEASE expired for ",        // (4) kLeaseExpired
         "KEY LEASE expired for",     // (5) kKeyLeaseExpired
     };
@@ -1566,105 +1763,72 @@
     {
         IgnoreError(GetServiceSubTypeLabel(subLabel, sizeof(subLabel)));
 
-        otLogInfoSrp("[server] %s service '%s'%s%s", kActionStrings[aAction], GetInstanceName(),
-                     IsSubType() ? " subtype:" : "", subLabel);
+        LogInfo("%s service '%s'%s%s", kActionStrings[aAction], GetInstanceName(), IsSubType() ? " subtype:" : "",
+                subLabel);
     }
 }
 #else
 void Server::Service::Log(Action) const
 {
 }
-#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && OPENTHREAD_CONFIG_LOG_SRP
+#endif // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
 //---------------------------------------------------------------------------------------------------------------------
 // Server::Service::Description
 
-Server::Service::Description *Server::Service::Description::New(const char *aInstanceName, Host &aHost)
+Error Server::Service::Description::Init(const char *aInstanceName, Host &aHost)
 {
-    void *       buf;
-    Description *desc = nullptr;
+    mNext       = nullptr;
+    mHost       = &aHost;
+    mPriority   = 0;
+    mWeight     = 0;
+    mTtl        = 0;
+    mPort       = 0;
+    mLease      = 0;
+    mKeyLease   = 0;
+    mUpdateTime = TimerMilli::GetNow().GetDistantPast();
+    mTxtData.Free();
 
-    buf = Instance::HeapCAlloc(1, sizeof(Description));
-    VerifyOrExit(buf != nullptr);
-
-    desc = new (buf) Description(aHost);
-
-    if (desc->mInstanceName.Set(aInstanceName) != kErrorNone)
-    {
-        desc->Free();
-        desc = nullptr;
-    }
-
-exit:
-    return desc;
+    return mInstanceName.Set(aInstanceName);
 }
 
-void Server::Service::Description::Free(void)
+bool Server::Service::Description::Matches(const char *aInstanceName) const
 {
-    mInstanceName.Free();
-    Instance::HeapFree(this);
-}
-
-Server::Service::Description::Description(Host &aHost)
-    : mNext(nullptr)
-    , mHost(aHost)
-    , mPriority(0)
-    , mWeight(0)
-    , mPort(0)
-    , mTxtLength(0)
-    , mTxtData(nullptr)
-    , mLease(0)
-    , mKeyLease(0)
-    , mTimeLastUpdate(TimerMilli::GetNow().GetDistantPast())
-{
+    return StringMatch(mInstanceName.AsCString(), aInstanceName, kStringCaseInsensitiveMatch);
 }
 
 void Server::Service::Description::ClearResources(void)
 {
     mPort = 0;
-    Instance::HeapFree(mTxtData);
-    mTxtData   = nullptr;
-    mTxtLength = 0;
+    mTxtData.Free();
 }
 
 void Server::Service::Description::TakeResourcesFrom(Description &aDescription)
 {
-    // Take ownership and move the heap allocated `mTxtData` buffer
-    // from `aDescription
-    Instance::HeapFree(mTxtData);
-    mTxtData                = aDescription.mTxtData;
-    mTxtLength              = aDescription.mTxtLength;
-    aDescription.mTxtData   = nullptr;
-    aDescription.mTxtLength = 0;
+    mTxtData.SetFrom(static_cast<Heap::Data &&>(aDescription.mTxtData));
 
     mPriority = aDescription.mPriority;
     mWeight   = aDescription.mWeight;
     mPort     = aDescription.mPort;
 
-    mLease          = aDescription.mLease;
-    mKeyLease       = aDescription.mKeyLease;
-    mTimeLastUpdate = TimerMilli::GetNow();
+    mTtl        = aDescription.mTtl;
+    mLease      = aDescription.mLease;
+    mKeyLease   = aDescription.mKeyLease;
+    mUpdateTime = TimerMilli::GetNow();
 }
 
 Error Server::Service::Description::SetTxtDataFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength)
 {
-    Error    error = kErrorNone;
-    uint8_t *txtData;
+    Error error;
 
-    txtData = static_cast<uint8_t *>(Instance::HeapCAlloc(1, aLength));
-    VerifyOrExit(txtData != nullptr, error = kErrorNoBufs);
-
-    VerifyOrExit(aMessage.ReadBytes(aOffset, txtData, aLength) == aLength, error = kErrorParse);
-    VerifyOrExit(Dns::TxtRecord::VerifyTxtData(txtData, aLength, /* aAllowEmpty */ false), error = kErrorParse);
-
-    Instance::HeapFree(mTxtData);
-    mTxtData   = txtData;
-    mTxtLength = aLength;
+    SuccessOrExit(error = mTxtData.SetFrom(aMessage, aOffset, aLength));
+    VerifyOrExit(Dns::TxtRecord::VerifyTxtData(mTxtData.GetBytes(), mTxtData.GetLength(), /* aAllowEmpty */ false),
+                 error = kErrorParse);
 
 exit:
     if (error != kErrorNone)
     {
-        Instance::HeapFree(txtData);
+        mTxtData.Free();
     }
 
     return error;
@@ -1673,36 +1837,20 @@
 //---------------------------------------------------------------------------------------------------------------------
 // Server::Host
 
-Server::Host *Server::Host::New(Instance &aInstance)
-{
-    void *buf;
-    Host *host = nullptr;
-
-    buf = Instance::HeapCAlloc(1, sizeof(Host));
-    VerifyOrExit(buf != nullptr);
-
-    host = new (buf) Host(aInstance);
-
-exit:
-    return host;
-}
-
-void Server::Host::Free(void)
-{
-    FreeAllServices();
-    mFullName.Free();
-    Instance::HeapFree(this);
-}
-
-Server::Host::Host(Instance &aInstance)
+Server::Host::Host(Instance &aInstance, TimeMilli aUpdateTime)
     : InstanceLocator(aInstance)
-    , mAddressesNum(0)
     , mNext(nullptr)
+    , mTtl(0)
     , mLease(0)
     , mKeyLease(0)
-    , mTimeLastUpdate(TimerMilli::GetNow())
+    , mUpdateTime(aUpdateTime)
 {
-    mKey.Clear();
+    mKeyRecord.Clear();
+}
+
+Server::Host::~Host(void)
+{
+    FreeAllServices();
 }
 
 Error Server::Host::SetFullName(const char *aFullName)
@@ -1725,23 +1873,60 @@
     return error;
 }
 
-void Server::Host::SetKey(Dns::Ecdsa256KeyRecord &aKey)
+bool Server::Host::Matches(const char *aFullName) const
 {
-    OT_ASSERT(aKey.IsValid());
+    return StringMatch(mFullName.AsCString(), aFullName, kStringCaseInsensitiveMatch);
+}
 
-    mKey = aKey;
+void Server::Host::SetKeyRecord(Dns::Ecdsa256KeyRecord &aKeyRecord)
+{
+    OT_ASSERT(aKeyRecord.IsValid());
+
+    mKeyRecord = aKeyRecord;
 }
 
 TimeMilli Server::Host::GetExpireTime(void) const
 {
     OT_ASSERT(!IsDeleted());
 
-    return mTimeLastUpdate + Time::SecToMsec(mLease);
+    return mUpdateTime + Time::SecToMsec(mLease);
 }
 
 TimeMilli Server::Host::GetKeyExpireTime(void) const
 {
-    return mTimeLastUpdate + Time::SecToMsec(mKeyLease);
+    return mUpdateTime + Time::SecToMsec(mKeyLease);
+}
+
+void Server::Host::GetLeaseInfo(LeaseInfo &aLeaseInfo) const
+{
+    TimeMilli now           = TimerMilli::GetNow();
+    TimeMilli expireTime    = GetExpireTime();
+    TimeMilli keyExpireTime = GetKeyExpireTime();
+
+    aLeaseInfo.mLease             = Time::SecToMsec(GetLease());
+    aLeaseInfo.mKeyLease          = Time::SecToMsec(GetKeyLease());
+    aLeaseInfo.mRemainingLease    = (now <= expireTime) ? (expireTime - now) : 0;
+    aLeaseInfo.mRemainingKeyLease = (now <= keyExpireTime) ? (keyExpireTime - now) : 0;
+}
+
+Error Server::Host::ProcessTtl(uint32_t aTtl)
+{
+    // This method processes the TTL value received in a resource record.
+    //
+    // If no TTL value is stored, this method wil set the stored value to @p aTtl and return `kErrorNone`.
+    // If a TTL value is stored and @p aTtl equals the stored value, this method returns `kErrorNone`.
+    // Otherwise, this method returns `kErrorRejected`.
+
+    Error error = kErrorRejected;
+
+    VerifyOrExit(aTtl && (mTtl == 0 || mTtl == aTtl));
+
+    mTtl = aTtl;
+
+    error = kErrorNone;
+
+exit:
+    return error;
 }
 
 const Server::Service *Server::Host::FindNextService(const Service *aPrevService,
@@ -1774,21 +1959,21 @@
     return service;
 }
 
-Server::Service *Server::Host::AddNewService(const char *aServiceName, const char *aInstanceName, bool aIsSubType)
+Server::Service *Server::Host::AddNewService(const char *aServiceName,
+                                             const char *aInstanceName,
+                                             bool        aIsSubType,
+                                             TimeMilli   aUpdateTime)
 {
-    Service *             service = nullptr;
-    Service::Description *desc;
-
-    desc = FindServiceDescription(aInstanceName);
+    Service *                       service = nullptr;
+    RetainPtr<Service::Description> desc(FindServiceDescription(aInstanceName));
 
     if (desc == nullptr)
     {
-        desc = Service::Description::New(aInstanceName, *this);
+        desc.Reset(Service::Description::AllocateAndInit(aInstanceName, *this));
         VerifyOrExit(desc != nullptr);
-        mServiceDescriptions.Push(*desc);
     }
 
-    service = Service::New(aServiceName, *desc, aIsSubType);
+    service = Service::AllocateAndInit(aServiceName, *desc, aIsSubType, aUpdateTime);
     VerifyOrExit(service != nullptr);
 
     mServices.Push(*service);
@@ -1797,7 +1982,7 @@
     return service;
 }
 
-void Server::Host::RemoveService(Service *aService, bool aRetainName, bool aNotifyServiceHandler)
+void Server::Host::RemoveService(Service *aService, RetainName aRetainName, NotifyMode aNotifyServiceHandler)
 {
     Server &server = Get<Server>();
 
@@ -1809,8 +1994,10 @@
 
     if (aNotifyServiceHandler && server.mServiceUpdateHandler != nullptr)
     {
-        server.mServiceUpdateHandler(server.AllocateId(), this, kDefaultEventsHandlerTimeout,
-                                     server.mServiceUpdateHandlerContext);
+        uint32_t updateId = server.AllocateId();
+
+        LogInfo("SRP update handler is notified (updatedId = %u)", updateId);
+        server.mServiceUpdateHandler(updateId, this, kDefaultEventsHandlerTimeout, server.mServiceUpdateHandlerContext);
         // We don't wait for the reply from the service update handler,
         // but always remove the service regardless of service update result.
         // Because removing a service should fail only when there is system
@@ -1822,50 +2009,42 @@
     {
         IgnoreError(mServices.Remove(*aService));
         aService->Free();
-        FreeUnusedServiceDescriptions();
     }
 
 exit:
     return;
 }
 
+Error Server::Host::AddCopyOfServiceAsDeletedIfNotPresent(const Service &aService, TimeMilli aUpdateTime)
+{
+    Error    error = kErrorNone;
+    Service *newService;
+
+    VerifyOrExit(FindService(aService.GetServiceName(), aService.GetInstanceName()) == nullptr);
+
+    newService =
+        AddNewService(aService.GetServiceName(), aService.GetInstanceName(), aService.IsSubType(), aUpdateTime);
+
+    VerifyOrExit(newService != nullptr, error = kErrorNoBufs);
+
+    newService->mDescription->mUpdateTime = aUpdateTime;
+    newService->mIsDeleted                = true;
+
+exit:
+    return error;
+}
+
 void Server::Host::FreeAllServices(void)
 {
     while (!mServices.IsEmpty())
     {
-        RemoveService(mServices.GetHead(), /* aRetainName */ false, /* aNotifyServiceHandler */ false);
-    }
-}
-
-void Server::Host::FreeUnusedServiceDescriptions(void)
-{
-    Service::Description *desc;
-    Service::Description *prev;
-    Service::Description *next;
-
-    for (prev = nullptr, desc = mServiceDescriptions.GetHead(); desc != nullptr; desc = next)
-    {
-        next = desc->GetNext();
-
-        if (FindNextService(/* aPrevService */ nullptr, kFlagsAnyService, /* aServiceName */ nullptr,
-                            desc->GetInstanceName()) == nullptr)
-        {
-            mServiceDescriptions.PopAfter(prev);
-            desc->Free();
-
-            // When the `desc` is removed from the list
-            // we keep the `prev` pointer same as before.
-        }
-        else
-        {
-            prev = desc;
-        }
+        RemoveService(mServices.GetHead(), kDeleteName, kDoNotNotifyServiceHandler);
     }
 }
 
 void Server::Host::ClearResources(void)
 {
-    mAddressesNum = 0;
+    mAddresses.Free();
 }
 
 Error Server::Host::MergeServicesAndResourcesFrom(Host &aHost)
@@ -1876,14 +2055,14 @@
 
     Error error = kErrorNone;
 
-    otLogInfoSrp("[server] update host %s", GetFullName());
+    LogInfo("Update host %s", GetFullName());
 
-    memcpy(mAddresses, aHost.mAddresses, aHost.mAddressesNum * sizeof(mAddresses[0]));
-    mAddressesNum   = aHost.mAddressesNum;
-    mKey            = aHost.mKey;
-    mLease          = aHost.mLease;
-    mKeyLease       = aHost.mKeyLease;
-    mTimeLastUpdate = TimerMilli::GetNow();
+    mAddresses.TakeFrom(static_cast<Heap::Array<Ip6::Address> &&>(aHost.mAddresses));
+    mKeyRecord  = aHost.mKeyRecord;
+    mTtl        = aHost.mTtl;
+    mLease      = aHost.mLease;
+    mKeyLease   = aHost.mKeyLease;
+    mUpdateTime = TimerMilli::GetNow();
 
     for (Service &service : aHost.mServices)
     {
@@ -1893,28 +2072,28 @@
         if (service.mIsDeleted)
         {
             // `RemoveService()` does nothing if `exitsingService` is `nullptr`.
-            RemoveService(existingService, /* aRetainName */ true, /* aNotifyServiceHandler */ false);
+            RemoveService(existingService, kRetainName, kDoNotNotifyServiceHandler);
             continue;
         }
 
         // Add/Merge `service` into the existing service or a allocate a new one
 
-        newService = (existingService != nullptr)
-                         ? existingService
-                         : AddNewService(service.GetServiceName(), service.GetInstanceName(), service.IsSubType());
+        newService = (existingService != nullptr) ? existingService
+                                                  : AddNewService(service.GetServiceName(), service.GetInstanceName(),
+                                                                  service.IsSubType(), service.GetUpdateTime());
 
         VerifyOrExit(newService != nullptr, error = kErrorNoBufs);
 
-        newService->mIsDeleted      = false;
-        newService->mIsCommitted    = true;
-        newService->mTimeLastUpdate = TimerMilli::GetNow();
+        newService->mIsDeleted   = false;
+        newService->mIsCommitted = true;
+        newService->mUpdateTime  = TimerMilli::GetNow();
 
         if (!service.mIsSubType)
         {
             // (1) Service description is shared across a base type and all its subtypes.
             // (2) `TakeResourcesFrom()` releases resources pinned to its argument.
             // Therefore, make sure the function is called only for the base type.
-            newService->mDescription.TakeResourcesFrom(service.mDescription);
+            newService->mDescription->TakeResourcesFrom(*service.mDescription);
         }
 
         newService->Log((existingService != nullptr) ? Service::kUpdateExisting : Service::kAddNew);
@@ -1924,12 +2103,28 @@
     return error;
 }
 
-const Server::Service::Description *Server::Host::FindServiceDescription(const char *aInstanceName) const
+bool Server::Host::HasServiceInstance(const char *aInstanceName) const
 {
-    return mServiceDescriptions.FindMatching(aInstanceName);
+    return (FindServiceDescription(aInstanceName) != nullptr);
 }
 
-Server::Service::Description *Server::Host::FindServiceDescription(const char *aInstanceName)
+const RetainPtr<Server::Service::Description> Server::Host::FindServiceDescription(const char *aInstanceName) const
+{
+    const Service::Description *desc = nullptr;
+
+    for (const Service &service : mServices)
+    {
+        if (service.mDescription->Matches(aInstanceName))
+        {
+            desc = service.mDescription.Get();
+            break;
+        }
+    }
+
+    return RetainPtr<Service::Description>(AsNonConst(desc));
+}
+
+RetainPtr<Server::Service::Description> Server::Host::FindServiceDescription(const char *aInstanceName)
 {
     return AsNonConst(AsConst(this)->FindServiceDescription(aInstanceName));
 }
@@ -1944,6 +2139,17 @@
     return AsNonConst(AsConst(this)->FindService(aServiceName, aInstanceName));
 }
 
+const Server::Service *Server::Host::FindBaseService(const char *aInstanceName) const
+{
+    return FindNextService(/*a PrevService */ nullptr, kFlagsBaseTypeServiceOnly, /* aServiceName */ nullptr,
+                           aInstanceName);
+}
+
+Server::Service *Server::Host::FindBaseService(const char *aInstanceName)
+{
+    return AsNonConst(AsConst(this)->FindBaseService(aInstanceName));
+}
+
 Error Server::Host::AddIp6Address(const Ip6::Address &aIp6Address)
 {
     Error error = kErrorNone;
@@ -1955,22 +2161,15 @@
         ExitNow(error = kErrorDrop);
     }
 
-    for (const Ip6::Address &addr : mAddresses)
-    {
-        if (aIp6Address == addr)
-        {
-            // Drop duplicate addresses.
-            ExitNow(error = kErrorDrop);
-        }
-    }
+    // Drop duplicate addresses.
+    VerifyOrExit(!mAddresses.Contains(aIp6Address), error = kErrorDrop);
 
-    if (mAddressesNum >= kMaxAddressesNum)
-    {
-        otLogWarnSrp("[server] too many addresses for host %s", GetFullName());
-        ExitNow(error = kErrorNoBufs);
-    }
+    error = mAddresses.PushBack(aIp6Address);
 
-    mAddresses[mAddressesNum++] = aIp6Address;
+    if (error == kErrorNoBufs)
+    {
+        LogWarn("Too many addresses for host %s", GetFullName());
+    }
 
 exit:
     return error;
@@ -1979,40 +2178,21 @@
 //---------------------------------------------------------------------------------------------------------------------
 // Server::UpdateMetadata
 
-Server::UpdateMetadata *Server::UpdateMetadata::New(Instance &               aInstance,
-                                                    const Dns::UpdateHeader &aHeader,
-                                                    Host *                   aHost,
-                                                    const Ip6::MessageInfo & aMessageInfo)
-{
-    void *          buf;
-    UpdateMetadata *update = nullptr;
-
-    buf = Instance::HeapCAlloc(1, sizeof(UpdateMetadata));
-    VerifyOrExit(buf != nullptr);
-
-    update = new (buf) UpdateMetadata(aInstance, aHeader, aHost, aMessageInfo);
-
-exit:
-    return update;
-}
-
-void Server::UpdateMetadata::Free(void)
-{
-    Instance::HeapFree(this);
-}
-
-Server::UpdateMetadata::UpdateMetadata(Instance &               aInstance,
-                                       const Dns::UpdateHeader &aHeader,
-                                       Host *                   aHost,
-                                       const Ip6::MessageInfo & aMessageInfo)
+Server::UpdateMetadata::UpdateMetadata(Instance &aInstance, Host &aHost, const MessageMetadata &aMessageMetadata)
     : InstanceLocator(aInstance)
-    , mExpireTime(TimerMilli::GetNow() + kDefaultEventsHandlerTimeout)
-    , mDnsHeader(aHeader)
-    , mId(Get<Server>().AllocateId())
-    , mHost(aHost)
-    , mMessageInfo(aMessageInfo)
     , mNext(nullptr)
+    , mExpireTime(TimerMilli::GetNow() + kDefaultEventsHandlerTimeout)
+    , mDnsHeader(aMessageMetadata.mDnsHeader)
+    , mId(Get<Server>().AllocateId())
+    , mTtlConfig(aMessageMetadata.mTtlConfig)
+    , mLeaseConfig(aMessageMetadata.mLeaseConfig)
+    , mHost(aHost)
+    , mIsDirectRxFromClient(aMessageMetadata.IsDirectRxFromClient())
 {
+    if (aMessageMetadata.mMessageInfo != nullptr)
+    {
+        mMessageInfo = *aMessageMetadata.mMessageInfo;
+    }
 }
 
 } // namespace Srp
diff --git a/src/core/net/srp_server.hpp b/src/core/net/srp_server.hpp
index f82cc42..b2c3716 100644
--- a/src/core/net/srp_server.hpp
+++ b/src/core/net/srp_server.hpp
@@ -53,12 +53,20 @@
 #include <openthread/ip6.h>
 #include <openthread/srp_server.h>
 
+#include "common/array.hpp"
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
+#include "common/heap.hpp"
+#include "common/heap_allocatable.hpp"
+#include "common/heap_array.hpp"
+#include "common/heap_data.hpp"
 #include "common/heap_string.hpp"
 #include "common/linked_list.hpp"
 #include "common/locator.hpp"
 #include "common/non_copyable.hpp"
 #include "common/notifier.hpp"
+#include "common/numeric_limits.hpp"
+#include "common/retain_ptr.hpp"
 #include "common/timer.hpp"
 #include "crypto/ecdsa.hpp"
 #include "net/dns_types.hpp"
@@ -97,6 +105,18 @@
     friend class Host;
     friend class Dns::ServiceDiscovery::Server;
 
+    enum RetainName : bool
+    {
+        kDeleteName = false,
+        kRetainName = true,
+    };
+
+    enum NotifyMode : bool
+    {
+        kDoNotNotifyServiceHandler = false,
+        kNotifyServiceHandler      = true,
+    };
+
 public:
     static constexpr uint16_t kUdpPortMin = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MIN; ///< The reserved min port.
     static constexpr uint16_t kUdpPortMax = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MAX; ///< The reserved max port.
@@ -110,6 +130,12 @@
     typedef otSrpServerServiceUpdateId ServiceUpdateId;
 
     /**
+     * The SRP server lease information of a host/service.
+     *
+     */
+    typedef otSrpServerLeaseInfo LeaseInfo;
+
+    /**
      * This enumeration represents the address mode used by the SRP server.
      *
      * Address mode specifies how the address and port number are determined by the SRP server and how this info ins
@@ -135,11 +161,15 @@
      * This class implements a server-side SRP service.
      *
      */
-    class Service : public otSrpServerService, public LinkedListEntry<Service>, private NonCopyable
+    class Service : public otSrpServerService,
+                    public LinkedListEntry<Service>,
+                    private Heap::Allocatable<Service>,
+                    private NonCopyable
     {
         friend class Server;
         friend class LinkedList<Service>;
         friend class LinkedListEntry<Service>;
+        friend class Heap::Allocatable<Service>;
 
     public:
         /**
@@ -200,7 +230,7 @@
          * @returns  A pointer service instance name (as a null-terminated C string).
          *
          */
-        const char *GetInstanceName(void) const { return mDescription.mInstanceName.AsCString(); }
+        const char *GetInstanceName(void) const { return mDescription->mInstanceName.AsCString(); }
 
         /**
          * This method gets the full service name of the service.
@@ -230,12 +260,20 @@
         Error GetServiceSubTypeLabel(char *aLabel, uint8_t aMaxSize) const;
 
         /**
+         * This method returns the TTL of the service instance.
+         *
+         * @returns The TTL of the service instance.
+         *
+         */
+        uint32_t GetTtl(void) const { return mDescription->mTtl; }
+
+        /**
          * This method returns the port of the service instance.
          *
          * @returns  The port of the service.
          *
          */
-        uint16_t GetPort(void) const { return mDescription.mPort; }
+        uint16_t GetPort(void) const { return mDescription->mPort; }
 
         /**
          * This method returns the weight of the service instance.
@@ -243,17 +281,15 @@
          * @returns  The weight of the service.
          *
          */
-        uint16_t GetWeight(void) const { return mDescription.mWeight; }
+        uint16_t GetWeight(void) const { return mDescription->mWeight; }
 
         /**
          * This method returns the priority of the service instance.
          *
-         * @param[in]  aService  A pointer to the SRP service.
-         *
          * @returns  The priority of the service.
          *
          */
-        uint16_t GetPriority(void) const { return mDescription.mPriority; }
+        uint16_t GetPriority(void) const { return mDescription->mPriority; }
 
         /**
          * This method returns the TXT record data of the service instance.
@@ -261,7 +297,7 @@
          * @returns A pointer to the buffer containing the TXT record data.
          *
          */
-        const uint8_t *GetTxtData(void) const { return mDescription.mTxtData; }
+        const uint8_t *GetTxtData(void) const { return mDescription->mTxtData.GetBytes(); }
 
         /**
          * This method returns the TXT record data length of the service instance.
@@ -269,7 +305,7 @@
          * @return The TXT record data length (number of bytes in buffer returned from `GetTxtData()`).
          *
          */
-        uint16_t GetTxtDataLength(void) const { return mDescription.mTxtLength; }
+        uint16_t GetTxtDataLength(void) const { return mDescription->mTxtData.GetLength(); }
 
         /**
          * This method returns the host which the service instance reside on.
@@ -277,7 +313,23 @@
          * @returns  A reference to the host instance.
          *
          */
-        const Host &GetHost(void) const { return mDescription.mHost; }
+        const Host &GetHost(void) const { return *mDescription->mHost; }
+
+        /**
+         * This method returns the LEASE time of the service.
+         *
+         * @returns  The LEASE time in seconds.
+         *
+         */
+        uint32_t GetLease(void) const { return mDescription->mLease; }
+
+        /**
+         * This method returns the KEY-LEASE time of the key of the service.
+         *
+         * @returns  The KEY-LEASE time in seconds.
+         *
+         */
+        uint32_t GetKeyLease(void) const { return mDescription->mKeyLease; }
 
         /**
          * This method returns the expire time (in milliseconds) of the service.
@@ -296,6 +348,15 @@
         TimeMilli GetKeyExpireTime(void) const;
 
         /**
+         * This method gets the LEASE and KEY-LEASE information of a given service.
+         *
+         * @param[out]  aLeaseInfo  A reference to a LeaseInfo instance. It contains the LEASE time, KEY-LEASE time,
+         *                          remaining LEASE time and the remaining KEY-LEASE time.
+         *
+         */
+        void GetLeaseInfo(LeaseInfo &aLeaseInfo) const;
+
+        /**
          * This method indicates whether this service matches a given service instance name.
          *
          * @param[in]  aInstanceName  The service instance name.
@@ -304,10 +365,7 @@
          * @retval  FALSE  If the service does not match the service instance name.
          *
          */
-        bool MatchesInstanceName(const char *aInstanceName) const
-        {
-            return (mDescription.mInstanceName == aInstanceName);
-        }
+        bool MatchesInstanceName(const char *aInstanceName) const;
 
         /**
          * This method tells whether this service matches a given service name.
@@ -318,32 +376,32 @@
          * @retval  FALSE  If the service does not match the full service name.
          *
          */
-        bool MatchesServiceName(const char *aServiceName) const { return (mServiceName == aServiceName); }
+        bool MatchesServiceName(const char *aServiceName) const;
 
     private:
-        struct Description : public LinkedListEntry<Description>, private NonCopyable
+        struct Description : public LinkedListEntry<Description>,
+                             public Heap::Allocatable<Description>,
+                             public RetainCountable,
+                             private NonCopyable
         {
-            static Description *New(const char *aInstanceName, Host &aHost);
-
-            explicit Description(Host &aHost);
-            void        Free(void);
+            Error       Init(const char *aInstanceName, Host &aHost);
             const char *GetInstanceName(void) const { return mInstanceName.AsCString(); }
-            bool        Matches(const char *aInstanceName) const { return (mInstanceName == aInstanceName); }
+            bool        Matches(const char *aInstanceName) const;
             void        ClearResources(void);
             void        TakeResourcesFrom(Description &aDescription);
             Error       SetTxtDataFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
 
             Description *mNext;
-            HeapString   mInstanceName;
-            Host &       mHost;
+            Heap::String mInstanceName;
+            Host *       mHost;
+            Heap::Data   mTxtData;
             uint16_t     mPriority;
             uint16_t     mWeight;
             uint16_t     mPort;
-            uint16_t     mTxtLength;
-            uint8_t *    mTxtData;
+            uint32_t     mTtl;      // The TTL in seconds.
             uint32_t     mLease;    // The LEASE time in seconds.
             uint32_t     mKeyLease; // The KEY-LEASE time in seconds.
-            TimeMilli    mTimeLastUpdate;
+            TimeMilli    mUpdateTime;
         };
 
         enum Action : uint8_t
@@ -356,31 +414,33 @@
             kKeyLeaseExpired,
         };
 
-        static Service *New(const char *aServiceName, Description &aDescription, bool aIsSubType);
+        Error Init(const char *aServiceName, Description &aDescription, bool aIsSubType, TimeMilli aUpdateTime);
+        bool  MatchesFlags(Flags aFlags) const;
+        const TimeMilli &GetUpdateTime(void) const { return mUpdateTime; }
+        void             Log(Action aAction) const;
 
-        Service(Description &aDescription, bool aIsSubType);
-
-        void Free(void);
-        bool MatchesFlags(Flags aFlags) const;
-        void Log(Action aAction) const;
-
-        HeapString   mServiceName;
-        Description &mDescription;
-        Service *    mNext;
-        TimeMilli    mTimeLastUpdate;
-        bool         mIsDeleted : 1;
-        bool         mIsSubType : 1;
-        bool         mIsCommitted : 1;
+        Heap::String           mServiceName;
+        RetainPtr<Description> mDescription;
+        Service *              mNext;
+        TimeMilli              mUpdateTime;
+        bool                   mIsDeleted : 1;
+        bool                   mIsSubType : 1;
+        bool                   mIsCommitted : 1;
     };
 
     /**
      * This class implements the Host which registers services on the SRP server.
      *
      */
-    class Host : public otSrpServerHost, public LinkedListEntry<Host>, public InstanceLocator, private NonCopyable
+    class Host : public otSrpServerHost,
+                 public InstanceLocator,
+                 public LinkedListEntry<Host>,
+                 private Heap::Allocatable<Host>,
+                 private NonCopyable
     {
-        friend class LinkedListEntry<Host>;
         friend class Server;
+        friend class LinkedListEntry<Host>;
+        friend class Heap::Allocatable<Host>;
 
     public:
         /**
@@ -407,16 +467,24 @@
          *
          * @param[out]  aAddressesNum  The number of the addresses.
          *
-         * @returns  A pointer to the addresses array.
+         * @returns  A pointer to the addresses array or `nullptr` if no addresses.
          *
          */
         const Ip6::Address *GetAddresses(uint8_t &aAddressesNum) const
         {
-            aAddressesNum = mAddressesNum;
-            return mAddresses;
+            aAddressesNum = static_cast<uint8_t>(OT_MIN(mAddresses.GetLength(), NumericLimits<uint8_t>::kMax));
+            return mAddresses.AsCArray();
         }
 
         /**
+         * This method returns the TTL of the host.
+         *
+         * @returns The TTL of the host.
+         *
+         */
+        uint32_t GetTtl(void) const { return mTtl; }
+
+        /**
          * This method returns the LEASE time of the host.
          *
          * @returns  The LEASE time in seconds.
@@ -433,13 +501,22 @@
         uint32_t GetKeyLease(void) const { return mKeyLease; }
 
         /**
-         * This method returns the KEY resource of the host.
+         * This method gets the LEASE and KEY-LEASE information of a given host.
          *
-         * @returns  A pointer to the ECDSA P 256 public key if there is valid one.
-         *           nullptr if no valid key exists.
+         * @param[out]  aLeaseInfo  A reference to a LeaseInfo instance. It contains the LEASE time, KEY-LEASE time,
+         *                          remaining LEASE time and the remaining KEY-LEASE time.
          *
          */
-        const Dns::Ecdsa256KeyRecord *GetKey(void) const { return mKey.IsValid() ? &mKey : nullptr; }
+        void GetLeaseInfo(LeaseInfo &aLeaseInfo) const;
+
+        /**
+         * This method returns the KEY resource record of the host.
+         *
+         * @returns  A pointer to the ECDSA P 256 public key resource record
+         *           if there is valid one. `nullptr` if no valid key exists.
+         *
+         */
+        const Dns::Ecdsa256KeyRecord *GetKeyRecord(void) const { return mKeyRecord.IsValid() ? &mKeyRecord : nullptr; }
 
         /**
          * This method returns the expire time (in milliseconds) of the host.
@@ -489,43 +566,70 @@
          * @returns  A boolean that indicates whether the host matches the given name.
          *
          */
-        bool Matches(const char *aFullName) const { return (mFullName == aFullName); }
+        bool Matches(const char *aFullName) const;
 
     private:
-        static constexpr uint16_t kMaxAddressesNum = OPENTHREAD_CONFIG_SRP_SERVER_MAX_ADDRESSES_NUM;
+        Host(Instance &aInstance, TimeMilli aUpdateTime);
+        ~Host(void);
 
-        static Host *New(Instance &aInstance);
+        Error SetFullName(const char *aFullName);
+        void  SetKeyRecord(Dns::Ecdsa256KeyRecord &aKeyRecord);
+        void  SetTtl(uint32_t aTtl) { mTtl = aTtl; }
+        void  SetLease(uint32_t aLease) { mLease = aLease; }
+        void  SetKeyLease(uint32_t aKeyLease) { mKeyLease = aKeyLease; }
+        Error ProcessTtl(uint32_t aTtl);
 
-        explicit Host(Instance &aInstance);
-        void                        Free(void);
-        Error                       SetFullName(const char *aFullName);
-        void                        SetKey(Dns::Ecdsa256KeyRecord &aKey);
-        void                        SetLease(uint32_t aLease) { mLease = aLease; }
-        void                        SetKeyLease(uint32_t aKeyLease) { mKeyLease = aKeyLease; }
-        LinkedList<Service> &       GetServices(void) { return mServices; }
-        Service *                   AddNewService(const char *aServiceName, const char *aInstanceName, bool aIsSubType);
-        void                        RemoveService(Service *aService, bool aRetainName, bool aNotifyServiceHandler);
-        void                        FreeAllServices(void);
-        void                        FreeUnusedServiceDescriptions(void);
-        void                        ClearResources(void);
-        Error                       MergeServicesAndResourcesFrom(Host &aHost);
-        Error                       AddIp6Address(const Ip6::Address &aIp6Address);
-        Service::Description *      FindServiceDescription(const char *aInstanceName);
-        const Service::Description *FindServiceDescription(const char *aInstanceName) const;
-        Service *                   FindService(const char *aServiceName, const char *aInstanceName);
-        const Service *             FindService(const char *aServiceName, const char *aInstanceName) const;
+        LinkedList<Service> &GetServices(void) { return mServices; }
+        Service *            AddNewService(const char *aServiceName,
+                                           const char *aInstanceName,
+                                           bool        aIsSubType,
+                                           TimeMilli   aUpdateTime);
+        void                 RemoveService(Service *aService, RetainName aRetainName, NotifyMode aNotifyServiceHandler);
+        Error                AddCopyOfServiceAsDeletedIfNotPresent(const Service &aService, TimeMilli aUpdateTime);
+        void                 FreeAllServices(void);
+        void                 ClearResources(void);
+        Error                MergeServicesAndResourcesFrom(Host &aHost);
+        Error                AddIp6Address(const Ip6::Address &aIp6Address);
+        bool                 HasServiceInstance(const char *aInstanceName) const;
+        RetainPtr<Service::Description>       FindServiceDescription(const char *aInstanceName);
+        const RetainPtr<Service::Description> FindServiceDescription(const char *aInstanceName) const;
+        Service *                             FindService(const char *aServiceName, const char *aInstanceName);
+        const Service *                       FindService(const char *aServiceName, const char *aInstanceName) const;
+        Service *                             FindBaseService(const char *aInstanceName);
+        const Service *                       FindBaseService(const char *aInstanceName) const;
 
-        HeapString   mFullName;
-        Ip6::Address mAddresses[kMaxAddressesNum];
-        uint8_t      mAddressesNum;
-        Host *       mNext;
+        Host *                    mNext;
+        Heap::String              mFullName;
+        Heap::Array<Ip6::Address> mAddresses;
 
-        Dns::Ecdsa256KeyRecord           mKey;
-        uint32_t                         mLease;    // The LEASE time in seconds.
-        uint32_t                         mKeyLease; // The KEY-LEASE time in seconds.
-        TimeMilli                        mTimeLastUpdate;
-        LinkedList<Service>              mServices;
-        LinkedList<Service::Description> mServiceDescriptions;
+        // TODO(wgtdkp): there is no necessary to save the entire resource
+        // record, saving only the ECDSA-256 public key should be enough.
+        Dns::Ecdsa256KeyRecord mKeyRecord;
+        uint32_t               mTtl;      // The TTL in seconds.
+        uint32_t               mLease;    // The LEASE time in seconds.
+        uint32_t               mKeyLease; // The KEY-LEASE time in seconds.
+        TimeMilli              mUpdateTime;
+        LinkedList<Service>    mServices;
+    };
+
+    /**
+     * This class handles TTL configuration.
+     *
+     */
+    class TtlConfig : public otSrpServerTtlConfig
+    {
+        friend class Server;
+
+    public:
+        /**
+         * This constructor initializes to default TTL configuration.
+         *
+         */
+        TtlConfig(void);
+
+    private:
+        bool     IsValid(void) const { return mMinTtl <= mMaxTtl; }
+        uint32_t GrantTtl(uint32_t aLease, uint32_t aTtl) const;
     };
 
     /**
@@ -618,7 +722,7 @@
      * A trailing dot will be appended to @p aDomain if it is not already there.
      * This method should only be called before the SRP server is enabled.
      *
-     * @param[in]  aDomain  The domain to be set. MUST NOT be nullptr.
+     * @param[in]  aDomain  The domain to be set. MUST NOT be `nullptr`.
      *
      * @retval  kErrorNone          Successfully set the domain to @p aDomain.
      * @retval  kErrorInvalidState  The SRP server is already enabled and the Domain cannot be changed.
@@ -685,6 +789,14 @@
     State GetState(void) const { return mState; }
 
     /**
+     * This method tells the port the SRP server is listening to.
+     *
+     * @returns  An integer that represents the port of the server. It returns 0 if the SRP server is not running.
+     *
+     */
+    uint16_t GetPort(void) const { return IsRunning() ? mPort : 0; }
+
+    /**
      * This method enables/disables the SRP server.
      *
      * @param[in]  aEnabled  A boolean to enable/disable the SRP server.
@@ -693,6 +805,25 @@
     void SetEnabled(bool aEnabled);
 
     /**
+     * This method returns the TTL configuration.
+     *
+     * @param[out]  aTtlConfig  A reference to the `TtlConfig` instance.
+     *
+     */
+    void GetTtlConfig(TtlConfig &aTtlConfig) const { aTtlConfig = mTtlConfig; }
+
+    /**
+     * This method sets the TTL configuration.
+     *
+     * @param[in]  aTtlConfig  A reference to the `TtlConfig` instance.
+     *
+     * @retval  kErrorNone         Successfully set the TTL configuration
+     * @retval  kErrorInvalidArgs  The TTL range is not valid.
+     *
+     */
+    Error SetTtlConfig(const TtlConfig &aTtlConfig);
+
+    /**
      * This method returns the LEASE and KEY-LEASE configurations.
      *
      * @param[out]  aLeaseConfig  A reference to the `LeaseConfig` instance.
@@ -718,14 +849,22 @@
     /**
      * This method returns the next registered SRP host.
      *
-     * @param[in]  aHost  The current SRP host; use nullptr to get the first SRP host.
+     * @param[in]  aHost  The current SRP host; use `nullptr` to get the first SRP host.
      *
-     * @returns  A pointer to the next SRP host or nullptr if no more SRP hosts can be found.
+     * @returns  A pointer to the next SRP host or `nullptr` if no more SRP hosts can be found.
      *
      */
     const Host *GetNextHost(const Host *aHost);
 
     /**
+     * This method returns the response counters of the SRP server.
+     *
+     * @returns  A pointer to the response counters of the SRP server.
+     *
+     */
+    const otSrpServerResponseCounters *GetResponseCounters(void) const { return &mResponseCounters; }
+
+    /**
      * This method receives the service update result from service handler set by
      * SetServiceHandler.
      *
@@ -736,8 +875,10 @@
     void HandleServiceUpdateResult(ServiceUpdateId aId, Error aError);
 
 private:
-    static constexpr uint16_t kUdpPayloadSize = Ip6::Ip6::kMaxDatagramLength - sizeof(Ip6::Udp::Header);
+    static constexpr uint16_t kUdpPayloadSize = Ip6::kMaxDatagramLength - sizeof(Ip6::Udp::Header);
 
+    static constexpr uint32_t kDefaultMinTtl               = 60u;             // 1 min (in seconds).
+    static constexpr uint32_t kDefaultMaxTtl               = 3600u * 2;       // 2 hours (in seconds).
     static constexpr uint32_t kDefaultMinLease             = 60u * 30;        // 30 min (in seconds).
     static constexpr uint32_t kDefaultMaxLease             = 3600u * 2;       // 2 hours (in seconds).
     static constexpr uint32_t kDefaultMinKeyLease          = 3600u * 24;      // 1 day (in seconds).
@@ -749,37 +890,54 @@
 
     static constexpr uint16_t kAnycastAddressModePort = 53;
 
+    // Metdata for a received SRP Update message.
+    struct MessageMetadata
+    {
+        // Indicates whether the `Message` is received directly from a
+        // client or from an SRPL partner.
+        bool IsDirectRxFromClient(void) const { return (mMessageInfo != nullptr); }
+
+        Dns::UpdateHeader       mDnsHeader;
+        Dns::Zone               mDnsZone;
+        uint16_t                mOffset;
+        TimeMilli               mRxTime;
+        TtlConfig               mTtlConfig;
+        LeaseConfig             mLeaseConfig;
+        const Ip6::MessageInfo *mMessageInfo; // Set to `nullptr` when from SRPL.
+    };
+
     // This class includes metadata for processing a SRP update (register, deregister)
     // and sending DNS response to the client.
-    class UpdateMetadata : public InstanceLocator, public LinkedListEntry<UpdateMetadata>
+    class UpdateMetadata : public InstanceLocator,
+                           public LinkedListEntry<UpdateMetadata>,
+                           public Heap::Allocatable<UpdateMetadata>
     {
         friend class LinkedListEntry<UpdateMetadata>;
+        friend class Heap::Allocatable<UpdateMetadata>;
 
     public:
-        static UpdateMetadata *  New(Instance &               aInstance,
-                                     const Dns::UpdateHeader &aHeader,
-                                     Host *                   aHost,
-                                     const Ip6::MessageInfo & aMessageInfo);
-        void                     Free(void);
         TimeMilli                GetExpireTime(void) const { return mExpireTime; }
         const Dns::UpdateHeader &GetDnsHeader(void) const { return mDnsHeader; }
         ServiceUpdateId          GetId(void) const { return mId; }
-        Host &                   GetHost(void) { return *mHost; }
+        const TtlConfig &        GetTtlConfig(void) const { return mTtlConfig; }
+        const LeaseConfig &      GetLeaseConfig(void) const { return mLeaseConfig; }
+        Host &                   GetHost(void) { return mHost; }
         const Ip6::MessageInfo & GetMessageInfo(void) const { return mMessageInfo; }
+        bool                     IsDirectRxFromClient(void) const { return mIsDirectRxFromClient; }
         bool                     Matches(ServiceUpdateId aId) const { return mId == aId; }
 
     private:
-        UpdateMetadata(Instance &               aInstance,
-                       const Dns::UpdateHeader &aHeader,
-                       Host *                   aHost,
-                       const Ip6::MessageInfo & aMessageInfo);
+        UpdateMetadata(Instance &aInstance, Host &aHost, const MessageMetadata &aMessageMetadata);
 
+        UpdateMetadata *  mNext;
         TimeMilli         mExpireTime;
         Dns::UpdateHeader mDnsHeader;
         ServiceUpdateId   mId;          // The ID of this service update transaction.
-        Host *            mHost;        // The host will be updated. The UpdateMetadata has no ownership of this host.
-        Ip6::MessageInfo  mMessageInfo; // The message info of the DNS update request.
-        UpdateMetadata *  mNext;
+        TtlConfig         mTtlConfig;   // TTL config to use when processing the message.
+        LeaseConfig       mLeaseConfig; // Lease config to use when processing the message.
+        Host &            mHost;        // The `UpdateMetadata` has no ownership of this host.
+        Ip6::MessageInfo  mMessageInfo; // Valid when `mIsDirectRxFromClient` is true.
+        bool              mIsDirectRxFromClient;
     };
 
     void              Start(void);
@@ -797,56 +955,46 @@
 
     ServiceUpdateId AllocateId(void) { return mServiceUpdateId++; }
 
+    void  InformUpdateHandlerOrCommit(Error aError, Host &aHost, const MessageMetadata &aMetadata);
+    void  CommitSrpUpdate(Error aError, Host &aHost, const MessageMetadata &aMessageMetadata);
+    void  CommitSrpUpdate(Error aError, UpdateMetadata &aUpdateMetadata);
     void  CommitSrpUpdate(Error                    aError,
-                          const Dns::UpdateHeader &aDnsHeader,
                           Host &                   aHost,
-                          const Ip6::MessageInfo & aMessageInfo);
+                          const Dns::UpdateHeader &aDnsHeader,
+                          const Ip6::MessageInfo * aMessageInfo,
+                          const TtlConfig &        aTtlConfig,
+                          const LeaseConfig &      aLeaseConfig);
     Error ProcessMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
-    void  ProcessDnsUpdate(Message &                aMessage,
-                           const Ip6::MessageInfo & aMessageInfo,
-                           const Dns::UpdateHeader &aDnsHeader,
-                           uint16_t                 aOffset);
-    Error ProcessUpdateSection(Host &                   aHost,
-                               const Message &          aMessage,
-                               const Dns::UpdateHeader &aDnsHeader,
-                               const Dns::Zone &        aZone,
-                               uint16_t &               aOffset) const;
-    Error ProcessAdditionalSection(Host *                   aHost,
-                                   const Message &          aMessage,
-                                   const Dns::UpdateHeader &aDnsHeader,
-                                   uint16_t &               aOffset) const;
-    Error VerifySignature(const Dns::Ecdsa256KeyRecord &aKey,
+    Error ProcessMessage(Message &               aMessage,
+                         TimeMilli               aRxTime,
+                         const TtlConfig &       aTtlConfig,
+                         const LeaseConfig &     aLeaseConfig,
+                         const Ip6::MessageInfo *aMessageInfo);
+    void  ProcessDnsUpdate(Message &aMessage, MessageMetadata &aMetadata);
+    Error ProcessUpdateSection(Host &aHost, const Message &aMessage, MessageMetadata &aMetadata) const;
+    Error ProcessAdditionalSection(Host *aHost, const Message &aMessage, MessageMetadata &aMetadata) const;
+    Error VerifySignature(const Dns::Ecdsa256KeyRecord &aKeyRecord,
                           const Message &               aMessage,
                           Dns::UpdateHeader             aDnsHeader,
                           uint16_t                      aSigOffset,
                           uint16_t                      aSigRdataOffset,
                           uint16_t                      aSigRdataLength,
                           const char *                  aSignerName) const;
-    Error ProcessZoneSection(const Message &          aMessage,
-                             const Dns::UpdateHeader &aDnsHeader,
-                             uint16_t &               aOffset,
-                             Dns::Zone &              aZone) const;
-    Error ProcessHostDescriptionInstruction(Host &                   aHost,
-                                            const Message &          aMessage,
-                                            const Dns::UpdateHeader &aDnsHeader,
-                                            const Dns::Zone &        aZone,
-                                            uint16_t                 aOffset) const;
-    Error ProcessServiceDiscoveryInstructions(Host &                   aHost,
-                                              const Message &          aMessage,
-                                              const Dns::UpdateHeader &aDnsHeader,
-                                              const Dns::Zone &        aZone,
-                                              uint16_t                 aOffset) const;
-    Error ProcessServiceDescriptionInstructions(Host &                   aHost,
-                                                const Message &          aMessage,
-                                                const Dns::UpdateHeader &aDnsHeader,
-                                                const Dns::Zone &        aZone,
-                                                uint16_t &               aOffset) const;
+    Error ValidateServiceSubTypes(Host &aHost, const MessageMetadata &aMetadata);
+    Error ProcessZoneSection(const Message &aMessage, MessageMetadata &aMetadata) const;
+    Error ProcessHostDescriptionInstruction(Host &                 aHost,
+                                            const Message &        aMessage,
+                                            const MessageMetadata &aMetadata) const;
+    Error ProcessServiceDiscoveryInstructions(Host &                 aHost,
+                                              const Message &        aMessage,
+                                              const MessageMetadata &aMetadata) const;
+    Error ProcessServiceDescriptionInstructions(Host &aHost, const Message &aMessage, MessageMetadata &aMetadata) const;
 
     static bool IsValidDeleteAllRecord(const Dns::ResourceRecord &aRecord);
 
-    void        HandleUpdate(const Dns::UpdateHeader &aDnsHeader, Host &aHost, const Ip6::MessageInfo &aMessageInfo);
+    void        HandleUpdate(Host &aHost, const MessageMetadata &aMetadata);
     void        AddHost(Host &aHost);
-    void        RemoveHost(Host *aHost, bool aRetainName, bool aNotifyServiceHandler);
+    void        RemoveHost(Host *aHost, RetainName aRetainName, NotifyMode aNotifyServiceHandler);
     bool        HasNameConflictsWith(Host &aHost) const;
     void        SendResponse(const Dns::UpdateHeader &   aHeader,
                              Dns::UpdateHeader::Response aResponseCode,
@@ -863,15 +1011,18 @@
     void        HandleOutstandingUpdatesTimer(void);
 
     void                  HandleServiceUpdateResult(UpdateMetadata *aUpdate, Error aError);
-    const UpdateMetadata *FindOutstandingUpdate(const Ip6::MessageInfo &aMessageInfo, uint16_t aDnsMessageId);
+    const UpdateMetadata *FindOutstandingUpdate(const MessageMetadata &aMessageMetadata) const;
     static const char *   AddressModeToString(AddressMode aMode);
 
+    void UpdateResponseCounters(Dns::Header::Response aResponseCode);
+
     Ip6::Udp::Socket                mSocket;
     otSrpServerServiceUpdateHandler mServiceUpdateHandler;
     void *                          mServiceUpdateHandlerContext;
 
-    HeapString mDomain;
+    Heap::String mDomain;
 
+    TtlConfig   mTtlConfig;
     LeaseConfig mLeaseConfig;
 
     LinkedList<Host> mHosts;
@@ -886,9 +1037,19 @@
     AddressMode     mAddressMode;
     uint8_t         mAnycastSequenceNumber;
     bool            mHasRegisteredAnyService : 1;
+
+    otSrpServerResponseCounters mResponseCounters;
 };
 
 } // namespace Srp
+
+DefineCoreType(otSrpServerTtlConfig, Srp::Server::TtlConfig);
+DefineCoreType(otSrpServerLeaseConfig, Srp::Server::LeaseConfig);
+DefineCoreType(otSrpServerHost, Srp::Server::Host);
+DefineCoreType(otSrpServerService, Srp::Server::Service);
+DefineMapEnum(otSrpServerState, Srp::Server::State);
+DefineMapEnum(otSrpServerAddressMode, Srp::Server::AddressMode);
+
 } // namespace ot
 
 #endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
diff --git a/src/core/net/tcp6.cpp b/src/core/net/tcp6.cpp
index 9ef8be4..9b18a06 100644
--- a/src/core/net/tcp6.cpp
+++ b/src/core/net/tcp6.cpp
@@ -41,94 +41,194 @@
 #include "common/code_utils.hpp"
 #include "common/error.hpp"
 #include "common/instance.hpp"
-#include "common/logging.hpp"
+#include "common/locator_getters.hpp"
+#include "common/log.hpp"
+#include "common/random.hpp"
+#include "net/checksum.hpp"
 #include "net/ip6.hpp"
+#include "net/netif.hpp"
+
+#include "../../third_party/tcplp/tcplp.h"
 
 namespace ot {
 namespace Ip6 {
 
+using ot::Encoding::BigEndian::HostSwap16;
+using ot::Encoding::BigEndian::HostSwap32;
+
+RegisterLogModule("Tcp");
+
+static_assert(sizeof(struct tcpcb) == sizeof(Tcp::Endpoint::mTcb), "mTcb field in otTcpEndpoint is sized incorrectly");
+static_assert(alignof(struct tcpcb) == alignof(decltype(Tcp::Endpoint::mTcb)),
+              "mTcb field in otTcpEndpoint is aligned incorrectly");
+static_assert(offsetof(Tcp::Endpoint, mTcb) == 0, "mTcb field in otTcpEndpoint has nonzero offset");
+
+static_assert(sizeof(struct tcpcb_listen) == sizeof(Tcp::Listener::mTcbListen),
+              "mTcbListen field in otTcpListener is sized incorrectly");
+static_assert(alignof(struct tcpcb_listen) == alignof(decltype(Tcp::Listener::mTcbListen)),
+              "mTcbListen field in otTcpListener is aligned incorrectly");
+static_assert(offsetof(Tcp::Listener, mTcbListen) == 0, "mTcbListen field in otTcpEndpoint has nonzero offset");
+
 Tcp::Tcp(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mTimer(aInstance, Tcp::HandleTimer)
+    , mTasklet(aInstance, Tcp::HandleTasklet)
     , mEphemeralPort(kDynamicPortMin)
 {
     OT_UNUSED_VARIABLE(mEphemeralPort);
 }
 
-Error Tcp::Endpoint::Initialize(Instance &aInstance, otTcpEndpointInitializeArgs &aArgs)
+Error Tcp::Endpoint::Initialize(Instance &aInstance, const otTcpEndpointInitializeArgs &aArgs)
 {
-    Error error;
+    Error         error;
+    struct tcpcb &tp = GetTcb();
+
+    memset(&tp, 0x00, sizeof(tp));
 
     SuccessOrExit(error = aInstance.Get<Tcp>().mEndpoints.Add(*this));
 
     mContext                  = aArgs.mContext;
     mEstablishedCallback      = aArgs.mEstablishedCallback;
     mSendDoneCallback         = aArgs.mSendDoneCallback;
-    mSendReadyCallback        = aArgs.mSendReadyCallback;
+    mForwardProgressCallback  = aArgs.mForwardProgressCallback;
     mReceiveAvailableCallback = aArgs.mReceiveAvailableCallback;
     mDisconnectedCallback     = aArgs.mDisconnectedCallback;
 
-    mInstance = &aInstance;
-
     memset(mTimers, 0x00, sizeof(mTimers));
+    memset(&mSockAddr, 0x00, sizeof(mSockAddr));
+    mPendingCallbacks = 0;
+
+    /*
+     * Initialize buffers --- formerly in initialize_tcb.
+     */
+    {
+        uint8_t *recvbuf    = static_cast<uint8_t *>(aArgs.mReceiveBuffer);
+        size_t   recvbuflen = aArgs.mReceiveBufferSize - ((aArgs.mReceiveBufferSize + 8) / 9);
+        uint8_t *reassbmp   = recvbuf + recvbuflen;
+
+        lbuf_init(&tp.sendbuf);
+        cbuf_init(&tp.recvbuf, recvbuf, recvbuflen);
+        tp.reassbmp = reassbmp;
+        bmp_init(tp.reassbmp, BITS_TO_BYTES(recvbuflen));
+    }
+
+    tp.accepted_from = nullptr;
+    initialize_tcb(&tp);
+
+    /* Note that we do not need to zero-initialize mReceiveLinks. */
+
+    tp.instance = &aInstance;
 
 exit:
     return error;
 }
 
-Instance &Tcp::Endpoint::GetInstance(void)
+Instance &Tcp::Endpoint::GetInstance(void) const
 {
-    return AsCoreType(mInstance);
+    return AsNonConst(AsCoreType(GetTcb().instance));
 }
 
 const SockAddr &Tcp::Endpoint::GetLocalAddress(void) const
 {
+    const struct tcpcb &tp = GetTcb();
+
     static otSockAddr temp;
+
+    memcpy(&temp.mAddress, &tp.laddr, sizeof(temp.mAddress));
+    temp.mPort = HostSwap16(tp.lport);
+
     return AsCoreType(&temp);
 }
 
 const SockAddr &Tcp::Endpoint::GetPeerAddress(void) const
 {
+    const struct tcpcb &tp = GetTcb();
+
     static otSockAddr temp;
+
+    memcpy(&temp.mAddress, &tp.faddr, sizeof(temp.mAddress));
+    temp.mPort = HostSwap16(tp.fport);
+
     return AsCoreType(&temp);
 }
 
 Error Tcp::Endpoint::Bind(const SockAddr &aSockName)
 {
-    OT_UNUSED_VARIABLE(aSockName);
+    Error         error;
+    struct tcpcb &tp = GetTcb();
 
-    return kErrorNotImplemented;
+    VerifyOrExit(!AsCoreType(&aSockName.mAddress).IsUnspecified(), error = kErrorInvalidArgs);
+    VerifyOrExit(Get<Tcp>().CanBind(aSockName), error = kErrorInvalidState);
+
+    memcpy(&tp.laddr, &aSockName.mAddress, sizeof(tp.laddr));
+    tp.lport = HostSwap16(aSockName.mPort);
+    error    = kErrorNone;
+
+exit:
+    return error;
 }
 
 Error Tcp::Endpoint::Connect(const SockAddr &aSockName, uint32_t aFlags)
 {
-    OT_UNUSED_VARIABLE(aSockName);
+    Error               error = kErrorNone;
+    struct tcpcb &      tp    = GetTcb();
+    struct sockaddr_in6 sin6p;
+
     OT_UNUSED_VARIABLE(aFlags);
 
-    return kErrorNotImplemented;
+    VerifyOrExit(tp.t_state == TCP6S_CLOSED, error = kErrorInvalidState);
+
+    memcpy(&sin6p.sin6_addr, &aSockName.mAddress, sizeof(sin6p.sin6_addr));
+    sin6p.sin6_port = HostSwap16(aSockName.mPort);
+    error           = BsdErrorToOtError(tcp6_usr_connect(&tp, &sin6p));
+
+exit:
+    return error;
 }
 
 Error Tcp::Endpoint::SendByReference(otLinkedBuffer &aBuffer, uint32_t aFlags)
 {
-    OT_UNUSED_VARIABLE(aBuffer);
-    OT_UNUSED_VARIABLE(aFlags);
+    Error         error;
+    struct tcpcb &tp = GetTcb();
 
-    return kErrorNotImplemented;
+    size_t backlogBefore = GetBacklogBytes();
+    size_t sent          = aBuffer.mLength;
+
+    SuccessOrExit(error = BsdErrorToOtError(tcp_usr_send(&tp, (aFlags & OT_TCP_SEND_MORE_TO_COME) != 0, &aBuffer, 0)));
+
+    PostCallbacksAfterSend(sent, backlogBefore);
+
+exit:
+    return error;
 }
 
 Error Tcp::Endpoint::SendByExtension(size_t aNumBytes, uint32_t aFlags)
 {
-    OT_UNUSED_VARIABLE(aNumBytes);
-    OT_UNUSED_VARIABLE(aFlags);
+    Error         error;
+    bool          moreToCome    = (aFlags & OT_TCP_SEND_MORE_TO_COME) != 0;
+    struct tcpcb &tp            = GetTcb();
+    size_t        backlogBefore = GetBacklogBytes();
+    int           bsdError;
 
-    return kErrorNotImplemented;
+    VerifyOrExit(lbuf_head(&tp.sendbuf) != nullptr, error = kErrorInvalidState);
+
+    bsdError = tcp_usr_send(&tp, moreToCome ? 1 : 0, nullptr, aNumBytes);
+    SuccessOrExit(error = BsdErrorToOtError(bsdError));
+
+    PostCallbacksAfterSend(aNumBytes, backlogBefore);
+
+exit:
+    return error;
 }
 
-Error Tcp::Endpoint::ReceiveByReference(const otLinkedBuffer *&aBuffer) const
+Error Tcp::Endpoint::ReceiveByReference(const otLinkedBuffer *&aBuffer)
 {
-    OT_UNUSED_VARIABLE(aBuffer);
+    struct tcpcb &tp = GetTcb();
 
-    return kErrorNotImplemented;
+    cbuf_reference(&tp.recvbuf, &mReceiveLinks[0], &mReceiveLinks[1]);
+    aBuffer = &mReceiveLinks[0];
+
+    return kErrorNone;
 }
 
 Error Tcp::Endpoint::ReceiveContiguify(void)
@@ -138,50 +238,102 @@
 
 Error Tcp::Endpoint::CommitReceive(size_t aNumBytes, uint32_t aFlags)
 {
-    OT_UNUSED_VARIABLE(aNumBytes);
+    Error         error = kErrorNone;
+    struct tcpcb &tp    = GetTcb();
+
     OT_UNUSED_VARIABLE(aFlags);
 
-    return kErrorNotImplemented;
+    VerifyOrExit(cbuf_used_space(&tp.recvbuf) >= aNumBytes, error = kErrorFailed);
+    VerifyOrExit(aNumBytes > 0, error = kErrorNone);
+
+    cbuf_pop(&tp.recvbuf, aNumBytes);
+    error = BsdErrorToOtError(tcp_usr_rcvd(&tp));
+
+exit:
+    return error;
 }
 
 Error Tcp::Endpoint::SendEndOfStream(void)
 {
-    return kErrorNotImplemented;
+    struct tcpcb &tp = GetTcb();
+
+    return BsdErrorToOtError(tcp_usr_shutdown(&tp));
 }
 
 Error Tcp::Endpoint::Abort(void)
 {
-    return kErrorNotImplemented;
+    struct tcpcb &tp = GetTcb();
+
+    tcp_usr_abort(&tp);
+    /* connection_lost will do any reinitialization work for this socket. */
+    return kErrorNone;
 }
 
 Error Tcp::Endpoint::Deinitialize(void)
 {
     Error error;
 
-    Tcp &tcp = GetInstance().Get<Tcp>();
-
-    SuccessOrExit(error = tcp.mEndpoints.Remove(*this));
+    SuccessOrExit(error = Get<Tcp>().mEndpoints.Remove(*this));
     SetNext(nullptr);
 
+    SuccessOrExit(error = Abort());
+
 exit:
     return error;
 }
 
+bool Tcp::Endpoint::IsClosed(void) const
+{
+    return GetTcb().t_state == TCP6S_CLOSED;
+}
+
 uint8_t Tcp::Endpoint::TimerFlagToIndex(uint8_t aTimerFlag)
 {
-    OT_UNUSED_VARIABLE(aTimerFlag);
-    /*
-     * TODO: Convert from the timer flag provided by TCPlp to the index in
-     * our timers array.
-     */
-    return 0;
+    uint8_t timerIndex = 0;
+
+    switch (aTimerFlag)
+    {
+    case TT_DELACK:
+        timerIndex = kTimerDelack;
+        break;
+    case TT_REXMT:
+    case TT_PERSIST:
+        timerIndex = kTimerRexmtPersist;
+        break;
+    case TT_KEEP:
+        timerIndex = kTimerKeep;
+        break;
+    case TT_2MSL:
+        timerIndex = kTimer2Msl;
+        break;
+    }
+
+    return timerIndex;
 }
 
 bool Tcp::Endpoint::IsTimerActive(uint8_t aTimerIndex)
 {
-    OT_UNUSED_VARIABLE(aTimerIndex);
-    /* TODO: Check whether TCPlp has marked this timer as active. */
-    return false;
+    bool          active = false;
+    struct tcpcb *tp     = &GetTcb();
+
+    OT_ASSERT(aTimerIndex < kNumTimers);
+    switch (aTimerIndex)
+    {
+    case kTimerDelack:
+        active = tcp_timer_active(tp, TT_DELACK);
+        break;
+    case kTimerRexmtPersist:
+        active = tcp_timer_active(tp, TT_REXMT) || tcp_timer_active(tp, TT_PERSIST);
+        break;
+    case kTimerKeep:
+        active = tcp_timer_active(tp, TT_KEEP);
+        break;
+    case kTimer2Msl:
+        active = tcp_timer_active(tp, TT_2MSL);
+        break;
+    }
+
+    return active;
 }
 
 void Tcp::Endpoint::SetTimer(uint8_t aTimerFlag, uint32_t aDelay)
@@ -197,10 +349,10 @@
     uint8_t   timerIndex  = TimerFlagToIndex(aTimerFlag);
 
     mTimers[timerIndex] = newFireTime.GetValue();
-    otLogDebgTcp("Endpoint %p set timer %u to %u ms", static_cast<void *>(this), static_cast<unsigned int>(timerIndex),
-                 static_cast<unsigned int>(aDelay));
+    LogDebg("Endpoint %p set timer %u to %u ms", static_cast<void *>(this), static_cast<unsigned int>(timerIndex),
+            static_cast<unsigned int>(aDelay));
 
-    GetInstance().Get<Tcp>().mTimer.FireAtIfEarlier(newFireTime);
+    Get<Tcp>().mTimer.FireAtIfEarlier(newFireTime);
 }
 
 void Tcp::Endpoint::CancelTimer(uint8_t aTimerFlag)
@@ -213,12 +365,15 @@
 
     OT_UNUSED_VARIABLE(aTimerFlag);
 
-    otLogDebgTcp("Endpoint %p cancelled timer %u", static_cast<void *>(this),
-                 static_cast<unsigned int>(TimerFlagToIndex(aTimerFlag)));
+    LogDebg("Endpoint %p cancelled timer %u", static_cast<void *>(this),
+            static_cast<unsigned int>(TimerFlagToIndex(aTimerFlag)));
 }
 
 bool Tcp::Endpoint::FirePendingTimers(TimeMilli aNow, bool &aHasFutureTimer, TimeMilli &aEarliestFutureExpiry)
 {
+    bool          calledUserCallback = false;
+    struct tcpcb *tp                 = &GetTcb();
+
     /*
      * NOTE: Firing a timer might potentially activate/deactivate other timers.
      * If timers x and y expire at the same time, but the callback for timer x
@@ -242,8 +397,36 @@
 
             if (expiry <= aNow)
             {
-                /* TODO: Call TCPlp's callback for this timer. */
-                /* If a user callback is called, then return true. */
+                /*
+                 * If a user callback is called, then return true. For TCPlp,
+                 * this only happens if the connection is dropped (e.g., it
+                 * times out).
+                 */
+                int dropped;
+
+                switch (timerIndex)
+                {
+                case kTimerDelack:
+                    dropped = tcp_timer_delack(tp);
+                    break;
+                case kTimerRexmtPersist:
+                    if (tcp_timer_active(tp, TT_REXMT))
+                    {
+                        dropped = tcp_timer_rexmt(tp);
+                    }
+                    else
+                    {
+                        dropped = tcp_timer_persist(tp);
+                    }
+                    break;
+                case kTimerKeep:
+                    dropped = tcp_timer_keep(tp);
+                    break;
+                case kTimer2Msl:
+                    dropped = tcp_timer_2msl(tp);
+                    break;
+                }
+                VerifyOrExit(dropped == 0, calledUserCallback = true);
             }
             else
             {
@@ -253,12 +436,94 @@
         }
     }
 
-    return false;
+exit:
+    return calledUserCallback;
 }
 
-Error Tcp::Listener::Initialize(Instance &aInstance, otTcpListenerInitializeArgs &aArgs)
+void Tcp::Endpoint::PostCallbacksAfterSend(size_t aSent, size_t aBacklogBefore)
 {
-    Error error;
+    size_t backlogAfter = GetBacklogBytes();
+
+    if (backlogAfter < aBacklogBefore + aSent && mForwardProgressCallback != nullptr)
+    {
+        mPendingCallbacks |= kForwardProgressCallbackFlag;
+        Get<Tcp>().mTasklet.Post();
+    }
+}
+
+bool Tcp::Endpoint::FirePendingCallbacks(void)
+{
+    bool calledUserCallback = false;
+
+    if ((mPendingCallbacks & kForwardProgressCallbackFlag) != 0 && mForwardProgressCallback != nullptr)
+    {
+        mForwardProgressCallback(this, GetSendBufferBytes(), GetBacklogBytes());
+        calledUserCallback = true;
+    }
+
+    mPendingCallbacks = 0;
+
+    return calledUserCallback;
+}
+
+size_t Tcp::Endpoint::GetSendBufferBytes(void) const
+{
+    const struct tcpcb &tp = GetTcb();
+    return lbuf_used_space(&tp.sendbuf);
+}
+
+size_t Tcp::Endpoint::GetInFlightBytes(void) const
+{
+    const struct tcpcb &tp = GetTcb();
+    return tp.snd_max - tp.snd_una;
+}
+
+size_t Tcp::Endpoint::GetBacklogBytes(void) const
+{
+    return GetSendBufferBytes() - GetInFlightBytes();
+}
+
+Address &Tcp::Endpoint::GetLocalIp6Address(void)
+{
+    return *reinterpret_cast<Address *>(&GetTcb().laddr);
+}
+
+const Address &Tcp::Endpoint::GetLocalIp6Address(void) const
+{
+    return *reinterpret_cast<const Address *>(&GetTcb().laddr);
+}
+
+Address &Tcp::Endpoint::GetForeignIp6Address(void)
+{
+    return *reinterpret_cast<Address *>(&GetTcb().faddr);
+}
+
+const Address &Tcp::Endpoint::GetForeignIp6Address(void) const
+{
+    return *reinterpret_cast<const Address *>(&GetTcb().faddr);
+}
+
+bool Tcp::Endpoint::Matches(const MessageInfo &aMessageInfo) const
+{
+    bool                matches = false;
+    const struct tcpcb *tp      = &GetTcb();
+
+    VerifyOrExit(tp->t_state != TCP6S_CLOSED);
+    VerifyOrExit(tp->lport == HostSwap16(aMessageInfo.GetSockPort()));
+    VerifyOrExit(tp->fport == HostSwap16(aMessageInfo.GetPeerPort()));
+    VerifyOrExit(GetLocalIp6Address().IsUnspecified() || GetLocalIp6Address() == aMessageInfo.GetSockAddr());
+    VerifyOrExit(GetForeignIp6Address() == aMessageInfo.GetPeerAddr());
+
+    matches = true;
+
+exit:
+    return matches;
+}
+
+Error Tcp::Listener::Initialize(Instance &aInstance, const otTcpListenerInitializeArgs &aArgs)
+{
+    Error                error;
+    struct tcpcb_listen *tpl = &GetTcbListen();
 
     SuccessOrExit(error = aInstance.Get<Tcp>().mListeners.Add(*this));
 
@@ -266,71 +531,327 @@
     mAcceptReadyCallback = aArgs.mAcceptReadyCallback;
     mAcceptDoneCallback  = aArgs.mAcceptDoneCallback;
 
-    mInstance = &aInstance;
+    memset(tpl, 0x00, sizeof(struct tcpcb_listen));
+    tpl->instance = &aInstance;
 
 exit:
     return error;
 }
 
-Instance &Tcp::Listener::GetInstance(void)
+Instance &Tcp::Listener::GetInstance(void) const
 {
-    return AsCoreType(mInstance);
+    return AsNonConst(AsCoreType(GetTcbListen().instance));
 }
 
 Error Tcp::Listener::Listen(const SockAddr &aSockName)
 {
-    OT_UNUSED_VARIABLE(aSockName);
+    Error                error;
+    uint16_t             port = HostSwap16(aSockName.mPort);
+    struct tcpcb_listen *tpl  = &GetTcbListen();
 
-    return kErrorNotImplemented;
+    VerifyOrExit(Get<Tcp>().CanBind(aSockName), error = kErrorInvalidState);
+
+    memcpy(&tpl->laddr, &aSockName.mAddress, sizeof(tpl->laddr));
+    tpl->lport   = port;
+    tpl->t_state = TCP6S_LISTEN;
+    error        = kErrorNone;
+
+exit:
+    return error;
 }
 
 Error Tcp::Listener::StopListening(void)
 {
-    return kErrorNotImplemented;
+    struct tcpcb_listen *tpl = &GetTcbListen();
+
+    memset(&tpl->laddr, 0x00, sizeof(tpl->laddr));
+    tpl->lport   = 0;
+    tpl->t_state = TCP6S_CLOSED;
+    return kErrorNone;
 }
 
 Error Tcp::Listener::Deinitialize(void)
 {
     Error error;
 
-    Tcp &tcp = GetInstance().Get<Tcp>();
-
-    SuccessOrExit(error = tcp.mListeners.Remove(*this));
+    SuccessOrExit(error = Get<Tcp>().mListeners.Remove(*this));
     SetNext(nullptr);
 
 exit:
     return error;
 }
 
+bool Tcp::Listener::IsClosed(void) const
+{
+    return GetTcbListen().t_state == TCP6S_CLOSED;
+}
+
+Address &Tcp::Listener::GetLocalIp6Address(void)
+{
+    return *reinterpret_cast<Address *>(&GetTcbListen().laddr);
+}
+
+const Address &Tcp::Listener::GetLocalIp6Address(void) const
+{
+    return *reinterpret_cast<const Address *>(&GetTcbListen().laddr);
+}
+
+bool Tcp::Listener::Matches(const MessageInfo &aMessageInfo) const
+{
+    bool                       matches = false;
+    const struct tcpcb_listen *tpl     = &GetTcbListen();
+
+    VerifyOrExit(tpl->t_state == TCP6S_LISTEN);
+    VerifyOrExit(tpl->lport == HostSwap16(aMessageInfo.GetSockPort()));
+    VerifyOrExit(GetLocalIp6Address().IsUnspecified() || GetLocalIp6Address() == aMessageInfo.GetSockAddr());
+
+    matches = true;
+
+exit:
+    return matches;
+}
+
 Error Tcp::HandleMessage(ot::Ip6::Header &aIp6Header, Message &aMessage, MessageInfo &aMessageInfo)
 {
-    OT_UNUSED_VARIABLE(aIp6Header);
-    OT_UNUSED_VARIABLE(aMessage);
-    OT_UNUSED_VARIABLE(aMessageInfo);
-
     Error error = kErrorNotImplemented;
 
-    for (Endpoint &active : mEndpoints)
+    /*
+     * The type uint32_t was chosen for alignment purposes. The size is the
+     * maximum TCP header size, including options.
+     */
+    uint32_t header[15];
+
+    uint16_t length = aIp6Header.GetPayloadLength();
+    uint8_t  headerSize;
+
+    struct ip6_hdr *ip6Header;
+    struct tcphdr * tcpHeader;
+
+    Endpoint *endpoint;
+    Endpoint *endpointPrev;
+
+    Listener *listener;
+    Listener *listenerPrev;
+
+    VerifyOrExit(length == aMessage.GetLength() - aMessage.GetOffset(), error = kErrorParse);
+    VerifyOrExit(length >= sizeof(Tcp::Header), error = kErrorParse);
+    SuccessOrExit(error = aMessage.Read(aMessage.GetOffset() + offsetof(struct tcphdr, th_off_x2), headerSize));
+    headerSize = static_cast<uint8_t>((headerSize >> TH_OFF_SHIFT) << 2);
+    VerifyOrExit(headerSize >= sizeof(struct tcphdr) && headerSize <= sizeof(header) &&
+                     static_cast<uint16_t>(headerSize) <= length,
+                 error = kErrorParse);
+    SuccessOrExit(error = Checksum::VerifyMessageChecksum(aMessage, aMessageInfo, kProtoTcp));
+    SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), &header[0], headerSize));
+
+    ip6Header = reinterpret_cast<struct ip6_hdr *>(&aIp6Header);
+    tcpHeader = reinterpret_cast<struct tcphdr *>(&header[0]);
+    tcp_fields_to_host(tcpHeader);
+
+    aMessageInfo.mPeerPort = HostSwap16(tcpHeader->th_sport);
+    aMessageInfo.mSockPort = HostSwap16(tcpHeader->th_dport);
+
+    endpoint = mEndpoints.FindMatching(aMessageInfo, endpointPrev);
+    if (endpoint != nullptr)
     {
-        OT_UNUSED_VARIABLE(active);
+        struct tcplp_signals sig;
+        int                  nextAction;
+        struct tcpcb *       tp = &endpoint->GetTcb();
+
+        otLinkedBuffer *priorHead    = lbuf_head(&tp->sendbuf);
+        size_t          priorBacklog = endpoint->GetSendBufferBytes() - endpoint->GetInFlightBytes();
+
+        memset(&sig, 0x00, sizeof(sig));
+        nextAction = tcp_input(ip6Header, tcpHeader, &aMessage, tp, nullptr, &sig);
+        if (nextAction != RELOOKUP_REQUIRED)
+        {
+            ProcessSignals(*endpoint, priorHead, priorBacklog, sig);
+            ExitNow();
+        }
+        /* If the matching socket was in the TIME-WAIT state, then we try passive sockets. */
     }
 
-    for (Listener &passive : mListeners)
+    listener = mListeners.FindMatching(aMessageInfo, listenerPrev);
+    if (listener != nullptr)
     {
-        OT_UNUSED_VARIABLE(passive);
+        struct tcpcb_listen *tpl = &listener->GetTcbListen();
+
+        tcp_input(ip6Header, tcpHeader, &aMessage, nullptr, tpl, nullptr);
+        ExitNow();
+    }
+
+    tcp_dropwithreset(ip6Header, tcpHeader, nullptr, &InstanceLocator::GetInstance(), length - headerSize,
+                      ECONNREFUSED);
+
+exit:
+    return error;
+}
+
+void Tcp::ProcessSignals(Endpoint &            aEndpoint,
+                         otLinkedBuffer *      aPriorHead,
+                         size_t                aPriorBacklog,
+                         struct tcplp_signals &aSignals)
+{
+    VerifyOrExit(IsInitialized(aEndpoint) && !aEndpoint.IsClosed());
+    if (aSignals.conn_established && aEndpoint.mEstablishedCallback != nullptr)
+    {
+        aEndpoint.mEstablishedCallback(&aEndpoint);
+    }
+
+    VerifyOrExit(IsInitialized(aEndpoint) && !aEndpoint.IsClosed());
+    if (aEndpoint.mSendDoneCallback != nullptr)
+    {
+        otLinkedBuffer *curr = aPriorHead;
+
+        for (uint32_t i = 0; i != aSignals.links_popped; i++)
+        {
+            otLinkedBuffer *next = curr->mNext;
+
+            VerifyOrExit(i == 0 || (IsInitialized(aEndpoint) && !aEndpoint.IsClosed()));
+
+            curr->mNext = nullptr;
+            aEndpoint.mSendDoneCallback(&aEndpoint, curr);
+            curr = next;
+        }
+    }
+
+    VerifyOrExit(IsInitialized(aEndpoint) && !aEndpoint.IsClosed());
+    if (aEndpoint.mForwardProgressCallback != nullptr)
+    {
+        size_t backlogBytes = aEndpoint.GetBacklogBytes();
+
+        if (aSignals.bytes_acked > 0 || backlogBytes < aPriorBacklog)
+        {
+            aEndpoint.mForwardProgressCallback(&aEndpoint, aEndpoint.GetSendBufferBytes(), backlogBytes);
+            aEndpoint.mPendingCallbacks &= ~kForwardProgressCallbackFlag;
+        }
+    }
+
+    VerifyOrExit(IsInitialized(aEndpoint) && !aEndpoint.IsClosed());
+    if ((aSignals.recvbuf_added || aSignals.rcvd_fin) && aEndpoint.mReceiveAvailableCallback != nullptr)
+    {
+        aEndpoint.mReceiveAvailableCallback(&aEndpoint, cbuf_used_space(&aEndpoint.GetTcb().recvbuf),
+                                            aEndpoint.GetTcb().reass_fin_index != -1,
+                                            cbuf_free_space(&aEndpoint.GetTcb().recvbuf));
+    }
+
+    VerifyOrExit(IsInitialized(aEndpoint) && !aEndpoint.IsClosed());
+    if (aEndpoint.GetTcb().t_state == TCP6S_TIME_WAIT && aEndpoint.mDisconnectedCallback != nullptr)
+    {
+        aEndpoint.mDisconnectedCallback(&aEndpoint, OT_TCP_DISCONNECTED_REASON_TIME_WAIT);
+    }
+
+exit:
+    return;
+}
+
+Error Tcp::BsdErrorToOtError(int aBsdError)
+{
+    Error error = kErrorFailed;
+
+    switch (aBsdError)
+    {
+    case 0:
+        error = kErrorNone;
+        break;
     }
 
     return error;
 }
 
-void Tcp::HandleTimer(Timer &aTimer)
+bool Tcp::CanBind(const SockAddr &aSockName)
 {
-    OT_ASSERT(&aTimer == &aTimer.GetInstance().Get<Tcp>().mTimer);
-    otLogDebgTcp("Main TCP timer expired");
-    aTimer.GetInstance().Get<Tcp>().ProcessTimers();
+    uint16_t port    = HostSwap16(aSockName.mPort);
+    bool     allowed = false;
+
+    for (Endpoint &endpoint : mEndpoints)
+    {
+        struct tcpcb *tp = &endpoint.GetTcb();
+
+        if (tp->lport == port)
+        {
+            VerifyOrExit(!aSockName.GetAddress().IsUnspecified());
+            VerifyOrExit(!reinterpret_cast<Address *>(&tp->laddr)->IsUnspecified());
+            VerifyOrExit(memcmp(&endpoint.GetTcb().laddr, &aSockName.mAddress, sizeof(tp->laddr)) != 0);
+        }
+    }
+
+    for (Listener &listener : mListeners)
+    {
+        struct tcpcb_listen *tpl = &listener.GetTcbListen();
+
+        if (tpl->lport == port)
+        {
+            VerifyOrExit(!aSockName.GetAddress().IsUnspecified());
+            VerifyOrExit(!reinterpret_cast<Address *>(&tpl->laddr)->IsUnspecified());
+            VerifyOrExit(memcmp(&tpl->laddr, &aSockName.mAddress, sizeof(tpl->laddr)) != 0);
+        }
+    }
+
+    allowed = true;
+
+exit:
+    return allowed;
 }
 
-void Tcp::ProcessTimers()
+bool Tcp::AutoBind(const SockAddr &aPeer, SockAddr &aToBind, bool aBindAddress, bool aBindPort)
+{
+    bool success;
+
+    if (aBindAddress)
+    {
+        MessageInfo                  peerInfo;
+        const Netif::UnicastAddress *netifAddress;
+
+        peerInfo.Clear();
+        peerInfo.SetPeerAddr(aPeer.GetAddress());
+        netifAddress = Get<Ip6>().SelectSourceAddress(peerInfo);
+        VerifyOrExit(netifAddress != nullptr, success = false);
+        aToBind.GetAddress() = netifAddress->GetAddress();
+    }
+
+    if (aBindPort)
+    {
+        /*
+         * TODO: Use a less naive algorithm to allocate ephemeral ports. For
+         * example, see RFC 6056.
+         */
+
+        for (uint16_t i = 0; i != kDynamicPortMax - kDynamicPortMin + 1; i++)
+        {
+            aToBind.SetPort(mEphemeralPort);
+
+            if (mEphemeralPort == kDynamicPortMax)
+            {
+                mEphemeralPort = kDynamicPortMin;
+            }
+            else
+            {
+                mEphemeralPort++;
+            }
+
+            if (CanBind(aToBind))
+            {
+                ExitNow(success = true);
+            }
+        }
+
+        ExitNow(success = false);
+    }
+
+    success = CanBind(aToBind);
+
+exit:
+    return success;
+}
+
+void Tcp::HandleTimer(Timer &aTimer)
+{
+    OT_ASSERT(&aTimer == &aTimer.Get<Tcp>().mTimer);
+    LogDebg("Main TCP timer expired");
+    aTimer.Get<Tcp>().ProcessTimers();
+}
+
+void Tcp::ProcessTimers(void)
 {
     TimeMilli now = TimerMilli::GetNow();
     bool      pendingTimer;
@@ -384,15 +905,270 @@
          * timers.
          */
         mTimer.FireAtIfEarlier(earliestPendingTimerExpiry);
-        otLogDebgTcp("Reset main TCP timer to %u ms", static_cast<unsigned int>(earliestPendingTimerExpiry - now));
+        LogDebg("Reset main TCP timer to %u ms", static_cast<unsigned int>(earliestPendingTimerExpiry - now));
     }
     else
     {
-        otLogDebgTcp("Did not reset main TCP timer");
+        LogDebg("Did not reset main TCP timer");
+    }
+}
+
+void Tcp::HandleTasklet(Tasklet &aTasklet)
+{
+    OT_ASSERT(&aTasklet == &aTasklet.Get<Tcp>().mTasklet);
+    LogDebg("TCP tasklet invoked");
+    aTasklet.Get<Tcp>().ProcessCallbacks();
+}
+
+void Tcp::ProcessCallbacks(void)
+{
+    for (Endpoint &endpoint : mEndpoints)
+    {
+        if (endpoint.FirePendingCallbacks())
+        {
+            mTasklet.Post();
+            break;
+        }
     }
 }
 
 } // namespace Ip6
 } // namespace ot
 
+/*
+ * Implement TCPlp system stubs declared in tcplp.h.
+ *
+ * Because these functions have C linkage, it is important that only one
+ * definition is given for each function name, regardless of the namespace it
+ * in. For example, if we give two definitions of tcplp_sys_new_message, we
+ * will get errors, even if they are in different namespaces. To avoid
+ * confusion, I've put these functions outside of any namespace.
+ */
+
+using namespace ot;
+using namespace ot::Ip6;
+
+extern "C" {
+
+otMessage *tcplp_sys_new_message(otInstance *aInstance)
+{
+    Instance &instance = AsCoreType(aInstance);
+    Message * message  = instance.Get<ot::Ip6::Ip6>().NewMessage(0);
+
+    if (message)
+    {
+        message->SetLinkSecurityEnabled(true);
+    }
+
+    return message;
+}
+
+void tcplp_sys_free_message(otInstance *aInstance, otMessage *aMessage)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+    Message &message = AsCoreType(aMessage);
+    message.Free();
+}
+
+void tcplp_sys_send_message(otInstance *aInstance, otMessage *aMessage, otMessageInfo *aMessageInfo)
+{
+    Instance &   instance = AsCoreType(aInstance);
+    Message &    message  = AsCoreType(aMessage);
+    MessageInfo &info     = AsCoreType(aMessageInfo);
+
+    LogDebg("Sending TCP segment: payload_size = %d", static_cast<int>(message.GetLength()));
+
+    IgnoreError(instance.Get<ot::Ip6::Ip6>().SendDatagram(message, info, kProtoTcp));
+}
+
+uint32_t tcplp_sys_get_ticks(void)
+{
+    return TimerMilli::GetNow().GetValue();
+}
+
+uint32_t tcplp_sys_get_millis(void)
+{
+    return TimerMilli::GetNow().GetValue();
+}
+
+void tcplp_sys_set_timer(struct tcpcb *aTcb, uint8_t aTimerFlag, uint32_t aDelay)
+{
+    Tcp::Endpoint &endpoint = Tcp::Endpoint::FromTcb(*aTcb);
+    endpoint.SetTimer(aTimerFlag, aDelay);
+}
+
+void tcplp_sys_stop_timer(struct tcpcb *aTcb, uint8_t aTimerFlag)
+{
+    Tcp::Endpoint &endpoint = Tcp::Endpoint::FromTcb(*aTcb);
+    endpoint.CancelTimer(aTimerFlag);
+}
+
+struct tcpcb *tcplp_sys_accept_ready(struct tcpcb_listen *aTcbListen, struct in6_addr *aAddr, uint16_t aPort)
+{
+    Tcp::Listener &               listener = Tcp::Listener::FromTcbListen(*aTcbListen);
+    Tcp &                         tcp      = listener.Get<Tcp>();
+    struct tcpcb *                rv       = (struct tcpcb *)-1;
+    otSockAddr                    addr;
+    otTcpEndpoint *               endpointPtr;
+    otTcpIncomingConnectionAction action;
+
+    VerifyOrExit(listener.mAcceptReadyCallback != nullptr);
+
+    memcpy(&addr.mAddress, aAddr, sizeof(addr.mAddress));
+    addr.mPort = HostSwap16(aPort);
+    action     = listener.mAcceptReadyCallback(&listener, &addr, &endpointPtr);
+
+    VerifyOrExit(tcp.IsInitialized(listener) && !listener.IsClosed());
+
+    switch (action)
+    {
+    case OT_TCP_INCOMING_CONNECTION_ACTION_ACCEPT:
+    {
+        Tcp::Endpoint &endpoint = AsCoreType(endpointPtr);
+
+        /*
+         * The documentation says that the user must initialize the
+         * endpoint before passing it here, so we do a sanity check to make
+         * sure the endpoint is initialized and closed. That check may not
+         * be necessary, but we do it anyway.
+         */
+        VerifyOrExit(tcp.IsInitialized(endpoint) && endpoint.IsClosed());
+
+        rv = &endpoint.GetTcb();
+
+        break;
+    }
+    case OT_TCP_INCOMING_CONNECTION_ACTION_DEFER:
+        rv = nullptr;
+        break;
+    case OT_TCP_INCOMING_CONNECTION_ACTION_REFUSE:
+        rv = (struct tcpcb *)-1;
+        break;
+    }
+
+exit:
+    return rv;
+}
+
+bool tcplp_sys_accepted_connection(struct tcpcb_listen *aTcbListen,
+                                   struct tcpcb *       aAccepted,
+                                   struct in6_addr *    aAddr,
+                                   uint16_t             aPort)
+{
+    Tcp::Listener &listener = Tcp::Listener::FromTcbListen(*aTcbListen);
+    Tcp::Endpoint &endpoint = Tcp::Endpoint::FromTcb(*aAccepted);
+    Tcp &          tcp      = endpoint.Get<Tcp>();
+    bool           accepted = true;
+
+    if (listener.mAcceptDoneCallback != nullptr)
+    {
+        otSockAddr addr;
+
+        memcpy(&addr.mAddress, aAddr, sizeof(addr.mAddress));
+        addr.mPort = HostSwap16(aPort);
+        listener.mAcceptDoneCallback(&listener, &endpoint, &addr);
+
+        if (!tcp.IsInitialized(endpoint) || endpoint.IsClosed())
+        {
+            accepted = false;
+        }
+    }
+
+    return accepted;
+}
+
+void tcplp_sys_connection_lost(struct tcpcb *aTcb, uint8_t aErrNum)
+{
+    Tcp::Endpoint &endpoint = Tcp::Endpoint::FromTcb(*aTcb);
+
+    if (endpoint.mDisconnectedCallback != nullptr)
+    {
+        otTcpDisconnectedReason reason;
+
+        switch (aErrNum)
+        {
+        case CONN_LOST_NORMAL:
+            reason = OT_TCP_DISCONNECTED_REASON_NORMAL;
+            break;
+        case ECONNREFUSED:
+            reason = OT_TCP_DISCONNECTED_REASON_REFUSED;
+            break;
+        case ETIMEDOUT:
+            reason = OT_TCP_DISCONNECTED_REASON_TIMED_OUT;
+            break;
+        case ECONNRESET:
+        default:
+            reason = OT_TCP_DISCONNECTED_REASON_RESET;
+            break;
+        }
+        endpoint.mDisconnectedCallback(&endpoint, reason);
+    }
+}
+
+void tcplp_sys_on_state_change(struct tcpcb *aTcb, int aNewState)
+{
+    if (aNewState == TCP6S_CLOSED)
+    {
+        /* Re-initialize the TCB. */
+        cbuf_pop(&aTcb->recvbuf, cbuf_used_space(&aTcb->recvbuf));
+        aTcb->accepted_from = nullptr;
+        initialize_tcb(aTcb);
+    }
+    /* Any adaptive changes to the sleep interval would go here. */
+}
+
+void tcplp_sys_log(const char *aFormat, ...)
+{
+    char    buffer[128];
+    va_list args;
+    va_start(args, aFormat);
+    vsnprintf(buffer, sizeof(buffer), aFormat, args);
+    va_end(args);
+
+    LogDebg(buffer);
+}
+
+void tcplp_sys_panic(const char *aFormat, ...)
+{
+    char    buffer[128];
+    va_list args;
+    va_start(args, aFormat);
+    vsnprintf(buffer, sizeof(buffer), aFormat, args);
+    va_end(args);
+
+    LogCrit("%s", buffer);
+
+    OT_ASSERT(false);
+}
+
+bool tcplp_sys_autobind(otInstance *      aInstance,
+                        const otSockAddr *aPeer,
+                        otSockAddr *      aToBind,
+                        bool              aBindAddress,
+                        bool              aBindPort)
+{
+    Instance &instance = AsCoreType(aInstance);
+
+    return instance.Get<Tcp>().AutoBind(*static_cast<const SockAddr *>(aPeer), *static_cast<SockAddr *>(aToBind),
+                                        aBindAddress, aBindPort);
+}
+
+uint32_t tcplp_sys_generate_isn()
+{
+    uint32_t isn;
+    IgnoreError(Random::Crypto::FillBuffer(reinterpret_cast<uint8_t *>(&isn), sizeof(isn)));
+    return isn;
+}
+
+uint16_t tcplp_sys_hostswap16(uint16_t aHostPort)
+{
+    return HostSwap16(aHostPort);
+}
+
+uint32_t tcplp_sys_hostswap32(uint32_t aHostPort)
+{
+    return HostSwap32(aHostPort);
+}
+}
+
 #endif // OPENTHREAD_CONFIG_TCP_ENABLE
diff --git a/src/core/net/tcp6.hpp b/src/core/net/tcp6.hpp
index d216bd0..501fd5a 100644
--- a/src/core/net/tcp6.hpp
+++ b/src/core/net/tcp6.hpp
@@ -38,13 +38,26 @@
 
 #include <openthread/tcp.h>
 
-#include "net/ip6_headers.hpp"
-#include "net/socket.hpp"
-
+#include "common/as_core_type.hpp"
+#include "common/clearable.hpp"
 #include "common/linked_list.hpp"
 #include "common/locator.hpp"
 #include "common/non_copyable.hpp"
 #include "common/timer.hpp"
+#include "net/ip6_headers.hpp"
+#include "net/socket.hpp"
+
+/*
+ * These structures and functions are forward-declared here to avoid
+ * #includ'ing third_party/tcplp/tcplp.h in this header file.
+ */
+extern "C" {
+struct tcpcb;
+struct tcpcb_listen;
+struct tcplp_signals;
+void tcplp_sys_set_timer(struct tcpcb *aTcb, uint8_t aTimerFlag, uint32_t aDelay);
+void tcplp_sys_stop_timer(struct tcpcb *aTcb, uint8_t aTimerFlag);
+}
 
 namespace ot {
 namespace Ip6 {
@@ -70,9 +83,10 @@
      * This class represents an endpoint of a TCP/IPv6 connection.
      *
      */
-    class Endpoint : public otTcpEndpoint, public LinkedListEntry<Endpoint>
+    class Endpoint : public otTcpEndpoint, public LinkedListEntry<Endpoint>, public GetProvider<Endpoint>
     {
         friend class Tcp;
+        friend class LinkedList<Endpoint>;
 
     public:
         /**
@@ -93,7 +107,7 @@
          * @retval kErrorFailed  Failed to open the TCP endpoint.
          *
          */
-        Error Initialize(Instance &aInstance, otTcpEndpointInitializeArgs &aArgs);
+        Error Initialize(Instance &aInstance, const otTcpEndpointInitializeArgs &aArgs);
 
         /**
          * Obtains the Instance that was associated with this Endpoint upon
@@ -104,7 +118,7 @@
          * @returns  The Instance pointer associated with this Endpoint.
          *
          */
-        Instance &GetInstance(void);
+        Instance &GetInstance(void) const;
 
         /**
          * Obtains the context pointer that was associated this Endpoint upon
@@ -236,7 +250,7 @@
          * @retval kErrorNone    Successfully completed the operation.
          * @retval kErrorFailed  Failed to complete the operation.
          */
-        Error ReceiveByReference(const otLinkedBuffer *&aBuffer) const;
+        Error ReceiveByReference(const otLinkedBuffer *&aBuffer);
 
         /**
          * Reorganizes the receive buffer to be entirely contiguous in memory.
@@ -329,7 +343,31 @@
          */
         Error Deinitialize(void);
 
+        /**
+         * Converts a reference to a struct tcpcb to a reference to its
+         * enclosing Endpoint.
+         */
+        static Endpoint &FromTcb(struct tcpcb &aTcb) { return *reinterpret_cast<Endpoint *>(&aTcb); }
+
+        /**
+         * Obtains a reference to this Endpoint's struct tcpcb.
+         */
+        struct tcpcb &GetTcb(void) { return *reinterpret_cast<struct tcpcb *>(&mTcb); }
+
+        /**
+         * Obtains a const reference to this Endpoint's struct tcpcb.
+         */
+        const struct tcpcb &GetTcb(void) const { return *reinterpret_cast<const struct tcpcb *>(&mTcb); }
+
+        /**
+         * Checks if this Endpoint is in the closed state.
+         */
+        bool IsClosed(void) const;
+
     private:
+        friend void ::tcplp_sys_set_timer(struct tcpcb *aTcb, uint8_t aTimerFlag, uint32_t aDelay);
+        friend void ::tcplp_sys_stop_timer(struct tcpcb *aTcb, uint8_t aTimerFlag);
+
         enum : uint8_t
         {
             kTimerDelack       = 0,
@@ -345,14 +383,29 @@
         void SetTimer(uint8_t aTimerFlag, uint32_t aDelay);
         void CancelTimer(uint8_t aTimerFlag);
         bool FirePendingTimers(TimeMilli aNow, bool &aHasFutureTimer, TimeMilli &aEarliestFutureExpiry);
+
+        void PostCallbacksAfterSend(size_t aSent, size_t aBacklogBefore);
+        bool FirePendingCallbacks(void);
+
+        size_t GetSendBufferBytes(void) const;
+        size_t GetInFlightBytes(void) const;
+        size_t GetBacklogBytes(void) const;
+
+        Address &      GetLocalIp6Address(void);
+        const Address &GetLocalIp6Address(void) const;
+        Address &      GetForeignIp6Address(void);
+        const Address &GetForeignIp6Address(void) const;
+        bool           Matches(const MessageInfo &aMessageInfo) const;
     };
 
     /**
      * This class represents a TCP/IPv6 listener.
      *
      */
-    class Listener : public otTcpListener, public LinkedListEntry<Listener>
+    class Listener : public otTcpListener, public LinkedListEntry<Listener>, public GetProvider<Listener>
     {
+        friend class LinkedList<Listener>;
+
     public:
         /**
          * Initializes a TCP listener.
@@ -372,7 +425,7 @@
          * @retval kErrorFailed  Failed to open the TCP listener.
          *
          */
-        Error Initialize(Instance &aInstance, otTcpListenerInitializeArgs &aArgs);
+        Error Initialize(Instance &aInstance, const otTcpListenerInitializeArgs &aArgs);
 
         /**
          * Obtains the otInstance that was associated with this Listener upon
@@ -383,7 +436,7 @@
          * @returns  The otInstance pointer associated with this Listener.
          *
          */
-        Instance &GetInstance(void);
+        Instance &GetInstance(void) const;
 
         /**
          * Obtains the context pointer that was associated with this Listener upon
@@ -438,6 +491,38 @@
          *
          */
         Error Deinitialize(void);
+
+        /**
+         * Converts a reference to a struct tcpcb_listen to a reference to its
+         * enclosing Listener.
+         */
+        static Listener &FromTcbListen(struct tcpcb_listen &aTcbListen)
+        {
+            return *reinterpret_cast<Listener *>(&aTcbListen);
+        }
+
+        /**
+         * Obtains a reference to this Listener's struct tcpcb_listen.
+         */
+        struct tcpcb_listen &GetTcbListen(void) { return *reinterpret_cast<struct tcpcb_listen *>(&mTcbListen); }
+
+        /**
+         * Obtains a const reference to this Listener's struct tcpcb_listen.
+         */
+        const struct tcpcb_listen &GetTcbListen(void) const
+        {
+            return *reinterpret_cast<const struct tcpcb_listen *>(&mTcbListen);
+        }
+
+        /**
+         * Checks if this Listener is in the closed state.
+         */
+        bool IsClosed(void) const;
+
+    private:
+        Address &      GetLocalIp6Address(void);
+        const Address &GetLocalIp6Address(void) const;
+        bool           Matches(const MessageInfo &aMessageInfo) const;
     };
 
     /**
@@ -445,7 +530,7 @@
      *
      */
     OT_TOOL_PACKED_BEGIN
-    class Header
+    class Header : public Clearable<Header>
     {
     public:
         static constexpr uint8_t kChecksumFieldOffset = 16; ///< Byte offset of the Checksum field in the TCP header.
@@ -546,6 +631,31 @@
      */
     Error HandleMessage(ot::Ip6::Header &aIp6Header, Message &aMessage, MessageInfo &aMessageInfo);
 
+    /**
+     * Automatically selects a local address and/or port for communication with the specified peer.
+     *
+     * @param[in] aPeer         The peer's address and port.
+     * @param[in,out] aToBind   The SockAddr into which to store the selected address and/or port.
+     * @param[in] aBindAddress  If true, the local address is selected; if not, the current address
+     *                          in @p aToBind is treated as a given.
+     * @param[in] aBindPort     If true, the local port is selected; if not, the current port in
+     *                          @p aToBind is treated as a given.
+     *
+     * @returns  True if successful, false otherwise.
+     *
+     */
+    bool AutoBind(const SockAddr &aPeer, SockAddr &aToBind, bool aBindAddress, bool aBindPort);
+
+    /**
+     * Checks if an Endpoint is in the list of initialized endpoints.
+     */
+    bool IsInitialized(const Endpoint &aEndpoint) const { return mEndpoints.Contains(aEndpoint); }
+
+    /**
+     * Checks if a Listener is in the list of initialized Listeners.
+     */
+    bool IsInitialized(const Listener &aListener) const { return mListeners.Contains(aListener); }
+
 private:
     enum
     {
@@ -553,10 +663,28 @@
         kDynamicPortMax = 65535, ///< Service Name and Transport Protocol Port Number Registry
     };
 
+    static constexpr uint8_t kEstablishedCallbackFlag      = (1 << 0);
+    static constexpr uint8_t kSendDoneCallbackFlag         = (1 << 1);
+    static constexpr uint8_t kForwardProgressCallbackFlag  = (1 << 2);
+    static constexpr uint8_t kReceiveAvailableCallbackFlag = (1 << 3);
+    static constexpr uint8_t kDisconnectedCallbackFlag     = (1 << 4);
+
+    void ProcessSignals(Endpoint &            aEndpoint,
+                        otLinkedBuffer *      aPriorHead,
+                        size_t                aPriorBacklog,
+                        struct tcplp_signals &aSignals);
+
+    static Error BsdErrorToOtError(int aBsdError);
+    bool         CanBind(const SockAddr &aSockName);
+
     static void HandleTimer(Timer &aTimer);
     void        ProcessTimers(void);
 
+    static void HandleTasklet(Tasklet &aTasklet);
+    void        ProcessCallbacks(void);
+
     TimerMilli mTimer;
+    Tasklet    mTasklet;
 
     LinkedList<Endpoint> mEndpoints;
     LinkedList<Listener> mListeners;
@@ -564,6 +692,10 @@
 };
 
 } // namespace Ip6
+
+DefineCoreType(otTcpEndpoint, Ip6::Tcp::Endpoint);
+DefineCoreType(otTcpListener, Ip6::Tcp::Listener);
+
 } // namespace ot
 
 #endif // TCP6_HPP_
diff --git a/src/core/net/udp6.hpp b/src/core/net/udp6.hpp
index 4068567..6471c4b 100644
--- a/src/core/net/udp6.hpp
+++ b/src/core/net/udp6.hpp
@@ -39,6 +39,7 @@
 #include <openthread/udp.h>
 #include <openthread/platform/udp.h>
 
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/linked_list.hpp"
 #include "common/locator.hpp"
@@ -96,7 +97,7 @@
          * @returns A reference to the local socket address.
          *
          */
-        SockAddr &GetSockName(void) { return *static_cast<SockAddr *>(&mSockName); }
+        SockAddr &GetSockName(void) { return AsCoreType(&mSockName); }
 
         /**
          * This method returns the local socket address.
@@ -104,7 +105,7 @@
          * @returns A reference to the local socket address.
          *
          */
-        const SockAddr &GetSockName(void) const { return *static_cast<const SockAddr *>(&mSockName); }
+        const SockAddr &GetSockName(void) const { return AsCoreType(&mSockName); }
 
         /**
          * This method returns the peer's socket address.
@@ -112,7 +113,7 @@
          * @returns A reference to the peer's socket address.
          *
          */
-        SockAddr &GetPeerName(void) { return *static_cast<SockAddr *>(&mPeerName); }
+        SockAddr &GetPeerName(void) { return AsCoreType(&mPeerName); }
 
         /**
          * This method returns the peer's socket address.
@@ -120,7 +121,7 @@
          * @returns A reference to the peer's socket address.
          *
          */
-        const SockAddr &GetPeerName(void) const { return *static_cast<const SockAddr *>(&mPeerName); }
+        const SockAddr &GetPeerName(void) const { return AsCoreType(&mPeerName); }
 
     private:
         bool Matches(const MessageInfo &aMessageInfo) const;
@@ -154,7 +155,7 @@
          * @param[in]  aReserved  The number of header bytes to reserve after the UDP header.
          * @param[in]  aSettings  The message settings (default is used if not provided).
          *
-         * @returns A pointer to the message or nullptr if no buffers are available.
+         * @returns A pointer to the message or `nullptr` if no buffers are available.
          *
          */
         Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings = Message::Settings::GetDefault());
@@ -305,8 +306,8 @@
         /**
          * This constructor initializes the UDP receiver.
          *
-         * @param[in]   aUdpHandler     A pointer to the function to handle UDP message.
-         * @param[in]   aContext        A pointer to arbitrary context information.
+         * @param[in]   aHandler     A pointer to the function to handle UDP message.
+         * @param[in]   aContext     A pointer to arbitrary context information.
          *
          */
         Receiver(otUdpHandler aHandler, void *aContext)
@@ -328,7 +329,7 @@
      *
      */
     OT_TOOL_PACKED_BEGIN
-    class Header
+    class Header : public Clearable<Header>
     {
     public:
         static constexpr uint16_t kSourcePortFieldOffset = 0; ///< Byte offset of Source Port field in UDP header.
@@ -526,7 +527,7 @@
      * @param[in]  aReserved  The number of header bytes to reserve after the UDP header.
      * @param[in]  aSettings  The message settings.
      *
-     * @returns A pointer to the message or nullptr if no buffers are available.
+     * @returns A pointer to the message or `nullptr` if no buffers are available.
      *
      */
     Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings = Message::Settings::GetDefault());
@@ -651,6 +652,10 @@
  */
 
 } // namespace Ip6
+
+DefineCoreType(otUdpSocket, Ip6::Udp::SocketHandle);
+DefineCoreType(otUdpReceiver, Ip6::Udp::Receiver);
+
 } // namespace ot
 
 #endif // UDP6_HPP_
diff --git a/src/core/openthread-core-config.h b/src/core/openthread-core-config.h
index d5f10fc..da7e185 100644
--- a/src/core/openthread-core-config.h
+++ b/src/core/openthread-core-config.h
@@ -37,8 +37,10 @@
 #include <openthread/config.h>
 
 #define OT_THREAD_VERSION_INVALID 0
+
 #define OT_THREAD_VERSION_1_1 2
 #define OT_THREAD_VERSION_1_2 3
+#define OT_THREAD_VERSION_1_3 4
 
 #define OPENTHREAD_CORE_CONFIG_H_IN
 
@@ -51,11 +53,9 @@
 #endif
 
 #ifndef OPENTHREAD_CONFIG_THREAD_VERSION
-#define OPENTHREAD_CONFIG_THREAD_VERSION OT_THREAD_VERSION_1_2
+#define OPENTHREAD_CONFIG_THREAD_VERSION OT_THREAD_VERSION_1_3
 #endif
 
-#include "config/openthread-core-default-config.h"
-
 #include "config/announce_sender.h"
 #include "config/backbone_router.h"
 #include "config/border_router.h"
@@ -70,6 +70,7 @@
 #include "config/dhcp6_server.h"
 #include "config/diag.h"
 #include "config/dns_client.h"
+#include "config/dns_dso.h"
 #include "config/dnssd_server.h"
 #include "config/dtls.h"
 #include "config/history_tracker.h"
@@ -79,6 +80,7 @@
 #include "config/link_raw.h"
 #include "config/logging.h"
 #include "config/mac.h"
+#include "config/misc.h"
 #include "config/mle.h"
 #include "config/netdata_publisher.h"
 #include "config/parent_search.h"
diff --git a/src/core/radio.cmake b/src/core/radio.cmake
index 5e4078b..f70a8dd 100644
--- a/src/core/radio.cmake
+++ b/src/core/radio.cmake
@@ -47,8 +47,12 @@
   target_sources(openthread-radio PRIVATE ${OT_VENDOR_EXTENSION})
 endif()
 
+if(NOT DEFINED OT_MBEDTLS_RCP)
+    set(OT_MBEDTLS_RCP ${OT_MBEDTLS})
+endif()
+
 target_link_libraries(openthread-radio
     PRIVATE
-        ${OT_MBEDTLS}
+        ${OT_MBEDTLS_RCP}
         ot-config
 )
diff --git a/src/core/radio/radio.hpp b/src/core/radio/radio.hpp
index 63e6911..aa7233e 100644
--- a/src/core/radio/radio.hpp
+++ b/src/core/radio/radio.hpp
@@ -81,6 +81,7 @@
     friend class Instance;
 
 public:
+    static constexpr uint32_t kSymbolTime = OT_RADIO_SYMBOL_TIME;
 #if (OPENTHREAD_CONFIG_RADIO_2P4GHZ_OQPSK_SUPPORT && OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT)
     static constexpr uint16_t kNumChannelPages = 2;
     static constexpr uint32_t kSupportedChannels =
@@ -127,7 +128,7 @@
         /**
          * This callback method handles a "Receive Done" event from radio platform.
          *
-         * @param[in]  aFrame    A pointer to the received frame or nullptr if the receive operation failed.
+         * @param[in]  aFrame    A pointer to the received frame or `nullptr` if the receive operation failed.
          * @param[in]  aError    kErrorNone when successfully received a frame,
          *                       kErrorAbort when reception was aborted and a frame was not received,
          *                       kErrorNoBufs when a frame could not be received due to lack of rx buffer space.
@@ -147,7 +148,7 @@
          * This callback method handles a "Transmit Done" event from radio platform.
          *
          * @param[in]  aFrame     The frame that was transmitted.
-         * @param[in]  aAckFrame  A pointer to the ACK frame, nullptr if no ACK was received.
+         * @param[in]  aAckFrame  A pointer to the ACK frame, `nullptr` if no ACK was received.
          * @param[in]  aError     kErrorNone when the frame was transmitted,
          *                        kErrorNoAck when the frame was transmitted but no ACK was received,
          *                        kErrorChannelAccessFailure tx could not take place due to activity on the
@@ -162,8 +163,7 @@
          * This method is used when radio provides OT_RADIO_CAPS_ENERGY_SCAN capability. It is called from
          * `otPlatRadioEnergyScanDone()`.
          *
-         * @param[in]  aInstance           The OpenThread instance structure.
-         * @param[in]  aEnergyScanMaxRssi  The maximum RSSI encountered on the scanned channel.
+         * @param[in]  aMaxRssi  The maximum RSSI encountered on the scanned channel.
          *
          */
         void HandleEnergyScanDone(int8_t aMaxRssi);
@@ -172,7 +172,7 @@
         /**
          * This callback method handles a "Receive Done" event from radio platform when diagnostics mode is enabled.
          *
-         * @param[in]  aFrame    A pointer to the received frame or nullptr if the receive operation failed.
+         * @param[in]  aFrame    A pointer to the received frame or `nullptr` if the receive operation failed.
          * @param[in]  aError    kErrorNone when successfully received a frame,
          *                       kErrorAbort when reception was aborted and a frame was not received,
          *                       kErrorNoBufs when a frame could not be received due to lack of rx buffer space.
@@ -473,14 +473,12 @@
     uint8_t GetCslAccuracy(void);
 
     /**
-     * Get the current uncertainty, in units of 10 us, of the clock used for scheduling CSL operations.
+     * Get the fixed uncertainty of the Device for scheduling CSL Transmissions in units of 10 microseconds.
      *
-     * @param[in]   aInstance    A pointer to an OpenThread instance.
-     *
-     * @returns The current CSL Clock Uncertainty in units of 10 us.
+     * @returns The CSL Uncertainty in units of 10 us.
      *
      */
-    uint8_t GetCslClockUncertainty(void);
+    uint8_t GetCslUncertainty(void);
 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
 
     /**
@@ -524,6 +522,7 @@
      * @param[in] aScanDuration  The duration, in milliseconds, for the channel to be scanned.
      *
      * @retval kErrorNone            Successfully started scanning the channel.
+     * @retval kErrorBusy            The radio is performing energy scanning.
      * @retval kErrorNotImplemented  The radio doesn't support energy scanning.
      *
      */
@@ -629,12 +628,11 @@
      * starts/stops to collect Link Metrics data and include Vendor-Specific IE that containing the data
      * in Enhanced-ACK sent to that Probing Initiator.
      *
-     * @param[in]  aInstance    The OpenThread instance structure.
-     * @param[in]  aDataLength  Length of Link Metrics data in the Vendor-Specific IE. Per spec 4.11.3.4.4.6,
-     *                          @p aDataLength should only be 1 or 2. The probing would be disabled if `aDataLength` is
-     *                          `0`.
-     * @param[in]  aShortAddr   The short address of the the probing Initiator.
-     * @param[in]  aExtAddr     The extended source address of the probing Initiator.
+     * @param[in]  aLinkMetrics  This parameter specifies what metrics to query. Per spec 4.11.3.4.4.6, at most 2
+     *                           metrics can be specified. The probing would be disabled if @p `aLinkMetrics` is
+     *                           bitwise 0.
+     * @param[in]  aShortAddress The short address of the the probing Initiator.
+     * @param[in]  aExtAddress   The extended source address of the probing Initiator.
      *
      * @retval kErrorNone            Successfully enable/disable or update Enhanced-ACK Based Probing for a specific
      *                               Initiator.
@@ -812,10 +810,12 @@
 {
     return otPlatRadioGetCslAccuracy(GetInstancePtr());
 }
+#endif
 
-inline uint8_t Radio::GetCslClockUncertainty(void)
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+inline uint8_t Radio::GetCslUncertainty(void)
 {
-    return otPlatRadioGetCslClockUncertainty(GetInstancePtr());
+    return otPlatRadioGetCslUncertainty(GetInstancePtr());
 }
 #endif
 
@@ -982,7 +982,7 @@
     return UINT8_MAX;
 }
 
-inline uint8_t Radio::GetCslClockUncertainty(void)
+inline uint8_t Radio::GetCslUncertainty(void)
 {
     return UINT8_MAX;
 }
diff --git a/src/core/radio/radio_platform.cpp b/src/core/radio/radio_platform.cpp
index 87ec5e6..fe994c1 100644
--- a/src/core/radio/radio_platform.cpp
+++ b/src/core/radio/radio_platform.cpp
@@ -250,11 +250,11 @@
     return UINT8_MAX;
 }
 
-OT_TOOL_WEAK uint8_t otPlatRadioGetCslClockUncertainty(otInstance *aInstance)
+OT_TOOL_WEAK uint8_t otPlatRadioGetCslUncertainty(otInstance *aInstance)
 {
     OT_UNUSED_VARIABLE(aInstance);
 
-    return OPENTHREAD_CONFIG_PLATFORM_CSL_UNCERT;
+    return UINT8_MAX;
 }
 
 OT_TOOL_WEAK otError otPlatRadioGetFemLnaGain(otInstance *aInstance, int8_t *aGain)
diff --git a/src/core/radio/trel_interface.cpp b/src/core/radio/trel_interface.cpp
index b541b94..68825e9 100644
--- a/src/core/radio/trel_interface.cpp
+++ b/src/core/radio/trel_interface.cpp
@@ -34,101 +34,393 @@
 
 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
 
-#include <openthread/platform/trel-udp6.h>
+#include <string.h>
 
+#include "common/array.hpp"
+#include "common/as_core_type.hpp"
 #include "common/code_utils.hpp"
+#include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
+#include "common/string.hpp"
+#include "net/dns_types.hpp"
 
 namespace ot {
 namespace Trel {
 
+RegisterLogModule("TrelInterface");
+
+const char Interface::kTxtRecordExtAddressKey[] = "xa";
+const char Interface::kTxtRecordExtPanIdKey[]   = "xp";
+
 Interface::Interface(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mInitialized(false)
+    , mEnabled(false)
+    , mFiltered(false)
+    , mRegisterServiceTask(aInstance, HandleRegisterServiceTask)
 {
 }
 
 void Interface::Init(void)
 {
-    Ip6::Address ip6Address;
-
     OT_ASSERT(!mInitialized);
 
-    ip6Address.SetToLinkLocalAddress(Get<Mac::Mac>().GetExtAddress());
-    otPlatTrelUdp6Init(&GetInstance(), &ip6Address, kUdpPort);
-
-    CreateMulticastIp6Address(ip6Address);
-    otPlatTrelUdp6SubscribeMulticastAddress(&GetInstance(), &ip6Address);
-
     mInitialized = true;
+
+    if (mEnabled)
+    {
+        mEnabled = false;
+        Enable();
+    }
+}
+
+void Interface::Enable(void)
+{
+    VerifyOrExit(!mEnabled);
+
+    mEnabled = true;
+    VerifyOrExit(mInitialized);
+
+    otPlatTrelEnable(&GetInstance(), &mUdpPort);
+
+    LogInfo("Enabled interface, local port:%u", mUdpPort);
+    mRegisterServiceTask.Post();
+
+exit:
+    return;
+}
+
+void Interface::Disable(void)
+{
+    VerifyOrExit(mEnabled);
+
+    mEnabled = false;
+    VerifyOrExit(mInitialized);
+
+    otPlatTrelDisable(&GetInstance());
+    mPeerTable.Clear();
+    LogDebg("Disabled interface");
+
+exit:
+    return;
 }
 
 void Interface::HandleExtAddressChange(void)
 {
-    Ip6::Address ip6Address;
-
-    VerifyOrExit(mInitialized);
-
-    ip6Address.SetToLinkLocalAddress(Get<Mac::Mac>().GetExtAddress());
-    otPlatTrelUdp6UpdateAddress(&GetInstance(), &ip6Address);
+    VerifyOrExit(mInitialized && mEnabled);
+    LogDebg("Extended Address changed, re-registering DNS-SD service");
+    mRegisterServiceTask.Post();
 
 exit:
     return;
 }
 
-Error Interface::Send(const Packet &aPacket)
+void Interface::HandleExtPanIdChange(void)
 {
-    Ip6::Address destIp6Address;
+    VerifyOrExit(mInitialized && mEnabled);
+    LogDebg("Extended PAN ID changed, re-registering DNS-SD service");
+    mRegisterServiceTask.Post();
+
+exit:
+    return;
+}
+
+void Interface::HandleRegisterServiceTask(Tasklet &aTasklet)
+{
+    aTasklet.Get<Interface>().RegisterService();
+}
+
+void Interface::RegisterService(void)
+{
+    // TXT data consists of two entries: the length fields, the
+    // "key" string, "=" char, and binary representation of the MAC
+    // or Extended PAN ID values.
+    static constexpr uint8_t kTxtDataSize =
+        /* ExtAddr  */ sizeof(uint8_t) + sizeof(kTxtRecordExtAddressKey) - 1 + sizeof(char) + sizeof(Mac::ExtAddress) +
+        /* ExtPanId */ sizeof(uint8_t) + sizeof(kTxtRecordExtPanIdKey) - 1 + sizeof(char) +
+        sizeof(MeshCoP::ExtendedPanId);
+
+    uint8_t                        txtDataBuffer[kTxtDataSize];
+    MutableData<kWithUint16Length> txtData;
+    Dns::TxtEntry                  txtEntries[2];
+
+    VerifyOrExit(mInitialized && mEnabled);
+
+    txtEntries[0].Init(kTxtRecordExtAddressKey, Get<Mac::Mac>().GetExtAddress().m8, sizeof(Mac::ExtAddress));
+    txtEntries[1].Init(kTxtRecordExtPanIdKey, Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId().m8,
+                       sizeof(MeshCoP::ExtendedPanId));
+
+    txtData.Init(txtDataBuffer, sizeof(txtDataBuffer));
+    SuccessOrAssert(Dns::TxtEntry::AppendEntries(txtEntries, GetArrayLength(txtEntries), txtData));
+
+    LogInfo("Registering DNS-SD service: port:%u, txt:\"%s=%s, %s=%s\"", mUdpPort, kTxtRecordExtAddressKey,
+            Get<Mac::Mac>().GetExtAddress().ToString().AsCString(), kTxtRecordExtPanIdKey,
+            Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId().ToString().AsCString());
+
+    otPlatTrelRegisterService(&GetInstance(), mUdpPort, txtData.GetBytes(), static_cast<uint8_t>(txtData.GetLength()));
+
+exit:
+    return;
+}
+
+extern "C" void otPlatTrelHandleDiscoveredPeerInfo(otInstance *aInstance, const otPlatTrelPeerInfo *aInfo)
+{
+    Instance &instance = AsCoreType(aInstance);
+
+    VerifyOrExit(instance.IsInitialized());
+    instance.Get<Interface>().HandleDiscoveredPeerInfo(*static_cast<const Interface::Peer::Info *>(aInfo));
+
+exit:
+    return;
+}
+
+void Interface::HandleDiscoveredPeerInfo(const Peer::Info &aInfo)
+{
+    Peer *                 entry;
+    Mac::ExtAddress        extAddress;
+    MeshCoP::ExtendedPanId extPanId;
+    bool                   isNew = false;
+
+    VerifyOrExit(mInitialized && mEnabled);
+
+    SuccessOrExit(ParsePeerInfoTxtData(aInfo, extAddress, extPanId));
+
+    VerifyOrExit(extAddress != Get<Mac::Mac>().GetExtAddress());
+
+    if (aInfo.IsRemoved())
+    {
+        entry = mPeerTable.FindMatching(extAddress);
+        VerifyOrExit(entry != nullptr);
+        RemovePeerEntry(*entry);
+        ExitNow();
+    }
+
+    // It is a new entry or an update to an existing entry. First
+    // check whether we have an existing entry that matches the same
+    // socket address, and remove it if it is associated with a
+    // different Extended MAC address. This ensures that we do not
+    // keep stale entries in the peer table.
+
+    entry = mPeerTable.FindMatching(aInfo.GetSockAddr());
+
+    if ((entry != nullptr) && !entry->Matches(extAddress))
+    {
+        RemovePeerEntry(*entry);
+        entry = nullptr;
+    }
+
+    if (entry == nullptr)
+    {
+        entry = mPeerTable.FindMatching(extAddress);
+    }
+
+    if (entry == nullptr)
+    {
+        entry = GetNewPeerEntry();
+        VerifyOrExit(entry != nullptr);
+
+        entry->SetExtAddress(extAddress);
+        isNew = true;
+    }
+
+    if (!isNew)
+    {
+        VerifyOrExit((entry->GetExtPanId() != extPanId) || (entry->GetSockAddr() != aInfo.GetSockAddr()));
+    }
+
+    entry->SetExtPanId(extPanId);
+    entry->SetSockAddr(aInfo.GetSockAddr());
+
+    entry->Log(isNew ? "Added" : "Updated");
+
+exit:
+    return;
+}
+
+Error Interface::ParsePeerInfoTxtData(const Peer::Info &      aInfo,
+                                      Mac::ExtAddress &       aExtAddress,
+                                      MeshCoP::ExtendedPanId &aExtPanId) const
+{
+    Error                   error;
+    Dns::TxtEntry           entry;
+    Dns::TxtEntry::Iterator iterator;
+    bool                    parsedExtAddress = false;
+    bool                    parsedExtPanId   = false;
+
+    aExtPanId.Clear();
+
+    iterator.Init(aInfo.GetTxtData(), aInfo.GetTxtLength());
+
+    while ((error = iterator.GetNextEntry(entry)) == kErrorNone)
+    {
+        if (strcmp(entry.mKey, kTxtRecordExtAddressKey) == 0)
+        {
+            VerifyOrExit(!parsedExtAddress, error = kErrorParse);
+            VerifyOrExit(entry.mValueLength == sizeof(Mac::ExtAddress), error = kErrorParse);
+            aExtAddress.Set(entry.mValue);
+            parsedExtAddress = true;
+        }
+        else if (strcmp(entry.mKey, kTxtRecordExtPanIdKey) == 0)
+        {
+            VerifyOrExit(!parsedExtPanId, error = kErrorParse);
+            VerifyOrExit(entry.mValueLength == sizeof(MeshCoP::ExtendedPanId), error = kErrorParse);
+            memcpy(aExtPanId.m8, entry.mValue, sizeof(MeshCoP::ExtendedPanId));
+            parsedExtPanId = true;
+        }
+
+        // Skip over and ignore any unknown keys.
+    }
+
+    VerifyOrExit(error == kErrorNotFound);
+    error = kErrorNone;
+
+    VerifyOrExit(parsedExtAddress && parsedExtPanId, error = kErrorParse);
+
+exit:
+    return error;
+}
+
+Interface::Peer *Interface::GetNewPeerEntry(void)
+{
+    Peer *peerEntry;
+
+    peerEntry = mPeerTable.PushBack();
+    VerifyOrExit(peerEntry == nullptr);
+
+    for (Peer &entry : mPeerTable)
+    {
+        if (entry.GetExtPanId() != Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId())
+        {
+            ExitNow(peerEntry = &entry);
+        }
+    }
+
+    for (Peer &entry : mPeerTable)
+    {
+        // We skip over any existing entry in neighbor table (even if the
+        // entry is in invalid state).
+
+        if (Get<NeighborTable>().FindNeighbor(entry.GetExtAddress(), Neighbor::kInStateAny) != nullptr)
+        {
+            continue;
+        }
+
+#if OPENTHREAD_FTD
+        {
+            Mac::Address macAddress;
+
+            macAddress.SetExtended(entry.GetExtAddress());
+
+            if (Get<NeighborTable>().FindRxOnlyNeighborRouter(macAddress) != nullptr)
+            {
+                continue;
+            }
+        }
+#endif
+
+        ExitNow(peerEntry = &entry);
+    }
+
+exit:
+    return peerEntry;
+}
+
+void Interface::RemovePeerEntry(Peer &aEntry)
+{
+    aEntry.Log("Removing");
+
+    // Replace the entry being removed with the last entry (if not the
+    // last one already) and then pop the last entry from array.
+
+    if (&aEntry != mPeerTable.Back())
+    {
+        aEntry = *mPeerTable.Back();
+    }
+
+    mPeerTable.PopBack();
+}
+
+Error Interface::Send(const Packet &aPacket, bool aIsDiscovery)
+{
+    Error error = kErrorNone;
+    Peer *peerEntry;
+
+    VerifyOrExit(mInitialized && mEnabled, error = kErrorAbort);
+    VerifyOrExit(!mFiltered);
 
     switch (aPacket.GetHeader().GetType())
     {
     case Header::kTypeBroadcast:
-        CreateMulticastIp6Address(destIp6Address);
+        for (Peer &entry : mPeerTable)
+        {
+            if (!aIsDiscovery && (entry.GetExtPanId() != Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId()))
+            {
+                continue;
+            }
+
+            otPlatTrelSend(&GetInstance(), aPacket.GetBuffer(), aPacket.GetLength(), &entry.mSockAddr);
+        }
         break;
 
     case Header::kTypeUnicast:
     case Header::kTypeAck:
-        destIp6Address.SetToLinkLocalAddress(aPacket.GetHeader().GetDestination());
+        peerEntry = mPeerTable.FindMatching(aPacket.GetHeader().GetDestination());
+        VerifyOrExit(peerEntry != nullptr, error = kErrorAbort);
+        otPlatTrelSend(&GetInstance(), aPacket.GetBuffer(), aPacket.GetLength(), &peerEntry->mSockAddr);
         break;
     }
 
-    return otPlatTrelUdp6SendTo(&GetInstance(), aPacket.GetBuffer(), aPacket.GetLength(), &destIp6Address);
+exit:
+    return error;
 }
 
-void Interface::HandleReceived(uint8_t *aBuffer, uint16_t aLength)
+extern "C" void otPlatTrelHandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength)
 {
-    mRxPacket.Init(aBuffer, aLength);
-    Get<Link>().ProcessReceivedPacket(mRxPacket);
-}
-
-void Interface::CreateMulticastIp6Address(Ip6::Address &aIp6Address)
-{
-    // Use ff02::1 (Link-local All Nodes multicast address).
-    aIp6Address.SetToLinkLocalAllNodesMulticast();
-}
-
-} // namespace Trel
-} // namespace ot
-
-extern "C" void otPlatTrelUdp6HandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength)
-{
-    ot::Instance &instance = *static_cast<ot::Instance *>(aInstance);
+    Instance &instance = AsCoreType(aInstance);
 
     VerifyOrExit(instance.IsInitialized());
-    instance.Get<ot::Trel::Interface>().HandleReceived(aBuffer, aLength);
+    instance.Get<Interface>().HandleReceived(aBuffer, aLength);
 
 exit:
     return;
 }
 
-extern "C" OT_TOOL_WEAK otError otPlatTrelUdp6SetTestMode(otInstance *aInstance, bool aEnable)
+void Interface::HandleReceived(uint8_t *aBuffer, uint16_t aLength)
 {
-    OT_UNUSED_VARIABLE(aInstance);
-    OT_UNUSED_VARIABLE(aEnable);
+    LogDebg("HandleReceived(aLength:%u)", aLength);
 
-    return ot::kErrorNotImplemented;
+    VerifyOrExit(mInitialized && mEnabled && !mFiltered);
+
+    mRxPacket.Init(aBuffer, aLength);
+    Get<Link>().ProcessReceivedPacket(mRxPacket);
+
+exit:
+    return;
 }
 
+const Interface::Peer *Interface::GetNextPeer(PeerIterator &aIterator) const
+{
+    const Peer *entry = mPeerTable.At(aIterator);
+
+    if (entry != nullptr)
+    {
+        aIterator++;
+    }
+
+    return entry;
+}
+
+void Interface::Peer::Log(const char *aAction) const
+{
+    OT_UNUSED_VARIABLE(aAction);
+
+    LogInfo("%s peer mac:%s, xpan:%s, %s", aAction, GetExtAddress().ToString().AsCString(),
+            GetExtPanId().ToString().AsCString(), GetSockAddr().ToString().AsCString());
+}
+
+} // namespace Trel
+} // namespace ot
+
 #endif // #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
diff --git a/src/core/radio/trel_interface.hpp b/src/core/radio/trel_interface.hpp
index 1d84f7f..b80bf1b 100644
--- a/src/core/radio/trel_interface.hpp
+++ b/src/core/radio/trel_interface.hpp
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2019, The OpenThread Authors.
+ *  Copyright (c) 2019-2021, The OpenThread Authors.
  *  All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -38,82 +38,225 @@
 
 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
 
+#include <openthread/trel.h>
+#include <openthread/platform/trel.h>
+
+#include "common/array.hpp"
 #include "common/locator.hpp"
+#include "common/tasklet.hpp"
+#include "common/time.hpp"
 #include "mac/mac_types.hpp"
 #include "net/ip6_address.hpp"
+#include "net/socket.hpp"
 #include "radio/trel_packet.hpp"
+#include "thread/mle_types.hpp"
 
 namespace ot {
 namespace Trel {
 
+class Link;
+
+extern "C" void otPlatTrelHandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength);
+extern "C" void otPlatTrelHandleDiscoveredPeerInfo(otInstance *aInstance, const otPlatTrelPeerInfo *aInfo);
+
 /**
  * This class represents a TREL link interface.
  *
  */
 class Interface : public InstanceLocator
 {
+    friend class Link;
+    friend void otPlatTrelHandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength);
+    friend void otPlatTrelHandleDiscoveredPeerInfo(otInstance *aInstance, const otPlatTrelPeerInfo *aInfo);
+
 public:
     /**
-     * This method initializes an `Interface` object
-     *
-     * @param[in]  aInstance  A reference to the OpenThread instance.
+     * This class represents information about a discovered TREL peer.
      *
      */
-    explicit Interface(Instance &aInstance);
+    class Peer : public otTrelPeer
+    {
+        friend class Interface;
+        friend void otPlatTrelHandleDiscoveredPeerInfo(otInstance *aInstance, const otPlatTrelPeerInfo *aInfo);
+
+    public:
+        /**
+         * This method returns the Extended MAC Address of the discovered TREL peer.
+         *
+         * @returns The Extended MAC Address of the TREL peer.
+         *
+         */
+        const Mac::ExtAddress &GetExtAddress(void) const { return static_cast<const Mac::ExtAddress &>(mExtAddress); }
+
+        /**
+         * This method returns the Extended PAN Identifier of the discovered TREL peer.
+         *
+         * @returns The Extended PAN Identifier of the TREL peer.
+         *
+         */
+        const MeshCoP::ExtendedPanId &GetExtPanId(void) const
+        {
+            return static_cast<const MeshCoP::ExtendedPanId &>(mExtPanId);
+        }
+
+        /**
+         * This method returns the IPv6 socket address of the discovered TREL peer.
+         *
+         * @returns The IPv6 socket address of the TREP peer.
+         *
+         */
+        const Ip6::SockAddr &GetSockAddr(void) const { return static_cast<const Ip6::SockAddr &>(mSockAddr); }
+
+        /**
+         * This method indicates whether the peer matches a given Extended Address.
+         *
+         * @param[in] aExtAddress   A Extended Address to match with.
+         *
+         * @retval TRUE if the peer matches @p aExtAddress.
+         * @retval FALSE if the peer does not match @p aExtAddress.
+         *
+         */
+        bool Matches(const Mac::ExtAddress &aExtAddress) const { return GetExtAddress() == aExtAddress; }
+
+        /**
+         * This method indicates whether the peer matches a given Socket Address.
+         *
+         * @param[in] aSockAddr   A Socket Address to match with.
+         *
+         * @retval TRUE if the peer matches @p aSockAddr.
+         * @retval FALSE if the peer does not match @p aSockAddr.
+         *
+         */
+        bool Matches(const Ip6::SockAddr &aSockAddr) const { return GetSockAddr() == aSockAddr; }
+
+    private:
+        class Info : public otPlatTrelPeerInfo
+        {
+        public:
+            bool                 IsRemoved(void) const { return mRemoved; }
+            const uint8_t *      GetTxtData(void) const { return mTxtData; }
+            uint16_t             GetTxtLength(void) const { return mTxtLength; }
+            const Ip6::SockAddr &GetSockAddr(void) const { return static_cast<const Ip6::SockAddr &>(mSockAddr); }
+        };
+
+        void SetExtAddress(const Mac::ExtAddress &aExtAddress) { mExtAddress = aExtAddress; }
+        void SetExtPanId(const MeshCoP::ExtendedPanId &aExtPanId) { mExtPanId = aExtPanId; }
+        void SetSockAddr(const Ip6::SockAddr &aSockAddr) { mSockAddr = aSockAddr; }
+        void Log(const char *aAction) const;
+    };
 
     /**
-     * This method initializes the interface.
-     *
-     * This method should be called after OpenThread instance itself is fully initialized, allowing the `Init()` method
-     * to use method from `Instance` and any of its containing objects.
+     * This type represents an iterator for iterating over TREL peer table entries.
      *
      */
-    void Init(void);
+    typedef otTrelPeerIterator PeerIterator;
 
     /**
-     * This method indicates whether the interface is initialized or not.
+     * This method enables the TREL interface.
      *
-     * @returns TRUE if the interface is initialized, FALSE otherwise.
+     * This call initiates an ongoing DNS-SD browse on the service name "_trel._udp" within the local browsing domain
+     * to discover other devices supporting TREL. Device also registers a new service to be advertised using DNS-SD,
+     * with the service name is "_trel._udp" indicating its support for TREL. Device is ready to receive TREL messages
+     * from peers.
      *
      */
-    bool IsInitialized(void) const { return mInitialized; }
+    void Enable(void);
 
     /**
-     * This method notifies the interface that device's extended MAC address has changed for it to update any
-     * internal address/state.
+     * This method disables the TREL interface.
+     *
+     * This call stops the DNS-SD browse on the service name "_trel._udp", stops advertising TREL DNS-SD service, and
+     * clears the TREL peer table.
      *
      */
-    void HandleExtAddressChange(void);
+    void Disable(void);
 
     /**
-     * This method sends a packet over the interface.
+     * This method indicates whether the TREL interface is enabled.
      *
-     * @note There is no expected callback from the interface to notify completion of send.
-     *
-     * @param[in] aPacket   A packet to send.
-     *
-     * @retval kErrorNone   The frame was sent successfully.
-     * @retval kErrorAbort  The interface is not ready and send was aborted.
+     * @retval TRUE if the TREL interface is enabled.
+     * @retval FALSE if the TREL interface is disabled.
      *
      */
-    Error Send(const Packet &aPacket);
+    bool IsEnabled(void) const { return mEnabled; }
 
     /**
-     * This method is a callback from platform layer to handle a received packet over the interface.
+     * This method initializes a peer table iterator.
      *
-     * @param[in] aBuffer  A pointer to buffer containing the received packet.
-     * @param[in] aLength  The length (number of bytes) in the received packet.
+     * @param[in] aIterator   The iterator to initialize.
      *
      */
-    void HandleReceived(uint8_t *aBuffer, uint16_t aLength);
+    void InitIterator(PeerIterator &aIterator) const { aIterator = 0; }
+
+    /**
+     * This method iterates over the peer table entries.
+     *
+     * @param[in] aIterator   The iterator. MUST be initialized.
+     *
+     * @returns A pointer to the next `Peer` entry or `nullptr` if no more entries in the table.
+     *
+     */
+    const Peer *GetNextPeer(PeerIterator &aIterator) const;
+
+    /**
+     * This method sets the filter mode (enables/disables filtering).
+     *
+     * When filtering is enabled, any rx and tx traffic through TREL interface is silently dropped. This is mainly
+     * intended for use during testing.
+     *
+     * Unlike `Enable()/Disable()` which fully start/stop the TREL interface operation, when filter mode is enabled the
+     * TREL interface continues to be enabled.
+     *
+     * @param[in] aFiltered  TRUE to enable filter mode, FALSE to disable filter mode.
+     *
+     */
+    void SetFilterEnabled(bool aEnable) { mFiltered = aEnable; }
+
+    /**
+     * This method indicates whether or not the filter mode is enabled.
+     *
+     * @retval TRUE if the TREL filter mode is enabled.
+     * @retval FALSE if the TREL filter mode is disabled.
+     *
+     */
+    bool IsFilterEnabled(void) const { return mFiltered; }
 
 private:
-    static constexpr uint16_t kUdpPort = 19788; // UDP port (same as MLE port).
+    static constexpr uint16_t kPeerTableExtraEntries = 32;
+    static constexpr uint16_t kPeerTableSize         = Mle::kMaxRouters + Mle::kMaxChildren + kPeerTableExtraEntries;
 
-    void CreateMulticastIp6Address(Ip6::Address &aIp6Address);
+    static const char kTxtRecordExtAddressKey[];
+    static const char kTxtRecordExtPanIdKey[];
 
-    bool   mInitialized;
-    Packet mRxPacket;
+    typedef Array<Peer, kPeerTableSize, uint16_t> PeerTable;
+
+    explicit Interface(Instance &aInstance);
+
+    // Methods used by `Trel::Link`.
+    void  Init(void);
+    void  HandleExtAddressChange(void);
+    void  HandleExtPanIdChange(void);
+    Error Send(const Packet &aPacket, bool aIsDiscovery = false);
+
+    // Callbacks from `otPlatTrel`.
+    void HandleReceived(uint8_t *aBuffer, uint16_t aLength);
+    void HandleDiscoveredPeerInfo(const Peer::Info &aInfo);
+
+    static void HandleRegisterServiceTask(Tasklet &aTasklet);
+    void        RegisterService(void);
+    Error       ParsePeerInfoTxtData(const Peer::Info &      aInfo,
+                                     Mac::ExtAddress &       aExtAddress,
+                                     MeshCoP::ExtendedPanId &aExtPanId) const;
+    Peer *      GetNewPeerEntry(void);
+    void        RemovePeerEntry(Peer &aEntry);
+
+    bool      mInitialized : 1;
+    bool      mEnabled : 1;
+    bool      mFiltered : 1;
+    Tasklet   mRegisterServiceTask;
+    uint16_t  mUdpPort;
+    Packet    mRxPacket;
+    PeerTable mPeerTable;
 };
 
 } // namespace Trel
diff --git a/src/core/radio/trel_link.cpp b/src/core/radio/trel_link.cpp
index eb8e0c1..549633b 100644
--- a/src/core/radio/trel_link.cpp
+++ b/src/core/radio/trel_link.cpp
@@ -38,11 +38,13 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 
 namespace ot {
 namespace Trel {
 
+RegisterLogModule("TrelLink");
+
 Link::Link(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mState(kStateDisabled)
@@ -75,6 +77,8 @@
 
 void Link::Enable(void)
 {
+    mInterface.Enable();
+
     if (mState == kStateDisabled)
     {
         SetState(kStateSleep);
@@ -83,6 +87,8 @@
 
 void Link::Disable(void)
 {
+    mInterface.Disable();
+
     if (mState != kStateDisabled)
     {
         SetState(kStateDisabled);
@@ -126,8 +132,9 @@
     Mac::PanId    destPanId;
     Header::Type  type;
     Packet        txPacket;
-    Neighbor *    neighbor = nullptr;
-    Mac::RxFrame *ackFrame = nullptr;
+    Neighbor *    neighbor   = nullptr;
+    Mac::RxFrame *ackFrame   = nullptr;
+    bool          isDisovery = false;
 
     VerifyOrExit(mState == kStateTransmit);
 
@@ -163,6 +170,28 @@
         }
     }
 
+    if (type == Header::kTypeBroadcast)
+    {
+        // Thread utilizes broadcast transmissions to discover
+        // neighboring devices. We determine whether this broadcast
+        // frame tx is a discovery or normal data. All messages
+        // used for discovery either disable MAC security or utilize
+        // MAC Key ID mode 2. All data communication uses MAC Key ID
+        // Mode 1.
+
+        if (!mTxFrame.GetSecurityEnabled())
+        {
+            isDisovery = true;
+        }
+        else
+        {
+            uint8_t keyIdMode;
+
+            IgnoreError(mTxFrame.GetKeyIdMode(keyIdMode));
+            isDisovery = (keyIdMode == Mac::Frame::kKeyIdMode2);
+        }
+    }
+
     if (mTxFrame.GetDstPanId(destPanId) != kErrorNone)
     {
         destPanId = Mac::kPanIdBroadcast;
@@ -192,10 +221,9 @@
         txPacket.GetHeader().SetDestination(destAddr.GetExtended());
     }
 
-    otLogDebgMac("Trel: BeginTransmit() [%s] plen:%d", txPacket.GetHeader().ToString().AsCString(),
-                 txPacket.GetPayloadLength());
+    LogDebg("BeginTransmit() [%s] plen:%d", txPacket.GetHeader().ToString().AsCString(), txPacket.GetPayloadLength());
 
-    VerifyOrExit(mInterface.Send(txPacket) == kErrorNone, InvokeSendDone(kErrorAbort));
+    VerifyOrExit(mInterface.Send(txPacket, isDisovery) == kErrorNone, InvokeSendDone(kErrorAbort));
 
     if (mTxFrame.GetAckRequest())
     {
@@ -345,8 +373,7 @@
         }
     }
 
-    otLogDebgMac("Trel: ReceivedPacket() [%s] plen:%d", aPacket.GetHeader().ToString().AsCString(),
-                 aPacket.GetPayloadLength());
+    LogDebg("ReceivedPacket() [%s] plen:%d", aPacket.GetHeader().ToString().AsCString(), aPacket.GetPayloadLength());
 
     if (aPacket.GetHeader().GetAckMode() == Header::kAckRequested)
     {
@@ -377,7 +404,7 @@
     Neighbor *   neighbor;
     uint32_t     ackNumber;
 
-    otLogDebgMac("Trel: HandleAck() [%s]", aAckPacket.GetHeader().ToString().AsCString());
+    LogDebg("HandleAck() [%s]", aAckPacket.GetHeader().ToString().AsCString());
 
     srcAddress.SetExtended(aAckPacket.GetHeader().GetSource());
     neighbor = Get<NeighborTable>().FindNeighbor(srcAddress, Neighbor::kInStateAnyExceptInvalid);
@@ -423,15 +450,15 @@
     ackPacket.GetHeader().SetSource(Get<Mac::Mac>().GetExtAddress());
     ackPacket.GetHeader().SetDestination(aRxPacket.GetHeader().GetSource());
 
-    otLogDebgMac("Trel: SendAck [%s]", ackPacket.GetHeader().ToString().AsCString());
+    LogDebg("SendAck [%s]", ackPacket.GetHeader().ToString().AsCString());
 
     IgnoreError(mInterface.Send(ackPacket));
 }
 
 void Link::ReportDeferredAckStatus(Neighbor &aNeighbor, Error aError)
 {
-    otLogDebgMac("Trel: ReportDeferredAckStatus(): %s for %s", aNeighbor.GetExtAddress().ToString().AsCString(),
-                 ErrorToString(aError));
+    LogDebg("ReportDeferredAckStatus(): %s for %s", aNeighbor.GetExtAddress().ToString().AsCString(),
+            ErrorToString(aError));
 
     Get<MeshForwarder>().HandleDeferredAck(aNeighbor, aError);
 }
@@ -440,23 +467,36 @@
 {
     if (mState != aState)
     {
-        otLogDebgMac("Trel: State: %s -> %s", StateToString(mState), StateToString(aState));
+        LogDebg("State: %s -> %s", StateToString(mState), StateToString(aState));
         mState = aState;
     }
 }
 
+void Link::HandleNotifierEvents(Events aEvents)
+{
+    if (aEvents.Contains(kEventThreadExtPanIdChanged))
+    {
+        mInterface.HandleExtPanIdChange();
+    }
+}
+
 // LCOV_EXCL_START
 
 const char *Link::StateToString(State aState)
 {
-    static const char *kStateStrings[] = {
-        "Disabled", // kStateDisabled
-        "Sleep",    // kStateSleep
-        "Receive",  // kStateReceive
-        "Transmit", // kStateTransmit
+    static const char *const kStateStrings[] = {
+        "Disabled", // (0) kStateDisabled
+        "Sleep",    // (1) kStateSleep
+        "Receive",  // (2) kStateReceive
+        "Transmit", // (3) kStateTransmit
     };
 
-    return (static_cast<uint8_t>(aState) < OT_ARRAY_LENGTH(kStateStrings)) ? kStateStrings[aState] : "Unknown";
+    static_assert(0 == kStateDisabled, "kStateDisabled value is incorrect");
+    static_assert(1 == kStateSleep, "kStateSleep value is incorrect");
+    static_assert(2 == kStateReceive, "kStateReceive value is incorrect");
+    static_assert(3 == kStateTransmit, "kStateTransmit value is incorrect");
+
+    return kStateStrings[aState];
 }
 
 // LCOV_EXCL_STOP
diff --git a/src/core/radio/trel_link.hpp b/src/core/radio/trel_link.hpp
index 617ece7..fd00ac5 100644
--- a/src/core/radio/trel_link.hpp
+++ b/src/core/radio/trel_link.hpp
@@ -40,6 +40,7 @@
 
 #include "common/encoding.hpp"
 #include "common/locator.hpp"
+#include "common/notifier.hpp"
 #include "common/tasklet.hpp"
 #include "common/timer.hpp"
 #include "mac/mac_frame.hpp"
@@ -70,6 +71,7 @@
 class Link : public InstanceLocator
 {
     friend class ot::Instance;
+    friend class ot::Notifier;
     friend class Interface;
 
 public:
@@ -170,6 +172,7 @@
     void SendAck(Packet &aRxPacket);
     void ReportDeferredAckStatus(Neighbor &aNeighbor, Error aError);
     void HandleTimer(Neighbor &aNeighbor);
+    void HandleNotifierEvents(Events aEvents);
 
     static void HandleTxTasklet(Tasklet &aTasklet);
     void        HandleTxTasklet(void);
diff --git a/src/core/radio/trel_packet.cpp b/src/core/radio/trel_packet.cpp
index ad2ae98..9b5cabd 100644
--- a/src/core/radio/trel_packet.cpp
+++ b/src/core/radio/trel_packet.cpp
@@ -38,7 +38,6 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
 
 namespace ot {
 namespace Trel {
@@ -110,12 +109,6 @@
     return string;
 }
 
-void Packet::Init(uint8_t *aBuffer, uint16_t aLength)
-{
-    mBuffer = aBuffer;
-    mLength = aLength;
-}
-
 void Packet::Init(Header::Type aType, uint8_t *aPayload, uint16_t aPayloadLength)
 {
     uint16_t headerSize = Header::GetSize(aType);
@@ -129,8 +122,8 @@
 
 bool Packet::IsHeaderValid(void) const
 {
-    return ((mBuffer != nullptr) && (mLength > 0) && GetHeader().IsVersionValid() &&
-            (mLength >= GetHeader().GetLength()));
+    return ((GetBytes() != nullptr) && (GetLength() > 0) && GetHeader().IsVersionValid() &&
+            (GetLength() >= GetHeader().GetLength()));
 }
 
 } // namespace Trel
diff --git a/src/core/radio/trel_packet.hpp b/src/core/radio/trel_packet.hpp
index 31c7ab9..5b28cb7 100644
--- a/src/core/radio/trel_packet.hpp
+++ b/src/core/radio/trel_packet.hpp
@@ -38,6 +38,7 @@
 
 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
 
+#include "common/data.hpp"
 #include "common/encoding.hpp"
 #include "common/locator.hpp"
 #include "common/string.hpp"
@@ -250,11 +251,13 @@
 } OT_TOOL_PACKED_END;
 
 /**
- * This class represent a TREL radio link packet.
+ * This class represents a TREL radio link packet.
  *
  */
-class Packet
+class Packet : private MutableData<kWithUint16Length>
 {
+    using Base = MutableData<kWithUint16Length>;
+
 public:
     /**
      * This method initializes the `Packet` with a given buffer and length.
@@ -263,7 +266,7 @@
      * @param[in] aLength  Length (number of bytes) of the packet (including header and payload).
      *
      */
-    void Init(uint8_t *aBuffer, uint16_t aLength);
+    void Init(uint8_t *aBuffer, uint16_t aLength) { Base::Init(aBuffer, aLength); }
 
     /**
      * This method initializes the `Packet` with a specified header type and given a payload.
@@ -286,7 +289,7 @@
      * @returns A pointer to buffer containing the packet.
      *
      */
-    uint8_t *GetBuffer(void) { return mBuffer; }
+    uint8_t *GetBuffer(void) { return Base::GetBytes(); }
 
     /**
      * This method gets a pointer to buffer containing the packet.
@@ -294,7 +297,7 @@
      * @returns A pointer to buffer containing the packet.
      *
      */
-    const uint8_t *GetBuffer(void) const { return mBuffer; }
+    const uint8_t *GetBuffer(void) const { return Base::GetBytes(); }
 
     /**
      * This method gets the length of packet.
@@ -302,7 +305,7 @@
      * @returns The length (number of bytes) of packet (header and payload).
      *
      */
-    uint16_t GetLength(void) const { return mLength; }
+    uint16_t GetLength(void) const { return Base::GetLength(); }
 
     /**
      * This method checks whether or not the packet header is valid.
@@ -319,7 +322,7 @@
      * @returns A reference to the packet header as `Header`.
      *
      */
-    Header &GetHeader(void) { return *reinterpret_cast<Header *>(mBuffer); }
+    Header &GetHeader(void) { return *reinterpret_cast<Header *>(Base::GetBytes()); }
 
     /**
      * This method gets the packet header.
@@ -327,7 +330,7 @@
      * @returns A reference to the packet header as `Header`.
      *
      */
-    const Header &GetHeader(void) const { return *reinterpret_cast<const Header *>(mBuffer); }
+    const Header &GetHeader(void) const { return *reinterpret_cast<const Header *>(Base::GetBytes()); }
 
     /**
      * This method gets a pointer to start of packet payload.
@@ -335,7 +338,7 @@
      * @returns A pointer to start of packet payload (after header).
      *
      */
-    uint8_t *GetPayload(void) { return mBuffer + GetHeader().GetLength(); }
+    uint8_t *GetPayload(void) { return Base::GetBytes() + GetHeader().GetLength(); }
 
     /**
      * This method gets a pointer to start of packet payload.
@@ -343,7 +346,7 @@
      * @returns A pointer to start of packet payload (after header).
      *
      */
-    const uint8_t *GetPayload(void) const { return mBuffer + GetHeader().GetLength(); }
+    const uint8_t *GetPayload(void) const { return Base::GetBytes() + GetHeader().GetLength(); }
 
     /**
      * This method gets the payload length.
@@ -351,11 +354,7 @@
      * @returns The packet payload length (number of bytes).
      *
      */
-    uint16_t GetPayloadLength(void) const { return mLength - GetHeader().GetLength(); }
-
-private:
-    uint8_t *mBuffer;
-    uint16_t mLength;
+    uint16_t GetPayloadLength(void) const { return GetLength() - GetHeader().GetLength(); }
 };
 
 } // namespace Trel
diff --git a/src/core/radio_cli.cmake b/src/core/radio_cli.cmake
index b7003d1..b4e26fe 100644
--- a/src/core/radio_cli.cmake
+++ b/src/core/radio_cli.cmake
@@ -47,8 +47,12 @@
   target_sources(openthread-radio-cli PRIVATE ${OT_VENDOR_EXTENSION})
 endif()
 
+if(NOT DEFINED OT_MBEDTLS_RCP)
+    set(OT_MBEDTLS_RCP ${OT_MBEDTLS})
+endif()
+
 target_link_libraries(openthread-radio-cli
     PRIVATE
-        ${OT_MBEDTLS}
+        ${OT_MBEDTLS_RCP}
         ot-config
 )
diff --git a/src/core/thread/address_resolver.cpp b/src/core/thread/address_resolver.cpp
index eb14994..9876e93 100644
--- a/src/core/thread/address_resolver.cpp
+++ b/src/core/thread/address_resolver.cpp
@@ -33,8 +33,6 @@
 
 #include "address_resolver.hpp"
 
-#if OPENTHREAD_FTD
-
 #include "coap/coap_message.hpp"
 #include "common/as_core_type.hpp"
 #include "common/code_utils.hpp"
@@ -42,7 +40,7 @@
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/time.hpp"
 #include "mac/mac_types.hpp"
 #include "thread/mesh_forwarder.hpp"
@@ -52,21 +50,29 @@
 
 namespace ot {
 
+RegisterLogModule("AddrResolver");
+
 AddressResolver::AddressResolver(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mAddressError(UriPath::kAddressError, &AddressResolver::HandleAddressError, this)
+#if OPENTHREAD_FTD
     , mAddressQuery(UriPath::kAddressQuery, &AddressResolver::HandleAddressQuery, this)
     , mAddressNotification(UriPath::kAddressNotify, &AddressResolver::HandleAddressNotification, this)
     , mCacheEntryPool(aInstance)
     , mIcmpHandler(&AddressResolver::HandleIcmpReceive, this)
+#endif
 {
     Get<Tmf::Agent>().AddResource(mAddressError);
+#if OPENTHREAD_FTD
     Get<Tmf::Agent>().AddResource(mAddressQuery);
     Get<Tmf::Agent>().AddResource(mAddressNotification);
 
     IgnoreError(Get<Ip6::Icmp>().RegisterHandler(mIcmpHandler));
+#endif
 }
 
+#if OPENTHREAD_FTD
+
 void AddressResolver::Clear(void)
 {
     CacheEntryList *lists[] = {&mCachedList, &mSnoopedList, &mQueryList, &mQueryRetryList};
@@ -459,6 +465,14 @@
     }
 }
 
+Mac::ShortAddress AddressResolver::LookUp(const Ip6::Address &aEid)
+{
+    Mac::ShortAddress rloc16 = Mac::kShortAddrInvalid;
+
+    IgnoreError(Resolve(aEid, rloc16, /* aAllowAddressQuery */ false));
+    return rloc16;
+}
+
 Error AddressResolver::Resolve(const Ip6::Address &aEid, Mac::ShortAddress &aRloc16, bool aAllowAddressQuery)
 {
     Error           error = kErrorNone;
@@ -474,6 +488,7 @@
         // allocate a new entry and perform address query. We do not
         // allow first-time address query entries to be evicted till
         // timeout.
+
         VerifyOrExit(aAllowAddressQuery, error = kErrorNotFound);
 
         entry = NewCacheEntry(/* aSnoopedEntry */ false);
@@ -503,9 +518,12 @@
         ExitNow();
     }
 
-    // Note that if `aAllowAddressQuery` is `false` then the `entry` is definitely already in a list, i.e., we cannot
-    // not get here with `aAllowAddressQuery` being `false` and `entry` being a newly allocated one, due to the
-    // `VerifyOrExit` check that `aAllowAddressQuery` is `true` before allocating a new cache entry.
+    // Note that if `aAllowAddressQuery` is `false` then the `entry`
+    // is definitely already in a list, i.e., we cannot not get here
+    // with `aAllowAddressQuery` being `false` and `entry` being a
+    // newly allocated one, due to the `VerifyOrExit` check that
+    // `aAllowAddressQuery` is `true` before allocating a new cache
+    // entry.
     VerifyOrExit(aAllowAddressQuery, error = kErrorNotFound);
 
     if (list == &mQueryList)
@@ -544,24 +562,18 @@
 {
     Error            error;
     Coap::Message *  message;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
 
-    VerifyOrExit((message = Get<Tmf::Agent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
-
-    message->InitAsNonConfirmablePost();
-    SuccessOrExit(error = message->AppendUriPathOptions(UriPath::kAddressQuery));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityNonConfirmablePostMessage(UriPath::kAddressQuery);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = Tlv::Append<ThreadTargetTlv>(*message, aEid));
 
-    messageInfo.GetPeerAddr().SetToRealmLocalAllRoutersMulticast();
-
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
+    messageInfo.SetSockAddrToRlocPeerAddrToRealmLocalAllRoutersMulticast();
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
 
-    otLogInfoArp("Sending address query for %s", aEid.ToString().AsCString());
+    LogInfo("Sending address query for %s", aEid.ToString().AsCString());
 
 exit:
 
@@ -573,8 +585,8 @@
     {
         uint16_t selfRloc16 = Get<Mle::MleRouter>().GetRloc16();
 
-        otLogInfoArp("Extending ADDR.qry to BB.qry for target=%s, rloc16=%04x(self)", aEid.ToString().AsCString(),
-                     selfRloc16);
+        LogInfo("Extending ADDR.qry to BB.qry for target=%s, rloc16=%04x(self)", aEid.ToString().AsCString(),
+                selfRloc16);
         IgnoreError(Get<BackboneRouter::Manager>().SendBackboneQuery(aEid, selfRloc16));
     }
 #endif
@@ -615,8 +627,8 @@
         ExitNow();
     }
 
-    otLogInfoArp("Received address notification from 0x%04x for %s to 0x%04x",
-                 aMessageInfo.GetPeerAddr().GetIid().GetLocator(), target.ToString().AsCString(), rloc16);
+    LogInfo("Received address notification from 0x%04x for %s to 0x%04x",
+            aMessageInfo.GetPeerAddr().GetIid().GetLocator(), target.ToString().AsCString(), rloc16);
 
     entry = FindCacheEntry(target, list, prev);
     VerifyOrExit(entry != nullptr);
@@ -647,7 +659,7 @@
 
     if (Get<Tmf::Agent>().SendEmptyAck(aMessage, aMessageInfo) == kErrorNone)
     {
-        otLogInfoArp("Sending address notification acknowledgment");
+        LogInfo("Sending address notification acknowledgment");
     }
 
     Get<MeshForwarder>().HandleResolved(target, kErrorNone);
@@ -662,7 +674,7 @@
 {
     Error            error;
     Coap::Message *  message;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
 
     VerifyOrExit((message = Get<Tmf::Agent>().NewMessage()) != nullptr, error = kErrorNoBufs);
 
@@ -675,29 +687,28 @@
 
     if (aDestination == nullptr)
     {
-        messageInfo.GetPeerAddr().SetToRealmLocalAllRoutersMulticast();
+        messageInfo.SetSockAddrToRlocPeerAddrToRealmLocalAllRoutersMulticast();
     }
     else
     {
-        messageInfo.SetPeerAddr(*aDestination);
+        messageInfo.SetSockAddrToRlocPeerAddrTo(*aDestination);
     }
 
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
-
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
 
-    otLogInfoArp("Sending address error for target %s", aTarget.ToString().AsCString());
+    LogInfo("Sending address error for target %s", aTarget.ToString().AsCString());
 
 exit:
 
     if (error != kErrorNone)
     {
         FreeMessage(message);
-        otLogInfoArp("Failed to send address error: %s", ErrorToString(error));
+        LogInfo("Failed to send address error: %s", ErrorToString(error));
     }
 }
 
+#endif // OPENTHREAD_FTD
+
 void AddressResolver::HandleAddressError(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
 {
     static_cast<AddressResolver *>(aContext)->HandleAddressError(AsCoapMessage(aMessage), AsCoreType(aMessageInfo));
@@ -708,18 +719,20 @@
     Error                    error = kErrorNone;
     Ip6::Address             target;
     Ip6::InterfaceIdentifier meshLocalIid;
-    Mac::ExtAddress          extAddr;
-    Ip6::Address             destination;
+#if OPENTHREAD_FTD
+    Mac::ExtAddress extAddr;
+    Ip6::Address    destination;
+#endif
 
     VerifyOrExit(aMessage.IsPostRequest(), error = kErrorDrop);
 
-    otLogInfoArp("Received address error notification");
+    LogInfo("Received address error notification");
 
     if (aMessage.IsConfirmable() && !aMessageInfo.GetSockAddr().IsMulticast())
     {
         if (Get<Tmf::Agent>().SendEmptyAck(aMessage, aMessageInfo) == kErrorNone)
         {
-            otLogInfoArp("Sent address error notification acknowledgment");
+            LogInfo("Sent address error notification acknowledgment");
         }
     }
 
@@ -746,6 +759,7 @@
         }
     }
 
+#if OPENTHREAD_FTD
     meshLocalIid.ConvertToExtAddress(extAddr);
 
     for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
@@ -769,15 +783,18 @@
             }
         }
     }
+#endif // OPENTHREAD_FTD
 
 exit:
 
     if (error != kErrorNone)
     {
-        otLogWarnArp("Error while processing address error notification: %s", ErrorToString(error));
+        LogWarn("Error while processing address error notification: %s", ErrorToString(error));
     }
 }
 
+#if OPENTHREAD_FTD
+
 void AddressResolver::HandleAddressQuery(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
 {
     static_cast<AddressResolver *>(aContext)->HandleAddressQuery(AsCoapMessage(aMessage), AsCoreType(aMessageInfo));
@@ -792,8 +809,8 @@
 
     SuccessOrExit(Tlv::Find<ThreadTargetTlv>(aMessage, target));
 
-    otLogInfoArp("Received address query from 0x%04x for target %s", aMessageInfo.GetPeerAddr().GetIid().GetLocator(),
-                 target.ToString().AsCString());
+    LogInfo("Received address query from 0x%04x for target %s", aMessageInfo.GetPeerAddr().GetIid().GetLocator(),
+            target.ToString().AsCString());
 
     if (Get<ThreadNetif>().HasUnicastAddress(target))
     {
@@ -822,8 +839,7 @@
     {
         uint16_t srcRloc16 = aMessageInfo.GetPeerAddr().GetIid().GetLocator();
 
-        otLogInfoArp("Extending ADDR.qry to BB.qry for target=%s, rloc16=%04x", target.ToString().AsCString(),
-                     srcRloc16);
+        LogInfo("Extending ADDR.qry to BB.qry for target=%s, rloc16=%04x", target.ToString().AsCString(), srcRloc16);
         IgnoreError(Get<BackboneRouter::Manager>().SendBackboneQuery(target, srcRloc16));
     }
 #endif
@@ -839,13 +855,10 @@
 {
     Error            error;
     Coap::Message *  message;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
 
-    VerifyOrExit((message = Get<Tmf::Agent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
-
-    message->InitAsConfirmablePost();
-    SuccessOrExit(error = message->AppendUriPathOptions(UriPath::kAddressNotify));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(UriPath::kAddressNotify);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = Tlv::Append<ThreadTargetTlv>(*message, aTarget));
     SuccessOrExit(error = Tlv::Append<ThreadMeshLocalEidTlv>(*message, aMeshLocalIid));
@@ -856,13 +869,11 @@
         SuccessOrExit(error = Tlv::Append<ThreadLastTransactionTimeTlv>(*message, *aLastTransactionTime));
     }
 
-    messageInfo.SetPeerAddr(aDestination);
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
+    messageInfo.SetSockAddrToRlocPeerAddrTo(aDestination);
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
 
-    otLogInfoArp("Sending address notification for target %s", aTarget.ToString().AsCString());
+    LogInfo("Sending address notification for target %s", aTarget.ToString().AsCString());
 
 exit:
     FreeMessageOnError(message, error);
@@ -930,8 +941,8 @@
                 mQueryList.PopAfter(prev);
                 mQueryRetryList.Push(*entry);
 
-                otLogInfoArp("Timed out waiting for address notification for %s, retry: %d",
-                             entry->GetTarget().ToString().AsCString(), entry->GetTimeout());
+                LogInfo("Timed out waiting for address notification for %s, retry: %d",
+                        entry->GetTarget().ToString().AsCString(), entry->GetTimeout());
 
                 Get<MeshForwarder>().HandleResolved(entry->GetTarget(), kErrorDrop);
 
@@ -982,59 +993,45 @@
 
 // LCOV_EXCL_START
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_ARP == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
 void AddressResolver::LogCacheEntryChange(EntryChange       aChange,
                                           Reason            aReason,
                                           const CacheEntry &aEntry,
                                           CacheEntryList *  aList)
 {
-    const char *change = "";
-    const char *reason = "";
+    static const char *const kChangeStrings[] = {
+        "added",   // (0) kEntryAdded
+        "updated", // (1) kEntryUpdated
+        "removed", // (2) kEntryRemoved
+    };
 
-    switch (aChange)
-    {
-    case kEntryAdded:
-        change = "added";
-        break;
-    case kEntryUpdated:
-        change = "updated";
-        break;
-    case kEntryRemoved:
-        change = "removed";
-        break;
-    }
+    static const char *const kReasonStrings[] = {
+        "query request",          // (0) kReasonQueryRequest
+        "snoop",                  // (1) kReasonSnoop
+        "rx notification",        // (2) kReasonReceivedNotification
+        "removing router id",     // (3) kReasonRemovingRouterId
+        "removing rloc16",        // (4) kReasonRemovingRloc16
+        "rx icmp no route",       // (5) kReasonReceivedIcmpDstUnreachNoRoute
+        "evicting for new entry", // (6) kReasonEvictingForNewEntry
+        "removing eid",           // (7) kReasonRemovingEid
+    };
 
-    switch (aReason)
-    {
-    case kReasonQueryRequest:
-        reason = "query request";
-        break;
-    case kReasonSnoop:
-        reason = "snoop";
-        break;
-    case kReasonReceivedNotification:
-        reason = "rx notification";
-        break;
-    case kReasonRemovingRouterId:
-        reason = "removing router id";
-        break;
-    case kReasonRemovingRloc16:
-        reason = "removing rloc16";
-        break;
-    case kReasonReceivedIcmpDstUnreachNoRoute:
-        reason = "rx icmp no route";
-        break;
-    case kReasonEvictingForNewEntry:
-        reason = "evicting for new entry";
-        break;
-    case kReasonRemovingEid:
-        reason = "removing eid";
-        break;
-    }
+    static_assert(0 == kEntryAdded, "kEntryAdded value is incorrect");
+    static_assert(1 == kEntryUpdated, "kEntryUpdated value is incorrect");
+    static_assert(2 == kEntryRemoved, "kEntryRemoved value is incorrect");
 
-    otLogNoteArp("Cache entry %s: %s, 0x%04x%s%s - %s", change, aEntry.GetTarget().ToString().AsCString(),
-                 aEntry.GetRloc16(), (aList == nullptr) ? "" : ", list:", ListToString(aList), reason);
+    static_assert(0 == kReasonQueryRequest, "kReasonQueryRequest value is incorrect");
+    static_assert(1 == kReasonSnoop, "kReasonSnoop value is incorrect");
+    static_assert(2 == kReasonReceivedNotification, "kReasonReceivedNotification value is incorrect");
+    static_assert(3 == kReasonRemovingRouterId, "kReasonRemovingRouterId value is incorrect");
+    static_assert(4 == kReasonRemovingRloc16, "kReasonRemovingRloc16 value is incorrect");
+    static_assert(5 == kReasonReceivedIcmpDstUnreachNoRoute, "kReasonReceivedIcmpDstUnreachNoRoute value is incorrect");
+    static_assert(6 == kReasonEvictingForNewEntry, "kReasonEvictingForNewEntry value is incorrect");
+    static_assert(7 == kReasonRemovingEid, "kReasonRemovingEid value is incorrect");
+
+    LogInfo("Cache entry %s: %s, 0x%04x%s%s - %s", kChangeStrings[aChange], aEntry.GetTarget().ToString().AsCString(),
+            aEntry.GetRloc16(), (aList == nullptr) ? "" : ", list:", ListToString(aList), kReasonStrings[aReason]);
 }
 
 const char *AddressResolver::ListToString(const CacheEntryList *aList) const
@@ -1050,13 +1047,13 @@
     return str;
 }
 
-#else // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_ARP == 1)
+#else // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
 void AddressResolver::LogCacheEntryChange(EntryChange, Reason, const CacheEntry &, CacheEntryList *)
 {
 }
 
-#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_ARP == 1)
+#endif // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
 
 // LCOV_EXCL_STOP
 
@@ -1088,6 +1085,6 @@
     return;
 }
 
-} // namespace ot
-
 #endif // OPENTHREAD_FTD
+
+} // namespace ot
diff --git a/src/core/thread/address_resolver.hpp b/src/core/thread/address_resolver.hpp
index 625fb4d..b65fc60 100644
--- a/src/core/thread/address_resolver.hpp
+++ b/src/core/thread/address_resolver.hpp
@@ -36,8 +36,6 @@
 
 #include "openthread-core-config.h"
 
-#if OPENTHREAD_FTD
-
 #include "coap/coap.hpp"
 #include "common/linked_list.hpp"
 #include "common/locator.hpp"
@@ -87,6 +85,7 @@
      */
     explicit AddressResolver(Instance &aInstance);
 
+#if OPENTHREAD_FTD
     /**
      * This method clears the EID-to-RLOC cache.
      *
@@ -96,8 +95,8 @@
     /**
      * This method gets the information about the next EID cache entry (using an iterator).
      *
-     * @param[out]   aInfo       An `EntryInfo` where the EID cache entry information is placed.
-     * @param[inout] aIterator   An iterator. It will be updated to point to the next entry on success.
+     * @param[out]    aInfo      An `EntryInfo` where the EID cache entry information is placed.
+     * @param[in,out] aIterator  An iterator. It will be updated to point to the next entry on success.
      *                           To get the first entry, initialize the iterator by setting all its fields to zero.
      *                           e.g., `memset` the the iterator structure to zero.
      *
@@ -145,21 +144,31 @@
     void UpdateSnoopedCacheEntry(const Ip6::Address &aEid, Mac::ShortAddress aRloc16, Mac::ShortAddress aDest);
 
     /**
-     * This method returns the RLOC16 for a given EID, initiates an Address Query if allowed and the mapping is not
-     * known.
+     * This method returns the RLOC16 for a given EID, initiates an Address Query if the mapping is not known.
      *
      * @param[in]   aEid                A reference to the EID.
      * @param[out]  aRloc16             The RLOC16 corresponding to @p aEid.
-     * @param[in]   aAllowAddressQuery  Allow to initiate Address Query if the mapping is not known.
      *
      * @retval kErrorNone           Successfully provided the RLOC16.
      * @retval kErrorAddressQuery   Initiated an Address Query if allowed.
      * @retval kErrorDrop           Earlier Address Query for the EID timed out. In retry timeout interval.
      * @retval kErrorNoBufs         Insufficient buffer space available to send Address Query.
-     * @retval kErrorNotFound       The mapping was not found and Address Query was not allowed.
      *
      */
-    Error Resolve(const Ip6::Address &aEid, Mac::ShortAddress &aRloc16, bool aAllowAddressQuery = true);
+    Error Resolve(const Ip6::Address &aEid, Mac::ShortAddress &aRloc16)
+    {
+        return Resolve(aEid, aRloc16, /* aAllowAddressQuery */ true);
+    }
+
+    /**
+     * This method looks up the RLOC16 for a given EID in the address cache.
+     *
+     * @param[in]   aEid                A reference to the EID.
+     *
+     * @returns The RLOC16 mapping to @p aEid or `Mac::kShortAddrInvalid` if it is not found in the address cache.
+     *
+     */
+    Mac::ShortAddress LookUp(const Ip6::Address &aEid);
 
     /**
      * This method restarts any ongoing address queries.
@@ -295,6 +304,7 @@
 
     CacheEntryPool &GetCacheEntryPool(void) { return mCacheEntryPool; }
 
+    Error       Resolve(const Ip6::Address &aEid, Mac::ShortAddress &aRloc16, bool aAllowAddressQuery);
     void        Remove(Mac::ShortAddress aRloc16, bool aMatchRouterId);
     void        Remove(const Ip6::Address &aEid, Reason aReason);
     CacheEntry *FindCacheEntry(const Ip6::Address &aEid, CacheEntryList *&aList, CacheEntry *&aPrevEntry);
@@ -306,9 +316,12 @@
 
     static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
 
+#endif // OPENTHREAD_FTD
+
     static void HandleAddressError(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
     void        HandleAddressError(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
 
+#if OPENTHREAD_FTD
     static void HandleAddressQuery(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
     void        HandleAddressQuery(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
 
@@ -334,7 +347,9 @@
 
     static AddressResolver::CacheEntry *GetEntryAfter(CacheEntry *aPrev, CacheEntryList &aList);
 
+#endif // OPENTHREAD_FTD
     Coap::Resource mAddressError;
+#if OPENTHREAD_FTD
     Coap::Resource mAddressQuery;
     Coap::Resource mAddressNotification;
 
@@ -345,6 +360,7 @@
     CacheEntryList mQueryRetryList;
 
     Ip6::Icmp::Handler mIcmpHandler;
+#endif //  OPENTHREAD_FTD
 };
 
 /**
@@ -353,6 +369,4 @@
 
 } // namespace ot
 
-#endif //  OPENTHREAD_FTD
-
 #endif // ADDRESS_RESOLVER_HPP_
diff --git a/src/core/thread/announce_begin_server.cpp b/src/core/thread/announce_begin_server.cpp
index b23713e..ddac782 100644
--- a/src/core/thread/announce_begin_server.cpp
+++ b/src/core/thread/announce_begin_server.cpp
@@ -41,13 +41,15 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "meshcop/meshcop_tlvs.hpp"
 #include "thread/thread_netif.hpp"
 #include "thread/uri_paths.hpp"
 
 namespace ot {
 
+RegisterLogModule("MeshCoP");
+
 AnnounceBeginServer::AnnounceBeginServer(Instance &aInstance)
     : AnnounceSenderBase(aInstance, AnnounceBeginServer::HandleTimer)
     , mAnnounceBegin(UriPath::kAnnounceBegin, &AnnounceBeginServer::HandleRequest, this)
@@ -86,7 +88,7 @@
     if (aMessage.IsConfirmable() && !aMessageInfo.GetSockAddr().IsMulticast())
     {
         SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMessage, responseInfo));
-        otLogInfoMeshCoP("sent announce begin response");
+        LogInfo("Sent announce begin response");
     }
 
 exit:
diff --git a/src/core/thread/announce_sender.cpp b/src/core/thread/announce_sender.cpp
index d088896..c500576 100644
--- a/src/core/thread/announce_sender.cpp
+++ b/src/core/thread/announce_sender.cpp
@@ -38,7 +38,7 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/random.hpp"
 #include "meshcop/meshcop.hpp"
 #include "meshcop/meshcop_tlvs.hpp"
@@ -46,6 +46,8 @@
 
 namespace ot {
 
+RegisterLogModule("AnnounceSender");
+
 //---------------------------------------------------------------------------------------------------------------------
 // AnnounceSenderBase
 
@@ -168,7 +170,7 @@
 {
     AnnounceSenderBase::Stop();
     mTrickleTimer.Stop();
-    otLogInfoMle("[announce-sender] Stopped");
+    LogInfo("Stopped");
 }
 
 void AnnounceSender::HandleTimer(Timer &aTimer)
@@ -191,7 +193,7 @@
     // message transmissions.
 
     SendAnnounce(1);
-    otLogInfoMle("[announce-sender] Schedule tx for one cycle");
+    LogInfo("Schedule tx for one cycle");
 }
 
 void AnnounceSender::HandleNotifierEvents(Events aEvents)
@@ -240,7 +242,7 @@
     // desired Announce Tx cycle interval.
 
     mTrickleTimer.Start(TrickleTimer::kModeTrickle, kInterval, kInterval, kRedundancyConstant);
-    otLogInfoMle("[announce-sender] Started");
+    LogInfo("Started");
 
 exit:
     return;
@@ -250,14 +252,14 @@
 {
     Mac::ChannelMask channelMask;
 
-    SuccessOrExit(Get<MeshCoP::ActiveDataset>().GetChannelMask(channelMask));
+    SuccessOrExit(Get<MeshCoP::ActiveDatasetManager>().GetChannelMask(channelMask));
     VerifyOrExit(!channelMask.IsEmpty());
 
     VerifyOrExit(channelMask != GetChannelMask());
 
     SetChannelMask(channelMask);
     SetPeriod(kTxInterval / channelMask.GetNumberOfChannels());
-    otLogInfoMle("[announce-sender] ChannelMask:%s, period:%u", GetChannelMask().ToString().AsCString(), GetPeriod());
+    LogInfo("ChannelMask:%s, period:%u", GetChannelMask().ToString().AsCString(), GetPeriod());
 
     // When channel mask is changed, we also check and update the PAN
     // channel. This handles the case where `ThreadChannelChanged` event
@@ -273,7 +275,7 @@
 void AnnounceSender::HandleThreadChannelChanged(void)
 {
     SetStartingChannel(Get<Mac::Mac>().GetPanChannel());
-    otLogInfoMle("[announce-sender] StartingChannel:%d", GetStartingChannel());
+    LogInfo("StartingChannel:%d", GetStartingChannel());
 }
 
 #endif // OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
diff --git a/src/core/thread/anycast_locator.cpp b/src/core/thread/anycast_locator.cpp
index fc703d2..a8989cd 100644
--- a/src/core/thread/anycast_locator.cpp
+++ b/src/core/thread/anycast_locator.cpp
@@ -62,25 +62,20 @@
 {
     Error            error   = kErrorNone;
     Coap::Message *  message = nullptr;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
 
     VerifyOrExit((aCallback != nullptr) && Get<Mle::Mle>().IsAnycastLocator(aAnycastAddress),
                  error = kErrorInvalidArgs);
 
-    message = Get<Tmf::Agent>().NewMessage();
+    message = Get<Tmf::Agent>().NewConfirmablePostMessage(UriPath::kAnycastLocate);
     VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
-    SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kAnycastLocate));
-    SuccessOrExit(error = message->SetPayloadMarker());
-
     if (mCallback != nullptr)
     {
         IgnoreError(Get<Tmf::Agent>().AbortTransaction(HandleResponse, this));
     }
 
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.SetPeerAddr(aAnycastAddress);
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
+    messageInfo.SetSockAddrToRlocPeerAddrTo(aAnycastAddress);
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, HandleResponse, this));
 
@@ -145,12 +140,9 @@
 
     VerifyOrExit(aRequest.IsConfirmablePostRequest());
 
-    message = Get<Tmf::Agent>().NewMessage();
+    message = Get<Tmf::Agent>().NewResponseMessage(aRequest);
     VerifyOrExit(message != nullptr);
 
-    SuccessOrExit(message->SetDefaultResponseHeader(aRequest));
-    SuccessOrExit(message->SetPayloadMarker());
-
     SuccessOrExit(Tlv::Append<ThreadMeshLocalEidTlv>(*message, Get<Mle::Mle>().GetMeshLocal64().GetIid()));
     SuccessOrExit(Tlv::Append<ThreadRloc16Tlv>(*message, Get<Mle::Mle>().GetRloc16()));
 
diff --git a/src/core/thread/child_table.hpp b/src/core/thread/child_table.hpp
index 70a49ce..7df7dee 100644
--- a/src/core/thread/child_table.hpp
+++ b/src/core/thread/child_table.hpp
@@ -276,7 +276,7 @@
     /**
      * This method removes a stored child information from non-volatile memory.
      *
-     * @param[in]  aChildRloc16     A reference to the child to remove from non-volatile memory.
+     * @param[in]  aChild     A reference to the child to remove from non-volatile memory.
      *
      */
     void RemoveStoredChild(const Child &aChild);
@@ -304,6 +304,22 @@
      */
     bool HasSleepyChildWithAddress(const Ip6::Address &aIp6Address) const;
 
+    /**
+     * This method indicates whether the child table contains a given `Neighbor` instance.
+     *
+     * @param[in]  aNeighbor  A reference to a `Neighbor`.
+     *
+     * @retval TRUE  if @p aNeighbor is a `Child` in the child table.
+     * @retval FALSE if @p aNeighbor is not a `Child` in the child table.
+     *
+     */
+    bool Contains(const Neighbor &aNeighbor) const
+    {
+        const Child *child = static_cast<const Child *>(&aNeighbor);
+
+        return (mChildren <= child) && (child < GetArrayEnd(mChildren));
+    }
+
 private:
     static constexpr uint16_t kMaxChildren = OPENTHREAD_CONFIG_MLE_MAX_CHILDREN;
 
diff --git a/src/core/thread/csl_tx_scheduler.cpp b/src/core/thread/csl_tx_scheduler.cpp
index 5347fd7..15beb59 100644
--- a/src/core/thread/csl_tx_scheduler.cpp
+++ b/src/core/thread/csl_tx_scheduler.cpp
@@ -31,12 +31,14 @@
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
 
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/time.hpp"
 #include "mac/mac.hpp"
 
 namespace ot {
 
+RegisterLogModule("CslTxScheduler");
+
 CslTxScheduler::Callbacks::Callbacks(Instance &aInstance)
     : InstanceLocator(aInstance)
 {
@@ -253,8 +255,8 @@
         OT_ASSERT(!aFrame.GetSecurityEnabled() || aFrame.IsHeaderUpdated());
 
         aChild.IncrementCslTxAttempts();
-        otLogInfoMac("CSL tx to child %04x failed, attempt %d/%d", aChild.GetRloc16(), aChild.GetCslTxAttempts(),
-                     kMaxCslTriggeredTxAttempts);
+        LogInfo("CSL tx to child %04x failed, attempt %d/%d", aChild.GetRloc16(), aChild.GetCslTxAttempts(),
+                kMaxCslTriggeredTxAttempts);
 
         if (aChild.GetCslTxAttempts() >= kMaxCslTriggeredTxAttempts)
         {
diff --git a/src/core/thread/discover_scanner.cpp b/src/core/thread/discover_scanner.cpp
index 3a89422..bf6d60f 100644
--- a/src/core/thread/discover_scanner.cpp
+++ b/src/core/thread/discover_scanner.cpp
@@ -37,7 +37,6 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
 #include "thread/mesh_forwarder.hpp"
 #include "thread/mle.hpp"
 #include "thread/mle_router.hpp"
@@ -68,7 +67,7 @@
                                 void *                  aContext)
 {
     Error                           error   = kErrorNone;
-    Message *                       message = nullptr;
+    Mle::TxMessage *                message = nullptr;
     Tlv                             tlv;
     Ip6::Address                    destination;
     MeshCoP::DiscoveryRequestTlv    discoveryRequest;
@@ -106,10 +105,8 @@
         mScanChannels.Intersect(aScanChannels);
     }
 
-    VerifyOrExit((message = Get<Mle>().NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    message->SetSubType(Message::kSubTypeMleDiscoverRequest);
+    VerifyOrExit((message = Get<Mle>().NewMleMessage(Mle::kCommandDiscoveryRequest)) != nullptr, error = kErrorNoBufs);
     message->SetPanId(aPanId);
-    SuccessOrExit(error = Get<Mle>().AppendHeader(*message, Mle::kCommandDiscoveryRequest));
 
     // Prepare sub-TLV MeshCoP Discovery Request.
     discoveryRequest.Init();
@@ -139,7 +136,7 @@
 
     destination.SetToLinkLocalAllRoutersMulticast();
 
-    SuccessOrExit(error = Get<Mle>().SendMessage(*message, destination));
+    SuccessOrExit(error = message->SendTo(destination));
 
     if ((aPanId == Mac::kPanIdBroadcast) && (Get<Mac::Mac>().GetPanId() == Mac::kPanIdBroadcast))
     {
@@ -216,6 +213,7 @@
         // the next scan channel. Also pause message tx on `MeshForwarder`
         // while listening to receive Discovery Responses.
         aMessage.SetDirectTransmission();
+        aMessage.SetTimestampToNow();
         Get<MeshForwarder>().PauseMessageTransmissions();
         mTimer.Start(kDefaultScanDuration);
         break;
@@ -286,10 +284,10 @@
     return;
 }
 
-void DiscoverScanner::HandleDiscoveryResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const
+void DiscoverScanner::HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const
 {
     Error                         error    = kErrorNone;
-    const ThreadLinkInfo *        linkInfo = aMessageInfo.GetThreadLinkInfo();
+    const ThreadLinkInfo *        linkInfo = aRxInfo.mMessageInfo.GetThreadLinkInfo();
     Tlv                           tlv;
     MeshCoP::Tlv                  meshcopTlv;
     MeshCoP::DiscoveryResponseTlv discoveryResponse;
@@ -299,46 +297,47 @@
     uint16_t                      end;
     bool                          didCheckSteeringData = false;
 
-    Mle::Log(Mle::kMessageReceive, Mle::kTypeDiscoveryResponse, aMessageInfo.GetPeerAddr());
+    Mle::Log(Mle::kMessageReceive, Mle::kTypeDiscoveryResponse, aRxInfo.mMessageInfo.GetPeerAddr());
 
     VerifyOrExit(mState == kStateScanning, error = kErrorDrop);
 
     // Find MLE Discovery TLV
-    VerifyOrExit(Tlv::FindTlvOffset(aMessage, Tlv::kDiscovery, offset) == kErrorNone, error = kErrorParse);
-    IgnoreError(aMessage.Read(offset, tlv));
+    VerifyOrExit(Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kDiscovery, offset) == kErrorNone, error = kErrorParse);
+    IgnoreError(aRxInfo.mMessage.Read(offset, tlv));
 
     offset += sizeof(tlv);
     end = offset + tlv.GetLength();
 
     memset(&result, 0, sizeof(result));
-    result.mPanId   = linkInfo->mPanId;
-    result.mChannel = linkInfo->mChannel;
-    result.mRssi    = linkInfo->mRss;
-    result.mLqi     = linkInfo->mLqi;
+    result.mDiscover = true;
+    result.mPanId    = linkInfo->mPanId;
+    result.mChannel  = linkInfo->mChannel;
+    result.mRssi     = linkInfo->mRss;
+    result.mLqi      = linkInfo->mLqi;
 
-    aMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(AsCoreType(&result.mExtAddress));
+    aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(AsCoreType(&result.mExtAddress));
 
     // Process MeshCoP TLVs
     while (offset < end)
     {
-        IgnoreError(aMessage.Read(offset, meshcopTlv));
+        IgnoreError(aRxInfo.mMessage.Read(offset, meshcopTlv));
 
         switch (meshcopTlv.GetType())
         {
         case MeshCoP::Tlv::kDiscoveryResponse:
-            IgnoreError(aMessage.Read(offset, discoveryResponse));
+            IgnoreError(aRxInfo.mMessage.Read(offset, discoveryResponse));
             VerifyOrExit(discoveryResponse.IsValid(), error = kErrorParse);
             result.mVersion  = discoveryResponse.GetVersion();
             result.mIsNative = discoveryResponse.IsNativeCommissioner();
             break;
 
         case MeshCoP::Tlv::kExtendedPanId:
-            SuccessOrExit(
-                error = Tlv::Read<MeshCoP::ExtendedPanIdTlv>(aMessage, offset, AsCoreType(&result.mExtendedPanId)));
+            SuccessOrExit(error = Tlv::Read<MeshCoP::ExtendedPanIdTlv>(aRxInfo.mMessage, offset,
+                                                                       AsCoreType(&result.mExtendedPanId)));
             break;
 
         case MeshCoP::Tlv::kNetworkName:
-            IgnoreError(aMessage.Read(offset, networkName));
+            IgnoreError(aRxInfo.mMessage.Read(offset, networkName));
             if (networkName.IsValid())
             {
                 IgnoreError(AsCoreType(&result.mNetworkName).Set(networkName.GetNetworkName()));
@@ -358,7 +357,7 @@
 
                 steeringData.Init(dataLength);
 
-                SuccessOrExit(error = Tlv::ReadTlv(aMessage, offset, steeringData.GetData(), dataLength));
+                SuccessOrExit(error = Tlv::ReadTlv(aRxInfo.mMessage, offset, steeringData.GetData(), dataLength));
 
                 if (mEnableFiltering)
                 {
@@ -370,7 +369,8 @@
             break;
 
         case MeshCoP::Tlv::kJoinerUdpPort:
-            SuccessOrExit(error = Tlv::Read<MeshCoP::JoinerUdpPortTlv>(aMessage, offset, result.mJoinerUdpPort));
+            SuccessOrExit(error =
+                              Tlv::Read<MeshCoP::JoinerUdpPortTlv>(aRxInfo.mMessage, offset, result.mJoinerUdpPort));
             break;
 
         default:
diff --git a/src/core/thread/discover_scanner.hpp b/src/core/thread/discover_scanner.hpp
index dd48d31..061aa2f 100644
--- a/src/core/thread/discover_scanner.hpp
+++ b/src/core/thread/discover_scanner.hpp
@@ -79,7 +79,7 @@
      * completes.
      *
      * The handler function format is `void (*oHandler)(ScanResult *aResult, void *aContext);`. End of scan is
-     * indicated by `aResult` pointer being set to nullptr.
+     * indicated by `aResult` pointer being set to `nullptr`.
      *
      */
     typedef otHandleActiveScanResult Handler;
@@ -111,8 +111,9 @@
      * @param[in]  aEnableFiltering   Enable filtering MLE Discovery Responses with steering data not containing a
      *                                given filter indexes.
      * @param[in]  aFilterIndexes     A pointer to `FilterIndexes` to use for filtering (when enabled).
-     *                                If set to nullptr, filter indexes are derived from hash of factory-assigned EUI64.
-     * @param[in]  aHandler           A pointer to a function that is called on receiving an MLE Discovery Response.
+     *                                If set to `nullptr`, filter indexes are derived from hash of factory-assigned
+     *                                EUI64.
+     * @param[in]  aCallback          A pointer to a function that is called on receiving an MLE Discovery Response.
      * @param[in]  aContext           A pointer to arbitrary context information.
      *
      * @retval kErrorNone           Successfully started a Thread Discovery Scan.
@@ -166,7 +167,7 @@
     void          Stop(void) { HandleDiscoverComplete(); }
 
     // Methods used from `Mle`
-    void HandleDiscoveryResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const;
+    void HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const;
 
     void        HandleDiscoverComplete(void);
     static void HandleTimer(Timer &aTimer);
diff --git a/src/core/thread/dua_manager.cpp b/src/core/thread/dua_manager.cpp
index 8119a69..108f07a 100644
--- a/src/core/thread/dua_manager.cpp
+++ b/src/core/thread/dua_manager.cpp
@@ -39,7 +39,7 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/settings.hpp"
 #include "net/ip6_address.hpp"
 #include "thread/mle_types.hpp"
@@ -50,6 +50,8 @@
 
 namespace ot {
 
+RegisterLogModule("DuaManager");
+
 DuaManager::DuaManager(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mRegistrationTask(aInstance, DuaManager::HandleRegistrationTask)
@@ -156,11 +158,11 @@
             IgnoreError(Store());
         }
 
-        otLogInfoDua("Generated DUA: %s", mDomainUnicastAddress.GetAddress().ToString().AsCString());
+        LogInfo("Generated DUA: %s", mDomainUnicastAddress.GetAddress().ToString().AsCString());
     }
     else
     {
-        otLogWarnDua("Generate DUA: %s", ErrorToString(error));
+        LogWarn("Generate DUA: %s", ErrorToString(error));
     }
 
     return error;
@@ -174,7 +176,7 @@
     VerifyOrExit(mFixedDuaInterfaceIdentifier.IsUnspecified() || mFixedDuaInterfaceIdentifier != aIid);
 
     mFixedDuaInterfaceIdentifier = aIid;
-    otLogInfoDua("Set DUA IID: %s", mFixedDuaInterfaceIdentifier.ToString().AsCString());
+    LogInfo("Set DUA IID: %s", mFixedDuaInterfaceIdentifier.ToString().AsCString());
 
     if (Get<ThreadNetif>().HasUnicastAddress(GetDomainUnicastAddress()))
     {
@@ -203,7 +205,7 @@
         }
     }
 
-    otLogInfoDua("Cleared DUA IID: %s", mFixedDuaInterfaceIdentifier.ToString().AsCString());
+    LogInfo("Cleared DUA IID: %s", mFixedDuaInterfaceIdentifier.ToString().AsCString());
     mFixedDuaInterfaceIdentifier.Clear();
 
 exit:
@@ -254,7 +256,7 @@
     {
         mDelay.mFields.mRegistrationDelay = aDelay;
 
-        otLogDebgDua("update regdelay %d", mDelay.mFields.mRegistrationDelay);
+        LogDebg("update regdelay %d", mDelay.mFields.mRegistrationDelay);
         UpdateTimeTickerRegistration();
     }
 }
@@ -284,7 +286,7 @@
     {
         mDelay.mFields.mReregistrationDelay = delay;
         UpdateTimeTickerRegistration();
-        otLogDebgDua("update reregdelay %d", mDelay.mFields.mReregistrationDelay);
+        LogDebg("update reregdelay %d", mDelay.mFields.mReregistrationDelay);
     }
 
 exit:
@@ -297,7 +299,7 @@
     {
         mDelay.mFields.mCheckDelay = aDelay;
 
-        otLogDebgDua("update checkdelay %d", mDelay.mFields.mCheckDelay);
+        LogDebg("update checkdelay %d", mDelay.mFields.mCheckDelay);
         UpdateTimeTickerRegistration();
     }
 }
@@ -355,8 +357,8 @@
     bool attempt = false;
 
 #if OPENTHREAD_CONFIG_DUA_ENABLE
-    otLogDebgDua("regdelay %d, reregdelay %d, checkdelay %d", mDelay.mFields.mRegistrationDelay,
-                 mDelay.mFields.mReregistrationDelay, mDelay.mFields.mCheckDelay);
+    LogDebg("regdelay %d, reregdelay %d, checkdelay %d", mDelay.mFields.mRegistrationDelay,
+            mDelay.mFields.mReregistrationDelay, mDelay.mFields.mCheckDelay);
 
     if ((mDuaState != kNotExist) &&
         (TimerMilli::GetNow() > (mLastRegistrationTime + TimeMilli::SecToMsec(Mle::kDuaDadPeriod))))
@@ -369,7 +371,7 @@
         attempt = true;
     }
 #else
-    otLogDebgDua("reregdelay %d, checkdelay %d", mDelay.mFields.mReregistrationDelay, mDelay.mFields.mCheckDelay);
+    LogDebg("reregdelay %d, checkdelay %d", mDelay.mFields.mReregistrationDelay, mDelay.mFields.mCheckDelay);
 #endif
 
     if ((mDelay.mFields.mCheckDelay > 0) && (--mDelay.mFields.mCheckDelay == 0))
@@ -422,7 +424,7 @@
     Error            error   = kErrorNone;
     Mle::MleRouter & mle     = Get<Mle::MleRouter>();
     Coap::Message *  message = nullptr;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
     Ip6::Address     dua;
 
     VerifyOrExit(mle.IsAttached(), error = kErrorInvalidState);
@@ -453,10 +455,8 @@
     }
 
     // Prepare DUA.req
-    VerifyOrExit((message = Get<Tmf::Agent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kDuaRegistrationRequest));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(UriPath::kDuaRegistrationRequest);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
 #if OPENTHREAD_CONFIG_DUA_ENABLE
     if (mDuaState == kToRegister && mDelay.mFields.mRegistrationDelay == 0)
@@ -515,8 +515,7 @@
                                                       Get<BackboneRouter::Leader>().GetServer16());
     }
 
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
+    messageInfo.SetSockAddrToRloc();
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, &DuaManager::HandleDuaResponse, this));
 
@@ -532,7 +531,7 @@
         Get<DataPollSender>().SendFastPolls();
     }
 
-    otLogInfoDua("Sent DUA.req for DUA %s", dua.ToString().AsCString());
+    LogInfo("Sent DUA.req for DUA %s", dua.ToString().AsCString());
 
 exit:
     if (error == kErrorNoBufs)
@@ -540,7 +539,7 @@
         UpdateCheckDelay(Mle::kNoBufDelay);
     }
 
-    otLogInfoDua("PerformNextRegistration: %s", ErrorToString(error));
+    LogInfo("PerformNextRegistration: %s", ErrorToString(error));
     FreeMessageOnError(message, error);
 }
 
@@ -583,7 +582,7 @@
         mRegistrationTask.Post();
     }
 
-    otLogInfoDua("Received DUA.rsp: %s", ErrorToString(error));
+    LogInfo("Received DUA.rsp: %s", ErrorToString(error));
 }
 
 void DuaManager::HandleDuaNotification(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
@@ -600,14 +599,14 @@
 
     if (aMessage.IsConfirmable() && Get<Tmf::Agent>().SendEmptyAck(aMessage, aMessageInfo) == kErrorNone)
     {
-        otLogInfoDua("Sent DUA.ntf acknowledgment");
+        LogInfo("Sent DUA.ntf acknowledgment");
     }
 
     error = ProcessDuaResponse(aMessage);
 
 exit:
     OT_UNUSED_VARIABLE(error);
-    otLogInfoDua("Received DUA.ntf: %d", ErrorToString(error));
+    LogInfo("Received DUA.ntf: %d", ErrorToString(error));
 }
 
 Error DuaManager::ProcessDuaResponse(Coap::Message &aMessage)
@@ -724,24 +723,20 @@
                                          const Child &              aChild)
 {
     Coap::Message *  message = nullptr;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
     Error            error;
 
-    VerifyOrExit((message = Get<Tmf::Agent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kDuaRegistrationNotify));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(UriPath::kDuaRegistrationNotify);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = Tlv::Append<ThreadStatusTlv>(*message, aStatus));
     SuccessOrExit(error = Tlv::Append<ThreadTargetTlv>(*message, aAddress));
 
-    messageInfo.GetPeerAddr().SetToRoutingLocator(Get<Mle::MleRouter>().GetMeshLocalPrefix(), aChild.GetRloc16());
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
+    messageInfo.SetSockAddrToRlocPeerAddrTo(aChild.GetRloc16());
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
 
-    otLogInfoDua("Sent ADDR_NTF for child %04x DUA %s", aChild.GetRloc16(), aAddress.ToString().AsCString());
+    LogInfo("Sent ADDR_NTF for child %04x DUA %s", aChild.GetRloc16(), aAddress.ToString().AsCString());
 
 exit:
 
@@ -750,8 +745,8 @@
         FreeMessage(message);
 
         // TODO: (DUA) (P4) may enhance to  guarantee the delivery of DUA.ntf
-        otLogWarnDua("Sent ADDR_NTF for child %04x DUA %s Error %s", aChild.GetRloc16(),
-                     aAddress.ToString().AsCString(), ErrorToString(error));
+        LogWarn("Sent ADDR_NTF for child %04x DUA %s Error %s", aChild.GetRloc16(), aAddress.ToString().AsCString(),
+                ErrorToString(error));
     }
 }
 
diff --git a/src/core/thread/energy_scan_server.cpp b/src/core/thread/energy_scan_server.cpp
index 54ae6d4..9c6b913 100644
--- a/src/core/thread/energy_scan_server.cpp
+++ b/src/core/thread/energy_scan_server.cpp
@@ -39,7 +39,7 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "meshcop/meshcop.hpp"
 #include "meshcop/meshcop_tlvs.hpp"
 #include "thread/thread_netif.hpp"
@@ -47,6 +47,8 @@
 
 namespace ot {
 
+RegisterLogModule("EnergyScanSrv");
+
 EnergyScanServer::EnergyScanServer(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mChannelMask(0)
@@ -97,7 +99,7 @@
     if (aMessage.IsConfirmable() && !aMessageInfo.GetSockAddr().IsMulticast())
     {
         SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMessage, responseInfo));
-        otLogInfoMeshCoP("sent energy scan query response");
+        LogInfo("sent energy scan query response");
     }
 
 exit:
@@ -172,13 +174,11 @@
     Error                   error = kErrorNone;
     MeshCoP::ChannelMaskTlv channelMask;
     MeshCoP::EnergyListTlv  energyList;
-    Ip6::MessageInfo        messageInfo;
+    Tmf::MessageInfo        messageInfo(GetInstance());
     Coap::Message *         message;
 
-    VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kEnergyReport));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(UriPath::kEnergyReport);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     channelMask.Init();
     channelMask.SetChannelMask(mChannelMask);
@@ -189,12 +189,11 @@
     SuccessOrExit(error = message->Append(energyList));
     SuccessOrExit(error = message->AppendBytes(mScanResults, mScanResultsLength));
 
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.SetPeerAddr(mCommissioner);
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
+    messageInfo.SetSockAddrToRlocPeerAddrTo(mCommissioner);
+
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
 
-    otLogInfoMeshCoP("sent scan results");
+    LogInfo("sent scan results");
 
 exit:
     FreeMessageOnError(message, error);
diff --git a/src/core/thread/indirect_sender.cpp b/src/core/thread/indirect_sender.cpp
index ed77a45..6b4e68c 100644
--- a/src/core/thread/indirect_sender.cpp
+++ b/src/core/thread/indirect_sender.cpp
@@ -38,7 +38,6 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
 #include "common/message.hpp"
 #include "thread/mesh_forwarder.hpp"
 #include "thread/mle_tlvs.hpp"
@@ -137,18 +136,13 @@
 
 void IndirectSender::ClearAllMessagesForSleepyChild(Child &aChild)
 {
-    Message *message;
-    Message *nextMessage;
-
     VerifyOrExit(aChild.GetIndirectMessageCount() > 0);
 
-    for (message = Get<MeshForwarder>().mSendQueue.GetHead(); message; message = nextMessage)
+    for (Message &message : Get<MeshForwarder>().mSendQueue)
     {
-        nextMessage = message->GetNext();
+        message.ClearChildMask(Get<ChildTable>().GetChildIndex(aChild));
 
-        message->ClearChildMask(Get<ChildTable>().GetChildIndex(aChild));
-
-        Get<MeshForwarder>().RemoveMessageIfNoPendingTx(*message);
+        Get<MeshForwarder>().RemoveMessageIfNoPendingTx(message);
     }
 
     aChild.SetIndirectMessage(nullptr);
@@ -187,12 +181,12 @@
     {
         uint16_t childIndex = Get<ChildTable>().GetChildIndex(aChild);
 
-        for (Message *message = Get<MeshForwarder>().mSendQueue.GetHead(); message; message = message->GetNext())
+        for (Message &message : Get<MeshForwarder>().mSendQueue)
         {
-            if (message->GetChildMask(childIndex))
+            if (message.GetChildMask(childIndex))
             {
-                message->ClearChildMask(childIndex);
-                message->SetDirectTransmission();
+                message.ClearChildMask(childIndex);
+                message.SetDirectTransmission();
             }
         }
 
@@ -215,19 +209,20 @@
 
 Message *IndirectSender::FindIndirectMessage(Child &aChild, bool aSupervisionTypeOnly)
 {
-    Message *message;
+    Message *msg        = nullptr;
     uint16_t childIndex = Get<ChildTable>().GetChildIndex(aChild);
 
-    for (message = Get<MeshForwarder>().mSendQueue.GetHead(); message; message = message->GetNext())
+    for (Message &message : Get<MeshForwarder>().mSendQueue)
     {
-        if (message->GetChildMask(childIndex) &&
-            (!aSupervisionTypeOnly || (message->GetType() == Message::kTypeSupervision)))
+        if (message.GetChildMask(childIndex) &&
+            (!aSupervisionTypeOnly || (message.GetType() == Message::kTypeSupervision)))
         {
+            msg = &message;
             break;
         }
     }
 
-    return message;
+    return msg;
 }
 
 void IndirectSender::RequestMessageUpdate(Child &aChild)
@@ -242,7 +237,7 @@
 
     if ((curMessage != nullptr) && !curMessage->GetChildMask(Get<ChildTable>().GetChildIndex(aChild)))
     {
-        // Set the indirect message for this child to nullptr to ensure
+        // Set the indirect message for this child to `nullptr` to ensure
         // it is not processed on `HandleSentFrameToChild()` callback.
 
         aChild.SetIndirectMessage(nullptr);
@@ -270,18 +265,19 @@
 
     if (curMessage == nullptr)
     {
-        // Current message is nullptr, but new message is not.
+        // Current message is `nullptr`, but new message is not.
         // We have a new indirect message.
 
         UpdateIndirectMessage(aChild);
         ExitNow();
     }
 
-    // Current message and new message differ and are both non-nullptr.
-    // We need to request the frame to be replaced. The current
-    // indirect message can be replaced only if it is the first
-    // fragment. If a next fragment frame for message is already
-    // prepared, we wait for the entire message to be delivered.
+    // Current message and new message differ and are both
+    // non-`nullptr`. We need to request the frame to be replaced.
+    // The current indirect message can be replaced only if it is
+    // the first fragment. If a next fragment frame for message is
+    // already prepared, we wait for the entire message to be
+    // delivered.
 
     VerifyOrExit(aChild.GetIndirectFragmentOffset() == 0);
 
@@ -324,7 +320,7 @@
         mDataPollHandler.HandleNewFrame(aChild);
 
         aChild.GetMacAddress(childAddress);
-        Get<MeshForwarder>().LogMessage(MeshForwarder::kMessagePrepareIndirect, *message, &childAddress, kErrorNone);
+        Get<MeshForwarder>().LogMessage(MeshForwarder::kMessagePrepareIndirect, *message, kErrorNone, &childAddress);
     }
 }
 
@@ -523,7 +519,7 @@
         if (!aFrame.IsEmpty())
         {
             IgnoreError(aFrame.GetDstAddr(macDest));
-            Get<MeshForwarder>().LogMessage(MeshForwarder::kMessageTransmit, *message, &macDest, txError);
+            Get<MeshForwarder>().LogMessage(MeshForwarder::kMessageTransmit, *message, txError, &macDest);
         }
 
         if (message->GetType() == Message::kTypeIp6)
diff --git a/src/core/thread/key_manager.cpp b/src/core/thread/key_manager.cpp
index df10e80..7563972 100644
--- a/src/core/thread/key_manager.cpp
+++ b/src/core/thread/key_manager.cpp
@@ -37,6 +37,7 @@
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
+#include "common/log.hpp"
 #include "common/timer.hpp"
 #include "crypto/hkdf_sha256.hpp"
 #include "crypto/storage.hpp"
@@ -45,6 +46,8 @@
 
 namespace ot {
 
+RegisterLogModule("KeyManager");
+
 const uint8_t KeyManager::kThreadString[] = {
     'T', 'h', 'r', 'e', 'a', 'd',
 };
@@ -69,7 +72,6 @@
     mNativeCommissioningEnabled     = true;
     mRoutersEnabled                 = true;
     mExternalCommissioningEnabled   = true;
-    mBeaconsEnabled                 = true;
     mCommercialCommissioningEnabled = false;
     mAutonomousEnrollmentEnabled    = false;
     mNetworkKeyProvisioningEnabled  = false;
@@ -88,7 +90,6 @@
     mNativeCommissioningEnabled     = aFlags[0] & kNativeCommissioningMask;
     mRoutersEnabled                 = aFlags[0] & kRoutersMask;
     mExternalCommissioningEnabled   = aFlags[0] & kExternalCommissioningMask;
-    mBeaconsEnabled                 = aFlags[0] & kBeaconsMask;
     mCommercialCommissioningEnabled = (aFlags[0] & kCommercialCommissioningMask) == 0;
     mAutonomousEnrollmentEnabled    = (aFlags[0] & kAutonomousEnrollmentMask) == 0;
     mNetworkKeyProvisioningEnabled  = (aFlags[0] & kNetworkKeyProvisioningMask) == 0;
@@ -128,11 +129,6 @@
         aFlags[0] |= kExternalCommissioningMask;
     }
 
-    if (mBeaconsEnabled)
-    {
-        aFlags[0] |= kBeaconsMask;
-    }
-
     if (!mCommercialCommissioningEnabled)
     {
         aFlags[0] |= kCommercialCommissioningMask;
@@ -180,7 +176,7 @@
     , mKekFrameCounter(0)
     , mIsPskcSet(false)
 {
-    IgnoreError(otPlatCryptoInit());
+    otPlatCryptoInit();
 
 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
     {
@@ -347,13 +343,13 @@
         Mac::KeyMaterial prevKey;
         Mac::KeyMaterial nextKey;
 
-        curKey.SetFrom(hashKeys.GetMacKey());
+        curKey.SetFrom(hashKeys.GetMacKey(), kExportableMacKeys);
 
         ComputeKeys(mKeySequence - 1, hashKeys);
-        prevKey.SetFrom(hashKeys.GetMacKey());
+        prevKey.SetFrom(hashKeys.GetMacKey(), kExportableMacKeys);
 
         ComputeKeys(mKeySequence + 1, hashKeys);
-        nextKey.SetFrom(hashKeys.GetMacKey());
+        nextKey.SetFrom(hashKeys.GetMacKey(), kExportableMacKeys);
 
         Get<Mac::SubMac>().SetMacKey(Mac::Frame::kKeyIdMode1, (mKeySequence & 0x7f) + 1, prevKey, curKey, nextKey);
     }
@@ -483,9 +479,16 @@
 
 void KeyManager::SetSecurityPolicy(const SecurityPolicy &aSecurityPolicy)
 {
-    OT_ASSERT(aSecurityPolicy.mRotationTime >= SecurityPolicy::kMinKeyRotationTime);
+    if (aSecurityPolicy.mRotationTime < SecurityPolicy::kMinKeyRotationTime)
+    {
+        LogNote("Key Rotation Time too small: %d", aSecurityPolicy.mRotationTime);
+        ExitNow();
+    }
 
     IgnoreError(Get<Notifier>().Update(mSecurityPolicy, aSecurityPolicy, kEventSecurityPolicyChanged));
+
+exit:
+    return;
 }
 
 void KeyManager::StartKeyRotationTimer(void)
@@ -562,7 +565,7 @@
 {
     NetworkKeyRef keyRef;
 
-    keyRef = kNetworkKeyPsaItsOffset;
+    keyRef = Crypto::Storage::kNetworkKeyRef;
 
     if (!aOverWriteExisting)
     {
@@ -593,7 +596,7 @@
 
 void KeyManager::StorePskc(const Pskc &aPskc)
 {
-    PskcRef keyRef = kPskcPsaItsOffset;
+    PskcRef keyRef = Crypto::Storage::kPskcRef;
 
     Crypto::Storage::DestroyKey(keyRef);
 
diff --git a/src/core/thread/key_manager.hpp b/src/core/thread/key_manager.hpp
index c1b77f5..a8e2e32 100644
--- a/src/core/thread/key_manager.hpp
+++ b/src/core/thread/key_manager.hpp
@@ -39,8 +39,9 @@
 #include <stdint.h>
 
 #include <openthread/dataset.h>
-
 #include <openthread/platform/crypto.h>
+
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/encoding.hpp"
 #include "common/equatable.hpp"
@@ -210,9 +211,6 @@
 class KeyManager : public InstanceLocator, private NonCopyable
 {
 public:
-    static constexpr uint32_t kNetworkKeyPsaItsOffset = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 1;
-    static constexpr uint32_t kPskcPsaItsOffset       = OPENTHREAD_CONFIG_PSA_ITS_NVM_OFFSET + 2;
-
     /**
      * This constructor initializes the object.
      *
@@ -553,6 +551,7 @@
 private:
     static constexpr uint32_t kDefaultKeySwitchGuardTime = 624;
     static constexpr uint32_t kOneHourIntervalInMsec     = 3600u * 1000u;
+    static constexpr bool     kExportableMacKeys         = OPENTHREAD_CONFIG_PLATFORM_MAC_KEYS_EXPORTABLE_ENABLE;
 
     OT_TOOL_PACKED_BEGIN
     struct Keys
@@ -636,6 +635,10 @@
  * @}
  */
 
+DefineCoreType(otSecurityPolicy, SecurityPolicy);
+DefineCoreType(otNetworkKey, NetworkKey);
+DefineCoreType(otPskc, Pskc);
+
 } // namespace ot
 
 #endif // KEY_MANAGER_HPP_
diff --git a/src/core/thread/link_metrics.cpp b/src/core/thread/link_metrics.cpp
index 265a96c..c9c917b 100644
--- a/src/core/thread/link_metrics.cpp
+++ b/src/core/thread/link_metrics.cpp
@@ -39,7 +39,7 @@
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "mac/mac.hpp"
 #include "thread/link_metrics_tlvs.hpp"
 #include "thread/neighbor_table.hpp"
@@ -47,6 +47,8 @@
 namespace ot {
 namespace LinkMetrics {
 
+RegisterLogModule("LinkMetrics");
+
 using ot::Encoding::BigEndian::HostSwap32;
 
 void SeriesInfo::Init(uint8_t aSeriesId, const SeriesFlags &aSeriesFlags, const Metrics &aMetrics)
@@ -115,7 +117,7 @@
     Neighbor *  neighbor         = GetNeighborFromLinkLocalAddr(aDestination);
 
     VerifyOrExit(neighbor != nullptr, error = kErrorUnknownNeighbor);
-    VerifyOrExit(neighbor->IsThreadVersion1p2(), error = kErrorNotCapable);
+    VerifyOrExit(neighbor->IsThreadVersion1p2OrHigher(), error = kErrorNotCapable);
 
     if (aMetrics != nullptr)
     {
@@ -148,7 +150,7 @@
     Neighbor *   neighbor          = GetNeighborFromLinkLocalAddr(aDestination);
 
     VerifyOrExit(neighbor != nullptr, error = kErrorUnknownNeighbor);
-    VerifyOrExit(neighbor->IsThreadVersion1p2(), error = kErrorNotCapable);
+    VerifyOrExit(neighbor->IsThreadVersion1p2OrHigher(), error = kErrorNotCapable);
 
     // Directly transform `aMetrics` into TypeIdFlags and put them into `subTlvs`
     if (aMetrics != nullptr)
@@ -171,7 +173,7 @@
     error = Get<Mle::MleRouter>().SendLinkMetricsManagementRequest(aDestination, subTlvs, fwdProbingSubTlv->GetSize());
 
 exit:
-    otLogDebgMle("SendMgmtRequestForwardTrackingSeries, error:%s, Series ID:%u", ErrorToString(error), aSeriesId);
+    LogDebg("SendMgmtRequestForwardTrackingSeries, error:%s, Series ID:%u", ErrorToString(error), aSeriesId);
     return error;
 }
 
@@ -185,7 +187,7 @@
     Neighbor *         neighbor = GetNeighborFromLinkLocalAddr(aDestination);
 
     VerifyOrExit(neighbor != nullptr, error = kErrorUnknownNeighbor);
-    VerifyOrExit(neighbor->IsThreadVersion1p2(), error = kErrorNotCapable);
+    VerifyOrExit(neighbor->IsThreadVersion1p2OrHigher(), error = kErrorNotCapable);
 
     if (aEnhAckFlags == kEnhAckClear)
     {
@@ -225,7 +227,7 @@
     Neighbor *neighbor = GetNeighborFromLinkLocalAddr(aDestination);
 
     VerifyOrExit(neighbor != nullptr, error = kErrorUnknownNeighbor);
-    VerifyOrExit(neighbor->IsThreadVersion1p2(), error = kErrorNotCapable);
+    VerifyOrExit(neighbor->IsThreadVersion1p2OrHigher(), error = kErrorNotCapable);
 
     VerifyOrExit(aLength <= LinkMetrics::kLinkProbeMaxLen && aSeriesId != kQueryIdSingleProbe &&
                      aSeriesId != kSeriesIdAllSeries,
@@ -233,7 +235,7 @@
 
     error = Get<Mle::MleRouter>().SendLinkProbe(aDestination, aSeriesId, buf, aLength);
 exit:
-    otLogDebgMle("SendLinkProbe, error:%s, Series ID:%u", ErrorToString(error), aSeriesId);
+    LogDebg("SendLinkProbe, error:%s, Series ID:%u", ErrorToString(error), aSeriesId);
     return error;
 }
 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
@@ -332,7 +334,7 @@
     aMessage.Write(startOffset, tlv);
 
 exit:
-    otLogDebgMle("AppendReport, error:%s", ErrorToString(error));
+    LogDebg("AppendReport, error:%s", ErrorToString(error));
     return error;
 }
 
@@ -510,14 +512,14 @@
                 SuccessOrExit(aMessage.Read(pos, values.mPduCountValue));
                 values.mPduCountValue = HostSwap32(values.mPduCountValue);
                 pos += sizeof(uint32_t);
-                otLogDebgMle(" - PDU Counter: %d (Count/Summation)", values.mPduCountValue);
+                LogDebg(" - PDU Counter: %d (Count/Summation)", values.mPduCountValue);
                 break;
 
             case TypeIdFlags::kLqi:
                 values.GetMetrics().mLqi = true;
                 SuccessOrExit(aMessage.Read(pos, values.mLqiValue));
                 pos += sizeof(uint8_t);
-                otLogDebgMle(" - LQI: %d (Exponential Moving Average)", values.mLqiValue);
+                LogDebg(" - LQI: %d (Exponential Moving Average)", values.mLqiValue);
                 break;
 
             case TypeIdFlags::kLinkMargin:
@@ -526,7 +528,7 @@
                 // Reverse operation for linear scale, map from [0, 255] to [0, 130]
                 values.mLinkMarginValue = rawValue * 130 / 255;
                 pos += sizeof(uint8_t);
-                otLogDebgMle(" - Margin: %d (dB) (Exponential Moving Average)", values.mLinkMarginValue);
+                LogDebg(" - Margin: %d (dB) (Exponential Moving Average)", values.mLinkMarginValue);
                 break;
 
             case TypeIdFlags::kRssi:
@@ -535,7 +537,7 @@
                 // Reverse operation for linear scale, map from [0, 255] to [-130, 0]
                 values.mRssiValue = rawValue * 130 / 255 - 130;
                 pos += sizeof(uint8_t);
-                otLogDebgMle(" - RSSI: %d (dBm) (Exponential Moving Average)", values.mRssiValue);
+                LogDebg(" - RSSI: %d (dBm) (Exponential Moving Average)", values.mRssiValue);
                 break;
 
             default:
@@ -555,7 +557,7 @@
     }
 
 exit:
-    otLogDebgMle("HandleReport, error:%s", ErrorToString(error));
+    LogDebg("HandleReport, error:%s", ErrorToString(error));
     return;
 }
 
diff --git a/src/core/thread/link_metrics.hpp b/src/core/thread/link_metrics.hpp
index 8bfc2b0..318aea0 100644
--- a/src/core/thread/link_metrics.hpp
+++ b/src/core/thread/link_metrics.hpp
@@ -45,6 +45,7 @@
 
 #include <openthread/link.h>
 
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/locator.hpp"
 #include "common/message.hpp"
@@ -401,7 +402,7 @@
      * This method processes received Enh-ACK Probing IE data.
      *
      * @param[in] aData      A pointer to buffer containing the Enh-ACK Probing IE data.
-     * @param[in] aLen       The length of @p aData.
+     * @param[in] aLength    The length of @p aData.
      * @param[in] aNeighbor  The neighbor from which the Enh-ACK Probing IE was received.
      *
      */
@@ -453,6 +454,11 @@
  */
 
 } // namespace LinkMetrics
+
+DefineCoreType(otLinkMetrics, LinkMetrics::Metrics);
+DefineCoreType(otLinkMetricsValues, LinkMetrics::MetricsValues);
+DefineMapEnum(otLinkMetricsEnhAckFlags, LinkMetrics::EnhAckFlags);
+
 } // namespace ot
 
 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
diff --git a/src/core/thread/link_metrics_tlvs.hpp b/src/core/thread/link_metrics_tlvs.hpp
index 10f9f0b..118f730 100644
--- a/src/core/thread/link_metrics_tlvs.hpp
+++ b/src/core/thread/link_metrics_tlvs.hpp
@@ -329,7 +329,7 @@
     /**
      * This method sets the Link Metrics Type ID.
      *
-     * @param[in]  aMetricsTypeID  The Link Metrics Type ID to set.
+     * @param[in]  aMetricsTypeId  The Link Metrics Type ID to set.
      *
      */
     void SetMetricsTypeId(TypeIdFlags aMetricsTypeId)
diff --git a/src/core/thread/link_quality.cpp b/src/core/thread/link_quality.cpp
index c16d114..f3e1cb2 100644
--- a/src/core/thread/link_quality.cpp
+++ b/src/core/thread/link_quality.cpp
@@ -131,7 +131,7 @@
 void LinkQualityInfo::Clear(void)
 {
     mRssAverager.Clear();
-    SetLinkQuality(0);
+    SetLinkQuality(kLinkQuality0);
     mLastRss = OT_RADIO_RSSI_INVALID;
 
     mFrameErrorRate.Clear();
@@ -186,31 +186,31 @@
     return static_cast<uint8_t>(linkMargin);
 }
 
-uint8_t LinkQualityInfo::ConvertLinkMarginToLinkQuality(uint8_t aLinkMargin)
+LinkQuality LinkQualityInfo::ConvertLinkMarginToLinkQuality(uint8_t aLinkMargin)
 {
     return CalculateLinkQuality(aLinkMargin, kNoLinkQuality);
 }
 
-uint8_t LinkQualityInfo::ConvertRssToLinkQuality(int8_t aNoiseFloor, int8_t aRss)
+LinkQuality LinkQualityInfo::ConvertRssToLinkQuality(int8_t aNoiseFloor, int8_t aRss)
 {
     return ConvertLinkMarginToLinkQuality(ConvertRssToLinkMargin(aNoiseFloor, aRss));
 }
 
-int8_t LinkQualityInfo::ConvertLinkQualityToRss(int8_t aNoiseFloor, uint8_t aLinkQuality)
+int8_t LinkQualityInfo::ConvertLinkQualityToRss(int8_t aNoiseFloor, LinkQuality aLinkQuality)
 {
     int8_t linkmargin = 0;
 
     switch (aLinkQuality)
     {
-    case 3:
+    case kLinkQuality3:
         linkmargin = kLinkQuality3LinkMargin;
         break;
 
-    case 2:
+    case kLinkQuality2:
         linkmargin = kLinkQuality2LinkMargin;
         break;
 
-    case 1:
+    case kLinkQuality1:
         linkmargin = kLinkQuality1LinkMargin;
         break;
 
@@ -222,7 +222,7 @@
     return linkmargin + aNoiseFloor;
 }
 
-uint8_t LinkQualityInfo::CalculateLinkQuality(uint8_t aLinkMargin, uint8_t aLastLinkQuality)
+LinkQuality LinkQualityInfo::CalculateLinkQuality(uint8_t aLinkMargin, uint8_t aLastLinkQuality)
 {
     // Static private method to calculate the link quality from a given
     // link margin while taking into account the last link quality
@@ -230,8 +230,8 @@
     // there is no previous value for link quality, the constant
     // kNoLinkQuality should be passed as the second argument.
 
-    uint8_t threshold1, threshold2, threshold3;
-    uint8_t linkQuality = 0;
+    uint8_t     threshold1, threshold2, threshold3;
+    LinkQuality linkQuality = kLinkQuality0;
 
     threshold1 = kThreshold1;
     threshold2 = kThreshold2;
@@ -262,15 +262,15 @@
 
     if (aLinkMargin > threshold3)
     {
-        linkQuality = 3;
+        linkQuality = kLinkQuality3;
     }
     else if (aLinkMargin > threshold2)
     {
-        linkQuality = 2;
+        linkQuality = kLinkQuality2;
     }
     else if (aLinkMargin > threshold1)
     {
-        linkQuality = 1;
+        linkQuality = kLinkQuality1;
     }
 
     return linkQuality;
diff --git a/src/core/thread/link_quality.hpp b/src/core/thread/link_quality.hpp
index a7d34e9..bc10957 100644
--- a/src/core/thread/link_quality.hpp
+++ b/src/core/thread/link_quality.hpp
@@ -227,6 +227,21 @@
 };
 
 /**
+ * This enumeration represents the link quality constants.
+ *
+ * Link Quality is an integer in [0, 3]. A higher link quality indicates a more usable link, with 0 indicating that the
+ * link is non-existent or unusable.
+ *
+ */
+enum LinkQuality : uint8_t
+{
+    kLinkQuality0 = 0, ///< Link quality 0 (non-existent link)
+    kLinkQuality1 = 1, ///< Link quality 1
+    kLinkQuality2 = 2, ///< Link quality 2
+    kLinkQuality3 = 3, ///< Link quality 3
+};
+
+/**
  * This class encapsulates/stores all relevant information about quality of a link, including average received signal
  * strength (RSS), last RSS, link margin, and link quality.
  *
@@ -312,7 +327,7 @@
      * @returns The current link quality value (value 0-3 as per Thread specification).
      *
      */
-    uint8_t GetLinkQuality(void) const { return mLinkQuality; }
+    LinkQuality GetLinkQuality(void) const { return mLinkQuality; }
 
     /**
      * Returns the most recent RSS value.
@@ -391,7 +406,7 @@
      * @returns The link quality value (0-3).
      *
      */
-    static uint8_t ConvertLinkMarginToLinkQuality(uint8_t aLinkMargin);
+    static LinkQuality ConvertLinkMarginToLinkQuality(uint8_t aLinkMargin);
 
     /**
      * This method converts a received signal strength value to a link quality value.
@@ -402,7 +417,7 @@
      * @returns The link quality value (0-3).
      *
      */
-    static uint8_t ConvertRssToLinkQuality(int8_t aNoiseFloor, int8_t aRss);
+    static LinkQuality ConvertRssToLinkQuality(int8_t aNoiseFloor, int8_t aRss);
 
     /**
      * This method converts a link quality value to a typical received signal strength value.
@@ -415,7 +430,7 @@
      * @returns The typical platform RSSI.
      *
      */
-    static int8_t ConvertLinkQualityToRss(int8_t aNoiseFloor, uint8_t aLinkQuality);
+    static int8_t ConvertLinkQualityToRss(int8_t aNoiseFloor, LinkQuality aLinkQuality);
 
 private:
     // Constants for obtaining link quality from link margin:
@@ -432,12 +447,12 @@
 
     static constexpr uint8_t kNoLinkQuality = 0xff; // Indicate that there is no previous/last link quality.
 
-    void SetLinkQuality(uint8_t aLinkQuality) { mLinkQuality = aLinkQuality; }
+    void SetLinkQuality(LinkQuality aLinkQuality) { mLinkQuality = aLinkQuality; }
 
-    static uint8_t CalculateLinkQuality(uint8_t aLinkMargin, uint8_t aLastLinkQuality);
+    static LinkQuality CalculateLinkQuality(uint8_t aLinkMargin, uint8_t aLastLinkQuality);
 
     RssAverager mRssAverager;
-    uint8_t     mLinkQuality;
+    LinkQuality mLinkQuality;
     int8_t      mLastRss;
 
     SuccessRateTracker mFrameErrorRate;
diff --git a/src/core/thread/lowpan.cpp b/src/core/thread/lowpan.cpp
index f9e1133..d373fbe 100644
--- a/src/core/thread/lowpan.cpp
+++ b/src/core/thread/lowpan.cpp
@@ -95,10 +95,9 @@
                                 const Ip6::Address &aIpAddr,
                                 const Context &     aContext,
                                 uint16_t &          aHcCtl,
-                                BufferWriter &      aBuf)
+                                FrameBuilder &      aFrameBuilder)
 {
     Error        error = kErrorNone;
-    BufferWriter buf   = aBuf;
     Ip6::Address ipaddr;
     Mac::Address tmp;
 
@@ -116,21 +115,16 @@
         if (ipaddr.GetIid() == aIpAddr.GetIid())
         {
             aHcCtl |= kHcSrcAddrMode2;
-            SuccessOrExit(error = buf.Write(aIpAddr.mFields.m8 + 14, 2));
+            SuccessOrExit(error = aFrameBuilder.AppendBytes(aIpAddr.mFields.m8 + 14, 2));
         }
         else
         {
             aHcCtl |= kHcSrcAddrMode1;
-            SuccessOrExit(error = buf.Write(aIpAddr.GetIid().GetBytes(), Ip6::InterfaceIdentifier::kSize));
+            SuccessOrExit(error = aFrameBuilder.Append(aIpAddr.GetIid()));
         }
     }
 
 exit:
-    if (error == kErrorNone)
-    {
-        aBuf = buf;
-    }
-
     return error;
 }
 
@@ -138,10 +132,9 @@
                                      const Ip6::Address &aIpAddr,
                                      const Context &     aContext,
                                      uint16_t &          aHcCtl,
-                                     BufferWriter &      aBuf)
+                                     FrameBuilder &      aFrameBuilder)
 {
     Error        error = kErrorNone;
-    BufferWriter buf   = aBuf;
     Ip6::Address ipaddr;
     Mac::Address tmp;
 
@@ -159,29 +152,23 @@
         if (ipaddr.GetIid() == aIpAddr.GetIid())
         {
             aHcCtl |= kHcDstAddrMode2;
-            SuccessOrExit(error = buf.Write(aIpAddr.mFields.m8 + 14, 2));
+            SuccessOrExit(error = aFrameBuilder.AppendBytes(aIpAddr.mFields.m8 + 14, 2));
         }
         else
         {
             aHcCtl |= kHcDstAddrMode1;
-            SuccessOrExit(error = buf.Write(aIpAddr.GetIid().GetBytes(), Ip6::InterfaceIdentifier::kSize));
+            SuccessOrExit(error = aFrameBuilder.Append(aIpAddr.GetIid()));
         }
     }
 
 exit:
-    if (error == kErrorNone)
-    {
-        aBuf = buf;
-    }
-
     return error;
 }
 
-Error Lowpan::CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, BufferWriter &aBuf)
+Error Lowpan::CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, FrameBuilder &aFrameBuilder)
 {
-    Error        error = kErrorNone;
-    BufferWriter buf   = aBuf;
-    Context      multicastContext;
+    Error   error = kErrorNone;
+    Context multicastContext;
 
     aHcCtl |= kHcMulticast;
 
@@ -193,21 +180,21 @@
             if (aIpAddr.mFields.m8[1] == 0x02 && i >= 15)
             {
                 aHcCtl |= kHcDstAddrMode3;
-                SuccessOrExit(error = buf.Write(aIpAddr.mFields.m8[15]));
+                SuccessOrExit(error = aFrameBuilder.AppendUint8(aIpAddr.mFields.m8[15]));
             }
             // Check if multicast address can be compressed to 32-bits (ffxx::00xx:xxxx)
             else if (i >= 13)
             {
                 aHcCtl |= kHcDstAddrMode2;
-                SuccessOrExit(error = buf.Write(aIpAddr.mFields.m8[1]));
-                SuccessOrExit(error = buf.Write(aIpAddr.mFields.m8 + 13, 3));
+                SuccessOrExit(error = aFrameBuilder.AppendUint8(aIpAddr.mFields.m8[1]));
+                SuccessOrExit(error = aFrameBuilder.AppendBytes(aIpAddr.mFields.m8 + 13, 3));
             }
             // Check if multicast address can be compressed to 48-bits (ffxx::00xx:xxxx:xxxx)
             else if (i >= 11)
             {
                 aHcCtl |= kHcDstAddrMode1;
-                SuccessOrExit(error = buf.Write(aIpAddr.mFields.m8[1]));
-                SuccessOrExit(error = buf.Write(aIpAddr.mFields.m8 + 11, 5));
+                SuccessOrExit(error = aFrameBuilder.AppendUint8(aIpAddr.mFields.m8[1]));
+                SuccessOrExit(error = aFrameBuilder.AppendBytes(aIpAddr.mFields.m8 + 11, 5));
             }
             else
             {
@@ -217,12 +204,12 @@
                     memcmp(multicastContext.mPrefix.GetBytes(), aIpAddr.mFields.m8 + 4, 8) == 0)
                 {
                     aHcCtl |= kHcDstAddrContext | kHcDstAddrMode0;
-                    SuccessOrExit(error = buf.Write(aIpAddr.mFields.m8 + 1, 2));
-                    SuccessOrExit(error = buf.Write(aIpAddr.mFields.m8 + 12, 4));
+                    SuccessOrExit(error = aFrameBuilder.AppendBytes(aIpAddr.mFields.m8 + 1, 2));
+                    SuccessOrExit(error = aFrameBuilder.AppendBytes(aIpAddr.mFields.m8 + 12, 4));
                 }
                 else
                 {
-                    SuccessOrExit(error = buf.Write(aIpAddr.mFields.m8, sizeof(Ip6::Address)));
+                    SuccessOrExit(error = aFrameBuilder.Append(aIpAddr));
                 }
             }
 
@@ -231,41 +218,47 @@
     }
 
 exit:
-    if (error == kErrorNone)
-    {
-        aBuf = buf;
-    }
-
     return error;
 }
 
 Error Lowpan::Compress(Message &           aMessage,
                        const Mac::Address &aMacSource,
                        const Mac::Address &aMacDest,
-                       BufferWriter &      aBuf)
+                       FrameBuilder &      aFrameBuilder)
 {
-    Error   error;
+    Error   error       = kErrorNone;
     uint8_t headerDepth = 0xff;
 
-    do
+    while (headerDepth > 0)
     {
-        error = Compress(aMessage, aMacSource, aMacDest, aBuf, headerDepth);
-    } while ((error != kErrorNone) && (headerDepth > 0));
+        FrameBuilder frameBuilder = aFrameBuilder;
 
+        error = Compress(aMessage, aMacSource, aMacDest, aFrameBuilder, headerDepth);
+
+        // We exit if `Compress()` is successful. Otherwise we reset
+        // the `aFrameBuidler` to its earlier state (remove all
+        // appended content from the failed `Compress()` call) and
+        // try again with a different `headerDepth`.
+
+        VerifyOrExit(error != kErrorNone);
+        aFrameBuilder = frameBuilder;
+    }
+
+exit:
     return error;
 }
 
 Error Lowpan::Compress(Message &           aMessage,
                        const Mac::Address &aMacSource,
                        const Mac::Address &aMacDest,
-                       BufferWriter &      aBuf,
+                       FrameBuilder &      aFrameBuilder,
                        uint8_t &           aHeaderDepth)
 {
     Error                error       = kErrorNone;
     NetworkData::Leader &networkData = Get<NetworkData::Leader>();
     uint16_t             startOffset = aMessage.GetOffset();
-    BufferWriter         buf         = aBuf;
     uint16_t             hcCtl       = kHcDispatch;
+    uint16_t             hcCtlOffset = 0;
     Ip6::Header          ip6Header;
     uint8_t *            ip6HeaderBytes = reinterpret_cast<uint8_t *>(&ip6Header);
     Context              srcContext, dstContext;
@@ -295,13 +288,14 @@
     }
 
     // Lowpan HC Control Bits
-    SuccessOrExit(error = buf.Advance(sizeof(hcCtl)));
+    hcCtlOffset = aFrameBuilder.GetLength();
+    SuccessOrExit(error = aFrameBuilder.AppendBigEndianUint16(hcCtl));
 
     // Context Identifier
     if (srcContext.mContextId != 0 || dstContext.mContextId != 0)
     {
         hcCtl |= kHcContextId;
-        SuccessOrExit(error = buf.Write(((srcContext.mContextId << 4) | dstContext.mContextId) & 0xff));
+        SuccessOrExit(error = aFrameBuilder.AppendUint8(((srcContext.mContextId << 4) | dstContext.mContextId) & 0xff));
     }
 
     dscp = ((ip6HeaderBytes[0] << 2) & 0x3c) | (ip6HeaderBytes[1] >> 6);
@@ -320,7 +314,7 @@
             // Elide Flow Label and carry Traffic Class in-line.
             hcCtl |= kHcFlowLabel;
 
-            SuccessOrExit(error = buf.Write(ecn | dscp));
+            SuccessOrExit(error = aFrameBuilder.AppendUint8(ecn | dscp));
         }
     }
     else if (dscp == 0)
@@ -328,15 +322,15 @@
         // Carry Flow Label and ECN only with 2-bit padding.
         hcCtl |= kHcTrafficClass;
 
-        SuccessOrExit(error = buf.Write(ecn | (ip6HeaderBytes[1] & 0x0f)));
-        SuccessOrExit(error = buf.Write(ip6HeaderBytes + 2, 2));
+        SuccessOrExit(error = aFrameBuilder.AppendUint8(ecn | (ip6HeaderBytes[1] & 0x0f)));
+        SuccessOrExit(error = aFrameBuilder.AppendBytes(ip6HeaderBytes + 2, 2));
     }
     else
     {
         // Carry Flow Label and Traffic Class in-line.
-        SuccessOrExit(error = buf.Write(ecn | dscp));
-        SuccessOrExit(error = buf.Write(ip6HeaderBytes[1] & 0x0f));
-        SuccessOrExit(error = buf.Write(ip6HeaderBytes + 2, 2));
+        SuccessOrExit(error = aFrameBuilder.AppendUint8(ecn | dscp));
+        SuccessOrExit(error = aFrameBuilder.AppendUint8(ip6HeaderBytes[1] & 0x0f));
+        SuccessOrExit(error = aFrameBuilder.AppendBytes(ip6HeaderBytes + 2, 2));
     }
 
     // Next Header
@@ -353,7 +347,7 @@
         OT_FALL_THROUGH;
 
     default:
-        SuccessOrExit(error = buf.Write(static_cast<uint8_t>(ip6Header.GetNextHeader())));
+        SuccessOrExit(error = aFrameBuilder.AppendUint8(static_cast<uint8_t>(ip6Header.GetNextHeader())));
         break;
     }
 
@@ -373,7 +367,7 @@
         break;
 
     default:
-        SuccessOrExit(error = buf.Write(ip6Header.GetHopLimit()));
+        SuccessOrExit(error = aFrameBuilder.AppendUint8(ip6Header.GetHopLimit()));
         break;
     }
 
@@ -384,35 +378,37 @@
     }
     else if (ip6Header.GetSource().IsLinkLocal())
     {
-        SuccessOrExit(error = CompressSourceIid(aMacSource, ip6Header.GetSource(), srcContext, hcCtl, buf));
+        SuccessOrExit(error = CompressSourceIid(aMacSource, ip6Header.GetSource(), srcContext, hcCtl, aFrameBuilder));
     }
     else if (srcContextValid)
     {
         hcCtl |= kHcSrcAddrContext;
-        SuccessOrExit(error = CompressSourceIid(aMacSource, ip6Header.GetSource(), srcContext, hcCtl, buf));
+        SuccessOrExit(error = CompressSourceIid(aMacSource, ip6Header.GetSource(), srcContext, hcCtl, aFrameBuilder));
     }
     else
     {
-        SuccessOrExit(error = buf.Write(ip6Header.GetSource().mFields.m8, sizeof(ip6Header.GetSource())));
+        SuccessOrExit(error = aFrameBuilder.Append(ip6Header.GetSource()));
     }
 
     // Destination Address
     if (ip6Header.GetDestination().IsMulticast())
     {
-        SuccessOrExit(error = CompressMulticast(ip6Header.GetDestination(), hcCtl, buf));
+        SuccessOrExit(error = CompressMulticast(ip6Header.GetDestination(), hcCtl, aFrameBuilder));
     }
     else if (ip6Header.GetDestination().IsLinkLocal())
     {
-        SuccessOrExit(error = CompressDestinationIid(aMacDest, ip6Header.GetDestination(), dstContext, hcCtl, buf));
+        SuccessOrExit(
+            error = CompressDestinationIid(aMacDest, ip6Header.GetDestination(), dstContext, hcCtl, aFrameBuilder));
     }
     else if (dstContextValid)
     {
         hcCtl |= kHcDstAddrContext;
-        SuccessOrExit(error = CompressDestinationIid(aMacDest, ip6Header.GetDestination(), dstContext, hcCtl, buf));
+        SuccessOrExit(
+            error = CompressDestinationIid(aMacDest, ip6Header.GetDestination(), dstContext, hcCtl, aFrameBuilder));
     }
     else
     {
-        SuccessOrExit(error = buf.Write(&ip6Header.GetDestination(), sizeof(ip6Header.GetDestination())));
+        SuccessOrExit(error = aFrameBuilder.Append(ip6Header.GetDestination()));
     }
 
     headerDepth++;
@@ -426,18 +422,18 @@
         switch (nextHeader)
         {
         case Ip6::kProtoHopOpts:
-            SuccessOrExit(error = CompressExtensionHeader(aMessage, buf, nextHeader));
+            SuccessOrExit(error = CompressExtensionHeader(aMessage, aFrameBuilder, nextHeader));
             break;
 
         case Ip6::kProtoUdp:
-            error = CompressUdp(aMessage, buf);
+            error = CompressUdp(aMessage, aFrameBuilder);
             ExitNow();
 
         case Ip6::kProtoIp6:
             // For IP-in-IP the NH bit of the LOWPAN_NHC encoding MUST be set to zero.
-            SuccessOrExit(error = buf.Write(kExtHdrDispatch | kExtHdrEidIp6));
+            SuccessOrExit(error = aFrameBuilder.AppendUint8(kExtHdrDispatch | kExtHdrEidIp6));
 
-            error = Compress(aMessage, aMacSource, aMacDest, buf);
+            error = Compress(aMessage, aMacSource, aMacDest, aFrameBuilder);
 
             OT_FALL_THROUGH;
 
@@ -453,9 +449,7 @@
 
     if (error == kErrorNone)
     {
-        IgnoreError(aBuf.Write(hcCtl >> 8));
-        IgnoreError(aBuf.Write(hcCtl & 0xff));
-        aBuf = buf;
+        aFrameBuilder.Write<uint16_t>(hcCtlOffset, HostSwap16(hcCtl));
     }
     else
     {
@@ -465,10 +459,9 @@
     return error;
 }
 
-Error Lowpan::CompressExtensionHeader(Message &aMessage, BufferWriter &aBuf, uint8_t &aNextHeader)
+Error Lowpan::CompressExtensionHeader(Message &aMessage, FrameBuilder &aFrameBuilder, uint8_t &aNextHeader)
 {
     Error                error       = kErrorNone;
-    BufferWriter         buf         = aBuf;
     uint16_t             startOffset = aMessage.GetOffset();
     Ip6::ExtensionHeader extHeader;
     uint16_t             len;
@@ -488,12 +481,12 @@
         break;
 
     default:
-        SuccessOrExit(error = buf.Write(tmpByte));
+        SuccessOrExit(error = aFrameBuilder.AppendUint8(tmpByte));
         tmpByte = static_cast<uint8_t>(extHeader.GetNextHeader());
         break;
     }
 
-    SuccessOrExit(error = buf.Write(tmpByte));
+    SuccessOrExit(error = aFrameBuilder.AppendUint8(tmpByte));
 
     len = (extHeader.GetLength() + 1) * 8 - sizeof(extHeader);
 
@@ -540,16 +533,12 @@
 
     aNextHeader = static_cast<uint8_t>(extHeader.GetNextHeader());
 
-    SuccessOrExit(error = buf.Write(static_cast<uint8_t>(len)));
-    SuccessOrExit(error = buf.Write(aMessage, static_cast<uint8_t>(len)));
+    SuccessOrExit(error = aFrameBuilder.AppendUint8(static_cast<uint8_t>(len)));
+    SuccessOrExit(error = aFrameBuilder.AppendBytesFromMessage(aMessage, aMessage.GetOffset(), len));
     aMessage.MoveOffset(len + padLength);
 
 exit:
-    if (error == kErrorNone)
-    {
-        aBuf = buf;
-    }
-    else
+    if (error != kErrorNone)
     {
         aMessage.SetOffset(startOffset);
     }
@@ -557,10 +546,9 @@
     return error;
 }
 
-Error Lowpan::CompressUdp(Message &aMessage, BufferWriter &aBuf)
+Error Lowpan::CompressUdp(Message &aMessage, FrameBuilder &aFrameBuilder)
 {
     Error            error       = kErrorNone;
-    BufferWriter     buf         = aBuf;
     uint16_t         startOffset = aMessage.GetOffset();
     Ip6::Udp::Header udpHeader;
     uint16_t         source;
@@ -573,40 +561,33 @@
 
     if ((source & 0xfff0) == 0xf0b0 && (destination & 0xfff0) == 0xf0b0)
     {
-        SuccessOrExit(error = buf.Write(kUdpDispatch | 3));
-        SuccessOrExit(error = buf.Write((((source & 0xf) << 4) | (destination & 0xf)) & 0xff));
+        SuccessOrExit(error = aFrameBuilder.AppendUint8(kUdpDispatch | 3));
+        SuccessOrExit(error = aFrameBuilder.AppendUint8((((source & 0xf) << 4) | (destination & 0xf)) & 0xff));
     }
     else if ((source & 0xff00) == 0xf000)
     {
-        SuccessOrExit(error = buf.Write(kUdpDispatch | 2));
-        SuccessOrExit(error = buf.Write(source & 0xff));
-        SuccessOrExit(error = buf.Write(destination >> 8));
-        SuccessOrExit(error = buf.Write(destination & 0xff));
+        SuccessOrExit(error = aFrameBuilder.AppendUint8(kUdpDispatch | 2));
+        SuccessOrExit(error = aFrameBuilder.AppendUint8(source & 0xff));
+        SuccessOrExit(error = aFrameBuilder.AppendBigEndianUint16(destination));
     }
     else if ((destination & 0xff00) == 0xf000)
     {
-        SuccessOrExit(error = buf.Write(kUdpDispatch | 1));
-        SuccessOrExit(error = buf.Write(source >> 8));
-        SuccessOrExit(error = buf.Write(source & 0xff));
-        SuccessOrExit(error = buf.Write(destination & 0xff));
+        SuccessOrExit(error = aFrameBuilder.AppendUint8(kUdpDispatch | 1));
+        SuccessOrExit(error = aFrameBuilder.AppendBigEndianUint16(source));
+        SuccessOrExit(error = aFrameBuilder.AppendUint8(destination & 0xff));
     }
     else
     {
-        SuccessOrExit(error = buf.Write(kUdpDispatch));
-        SuccessOrExit(error = buf.Write(&udpHeader, Ip6::Udp::Header::kLengthFieldOffset));
+        SuccessOrExit(error = aFrameBuilder.AppendUint8(kUdpDispatch));
+        SuccessOrExit(error = aFrameBuilder.AppendBytes(&udpHeader, Ip6::Udp::Header::kLengthFieldOffset));
     }
 
-    SuccessOrExit(error =
-                      buf.Write(reinterpret_cast<uint8_t *>(&udpHeader) + Ip6::Udp::Header::kChecksumFieldOffset, 2));
+    SuccessOrExit(error = aFrameBuilder.AppendBigEndianUint16(udpHeader.GetChecksum()));
 
     aMessage.MoveOffset(sizeof(udpHeader));
 
 exit:
-    if (error == kErrorNone)
-    {
-        aBuf = buf;
-    }
-    else
+    if (error != kErrorNone)
     {
         aMessage.SetOffset(startOffset);
     }
@@ -655,26 +636,21 @@
     return error;
 }
 
-int Lowpan::DecompressBaseHeader(Ip6::Header &       aIp6Header,
-                                 bool &              aCompressedNextHeader,
-                                 const Mac::Address &aMacSource,
-                                 const Mac::Address &aMacDest,
-                                 const uint8_t *     aBuf,
-                                 uint16_t            aBufLength)
+Error Lowpan::DecompressBaseHeader(Ip6::Header &       aIp6Header,
+                                   bool &              aCompressedNextHeader,
+                                   const Mac::Address &aMacSource,
+                                   const Mac::Address &aMacDest,
+                                   FrameData &         aFrameData)
 {
     NetworkData::Leader &networkData = Get<NetworkData::Leader>();
     Error                error       = kErrorParse;
-    const uint8_t *      cur         = aBuf;
-    const uint8_t *      end         = aBuf + aBufLength;
     uint16_t             hcCtl;
+    uint8_t              byte;
     Context              srcContext, dstContext;
     bool                 srcContextValid = true, dstContextValid = true;
     uint8_t              nextHeader;
-    uint8_t *            bytes;
 
-    VerifyOrExit(cur + 2 <= end);
-    hcCtl = ReadUint16(cur);
-    cur += 2;
+    SuccessOrExit(aFrameData.ReadBigEndianUint16(hcCtl));
 
     // check Dispatch bits
     VerifyOrExit((hcCtl & kHcDispatchMask) == kHcDispatch);
@@ -685,19 +661,17 @@
 
     if ((hcCtl & kHcContextId) != 0)
     {
-        VerifyOrExit(cur < end);
+        SuccessOrExit(aFrameData.ReadUint8(byte));
 
-        if (networkData.GetContext(cur[0] >> 4, srcContext) != kErrorNone)
+        if (networkData.GetContext(byte >> 4, srcContext) != kErrorNone)
         {
             srcContextValid = false;
         }
 
-        if (networkData.GetContext(cur[0] & 0xf, dstContext) != kErrorNone)
+        if (networkData.GetContext(byte & 0xf, dstContext) != kErrorNone)
         {
             dstContextValid = false;
         }
-
-        cur++;
     }
     else
     {
@@ -705,40 +679,41 @@
         IgnoreError(networkData.GetContext(0, dstContext));
     }
 
-    memset(&aIp6Header, 0, sizeof(aIp6Header));
-    aIp6Header.Init();
+    aIp6Header.Clear();
+    aIp6Header.InitVersionTrafficClassFlow();
 
     // Traffic Class and Flow Label
     if ((hcCtl & kHcTrafficFlowMask) != kHcTrafficFlow)
     {
-        VerifyOrExit(cur < end);
+        uint8_t *ip6HeaderBytes = reinterpret_cast<uint8_t *>(&aIp6Header);
 
-        bytes = reinterpret_cast<uint8_t *>(&aIp6Header);
-        bytes[1] |= (cur[0] & 0xc0) >> 2;
+        VerifyOrExit(aFrameData.GetLength() > 0);
+
+        ip6HeaderBytes[1] |= (aFrameData.GetBytes()[0] & 0xc0) >> 2;
 
         if ((hcCtl & kHcTrafficClass) == 0)
         {
-            bytes[0] |= (cur[0] >> 2) & 0x0f;
-            bytes[1] |= (cur[0] << 6) & 0xc0;
-            cur++;
+            IgnoreError(aFrameData.ReadUint8(byte));
+            ip6HeaderBytes[0] |= (byte >> 2) & 0x0f;
+            ip6HeaderBytes[1] |= (byte << 6) & 0xc0;
         }
 
         if ((hcCtl & kHcFlowLabel) == 0)
         {
-            VerifyOrExit(cur + 3 <= end);
-            bytes[1] |= cur[0] & 0x0f;
-            bytes[2] |= cur[1];
-            bytes[3] |= cur[2];
-            cur += 3;
+            VerifyOrExit(aFrameData.GetLength() >= 3);
+            ip6HeaderBytes[1] |= aFrameData.GetBytes()[0] & 0x0f;
+            ip6HeaderBytes[2] |= aFrameData.GetBytes()[1];
+            ip6HeaderBytes[3] |= aFrameData.GetBytes()[2];
+            aFrameData.SkipOver(3);
         }
     }
 
     // Next Header
     if ((hcCtl & kHcNextHeader) == 0)
     {
-        VerifyOrExit(cur < end);
-        aIp6Header.SetNextHeader(cur[0]);
-        cur++;
+        SuccessOrExit(aFrameData.ReadUint8(byte));
+
+        aIp6Header.SetNextHeader(byte);
         aCompressedNextHeader = false;
     }
     else
@@ -762,9 +737,8 @@
         break;
 
     default:
-        VerifyOrExit(cur < end);
-        aIp6Header.SetHopLimit(cur[0]);
-        cur++;
+        SuccessOrExit(aFrameData.ReadUint8(byte));
+        aIp6Header.SetHopLimit(byte);
         break;
     }
 
@@ -774,25 +748,19 @@
     case kHcSrcAddrMode0:
         if ((hcCtl & kHcSrcAddrContext) == 0)
         {
-            VerifyOrExit(cur + sizeof(Ip6::Address) <= end);
-            memcpy(&aIp6Header.GetSource(), cur, sizeof(aIp6Header.GetSource()));
-            cur += sizeof(Ip6::Address);
+            SuccessOrExit(aFrameData.Read(aIp6Header.GetSource()));
         }
 
         break;
 
     case kHcSrcAddrMode1:
-        VerifyOrExit(cur + Ip6::InterfaceIdentifier::kSize <= end);
-        aIp6Header.GetSource().GetIid().SetBytes(cur);
-        cur += Ip6::InterfaceIdentifier::kSize;
+        SuccessOrExit(aFrameData.Read(aIp6Header.GetSource().GetIid()));
         break;
 
     case kHcSrcAddrMode2:
-        VerifyOrExit(cur + 2 <= end);
         aIp6Header.GetSource().mFields.m8[11] = 0xff;
         aIp6Header.GetSource().mFields.m8[12] = 0xfe;
-        memcpy(aIp6Header.GetSource().mFields.m8 + 14, cur, 2);
-        cur += 2;
+        SuccessOrExit(aFrameData.ReadBytes(aIp6Header.GetSource().mFields.m8 + 14, 2));
         break;
 
     case kHcSrcAddrMode3:
@@ -821,23 +789,17 @@
         {
         case kHcDstAddrMode0:
             VerifyOrExit((hcCtl & kHcDstAddrContext) == 0);
-            VerifyOrExit(cur + sizeof(Ip6::Address) <= end);
-            memcpy(&aIp6Header.GetDestination(), cur, sizeof(aIp6Header.GetDestination()));
-            cur += sizeof(Ip6::Address);
+            SuccessOrExit(aFrameData.Read(aIp6Header.GetDestination()));
             break;
 
         case kHcDstAddrMode1:
-            VerifyOrExit(cur + Ip6::InterfaceIdentifier::kSize <= end);
-            aIp6Header.GetDestination().GetIid().SetBytes(cur);
-            cur += Ip6::InterfaceIdentifier::kSize;
+            SuccessOrExit(aFrameData.Read(aIp6Header.GetDestination().GetIid()));
             break;
 
         case kHcDstAddrMode2:
-            VerifyOrExit(cur + 2 <= end);
             aIp6Header.GetDestination().mFields.m8[11] = 0xff;
             aIp6Header.GetDestination().mFields.m8[12] = 0xfe;
-            memcpy(aIp6Header.GetDestination().mFields.m8 + 14, cur, 2);
-            cur += 2;
+            SuccessOrExit(aFrameData.ReadBytes(aIp6Header.GetDestination().mFields.m8 + 14, 2));
             break;
 
         case kHcDstAddrMode3:
@@ -869,30 +831,22 @@
             switch (hcCtl & kHcDstAddrModeMask)
             {
             case kHcDstAddrMode0:
-                VerifyOrExit(cur + sizeof(Ip6::Address) <= end);
-                memcpy(aIp6Header.GetDestination().mFields.m8, cur, sizeof(Ip6::Address));
-                cur += sizeof(Ip6::Address);
+                SuccessOrExit(aFrameData.Read(aIp6Header.GetDestination()));
                 break;
 
             case kHcDstAddrMode1:
-                VerifyOrExit(cur + 6 <= end);
-                aIp6Header.GetDestination().mFields.m8[1] = cur[0];
-                memcpy(aIp6Header.GetDestination().mFields.m8 + 11, cur + 1, 5);
-                cur += 6;
+                SuccessOrExit(aFrameData.ReadUint8(aIp6Header.GetDestination().mFields.m8[1]));
+                SuccessOrExit(aFrameData.ReadBytes(aIp6Header.GetDestination().mFields.m8 + 11, 5));
                 break;
 
             case kHcDstAddrMode2:
-                VerifyOrExit(cur + 4 <= end);
-                aIp6Header.GetDestination().mFields.m8[1] = cur[0];
-                memcpy(aIp6Header.GetDestination().mFields.m8 + 13, cur + 1, 3);
-                cur += 4;
+                SuccessOrExit(aFrameData.ReadUint8(aIp6Header.GetDestination().mFields.m8[1]));
+                SuccessOrExit(aFrameData.ReadBytes(aIp6Header.GetDestination().mFields.m8 + 13, 3));
                 break;
 
             case kHcDstAddrMode3:
-                VerifyOrExit(cur < end);
-                aIp6Header.GetDestination().mFields.m8[1]  = 0x02;
-                aIp6Header.GetDestination().mFields.m8[15] = cur[0];
-                cur++;
+                aIp6Header.GetDestination().mFields.m8[1] = 0x02;
+                SuccessOrExit(aFrameData.ReadUint8(aIp6Header.GetDestination().mFields.m8[15]));
                 break;
             }
         }
@@ -901,14 +855,11 @@
             switch (hcCtl & kHcDstAddrModeMask)
             {
             case 0:
-                VerifyOrExit(cur + 6 <= end);
                 VerifyOrExit(dstContextValid);
-                aIp6Header.GetDestination().mFields.m8[1] = cur[0];
-                aIp6Header.GetDestination().mFields.m8[2] = cur[1];
+                SuccessOrExit(aFrameData.ReadBytes(aIp6Header.GetDestination().mFields.m8 + 1, 2));
                 aIp6Header.GetDestination().mFields.m8[3] = dstContext.mPrefix.GetLength();
                 memcpy(aIp6Header.GetDestination().mFields.m8 + 4, dstContext.mPrefix.GetBytes(), 8);
-                memcpy(aIp6Header.GetDestination().mFields.m8 + 12, cur + 2, 4);
-                cur += 6;
+                SuccessOrExit(aFrameData.ReadBytes(aIp6Header.GetDestination().mFields.m8 + 12, 4));
                 break;
 
             default:
@@ -919,54 +870,41 @@
 
     if ((hcCtl & kHcNextHeader) != 0)
     {
-        VerifyOrExit(cur < end);
-        SuccessOrExit(DispatchToNextHeader(cur[0], nextHeader));
+        VerifyOrExit(aFrameData.GetLength() > 0);
+        SuccessOrExit(DispatchToNextHeader(*aFrameData.GetBytes(), nextHeader));
         aIp6Header.SetNextHeader(nextHeader);
     }
 
     error = kErrorNone;
 
 exit:
-    return (error == kErrorNone) ? static_cast<int>(cur - aBuf) : -1;
+    return error;
 }
 
-int Lowpan::DecompressExtensionHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength)
+Error Lowpan::DecompressExtensionHeader(Message &aMessage, FrameData &aFrameData)
 {
-    Error           error = kErrorParse;
-    const uint8_t * cur   = aBuf;
-    const uint8_t * end   = aBuf + aBufLength;
-    uint8_t         hdr[2];
-    uint8_t         len;
-    uint8_t         nextHeader;
-    uint8_t         ctl = cur[0];
-    uint8_t         padLength;
-    Ip6::OptionPad1 optionPad1;
-    Ip6::OptionPadN optionPadN;
+    Error   error = kErrorParse;
+    uint8_t hdr[2];
+    uint8_t len;
+    uint8_t ctl;
+    uint8_t padLength;
 
-    VerifyOrExit(cur < end);
-    cur++;
+    SuccessOrExit(aFrameData.ReadUint8(ctl));
 
     // next header
     if (ctl & kExtHdrNextHeader)
     {
-        VerifyOrExit(cur < end);
+        SuccessOrExit(aFrameData.ReadUint8(len));
 
-        len = cur[0];
-        cur++;
-
-        VerifyOrExit(cur + len <= end);
-        SuccessOrExit(DispatchToNextHeader(cur[len], nextHeader));
-        hdr[0] = static_cast<uint8_t>(nextHeader);
+        VerifyOrExit(aFrameData.CanRead(len + 1));
+        SuccessOrExit(DispatchToNextHeader(aFrameData.GetBytes()[len], hdr[0]));
     }
     else
     {
-        VerifyOrExit(cur + 2 <= end);
+        SuccessOrExit(aFrameData.ReadUint8(hdr[0]));
+        SuccessOrExit(aFrameData.ReadUint8(len));
 
-        hdr[0] = cur[0];
-        len    = cur[1];
-        cur += 2;
-
-        VerifyOrExit(cur + len <= end);
+        VerifyOrExit(aFrameData.CanRead(len));
     }
 
     // length
@@ -976,9 +914,9 @@
     aMessage.MoveOffset(sizeof(hdr));
 
     // payload
-    SuccessOrExit(aMessage.AppendBytes(cur, len));
+    SuccessOrExit(aMessage.AppendBytes(aFrameData.GetBytes(), len));
     aMessage.MoveOffset(len);
-    cur += len;
+    aFrameData.SkipOver(len);
 
     // The RFC6282 says: "The trailing Pad1 or PadN option MAY be elided by the compressor.
     // A decompressor MUST ensure that the containing header is padded out to a multiple of 8 octets
@@ -989,11 +927,15 @@
     {
         if (padLength == 1)
         {
+            Ip6::OptionPad1 optionPad1;
+
             optionPad1.Init();
             SuccessOrExit(aMessage.AppendBytes(&optionPad1, padLength));
         }
         else
         {
+            Ip6::OptionPadN optionPadN;
+
             optionPadN.Init(padLength);
             SuccessOrExit(aMessage.AppendBytes(&optionPadN, padLength));
         }
@@ -1004,163 +946,145 @@
     error = kErrorNone;
 
 exit:
-    return (error == kErrorNone) ? static_cast<int>(cur - aBuf) : -1;
+    return error;
 }
 
-int Lowpan::DecompressUdpHeader(Ip6::Udp::Header &aUdpHeader, const uint8_t *aBuf, uint16_t aBufLength)
+Error Lowpan::DecompressUdpHeader(Ip6::Udp::Header &aUdpHeader, FrameData &aFrameData)
 {
-    Error          error = kErrorParse;
-    const uint8_t *cur   = aBuf;
-    const uint8_t *end   = aBuf + aBufLength;
-    uint8_t        udpCtl;
+    Error    error = kErrorParse;
+    uint8_t  udpCtl;
+    uint8_t  byte;
+    uint16_t srcPort = 0;
+    uint16_t dstPort = 0;
 
-    VerifyOrExit(cur < end);
-    udpCtl = cur[0];
-    cur++;
+    SuccessOrExit(aFrameData.ReadUint8(udpCtl));
 
     VerifyOrExit((udpCtl & kUdpDispatchMask) == kUdpDispatch);
 
-    memset(&aUdpHeader, 0, sizeof(aUdpHeader));
+    aUdpHeader.Clear();
 
-    // source and dest ports
     switch (udpCtl & kUdpPortMask)
     {
     case 0:
-        VerifyOrExit(cur + 4 <= end);
-        aUdpHeader.SetSourcePort(ReadUint16(cur));
-        aUdpHeader.SetDestinationPort(ReadUint16(cur + 2));
-        cur += 4;
+        SuccessOrExit(aFrameData.ReadBigEndianUint16(srcPort));
+        SuccessOrExit(aFrameData.ReadBigEndianUint16(dstPort));
         break;
 
     case 1:
-        VerifyOrExit(cur + 3 <= end);
-        aUdpHeader.SetSourcePort(ReadUint16(cur));
-        aUdpHeader.SetDestinationPort(0xf000 | cur[2]);
-        cur += 3;
+        SuccessOrExit(aFrameData.ReadBigEndianUint16(srcPort));
+        SuccessOrExit(aFrameData.ReadUint8(byte));
+        dstPort = (0xf000 | byte);
         break;
 
     case 2:
-        VerifyOrExit(cur + 3 <= end);
-        aUdpHeader.SetSourcePort(0xf000 | cur[0]);
-        aUdpHeader.SetDestinationPort(ReadUint16(cur + 1));
-        cur += 3;
+        SuccessOrExit(aFrameData.ReadUint8(byte));
+        srcPort = (0xf000 | byte);
+        SuccessOrExit(aFrameData.ReadBigEndianUint16(dstPort));
         break;
 
     case 3:
-        VerifyOrExit(cur < end);
-        aUdpHeader.SetSourcePort(0xf0b0 | (cur[0] >> 4));
-        aUdpHeader.SetDestinationPort(0xf0b0 | (cur[0] & 0xf));
-        cur++;
+        SuccessOrExit(aFrameData.ReadUint8(byte));
+        srcPort = (0xf0b0 | (byte >> 4));
+        dstPort = (0xf0b0 | (byte & 0xf));
         break;
     }
 
-    // checksum
+    aUdpHeader.SetSourcePort(srcPort);
+    aUdpHeader.SetDestinationPort(dstPort);
+
     if ((udpCtl & kUdpChecksum) != 0)
     {
         ExitNow();
     }
     else
     {
-        VerifyOrExit(cur + 2 <= end);
-        aUdpHeader.SetChecksum(ReadUint16(cur));
-        cur += 2;
+        uint16_t checksum;
+
+        SuccessOrExit(aFrameData.ReadBigEndianUint16(checksum));
+        aUdpHeader.SetChecksum(checksum);
     }
 
     error = kErrorNone;
 
 exit:
-    return (error == kErrorNone) ? static_cast<int>(cur - aBuf) : -1;
+    return error;
 }
 
-int Lowpan::DecompressUdpHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength, uint16_t aDatagramLength)
+Error Lowpan::DecompressUdpHeader(Message &aMessage, FrameData &aFrameData, uint16_t aDatagramLength)
 {
+    Error            error;
     Ip6::Udp::Header udpHeader;
-    int              headerLen = -1;
 
-    headerLen = DecompressUdpHeader(udpHeader, aBuf, aBufLength);
-    VerifyOrExit(headerLen >= 0);
+    SuccessOrExit(error = DecompressUdpHeader(udpHeader, aFrameData));
 
     // length
     if (aDatagramLength == 0)
     {
-        udpHeader.SetLength(sizeof(udpHeader) + static_cast<uint16_t>(aBufLength - headerLen));
+        udpHeader.SetLength(sizeof(udpHeader) + aFrameData.GetLength());
     }
     else
     {
         udpHeader.SetLength(aDatagramLength - aMessage.GetOffset());
     }
 
-    VerifyOrExit(aMessage.Append(udpHeader) == kErrorNone, headerLen = -1);
+    SuccessOrExit(error = aMessage.Append(udpHeader));
     aMessage.MoveOffset(sizeof(udpHeader));
 
 exit:
-    return headerLen;
+    return error;
 }
 
-int Lowpan::Decompress(Message &           aMessage,
-                       const Mac::Address &aMacSource,
-                       const Mac::Address &aMacDest,
-                       const uint8_t *     aBuf,
-                       uint16_t            aBufLength,
-                       uint16_t            aDatagramLength)
+Error Lowpan::Decompress(Message &           aMessage,
+                         const Mac::Address &aMacSource,
+                         const Mac::Address &aMacDest,
+                         FrameData &         aFrameData,
+                         uint16_t            aDatagramLength)
 {
-    Error          error = kErrorParse;
-    Ip6::Header    ip6Header;
-    const uint8_t *cur       = aBuf;
-    uint16_t       remaining = aBufLength;
-    bool           compressed;
-    int            rval;
-    uint16_t       ip6PayloadLength;
-    uint16_t       compressedLength = 0;
-    uint16_t       currentOffset    = aMessage.GetOffset();
+    Error       error = kErrorParse;
+    Ip6::Header ip6Header;
+    bool        compressed;
+    uint16_t    ip6PayloadLength;
+    uint16_t    currentOffset = aMessage.GetOffset();
 
-    VerifyOrExit(remaining >= 2);
-    VerifyOrExit((rval = DecompressBaseHeader(ip6Header, compressed, aMacSource, aMacDest, cur, remaining)) >= 0);
-
-    cur += rval;
-    remaining -= rval;
+    SuccessOrExit(DecompressBaseHeader(ip6Header, compressed, aMacSource, aMacDest, aFrameData));
 
     SuccessOrExit(aMessage.Append(ip6Header));
     aMessage.MoveOffset(sizeof(ip6Header));
 
     while (compressed)
     {
-        VerifyOrExit(remaining >= 1);
+        uint8_t byte;
 
-        if ((cur[0] & kExtHdrDispatchMask) == kExtHdrDispatch)
+        VerifyOrExit(aFrameData.GetLength() > 0);
+        byte = *aFrameData.GetBytes();
+
+        if ((byte & kExtHdrDispatchMask) == kExtHdrDispatch)
         {
-            if ((cur[0] & kExtHdrEidMask) == kExtHdrEidIp6)
+            if ((byte & kExtHdrEidMask) == kExtHdrEidIp6)
             {
                 compressed = false;
 
-                cur++;
-                remaining--;
+                aFrameData.SkipOver(sizeof(uint8_t));
 
-                VerifyOrExit((rval = Decompress(aMessage, aMacSource, aMacDest, cur, remaining, aDatagramLength)) >= 0);
+                SuccessOrExit(Decompress(aMessage, aMacSource, aMacDest, aFrameData, aDatagramLength));
             }
             else
             {
-                compressed = (cur[0] & kExtHdrNextHeader) != 0;
-                VerifyOrExit((rval = DecompressExtensionHeader(aMessage, cur, remaining)) >= 0);
+                compressed = (byte & kExtHdrNextHeader) != 0;
+                SuccessOrExit(DecompressExtensionHeader(aMessage, aFrameData));
             }
         }
-        else if ((cur[0] & kUdpDispatchMask) == kUdpDispatch)
+        else if ((byte & kUdpDispatchMask) == kUdpDispatch)
         {
             compressed = false;
-            VerifyOrExit((rval = DecompressUdpHeader(aMessage, cur, remaining, aDatagramLength)) >= 0);
+            SuccessOrExit(DecompressUdpHeader(aMessage, aFrameData, aDatagramLength));
         }
         else
         {
             ExitNow();
         }
-
-        VerifyOrExit(remaining >= rval);
-        cur += rval;
-        remaining -= rval;
     }
 
-    compressedLength = static_cast<uint16_t>(cur - aBuf);
-
     if (aDatagramLength)
     {
         ip6PayloadLength = HostSwap16(aDatagramLength - currentOffset - sizeof(Ip6::Header));
@@ -1168,7 +1092,7 @@
     else
     {
         ip6PayloadLength =
-            HostSwap16(aMessage.GetOffset() - currentOffset - sizeof(Ip6::Header) + aBufLength - compressedLength);
+            HostSwap16(aMessage.GetOffset() - currentOffset - sizeof(Ip6::Header) + aFrameData.GetLength());
     }
 
     aMessage.Write(currentOffset + Ip6::Header::kPayloadLengthFieldOffset, ip6PayloadLength);
@@ -1176,7 +1100,47 @@
     error = kErrorNone;
 
 exit:
-    return (error == kErrorNone) ? static_cast<int>(compressedLength) : -1;
+    return error;
+}
+
+Ip6::Ecn Lowpan::DecompressEcn(const Message &aMessage, uint16_t aOffset) const
+{
+    Ip6::Ecn ecn = Ip6::kEcnNotCapable;
+    uint16_t hcCtl;
+    uint8_t  byte;
+
+    SuccessOrExit(aMessage.Read(aOffset, hcCtl));
+    hcCtl = HostSwap16(hcCtl);
+
+    VerifyOrExit((hcCtl & kHcDispatchMask) == kHcDispatch);
+    aOffset += sizeof(uint16_t);
+
+    if ((hcCtl & kHcTrafficFlowMask) == kHcTrafficFlow)
+    {
+        // ECN is elided and is zero (`kEcnNotCapable`).
+        ExitNow();
+    }
+
+    // When ECN is not elided, it is always included as the
+    // first two bits of the next byte.
+    SuccessOrExit(aMessage.Read(aOffset, byte));
+    ecn = static_cast<Ip6::Ecn>((byte & kEcnMask) >> kEcnOffset);
+
+exit:
+    return ecn;
+}
+
+void Lowpan::MarkCompressedEcn(Message &aMessage, uint16_t aOffset)
+{
+    uint8_t byte;
+
+    aOffset += sizeof(uint16_t);
+    IgnoreError(aMessage.Read(aOffset, byte));
+
+    byte &= ~kEcnMask;
+    byte |= static_cast<uint8_t>(Ip6::kEcnMarked << kEcnOffset);
+
+    aMessage.Write(aOffset, byte);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1189,9 +1153,21 @@
     mHopsLeft    = aHopsLeft;
 }
 
-bool MeshHeader::IsMeshHeader(const uint8_t *aFrame, uint16_t aFrameLength)
+bool MeshHeader::IsMeshHeader(const FrameData &aFrameData)
 {
-    return (aFrameLength >= kMinHeaderLength) && ((*aFrame & kDispatchMask) == kDispatch);
+    return (aFrameData.GetLength() >= kMinHeaderLength) && ((*aFrameData.GetBytes() & kDispatchMask) == kDispatch);
+}
+
+Error MeshHeader::ParseFrom(FrameData &aFrameData)
+{
+    Error    error;
+    uint16_t headerLength;
+
+    SuccessOrExit(error = ParseFrom(aFrameData.GetBytes(), aFrameData.GetLength(), headerLength));
+    aFrameData.SkipOver(headerLength);
+
+exit:
+    return error;
 }
 
 Error MeshHeader::ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength)
@@ -1280,15 +1256,14 @@
     return static_cast<uint16_t>(cur - aFrame);
 }
 
-uint16_t MeshHeader::WriteTo(Message &aMessage, uint16_t aOffset) const
+Error MeshHeader::AppendTo(Message &aMessage) const
 {
     uint8_t  frame[kDeepHopsHeaderLength];
     uint16_t headerLength;
 
     headerLength = WriteTo(frame);
-    aMessage.WriteBytes(aOffset, frame, headerLength);
 
-    return headerLength;
+    return aMessage.AppendBytes(frame, headerLength);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -1301,11 +1276,28 @@
     mOffset = (aOffset & kOffsetMask);
 }
 
+bool FragmentHeader::IsFragmentHeader(const FrameData &aFrameData)
+{
+    return IsFragmentHeader(aFrameData.GetBytes(), aFrameData.GetLength());
+}
+
 bool FragmentHeader::IsFragmentHeader(const uint8_t *aFrame, uint16_t aFrameLength)
 {
     return (aFrameLength >= kFirstFragmentHeaderSize) && ((*aFrame & kDispatchMask) == kDispatch);
 }
 
+Error FragmentHeader::ParseFrom(FrameData &aFrameData)
+{
+    Error    error;
+    uint16_t headerLength;
+
+    SuccessOrExit(error = ParseFrom(aFrameData.GetBytes(), aFrameData.GetLength(), headerLength));
+    aFrameData.SkipOver(headerLength);
+
+exit:
+    return error;
+}
+
 Error FragmentHeader::ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength)
 {
     Error error = kErrorParse;
diff --git a/src/core/thread/lowpan.hpp b/src/core/thread/lowpan.hpp
index 7eab56f..7193607 100644
--- a/src/core/thread/lowpan.hpp
+++ b/src/core/thread/lowpan.hpp
@@ -37,12 +37,15 @@
 #include "openthread-core-config.h"
 
 #include "common/debug.hpp"
+#include "common/frame_builder.hpp"
+#include "common/frame_data.hpp"
 #include "common/locator.hpp"
 #include "common/message.hpp"
 #include "common/non_copyable.hpp"
 #include "mac/mac_types.hpp"
 #include "net/ip6.hpp"
 #include "net/ip6_address.hpp"
+#include "net/ip6_types.hpp"
 
 namespace ot {
 
@@ -78,144 +81,6 @@
 };
 
 /**
- * This class defines a buffer writer used by the 6LoWPAN compressor.
- *
- */
-class BufferWriter
-{
-public:
-    /**
-     * This constructor initializes the buffer writer.
-     *
-     * @param[in]  aBuf     A pointer to the write buffer.
-     * @param[in]  aLength  The size of the write buffer.
-     *
-     */
-    BufferWriter(uint8_t *aBuf, uint16_t aLength)
-        : mWritePointer(aBuf)
-        , mEndPointer(aBuf + aLength)
-    {
-    }
-
-    /**
-     * This method indicates whether there is buffer space available to write @p aLength bytes.
-     *
-     * @param[in]  aLength  Number of bytes to write.
-     *
-     * @retval  TRUE   Enough buffer space is available to write the requested number of bytes.
-     * @retval  FALSE  Insufficient buffer space to write the requested number of bytes.
-     *
-     */
-    bool CanWrite(uint8_t aLength) const { return (mWritePointer + aLength) <= mEndPointer; }
-
-    /**
-     * This method returns the current write pointer value.
-     *
-     * @returns the current write pointer value.
-     *
-     */
-    uint8_t *GetWritePointer(void) { return mWritePointer; }
-
-    /**
-     * This method advances the write pointer.
-     *
-     * @param[in]  aLength  Number of bytes to advance.
-     *
-     * @retval kErrorNone    Enough buffer space is available to advance the requested number of bytes.
-     * @retval kErrorNoBufs  Insufficient buffer space to advance the requested number of bytes.
-     *
-     */
-    Error Advance(uint8_t aLength)
-    {
-        Error error = kErrorNone;
-
-        VerifyOrExit(CanWrite(aLength), error = kErrorNoBufs);
-        mWritePointer += aLength;
-
-    exit:
-        return error;
-    }
-
-    /**
-     * This method writes a byte into the buffer and updates the write pointer, if space is available.
-     *
-     * @param[in]  aByte  Byte to write.
-     *
-     * @retval  kErrorNone     Successfully wrote the byte and updated the pointer.
-     * @retval  kErrorNoBufs  Insufficient buffer space to write the byte.
-     *
-     */
-    Error Write(uint8_t aByte)
-    {
-        Error error = kErrorNone;
-
-        VerifyOrExit(CanWrite(sizeof(aByte)), error = kErrorNoBufs);
-
-        *mWritePointer++ = aByte;
-
-    exit:
-        return error;
-    }
-
-    /**
-     * This method writes a byte sequence into the buffer and updates the write pointer, if space is available.
-     *
-     * @param[in]  aBuf     A pointer to the byte sequence.
-     * @param[in]  aLength  Number of bytes to write.
-     *
-     * @retval kErrorNone    Successfully wrote the byte sequence and updated the pointer.
-     * @retval kErrorNoBufs  Insufficient buffer space to write the byte sequence.
-     *
-     */
-    Error Write(const void *aBuf, uint8_t aLength)
-    {
-        Error error = kErrorNone;
-
-        VerifyOrExit(CanWrite(aLength), error = kErrorNoBufs);
-
-        memcpy(mWritePointer, aBuf, aLength);
-        mWritePointer += aLength;
-
-    exit:
-        return error;
-    }
-
-    /**
-     * This method writes a byte sequence into the buffer and updates the write pointer, if space is available.
-     *
-     * The byte sequence is taken from a message buffer at the current message buffer's offset.
-     *
-     * @param[in]  aMessage  A message buffer.
-     * @param[in]  aLength   Number of bytes to write.
-     *
-     * @retval kErrorNone    Successfully wrote the byte sequence and updated the pointer.
-     * @retval kErrorNoBufs  Insufficient buffer space to write the byte sequence.
-     *
-     */
-    Error Write(const Message &aMessage, uint8_t aLength)
-    {
-        Error error = kErrorNone;
-        int   rval;
-
-        OT_UNUSED_VARIABLE(rval);
-
-        VerifyOrExit(CanWrite(aLength), error = kErrorNoBufs);
-
-        rval = aMessage.ReadBytes(aMessage.GetOffset(), mWritePointer, aLength);
-        OT_ASSERT(rval == aLength);
-
-        mWritePointer += aLength;
-
-    exit:
-        return error;
-    }
-
-private:
-    uint8_t *mWritePointer;
-    uint8_t *mEndPointer;
-};
-
-/**
  * This class implements LOWPAN_IPHC header compression.
  *
  */
@@ -244,69 +109,113 @@
     }
 
     /**
+     * This method indicates whether or not header in a given frame is a LOWPAN_IPHC header.
+     *
+     * @param[in] aFrameData    The frame data.
+     *
+     * @retval TRUE   If the header matches the LOWPAN_IPHC dispatch value.
+     * @retval FALSE  If the header does not match the LOWPAN_IPHC dispatch value.
+     */
+    static bool IsLowpanHc(const FrameData &aFrameData)
+    {
+        return (aFrameData.GetLength() > 0) && IsLowpanHc(aFrameData.GetBytes());
+    }
+
+    /**
      * This method compresses an IPv6 header.
      *
-     * @param[in]   aMessage     A reference to the IPv6 message.
-     * @param[in]   aMacSource   The MAC source address.
-     * @param[in]   aMacDest     The MAC destination address.
-     * @param[out]  aBuf         A pointer where the compressed IPv6 header will be placed.
+     * @param[in]   aMessage       A reference to the IPv6 message.
+     * @param[in]   aMacSource     The MAC source address.
+     * @param[in]   aMacDest       The MAC destination address.
+     * @param[in]  aFrameBuilder   The `FrameBuilder` to use to append the compressed headers.
      *
      * @returns The size of the compressed header in bytes.
      *
      */
-    Error Compress(Message &aMessage, const Mac::Address &aMacSource, const Mac::Address &aMacDest, BufferWriter &aBuf);
-
-    /**
-     * This method decompresses a LOWPAN_IPHC header.
-     *
-     * @param[out]  aMessage         A reference where the IPv6 header will be placed.
-     * @param[in]   aMacSource       The MAC source address.
-     * @param[in]   aMacDest         The MAC destination address.
-     * @param[in]   aBuf             A pointer to the LOWPAN_IPHC header.
-     * @param[in]   aBufLength       The number of bytes in @p aBuf.
-     * @param[in]   aDatagramLength  The IPv6 datagram length.
-     *
-     * @returns The size of the compressed header in bytes.
-     *
-     */
-    int Decompress(Message &           aMessage,
+    Error Compress(Message &           aMessage,
                    const Mac::Address &aMacSource,
                    const Mac::Address &aMacDest,
-                   const uint8_t *     aBuf,
-                   uint16_t            aBufLength,
-                   uint16_t            aDatagramLength);
+                   FrameBuilder &      aFrameBuilder);
 
     /**
      * This method decompresses a LOWPAN_IPHC header.
      *
-     * @param[out]  aIp6Header              A reference where the IPv6 header will be placed.
-     * @param[out]  aCommpressedNextHeader  A boolean reference to output whether next header is compressed or not.
-     * @param[in]   aMacSource              The MAC source address.
-     * @param[in]   aMacDest                The MAC destination address.
-     * @param[in]   aBuf                    A pointer to the LOWPAN_IPHC header.
-     * @param[in]   aBufLength              The number of bytes in @p aBuf.
+     * If the header is parsed successfully the @p aFrameData is updated to skip over the parsed header bytes.
      *
-     * @returns The size of the compressed header in bytes or -1 if decompression fails.
+     * @param[out]    aMessage         A reference where the IPv6 header will be placed.
+     * @param[in]     aMacSource       The MAC source address.
+     * @param[in]     aMacDest         The MAC destination address.
+     * @param[in,out] aFrameData       A frame data containing the LOWPAN_IPHC header.
+     * @param[in]     aDatagramLength  The IPv6 datagram length.
+     *
+     * @retval kErrorNone    The header was decompressed successfully. @p aMessage and @p aFrameData are updated.
+     * @retval kErrorParse   Failed to parse the lowpan header.
+     * @retval kErrorNoBufs  Could not grow @p aMessage to write the parsed IPv6 header.
      *
      */
-    int DecompressBaseHeader(Ip6::Header &       aIp6Header,
-                             bool &              aCompressedNextHeader,
-                             const Mac::Address &aMacSource,
-                             const Mac::Address &aMacDest,
-                             const uint8_t *     aBuf,
-                             uint16_t            aBufLength);
+    Error Decompress(Message &           aMessage,
+                     const Mac::Address &aMacSource,
+                     const Mac::Address &aMacDest,
+                     FrameData &         aFrameData,
+                     uint16_t            aDatagramLength);
+
+    /**
+     * This method decompresses a LOWPAN_IPHC header.
+     *
+     * If the header is parsed successfully the @p aFrameData is updated to skip over the parsed header bytes.
+     *
+     * @param[out]    aIp6Header             A reference where the IPv6 header will be placed.
+     * @param[out]    aCompressedNextHeader  A boolean reference to output whether next header is compressed or not.
+     * @param[in]     aMacSource             The MAC source address.
+     * @param[in]     aMacDest               The MAC destination address.
+     * @param[in,out] aFrameData             A frame data containing the LOWPAN_IPHC header.
+     *
+     * @retval kErrorNone    The header was decompressed successfully. @p aIp6Headre and @p aFrameData are updated.
+     * @retval kErrorParse   Failed to parse the lowpan header.
+     *
+     */
+    Error DecompressBaseHeader(Ip6::Header &       aIp6Header,
+                               bool &              aCompressedNextHeader,
+                               const Mac::Address &aMacSource,
+                               const Mac::Address &aMacDest,
+                               FrameData &         aFrameData);
 
     /**
      * This method decompresses a LOWPAN_NHC UDP header.
      *
-     * @param[out]  aUdpHeader    A reference where the UDP header will be placed.
-     * @param[in]   aBuf          A pointer to the LOWPAN_NHC header.
-     * @param[in]   aBufLength    The number of bytes in @p aBuf.
+     * If the header is parsed successfully the @p aFrameData is updated to skip over the parsed header bytes.
      *
-     * @returns The size of the compressed header in bytes or -1 if decompression fails.
+     * @param[out]    aUdpHeader    A reference where the UDP header will be placed.
+     * @param[in,out] aFrameData    A frame data containing the LOWPAN_NHC header.
+     *
+     * @retval kErrorNone    The header was decompressed successfully. @p aUdpHeader and @p aFrameData are updated.
+     * @retval kErrorParse   Failed to parse the lowpan header.
      *
      */
-    int DecompressUdpHeader(Ip6::Udp::Header &aUdpHeader, const uint8_t *aBuf, uint16_t aBufLength);
+    Error DecompressUdpHeader(Ip6::Udp::Header &aUdpHeader, FrameData &aFrameData);
+
+    /**
+     * This method decompresses the IPv6 ECN field in a LOWPAN_IPHC header.
+     *
+     * @param[in] aMessage  The message to read the IPHC header from.
+     * @param[in] aOffset   The offset in @p aMessage to start of IPHC header.
+     *
+     * @returns The decompressed ECN field. If the IPHC header is not valid `kEcnNotCapable` is returned.
+     *
+     */
+    Ip6::Ecn DecompressEcn(const Message &aMessage, uint16_t aOffset) const;
+
+    /**
+     * This method updates the compressed ECN field in a LOWPAN_IPHC header to `kEcnMarked`.
+     *
+     * This method MUST be used when the ECN field is not elided in the IPHC header. Note that the ECN is not elided
+     * when it is not zero (`kEcnNotCapable`).
+     *
+     * @param[in,out] aMessage  The message containing the IPHC header and to update.
+     * @param[in]     aOffset   The offset in @p aMessage to start of IPHC header.
+     *
+     */
+    void MarkCompressedEcn(Message &aMessage, uint16_t aOffset);
 
 private:
     static constexpr uint16_t kHcDispatch     = 3 << 13;
@@ -336,6 +245,9 @@
     static constexpr uint16_t kHcDstAddrMode3    = 3 << 0;
     static constexpr uint16_t kHcDstAddrModeMask = 3 << 0;
 
+    static constexpr uint8_t kEcnOffset = 6;
+    static constexpr uint8_t kEcnMask   = 3 << kEcnOffset;
+
     static constexpr uint8_t kExtHdrDispatch     = 0xe0;
     static constexpr uint8_t kExtHdrDispatchMask = 0xf0;
 
@@ -359,25 +271,25 @@
     Error Compress(Message &           aMessage,
                    const Mac::Address &aMacSource,
                    const Mac::Address &aMacDest,
-                   BufferWriter &      aBuf,
+                   FrameBuilder &      aFrameBuilder,
                    uint8_t &           aHeaderDepth);
 
-    Error CompressExtensionHeader(Message &aMessage, BufferWriter &aBuf, uint8_t &aNextHeader);
+    Error CompressExtensionHeader(Message &aMessage, FrameBuilder &aFrameBuilder, uint8_t &aNextHeader);
     Error CompressSourceIid(const Mac::Address &aMacAddr,
                             const Ip6::Address &aIpAddr,
                             const Context &     aContext,
                             uint16_t &          aHcCtl,
-                            BufferWriter &      aBuf);
+                            FrameBuilder &      aFrameBuilder);
     Error CompressDestinationIid(const Mac::Address &aMacAddr,
                                  const Ip6::Address &aIpAddr,
                                  const Context &     aContext,
                                  uint16_t &          aHcCtl,
-                                 BufferWriter &      aBuf);
-    Error CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, BufferWriter &aBuf);
-    Error CompressUdp(Message &aMessage, BufferWriter &aBuf);
+                                 FrameBuilder &      aFrameBuilder);
+    Error CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, FrameBuilder &aFrameBuilder);
+    Error CompressUdp(Message &aMessage, FrameBuilder &aFrameBuilder);
 
-    int   DecompressExtensionHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength);
-    int   DecompressUdpHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength, uint16_t aDatagramLength);
+    Error DecompressExtensionHeader(Message &aMessage, FrameData &aFrameData);
+    Error DecompressUdpHeader(Message &aMessage, FrameData &aFrameData, uint16_t aDatagramLength);
     Error DispatchToNextHeader(uint8_t aDispatch, uint8_t &aNextHeader);
 
     static void  CopyContext(const Context &aContext, Ip6::Address &aAddress);
@@ -418,7 +330,7 @@
      * @retval FALSE  If the header does not match the Mesh Header dispatch value.
      *
      */
-    static bool IsMeshHeader(const uint8_t *aFrame, uint16_t aFrameLength);
+    static bool IsMeshHeader(const FrameData &aFrameData);
 
     /**
      * This method parses the Mesh Header from a frame @p aFrame.
@@ -434,6 +346,19 @@
     Error ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength);
 
     /**
+     * This method parses the Mesh Header from a given frame data.
+     *
+     * If the Mesh Header is parsed successfully the @p aFrameData is updated to skip over the parsed header bytes.
+     *
+     * @param[in,out]  aFrameData    The frame data to parse from.
+     *
+     * @retval kErrorNone     Mesh Header parsed successfully. @p aFrameData is updated to skip over parsed header.
+     * @retval kErrorParse    Mesh Header could not be parsed.
+     *
+     */
+    Error ParseFrom(FrameData &aFrameData);
+
+    /**
      * This method parses the Mesh Header from a given message.
      *
      * @note The Mesh Header is read from offset zero within the @p aMessage.
@@ -515,18 +440,16 @@
     uint16_t WriteTo(uint8_t *aFrame) const;
 
     /**
-     * This method writes the Mesh Header to a message at a given offset.
+     * This method appends the Mesh Header to a given message.
      *
-     * @note This method expects the @p aMessage length to be already set such that there is enough space for the
-     * entire Mesh Header to be written.
      *
-     * @param[out] aMessage  A message to write the Mesh Header into.
-     * @param[in]  aOffset   The offset at which to write the header.
+     * @param[out] aMessage  A message to append the Mesh Header to.
      *
-     * @returns The header length (number of bytes written).
+     * @retval kErrorNone    Successfully appended the Mesh Header to @p aMessage.
+     * @retval kErrorNoBufs  Insufficient available buffers to grow @p aMessage.
      *
      */
-    uint16_t WriteTo(Message &aMessage, uint16_t aOffset) const;
+    Error AppendTo(Message &aMessage) const;
 
 private:
     static constexpr uint8_t kDispatch     = 2 << 6;
@@ -585,11 +508,13 @@
      * header (dispatch byte) matches the Fragment Header dispatch value. It does not fully parse and validate the
      * Fragment Header. `ParseFrom()` method can be used to fully parse and validate the header.
      *
+     * @param[in] aFrameData   The frame data.
+     *
      * @retval TRUE   If the header matches the Fragment Header dispatch value.
      * @retval FALSE  If the header does not match the Fragment Header dispatch value.
      *
      */
-    static bool IsFragmentHeader(const uint8_t *aFrame, uint16_t aFrameLength);
+    static bool IsFragmentHeader(const FrameData &aFrameData);
 
     /**
      * This method parses the Fragment Header from a frame @p aFrame.
@@ -602,7 +527,20 @@
      * @retval kErrorParse    Fragment header could not be parsed from @p aFrame.
      *
      */
-    Error ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength);
+    Error ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength); //~~~ REMOVE OR MAKE PRIVATE
+
+    /**
+     * This method parses the Fragment Header from a given frame data.
+     *
+     * If the Fragment Header is parsed successfully the @p aFrameData is updated to skip over the parsed header bytes.
+     *
+     * @param[in,out]  aFrameData    The frame data to parse from.
+     *
+     * @retval kErrorNone     Fragment Header parsed successfully. @p aFrameData is updated to skip over parsed header.
+     * @retval kErrorParse    Fragment header could not be parsed.
+     *
+     */
+    Error ParseFrom(FrameData &aFrameData);
 
     /**
      * This method parses the Fragment Header from a message.
@@ -667,6 +605,8 @@
     static constexpr uint8_t kTagIndex    = 2; // Start index of Tag field in the Fragment Header byte sequence.
     static constexpr uint8_t kOffsetIndex = 4; // Start index of Offset field in the Fragment Header byte sequence.
 
+    static bool IsFragmentHeader(const uint8_t *aFrame, uint16_t aFrameLength);
+
     uint16_t mSize;
     uint16_t mTag;
     uint16_t mOffset;
diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp
index a0b02f5..bd55d74 100644
--- a/src/core/thread/mesh_forwarder.cpp
+++ b/src/core/thread/mesh_forwarder.cpp
@@ -38,7 +38,6 @@
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
 #include "common/message.hpp"
 #include "common/random.hpp"
 #include "common/time_ticker.hpp"
@@ -54,6 +53,8 @@
 
 namespace ot {
 
+RegisterLogModule("MeshForwarder");
+
 void ThreadLinkInfo::SetFrom(const Mac::RxFrame &aFrame)
 {
     Clear();
@@ -63,6 +64,17 @@
         IgnoreError(aFrame.GetDstPanId(mPanId));
     }
 
+    {
+        Mac::PanId dstPanId;
+
+        if (kErrorNone != aFrame.GetDstPanId(dstPanId))
+        {
+            dstPanId = mPanId;
+        }
+
+        mIsDstPanIdBroadcast = (dstPanId == Mac::kPanIdBroadcast);
+    }
+
     mChannel      = aFrame.GetChannel();
     mRss          = aFrame.GetRssi();
     mLqi          = aFrame.GetLqi();
@@ -89,6 +101,10 @@
     , mEnabled(false)
     , mTxPaused(false)
     , mSendBusy(false)
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
+    , mDelayNextTx(false)
+    , mTxDelayTimer(aInstance, HandleTxDelayTimer)
+#endif
     , mScheduleTransmissionTask(aInstance, MeshForwarder::ScheduleTransmissionTask)
 #if OPENTHREAD_FTD
     , mIndirectSender(aInstance)
@@ -133,6 +149,11 @@
     mFragmentPriorityList.Clear();
 #endif
 
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
+    mTxDelayTimer.Stop();
+    mDelayNextTx = false;
+#endif
+
     mEnabled     = false;
     mSendMessage = nullptr;
     Get<Mac::Mac>().SetRxOnWhenIdle(false);
@@ -212,7 +233,7 @@
         }
     }
 
-    LogMessage(kMessageEvict, aMessage, nullptr, kErrorNoBufs);
+    LogMessage(kMessageEvict, aMessage, kErrorNoBufs);
     queue->DequeueAndFree(aMessage);
 }
 
@@ -225,6 +246,281 @@
     }
 }
 
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
+void MeshForwarder::HandleTxDelayTimer(Timer &aTimer)
+{
+    aTimer.Get<MeshForwarder>().HandleTxDelayTimer();
+}
+
+void MeshForwarder::HandleTxDelayTimer(void)
+{
+    mDelayNextTx = false;
+    mScheduleTransmissionTask.Post();
+    LogDebg("Tx delay timer expired");
+}
+#endif
+
+#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+
+Error MeshForwarder::UpdateEcnOrDrop(Message &aMessage, bool aPreparingToSend)
+{
+    // This method performs delay-aware active queue management for
+    // direct message transmission. It parses the IPv6 header from
+    // `aMessage` to determine if message is  ECN-capable. This is
+    // then used along with the message's time-in-queue to decide
+    // whether to keep the message as is, change the ECN field to
+    // mark congestion, or drop the message. If the message is to be
+    // dropped, this method clears the direct tx flag on `aMessage`
+    // and removes it from the send queue (if no pending indirect tx)
+    // and returns `kErrorDrop`. This method returns `kErrorNone`
+    // when the message is kept as is or ECN field is updated.
+
+    Error    error         = kErrorNone;
+    uint32_t timeInQueue   = TimerMilli::GetNow() - aMessage.GetTimestamp();
+    bool     shouldMarkEcn = (timeInQueue >= kTimeInQueueMarkEcn);
+    bool     isEcnCapable  = false;
+
+    VerifyOrExit(aMessage.IsDirectTransmission() && (aMessage.GetOffset() == 0));
+
+    if (aMessage.GetType() == Message::kTypeIp6)
+    {
+        Ip6::Header ip6Header;
+
+        IgnoreError(aMessage.Read(0, ip6Header));
+
+        VerifyOrExit(!Get<ThreadNetif>().HasUnicastAddress(ip6Header.GetSource()));
+
+        isEcnCapable = (ip6Header.GetEcn() != Ip6::kEcnNotCapable);
+
+        if ((shouldMarkEcn && !isEcnCapable) || (timeInQueue >= kTimeInQueueDropMsg))
+        {
+            ExitNow(error = kErrorDrop);
+        }
+
+        if (shouldMarkEcn)
+        {
+            switch (ip6Header.GetEcn())
+            {
+            case Ip6::kEcnCapable0:
+            case Ip6::kEcnCapable1:
+                ip6Header.SetEcn(Ip6::kEcnMarked);
+                aMessage.Write(0, ip6Header);
+                LogMessage(kMessageMarkEcn, aMessage);
+                break;
+
+            case Ip6::kEcnMarked:
+            case Ip6::kEcnNotCapable:
+                break;
+            }
+        }
+    }
+#if OPENTHREAD_FTD
+    else if (aMessage.GetType() == Message::kType6lowpan)
+    {
+        uint16_t               headerLength = 0;
+        uint16_t               offset;
+        bool                   hasFragmentHeader = false;
+        Lowpan::FragmentHeader fragmentHeader;
+        Lowpan::MeshHeader     meshHeader;
+
+        IgnoreError(meshHeader.ParseFrom(aMessage, headerLength));
+
+        offset = headerLength;
+
+        if (fragmentHeader.ParseFrom(aMessage, offset, headerLength) == kErrorNone)
+        {
+            hasFragmentHeader = true;
+            offset += headerLength;
+        }
+
+        if (!hasFragmentHeader || (fragmentHeader.GetDatagramOffset() == 0))
+        {
+            Ip6::Ecn ecn = Get<Lowpan::Lowpan>().DecompressEcn(aMessage, offset);
+
+            isEcnCapable = (ecn != Ip6::kEcnNotCapable);
+
+            if ((shouldMarkEcn && !isEcnCapable) || (timeInQueue >= kTimeInQueueDropMsg))
+            {
+                FragmentPriorityList::Entry *entry;
+
+                entry = mFragmentPriorityList.FindEntry(meshHeader.GetSource(), fragmentHeader.GetDatagramTag());
+
+                if (entry != nullptr)
+                {
+                    entry->MarkToDrop();
+                    entry->ResetLifetime();
+                }
+
+                ExitNow(error = kErrorDrop);
+            }
+
+            if (shouldMarkEcn)
+            {
+                switch (ecn)
+                {
+                case Ip6::kEcnCapable0:
+                case Ip6::kEcnCapable1:
+                    Get<Lowpan::Lowpan>().MarkCompressedEcn(aMessage, offset);
+                    LogMessage(kMessageMarkEcn, aMessage);
+                    break;
+
+                case Ip6::kEcnMarked:
+                case Ip6::kEcnNotCapable:
+                    break;
+                }
+            }
+        }
+        else if (hasFragmentHeader)
+        {
+            FragmentPriorityList::Entry *entry;
+
+            entry = mFragmentPriorityList.FindEntry(meshHeader.GetSource(), fragmentHeader.GetDatagramTag());
+            VerifyOrExit(entry != nullptr);
+
+            if (entry->ShouldDrop())
+            {
+                error = kErrorDrop;
+            }
+
+            // We can clear the entry if it is the last fragment and
+            // only if the message is being prepared to be sent out.
+            if (aPreparingToSend && (fragmentHeader.GetDatagramOffset() + aMessage.GetLength() - offset >=
+                                     fragmentHeader.GetDatagramSize()))
+            {
+                entry->Clear();
+            }
+        }
+    }
+#else
+    OT_UNUSED_VARIABLE(aPreparingToSend);
+#endif // OPENTHREAD_FTD
+
+exit:
+    if (error == kErrorDrop)
+    {
+        LogMessage(kMessageQueueMgmtDrop, aMessage);
+        aMessage.ClearDirectTransmission();
+        RemoveMessageIfNoPendingTx(aMessage);
+    }
+
+    return error;
+}
+
+Error MeshForwarder::RemoveAgedMessages(void)
+{
+    // This method goes through all messages in the send queue and
+    // removes all aged messages determined based on the delay-aware
+    // active queue management rules. It may also mark ECN on some
+    // messages. It returns `kErrorNone` if at least one message was
+    // removed, or `kErrorNotFound` if none was removed.
+
+    Error    error = kErrorNotFound;
+    Message *nextMessage;
+
+    for (Message *message = mSendQueue.GetHead(); message != nullptr; message = nextMessage)
+    {
+        nextMessage = message->GetNext();
+
+        // Exclude the current message being sent `mSendMessage`.
+        if ((message == mSendMessage) || !message->IsDirectTransmission())
+        {
+            continue;
+        }
+
+        if (UpdateEcnOrDrop(*message, /* aPreparingToSend */ false) == kErrorDrop)
+        {
+            error = kErrorNone;
+        }
+    }
+
+    return error;
+}
+
+#endif // OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+
+#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
+
+bool MeshForwarder::IsDirectTxQueueOverMaxFrameThreshold(void) const
+{
+    uint16_t frameCount = 0;
+
+    for (const Message &message : mSendQueue)
+    {
+        if (!message.IsDirectTransmission() || (&message == mSendMessage))
+        {
+            continue;
+        }
+
+        switch (message.GetType())
+        {
+        case Message::kTypeIp6:
+        {
+            // If it is an IPv6 message, we estimate the number of
+            // fragment frames assuming typical header sizes and lowpan
+            // compression. Since this estimate is only used for queue
+            // management, we lean towards an under estimate in sense
+            // that we may allow few more frames in the tx queue over
+            // threshold in some rare cases.
+            //
+            // The constants below are derived as follows: Typical MAC
+            // header (15 bytes) and MAC footer (6 bytes) leave 106
+            // bytes for MAC payload. Next fragment header is 5 bytes
+            // leaving 96 for next fragment payload. Lowpan compression
+            // on average compresses 40 bytes IPv6 header into about 19
+            // bytes leaving 87 bytes for the IPv6 payload, so the first
+            // fragment can fit 87 + 40 = 127 bytes.
+
+            static constexpr uint16_t kFirstFragmentMaxLength = 127;
+            static constexpr uint16_t kNextFragmentSize       = 96;
+
+            uint16_t length = message.GetLength();
+
+            frameCount++;
+
+            if (length > kFirstFragmentMaxLength)
+            {
+                frameCount += (length - kFirstFragmentMaxLength) / kNextFragmentSize;
+            }
+
+            break;
+        }
+
+        case Message::kType6lowpan:
+        case Message::kTypeMacEmptyData:
+            frameCount++;
+            break;
+
+        case Message::kTypeSupervision:
+        default:
+            break;
+        }
+    }
+
+    return (frameCount > OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE);
+}
+
+void MeshForwarder::ApplyDirectTxQueueLimit(Message &aMessage)
+{
+    VerifyOrExit(aMessage.IsDirectTransmission());
+    VerifyOrExit(IsDirectTxQueueOverMaxFrameThreshold());
+
+#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+    if (RemoveAgedMessages() == kErrorNone)
+    {
+        VerifyOrExit(IsDirectTxQueueOverMaxFrameThreshold());
+    }
+#endif
+
+    LogMessage(kMessageFullQueueDrop, aMessage);
+    aMessage.ClearDirectTransmission();
+    RemoveMessageIfNoPendingTx(aMessage);
+
+exit:
+    return;
+}
+
+#endif // (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
+
 void MeshForwarder::ScheduleTransmissionTask(Tasklet &aTasklet)
 {
     aTasklet.Get<MeshForwarder>().ScheduleTransmissionTask();
@@ -234,7 +530,11 @@
 {
     VerifyOrExit(!mSendBusy && !mTxPaused);
 
-    mSendMessage = GetDirectTransmission();
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
+    VerifyOrExit(!mDelayNextTx);
+#endif
+
+    mSendMessage = PrepareNextDirectTransmission();
     VerifyOrExit(mSendMessage != nullptr);
 
     if (mSendMessage->GetOffset() == 0)
@@ -248,19 +548,31 @@
     return;
 }
 
-Message *MeshForwarder::GetDirectTransmission(void)
+Message *MeshForwarder::PrepareNextDirectTransmission(void)
 {
     Message *curMessage, *nextMessage;
     Error    error = kErrorNone;
 
     for (curMessage = mSendQueue.GetHead(); curMessage; curMessage = nextMessage)
     {
-        if (!curMessage->GetDirectTransmission())
+        // We set the `nextMessage` here but it can be updated again
+        // after the `switch(message.GetType())` since it may be
+        // evicted during message processing (e.g., from the call to
+        // `UpdateIp6Route()` due to Address Solicit).
+
+        nextMessage = curMessage->GetNext();
+
+        if (!curMessage->IsDirectTransmission() || curMessage->IsResolvingAddress())
         {
-            nextMessage = curMessage->GetNext();
             continue;
         }
 
+#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+        if (UpdateEcnOrDrop(*curMessage) == kErrorDrop)
+        {
+            continue;
+        }
+#endif
         curMessage->SetDoNotEvict(true);
 
         switch (curMessage->GetType())
@@ -299,16 +611,13 @@
             ExitNow();
 
 #if OPENTHREAD_FTD
-
         case kErrorAddressQuery:
-            mSendQueue.Dequeue(*curMessage);
-            mResolvingQueue.Enqueue(*curMessage);
+            curMessage->SetResolvingAddress(true);
             continue;
-
 #endif
 
         default:
-            LogMessage(kMessageDrop, *curMessage, nullptr, error);
+            LogMessage(kMessageDrop, *curMessage, error);
             mSendQueue.DequeueAndFree(*curMessage);
             continue;
         }
@@ -433,39 +742,6 @@
     }
 }
 
-Error MeshForwarder::DecompressIp6Header(const uint8_t *     aFrame,
-                                         uint16_t            aFrameLength,
-                                         const Mac::Address &aMacSource,
-                                         const Mac::Address &aMacDest,
-                                         Ip6::Header &       aIp6Header,
-                                         uint8_t &           aHeaderLength,
-                                         bool &              aNextHeaderCompressed)
-{
-    Error                  error = kErrorNone;
-    const uint8_t *        start = aFrame;
-    Lowpan::FragmentHeader fragmentHeader;
-    uint16_t               fragmentHeaderLength;
-    int                    headerLength;
-
-    if (fragmentHeader.ParseFrom(aFrame, aFrameLength, fragmentHeaderLength) == kErrorNone)
-    {
-        // Only the first fragment header is followed by a LOWPAN_IPHC header
-        VerifyOrExit(fragmentHeader.GetDatagramOffset() == 0, error = kErrorNotFound);
-        aFrame += fragmentHeaderLength;
-        aFrameLength -= fragmentHeaderLength;
-    }
-
-    VerifyOrExit(aFrameLength >= 1 && Lowpan::Lowpan::IsLowpanHc(aFrame), error = kErrorNotFound);
-    headerLength = Get<Lowpan::Lowpan>().DecompressBaseHeader(aIp6Header, aNextHeaderCompressed, aMacSource, aMacDest,
-                                                              aFrame, aFrameLength);
-
-    VerifyOrExit(headerLength > 0, error = kErrorParse);
-    aHeaderLength = static_cast<uint8_t>(aFrame - start) + static_cast<uint8_t>(headerLength);
-
-exit:
-    return error;
-}
-
 Mac::TxFrame *MeshForwarder::HandleFrameRequest(Mac::TxFrames &aTxFrames)
 {
     Mac::TxFrame *frame         = nullptr;
@@ -511,12 +787,11 @@
 
         if ((mSendMessage->GetSubType() == Message::kSubTypeMleChildIdRequest) && mSendMessage->IsLinkSecurityEnabled())
         {
-            otLogNoteMac("Child ID Request requires fragmentation, aborting tx");
+            LogNote("Child ID Request requires fragmentation, aborting tx");
             mMessageNextOffset = mSendMessage->GetLength();
             ExitNow(frame = nullptr);
         }
 
-        OT_ASSERT(frame->GetLength() != 7);
         break;
 
 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
@@ -771,10 +1046,11 @@
     // Compress IPv6 Header
     if (aMessage.GetOffset() == 0)
     {
-        Lowpan::BufferWriter buffer(payload,
-                                    maxPayloadLength - headerLength - Lowpan::FragmentHeader::kFirstFragmentHeaderSize);
-        uint8_t              hcLength;
-        Mac::Address         meshSource, meshDest;
+        FrameBuilder frameBuilder;
+        uint8_t      hcLength;
+        Mac::Address meshSource, meshDest;
+
+        frameBuilder.Init(payload, maxPayloadLength - headerLength - Lowpan::FragmentHeader::kFirstFragmentHeaderSize);
 
         if (aAddMeshHeader)
         {
@@ -787,9 +1063,9 @@
             meshDest   = aMacDest;
         }
 
-        SuccessOrAssert(Get<Lowpan::Lowpan>().Compress(aMessage, meshSource, meshDest, buffer));
+        SuccessOrAssert(Get<Lowpan::Lowpan>().Compress(aMessage, meshSource, meshDest, frameBuilder));
 
-        hcLength = static_cast<uint8_t>(buffer.GetWritePointer() - payload);
+        hcLength = static_cast<uint8_t>(frameBuilder.GetLength());
         headerLength += hcLength;
         payloadLength  = aMessage.GetLength() - aMessage.GetOffset();
         fragmentLength = maxPayloadLength - headerLength;
@@ -883,8 +1159,13 @@
     return nextOffset;
 }
 
-Neighbor *MeshForwarder::UpdateNeighborOnSentFrame(Mac::TxFrame &aFrame, Error aError, const Mac::Address &aMacDest)
+Neighbor *MeshForwarder::UpdateNeighborOnSentFrame(Mac::TxFrame &      aFrame,
+                                                   Error               aError,
+                                                   const Mac::Address &aMacDest,
+                                                   bool                aIsDataPoll)
 {
+    OT_UNUSED_VARIABLE(aIsDataPoll);
+
     Neighbor *neighbor = nullptr;
 
     VerifyOrExit(mEnabled);
@@ -907,7 +1188,7 @@
 #endif // OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
 
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-    if ((aFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) != nullptr) && aFrame.IsDataRequestCommand())
+    if ((aFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) != nullptr) && aIsDataPoll)
     {
         UpdateNeighborLinkFailures(*neighbor, aError, /* aAllowNeighborRemove */ true,
                                    /* aFailLimit */ Mle::kFailedCslDataPollTransmissions);
@@ -954,8 +1235,8 @@
 
     if (aError == kErrorNoAck)
     {
-        otLogInfoMac("Deferred ack timeout on trel for neighbor %s rloc16:0x%04x",
-                     aNeighbor.GetExtAddress().ToString().AsCString(), aNeighbor.GetRloc16());
+        LogInfo("Deferred ack timeout on trel for neighbor %s rloc16:0x%04x",
+                aNeighbor.GetExtAddress().ToString().AsCString(), aNeighbor.GetRloc16());
     }
 
 #if OPENTHREAD_CONFIG_MULTI_RADIO
@@ -983,6 +1264,18 @@
 
     VerifyOrExit(mEnabled);
 
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
+    if (mDelayNextTx && (aError == kErrorNone))
+    {
+        mTxDelayTimer.Start(kTxDelayInterval);
+        LogDebg("Start tx delay timer for %u msec", kTxDelayInterval);
+    }
+    else
+    {
+        mDelayNextTx = false;
+    }
+#endif
+
     if (!aFrame.IsEmpty())
     {
         IgnoreError(aFrame.GetDstAddr(macDest));
@@ -1001,7 +1294,7 @@
 
     VerifyOrExit(mSendMessage != nullptr);
 
-    OT_ASSERT(mSendMessage->GetDirectTransmission());
+    OT_ASSERT(mSendMessage->IsDirectTransmission());
 
     if (aFrameTxError != kErrorNone)
     {
@@ -1055,7 +1348,7 @@
     Get<Utils::HistoryTracker>().RecordTxMessage(*mSendMessage, aMacDest);
 #endif
 
-    LogMessage(kMessageTransmit, *mSendMessage, &aMacDest, txError);
+    LogMessage(kMessageTransmit, *mSendMessage, txError, &aMacDest);
 
     if (mSendMessage->GetType() == Message::kTypeIp6)
     {
@@ -1086,7 +1379,7 @@
             // shorter Child ID Request message (by only including mesh-local
             // address in the Address Registration TLV).
 
-            otLogInfoMac("Requesting shorter `Child ID Request`");
+            LogInfo("Requesting shorter `Child ID Request`");
             Get<Mle::Mle>().RequestShorterChildIdRequest();
         }
 
@@ -1104,7 +1397,7 @@
 
 void MeshForwarder::RemoveMessageIfNoPendingTx(Message &aMessage)
 {
-    VerifyOrExit(!aMessage.GetDirectTransmission() && !aMessage.IsChildPending());
+    VerifyOrExit(!aMessage.IsDirectTransmission() && !aMessage.IsChildPending());
 
     if (mSendMessage == &aMessage)
     {
@@ -1123,8 +1416,7 @@
     ThreadLinkInfo linkInfo;
     Mac::Address   macDest;
     Mac::Address   macSource;
-    uint8_t *      payload;
-    uint16_t       payloadLength;
+    FrameData      frameData;
     Error          error = kErrorNone;
 
     VerifyOrExit(mEnabled, error = kErrorInvalidState);
@@ -1134,8 +1426,7 @@
 
     linkInfo.SetFrom(aFrame);
 
-    payload       = aFrame.GetPayload();
-    payloadLength = aFrame.GetPayloadLength();
+    frameData.Init(aFrame.GetPayload(), aFrame.GetPayloadLength());
 
 #if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
     Get<Utils::SupervisionListener>().UpdateOnReceive(macSource, linkInfo.IsLinkSecurityEnabled());
@@ -1144,23 +1435,23 @@
     switch (aFrame.GetType())
     {
     case Mac::Frame::kFcfFrameData:
-        if (Lowpan::MeshHeader::IsMeshHeader(payload, payloadLength))
+        if (Lowpan::MeshHeader::IsMeshHeader(frameData))
         {
 #if OPENTHREAD_FTD
-            HandleMesh(payload, payloadLength, macSource, linkInfo);
+            HandleMesh(frameData, macSource, linkInfo);
 #endif
         }
-        else if (Lowpan::FragmentHeader::IsFragmentHeader(payload, payloadLength))
+        else if (Lowpan::FragmentHeader::IsFragmentHeader(frameData))
         {
-            HandleFragment(payload, payloadLength, macSource, macDest, linkInfo);
+            HandleFragment(frameData, macSource, macDest, linkInfo);
         }
-        else if (payloadLength >= 1 && Lowpan::Lowpan::IsLowpanHc(payload))
+        else if (Lowpan::Lowpan::IsLowpanHc(frameData))
         {
-            HandleLowpanHC(payload, payloadLength, macSource, macDest, linkInfo);
+            HandleLowpanHC(frameData, macSource, macDest, linkInfo);
         }
         else
         {
-            VerifyOrExit(payloadLength == 0, error = kErrorNotLowpanDataFrame);
+            VerifyOrExit(frameData.GetLength() == 0, error = kErrorNotLowpanDataFrame);
 
             LogFrame("Received empty payload frame", aFrame, kErrorNone);
         }
@@ -1183,21 +1474,16 @@
     }
 }
 
-void MeshForwarder::HandleFragment(const uint8_t *       aFrame,
-                                   uint16_t              aFrameLength,
+void MeshForwarder::HandleFragment(FrameData &           aFrameData,
                                    const Mac::Address &  aMacSource,
                                    const Mac::Address &  aMacDest,
                                    const ThreadLinkInfo &aLinkInfo)
 {
     Error                  error = kErrorNone;
     Lowpan::FragmentHeader fragmentHeader;
-    uint16_t               fragmentHeaderLength;
     Message *              message = nullptr;
 
-    // Check the fragment header
-    SuccessOrExit(error = fragmentHeader.ParseFrom(aFrame, aFrameLength, fragmentHeaderLength));
-    aFrame += fragmentHeaderLength;
-    aFrameLength -= fragmentHeaderLength;
+    SuccessOrExit(error = fragmentHeader.ParseFrom(aFrameData));
 
 #if OPENTHREAD_CONFIG_MULTI_RADIO
 
@@ -1239,18 +1525,16 @@
         uint16_t datagramSize = fragmentHeader.GetDatagramSize();
 
 #if OPENTHREAD_FTD
-        UpdateRoutes(aFrame, aFrameLength, aMacSource, aMacDest);
+        UpdateRoutes(aFrameData, aMacSource, aMacDest);
 #endif
 
-        error = FrameToMessage(aFrame, aFrameLength, datagramSize, aMacSource, aMacDest, message);
-        SuccessOrExit(error);
+        SuccessOrExit(error = FrameToMessage(aFrameData, datagramSize, aMacSource, aMacDest, message));
 
         VerifyOrExit(datagramSize >= message->GetLength(), error = kErrorParse);
-        error = message->SetLength(datagramSize);
-        SuccessOrExit(error);
+        SuccessOrExit(error = message->SetLength(datagramSize));
 
         message->SetDatagramTag(fragmentHeader.GetDatagramTag());
-        message->SetTimeout(kReassemblyTimeout);
+        message->SetTimestampToNow();
         message->SetLinkInfo(aLinkInfo);
 
         VerifyOrExit(Get<Ip6::Filter>().Accept(*message), error = kErrorDrop);
@@ -1274,15 +1558,16 @@
     }
     else // Received frame is a "next fragment".
     {
-        for (message = mReassemblyList.GetHead(); message; message = message->GetNext())
+        for (Message &msg : mReassemblyList)
         {
             // Security Check: only consider reassembly buffers that had the same Security Enabled setting.
-            if (message->GetLength() == fragmentHeader.GetDatagramSize() &&
-                message->GetDatagramTag() == fragmentHeader.GetDatagramTag() &&
-                message->GetOffset() == fragmentHeader.GetDatagramOffset() &&
-                message->GetOffset() + aFrameLength <= fragmentHeader.GetDatagramSize() &&
-                message->IsLinkSecurityEnabled() == aLinkInfo.IsLinkSecurityEnabled())
+            if (msg.GetLength() == fragmentHeader.GetDatagramSize() &&
+                msg.GetDatagramTag() == fragmentHeader.GetDatagramTag() &&
+                msg.GetOffset() == fragmentHeader.GetDatagramOffset() &&
+                msg.GetOffset() + aFrameData.GetLength() <= fragmentHeader.GetDatagramSize() &&
+                msg.IsLinkSecurityEnabled() == aLinkInfo.IsLinkSecurityEnabled())
             {
+                message = &msg;
                 break;
             }
         }
@@ -1300,13 +1585,13 @@
 
         VerifyOrExit(message != nullptr, error = kErrorDrop);
 
-        message->WriteBytes(message->GetOffset(), aFrame, aFrameLength);
-        message->MoveOffset(aFrameLength);
+        message->WriteData(message->GetOffset(), aFrameData);
+        message->MoveOffset(aFrameData.GetLength());
         message->AddRss(aLinkInfo.GetRss());
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
         message->AddLqi(aLinkInfo.GetLqi());
 #endif
-        message->SetTimeout(kReassemblyTimeout);
+        message->SetTimestampToNow();
     }
 
 exit:
@@ -1321,7 +1606,7 @@
     }
     else
     {
-        LogFragmentFrameDrop(error, aFrameLength, aMacSource, aMacDest, fragmentHeader,
+        LogFragmentFrameDrop(error, aFrameData.GetLength(), aMacSource, aMacDest, fragmentHeader,
                              aLinkInfo.IsLinkSecurityEnabled());
         FreeMessage(message);
     }
@@ -1329,17 +1614,17 @@
 
 void MeshForwarder::ClearReassemblyList(void)
 {
-    for (const Message *message = mReassemblyList.GetHead(); message != nullptr; message = message->GetNext())
+    for (Message &message : mReassemblyList)
     {
-        LogMessage(kMessageReassemblyDrop, *message, nullptr, kErrorNoFrameReceived);
+        LogMessage(kMessageReassemblyDrop, message, kErrorNoFrameReceived);
 
-        if (message->GetType() == Message::kTypeIp6)
+        if (message.GetType() == Message::kTypeIp6)
         {
             mIpCounters.mRxFailure++;
         }
-    }
 
-    mReassemblyList.DequeueAndFreeAll();
+        mReassemblyList.DequeueAndFree(message);
+    }
 }
 
 void MeshForwarder::HandleTimeTick(void)
@@ -1360,66 +1645,51 @@
 
 bool MeshForwarder::UpdateReassemblyList(void)
 {
-    Message *next = nullptr;
+    TimeMilli now = TimerMilli::GetNow();
 
-    for (Message *message = mReassemblyList.GetHead(); message; message = next)
+    for (Message &message : mReassemblyList)
     {
-        next = message->GetNext();
-
-        if (message->GetTimeout() > 0)
+        if (now - message.GetTimestamp() >= TimeMilli::SecToMsec(kReassemblyTimeout))
         {
-            message->DecrementTimeout();
-        }
-        else
-        {
-            LogMessage(kMessageReassemblyDrop, *message, nullptr, kErrorReassemblyTimeout);
+            LogMessage(kMessageReassemblyDrop, message, kErrorReassemblyTimeout);
 
-            if (message->GetType() == Message::kTypeIp6)
+            if (message.GetType() == Message::kTypeIp6)
             {
                 mIpCounters.mRxFailure++;
             }
 
-            mReassemblyList.DequeueAndFree(*message);
+            mReassemblyList.DequeueAndFree(message);
         }
     }
 
     return mReassemblyList.GetHead() != nullptr;
 }
 
-Error MeshForwarder::FrameToMessage(const uint8_t *     aFrame,
-                                    uint16_t            aFrameLength,
+Error MeshForwarder::FrameToMessage(const FrameData &   aFrameData,
                                     uint16_t            aDatagramSize,
                                     const Mac::Address &aMacSource,
                                     const Mac::Address &aMacDest,
                                     Message *&          aMessage)
 {
-    Error             error = kErrorNone;
-    int               headerLength;
+    Error             error     = kErrorNone;
+    FrameData         frameData = aFrameData;
     Message::Priority priority;
 
-    error = GetFramePriority(aFrame, aFrameLength, aMacSource, aMacDest, priority);
-    SuccessOrExit(error);
+    SuccessOrExit(error = GetFramePriority(frameData, aMacSource, aMacDest, priority));
 
-    aMessage = Get<MessagePool>().New(Message::kTypeIp6, 0, priority);
+    aMessage = Get<MessagePool>().Allocate(Message::kTypeIp6, /* aReserveHeader */ 0, Message::Settings(priority));
     VerifyOrExit(aMessage, error = kErrorNoBufs);
 
-    headerLength =
-        Get<Lowpan::Lowpan>().Decompress(*aMessage, aMacSource, aMacDest, aFrame, aFrameLength, aDatagramSize);
-    VerifyOrExit(headerLength > 0, error = kErrorParse);
+    SuccessOrExit(error = Get<Lowpan::Lowpan>().Decompress(*aMessage, aMacSource, aMacDest, frameData, aDatagramSize));
 
-    aFrame += headerLength;
-    aFrameLength -= static_cast<uint16_t>(headerLength);
-
-    SuccessOrExit(error = aMessage->SetLength(aMessage->GetLength() + aFrameLength));
-    aMessage->WriteBytes(aMessage->GetOffset(), aFrame, aFrameLength);
-    aMessage->MoveOffset(aFrameLength);
+    SuccessOrExit(error = aMessage->AppendData(frameData));
+    aMessage->MoveOffset(frameData.GetLength());
 
 exit:
     return error;
 }
 
-void MeshForwarder::HandleLowpanHC(const uint8_t *       aFrame,
-                                   uint16_t              aFrameLength,
+void MeshForwarder::HandleLowpanHC(const FrameData &     aFrameData,
                                    const Mac::Address &  aMacSource,
                                    const Mac::Address &  aMacDest,
                                    const ThreadLinkInfo &aLinkInfo)
@@ -1428,10 +1698,10 @@
     Message *message = nullptr;
 
 #if OPENTHREAD_FTD
-    UpdateRoutes(aFrame, aFrameLength, aMacSource, aMacDest);
+    UpdateRoutes(aFrameData, aMacSource, aMacDest);
 #endif
 
-    SuccessOrExit(error = FrameToMessage(aFrame, aFrameLength, 0, aMacSource, aMacDest, message));
+    SuccessOrExit(error = FrameToMessage(aFrameData, 0, aMacSource, aMacDest, message));
 
     message->SetLinkInfo(aLinkInfo);
 
@@ -1449,7 +1719,7 @@
     }
     else
     {
-        LogLowpanHcFrameDrop(error, aFrameLength, aMacSource, aMacDest, aLinkInfo.IsLinkSecurityEnabled());
+        LogLowpanHcFrameDrop(error, aFrameData.GetLength(), aMacSource, aMacDest, aLinkInfo.IsLinkSecurityEnabled());
         FreeMessage(message);
     }
 }
@@ -1462,7 +1732,7 @@
     Get<Utils::HistoryTracker>().RecordRxMessage(aMessage, aMacSource);
 #endif
 
-    LogMessage(kMessageReceive, aMessage, &aMacSource, kErrorNone);
+    LogMessage(kMessageReceive, aMessage, kErrorNone, &aMacSource);
 
     if (aMessage.GetType() == Message::kTypeIp6)
     {
@@ -1472,65 +1742,32 @@
     return Get<Ip6::Ip6>().HandleDatagram(aMessage, &netif, &aLinkInfo, false);
 }
 
-Error MeshForwarder::GetFramePriority(const uint8_t *     aFrame,
-                                      uint16_t            aFrameLength,
+Error MeshForwarder::GetFramePriority(const FrameData &   aFrameData,
                                       const Mac::Address &aMacSource,
                                       const Mac::Address &aMacDest,
                                       Message::Priority & aPriority)
 {
-    Error       error = kErrorNone;
-    Ip6::Header ip6Header;
-    uint16_t    dstPort;
-    uint8_t     headerLength;
-    bool        nextHeaderCompressed;
+    Error        error = kErrorNone;
+    Ip6::Headers headers;
 
-    SuccessOrExit(error = DecompressIp6Header(aFrame, aFrameLength, aMacSource, aMacDest, ip6Header, headerLength,
-                                              nextHeaderCompressed));
-    aPriority = Ip6::Ip6::DscpToPriority(ip6Header.GetDscp());
+    SuccessOrExit(error = headers.DecompressFrom(aFrameData, aMacSource, aMacDest, GetInstance()));
 
-    aFrame += headerLength;
-    aFrameLength -= headerLength;
+    aPriority = Ip6::Ip6::DscpToPriority(headers.GetIp6Header().GetDscp());
 
-    switch (ip6Header.GetNextHeader())
+    // Only ICMPv6 error messages are prioritized.
+    if (headers.IsIcmp6() && headers.GetIcmpHeader().IsError())
     {
-    case Ip6::kProtoIcmp6:
+        aPriority = Message::kPriorityNet;
+    }
 
-        VerifyOrExit(aFrameLength >= sizeof(Ip6::Icmp::Header), error = kErrorParse);
+    if (headers.IsUdp())
+    {
+        uint16_t destPort = headers.GetUdpHeader().GetDestinationPort();
 
-        // Only ICMPv6 error messages are prioritized.
-        if (reinterpret_cast<const Ip6::Icmp::Header *>(aFrame)->IsError())
+        if ((destPort == Mle::kUdpPort) || (destPort == Tmf::kUdpPort))
         {
             aPriority = Message::kPriorityNet;
         }
-
-        break;
-
-    case Ip6::kProtoUdp:
-
-        if (nextHeaderCompressed)
-        {
-            Ip6::Udp::Header udpHeader;
-
-            VerifyOrExit(Get<Lowpan::Lowpan>().DecompressUdpHeader(udpHeader, aFrame, aFrameLength) >= 0,
-                         error = kErrorParse);
-
-            dstPort = udpHeader.GetDestinationPort();
-        }
-        else
-        {
-            VerifyOrExit(aFrameLength >= sizeof(Ip6::Udp::Header), error = kErrorParse);
-            dstPort = reinterpret_cast<const Ip6::Udp::Header *>(aFrame)->GetDestinationPort();
-        }
-
-        if ((dstPort == Mle::kUdpPort) || (dstPort == Tmf::kUdpPort))
-        {
-            aPriority = Message::kPriorityNet;
-        }
-
-        break;
-
-    default:
-        break;
     }
 
 exit:
@@ -1547,14 +1784,14 @@
                      Get<Mle::MleRouter>().GetParent().IsStateValidOrRestoring(),
                  error = kErrorInvalidState);
 
-    message = Get<MessagePool>().New(Message::kTypeMacEmptyData, 0);
+    message = Get<MessagePool>().Allocate(Message::kTypeMacEmptyData);
     VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = SendMessage(*message));
 
 exit:
     FreeMessageOnError(message, error);
-    otLogDebgMac("Send empty message, error:%s", ErrorToString(error));
+    LogDebg("Send empty message, error:%s", ErrorToString(error));
     return error;
 }
 #endif // OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
@@ -1582,10 +1819,8 @@
 {
     uint8_t index     = 0;
     bool    iePresent = false;
-    // MIC is a part of Data Payload, so if it's present, Data Payload is not empty even if the message is
-    // MIC is always present when the frame is secured
-    bool payloadPresent = (aFrame.GetType() == Mac::Frame::kFcfFrameMacCmd) ||
-                          (aMessage != nullptr && aMessage->GetLength() != 0) || aFrame.GetSecurityEnabled();
+    bool    payloadPresent =
+        (aFrame.GetType() == Mac::Frame::kFcfFrameMacCmd) || (aMessage != nullptr && aMessage->GetLength() != 0);
 
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
     if (aMessage != nullptr && aMessage->IsTimeSync())
@@ -1643,53 +1878,7 @@
 
 // LCOV_EXCL_START
 
-Error MeshForwarder::ParseIp6UdpTcpHeader(const Message &aMessage,
-                                          Ip6::Header &  aIp6Header,
-                                          uint16_t &     aChecksum,
-                                          uint16_t &     aSourcePort,
-                                          uint16_t &     aDestPort)
-{
-    Error error = kErrorParse;
-    union
-    {
-        Ip6::Udp::Header udp;
-        Ip6::Tcp::Header tcp;
-    } header;
-
-    aChecksum   = 0;
-    aSourcePort = 0;
-    aDestPort   = 0;
-
-    SuccessOrExit(aMessage.Read(0, aIp6Header));
-    VerifyOrExit(aIp6Header.IsVersion6());
-
-    switch (aIp6Header.GetNextHeader())
-    {
-    case Ip6::kProtoUdp:
-        SuccessOrExit(aMessage.Read(sizeof(Ip6::Header), header.udp));
-        aChecksum   = header.udp.GetChecksum();
-        aSourcePort = header.udp.GetSourcePort();
-        aDestPort   = header.udp.GetDestinationPort();
-        break;
-
-    case Ip6::kProtoTcp:
-        SuccessOrExit(aMessage.Read(sizeof(Ip6::Header), header.tcp));
-        aChecksum   = header.tcp.GetChecksum();
-        aSourcePort = header.tcp.GetSourcePort();
-        aDestPort   = header.tcp.GetDestinationPort();
-        break;
-
-    default:
-        break;
-    }
-
-    error = kErrorNone;
-
-exit:
-    return error;
-}
-
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
 
 const char *MeshForwarder::MessageActionToString(MessageAction aAction, Error aError)
 {
@@ -1700,16 +1889,41 @@
         "Dropping",                    // (3) kMessageDrop
         "Dropping (reassembly queue)", // (4) kMessageReassemblyDrop
         "Evicting",                    // (5) kMessageEvict
+#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+        "Marked ECN",            // (6) kMessageMarkEcn
+        "Dropping (queue mgmt)", // (7) kMessageQueueMgmtDrop
+#endif
+#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
+        "Dropping (dir queue full)", // (8) kMessageFullQueueDrop
+#endif
     };
 
+    const char *string = kMessageActionStrings[aAction];
+
     static_assert(kMessageReceive == 0, "kMessageReceive value is incorrect");
     static_assert(kMessageTransmit == 1, "kMessageTransmit value is incorrect");
     static_assert(kMessagePrepareIndirect == 2, "kMessagePrepareIndirect value is incorrect");
     static_assert(kMessageDrop == 3, "kMessageDrop value is incorrect");
     static_assert(kMessageReassemblyDrop == 4, "kMessageReassemblyDrop value is incorrect");
     static_assert(kMessageEvict == 5, "kMessageEvict value is incorrect");
+#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+    static_assert(kMessageMarkEcn == 6, "kMessageMarkEcn is incorrect");
+    static_assert(kMessageQueueMgmtDrop == 7, "kMessageQueueMgmtDrop is incorrect");
+#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
+    static_assert(kMessageFullQueueDrop == 8, "kMessageFullQueueDrop is incorrect");
+#endif
+#else
+#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
+    static_assert(kMessageFullQueueDrop == 6, "kMessageFullQueueDrop is incorrect");
+#endif
+#endif
 
-    return (aError == kErrorNone) ? kMessageActionStrings[aAction] : "Failed to send";
+    if ((aAction == kMessageTransmit) && (aError != kErrorNone))
+    {
+        string = "Failed to send";
+    }
+
+    return string;
 }
 
 const char *MeshForwarder::MessagePriorityToString(const Message &aMessage)
@@ -1718,31 +1932,31 @@
 }
 
 #if OPENTHREAD_CONFIG_LOG_SRC_DST_IP_ADDRESSES
-void MeshForwarder::LogIp6SourceDestAddresses(Ip6::Header &aIp6Header,
-                                              uint16_t     aSourcePort,
-                                              uint16_t     aDestPort,
-                                              otLogLevel   aLogLevel)
+void MeshForwarder::LogIp6SourceDestAddresses(const Ip6::Headers &aHeaders, LogLevel aLogLevel)
 {
-    if (aSourcePort != 0)
+    uint16_t srcPort = aHeaders.GetSourcePort();
+    uint16_t dstPort = aHeaders.GetDestinationPort();
+
+    if (srcPort != 0)
     {
-        otLogMac(aLogLevel, "    src:[%s]:%d", aIp6Header.GetSource().ToString().AsCString(), aSourcePort);
+        LogAt(aLogLevel, "    src:[%s]:%d", aHeaders.GetSourceAddress().ToString().AsCString(), srcPort);
     }
     else
     {
-        otLogMac(aLogLevel, "    src:[%s]", aIp6Header.GetSource().ToString().AsCString());
+        LogAt(aLogLevel, "    src:[%s]", aHeaders.GetSourceAddress().ToString().AsCString());
     }
 
-    if (aDestPort != 0)
+    if (dstPort != 0)
     {
-        otLogMac(aLogLevel, "    dst:[%s]:%d", aIp6Header.GetDestination().ToString().AsCString(), aDestPort);
+        LogAt(aLogLevel, "    dst:[%s]:%d", aHeaders.GetDestinationAddress().ToString().AsCString(), dstPort);
     }
     else
     {
-        otLogMac(aLogLevel, "    dst:[%s]", aIp6Header.GetDestination().ToString().AsCString());
+        LogAt(aLogLevel, "    dst:[%s]", aHeaders.GetDestinationAddress().ToString().AsCString());
     }
 }
 #else
-void MeshForwarder::LogIp6SourceDestAddresses(Ip6::Header &, uint16_t, uint16_t, otLogLevel)
+void MeshForwarder::LogIp6SourceDestAddresses(const Ip6::Headers &, LogLevel)
 {
 }
 #endif
@@ -1751,17 +1965,14 @@
                                   const Message &     aMessage,
                                   const Mac::Address *aMacAddress,
                                   Error               aError,
-                                  otLogLevel          aLogLevel)
+                                  LogLevel            aLogLevel)
 {
-    Ip6::Header ip6Header;
-    uint16_t    checksum;
-    uint16_t    sourcePort;
-    uint16_t    destPort;
-    bool        shouldLogRss;
-    bool        shouldLogRadio = false;
-    const char *radioString    = "";
+    Ip6::Headers headers;
+    bool         shouldLogRss;
+    bool         shouldLogRadio = false;
+    const char * radioString    = "";
 
-    SuccessOrExit(ParseIp6UdpTcpHeader(aMessage, ip6Header, checksum, sourcePort, destPort));
+    SuccessOrExit(headers.ParseFrom(aMessage));
 
     shouldLogRss = (aAction == kMessageReceive) || (aAction == kMessageReassemblyDrop);
 
@@ -1770,20 +1981,20 @@
     radioString    = aMessage.IsRadioTypeSet() ? RadioTypeToString(aMessage.GetRadioType()) : "all";
 #endif
 
-    otLogMac(aLogLevel, "%s IPv6 %s msg, len:%d, chksum:%04x%s%s, sec:%s%s%s, prio:%s%s%s%s%s",
-             MessageActionToString(aAction, aError), Ip6::Ip6::IpProtoToString(ip6Header.GetNextHeader()),
-             aMessage.GetLength(), checksum,
-             (aMacAddress == nullptr) ? "" : ((aAction == kMessageReceive) ? ", from:" : ", to:"),
-             (aMacAddress == nullptr) ? "" : aMacAddress->ToString().AsCString(),
-             aMessage.IsLinkSecurityEnabled() ? "yes" : "no",
-             (aError == kErrorNone) ? "" : ", error:", (aError == kErrorNone) ? "" : ErrorToString(aError),
-             MessagePriorityToString(aMessage), shouldLogRss ? ", rss:" : "",
-             shouldLogRss ? aMessage.GetRssAverager().ToString().AsCString() : "", shouldLogRadio ? ", radio:" : "",
-             radioString);
+    LogAt(aLogLevel, "%s IPv6 %s msg, len:%d, chksum:%04x, ecn:%s%s%s, sec:%s%s%s, prio:%s%s%s%s%s",
+          MessageActionToString(aAction, aError), Ip6::Ip6::IpProtoToString(headers.GetIpProto()), aMessage.GetLength(),
+          headers.GetChecksum(), Ip6::Ip6::EcnToString(headers.GetEcn()),
+          (aMacAddress == nullptr) ? "" : ((aAction == kMessageReceive) ? ", from:" : ", to:"),
+          (aMacAddress == nullptr) ? "" : aMacAddress->ToString().AsCString(),
+          ToYesNo(aMessage.IsLinkSecurityEnabled()),
+          (aError == kErrorNone) ? "" : ", error:", (aError == kErrorNone) ? "" : ErrorToString(aError),
+          MessagePriorityToString(aMessage), shouldLogRss ? ", rss:" : "",
+          shouldLogRss ? aMessage.GetRssAverager().ToString().AsCString() : "", shouldLogRadio ? ", radio:" : "",
+          radioString);
 
     if (aAction != kMessagePrepareIndirect)
     {
-        LogIp6SourceDestAddresses(ip6Header, sourcePort, destPort, aLogLevel);
+        LogIp6SourceDestAddresses(headers, aLogLevel);
     }
 
 exit:
@@ -1792,23 +2003,33 @@
 
 void MeshForwarder::LogMessage(MessageAction       aAction,
                                const Message &     aMessage,
-                               const Mac::Address *aMacAddress,
-                               Error               aError)
+                               Error               aError,
+                               const Mac::Address *aMacAddress)
+
 {
-    otLogLevel logLevel = OT_LOG_LEVEL_INFO;
+    LogLevel logLevel = kLogLevelInfo;
 
     switch (aAction)
     {
     case kMessageReceive:
     case kMessageTransmit:
     case kMessagePrepareIndirect:
-        logLevel = (aError == kErrorNone) ? OT_LOG_LEVEL_INFO : OT_LOG_LEVEL_NOTE;
+#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+    case kMessageMarkEcn:
+#endif
+        logLevel = (aError == kErrorNone) ? kLogLevelInfo : kLogLevelNote;
         break;
 
     case kMessageDrop:
     case kMessageReassemblyDrop:
     case kMessageEvict:
-        logLevel = OT_LOG_LEVEL_NOTE;
+#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+    case kMessageQueueMgmtDrop:
+#endif
+#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
+    case kMessageFullQueueDrop:
+#endif
+        logLevel = kLogLevelNote;
         break;
     }
 
@@ -1838,11 +2059,11 @@
 {
     if (aError != kErrorNone)
     {
-        otLogNoteMac("%s, aError:%s, %s", aActionText, ErrorToString(aError), aFrame.ToInfoString().AsCString());
+        LogNote("%s, aError:%s, %s", aActionText, ErrorToString(aError), aFrame.ToInfoString().AsCString());
     }
     else
     {
-        otLogInfoMac("%s, %s", aActionText, aFrame.ToInfoString().AsCString());
+        LogInfo("%s, %s", aActionText, aFrame.ToInfoString().AsCString());
     }
 }
 
@@ -1853,10 +2074,10 @@
                                          const Lowpan::FragmentHeader &aFragmentHeader,
                                          bool                          aIsSecure)
 {
-    otLogNoteMac("Dropping rx frag frame, error:%s, len:%d, src:%s, dst:%s, tag:%d, offset:%d, dglen:%d, sec:%s",
-                 ErrorToString(aError), aFrameLength, aMacSource.ToString().AsCString(),
-                 aMacDest.ToString().AsCString(), aFragmentHeader.GetDatagramTag(), aFragmentHeader.GetDatagramOffset(),
-                 aFragmentHeader.GetDatagramSize(), aIsSecure ? "yes" : "no");
+    LogNote("Dropping rx frag frame, error:%s, len:%d, src:%s, dst:%s, tag:%d, offset:%d, dglen:%d, sec:%s",
+            ErrorToString(aError), aFrameLength, aMacSource.ToString().AsCString(), aMacDest.ToString().AsCString(),
+            aFragmentHeader.GetDatagramTag(), aFragmentHeader.GetDatagramOffset(), aFragmentHeader.GetDatagramSize(),
+            ToYesNo(aIsSecure));
 }
 
 void MeshForwarder::LogLowpanHcFrameDrop(Error               aError,
@@ -1865,14 +2086,13 @@
                                          const Mac::Address &aMacDest,
                                          bool                aIsSecure)
 {
-    otLogNoteMac("Dropping rx lowpan HC frame, error:%s, len:%d, src:%s, dst:%s, sec:%s", ErrorToString(aError),
-                 aFrameLength, aMacSource.ToString().AsCString(), aMacDest.ToString().AsCString(),
-                 aIsSecure ? "yes" : "no");
+    LogNote("Dropping rx lowpan HC frame, error:%s, len:%d, src:%s, dst:%s, sec:%s", ErrorToString(aError),
+            aFrameLength, aMacSource.ToString().AsCString(), aMacDest.ToString().AsCString(), ToYesNo(aIsSecure));
 }
 
-#else // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
+#else // #if OT_SHOULD_LOG_AT( OT_LOG_LEVEL_NOTE)
 
-void MeshForwarder::LogMessage(MessageAction, const Message &, const Mac::Address *, Error)
+void MeshForwarder::LogMessage(MessageAction, const Message &, Error, const Mac::Address *)
 {
 }
 
@@ -1893,7 +2113,7 @@
 {
 }
 
-#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
+#endif // #if OT_SHOULD_LOG_AT( OT_LOG_LEVEL_NOTE)
 
 // LCOV_EXCL_STOP
 
diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp
index f6a9e89..e063c9d 100644
--- a/src/core/thread/mesh_forwarder.hpp
+++ b/src/core/thread/mesh_forwarder.hpp
@@ -36,8 +36,11 @@
 
 #include "openthread-core-config.h"
 
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
+#include "common/frame_data.hpp"
 #include "common/locator.hpp"
+#include "common/log.hpp"
 #include "common/non_copyable.hpp"
 #include "common/tasklet.hpp"
 #include "common/time_ticker.hpp"
@@ -95,6 +98,15 @@
     uint8_t GetChannel(void) const { return mChannel; }
 
     /**
+     * This method returns whether the Destination PAN ID is broadcast.
+     *
+     * @retval TRUE   If Destination PAN ID is broadcast.
+     * @retval FALSE  If Destination PAN ID is not broadcast.
+     *
+     */
+    bool IsDstPanIdBroadcast(void) const { return mIsDstPanIdBroadcast; }
+
+    /**
      * This method indicates whether or not link security is enabled.
      *
      * @retval TRUE   If link security is enabled.
@@ -156,9 +168,9 @@
     friend class Instance;
     friend class DataPollSender;
     friend class IndirectSender;
+    friend class Ip6::Ip6;
     friend class Mle::DiscoverScanner;
     friend class TimeTicker;
-    friend class Utils::HistoryTracker;
 
 public:
     /**
@@ -299,15 +311,6 @@
      */
     void ResetCounters(void) { memset(&mIpCounters, 0, sizeof(mIpCounters)); }
 
-#if OPENTHREAD_FTD
-    /**
-     * This method returns a reference to the resolving queue.
-     *
-     * @returns  A reference to the resolving queue.
-     *
-     */
-    const PriorityQueue &GetResolvingQueue(void) const { return mResolvingQueue; }
-#endif
 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
     /**
      * This method handles a deferred ack.
@@ -331,14 +334,28 @@
     static constexpr uint8_t kMeshHeaderFrameMtu     = OT_RADIO_FRAME_MAX_SIZE; // Max MTU with a Mesh Header frame.
     static constexpr uint8_t kMeshHeaderFrameFcsSize = sizeof(uint16_t);        // Frame FCS size for Mesh Header frame.
 
+    static constexpr uint32_t kTxDelayInterval = OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_INTERVAL; // In msec
+
+#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+    static constexpr uint32_t kTimeInQueueMarkEcn = OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_MARK_ECN_INTERVAL;
+    static constexpr uint32_t kTimeInQueueDropMsg = OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_DROP_MSG_INTERVAL;
+#endif
+
     enum MessageAction : uint8_t
     {
         kMessageReceive,         // Indicates that the message was received.
         kMessageTransmit,        // Indicates that the message was sent.
         kMessagePrepareIndirect, // Indicates that the message is being prepared for indirect tx.
-        kMessageDrop,            // Indicates that the outbound message is being dropped (e.g., dst unknown).
+        kMessageDrop,            // Indicates that the outbound message is dropped (e.g., dst unknown).
         kMessageReassemblyDrop,  // Indicates that the message is being dropped from reassembly list.
         kMessageEvict,           // Indicates that the message was evicted.
+#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+        kMessageMarkEcn,       // Indicates that ECN is marked on an outbound message by delay-aware queue management.
+        kMessageQueueMgmtDrop, // Indicates that an outbound message is dropped by delay-aware queue management.
+#endif
+#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
+        kMessageFullQueueDrop, // Indicates message drop due to reaching max allowed frames in direct tx queue.
+#endif
     };
 
     enum AnycastType : uint8_t
@@ -357,21 +374,39 @@
             friend class FragmentPriorityList;
 
         public:
-            Message::Priority GetPriority(void) const { return mPriority; }
+            // Lifetime of an entry in seconds.
+            static constexpr uint8_t kLifetime =
+#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+                OT_MAX(kReassemblyTimeout, OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_FRAG_TAG_RETAIN_TIME);
+#else
+                kReassemblyTimeout;
+#endif
+
+            Message::Priority GetPriority(void) const { return static_cast<Message::Priority>(mPriority); }
             bool              IsExpired(void) const { return (mLifetime == 0); }
             void              DecrementLifetime(void) { mLifetime--; }
-            void              ResetLifetime(void) { mLifetime = kReassemblyTimeout; }
+            void              ResetLifetime(void) { mLifetime = kLifetime; }
 
             bool Matches(uint16_t aSrcRloc16, uint16_t aTag) const
             {
                 return (mSrcRloc16 == aSrcRloc16) && (mDatagramTag == aTag);
             }
 
+#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+            bool ShouldDrop(void) const { return mShouldDrop; }
+            void MarkToDrop(void) { mShouldDrop = true; }
+#endif
+
         private:
-            uint16_t          mSrcRloc16;
-            uint16_t          mDatagramTag;
-            Message::Priority mPriority;
-            uint8_t           mLifetime;
+            uint16_t mSrcRloc16;
+            uint16_t mDatagramTag;
+            uint8_t  mLifetime;
+            uint8_t  mPriority : 2;
+#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+            bool mShouldDrop : 1;
+#endif
+
+            static_assert(Message::kNumPriorities <= 4, "mPriority as a 2-bit does not fit all `Priority` values");
         };
 
         Entry *AllocateEntry(uint16_t aSrcRloc16, uint16_t aTag, Message::Priority aPriority);
@@ -379,56 +414,39 @@
         bool   UpdateOnTimeTick(void);
 
     private:
-        static constexpr uint16_t kNumEntries = OPENTHREAD_CONFIG_NUM_FRAGMENT_PRIORITY_ENTRIES;
+        static constexpr uint16_t kNumEntries =
+#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+            OT_MAX(OPENTHREAD_CONFIG_NUM_FRAGMENT_PRIORITY_ENTRIES,
+                   OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_FRAG_TAG_ENTRY_LIST_SIZE);
+#else
+            OPENTHREAD_CONFIG_NUM_FRAGMENT_PRIORITY_ENTRIES;
+#endif
 
         Entry mEntries[kNumEntries];
     };
 #endif // OPENTHREAD_FTD
 
-    void  SendIcmpErrorIfDstUnreach(const Message &     aMessage,
-                                    const Mac::Address &aMacSource,
-                                    const Mac::Address &aMacDest);
-    Error CheckReachability(const uint8_t *     aFrame,
-                            uint16_t            aFrameLength,
-                            const Mac::Address &aMeshSource,
-                            const Mac::Address &aMeshDest);
-    void  UpdateRoutes(const uint8_t *     aFrame,
-                       uint16_t            aFrameLength,
-                       const Mac::Address &aMeshSource,
-                       const Mac::Address &aMeshDest);
-
-    Error    DecompressIp6Header(const uint8_t *     aFrame,
-                                 uint16_t            aFrameLength,
-                                 const Mac::Address &aMacSource,
-                                 const Mac::Address &aMacDest,
-                                 Ip6::Header &       aIp6Header,
-                                 uint8_t &           aHeaderLength,
-                                 bool &              aNextHeaderCompressed);
-    Error    FrameToMessage(const uint8_t *     aFrame,
-                            uint16_t            aFrameLength,
+    void     SendIcmpErrorIfDstUnreach(const Message &     aMessage,
+                                       const Mac::Address &aMacSource,
+                                       const Mac::Address &aMacDest);
+    Error    CheckReachability(const FrameData &   aFrameData,
+                               const Mac::Address &aMeshSource,
+                               const Mac::Address &aMeshDest);
+    void     UpdateRoutes(const FrameData &aFrameData, const Mac::Address &aMeshSource, const Mac::Address &aMeshDest);
+    Error    FrameToMessage(const FrameData &   aFrameData,
                             uint16_t            aDatagramSize,
                             const Mac::Address &aMacSource,
                             const Mac::Address &aMacDest,
                             Message *&          aMessage);
-    Error    GetIp6Header(const uint8_t *     aFrame,
-                          uint16_t            aFrameLength,
-                          const Mac::Address &aMacSource,
-                          const Mac::Address &aMacDest,
-                          Ip6::Header &       aIp6Header);
     void     GetMacDestinationAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr);
     void     GetMacSourceAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr);
-    Message *GetDirectTransmission(void);
-    void     HandleMesh(uint8_t *             aFrame,
-                        uint16_t              aFrameLength,
-                        const Mac::Address &  aMacSource,
-                        const ThreadLinkInfo &aLinkInfo);
-    void     HandleFragment(const uint8_t *       aFrame,
-                            uint16_t              aFrameLength,
+    Message *PrepareNextDirectTransmission(void);
+    void     HandleMesh(FrameData &aFrameData, const Mac::Address &aMacSource, const ThreadLinkInfo &aLinkInfo);
+    void     HandleFragment(FrameData &           aFrameData,
                             const Mac::Address &  aMacSource,
                             const Mac::Address &  aMacDest,
                             const ThreadLinkInfo &aLinkInfo);
-    void     HandleLowpanHC(const uint8_t *       aFrame,
-                            uint16_t              aFrameLength,
+    void     HandleLowpanHC(const FrameData &     aFrameData,
                             const Mac::Address &  aMacSource,
                             const Mac::Address &  aMacDest,
                             const ThreadLinkInfo &aLinkInfo);
@@ -442,8 +460,16 @@
                               bool                aAddFragHeader = false);
     void     PrepareEmptyFrame(Mac::TxFrame &aFrame, const Mac::Address &aMacDest, bool aAckRequest);
 
+#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+    Error UpdateEcnOrDrop(Message &aMessage, bool aPreparingToSend = true);
+    Error RemoveAgedMessages(void);
+#endif
+#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
+    bool IsDirectTxQueueOverMaxFrameThreshold(void) const;
+    void ApplyDirectTxQueueLimit(Message &aMessage);
+#endif
     void  SendMesh(Message &aMessage, Mac::TxFrame &aFrame);
-    void  SendDestinationUnreachable(uint16_t aMeshSource, const Message &aMessage);
+    void  SendDestinationUnreachable(uint16_t aMeshSource, const Ip6::Headers &aIp6Headers);
     Error UpdateIp6Route(Message &aMessage);
     Error UpdateIp6RouteFtd(Ip6::Header &ip6Header, Message &aMessage);
     void  EvaluateRoutingCost(uint16_t aDest, uint8_t &aBestCost, uint16_t &aBestDest) const;
@@ -461,7 +487,10 @@
 
     void          HandleReceivedFrame(Mac::RxFrame &aFrame);
     Mac::TxFrame *HandleFrameRequest(Mac::TxFrames &aTxFrames);
-    Neighbor *    UpdateNeighborOnSentFrame(Mac::TxFrame &aFrame, Error aError, const Mac::Address &aMacDest);
+    Neighbor *    UpdateNeighborOnSentFrame(Mac::TxFrame &      aFrame,
+                                            Error               aError,
+                                            const Mac::Address &aMacDest,
+                                            bool                aIsDataPoll = false);
     void          UpdateNeighborLinkFailures(Neighbor &aNeighbor,
                                              Error     aError,
                                              bool      aAllowNeighborRemove,
@@ -474,16 +503,14 @@
     static void ScheduleTransmissionTask(Tasklet &aTasklet);
     void        ScheduleTransmissionTask(void);
 
-    Error GetFramePriority(const uint8_t *     aFrame,
-                           uint16_t            aFrameLength,
+    Error GetFramePriority(const FrameData &   aFrameData,
                            const Mac::Address &aMacSource,
                            const Mac::Address &aMacDest,
                            Message::Priority & aPriority);
     Error GetFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader,
                               uint16_t                aSrcRloc16,
                               Message::Priority &     aPriority);
-    void  GetForwardFramePriority(const uint8_t *     aFrame,
-                                  uint16_t            aFrameLength,
+    void  GetForwardFramePriority(const FrameData &   aFrameData,
                                   const Mac::Address &aMeshSource,
                                   const Mac::Address &aMeshDest,
                                   Message::Priority & aPriority);
@@ -497,7 +524,15 @@
     void PauseMessageTransmissions(void) { mTxPaused = true; }
     void ResumeMessageTransmissions(void);
 
-    void LogMessage(MessageAction aAction, const Message &aMessage, const Mac::Address *aAddress, Error aError);
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
+    static void HandleTxDelayTimer(Timer &aTimer);
+    void        HandleTxDelayTimer(void);
+#endif
+
+    void LogMessage(MessageAction       aAction,
+                    const Message &     aMessage,
+                    Error               aError   = kErrorNone,
+                    const Mac::Address *aAddress = nullptr);
     void LogFrame(const char *aActionText, const Mac::Frame &aFrame, Error aError);
     void LogFragmentFrameDrop(Error                         aError,
                               uint16_t                      aFrameLength,
@@ -511,25 +546,11 @@
                               const Mac::Address &aMacDest,
                               bool                aIsSecure);
 
-    static Error ParseIp6UdpTcpHeader(const Message &aMessage,
-                                      Ip6::Header &  aIp6Header,
-                                      uint16_t &     aChecksum,
-                                      uint16_t &     aSourcePort,
-                                      uint16_t &     aDestPort);
-
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
     const char *MessageActionToString(MessageAction aAction, Error aError);
     const char *MessagePriorityToString(const Message &aMessage);
 
 #if OPENTHREAD_FTD
-    Error DecompressIp6UdpTcpHeader(const Message &     aMessage,
-                                    uint16_t            aOffset,
-                                    const Mac::Address &aMeshSource,
-                                    const Mac::Address &aMeshDest,
-                                    Ip6::Header &       aIp6Header,
-                                    uint16_t &          aChecksum,
-                                    uint16_t &          aSourcePort,
-                                    uint16_t &          aDestPort);
     Error LogMeshFragmentHeader(MessageAction       aAction,
                                 const Message &     aMessage,
                                 const Mac::Address *aMacAddress,
@@ -537,28 +558,25 @@
                                 uint16_t &          aOffset,
                                 Mac::Address &      aMeshSource,
                                 Mac::Address &      aMeshDest,
-                                otLogLevel          aLogLevel);
+                                LogLevel            aLogLevel);
     void  LogMeshIpHeader(const Message &     aMessage,
                           uint16_t            aOffset,
                           const Mac::Address &aMeshSource,
                           const Mac::Address &aMeshDest,
-                          otLogLevel          aLogLevel);
+                          LogLevel            aLogLevel);
     void  LogMeshMessage(MessageAction       aAction,
                          const Message &     aMessage,
                          const Mac::Address *aAddress,
                          Error               aError,
-                         otLogLevel          aLogLevel);
+                         LogLevel            aLogLevel);
 #endif
-    void LogIp6SourceDestAddresses(Ip6::Header &aIp6Header,
-                                   uint16_t     aSourcePort,
-                                   uint16_t     aDestPort,
-                                   otLogLevel   aLogLevel);
+    void LogIp6SourceDestAddresses(const Ip6::Headers &aHeaders, LogLevel aLogLevel);
     void LogIp6Message(MessageAction       aAction,
                        const Message &     aMessage,
                        const Mac::Address *aAddress,
                        Error               aError,
-                       otLogLevel          aLogLevel);
-#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
+                       LogLevel            aLogLevel);
+#endif // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
 
     PriorityQueue mSendQueue;
     MessageQueue  mReassemblyList;
@@ -575,6 +593,10 @@
     bool         mEnabled : 1;
     bool         mTxPaused : 1;
     bool         mSendBusy : 1;
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
+    bool       mDelayNextTx : 1;
+    TimerMilli mTxDelayTimer;
+#endif
 
     Tasklet mScheduleTransmissionTask;
 
@@ -582,7 +604,6 @@
 
 #if OPENTHREAD_FTD
     FragmentPriorityList mFragmentPriorityList;
-    PriorityQueue        mResolvingQueue;
     IndirectSender       mIndirectSender;
 #endif
 
@@ -594,6 +615,8 @@
  *
  */
 
+DefineCoreType(otThreadLinkInfo, ThreadLinkInfo);
+
 } // namespace ot
 
 #endif // MESH_FORWARDER_HPP_
diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp
index f6d3687..9b5cdc3 100644
--- a/src/core/thread/mesh_forwarder_ftd.cpp
+++ b/src/core/thread/mesh_forwarder_ftd.cpp
@@ -36,7 +36,6 @@
 #if OPENTHREAD_FTD
 
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
 #include "meshcop/meshcop.hpp"
 #include "net/ip6.hpp"
 #include "net/tcp6.hpp"
@@ -44,6 +43,8 @@
 
 namespace ot {
 
+RegisterLogModule("MeshForwarder");
+
 Error MeshForwarder::SendMessage(Message &aMessage)
 {
     Mle::MleRouter &mle   = Get<Mle::MleRouter>();
@@ -52,6 +53,7 @@
 
     aMessage.SetOffset(0);
     aMessage.SetDatagramTag(0);
+    aMessage.SetTimestampToNow();
     mSendQueue.Enqueue(aMessage);
 
     switch (aMessage.GetType())
@@ -102,7 +104,7 @@
             }
         }
         else if ((neighbor = Get<NeighborTable>().FindNeighbor(ip6Header.GetDestination())) != nullptr &&
-                 !neighbor->IsRxOnWhenIdle() && !aMessage.GetDirectTransmission())
+                 !neighbor->IsRxOnWhenIdle() && !aMessage.IsDirectTransmission())
         {
             // destined for a sleepy child
             Child &child = *static_cast<Child *>(neighbor);
@@ -132,6 +134,10 @@
         break;
     }
 
+#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
+    ApplyDirectTxQueueLimit(aMessage);
+#endif
+
     mScheduleTransmissionTask.Post();
 
     return error;
@@ -139,39 +145,55 @@
 
 void MeshForwarder::HandleResolved(const Ip6::Address &aEid, Error aError)
 {
-    Message *    cur, *next;
     Ip6::Address ip6Dst;
-    bool         enqueuedMessage = false;
+    bool         didUpdate = false;
 
-    for (cur = mResolvingQueue.GetHead(); cur; cur = next)
+    for (Message &message : mSendQueue)
     {
-        next = cur->GetNext();
-
-        if (cur->GetType() != Message::kTypeIp6)
+        if (!message.IsResolvingAddress())
         {
             continue;
         }
 
-        IgnoreError(cur->Read(Ip6::Header::kDestinationFieldOffset, ip6Dst));
+        IgnoreError(message.Read(Ip6::Header::kDestinationFieldOffset, ip6Dst));
 
-        if (ip6Dst == aEid)
+        if (ip6Dst != aEid)
         {
-            mResolvingQueue.Dequeue(*cur);
-
-            if (aError == kErrorNone)
-            {
-                mSendQueue.Enqueue(*cur);
-                enqueuedMessage = true;
-            }
-            else
-            {
-                LogMessage(kMessageDrop, *cur, nullptr, aError);
-                cur->Free();
-            }
+            continue;
         }
+
+        if (aError != kErrorNone)
+        {
+            LogMessage(kMessageDrop, message, kErrorAddressQuery);
+            mSendQueue.DequeueAndFree(message);
+            continue;
+        }
+
+#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
+        // Pass back to IPv6 layer for DUA destination resolved
+        // by Backbone Query
+        if (Get<BackboneRouter::Local>().IsPrimary() && Get<BackboneRouter::Leader>().IsDomainUnicast(ip6Dst) &&
+            Get<AddressResolver>().LookUp(ip6Dst) == Get<Mle::MleRouter>().GetRloc16())
+        {
+            uint8_t hopLimit;
+
+            mSendQueue.Dequeue(message);
+
+            // Avoid decreasing Hop Limit twice
+            IgnoreError(message.Read(Ip6::Header::kHopLimitFieldOffset, hopLimit));
+            hopLimit++;
+            message.Write(Ip6::Header::kHopLimitFieldOffset, hopLimit);
+
+            IgnoreError(Get<Ip6::Ip6>().HandleDatagram(message, nullptr, nullptr, /* aFromHost */ false));
+            continue;
+        }
+#endif
+
+        message.SetResolvingAddress(false);
+        didUpdate = true;
     }
 
-    if (enqueuedMessage)
+    if (didUpdate)
     {
         mScheduleTransmissionTask.Post();
     }
@@ -179,38 +201,34 @@
 
 Error MeshForwarder::EvictMessage(Message::Priority aPriority)
 {
-    Error          error    = kErrorNotFound;
-    PriorityQueue *queues[] = {&mResolvingQueue, &mSendQueue};
-    Message *      evict    = nullptr;
+    Error    error = kErrorNotFound;
+    Message *evict = nullptr;
 
-    // search for a lower priority message to evict (choose lowest priority message among all queues)
-    for (PriorityQueue *queue : queues)
+#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+    error = RemoveAgedMessages();
+    VerifyOrExit(error == kErrorNotFound);
+#endif
+
+    // Search for a lower priority message to evict
+    for (uint8_t priority = 0; priority < aPriority; priority++)
     {
-        for (uint8_t priority = 0; priority < aPriority; priority++)
+        for (Message *message = mSendQueue.GetHeadForPriority(static_cast<Message::Priority>(priority)); message;
+             message          = message->GetNext())
         {
-            for (Message *message = queue->GetHeadForPriority(static_cast<Message::Priority>(priority)); message;
-                 message          = message->GetNext())
+            if (message->GetPriority() != priority)
             {
-                if (message->GetPriority() != priority)
-                {
-                    break;
-                }
-
-                if (message->GetDoNotEvict())
-                {
-                    continue;
-                }
-
-                evict     = message;
-                aPriority = static_cast<Message::Priority>(priority);
                 break;
             }
-        }
-    }
 
-    if (evict != nullptr)
-    {
-        ExitNow(error = kErrorNone);
+            if (message->GetDoNotEvict())
+            {
+                continue;
+            }
+
+            evict = message;
+            error = kErrorNone;
+            ExitNow();
+        }
     }
 
     for (uint8_t priority = aPriority; priority < Message::kNumPriorities; priority++)
@@ -237,8 +255,7 @@
     }
 
 exit:
-
-    if (error == kErrorNone)
+    if ((error == kErrorNone) && (evict != nullptr))
     {
         RemoveMessage(*evict);
     }
@@ -248,30 +265,26 @@
 
 void MeshForwarder::RemoveMessages(Child &aChild, Message::SubType aSubType)
 {
-    Message *nextMessage;
-
-    for (Message *message = mSendQueue.GetHead(); message; message = nextMessage)
+    for (Message &message : mSendQueue)
     {
-        nextMessage = message->GetNext();
-
-        if ((aSubType != Message::kSubTypeNone) && (aSubType != message->GetSubType()))
+        if ((aSubType != Message::kSubTypeNone) && (aSubType != message.GetSubType()))
         {
             continue;
         }
 
-        if (mIndirectSender.RemoveMessageFromSleepyChild(*message, aChild) != kErrorNone)
+        if (mIndirectSender.RemoveMessageFromSleepyChild(message, aChild) != kErrorNone)
         {
-            switch (message->GetType())
+            switch (message.GetType())
             {
             case Message::kTypeIp6:
             {
                 Ip6::Header ip6header;
 
-                IgnoreError(message->Read(0, ip6header));
+                IgnoreError(message.Read(0, ip6header));
 
                 if (&aChild == static_cast<Child *>(Get<NeighborTable>().FindNeighbor(ip6header.GetDestination())))
                 {
-                    message->ClearDirectTransmission();
+                    message.ClearDirectTransmission();
                 }
 
                 break;
@@ -281,11 +294,11 @@
             {
                 Lowpan::MeshHeader meshHeader;
 
-                IgnoreError(meshHeader.ParseFrom(*message));
+                IgnoreError(meshHeader.ParseFrom(message));
 
                 if (&aChild == static_cast<Child *>(Get<NeighborTable>().FindNeighbor(meshHeader.GetDestination())))
                 {
-                    message->ClearDirectTransmission();
+                    message.ClearDirectTransmission();
                 }
 
                 break;
@@ -296,41 +309,38 @@
             }
         }
 
-        RemoveMessageIfNoPendingTx(*message);
+        RemoveMessageIfNoPendingTx(message);
     }
 }
 
 void MeshForwarder::RemoveDataResponseMessages(void)
 {
     Ip6::Header ip6Header;
-    Message *   next;
 
-    for (Message *message = mSendQueue.GetHead(); message != nullptr; message = next)
+    for (Message &message : mSendQueue)
     {
-        next = message->GetNext();
-
-        if (message->GetSubType() != Message::kSubTypeMleDataResponse)
+        if (message.GetSubType() != Message::kSubTypeMleDataResponse)
         {
             continue;
         }
 
-        IgnoreError(message->Read(0, ip6Header));
+        IgnoreError(message.Read(0, ip6Header));
 
         if (!(ip6Header.GetDestination().IsMulticast()))
         {
             for (Child &child : Get<ChildTable>().Iterate(Child::kInStateAnyExceptInvalid))
             {
-                IgnoreError(mIndirectSender.RemoveMessageFromSleepyChild(*message, child));
+                IgnoreError(mIndirectSender.RemoveMessageFromSleepyChild(message, child));
             }
         }
 
-        if (mSendMessage == message)
+        if (mSendMessage == &message)
         {
             mSendMessage = nullptr;
         }
 
-        LogMessage(kMessageDrop, *message, nullptr, kErrorNone);
-        mSendQueue.DequeueAndFree(*message);
+        LogMessage(kMessageDrop, message);
+        mSendQueue.DequeueAndFree(message);
     }
 }
 
@@ -402,6 +412,13 @@
     mMeshDest      = meshHeader.GetDestination();
     mMeshSource    = meshHeader.GetSource();
 
+#if OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
+    if (mMacDest.GetShort() != mMeshDest)
+    {
+        mDelayNextTx = true;
+    }
+#endif
+
 exit:
     return error;
 }
@@ -615,100 +632,71 @@
         // destination is not neighbor
         mMacSource.SetShort(mMeshSource);
         mAddMeshHeader = true;
+#if OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
+        mDelayNextTx = true;
+#endif
     }
 
 exit:
     return error;
 }
 
-Error MeshForwarder::GetIp6Header(const uint8_t *     aFrame,
-                                  uint16_t            aFrameLength,
-                                  const Mac::Address &aMacSource,
-                                  const Mac::Address &aMacDest,
-                                  Ip6::Header &       aIp6Header)
-{
-    uint8_t headerLength;
-    bool    nextHeaderCompressed;
-
-    return DecompressIp6Header(aFrame, aFrameLength, aMacSource, aMacDest, aIp6Header, headerLength,
-                               nextHeaderCompressed);
-}
-
 void MeshForwarder::SendIcmpErrorIfDstUnreach(const Message &     aMessage,
                                               const Mac::Address &aMacSource,
                                               const Mac::Address &aMacDest)
 {
-    Error       error;
-    Ip6::Header ip6header;
-    Child *     child;
+    Error        error;
+    Ip6::Headers ip6Headers;
+    Child *      child;
 
     VerifyOrExit(aMacSource.IsShort() && aMacDest.IsShort());
 
     child = Get<ChildTable>().FindChild(aMacSource.GetShort(), Child::kInStateAnyExceptInvalid);
     VerifyOrExit((child == nullptr) || child->IsFullThreadDevice());
 
-    IgnoreError(aMessage.Read(0, ip6header));
-    VerifyOrExit(!ip6header.GetDestination().IsMulticast() &&
-                 Get<NetworkData::Leader>().IsOnMesh(ip6header.GetDestination()));
+    SuccessOrExit(ip6Headers.ParseFrom(aMessage));
 
-    error = Get<Mle::MleRouter>().CheckReachability(aMacDest.GetShort(), ip6header);
+    VerifyOrExit(!ip6Headers.GetDestinationAddress().IsMulticast() &&
+                 Get<NetworkData::Leader>().IsOnMesh(ip6Headers.GetDestinationAddress()));
+
+    error = Get<Mle::MleRouter>().CheckReachability(aMacDest.GetShort(), ip6Headers.GetIp6Header());
 
     if (error == kErrorNoRoute)
     {
-        SendDestinationUnreachable(aMacSource.GetShort(), aMessage);
+        SendDestinationUnreachable(aMacSource.GetShort(), ip6Headers);
     }
 
 exit:
     return;
 }
 
-Error MeshForwarder::CheckReachability(const uint8_t *     aFrame,
-                                       uint16_t            aFrameLength,
+Error MeshForwarder::CheckReachability(const FrameData &   aFrameData,
                                        const Mac::Address &aMeshSource,
                                        const Mac::Address &aMeshDest)
 {
-    Error                  error = kErrorNone;
-    Ip6::Header            ip6Header;
-    Message *              message = nullptr;
-    Lowpan::FragmentHeader fragmentHeader;
-    uint16_t               fragmentHeaderLength;
-    uint16_t               datagramSize = 0;
+    Error        error;
+    Ip6::Headers ip6Headers;
 
-    if (fragmentHeader.ParseFrom(aFrame, aFrameLength, fragmentHeaderLength) == kErrorNone)
-    {
-        // Only the first fragment header is followed by a LOWPAN_IPHC header
-        VerifyOrExit(fragmentHeader.GetDatagramOffset() == 0, error = kErrorNotFound);
-        aFrame += fragmentHeaderLength;
-        aFrameLength -= fragmentHeaderLength;
+    error = ip6Headers.DecompressFrom(aFrameData, aMeshSource, aMeshDest, GetInstance());
 
-        datagramSize = fragmentHeader.GetDatagramSize();
-    }
-
-    VerifyOrExit(aFrameLength >= 1 && Lowpan::Lowpan::IsLowpanHc(aFrame), error = kErrorNotFound);
-
-    error = FrameToMessage(aFrame, aFrameLength, datagramSize, aMeshSource, aMeshDest, message);
-    SuccessOrExit(error);
-
-    IgnoreError(message->Read(0, ip6Header));
-    error = Get<Mle::MleRouter>().CheckReachability(aMeshDest.GetShort(), ip6Header);
-
-exit:
     if (error == kErrorNotFound)
     {
-        // the message may not contain an IPv6 header
-        error = kErrorNone;
+        // Frame may not contain an IPv6 header.
+        ExitNow(error = kErrorNone);
     }
-    else if (error == kErrorNoRoute)
+
+    error = Get<Mle::MleRouter>().CheckReachability(aMeshDest.GetShort(), ip6Headers.GetIp6Header());
+
+    if (error == kErrorNoRoute)
     {
-        SendDestinationUnreachable(aMeshSource.GetShort(), *message);
+        SendDestinationUnreachable(aMeshSource.GetShort(), ip6Headers);
     }
 
-    FreeMessage(message);
-
+exit:
     return error;
 }
 
-void MeshForwarder::SendDestinationUnreachable(uint16_t aMeshSource, const Message &aMessage)
+void MeshForwarder::SendDestinationUnreachable(uint16_t aMeshSource, const Ip6::Headers &aIp6Headers)
 {
     Ip6::MessageInfo messageInfo;
 
@@ -716,44 +704,37 @@
     messageInfo.GetPeerAddr().GetIid().SetLocator(aMeshSource);
 
     IgnoreError(Get<Ip6::Icmp>().SendError(Ip6::Icmp::Header::kTypeDstUnreach,
-                                           Ip6::Icmp::Header::kCodeDstUnreachNoRoute, messageInfo, aMessage));
+                                           Ip6::Icmp::Header::kCodeDstUnreachNoRoute, messageInfo, aIp6Headers));
 }
 
-void MeshForwarder::HandleMesh(uint8_t *             aFrame,
-                               uint16_t              aFrameLength,
-                               const Mac::Address &  aMacSource,
-                               const ThreadLinkInfo &aLinkInfo)
+void MeshForwarder::HandleMesh(FrameData &aFrameData, const Mac::Address &aMacSource, const ThreadLinkInfo &aLinkInfo)
 {
     Error              error   = kErrorNone;
     Message *          message = nullptr;
     Mac::Address       meshDest;
     Mac::Address       meshSource;
     Lowpan::MeshHeader meshHeader;
-    uint16_t           headerLength;
 
     // Security Check: only process Mesh Header frames that had security enabled.
     VerifyOrExit(aLinkInfo.IsLinkSecurityEnabled(), error = kErrorSecurity);
 
-    SuccessOrExit(error = meshHeader.ParseFrom(aFrame, aFrameLength, headerLength));
+    SuccessOrExit(error = meshHeader.ParseFrom(aFrameData));
 
     meshSource.SetShort(meshHeader.GetSource());
     meshDest.SetShort(meshHeader.GetDestination());
 
-    aFrame += headerLength;
-    aFrameLength -= headerLength;
-
-    UpdateRoutes(aFrame, aFrameLength, meshSource, meshDest);
+    UpdateRoutes(aFrameData, meshSource, meshDest);
 
     if (meshDest.GetShort() == Get<Mac::Mac>().GetShortAddress() ||
         Get<Mle::MleRouter>().IsMinimalChild(meshDest.GetShort()))
     {
-        if (Lowpan::FragmentHeader::IsFragmentHeader(aFrame, aFrameLength))
+        if (Lowpan::FragmentHeader::IsFragmentHeader(aFrameData))
         {
-            HandleFragment(aFrame, aFrameLength, meshSource, meshDest, aLinkInfo);
+            HandleFragment(aFrameData, meshSource, meshDest, aLinkInfo);
         }
-        else if (Lowpan::Lowpan::IsLowpanHc(aFrame))
+        else if (Lowpan::Lowpan::IsLowpanHc(aFrameData))
         {
-            HandleLowpanHC(aFrame, aFrameLength, meshSource, meshDest, aLinkInfo);
+            HandleLowpanHC(aFrameData, meshSource, meshDest, aLinkInfo);
         }
         else
         {
@@ -763,21 +744,21 @@
     else if (meshHeader.GetHopsLeft() > 0)
     {
         Message::Priority priority = Message::kPriorityNormal;
-        uint16_t          offset   = 0;
 
         Get<Mle::MleRouter>().ResolveRoutingLoops(aMacSource.GetShort(), meshDest.GetShort());
 
-        SuccessOrExit(error = CheckReachability(aFrame, aFrameLength, meshSource, meshDest));
+        SuccessOrExit(error = CheckReachability(aFrameData, meshSource, meshDest));
 
         meshHeader.DecrementHopsLeft();
 
-        GetForwardFramePriority(aFrame, aFrameLength, meshSource, meshDest, priority);
-        message = Get<MessagePool>().New(Message::kType6lowpan, priority);
+        GetForwardFramePriority(aFrameData, meshSource, meshDest, priority);
+        message =
+            Get<MessagePool>().Allocate(Message::kType6lowpan, /* aReserveHeader */ 0, Message::Settings(priority));
         VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
-        SuccessOrExit(error = message->SetLength(meshHeader.GetHeaderLength() + aFrameLength));
-        offset += meshHeader.WriteTo(*message, offset);
-        message->WriteBytes(offset, aFrame, aFrameLength);
+        SuccessOrExit(error = meshHeader.AppendTo(*message));
+        SuccessOrExit(error = message->AppendData(aFrameData));
+
         message->SetLinkInfo(aLinkInfo);
 
 #if OPENTHREAD_CONFIG_MULTI_RADIO
@@ -786,7 +767,7 @@
         message->SetRadioType(static_cast<Mac::RadioType>(aLinkInfo.mRadioType));
 #endif
 
-        LogMessage(kMessageReceive, *message, &aMacSource, kErrorNone);
+        LogMessage(kMessageReceive, *message, kErrorNone, &aMacSource);
 
 #if OPENTHREAD_CONFIG_MULTI_RADIO
         // Since the message will be forwarded, we clear the radio
@@ -803,34 +784,35 @@
 
     if (error != kErrorNone)
     {
-        otLogInfoMac("Dropping rx mesh frame, error:%s, len:%d, src:%s, sec:%s", ErrorToString(error), aFrameLength,
-                     aMacSource.ToString().AsCString(), aLinkInfo.IsLinkSecurityEnabled() ? "yes" : "no");
+        LogInfo("Dropping rx mesh frame, error:%s, len:%d, src:%s, sec:%s", ErrorToString(error),
+                aFrameData.GetLength(), aMacSource.ToString().AsCString(), ToYesNo(aLinkInfo.IsLinkSecurityEnabled()));
         FreeMessage(message);
     }
 }
 
-void MeshForwarder::UpdateRoutes(const uint8_t *     aFrame,
-                                 uint16_t            aFrameLength,
+void MeshForwarder::UpdateRoutes(const FrameData &   aFrameData,
                                  const Mac::Address &aMeshSource,
                                  const Mac::Address &aMeshDest)
 {
-    Ip6::Header ip6Header;
-    Neighbor *  neighbor;
+    Ip6::Headers ip6Headers;
+    Neighbor *   neighbor;
 
     VerifyOrExit(!aMeshDest.IsBroadcast() && aMeshSource.IsShort());
-    SuccessOrExit(GetIp6Header(aFrame, aFrameLength, aMeshSource, aMeshDest, ip6Header));
 
-    if (!ip6Header.GetSource().GetIid().IsLocator() &&
-        Get<NetworkData::Leader>().IsOnMesh(ip6Header.GetSource()) /* only for on mesh address which may require AQ */)
+    SuccessOrExit(ip6Headers.DecompressFrom(aFrameData, aMeshSource, aMeshDest, GetInstance()));
+
+    if (!ip6Headers.GetSourceAddress().GetIid().IsLocator() &&
+        Get<NetworkData::Leader>().IsOnMesh(ip6Headers.GetSourceAddress()))
     {
         // FTDs MAY add/update EID-to-RLOC Map Cache entries by
-        // inspecting packets being received.
+        // inspecting packets being received only for on mesh
+        // addresses.
 
-        Get<AddressResolver>().UpdateSnoopedCacheEntry(ip6Header.GetSource(), aMeshSource.GetShort(),
+        Get<AddressResolver>().UpdateSnoopedCacheEntry(ip6Headers.GetSourceAddress(), aMeshSource.GetShort(),
                                                        aMeshDest.GetShort());
     }
 
-    neighbor = Get<NeighborTable>().FindNeighbor(ip6Header.GetSource());
+    neighbor = Get<NeighborTable>().FindNeighbor(ip6Headers.GetSourceAddress());
     VerifyOrExit(neighbor != nullptr && !neighbor->IsFullThreadDevice());
 
     if (!Mle::Mle::RouterIdMatch(aMeshSource.GetShort(), Get<Mac::Mac>().GetShortAddress()))
@@ -880,11 +862,18 @@
         ExitNow();
     }
 
+#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+    OT_UNUSED_VARIABLE(aFragmentLength);
+#else
+    // We can clear the entry in `mFragmentPriorityList` if it is the
+    // last fragment. But if "delay aware active queue management" is
+    // used we need to keep entry until the message is sent.
     if (aFragmentHeader.GetDatagramOffset() + aFragmentLength >= aFragmentHeader.GetDatagramSize())
     {
         entry->Clear();
     }
     else
+#endif
     {
         entry->ResetLifetime();
     }
@@ -921,6 +910,7 @@
     {
         if (entry.IsExpired())
         {
+            entry.Clear();
             entry.mSrcRloc16   = aSrcRloc16;
             entry.mDatagramTag = aTag;
             entry.mPriority    = aPriority;
@@ -948,22 +938,19 @@
     return error;
 }
 
-void MeshForwarder::GetForwardFramePriority(const uint8_t *     aFrame,
-                                            uint16_t            aFrameLength,
+void MeshForwarder::GetForwardFramePriority(const FrameData &   aFrameData,
                                             const Mac::Address &aMeshSource,
                                             const Mac::Address &aMeshDest,
                                             Message::Priority & aPriority)
 {
     Error                  error      = kErrorNone;
+    FrameData              frameData  = aFrameData;
     bool                   isFragment = false;
     Lowpan::FragmentHeader fragmentHeader;
-    uint16_t               fragmentHeaderLength;
 
-    if (fragmentHeader.ParseFrom(aFrame, aFrameLength, fragmentHeaderLength) == kErrorNone)
+    if (fragmentHeader.ParseFrom(frameData) == kErrorNone)
     {
         isFragment = true;
-        aFrame += fragmentHeaderLength;
-        aFrameLength -= fragmentHeaderLength;
 
         if (fragmentHeader.GetDatagramOffset() > 0)
         {
@@ -973,25 +960,23 @@
     }
 
     // Get priority from IPv6 header or UDP destination port directly
-    error = GetFramePriority(aFrame, aFrameLength, aMeshSource, aMeshDest, aPriority);
+    error = GetFramePriority(frameData, aMeshSource, aMeshDest, aPriority);
 
 exit:
     if (error != kErrorNone)
     {
-        otLogNoteMac("Failed to get forwarded frame priority, error:%s, len:%d, src:%d, dst:%s", ErrorToString(error),
-                     aFrameLength, aMeshSource.ToString().AsCString(), aMeshDest.ToString().AsCString());
+        LogNote("Failed to get forwarded frame priority, error:%s, len:%d, src:%d, dst:%s", ErrorToString(error),
+                frameData.GetLength(), aMeshSource.ToString().AsCString(), aMeshDest.ToString().AsCString());
     }
     else if (isFragment)
     {
-        UpdateFragmentPriority(fragmentHeader, aFrameLength, aMeshSource.GetShort(), aPriority);
+        UpdateFragmentPriority(fragmentHeader, frameData.GetLength(), aMeshSource.GetShort(), aPriority);
     }
-
-    return;
 }
 
 // LCOV_EXCL_START
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
 
 Error MeshForwarder::LogMeshFragmentHeader(MessageAction       aAction,
                                            const Message &     aMessage,
@@ -1000,7 +985,7 @@
                                            uint16_t &          aOffset,
                                            Mac::Address &      aMeshSource,
                                            Mac::Address &      aMeshDest,
-                                           otLogLevel          aLogLevel)
+                                           LogLevel            aLogLevel)
 {
     Error                  error             = kErrorFailed;
     bool                   hasFragmentHeader = false;
@@ -1031,20 +1016,20 @@
     radioString    = aMessage.IsRadioTypeSet() ? RadioTypeToString(aMessage.GetRadioType()) : "all";
 #endif
 
-    otLogMac(aLogLevel, "%s mesh frame, len:%d%s%s, msrc:%s, mdst:%s, hops:%d, frag:%s, sec:%s%s%s%s%s%s%s",
-             MessageActionToString(aAction, aError), aMessage.GetLength(),
-             (aMacAddress == nullptr) ? "" : ((aAction == kMessageReceive) ? ", from:" : ", to:"),
-             (aMacAddress == nullptr) ? "" : aMacAddress->ToString().AsCString(), aMeshSource.ToString().AsCString(),
-             aMeshDest.ToString().AsCString(), meshHeader.GetHopsLeft() + ((aAction == kMessageReceive) ? 1 : 0),
-             hasFragmentHeader ? "yes" : "no", aMessage.IsLinkSecurityEnabled() ? "yes" : "no",
-             (aError == kErrorNone) ? "" : ", error:", (aError == kErrorNone) ? "" : ErrorToString(aError),
-             shouldLogRss ? ", rss:" : "", shouldLogRss ? aMessage.GetRssAverager().ToString().AsCString() : "",
-             shouldLogRadio ? ", radio:" : "", radioString);
+    LogAt(aLogLevel, "%s mesh frame, len:%d%s%s, msrc:%s, mdst:%s, hops:%d, frag:%s, sec:%s%s%s%s%s%s%s",
+          MessageActionToString(aAction, aError), aMessage.GetLength(),
+          (aMacAddress == nullptr) ? "" : ((aAction == kMessageReceive) ? ", from:" : ", to:"),
+          (aMacAddress == nullptr) ? "" : aMacAddress->ToString().AsCString(), aMeshSource.ToString().AsCString(),
+          aMeshDest.ToString().AsCString(), meshHeader.GetHopsLeft() + ((aAction == kMessageReceive) ? 1 : 0),
+          ToYesNo(hasFragmentHeader), ToYesNo(aMessage.IsLinkSecurityEnabled()),
+          (aError == kErrorNone) ? "" : ", error:", (aError == kErrorNone) ? "" : ErrorToString(aError),
+          shouldLogRss ? ", rss:" : "", shouldLogRss ? aMessage.GetRssAverager().ToString().AsCString() : "",
+          shouldLogRadio ? ", radio:" : "", radioString);
 
     if (hasFragmentHeader)
     {
-        otLogMac(aLogLevel, "    Frag tag:%04x, offset:%d, size:%d", fragmentHeader.GetDatagramTag(),
-                 fragmentHeader.GetDatagramOffset(), fragmentHeader.GetDatagramSize());
+        LogAt(aLogLevel, "    Frag tag:%04x, offset:%d, size:%d", fragmentHeader.GetDatagramTag(),
+              fragmentHeader.GetDatagramOffset(), fragmentHeader.GetDatagramSize());
 
         VerifyOrExit(fragmentHeader.GetDatagramOffset() == 0);
     }
@@ -1055,96 +1040,20 @@
     return error;
 }
 
-Error MeshForwarder::DecompressIp6UdpTcpHeader(const Message &     aMessage,
-                                               uint16_t            aOffset,
-                                               const Mac::Address &aMeshSource,
-                                               const Mac::Address &aMeshDest,
-                                               Ip6::Header &       aIp6Header,
-                                               uint16_t &          aChecksum,
-                                               uint16_t &          aSourcePort,
-                                               uint16_t &          aDestPort)
-{
-    Error    error = kErrorParse;
-    int      headerLength;
-    bool     nextHeaderCompressed;
-    uint8_t  frameBuffer[sizeof(Ip6::Header)];
-    uint16_t frameLength;
-    union
-    {
-        Ip6::Udp::Header udp;
-        Ip6::Tcp::Header tcp;
-    } header;
-
-    aChecksum   = 0;
-    aSourcePort = 0;
-    aDestPort   = 0;
-
-    // Read and decompress the IPv6 header
-
-    frameLength = aMessage.ReadBytes(aOffset, frameBuffer, sizeof(frameBuffer));
-
-    headerLength = Get<Lowpan::Lowpan>().DecompressBaseHeader(aIp6Header, nextHeaderCompressed, aMeshSource, aMeshDest,
-                                                              frameBuffer, frameLength);
-    VerifyOrExit(headerLength >= 0);
-
-    aOffset += headerLength;
-
-    // Read and decompress UDP or TCP header
-
-    switch (aIp6Header.GetNextHeader())
-    {
-    case Ip6::kProtoUdp:
-        if (nextHeaderCompressed)
-        {
-            frameLength  = aMessage.ReadBytes(aOffset, frameBuffer, sizeof(Ip6::Udp::Header));
-            headerLength = Get<Lowpan::Lowpan>().DecompressUdpHeader(header.udp, frameBuffer, frameLength);
-            VerifyOrExit(headerLength >= 0);
-        }
-        else
-        {
-            SuccessOrExit(aMessage.Read(aOffset, header.udp));
-        }
-
-        aChecksum   = header.udp.GetChecksum();
-        aSourcePort = header.udp.GetSourcePort();
-        aDestPort   = header.udp.GetDestinationPort();
-        break;
-
-    case Ip6::kProtoTcp:
-        SuccessOrExit(aMessage.Read(aOffset, header.tcp));
-        aChecksum   = header.tcp.GetChecksum();
-        aSourcePort = header.tcp.GetSourcePort();
-        aDestPort   = header.tcp.GetDestinationPort();
-        break;
-
-    default:
-        break;
-    }
-
-    error = kErrorNone;
-
-exit:
-    return error;
-}
-
 void MeshForwarder::LogMeshIpHeader(const Message &     aMessage,
                                     uint16_t            aOffset,
                                     const Mac::Address &aMeshSource,
                                     const Mac::Address &aMeshDest,
-                                    otLogLevel          aLogLevel)
+                                    LogLevel            aLogLevel)
 {
-    uint16_t    checksum;
-    uint16_t    sourcePort;
-    uint16_t    destPort;
-    Ip6::Header ip6Header;
+    Ip6::Headers headers;
 
-    SuccessOrExit(DecompressIp6UdpTcpHeader(aMessage, aOffset, aMeshSource, aMeshDest, ip6Header, checksum, sourcePort,
-                                            destPort));
+    SuccessOrExit(headers.DecompressFrom(aMessage, aOffset, aMeshSource, aMeshDest));
 
-    otLogMac(aLogLevel, "    IPv6 %s msg, chksum:%04x, prio:%s", Ip6::Ip6::IpProtoToString(ip6Header.GetNextHeader()),
-             checksum, MessagePriorityToString(aMessage));
+    LogAt(aLogLevel, "    IPv6 %s msg, chksum:%04x, ecn:%s, prio:%s", Ip6::Ip6::IpProtoToString(headers.GetIpProto()),
+          headers.GetChecksum(), Ip6::Ip6::EcnToString(headers.GetEcn()), MessagePriorityToString(aMessage));
 
-    LogIp6SourceDestAddresses(ip6Header, sourcePort, destPort, aLogLevel);
+    LogIp6SourceDestAddresses(headers, aLogLevel);
 
 exit:
     return;
@@ -1154,7 +1063,7 @@
                                    const Message &     aMessage,
                                    const Mac::Address *aMacAddress,
                                    Error               aError,
-                                   otLogLevel          aLogLevel)
+                                   LogLevel            aLogLevel)
 {
     uint16_t     offset;
     Mac::Address meshSource;
@@ -1176,7 +1085,7 @@
     return;
 }
 
-#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
+#endif // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
 
 // LCOV_EXCL_STOP
 
diff --git a/src/core/thread/mesh_forwarder_mtd.cpp b/src/core/thread/mesh_forwarder_mtd.cpp
index 76db595..5e69705 100644
--- a/src/core/thread/mesh_forwarder_mtd.cpp
+++ b/src/core/thread/mesh_forwarder_mtd.cpp
@@ -42,10 +42,15 @@
     aMessage.SetDirectTransmission();
     aMessage.SetOffset(0);
     aMessage.SetDatagramTag(0);
+    aMessage.SetTimestampToNow();
 
     mSendQueue.Enqueue(aMessage);
     mScheduleTransmissionTask.Post();
 
+#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
+    ApplyDirectTxQueueLimit(aMessage);
+#endif
+
     return kErrorNone;
 }
 
@@ -54,6 +59,11 @@
     Error    error = kErrorNotFound;
     Message *message;
 
+#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+    error = RemoveAgedMessages();
+    VerifyOrExit(error == kErrorNotFound);
+#endif
+
     VerifyOrExit((message = mSendQueue.GetTail()) != nullptr);
 
     if (message->GetPriority() < static_cast<uint8_t>(aPriority))
diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp
index d7c8886..451aa92 100644
--- a/src/core/thread/mle.cpp
+++ b/src/core/thread/mle.cpp
@@ -36,16 +36,16 @@
 #include <openthread/platform/radio.h>
 #include <openthread/platform/time.h>
 
+#include "common/array.hpp"
 #include "common/as_core_type.hpp"
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
 #include "common/random.hpp"
+#include "common/serial_number.hpp"
 #include "common/settings.hpp"
-#include "crypto/aes_ccm.hpp"
 #include "meshcop/meshcop.hpp"
 #include "meshcop/meshcop_tlvs.hpp"
 #include "net/netif.hpp"
@@ -62,6 +62,12 @@
 namespace ot {
 namespace Mle {
 
+RegisterLogModule("Mle");
+
+const otMeshLocalPrefix Mle::sMeshLocalPrefixInit = {
+    {0xfd, 0xde, 0xad, 0x00, 0xbe, 0xef, 0x00, 0x00},
+};
+
 Mle::Mle(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mRetrieveNewNetworkData(false)
@@ -75,8 +81,11 @@
     , mAttachTimer(aInstance, Mle::HandleAttachTimer)
     , mDelayedResponseTimer(aInstance, Mle::HandleDelayedResponseTimer)
     , mMessageTransmissionTimer(aInstance, Mle::HandleMessageTransmissionTimer)
+    , mDetachGracefullyTimer(aInstance, Mle::HandleDetachGracefullyTimer)
     , mParentLeaderCost(0)
-    , mParentRequestMode(kAttachAny)
+    , mDetachGracefullyCallback(nullptr)
+    , mDetachGracefullyContext(nullptr)
+    , mAttachMode(kAnyPartition)
     , mParentPriority(0)
     , mParentLinkQuality3(0)
     , mParentLinkQuality2(0)
@@ -97,9 +106,7 @@
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
     , mCslTimeout(OPENTHREAD_CONFIG_CSL_TIMEOUT)
 #endif
-#if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
     , mPreviousParentRloc(Mac::kShortAddrInvalid)
-#endif
 #if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
     , mParentSearchIsInBackoff(false)
     , mParentSearchBackoffWasCanceled(false)
@@ -114,8 +121,6 @@
     , mParentResponseCb(nullptr)
     , mParentResponseCbContext(nullptr)
 {
-    MeshLocalPrefix meshLocalPrefix;
-
     mParent.Init(aInstance);
     mParentCandidate.Init(aInstance);
 
@@ -130,16 +135,6 @@
 
     mLeaderAloc.InitAsThreadOriginRealmLocalScope();
 
-#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-    for (Ip6::Netif::UnicastAddress &serviceAloc : mServiceAlocs)
-    {
-        serviceAloc.InitAsThreadOriginRealmLocalScope();
-        serviceAloc.GetAddress().GetIid().SetLocator(Mac::kShortAddrInvalid);
-    }
-#endif
-
-    meshLocalPrefix.SetFromExtendedPanId(Get<Mac::Mac>().GetExtendedPanId());
-
     mMeshLocal64.InitAsThreadOriginRealmLocalScope();
     mMeshLocal64.GetAddress().GetIid().GenerateRandom();
 
@@ -158,7 +153,7 @@
     mRealmLocalAllThreadNodes.GetAddress().mFields.m16[0] = HostSwap16(0xff33);
     mRealmLocalAllThreadNodes.GetAddress().mFields.m16[7] = HostSwap16(0x0001);
 
-    SetMeshLocalPrefix(meshLocalPrefix);
+    SetMeshLocalPrefix(AsCoreType(&sMeshLocalPrefixInit));
 
     // `SetMeshLocalPrefix()` also adds the Mesh-Local EID and subscribes
     // to the Link- and Realm-Local All Thread Nodes multicast addresses.
@@ -226,14 +221,14 @@
 
     if ((aMode == kAnnounceAttach) || (GetRloc16() == Mac::kShortAddrInvalid))
     {
-        IgnoreError(BecomeChild(kAttachAny));
+        Attach(kAnyPartition);
     }
 #if OPENTHREAD_FTD
     else if (IsActiveRouter(GetRloc16()))
     {
         if (Get<MleRouter>().BecomeRouter(ThreadStatusTlv::kTooFewRouters) != kErrorNone)
         {
-            IgnoreError(BecomeChild(kAttachAny));
+            Attach(kAnyPartition);
         }
     }
 #endif
@@ -251,8 +246,8 @@
 {
     if (aMode == kUpdateNetworkDatasets)
     {
-        Get<MeshCoP::ActiveDataset>().HandleDetach();
-        Get<MeshCoP::PendingDataset>().HandleDetach();
+        Get<MeshCoP::ActiveDatasetManager>().HandleDetach();
+        Get<MeshCoP::PendingDatasetManager>().HandleDetach();
     }
 
     VerifyOrExit(!IsDisabled());
@@ -267,7 +262,18 @@
     SetRole(kRoleDisabled);
 
 exit:
-    return;
+    mDetachGracefullyTimer.Stop();
+
+    if (mDetachGracefullyCallback != nullptr)
+    {
+        otDetachGracefullyCallback callback = mDetachGracefullyCallback;
+        void *                     context  = mDetachGracefullyContext;
+
+        mDetachGracefullyCallback = nullptr;
+        mDetachGracefullyContext  = nullptr;
+
+        callback(context);
+    }
 }
 
 void Mle::SetRole(DeviceRole aRole)
@@ -276,7 +282,7 @@
 
     SuccessOrExit(Get<Notifier>().Update(mRole, aRole, kEventThreadRoleChanged));
 
-    otLogNoteMle("Role %s -> %s", RoleToString(oldRole), RoleToString(mRole));
+    LogNote("Role %s -> %s", RoleToString(oldRole), RoleToString(mRole));
 
     switch (mRole)
     {
@@ -304,38 +310,42 @@
     }
 
 exit:
-    OT_UNUSED_VARIABLE(oldRole);
+    return;
 }
 
 void Mle::SetAttachState(AttachState aState)
 {
     VerifyOrExit(aState != mAttachState);
-    otLogInfoMle("AttachState %s -> %s", AttachStateToString(mAttachState), AttachStateToString(aState));
+    LogInfo("AttachState %s -> %s", AttachStateToString(mAttachState), AttachStateToString(aState));
     mAttachState = aState;
 
 exit:
     return;
 }
 
-Error Mle::Restore(void)
+void Mle::Restore(void)
 {
-    Error                 error = kErrorNone;
     Settings::NetworkInfo networkInfo;
     Settings::ParentInfo  parentInfo;
 
-    IgnoreError(Get<MeshCoP::ActiveDataset>().Restore());
-    IgnoreError(Get<MeshCoP::PendingDataset>().Restore());
+    IgnoreError(Get<MeshCoP::ActiveDatasetManager>().Restore());
+    IgnoreError(Get<MeshCoP::PendingDatasetManager>().Restore());
 
 #if OPENTHREAD_CONFIG_DUA_ENABLE
     Get<DuaManager>().Restore();
 #endif
 
-    SuccessOrExit(error = Get<Settings>().Read(networkInfo));
+    SuccessOrExit(Get<Settings>().Read(networkInfo));
 
     Get<KeyManager>().SetCurrentKeySequence(networkInfo.GetKeySequence());
     Get<KeyManager>().SetMleFrameCounter(networkInfo.GetMleFrameCounter());
     Get<KeyManager>().SetAllMacFrameCounters(networkInfo.GetMacFrameCounter());
+
+#if OPENTHREAD_MTD
+    mDeviceMode.Set(networkInfo.GetDeviceMode() & ~DeviceMode::kModeFullThreadDevice);
+#else
     mDeviceMode.Set(networkInfo.GetDeviceMode());
+#endif
 
     // force re-attach when version mismatch.
     VerifyOrExit(networkInfo.GetVersion() == kThreadVersion);
@@ -351,7 +361,12 @@
         ExitNow();
     }
 
-    Get<Mac::Mac>().SetShortAddress(networkInfo.GetRloc16());
+#if OPENTHREAD_MTD
+    if (!IsActiveRouter(networkInfo.GetRloc16()))
+#endif
+    {
+        Get<Mac::Mac>().SetShortAddress(networkInfo.GetRloc16());
+    }
     Get<Mac::Mac>().SetExtAddress(networkInfo.GetExtAddress());
 
     mMeshLocal64.GetAddress().SetIid(networkInfo.GetMeshLocalIid());
@@ -363,9 +378,7 @@
 
     if (!IsActiveRouter(networkInfo.GetRloc16()))
     {
-        error = Get<Settings>().Read(parentInfo);
-
-        if (error != kErrorNone)
+        if (Get<Settings>().Read(parentInfo) != kErrorNone)
         {
             // If the restored RLOC16 corresponds to an end-device, it
             // is expected that the `ParentInfo` settings to be valid
@@ -373,8 +386,8 @@
             // setting by skipping the re-attach ("Child Update Request"
             // exchange) and going through the full attach process.
 
-            otLogWarnMle("Invalid settings - no saved parent info with valid end-device RLOC16 0x%04x",
-                         networkInfo.GetRloc16());
+            LogWarn("Invalid settings - no saved parent info with valid end-device RLOC16 0x%04x",
+                    networkInfo.GetRloc16());
             ExitNow();
         }
 
@@ -386,9 +399,7 @@
         mParent.SetRloc16(Rloc16FromRouterId(RouterIdFromRloc16(networkInfo.GetRloc16())));
         mParent.SetState(Neighbor::kStateRestored);
 
-#if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
         mPreviousParentRloc = mParent.GetRloc16();
-#endif
     }
 #if OPENTHREAD_FTD
     else
@@ -399,11 +410,11 @@
     }
 #endif
 
-    // Sucessfully restored the network information from non-volatile settings after boot.
+    // Successfully restored the network information from non-volatile settings after boot.
     mHasRestored = true;
 
 exit:
-    return error;
+    return;
 }
 
 Error Mle::Store(void)
@@ -462,7 +473,7 @@
     Get<KeyManager>().SetStoredMleFrameCounter(networkInfo.GetMleFrameCounter());
     Get<KeyManager>().SetStoredMacFrameCounter(networkInfo.GetMacFrameCounter());
 
-    otLogDebgMle("Store Network Information");
+    LogDebg("Store Network Information");
 
 exit:
     return error;
@@ -483,7 +494,7 @@
     // not in reattach stage after reset
     if (mReattachState == kReattachStop)
     {
-        Get<MeshCoP::PendingDataset>().HandleDetach();
+        Get<MeshCoP::PendingDatasetManager>().HandleDetach();
     }
 
 #if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
@@ -493,19 +504,29 @@
     SetStateDetached();
     mParent.SetState(Neighbor::kStateInvalid);
     SetRloc16(Mac::kShortAddrInvalid);
-    IgnoreError(BecomeChild(kAttachAny));
+    Attach(kAnyPartition);
 
 exit:
     return error;
 }
 
-Error Mle::BecomeChild(AttachMode aMode)
+Error Mle::BecomeChild(void)
 {
     Error error = kErrorNone;
 
     VerifyOrExit(!IsDisabled(), error = kErrorInvalidState);
     VerifyOrExit(!IsAttaching(), error = kErrorBusy);
 
+    Attach(kAnyPartition);
+
+exit:
+    return error;
+}
+
+void Mle::Attach(AttachMode aMode)
+{
+    VerifyOrExit(!IsDisabled() && !IsAttaching());
+
     if (!IsDetached())
     {
         mAttachCounter = 0;
@@ -513,7 +534,7 @@
 
     if (mReattachState == kReattachStart)
     {
-        if (Get<MeshCoP::ActiveDataset>().Restore() == kErrorNone)
+        if (Get<MeshCoP::ActiveDatasetManager>().Restore() == kErrorNone)
         {
             mReattachState = kReattachActive;
         }
@@ -525,9 +546,9 @@
 
     mParentCandidate.Clear();
     SetAttachState(kAttachStateStart);
-    mParentRequestMode = aMode;
+    mAttachMode = aMode;
 
-    if (aMode != kAttachBetter)
+    if (aMode != kBetterPartition)
     {
 #if OPENTHREAD_FTD
         if (IsFullThreadDevice())
@@ -561,7 +582,7 @@
     }
 
 exit:
-    return error;
+    return;
 }
 
 uint32_t Mle::GetAttachStartDelay(void) const
@@ -601,8 +622,8 @@
         delay += jitter;
     }
 
-    otLogNoteMle("Attach attempt %d unsuccessful, will try again in %u.%03u seconds", mAttachCounter, delay / 1000,
-                 delay % 1000);
+    LogNote("Attach attempt %d unsuccessful, will try again in %u.%03u seconds", mAttachCounter, delay / 1000,
+            delay % 1000);
 
 exit:
     return delay;
@@ -620,12 +641,6 @@
 
 void Mle::SetStateDetached(void)
 {
-#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-    if (Get<Mac::Mac>().IsCslEnabled())
-    {
-        IgnoreError(Get<Radio>().EnableCsl(0, GetParent().GetRloc16(), &GetParent().GetExtAddress()));
-    }
-#endif
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
     Get<BackboneRouter::Local>().Reset();
 #endif
@@ -655,6 +670,9 @@
 #if OPENTHREAD_FTD
     Get<Ip6::Mpl>().SetTimerExpirations(0);
 #endif
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+    Get<Mac::Mac>().UpdateCsl();
+#endif
 }
 
 void Mle::SetStateChild(uint16_t aRloc16)
@@ -677,7 +695,7 @@
 #if OPENTHREAD_FTD
     if (IsFullThreadDevice())
     {
-        Get<MleRouter>().HandleChildStart(mParentRequestMode);
+        Get<MleRouter>().HandleChildStart(mAttachMode);
     }
 #endif
 
@@ -693,18 +711,19 @@
     UpdateParentSearchState();
 #endif
 
+    if ((mPreviousParentRloc != Mac::kShortAddrInvalid) && (mPreviousParentRloc != mParent.GetRloc16()))
+    {
+        mCounters.mParentChanges++;
+
 #if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
-    InformPreviousParent();
-    mPreviousParentRloc = mParent.GetRloc16();
+        InformPreviousParent();
 #endif
+    }
+
+    mPreviousParentRloc = mParent.GetRloc16();
 
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-    if (Get<Mac::Mac>().IsCslCapable())
-    {
-        uint32_t period = IsRxOnWhenIdle() ? 0 : Get<Mac::Mac>().GetCslPeriod();
-        IgnoreError(Get<Radio>().EnableCsl(period, GetParent().GetRloc16(), &GetParent().GetExtAddress()));
-        ScheduleChildUpdateRequest();
-    }
+    Get<Mac::Mac>().UpdateCsl();
 #endif
 }
 
@@ -751,6 +770,10 @@
     Error      error   = kErrorNone;
     DeviceMode oldMode = mDeviceMode;
 
+#if OPENTHREAD_MTD
+    VerifyOrExit(!aDeviceMode.IsFullThreadDevice(), error = kErrorInvalidArgs);
+#endif
+
     VerifyOrExit(aDeviceMode.IsValid(), error = kErrorInvalidArgs);
     VerifyOrExit(mDeviceMode != aDeviceMode);
     mDeviceMode = aDeviceMode;
@@ -763,7 +786,7 @@
     Get<Utils::Otns>().EmitDeviceMode(mDeviceMode);
 #endif
 
-    otLogNoteMle("Mode 0x%02x -> 0x%02x [%s]", oldMode.Get(), mDeviceMode.Get(), mDeviceMode.ToString().AsCString());
+    LogNote("Mode 0x%02x -> 0x%02x [%s]", oldMode.Get(), mDeviceMode.Get(), mDeviceMode.ToString().AsCString());
 
     IgnoreError(Store());
 
@@ -775,7 +798,7 @@
     case kRoleDetached:
         mAttachCounter = 0;
         SetStateDetached();
-        IgnoreError(BecomeChild(kAttachAny));
+        Attach(kAnyPartition);
         break;
 
     case kRoleChild:
@@ -806,7 +829,7 @@
     Get<Notifier>().Signal(kEventThreadLinkLocalAddrChanged);
 }
 
-void Mle::SetMeshLocalPrefix(const MeshLocalPrefix &aMeshLocalPrefix)
+void Mle::SetMeshLocalPrefix(const Ip6::NetworkPrefix &aMeshLocalPrefix)
 {
     VerifyOrExit(GetMeshLocalPrefix() != aMeshLocalPrefix,
                  Get<Notifier>().SignalIfFirst(kEventThreadMeshLocalAddrChanged));
@@ -888,17 +911,20 @@
 #endif
 
 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-
-    for (Ip6::Netif::UnicastAddress &serviceAloc : mServiceAlocs)
+    for (ServiceAloc &serviceAloc : mServiceAlocs)
     {
-        if (serviceAloc.GetAddress().GetIid().GetLocator() != Mac::kShortAddrInvalid)
+        if (serviceAloc.IsInUse())
         {
             Get<ThreadNetif>().RemoveUnicastAddress(serviceAloc);
-            serviceAloc.GetAddress().SetPrefix(GetMeshLocalPrefix());
+        }
+
+        serviceAloc.ApplyMeshLocalPrefix(GetMeshLocalPrefix());
+
+        if (serviceAloc.IsInUse())
+        {
             Get<ThreadNetif>().AddUnicastAddress(serviceAloc);
         }
     }
-
 #endif
 
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
@@ -921,7 +947,7 @@
 
     if (aRloc16 != oldRloc16)
     {
-        otLogNoteMle("RLOC16 %04x -> %04x", oldRloc16, aRloc16);
+        LogNote("RLOC16 %04x -> %04x", oldRloc16, aRloc16);
     }
 
     if (Get<ThreadNetif>().HasUnicastAddress(mMeshLocal16) &&
@@ -1005,249 +1031,12 @@
 
 const LeaderData &Mle::GetLeaderData(void)
 {
-    mLeaderData.SetDataVersion(Get<NetworkData::Leader>().GetVersion());
-    mLeaderData.SetStableDataVersion(Get<NetworkData::Leader>().GetStableVersion());
+    mLeaderData.SetDataVersion(Get<NetworkData::Leader>().GetVersion(NetworkData::kFullSet));
+    mLeaderData.SetStableDataVersion(Get<NetworkData::Leader>().GetVersion(NetworkData::kStableSubset));
 
     return mLeaderData;
 }
 
-Message *Mle::NewMleMessage(void)
-{
-    Message *         message;
-    Message::Settings settings(Message::kNoLinkSecurity, Message::kPriorityNet);
-
-    message = mSocket.NewMessage(0, settings);
-    VerifyOrExit(message != nullptr);
-
-    message->SetSubType(Message::kSubTypeMleGeneral);
-
-exit:
-    return message;
-}
-
-Error Mle::AppendHeader(Message &aMessage, Command aCommand)
-{
-    Error  error = kErrorNone;
-    Header header;
-
-    header.Init();
-
-    if (aCommand == kCommandDiscoveryRequest || aCommand == kCommandDiscoveryResponse)
-    {
-        header.SetSecuritySuite(Header::kNoSecurity);
-    }
-    else
-    {
-        header.SetKeyIdMode2();
-    }
-
-    header.SetCommand(aCommand);
-
-    SuccessOrExit(error = aMessage.AppendBytes(&header, header.GetLength()));
-
-exit:
-    return error;
-}
-
-Error Mle::AppendSourceAddress(Message &aMessage) const
-{
-    return Tlv::Append<SourceAddressTlv>(aMessage, GetRloc16());
-}
-
-Error Mle::AppendStatus(Message &aMessage, StatusTlv::Status aStatus)
-{
-    return Tlv::Append<StatusTlv>(aMessage, aStatus);
-}
-
-Error Mle::AppendMode(Message &aMessage, DeviceMode aMode)
-{
-    return Tlv::Append<ModeTlv>(aMessage, aMode.Get());
-}
-
-Error Mle::AppendTimeout(Message &aMessage, uint32_t aTimeout)
-{
-    return Tlv::Append<TimeoutTlv>(aMessage, aTimeout);
-}
-
-Error Mle::AppendChallenge(Message &aMessage, const Challenge &aChallenge)
-{
-    return Tlv::Append<ChallengeTlv>(aMessage, aChallenge.mBuffer, aChallenge.mLength);
-}
-
-Error Mle::AppendChallenge(Message &aMessage, const uint8_t *aChallenge, uint8_t aChallengeLength)
-{
-    return Tlv::Append<ChallengeTlv>(aMessage, aChallenge, aChallengeLength);
-}
-
-Error Mle::AppendResponse(Message &aMessage, const Challenge &aResponse)
-{
-    return Tlv::Append<ResponseTlv>(aMessage, aResponse.mBuffer, aResponse.mLength);
-}
-
-Error Mle::ReadChallengeOrResponse(const Message &aMessage, uint8_t aTlvType, Challenge &aBuffer)
-{
-    Error    error;
-    uint16_t offset;
-    uint16_t length;
-
-    SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, aTlvType, offset, length));
-    VerifyOrExit(length >= kMinChallengeSize, error = kErrorParse);
-
-    if (length > kMaxChallengeSize)
-    {
-        length = kMaxChallengeSize;
-    }
-
-    aMessage.ReadBytes(offset, aBuffer.mBuffer, length);
-    aBuffer.mLength = static_cast<uint8_t>(length);
-
-exit:
-    return error;
-}
-
-Error Mle::ReadChallenge(const Message &aMessage, Challenge &aChallenge)
-{
-    return ReadChallengeOrResponse(aMessage, Tlv::kChallenge, aChallenge);
-}
-
-Error Mle::ReadResponse(const Message &aMessage, Challenge &aResponse)
-{
-    return ReadChallengeOrResponse(aMessage, Tlv::kResponse, aResponse);
-}
-
-Error Mle::AppendLinkFrameCounter(Message &aMessage)
-{
-    uint32_t counter;
-
-    // When including Link-layer Frame Counter TLV in an MLE message
-    // the value is set to the maximum MAC frame counter on all
-    // supported radio links. All radio links must also start using
-    // the same counter value as the value included in the TLV.
-
-    counter = Get<KeyManager>().GetMaximumMacFrameCounter();
-
-#if OPENTHREAD_CONFIG_MULTI_RADIO
-    Get<KeyManager>().SetAllMacFrameCounters(counter);
-#endif
-
-    return Tlv::Append<LinkFrameCounterTlv>(aMessage, counter);
-}
-
-Error Mle::AppendMleFrameCounter(Message &aMessage)
-{
-    return Tlv::Append<MleFrameCounterTlv>(aMessage, Get<KeyManager>().GetMleFrameCounter());
-}
-
-Error Mle::ReadFrameCounters(const Message &aMessage, uint32_t &aLinkFrameCounter, uint32_t &aMleFrameCounter) const
-{
-    Error error;
-
-    SuccessOrExit(error = Tlv::Find<LinkFrameCounterTlv>(aMessage, aLinkFrameCounter));
-
-    switch (Tlv::Find<MleFrameCounterTlv>(aMessage, aMleFrameCounter))
-    {
-    case kErrorNone:
-        break;
-    case kErrorNotFound:
-        aMleFrameCounter = aLinkFrameCounter;
-        break;
-    default:
-        error = kErrorParse;
-        break;
-    }
-
-exit:
-    return error;
-}
-
-Error Mle::AppendAddress16(Message &aMessage, uint16_t aRloc16)
-{
-    return Tlv::Append<Address16Tlv>(aMessage, aRloc16);
-}
-
-Error Mle::AppendLeaderData(Message &aMessage)
-{
-    LeaderDataTlv leaderDataTlv;
-
-    mLeaderData.SetDataVersion(Get<NetworkData::Leader>().GetVersion());
-    mLeaderData.SetStableDataVersion(Get<NetworkData::Leader>().GetStableVersion());
-
-    leaderDataTlv.Init();
-    leaderDataTlv.Set(mLeaderData);
-
-    return leaderDataTlv.AppendTo(aMessage);
-}
-
-Error Mle::ReadLeaderData(const Message &aMessage, LeaderData &aLeaderData)
-{
-    Error         error;
-    LeaderDataTlv leaderDataTlv;
-
-    SuccessOrExit(error = Tlv::FindTlv(aMessage, leaderDataTlv));
-    VerifyOrExit(leaderDataTlv.IsValid(), error = kErrorParse);
-    leaderDataTlv.Get(aLeaderData);
-
-exit:
-    return error;
-}
-
-Error Mle::AppendNetworkData(Message &aMessage, bool aStableOnly)
-{
-    Error   error = kErrorNone;
-    uint8_t networkData[NetworkData::NetworkData::kMaxSize];
-    uint8_t length;
-
-    VerifyOrExit(!mRetrieveNewNetworkData, error = kErrorInvalidState);
-
-    length = sizeof(networkData);
-    IgnoreError(Get<NetworkData::Leader>().CopyNetworkData(aStableOnly, networkData, length));
-
-    error = Tlv::Append<NetworkDataTlv>(aMessage, networkData, length);
-
-exit:
-    return error;
-}
-
-Error Mle::AppendTlvRequest(Message &aMessage, const uint8_t *aTlvs, uint8_t aTlvsLength)
-{
-    return Tlv::Append<TlvRequestTlv>(aMessage, aTlvs, aTlvsLength);
-}
-
-Error Mle::FindTlvRequest(const Message &aMessage, RequestedTlvs &aRequestedTlvs)
-{
-    Error    error;
-    uint16_t offset;
-    uint16_t length;
-
-    SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Tlv::kTlvRequest, offset, length));
-
-    if (length > sizeof(aRequestedTlvs.mTlvs))
-    {
-        length = sizeof(aRequestedTlvs.mTlvs);
-    }
-
-    aMessage.ReadBytes(offset, aRequestedTlvs.mTlvs, length);
-    aRequestedTlvs.mNumTlvs = static_cast<uint8_t>(length);
-
-exit:
-    return error;
-}
-
-Error Mle::AppendScanMask(Message &aMessage, uint8_t aScanMask)
-{
-    return Tlv::Append<ScanMaskTlv>(aMessage, aScanMask);
-}
-
-Error Mle::AppendLinkMargin(Message &aMessage, uint8_t aLinkMargin)
-{
-    return Tlv::Append<LinkMarginTlv>(aMessage, aLinkMargin);
-}
-
-Error Mle::AppendVersion(Message &aMessage)
-{
-    return Tlv::Append<VersionTlv>(aMessage, kThreadVersion);
-}
-
 bool Mle::HasUnregisteredAddress(void)
 {
     bool retval = false;
@@ -1276,205 +1065,7 @@
     return retval;
 }
 
-Error Mle::AppendAddressRegistration(Message &aMessage, AddressRegistrationMode aMode)
-{
-    Error                    error = kErrorNone;
-    Tlv                      tlv;
-    AddressRegistrationEntry entry;
-    Lowpan::Context          context;
-    uint8_t                  length      = 0;
-    uint8_t                  counter     = 0;
-    uint16_t                 startOffset = aMessage.GetLength();
-#if OPENTHREAD_CONFIG_DUA_ENABLE
-    Ip6::Address domainUnicastAddress;
-#endif
-
-    tlv.SetType(Tlv::kAddressRegistration);
-    SuccessOrExit(error = aMessage.Append(tlv));
-
-    // Prioritize ML-EID
-    entry.SetContextId(kMeshLocalPrefixContextId);
-    entry.SetIid(GetMeshLocal64().GetIid());
-    SuccessOrExit(error = aMessage.AppendBytes(&entry, entry.GetLength()));
-    length += entry.GetLength();
-
-    // Continue to append the other addresses if not `kAppendMeshLocalOnly` mode
-    VerifyOrExit(aMode != kAppendMeshLocalOnly);
-    counter++;
-
-#if OPENTHREAD_CONFIG_DUA_ENABLE
-    // Cache Domain Unicast Address.
-    domainUnicastAddress = Get<DuaManager>().GetDomainUnicastAddress();
-
-    if (Get<ThreadNetif>().HasUnicastAddress(domainUnicastAddress))
-    {
-        SuccessOrAssert(Get<NetworkData::Leader>().GetContext(domainUnicastAddress, context));
-
-        // Prioritize DUA, compressed entry
-        entry.SetContextId(context.mContextId);
-        entry.SetIid(domainUnicastAddress.GetIid());
-        SuccessOrExit(error = aMessage.AppendBytes(&entry, entry.GetLength()));
-        length += entry.GetLength();
-        counter++;
-    }
-#endif // OPENTHREAD_CONFIG_DUA_ENABLE
-
-    for (const Ip6::Netif::UnicastAddress &addr : Get<ThreadNetif>().GetUnicastAddresses())
-    {
-        if (addr.GetAddress().IsLinkLocal() || IsRoutingLocator(addr.GetAddress()) ||
-            IsAnycastLocator(addr.GetAddress()) || addr.GetAddress() == GetMeshLocal64())
-        {
-            continue;
-        }
-
-#if OPENTHREAD_CONFIG_DUA_ENABLE
-        // Skip DUA that was already appended above.
-        if (addr.GetAddress() == domainUnicastAddress)
-        {
-            continue;
-        }
-#endif
-
-        if (Get<NetworkData::Leader>().GetContext(addr.GetAddress(), context) == kErrorNone)
-        {
-            // compressed entry
-            entry.SetContextId(context.mContextId);
-            entry.SetIid(addr.GetAddress().GetIid());
-        }
-        else
-        {
-            // uncompressed entry
-            entry.SetUncompressed();
-            entry.SetIp6Address(addr.GetAddress());
-        }
-
-        SuccessOrExit(error = aMessage.AppendBytes(&entry, entry.GetLength()));
-        length += entry.GetLength();
-        counter++;
-        // only continue to append if there is available entry.
-        VerifyOrExit(counter < OPENTHREAD_CONFIG_MLE_IP_ADDRS_TO_REGISTER);
-    }
-
-    // Append external multicast addresses.  For sleepy end device,
-    // register all external multicast addresses with the parent for
-    // indirect transmission. Since Thread 1.2, non-sleepy MED should
-    // also register external multicast addresses of scope larger than
-    // realm with a 1.2 or higher parent.
-    if (!IsRxOnWhenIdle()
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-        || !GetParent().IsThreadVersion1p1()
-#endif
-    )
-    {
-        for (const Ip6::Netif::MulticastAddress &addr : Get<ThreadNetif>().IterateExternalMulticastAddresses())
-        {
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-            // For Thread 1.2 MED, skip multicast address with scope not
-            // larger than realm local when registering.
-            if (IsRxOnWhenIdle() && !addr.GetAddress().IsMulticastLargerThanRealmLocal())
-            {
-                continue;
-            }
-#endif
-
-            entry.SetUncompressed();
-            entry.SetIp6Address(addr.GetAddress());
-            SuccessOrExit(error = aMessage.AppendBytes(&entry, entry.GetLength()));
-            length += entry.GetLength();
-
-            counter++;
-            // only continue to append if there is available entry.
-            VerifyOrExit(counter < OPENTHREAD_CONFIG_MLE_IP_ADDRS_TO_REGISTER);
-        }
-    }
-
-exit:
-
-    if (error == kErrorNone && length > 0)
-    {
-        tlv.SetLength(length);
-        aMessage.Write(startOffset, tlv);
-    }
-
-    return error;
-}
-
-#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-Error Mle::AppendTimeRequest(Message &aMessage)
-{
-    // `TimeRequestTlv` has no value.
-    return Tlv::Append<TimeRequestTlv>(aMessage, nullptr, 0);
-}
-
-Error Mle::AppendTimeParameter(Message &aMessage)
-{
-    TimeParameterTlv tlv;
-
-    tlv.Init();
-    tlv.SetTimeSyncPeriod(Get<TimeSync>().GetTimeSyncPeriod());
-    tlv.SetXtalThreshold(Get<TimeSync>().GetXtalThreshold());
-
-    return tlv.AppendTo(aMessage);
-}
-
-Error Mle::AppendXtalAccuracy(Message &aMessage)
-{
-    return Tlv::Append<XtalAccuracyTlv>(aMessage, otPlatTimeGetXtalAccuracy());
-}
-#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-
-Error Mle::AppendActiveTimestamp(Message &aMessage)
-{
-    Error                     error     = kErrorNone;
-    const MeshCoP::Timestamp *timestamp = Get<MeshCoP::ActiveDataset>().GetTimestamp();
-
-    VerifyOrExit(timestamp != nullptr);
-    error = Tlv::Append<ActiveTimestampTlv>(aMessage, *timestamp);
-
-exit:
-    return error;
-}
-
-Error Mle::AppendPendingTimestamp(Message &aMessage)
-{
-    Error                     error     = kErrorNone;
-    const MeshCoP::Timestamp *timestamp = Get<MeshCoP::PendingDataset>().GetTimestamp();
-
-    VerifyOrExit(timestamp != nullptr && timestamp->GetSeconds() != 0);
-    error = Tlv::Append<PendingTimestampTlv>(aMessage, *timestamp);
-
-exit:
-    return error;
-}
-
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-Error Mle::AppendCslChannel(Message &aMessage)
-{
-    Error         error = kErrorNone;
-    CslChannelTlv cslChannel;
-
-    // In current implementation, it's allowed to set CSL Channel unspecified. As `0` is not valid for Channel value
-    // in CSL Channel TLV, if CSL channel is not specified, we don't append CSL Channel TLV.
-    // And on transmitter side, it would also set CSL Channel for the child to `0` if it doesn't find a CSL Channel
-    // TLV.
-    VerifyOrExit(Get<Mac::Mac>().IsCslChannelSpecified());
-
-    cslChannel.Init();
-    cslChannel.SetChannelPage(0);
-    cslChannel.SetChannel(Get<Mac::Mac>().GetCslChannel());
-
-    SuccessOrExit(error = aMessage.Append(cslChannel));
-
-exit:
-    return error;
-}
-
-Error Mle::AppendCslTimeout(Message &aMessage)
-{
-    OT_ASSERT(Get<Mac::Mac>().IsCslEnabled());
-    return Tlv::Append<CslTimeoutTlv>(aMessage, mCslTimeout == 0 ? mTimeout : mCslTimeout);
-}
-
 void Mle::SetCslTimeout(uint32_t aTimeout)
 {
     VerifyOrExit(mCslTimeout != aTimeout);
@@ -1491,24 +1082,6 @@
 exit:
     return;
 }
-#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-
-#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
-Error Mle::AppendCslClockAccuracy(Message &aMessage)
-{
-    Error               error = kErrorNone;
-    CslClockAccuracyTlv cslClockAccuracy;
-
-    cslClockAccuracy.Init();
-
-    cslClockAccuracy.SetCslClockAccuracy(Get<Radio>().GetCslAccuracy());
-    cslClockAccuracy.SetCslUncertainty(Get<Radio>().GetCslClockUncertainty());
-
-    SuccessOrExit(error = aMessage.Append(cslClockAccuracy));
-
-exit:
-    return error;
-}
 #endif
 
 void Mle::HandleNotifierEvents(Events aEvents)
@@ -1525,8 +1098,7 @@
             // addresses.
 
             mAddressRegistrationMode = kAppendAllAddresses;
-            mChildUpdateRequestState = kChildUpdateRequestPending;
-            ScheduleMessageTransmissionTimer();
+            ScheduleChildUpdateRequest();
         }
     }
 
@@ -1543,8 +1115,7 @@
 
         if (IsChild() && !IsFullThreadDevice())
         {
-            mChildUpdateRequestState = kChildUpdateRequestPending;
-            ScheduleMessageTransmissionTimer();
+            ScheduleChildUpdateRequest();
         }
     }
 
@@ -1561,8 +1132,7 @@
                  ))
 
         {
-            mChildUpdateRequestState = kChildUpdateRequestPending;
-            ScheduleMessageTransmissionTimer();
+            ScheduleChildUpdateRequest();
         }
     }
 
@@ -1578,8 +1148,7 @@
         {
             if (!aEvents.Contains(kEventThreadRoleChanged))
             {
-                mChildUpdateRequestState = kChildUpdateRequestPending;
-                ScheduleMessageTransmissionTimer();
+                ScheduleChildUpdateRequest();
             }
         }
 
@@ -1619,107 +1188,218 @@
 }
 
 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-void Mle::UpdateServiceAlocs(void)
+
+Mle::ServiceAloc::ServiceAloc(void)
 {
-    uint16_t              rloc               = GetRloc16();
-    uint16_t              serviceAloc        = 0;
-    uint8_t               serviceId          = 0;
-    NetworkData::Iterator serviceIterator    = NetworkData::kIteratorInit;
-    size_t                serviceAlocsLength = OT_ARRAY_LENGTH(mServiceAlocs);
-    size_t                i                  = 0;
+    InitAsThreadOriginRealmLocalScope();
+    GetAddress().GetIid().SetToLocator(kNotInUse);
+}
 
-    VerifyOrExit(!IsDisabled());
+Mle::ServiceAloc *Mle::FindInServiceAlocs(uint16_t aAloc16)
+{
+    // Search in `mServiceAlocs` for an entry matching `aAloc16`.
+    // Can be used with `aAloc16 = ServerAloc::kNotInUse` to find
+    // an unused entry in the array.
 
-    // First remove all alocs which are no longer necessary, to free up space in mServiceAlocs
-    for (i = 0; i < serviceAlocsLength; i++)
+    ServiceAloc *match = nullptr;
+
+    for (ServiceAloc &serviceAloc : mServiceAlocs)
     {
-        serviceAloc = mServiceAlocs[i].GetAddress().GetIid().GetLocator();
-
-        if ((serviceAloc != Mac::kShortAddrInvalid) &&
-            (!Get<NetworkData::Leader>().ContainsService(Mle::ServiceIdFromAloc(serviceAloc), rloc)))
+        if (serviceAloc.GetAloc16() == aAloc16)
         {
-            Get<ThreadNetif>().RemoveUnicastAddress(mServiceAlocs[i]);
-            mServiceAlocs[i].GetAddress().GetIid().SetLocator(Mac::kShortAddrInvalid);
+            match = &serviceAloc;
+            break;
         }
     }
 
-    // Now add any missing service alocs which should be there, if there is enough space in mServiceAlocs
-    while (Get<NetworkData::Leader>().GetNextServiceId(serviceIterator, rloc, serviceId) == kErrorNone)
-    {
-        for (i = 0; i < serviceAlocsLength; i++)
-        {
-            serviceAloc = mServiceAlocs[i].GetAddress().GetIid().GetLocator();
+    return match;
+}
 
-            if ((serviceAloc != Mac::kShortAddrInvalid) && (Mle::ServiceIdFromAloc(serviceAloc) == serviceId))
+void Mle::UpdateServiceAlocs(void)
+{
+    NetworkData::Iterator      iterator;
+    NetworkData::ServiceConfig service;
+
+    VerifyOrExit(!IsDisabled());
+
+    // First remove all ALOCs which are no longer in the Network
+    // Data to free up space in `mServiceAlocs` array.
+
+    for (ServiceAloc &serviceAloc : mServiceAlocs)
+    {
+        bool found = false;
+
+        if (!serviceAloc.IsInUse())
+        {
+            continue;
+        }
+
+        iterator = NetworkData::kIteratorInit;
+
+        while (Get<NetworkData::Leader>().GetNextService(iterator, GetRloc16(), service) == kErrorNone)
+        {
+            if (service.mServiceId == ServiceIdFromAloc(serviceAloc.GetAloc16()))
             {
+                found = true;
                 break;
             }
         }
 
-        if (i >= serviceAlocsLength)
+        if (!found)
         {
-            // Service Aloc is not there, but it should be. Lets add it into first empty space
-            for (i = 0; i < serviceAlocsLength; i++)
-            {
-                serviceAloc = mServiceAlocs[i].GetAddress().GetIid().GetLocator();
+            Get<ThreadNetif>().RemoveUnicastAddress(serviceAloc);
+            serviceAloc.MarkAsNotInUse();
+        }
+    }
 
-                if (serviceAloc == Mac::kShortAddrInvalid)
-                {
-                    SuccessOrExit(GetServiceAloc(serviceId, mServiceAlocs[i].GetAddress()));
-                    Get<ThreadNetif>().AddUnicastAddress(mServiceAlocs[i]);
-                    break;
-                }
-            }
+    // Now add any new ALOCs if there is space in `mServiceAlocs`.
+
+    iterator = NetworkData::kIteratorInit;
+
+    while (Get<NetworkData::Leader>().GetNextService(iterator, GetRloc16(), service) == kErrorNone)
+    {
+        uint16_t aloc16 = ServiceAlocFromId(service.mServiceId);
+
+        if (FindInServiceAlocs(aloc16) == nullptr)
+        {
+            // No matching ALOC in `mServiceAlocs`, so we try to add it.
+            ServiceAloc *newServiceAloc = FindInServiceAlocs(ServiceAloc::kNotInUse);
+
+            VerifyOrExit(newServiceAloc != nullptr);
+            newServiceAloc->SetAloc16(aloc16);
+            Get<ThreadNetif>().AddUnicastAddress(*newServiceAloc);
         }
     }
 
 exit:
     return;
 }
-#endif
+
+#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
 
 void Mle::HandleAttachTimer(Timer &aTimer)
 {
     aTimer.Get<Mle>().HandleAttachTimer();
 }
 
-void Mle::HandleAttachTimer(void)
+Error Mle::DetermineParentRequestType(ParentRequestType &aType) const
 {
-    uint32_t delay          = 0;
-    bool     shouldAnnounce = true;
+    // This method determines the Parent Request type to use during an
+    // attach cycle based on `mAttachMode`, `mAttachCounter` and
+    // `mParentRequestCounter`. This method MUST be used while in
+    // `kAttachStateParentRequest` state.
+    //
+    // On success it returns `kErrorNone` and sets `aType`. It returns
+    // `kErrorNotFound` to indicate that device can now transition
+    // from `kAttachStateParentRequest` state (has already sent the
+    // required number of Parent Requests for this attach attempt
+    // cycle).
 
-    if (mAttachState == kAttachStateParentRequestRouter || mAttachState == kAttachStateParentRequestReed ||
-        (mAttachState == kAttachStateAnnounce && !HasMoreChannelsToAnnouce()))
+    Error error = kErrorNone;
+
+    OT_ASSERT(mAttachState == kAttachStateParentRequest);
+
+    aType = kToRoutersAndReeds;
+
+    // If device is not yet attached, `mAttachCounter` will track the
+    // number of attach attempt cycles so far, starting from one for
+    // the first attempt. `mAttachCounter` will be zero if device is
+    // already attached. Examples of this situation include a leader or
+    // router trying to attach to a better partition, or a child trying
+    // to find a better parent.
+
+    if ((mAttachCounter <= 1) && (mAttachMode != kBetterParent))
     {
-        uint8_t linkQuality;
+        VerifyOrExit(mParentRequestCounter <= kFirstAttachCycleTotalParentRequests, error = kErrorNotFound);
 
-        linkQuality = mParentCandidate.GetLinkInfo().GetLinkQuality();
+        // During reattach to the same partition all the Parent
+        // Request are sent to Routers and REEDs.
 
-        if (linkQuality > mParentCandidate.GetLinkQualityOut())
+        if ((mAttachMode != kSamePartition) && (mAttachMode != kSamePartitionRetry) &&
+            (mParentRequestCounter <= kFirstAttachCycleNumParentRequestToRouters))
         {
-            linkQuality = mParentCandidate.GetLinkQualityOut();
+            aType = kToRouters;
+        }
+    }
+    else
+    {
+        VerifyOrExit(mParentRequestCounter <= kNextAttachCycleTotalParentRequests, error = kErrorNotFound);
+
+        if (mParentRequestCounter <= kNextAttachCycleNumParentRequestToRouters)
+        {
+            aType = kToRouters;
+        }
+    }
+
+exit:
+    return error;
+}
+
+bool Mle::HasAcceptableParentCandidate(void) const
+{
+    bool              hasAcceptableParent = false;
+    LinkQuality       linkQuality;
+    ParentRequestType parentReqType;
+
+    VerifyOrExit(mParentCandidate.IsStateParentResponse());
+
+    switch (mAttachState)
+    {
+    case kAttachStateAnnounce:
+        VerifyOrExit(!HasMoreChannelsToAnnouce());
+        break;
+
+    case kAttachStateParentRequest:
+        SuccessOrAssert(DetermineParentRequestType(parentReqType));
+
+        if (parentReqType == kToRouters)
+        {
+            // If we cannot find a parent with best link quality (3) when
+            // in Parent Request was sent to routers, we will keep the
+            // candidate and forward to REED stage to potentially find a
+            // better parent.
+            linkQuality = OT_MIN(mParentCandidate.GetLinkInfo().GetLinkQuality(), mParentCandidate.GetLinkQualityOut());
+            VerifyOrExit(linkQuality == kLinkQuality3);
         }
 
+        break;
+
+    default:
+        ExitNow();
+    }
+
+    if (IsChild())
+    {
         // If already attached, accept the parent candidate if
         // we are trying to attach to a better partition or if a
         // Parent Response was also received from the current parent
         // to which the device is attached. This ensures that the
         // new parent candidate is compared with the current parent
         // and that it is indeed preferred over the current one.
-        // If we are in kAttachStateParentRequestRouter and cannot
-        // find a parent with best link quality(3), we will keep
-        // the candidate and forward to REED stage to find a better
-        // parent.
 
-        if ((linkQuality == 3 || mAttachState != kAttachStateParentRequestRouter) &&
-            mParentCandidate.IsStateParentResponse() &&
-            (!IsChild() || mReceivedResponseFromParent || mParentRequestMode == kAttachBetter) &&
-            SendChildIdRequest() == kErrorNone)
-        {
-            SetAttachState(kAttachStateChildIdRequest);
-            delay = kParentRequestReedTimeout;
-            ExitNow();
-        }
+        VerifyOrExit(mReceivedResponseFromParent || (mAttachMode == kBetterPartition));
+    }
+
+    hasAcceptableParent = true;
+
+exit:
+    return hasAcceptableParent;
+}
+
+void Mle::HandleAttachTimer(void)
+{
+    uint32_t          delay          = 0;
+    bool              shouldAnnounce = true;
+    ParentRequestType type;
+
+    // First, check if we are waiting to receive parent responses and
+    // found an acceptable parent candidate.
+
+    if (HasAcceptableParentCandidate() && (SendChildIdRequest() == kErrorNone))
+    {
+        SetAttachState(kAttachStateChildIdRequest);
+        delay = kParentRequestReedTimeout;
+        ExitNow();
     }
 
     switch (mAttachState)
@@ -1733,46 +1413,26 @@
         break;
 
     case kAttachStateStart:
-        if (mAttachCounter > 0)
-        {
-            otLogNoteMle("Attempt to attach - attempt %d, %s %s", mAttachCounter,
-                         AttachModeToString(mParentRequestMode), ReattachStateToString(mReattachState));
-        }
-        else
-        {
-            otLogNoteMle("Attempt to attach - %s %s", AttachModeToString(mParentRequestMode),
-                         ReattachStateToString(mReattachState));
-        }
+        LogNote("Attach attempt %d, %s %s", mAttachCounter, AttachModeToString(mAttachMode),
+                ReattachStateToString(mReattachState));
 
-        SetAttachState(kAttachStateParentRequestRouter);
+        SetAttachState(kAttachStateParentRequest);
         mParentCandidate.SetState(Neighbor::kStateInvalid);
         mReceivedResponseFromParent = false;
+        mParentRequestCounter       = 0;
         Get<MeshForwarder>().SetRxOnWhenIdle(true);
 
-        // initial MLE Parent Request has both E and R flags set in Scan Mask TLV
-        // during reattach when losing connectivity.
-        if (mParentRequestMode == kAttachSame1 || mParentRequestMode == kAttachSame2)
+        OT_FALL_THROUGH;
+
+    case kAttachStateParentRequest:
+        mParentRequestCounter++;
+        if (DetermineParentRequestType(type) == kErrorNone)
         {
-            IgnoreError(SendParentRequest(kParentRequestTypeRoutersAndReeds));
-            delay = kParentRequestReedTimeout;
-        }
-        // initial MLE Parent Request has only R flag set in Scan Mask TLV for
-        // during initial attach or downgrade process
-        else
-        {
-            IgnoreError(SendParentRequest(kParentRequestTypeRouters));
-            delay = kParentRequestRouterTimeout;
+            SendParentRequest(type);
+            delay = (type == kToRouters) ? kParentRequestRouterTimeout : kParentRequestReedTimeout;
+            break;
         }
 
-        break;
-
-    case kAttachStateParentRequestRouter:
-        SetAttachState(kAttachStateParentRequestReed);
-        IgnoreError(SendParentRequest(kParentRequestTypeRoutersAndReeds));
-        delay = kParentRequestReedTimeout;
-        break;
-
-    case kAttachStateParentRequestReed:
         shouldAnnounce = PrepareAnnounceState();
 
         if (shouldAnnounce)
@@ -1786,7 +1446,7 @@
             // (with `mAnnounceDelay` wait between them).
 
             SetAttachState(kAttachStateAnnounce);
-            IgnoreError(SendParentRequest(kParentRequestTypeRoutersAndReeds));
+            SendParentRequest(kToRoutersAndReeds);
             mAnnounceChannel = Mac::ChannelMask::kChannelIteratorFirst;
             delay            = mAnnounceDelay;
             break;
@@ -1825,9 +1485,9 @@
     Mac::ChannelMask channelMask;
 
     VerifyOrExit(!IsChild() && (mReattachState == kReattachStop) &&
-                 (Get<MeshCoP::ActiveDataset>().IsPartiallyComplete() || !IsFullThreadDevice()));
+                 (Get<MeshCoP::ActiveDatasetManager>().IsPartiallyComplete() || !IsFullThreadDevice()));
 
-    if (Get<MeshCoP::ActiveDataset>().GetChannelMask(channelMask) != kErrorNone)
+    if (Get<MeshCoP::ActiveDatasetManager>().GetChannelMask(channelMask) != kErrorNone)
     {
         channelMask = Get<Mac::Mac>().GetSupportedChannelMask();
     }
@@ -1851,9 +1511,9 @@
 
     if (mReattachState == kReattachActive)
     {
-        if (Get<MeshCoP::PendingDataset>().Restore() == kErrorNone)
+        if (Get<MeshCoP::PendingDatasetManager>().Restore() == kErrorNone)
         {
-            IgnoreError(Get<MeshCoP::PendingDataset>().ApplyConfiguration());
+            IgnoreError(Get<MeshCoP::PendingDatasetManager>().ApplyConfiguration());
             mReattachState = kReattachPending;
             SetAttachState(kAttachStateStart);
             delay = 1 + Random::NonCrypto::GetUint32InRange(0, kAttachStartJitter);
@@ -1866,14 +1526,15 @@
     else if (mReattachState == kReattachPending)
     {
         mReattachState = kReattachStop;
-        IgnoreError(Get<MeshCoP::ActiveDataset>().Restore());
+        IgnoreError(Get<MeshCoP::ActiveDatasetManager>().Restore());
     }
 
     VerifyOrExit(mReattachState == kReattachStop);
 
-    switch (mParentRequestMode)
+    switch (mAttachMode)
     {
-    case kAttachAny:
+    case kAnyPartition:
+    case kBetterParent:
         if (!IsChild())
         {
             if (mAlternatePanId != Mac::kPanIdBroadcast)
@@ -1903,16 +1564,16 @@
 
         break;
 
-    case kAttachSame1:
-        IgnoreError(BecomeChild(kAttachSame2));
+    case kSamePartition:
+        Attach(kSamePartitionRetry);
         break;
 
-    case kAttachSame2:
-    case kAttachSameDowngrade:
-        IgnoreError(BecomeChild(kAttachAny));
+    case kSamePartitionRetry:
+    case kDowngradeToReed:
+        Attach(kAnyPartition);
         break;
 
-    case kAttachBetter:
+    case kBetterPartition:
         break;
     }
 
@@ -1927,17 +1588,14 @@
 
 void Mle::HandleDelayedResponseTimer(void)
 {
-    DelayedResponseMetadata metadata;
-    TimeMilli               now          = TimerMilli::GetNow();
-    TimeMilli               nextSendTime = now.GetDistantFuture();
-    Message *               message;
-    Message *               nextMessage;
+    TimeMilli now          = TimerMilli::GetNow();
+    TimeMilli nextSendTime = now.GetDistantFuture();
 
-    for (message = mDelayedResponses.GetHead(); message != nullptr; message = nextMessage)
+    for (Message &message : mDelayedResponses)
     {
-        nextMessage = message->GetNext();
+        DelayedResponseMetadata metadata;
 
-        metadata.ReadFrom(*message);
+        metadata.ReadFrom(message);
 
         if (now < metadata.mSendTime)
         {
@@ -1948,37 +1606,8 @@
         }
         else
         {
-            Error error = kErrorNone;
-
-            mDelayedResponses.Dequeue(*message);
-            metadata.RemoveFrom(*message);
-
-            if (message->GetSubType() == Message::kSubTypeMleDataRequest)
-            {
-                error = AppendActiveTimestamp(*message);
-                error = (error == kErrorNone) ? AppendPendingTimestamp(*message) : error;
-            }
-
-            error = (error == kErrorNone) ? SendMessage(*message, metadata.mDestination) : error;
-
-            if (error == kErrorNone)
-            {
-                Log(kMessageSend, kTypeGenericDelayed, metadata.mDestination);
-
-                // Here enters fast poll mode, as for Rx-Off-when-idle device, the enqueued msg should
-                // be Mle Data Request.
-                // Note: Finer-grade check (e.g. message subtype) might be required when deciding whether
-                // or not enters fast poll mode fast poll mode if there are other type of delayed message
-                // for Rx-Off-when-idle device.
-                if (!IsRxOnWhenIdle())
-                {
-                    Get<DataPollSender>().SendFastPolls(DataPollSender::kDefaultFastPolls);
-                }
-            }
-            else
-            {
-                message->Free();
-            }
+            mDelayedResponses.Dequeue(message);
+            SendDelayedResponse(static_cast<TxMessage &>(message), metadata);
         }
     }
 
@@ -1988,51 +1617,66 @@
     }
 }
 
+void Mle::SendDelayedResponse(TxMessage &aMessage, const DelayedResponseMetadata &aMetadata)
+{
+    Error error = kErrorNone;
+
+    aMetadata.RemoveFrom(aMessage);
+
+    if (aMessage.GetSubType() == Message::kSubTypeMleDataRequest)
+    {
+        SuccessOrExit(error = aMessage.AppendActiveTimestampTlv());
+        SuccessOrExit(error = aMessage.AppendPendingTimestampTlv());
+    }
+
+    SuccessOrExit(error = aMessage.SendTo(aMetadata.mDestination));
+
+    Log(kMessageSend, kTypeGenericDelayed, aMetadata.mDestination);
+
+    if (!IsRxOnWhenIdle())
+    {
+        // Start fast poll mode, assuming enqueued msg is MLE Data Request.
+        // Note: Finer-grade check may be required when deciding whether or
+        // not to enter fast poll mode for other type of delayed message.
+
+        Get<DataPollSender>().SendFastPolls(DataPollSender::kDefaultFastPolls);
+    }
+
+exit:
+    FreeMessageOnError(&aMessage, error);
+}
+
 void Mle::RemoveDelayedDataResponseMessage(void)
 {
-    Message *               message = mDelayedResponses.GetHead();
-    DelayedResponseMetadata metadata;
-
-    while (message != nullptr)
-    {
-        metadata.ReadFrom(*message);
-
-        if (message->GetSubType() == Message::kSubTypeMleDataResponse)
-        {
-            mDelayedResponses.DequeueAndFree(*message);
-            Log(kMessageRemoveDelayed, kTypeDataResponse, metadata.mDestination);
-
-            // no more than one multicast MLE Data Response in Delayed Message Queue.
-            break;
-        }
-
-        message = message->GetNext();
-    }
+    RemoveDelayedMessage(Message::kSubTypeMleDataResponse, kTypeDataResponse, nullptr);
 }
 
 void Mle::RemoveDelayedDataRequestMessage(const Ip6::Address &aDestination)
 {
-    for (Message *message = mDelayedResponses.GetHead(); message != nullptr; message = message->GetNext())
+    RemoveDelayedMessage(Message::kSubTypeMleDataRequest, kTypeDataRequest, &aDestination);
+}
+
+void Mle::RemoveDelayedMessage(Message::SubType aSubType, MessageType aMessageType, const Ip6::Address *aDestination)
+{
+    for (Message &message : mDelayedResponses)
     {
         DelayedResponseMetadata metadata;
 
-        metadata.ReadFrom(*message);
+        metadata.ReadFrom(message);
 
-        if (message->GetSubType() == Message::kSubTypeMleDataRequest && metadata.mDestination == aDestination)
+        if ((message.GetSubType() == aSubType) &&
+            ((aDestination == nullptr) || (metadata.mDestination == *aDestination)))
         {
-            mDelayedResponses.DequeueAndFree(*message);
-            Log(kMessageRemoveDelayed, kTypeDataRequest, metadata.mDestination);
-
-            // no more than one MLE Data Request for the destination in Delayed Message Queue.
-            break;
+            mDelayedResponses.DequeueAndFree(message);
+            Log(kMessageRemoveDelayed, aMessageType, metadata.mDestination);
         }
     }
 }
 
-Error Mle::SendParentRequest(ParentRequestType aType)
+void Mle::SendParentRequest(ParentRequestType aType)
 {
     Error        error = kErrorNone;
-    Message *    message;
+    TxMessage *  message;
     uint8_t      scanMask = 0;
     Ip6::Address destination;
 
@@ -2040,42 +1684,40 @@
 
     switch (aType)
     {
-    case kParentRequestTypeRouters:
+    case kToRouters:
         scanMask = ScanMaskTlv::kRouterFlag;
         break;
 
-    case kParentRequestTypeRoutersAndReeds:
+    case kToRoutersAndReeds:
         scanMask = ScanMaskTlv::kRouterFlag | ScanMaskTlv::kEndDeviceFlag;
         break;
     }
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    SuccessOrExit(error = AppendHeader(*message, kCommandParentRequest));
-    SuccessOrExit(error = AppendMode(*message, mDeviceMode));
-    SuccessOrExit(error = AppendChallenge(*message, mParentRequestChallenge));
-    SuccessOrExit(error = AppendScanMask(*message, scanMask));
-    SuccessOrExit(error = AppendVersion(*message));
+    VerifyOrExit((message = NewMleMessage(kCommandParentRequest)) != nullptr, error = kErrorNoBufs);
+    SuccessOrExit(error = message->AppendModeTlv(mDeviceMode));
+    SuccessOrExit(error = message->AppendChallengeTlv(mParentRequestChallenge));
+    SuccessOrExit(error = message->AppendScanMaskTlv(scanMask));
+    SuccessOrExit(error = message->AppendVersionTlv());
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-    SuccessOrExit(error = AppendTimeRequest(*message));
+    SuccessOrExit(error = message->AppendTimeRequestTlv());
 #endif
 
     destination.SetToLinkLocalAllRoutersMulticast();
-    SuccessOrExit(error = SendMessage(*message, destination));
+    SuccessOrExit(error = message->SendTo(destination));
 
     switch (aType)
     {
-    case kParentRequestTypeRouters:
+    case kToRouters:
         Log(kMessageSend, kTypeParentRequestToRouters, destination);
         break;
 
-    case kParentRequestTypeRoutersAndReeds:
+    case kToRoutersAndReeds:
         Log(kMessageSend, kTypeParentRequestToRoutersReeds, destination);
         break;
     }
 
 exit:
     FreeMessageOnError(message, error);
-    return error;
 }
 
 void Mle::RequestShorterChildIdRequest(void)
@@ -2092,14 +1734,14 @@
     Error        error   = kErrorNone;
     uint8_t      tlvs[]  = {Tlv::kAddress16, Tlv::kNetworkData, Tlv::kRoute};
     uint8_t      tlvsLen = sizeof(tlvs);
-    Message *    message = nullptr;
+    TxMessage *  message = nullptr;
     Ip6::Address destination;
 
     if (mParent.GetExtAddress() == mParentCandidate.GetExtAddress())
     {
         if (IsChild())
         {
-            otLogInfoMle("Already attached to candidate parent");
+            LogInfo("Already attached to candidate parent");
             ExitNow(error = kErrorAlready);
         }
         else
@@ -2113,32 +1755,30 @@
         }
     }
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    message->SetSubType(Message::kSubTypeMleChildIdRequest);
-    SuccessOrExit(error = AppendHeader(*message, kCommandChildIdRequest));
-    SuccessOrExit(error = AppendResponse(*message, mParentCandidateChallenge));
-    SuccessOrExit(error = AppendLinkFrameCounter(*message));
-    SuccessOrExit(error = AppendMleFrameCounter(*message));
-    SuccessOrExit(error = AppendMode(*message, mDeviceMode));
-    SuccessOrExit(error = AppendTimeout(*message, mTimeout));
-    SuccessOrExit(error = AppendVersion(*message));
+    VerifyOrExit((message = NewMleMessage(kCommandChildIdRequest)) != nullptr, error = kErrorNoBufs);
+    SuccessOrExit(error = message->AppendResponseTlv(mParentCandidateChallenge));
+    SuccessOrExit(error = message->AppendLinkFrameCounterTlv());
+    SuccessOrExit(error = message->AppendMleFrameCounterTlv());
+    SuccessOrExit(error = message->AppendModeTlv(mDeviceMode));
+    SuccessOrExit(error = message->AppendTimeoutTlv(mTimeout));
+    SuccessOrExit(error = message->AppendVersionTlv());
 
     if (!IsFullThreadDevice())
     {
-        SuccessOrExit(error = AppendAddressRegistration(*message, mAddressRegistrationMode));
+        SuccessOrExit(error = message->AppendAddressRegistrationTlv(mAddressRegistrationMode));
 
         // no need to request the last Route64 TLV for MTD
         tlvsLen -= 1;
     }
 
-    SuccessOrExit(error = AppendTlvRequest(*message, tlvs, tlvsLen));
-    SuccessOrExit(error = AppendActiveTimestamp(*message));
-    SuccessOrExit(error = AppendPendingTimestamp(*message));
+    SuccessOrExit(error = message->AppendTlvRequestTlv(tlvs, tlvsLen));
+    SuccessOrExit(error = message->AppendActiveTimestampTlv());
+    SuccessOrExit(error = message->AppendPendingTimestampTlv());
 
     mParentCandidate.SetState(Neighbor::kStateValid);
 
     destination.SetToLinkLocalAddress(mParentCandidate.GetExtAddress());
-    SuccessOrExit(error = SendMessage(*message, destination));
+    SuccessOrExit(error = message->SendTo(destination));
 
     Log(kMessageSend,
         (mAddressRegistrationMode == kAppendMeshLocalOnly) ? kTypeChildIdRequestShort : kTypeChildIdRequest,
@@ -2162,18 +1802,13 @@
                            const uint8_t *     aExtraTlvs,
                            uint8_t             aExtraTlvsLength)
 {
-    OT_UNUSED_VARIABLE(aExtraTlvs);
-    OT_UNUSED_VARIABLE(aExtraTlvsLength);
-
-    Error    error = kErrorNone;
-    Message *message;
+    Error      error = kErrorNone;
+    TxMessage *message;
 
     RemoveDelayedDataRequestMessage(aDestination);
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    message->SetSubType(Message::kSubTypeMleDataRequest);
-    SuccessOrExit(error = AppendHeader(*message, kCommandDataRequest));
-    SuccessOrExit(error = AppendTlvRequest(*message, aTlvs, aTlvsLength));
+    VerifyOrExit((message = NewMleMessage(kCommandDataRequest)) != nullptr, error = kErrorNoBufs);
+    SuccessOrExit(error = message->AppendTlvRequestTlv(aTlvs, aTlvsLength));
 
     if (aExtraTlvs != nullptr && aExtraTlvsLength > 0)
     {
@@ -2182,15 +1817,15 @@
 
     if (aDelay)
     {
-        SuccessOrExit(error = AddDelayedResponse(*message, aDestination, aDelay));
+        SuccessOrExit(error = message->SendAfterDelay(aDestination, aDelay));
         Log(kMessageDelay, kTypeDataRequest, aDestination);
     }
     else
     {
-        SuccessOrExit(error = AppendActiveTimestamp(*message));
-        SuccessOrExit(error = AppendPendingTimestamp(*message));
+        SuccessOrExit(error = message->AppendActiveTimestampTlv());
+        SuccessOrExit(error = message->AppendPendingTimestampTlv());
 
-        SuccessOrExit(error = SendMessage(*message, aDestination));
+        SuccessOrExit(error = message->SendTo(aDestination));
         Log(kMessageSend, kTypeDataRequest, aDestination);
 
         if (!IsRxOnWhenIdle())
@@ -2229,12 +1864,7 @@
 
     case kChildUpdateRequestActive:
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-        // CSL transmitter may respond in next CSL cycle.
-        // This condition IsCslCapable() && !IsRxOnWhenIdle() is used instead of
-        // IsCslEnabled because during transitions SSED -> MED and MED -> SSED
-        // there is a delay in synchronisation of IsRxOnWhenIdle residing in MAC
-        // and in MLE, which causes below datapoll interval to be calculated incorrectly.
-        if (Get<Mac::Mac>().IsCslCapable() && !IsRxOnWhenIdle())
+        if (Get<Mac::Mac>().IsCslEnabled())
         {
             ExitNow(interval = Get<Mac::Mac>().GetCslPeriod() * kUsPerTenSymbols / 1000 +
                                static_cast<uint32_t>(kUnicastRetransmissionDelay));
@@ -2338,16 +1968,21 @@
     return;
 }
 
-Error Mle::SendChildUpdateRequest(void)
+Error Mle::SendChildUpdateRequest(bool aAppendChallenge)
+{
+    return SendChildUpdateRequest(aAppendChallenge, mTimeout);
+}
+
+Error Mle::SendChildUpdateRequest(bool aAppendChallenge, uint32_t aTimeout)
 {
     Error                   error = kErrorNone;
     Ip6::Address            destination;
-    Message *               message = nullptr;
+    TxMessage *             message = nullptr;
     AddressRegistrationMode mode    = kAppendAllAddresses;
 
     if (!mParent.IsStateValidOrRestoring())
     {
-        otLogWarnMle("No valid parent when sending Child Update Request");
+        LogWarn("No valid parent when sending Child Update Request");
         IgnoreError(BecomeDetached());
         ExitNow();
     }
@@ -2355,28 +1990,30 @@
     mChildUpdateRequestState = kChildUpdateRequestActive;
     ScheduleMessageTransmissionTimer();
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    message->SetSubType(Message::kSubTypeMleChildUpdateRequest);
-    SuccessOrExit(error = AppendHeader(*message, kCommandChildUpdateRequest));
-    SuccessOrExit(error = AppendMode(*message, mDeviceMode));
+    VerifyOrExit((message = NewMleMessage(kCommandChildUpdateRequest)) != nullptr, error = kErrorNoBufs);
+    SuccessOrExit(error = message->AppendModeTlv(mDeviceMode));
+
+    if (aAppendChallenge || IsDetached())
+    {
+        mParentRequestChallenge.GenerateRandom();
+        SuccessOrExit(error = message->AppendChallengeTlv(mParentRequestChallenge));
+    }
 
     switch (mRole)
     {
     case kRoleDetached:
-        mParentRequestChallenge.GenerateRandom();
-        SuccessOrExit(error = AppendChallenge(*message, mParentRequestChallenge));
         mode = kAppendMeshLocalOnly;
         break;
 
     case kRoleChild:
-        SuccessOrExit(error = AppendSourceAddress(*message));
-        SuccessOrExit(error = AppendLeaderData(*message));
-        SuccessOrExit(error = AppendTimeout(*message, mTimeout));
+        SuccessOrExit(error = message->AppendSourceAddressTlv());
+        SuccessOrExit(error = message->AppendLeaderDataTlv());
+        SuccessOrExit(error = message->AppendTimeoutTlv(aTimeout));
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
         if (Get<Mac::Mac>().IsCslEnabled())
         {
-            SuccessOrExit(error = AppendCslChannel(*message));
-            SuccessOrExit(error = AppendCslTimeout(*message));
+            SuccessOrExit(error = message->AppendCslChannelTlv());
+            SuccessOrExit(error = message->AppendCslTimeoutTlv());
         }
 #endif
         break;
@@ -2390,11 +2027,11 @@
 
     if (!IsFullThreadDevice())
     {
-        SuccessOrExit(error = AppendAddressRegistration(*message, mode));
+        SuccessOrExit(error = message->AppendAddressRegistrationTlv(mode));
     }
 
     destination.SetToLinkLocalAddress(mParent.GetExtAddress());
-    SuccessOrExit(error = SendMessage(*message, destination));
+    SuccessOrExit(error = message->SendTo(destination));
 
     Log(kMessageSend, kTypeChildUpdateRequestOfParent, destination);
 
@@ -2421,24 +2058,23 @@
 {
     Error        error = kErrorNone;
     Ip6::Address destination;
-    Message *    message;
+    TxMessage *  message;
     bool         checkAddress = false;
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    SuccessOrExit(error = AppendHeader(*message, kCommandChildUpdateResponse));
-    SuccessOrExit(error = AppendSourceAddress(*message));
-    SuccessOrExit(error = AppendLeaderData(*message));
+    VerifyOrExit((message = NewMleMessage(kCommandChildUpdateResponse)) != nullptr, error = kErrorNoBufs);
+    SuccessOrExit(error = message->AppendSourceAddressTlv());
+    SuccessOrExit(error = message->AppendLeaderDataTlv());
 
     for (int i = 0; i < aNumTlvs; i++)
     {
         switch (aTlvs[i])
         {
         case Tlv::kTimeout:
-            SuccessOrExit(error = AppendTimeout(*message, mTimeout));
+            SuccessOrExit(error = message->AppendTimeoutTlv(mTimeout));
             break;
 
         case Tlv::kStatus:
-            SuccessOrExit(error = AppendStatus(*message, StatusTlv::kError));
+            SuccessOrExit(error = message->AppendStatusTlv(StatusTlv::kError));
             break;
 
         case Tlv::kAddressRegistration:
@@ -2449,28 +2085,37 @@
                 // addresses to register we follow up with a "Child Update
                 // Request".
 
-                SuccessOrExit(error = AppendAddressRegistration(*message, kAppendMeshLocalOnly));
+                SuccessOrExit(error = message->AppendAddressRegistrationTlv(kAppendMeshLocalOnly));
                 checkAddress = true;
             }
 
             break;
 
         case Tlv::kResponse:
-            SuccessOrExit(error = AppendResponse(*message, aChallenge));
+            SuccessOrExit(error = message->AppendResponseTlv(aChallenge));
             break;
 
         case Tlv::kLinkFrameCounter:
-            SuccessOrExit(error = AppendLinkFrameCounter(*message));
+            SuccessOrExit(error = message->AppendLinkFrameCounterTlv());
             break;
 
         case Tlv::kMleFrameCounter:
-            SuccessOrExit(error = AppendMleFrameCounter(*message));
+            SuccessOrExit(error = message->AppendMleFrameCounterTlv());
             break;
+
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+        case Tlv::kCslTimeout:
+            if (Get<Mac::Mac>().IsCslEnabled())
+            {
+                SuccessOrExit(error = message->AppendCslTimeoutTlv());
+            }
+            break;
+#endif
         }
     }
 
     destination.SetToLinkLocalAddress(mParent.GetExtAddress());
-    SuccessOrExit(error = SendMessage(*message, destination));
+    SuccessOrExit(error = message->SendTo(destination));
 
     Log(kMessageSend, kTypeChildUpdateResponseOfParent, destination);
 
@@ -2498,16 +2143,15 @@
     Error              error = kErrorNone;
     ChannelTlv         channel;
     MeshCoP::Timestamp activeTimestamp;
-    Message *          message = nullptr;
+    TxMessage *        message = nullptr;
 
     VerifyOrExit(Get<Mac::Mac>().GetSupportedChannelMask().ContainsChannel(aChannel), error = kErrorInvalidArgs);
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
+    VerifyOrExit((message = NewMleMessage(kCommandAnnounce)) != nullptr, error = kErrorNoBufs);
     message->SetLinkSecurityEnabled(true);
-    message->SetSubType(Message::kSubTypeMleAnnounce);
     message->SetChannel(aChannel);
-    SuccessOrExit(error = AppendHeader(*message, kCommandAnnounce));
 
     channel.Init();
+    channel.SetChannelPage(0);
     channel.SetChannel(Get<Mac::Mac>().GetPanChannel());
     SuccessOrExit(error = channel.AppendTo(*message));
 
@@ -2520,15 +2164,15 @@
         break;
 
     case kNormalAnnounce:
-        SuccessOrExit(error = AppendActiveTimestamp(*message));
+        SuccessOrExit(error = message->AppendActiveTimestampTlv());
         break;
     }
 
     SuccessOrExit(error = Tlv::Append<PanIdTlv>(*message, Get<Mac::Mac>().GetPanId()));
 
-    SuccessOrExit(error = SendMessage(*message, aDestination));
+    SuccessOrExit(error = message->SendTo(aDestination));
 
-    otLogInfoMle("Send Announce on channel %d", aChannel);
+    LogInfo("Send Announce on channel %d", aChannel);
 
 exit:
     FreeMessageOnError(message, error);
@@ -2542,7 +2186,7 @@
 
     Mac::ChannelMask channelMask;
 
-    if (Get<MeshCoP::ActiveDataset>().GetChannelMask(channelMask) != kErrorNone)
+    if (Get<MeshCoP::ActiveDatasetManager>().GetChannelMask(channelMask) != kErrorNone)
     {
         channelMask = Get<Mac::Mac>().GetSupportedChannelMask();
     }
@@ -2560,13 +2204,12 @@
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
 Error Mle::SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, LinkMetrics::Status aStatus)
 {
-    Error    error = kErrorNone;
-    Message *message;
-    Tlv      tlv;
-    ot::Tlv  statusSubTlv;
+    Error      error = kErrorNone;
+    TxMessage *message;
+    Tlv        tlv;
+    ot::Tlv    statusSubTlv;
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    SuccessOrExit(error = AppendHeader(*message, kCommandLinkMetricsManagementResponse));
+    VerifyOrExit((message = NewMleMessage(kCommandLinkMetricsManagementResponse)) != nullptr, error = kErrorNoBufs);
 
     tlv.SetType(Tlv::kLinkMetricsManagement);
     statusSubTlv.SetType(LinkMetrics::SubTlv::kStatus);
@@ -2577,7 +2220,7 @@
     SuccessOrExit(error = message->Append(statusSubTlv));
     SuccessOrExit(error = message->Append(aStatus));
 
-    SuccessOrExit(error = SendMessage(*message, aDestination));
+    SuccessOrExit(error = message->SendTo(aDestination));
 
 exit:
     FreeMessageOnError(message, error);
@@ -2588,12 +2231,11 @@
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
 Error Mle::SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t *aBuf, uint8_t aLength)
 {
-    Error    error = kErrorNone;
-    Message *message;
-    Tlv      tlv;
+    Error      error = kErrorNone;
+    TxMessage *message;
+    Tlv        tlv;
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    SuccessOrExit(error = AppendHeader(*message, kCommandLinkProbe));
+    VerifyOrExit((message = NewMleMessage(kCommandLinkProbe)) != nullptr, error = kErrorNoBufs);
 
     tlv.SetType(Tlv::kLinkProbe);
     tlv.SetLength(sizeof(aSeriesId) + aLength);
@@ -2602,7 +2244,7 @@
     SuccessOrExit(error = message->Append(aSeriesId));
     SuccessOrExit(error = message->AppendBytes(aBuf, aLength));
 
-    SuccessOrExit(error = SendMessage(*message, aDestination));
+    SuccessOrExit(error = message->SendTo(aDestination));
 
 exit:
     FreeMessageOnError(message, error);
@@ -2610,79 +2252,93 @@
 }
 #endif
 
-Error Mle::SendMessage(Message &aMessage, const Ip6::Address &aDestination)
+Error Mle::ProcessMessageSecurity(Crypto::AesCcm::Mode    aMode,
+                                  Message &               aMessage,
+                                  const Ip6::MessageInfo &aMessageInfo,
+                                  uint16_t                aCmdOffset,
+                                  const SecurityHeader &  aHeader)
 {
-    Error            error = kErrorNone;
-    Header           header;
-    uint32_t         keySequence;
-    uint8_t          nonce[Crypto::AesCcm::kNonceSize];
-    uint8_t          tag[kMleSecurityTagSize];
-    Crypto::AesCcm   aesCcm;
-    uint8_t          buf[64];
-    uint16_t         length;
-    Ip6::MessageInfo messageInfo;
+    // This method performs MLE message security. Based on `aMode` it
+    // can be used to encrypt and append tag to `aMessage` or to
+    // decrypt and validate the tag in a received `aMessage` (which is
+    // then removed from `aMessage`).
+    //
+    // `aCmdOffset` in both cases specifies the offset in `aMessage`
+    // to the start of MLE payload (i.e., the command field).
+    //
+    // When decrypting, possible errors are:
+    // `kErrorNone` decrypted and verified tag, tag is also removed.
+    // `kErrorParse` message does not contain the tag
+    // `kErrorSecurity` message tag is invalid.
+    //
+    // When encrypting, possible errors are:
+    // `kErrorNone` message encrypted and tag appended to message.
+    // `kErrorNoBufs` could not grow the message to append the tag.
 
-    IgnoreError(aMessage.Read(0, header));
+    Error               error = kErrorNone;
+    Crypto::AesCcm      aesCcm;
+    uint8_t             nonce[Crypto::AesCcm::kNonceSize];
+    uint8_t             tag[kMleSecurityTagSize];
+    Mac::ExtAddress     extAddress;
+    uint32_t            keySequence;
+    uint16_t            payloadLength   = aMessage.GetLength() - aCmdOffset;
+    const Ip6::Address *senderAddress   = &aMessageInfo.GetSockAddr();
+    const Ip6::Address *receiverAddress = &aMessageInfo.GetPeerAddr();
 
-    if (header.GetSecuritySuite() == Header::k154Security)
+    switch (aMode)
     {
-        header.SetFrameCounter(Get<KeyManager>().GetMleFrameCounter());
+    case Crypto::AesCcm::kEncrypt:
+        // Use the initialized values for `senderAddress`,
+        // `receiverAddress` and `payloadLength`
+        break;
 
-        keySequence = Get<KeyManager>().GetCurrentKeySequence();
-        header.SetKeyId(keySequence);
-
-        aMessage.WriteBytes(0, &header, header.GetLength());
-
-        Crypto::AesCcm::GenerateNonce(Get<Mac::Mac>().GetExtAddress(), Get<KeyManager>().GetMleFrameCounter(),
-                                      Mac::Frame::kSecEncMic32, nonce);
-
-        aesCcm.SetKey(Get<KeyManager>().GetCurrentMleKey());
-        aesCcm.Init(16 + 16 + header.GetHeaderLength(), aMessage.GetLength() - (header.GetLength() - 1), sizeof(tag),
-                    nonce, sizeof(nonce));
-
-        aesCcm.Header(&mLinkLocal64.GetAddress(), sizeof(mLinkLocal64.GetAddress()));
-        aesCcm.Header(&aDestination, sizeof(aDestination));
-        aesCcm.Header(header.GetBytes() + 1, header.GetHeaderLength());
-
-        aMessage.SetOffset(header.GetLength() - 1);
-
-        while (aMessage.GetOffset() < aMessage.GetLength())
-        {
-            length = aMessage.ReadBytes(aMessage.GetOffset(), buf, sizeof(buf));
-            aesCcm.Payload(buf, buf, length, Crypto::AesCcm::kEncrypt);
-            aMessage.WriteBytes(aMessage.GetOffset(), buf, length);
-            aMessage.MoveOffset(length);
-        }
-
-        aesCcm.Finalize(tag);
-        SuccessOrExit(error = aMessage.AppendBytes(tag, sizeof(tag)));
-
-        Get<KeyManager>().IncrementMleFrameCounter();
+    case Crypto::AesCcm::kDecrypt:
+        senderAddress   = &aMessageInfo.GetPeerAddr();
+        receiverAddress = &aMessageInfo.GetSockAddr();
+        // Ensure message contains command field (uint8_t) and
+        // tag. Then exclude the tag from payload to decrypt.
+        VerifyOrExit(aCmdOffset + sizeof(uint8_t) + kMleSecurityTagSize <= aMessage.GetLength(), error = kErrorParse);
+        payloadLength -= kMleSecurityTagSize;
+        break;
     }
 
-    messageInfo.SetPeerAddr(aDestination);
-    messageInfo.SetSockAddr(mLinkLocal64.GetAddress());
-    messageInfo.SetPeerPort(kUdpPort);
-    messageInfo.SetHopLimit(kMleHopLimit);
+    senderAddress->GetIid().ConvertToExtAddress(extAddress);
+    Crypto::AesCcm::GenerateNonce(extAddress, aHeader.GetFrameCounter(), Mac::Frame::kSecEncMic32, nonce);
 
-    SuccessOrExit(error = mSocket.SendTo(aMessage, messageInfo));
+    keySequence = aHeader.GetKeyId();
 
-exit:
-    return error;
-}
+    aesCcm.SetKey(keySequence == Get<KeyManager>().GetCurrentKeySequence()
+                      ? Get<KeyManager>().GetCurrentMleKey()
+                      : Get<KeyManager>().GetTemporaryMleKey(keySequence));
 
-Error Mle::AddDelayedResponse(Message &aMessage, const Ip6::Address &aDestination, uint16_t aDelay)
-{
-    Error                   error = kErrorNone;
-    DelayedResponseMetadata metadata;
+    aesCcm.Init(sizeof(Ip6::Address) + sizeof(Ip6::Address) + sizeof(SecurityHeader), payloadLength,
+                kMleSecurityTagSize, nonce, sizeof(nonce));
 
-    metadata.mSendTime    = TimerMilli::GetNow() + aDelay;
-    metadata.mDestination = aDestination;
+    aesCcm.Header(*senderAddress);
+    aesCcm.Header(*receiverAddress);
+    aesCcm.Header(aHeader);
 
-    SuccessOrExit(error = metadata.AppendTo(aMessage));
-    mDelayedResponses.Enqueue(aMessage);
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    if (aMode == Crypto::AesCcm::kDecrypt)
+    {
+        // Skip decrypting the message under fuzz build mode
+        IgnoreError(aMessage.SetLength(aMessage.GetLength() - kMleSecurityTagSize));
+        ExitNow();
+    }
+#endif
 
-    mDelayedResponseTimer.FireAtIfEarlier(metadata.mSendTime);
+    aesCcm.Payload(aMessage, aCmdOffset, payloadLength, aMode);
+    aesCcm.Finalize(tag);
+
+    if (aMode == Crypto::AesCcm::kEncrypt)
+    {
+        SuccessOrExit(error = aMessage.Append(tag));
+    }
+    else
+    {
+        VerifyOrExit(aMessage.Compare(aMessage.GetLength() - kMleSecurityTagSize, tag), error = kErrorSecurity);
+        IgnoreError(aMessage.SetLength(aMessage.GetLength() - kMleSecurityTagSize));
+    }
 
 exit:
     return error;
@@ -2695,44 +2351,38 @@
 
 void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
 {
-    Error              error = kErrorNone;
-    Header             header;
-    uint32_t           keySequence;
-    const KeyMaterial *mleKey;
-    uint32_t           frameCounter;
-    uint8_t            messageTag[kMleSecurityTagSize];
-    uint8_t            nonce[Crypto::AesCcm::kNonceSize];
-    Mac::ExtAddress    extAddr;
-    Crypto::AesCcm     aesCcm;
-    uint16_t           mleOffset;
-    uint8_t            buf[64];
-    uint16_t           length;
-    uint8_t            tag[kMleSecurityTagSize];
-    uint8_t            command;
-    Neighbor *         neighbor;
+    Error           error = kErrorNone;
+    RxInfo          rxInfo(aMessage, aMessageInfo);
+    uint8_t         securitySuite;
+    SecurityHeader  header;
+    uint32_t        keySequence;
+    uint32_t        frameCounter;
+    Mac::ExtAddress extAddr;
+    uint8_t         command;
+    Neighbor *      neighbor;
 
-    otLogDebgMle("Receive UDP message");
+    LogDebg("Receive MLE message");
 
     VerifyOrExit(aMessageInfo.GetLinkInfo() != nullptr);
     VerifyOrExit(aMessageInfo.GetHopLimit() == kMleHopLimit, error = kErrorParse);
 
-    length = aMessage.ReadBytes(aMessage.GetOffset(), &header, sizeof(header));
-    VerifyOrExit(header.IsValid() && header.GetLength() <= length, error = kErrorParse);
+    SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), securitySuite));
+    aMessage.MoveOffset(sizeof(securitySuite));
 
-    if (header.GetSecuritySuite() == Header::kNoSecurity)
+    if (securitySuite == kNoSecurity)
     {
-        aMessage.MoveOffset(header.GetLength());
+        SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), command));
+        aMessage.MoveOffset(sizeof(command));
 
-        switch (header.GetCommand())
+        switch (command)
         {
 #if OPENTHREAD_FTD
         case kCommandDiscoveryRequest:
-            Get<MleRouter>().HandleDiscoveryRequest(aMessage, aMessageInfo);
+            Get<MleRouter>().HandleDiscoveryRequest(rxInfo);
             break;
 #endif
-
         case kCommandDiscoveryResponse:
-            Get<DiscoverScanner>().HandleDiscoveryResponse(aMessage, aMessageInfo);
+            Get<DiscoverScanner>().HandleDiscoveryResponse(rxInfo);
             break;
 
         default:
@@ -2743,66 +2393,23 @@
     }
 
     VerifyOrExit(!IsDisabled(), error = kErrorInvalidState);
-    VerifyOrExit(header.GetSecuritySuite() == Header::k154Security, error = kErrorParse);
+    VerifyOrExit(securitySuite == k154Security, error = kErrorParse);
 
-    keySequence = header.GetKeyId();
+    SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), header));
+    aMessage.MoveOffset(sizeof(header));
 
-    if (keySequence == Get<KeyManager>().GetCurrentKeySequence())
-    {
-        mleKey = &Get<KeyManager>().GetCurrentMleKey();
-    }
-    else
-    {
-        mleKey = &Get<KeyManager>().GetTemporaryMleKey(keySequence);
-    }
+    VerifyOrExit(header.IsSecurityControlValid(), error = kErrorParse);
 
-    VerifyOrExit(aMessage.GetOffset() + header.GetLength() + sizeof(messageTag) <= aMessage.GetLength(),
-                 error = kErrorParse);
-    aMessage.MoveOffset(header.GetLength() - 1);
-
-    IgnoreError(aMessage.Read(aMessage.GetLength() - sizeof(messageTag), messageTag));
-    SuccessOrExit(error = aMessage.SetLength(aMessage.GetLength() - sizeof(messageTag)));
-
-    aMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
-
+    keySequence  = header.GetKeyId();
     frameCounter = header.GetFrameCounter();
-    Crypto::AesCcm::GenerateNonce(extAddr, frameCounter, Mac::Frame::kSecEncMic32, nonce);
 
-    aesCcm.SetKey(*mleKey);
-    aesCcm.Init(sizeof(aMessageInfo.GetPeerAddr()) + sizeof(aMessageInfo.GetSockAddr()) + header.GetHeaderLength(),
-                aMessage.GetLength() - aMessage.GetOffset(), sizeof(messageTag), nonce, sizeof(nonce));
-
-    aesCcm.Header(&aMessageInfo.GetPeerAddr(), sizeof(aMessageInfo.GetPeerAddr()));
-    aesCcm.Header(&aMessageInfo.GetSockAddr(), sizeof(aMessageInfo.GetSockAddr()));
-    aesCcm.Header(header.GetBytes() + 1, header.GetHeaderLength());
-
-    mleOffset = aMessage.GetOffset();
-
-    while (aMessage.GetOffset() < aMessage.GetLength())
-    {
-        length = aMessage.ReadBytes(aMessage.GetOffset(), buf, sizeof(buf));
-        aesCcm.Payload(buf, buf, length, Crypto::AesCcm::kDecrypt);
-#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-        aMessage.WriteBytes(aMessage.GetOffset(), buf, length);
-#endif
-        aMessage.MoveOffset(length);
-    }
-
-    aesCcm.Finalize(tag);
-#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-    VerifyOrExit(memcmp(messageTag, tag, sizeof(tag)) == 0, error = kErrorSecurity);
-#endif
-
-    if (keySequence > Get<KeyManager>().GetCurrentKeySequence())
-    {
-        Get<KeyManager>().SetCurrentKeySequence(keySequence);
-    }
-
-    aMessage.SetOffset(mleOffset);
+    SuccessOrExit(
+        error = ProcessMessageSecurity(Crypto::AesCcm::kDecrypt, aMessage, aMessageInfo, aMessage.GetOffset(), header));
 
     IgnoreError(aMessage.Read(aMessage.GetOffset(), command));
     aMessage.MoveOffset(sizeof(command));
 
+    aMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
     neighbor = (command == kCommandChildIdResponse) ? mNeighborTable.FindParent(extAddr)
                                                     : mNeighborTable.FindNeighbor(extAddr);
 
@@ -2853,38 +2460,42 @@
     }
 #endif
 
+    rxInfo.mKeySequence  = keySequence;
+    rxInfo.mFrameCounter = frameCounter;
+    rxInfo.mNeighbor     = neighbor;
+
     switch (command)
     {
     case kCommandAdvertisement:
-        HandleAdvertisement(aMessage, aMessageInfo, neighbor);
+        HandleAdvertisement(rxInfo);
         break;
 
     case kCommandDataResponse:
-        HandleDataResponse(aMessage, aMessageInfo, neighbor);
+        HandleDataResponse(rxInfo);
         break;
 
     case kCommandParentResponse:
-        HandleParentResponse(aMessage, aMessageInfo, keySequence);
+        HandleParentResponse(rxInfo);
         break;
 
     case kCommandChildIdResponse:
-        HandleChildIdResponse(aMessage, aMessageInfo, neighbor);
+        HandleChildIdResponse(rxInfo);
         break;
 
     case kCommandAnnounce:
-        HandleAnnounce(aMessage, aMessageInfo);
+        HandleAnnounce(rxInfo);
         break;
 
     case kCommandChildUpdateRequest:
 #if OPENTHREAD_FTD
         if (IsRouterOrLeader())
         {
-            Get<MleRouter>().HandleChildUpdateRequest(aMessage, aMessageInfo);
+            Get<MleRouter>().HandleChildUpdateRequest(rxInfo);
         }
         else
 #endif
         {
-            HandleChildUpdateRequest(aMessage, aMessageInfo, neighbor);
+            HandleChildUpdateRequest(rxInfo);
         }
 
         break;
@@ -2893,63 +2504,63 @@
 #if OPENTHREAD_FTD
         if (IsRouterOrLeader())
         {
-            Get<MleRouter>().HandleChildUpdateResponse(aMessage, aMessageInfo, keySequence, neighbor);
+            Get<MleRouter>().HandleChildUpdateResponse(rxInfo);
         }
         else
 #endif
         {
-            HandleChildUpdateResponse(aMessage, aMessageInfo, neighbor);
+            HandleChildUpdateResponse(rxInfo);
         }
 
         break;
 
 #if OPENTHREAD_FTD
     case kCommandLinkRequest:
-        Get<MleRouter>().HandleLinkRequest(aMessage, aMessageInfo, neighbor);
+        Get<MleRouter>().HandleLinkRequest(rxInfo);
         break;
 
     case kCommandLinkAccept:
-        Get<MleRouter>().HandleLinkAccept(aMessage, aMessageInfo, keySequence, neighbor);
+        Get<MleRouter>().HandleLinkAccept(rxInfo);
         break;
 
     case kCommandLinkAcceptAndRequest:
-        Get<MleRouter>().HandleLinkAcceptAndRequest(aMessage, aMessageInfo, keySequence, neighbor);
+        Get<MleRouter>().HandleLinkAcceptAndRequest(rxInfo);
         break;
 
     case kCommandDataRequest:
-        Get<MleRouter>().HandleDataRequest(aMessage, aMessageInfo, neighbor);
+        Get<MleRouter>().HandleDataRequest(rxInfo);
         break;
 
     case kCommandParentRequest:
-        Get<MleRouter>().HandleParentRequest(aMessage, aMessageInfo);
+        Get<MleRouter>().HandleParentRequest(rxInfo);
         break;
 
     case kCommandChildIdRequest:
-        Get<MleRouter>().HandleChildIdRequest(aMessage, aMessageInfo, keySequence);
+        Get<MleRouter>().HandleChildIdRequest(rxInfo);
         break;
 
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
     case kCommandTimeSync:
-        Get<MleRouter>().HandleTimeSync(aMessage, aMessageInfo, neighbor);
+        Get<MleRouter>().HandleTimeSync(rxInfo);
         break;
 #endif
 #endif // OPENTHREAD_FTD
 
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
     case kCommandLinkMetricsManagementRequest:
-        HandleLinkMetricsManagementRequest(aMessage, aMessageInfo, neighbor);
+        HandleLinkMetricsManagementRequest(rxInfo);
         break;
 #endif
 
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
     case kCommandLinkMetricsManagementResponse:
-        HandleLinkMetricsManagementResponse(aMessage, aMessageInfo, neighbor);
+        HandleLinkMetricsManagementResponse(rxInfo);
         break;
 #endif
 
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
     case kCommandLinkProbe:
-        HandleLinkProbe(aMessage, aMessageInfo, neighbor);
+        HandleLinkProbe(rxInfo);
         break;
 #endif
 
@@ -2957,6 +2568,48 @@
         ExitNow(error = kErrorDrop);
     }
 
+    // In case key sequence is larger, we determine whether to adopt it
+    // or not. The `Handle{MleMsg}()` methods set the `rxInfo.mClass`
+    // based on the message command type and the included TLVs. If
+    // there is any error during parsing of the message the `mClass`
+    // remains as its default value of `RxInfo::kUnknown`. Message
+    // classes are determined based on this:
+    //
+    // Authoritative : Larger key seq MUST be adopted.
+    // Peer          : If from a known neighbor
+    //                    If difference is 1, adopt
+    //                    Otherwise don't adopt and try to re-sync with
+    //                    neighbor.
+    //                 Otherwise larger key seq MUST NOT be adopted.
+
+    if (keySequence > Get<KeyManager>().GetCurrentKeySequence())
+    {
+        switch (rxInfo.mClass)
+        {
+        case RxInfo::kAuthoritativeMessage:
+            Get<KeyManager>().SetCurrentKeySequence(keySequence);
+            break;
+
+        case RxInfo::kPeerMessage:
+            if ((neighbor != nullptr) && neighbor->IsStateValid())
+            {
+                if (keySequence - Get<KeyManager>().GetCurrentKeySequence() == 1)
+                {
+                    Get<KeyManager>().SetCurrentKeySequence(keySequence);
+                }
+                else
+                {
+                    LogInfo("Large key seq jump in peer class msg from 0x%04x ", neighbor->GetRloc16());
+                    ReestablishLinkWithNeighbor(*neighbor);
+                }
+            }
+            break;
+
+        case RxInfo::kUnknown:
+            break;
+        }
+    }
+
 #if OPENTHREAD_CONFIG_MULTI_RADIO
     // If we could not find a neighbor matching the MAC address of the
     // received MLE messages, or if the neighbor is now invalid, we
@@ -2979,10 +2632,46 @@
 #endif
 
 exit:
-    LogProcessError(kTypeGenericUdp, error);
+    // We skip logging failures for broadcast MLE messages since it
+    // can be common to receive such messages from adjacent Thread
+    // networks.
+    if (!aMessageInfo.GetSockAddr().IsMulticast() || !aMessageInfo.GetThreadLinkInfo()->IsDstPanIdBroadcast())
+    {
+        LogProcessError(kTypeGenericUdp, error);
+    }
 }
 
-void Mle::HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor)
+void Mle::ReestablishLinkWithNeighbor(Neighbor &aNeighbor)
+{
+    VerifyOrExit(IsAttached() && aNeighbor.IsStateValid());
+
+    if (IsChild() && (&aNeighbor == &mParent))
+    {
+        IgnoreError(SendChildUpdateRequest(/* aAppendChallenge */ true));
+        ExitNow();
+    }
+
+#if OPENTHREAD_FTD
+    VerifyOrExit(IsFullThreadDevice());
+
+    if (IsActiveRouter(aNeighbor.GetRloc16()))
+    {
+        IgnoreError(Get<MleRouter>().SendLinkRequest(&aNeighbor));
+    }
+    else if (Get<ChildTable>().Contains(aNeighbor))
+    {
+        Child &child = static_cast<Child &>(aNeighbor);
+
+        child.SetState(Child::kStateChildUpdateRequest);
+        IgnoreError(Get<MleRouter>().SendChildUpdateRequest(child));
+    }
+#endif
+
+exit:
+    return;
+}
+
+void Mle::HandleAdvertisement(RxInfo &aRxInfo)
 {
     Error      error = kErrorNone;
     uint16_t   sourceAddress;
@@ -2991,24 +2680,24 @@
     uint16_t   delay;
 
     // Source Address
-    SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aMessage, sourceAddress));
+    SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress));
 
-    Log(kMessageReceive, kTypeAdvertisement, aMessageInfo.GetPeerAddr(), sourceAddress);
+    Log(kMessageReceive, kTypeAdvertisement, aRxInfo.mMessageInfo.GetPeerAddr(), sourceAddress);
 
     // Leader Data
-    SuccessOrExit(error = ReadLeaderData(aMessage, leaderData));
+    SuccessOrExit(error = aRxInfo.mMessage.ReadLeaderDataTlv(leaderData));
 
     if (!IsDetached())
     {
 #if OPENTHREAD_FTD
         if (IsFullThreadDevice())
         {
-            SuccessOrExit(error = Get<MleRouter>().HandleAdvertisement(aMessage, aMessageInfo, aNeighbor));
+            SuccessOrExit(error = Get<MleRouter>().HandleAdvertisement(aRxInfo));
         }
         else
 #endif
         {
-            if ((aNeighbor == &mParent) && (mParent.GetRloc16() != sourceAddress))
+            if ((aRxInfo.mNeighbor == &mParent) && (mParent.GetRloc16() != sourceAddress))
             {
                 // Remove stale parent.
                 IgnoreError(BecomeDetached());
@@ -3023,7 +2712,7 @@
         ExitNow();
 
     case kRoleChild:
-        VerifyOrExit(aNeighbor == &mParent);
+        VerifyOrExit(aRxInfo.mNeighbor == &mParent);
 
         if ((mParent.GetRloc16() == sourceAddress) && (leaderData.GetPartitionId() != mLeaderData.GetPartitionId() ||
                                                        leaderData.GetLeaderRouterId() != GetLeaderId()))
@@ -3033,12 +2722,13 @@
 #if OPENTHREAD_FTD
             if (IsFullThreadDevice())
             {
-                RouteTlv route;
-
-                if ((Tlv::FindTlv(aMessage, route) == kErrorNone) && route.IsValid())
+                switch (Get<MleRouter>().ProcessRouteTlv(aRxInfo))
                 {
-                    // Overwrite Route Data
-                    IgnoreError(Get<MleRouter>().ProcessRouteTlv(route));
+                case kErrorNone:
+                case kErrorNotFound:
+                    break;
+                default:
+                    ExitNow(error = kErrorParse);
                 }
             }
 #endif
@@ -3051,21 +2741,23 @@
 
     case kRoleRouter:
     case kRoleLeader:
-        VerifyOrExit(aNeighbor && aNeighbor->IsStateValid());
+        VerifyOrExit(aRxInfo.mNeighbor && aRxInfo.mNeighbor->IsStateValid());
         break;
     }
 
     if (mRetrieveNewNetworkData || IsNetworkDataNewer(leaderData))
     {
         delay = Random::NonCrypto::GetUint16InRange(0, kMleMaxResponseDelay);
-        IgnoreError(SendDataRequest(aMessageInfo.GetPeerAddr(), tlvs, sizeof(tlvs), delay));
+        IgnoreError(SendDataRequest(aRxInfo.mMessageInfo.GetPeerAddr(), tlvs, sizeof(tlvs), delay));
     }
 
+    aRxInfo.mClass = RxInfo::kPeerMessage;
+
 exit:
     LogProcessError(kTypeAdvertisement, error);
 }
 
-void Mle::HandleDataResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const Neighbor *aNeighbor)
+void Mle::HandleDataResponse(RxInfo &aRxInfo)
 {
     Error error;
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
@@ -3073,19 +2765,20 @@
     uint16_t length;
 #endif
 
-    Log(kMessageReceive, kTypeDataResponse, aMessageInfo.GetPeerAddr());
+    Log(kMessageReceive, kTypeDataResponse, aRxInfo.mMessageInfo.GetPeerAddr());
 
-    VerifyOrExit(aNeighbor && aNeighbor->IsStateValid(), error = kErrorSecurity);
+    VerifyOrExit(aRxInfo.mNeighbor && aRxInfo.mNeighbor->IsStateValid(), error = kErrorDrop);
 
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
-    if (Tlv::FindTlvValueOffset(aMessage, Tlv::kLinkMetricsReport, metricsReportValueOffset, length) == kErrorNone)
+    if (Tlv::FindTlvValueOffset(aRxInfo.mMessage, Tlv::kLinkMetricsReport, metricsReportValueOffset, length) ==
+        kErrorNone)
     {
-        Get<LinkMetrics::LinkMetrics>().HandleReport(aMessage, metricsReportValueOffset, length,
-                                                     aMessageInfo.GetPeerAddr());
+        Get<LinkMetrics::LinkMetrics>().HandleReport(aRxInfo.mMessage, metricsReportValueOffset, length,
+                                                     aRxInfo.mMessageInfo.GetPeerAddr());
     }
 #endif
 
-    error = HandleLeaderData(aMessage, aMessageInfo);
+    error = HandleLeaderData(aRxInfo);
 
     if (mDataRequestState == kDataRequestNone && !IsRxOnWhenIdle())
     {
@@ -3097,27 +2790,20 @@
         Get<DataPollSender>().StopFastPolls();
     }
 
+    SuccessOrExit(error);
+    aRxInfo.mClass = RxInfo::kPeerMessage;
+
 exit:
     LogProcessError(kTypeDataResponse, error);
 }
 
 bool Mle::IsNetworkDataNewer(const LeaderData &aLeaderData)
 {
-    int8_t diff;
-
-    if (IsFullNetworkData())
-    {
-        diff = static_cast<int8_t>(aLeaderData.GetDataVersion() - Get<NetworkData::Leader>().GetVersion());
-    }
-    else
-    {
-        diff = static_cast<int8_t>(aLeaderData.GetStableDataVersion() - Get<NetworkData::Leader>().GetStableVersion());
-    }
-
-    return (diff > 0);
+    return SerialNumber::IsGreater(aLeaderData.GetDataVersion(GetNetworkDataType()),
+                                   Get<NetworkData::Leader>().GetVersion(GetNetworkDataType()));
 }
 
-Error Mle::HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+Error Mle::HandleLeaderData(RxInfo &aRxInfo)
 {
     Error                     error = kErrorNone;
     LeaderData                leaderData;
@@ -3133,7 +2819,7 @@
     Tlv                       tlv;
 
     // Leader Data
-    SuccessOrExit(error = ReadLeaderData(aMessage, leaderData));
+    SuccessOrExit(error = aRxInfo.mMessage.ReadLeaderDataTlv(leaderData));
 
     if ((leaderData.GetPartitionId() != mLeaderData.GetPartitionId()) ||
         (leaderData.GetWeighting() != mLeaderData.GetWeighting()) || (leaderData.GetLeaderRouterId() != GetLeaderId()))
@@ -3154,17 +2840,17 @@
     }
 
     // Active Timestamp
-    switch (Tlv::Find<ActiveTimestampTlv>(aMessage, activeTimestamp))
+    switch (Tlv::Find<ActiveTimestampTlv>(aRxInfo.mMessage, activeTimestamp))
     {
     case kErrorNone:
         hasActiveTimestamp = true;
 
-        timestamp = Get<MeshCoP::ActiveDataset>().GetTimestamp();
+        timestamp = Get<MeshCoP::ActiveDatasetManager>().GetTimestamp();
 
         // if received timestamp does not match the local value and message does not contain the dataset,
         // send MLE Data Request
         if (!IsLeader() && (MeshCoP::Timestamp::Compare(&activeTimestamp, timestamp) != 0) &&
-            (Tlv::FindTlvOffset(aMessage, Tlv::kActiveDataset, activeDatasetOffset) != kErrorNone))
+            (Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kActiveDataset, activeDatasetOffset) != kErrorNone))
         {
             ExitNow(dataRequest = true);
         }
@@ -3179,17 +2865,17 @@
     }
 
     // Pending Timestamp
-    switch (Tlv::Find<PendingTimestampTlv>(aMessage, pendingTimestamp))
+    switch (Tlv::Find<PendingTimestampTlv>(aRxInfo.mMessage, pendingTimestamp))
     {
     case kErrorNone:
         hasPendingTimestamp = true;
 
-        timestamp = Get<MeshCoP::PendingDataset>().GetTimestamp();
+        timestamp = Get<MeshCoP::PendingDatasetManager>().GetTimestamp();
 
         // if received timestamp does not match the local value and message does not contain the dataset,
         // send MLE Data Request
         if (!IsLeader() && (MeshCoP::Timestamp::Compare(&pendingTimestamp, timestamp) != 0) &&
-            (Tlv::FindTlvOffset(aMessage, Tlv::kPendingDataset, pendingDatasetOffset) != kErrorNone))
+            (Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kPendingDataset, pendingDatasetOffset) != kErrorNone))
         {
             ExitNow(dataRequest = true);
         }
@@ -3203,11 +2889,11 @@
         ExitNow(error = kErrorParse);
     }
 
-    if (Tlv::FindTlvOffset(aMessage, Tlv::kNetworkData, networkDataOffset) == kErrorNone)
+    if (Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kNetworkData, networkDataOffset) == kErrorNone)
     {
-        error =
-            Get<NetworkData::Leader>().SetNetworkData(leaderData.GetDataVersion(), leaderData.GetStableDataVersion(),
-                                                      !IsFullNetworkData(), aMessage, networkDataOffset);
+        error = Get<NetworkData::Leader>().SetNetworkData(leaderData.GetDataVersion(NetworkData::kFullSet),
+                                                          leaderData.GetDataVersion(NetworkData::kStableSubset),
+                                                          GetNetworkDataType(), aRxInfo.mMessage, networkDataOffset);
         SuccessOrExit(error);
     }
     else
@@ -3228,9 +2914,9 @@
         {
             if (activeDatasetOffset > 0)
             {
-                IgnoreError(aMessage.Read(activeDatasetOffset, tlv));
-                IgnoreError(Get<MeshCoP::ActiveDataset>().Save(activeTimestamp, aMessage,
-                                                               activeDatasetOffset + sizeof(tlv), tlv.GetLength()));
+                IgnoreError(aRxInfo.mMessage.Read(activeDatasetOffset, tlv));
+                IgnoreError(Get<MeshCoP::ActiveDatasetManager>().Save(
+                    activeTimestamp, aRxInfo.mMessage, activeDatasetOffset + sizeof(tlv), tlv.GetLength()));
             }
         }
 
@@ -3239,9 +2925,9 @@
         {
             if (pendingDatasetOffset > 0)
             {
-                IgnoreError(aMessage.Read(pendingDatasetOffset, tlv));
-                IgnoreError(Get<MeshCoP::PendingDataset>().Save(pendingTimestamp, aMessage,
-                                                                pendingDatasetOffset + sizeof(tlv), tlv.GetLength()));
+                IgnoreError(aRxInfo.mMessage.Read(pendingDatasetOffset, tlv));
+                IgnoreError(Get<MeshCoP::PendingDatasetManager>().Save(
+                    pendingTimestamp, aRxInfo.mMessage, pendingDatasetOffset + sizeof(tlv), tlv.GetLength()));
             }
         }
     }
@@ -3255,7 +2941,7 @@
         static const uint8_t tlvs[] = {Tlv::kNetworkData};
         uint16_t             delay;
 
-        if (aMessageInfo.GetSockAddr().IsMulticast())
+        if (aRxInfo.mMessageInfo.GetSockAddr().IsMulticast())
         {
             delay = Random::NonCrypto::GetUint16InRange(0, kMleMaxResponseDelay);
         }
@@ -3267,7 +2953,7 @@
             delay = 10;
         }
 
-        IgnoreError(SendDataRequest(aMessageInfo.GetPeerAddr(), tlvs, sizeof(tlvs), delay));
+        IgnoreError(SendDataRequest(aRxInfo.mMessageInfo.GetPeerAddr(), tlvs, sizeof(tlvs), delay));
     }
     else if (error == kErrorNone)
     {
@@ -3286,7 +2972,7 @@
 }
 
 bool Mle::IsBetterParent(uint16_t               aRloc16,
-                         uint8_t                aLinkQuality,
+                         LinkQuality            aLinkQuality,
                          uint8_t                aLinkMargin,
                          const ConnectivityTlv &aConnectivityTlv,
                          uint8_t                aVersion,
@@ -3295,10 +2981,8 @@
 {
     bool rval = false;
 
-    uint8_t candidateLinkQualityIn     = mParentCandidate.GetLinkInfo().GetLinkQuality();
-    uint8_t candidateTwoWayLinkQuality = (candidateLinkQualityIn < mParentCandidate.GetLinkQualityOut())
-                                             ? candidateLinkQualityIn
-                                             : mParentCandidate.GetLinkQualityOut();
+    LinkQuality candidateLinkQualityIn     = mParentCandidate.GetLinkInfo().GetLinkQuality();
+    LinkQuality candidateTwoWayLinkQuality = OT_MIN(candidateLinkQualityIn, mParentCandidate.GetLinkQualityOut());
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
     uint64_t candidateCslMetric = 0;
     uint64_t cslMetric          = 0;
@@ -3362,7 +3046,7 @@
     {
         cslMetric = CalcParentCslMetric(aCslClockAccuracy, aCslUncertainty);
         candidateCslMetric =
-            CalcParentCslMetric(mParentCandidate.GetCslClockAccuracy(), mParentCandidate.GetCslClockUncertainty());
+            CalcParentCslMetric(mParentCandidate.GetCslClockAccuracy(), mParentCandidate.GetCslUncertainty());
         if (candidateCslMetric != cslMetric)
         {
             ExitNow(rval = (cslMetric < candidateCslMetric));
@@ -3376,17 +3060,17 @@
     return rval;
 }
 
-void Mle::HandleParentResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, uint32_t aKeySequence)
+void Mle::HandleParentResponse(RxInfo &aRxInfo)
 {
     Error                 error    = kErrorNone;
-    const ThreadLinkInfo *linkInfo = aMessageInfo.GetThreadLinkInfo();
+    const ThreadLinkInfo *linkInfo = aRxInfo.mMessageInfo.GetThreadLinkInfo();
     Challenge             response;
     uint16_t              version;
     uint16_t              sourceAddress;
     LeaderData            leaderData;
     uint8_t               linkMarginFromTlv;
     uint8_t               linkMargin;
-    uint8_t               linkQuality;
+    LinkQuality           linkQuality;
     ConnectivityTlv       connectivity;
     uint32_t              linkFrameCounter;
     uint32_t              mleFrameCounter;
@@ -3399,19 +3083,19 @@
 #endif
 
     // Source Address
-    SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aMessage, sourceAddress));
+    SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress));
 
-    Log(kMessageReceive, kTypeParentResponse, aMessageInfo.GetPeerAddr(), sourceAddress);
+    Log(kMessageReceive, kTypeParentResponse, aRxInfo.mMessageInfo.GetPeerAddr(), sourceAddress);
 
     // Version
-    SuccessOrExit(error = Tlv::Find<VersionTlv>(aMessage, version));
+    SuccessOrExit(error = Tlv::Find<VersionTlv>(aRxInfo.mMessage, version));
     VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = kErrorParse);
 
     // Response
-    SuccessOrExit(error = ReadResponse(aMessage, response));
+    SuccessOrExit(error = aRxInfo.mMessage.ReadResponseTlv(response));
     VerifyOrExit(response == mParentRequestChallenge, error = kErrorParse);
 
-    aMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddress);
+    aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddress);
 
     if (IsChild() && mParent.GetExtAddress() == extAddress)
     {
@@ -3419,10 +3103,10 @@
     }
 
     // Leader Data
-    SuccessOrExit(error = ReadLeaderData(aMessage, leaderData));
+    SuccessOrExit(error = aRxInfo.mMessage.ReadLeaderDataTlv(leaderData));
 
     // Link Margin
-    SuccessOrExit(error = Tlv::Find<LinkMarginTlv>(aMessage, linkMarginFromTlv));
+    SuccessOrExit(error = Tlv::Find<LinkMarginTlv>(aRxInfo.mMessage, linkMarginFromTlv));
 
     linkMargin = LinkQualityInfo::ConvertRssToLinkMargin(Get<Mac::Mac>().GetNoiseFloor(), linkInfo->GetRss());
 
@@ -3434,12 +3118,12 @@
     linkQuality = LinkQualityInfo::ConvertLinkMarginToLinkQuality(linkMargin);
 
     // Connectivity
-    SuccessOrExit(error = Tlv::FindTlv(aMessage, connectivity));
+    SuccessOrExit(error = Tlv::FindTlv(aRxInfo.mMessage, connectivity));
     VerifyOrExit(connectivity.IsValid(), error = kErrorParse);
 
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
     // CSL Accuracy
-    if (Tlv::FindTlv(aMessage, clockAccuracy) != kErrorNone)
+    if (Tlv::FindTlv(aRxInfo.mMessage, clockAccuracy) != kErrorNone)
     {
         clockAccuracy.SetCslClockAccuracy(kCslWorstCrystalPpm);
         clockAccuracy.SetCslUncertainty(kCslWorstUncertainty);
@@ -3463,30 +3147,34 @@
         mParentResponseCb(&parentinfo, mParentResponseCbContext);
     }
 
+    aRxInfo.mClass = RxInfo::kAuthoritativeMessage;
+
 #if OPENTHREAD_FTD
     if (IsFullThreadDevice() && !IsDetached())
     {
-        int8_t diff = static_cast<int8_t>(connectivity.GetIdSequence() - Get<RouterTable>().GetRouterIdSequence());
+        bool isPartitionIdSame = (leaderData.GetPartitionId() == mLeaderData.GetPartitionId());
+        bool isIdSequenceSame  = (connectivity.GetIdSequence() == Get<RouterTable>().GetRouterIdSequence());
+        bool isIdSequenceGreater =
+            SerialNumber::IsGreater(connectivity.GetIdSequence(), Get<RouterTable>().GetRouterIdSequence());
 
-        switch (mParentRequestMode)
+        switch (mAttachMode)
         {
-        case kAttachAny:
-            VerifyOrExit(leaderData.GetPartitionId() != mLeaderData.GetPartitionId() || diff > 0);
+        case kAnyPartition:
+        case kBetterParent:
+            VerifyOrExit(!isPartitionIdSame || isIdSequenceGreater);
             break;
 
-        case kAttachSame1:
-        case kAttachSame2:
-            VerifyOrExit(leaderData.GetPartitionId() == mLeaderData.GetPartitionId());
-            VerifyOrExit(diff > 0);
+        case kSamePartition:
+        case kSamePartitionRetry:
+            VerifyOrExit(isPartitionIdSame && isIdSequenceGreater);
             break;
 
-        case kAttachSameDowngrade:
-            VerifyOrExit(leaderData.GetPartitionId() == mLeaderData.GetPartitionId());
-            VerifyOrExit(diff >= 0);
+        case kDowngradeToReed:
+            VerifyOrExit(isPartitionIdSame && (isIdSequenceSame || isIdSequenceGreater));
             break;
 
-        case kAttachBetter:
-            VerifyOrExit(leaderData.GetPartitionId() != mLeaderData.GetPartitionId());
+        case kBetterPartition:
+            VerifyOrExit(!isPartitionIdSame);
 
             VerifyOrExit(MleRouter::ComparePartitions(connectivity.GetActiveRouters() <= 1, leaderData,
                                                       Get<MleRouter>().IsSingleton(), mLeaderData) > 0);
@@ -3527,12 +3215,12 @@
     }
 
     // Link/MLE Frame Counters
-    SuccessOrExit(error = ReadFrameCounters(aMessage, linkFrameCounter, mleFrameCounter));
+    SuccessOrExit(error = aRxInfo.mMessage.ReadFrameCounterTlvs(linkFrameCounter, mleFrameCounter));
 
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
 
     // Time Parameter
-    if (Tlv::FindTlv(aMessage, timeParameter) == kErrorNone)
+    if (Tlv::FindTlv(aRxInfo.mMessage, timeParameter) == kErrorNone)
     {
         VerifyOrExit(timeParameter.IsValid());
 
@@ -3551,7 +3239,7 @@
 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
 
     // Challenge
-    SuccessOrExit(error = ReadChallenge(aMessage, mParentCandidateChallenge));
+    SuccessOrExit(error = aRxInfo.mMessage.ReadChallengeTlv(mParentCandidateChallenge));
 
     mParentCandidate.SetExtAddress(extAddress);
     mParentCandidate.SetRloc16(sourceAddress);
@@ -3566,10 +3254,10 @@
     mParentCandidate.ResetLinkFailures();
     mParentCandidate.SetLinkQualityOut(LinkQualityInfo::ConvertLinkMarginToLinkQuality(linkMarginFromTlv));
     mParentCandidate.SetState(Neighbor::kStateParentResponse);
-    mParentCandidate.SetKeySequence(aKeySequence);
+    mParentCandidate.SetKeySequence(aRxInfo.mKeySequence);
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
     mParentCandidate.SetCslClockAccuracy(clockAccuracy.GetCslClockAccuracy());
-    mParentCandidate.SetCslClockUncertainty(clockAccuracy.GetCslUncertainty());
+    mParentCandidate.SetCslUncertainty(clockAccuracy.GetCslUncertainty());
 #endif
 
     mParentPriority         = connectivity.GetParentPriority();
@@ -3587,12 +3275,8 @@
     LogProcessError(kTypeParentResponse, error);
 }
 
-void Mle::HandleChildIdResponse(const Message &         aMessage,
-                                const Ip6::MessageInfo &aMessageInfo,
-                                const Neighbor *        aNeighbor)
+void Mle::HandleChildIdResponse(RxInfo &aRxInfo)
 {
-    OT_UNUSED_VARIABLE(aMessageInfo);
-
     Error              error = kErrorNone;
     LeaderData         leaderData;
     uint16_t           sourceAddress;
@@ -3603,33 +3287,34 @@
     uint16_t           offset;
 
     // Source Address
-    SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aMessage, sourceAddress));
+    SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress));
 
-    Log(kMessageReceive, kTypeChildIdResponse, aMessageInfo.GetPeerAddr(), sourceAddress);
+    Log(kMessageReceive, kTypeChildIdResponse, aRxInfo.mMessageInfo.GetPeerAddr(), sourceAddress);
 
-    VerifyOrExit(aNeighbor && aNeighbor->IsStateValid(), error = kErrorSecurity);
+    VerifyOrExit(aRxInfo.mNeighbor && aRxInfo.mNeighbor->IsStateValid(), error = kErrorSecurity);
 
     VerifyOrExit(mAttachState == kAttachStateChildIdRequest);
 
-    // Leader Data
-    SuccessOrExit(error = ReadLeaderData(aMessage, leaderData));
-
     // ShortAddress
-    SuccessOrExit(error = Tlv::Find<Address16Tlv>(aMessage, shortAddress));
+    SuccessOrExit(error = Tlv::Find<Address16Tlv>(aRxInfo.mMessage, shortAddress));
+    VerifyOrExit(RouterIdMatch(sourceAddress, shortAddress), error = kErrorRejected);
+
+    // Leader Data
+    SuccessOrExit(error = aRxInfo.mMessage.ReadLeaderDataTlv(leaderData));
 
     // Network Data
-    error = Tlv::FindTlvOffset(aMessage, Tlv::kNetworkData, networkDataOffset);
-    SuccessOrExit(error);
+    SuccessOrExit(error = Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kNetworkData, networkDataOffset));
 
     // Active Timestamp
-    switch (Tlv::Find<ActiveTimestampTlv>(aMessage, timestamp))
+    switch (Tlv::Find<ActiveTimestampTlv>(aRxInfo.mMessage, timestamp))
     {
     case kErrorNone:
         // Active Dataset
-        if (Tlv::FindTlvOffset(aMessage, Tlv::kActiveDataset, offset) == kErrorNone)
+        if (Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kActiveDataset, offset) == kErrorNone)
         {
-            IgnoreError(aMessage.Read(offset, tlv));
-            IgnoreError(Get<MeshCoP::ActiveDataset>().Save(timestamp, aMessage, offset + sizeof(tlv), tlv.GetLength()));
+            IgnoreError(aRxInfo.mMessage.Read(offset, tlv));
+            SuccessOrExit(error = Get<MeshCoP::ActiveDatasetManager>().Save(timestamp, aRxInfo.mMessage,
+                                                                            offset + sizeof(tlv), tlv.GetLength()));
         }
         break;
 
@@ -3643,24 +3328,24 @@
     // clear Pending Dataset if device succeed to reattach using stored Pending Dataset
     if (mReattachState == kReattachPending)
     {
-        Get<MeshCoP::PendingDataset>().Clear();
+        Get<MeshCoP::PendingDatasetManager>().Clear();
     }
 
     // Pending Timestamp
-    switch (Tlv::Find<PendingTimestampTlv>(aMessage, timestamp))
+    switch (Tlv::Find<PendingTimestampTlv>(aRxInfo.mMessage, timestamp))
     {
     case kErrorNone:
         // Pending Dataset
-        if (Tlv::FindTlvOffset(aMessage, Tlv::kPendingDataset, offset) == kErrorNone)
+        if (Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kPendingDataset, offset) == kErrorNone)
         {
-            IgnoreError(aMessage.Read(offset, tlv));
-            IgnoreError(
-                Get<MeshCoP::PendingDataset>().Save(timestamp, aMessage, offset + sizeof(tlv), tlv.GetLength()));
+            IgnoreError(aRxInfo.mMessage.Read(offset, tlv));
+            IgnoreError(Get<MeshCoP::PendingDatasetManager>().Save(timestamp, aRxInfo.mMessage, offset + sizeof(tlv),
+                                                                   tlv.GetLength()));
         }
         break;
 
     case kErrorNotFound:
-        Get<MeshCoP::PendingDataset>().ClearNetwork();
+        Get<MeshCoP::PendingDatasetManager>().ClearNetwork();
         break;
 
     default:
@@ -3669,9 +3354,9 @@
 
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
     // Sync to Thread network time
-    if (aMessage.GetTimeSyncSeq() != OT_TIME_SYNC_INVALID_SEQ)
+    if (aRxInfo.mMessage.GetTimeSyncSeq() != OT_TIME_SYNC_INVALID_SEQ)
     {
-        Get<TimeSync>().HandleTimeSyncMessage(aMessage);
+        Get<TimeSync>().HandleTimeSyncMessage(aRxInfo.mMessage);
     }
 #endif
 
@@ -3684,11 +3369,13 @@
 #if OPENTHREAD_FTD
     if (IsFullThreadDevice())
     {
-        RouteTlv route;
-
-        if (Tlv::FindTlv(aMessage, route) == kErrorNone)
+        switch (Get<MleRouter>().ProcessRouteTlv(aRxInfo))
         {
-            SuccessOrExit(error = Get<MleRouter>().ProcessRouteTlv(route));
+        case kErrorNone:
+        case kErrorNotFound:
+            break;
+        default:
+            ExitNow(error = kErrorParse);
         }
     }
 #endif
@@ -3697,15 +3384,15 @@
     mParentCandidate.Clear();
 
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-    Get<Mac::Mac>().SetCslParentUncertainty(mParent.GetCslClockUncertainty());
+    Get<Mac::Mac>().SetCslParentUncertainty(mParent.GetCslUncertainty());
     Get<Mac::Mac>().SetCslParentClockAccuracy(mParent.GetCslClockAccuracy());
 #endif
 
     mParent.SetRloc16(sourceAddress);
 
-    IgnoreError(Get<NetworkData::Leader>().SetNetworkData(leaderData.GetDataVersion(),
-                                                          leaderData.GetStableDataVersion(), !IsFullNetworkData(),
-                                                          aMessage, networkDataOffset));
+    IgnoreError(Get<NetworkData::Leader>().SetNetworkData(leaderData.GetDataVersion(NetworkData::kFullSet),
+                                                          leaderData.GetDataVersion(NetworkData::kStableSubset),
+                                                          GetNetworkDataType(), aRxInfo.mMessage, networkDataOffset));
 
     SetStateChild(shortAddress);
 
@@ -3719,11 +3406,13 @@
         Get<MeshForwarder>().SetRxOnWhenIdle(true);
     }
 
+    aRxInfo.mClass = RxInfo::kPeerMessage;
+
 exit:
     LogProcessError(kTypeChildIdResponse, error);
 }
 
-void Mle::HandleChildUpdateRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor)
+void Mle::HandleChildUpdateRequest(RxInfo &aRxInfo)
 {
     static const uint8_t kMaxResponseTlvs = 6;
 
@@ -3735,12 +3424,12 @@
     uint8_t       numTlvs                = 0;
 
     // Source Address
-    SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aMessage, sourceAddress));
+    SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress));
 
-    Log(kMessageReceive, kTypeChildUpdateRequestOfParent, aMessageInfo.GetPeerAddr(), sourceAddress);
+    Log(kMessageReceive, kTypeChildUpdateRequestOfParent, aRxInfo.mMessageInfo.GetPeerAddr(), sourceAddress);
 
     // Challenge
-    switch (ReadChallenge(aMessage, challenge))
+    switch (aRxInfo.mMessage.ReadChallengeTlv(challenge))
     {
     case kErrorNone:
         tlvs[numTlvs++] = Tlv::kResponse;
@@ -3754,11 +3443,11 @@
         ExitNow(error = kErrorParse);
     }
 
-    if (aNeighbor == &mParent)
+    if (aRxInfo.mNeighbor == &mParent)
     {
         uint8_t status;
 
-        switch (Tlv::Find<StatusTlv>(aMessage, status))
+        switch (Tlv::Find<StatusTlv>(aRxInfo.mMessage, status))
         {
         case kErrorNone:
             VerifyOrExit(status != StatusTlv::kError, IgnoreError(BecomeDetached()));
@@ -3776,7 +3465,16 @@
         }
 
         // Leader Data, Network Data, Active Timestamp, Pending Timestamp
-        SuccessOrExit(error = HandleLeaderData(aMessage, aMessageInfo));
+        SuccessOrExit(error = HandleLeaderData(aRxInfo));
+
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+        CslClockAccuracyTlv cslClockAccuracyTlv;
+        if (Tlv::FindTlv(aRxInfo.mMessage, cslClockAccuracyTlv) == kErrorNone)
+        {
+            // MUST include CSL timeout TLV when request includes CSL accuracy
+            tlvs[numTlvs++] = Tlv::kCslTimeout;
+        }
+#endif
     }
     else
     {
@@ -3785,14 +3483,14 @@
     }
 
     // TLV Request
-    switch (FindTlvRequest(aMessage, requestedTlvs))
+    switch (aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvs))
     {
     case kErrorNone:
         for (uint8_t i = 0; i < requestedTlvs.mNumTlvs; i++)
         {
             if (numTlvs >= sizeof(tlvs))
             {
-                otLogWarnMle("Failed to respond with TLVs: %d of %d", i, requestedTlvs.mNumTlvs);
+                LogWarn("Failed to respond with TLVs: %d of %d", i, requestedTlvs.mNumTlvs);
                 break;
             }
 
@@ -3805,10 +3503,12 @@
         ExitNow(error = kErrorParse);
     }
 
+    aRxInfo.mClass = RxInfo::kPeerMessage;
+
 #if OPENTHREAD_CONFIG_MULTI_RADIO
-    if ((aNeighbor != nullptr) && (challenge.mLength != 0))
+    if ((aRxInfo.mNeighbor != nullptr) && (challenge.mLength != 0))
     {
-        aNeighbor->ClearLastRxFragmentTag();
+        aRxInfo.mNeighbor->ClearLastRxFragmentTag();
     }
 #endif
 
@@ -3818,9 +3518,7 @@
     LogProcessError(kTypeChildUpdateRequestOfParent, error);
 }
 
-void Mle::HandleChildUpdateResponse(const Message &         aMessage,
-                                    const Ip6::MessageInfo &aMessageInfo,
-                                    const Neighbor *        aNeighbor)
+void Mle::HandleChildUpdateResponse(RxInfo &aRxInfo)
 {
     Error     error = kErrorNone;
     uint8_t   status;
@@ -3830,18 +3528,31 @@
     uint32_t  mleFrameCounter;
     uint16_t  sourceAddress;
     uint32_t  timeout;
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+    CslClockAccuracyTlv clockAccuracy;
+#endif
 
-    Log(kMessageReceive, kTypeChildUpdateResponseOfParent, aMessageInfo.GetPeerAddr());
+    Log(kMessageReceive, kTypeChildUpdateResponseOfParent, aRxInfo.mMessageInfo.GetPeerAddr());
+
+    switch (aRxInfo.mMessage.ReadResponseTlv(response))
+    {
+    case kErrorNone:
+        break;
+    case kErrorNotFound:
+        response.mLength = 0;
+        break;
+    default:
+        ExitNow(error = kErrorParse);
+    }
 
     switch (mRole)
     {
     case kRoleDetached:
-        SuccessOrExit(error = ReadResponse(aMessage, response));
         VerifyOrExit(response == mParentRequestChallenge, error = kErrorSecurity);
         break;
 
     case kRoleChild:
-        VerifyOrExit((aNeighbor == &mParent) && mParent.IsStateValid(), error = kErrorSecurity);
+        VerifyOrExit((aRxInfo.mNeighbor == &mParent) && mParent.IsStateValid(), error = kErrorSecurity);
         break;
 
     default:
@@ -3850,20 +3561,20 @@
     }
 
     // Status
-    if (Tlv::Find<StatusTlv>(aMessage, status) == kErrorNone)
+    if (Tlv::Find<StatusTlv>(aRxInfo.mMessage, status) == kErrorNone)
     {
         IgnoreError(BecomeDetached());
         ExitNow();
     }
 
     // Mode
-    SuccessOrExit(error = Tlv::Find<ModeTlv>(aMessage, mode));
+    SuccessOrExit(error = Tlv::Find<ModeTlv>(aRxInfo.mMessage, mode));
     VerifyOrExit(DeviceMode(mode) == mDeviceMode, error = kErrorDrop);
 
     switch (mRole)
     {
     case kRoleDetached:
-        SuccessOrExit(error = ReadFrameCounters(aMessage, linkFrameCounter, mleFrameCounter));
+        SuccessOrExit(error = aRxInfo.mMessage.ReadFrameCounterTlvs(linkFrameCounter, mleFrameCounter));
 
         mParent.GetLinkFrameCounters().SetAll(linkFrameCounter);
         mParent.SetLinkAckFrameCounter(linkFrameCounter);
@@ -3878,7 +3589,7 @@
 
     case kRoleChild:
         // Source Address
-        SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aMessage, sourceAddress));
+        SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress));
 
         if (RouterIdFromRloc16(sourceAddress) != RouterIdFromRloc16(GetRloc16()))
         {
@@ -3887,13 +3598,20 @@
         }
 
         // Leader Data, Network Data, Active Timestamp, Pending Timestamp
-        SuccessOrExit(error = HandleLeaderData(aMessage, aMessageInfo));
+        SuccessOrExit(error = HandleLeaderData(aRxInfo));
 
         // Timeout optional
-        switch (Tlv::Find<TimeoutTlv>(aMessage, timeout))
+        switch (Tlv::Find<TimeoutTlv>(aRxInfo.mMessage, timeout))
         {
         case kErrorNone:
-            mTimeout = timeout;
+            if (timeout == 0 && IsDetachingGracefully())
+            {
+                Stop();
+            }
+            else
+            {
+                mTimeout = timeout;
+            }
             break;
         case kErrorNotFound:
             break;
@@ -3901,6 +3619,15 @@
             ExitNow(error = kErrorParse);
         }
 
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+        // CSL Accuracy
+        if (Tlv::FindTlv(aRxInfo.mMessage, clockAccuracy) != kErrorNone)
+        {
+            Get<Mac::Mac>().SetCslParentClockAccuracy(clockAccuracy.GetCslClockAccuracy());
+            Get<Mac::Mac>().SetCslParentUncertainty(clockAccuracy.GetCslUncertainty());
+        }
+#endif
+
         if (!IsRxOnWhenIdle())
         {
             Get<DataPollSender>().SetAttachMode(false);
@@ -3918,6 +3645,8 @@
         OT_UNREACHABLE_CODE(break);
     }
 
+    aRxInfo.mClass = (response.mLength == 0) ? RxInfo::kPeerMessage : RxInfo::kAuthoritativeMessage;
+
 exit:
 
     if (error == kErrorNone)
@@ -3933,10 +3662,8 @@
     LogProcessError(kTypeChildUpdateResponseOfParent, error);
 }
 
-void Mle::HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+void Mle::HandleAnnounce(RxInfo &aRxInfo)
 {
-    OT_UNUSED_VARIABLE(aMessageInfo);
-
     Error                     error = kErrorNone;
     ChannelTlv                channelTlv;
     MeshCoP::Timestamp        timestamp;
@@ -3944,19 +3671,29 @@
     uint8_t                   channel;
     uint16_t                  panId;
 
-    Log(kMessageReceive, kTypeAnnounce, aMessageInfo.GetPeerAddr());
+    Log(kMessageReceive, kTypeAnnounce, aRxInfo.mMessageInfo.GetPeerAddr());
 
-    SuccessOrExit(error = Tlv::FindTlv(aMessage, channelTlv));
+    SuccessOrExit(error = Tlv::FindTlv(aRxInfo.mMessage, channelTlv));
     VerifyOrExit(channelTlv.IsValid(), error = kErrorParse);
 
     channel = static_cast<uint8_t>(channelTlv.GetChannel());
 
-    SuccessOrExit(error = Tlv::Find<ActiveTimestampTlv>(aMessage, timestamp));
-    SuccessOrExit(error = Tlv::Find<PanIdTlv>(aMessage, panId));
+    SuccessOrExit(error = Tlv::Find<ActiveTimestampTlv>(aRxInfo.mMessage, timestamp));
+    SuccessOrExit(error = Tlv::Find<PanIdTlv>(aRxInfo.mMessage, panId));
 
-    localTimestamp = Get<MeshCoP::ActiveDataset>().GetTimestamp();
+    aRxInfo.mClass = RxInfo::kPeerMessage;
 
-    if (MeshCoP::Timestamp::Compare(&timestamp, localTimestamp) > 0)
+    localTimestamp = Get<MeshCoP::ActiveDatasetManager>().GetTimestamp();
+
+    if (timestamp.IsOrphanTimestamp() || MeshCoP::Timestamp::Compare(&timestamp, localTimestamp) < 0)
+    {
+        SendAnnounce(channel);
+
+#if OPENTHREAD_CONFIG_MLE_SEND_UNICAST_ANNOUNCE_RESPONSE
+        SendAnnounce(channel, aRxInfo.mMessageInfo.GetPeerAddr());
+#endif
+    }
+    else if (MeshCoP::Timestamp::Compare(&timestamp, localTimestamp) > 0)
     {
         // No action is required if device is detached, and current
         // channel and pan-id match the values from the received MLE
@@ -3977,15 +3714,7 @@
         mAttachTimer.Start(kAnnounceProcessTimeout);
         mAttachCounter = 0;
 
-        otLogNoteMle("Delay processing Announce - channel %d, panid 0x%02x", channel, panId);
-    }
-    else if (MeshCoP::Timestamp::Compare(&timestamp, localTimestamp) < 0)
-    {
-        SendAnnounce(channel);
-
-#if OPENTHREAD_CONFIG_MLE_SEND_UNICAST_ANNOUNCE_RESPONSE
-        SendAnnounce(channel, aMessageInfo.GetPeerAddr());
-#endif
+        LogNote("Delay processing Announce - channel %d, panid 0x%02x", channel, panId);
     }
     else
     {
@@ -4004,19 +3733,21 @@
 }
 
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
-void Mle::HandleLinkMetricsManagementRequest(const Message &         aMessage,
-                                             const Ip6::MessageInfo &aMessageInfo,
-                                             Neighbor *              aNeighbor)
+void Mle::HandleLinkMetricsManagementRequest(RxInfo &aRxInfo)
 {
     Error               error = kErrorNone;
     LinkMetrics::Status status;
 
-    Log(kMessageReceive, kTypeLinkMetricsManagementRequest, aMessageInfo.GetPeerAddr());
+    Log(kMessageReceive, kTypeLinkMetricsManagementRequest, aRxInfo.mMessageInfo.GetPeerAddr());
 
-    VerifyOrExit(aNeighbor != nullptr, error = kErrorInvalidState);
+    VerifyOrExit(aRxInfo.mNeighbor != nullptr, error = kErrorInvalidState);
 
-    SuccessOrExit(error = Get<LinkMetrics::LinkMetrics>().HandleManagementRequest(aMessage, *aNeighbor, status));
-    error = SendLinkMetricsManagementResponse(aMessageInfo.GetPeerAddr(), status);
+    SuccessOrExit(
+        error = Get<LinkMetrics::LinkMetrics>().HandleManagementRequest(aRxInfo.mMessage, *aRxInfo.mNeighbor, status));
+
+    error = SendLinkMetricsManagementResponse(aRxInfo.mMessageInfo.GetPeerAddr(), status);
+
+    aRxInfo.mClass = RxInfo::kPeerMessage;
 
 exit:
     LogProcessError(kTypeLinkMetricsManagementRequest, error);
@@ -4025,17 +3756,18 @@
 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
 
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
-void Mle::HandleLinkMetricsManagementResponse(const Message &         aMessage,
-                                              const Ip6::MessageInfo &aMessageInfo,
-                                              Neighbor *              aNeighbor)
+void Mle::HandleLinkMetricsManagementResponse(RxInfo &aRxInfo)
 {
     Error error = kErrorNone;
 
-    Log(kMessageReceive, kTypeLinkMetricsManagementResponse, aMessageInfo.GetPeerAddr());
+    Log(kMessageReceive, kTypeLinkMetricsManagementResponse, aRxInfo.mMessageInfo.GetPeerAddr());
 
-    VerifyOrExit(aNeighbor != nullptr, error = kErrorInvalidState);
+    VerifyOrExit(aRxInfo.mNeighbor != nullptr, error = kErrorInvalidState);
 
-    error = Get<LinkMetrics::LinkMetrics>().HandleManagementResponse(aMessage, aMessageInfo.GetPeerAddr());
+    error =
+        Get<LinkMetrics::LinkMetrics>().HandleManagementResponse(aRxInfo.mMessage, aRxInfo.mMessageInfo.GetPeerAddr());
+
+    aRxInfo.mClass = RxInfo::kPeerMessage;
 
 exit:
     LogProcessError(kTypeLinkMetricsManagementResponse, error);
@@ -4043,16 +3775,18 @@
 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
 
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
-void Mle::HandleLinkProbe(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor)
+void Mle::HandleLinkProbe(RxInfo &aRxInfo)
 {
     Error   error = kErrorNone;
     uint8_t seriesId;
 
-    Log(kMessageReceive, kTypeLinkProbe, aMessageInfo.GetPeerAddr());
+    Log(kMessageReceive, kTypeLinkProbe, aRxInfo.mMessageInfo.GetPeerAddr());
 
-    SuccessOrExit(error = Get<LinkMetrics::LinkMetrics>().HandleLinkProbe(aMessage, seriesId));
-    aNeighbor->AggregateLinkMetrics(seriesId, LinkMetrics::SeriesInfo::kSeriesTypeLinkProbe, aMessage.GetAverageLqi(),
-                                    aMessage.GetAverageRss());
+    SuccessOrExit(error = Get<LinkMetrics::LinkMetrics>().HandleLinkProbe(aRxInfo.mMessage, seriesId));
+    aRxInfo.mNeighbor->AggregateLinkMetrics(seriesId, LinkMetrics::SeriesInfo::kSeriesTypeLinkProbe,
+                                            aRxInfo.mMessage.GetAverageLqi(), aRxInfo.mMessage.GetAverageRss());
+
+    aRxInfo.mClass = RxInfo::kPeerMessage;
 
 exit:
     LogProcessError(kTypeLinkProbe, error);
@@ -4066,7 +3800,7 @@
 
     OT_ASSERT(mAttachState == kAttachStateProcessAnnounce);
 
-    otLogNoteMle("Processing Announce - channel %d, panid 0x%02x", newChannel, newPanId);
+    LogNote("Processing Announce - channel %d, panid 0x%02x", newChannel, newPanId);
 
     Stop(kKeepNetworkDatasets);
 
@@ -4102,7 +3836,7 @@
     return (aAddress.GetPrefix() == GetMeshLocalPrefix());
 }
 
-Error Mle::CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header)
+Error Mle::CheckReachability(uint16_t aMeshDest, const Ip6::Header &aIp6Header)
 {
     Error error;
 
@@ -4125,10 +3859,6 @@
     Message *        message = nullptr;
     Ip6::MessageInfo messageInfo;
 
-    VerifyOrExit((mPreviousParentRloc != Mac::kShortAddrInvalid) && (mPreviousParentRloc != mParent.GetRloc16()));
-
-    mCounters.mParentChanges++;
-
     VerifyOrExit((message = Get<Ip6::Ip6>().NewMessage(0)) != nullptr, error = kErrorNoBufs);
     SuccessOrExit(error = message->SetLength(0));
 
@@ -4138,13 +3868,13 @@
 
     SuccessOrExit(error = Get<Ip6::Ip6>().SendDatagram(*message, messageInfo, Ip6::kProtoNone));
 
-    otLogNoteMle("Sending message to inform previous parent 0x%04x", mPreviousParentRloc);
+    LogNote("Sending message to inform previous parent 0x%04x", mPreviousParentRloc);
 
 exit:
 
     if (error != kErrorNone)
     {
-        otLogWarnMle("Failed to inform previous parent: %s", ErrorToString(error));
+        LogWarn("Failed to inform previous parent: %s", ErrorToString(error));
 
         FreeMessage(message);
     }
@@ -4161,7 +3891,7 @@
 {
     int8_t parentRss;
 
-    otLogInfoMle("PeriodicParentSearch: %s interval passed", mParentSearchIsInBackoff ? "Backoff" : "Check");
+    LogInfo("PeriodicParentSearch: %s interval passed", mParentSearchIsInBackoff ? "Backoff" : "Check");
 
     if (mParentSearchBackoffWasCanceled)
     {
@@ -4172,7 +3902,7 @@
         if (TimerMilli::GetNow() - mParentSearchBackoffCancelTime >= kParentSearchBackoffInterval)
         {
             mParentSearchBackoffWasCanceled = false;
-            otLogInfoMle("PeriodicParentSearch: Backoff cancellation is allowed on parent switch");
+            LogInfo("PeriodicParentSearch: Backoff cancellation is allowed on parent switch");
         }
     }
 
@@ -4181,15 +3911,14 @@
     VerifyOrExit(IsChild());
 
     parentRss = GetParent().GetLinkInfo().GetAverageRss();
-    otLogInfoMle("PeriodicParentSearch: Parent RSS %d", parentRss);
+    LogInfo("PeriodicParentSearch: Parent RSS %d", parentRss);
     VerifyOrExit(parentRss != OT_RADIO_RSSI_INVALID);
 
     if (parentRss < kParentSearchRssThreadhold)
     {
-        otLogInfoMle("PeriodicParentSearch: Parent RSS less than %d, searching for new parents",
-                     kParentSearchRssThreadhold);
+        LogInfo("PeriodicParentSearch: Parent RSS less than %d, searching for new parents", kParentSearchRssThreadhold);
         mParentSearchIsInBackoff = true;
-        IgnoreError(BecomeChild(kAttachAny));
+        Attach(kBetterParent);
     }
 
 exit:
@@ -4213,8 +3942,7 @@
 
     mParentSearchTimer.Start(interval);
 
-    otLogInfoMle("PeriodicParentSearch: (Re)starting timer for %s interval",
-                 mParentSearchIsInBackoff ? "backoff" : "check");
+    LogInfo("PeriodicParentSearch: (Re)starting timer for %s interval", mParentSearchIsInBackoff ? "backoff" : "check");
 }
 
 void Mle::UpdateParentSearchState(void)
@@ -4243,7 +3971,7 @@
             mParentSearchIsInBackoff        = false;
             mParentSearchBackoffWasCanceled = true;
             mParentSearchBackoffCancelTime  = TimerMilli::GetNow();
-            otLogInfoMle("PeriodicParentSearch: Canceling backoff on switching to a new parent");
+            LogInfo("PeriodicParentSearch: Canceling backoff on switching to a new parent");
         }
     }
 
@@ -4258,7 +3986,7 @@
 }
 #endif // OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MLE == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 void Mle::Log(MessageAction aAction, MessageType aType, const Ip6::Address &aAddress)
 {
     Log(aAction, aType, aAddress, Mac::kShortAddrInvalid);
@@ -4278,13 +4006,12 @@
         rlocString.Append(",0x%04x", aRloc);
     }
 
-    otLogInfoMle("%s %s%s (%s%s)", MessageActionToString(aAction), MessageTypeToString(aType),
-                 MessageTypeActionToSuffixString(aType, aAction), aAddress.ToString().AsCString(),
-                 rlocString.AsCString());
+    LogInfo("%s %s%s (%s%s)", MessageActionToString(aAction), MessageTypeToString(aType),
+            MessageTypeActionToSuffixString(aType, aAction), aAddress.ToString().AsCString(), rlocString.AsCString());
 }
 #endif
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN) && (OPENTHREAD_CONFIG_LOG_MLE == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
 void Mle::LogProcessError(MessageType aType, Error aError)
 {
     LogError(kMessageReceive, aType, aError);
@@ -4299,8 +4026,16 @@
 {
     if (aError != kErrorNone)
     {
-        otLogWarnMle("Failed to %s %s%s: %s", aAction == kMessageSend ? "send" : "process", MessageTypeToString(aType),
-                     MessageTypeActionToSuffixString(aType, aAction), ErrorToString(aError));
+        if (aAction == kMessageReceive && (aError == kErrorDrop || aError == kErrorNoRoute))
+        {
+            LogInfo("Failed to %s %s%s: %s", "process", MessageTypeToString(aType),
+                    MessageTypeActionToSuffixString(aType, aAction), ErrorToString(aError));
+        }
+        else
+        {
+            LogWarn("Failed to %s %s%s: %s", aAction == kMessageSend ? "send" : "process", MessageTypeToString(aType),
+                    MessageTypeActionToSuffixString(aType, aAction), ErrorToString(aError));
+        }
     }
 }
 
@@ -4453,7 +4188,7 @@
     return str;
 }
 
-#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN) && (OPENTHREAD_CONFIG_LOG_MLE == 1)
+#endif // #if OT_SHOULD_LOG_AT( OT_LOG_LEVEL_WARN)
 
 const char *Mle::RoleToString(DeviceRole aRole)
 {
@@ -4471,28 +4206,30 @@
     static_assert(kRoleRouter == 3, "kRoleRouter value is incorrect");
     static_assert(kRoleLeader == 4, "kRoleLeader value is incorrect");
 
-    return (aRole <= OT_ARRAY_LENGTH(kRoleStrings)) ? kRoleStrings[aRole] : "invalid";
+    return (aRole < GetArrayLength(kRoleStrings)) ? kRoleStrings[aRole] : "invalid";
 }
 
 // LCOV_EXCL_START
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MLE == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
 
 const char *Mle::AttachModeToString(AttachMode aMode)
 {
     static const char *const kAttachModeStrings[] = {
-        "any-partition",            // (0) kAttachAny
-        "same-partition-try-1",     // (1) kAttachSame1
-        "same-partition-try-2",     // (2) kAttachSame2
-        "better-partition",         // (3) kAttachBetter
-        "same-partition-downgrade", // (4) kAttachSameDowngrade
+        "AnyPartition",       // (0) kAnyPartition
+        "SamePartition",      // (1) kSamePartition
+        "SamePartitionRetry", // (2) kSamePartitionRetry
+        "BetterPartition",    // (3) kBetterPartition
+        "DowngradeToReed",    // (4) kDowngradeToReed
+        "BetterParent",       // (5) kBetterParent
     };
 
-    static_assert(kAttachAny == 0, "kAttachAny value is incorrect");
-    static_assert(kAttachSame1 == 1, "kAttachSame1 value is incorrect");
-    static_assert(kAttachSame2 == 2, "kAttachSame2 value is incorrect");
-    static_assert(kAttachBetter == 3, "kAttachBetter value is incorrect");
-    static_assert(kAttachSameDowngrade == 4, "kAttachSameDowngrade value is incorrect");
+    static_assert(kAnyPartition == 0, "kAnyPartition value is incorrect");
+    static_assert(kSamePartition == 1, "kSamePartition value is incorrect");
+    static_assert(kSamePartitionRetry == 2, "kSamePartitionRetry value is incorrect");
+    static_assert(kBetterPartition == 3, "kBetterPartition value is incorrect");
+    static_assert(kDowngradeToReed == 4, "kDowngradeToReed value is incorrect");
+    static_assert(kBetterParent == 5, "kBetterParent value is incorrect");
 
     return kAttachModeStrings[aMode];
 }
@@ -4500,22 +4237,20 @@
 const char *Mle::AttachStateToString(AttachState aState)
 {
     static const char *const kAttachStateStrings[] = {
-        "Idle",             // (0) kAttachStateIdle
-        "ProcessAnnounce",  // (1) kAttachStateProcessAnnounce
-        "Start",            // (2) kAttachStateStart
-        "ParentReqRouters", // (3) kAttachStateParentRequestRouter
-        "ParentReqReeds",   // (4) kAttachStateParentRequestReed
-        "Announce",         // (5) kAttachStateAnnounce
-        "ChildIdReq",       // (6) kAttachStateChildIdRequest
+        "Idle",            // (0) kAttachStateIdle
+        "ProcessAnnounce", // (1) kAttachStateProcessAnnounce
+        "Start",           // (2) kAttachStateStart
+        "ParentReq",       // (3) kAttachStateParent
+        "Announce",        // (4) kAttachStateAnnounce
+        "ChildIdReq",      // (5) kAttachStateChildIdRequest
     };
 
     static_assert(kAttachStateIdle == 0, "kAttachStateIdle value is incorrect");
     static_assert(kAttachStateProcessAnnounce == 1, "kAttachStateProcessAnnounce value is incorrect");
     static_assert(kAttachStateStart == 2, "kAttachStateStart value is incorrect");
-    static_assert(kAttachStateParentRequestRouter == 3, "kAttachStateParentRequestRouter value is incorrect");
-    static_assert(kAttachStateParentRequestReed == 4, "kAttachStateParentRequestReed value is incorrect");
-    static_assert(kAttachStateAnnounce == 5, "kAttachStateAnnounce value is incorrect");
-    static_assert(kAttachStateChildIdRequest == 6, "kAttachStateChildIdRequest value is incorrect");
+    static_assert(kAttachStateParentRequest == 3, "kAttachStateParentRequest value is incorrect");
+    static_assert(kAttachStateAnnounce == 4, "kAttachStateAnnounce value is incorrect");
+    static_assert(kAttachStateChildIdRequest == 5, "kAttachStateChildIdRequest value is incorrect");
 
     return kAttachStateStrings[aState];
 }
@@ -4537,19 +4272,18 @@
     return kReattachStateStrings[aState];
 }
 
-#endif // (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MLE == 1)
+#endif // OT_SHOULD_LOG_AT( OT_LOG_LEVEL_NOTE)
 
 // LCOV_EXCL_STOP
 
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
 Error Mle::SendLinkMetricsManagementRequest(const Ip6::Address &aDestination, const uint8_t *aSubTlvs, uint8_t aLength)
 {
-    Error    error = kErrorNone;
-    Message *message;
-    Tlv      tlv;
+    Error      error = kErrorNone;
+    TxMessage *message;
+    Tlv        tlv;
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    SuccessOrExit(error = AppendHeader(*message, kCommandLinkMetricsManagementRequest));
+    VerifyOrExit((message = NewMleMessage(kCommandLinkMetricsManagementRequest)) != nullptr, error = kErrorNoBufs);
 
     // Link Metrics Management TLV
     tlv.SetType(Tlv::kLinkMetricsManagement);
@@ -4558,7 +4292,7 @@
     SuccessOrExit(error = message->AppendBytes(&tlv, sizeof(tlv)));
     SuccessOrExit(error = message->AppendBytes(aSubTlvs, aLength));
 
-    SuccessOrExit(error = SendMessage(*message, aDestination));
+    SuccessOrExit(error = message->SendTo(aDestination));
 
 exit:
     FreeMessageOnError(message, error);
@@ -4588,6 +4322,78 @@
 }
 #endif
 
+Error Mle::DetachGracefully(otDetachGracefullyCallback aCallback, void *aContext)
+{
+    Error error = kErrorNone;
+
+    VerifyOrExit(!IsDetachingGracefully(), error = kErrorBusy);
+
+    OT_ASSERT(mDetachGracefullyCallback == nullptr);
+
+    mDetachGracefullyCallback = aCallback;
+    mDetachGracefullyContext  = aContext;
+
+    if (IsChild() || IsRouter())
+    {
+        mDetachGracefullyTimer.Start(kDetachGracefullyTimeout);
+    }
+    else
+    {
+        // If the device is a leader, or it's already detached or disabled, we start the timer with zero duration to
+        // stop and invoke the callback when the timer fires, so the operation finishes immediately and asynchronously.
+        mDetachGracefullyTimer.Start(0);
+    }
+
+    if (IsChild())
+    {
+        IgnoreError(SendChildUpdateRequest(/* aAppendChallenge */ false, /* aTimeout */ 0));
+    }
+#if OPENTHREAD_FTD
+    else if (IsRouter())
+    {
+        Get<MleRouter>().SendAddressRelease(&Mle::HandleDetachGracefullyAddressReleaseResponse, this);
+    }
+#endif
+
+exit:
+    return error;
+}
+
+void Mle::HandleDetachGracefullyTimer(Timer &aTimer)
+{
+    aTimer.Get<Mle>().HandleDetachGracefullyTimer();
+}
+
+void Mle::HandleDetachGracefullyTimer(void)
+{
+    Stop();
+}
+
+#if OPENTHREAD_FTD
+void Mle::HandleDetachGracefullyAddressReleaseResponse(void *               aContext,
+                                                       otMessage *          aMessage,
+                                                       const otMessageInfo *aMessageInfo,
+                                                       Error                aResult)
+{
+    OT_UNUSED_VARIABLE(aMessage);
+    OT_UNUSED_VARIABLE(aMessageInfo);
+    OT_UNUSED_VARIABLE(aResult);
+
+    static_cast<MleRouter *>(aContext)->HandleDetachGracefullyAddressReleaseResponse();
+}
+
+void Mle::HandleDetachGracefullyAddressReleaseResponse(void)
+{
+    if (IsDetachingGracefully())
+    {
+        Stop();
+    }
+}
+#endif // OPENTHREAD_FTD
+
+//---------------------------------------------------------------------------------------------------------------------
+// Challenge
+
 void Mle::Challenge::GenerateRandom(void)
 {
     mLength = kMaxChallengeSize;
@@ -4599,6 +4405,9 @@
     return (mLength == aLength) && (memcmp(mBuffer, aBuffer, aLength) == 0);
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+// DelayedResponseMetadata
+
 void Mle::DelayedResponseMetadata::ReadFrom(const Message &aMessage)
 {
     uint16_t length = aMessage.GetLength();
@@ -4612,5 +4421,633 @@
     SuccessOrAssert(aMessage.SetLength(aMessage.GetLength() - sizeof(*this)));
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+// TxMessage
+
+Mle::TxMessage *Mle::NewMleMessage(Command aCommand)
+{
+    Error             error = kErrorNone;
+    TxMessage *       message;
+    Message::Settings settings(Message::kNoLinkSecurity, Message::kPriorityNet);
+    Message::SubType  subType;
+    uint8_t           securitySuite;
+
+    message = static_cast<TxMessage *>(mSocket.NewMessage(0, settings));
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
+
+    securitySuite = k154Security;
+    subType       = Message::kSubTypeMleGeneral;
+
+    switch (aCommand)
+    {
+    case kCommandAnnounce:
+        subType = Message::kSubTypeMleAnnounce;
+        break;
+
+    case kCommandDiscoveryRequest:
+        subType       = Message::kSubTypeMleDiscoverRequest;
+        securitySuite = kNoSecurity;
+        break;
+
+    case kCommandDiscoveryResponse:
+        subType       = Message::kSubTypeMleDiscoverResponse;
+        securitySuite = kNoSecurity;
+        break;
+
+    case kCommandChildUpdateRequest:
+        subType = Message::kSubTypeMleChildUpdateRequest;
+        break;
+
+    case kCommandDataResponse:
+        subType = Message::kSubTypeMleDataResponse;
+        break;
+
+    case kCommandChildIdRequest:
+        subType = Message::kSubTypeMleChildIdRequest;
+        break;
+
+    case kCommandDataRequest:
+        subType = Message::kSubTypeMleDataRequest;
+        break;
+
+    default:
+        break;
+    }
+
+    message->SetSubType(subType);
+
+    SuccessOrExit(error = message->Append(securitySuite));
+
+    if (securitySuite == k154Security)
+    {
+        SecurityHeader securityHeader;
+
+        // The other fields in security header are updated in the
+        // message in `TxMessage::SendTo()` before message is sent.
+
+        securityHeader.InitSecurityControl();
+        SuccessOrExit(error = message->Append(securityHeader));
+    }
+
+    error = message->Append<uint8_t>(aCommand);
+
+exit:
+    FreeAndNullMessageOnError(message, error);
+    return message;
+}
+
+Error Mle::TxMessage::AppendSourceAddressTlv(void)
+{
+    return Tlv::Append<SourceAddressTlv>(*this, Get<Mle>().GetRloc16());
+}
+
+Error Mle::TxMessage::AppendStatusTlv(StatusTlv::Status aStatus)
+{
+    return Tlv::Append<StatusTlv>(*this, aStatus);
+}
+
+Error Mle::TxMessage::AppendModeTlv(DeviceMode aMode)
+{
+    return Tlv::Append<ModeTlv>(*this, aMode.Get());
+}
+
+Error Mle::TxMessage::AppendTimeoutTlv(uint32_t aTimeout)
+{
+    return Tlv::Append<TimeoutTlv>(*this, aTimeout);
+}
+
+Error Mle::TxMessage::AppendChallengeTlv(const Challenge &aChallenge)
+{
+    return Tlv::Append<ChallengeTlv>(*this, aChallenge.mBuffer, aChallenge.mLength);
+}
+
+Error Mle::TxMessage::AppendChallengeTlv(const uint8_t *aChallenge, uint8_t aChallengeLength)
+{
+    return Tlv::Append<ChallengeTlv>(*this, aChallenge, aChallengeLength);
+}
+
+Error Mle::TxMessage::AppendResponseTlv(const Challenge &aResponse)
+{
+    return Tlv::Append<ResponseTlv>(*this, aResponse.mBuffer, aResponse.mLength);
+}
+
+Error Mle::TxMessage::AppendLinkFrameCounterTlv(void)
+{
+    uint32_t counter;
+
+    // When including Link-layer Frame Counter TLV in an MLE message
+    // the value is set to the maximum MAC frame counter on all
+    // supported radio links. All radio links must also start using
+    // the same counter value as the value included in the TLV.
+
+    counter = Get<KeyManager>().GetMaximumMacFrameCounter();
+
+#if OPENTHREAD_CONFIG_MULTI_RADIO
+    Get<KeyManager>().SetAllMacFrameCounters(counter);
+#endif
+
+    return Tlv::Append<LinkFrameCounterTlv>(*this, counter);
+}
+
+Error Mle::TxMessage::AppendMleFrameCounterTlv(void)
+{
+    return Tlv::Append<MleFrameCounterTlv>(*this, Get<KeyManager>().GetMleFrameCounter());
+}
+
+Error Mle::TxMessage::AppendAddress16Tlv(uint16_t aRloc16)
+{
+    return Tlv::Append<Address16Tlv>(*this, aRloc16);
+}
+
+Error Mle::TxMessage::AppendLeaderDataTlv(void)
+{
+    LeaderDataTlv leaderDataTlv;
+
+    Get<Mle>().mLeaderData.SetDataVersion(Get<NetworkData::Leader>().GetVersion(NetworkData::kFullSet));
+    Get<Mle>().mLeaderData.SetStableDataVersion(Get<NetworkData::Leader>().GetVersion(NetworkData::kStableSubset));
+
+    leaderDataTlv.Init();
+    leaderDataTlv.Set(Get<Mle>().mLeaderData);
+
+    return leaderDataTlv.AppendTo(*this);
+}
+
+Error Mle::TxMessage::AppendNetworkDataTlv(NetworkData::Type aType)
+{
+    Error   error = kErrorNone;
+    uint8_t networkData[NetworkData::NetworkData::kMaxSize];
+    uint8_t length;
+
+    VerifyOrExit(!Get<Mle>().mRetrieveNewNetworkData, error = kErrorInvalidState);
+
+    length = sizeof(networkData);
+    IgnoreError(Get<NetworkData::Leader>().CopyNetworkData(aType, networkData, length));
+
+    error = Tlv::Append<NetworkDataTlv>(*this, networkData, length);
+
+exit:
+    return error;
+}
+
+Error Mle::TxMessage::AppendTlvRequestTlv(const uint8_t *aTlvs, uint8_t aTlvsLength)
+{
+    return Tlv::Append<TlvRequestTlv>(*this, aTlvs, aTlvsLength);
+}
+
+Error Mle::TxMessage::AppendScanMaskTlv(uint8_t aScanMask)
+{
+    return Tlv::Append<ScanMaskTlv>(*this, aScanMask);
+}
+
+Error Mle::TxMessage::AppendLinkMarginTlv(uint8_t aLinkMargin)
+{
+    return Tlv::Append<LinkMarginTlv>(*this, aLinkMargin);
+}
+
+Error Mle::TxMessage::AppendVersionTlv(void)
+{
+    return Tlv::Append<VersionTlv>(*this, kThreadVersion);
+}
+
+Error Mle::TxMessage::AppendAddressRegistrationTlv(AddressRegistrationMode aMode)
+{
+    Error                    error = kErrorNone;
+    Tlv                      tlv;
+    AddressRegistrationEntry entry;
+    Lowpan::Context          context;
+    uint8_t                  length      = 0;
+    uint8_t                  counter     = 0;
+    uint16_t                 startOffset = GetLength();
+#if OPENTHREAD_CONFIG_DUA_ENABLE
+    Ip6::Address domainUnicastAddress;
+#endif
+
+    tlv.SetType(Tlv::kAddressRegistration);
+    SuccessOrExit(error = Append(tlv));
+
+    // Prioritize ML-EID
+    entry.SetContextId(kMeshLocalPrefixContextId);
+    entry.SetIid(Get<Mle>().GetMeshLocal64().GetIid());
+    SuccessOrExit(error = AppendBytes(&entry, entry.GetLength()));
+    length += entry.GetLength();
+
+    // Continue to append the other addresses if not `kAppendMeshLocalOnly` mode
+    VerifyOrExit(aMode != kAppendMeshLocalOnly);
+    counter++;
+
+#if OPENTHREAD_CONFIG_DUA_ENABLE
+    // Cache Domain Unicast Address.
+    domainUnicastAddress = Get<DuaManager>().GetDomainUnicastAddress();
+
+    if (Get<ThreadNetif>().HasUnicastAddress(domainUnicastAddress))
+    {
+        SuccessOrAssert(Get<NetworkData::Leader>().GetContext(domainUnicastAddress, context));
+
+        // Prioritize DUA, compressed entry
+        entry.SetContextId(context.mContextId);
+        entry.SetIid(domainUnicastAddress.GetIid());
+        SuccessOrExit(error = AppendBytes(&entry, entry.GetLength()));
+        length += entry.GetLength();
+        counter++;
+    }
+#endif // OPENTHREAD_CONFIG_DUA_ENABLE
+
+    for (const Ip6::Netif::UnicastAddress &addr : Get<ThreadNetif>().GetUnicastAddresses())
+    {
+        if (addr.GetAddress().IsLinkLocal() || Get<Mle>().IsRoutingLocator(addr.GetAddress()) ||
+            Get<Mle>().IsAnycastLocator(addr.GetAddress()) || addr.GetAddress() == Get<Mle>().GetMeshLocal64())
+        {
+            continue;
+        }
+
+#if OPENTHREAD_CONFIG_DUA_ENABLE
+        // Skip DUA that was already appended above.
+        if (addr.GetAddress() == domainUnicastAddress)
+        {
+            continue;
+        }
+#endif
+
+        if (Get<NetworkData::Leader>().GetContext(addr.GetAddress(), context) == kErrorNone)
+        {
+            // compressed entry
+            entry.SetContextId(context.mContextId);
+            entry.SetIid(addr.GetAddress().GetIid());
+        }
+        else
+        {
+            // uncompressed entry
+            entry.SetUncompressed();
+            entry.SetIp6Address(addr.GetAddress());
+        }
+
+        SuccessOrExit(error = AppendBytes(&entry, entry.GetLength()));
+        length += entry.GetLength();
+        counter++;
+        // only continue to append if there is available entry.
+        VerifyOrExit(counter < OPENTHREAD_CONFIG_MLE_IP_ADDRS_TO_REGISTER);
+    }
+
+    // Append external multicast addresses.  For sleepy end device,
+    // register all external multicast addresses with the parent for
+    // indirect transmission. Since Thread 1.2, non-sleepy MED should
+    // also register external multicast addresses of scope larger than
+    // realm with a 1.2 or higher parent.
+    if (!Get<Mle>().IsRxOnWhenIdle()
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+        || !Get<Mle>().GetParent().IsThreadVersion1p1()
+#endif
+    )
+    {
+        for (const Ip6::Netif::MulticastAddress &addr : Get<ThreadNetif>().IterateExternalMulticastAddresses())
+        {
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+            // For Thread 1.2 MED, skip multicast address with scope not
+            // larger than realm local when registering.
+            if (Get<Mle>().IsRxOnWhenIdle() && !addr.GetAddress().IsMulticastLargerThanRealmLocal())
+            {
+                continue;
+            }
+#endif
+
+            entry.SetUncompressed();
+            entry.SetIp6Address(addr.GetAddress());
+            SuccessOrExit(error = AppendBytes(&entry, entry.GetLength()));
+            length += entry.GetLength();
+
+            counter++;
+            // only continue to append if there is available entry.
+            VerifyOrExit(counter < OPENTHREAD_CONFIG_MLE_IP_ADDRS_TO_REGISTER);
+        }
+    }
+
+exit:
+
+    if (error == kErrorNone && length > 0)
+    {
+        tlv.SetLength(length);
+        Write(startOffset, tlv);
+    }
+
+    return error;
+}
+
+#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+Error Mle::TxMessage::AppendTimeRequestTlv(void)
+{
+    // `TimeRequestTlv` has no value.
+    return Tlv::Append<TimeRequestTlv>(*this, nullptr, 0);
+}
+
+Error Mle::TxMessage::AppendTimeParameterTlv(void)
+{
+    TimeParameterTlv tlv;
+
+    tlv.Init();
+    tlv.SetTimeSyncPeriod(Get<TimeSync>().GetTimeSyncPeriod());
+    tlv.SetXtalThreshold(Get<TimeSync>().GetXtalThreshold());
+
+    return tlv.AppendTo(*this);
+}
+
+Error Mle::TxMessage::AppendXtalAccuracyTlv(void)
+{
+    return Tlv::Append<XtalAccuracyTlv>(*this, otPlatTimeGetXtalAccuracy());
+}
+#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+
+Error Mle::TxMessage::AppendActiveTimestampTlv(void)
+{
+    Error                     error     = kErrorNone;
+    const MeshCoP::Timestamp *timestamp = Get<MeshCoP::ActiveDatasetManager>().GetTimestamp();
+
+    VerifyOrExit(timestamp != nullptr);
+    error = Tlv::Append<ActiveTimestampTlv>(*this, *timestamp);
+
+exit:
+    return error;
+}
+
+Error Mle::TxMessage::AppendPendingTimestampTlv(void)
+{
+    Error                     error     = kErrorNone;
+    const MeshCoP::Timestamp *timestamp = Get<MeshCoP::PendingDatasetManager>().GetTimestamp();
+
+    VerifyOrExit(timestamp != nullptr && timestamp->GetSeconds() != 0);
+    error = Tlv::Append<PendingTimestampTlv>(*this, *timestamp);
+
+exit:
+    return error;
+}
+
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+Error Mle::TxMessage::AppendCslChannelTlv(void)
+{
+    Error         error = kErrorNone;
+    CslChannelTlv cslChannel;
+
+    // In current implementation, it's allowed to set CSL Channel unspecified. As `0` is not valid for Channel value
+    // in CSL Channel TLV, if CSL channel is not specified, we don't append CSL Channel TLV.
+    // And on transmitter side, it would also set CSL Channel for the child to `0` if it doesn't find a CSL Channel
+    // TLV.
+    VerifyOrExit(Get<Mac::Mac>().GetCslChannel());
+
+    cslChannel.Init();
+    cslChannel.SetChannelPage(0);
+    cslChannel.SetChannel(Get<Mac::Mac>().GetCslChannel());
+
+    SuccessOrExit(error = Append(cslChannel));
+
+exit:
+    return error;
+}
+
+Error Mle::TxMessage::AppendCslTimeoutTlv(void)
+{
+    OT_ASSERT(Get<Mac::Mac>().IsCslEnabled());
+    return Tlv::Append<CslTimeoutTlv>(*this,
+                                      Get<Mle>().mCslTimeout == 0 ? Get<Mle>().mTimeout : Get<Mle>().mCslTimeout);
+}
+#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+Error Mle::TxMessage::AppendCslClockAccuracyTlv(void)
+{
+    Error               error = kErrorNone;
+    CslClockAccuracyTlv cslClockAccuracy;
+
+    cslClockAccuracy.Init();
+
+    cslClockAccuracy.SetCslClockAccuracy(Get<Radio>().GetCslAccuracy());
+    cslClockAccuracy.SetCslUncertainty(Get<Radio>().GetCslUncertainty());
+
+    SuccessOrExit(error = Append(cslClockAccuracy));
+
+exit:
+    return error;
+}
+#endif
+
+Error Mle::TxMessage::SendTo(const Ip6::Address &aDestination)
+{
+    Error            error  = kErrorNone;
+    uint16_t         offset = 0;
+    uint8_t          securitySuite;
+    Ip6::MessageInfo messageInfo;
+
+    messageInfo.SetPeerAddr(aDestination);
+    messageInfo.SetSockAddr(Get<Mle>().mLinkLocal64.GetAddress());
+    messageInfo.SetPeerPort(kUdpPort);
+    messageInfo.SetHopLimit(kMleHopLimit);
+
+    IgnoreError(Read(offset, securitySuite));
+    offset += sizeof(securitySuite);
+
+    if (securitySuite == k154Security)
+    {
+        SecurityHeader header;
+
+        // Update the fields in the security header
+
+        IgnoreError(Read(offset, header));
+        header.SetFrameCounter(Get<KeyManager>().GetMleFrameCounter());
+        header.SetKeyId(Get<KeyManager>().GetCurrentKeySequence());
+        Write(offset, header);
+        offset += sizeof(SecurityHeader);
+
+        SuccessOrExit(
+            error = Get<Mle>().ProcessMessageSecurity(Crypto::AesCcm::kEncrypt, *this, messageInfo, offset, header));
+
+        Get<KeyManager>().IncrementMleFrameCounter();
+    }
+
+    SuccessOrExit(error = Get<Mle>().mSocket.SendTo(*this, messageInfo));
+
+exit:
+    return error;
+}
+
+Error Mle::TxMessage::SendAfterDelay(const Ip6::Address &aDestination, uint16_t aDelay)
+{
+    Error                   error = kErrorNone;
+    DelayedResponseMetadata metadata;
+
+    metadata.mSendTime    = TimerMilli::GetNow() + aDelay;
+    metadata.mDestination = aDestination;
+
+    SuccessOrExit(error = metadata.AppendTo(*this));
+    Get<Mle>().mDelayedResponses.Enqueue(*this);
+
+    Get<Mle>().mDelayedResponseTimer.FireAtIfEarlier(metadata.mSendTime);
+
+exit:
+    return error;
+}
+
+#if OPENTHREAD_FTD
+
+Error Mle::TxMessage::AppendConnectivityTlv(void)
+{
+    ConnectivityTlv tlv;
+
+    tlv.Init();
+    Get<MleRouter>().FillConnectivityTlv(tlv);
+
+    return tlv.AppendTo(*this);
+}
+
+Error Mle::TxMessage::AppendAddresseRegisterationTlv(Child &aChild)
+{
+    Error                    error;
+    Tlv                      tlv;
+    AddressRegistrationEntry entry;
+    Lowpan::Context          context;
+    uint8_t                  length      = 0;
+    uint16_t                 startOffset = GetLength();
+
+    tlv.SetType(Tlv::kAddressRegistration);
+    SuccessOrExit(error = Append(tlv));
+
+    for (const Ip6::Address &address : aChild.IterateIp6Addresses())
+    {
+        if (address.IsMulticast() || Get<NetworkData::Leader>().GetContext(address, context) != kErrorNone)
+        {
+            // uncompressed entry
+            entry.SetUncompressed();
+            entry.SetIp6Address(address);
+        }
+        else if (context.mContextId != kMeshLocalPrefixContextId)
+        {
+            // compressed entry
+            entry.SetContextId(context.mContextId);
+            entry.SetIid(address.GetIid());
+        }
+        else
+        {
+            continue;
+        }
+
+        SuccessOrExit(error = AppendBytes(&entry, entry.GetLength()));
+        length += entry.GetLength();
+    }
+
+    tlv.SetLength(length);
+    Write(startOffset, tlv);
+
+exit:
+    return error;
+}
+
+Error Mle::TxMessage::AppendRouteTlv(Neighbor *aNeighbor)
+{
+    RouteTlv tlv;
+
+    tlv.Init();
+    Get<MleRouter>().FillRouteTlv(tlv, aNeighbor);
+
+    return tlv.AppendTo(*this);
+}
+
+Error Mle::TxMessage::AppendActiveDatasetTlv(void)
+{
+    return Get<MeshCoP::ActiveDatasetManager>().AppendMleDatasetTlv(*this);
+}
+
+Error Mle::TxMessage::AppendPendingDatasetTlv(void)
+{
+    return Get<MeshCoP::PendingDatasetManager>().AppendMleDatasetTlv(*this);
+}
+
+#endif // OPENTHREAD_FTD
+
+//---------------------------------------------------------------------------------------------------------------------
+// RxMessage
+
+Error Mle::RxMessage::ReadChallengeOrResponse(uint8_t aTlvType, Challenge &aBuffer) const
+{
+    Error    error;
+    uint16_t offset;
+    uint16_t length;
+
+    SuccessOrExit(error = Tlv::FindTlvValueOffset(*this, aTlvType, offset, length));
+    VerifyOrExit(length >= kMinChallengeSize, error = kErrorParse);
+
+    if (length > kMaxChallengeSize)
+    {
+        length = kMaxChallengeSize;
+    }
+
+    ReadBytes(offset, aBuffer.mBuffer, length);
+    aBuffer.mLength = static_cast<uint8_t>(length);
+
+exit:
+    return error;
+}
+
+Error Mle::RxMessage::ReadChallengeTlv(Challenge &aChallenge) const
+{
+    return ReadChallengeOrResponse(Tlv::kChallenge, aChallenge);
+}
+
+Error Mle::RxMessage::ReadResponseTlv(Challenge &aResponse) const
+{
+    return ReadChallengeOrResponse(Tlv::kResponse, aResponse);
+}
+
+Error Mle::RxMessage::ReadFrameCounterTlvs(uint32_t &aLinkFrameCounter, uint32_t &aMleFrameCounter) const
+{
+    Error error;
+
+    SuccessOrExit(error = Tlv::Find<LinkFrameCounterTlv>(*this, aLinkFrameCounter));
+
+    switch (Tlv::Find<MleFrameCounterTlv>(*this, aMleFrameCounter))
+    {
+    case kErrorNone:
+        break;
+    case kErrorNotFound:
+        aMleFrameCounter = aLinkFrameCounter;
+        break;
+    default:
+        error = kErrorParse;
+        break;
+    }
+
+exit:
+    return error;
+}
+
+Error Mle::RxMessage::ReadLeaderDataTlv(LeaderData &aLeaderData) const
+{
+    Error         error;
+    LeaderDataTlv leaderDataTlv;
+
+    SuccessOrExit(error = Tlv::FindTlv(*this, leaderDataTlv));
+    VerifyOrExit(leaderDataTlv.IsValid(), error = kErrorParse);
+    leaderDataTlv.Get(aLeaderData);
+
+exit:
+    return error;
+}
+
+Error Mle::RxMessage::ReadTlvRequestTlv(RequestedTlvs &aRequestedTlvs) const
+{
+    Error    error;
+    uint16_t offset;
+    uint16_t length;
+
+    SuccessOrExit(error = Tlv::FindTlvValueOffset(*this, Tlv::kTlvRequest, offset, length));
+
+    if (length > sizeof(aRequestedTlvs.mTlvs))
+    {
+        length = sizeof(aRequestedTlvs.mTlvs);
+    }
+
+    ReadBytes(offset, aRequestedTlvs.mTlvs, length);
+    aRequestedTlvs.mNumTlvs = static_cast<uint8_t>(length);
+
+exit:
+    return error;
+}
+
 } // namespace Mle
 } // namespace ot
diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp
index 71c27e2..5d07436 100644
--- a/src/core/thread/mle.hpp
+++ b/src/core/thread/mle.hpp
@@ -38,9 +38,11 @@
 
 #include "common/encoding.hpp"
 #include "common/locator.hpp"
+#include "common/log.hpp"
 #include "common/non_copyable.hpp"
 #include "common/notifier.hpp"
 #include "common/timer.hpp"
+#include "crypto/aes_ccm.hpp"
 #include "mac/mac.hpp"
 #include "meshcop/joiner_router.hpp"
 #include "meshcop/meshcop.hpp"
@@ -50,6 +52,7 @@
 #include "thread/mle_tlvs.hpp"
 #include "thread/mle_types.hpp"
 #include "thread/neighbor_table.hpp"
+#include "thread/network_data_types.hpp"
 #include "thread/topology.hpp"
 
 namespace ot {
@@ -142,13 +145,10 @@
     void Stop(void) { Stop(kUpdateNetworkDatasets); }
 
     /**
-     * This method restores network information from non-volatile memory.
-     *
-     * @retval kErrorNone      Successfully restore the network information.
-     * @retval kErrorNotFound  There is no valid network information stored in non-volatile memory.
+     * This method restores network information from non-volatile memory (if any).
      *
      */
-    Error Restore(void);
+    void Restore(void);
 
     /**
      * This method stores network information into non-volatile memory.
@@ -179,14 +179,26 @@
     /**
      * This method causes the Thread interface to attempt an MLE attach.
      *
-     * @param[in]  aMode  Indicates what partitions to attach to.
-     *
      * @retval kErrorNone          Successfully began the attach process.
      * @retval kErrorInvalidState  MLE is Disabled.
      * @retval kErrorBusy          An attach process is in progress.
      *
      */
-    Error BecomeChild(AttachMode aMode);
+    Error BecomeChild(void);
+
+    /**
+     * This function notifies other nodes in the network (if any) and then stops Thread protocol operation.
+     *
+     * It sends an Address Release if it's a router, or sets its child timeout to 0 if it's a child.
+     *
+     * @param[in] aCallback A pointer to a function that is called upon finishing detaching.
+     * @param[in] aContext  A pointer to callback application-specific context.
+     *
+     * @retval kErrorNone   Successfully started detaching.
+     * @retval kErrorBusy   Detaching is already in progress.
+     *
+     */
+    Error DetachGracefully(otDetachGracefullyCallback aCallback, void *aContext);
 
     /**
      * This method indicates whether or not the Thread device is attached to a Thread network.
@@ -308,14 +320,6 @@
     bool IsFullThreadDevice(void) const { return mDeviceMode.IsFullThreadDevice(); }
 
     /**
-     * This method indicates whether or not the device requests Full Network Data.
-     *
-     * @returns TRUE if requests Full Network Data, FALSE otherwise.
-     *
-     */
-    bool IsFullNetworkData(void) const { return mDeviceMode.IsFullNetworkData(); }
-
-    /**
      * This method indicates whether or not the device is a Minimal End Device.
      *
      * @returns TRUE if the device is a Minimal End Device, FALSE otherwise.
@@ -324,15 +328,20 @@
     bool IsMinimalEndDevice(void) const { return mDeviceMode.IsMinimalEndDevice(); }
 
     /**
+     * This method gets the Network Data type (full set or stable subset) that this device requests.
+     *
+     * @returns The Network Data type requested by this device.
+     *
+     */
+    NetworkData::Type GetNetworkDataType(void) const { return mDeviceMode.GetNetworkDataType(); }
+
+    /**
      * This method returns a pointer to the Mesh Local Prefix.
      *
      * @returns A reference to the Mesh Local Prefix.
      *
      */
-    const MeshLocalPrefix &GetMeshLocalPrefix(void) const
-    {
-        return static_cast<const MeshLocalPrefix &>(mMeshLocal16.GetAddress().GetPrefix());
-    }
+    const Ip6::NetworkPrefix &GetMeshLocalPrefix(void) const { return mMeshLocal16.GetAddress().GetPrefix(); }
 
     /**
      * This method sets the Mesh Local Prefix.
@@ -340,7 +349,7 @@
      * @param[in]  aMeshLocalPrefix  A reference to the Mesh Local Prefix.
      *
      */
-    void SetMeshLocalPrefix(const MeshLocalPrefix &aMeshLocalPrefix);
+    void SetMeshLocalPrefix(const Ip6::NetworkPrefix &aMeshLocalPrefix);
 
 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
     /**
@@ -585,7 +594,7 @@
     /**
      * This method returns the Service ID corresponding to a Service ALOC16.
      *
-     * @param[in]  aAloc16  The Servicer ALOC16 value.
+     * @param[in]  aAloc16  The Service ALOC16 value.
      *
      * @returns The Service ID corresponding to given ALOC16.
      *
@@ -593,7 +602,7 @@
     static uint8_t ServiceIdFromAloc(uint16_t aAloc16) { return static_cast<uint8_t>(aAloc16 - kAloc16ServiceStart); }
 
     /**
-     * This method returns the Service Aloc corresponding to a Service ID.
+     * This method returns the Service ALOC16 corresponding to a Service ID.
      *
      * @param[in]  aServiceId  The Service ID value.
      *
@@ -784,18 +793,31 @@
     };
 
     /**
+     * Attach mode.
+     *
+     */
+    enum AttachMode : uint8_t
+    {
+        kAnyPartition,       ///< Attach to any Thread partition.
+        kSamePartition,      ///< Attach to the same Thread partition (attempt 1 when losing connectivity).
+        kSamePartitionRetry, ///< Attach to the same Thread partition (attempt 2 when losing connectivity).
+        kBetterPartition,    ///< Attach to a better (i.e. higher weight/partition id) Thread partition.
+        kDowngradeToReed,    ///< Attach to the same Thread partition during downgrade process.
+        kBetterParent,       ///< Attach to a better parent.
+    };
+
+    /**
      * States during attach (when searching for a parent).
      *
      */
     enum AttachState : uint8_t
     {
-        kAttachStateIdle,                ///< Not currently searching for a parent.
-        kAttachStateProcessAnnounce,     ///< Waiting to process a received Announce (to switch channel/pan-id).
-        kAttachStateStart,               ///< Starting to look for a parent.
-        kAttachStateParentRequestRouter, ///< Searching for a Router to attach to.
-        kAttachStateParentRequestReed,   ///< Searching for Routers or REEDs to attach to.
-        kAttachStateAnnounce,            ///< Send Announce messages
-        kAttachStateChildIdRequest,      ///< Sending a Child ID Request message.
+        kAttachStateIdle,            ///< Not currently searching for a parent.
+        kAttachStateProcessAnnounce, ///< Waiting to process a received Announce (to switch channel/pan-id).
+        kAttachStateStart,           ///< Starting to look for a parent.
+        kAttachStateParentRequest,   ///< Send Parent Request (current number tracked by `mParentRequestCounter`).
+        kAttachStateAnnounce,        ///< Send Announce messages
+        kAttachStateChildIdRequest,  ///< Sending a Child ID Request message.
     };
 
     /**
@@ -804,16 +826,16 @@
      */
     enum ReattachState : uint8_t
     {
-        kReattachStop    = 0, ///< Reattach process is disabled or finished
-        kReattachStart   = 1, ///< Start reattach process
-        kReattachActive  = 2, ///< Reattach using stored Active Dataset
-        kReattachPending = 3, ///< Reattach using stored Pending Dataset
+        kReattachStop,    ///< Reattach process is disabled or finished
+        kReattachStart,   ///< Start reattach process
+        kReattachActive,  ///< Reattach using stored Active Dataset
+        kReattachPending, ///< Reattach using stored Pending Dataset
     };
 
     static constexpr uint16_t kMleMaxResponseDelay = 1000u; ///< Max delay before responding to a multicast request.
 
     /**
-     * This enumeration type is used in `AppendAddressRegistration()` to determine which addresses to include in the
+     * This enumeration type is used in `AppendAddressRegistrationTlv()` to determine which addresses to include in the
      * appended Address Registration TLV.
      *
      */
@@ -933,12 +955,472 @@
     };
 
     /**
-     * This method allocates a new message buffer for preparing an MLE message.
-     *
-     * @returns A pointer to the message or nullptr if insufficient message buffers are available.
+     * This class represents an MLE Tx message.
      *
      */
-    Message *NewMleMessage(void);
+    class TxMessage : public Message
+    {
+    public:
+        /**
+         * This method appends a Source Address TLV to the message.
+         *
+         * @retval kErrorNone    Successfully appended the Source Address TLV.
+         * @retval kErrorNoBufs  Insufficient buffers available to append the Source Address TLV.
+         *
+         */
+        Error AppendSourceAddressTlv(void);
+
+        /**
+         * This method appends a Mode TLV to the message.
+         *
+         * @param[in]  aMode     The Device Mode.
+         *
+         * @retval kErrorNone    Successfully appended the Mode TLV.
+         * @retval kErrorNoBufs  Insufficient buffers available to append the Mode TLV.
+         *
+         */
+        Error AppendModeTlv(DeviceMode aMode);
+
+        /**
+         * This method appends a Timeout TLV to the message.
+         *
+         * @param[in]  aTimeout  The Timeout value.
+         *
+         * @retval kErrorNone    Successfully appended the Timeout TLV.
+         * @retval kErrorNoBufs  Insufficient buffers available to append the Timeout TLV.
+         *
+         */
+        Error AppendTimeoutTlv(uint32_t aTimeout);
+
+        /**
+         * This method appends a Challenge TLV to the message.
+         *
+         * @param[in]  aChallenge        A pointer to the Challenge value.
+         * @param[in]  aChallengeLength  The length of the Challenge value in bytes.
+         *
+         * @retval kErrorNone    Successfully appended the Challenge TLV.
+         * @retval kErrorNoBufs  Insufficient buffers available to append the Challenge TLV.
+         *
+         */
+        Error AppendChallengeTlv(const uint8_t *aChallenge, uint8_t aChallengeLength);
+
+        /**
+         * This method appends a Challenge TLV to the message.
+         *
+         * @param[in] aChallenge A reference to the Challenge data.
+         *
+         * @retval kErrorNone    Successfully appended the Challenge TLV.
+         * @retval kErrorNoBufs  Insufficient buffers available to append the Challenge TLV.
+         *
+         */
+        Error AppendChallengeTlv(const Challenge &aChallenge);
+
+        /**
+         * This method appends a Response TLV to the message.
+         *
+         * @param[in] aResponse  A reference to the Response data.
+         *
+         * @retval kErrorNone    Successfully appended the Response TLV.
+         * @retval kErrorNoBufs  Insufficient buffers available to append the Response TLV.
+         *
+         */
+        Error AppendResponseTlv(const Challenge &aResponse);
+
+        /**
+         * This method appends a Link Frame Counter TLV to the message.
+         *
+         * @retval kErrorNone     Successfully appended the Link Frame Counter TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Link Frame Counter TLV.
+         *
+         */
+        Error AppendLinkFrameCounterTlv(void);
+
+        /**
+         * This method appends an MLE Frame Counter TLV to the message.
+         *
+         * @retval kErrorNone     Successfully appended the Frame Counter TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the MLE Frame Counter TLV.
+         *
+         */
+        Error AppendMleFrameCounterTlv(void);
+
+        /**
+         * This method appends an Address16 TLV to the message.
+         *
+         * @param[in]  aRloc16    The RLOC16 value.
+         *
+         * @retval kErrorNone     Successfully appended the Address16 TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Address16 TLV.
+         *
+         */
+        Error AppendAddress16Tlv(uint16_t aRloc16);
+
+        /**
+         * This method appends a Network Data TLV to the message.
+         *
+         * @param[in]  aType      The Network Data type to append, full set or stable subset.
+         *
+         * @retval kErrorNone     Successfully appended the Network Data TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Network Data TLV.
+         *
+         */
+        Error AppendNetworkDataTlv(NetworkData::Type aType);
+
+        /**
+         * This method appends a TLV Request TLV to the message.
+         *
+         * @param[in]  aTlvs        A pointer to the list of TLV types.
+         * @param[in]  aTlvsLength  The number of TLV types in @p aTlvs
+         *
+         * @retval kErrorNone     Successfully appended the TLV Request TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the TLV Request TLV.
+         *
+         */
+        Error AppendTlvRequestTlv(const uint8_t *aTlvs, uint8_t aTlvsLength);
+
+        /**
+         * This method appends a Leader Data TLV to the message.
+         *
+         * @retval kErrorNone     Successfully appended the Leader Data TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Leader Data TLV.
+         *
+         */
+        Error AppendLeaderDataTlv(void);
+
+        /**
+         * This method appends a Scan Mask TLV to th message.
+         *
+         * @param[in]  aScanMask  The Scan Mask value.
+         *
+         * @retval kErrorNone     Successfully appended the Scan Mask TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Scan Mask TLV.
+         *
+         */
+        Error AppendScanMaskTlv(uint8_t aScanMask);
+
+        /**
+         * This method appends a Status TLV to the message.
+         *
+         * @param[in] aStatus     The Status value.
+         *
+         * @retval kErrorNone     Successfully appended the Status TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Status TLV.
+         *
+         */
+        Error AppendStatusTlv(StatusTlv::Status aStatus);
+
+        /**
+         * This method appends a Link Margin TLV to the message.
+         *
+         * @param[in] aLinkMargin The Link Margin value.
+         *
+         * @retval kErrorNone     Successfully appended the Link Margin TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Link Margin TLV.
+         *
+         */
+        Error AppendLinkMarginTlv(uint8_t aLinkMargin);
+
+        /**
+         * This method appends a Version TLV to the message.
+         *
+         * @retval kErrorNone     Successfully appended the Version TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Version TLV.
+         *
+         */
+        Error AppendVersionTlv(void);
+
+        /**
+         * This method appends an Address Registration TLV to the message.
+         *
+         * @param[in]  aMode      Determines which addresses to include in the TLV (see `AddressRegistrationMode`).
+         *
+         * @retval kErrorNone     Successfully appended the Address Registration TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Address Registration TLV.
+         *
+         */
+        Error AppendAddressRegistrationTlv(AddressRegistrationMode aMode = kAppendAllAddresses);
+
+#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+        /**
+         * This method appends a Time Request TLV to the message.
+         *
+         * @retval kErrorNone     Successfully appended the Time Request TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Time Request TLV.
+         *
+         */
+        Error AppendTimeRequestTlv(void);
+
+        /**
+         * This method appends a Time Parameter TLV to the message.
+         *
+         * @retval kErrorNone     Successfully appended the Time Parameter TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Time Parameter TLV.
+         *
+         */
+        Error AppendTimeParameterTlv(void);
+#endif
+        /**
+         * This method appends a XTAL Accuracy TLV to the message.
+         *
+         * @retval kErrorNone     Successfully appended the XTAL Accuracy TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the XTAl Accuracy TLV.
+         *
+         */
+        Error AppendXtalAccuracyTlv(void);
+
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+        /**
+         * This method appends a CSL Channel TLV to the message.
+         *
+         * @retval kErrorNone     Successfully appended the CSL Channel TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the CSL Channel TLV.
+         *
+         */
+        Error AppendCslChannelTlv(void);
+
+        /**
+         * This method appends a CSL Sync Timeout TLV to the message.
+         *
+         * @retval kErrorNone     Successfully appended the CSL Timeout TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the CSL Timeout TLV.
+         *
+         */
+        Error AppendCslTimeoutTlv(void);
+#endif
+
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+        /**
+         * This method appends a CSL Clock Accuracy TLV to the message.
+         *
+         * @retval kErrorNone     Successfully appended the CSL Accuracy TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the CSL Accuracy TLV.
+         *
+         */
+        Error AppendCslClockAccuracyTlv(void);
+#endif
+
+        /**
+         * This method appends a Active Timestamp TLV to the message.
+         *
+         * @retval kErrorNone     Successfully appended the Active Timestamp TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Active Timestamp TLV.
+         *
+         */
+        Error AppendActiveTimestampTlv(void);
+
+        /**
+         * This method appends a Pending Timestamp TLV to the message.
+         *
+         * @retval kErrorNone     Successfully appended the Pending Timestamp TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Pending Timestamp TLV.
+         *
+         */
+        Error AppendPendingTimestampTlv(void);
+
+#if OPENTHREAD_FTD
+        /**
+         * This method appends a Route TLV to the message.
+         *
+         * @param[in] aNeighbor   A pointer to the intended destination  (can be `nullptr`).
+         *
+         * @retval kErrorNone     Successfully appended the Route TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Route TLV.
+         *
+         */
+        Error AppendRouteTlv(Neighbor *aNeighbor = nullptr);
+
+        /**
+         * This method appends a Active Dataset TLV to the message.
+         *
+         * @retval kErrorNone     Successfully appended the Active Dataset TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Active Dataset TLV.
+         *
+         */
+        Error AppendActiveDatasetTlv(void);
+
+        /**
+         * This method appends a Pending Dataset TLV to the message.
+         *
+         * @retval kErrorNone     Successfully appended the Pending Dataset TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Pending Dataset TLV.
+         *
+         */
+        Error AppendPendingDatasetTlv(void);
+
+        /**
+         * This method appends a Connectivity TLV to the message.
+         *
+         * @retval kErrorNone     Successfully appended the Connectivity TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Connectivity TLV.
+         *
+         */
+        Error AppendConnectivityTlv(void);
+
+        /**
+         * This method appends a Address Registration TLV to the message with addresses from a given child.
+         *
+         * @param[in] aChild  The child to include its list of addresses in the Address Registration TLV.
+         *
+         * @retval kErrorNone     Successfully appended the Connectivity TLV.
+         * @retval kErrorNoBufs   Insufficient buffers available to append the Connectivity TLV.
+         *
+         */
+        Error AppendAddresseRegisterationTlv(Child &aChild);
+#endif // OPENTHREAD_FTD
+
+        /**
+         * This method submits the MLE message to the UDP socket to be sent.
+         *
+         * @param[in]  aDestination  A reference to the IPv6 address of the destination.
+         *
+         * @retval kErrorNone     Successfully submitted the MLE message.
+         * @retval kErrorNoBufs   Insufficient buffers to form the rest of the MLE message.
+         *
+         */
+        Error SendTo(const Ip6::Address &aDestination);
+
+        /**
+         * This method enqueues the message to be sent after a given delay.
+         *
+         * @param[in]  aDestination         The IPv6 address of the recipient of the message.
+         * @param[in]  aDelay               The delay in milliseconds before transmission of the message.
+         *
+         * @retval kErrorNone     Successfully queued the message to transmit after the delay.
+         * @retval kErrorNoBufs   Insufficient buffers to queue the message.
+         *
+         */
+        Error SendAfterDelay(const Ip6::Address &aDestination, uint16_t aDelay);
+    };
+
+    /**
+     * This class represents an MLE Rx message.
+     *
+     */
+    class RxMessage : public Message
+    {
+    public:
+        /**
+         * This method reads Challenge TLV from the message.
+         *
+         * @param[out] aChallenge        A reference to the Challenge data where to output the read value.
+         *
+         * @retval kErrorNone       Successfully read the Challenge TLV.
+         * @retval kErrorNotFound   Challenge TLV was not found in the message.
+         * @retval kErrorParse      Challenge TLV was found but could not be parsed.
+         *
+         */
+        Error ReadChallengeTlv(Challenge &aChallenge) const;
+
+        /**
+         * This method reads Response TLV from the message.
+         *
+         * @param[out] aResponse        A reference to the Response data where to output the read value.
+         *
+         * @retval kErrorNone       Successfully read the Response TLV.
+         * @retval kErrorNotFound   Response TLV was not found in the message.
+         * @retval kErrorParse      Response TLV was found but could not be parsed.
+         *
+         */
+        Error ReadResponseTlv(Challenge &aResponse) const;
+
+        /**
+         * This method reads Link and MLE Frame Counters from the message.
+         *
+         * Link Frame Counter TLV must be present in the message and its value is read into @p aLinkFrameCounter. If MLE
+         * Frame Counter TLV is present in the message, its value is read into @p aMleFrameCounter. If the MLE Frame
+         * Counter TLV is not present in the message, then @p aMleFrameCounter is set to the same value as
+         * @p aLinkFrameCounter.
+         *
+         * @param[out] aLinkFrameCounter  A reference to an `uint32_t` to output the Link Frame Counter.
+         * @param[out] aMleFrameCounter   A reference to an `uint32_t` to output the MLE Frame Counter.
+         *
+         * @retval kErrorNone       Successfully read the counters.
+         * @retval kErrorNotFound   Link Frame Counter TLV was not found in the message.
+         * @retval kErrorParse      TLVs are not well-formed.
+         *
+         */
+        Error ReadFrameCounterTlvs(uint32_t &aLinkFrameCounter, uint32_t &aMleFrameCounter) const;
+
+        /**
+         * This method reads TLV Request TLV from the message.
+         *
+         * @param[out] aRequestedTlvs   A reference to output the read list of requested TLVs.
+         *
+         * @retval kErrorNone       Successfully read the TLV.
+         * @retval kErrorNotFound   TLV was not found in the message.
+         * @retval kErrorParse      TLV was found but could not be parsed.
+         *
+         */
+        Error ReadTlvRequestTlv(RequestedTlvs &aRequestedTlvs) const;
+
+        /**
+         * This method reads Leader Data TLV from a message.
+         *
+         * @param[out] aLeaderData     A reference to output the Leader Data.
+         *
+         * @retval kErrorNone       Successfully read the TLV.
+         * @retval kErrorNotFound   TLV was not found in the message.
+         * @retval kErrorParse      TLV was found but could not be parsed.
+         *
+         */
+        Error ReadLeaderDataTlv(LeaderData &aLeaderData) const;
+
+    private:
+        Error ReadChallengeOrResponse(uint8_t aTlvType, Challenge &aBuffer) const;
+    };
+
+    /**
+     * This structure represents a received MLE message containing additional information about the message (e.g.
+     * key sequence, neighbor from which it was received).
+     *
+     */
+    struct RxInfo
+    {
+        /**
+         * This enumeration represents a received MLE message class.
+         *
+         */
+        enum Class : uint8_t
+        {
+            kUnknown,              ///< Unknown (default value, also indicates MLE message parse error).
+            kAuthoritativeMessage, ///< Authoritative message (larger received key seq MUST be adopted).
+            kPeerMessage,          ///< Peer message (adopt only if from a known neighbor and is greater by one).
+        };
+
+        /**
+         * This constructor initializes the `RxInfo`.
+         *
+         * @param[in] aMessage       The received MLE message.
+         * @param[in] aMessageInfo   The `Ip6::MessageInfo` associated with message.
+         *
+         */
+        RxInfo(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+            : mMessage(static_cast<RxMessage &>(aMessage))
+            , mMessageInfo(aMessageInfo)
+            , mFrameCounter(0)
+            , mKeySequence(0)
+            , mNeighbor(nullptr)
+            , mClass(kUnknown)
+        {
+        }
+
+        RxMessage &             mMessage;      ///< The MLE message.
+        const Ip6::MessageInfo &mMessageInfo;  ///< The `MessageInfo` associated with the message.
+        uint32_t                mFrameCounter; ///< The frame counter from aux security header.
+        uint32_t                mKeySequence;  ///< The key sequence from aux security header.
+        Neighbor *              mNeighbor;     ///< Neighbor from which message was received (can be `nullptr`).
+        Class                   mClass;        ///< The message class (authoritative, peer, or unknown).
+    };
+
+    /**
+     * This method allocates and initializes new MLE message for a given command.
+     *
+     * @param[in] aCommand   The MLE command.
+     *
+     * @returns A pointer to the message or `nullptr` if insufficient message buffers are available.
+     *
+     */
+    TxMessage *NewMleMessage(Command aCommand);
 
     /**
      * This method sets the device role.
@@ -949,6 +1431,14 @@
     void SetRole(DeviceRole aRole);
 
     /**
+     * This method causes the Thread interface to attempt an MLE attach.
+     *
+     * @param[in]  aMode  Indicates what partitions to attach to.
+     *
+     */
+    void Attach(AttachMode aMode);
+
+    /**
      * This method sets the attach state
      *
      * @param[in] aState An attach state
@@ -957,382 +1447,6 @@
     void SetAttachState(AttachState aState);
 
     /**
-     * This method appends an MLE header to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     * @param[in]  aCommand  The MLE Command Type.
-     *
-     * @retval kErrorNone    Successfully appended the header.
-     * @retval kErrorNoBufs  Insufficient buffers available to append the header.
-     *
-     */
-    Error AppendHeader(Message &aMessage, Command aCommand);
-
-    /**
-     * This method appends a Source Address TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     *
-     * @retval kErrorNone    Successfully appended the Source Address TLV.
-     * @retval kErrorNoBufs  Insufficient buffers available to append the Source Address TLV.
-     *
-     */
-    Error AppendSourceAddress(Message &aMessage) const;
-
-    /**
-     * This method appends a Mode TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     * @param[in]  aMode     The Device Mode.
-     *
-     * @retval kErrorNone    Successfully appended the Mode TLV.
-     * @retval kErrorNoBufs  Insufficient buffers available to append the Mode TLV.
-     *
-     */
-    Error AppendMode(Message &aMessage, DeviceMode aMode);
-
-    /**
-     * This method appends a Timeout TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     * @param[in]  aTimeout  The Timeout value.
-     *
-     * @retval kErrorNone    Successfully appended the Timeout TLV.
-     * @retval kErrorNoBufs  Insufficient buffers available to append the Timeout TLV.
-     *
-     */
-    Error AppendTimeout(Message &aMessage, uint32_t aTimeout);
-
-    /**
-     * This method appends a Challenge TLV to a message.
-     *
-     * @param[in]  aMessage          A reference to the message.
-     * @param[in]  aChallenge        A pointer to the Challenge value.
-     * @param[in]  aChallengeLength  The length of the Challenge value in bytes.
-     *
-     * @retval kErrorNone    Successfully appended the Challenge TLV.
-     * @retval kErrorNoBufs  Insufficient buffers available to append the Challenge TLV.
-     *
-     */
-    Error AppendChallenge(Message &aMessage, const uint8_t *aChallenge, uint8_t aChallengeLength);
-
-    /**
-     * This method appends a Challenge TLV to a message.
-     *
-     * @param[in]  aMessage          A reference to the message.
-     * @param[in]  aChallenge        A reference to the Challenge data.
-     *
-     * @retval kErrorNone    Successfully appended the Challenge TLV.
-     * @retval kErrorNoBufs  Insufficient buffers available to append the Challenge TLV.
-     *
-     */
-    Error AppendChallenge(Message &aMessage, const Challenge &aChallenge);
-
-    /**
-     * This method reads Challenge TLV from a message.
-     *
-     * @param[in]  aMessage          A reference to the message.
-     * @param[out] aChallenge        A reference to the Challenge data where to output the read value.
-     *
-     * @retval kErrorNone       Successfully read the Challenge TLV.
-     * @retval kErrorNotFound   Challenge TLV was not found in the message.
-     * @retval kErrorParse      Challenge TLV was found but could not be parsed.
-     *
-     */
-    Error ReadChallenge(const Message &aMessage, Challenge &aChallenge);
-
-    /**
-     * This method appends a Response TLV to a message.
-     *
-     * @param[in]  aMessage         A reference to the message.
-     * @param[in]  aResponse        A reference to the Response data.
-     *
-     * @retval kErrorNone    Successfully appended the Response TLV.
-     * @retval kErrorNoBufs  Insufficient buffers available to append the Response TLV.
-     *
-     */
-    Error AppendResponse(Message &aMessage, const Challenge &aResponse);
-
-    /**
-     * This method reads Response TLV from a message.
-     *
-     * @param[in]  aMessage         A reference to the message.
-     * @param[out] aResponse        A reference to the Response data where to output the read value.
-     *
-     * @retval kErrorNone       Successfully read the Response TLV.
-     * @retval kErrorNotFound   Response TLV was not found in the message.
-     * @retval kErrorParse      Response TLV was found but could not be parsed.
-     *
-     */
-    Error ReadResponse(const Message &aMessage, Challenge &aResponse);
-
-    /**
-     * This method appends a Link Frame Counter TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     *
-     * @retval kErrorNone     Successfully appended the Link Frame Counter TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the Link Frame Counter TLV.
-     *
-     */
-    Error AppendLinkFrameCounter(Message &aMessage);
-
-    /**
-     * This method reads Link and MLE Frame Counters from a message.
-     *
-     * Link Frame Counter TLV must be present in the message and its value is read into @p aLinkFrameCounter. If MLE
-     * Frame Counter TLV is present in the message, its value is read into @p aMleFrameCounter. If the MLE Frame
-     * Counter TLV is not present in the message, then @p aMleFrameCounter is set to same value as @p aLinkFrameCounter.
-     *
-     * @param[in]  aMesssage           A reference to the message to read from.
-     * @param[out] aLinkFrameCounter   A reference to an `uint32_t` to output the Link Frame Counter.
-     * @param[out] aMleFrameCounter    A reference to an `uint32_t` to output the MLE Frame Counter.
-     *
-     * @retval kErrorNone       Successfully read the counters.
-     * @retval kErrorNotFound   Link Frame Counter TLV was not found in the message.
-     * @retval kErrorParse      TLVs are not well-formed.
-     *
-     */
-    Error ReadFrameCounters(const Message &aMessage, uint32_t &aLinkFrameCounter, uint32_t &aMleFrameCounter) const;
-
-    /**
-     * This method appends an MLE Frame Counter TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     *
-     * @retval kErrorNone     Successfully appended the Frame Counter TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the MLE Frame Counter TLV.
-     *
-     */
-    Error AppendMleFrameCounter(Message &aMessage);
-
-    /**
-     * This method appends an Address16 TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     * @param[in]  aRloc16   The RLOC16 value.
-     *
-     * @retval kErrorNone     Successfully appended the Address16 TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the Address16 TLV.
-     *
-     */
-    Error AppendAddress16(Message &aMessage, uint16_t aRloc16);
-
-    /**
-     * This method appends a Network Data TLV to the message.
-     *
-     * @param[in]  aMessage     A reference to the message.
-     * @param[in]  aStableOnly  TRUE to append stable data, FALSE otherwise.
-     *
-     * @retval kErrorNone     Successfully appended the Network Data TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the Network Data TLV.
-     *
-     */
-    Error AppendNetworkData(Message &aMessage, bool aStableOnly);
-
-    /**
-     * This method appends a TLV Request TLV to a message.
-     *
-     * @param[in]  aMessage     A reference to the message.
-     * @param[in]  aTlvs        A pointer to the list of TLV types.
-     * @param[in]  aTlvsLength  The number of TLV types in @p aTlvs
-     *
-     * @retval kErrorNone     Successfully appended the TLV Request TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the TLV Request TLV.
-     *
-     */
-    Error AppendTlvRequest(Message &aMessage, const uint8_t *aTlvs, uint8_t aTlvsLength);
-
-    /**
-     * This method reads TLV Request TLV from a message.
-     *
-     * @param[in]  aMessage         A reference to the message.
-     * @param[out] aRequestedTlvs   A reference to output the read list of requested TLVs.
-     *
-     * @retval kErrorNone       Successfully read the TLV.
-     * @retval kErrorNotFound   TLV was not found in the message.
-     * @retval kErrorParse      TLV was found but could not be parsed.
-     *
-     */
-    Error FindTlvRequest(const Message &aMessage, RequestedTlvs &aRequestedTlvs);
-
-    /**
-     * This method appends a Leader Data TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     *
-     * @retval kErrorNone     Successfully appended the Leader Data TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the Leader Data TLV.
-     *
-     */
-    Error AppendLeaderData(Message &aMessage);
-
-    /**
-     * This method reads Leader Data TLV from a message.
-     *
-     * @param[in]  aMessage        A reference to the message.
-     * @param[out] aLeaderData     A reference to output the Leader Data.
-     *
-     * @retval kErrorNone       Successfully read the TLV.
-     * @retval kErrorNotFound   TLV was not found in the message.
-     * @retval kErrorParse      TLV was found but could not be parsed.
-     *
-     */
-    Error ReadLeaderData(const Message &aMessage, LeaderData &aLeaderData);
-
-    /**
-     * This method appends a Scan Mask TLV to a message.
-     *
-     * @param[in]  aMessage   A reference to the message.
-     * @param[in]  aScanMask  The Scan Mask value.
-     *
-     * @retval kErrorNone     Successfully appended the Scan Mask TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the Scan Mask TLV.
-     *
-     */
-    Error AppendScanMask(Message &aMessage, uint8_t aScanMask);
-
-    /**
-     * This method appends a Status TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     * @param[in]  aStatus   The Status value.
-     *
-     * @retval kErrorNone     Successfully appended the Status TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the Status TLV.
-     *
-     */
-    Error AppendStatus(Message &aMessage, StatusTlv::Status aStatus);
-
-    /**
-     * This method appends a Link Margin TLV to a message.
-     *
-     * @param[in]  aMessage     A reference to the message.
-     * @param[in]  aLinkMargin  The Link Margin value.
-     *
-     * @retval kErrorNone     Successfully appended the Link Margin TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the Link Margin TLV.
-     *
-     */
-    Error AppendLinkMargin(Message &aMessage, uint8_t aLinkMargin);
-
-    /**
-     * This method appends a Version TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     *
-     * @retval kErrorNone     Successfully appended the Version TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the Version TLV.
-     *
-     */
-    Error AppendVersion(Message &aMessage);
-
-    /**
-     * This method appends an Address Registration TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     * @param[in]  aMode     Determines which addresses to include in the TLV (see `AddressRegistrationMode`).
-     *
-     * @retval kErrorNone     Successfully appended the Address Registration TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the Address Registration TLV.
-     *
-     */
-    Error AppendAddressRegistration(Message &aMessage, AddressRegistrationMode aMode = kAppendAllAddresses);
-
-#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-    /**
-     * This method appends a Time Request TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     *
-     * @retval kErrorNone     Successfully appended the Time Request TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the Time Request TLV.
-     *
-     */
-    Error AppendTimeRequest(Message &aMessage);
-
-    /**
-     * This method appends a Time Parameter TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     *
-     * @retval kErrorNone     Successfully appended the Time Parameter TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the Time Parameter TLV.
-     *
-     */
-    Error AppendTimeParameter(Message &aMessage);
-
-    /**
-     * This method appends a XTAL Accuracy TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     *
-     * @retval kErrorNone     Successfully appended the XTAL Accuracy TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the XTAl Accuracy TLV.
-     *
-     */
-    Error AppendXtalAccuracy(Message &aMessage);
-#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-
-#if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE) || OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-    /**
-     * This method appends a CSL Channel TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     *
-     * @retval kErrorNone     Successfully appended the CSL Channel TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the CSL Channel TLV.
-     *
-     */
-    Error AppendCslChannel(Message &aMessage);
-
-    /**
-     * This method appends a CSL Sync Timeout TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     *
-     * @retval kErrorNone     Successfully appended the CSL Timeout TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the CSL Timeout TLV.
-     *
-     */
-    Error AppendCslTimeout(Message &aMessage);
-#endif // (OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE) || OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-
-#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
-    /**
-     * This method appends a CSL Clock Accuracy TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     *
-     * @retval kErrorNone     Successfully appended the CSL Accuracy TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the CSL Accuracy TLV.
-     */
-    Error AppendCslClockAccuracy(Message &aMessage);
-#endif
-
-    /**
-     * This method appends a Active Timestamp TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     *
-     * @retval kErrorNone     Successfully appended the Active Timestamp TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the Active Timestamp TLV.
-     *
-     */
-    Error AppendActiveTimestamp(Message &aMessage);
-
-    /**
-     * This method appends a Pending Timestamp TLV to a message.
-     *
-     * @param[in]  aMessage  A reference to the message.
-     *
-     * @retval kErrorNone     Successfully appended the Pending Timestamp TLV.
-     * @retval kErrorNoBufs   Insufficient buffers available to append the Pending Timestamp TLV.
-     *
-     */
-    Error AppendPendingTimestamp(Message &aMessage);
-
-    /**
      * This method checks if the destination is reachable.
      *
      * @param[in]  aMeshDest   The RLOC16 of the destination.
@@ -1342,7 +1456,7 @@
      * @retval kErrorNoRoute   The destination is not reachable and the message should be dropped.
      *
      */
-    Error CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header);
+    Error CheckReachability(uint16_t aMeshDest, const Ip6::Header &aIp6Header);
 
     /**
      * This method returns the next hop towards an RLOC16 destination.
@@ -1378,11 +1492,13 @@
     /**
      * This method generates an MLE Child Update Request message.
      *
+     * @param[in] aAppendChallenge   Indicates whether or not to include a Challenge TLV (even when already attached).
+     *
      * @retval kErrorNone    Successfully generated an MLE Child Update Request message.
      * @retval kErrorNoBufs  Insufficient buffers to generate the MLE Child Update Request message.
      *
      */
-    Error SendChildUpdateRequest(void);
+    Error SendChildUpdateRequest(bool aAppendChallenge = false);
 
     /**
      * This method generates an MLE Child Update Response message.
@@ -1398,18 +1514,6 @@
     Error SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, const Challenge &aChallenge);
 
     /**
-     * This method submits an MLE message to the UDP socket.
-     *
-     * @param[in]  aMessage      A reference to the message.
-     * @param[in]  aDestination  A reference to the IPv6 address of the destination.
-     *
-     * @retval kErrorNone     Successfully submitted the MLE message.
-     * @retval kErrorNoBufs   Insufficient buffers to form the rest of the MLE message.
-     *
-     */
-    Error SendMessage(Message &aMessage, const Ip6::Address &aDestination);
-
-    /**
      * This method sets the RLOC16 assigned to the Thread interface.
      *
      * @param[in]  aRloc16  The RLOC16 to set.
@@ -1439,20 +1543,7 @@
      */
     void SetLeaderData(uint32_t aPartitionId, uint8_t aWeighting, uint8_t aLeaderRouterId);
 
-    /**
-     * This method adds a message to the message queue. The queued message will be transmitted after given delay.
-     *
-     * @param[in]  aMessage             The message to transmit after given delay.
-     * @param[in]  aDestination         The IPv6 address of the recipient of the message.
-     * @param[in]  aDelay               The delay in milliseconds before transmission of the message.
-     *
-     * @retval kErrorNone     Successfully queued the message to transmit after the delay.
-     * @retval kErrorNoBufs   Insufficient buffers to queue the message.
-     *
-     */
-    Error AddDelayedResponse(Message &aMessage, const Ip6::Address &aDestination, uint16_t aDelay);
-
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MLE == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
     /**
      * This static method emits a log message with an IPv6 address.
      *
@@ -1476,9 +1567,9 @@
 #else
     static void Log(MessageAction, MessageType, const Ip6::Address &) {}
     static void Log(MessageAction, MessageType, const Ip6::Address &, uint16_t) {}
-#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MLE == 1)
+#endif // #if OT_SHOULD_LOG_AT( OT_LOG_LEVEL_INFO)
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN) && (OPENTHREAD_CONFIG_LOG_MLE == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
     /**
      * This static method emits a log message indicating an error in processing of a message.
      *
@@ -1505,7 +1596,7 @@
 #else
     static void LogProcessError(MessageType, Error) {}
     static void LogSendError(MessageType, Error) {}
-#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN) && (OPENTHREAD_CONFIG_LOG_MLE == 1)
+#endif // #if OT_SHOULD_LOG_AT( OT_LOG_LEVEL_WARN)
 
     /**
      * This method triggers MLE Announce on previous channel after the Thread device successfully
@@ -1525,7 +1616,7 @@
      */
     bool IsAnnounceAttach(void) const { return mAlternatePanId != Mac::kPanIdBroadcast; }
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MLE == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
     /**
      * This method converts an `AttachMode` enumeration value into a human-readable string.
      *
@@ -1588,6 +1679,15 @@
 
 #endif
 
+    /**
+     * This method indicates whether the device is detaching gracefully.
+     *
+     * @retval TRUE  Detaching is in progress.
+     * @retval FALSE Not detaching.
+     *
+     */
+    bool IsDetachingGracefully(void) { return mDetachGracefullyTimer.IsRunning(); }
+
     Ip6::Netif::UnicastAddress mLeaderAloc; ///< Leader anycast locator
 
     LeaderData    mLeaderData;               ///< Last received Leader Data TLV.
@@ -1597,15 +1697,22 @@
     Router        mParentCandidate;          ///< Parent candidate information.
     NeighborTable mNeighborTable;            ///< The neighbor table.
     DeviceMode    mDeviceMode;               ///< Device mode setting.
-    AttachState   mAttachState;              ///< The parent request state.
+    AttachState   mAttachState;              ///< The attach state.
+    uint8_t       mParentRequestCounter;     ///< Number of parent requests while in `kAttachStateParentRequest`.
     ReattachState mReattachState;            ///< Reattach state
     uint16_t      mAttachCounter;            ///< Attach attempt counter.
     uint16_t      mAnnounceDelay;            ///< Delay in between sending Announce messages during attach.
     TimerMilli    mAttachTimer;              ///< The timer for driving the attach process.
     TimerMilli    mDelayedResponseTimer;     ///< The timer to delay MLE responses.
     TimerMilli    mMessageTransmissionTimer; ///< The timer for (re-)sending of MLE messages (e.g. Child Update).
+    TimerMilli    mDetachGracefullyTimer;
     uint8_t       mParentLeaderCost;
 
+    otDetachGracefullyCallback mDetachGracefullyCallback;
+    void *                     mDetachGracefullyContext;
+
+    static constexpr uint32_t kDetachGracefullyTimeout = 1000;
+
 private:
     static constexpr uint8_t kMleHopLimit        = 255;
     static constexpr uint8_t kMleSecurityTagSize = 4; // Security tag size in bytes.
@@ -1624,6 +1731,20 @@
     static constexpr uint32_t kAttachBackoffDelayToResetCounter =
         OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_DELAY_TO_RESET_BACKOFF_INTERVAL;
 
+#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_3
+    // First attach cycle includes two Parent Requests to routers, followed by four to routers and REEDs.
+    static constexpr uint8_t kFirstAttachCycleTotalParentRequests       = 6;
+    static constexpr uint8_t kFirstAttachCycleNumParentRequestToRouters = 2;
+#else
+    // First attach cycle in Thread 1.1/1.2 includes a Parent Requests to routers, followed by one to routers and REEDs.
+    static constexpr uint8_t kFirstAttachCycleTotalParentRequests       = 2;
+    static constexpr uint8_t kFirstAttachCycleNumParentRequestToRouters = 1;
+#endif
+
+    // Next attach cycles includes one Parent Request to routers, followed by one to routers and REEDs.
+    static constexpr uint8_t kNextAttachCycleTotalParentRequests       = 2;
+    static constexpr uint8_t kNextAttachCycleNumParentRequestToRouters = 1;
+
     enum StartMode : uint8_t // Used in `Start()`.
     {
         kNormalAttach,
@@ -1644,8 +1765,8 @@
 
     enum ParentRequestType : uint8_t
     {
-        kParentRequestTypeRouters,         // Parent Request to all routers.
-        kParentRequestTypeRoutersAndReeds, // Parent Request to all routers and REEDs.
+        kToRouters,         // Parent Request to routers only.
+        kToRoutersAndReeds, // Parent Request to all routers and REEDs.
     };
 
     enum ChildUpdateRequestState : uint8_t
@@ -1661,6 +1782,12 @@
         kDataRequestActive, // Data Request has been sent, Data Response is expected.
     };
 
+    enum SecuritySuite : uint8_t
+    {
+        k154Security = 0,   // Security suite value indicating that MLE message is not secured.
+        kNoSecurity  = 255, // Security suite value indicating that MLE message is secured.
+    };
+
     struct DelayedResponseMetadata
     {
         Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
@@ -1672,97 +1799,47 @@
     };
 
     OT_TOOL_PACKED_BEGIN
-    class Header
+    class SecurityHeader
     {
     public:
-        enum SecuritySuite : uint8_t
-        {
-            k154Security = 0,
-            kNoSecurity  = 255,
-        };
+        void InitSecurityControl(void) { mSecurityControl = kKeyIdMode2Mic32; }
+        bool IsSecurityControlValid(void) const { return (mSecurityControl == kKeyIdMode2Mic32); }
 
-        void Init(void)
-        {
-            mSecuritySuite   = k154Security;
-            mSecurityControl = Mac::Frame::kSecEncMic32;
-        }
-
-        bool IsValid(void) const
-        {
-            return (mSecuritySuite == kNoSecurity) ||
-                   (mSecuritySuite == k154Security &&
-                    mSecurityControl == (Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecEncMic32));
-        }
-
-        uint8_t GetLength(void) const
-        {
-            return sizeof(mSecuritySuite) + sizeof(mCommand) +
-                   ((mSecuritySuite == k154Security)
-                        ? sizeof(mSecurityControl) + sizeof(mFrameCounter) + sizeof(mKeySource) + sizeof(mKeyIndex)
-                        : 0);
-        }
-
-        SecuritySuite GetSecuritySuite(void) const { return static_cast<SecuritySuite>(mSecuritySuite); }
-        void SetSecuritySuite(SecuritySuite aSecuritySuite) { mSecuritySuite = static_cast<uint8_t>(aSecuritySuite); }
-
-        uint8_t GetHeaderLength(void) const
-        {
-            return sizeof(mSecurityControl) + sizeof(mFrameCounter) + sizeof(mKeySource) + sizeof(mKeyIndex);
-        }
-
-        const uint8_t *GetBytes(void) const { return reinterpret_cast<const uint8_t *>(&mSecuritySuite); }
-        uint8_t        GetSecurityControl(void) const { return mSecurityControl; }
-
-        bool IsKeyIdMode2(void) const
-        {
-            return (mSecurityControl & Mac::Frame::kKeyIdModeMask) == Mac::Frame::kKeyIdMode2;
-        }
-
-        void SetKeyIdMode2(void)
-        {
-            mSecurityControl = (mSecurityControl & ~Mac::Frame::kKeyIdModeMask) | Mac::Frame::kKeyIdMode2;
-        }
+        uint32_t GetFrameCounter(void) const { return Encoding::LittleEndian::HostSwap32(mFrameCounter); }
+        void     SetFrameCounter(uint32_t aCounter) { mFrameCounter = Encoding::LittleEndian::HostSwap32(aCounter); }
 
         uint32_t GetKeyId(void) const { return Encoding::BigEndian::HostSwap32(mKeySource); }
-
-        void SetKeyId(uint32_t aKeySequence)
+        void     SetKeyId(uint32_t aKeySequence)
         {
             mKeySource = Encoding::BigEndian::HostSwap32(aKeySequence);
             mKeyIndex  = (aKeySequence & 0x7f) + 1;
         }
 
-        uint32_t GetFrameCounter(void) const { return Encoding::LittleEndian::HostSwap32(mFrameCounter); }
-        void     SetFrameCounter(uint32_t aFrameCounter)
-        {
-            mFrameCounter = Encoding::LittleEndian::HostSwap32(aFrameCounter);
-        }
-
-        Command GetCommand(void) const
-        {
-            return static_cast<Command>((mSecuritySuite == kNoSecurity) ? mSecurityControl : mCommand);
-        }
-
-        void SetCommand(Command aCommand)
-        {
-            if (mSecuritySuite == kNoSecurity)
-            {
-                mSecurityControl = static_cast<uint8_t>(aCommand);
-            }
-            else
-            {
-                mCommand = static_cast<uint8_t>(aCommand);
-            }
-        }
-
     private:
-        uint8_t  mSecuritySuite;
+        static constexpr uint8_t kKeyIdMode2Mic32 = (Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecEncMic32);
+
         uint8_t  mSecurityControl;
         uint32_t mFrameCounter;
         uint32_t mKeySource;
         uint8_t  mKeyIndex;
-        uint8_t  mCommand;
     } OT_TOOL_PACKED_END;
 
+#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
+    class ServiceAloc : public Ip6::Netif::UnicastAddress
+    {
+    public:
+        static constexpr uint16_t kNotInUse = Mac::kShortAddrInvalid;
+
+        ServiceAloc(void);
+
+        bool     IsInUse(void) const { return GetAloc16() != kNotInUse; }
+        void     MarkAsNotInUse(void) { SetAloc16(kNotInUse); }
+        uint16_t GetAloc16(void) const { return GetAddress().GetIid().GetLocator(); }
+        void     SetAloc16(uint16_t aAloc16) { GetAddress().GetIid().SetLocator(aAloc16); }
+        void     ApplyMeshLocalPrefix(const Ip6::NetworkPrefix &aPrefix) { GetAddress().SetPrefix(aPrefix); }
+    };
+#endif
+
     Error       Start(StartMode aMode);
     void        Stop(StopMode aMode);
     void        HandleNotifierEvents(Events aEvents);
@@ -1770,57 +1847,64 @@
     void        HandleAttachTimer(void);
     static void HandleDelayedResponseTimer(Timer &aTimer);
     void        HandleDelayedResponseTimer(void);
+    void        SendDelayedResponse(TxMessage &aMessage, const DelayedResponseMetadata &aMetadata);
     static void HandleMessageTransmissionTimer(Timer &aTimer);
     void        HandleMessageTransmissionTimer(void);
     static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
     void        HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
     void        ScheduleMessageTransmissionTimer(void);
-    Error       ReadChallengeOrResponse(const Message &aMessage, uint8_t aTlvType, Challenge &aBuffer);
+    void        ReestablishLinkWithNeighbor(Neighbor &aNeighbor);
+    static void HandleDetachGracefullyTimer(Timer &aTimer);
+    void        HandleDetachGracefullyTimer(void);
+    Error       SendChildUpdateRequest(bool aAppendChallenge, uint32_t aTimeout);
 
-    void HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor);
-    void HandleChildIdResponse(const Message &         aMessage,
-                               const Ip6::MessageInfo &aMessageInfo,
-                               const Neighbor *        aNeighbor);
-    void HandleChildUpdateRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor);
-    void HandleChildUpdateResponse(const Message &         aMessage,
-                                   const Ip6::MessageInfo &aMessageInfo,
-                                   const Neighbor *        aNeighbor);
-    void HandleDataResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const Neighbor *aNeighbor);
-    void HandleParentResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, uint32_t aKeySequence);
-    void HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+#if OPENTHREAD_FTD
+    static void HandleDetachGracefullyAddressReleaseResponse(void *               aContext,
+                                                             otMessage *          aMessage,
+                                                             const otMessageInfo *aMessageInfo,
+                                                             Error                aResult);
+    void        HandleDetachGracefullyAddressReleaseResponse(void);
+#endif
+
+    void HandleAdvertisement(RxInfo &aRxInfo);
+    void HandleChildIdResponse(RxInfo &aRxInfo);
+    void HandleChildUpdateRequest(RxInfo &aRxInfo);
+    void HandleChildUpdateResponse(RxInfo &aRxInfo);
+    void HandleDataResponse(RxInfo &aRxInfo);
+    void HandleParentResponse(RxInfo &aRxInfo);
+    void HandleAnnounce(RxInfo &aRxInfo);
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
-    void HandleLinkMetricsManagementRequest(const Message &         aMessage,
-                                            const Ip6::MessageInfo &aMessageInfo,
-                                            Neighbor *              aNeighbor);
+    void HandleLinkMetricsManagementRequest(RxInfo &aRxInfo);
 #endif
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
-    void HandleLinkMetricsManagementResponse(const Message &         aMessage,
-                                             const Ip6::MessageInfo &aMessageInfo,
-                                             Neighbor *              aNeighbor);
+    void HandleLinkMetricsManagementResponse(RxInfo &aRxInfo);
 #endif
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
-    void HandleLinkProbe(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor);
+    void HandleLinkProbe(RxInfo &aRxInfo);
 #endif
-    Error HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+    Error HandleLeaderData(RxInfo &aRxInfo);
     void  ProcessAnnounce(void);
     bool  HasUnregisteredAddress(void);
 
     uint32_t GetAttachStartDelay(void) const;
-    Error    SendParentRequest(ParentRequestType aType);
+    void     SendParentRequest(ParentRequestType aType);
     Error    SendChildIdRequest(void);
     Error    GetNextAnnouceChannel(uint8_t &aChannel) const;
     bool     HasMoreChannelsToAnnouce(void) const;
     bool     PrepareAnnounceState(void);
     void     SendAnnounce(uint8_t aChannel, AnnounceMode aMode);
     void     SendAnnounce(uint8_t aChannel, const Ip6::Address &aDestination, AnnounceMode aMode = kNormalAnnounce);
-    void     RemoveDelayedDataRequestMessage(const Ip6::Address &aDestination);
+    void RemoveDelayedMessage(Message::SubType aSubType, MessageType aMessageType, const Ip6::Address *aDestination);
+    void RemoveDelayedDataRequestMessage(const Ip6::Address &aDestination);
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
     Error SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, LinkMetrics::Status aStatus);
 #endif
     uint32_t Reattach(void);
+    bool     HasAcceptableParentCandidate(void) const;
+    Error    DetermineParentRequestType(ParentRequestType &aType) const;
 
     bool IsBetterParent(uint16_t               aRloc16,
-                        uint8_t                aLinkQuality,
+                        LinkQuality            aLinkQuality,
                         uint8_t                aLinkMargin,
                         const ConnectivityTlv &aConnectivityTlv,
                         uint8_t                aVersion,
@@ -1828,12 +1912,15 @@
                         uint8_t                aCslUncertainty);
     bool IsNetworkDataNewer(const LeaderData &aLeaderData);
 
+    Error ProcessMessageSecurity(Crypto::AesCcm::Mode    aMode,
+                                 Message &               aMessage,
+                                 const Ip6::MessageInfo &aMessageInfo,
+                                 uint16_t                aCmdOffset,
+                                 const SecurityHeader &  aHeader);
+
 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-    /**
-     * This method scans for network data from the leader and updates IP addresses assigned to this
-     * interface to make sure that all Service ALOCs (0xfc10-0xfc1f) are properly set.
-     */
-    void UpdateServiceAlocs(void);
+    ServiceAloc *FindInServiceAlocs(uint16_t aAloc16);
+    void         UpdateServiceAlocs(void);
 #endif
 
 #if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
@@ -1847,7 +1934,7 @@
     void        UpdateParentSearchState(void);
 #endif
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN) && (OPENTHREAD_CONFIG_LOG_MLE == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
     static void        LogError(MessageAction aAction, MessageType aType, Error aError);
     static const char *MessageActionToString(MessageAction aAction);
     static const char *MessageTypeToString(MessageType aType);
@@ -1858,7 +1945,7 @@
 
     Challenge mParentRequestChallenge;
 
-    AttachMode mParentRequestMode;
+    AttachMode mAttachMode;
     int8_t     mParentPriority;
     uint8_t    mParentLinkQuality3;
     uint8_t    mParentLinkQuality2;
@@ -1887,9 +1974,7 @@
     uint32_t mCslTimeout;
 #endif
 
-#if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
     uint16_t mPreviousParentRloc;
-#endif
 
 #if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
     bool       mParentSearchIsInBackoff : 1;
@@ -1905,11 +1990,13 @@
     uint64_t mAlternateTimestamp;
 
 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-    Ip6::Netif::UnicastAddress mServiceAlocs[kMaxServiceAlocs];
+    ServiceAloc mServiceAlocs[kMaxServiceAlocs];
 #endif
 
     otMleCounters mCounters;
 
+    static const otMeshLocalPrefix sMeshLocalPrefixInit;
+
     Ip6::Netif::UnicastAddress   mLinkLocal64;
     Ip6::Netif::UnicastAddress   mMeshLocal64;
     Ip6::Netif::UnicastAddress   mMeshLocal16;
diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp
index af41b00..d630347 100644
--- a/src/core/thread/mle_router.cpp
+++ b/src/core/thread/mle_router.cpp
@@ -40,8 +40,8 @@
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
 #include "common/random.hpp"
+#include "common/serial_number.hpp"
 #include "common/settings.hpp"
 #include "mac/mac_types.hpp"
 #include "meshcop/meshcop.hpp"
@@ -56,6 +56,8 @@
 namespace ot {
 namespace Mle {
 
+RegisterLogModule("Mle");
+
 MleRouter::MleRouter(Instance &aInstance)
     : Mle(aInstance)
     , mAdvertiseTrickleTimer(aInstance, MleRouter::HandleAdvertiseTrickleTimer)
@@ -72,6 +74,7 @@
 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
     , mPreferredLeaderPartitionId(0)
     , mCcmEnabled(false)
+    , mThreadVersionCheckEnabled(true)
 #endif
     , mRouterEligible(true)
     , mAddressSolicitPending(false)
@@ -82,6 +85,7 @@
     , mPreviousPartitionIdTimeout(0)
     , mRouterSelectionJitter(kRouterSelectionJitter)
     , mRouterSelectionJitterTimeout(0)
+    , mLinkRequestDelay(0)
     , mParentPriority(kParentPriorityUnspecified)
 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
     , mBackboneRouterRegistrationDelay(0)
@@ -132,8 +136,14 @@
     }
     if (!secPolicy.mRoutersEnabled)
     {
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+        VerifyOrExit(!mThreadVersionCheckEnabled ||
+                     secPolicy.mVersionThresholdForRouting + SecurityPolicy::kVersionThresholdOffsetVersion <=
+                         kThreadVersion);
+#else
         VerifyOrExit(secPolicy.mVersionThresholdForRouting + SecurityPolicy::kVersionThresholdOffsetVersion <=
                      kThreadVersion);
+#endif
     }
 #endif
 
@@ -183,10 +193,11 @@
     VerifyOrExit(!IsRouter(), error = kErrorNone);
     VerifyOrExit(IsRouterEligible(), error = kErrorNotCapable);
 
-    otLogInfoMle("Attempt to become router");
+    LogInfo("Attempt to become router");
 
     Get<MeshForwarder>().SetRxOnWhenIdle(true);
     mRouterSelectionJitterTimeout = 0;
+    mLinkRequestDelay             = 0;
 
     switch (mRole)
     {
@@ -214,8 +225,12 @@
     Router * router;
     uint32_t partitionId;
     uint8_t  leaderId;
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+    uint8_t minRouterId;
+    uint8_t maxRouterId;
+#endif
 
-    VerifyOrExit(!Get<MeshCoP::ActiveDataset>().IsPartiallyComplete(), error = kErrorInvalidState);
+    VerifyOrExit(!Get<MeshCoP::ActiveDatasetManager>().IsPartiallyComplete(), error = kErrorInvalidState);
     VerifyOrExit(!IsDisabled(), error = kErrorInvalidState);
     VerifyOrExit(!IsLeader(), error = kErrorNone);
     VerifyOrExit(IsRouterEligible(), error = kErrorNotCapable);
@@ -228,8 +243,20 @@
     partitionId = Random::NonCrypto::GetUint32();
 #endif
 
-    leaderId = IsRouterIdValid(mPreviousRouterId) ? mPreviousRouterId
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+    mRouterTable.GetRouterIdRange(minRouterId, maxRouterId);
+    if (IsRouterIdValid(mPreviousRouterId) && minRouterId <= mPreviousRouterId && mPreviousRouterId <= maxRouterId)
+    {
+        leaderId = mPreviousRouterId;
+    }
+    else
+    {
+        leaderId = Random::NonCrypto::GetUint8InRange(minRouterId, maxRouterId + 1);
+    }
+#else
+    leaderId    = IsRouterIdValid(mPreviousRouterId) ? mPreviousRouterId
                                                   : Random::NonCrypto::GetUint8InRange(0, kMaxRouterId + 1);
+#endif
 
     SetLeaderData(partitionId, mLeaderWeight, leaderId);
 
@@ -242,7 +269,7 @@
     Get<NetworkData::Leader>().Reset();
     Get<MeshCoP::Leader>().SetEmptyCommissionerData();
 
-    SetStateLeader(Rloc16FromRouterId(leaderId));
+    SetStateLeader(Rloc16FromRouterId(leaderId), kStartingAsLeader);
 
 exit:
     return error;
@@ -252,8 +279,8 @@
 {
     Get<Tmf::Agent>().RemoveResource(mAddressSolicit);
     Get<Tmf::Agent>().RemoveResource(mAddressRelease);
-    Get<MeshCoP::ActiveDataset>().StopLeader();
-    Get<MeshCoP::PendingDataset>().StopLeader();
+    Get<MeshCoP::ActiveDatasetManager>().StopLeader();
+    Get<MeshCoP::PendingDatasetManager>().StopLeader();
     StopAdvertiseTrickleTimer();
     Get<NetworkData::Leader>().Stop();
     Get<ThreadNetif>().UnsubscribeAllRoutersMulticast();
@@ -268,7 +295,7 @@
 
 void MleRouter::HandleChildStart(AttachMode aMode)
 {
-    // reset `rejected` flag whenever REED becomes child.
+    mLinkRequestDelay       = 0;
     mAddressSolicitRejected = false;
 
     mRouterSelectionJitterTimeout = 1 + Random::NonCrypto::GetUint8InRange(0, mRouterSelectionJitter);
@@ -287,7 +314,7 @@
 
     switch (aMode)
     {
-    case kAttachSameDowngrade:
+    case kDowngradeToReed:
         SendAddressRelease();
 
         // reset children info if any
@@ -300,8 +327,8 @@
         SetRouterId(kInvalidRouterId);
         break;
 
-    case kAttachSame1:
-    case kAttachSame2:
+    case kSamePartition:
+    case kSamePartitionRetry:
         if (HasChildren())
         {
             IgnoreError(BecomeRouter(ThreadStatusTlv::kHaveChildIdRequest));
@@ -309,7 +336,8 @@
 
         break;
 
-    case kAttachAny:
+    case kAnyPartition:
+    case kBetterParent:
         // If attach was started due to receiving MLE Announce Messages, all rx-on-when-idle devices would
         // start attach immediately when receiving such Announce message as in Thread 1.1 specification,
         // Section 4.8.1,
@@ -326,7 +354,7 @@
 
         OT_FALL_THROUGH;
 
-    case kAttachBetter:
+    case kBetterPartition:
         if (HasChildren() && mPreviousPartitionIdRouter != mLeaderData.GetPartitionId())
         {
             IgnoreError(BecomeRouter(ThreadStatusTlv::kParentPartitionChange));
@@ -371,12 +399,16 @@
             RemoveNeighbor(child);
         }
     }
+
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+    Get<Mac::Mac>().UpdateCsl();
+#endif
 }
 
-void MleRouter::SetStateLeader(uint16_t aRloc16)
+void MleRouter::SetStateLeader(uint16_t aRloc16, LeaderStartMode aStartMode)
 {
-    IgnoreError(Get<MeshCoP::ActiveDataset>().Restore());
-    IgnoreError(Get<MeshCoP::PendingDataset>().Restore());
+    IgnoreError(Get<MeshCoP::ActiveDatasetManager>().Restore());
+    IgnoreError(Get<MeshCoP::PendingDatasetManager>().Restore());
     SetRloc16(aRloc16);
 
     SetRole(kRoleLeader);
@@ -393,9 +425,9 @@
     mPreviousPartitionIdRouter = mLeaderData.GetPartitionId();
     Get<TimeTicker>().RegisterReceiver(TimeTicker::kMleRouter);
 
-    Get<NetworkData::Leader>().Start();
-    Get<MeshCoP::ActiveDataset>().StartLeader();
-    Get<MeshCoP::PendingDataset>().StartLeader();
+    Get<NetworkData::Leader>().Start(aStartMode);
+    Get<MeshCoP::ActiveDatasetManager>().StartLeader();
+    Get<MeshCoP::PendingDatasetManager>().StartLeader();
     Get<Tmf::Agent>().AddResource(mAddressSolicit);
     Get<Tmf::Agent>().AddResource(mAddressRelease);
     Get<Ip6::Ip6>().SetForwardingEnabled(true);
@@ -412,7 +444,11 @@
         }
     }
 
-    otLogNoteMle("Leader partition id 0x%x", mLeaderData.GetPartitionId());
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+    Get<Mac::Mac>().UpdateCsl();
+#endif
+
+    LogNote("Leader partition id 0x%x", mLeaderData.GetPartitionId());
 }
 
 void MleRouter::HandleAdvertiseTrickleTimer(TrickleTimer &aTimer)
@@ -455,7 +491,7 @@
 {
     Error        error = kErrorNone;
     Ip6::Address destination;
-    Message *    message = nullptr;
+    TxMessage *  message = nullptr;
 
     // Suppress MLE Advertisements when trying to attach to a better partition.
     //
@@ -470,10 +506,14 @@
     // children to detach.
     VerifyOrExit(!mAddressSolicitPending);
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    SuccessOrExit(error = AppendHeader(*message, kCommandAdvertisement));
-    SuccessOrExit(error = AppendSourceAddress(*message));
-    SuccessOrExit(error = AppendLeaderData(*message));
+    // Suppress MLE Advertisements before sending multicast Link Request.
+    //
+    // Before sending the multicast Link Request message, no links have been established to neighboring routers.
+    VerifyOrExit(mLinkRequestDelay == 0);
+
+    VerifyOrExit((message = NewMleMessage(kCommandAdvertisement)) != nullptr, error = kErrorNoBufs);
+    SuccessOrExit(error = message->AppendSourceAddressTlv());
+    SuccessOrExit(error = message->AppendLeaderDataTlv());
 
     switch (mRole)
     {
@@ -487,12 +527,12 @@
 
     case kRoleRouter:
     case kRoleLeader:
-        SuccessOrExit(error = AppendRoute(*message));
+        SuccessOrExit(error = message->AppendRouteTlv());
         break;
     }
 
     destination.SetToLinkLocalAllNodesMulticast();
-    SuccessOrExit(error = SendMessage(*message, destination));
+    SuccessOrExit(error = message->SendTo(destination));
 
     Log(kMessageSend, kTypeAdvertisement, destination);
 
@@ -507,14 +547,15 @@
     static const uint8_t routerTlvs[]        = {Tlv::kLinkMargin};
     static const uint8_t validNeighborTlvs[] = {Tlv::kLinkMargin, Tlv::kRoute};
     Error                error               = kErrorNone;
-    Message *            message;
+    TxMessage *          message             = nullptr;
     Ip6::Address         destination;
 
+    VerifyOrExit(mLinkRequestDelay == 0 && mChallengeTimeout == 0);
+
     destination.Clear();
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    SuccessOrExit(error = AppendHeader(*message, kCommandLinkRequest));
-    SuccessOrExit(error = AppendVersion(*message));
+    VerifyOrExit((message = NewMleMessage(kCommandLinkRequest)) != nullptr, error = kErrorNoBufs);
+    SuccessOrExit(error = message->AppendVersionTlv());
 
     switch (mRole)
     {
@@ -523,32 +564,32 @@
         OT_UNREACHABLE_CODE(break);
 
     case kRoleDetached:
-        SuccessOrExit(error = AppendTlvRequest(*message, detachedTlvs, sizeof(detachedTlvs)));
+        SuccessOrExit(error = message->AppendTlvRequestTlv(detachedTlvs, sizeof(detachedTlvs)));
         break;
 
     case kRoleChild:
-        SuccessOrExit(error = AppendSourceAddress(*message));
-        SuccessOrExit(error = AppendLeaderData(*message));
+        SuccessOrExit(error = message->AppendSourceAddressTlv());
+        SuccessOrExit(error = message->AppendLeaderDataTlv());
         break;
 
     case kRoleRouter:
     case kRoleLeader:
         if (aNeighbor == nullptr || !aNeighbor->IsStateValid())
         {
-            SuccessOrExit(error = AppendTlvRequest(*message, routerTlvs, sizeof(routerTlvs)));
+            SuccessOrExit(error = message->AppendTlvRequestTlv(routerTlvs, sizeof(routerTlvs)));
         }
         else
         {
-            SuccessOrExit(error = AppendTlvRequest(*message, validNeighborTlvs, sizeof(validNeighborTlvs)));
+            SuccessOrExit(error = message->AppendTlvRequestTlv(validNeighborTlvs, sizeof(validNeighborTlvs)));
         }
 
-        SuccessOrExit(error = AppendSourceAddress(*message));
-        SuccessOrExit(error = AppendLeaderData(*message));
+        SuccessOrExit(error = message->AppendSourceAddressTlv());
+        SuccessOrExit(error = message->AppendLeaderDataTlv());
         break;
     }
 
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-    SuccessOrExit(error = AppendTimeRequest(*message));
+    SuccessOrExit(error = message->AppendTimeRequestTlv());
 #endif
 
     if (aNeighbor == nullptr)
@@ -556,7 +597,7 @@
         mChallenge.GenerateRandom();
         mChallengeTimeout = (((2 * kMaxResponseDelay) + kStateUpdatePeriod - 1) / kStateUpdatePeriod);
 
-        SuccessOrExit(error = AppendChallenge(*message, mChallenge));
+        SuccessOrExit(error = message->AppendChallengeTlv(mChallenge));
         destination.SetToLinkLocalAllRoutersMulticast();
     }
     else
@@ -564,20 +605,21 @@
         if (!aNeighbor->IsStateValid())
         {
             aNeighbor->GenerateChallenge();
-            SuccessOrExit(error = AppendChallenge(*message, aNeighbor->GetChallenge(), aNeighbor->GetChallengeSize()));
+            SuccessOrExit(error =
+                              message->AppendChallengeTlv(aNeighbor->GetChallenge(), aNeighbor->GetChallengeSize()));
         }
         else
         {
             Challenge challenge;
 
             challenge.GenerateRandom();
-            SuccessOrExit(error = AppendChallenge(*message, challenge));
+            SuccessOrExit(error = message->AppendChallengeTlv(challenge));
         }
 
         destination.SetToLinkLocalAddress(aNeighbor->GetExtAddress());
     }
 
-    SuccessOrExit(error = SendMessage(*message, destination));
+    SuccessOrExit(error = message->SendTo(destination));
 
     Log(kMessageSend, kTypeLinkRequest, destination);
 
@@ -586,7 +628,7 @@
     return error;
 }
 
-void MleRouter::HandleLinkRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor)
+void MleRouter::HandleLinkRequest(RxInfo &aRxInfo)
 {
     Error         error    = kErrorNone;
     Neighbor *    neighbor = nullptr;
@@ -596,21 +638,21 @@
     uint16_t      sourceAddress;
     RequestedTlvs requestedTlvs;
 
-    Log(kMessageReceive, kTypeLinkRequest, aMessageInfo.GetPeerAddr());
+    Log(kMessageReceive, kTypeLinkRequest, aRxInfo.mMessageInfo.GetPeerAddr());
 
     VerifyOrExit(IsRouterOrLeader(), error = kErrorInvalidState);
 
     VerifyOrExit(!IsAttaching(), error = kErrorInvalidState);
 
     // Challenge
-    SuccessOrExit(error = ReadChallenge(aMessage, challenge));
+    SuccessOrExit(error = aRxInfo.mMessage.ReadChallengeTlv(challenge));
 
     // Version
-    SuccessOrExit(error = Tlv::Find<VersionTlv>(aMessage, version));
+    SuccessOrExit(error = Tlv::Find<VersionTlv>(aRxInfo.mMessage, version));
     VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = kErrorParse);
 
     // Leader Data
-    switch (ReadLeaderData(aMessage, leaderData))
+    switch (aRxInfo.mMessage.ReadLeaderDataTlv(leaderData))
     {
     case kErrorNone:
         VerifyOrExit(leaderData.GetPartitionId() == mLeaderData.GetPartitionId(), error = kErrorInvalidState);
@@ -622,14 +664,14 @@
     }
 
     // Source Address
-    switch (Tlv::Find<SourceAddressTlv>(aMessage, sourceAddress))
+    switch (Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress))
     {
     case kErrorNone:
         if (IsActiveRouter(sourceAddress))
         {
             Mac::ExtAddress extAddr;
 
-            aMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
+            aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
 
             neighbor = mRouterTable.GetRouter(RouterIdFromRloc16(sourceAddress));
             VerifyOrExit(neighbor != nullptr, error = kErrorParse);
@@ -639,7 +681,7 @@
             {
                 neighbor->SetExtAddress(extAddr);
                 neighbor->GetLinkInfo().Clear();
-                neighbor->GetLinkInfo().AddRss(aMessageInfo.GetThreadLinkInfo()->GetRss());
+                neighbor->GetLinkInfo().AddRss(aRxInfo.mMessageInfo.GetThreadLinkInfo()->GetRss());
                 neighbor->ResetLinkFailures();
                 neighbor->SetLastHeard(TimerMilli::GetNow());
                 neighbor->SetState(Neighbor::kStateLinkRequest);
@@ -654,9 +696,10 @@
 
     case kErrorNotFound:
         // lack of source address indicates router coming out of reset
-        VerifyOrExit(aNeighbor && aNeighbor->IsStateValid() && IsActiveRouter(aNeighbor->GetRloc16()),
+        VerifyOrExit(aRxInfo.mNeighbor && aRxInfo.mNeighbor->IsStateValid() &&
+                         IsActiveRouter(aRxInfo.mNeighbor->GetRloc16()),
                      error = kErrorDrop);
-        neighbor = aNeighbor;
+        neighbor = aRxInfo.mNeighbor;
         break;
 
     default:
@@ -664,7 +707,7 @@
     }
 
     // TLV Request
-    switch (FindTlvRequest(aMessage, requestedTlvs))
+    switch (aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvs))
     {
     case kErrorNone:
         break;
@@ -678,7 +721,7 @@
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
     if (neighbor != nullptr)
     {
-        neighbor->SetTimeSyncEnabled(Tlv::Find<TimeRequestTlv>(aMessage, nullptr, 0) == kErrorNone);
+        neighbor->SetTimeSyncEnabled(Tlv::Find<TimeRequestTlv>(aRxInfo.mMessage, nullptr, 0) == kErrorNone);
     }
 #endif
 
@@ -689,7 +732,9 @@
     }
 #endif
 
-    SuccessOrExit(error = SendLinkAccept(aMessageInfo, neighbor, requestedTlvs, challenge));
+    aRxInfo.mClass = RxInfo::kPeerMessage;
+
+    SuccessOrExit(error = SendLinkAccept(aRxInfo.mMessageInfo, neighbor, requestedTlvs, challenge));
 
 exit:
     LogProcessError(kTypeLinkRequest, error);
@@ -702,29 +747,28 @@
 {
     Error                error        = kErrorNone;
     static const uint8_t routerTlvs[] = {Tlv::kLinkMargin};
-    Message *            message;
+    TxMessage *          message;
     Command              command;
     uint8_t              linkMargin;
 
     command = (aNeighbor == nullptr || aNeighbor->IsStateValid()) ? kCommandLinkAccept : kCommandLinkAcceptAndRequest;
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    SuccessOrExit(error = AppendHeader(*message, command));
-    SuccessOrExit(error = AppendVersion(*message));
-    SuccessOrExit(error = AppendSourceAddress(*message));
-    SuccessOrExit(error = AppendResponse(*message, aChallenge));
-    SuccessOrExit(error = AppendLinkFrameCounter(*message));
-    SuccessOrExit(error = AppendMleFrameCounter(*message));
+    VerifyOrExit((message = NewMleMessage(command)) != nullptr, error = kErrorNoBufs);
+    SuccessOrExit(error = message->AppendVersionTlv());
+    SuccessOrExit(error = message->AppendSourceAddressTlv());
+    SuccessOrExit(error = message->AppendResponseTlv(aChallenge));
+    SuccessOrExit(error = message->AppendLinkFrameCounterTlv());
+    SuccessOrExit(error = message->AppendMleFrameCounterTlv());
 
     // always append a link margin, regardless of whether or not it was requested
     linkMargin = LinkQualityInfo::ConvertRssToLinkMargin(Get<Mac::Mac>().GetNoiseFloor(),
                                                          aMessageInfo.GetThreadLinkInfo()->GetRss());
 
-    SuccessOrExit(error = AppendLinkMargin(*message, linkMargin));
+    SuccessOrExit(error = message->AppendLinkMarginTlv(linkMargin));
 
     if (aNeighbor != nullptr && IsActiveRouter(aNeighbor->GetRloc16()))
     {
-        SuccessOrExit(error = AppendLeaderData(*message));
+        SuccessOrExit(error = message->AppendLeaderDataTlv());
     }
 
     for (uint8_t i = 0; i < aRequestedTlvs.mNumTlvs; i++)
@@ -732,12 +776,12 @@
         switch (aRequestedTlvs.mTlvs[i])
         {
         case Tlv::kRoute:
-            SuccessOrExit(error = AppendRoute(*message, aNeighbor));
+            SuccessOrExit(error = message->AppendRouteTlv(aNeighbor));
             break;
 
         case Tlv::kAddress16:
             VerifyOrExit(aNeighbor != nullptr, error = kErrorDrop);
-            SuccessOrExit(error = AppendAddress16(*message, aNeighbor->GetRloc16()));
+            SuccessOrExit(error = message->AppendAddress16Tlv(aNeighbor->GetRloc16()));
             break;
 
         case Tlv::kLinkMargin:
@@ -752,8 +796,8 @@
     {
         aNeighbor->GenerateChallenge();
 
-        SuccessOrExit(error = AppendChallenge(*message, aNeighbor->GetChallenge(), aNeighbor->GetChallengeSize()));
-        SuccessOrExit(error = AppendTlvRequest(*message, routerTlvs, sizeof(routerTlvs)));
+        SuccessOrExit(error = message->AppendChallengeTlv(aNeighbor->GetChallenge(), aNeighbor->GetChallengeSize()));
+        SuccessOrExit(error = message->AppendTlvRequestTlv(routerTlvs, sizeof(routerTlvs)));
         aNeighbor->SetLastHeard(TimerMilli::GetNow());
         aNeighbor->SetState(Neighbor::kStateLinkRequest);
     }
@@ -767,14 +811,14 @@
 
     if (aMessageInfo.GetSockAddr().IsMulticast())
     {
-        SuccessOrExit(error = AddDelayedResponse(*message, aMessageInfo.GetPeerAddr(),
-                                                 1 + Random::NonCrypto::GetUint16InRange(0, kMaxResponseDelay)));
+        SuccessOrExit(error = message->SendAfterDelay(aMessageInfo.GetPeerAddr(),
+                                                      1 + Random::NonCrypto::GetUint16InRange(0, kMaxResponseDelay)));
 
         Log(kMessageDelay, kTypeLinkAccept, aMessageInfo.GetPeerAddr());
     }
     else
     {
-        SuccessOrExit(error = SendMessage(*message, aMessageInfo.GetPeerAddr()));
+        SuccessOrExit(error = message->SendTo(aMessageInfo.GetPeerAddr()));
 
         Log(kMessageSend, kTypeLinkAccept, aMessageInfo.GetPeerAddr());
     }
@@ -784,31 +828,21 @@
     return error;
 }
 
-void MleRouter::HandleLinkAccept(const Message &         aMessage,
-                                 const Ip6::MessageInfo &aMessageInfo,
-                                 uint32_t                aKeySequence,
-                                 Neighbor *              aNeighbor)
+void MleRouter::HandleLinkAccept(RxInfo &aRxInfo)
 {
-    Error error = HandleLinkAccept(aMessage, aMessageInfo, aKeySequence, aNeighbor, false);
+    Error error = HandleLinkAccept(aRxInfo, false);
 
     LogProcessError(kTypeLinkAccept, error);
 }
 
-void MleRouter::HandleLinkAcceptAndRequest(const Message &         aMessage,
-                                           const Ip6::MessageInfo &aMessageInfo,
-                                           uint32_t                aKeySequence,
-                                           Neighbor *              aNeighbor)
+void MleRouter::HandleLinkAcceptAndRequest(RxInfo &aRxInfo)
 {
-    Error error = HandleLinkAccept(aMessage, aMessageInfo, aKeySequence, aNeighbor, true);
+    Error error = HandleLinkAccept(aRxInfo, true);
 
     LogProcessError(kTypeLinkAcceptAndRequest, error);
 }
 
-Error MleRouter::HandleLinkAccept(const Message &         aMessage,
-                                  const Ip6::MessageInfo &aMessageInfo,
-                                  uint32_t                aKeySequence,
-                                  Neighbor *              aNeighbor,
-                                  bool                    aRequest)
+Error MleRouter::HandleLinkAccept(RxInfo &aRxInfo, bool aRequest)
 {
     static const uint8_t dataRequestTlvs[] = {Tlv::kNetworkData};
 
@@ -823,14 +857,14 @@
     uint32_t        mleFrameCounter;
     uint8_t         routerId;
     uint16_t        address16;
-    RouteTlv        route;
+    RouteTlv        routeTlv;
     LeaderData      leaderData;
     uint8_t         linkMargin;
 
     // Source Address
-    SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aMessage, sourceAddress));
+    SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress));
 
-    Log(kMessageReceive, aRequest ? kTypeLinkAcceptAndRequest : kTypeLinkAccept, aMessageInfo.GetPeerAddr(),
+    Log(kMessageReceive, aRequest ? kTypeLinkAcceptAndRequest : kTypeLinkAccept, aRxInfo.mMessageInfo.GetPeerAddr(),
         sourceAddress);
 
     VerifyOrExit(IsActiveRouter(sourceAddress), error = kErrorParse);
@@ -840,7 +874,7 @@
     neighborState = (router != nullptr) ? router->GetState() : Neighbor::kStateInvalid;
 
     // Response
-    SuccessOrExit(error = ReadResponse(aMessage, response));
+    SuccessOrExit(error = aRxInfo.mMessage.ReadResponseTlv(response));
 
     // verify response
     switch (neighborState)
@@ -862,20 +896,20 @@
     }
 
     // Remove stale neighbors
-    if (aNeighbor && aNeighbor->GetRloc16() != sourceAddress)
+    if (aRxInfo.mNeighbor && aRxInfo.mNeighbor->GetRloc16() != sourceAddress)
     {
-        RemoveNeighbor(*aNeighbor);
+        RemoveNeighbor(*aRxInfo.mNeighbor);
     }
 
     // Version
-    SuccessOrExit(error = Tlv::Find<VersionTlv>(aMessage, version));
+    SuccessOrExit(error = Tlv::Find<VersionTlv>(aRxInfo.mMessage, version));
     VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = kErrorParse);
 
     // Link and MLE Frame Counters
-    SuccessOrExit(error = ReadFrameCounters(aMessage, linkFrameCounter, mleFrameCounter));
+    SuccessOrExit(error = aRxInfo.mMessage.ReadFrameCounterTlvs(linkFrameCounter, mleFrameCounter));
 
     // Link Margin
-    switch (Tlv::Find<LinkMarginTlv>(aMessage, linkMargin))
+    switch (Tlv::Find<LinkMarginTlv>(aRxInfo.mMessage, linkMargin))
     {
     case kErrorNone:
         break;
@@ -897,24 +931,22 @@
 
     case kRoleDetached:
         // Address16
-        SuccessOrExit(error = Tlv::Find<Address16Tlv>(aMessage, address16));
+        SuccessOrExit(error = Tlv::Find<Address16Tlv>(aRxInfo.mMessage, address16));
         VerifyOrExit(GetRloc16() == address16, error = kErrorDrop);
 
         // Leader Data
-        SuccessOrExit(error = ReadLeaderData(aMessage, leaderData));
+        SuccessOrExit(error = aRxInfo.mMessage.ReadLeaderDataTlv(leaderData));
         SetLeaderData(leaderData.GetPartitionId(), leaderData.GetWeighting(), leaderData.GetLeaderRouterId());
 
         // Route
-        SuccessOrExit(error = Tlv::FindTlv(aMessage, Tlv::kRoute, sizeof(route), route));
-        VerifyOrExit(route.IsValid(), error = kErrorParse);
         mRouterTable.Clear();
-        SuccessOrExit(error = ProcessRouteTlv(route));
+        SuccessOrExit(error = ProcessRouteTlv(aRxInfo));
         router = mRouterTable.GetRouter(routerId);
         VerifyOrExit(router != nullptr);
 
         if (mLeaderData.GetLeaderRouterId() == RouterIdFromRloc16(GetRloc16()))
         {
-            SetStateLeader(GetRloc16());
+            SetStateLeader(GetRloc16(), kRestoringLeaderRoleAfterReset);
         }
         else
         {
@@ -922,10 +954,10 @@
         }
 
         mRetrieveNewNetworkData = true;
-        IgnoreError(SendDataRequest(aMessageInfo.GetPeerAddr(), dataRequestTlvs, sizeof(dataRequestTlvs), 0));
+        IgnoreError(SendDataRequest(aRxInfo.mMessageInfo.GetPeerAddr(), dataRequestTlvs, sizeof(dataRequestTlvs), 0));
 
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-        Get<TimeSync>().HandleTimeSyncMessage(aMessage);
+        Get<TimeSync>().HandleTimeSyncMessage(aRxInfo.mMessage);
 #endif
         break;
 
@@ -938,24 +970,33 @@
         VerifyOrExit(router != nullptr);
 
         // Leader Data
-        SuccessOrExit(error = ReadLeaderData(aMessage, leaderData));
+        SuccessOrExit(error = aRxInfo.mMessage.ReadLeaderDataTlv(leaderData));
         VerifyOrExit(leaderData.GetPartitionId() == mLeaderData.GetPartitionId());
 
         if (mRetrieveNewNetworkData ||
-            (static_cast<int8_t>(leaderData.GetDataVersion() - Get<NetworkData::Leader>().GetVersion()) > 0))
+            SerialNumber::IsGreater(leaderData.GetDataVersion(NetworkData::kFullSet),
+                                    Get<NetworkData::Leader>().GetVersion(NetworkData::kFullSet)))
         {
-            IgnoreError(SendDataRequest(aMessageInfo.GetPeerAddr(), dataRequestTlvs, sizeof(dataRequestTlvs), 0));
+            IgnoreError(
+                SendDataRequest(aRxInfo.mMessageInfo.GetPeerAddr(), dataRequestTlvs, sizeof(dataRequestTlvs), 0));
         }
 
         // Route (optional)
-        if (Tlv::FindTlv(aMessage, route) == kErrorNone)
+        switch (error = ProcessRouteTlv(aRxInfo, routeTlv))
         {
-            VerifyOrExit(route.IsValid(), error = kErrorParse);
-            SuccessOrExit(error = ProcessRouteTlv(route));
-            UpdateRoutes(route, routerId);
-            // need to update router after ProcessRouteTlv
+        case kErrorNone:
+            UpdateRoutes(routeTlv, routerId);
+            // Need to update router after ProcessRouteTlv
             router = mRouterTable.GetRouter(routerId);
             OT_ASSERT(router != nullptr);
+            break;
+
+        case kErrorNotFound:
+            error = kErrorNone;
+            break;
+
+        default:
+            ExitNow();
         }
 
         // update routing table
@@ -968,7 +1009,7 @@
     }
 
     // finish link synchronization
-    aMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
+    aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
     router->SetExtAddress(extAddr);
     router->SetRloc16(sourceAddress);
     router->GetLinkFrameCounters().SetAll(linkFrameCounter);
@@ -979,24 +1020,26 @@
     router->SetDeviceMode(DeviceMode(DeviceMode::kModeFullThreadDevice | DeviceMode::kModeRxOnWhenIdle |
                                      DeviceMode::kModeFullNetworkData));
     router->GetLinkInfo().Clear();
-    router->GetLinkInfo().AddRss(aMessageInfo.GetThreadLinkInfo()->GetRss());
+    router->GetLinkInfo().AddRss(aRxInfo.mMessageInfo.GetThreadLinkInfo()->GetRss());
     router->SetLinkQualityOut(LinkQualityInfo::ConvertLinkMarginToLinkQuality(linkMargin));
     router->ResetLinkFailures();
     router->SetState(Neighbor::kStateValid);
-    router->SetKeySequence(aKeySequence);
+    router->SetKeySequence(aRxInfo.mKeySequence);
 
     mNeighborTable.Signal(NeighborTable::kRouterAdded, *router);
 
+    aRxInfo.mClass = RxInfo::kAuthoritativeMessage;
+
     if (aRequest)
     {
         Challenge     challenge;
         RequestedTlvs requestedTlvs;
 
         // Challenge
-        SuccessOrExit(error = ReadChallenge(aMessage, challenge));
+        SuccessOrExit(error = aRxInfo.mMessage.ReadChallengeTlv(challenge));
 
         // TLV Request
-        switch (FindTlvRequest(aMessage, requestedTlvs))
+        switch (aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvs))
         {
         case kErrorNone:
             break;
@@ -1007,7 +1050,7 @@
             ExitNow(error = kErrorParse);
         }
 
-        SuccessOrExit(error = SendLinkAccept(aMessageInfo, router, requestedTlvs, challenge));
+        SuccessOrExit(error = SendLinkAccept(aRxInfo.mMessageInfo, router, requestedTlvs, challenge));
     }
 
 exit:
@@ -1047,7 +1090,7 @@
 
     router = mRouterTable.GetRouter(aRouterId);
 
-    // nullptr aRouterId indicates non-existing next hop, hence return kMaxRouteCost for it.
+    // `nullptr` aRouterId indicates non-existing next hop, hence return kMaxRouteCost for it.
     VerifyOrExit(router != nullptr);
 
     rval = mRouterTable.GetLinkCost(*router);
@@ -1068,18 +1111,54 @@
     return error;
 }
 
-Error MleRouter::ProcessRouteTlv(const RouteTlv &aRoute)
+Error MleRouter::ProcessRouteTlv(RxInfo &aRxInfo)
 {
-    Error error = kErrorNone;
+    RouteTlv routeTlv;
 
-    mRouterTable.UpdateRouterIdSet(aRoute.GetRouterIdSequence(), aRoute.GetRouterIdMask());
+    return ProcessRouteTlv(aRxInfo, routeTlv);
+}
 
-    if (IsRouter() && !mRouterTable.IsAllocated(mRouterId))
+Error MleRouter::ProcessRouteTlv(RxInfo &aRxInfo, RouteTlv &aRouteTlv)
+{
+    // This method processes Route TLV in a received MLE message
+    // (from `RxInfo`). In case of success, `aRouteTlv` is updated
+    // to return the read/processed route TLV from the message.
+    // If the message contains no Route TLV, `kErrorNotFound` is
+    // returned.
+    //
+    // During processing of Route TLV, the entries in the router table
+    // may shuffle. This method ensures that the `aRxInfo.mNeighbor`
+    // (which indicates the neighbor from which the MLE message was
+    // received) is correctly updated to point to the same neighbor
+    // (in case `mNeighbor` was pointing to a router entry from the
+    // `RouterTable`).
+
+    Error    error;
+    uint16_t neighborRloc16 = Mac::kShortAddrInvalid;
+
+    if ((aRxInfo.mNeighbor != nullptr) && Get<RouterTable>().Contains(*aRxInfo.mNeighbor))
+    {
+        neighborRloc16 = aRxInfo.mNeighbor->GetRloc16();
+    }
+
+    SuccessOrExit(error = Tlv::FindTlv(aRxInfo.mMessage, aRouteTlv));
+
+    VerifyOrExit(aRouteTlv.IsValid(), error = kErrorParse);
+
+    Get<RouterTable>().UpdateRouterIdSet(aRouteTlv.GetRouterIdSequence(), aRouteTlv.GetRouterIdMask());
+
+    if (IsRouter() && !Get<RouterTable>().IsAllocated(mRouterId))
     {
         IgnoreError(BecomeDetached());
         error = kErrorNoRoute;
     }
 
+    if (neighborRloc16 != Mac::kShortAddrInvalid)
+    {
+        aRxInfo.mNeighbor = Get<RouterTable>().GetNeighbor(neighborRloc16);
+    }
+
+exit:
     return error;
 }
 
@@ -1150,10 +1229,10 @@
     return rval;
 }
 
-Error MleRouter::HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor)
+Error MleRouter::HandleAdvertisement(RxInfo &aRxInfo)
 {
     Error                 error    = kErrorNone;
-    const ThreadLinkInfo *linkInfo = aMessageInfo.GetThreadLinkInfo();
+    const ThreadLinkInfo *linkInfo = aRxInfo.mMessageInfo.GetThreadLinkInfo();
     uint8_t linkMargin = LinkQualityInfo::ConvertRssToLinkMargin(Get<Mac::Mac>().GetNoiseFloor(), linkInfo->GetRss());
     Mac::ExtAddress extAddr;
     uint16_t        sourceAddress = Mac::kShortAddrInvalid;
@@ -1164,16 +1243,16 @@
     uint8_t         routerId;
     uint8_t         routerCount;
 
-    aMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
+    aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
 
     // Source Address
-    SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aMessage, sourceAddress));
+    SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress));
 
     // Leader Data
-    SuccessOrExit(error = ReadLeaderData(aMessage, leaderData));
+    SuccessOrExit(error = aRxInfo.mMessage.ReadLeaderDataTlv(leaderData));
 
     // Route Data (optional)
-    if (Tlv::FindTlv(aMessage, route) == kErrorNone)
+    if (Tlv::FindTlv(aRxInfo.mMessage, route) == kErrorNone)
     {
         VerifyOrExit(route.IsValid(), error = kErrorParse);
     }
@@ -1187,18 +1266,18 @@
 
     if (partitionId != mLeaderData.GetPartitionId())
     {
-        otLogNoteMle("Different partition (peer:%u, local:%u)", partitionId, mLeaderData.GetPartitionId());
+        LogNote("Different partition (peer:%u, local:%u)", partitionId, mLeaderData.GetPartitionId());
 
         VerifyOrExit(linkMargin >= OPENTHREAD_CONFIG_MLE_PARTITION_MERGE_MARGIN_MIN, error = kErrorLinkMarginLow);
 
         if (route.IsValid() && IsFullThreadDevice() && (mPreviousPartitionIdTimeout > 0) &&
             (partitionId == mPreviousPartitionId))
         {
-            VerifyOrExit((static_cast<int8_t>(route.GetRouterIdSequence() - mPreviousPartitionRouterIdSequence) > 0),
+            VerifyOrExit(SerialNumber::IsGreater(route.GetRouterIdSequence(), mPreviousPartitionRouterIdSequence),
                          error = kErrorDrop);
         }
 
-        if (IsChild() && (aNeighbor == &mParent || !IsFullThreadDevice()))
+        if (IsChild() && (aRxInfo.mNeighbor == &mParent || !IsFullThreadDevice()))
         {
             ExitNow();
         }
@@ -1206,22 +1285,22 @@
         if (ComparePartitions(IsSingleton(route), leaderData, IsSingleton(), mLeaderData) > 0
 #if OPENTHREAD_CONFIG_TIME_SYNC_REQUIRED
             // if time sync is required, it will only migrate to a better network which also enables time sync.
-            && aMessage.GetTimeSyncSeq() != OT_TIME_SYNC_INVALID_SEQ
+            && aRxInfo.mMessage.GetTimeSyncSeq() != OT_TIME_SYNC_INVALID_SEQ
 #endif
         )
         {
-            IgnoreError(BecomeChild(kAttachBetter));
+            Attach(kBetterPartition);
         }
 
         ExitNow(error = kErrorDrop);
     }
     else if (leaderData.GetLeaderRouterId() != GetLeaderId())
     {
-        VerifyOrExit(aNeighbor && aNeighbor->IsStateValid());
+        VerifyOrExit(aRxInfo.mNeighbor && aRxInfo.mNeighbor->IsStateValid());
 
         if (!IsChild())
         {
-            otLogInfoMle("Leader ID mismatch");
+            LogInfo("Leader ID mismatch");
             IgnoreError(BecomeDetached());
             error = kErrorDrop;
         }
@@ -1233,12 +1312,12 @@
     routerId = RouterIdFromRloc16(sourceAddress);
 
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-    Get<TimeSync>().HandleTimeSyncMessage(aMessage);
+    Get<TimeSync>().HandleTimeSyncMessage(aRxInfo.mMessage);
 #endif
 
-    if (IsFullThreadDevice() && (aNeighbor && aNeighbor->IsStateValid()) &&
+    if (IsFullThreadDevice() && (aRxInfo.mNeighbor && aRxInfo.mNeighbor->IsStateValid()) &&
         ((mRouterTable.GetActiveRouterCount() == 0) ||
-         (static_cast<int8_t>(route.GetRouterIdSequence() - mRouterTable.GetRouterIdSequence()) > 0)))
+         SerialNumber::IsGreater(route.GetRouterIdSequence(), mRouterTable.GetRouterIdSequence())))
     {
         bool processRouteTlv = false;
 
@@ -1273,11 +1352,7 @@
 
         if (processRouteTlv)
         {
-            SuccessOrExit(error = ProcessRouteTlv(route));
-            if (Get<RouterTable>().Contains(*aNeighbor))
-            {
-                aNeighbor = nullptr; // aNeighbor is no longer valid after `ProcessRouteTlv`
-            }
+            SuccessOrExit(error = ProcessRouteTlv(aRxInfo));
         }
     }
 
@@ -1288,7 +1363,7 @@
         ExitNow();
 
     case kRoleChild:
-        if (aNeighbor == &mParent)
+        if (aRxInfo.mNeighbor == &mParent)
         {
             // MLE Advertisement from parent
             router = &mParent;
@@ -1296,7 +1371,7 @@
             if (mParent.GetRloc16() != sourceAddress)
             {
                 IgnoreError(BecomeDetached());
-                ExitNow(error = kErrorNoRoute);
+                ExitNow(error = kErrorDetached);
             }
 
             if (IsFullThreadDevice())
@@ -1368,6 +1443,12 @@
         ExitNow();
 
     case kRoleRouter:
+        if (mLinkRequestDelay > 0 && route.IsRouterIdSet(mRouterId))
+        {
+            mLinkRequestDelay = 0;
+            IgnoreError(SendLinkRequest(nullptr));
+        }
+
         router = mRouterTable.GetRouter(routerId);
         VerifyOrExit(router != nullptr);
 
@@ -1384,7 +1465,11 @@
 
         if (routerCount > mRouterDowngradeThreshold && mRouterSelectionJitterTimeout == 0 &&
             HasMinDowngradeNeighborRouters() && HasSmallNumberOfChildren() &&
-            HasOneNeighborWithComparableConnectivity(route, routerId))
+            HasOneNeighborWithComparableConnectivity(route, routerId)
+#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
+            && !Get<NetworkData::Notifier>().IsEligibleForRouterRoleUpgradeAsBorderRouter()
+#endif
+        )
         {
             mRouterSelectionJitterTimeout = 1 + Random::NonCrypto::GetUint8InRange(0, mRouterSelectionJitter);
         }
@@ -1416,10 +1501,10 @@
     UpdateRoutes(route, routerId);
 
 exit:
-    if (aNeighbor && aNeighbor->GetRloc16() != sourceAddress)
+    if (aRxInfo.mNeighbor && aRxInfo.mNeighbor->GetRloc16() != sourceAddress)
     {
         // Remove stale neighbors
-        RemoveNeighbor(*aNeighbor);
+        RemoveNeighbor(*aRxInfo.mNeighbor);
     }
 
     return error;
@@ -1525,18 +1610,18 @@
         ResetAdvertiseInterval();
     }
 
-#if (OPENTHREAD_CONFIG_LOG_MLE && (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO))
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
     VerifyOrExit(changed);
-    otLogInfoMle("Route table updated");
+    LogInfo("Route table updated");
 
     for (Router &router : Get<RouterTable>().Iterate())
     {
-        otLogInfoMle("    %04x -> %04x, cost:%d %d, lqin:%d, lqout:%d, link:%s", router.GetRloc16(),
-                     (router.GetNextHop() == kInvalidRouterId) ? 0xffff : Rloc16FromRouterId(router.GetNextHop()),
-                     router.GetCost(), mRouterTable.GetLinkCost(router), router.GetLinkInfo().GetLinkQuality(),
-                     router.GetLinkQualityOut(),
-                     router.GetRloc16() == GetRloc16() ? "device" : (router.IsStateValid() ? "yes" : "no"));
+        LogInfo("    %04x -> %04x, cost:%d %d, lqin:%d, lqout:%d, link:%s", router.GetRloc16(),
+                (router.GetNextHop() == kInvalidRouterId) ? 0xffff : Rloc16FromRouterId(router.GetNextHop()),
+                router.GetCost(), mRouterTable.GetLinkCost(router), router.GetLinkInfo().GetLinkQuality(),
+                router.GetLinkQualityOut(),
+                router.GetRloc16() == GetRloc16() ? "device" : ToYesNo(router.IsStateValid()));
     }
 
 #else
@@ -1549,12 +1634,12 @@
 
 bool MleRouter::UpdateLinkQualityOut(const RouteTlv &aRoute, Router &aNeighbor, bool &aResetAdvInterval)
 {
-    bool    changed = false;
-    uint8_t linkQuality;
-    uint8_t myRouterId;
-    uint8_t myRouteCount;
-    uint8_t oldLinkCost;
-    Router *nextHop;
+    bool        changed = false;
+    LinkQuality linkQuality;
+    uint8_t     myRouterId;
+    uint8_t     myRouteCount;
+    uint8_t     oldLinkCost;
+    Router *    nextHop;
 
     myRouterId = RouterIdFromRloc16(GetRloc16());
     VerifyOrExit(aRoute.IsRouterIdSet(myRouterId));
@@ -1584,7 +1669,7 @@
     return changed;
 }
 
-void MleRouter::HandleParentRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+void MleRouter::HandleParentRequest(RxInfo &aRxInfo)
 {
     Error           error = kErrorNone;
     Mac::ExtAddress extAddr;
@@ -1593,8 +1678,10 @@
     Challenge       challenge;
     Router *        leader;
     Child *         child;
+    uint8_t         modeBitmask;
+    DeviceMode      mode;
 
-    Log(kMessageReceive, kTypeParentRequest, aMessageInfo.GetPeerAddr());
+    Log(kMessageReceive, kTypeParentRequest, aRxInfo.mMessageInfo.GetPeerAddr());
 
     VerifyOrExit(IsRouterEligible(), error = kErrorInvalidState);
 
@@ -1625,14 +1712,14 @@
     // the network (because Leader would reject any further address solicit).
     // ==> Verified below when checking the scan mask.
 
-    aMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
+    aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
 
     // Version
-    SuccessOrExit(error = Tlv::Find<VersionTlv>(aMessage, version));
+    SuccessOrExit(error = Tlv::Find<VersionTlv>(aRxInfo.mMessage, version));
     VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = kErrorParse);
 
     // Scan Mask
-    SuccessOrExit(error = Tlv::Find<ScanMaskTlv>(aMessage, scanMask));
+    SuccessOrExit(error = Tlv::Find<ScanMaskTlv>(aRxInfo.mMessage, scanMask));
 
     switch (mRole)
     {
@@ -1652,7 +1739,7 @@
     }
 
     // Challenge
-    SuccessOrExit(error = ReadChallenge(aMessage, challenge));
+    SuccessOrExit(error = aRxInfo.mMessage.ReadChallengeTlv(challenge));
 
     child = mChildTable.FindChild(extAddr, Child::kInStateAnyExceptInvalid);
 
@@ -1663,12 +1750,18 @@
         // MAC Address
         child->SetExtAddress(extAddr);
         child->GetLinkInfo().Clear();
-        child->GetLinkInfo().AddRss(aMessageInfo.GetThreadLinkInfo()->GetRss());
+        child->GetLinkInfo().AddRss(aRxInfo.mMessageInfo.GetThreadLinkInfo()->GetRss());
         child->ResetLinkFailures();
         child->SetState(Neighbor::kStateParentRequest);
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-        child->SetTimeSyncEnabled(Tlv::Find<TimeRequestTlv>(aMessage, nullptr, 0) == kErrorNone);
+        child->SetTimeSyncEnabled(Tlv::Find<TimeRequestTlv>(aRxInfo.mMessage, nullptr, 0) == kErrorNone);
 #endif
+        if (Tlv::Find<ModeTlv>(aRxInfo.mMessage, modeBitmask) == kErrorNone)
+        {
+            mode.Set(modeBitmask);
+            child->SetDeviceMode(mode);
+            child->SetVersion(static_cast<uint8_t>(version));
+        }
     }
     else if (TimerMilli::GetNow() - child->GetLastHeard() < kParentRequestRouterTimeout - kParentRequestDuplicateMargin)
     {
@@ -1681,18 +1774,60 @@
         child->SetTimeout(Time::MsecToSec(kMaxChildIdRequestTimeout));
     }
 
+    aRxInfo.mClass = RxInfo::kPeerMessage;
+
     SendParentResponse(child, challenge, !ScanMaskTlv::IsEndDeviceFlagSet(scanMask));
 
 exit:
     LogProcessError(kTypeParentRequest, error);
 }
 
+bool MleRouter::HasNeighborWithGoodLinkQuality(void) const
+{
+    bool    haveNeighbor = true;
+    uint8_t linkMargin;
+
+    linkMargin =
+        LinkQualityInfo::ConvertRssToLinkMargin(Get<Mac::Mac>().GetNoiseFloor(), mParent.GetLinkInfo().GetLastRss());
+
+    if (linkMargin >= OPENTHREAD_CONFIG_MLE_LINK_REQUEST_MARGIN_MIN)
+    {
+        ExitNow();
+    }
+
+    for (Router &router : Get<RouterTable>().Iterate())
+    {
+        if (!router.IsStateValid())
+        {
+            continue;
+        }
+
+        linkMargin =
+            LinkQualityInfo::ConvertRssToLinkMargin(Get<Mac::Mac>().GetNoiseFloor(), router.GetLinkInfo().GetLastRss());
+
+        if (linkMargin >= OPENTHREAD_CONFIG_MLE_LINK_REQUEST_MARGIN_MIN)
+        {
+            ExitNow();
+        }
+    }
+
+    haveNeighbor = false;
+
+exit:
+    return haveNeighbor;
+}
+
 void MleRouter::HandleTimeTick(void)
 {
     bool routerStateUpdate = false;
 
     VerifyOrExit(IsFullThreadDevice(), Get<TimeTicker>().UnregisterReceiver(TimeTicker::kMleRouter));
 
+    if (mLinkRequestDelay > 0 && --mLinkRequestDelay == 0)
+    {
+        IgnoreError(SendLinkRequest(nullptr));
+    }
+
     if (mChallengeTimeout > 0)
     {
         mChallengeTimeout--;
@@ -1751,7 +1886,7 @@
     case kRoleChild:
         if (routerStateUpdate)
         {
-            if (mRouterTable.GetActiveRouterCount() < mRouterUpgradeThreshold)
+            if (mRouterTable.GetActiveRouterCount() < mRouterUpgradeThreshold && HasNeighborWithGoodLinkQuality())
             {
                 // upgrade to Router
                 IgnoreError(BecomeRouter(ThreadStatusTlv::kTooFewRouters));
@@ -1777,19 +1912,18 @@
 
     case kRoleRouter:
         // verify path to leader
-        otLogDebgMle("network id timeout = %d", mRouterTable.GetLeaderAge());
+        LogDebg("network id timeout = %d", mRouterTable.GetLeaderAge());
 
         if ((mRouterTable.GetActiveRouterCount() > 0) && (mRouterTable.GetLeaderAge() >= mNetworkIdTimeout))
         {
-            otLogInfoMle("Router ID Sequence timeout");
-            IgnoreError(BecomeChild(kAttachSame1));
+            LogInfo("Router ID Sequence timeout");
+            Attach(kSamePartition);
         }
 
         if (routerStateUpdate && mRouterTable.GetActiveRouterCount() > mRouterDowngradeThreshold)
         {
-            // downgrade to REED
-            otLogNoteMle("Downgrade to REED");
-            IgnoreError(BecomeChild(kAttachSameDowngrade));
+            LogNote("Downgrade to REED");
+            Attach(kDowngradeToReed);
         }
 
         break;
@@ -1826,7 +1960,7 @@
         if (child.IsCslSynchronized() &&
             TimerMilli::GetNow() - child.GetCslLastHeard() >= Time::SecToMsec(child.GetCslTimeout()))
         {
-            otLogInfoMle("Child CSL synchronization expired");
+            LogInfo("Child CSL synchronization expired");
             child.SetCslSynchronized(false);
             Get<CslTxScheduler>().Update();
         }
@@ -1834,7 +1968,7 @@
 
         if (TimerMilli::GetNow() - child.GetLastHeard() >= timeout)
         {
-            otLogInfoMle("Child timeout expired");
+            LogInfo("Child timeout expired");
             RemoveNeighbor(child);
         }
         else if (IsRouterOrLeader() && child.IsStateRestored())
@@ -1862,7 +1996,7 @@
 
             if (age >= Time::SecToMsec(kMaxNeighborAge))
             {
-                otLogInfoMle("Router timeout expired");
+                LogInfo("Router timeout expired");
                 RemoveNeighbor(router);
                 continue;
             }
@@ -1873,7 +2007,7 @@
             {
                 if (age < Time::SecToMsec(kMaxNeighborAge) + kMaxTransmissionCount * kUnicastRetransmissionDelay)
                 {
-                    otLogInfoMle("Router timeout expired");
+                    LogInfo("Router timeout expired");
                     IgnoreError(SendLinkRequest(&router));
                 }
                 else
@@ -1889,7 +2023,7 @@
         {
             if (age >= kMaxLinkRequestTimeout)
             {
-                otLogInfoMle("Link Request timeout expired");
+                LogInfo("Link Request timeout expired");
                 RemoveNeighbor(router);
                 continue;
             }
@@ -1900,7 +2034,7 @@
             if (mRouterTable.GetRouter(router.GetNextHop()) == nullptr &&
                 mRouterTable.GetLinkCost(router) >= kMaxRouteCost && age >= Time::SecToMsec(kMaxLeaderToRouterTimeout))
             {
-                otLogInfoMle("Router ID timeout expired (no route)");
+                LogInfo("Router ID timeout expired (no route)");
                 IgnoreError(mRouterTable.Release(router.GetRouterId()));
             }
         }
@@ -1925,39 +2059,38 @@
 {
     Error        error = kErrorNone;
     Ip6::Address destination;
-    Message *    message;
+    TxMessage *  message;
     uint16_t     delay;
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
+    VerifyOrExit((message = NewMleMessage(kCommandParentResponse)) != nullptr, error = kErrorNoBufs);
     message->SetDirectTransmission();
 
-    SuccessOrExit(error = AppendHeader(*message, kCommandParentResponse));
-    SuccessOrExit(error = AppendSourceAddress(*message));
-    SuccessOrExit(error = AppendLeaderData(*message));
-    SuccessOrExit(error = AppendLinkFrameCounter(*message));
-    SuccessOrExit(error = AppendMleFrameCounter(*message));
-    SuccessOrExit(error = AppendResponse(*message, aChallenge));
+    SuccessOrExit(error = message->AppendSourceAddressTlv());
+    SuccessOrExit(error = message->AppendLeaderDataTlv());
+    SuccessOrExit(error = message->AppendLinkFrameCounterTlv());
+    SuccessOrExit(error = message->AppendMleFrameCounterTlv());
+    SuccessOrExit(error = message->AppendResponseTlv(aChallenge));
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
     if (aChild->IsTimeSyncEnabled())
     {
-        SuccessOrExit(error = AppendTimeParameter(*message));
+        SuccessOrExit(error = message->AppendTimeParameterTlv());
     }
 #endif
 #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
-    if (!aChild->IsRxOnWhenIdle())
+    if (aChild->IsThreadVersionCslCapable())
     {
-        SuccessOrExit(error = AppendCslClockAccuracy(*message));
+        SuccessOrExit(error = message->AppendCslClockAccuracyTlv());
     }
 #endif
 
     aChild->GenerateChallenge();
 
-    SuccessOrExit(error = AppendChallenge(*message, aChild->GetChallenge(), aChild->GetChallengeSize()));
-    error = AppendLinkMargin(*message, aChild->GetLinkInfo().GetLinkMargin());
+    SuccessOrExit(error = message->AppendChallengeTlv(aChild->GetChallenge(), aChild->GetChallengeSize()));
+    error = message->AppendLinkMarginTlv(aChild->GetLinkInfo().GetLinkMargin());
     SuccessOrExit(error);
 
-    SuccessOrExit(error = AppendConnectivity(*message));
-    SuccessOrExit(error = AppendVersion(*message));
+    SuccessOrExit(error = message->AppendConnectivityTlv());
+    SuccessOrExit(error = message->AppendVersionTlv());
 
     destination.SetToLinkLocalAddress(aChild->GetExtAddress());
 
@@ -1970,7 +2103,7 @@
         delay = 1 + Random::NonCrypto::GetUint16InRange(0, kParentResponseMaxDelayAll);
     }
 
-    SuccessOrExit(error = AddDelayedResponse(*message, destination, delay));
+    SuccessOrExit(error = message->SendAfterDelay(destination, delay));
 
     Log(kMessageDelay, kTypeParentResponse, destination);
 
@@ -2079,31 +2212,14 @@
         {
             if (Get<NetworkData::Leader>().GetContext(entry.GetContextId(), context) != kErrorNone)
             {
-                otLogWarnMle("Failed to get context %d for compressed address from child 0x%04x", entry.GetContextId(),
-                             aChild.GetRloc16());
+                LogWarn("Failed to get context %d for compressed address from child 0x%04x", entry.GetContextId(),
+                        aChild.GetRloc16());
                 continue;
             }
 
             address.Clear();
             address.SetPrefix(context.mPrefix);
             address.SetIid(entry.GetIid());
-
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
-            if (Get<BackboneRouter::Leader>().IsDomainUnicast(address))
-            {
-                hasDua = true;
-
-                if (oldDuaPtr != nullptr)
-                {
-                    Get<DuaManager>().UpdateChildDomainUnicastAddress(
-                        aChild, oldDua != address ? ChildDuaState::kChanged : ChildDuaState::kUnchanged);
-                }
-                else
-                {
-                    Get<DuaManager>().UpdateChildDomainUnicastAddress(aChild, ChildDuaState::kAdded);
-                }
-            }
-#endif
         }
         else
         {
@@ -2128,13 +2244,39 @@
         if (error == kErrorNone)
         {
             storedCount++;
-            otLogInfoMle("Child 0x%04x IPv6 address[%d]=%s", aChild.GetRloc16(), storedCount,
-                         address.ToString().AsCString());
+
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
+            if (Get<BackboneRouter::Leader>().IsDomainUnicast(address))
+            {
+                hasDua = true;
+
+                if (oldDuaPtr != nullptr)
+                {
+                    Get<DuaManager>().UpdateChildDomainUnicastAddress(
+                        aChild, oldDua != address ? ChildDuaState::kChanged : ChildDuaState::kUnchanged);
+                }
+                else
+                {
+                    Get<DuaManager>().UpdateChildDomainUnicastAddress(aChild, ChildDuaState::kAdded);
+                }
+            }
+#endif
+
+            LogInfo("Child 0x%04x IPv6 address[%d]=%s", aChild.GetRloc16(), storedCount,
+                    address.ToString().AsCString());
         }
         else
         {
-            otLogWarnMle("Error %s adding IPv6 address %s to child 0x%04x", ErrorToString(error),
-                         address.ToString().AsCString(), aChild.GetRloc16());
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
+            if (Get<BackboneRouter::Leader>().IsDomainUnicast(address))
+            {
+                // if not able to store DUA, then assume child does not have one
+                hasDua = false;
+            }
+#endif
+
+            LogWarn("Error %s adding IPv6 address %s to child 0x%04x", ErrorToString(error),
+                    address.ToString().AsCString(), aChild.GetRloc16());
         }
 
         if (address.IsMulticast())
@@ -2179,12 +2321,12 @@
 
     if (registeredCount == 0)
     {
-        otLogInfoMle("Child 0x%04x has no registered IPv6 address", aChild.GetRloc16());
+        LogInfo("Child 0x%04x has no registered IPv6 address", aChild.GetRloc16());
     }
     else
     {
-        otLogInfoMle("Child 0x%04x has %d registered IPv6 address%s, %d address%s stored", aChild.GetRloc16(),
-                     registeredCount, (registeredCount == 1) ? "" : "es", storedCount, (storedCount == 1) ? "" : "es");
+        LogInfo("Child 0x%04x has %d registered IPv6 address%s, %d address%s stored", aChild.GetRloc16(),
+                registeredCount, (registeredCount == 1) ? "" : "es", storedCount, (storedCount == 1) ? "" : "es");
     }
 
     error = kErrorNone;
@@ -2193,9 +2335,7 @@
     return error;
 }
 
-void MleRouter::HandleChildIdRequest(const Message &         aMessage,
-                                     const Ip6::MessageInfo &aMessageInfo,
-                                     uint32_t                aKeySequence)
+void MleRouter::HandleChildIdRequest(RxInfo &aRxInfo)
 {
     Error              error = kErrorNone;
     Mac::ExtAddress    extAddr;
@@ -2215,7 +2355,7 @@
     uint8_t            numTlvs;
     uint16_t           addressRegistrationOffset = 0;
 
-    Log(kMessageReceive, kTypeChildIdRequest, aMessageInfo.GetPeerAddr());
+    Log(kMessageReceive, kTypeChildIdRequest, aRxInfo.mMessageInfo.GetPeerAddr());
 
     VerifyOrExit(IsRouterEligible(), error = kErrorInvalidState);
 
@@ -2223,17 +2363,17 @@
     VerifyOrExit(IsAttached(), error = kErrorInvalidState);
 
     // Find Child
-    aMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
+    aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
 
     child = mChildTable.FindChild(extAddr, Child::kInStateAnyExceptInvalid);
     VerifyOrExit(child != nullptr, error = kErrorAlready);
 
     // Version
-    SuccessOrExit(error = Tlv::Find<VersionTlv>(aMessage, version));
+    SuccessOrExit(error = Tlv::Find<VersionTlv>(aRxInfo.mMessage, version));
     VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = kErrorParse);
 
     // Response
-    SuccessOrExit(error = ReadResponse(aMessage, response));
+    SuccessOrExit(error = aRxInfo.mMessage.ReadResponseTlv(response));
     VerifyOrExit(response.Matches(child->GetChallenge(), child->GetChallengeSize()), error = kErrorSecurity);
 
     // Remove existing MLE messages
@@ -2243,26 +2383,26 @@
     Get<MeshForwarder>().RemoveMessages(*child, Message::kSubTypeMleDataResponse);
 
     // Link-Layer and MLE Frame Counters
-    SuccessOrExit(error = ReadFrameCounters(aMessage, linkFrameCounter, mleFrameCounter));
+    SuccessOrExit(error = aRxInfo.mMessage.ReadFrameCounterTlvs(linkFrameCounter, mleFrameCounter));
 
     // Mode
-    SuccessOrExit(error = Tlv::Find<ModeTlv>(aMessage, modeBitmask));
+    SuccessOrExit(error = Tlv::Find<ModeTlv>(aRxInfo.mMessage, modeBitmask));
     mode.Set(modeBitmask);
 
     // Timeout
-    SuccessOrExit(error = Tlv::Find<TimeoutTlv>(aMessage, timeout));
+    SuccessOrExit(error = Tlv::Find<TimeoutTlv>(aRxInfo.mMessage, timeout));
 
     // TLV Request
-    SuccessOrExit(error = FindTlvRequest(aMessage, requestedTlvs));
+    SuccessOrExit(error = aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvs));
     VerifyOrExit(requestedTlvs.mNumTlvs <= Child::kMaxRequestTlvs, error = kErrorParse);
 
     // Active Timestamp
     needsActiveDatasetTlv = true;
-    switch (Tlv::Find<ActiveTimestampTlv>(aMessage, timestamp))
+    switch (Tlv::Find<ActiveTimestampTlv>(aRxInfo.mMessage, timestamp))
     {
     case kErrorNone:
         needsActiveDatasetTlv =
-            (MeshCoP::Timestamp::Compare(&timestamp, Get<MeshCoP::ActiveDataset>().GetTimestamp()) != 0);
+            (MeshCoP::Timestamp::Compare(&timestamp, Get<MeshCoP::ActiveDatasetManager>().GetTimestamp()) != 0);
         break;
     case kErrorNotFound:
         break;
@@ -2272,11 +2412,11 @@
 
     // Pending Timestamp
     needsPendingDatasetTlv = true;
-    switch (Tlv::Find<PendingTimestampTlv>(aMessage, timestamp))
+    switch (Tlv::Find<PendingTimestampTlv>(aRxInfo.mMessage, timestamp))
     {
     case kErrorNone:
         needsPendingDatasetTlv =
-            (MeshCoP::Timestamp::Compare(&timestamp, Get<MeshCoP::PendingDataset>().GetTimestamp()) != 0);
+            (MeshCoP::Timestamp::Compare(&timestamp, Get<MeshCoP::PendingDatasetManager>().GetTimestamp()) != 0);
         break;
     case kErrorNotFound:
         break;
@@ -2286,8 +2426,9 @@
 
     if (!mode.IsFullThreadDevice())
     {
-        SuccessOrExit(error = Tlv::FindTlvOffset(aMessage, Tlv::kAddressRegistration, addressRegistrationOffset));
-        SuccessOrExit(error = UpdateChildAddresses(aMessage, addressRegistrationOffset, *child));
+        SuccessOrExit(error =
+                          Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kAddressRegistration, addressRegistrationOffset));
+        SuccessOrExit(error = UpdateChildAddresses(aRxInfo.mMessage, addressRegistrationOffset, *child));
     }
 
     // Remove from router table
@@ -2311,24 +2452,16 @@
     child->GetLinkFrameCounters().SetAll(linkFrameCounter);
     child->SetLinkAckFrameCounter(linkFrameCounter);
     child->SetMleFrameCounter(mleFrameCounter);
-    child->SetKeySequence(aKeySequence);
+    child->SetKeySequence(aRxInfo.mKeySequence);
     child->SetDeviceMode(mode);
     child->SetVersion(static_cast<uint8_t>(version));
-    child->GetLinkInfo().AddRss(aMessageInfo.GetThreadLinkInfo()->GetRss());
+    child->GetLinkInfo().AddRss(aRxInfo.mMessageInfo.GetThreadLinkInfo()->GetRss());
     child->SetTimeout(timeout);
 #if OPENTHREAD_CONFIG_MULTI_RADIO
     child->ClearLastRxFragmentTag();
 #endif
 
-    if (mode.IsFullNetworkData())
-    {
-        child->SetNetworkDataVersion(mLeaderData.GetDataVersion());
-    }
-    else
-    {
-        child->SetNetworkDataVersion(mLeaderData.GetStableDataVersion());
-    }
-
+    child->SetNetworkDataVersion(mLeaderData.GetDataVersion(mode.GetNetworkDataType()));
     child->ClearRequestTlvs();
 
     for (numTlvs = 0; numTlvs < requestedTlvs.mNumTlvs; numTlvs++)
@@ -2346,6 +2479,8 @@
         child->SetRequestTlv(numTlvs++, Tlv::kPendingDataset);
     }
 
+    aRxInfo.mClass = RxInfo::kAuthoritativeMessage;
+
     switch (mRole)
     {
     case kRoleDisabled:
@@ -2368,7 +2503,7 @@
     LogProcessError(kTypeChildIdRequest, error);
 }
 
-void MleRouter::HandleChildUpdateRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo)
 {
     static const uint8_t kMaxResponseTlvs = 10;
 
@@ -2387,14 +2522,14 @@
     uint16_t        addressRegistrationOffset = 0;
     bool            childDidChange            = false;
 
-    Log(kMessageReceive, kTypeChildUpdateRequestOfChild, aMessageInfo.GetPeerAddr());
+    Log(kMessageReceive, kTypeChildUpdateRequestOfChild, aRxInfo.mMessageInfo.GetPeerAddr());
 
     // Mode
-    SuccessOrExit(error = Tlv::Find<ModeTlv>(aMessage, modeBitmask));
+    SuccessOrExit(error = Tlv::Find<ModeTlv>(aRxInfo.mMessage, modeBitmask));
     mode.Set(modeBitmask);
 
     // Challenge
-    switch (ReadChallenge(aMessage, challenge))
+    switch (aRxInfo.mMessage.ReadChallengeTlv(challenge))
     {
     case kErrorNone:
         tlvs[tlvslength++] = Tlv::kResponse;
@@ -2408,7 +2543,7 @@
 
     tlvs[tlvslength++] = Tlv::kSourceAddress;
 
-    aMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
+    aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
     child = mChildTable.FindChild(extAddr, Child::kInStateAnyExceptInvalid);
 
     if (child == nullptr)
@@ -2418,7 +2553,7 @@
         if (mode.IsRxOnWhenIdle())
         {
             tlvs[tlvslength++] = Tlv::kStatus;
-            SendChildUpdateResponse(nullptr, aMessageInfo, tlvs, tlvslength, challenge);
+            SendChildUpdateResponse(nullptr, aRxInfo.mMessageInfo, tlvs, tlvslength, challenge);
         }
 
         ExitNow();
@@ -2447,16 +2582,18 @@
     }
 
     // IPv6 Address TLV
-    if (Tlv::FindTlvOffset(aMessage, Tlv::kAddressRegistration, addressRegistrationOffset) == kErrorNone)
+    if (Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kAddressRegistration, addressRegistrationOffset) == kErrorNone)
     {
-        SuccessOrExit(error = UpdateChildAddresses(aMessage, addressRegistrationOffset, *child));
+        SuccessOrExit(error = UpdateChildAddresses(aRxInfo.mMessage, addressRegistrationOffset, *child));
         tlvs[tlvslength++] = Tlv::kAddressRegistration;
     }
 
     // Leader Data
-    switch (ReadLeaderData(aMessage, leaderData))
+    switch (aRxInfo.mMessage.ReadLeaderDataTlv(leaderData))
     {
     case kErrorNone:
+        child->SetNetworkDataVersion(leaderData.GetDataVersion(child->GetNetworkDataType()));
+        break;
     case kErrorNotFound:
         break;
     default:
@@ -2464,7 +2601,7 @@
     }
 
     // Timeout
-    switch (Tlv::Find<TimeoutTlv>(aMessage, timeout))
+    switch (Tlv::Find<TimeoutTlv>(aRxInfo.mMessage, timeout))
     {
     case kErrorNone:
         if (child->GetTimeout() != timeout)
@@ -2484,7 +2621,7 @@
     }
 
     // TLV Request
-    switch (FindTlvRequest(aMessage, requestedTlvs))
+    switch (aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvs))
     {
     case kErrorNone:
         VerifyOrExit(requestedTlvs.mNumTlvs <= (kMaxResponseTlvs - tlvslength), error = kErrorParse);
@@ -2509,12 +2646,14 @@
         CslChannelTlv cslChannel;
         uint32_t      cslTimeout;
 
-        if (Tlv::Find<CslTimeoutTlv>(aMessage, cslTimeout) == kErrorNone)
+        if (Tlv::Find<CslTimeoutTlv>(aRxInfo.mMessage, cslTimeout) == kErrorNone)
         {
             child->SetCslTimeout(cslTimeout);
+            // MUST include CSL accuracy TLV when request includes CSL timeout
+            tlvs[tlvslength++] = Tlv::kCslClockAccuracy;
         }
 
-        if (Tlv::FindTlv(aMessage, cslChannel) == kErrorNone)
+        if (Tlv::FindTlv(aRxInfo.mMessage, cslChannel) == kErrorNone)
         {
             child->SetCslChannel(static_cast<uint8_t>(cslChannel.GetChannel()));
         }
@@ -2530,8 +2669,8 @@
 
     if (oldMode != child->GetDeviceMode())
     {
-        otLogNoteMle("Child 0x%04x mode change 0x%02x -> 0x%02x [%s]", child->GetRloc16(), oldMode.Get(),
-                     child->GetDeviceMode().Get(), child->GetDeviceMode().ToString().AsCString());
+        LogNote("Child 0x%04x mode change 0x%02x -> 0x%02x [%s]", child->GetRloc16(), oldMode.Get(),
+                child->GetDeviceMode().Get(), child->GetDeviceMode().ToString().AsCString());
 
         childDidChange = true;
 
@@ -2567,16 +2706,15 @@
     }
 #endif
 
-    SendChildUpdateResponse(child, aMessageInfo, tlvs, tlvslength, challenge);
+    SendChildUpdateResponse(child, aRxInfo.mMessageInfo, tlvs, tlvslength, challenge);
+
+    aRxInfo.mClass = RxInfo::kPeerMessage;
 
 exit:
     LogProcessError(kTypeChildUpdateRequestOfChild, error);
 }
 
-void MleRouter::HandleChildUpdateResponse(const Message &         aMessage,
-                                          const Ip6::MessageInfo &aMessageInfo,
-                                          uint32_t                aKeySequence,
-                                          Neighbor *              aNeighbor)
+void MleRouter::HandleChildUpdateResponse(RxInfo &aRxInfo)
 {
     Error      error = kErrorNone;
     uint16_t   sourceAddress;
@@ -2589,31 +2727,32 @@
     Child *    child;
     uint16_t   addressRegistrationOffset = 0;
 
-    if ((aNeighbor == nullptr) || IsActiveRouter(aNeighbor->GetRloc16()))
+    if ((aRxInfo.mNeighbor == nullptr) || IsActiveRouter(aRxInfo.mNeighbor->GetRloc16()))
     {
-        Log(kMessageReceive, kTypeChildUpdateResponseOfUnknownChild, aMessageInfo.GetPeerAddr());
+        Log(kMessageReceive, kTypeChildUpdateResponseOfUnknownChild, aRxInfo.mMessageInfo.GetPeerAddr());
         ExitNow(error = kErrorNotFound);
     }
 
-    child = static_cast<Child *>(aNeighbor);
+    child = static_cast<Child *>(aRxInfo.mNeighbor);
 
     // Response
-    switch (ReadResponse(aMessage, response))
+    switch (aRxInfo.mMessage.ReadResponseTlv(response))
     {
     case kErrorNone:
         VerifyOrExit(response.Matches(child->GetChallenge(), child->GetChallengeSize()), error = kErrorSecurity);
         break;
     case kErrorNotFound:
         VerifyOrExit(child->IsStateValid(), error = kErrorSecurity);
+        response.mLength = 0;
         break;
     default:
         ExitNow(error = kErrorNone);
     }
 
-    Log(kMessageReceive, kTypeChildUpdateResponseOfChild, aMessageInfo.GetPeerAddr(), child->GetRloc16());
+    Log(kMessageReceive, kTypeChildUpdateResponseOfChild, aRxInfo.mMessageInfo.GetPeerAddr(), child->GetRloc16());
 
     // Source Address
-    switch (Tlv::Find<SourceAddressTlv>(aMessage, sourceAddress))
+    switch (Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress))
     {
     case kErrorNone:
         if (child->GetRloc16() != sourceAddress)
@@ -2632,7 +2771,7 @@
     }
 
     // Status
-    switch (Tlv::Find<ThreadStatusTlv>(aMessage, status))
+    switch (Tlv::Find<ThreadStatusTlv>(aRxInfo.mMessage, status))
     {
     case kErrorNone:
         VerifyOrExit(status != StatusTlv::kError, RemoveNeighbor(*child));
@@ -2645,7 +2784,7 @@
 
     // Link-Layer Frame Counter
 
-    switch (Tlv::Find<LinkFrameCounterTlv>(aMessage, linkFrameCounter))
+    switch (Tlv::Find<LinkFrameCounterTlv>(aRxInfo.mMessage, linkFrameCounter))
     {
     case kErrorNone:
         child->GetLinkFrameCounters().SetAll(linkFrameCounter);
@@ -2658,7 +2797,7 @@
     }
 
     // MLE Frame Counter
-    switch (Tlv::Find<MleFrameCounterTlv>(aMessage, mleFrameCounter))
+    switch (Tlv::Find<MleFrameCounterTlv>(aRxInfo.mMessage, mleFrameCounter))
     {
     case kErrorNone:
         child->SetMleFrameCounter(mleFrameCounter);
@@ -2670,7 +2809,7 @@
     }
 
     // Timeout
-    switch (Tlv::Find<TimeoutTlv>(aMessage, timeout))
+    switch (Tlv::Find<TimeoutTlv>(aRxInfo.mMessage, timeout))
     {
     case kErrorNone:
         child->SetTimeout(timeout);
@@ -2682,23 +2821,16 @@
     }
 
     // IPv6 Address
-    if (Tlv::FindTlvOffset(aMessage, Tlv::kAddressRegistration, addressRegistrationOffset) == kErrorNone)
+    if (Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kAddressRegistration, addressRegistrationOffset) == kErrorNone)
     {
-        SuccessOrExit(error = UpdateChildAddresses(aMessage, addressRegistrationOffset, *child));
+        SuccessOrExit(error = UpdateChildAddresses(aRxInfo.mMessage, addressRegistrationOffset, *child));
     }
 
     // Leader Data
-    switch (ReadLeaderData(aMessage, leaderData))
+    switch (aRxInfo.mMessage.ReadLeaderDataTlv(leaderData))
     {
     case kErrorNone:
-        if (child->IsFullNetworkData())
-        {
-            child->SetNetworkDataVersion(leaderData.GetDataVersion());
-        }
-        else
-        {
-            child->SetNetworkDataVersion(leaderData.GetStableDataVersion());
-        }
+        child->SetNetworkDataVersion(leaderData.GetDataVersion(child->GetNetworkDataType()));
         break;
     case kErrorNotFound:
         break;
@@ -2708,16 +2840,16 @@
 
     SetChildStateToValid(*child);
     child->SetLastHeard(TimerMilli::GetNow());
-    child->SetKeySequence(aKeySequence);
-    child->GetLinkInfo().AddRss(aMessageInfo.GetThreadLinkInfo()->GetRss());
+    child->SetKeySequence(aRxInfo.mKeySequence);
+    child->GetLinkInfo().AddRss(aRxInfo.mMessageInfo.GetThreadLinkInfo()->GetRss());
+
+    aRxInfo.mClass = (response.mLength == 0) ? RxInfo::kPeerMessage : RxInfo::kAuthoritativeMessage;
 
 exit:
     LogProcessError(kTypeChildUpdateResponseOfChild, error);
 }
 
-void MleRouter::HandleDataRequest(const Message &         aMessage,
-                                  const Ip6::MessageInfo &aMessageInfo,
-                                  const Neighbor *        aNeighbor)
+void MleRouter::HandleDataRequest(RxInfo &aRxInfo)
 {
     Error              error = kErrorNone;
     RequestedTlvs      requestedTlvs;
@@ -2725,12 +2857,12 @@
     uint8_t            tlvs[4];
     uint8_t            numTlvs;
 
-    Log(kMessageReceive, kTypeDataRequest, aMessageInfo.GetPeerAddr());
+    Log(kMessageReceive, kTypeDataRequest, aRxInfo.mMessageInfo.GetPeerAddr());
 
-    VerifyOrExit(aNeighbor && aNeighbor->IsStateValid(), error = kErrorSecurity);
+    VerifyOrExit(aRxInfo.mNeighbor && aRxInfo.mNeighbor->IsStateValid(), error = kErrorSecurity);
 
     // TLV Request
-    SuccessOrExit(error = FindTlvRequest(aMessage, requestedTlvs));
+    SuccessOrExit(error = aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvs));
     VerifyOrExit(requestedTlvs.mNumTlvs <= sizeof(tlvs), error = kErrorParse);
 
     memset(tlvs, Tlv::kInvalid, sizeof(tlvs));
@@ -2738,10 +2870,10 @@
     numTlvs = requestedTlvs.mNumTlvs;
 
     // Active Timestamp
-    switch (Tlv::Find<ActiveTimestampTlv>(aMessage, timestamp))
+    switch (Tlv::Find<ActiveTimestampTlv>(aRxInfo.mMessage, timestamp))
     {
     case kErrorNone:
-        if (MeshCoP::Timestamp::Compare(&timestamp, Get<MeshCoP::ActiveDataset>().GetTimestamp()) == 0)
+        if (MeshCoP::Timestamp::Compare(&timestamp, Get<MeshCoP::ActiveDatasetManager>().GetTimestamp()) == 0)
         {
             break;
         }
@@ -2757,10 +2889,10 @@
     }
 
     // Pending Timestamp
-    switch (Tlv::Find<PendingTimestampTlv>(aMessage, timestamp))
+    switch (Tlv::Find<PendingTimestampTlv>(aRxInfo.mMessage, timestamp))
     {
     case kErrorNone:
-        if (MeshCoP::Timestamp::Compare(&timestamp, Get<MeshCoP::PendingDataset>().GetTimestamp()) == 0)
+        if (MeshCoP::Timestamp::Compare(&timestamp, Get<MeshCoP::PendingDatasetManager>().GetTimestamp()) == 0)
         {
             break;
         }
@@ -2775,7 +2907,9 @@
         ExitNow(error = kErrorParse);
     }
 
-    SendDataResponse(aMessageInfo.GetPeerAddr(), tlvs, numTlvs, 0, &aMessage);
+    aRxInfo.mClass = RxInfo::kPeerMessage;
+
+    SendDataResponse(aRxInfo.mMessageInfo.GetPeerAddr(), tlvs, numTlvs, 0, &aRxInfo.mMessage);
 
 exit:
     LogProcessError(kTypeDataRequest, error);
@@ -2806,23 +2940,12 @@
 
     for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
     {
-        uint8_t version;
-
         if (child.IsRxOnWhenIdle())
         {
             continue;
         }
 
-        if (child.IsFullNetworkData())
-        {
-            version = Get<NetworkData::Leader>().GetVersion();
-        }
-        else
-        {
-            version = Get<NetworkData::Leader>().GetStableVersion();
-        }
-
-        if (child.GetNetworkDataVersion() == version)
+        if (child.GetNetworkDataVersion() == Get<NetworkData::Leader>().GetVersion(child.GetNetworkDataType()))
         {
             continue;
         }
@@ -2862,17 +2985,17 @@
 }
 #endif // OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
 
-void MleRouter::HandleDiscoveryRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+void MleRouter::HandleDiscoveryRequest(RxInfo &aRxInfo)
 {
     Error                        error = kErrorNone;
     Tlv                          tlv;
     MeshCoP::Tlv                 meshcopTlv;
     MeshCoP::DiscoveryRequestTlv discoveryRequest;
-    Mac::ExtendedPanId           extPanId;
+    MeshCoP::ExtendedPanId       extPanId;
     uint16_t                     offset;
     uint16_t                     end;
 
-    Log(kMessageReceive, kTypeDiscoveryRequest, aMessageInfo.GetPeerAddr());
+    Log(kMessageReceive, kTypeDiscoveryRequest, aRxInfo.mMessageInfo.GetPeerAddr());
 
     discoveryRequest.SetLength(0);
 
@@ -2880,27 +3003,27 @@
     VerifyOrExit(IsRouterEligible(), error = kErrorInvalidState);
 
     // find MLE Discovery TLV
-    VerifyOrExit(Tlv::FindTlvOffset(aMessage, Tlv::kDiscovery, offset) == kErrorNone, error = kErrorParse);
-    IgnoreError(aMessage.Read(offset, tlv));
+    VerifyOrExit(Tlv::FindTlvOffset(aRxInfo.mMessage, Tlv::kDiscovery, offset) == kErrorNone, error = kErrorParse);
+    IgnoreError(aRxInfo.mMessage.Read(offset, tlv));
 
     offset += sizeof(tlv);
     end = offset + sizeof(tlv) + tlv.GetLength();
 
     while (offset < end)
     {
-        IgnoreError(aMessage.Read(offset, meshcopTlv));
+        IgnoreError(aRxInfo.mMessage.Read(offset, meshcopTlv));
 
         switch (meshcopTlv.GetType())
         {
         case MeshCoP::Tlv::kDiscoveryRequest:
-            IgnoreError(aMessage.Read(offset, discoveryRequest));
+            IgnoreError(aRxInfo.mMessage.Read(offset, discoveryRequest));
             VerifyOrExit(discoveryRequest.IsValid(), error = kErrorParse);
 
             break;
 
         case MeshCoP::Tlv::kExtendedPanId:
-            SuccessOrExit(error = Tlv::Read<MeshCoP::ExtendedPanIdTlv>(aMessage, offset, extPanId));
-            VerifyOrExit(Get<Mac::Mac>().GetExtendedPanId() != extPanId, error = kErrorDrop);
+            SuccessOrExit(error = Tlv::Read<MeshCoP::ExtendedPanIdTlv>(aRxInfo.mMessage, offset, extPanId));
+            VerifyOrExit(Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId() != extPanId, error = kErrorDrop);
 
             break;
 
@@ -2917,7 +3040,7 @@
         {
             otThreadDiscoveryRequestInfo info;
 
-            aMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(AsCoreType(&info.mExtAddress));
+            aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(AsCoreType(&info.mExtAddress));
             info.mVersion  = discoveryRequest.GetVersion();
             info.mIsJoiner = discoveryRequest.IsJoiner();
 
@@ -2938,7 +3061,7 @@
         }
     }
 
-    error = SendDiscoveryResponse(aMessageInfo.GetPeerAddr(), aMessage);
+    error = SendDiscoveryResponse(aRxInfo.mMessageInfo.GetPeerAddr(), aRxInfo.mMessage);
 
 exit:
     LogProcessError(kTypeDiscoveryRequest, error);
@@ -2947,15 +3070,14 @@
 Error MleRouter::SendDiscoveryResponse(const Ip6::Address &aDestination, const Message &aDiscoverRequestMessage)
 {
     Error                         error = kErrorNone;
-    Message *                     message;
+    TxMessage *                   message;
     uint16_t                      startOffset;
     Tlv                           tlv;
     MeshCoP::DiscoveryResponseTlv discoveryResponse;
     MeshCoP::NetworkNameTlv       networkName;
     uint16_t                      delay;
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    message->SetSubType(Message::kSubTypeMleDiscoverResponse);
+    VerifyOrExit((message = NewMleMessage(kCommandDiscoveryResponse)) != nullptr, error = kErrorNoBufs);
     message->SetPanId(aDiscoverRequestMessage.GetPanId());
 #if OPENTHREAD_CONFIG_MULTI_RADIO
     // Send the MLE Discovery Response message on same radio link
@@ -2963,8 +3085,6 @@
     message->SetRadioType(aDiscoverRequestMessage.GetRadioType());
 #endif
 
-    SuccessOrExit(error = AppendHeader(*message, kCommandDiscoveryResponse));
-
     // Discovery TLV
     tlv.SetType(Tlv::kDiscovery);
     SuccessOrExit(error = message->Append(tlv));
@@ -2997,11 +3117,12 @@
     SuccessOrExit(error = discoveryResponse.AppendTo(*message));
 
     // Extended PAN ID TLV
-    SuccessOrExit(error = Tlv::Append<MeshCoP::ExtendedPanIdTlv>(*message, Get<Mac::Mac>().GetExtendedPanId()));
+    SuccessOrExit(
+        error = Tlv::Append<MeshCoP::ExtendedPanIdTlv>(*message, Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId()));
 
     // Network Name TLV
     networkName.Init();
-    networkName.SetNetworkName(Get<Mac::Mac>().GetNetworkName().GetAsData());
+    networkName.SetNetworkName(Get<MeshCoP::NetworkNameManager>().GetNetworkName().GetAsData());
     SuccessOrExit(error = networkName.AppendTo(*message));
 
 #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
@@ -3033,7 +3154,7 @@
 
     delay = Random::NonCrypto::GetUint16InRange(0, kDiscoveryMaxJitter + 1);
 
-    SuccessOrExit(error = AddDelayedResponse(*message, aDestination, delay));
+    SuccessOrExit(error = message->SendAfterDelay(aDestination, delay));
 
     Log(kMessageDelay, kTypeDiscoveryResponse, aDestination);
 
@@ -3047,16 +3168,15 @@
 {
     Error        error = kErrorNone;
     Ip6::Address destination;
-    Message *    message;
+    TxMessage *  message;
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    SuccessOrExit(error = AppendHeader(*message, kCommandChildIdResponse));
-    SuccessOrExit(error = AppendSourceAddress(*message));
-    SuccessOrExit(error = AppendLeaderData(*message));
-    SuccessOrExit(error = AppendActiveTimestamp(*message));
-    SuccessOrExit(error = AppendPendingTimestamp(*message));
+    VerifyOrExit((message = NewMleMessage(kCommandChildIdResponse)) != nullptr, error = kErrorNoBufs);
+    SuccessOrExit(error = message->AppendSourceAddressTlv());
+    SuccessOrExit(error = message->AppendLeaderDataTlv());
+    SuccessOrExit(error = message->AppendActiveTimestampTlv());
+    SuccessOrExit(error = message->AppendPendingTimestampTlv());
 
-    if (aChild.GetRloc16() == 0)
+    if ((aChild.GetRloc16() == 0) || !RouterIdMatch(aChild.GetRloc16(), GetRloc16()))
     {
         uint16_t rloc16;
 
@@ -3078,26 +3198,26 @@
         aChild.SetRloc16(rloc16);
     }
 
-    SuccessOrExit(error = AppendAddress16(*message, aChild.GetRloc16()));
+    SuccessOrExit(error = message->AppendAddress16Tlv(aChild.GetRloc16()));
 
     for (uint8_t i = 0; i < Child::kMaxRequestTlvs; i++)
     {
         switch (aChild.GetRequestTlv(i))
         {
         case Tlv::kNetworkData:
-            SuccessOrExit(error = AppendNetworkData(*message, !aChild.IsFullNetworkData()));
+            SuccessOrExit(error = message->AppendNetworkDataTlv(aChild.GetNetworkDataType()));
             break;
 
         case Tlv::kRoute:
-            SuccessOrExit(error = AppendRoute(*message));
+            SuccessOrExit(error = message->AppendRouteTlv());
             break;
 
         case Tlv::kActiveDataset:
-            SuccessOrExit(error = AppendActiveDataset(*message));
+            SuccessOrExit(error = message->AppendActiveDatasetTlv());
             break;
 
         case Tlv::kPendingDataset:
-            SuccessOrExit(error = AppendPendingDataset(*message));
+            SuccessOrExit(error = message->AppendPendingDatasetTlv());
             break;
 
         default:
@@ -3107,7 +3227,7 @@
 
     if (!aChild.IsFullThreadDevice())
     {
-        SuccessOrExit(error = AppendChildAddresses(*message, aChild));
+        SuccessOrExit(error = message->AppendAddresseRegisterationTlv(aChild));
     }
 
     SetChildStateToValid(aChild);
@@ -3125,7 +3245,7 @@
 #endif
 
     destination.SetToLinkLocalAddress(aChild.GetExtAddress());
-    SuccessOrExit(error = SendMessage(*message, destination));
+    SuccessOrExit(error = message->SendTo(destination));
 
     Log(kMessageSend, kTypeChildIdResponse, destination, aChild.GetRloc16());
 
@@ -3139,15 +3259,15 @@
     static const uint8_t tlvs[] = {Tlv::kTimeout, Tlv::kAddressRegistration};
     Error                error  = kErrorNone;
     Ip6::Address         destination;
-    Message *            message;
+    TxMessage *          message = nullptr;
 
     if (!aChild.IsRxOnWhenIdle())
     {
         uint16_t childIndex = Get<ChildTable>().GetChildIndex(aChild);
 
-        for (message = Get<MeshForwarder>().GetSendQueue().GetHead(); message; message = message->GetNext())
+        for (const Message &msg : Get<MeshForwarder>().GetSendQueue())
         {
-            if (message->GetChildMask(childIndex) && message->GetSubType() == Message::kSubTypeMleChildUpdateRequest)
+            if (msg.GetChildMask(childIndex) && msg.GetSubType() == Message::kSubTypeMleChildUpdateRequest)
             {
                 // No need to send the resync "Child Update Request" to the sleepy child
                 // if there is one already queued.
@@ -3163,24 +3283,22 @@
         }
     }
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    message->SetSubType(Message::kSubTypeMleChildUpdateRequest);
-    SuccessOrExit(error = AppendHeader(*message, kCommandChildUpdateRequest));
-    SuccessOrExit(error = AppendSourceAddress(*message));
-    SuccessOrExit(error = AppendLeaderData(*message));
-    SuccessOrExit(error = AppendNetworkData(*message, !aChild.IsFullNetworkData()));
-    SuccessOrExit(error = AppendActiveTimestamp(*message));
-    SuccessOrExit(error = AppendPendingTimestamp(*message));
+    VerifyOrExit((message = NewMleMessage(kCommandChildUpdateRequest)) != nullptr, error = kErrorNoBufs);
+    SuccessOrExit(error = message->AppendSourceAddressTlv());
+    SuccessOrExit(error = message->AppendLeaderDataTlv());
+    SuccessOrExit(error = message->AppendNetworkDataTlv(aChild.GetNetworkDataType()));
+    SuccessOrExit(error = message->AppendActiveTimestampTlv());
+    SuccessOrExit(error = message->AppendPendingTimestampTlv());
 
     if (!aChild.IsStateValid())
     {
-        SuccessOrExit(error = AppendTlvRequest(*message, tlvs, sizeof(tlvs)));
+        SuccessOrExit(error = message->AppendTlvRequestTlv(tlvs, sizeof(tlvs)));
         aChild.GenerateChallenge();
-        SuccessOrExit(error = AppendChallenge(*message, aChild.GetChallenge(), aChild.GetChallengeSize()));
+        SuccessOrExit(error = message->AppendChallengeTlv(aChild.GetChallenge(), aChild.GetChallengeSize()));
     }
 
     destination.SetToLinkLocalAddress(aChild.GetExtAddress());
-    SuccessOrExit(error = SendMessage(*message, destination));
+    SuccessOrExit(error = message->SendTo(destination));
 
     if (aChild.IsRxOnWhenIdle())
     {
@@ -3201,61 +3319,69 @@
                                         uint8_t                 aTlvsLength,
                                         const Challenge &       aChallenge)
 {
-    Error    error = kErrorNone;
-    Message *message;
+    Error      error = kErrorNone;
+    TxMessage *message;
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    SuccessOrExit(error = AppendHeader(*message, kCommandChildUpdateResponse));
+    VerifyOrExit((message = NewMleMessage(kCommandChildUpdateResponse)) != nullptr, error = kErrorNoBufs);
 
     for (int i = 0; i < aTlvsLength; i++)
     {
         switch (aTlvs[i])
         {
         case Tlv::kStatus:
-            SuccessOrExit(error = AppendStatus(*message, StatusTlv::kError));
+            SuccessOrExit(error = message->AppendStatusTlv(StatusTlv::kError));
             break;
 
         case Tlv::kAddressRegistration:
-            SuccessOrExit(error = AppendChildAddresses(*message, *aChild));
+            SuccessOrExit(error = message->AppendAddresseRegisterationTlv(*aChild));
             break;
 
         case Tlv::kLeaderData:
-            SuccessOrExit(error = AppendLeaderData(*message));
+            SuccessOrExit(error = message->AppendLeaderDataTlv());
             break;
 
         case Tlv::kMode:
-            SuccessOrExit(error = AppendMode(*message, aChild->GetDeviceMode()));
+            SuccessOrExit(error = message->AppendModeTlv(aChild->GetDeviceMode()));
             break;
 
         case Tlv::kNetworkData:
-            SuccessOrExit(error = AppendNetworkData(*message, !aChild->IsFullNetworkData()));
-            SuccessOrExit(error = AppendActiveTimestamp(*message));
-            SuccessOrExit(error = AppendPendingTimestamp(*message));
+            SuccessOrExit(error = message->AppendNetworkDataTlv(aChild->GetNetworkDataType()));
+            SuccessOrExit(error = message->AppendActiveTimestampTlv());
+            SuccessOrExit(error = message->AppendPendingTimestampTlv());
             break;
 
         case Tlv::kResponse:
-            SuccessOrExit(error = AppendResponse(*message, aChallenge));
+            SuccessOrExit(error = message->AppendResponseTlv(aChallenge));
             break;
 
         case Tlv::kSourceAddress:
-            SuccessOrExit(error = AppendSourceAddress(*message));
+            SuccessOrExit(error = message->AppendSourceAddressTlv());
             break;
 
         case Tlv::kTimeout:
-            SuccessOrExit(error = AppendTimeout(*message, aChild->GetTimeout()));
+            SuccessOrExit(error = message->AppendTimeoutTlv(aChild->GetTimeout()));
             break;
 
         case Tlv::kMleFrameCounter:
-            SuccessOrExit(error = AppendMleFrameCounter(*message));
+            SuccessOrExit(error = message->AppendMleFrameCounterTlv());
             break;
 
         case Tlv::kLinkFrameCounter:
-            SuccessOrExit(error = AppendLinkFrameCounter(*message));
+            SuccessOrExit(error = message->AppendLinkFrameCounterTlv());
             break;
+
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+        case Tlv::kCslClockAccuracy:
+            if (!aChild->IsRxOnWhenIdle())
+            {
+                SuccessOrExit(error = message->AppendCslClockAccuracyTlv());
+            }
+            break;
+#endif
         }
     }
 
-    SuccessOrExit(error = SendMessage(*message, aMessageInfo.GetPeerAddr()));
+    SuccessOrExit(error = message->SendTo(aMessageInfo.GetPeerAddr()));
 
     if (aChild == nullptr)
     {
@@ -3278,41 +3404,38 @@
 {
     OT_UNUSED_VARIABLE(aRequestMessage);
 
-    Error     error   = kErrorNone;
-    Message * message = nullptr;
-    Neighbor *neighbor;
-    bool      stableOnly;
+    Error      error   = kErrorNone;
+    TxMessage *message = nullptr;
+    Neighbor * neighbor;
 
     if (mRetrieveNewNetworkData)
     {
-        otLogInfoMle("Suppressing Data Response - waiting for new network data");
+        LogInfo("Suppressing Data Response - waiting for new network data");
         ExitNow();
     }
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    message->SetSubType(Message::kSubTypeMleDataResponse);
-    SuccessOrExit(error = AppendHeader(*message, kCommandDataResponse));
-    SuccessOrExit(error = AppendSourceAddress(*message));
-    SuccessOrExit(error = AppendLeaderData(*message));
-    SuccessOrExit(error = AppendActiveTimestamp(*message));
-    SuccessOrExit(error = AppendPendingTimestamp(*message));
+    VerifyOrExit((message = NewMleMessage(kCommandDataResponse)) != nullptr, error = kErrorNoBufs);
+    SuccessOrExit(error = message->AppendSourceAddressTlv());
+    SuccessOrExit(error = message->AppendLeaderDataTlv());
+    SuccessOrExit(error = message->AppendActiveTimestampTlv());
+    SuccessOrExit(error = message->AppendPendingTimestampTlv());
 
     for (int i = 0; i < aTlvsLength; i++)
     {
         switch (aTlvs[i])
         {
         case Tlv::kNetworkData:
-            neighbor   = mNeighborTable.FindNeighbor(aDestination);
-            stableOnly = neighbor != nullptr ? !neighbor->IsFullNetworkData() : false;
-            SuccessOrExit(error = AppendNetworkData(*message, stableOnly));
+            neighbor = mNeighborTable.FindNeighbor(aDestination);
+            SuccessOrExit(error = message->AppendNetworkDataTlv((neighbor != nullptr) ? neighbor->GetNetworkDataType()
+                                                                                      : NetworkData::kFullSet));
             break;
 
         case Tlv::kActiveDataset:
-            SuccessOrExit(error = AppendActiveDataset(*message));
+            SuccessOrExit(error = message->AppendActiveDatasetTlv());
             break;
 
         case Tlv::kPendingDataset:
-            SuccessOrExit(error = AppendPendingDataset(*message));
+            SuccessOrExit(error = message->AppendPendingDatasetTlv());
             break;
 
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
@@ -3334,12 +3457,12 @@
         // Remove multicast MLE Data Response from Delayed Message Queue.
         RemoveDelayedDataResponseMessage();
 
-        SuccessOrExit(error = AddDelayedResponse(*message, aDestination, aDelay));
+        SuccessOrExit(error = message->SendAfterDelay(aDestination, aDelay));
         Log(kMessageDelay, kTypeDataResponse, aDestination);
     }
     else
     {
-        SuccessOrExit(error = SendMessage(*message, aDestination));
+        SuccessOrExit(error = message->SendTo(aDestination));
         Log(kMessageSend, kTypeDataResponse, aDestination);
     }
 
@@ -3554,7 +3677,7 @@
     return;
 }
 
-Error MleRouter::CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header)
+Error MleRouter::CheckReachability(uint16_t aMeshDest, const Ip6::Header &aIp6Header)
 {
     Error error = kErrorNone;
 
@@ -3601,15 +3724,13 @@
 Error MleRouter::SendAddressSolicit(ThreadStatusTlv::Status aStatus)
 {
     Error            error = kErrorNone;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
     Coap::Message *  message = nullptr;
 
     VerifyOrExit(!mAddressSolicitPending);
 
-    VerifyOrExit((message = Get<Tmf::Agent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kAddressSolicit));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(UriPath::kAddressSolicit);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = Tlv::Append<ThreadExtMacAddressTlv>(*message, Get<Mac::Mac>().GetExtAddress()));
 
@@ -3621,15 +3742,12 @@
     SuccessOrExit(error = Tlv::Append<ThreadStatusTlv>(*message, aStatus));
 
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-    SuccessOrExit(error = AppendXtalAccuracy(*message));
+    SuccessOrExit(error = Tlv::Append<XtalAccuracyTlv>(*message, otPlatTimeGetXtalAccuracy()));
 #endif
 
-    SuccessOrExit(error = GetLeaderAddress(messageInfo.GetPeerAddr()));
-    messageInfo.SetSockAddr(GetMeshLocal16());
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
+    SuccessOrExit(error = messageInfo.SetSockAddrToRlocPeerAddrToLeaderRloc());
 
-    SuccessOrExit(
-        error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, &MleRouter::HandleAddressSolicitResponse, this));
+    SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, &HandleAddressSolicitResponse, this));
     mAddressSolicitPending = true;
 
     Log(kMessageSend, kTypeAddressSolicit, messageInfo.GetPeerAddr());
@@ -3639,25 +3757,22 @@
     return error;
 }
 
-void MleRouter::SendAddressRelease(void)
+void MleRouter::SendAddressRelease(Coap::ResponseHandler aResponseHandler, void *aResponseHandlerContext)
 {
     Error            error = kErrorNone;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
     Coap::Message *  message;
 
-    VerifyOrExit((message = Get<Tmf::Agent>().NewMessage()) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kAddressRelease));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(UriPath::kAddressRelease);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = Tlv::Append<ThreadRloc16Tlv>(*message, Rloc16FromRouterId(mRouterId)));
-
     SuccessOrExit(error = Tlv::Append<ThreadExtMacAddressTlv>(*message, Get<Mac::Mac>().GetExtAddress()));
 
-    messageInfo.SetSockAddr(GetMeshLocal16());
-    SuccessOrExit(error = GetLeaderAddress(messageInfo.GetPeerAddr()));
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
-    SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
+    SuccessOrExit(error = messageInfo.SetSockAddrToRlocPeerAddrToLeaderRloc());
+
+    SuccessOrExit(error =
+                      Get<Tmf::Agent>().SendMessage(*message, messageInfo, aResponseHandler, aResponseHandlerContext));
 
     Log(kMessageSend, kTypeAddressRelease, messageInfo.GetPeerAddr());
 
@@ -3679,8 +3794,6 @@
                                              const Ip6::MessageInfo *aMessageInfo,
                                              Error                   aResult)
 {
-    OT_UNUSED_VARIABLE(aMessageInfo);
-
     uint8_t             status;
     uint16_t            rloc16;
     ThreadRouterMaskTlv routerMaskTlv;
@@ -3690,7 +3803,7 @@
 
     mAddressSolicitPending = false;
 
-    VerifyOrExit(aResult == kErrorNone && aMessage != nullptr && aMessage != nullptr);
+    VerifyOrExit(aResult == kErrorNone && aMessage != nullptr && aMessageInfo != nullptr);
 
     VerifyOrExit(aMessage->GetCode() == Coap::kCodeChanged);
 
@@ -3753,18 +3866,15 @@
         leader->SetNextHop(RouterIdFromRloc16(mParent.GetRloc16()));
     }
 
-    // send link request
-    IgnoreError(SendLinkRequest(nullptr));
-
-    // send child id responses
     for (Child &child : Get<ChildTable>().Iterate(Child::kInStateChildIdRequest))
     {
         IgnoreError(SendChildIdResponse(child));
     }
 
-exit:
+    mLinkRequestDelay = kMulticastLinkRequestDelay;
 
-    // send announce after received address solicit reply if needed
+exit:
+    // Send announce after received address solicit reply if needed
     InformPreviousChannel();
 }
 
@@ -3784,14 +3894,12 @@
 
 void MleRouter::HandleAddressSolicit(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
 {
-    Error           error = kErrorNone;
-    Mac::ExtAddress extAddress;
-    uint16_t        rloc16;
-    uint8_t         status;
-    Router *        router = nullptr;
-#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-    uint16_t xtalAccuracy;
-#endif
+    Error                   error          = kErrorNone;
+    ThreadStatusTlv::Status responseStatus = ThreadStatusTlv::kNoAddressAvailable;
+    Router *                router         = nullptr;
+    Mac::ExtAddress         extAddress;
+    uint16_t                rloc16;
+    uint8_t                 status;
 
     VerifyOrExit(aMessage.IsConfirmablePostRequest(), error = kErrorParse);
 
@@ -3800,21 +3908,35 @@
     SuccessOrExit(error = Tlv::Find<ThreadExtMacAddressTlv>(aMessage, extAddress));
     SuccessOrExit(error = Tlv::Find<ThreadStatusTlv>(aMessage, status));
 
+    switch (Tlv::Find<ThreadRloc16Tlv>(aMessage, rloc16))
+    {
+    case kErrorNone:
+        break;
+    case kErrorNotFound:
+        rloc16 = Mac::kShortAddrInvalid;
+        break;
+    default:
+        ExitNow(error = kErrorParse);
+    }
+
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-    // In a time sync enabled network, all routers' xtal accuracy must be less than the threshold.
-    SuccessOrExit(Tlv::Find<XtalAccuracyTlv>(aMessage, xtalAccuracy));
-    VerifyOrExit(xtalAccuracy <= Get<TimeSync>().GetXtalThreshold());
+    {
+        uint16_t xtalAccuracy;
+
+        SuccessOrExit(Tlv::Find<XtalAccuracyTlv>(aMessage, xtalAccuracy));
+        VerifyOrExit(xtalAccuracy <= Get<TimeSync>().GetXtalThreshold());
+    }
 #endif
 
-    // see if allocation already exists
+    // Check if allocation already exists
     router = mRouterTable.GetRouter(extAddress);
 
     if (router != nullptr)
     {
+        responseStatus = ThreadStatusTlv::kSuccess;
         ExitNow();
     }
 
-    // check the request reason
     switch (status)
     {
     case ThreadStatusTlv::kTooFewRouters:
@@ -3825,82 +3947,79 @@
     case ThreadStatusTlv::kParentPartitionChange:
         break;
 
+    case ThreadStatusTlv::kBorderRouterRequest:
+        if ((mRouterTable.GetActiveRouterCount() >= mRouterUpgradeThreshold) &&
+            (Get<NetworkData::Leader>().CountBorderRouters(NetworkData::kRouterRoleOnly) >=
+             kRouterUpgradeBorderRouterRequestThreshold))
+        {
+            LogInfo("Rejecting BR %s router role req - have %d BR routers", extAddress.ToString().AsCString(),
+                    kRouterUpgradeBorderRouterRequestThreshold);
+            ExitNow();
+        }
+        break;
+
     default:
-        ExitNow(error = kErrorParse);
-        OT_UNREACHABLE_CODE(break);
+        responseStatus = ThreadStatusTlv::kUnrecognizedStatus;
+        ExitNow();
     }
 
-    switch (Tlv::Find<ThreadRloc16Tlv>(aMessage, rloc16))
+    if (rloc16 != Mac::kShortAddrInvalid)
     {
-    case kErrorNone:
         router = mRouterTable.Allocate(RouterIdFromRloc16(rloc16));
-        break;
-    case kErrorNotFound:
-        break;
-    default:
-        ExitNow(error = kErrorParse);
+
+        if (router != nullptr)
+        {
+            LogInfo("Router id %d requested and provided!", RouterIdFromRloc16(rloc16));
+        }
     }
 
-    // allocate new router id
     if (router == nullptr)
     {
         router = mRouterTable.Allocate();
-    }
-    else
-    {
-        otLogInfoMle("router id requested and provided!");
+        VerifyOrExit(router != nullptr);
     }
 
-    if (router != nullptr)
-    {
-        router->SetExtAddress(extAddress);
-    }
-    else
-    {
-        otLogInfoMle("router address unavailable!");
-    }
+    router->SetExtAddress(extAddress);
+    responseStatus = ThreadStatusTlv::kSuccess;
 
 exit:
-
     if (error == kErrorNone)
     {
-        SendAddressSolicitResponse(aMessage, router, aMessageInfo);
+        SendAddressSolicitResponse(aMessage, responseStatus, router, aMessageInfo);
     }
 }
 
 void MleRouter::SendAddressSolicitResponse(const Coap::Message &   aRequest,
+                                           ThreadStatusTlv::Status aResponseStatus,
                                            const Router *          aRouter,
                                            const Ip6::MessageInfo &aMessageInfo)
 {
-    Error               error = kErrorNone;
-    ThreadRouterMaskTlv routerMaskTlv;
-    Coap::Message *     message;
+    Coap::Message *message = Get<Tmf::Agent>().NewPriorityResponseMessage(aRequest);
 
-    VerifyOrExit((message = Get<Tmf::Agent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
+    VerifyOrExit(message != nullptr);
 
-    SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
-    SuccessOrExit(error = message->SetPayloadMarker());
-
-    SuccessOrExit(error = Tlv::Append<ThreadStatusTlv>(
-                      *message, aRouter == nullptr ? ThreadStatusTlv::kNoAddressAvailable : ThreadStatusTlv::kSuccess));
+    SuccessOrExit(Tlv::Append<ThreadStatusTlv>(*message, aResponseStatus));
 
     if (aRouter != nullptr)
     {
-        SuccessOrExit(error = Tlv::Append<ThreadRloc16Tlv>(*message, aRouter->GetRloc16()));
+        ThreadRouterMaskTlv routerMaskTlv;
+
+        SuccessOrExit(Tlv::Append<ThreadRloc16Tlv>(*message, aRouter->GetRloc16()));
 
         routerMaskTlv.Init();
         routerMaskTlv.SetIdSequence(mRouterTable.GetRouterIdSequence());
         routerMaskTlv.SetAssignedRouterIdMask(mRouterTable.GetRouterIdSet());
 
-        SuccessOrExit(error = routerMaskTlv.AppendTo(*message));
+        SuccessOrExit(routerMaskTlv.AppendTo(*message));
     }
 
-    SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, aMessageInfo));
+    SuccessOrExit(Get<Tmf::Agent>().SendMessage(*message, aMessageInfo));
+    message = nullptr;
 
     Log(kMessageSend, kTypeAddressReply, aMessageInfo.GetPeerAddr());
 
 exit:
-    FreeMessageOnError(message, error);
+    FreeMessage(message);
 }
 
 void MleRouter::HandleAddressRelease(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
@@ -3982,15 +4101,18 @@
     case kRoleChild:
         switch (mParent.GetLinkInfo().GetLinkQuality())
         {
-        case 1:
+        case kLinkQuality0:
+            break;
+
+        case kLinkQuality1:
             aTlv.SetLinkQuality1(aTlv.GetLinkQuality1() + 1);
             break;
 
-        case 2:
+        case kLinkQuality2:
             aTlv.SetLinkQuality2(aTlv.GetLinkQuality2() + 1);
             break;
 
-        case 3:
+        case kLinkQuality3:
             aTlv.SetLinkQuality3(aTlv.GetLinkQuality3() + 1);
             break;
         }
@@ -4020,7 +4142,7 @@
 
     for (Router &router : Get<RouterTable>().Iterate())
     {
-        uint8_t linkQuality;
+        LinkQuality linkQuality;
 
         if (router.GetRloc16() == GetRloc16())
         {
@@ -4043,15 +4165,18 @@
 
         switch (linkQuality)
         {
-        case 1:
+        case kLinkQuality0:
+            break;
+
+        case kLinkQuality1:
             aTlv.SetLinkQuality1(aTlv.GetLinkQuality1() + 1);
             break;
 
-        case 2:
+        case kLinkQuality2:
             aTlv.SetLinkQuality2(aTlv.GetLinkQuality2() + 1);
             break;
 
-        case 3:
+        case kLinkQuality3:
             aTlv.SetLinkQuality3(aTlv.GetLinkQuality3() + 1);
             break;
         }
@@ -4063,58 +4188,6 @@
     aTlv.SetSedDatagramCount(OPENTHREAD_CONFIG_DEFAULT_SED_DATAGRAM_COUNT);
 }
 
-Error MleRouter::AppendConnectivity(Message &aMessage)
-{
-    ConnectivityTlv tlv;
-
-    tlv.Init();
-    FillConnectivityTlv(tlv);
-
-    return tlv.AppendTo(aMessage);
-}
-
-Error MleRouter::AppendChildAddresses(Message &aMessage, Child &aChild)
-{
-    Error                    error;
-    Tlv                      tlv;
-    AddressRegistrationEntry entry;
-    Lowpan::Context          context;
-    uint8_t                  length      = 0;
-    uint16_t                 startOffset = aMessage.GetLength();
-
-    tlv.SetType(Tlv::kAddressRegistration);
-    SuccessOrExit(error = aMessage.Append(tlv));
-
-    for (const Ip6::Address &address : aChild.IterateIp6Addresses())
-    {
-        if (address.IsMulticast() || Get<NetworkData::Leader>().GetContext(address, context) != kErrorNone)
-        {
-            // uncompressed entry
-            entry.SetUncompressed();
-            entry.SetIp6Address(address);
-        }
-        else if (context.mContextId != kMeshLocalPrefixContextId)
-        {
-            // compressed entry
-            entry.SetContextId(context.mContextId);
-            entry.SetIid(address.GetIid());
-        }
-        else
-        {
-            continue;
-        }
-
-        SuccessOrExit(error = aMessage.AppendBytes(&entry, entry.GetLength()));
-        length += entry.GetLength();
-    }
-
-    tlv.SetLength(length);
-    aMessage.Write(startOffset, tlv);
-
-exit:
-    return error;
-}
-
 void MleRouter::FillRouteTlv(RouteTlv &aTlv, Neighbor *aNeighbor)
 {
     uint8_t     routerIdSequence = mRouterTable.GetRouterIdSequence();
@@ -4173,8 +4246,8 @@
 
         if (router.GetRloc16() == GetRloc16())
         {
-            aTlv.SetLinkQualityIn(routerCount, 0);
-            aTlv.SetLinkQualityOut(routerCount, 0);
+            aTlv.SetLinkQualityIn(routerCount, kLinkQuality0);
+            aTlv.SetLinkQualityOut(routerCount, kLinkQuality0);
             aTlv.SetRouteCost(routerCount, 1);
         }
         else
@@ -4216,26 +4289,6 @@
     aTlv.SetRouteDataLength(routerCount);
 }
 
-Error MleRouter::AppendRoute(Message &aMessage, Neighbor *aNeighbor)
-{
-    RouteTlv tlv;
-
-    tlv.Init();
-    FillRouteTlv(tlv, aNeighbor);
-
-    return tlv.AppendTo(aMessage);
-}
-
-Error MleRouter::AppendActiveDataset(Message &aMessage)
-{
-    return Get<MeshCoP::ActiveDataset>().AppendMleDatasetTlv(aMessage);
-}
-
-Error MleRouter::AppendPendingDataset(Message &aMessage)
-{
-    return Get<MeshCoP::PendingDataset>().AppendMleDatasetTlv(aMessage);
-}
-
 bool MleRouter::HasMinDowngradeNeighborRouters(void)
 {
     uint8_t linkQuality;
@@ -4266,66 +4319,56 @@
 
 bool MleRouter::HasOneNeighborWithComparableConnectivity(const RouteTlv &aRoute, uint8_t aRouterId)
 {
-    bool rval = true;
+    uint8_t routerCount = 0;
+    bool    rval        = true;
 
     // process local neighbor routers
     for (Router &router : Get<RouterTable>().Iterate())
     {
-        uint8_t localLinkQuality = 0;
-        uint8_t peerLinkQuality  = 0;
-        uint8_t routerCount      = 0;
+        uint8_t localLinkQuality;
+        uint8_t peerLinkQuality;
 
-        if (router.GetRouterId() == mRouterId)
+        if (!router.IsStateValid() || router.GetRouterId() == mRouterId || router.GetRouterId() == aRouterId)
         {
             routerCount++;
             continue;
         }
 
-        // check if neighbor is valid
-        if (router.IsStateValid())
+        localLinkQuality = router.GetLinkInfo().GetLinkQuality();
+
+        if (localLinkQuality > router.GetLinkQualityOut())
         {
-            // if neighbor is just peer
-            if (router.GetRouterId() == aRouterId)
-            {
-                routerCount++;
-                continue;
-            }
-
-            localLinkQuality = router.GetLinkInfo().GetLinkQuality();
-
-            if (localLinkQuality > router.GetLinkQualityOut())
-            {
-                localLinkQuality = router.GetLinkQualityOut();
-            }
-
-            if (localLinkQuality >= 2)
-            {
-                // check if this neighbor router is in peer Route64 TLV
-                if (!aRoute.IsRouterIdSet(router.GetRouterId()))
-                {
-                    ExitNow(rval = false);
-                }
-
-                // get the peer's two-way link quality to this router
-                peerLinkQuality = aRoute.GetLinkQualityIn(routerCount);
-
-                if (peerLinkQuality > aRoute.GetLinkQualityOut(routerCount))
-                {
-                    peerLinkQuality = aRoute.GetLinkQualityOut(routerCount);
-                }
-
-                // compare local link quality to this router with peer's
-                if (peerLinkQuality >= localLinkQuality)
-                {
-                    routerCount++;
-                    continue;
-                }
-
-                ExitNow(rval = false);
-            }
+            localLinkQuality = router.GetLinkQualityOut();
         }
 
-        routerCount++;
+        if (localLinkQuality < 2)
+        {
+            routerCount++;
+            continue;
+        }
+
+        // check if this neighbor router is in peer Route64 TLV
+        if (!aRoute.IsRouterIdSet(router.GetRouterId()))
+        {
+            ExitNow(rval = false);
+        }
+
+        // get the peer's two-way link quality to this router
+        peerLinkQuality = aRoute.GetLinkQualityIn(routerCount);
+
+        if (peerLinkQuality > aRoute.GetLinkQualityOut(routerCount))
+        {
+            peerLinkQuality = aRoute.GetLinkQualityOut(routerCount);
+        }
+
+        // compare local link quality to this router with peer's
+        if (peerLinkQuality >= localLinkQuality)
+        {
+            routerCount++;
+            continue;
+        }
+
+        ExitNow(rval = false);
     }
 
 exit:
@@ -4418,13 +4461,15 @@
 }
 
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-void MleRouter::HandleTimeSync(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const Neighbor *aNeighbor)
+void MleRouter::HandleTimeSync(RxInfo &aRxInfo)
 {
-    Log(kMessageReceive, kTypeTimeSync, aMessageInfo.GetPeerAddr());
+    Log(kMessageReceive, kTypeTimeSync, aRxInfo.mMessageInfo.GetPeerAddr());
 
-    VerifyOrExit(aNeighbor && aNeighbor->IsStateValid());
+    VerifyOrExit(aRxInfo.mNeighbor && aRxInfo.mNeighbor->IsStateValid());
 
-    Get<TimeSync>().HandleTimeSyncMessage(aMessage);
+    aRxInfo.mClass = RxInfo::kPeerMessage;
+
+    Get<TimeSync>().HandleTimeSyncMessage(aRxInfo.mMessage);
 
 exit:
     return;
@@ -4434,15 +4479,14 @@
 {
     Error        error = kErrorNone;
     Ip6::Address destination;
-    Message *    message = nullptr;
+    TxMessage *  message = nullptr;
 
-    VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
-    SuccessOrExit(error = AppendHeader(*message, kCommandTimeSync));
+    VerifyOrExit((message = NewMleMessage(kCommandTimeSync)) != nullptr, error = kErrorNoBufs);
 
     message->SetTimeSync(true);
 
     destination.SetToLinkLocalAllNodesMulticast();
-    SuccessOrExit(error = SendMessage(*message, destination));
+    SuccessOrExit(error = message->SendTo(destination));
 
     Log(kMessageSend, kTypeTimeSync, destination);
 
diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp
index ed8a7b7..e0c7778 100644
--- a/src/core/thread/mle_router.hpp
+++ b/src/core/thread/mle_router.hpp
@@ -303,7 +303,7 @@
     /**
      * This method sets the ROUTER_UPGRADE_THRESHOLD value.
      *
-     * @returns The ROUTER_UPGRADE_THRESHOLD value.
+     * @param[in]  aThreshold  The ROUTER_UPGRADE_THRESHOLD value.
      *
      */
     void SetRouterUpgradeThreshold(uint8_t aThreshold) { mRouterUpgradeThreshold = aThreshold; }
@@ -319,7 +319,7 @@
     /**
      * This method sets the ROUTER_DOWNGRADE_THRESHOLD value.
      *
-     * @returns The ROUTER_DOWNGRADE_THRESHOLD value.
+     * @param[in]  aThreshold  The ROUTER_DOWNGRADE_THRESHOLD value.
      *
      */
     void SetRouterDowngradeThreshold(uint8_t aThreshold) { mRouterDowngradeThreshold = aThreshold; }
@@ -388,7 +388,7 @@
      * @retval kErrorNoRoute   The destination is not reachable and the message should be dropped.
      *
      */
-    Error CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header);
+    Error CheckReachability(uint16_t aMeshDest, const Ip6::Header &aIp6Header);
 
     /**
      * This method resolves 2-hop routing loops.
@@ -560,54 +560,59 @@
      *
      */
     void SetCcmEnabled(bool aEnabled) { mCcmEnabled = aEnabled; }
+
+    /**
+     * This function sets whether the Security Policy TLV version-threshold for routing (VR field) is enabled.
+     *
+     * @param[in]  aEnabled  TRUE to enable Security Policy TLV version-threshold for routing, FALSE otherwise.
+     *
+     */
+    void SetThreadVersionCheckEnabled(bool aEnabled) { mThreadVersionCheckEnabled = aEnabled; }
 #endif
 
+    /**
+     * This function sends an Address Release.
+     *
+     * @param[in] aResponseHandler        A pointer to a function that is called upon response reception or time-out.
+     * @param[in] aResponseHandlerContext A pointer to callback application-specific context.
+     *
+     */
+    void SendAddressRelease(Coap::ResponseHandler aResponseHandler = nullptr, void *aResponseHandlerContext = nullptr);
+
 private:
     static constexpr uint16_t kDiscoveryMaxJitter            = 250;  // Max jitter delay Discovery Responses (in msec).
     static constexpr uint32_t kStateUpdatePeriod             = 1000; // State update period (in msec).
     static constexpr uint16_t kUnsolicitedDataResponseJitter = 500;  // Max delay for unsol Data Response (in msec).
 
-    Error AppendConnectivity(Message &aMessage);
-    Error AppendChildAddresses(Message &aMessage, Child &aChild);
-    Error AppendRoute(Message &aMessage, Neighbor *aNeighbor = nullptr);
-    Error AppendActiveDataset(Message &aMessage);
-    Error AppendPendingDataset(Message &aMessage);
+    // Threshold to accept a router upgrade request with reason
+    // `kBorderRouterRequest` (number of BRs acting as router in
+    // Network Data).
+    static constexpr uint8_t kRouterUpgradeBorderRouterRequestThreshold = 2;
+
     void  HandleDetachStart(void);
     void  HandleChildStart(AttachMode aMode);
-    void  HandleLinkRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor);
-    void  HandleLinkAccept(const Message &         aMessage,
-                           const Ip6::MessageInfo &aMessageInfo,
-                           uint32_t                aKeySequence,
-                           Neighbor *              aNeighbor);
-    Error HandleLinkAccept(const Message &         aMessage,
-                           const Ip6::MessageInfo &aMessageInfo,
-                           uint32_t                aKeySequence,
-                           Neighbor *              aNeighbor,
-                           bool                    aRequest);
-    void  HandleLinkAcceptAndRequest(const Message &         aMessage,
-                                     const Ip6::MessageInfo &aMessageInfo,
-                                     uint32_t                aKeySequence,
-                                     Neighbor *              aNeighbor);
-    Error HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *);
-    void  HandleParentRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
-    void  HandleChildIdRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, uint32_t aKeySequence);
-    void  HandleChildUpdateRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
-    void  HandleChildUpdateResponse(const Message &         aMessage,
-                                    const Ip6::MessageInfo &aMessageInfo,
-                                    uint32_t                aKeySequence,
-                                    Neighbor *              aNeighbor);
-    void  HandleDataRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const Neighbor *aNeighbor);
+    void  HandleLinkRequest(RxInfo &aRxInfo);
+    void  HandleLinkAccept(RxInfo &aRxInfo);
+    Error HandleLinkAccept(RxInfo &aRxInfo, bool aRequest);
+    void  HandleLinkAcceptAndRequest(RxInfo &aRxInfo);
+    Error HandleAdvertisement(RxInfo &aRxInfo);
+    void  HandleParentRequest(RxInfo &aRxInfo);
+    void  HandleChildIdRequest(RxInfo &aRxInfo);
+    void  HandleChildUpdateRequest(RxInfo &aRxInfo);
+    void  HandleChildUpdateResponse(RxInfo &aRxInfo);
+    void  HandleDataRequest(RxInfo &aRxInfo);
     void  HandleNetworkDataUpdateRouter(void);
-    void  HandleDiscoveryRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+    void  HandleDiscoveryRequest(RxInfo &aRxInfo);
 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-    void HandleTimeSync(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const Neighbor *aNeighbor);
+    void HandleTimeSync(RxInfo &aRxInfo);
 #endif
 
-    Error ProcessRouteTlv(const RouteTlv &aRoute);
+    Error ProcessRouteTlv(RxInfo &aRxInfo);
+    Error ProcessRouteTlv(RxInfo &aRxInfo, RouteTlv &aRouteTlv);
     void  StopAdvertiseTrickleTimer(void);
     Error SendAddressSolicit(ThreadStatusTlv::Status aStatus);
-    void  SendAddressRelease(void);
     void  SendAddressSolicitResponse(const Coap::Message &   aRequest,
+                                     ThreadStatusTlv::Status aResponseStatus,
                                      const Router *          aRouter,
                                      const Ip6::MessageInfo &aMessageInfo);
     void  SendAdvertisement(void);
@@ -630,12 +635,13 @@
                            const Message *     aRequestMessage = nullptr);
     Error SendDiscoveryResponse(const Ip6::Address &aDestination, const Message &aDiscoverRequestMessage);
     void  SetStateRouter(uint16_t aRloc16);
-    void  SetStateLeader(uint16_t aRloc16);
+    void  SetStateLeader(uint16_t aRloc16, LeaderStartMode aStartMode);
     void  StopLeader(void);
     void  SynchronizeChildNetworkData(void);
     Error UpdateChildAddresses(const Message &aMessage, uint16_t aOffset, Child &aChild);
     void  UpdateRoutes(const RouteTlv &aRoute, uint8_t aRouterId);
     bool  UpdateLinkQualityOut(const RouteTlv &aRoute, Router &aNeighbor, bool &aResetAdvInterval);
+    bool  HasNeighborWithGoodLinkQuality(void) const;
 
     static void HandleAddressSolicitResponse(void *               aContext,
                                              otMessage *          aMessage,
@@ -681,6 +687,7 @@
 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
     uint32_t mPreferredLeaderPartitionId; ///< only for certification testing
     bool     mCcmEnabled : 1;
+    bool     mThreadVersionCheckEnabled : 1;
 #endif
     bool mRouterEligible : 1;
     bool mAddressSolicitPending : 1;
@@ -697,6 +704,8 @@
     uint8_t mRouterSelectionJitter;        ///< The variable to save the assigned jitter value.
     uint8_t mRouterSelectionJitterTimeout; ///< The Timeout prior to request/release Router ID.
 
+    uint8_t mLinkRequestDelay;
+
     int8_t mParentPriority; ///< The assigned parent priority value, -2 means not assigned.
 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
     uint8_t mBackboneRouterRegistrationDelay; ///< Delay before registering Backbone Router service.
diff --git a/src/core/thread/mle_tlvs.hpp b/src/core/thread/mle_tlvs.hpp
index 1ca11f3..4b1dd67 100644
--- a/src/core/thread/mle_tlvs.hpp
+++ b/src/core/thread/mle_tlvs.hpp
@@ -360,9 +360,9 @@
      * @returns The Link Quality In value for a given Router index.
      *
      */
-    uint8_t GetLinkQualityIn(uint8_t aRouterIndex) const
+    LinkQuality GetLinkQualityIn(uint8_t aRouterIndex) const
     {
-        return (mRouteData[aRouterIndex] & kLinkQualityInMask) >> kLinkQualityInOffset;
+        return static_cast<LinkQuality>((mRouteData[aRouterIndex] & kLinkQualityInMask) >> kLinkQualityInOffset);
     }
 
     /**
@@ -372,7 +372,7 @@
      * @param[in]  aLinkQuality  The Link Quality In value for a given Router index.
      *
      */
-    void SetLinkQualityIn(uint8_t aRouterIndex, uint8_t aLinkQuality)
+    void SetLinkQualityIn(uint8_t aRouterIndex, LinkQuality aLinkQuality)
     {
         mRouteData[aRouterIndex] = (mRouteData[aRouterIndex] & ~kLinkQualityInMask) |
                                    ((aLinkQuality << kLinkQualityInOffset) & kLinkQualityInMask);
@@ -386,9 +386,9 @@
      * @returns The Link Quality Out value for a given Router index.
      *
      */
-    uint8_t GetLinkQualityOut(uint8_t aRouterIndex) const
+    LinkQuality GetLinkQualityOut(uint8_t aRouterIndex) const
     {
-        return (mRouteData[aRouterIndex] & kLinkQualityOutMask) >> kLinkQualityOutOffset;
+        return static_cast<LinkQuality>((mRouteData[aRouterIndex] & kLinkQualityOutMask) >> kLinkQualityOutOffset);
     }
 
     /**
@@ -398,7 +398,7 @@
      * @param[in]  aLinkQuality  The Link Quality Out value for a given Router index.
      *
      */
-    void SetLinkQualityOut(uint8_t aRouterIndex, uint8_t aLinkQuality)
+    void SetLinkQualityOut(uint8_t aRouterIndex, LinkQuality aLinkQuality)
     {
         mRouteData[aRouterIndex] = (mRouteData[aRouterIndex] & ~kLinkQualityOutMask) |
                                    ((aLinkQuality << kLinkQualityOutOffset) & kLinkQualityOutMask);
@@ -600,11 +600,12 @@
      * @returns The Link Quality Out value for a given Router index.
      *
      */
-    uint8_t GetLinkQualityOut(uint8_t aRouterIndex) const
+    LinkQuality GetLinkQualityOut(uint8_t aRouterIndex) const
     {
         int offset = ((aRouterIndex & 1) ? kOddEntryOffset : 0);
-        return (mRouteData[aRouterIndex + aRouterIndex / 2] & (kLinkQualityOutMask >> offset)) >>
-               (kLinkQualityOutOffset - offset);
+        return static_cast<LinkQuality>(
+            (mRouteData[aRouterIndex + aRouterIndex / 2] & (kLinkQualityOutMask >> offset)) >>
+            (kLinkQualityOutOffset - offset));
     }
 
     /**
@@ -614,7 +615,7 @@
      * @param[in]  aLinkQuality  The Link Quality Out value for a given Router index.
      *
      */
-    void SetLinkQualityOut(uint8_t aRouterIndex, uint8_t aLinkQuality)
+    void SetLinkQualityOut(uint8_t aRouterIndex, LinkQuality aLinkQuality)
     {
         int offset = ((aRouterIndex & 1) ? kOddEntryOffset : 0);
         mRouteData[aRouterIndex + aRouterIndex / 2] =
@@ -692,8 +693,8 @@
     {
         mPartitionId       = HostSwap32(aLeaderData.GetPartitionId());
         mWeighting         = aLeaderData.GetWeighting();
-        mDataVersion       = aLeaderData.GetDataVersion();
-        mStableDataVersion = aLeaderData.GetStableDataVersion();
+        mDataVersion       = aLeaderData.GetDataVersion(NetworkData::kFullSet);
+        mStableDataVersion = aLeaderData.GetDataVersion(NetworkData::kStableSubset);
         mLeaderRouterId    = aLeaderData.GetLeaderRouterId();
     }
 
diff --git a/src/core/thread/mle_types.cpp b/src/core/thread/mle_types.cpp
index 5a13a0d..28233ba 100644
--- a/src/core/thread/mle_types.cpp
+++ b/src/core/thread/mle_types.cpp
@@ -42,7 +42,7 @@
 {
     aModeConfig.mRxOnWhenIdle = IsRxOnWhenIdle();
     aModeConfig.mDeviceType   = IsFullThreadDevice();
-    aModeConfig.mNetworkData  = IsFullNetworkData();
+    aModeConfig.mNetworkData  = (GetNetworkDataType() == NetworkData::kFullSet);
 }
 
 void DeviceMode::Set(const ModeConfig &aModeConfig)
@@ -57,19 +57,11 @@
 {
     InfoString string;
 
-    string.Append("rx-on:%s ftd:%s full-net:%s", IsRxOnWhenIdle() ? "yes" : "no", IsFullThreadDevice() ? "yes" : "no",
-                  IsFullNetworkData() ? "yes" : "no");
+    string.Append("rx-on:%s ftd:%s full-net:%s", ToYesNo(IsRxOnWhenIdle()), ToYesNo(IsFullThreadDevice()),
+                  ToYesNo(GetNetworkDataType() == NetworkData::kFullSet));
 
     return string;
 }
 
-void MeshLocalPrefix::SetFromExtendedPanId(const Mac::ExtendedPanId &aExtendedPanId)
-{
-    m8[0] = 0xfd;
-    memcpy(&m8[1], aExtendedPanId.m8, 5);
-    m8[6] = 0x00;
-    m8[7] = 0x00;
-}
-
 } // namespace Mle
 } // namespace ot
diff --git a/src/core/thread/mle_types.hpp b/src/core/thread/mle_types.hpp
index 942c96f..fbc92a6 100644
--- a/src/core/thread/mle_types.hpp
+++ b/src/core/thread/mle_types.hpp
@@ -42,13 +42,16 @@
 
 #include <openthread/thread.h>
 
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/code_utils.hpp"
 #include "common/encoding.hpp"
 #include "common/equatable.hpp"
 #include "common/string.hpp"
 #include "mac/mac_types.hpp"
+#include "meshcop/extended_panid.hpp"
 #include "net/ip6_address.hpp"
+#include "thread/network_data_types.hpp"
 
 namespace ot {
 namespace Mle {
@@ -97,6 +100,7 @@
 constexpr uint32_t kMaxChildIdRequestTimeout       = 5000; ///< Max delay to rx a Child ID Request (in msec)
 constexpr uint32_t kMaxChildUpdateResponseTimeout  = 2000; ///< Max delay to rx a Child Update Response (in msec)
 constexpr uint32_t kMaxLinkRequestTimeout          = 2000; ///< Max delay to rx a Link Accept
+constexpr uint8_t  kMulticastLinkRequestDelay      = 5;    ///< Max delay for sending a mcast Link Request (in sec)
 
 constexpr uint32_t kMinTimeoutKeepAlive = (((kMaxChildKeepAliveAttempts + 1) * kUnicastRetransmissionDelay) / 1000);
 constexpr uint32_t kMinPollPeriod       = OPENTHREAD_CONFIG_MAC_MINIMUM_POLL_PERIOD;
@@ -158,6 +162,13 @@
 constexpr uint8_t kRouterDowngradeThreshold = 23;
 constexpr uint8_t kRouterUpgradeThreshold   = 16;
 
+/**
+ * Threshold to accept a router upgrade request with reason `kBorderRouterRequest` (number of BRs acting as router in
+ * Network Data).
+ *
+ */
+constexpr uint8_t kRouterUpgradeBorderRouterRequestThreshold = 2;
+
 constexpr uint32_t kMaxLeaderToRouterTimeout = 90;  ///< (in sec)
 constexpr uint32_t kReedAdvertiseInterval    = 570; ///< (in sec)
 constexpr uint32_t kReedAdvertiseJitter      = 60;  ///< (in sec)
@@ -192,19 +203,6 @@
     kRoleLeader   = OT_DEVICE_ROLE_LEADER,   ///< The Thread Leader role.
 };
 
-/**
- * MLE Attach modes
- *
- */
-enum AttachMode : uint8_t
-{
-    kAttachAny           = 0, ///< Attach to any Thread partition.
-    kAttachSame1         = 1, ///< Attach to the same Thread partition (attempt 1 when losing connectivity).
-    kAttachSame2         = 2, ///< Attach to the same Thread partition (attempt 2 when losing connectivity).
-    kAttachBetter        = 3, ///< Attach to a better (i.e. higher weight/partition id) Thread partition.
-    kAttachSameDowngrade = 4, ///< Attach to the same Thread partition during downgrade process.
-};
-
 constexpr uint16_t kAloc16Leader                      = 0xfc00;
 constexpr uint16_t kAloc16DhcpAgentStart              = 0xfc01;
 constexpr uint16_t kAloc16DhcpAgentEnd                = 0xfc0f;
@@ -220,6 +218,18 @@
 constexpr uint8_t kServiceMinId = 0x00; ///< Minimal Service ID.
 constexpr uint8_t kServiceMaxId = 0x0f; ///< Maximal Service ID.
 
+/**
+ * This enumeration specifies the leader role start mode.
+ *
+ * The start mode indicates whether device is starting normally as leader or restoring its role after reset.
+ *
+ */
+enum LeaderStartMode : uint8_t
+{
+    kStartingAsLeader,              ///< Starting as leader normally.
+    kRestoringLeaderRoleAfterReset, ///< Restoring leader role after reset.
+};
+
 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
 
 /*
@@ -379,13 +389,15 @@
     bool IsFullThreadDevice(void) const { return (mMode & kModeFullThreadDevice) != 0; }
 
     /**
-     * This method indicates whether or not the device requests Full Network Data.
+     * This method gets the Network Data type (full set or stable subset) that the device requests.
      *
-     * @retval TRUE   If the device requests Full Network Data.
-     * @retval FALSE  If the device does not request Full Network Data (only stable Network Data).
+     * @returns The Network Data type requested by this device.
      *
      */
-    bool IsFullNetworkData(void) const { return (mMode & kModeFullNetworkData) != 0; }
+    NetworkData::Type GetNetworkDataType(void) const
+    {
+        return (mMode & kModeFullNetworkData) ? NetworkData::kFullSet : NetworkData::kStableSubset;
+    }
 
     /**
      * This method indicates whether or not the device is a Minimal End Device.
@@ -424,24 +436,6 @@
 };
 
 /**
- * This class represents a Mesh Local Prefix.
- *
- */
-OT_TOOL_PACKED_BEGIN
-class MeshLocalPrefix : public Ip6::NetworkPrefix
-{
-public:
-    /**
-     * This method derives and sets the Mesh Local Prefix from an Extended PAN ID.
-     *
-     * @param[in] aExtendedPanId   An Extended PAN ID.
-     *
-     */
-    void SetFromExtendedPanId(const Mac::ExtendedPanId &aExtendedPanId);
-
-} OT_TOOL_PACKED_END;
-
-/**
  * This class represents the Thread Leader Data.
  *
  */
@@ -481,12 +475,17 @@
     void SetWeighting(uint8_t aWeighting) { mWeighting = aWeighting; }
 
     /**
-     * This method returns the Data Version value.
+     * This method returns the Data Version value for a type (full set or stable subset).
      *
-     * @returns The Data Version value.
+     * @param[in] aType   The Network Data type (full set or stable subset).
+     *
+     * @returns The Data Version value for @p aType.
      *
      */
-    uint8_t GetDataVersion(void) const { return mDataVersion; }
+    uint8_t GetDataVersion(NetworkData::Type aType) const
+    {
+        return (aType == NetworkData::kFullSet) ? mDataVersion : mStableDataVersion;
+    }
 
     /**
      * This method sets the Data Version value.
@@ -497,14 +496,6 @@
     void SetDataVersion(uint8_t aVersion) { mDataVersion = aVersion; }
 
     /**
-     * This method returns the Stable Data Version value.
-     *
-     * @returns The Stable Data Version value.
-     *
-     */
-    uint8_t GetStableDataVersion(void) const { return mStableDataVersion; }
-
-    /**
      * This method sets the Stable Data Version value.
      *
      * @param[in]  aVersion  The Stable Data Version value.
@@ -588,6 +579,10 @@
  */
 
 } // namespace Mle
+
+DefineCoreType(otLeaderData, Mle::LeaderData);
+DefineMapEnum(otDeviceRole, Mle::DeviceRole);
+
 } // namespace ot
 
 #endif // MLE_TYPES_HPP_
diff --git a/src/core/thread/mlr_manager.cpp b/src/core/thread/mlr_manager.cpp
index 3623089..98272fe 100644
--- a/src/core/thread/mlr_manager.cpp
+++ b/src/core/thread/mlr_manager.cpp
@@ -39,7 +39,7 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "net/ip6_address.hpp"
 #include "thread/thread_netif.hpp"
 #include "thread/uri_paths.hpp"
@@ -47,6 +47,8 @@
 
 namespace ot {
 
+RegisterLogModule("MlrManager");
+
 MlrManager::MlrManager(Instance &aInstance)
     : InstanceLocator(aInstance)
 #if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
@@ -228,7 +230,7 @@
 {
     Error           error;
     Mle::MleRouter &mle = Get<Mle::MleRouter>();
-    Ip6::Address    addresses[kIp6AddressesNumMax];
+    Ip6::Address    addresses[Ip6AddressesTlv::kMaxAddresses];
     uint8_t         addressesNum = 0;
 
     VerifyOrExit(!mMlrPending, error = kErrorBusy);
@@ -241,7 +243,7 @@
     for (Ip6::Netif::ExternalMulticastAddress &addr :
          Get<ThreadNetif>().IterateExternalMulticastAddresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
     {
-        if (addressesNum >= kIp6AddressesNumMax)
+        if (addressesNum >= Ip6AddressesTlv::kMaxAddresses)
         {
             break;
         }
@@ -258,7 +260,7 @@
     // Append Child multicast addresses
     for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
     {
-        if (addressesNum >= kIp6AddressesNumMax)
+        if (addressesNum >= Ip6AddressesTlv::kMaxAddresses)
         {
             break;
         }
@@ -270,7 +272,7 @@
 
         for (const Ip6::Address &address : child.IterateIp6Addresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
         {
-            if (addressesNum >= kIp6AddressesNumMax)
+            if (addressesNum >= Ip6AddressesTlv::kMaxAddresses)
             {
                 break;
             }
@@ -324,14 +326,14 @@
     Error error;
 
     VerifyOrExit(aAddresses != nullptr, error = kErrorInvalidArgs);
-    VerifyOrExit(aAddressNum > 0 && aAddressNum <= kIp6AddressesNumMax, error = kErrorInvalidArgs);
+    VerifyOrExit(aAddressNum > 0 && aAddressNum <= Ip6AddressesTlv::kMaxAddresses, error = kErrorInvalidArgs);
     VerifyOrExit(aContext == nullptr || aCallback != nullptr, error = kErrorInvalidArgs);
 #if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
     VerifyOrExit(Get<MeshCoP::Commissioner>().IsActive(), error = kErrorInvalidState);
 #else
     if (!Get<MeshCoP::Commissioner>().IsActive())
     {
-        otLogWarnMlr("MLR.req without active commissioner session for test.");
+        LogWarn("MLR.req without active commissioner session for test.");
     }
 #endif
 
@@ -366,7 +368,7 @@
 
     uint8_t                                 status;
     Error                                   error;
-    Ip6::Address                            failedAddresses[kIp6AddressesNumMax];
+    Ip6::Address                            failedAddresses[Ip6AddressesTlv::kMaxAddresses];
     uint8_t                                 failedAddressNum = 0;
     otIp6RegisterMulticastListenersCallback callback         = mRegisterMulticastListenersCallback;
     void *                                  context          = mRegisterMulticastListenersContext;
@@ -397,17 +399,13 @@
     Error            error   = kErrorNone;
     Mle::MleRouter & mle     = Get<Mle::MleRouter>();
     Coap::Message *  message = nullptr;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
     Ip6AddressesTlv  addressesTlv;
 
     VerifyOrExit(Get<BackboneRouter::Leader>().HasPrimary(), error = kErrorInvalidState);
 
-    VerifyOrExit((message = Get<Tmf::Agent>().NewMessage()) != nullptr, error = kErrorNoBufs);
-
-    message->InitAsConfirmablePost();
-    SuccessOrExit(message->GenerateRandomToken(Coap::Message::kDefaultTokenLength));
-    SuccessOrExit(message->AppendUriPathOptions(UriPath::kMlr));
-    SuccessOrExit(message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewConfirmablePostMessage(UriPath::kMlr);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     addressesTlv.Init();
     addressesTlv.SetLength(sizeof(Ip6::Address) * aAddressNum);
@@ -442,15 +440,14 @@
                                                       Get<BackboneRouter::Leader>().GetServer16());
     }
 
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
-    messageInfo.SetSockAddr(mle.GetMeshLocal16());
+    messageInfo.SetSockAddrToRloc();
 
     error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, aResponseHandler, aResponseContext);
 
-    otLogInfoMlr("Sent MLR.req: addressNum=%d", aAddressNum);
+    LogInfo("Sent MLR.req: addressNum=%d", aAddressNum);
 
 exit:
-    otLogInfoMlr("SendMulticastListenerRegistrationMessage(): %s", ErrorToString(error));
+    LogInfo("SendMulticastListenerRegistrationMessage(): %s", ErrorToString(error));
     FreeMessageOnError(message, error);
     return error;
 }
@@ -472,7 +469,7 @@
 
     uint8_t      status;
     Error        error;
-    Ip6::Address failedAddresses[kIp6AddressesNumMax];
+    Ip6::Address failedAddresses[Ip6AddressesTlv::kMaxAddresses];
     uint8_t      failedAddressNum = 0;
 
     error = ParseMulticastListenerRegistrationResponse(aResult, aMessage, status, failedAddresses, failedAddressNum);
@@ -523,7 +520,7 @@
         kErrorNone)
     {
         VerifyOrExit(addressesLength % sizeof(Ip6::Address) == 0, error = kErrorParse);
-        VerifyOrExit(addressesLength / sizeof(Ip6::Address) <= kIp6AddressesNumMax, error = kErrorParse);
+        VerifyOrExit(addressesLength / sizeof(Ip6::Address) <= Ip6AddressesTlv::kMaxAddresses, error = kErrorParse);
 
         for (uint16_t offset = 0; offset < addressesLength; offset += sizeof(Ip6::Address))
         {
@@ -621,7 +618,7 @@
 
 void MlrManager::Reregister(void)
 {
-    otLogInfoMlr("MLR Reregister!");
+    LogInfo("MLR Reregister!");
 
     SetMulticastAddressMlrState(kMlrStateRegistered, kMlrStateToRegister);
     CheckInvariants();
@@ -674,19 +671,19 @@
 
     UpdateTimeTickerRegistration();
 
-    otLogDebgMlr("MlrManager::UpdateReregistrationDelay: rereg=%d, needSendMlr=%d, ReregDelay=%lu", aRereg, needSendMlr,
-                 mReregistrationDelay);
+    LogDebg("MlrManager::UpdateReregistrationDelay: rereg=%d, needSendMlr=%d, ReregDelay=%lu", aRereg, needSendMlr,
+            mReregistrationDelay);
 }
 
 void MlrManager::LogMulticastAddresses(void)
 {
-#if OPENTHREAD_CONFIG_LOG_MLR && OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_DEBG
-    otLogDebgMlr("-------- Multicast Addresses --------");
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_DEBG)
+    LogDebg("-------- Multicast Addresses --------");
 
 #if OPENTHREAD_CONFIG_MLR_ENABLE
     for (const Ip6::Netif::ExternalMulticastAddress &addr : Get<ThreadNetif>().IterateExternalMulticastAddresses())
     {
-        otLogDebgMlr("%-32s%c", addr.GetAddress().ToString().AsCString(), "-rR"[addr.GetMlrState()]);
+        LogDebg("%-32s%c", addr.GetAddress().ToString().AsCString(), "-rR"[addr.GetMlrState()]);
     }
 #endif
 
@@ -695,16 +692,16 @@
     {
         for (const Ip6::Address &address : child.IterateIp6Addresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
         {
-            otLogDebgMlr("%-32s%c %04x", address.ToString().AsCString(), "-rR"[child.GetAddressMlrState(address)],
-                         child.GetRloc16());
+            LogDebg("%-32s%c %04x", address.ToString().AsCString(), "-rR"[child.GetAddressMlrState(address)],
+                    child.GetRloc16());
         }
     }
 #endif
 
-#endif // OPENTHREAD_CONFIG_LOG_MLR && OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_DEBG
+#endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_DEBG)
 }
 
-void MlrManager::AppendToUniqueAddressList(Ip6::Address (&aAddresses)[kIp6AddressesNumMax],
+void MlrManager::AppendToUniqueAddressList(Ip6::Address (&aAddresses)[Ip6AddressesTlv::kMaxAddresses],
                                            uint8_t &           aAddressNum,
                                            const Ip6::Address &aAddress)
 {
@@ -759,19 +756,19 @@
     OT_UNUSED_VARIABLE(aFailedAddresses);
     OT_UNUSED_VARIABLE(aFailedAddressNum);
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN) && (OPENTHREAD_CONFIG_LOG_MLR == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
     if (aResult == kErrorNone && aError == kErrorNone && aStatus == ThreadStatusTlv::MlrStatus::kMlrSuccess)
     {
-        otLogInfoMlr("Receive MLR.rsp OK");
+        LogInfo("Receive MLR.rsp OK");
     }
     else
     {
-        otLogWarnMlr("Receive MLR.rsp: result=%s, error=%s, status=%d, failedAddressNum=%d", ErrorToString(aResult),
-                     ErrorToString(aError), aStatus, aFailedAddressNum);
+        LogWarn("Receive MLR.rsp: result=%s, error=%s, status=%d, failedAddressNum=%d", ErrorToString(aResult),
+                ErrorToString(aError), aStatus, aFailedAddressNum);
 
         for (uint8_t i = 0; i < aFailedAddressNum; i++)
         {
-            otLogWarnMlr("MA failed: %s", aFailedAddresses[i].ToString().AsCString());
+            LogWarn("MA failed: %s", aFailedAddresses[i].ToString().AsCString());
         }
     }
 #endif
@@ -779,7 +776,7 @@
 
 void MlrManager::CheckInvariants(void) const
 {
-#if OPENTHREAD_EXAMPLES_SIMULATION
+#if OPENTHREAD_EXAMPLES_SIMULATION && OPENTHREAD_CONFIG_ASSERT_ENABLE
     uint16_t registeringNum = 0;
 
     OT_ASSERT(!mMlrPending || mSendDelay == 0);
diff --git a/src/core/thread/mlr_manager.hpp b/src/core/thread/mlr_manager.hpp
index 4bd77a8..6eda998 100644
--- a/src/core/thread/mlr_manager.hpp
+++ b/src/core/thread/mlr_manager.hpp
@@ -120,7 +120,7 @@
      *
      * @param aAddresses   A pointer to IPv6 multicast addresses to register.
      * @param aAddressNum  The number of IPv6 multicast addresses.
-     * @param aTimeout     A pointer to the timeout (in seconds), or nullptr to use the default MLR timeout.
+     * @param aTimeout     A pointer to the timeout (in seconds), or `nullptr` to use the default MLR timeout.
      *                     A timeout of 0 seconds removes the Multicast Listener addresses.
      * @param aCallback    A callback function.
      * @param aContext     A user context pointer.
@@ -192,7 +192,7 @@
                                              const Ip6::Address *aFailedAddresses,
                                              uint8_t             aFailedAddressNum);
 
-    void        AppendToUniqueAddressList(Ip6::Address (&aAddresses)[kIp6AddressesNumMax],
+    void        AppendToUniqueAddressList(Ip6::Address (&aAddresses)[Ip6AddressesTlv::kMaxAddresses],
                                           uint8_t &           aAddressNum,
                                           const Ip6::Address &aAddress);
     static bool AddressListContains(const Ip6::Address *aAddressList,
diff --git a/src/core/thread/neighbor_table.hpp b/src/core/thread/neighbor_table.hpp
index ec7b18a..abe2df6 100644
--- a/src/core/thread/neighbor_table.hpp
+++ b/src/core/thread/neighbor_table.hpp
@@ -95,7 +95,7 @@
      * @param[in]  aShortAddress  A short address.
      * @param[in]  aFilter        A neighbor state filter
      *
-     * @returns A pointer to the `Neighbor` corresponding to @p aShortAddress, nullptr otherwise.
+     * @returns A pointer to the `Neighbor` corresponding to @p aShortAddress, `nullptr` otherwise.
      *
      */
     Neighbor *FindParent(Mac::ShortAddress     aShortAddress,
@@ -108,7 +108,7 @@
      * @param[in]  aExtAddress   A MAC Extended Address.
      * @param[in]  aFilter       A neighbor state filter
      *
-     * @returns A pointer to the `Neighbor` corresponding to @p aExtAddress, nullptr otherwise.
+     * @returns A pointer to the `Neighbor` corresponding to @p aExtAddress, `nullptr` otherwise.
      *
      */
     Neighbor *FindParent(const Mac::ExtAddress &aExtAddress,
@@ -121,7 +121,7 @@
      * @param[in]  aMacAddress  A MAC address.
      * @param[in]  aFilter      A neighbor state filter
      *
-     * @returns A pointer to the `Neighbor` corresponding to @p aMacAddress, nullptr otherwise.
+     * @returns A pointer to the `Neighbor` corresponding to @p aMacAddress, `nullptr` otherwise.
      *
      */
     Neighbor *FindParent(const Mac::Address &  aMacAddress,
@@ -133,7 +133,7 @@
      * @param[in]  aShortAddress  A short address.
      * @param[in]  aFilter        A neighbor state filter.
      *
-     * @returns A pointer to the `Neighbor` corresponding to @p aShortAddress, nullptr otherwise.
+     * @returns A pointer to the `Neighbor` corresponding to @p aShortAddress, `nullptr` otherwise.
      *
      */
     Neighbor *FindNeighbor(Mac::ShortAddress     aShortAddress,
@@ -145,7 +145,7 @@
      * @param[in]  aExtAddress   A MAC Extended Address.
      * @param[in]  aFilter       A neighbor state filter.
      *
-     * @returns A pointer to the `Neighbor` corresponding to @p aExtAddress, nullptr otherwise.
+     * @returns A pointer to the `Neighbor` corresponding to @p aExtAddress, `nullptr` otherwise.
      *
      */
     Neighbor *FindNeighbor(const Mac::ExtAddress &aExtAddress,
@@ -157,7 +157,7 @@
      * @param[in]  aMacAddress  A MAC address.
      * @param[in]  aFilter      A neighbor state filter.
      *
-     * @returns A pointer to the `Neighbor` corresponding to @p aMacAddress, nullptr otherwise.
+     * @returns A pointer to the `Neighbor` corresponding to @p aMacAddress, `nullptr` otherwise.
      *
      */
     Neighbor *FindNeighbor(const Mac::Address &  aMacAddress,
@@ -171,7 +171,7 @@
      * @param[in]  aIp6Address  An IPv6 address.
      * @pram[in]   aFilter      A neighbor state filter.
      *
-     * @returns A pointer to the `Neighbor` corresponding to @p aIp6Address, nullptr otherwise.
+     * @returns A pointer to the `Neighbor` corresponding to @p aIp6Address, `nullptr` otherwise.
      *
      */
     Neighbor *FindNeighbor(const Ip6::Address &  aIp6Address,
@@ -183,7 +183,7 @@
      *
      * @param[in]  aMacAddress  A MAC address.
      *
-     * @returns A pointer to the Neighbor corresponding to @p aMacAddress, nullptr otherwise.
+     * @returns A pointer to the Neighbor corresponding to @p aMacAddress, `nullptr` otherwise.
      *
      */
     Neighbor *FindRxOnlyNeighborRouter(const Mac::Address &aMacAddress);
@@ -194,9 +194,9 @@
      * This method gets the next neighbor information. It is used to iterate through the entries of
      * the neighbor table.
      *
-     * @param[inout]  aIterator  A reference to the iterator context. To get the first neighbor entry
-                                 it should be set to OT_NEIGHBOR_INFO_ITERATOR_INIT.
-     * @param[out]    aNeighInfo The neighbor information.
+     * @param[in,out]  aIterator  A reference to the iterator context. To get the first neighbor entry
+                                  it should be set to OT_NEIGHBOR_INFO_ITERATOR_INIT.
+     * @param[out]     aNeighInfo The neighbor information.
      *
      * @retval kErrorNone         Successfully found the next neighbor entry in table.
      * @retval kErrorNotFound     No subsequent neighbor entry exists in the table.
@@ -207,7 +207,7 @@
     /**
      * This method registers the "neighbor table changed" callback function.
      *
-     * The provided callback (if non-nullptr) will be invoked when a child/router entry is being added/remove to/from
+     * The provided callback (if non-`nullptr`) will be invoked when a child/router entry is being added/remove to/from
      * the neighbor table. Subsequent calls to this method will overwrite the previous callback.
      *
      * @param[in] aCallback    A pointer to callback handler function.
diff --git a/src/core/thread/network_data.cpp b/src/core/thread/network_data.cpp
index e950357..3c96a92 100644
--- a/src/core/thread/network_data.cpp
+++ b/src/core/thread/network_data.cpp
@@ -34,11 +34,12 @@
 #include "network_data.hpp"
 
 #include "coap/coap_message.hpp"
+#include "common/array.hpp"
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "mac/mac_types.hpp"
 #include "thread/thread_netif.hpp"
 #include "thread/thread_tlvs.hpp"
@@ -47,19 +48,21 @@
 namespace ot {
 namespace NetworkData {
 
-Error NetworkData::CopyNetworkData(bool aStable, uint8_t *aData, uint8_t &aDataLength) const
+RegisterLogModule("NetworkData");
+
+Error NetworkData::CopyNetworkData(Type aType, uint8_t *aData, uint8_t &aDataLength) const
 {
     Error              error;
     MutableNetworkData netDataCopy(GetInstance(), aData, 0, aDataLength);
 
-    SuccessOrExit(error = CopyNetworkData(aStable, netDataCopy));
+    SuccessOrExit(error = CopyNetworkData(aType, netDataCopy));
     aDataLength = netDataCopy.GetLength();
 
 exit:
     return error;
 }
 
-Error NetworkData::CopyNetworkData(bool aStable, MutableNetworkData &aNetworkData) const
+Error NetworkData::CopyNetworkData(Type aType, MutableNetworkData &aNetworkData) const
 {
     Error error = kErrorNone;
 
@@ -68,7 +71,7 @@
     memcpy(aNetworkData.GetBytes(), mTlvs, mLength);
     aNetworkData.SetLength(mLength);
 
-    if (aStable)
+    if (aType == kStableSubset)
     {
         aNetworkData.RemoveTemporaryData();
     }
@@ -130,12 +133,12 @@
     // Iterate to the next entry in Network Data matching `aRloc16`
     // (can be set to `Mac::kShortAddrBroadcast` to allow any RLOC).
     // The `aIterator` is used to track and save the current position.
-    // On input, the non-nullptr pointer members in `aConfig` specify the
-    // Network Data entry types (`mOnMeshPrefix`, `mExternalRoute`,
+    // On input, the non-`nullptr` pointer members in `aConfig` specify
+    // the Network Data entry types (`mOnMeshPrefix`, `mExternalRoute`,
     // `mService`) to iterate over. On successful exit, the `aConfig`
-    // is updated such that only one member pointer is not nullptr
-    // indicating the type of entry and the non-nullptr config is updated
-    // with the entry info.
+    // is updated such that only one member pointer is not `nullptr`
+    // indicating the type of entry and the non-`nullptr` config is
+    // updated with the entry info.
 
     Error               error = kErrorNotFound;
     NetworkDataIterator iterator(aIterator);
@@ -151,13 +154,13 @@
         case NetworkDataTlv::kTypePrefix:
             if ((aConfig.mOnMeshPrefix != nullptr) || (aConfig.mExternalRoute != nullptr))
             {
-                subTlvs = static_cast<const PrefixTlv *>(cur)->GetSubTlvs();
+                subTlvs = As<PrefixTlv>(cur)->GetSubTlvs();
             }
             break;
         case NetworkDataTlv::kTypeService:
             if (aConfig.mService != nullptr)
             {
-                subTlvs = static_cast<const ServiceTlv *>(cur)->GetSubTlvs();
+                subTlvs = As<ServiceTlv>(cur)->GetSubTlvs();
             }
             break;
         default:
@@ -175,13 +178,13 @@
         {
             if (cur->GetType() == NetworkDataTlv::kTypePrefix)
             {
-                const PrefixTlv *prefixTlv = static_cast<const PrefixTlv *>(cur);
+                const PrefixTlv *prefixTlv = As<PrefixTlv>(cur);
 
                 switch (subCur->GetType())
                 {
                 case NetworkDataTlv::kTypeBorderRouter:
                 {
-                    const BorderRouterTlv *borderRouter = static_cast<const BorderRouterTlv *>(subCur);
+                    const BorderRouterTlv *borderRouter = As<BorderRouterTlv>(subCur);
 
                     if (aConfig.mOnMeshPrefix == nullptr)
                     {
@@ -207,7 +210,7 @@
 
                 case NetworkDataTlv::kTypeHasRoute:
                 {
-                    const HasRouteTlv *hasRoute = static_cast<const HasRouteTlv *>(subCur);
+                    const HasRouteTlv *hasRoute = As<HasRouteTlv>(subCur);
 
                     if (aConfig.mExternalRoute == nullptr)
                     {
@@ -237,7 +240,7 @@
             }
             else // cur is `ServiceTLv`
             {
-                const ServiceTlv *service = static_cast<const ServiceTlv *>(cur);
+                const ServiceTlv *service = As<ServiceTlv>(cur);
 
                 if (aConfig.mService == nullptr)
                 {
@@ -246,7 +249,7 @@
 
                 if (subCur->GetType() == NetworkDataTlv::kTypeServer)
                 {
-                    const ServerTlv *server = static_cast<const ServerTlv *>(subCur);
+                    const ServerTlv *server = As<ServerTlv>(subCur);
 
                     if (!iterator.IsNewEntry())
                     {
@@ -272,124 +275,88 @@
     return error;
 }
 
-Error NetworkData::GetNextServiceId(Iterator &aIterator, uint16_t aRloc16, uint8_t &aServiceId) const
+bool NetworkData::ContainsOnMeshPrefix(const OnMeshPrefixConfig &aPrefix) const
 {
-    Error         error;
-    ServiceConfig config;
+    bool               contains = false;
+    Iterator           iterator = kIteratorInit;
+    OnMeshPrefixConfig prefix;
 
-    SuccessOrExit(error = GetNextService(aIterator, aRloc16, config));
-    aServiceId = config.mServiceId;
-
-exit:
-    return error;
-}
-
-bool NetworkData::ContainsOnMeshPrefixes(const NetworkData &aCompare, uint16_t aRloc16) const
-{
-    Iterator           outerIterator = kIteratorInit;
-    OnMeshPrefixConfig outerConfig;
-    bool               rval = true;
-
-    while (aCompare.GetNextOnMeshPrefix(outerIterator, aRloc16, outerConfig) == kErrorNone)
+    while (GetNextOnMeshPrefix(iterator, aPrefix.mRloc16, prefix) == kErrorNone)
     {
-        Iterator           innerIterator = kIteratorInit;
-        OnMeshPrefixConfig innerConfig;
-        Error              error;
-
-        while ((error = GetNextOnMeshPrefix(innerIterator, aRloc16, innerConfig)) == kErrorNone)
+        if (prefix == aPrefix)
         {
-            if (outerConfig == innerConfig)
-            {
-                break;
-            }
-        }
-
-        if (error != kErrorNone)
-        {
-            ExitNow(rval = false);
+            contains = true;
+            break;
         }
     }
 
-exit:
-    return rval;
+    return contains;
 }
 
-bool NetworkData::ContainsExternalRoutes(const NetworkData &aCompare, uint16_t aRloc16) const
+bool NetworkData::ContainsExternalRoute(const ExternalRouteConfig &aRoute) const
 {
-    Iterator            outerIterator = kIteratorInit;
-    ExternalRouteConfig outerConfig;
-    bool                rval = true;
+    bool                contains = false;
+    Iterator            iterator = kIteratorInit;
+    ExternalRouteConfig route;
 
-    while (aCompare.GetNextExternalRoute(outerIterator, aRloc16, outerConfig) == kErrorNone)
+    while (GetNextExternalRoute(iterator, aRoute.mRloc16, route) == kErrorNone)
     {
-        Iterator            innerIterator = kIteratorInit;
-        ExternalRouteConfig innerConfig;
-        Error               error;
-
-        while ((error = GetNextExternalRoute(innerIterator, aRloc16, innerConfig)) == kErrorNone)
+        if (route == aRoute)
         {
-            if (outerConfig == innerConfig)
-            {
-                break;
-            }
-        }
-
-        if (error != kErrorNone)
-        {
-            ExitNow(rval = false);
+            contains = true;
+            break;
         }
     }
 
-exit:
-    return rval;
+    return contains;
 }
 
-bool NetworkData::ContainsServices(const NetworkData &aCompare, uint16_t aRloc16) const
+bool NetworkData::ContainsService(const ServiceConfig &aService) const
 {
-    Iterator      outerIterator = kIteratorInit;
-    ServiceConfig outerConfig;
-    bool          rval = true;
+    bool          contains = false;
+    Iterator      iterator = kIteratorInit;
+    ServiceConfig service;
 
-    while (aCompare.GetNextService(outerIterator, aRloc16, outerConfig) == kErrorNone)
+    while (GetNextService(iterator, aService.GetServerConfig().mRloc16, service) == kErrorNone)
     {
-        Iterator      innerIterator = kIteratorInit;
-        ServiceConfig innerConfig;
-        Error         error;
-
-        while ((error = GetNextService(innerIterator, aRloc16, innerConfig)) == kErrorNone)
+        if (service == aService)
         {
-            if (outerConfig == innerConfig)
-            {
-                break;
-            }
-        }
-
-        if (error != kErrorNone)
-        {
-            ExitNow(rval = false);
+            contains = true;
+            break;
         }
     }
 
-exit:
-    return rval;
+    return contains;
 }
 
-bool NetworkData::ContainsService(uint8_t aServiceId, uint16_t aRloc16) const
+bool NetworkData::ContainsEntriesFrom(const NetworkData &aCompare, uint16_t aRloc16) const
 {
+    bool     contains = true;
     Iterator iterator = kIteratorInit;
-    uint8_t  serviceId;
-    bool     rval = false;
 
-    while (GetNextServiceId(iterator, aRloc16, serviceId) == kErrorNone)
+    while (true)
     {
-        if (serviceId == aServiceId)
+        Config              config;
+        OnMeshPrefixConfig  prefix;
+        ExternalRouteConfig route;
+        ServiceConfig       service;
+
+        config.mOnMeshPrefix  = &prefix;
+        config.mExternalRoute = &route;
+        config.mService       = &service;
+
+        SuccessOrExit(aCompare.Iterate(iterator, aRloc16, config));
+
+        if (((config.mOnMeshPrefix != nullptr) && !ContainsOnMeshPrefix(*config.mOnMeshPrefix)) ||
+            ((config.mExternalRoute != nullptr) && !ContainsExternalRoute(*config.mExternalRoute)) ||
+            ((config.mService != nullptr) && !ContainsService(*config.mService)))
         {
-            ExitNow(rval = true);
+            ExitNow(contains = false);
         }
     }
 
 exit:
-    return rval;
+    return contains;
 }
 
 void MutableNetworkData::RemoveTemporaryData(void)
@@ -402,7 +369,7 @@
         {
         case NetworkDataTlv::kTypePrefix:
         {
-            PrefixTlv *prefix = static_cast<PrefixTlv *>(cur);
+            PrefixTlv *prefix = As<PrefixTlv>(cur);
 
             RemoveTemporaryDataIn(*prefix);
 
@@ -417,7 +384,8 @@
 
         case NetworkDataTlv::kTypeService:
         {
-            ServiceTlv *service = static_cast<ServiceTlv *>(cur);
+            ServiceTlv *service = As<ServiceTlv>(cur);
+
             RemoveTemporaryDataIn(*service);
 
             if (service->GetSubTlvsLength() == 0)
@@ -456,7 +424,7 @@
             {
             case NetworkDataTlv::kTypeBorderRouter:
             {
-                BorderRouterTlv *borderRouter = static_cast<BorderRouterTlv *>(cur);
+                BorderRouterTlv *borderRouter = As<BorderRouterTlv>(cur);
                 ContextTlv *     context      = aPrefix.FindSubTlv<ContextTlv>();
 
                 // Replace p_border_router_16
@@ -478,7 +446,7 @@
 
             case NetworkDataTlv::kTypeHasRoute:
             {
-                HasRouteTlv *hasRoute = static_cast<HasRouteTlv *>(cur);
+                HasRouteTlv *hasRoute = As<HasRouteTlv>(cur);
 
                 // Replace r_border_router_16
                 for (HasRouteEntry *entry = hasRoute->GetFirstEntry(); entry <= hasRoute->GetLastEntry();
@@ -518,11 +486,8 @@
             switch (cur->GetType())
             {
             case NetworkDataTlv::kTypeServer:
-            {
-                ServerTlv *server = static_cast<ServerTlv *>(cur);
-                server->SetServer16(Mle::Mle::ServiceAlocFromId(aService.GetServiceId()));
+                As<ServerTlv>(cur)->SetServer16(Mle::Mle::ServiceAlocFromId(aService.GetServiceId()));
                 break;
-            }
 
             default:
                 break;
@@ -675,14 +640,12 @@
                                               Coap::ResponseHandler aHandler,
                                               void *                aContext) const
 {
-    Error            error   = kErrorNone;
-    Coap::Message *  message = nullptr;
-    Ip6::MessageInfo messageInfo;
+    Error            error = kErrorNone;
+    Coap::Message *  message;
+    Tmf::MessageInfo messageInfo(GetInstance());
 
-    VerifyOrExit((message = Get<Tmf::Agent>().NewMessage()) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kServerData));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(UriPath::kServerData);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     if (aAppendNetDataTlv)
     {
@@ -698,12 +661,10 @@
         SuccessOrExit(error = Tlv::Append<ThreadRloc16Tlv>(*message, aRloc16));
     }
 
-    IgnoreError(Get<Mle::MleRouter>().GetLeaderAloc(messageInfo.GetPeerAddr()));
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
+    IgnoreError(messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc());
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, aHandler, aContext));
 
-    otLogInfoNetData("Sent server data notification");
+    LogInfo("Sent server data notification");
 
 exit:
     FreeMessageOnError(message, error);
@@ -745,5 +706,142 @@
     return error;
 }
 
+Error NetworkData::FindBorderRouters(RoleFilter aRoleFilter, uint16_t aRlocs[], uint8_t &aRlocsLength) const
+{
+    class Rlocs // Wrapper over an array of RLOC16s.
+    {
+    public:
+        Rlocs(RoleFilter aRoleFilter, uint16_t *aRlocs, uint8_t aRlocsMaxLength)
+            : mRoleFilter(aRoleFilter)
+            , mRlocs(aRlocs)
+            , mLength(0)
+            , mMaxLength(aRlocsMaxLength)
+        {
+        }
+
+        uint8_t GetLength(void) const { return mLength; }
+
+        Error AddRloc16(uint16_t aRloc16)
+        {
+            // Add `aRloc16` into the array if it matches `RoleFilter` and
+            // it is not in the array already. If we need to add the `aRloc16`
+            // but there is no more room in the array, return `kErrorNoBufs`.
+
+            Error   error = kErrorNone;
+            uint8_t index;
+
+            switch (mRoleFilter)
+            {
+            case kAnyRole:
+                break;
+
+            case kRouterRoleOnly:
+                VerifyOrExit(Mle::Mle::IsActiveRouter(aRloc16));
+                break;
+
+            case kChildRoleOnly:
+                VerifyOrExit(!Mle::Mle::IsActiveRouter(aRloc16));
+                break;
+            }
+
+            for (index = 0; index < mLength; index++)
+            {
+                if (mRlocs[index] == aRloc16)
+                {
+                    break;
+                }
+            }
+
+            if (index == mLength)
+            {
+                VerifyOrExit(mLength < mMaxLength, error = kErrorNoBufs);
+                mRlocs[mLength++] = aRloc16;
+            }
+
+        exit:
+            return error;
+        }
+
+    private:
+        RoleFilter mRoleFilter;
+        uint16_t * mRlocs;
+        uint8_t    mLength;
+        uint8_t    mMaxLength;
+    };
+
+    Error               error = kErrorNone;
+    Rlocs               rlocs(aRoleFilter, aRlocs, aRlocsLength);
+    Iterator            iterator = kIteratorInit;
+    ExternalRouteConfig route;
+    OnMeshPrefixConfig  prefix;
+
+    while (GetNextExternalRoute(iterator, route) == kErrorNone)
+    {
+        SuccessOrExit(error = rlocs.AddRloc16(route.mRloc16));
+    }
+
+    iterator = kIteratorInit;
+
+    while (GetNextOnMeshPrefix(iterator, prefix) == kErrorNone)
+    {
+        if (!prefix.mDefaultRoute || !prefix.mOnMesh)
+        {
+            continue;
+        }
+
+        SuccessOrExit(error = rlocs.AddRloc16(prefix.mRloc16));
+    }
+
+exit:
+    aRlocsLength = rlocs.GetLength();
+    return error;
+}
+
+uint8_t NetworkData::CountBorderRouters(RoleFilter aRoleFilter) const
+{
+    // We use an over-estimate of max number of border routers in the
+    // Network Data using the facts that network data is limited to 254
+    // bytes and that an external route entry uses at minimum 3 bytes
+    // for RLOC16 and flag, so `ceil(254/3) = 85`.
+
+    static constexpr uint16_t kMaxRlocs = 85;
+
+    uint16_t rlocs[kMaxRlocs];
+    uint8_t  rlocsLength = kMaxRlocs;
+
+    SuccessOrAssert(FindBorderRouters(aRoleFilter, rlocs, rlocsLength));
+
+    return rlocsLength;
+}
+
+bool NetworkData::ContainsBorderRouterWithRloc(uint16_t aRloc16) const
+{
+    bool                contains = false;
+    Iterator            iterator = kIteratorInit;
+    ExternalRouteConfig route;
+    OnMeshPrefixConfig  prefix;
+
+    while (GetNextExternalRoute(iterator, route) == kErrorNone)
+    {
+        if (route.mRloc16 == aRloc16)
+        {
+            ExitNow(contains = true);
+        }
+    }
+
+    iterator = kIteratorInit;
+
+    while (GetNextOnMeshPrefix(iterator, prefix) == kErrorNone)
+    {
+        if ((prefix.mRloc16 == aRloc16) && prefix.mOnMesh && (prefix.mDefaultRoute || prefix.mDp))
+        {
+            ExitNow(contains = true);
+        }
+    }
+
+exit:
+    return contains;
+}
+
 } // namespace NetworkData
 } // namespace ot
diff --git a/src/core/thread/network_data.hpp b/src/core/thread/network_data.hpp
index 61a8515..cbe5133 100644
--- a/src/core/thread/network_data.hpp
+++ b/src/core/thread/network_data.hpp
@@ -168,34 +168,34 @@
     /**
      * This method provides full or stable copy of the Thread Network Data.
      *
-     * @param[in]    aStable      TRUE when copying the stable version, FALSE when copying the full version.
-     * @param[out]   aData        A pointer to the data buffer to copy the Network Data into.
-     * @param[inout] aDataLength  On entry, size of the data buffer pointed to by @p aData.
-     *                            On exit, number of copied bytes.
+     * @param[in]     aType        The Network Data type to copy, the full set or stable subset.
+     * @param[out]    aData        A pointer to the data buffer to copy the Network Data into.
+     * @param[in,out] aDataLength  On entry, size of the data buffer pointed to by @p aData.
+     *                             On exit, number of copied bytes.
      *
-     * @retval kErrorNone       Successfully copied full Thread Network Data.
+     * @retval kErrorNone       Successfully copied Thread Network Data.
      * @retval kErrorNoBufs     Not enough space in @p aData to fully copy Thread Network Data.
      *
      */
-    Error CopyNetworkData(bool aStable, uint8_t *aData, uint8_t &aDataLength) const;
+    Error CopyNetworkData(Type aType, uint8_t *aData, uint8_t &aDataLength) const;
 
     /**
      * This method provides full or stable copy of the Thread Network Data.
      *
-     * @param[in]    aStable      TRUE when copying the stable version, FALSE when copying the full version.
+     * @param[in]    aType        The Network Data type to copy, the full set or stable subset.
      * @param[out]   aNetworkData A reference to a `MutableNetworkData` to copy the Network Data into.
      *
-     * @retval kErrorNone       Successfully copied full Thread Network Data.
+     * @retval kErrorNone       Successfully copied Thread Network Data.
      * @retval kErrorNoBufs     Not enough space in @p aNetworkData to fully copy Thread Network Data.
      *
      */
-    Error CopyNetworkData(bool aStable, MutableNetworkData &aNetworkData) const;
+    Error CopyNetworkData(Type aType, MutableNetworkData &aNetworkData) const;
 
     /**
      * This method provides the next On Mesh prefix in the Thread Network Data.
      *
-     * @param[inout]  aIterator  A reference to the Network Data iterator.
-     * @param[out]    aConfig    A reference to a config variable where the On Mesh Prefix information will be placed.
+     * @param[in,out]  aIterator  A reference to the Network Data iterator.
+     * @param[out]     aConfig    A reference to a config variable where the On Mesh Prefix information will be placed.
      *
      * @retval kErrorNone       Successfully found the next On Mesh prefix.
      * @retval kErrorNotFound   No subsequent On Mesh prefix exists in the Thread Network Data.
@@ -206,9 +206,9 @@
     /**
      * This method provides the next On Mesh prefix in the Thread Network Data for a given RLOC16.
      *
-     * @param[inout]  aIterator  A reference to the Network Data iterator.
-     * @param[in]     aRloc16    The RLOC16 value.
-     * @param[out]    aConfig    A reference to a config variable where the On Mesh Prefix information will be placed.
+     * @param[in,out]  aIterator  A reference to the Network Data iterator.
+     * @param[in]      aRloc16    The RLOC16 value.
+     * @param[out]     aConfig    A reference to a config variable where the On Mesh Prefix information will be placed.
      *
      * @retval kErrorNone       Successfully found the next On Mesh prefix.
      * @retval kErrorNotFound   No subsequent On Mesh prefix exists in the Thread Network Data.
@@ -219,8 +219,8 @@
     /**
      * This method provides the next external route in the Thread Network Data.
      *
-     * @param[inout]  aIterator  A reference to the Network Data iterator.
-     * @param[out]    aConfig    A reference to a config variable where the external route information will be placed.
+     * @param[in,out]  aIterator  A reference to the Network Data iterator.
+     * @param[out]     aConfig    A reference to a config variable where the external route information will be placed.
      *
      * @retval kErrorNone       Successfully found the next external route.
      * @retval kErrorNotFound   No subsequent external route exists in the Thread Network Data.
@@ -231,9 +231,9 @@
     /**
      * This method provides the next external route in the Thread Network Data for a given RLOC16.
      *
-     * @param[inout]  aIterator  A reference to the Network Data iterator.
-     * @param[in]     aRloc16    The RLOC16 value.
-     * @param[out]    aConfig    A reference to a config variable where the external route information will be placed.
+     * @param[in,out]  aIterator  A reference to the Network Data iterator.
+     * @param[in]      aRloc16    The RLOC16 value.
+     * @param[out]     aConfig    A reference to a config variable where the external route information will be placed.
      *
      * @retval kErrorNone       Successfully found the next external route.
      * @retval kErrorNotFound   No subsequent external route exists in the Thread Network Data.
@@ -244,8 +244,8 @@
     /**
      * This method provides the next service in the Thread Network Data.
      *
-     * @param[inout]  aIterator  A reference to the Network Data iterator.
-     * @param[out]    aConfig    A reference to a config variable where the service information will be placed.
+     * @param[in,out]  aIterator  A reference to the Network Data iterator.
+     * @param[out]     aConfig    A reference to a config variable where the service information will be placed.
      *
      * @retval kErrorNone       Successfully found the next service.
      * @retval kErrorNotFound   No subsequent service exists in the Thread Network Data.
@@ -256,9 +256,9 @@
     /**
      * This method provides the next service in the Thread Network Data for a given RLOC16.
      *
-     * @param[inout]  aIterator  A reference to the Network Data iterator.
-     * @param[in]     aRloc16    The RLOC16 value.
-     * @param[out]    aConfig    A reference to a config variable where the service information will be placed.
+     * @param[in,out]  aIterator  A reference to the Network Data iterator.
+     * @param[in]      aRloc16    The RLOC16 value.
+     * @param[out]     aConfig    A reference to a config variable where the service information will be placed.
      *
      * @retval kErrorNone       Successfully found the next service.
      * @retval kErrorNotFound   No subsequent service exists in the Thread Network Data.
@@ -267,75 +267,56 @@
     Error GetNextService(Iterator &aIterator, uint16_t aRloc16, ServiceConfig &aConfig) const;
 
     /**
-     * This method provides the next Service ID in the Thread Network Data for a given RLOC16.
+     * This method indicates whether or not the Thread Network Data contains a given on mesh prefix entry.
      *
-     * @param[inout]  aIterator  A reference to the Network Data iterator.
-     * @param[in]     aRloc16    The RLOC16 value.
-     * @param[out]    aServiceId A reference to variable where the Service ID will be placed.
+     * @param[in]  aPrefix   The on mesh prefix config to check.
      *
-     * @retval kErrorNone       Successfully found the next service.
-     * @retval kErrorNotFound   No subsequent service exists in the Thread Network Data.
+     * @retval TRUE  if Network Data contains an on mesh prefix matching @p aPrefix.
+     * @retval FALSE if Network Data does not contain an on mesh prefix matching @p aPrefix.
      *
      */
-    Error GetNextServiceId(Iterator &aIterator, uint16_t aRloc16, uint8_t &aServiceId) const;
+    bool ContainsOnMeshPrefix(const OnMeshPrefixConfig &aPrefix) const;
 
     /**
-     * This method indicates whether or not the Thread Network Data contains all of the on mesh prefix information
-     * in @p aCompare associated with @p aRloc16.
+     * This method indicates whether or not the Thread Network Data contains a given external route entry.
      *
-     * @param[in]  aCompare  The Network Data to use for the query.
-     * @param[in]  aRloc16   The RLOC16 to consider.
+     * @param[in]  aRoute   The external route config to check.
      *
-     * @returns TRUE if this object contains all on mesh prefix information in @p aCompare associated with @p aRloc16,
-     *          FALSE otherwise.
+     * @retval TRUE  if Network Data contains an external route matching @p aRoute.
+     * @retval FALSE if Network Data does not contain an external route matching @p aRoute.
      *
      */
-    bool ContainsOnMeshPrefixes(const NetworkData &aCompare, uint16_t aRloc16) const;
+    bool ContainsExternalRoute(const ExternalRouteConfig &aRoute) const;
 
     /**
-     * This method indicates whether or not the Thread Network Data contains all of the external route information
-     * in @p aCompare associated with @p aRloc16.
+     * This method indicates whether or not the Thread Network Data contains a given service entry.
      *
-     * @param[in]  aCompare  The Network Data to use for the query.
-     * @param[in]  aRloc16   The RLOC16 to consider.
+     * @param[in]  aService   The service config to check.
      *
-     * @returns TRUE if this object contains all external route information in @p aCompare associated with @p aRloc16,
-     *          FALSE otherwise.
+     * @retval TRUE  if Network Data contains a service matching @p aService.
+     * @retval FALSE if Network Data does not contain a service matching @p aService.
      *
      */
-    bool ContainsExternalRoutes(const NetworkData &aCompare, uint16_t aRloc16) const;
+    bool ContainsService(const ServiceConfig &aService) const;
 
     /**
-     * This method indicates whether or not the Thread Network Data contains all of the service information
-     * in @p aCompare associated with @p aRloc16.
+     * This method indicates whether or not the Thread Network Data contains all the on mesh prefixes, external
+     * routes, and service entries as in another given Network Data associated with a given RLOC16.
      *
-     * @param[in]  aCompare  The Network Data to use for the query.
-     * @param[in]  aRloc16   The RLOC16 to consider.
+     * @param[in] aCompare         The Network Data to compare with.
+     * @param[in] aRloc16          The RLOC16 to consider.
      *
-     * @returns TRUE if this object contains all service information in @p aCompare associated with @p aRloc16,
-     *          FALSE otherwise.
+     * @retval TRUE  if Network Data contains all the same entries as in @p aCompare for @p aRloc16.
+     * @retval FALSE if Network Data does not contains all the same entries as in @p aCompare for @p aRloc16.
      *
      */
-    bool ContainsServices(const NetworkData &aCompare, uint16_t aRloc16) const;
-
-    /**
-     * This method indicates whether or not the Thread Network Data contains the service with given Service ID
-     * associated with @p aRloc16.
-     *
-     * @param[in]  aServiceId The Service ID to search for.
-     * @param[in]  aRloc16    The RLOC16 to consider.
-     *
-     * @returns TRUE if this object contains the service with given ID associated with @p aRloc16,
-     *          FALSE otherwise.
-     *
-     */
-    bool ContainsService(uint8_t aServiceId, uint16_t aRloc16) const;
+    bool ContainsEntriesFrom(const NetworkData &aCompare, uint16_t aRloc16) const;
 
     /**
      * This method provides the next server RLOC16 in the Thread Network Data.
      *
-     * @param[inout]  aIterator  A reference to the Network Data iterator.
-     * @param[out]    aRloc16    The RLOC16 value.
+     * @param[in,out]  aIterator  A reference to the Network Data iterator.
+     * @param[out]     aRloc16    The RLOC16 value.
      *
      * @retval kErrorNone       Successfully found the next server.
      * @retval kErrorNotFound   No subsequent server exists in the Thread Network Data.
@@ -343,6 +324,67 @@
      */
     Error GetNextServer(Iterator &aIterator, uint16_t &aRloc16) const;
 
+    /**
+     * This method finds and returns the list of RLOCs of border routers providing external IP connectivity.
+     *
+     * A border router is considered to provide external IP connectivity if it has added at least one external route
+     * entry, or an on-mesh prefix with default-route and on-mesh flags set.
+     *
+     * This method should be used when the RLOC16s are present in the Network Data (when the Network Data contains the
+     * full set and not the stable subset).
+     *
+     * @param[in]      aRoleFilter   Indicates which devices to include (any role, router role only, or child only).
+     * @param[out]     aRlocs        Array to output the list of RLOCs.
+     * @param[in,out]  aRlocsLength  On entry, @p aRlocs array length (max number of elements).
+     *                               On exit, number RLOC16 entries added in @p aRlocs.
+     *
+     * @retval kErrorNone     Successfully found all RLOC16s and updated @p aRlocs and @p aRlocsLength.
+     * @retval kErrorNoBufs   Ran out of space in @p aRlocs array. @p aRlocs and @p aRlocsLength are still updated up
+     *                        to the maximum array length.
+     *
+     */
+    Error FindBorderRouters(RoleFilter aRoleFilter, uint16_t aRlocs[], uint8_t &aRlocsLength) const;
+
+    /**
+     * This method counts the number of border routers providing external IP connectivity.
+     *
+     * A border router is considered to provide external IP connectivity if at least one of the below conditions hold
+     *
+     * - It has added at least one external route entry.
+     * - It has added at least one prefix entry with default-route and on-mesh flags set.
+     * - It has added at least one domain prefix (domain and on-mesh flags set).
+     *
+     * This method should be used when the RLOC16s are present in the Network Data (when the Network Data contains the
+     * full set and not the stable subset).
+     *
+     * @param[in] aRoleFilter   Indicates which RLOCs to include (any role, router only, or child only).
+     *
+     * @returns The number of border routers in Thread Network Data matching @p aRoleFilter.
+     *
+     */
+    uint8_t CountBorderRouters(RoleFilter aRoleFilter) const;
+
+    /**
+     * This method indicates whether the network data contains a border providing external IP connectivity with a given
+     * RLOC16.
+     *
+     * A border router is considered to provide external IP connectivity if at least one of the below conditions hold
+     *
+     * - It has added at least one external route entry.
+     * - It has added at least one prefix entry with default-route and on-mesh flags set.
+     * - It has added at least one domain prefix (domain and on-mesh flags set).
+     *
+     * This method should be used when the RLOC16s are present in the Network Data (when the Network Data contains the
+     * full set and not the stable subset).
+     *
+     * @param[in] aRloc16   The RLOC16 to check.
+     *
+     * @returns TRUE  If the network data contains a border router with @p aRloc16 providing IP connectivity.
+     * @returns FALSE If the network data does not contain a border router with @p aRloc16 providing IP connectivity.
+     *
+     */
+    bool ContainsBorderRouterWithRloc(uint16_t aRloc16) const;
+
 protected:
     /**
      * This enumeration defines Service Data match mode.
@@ -376,7 +418,7 @@
      * @param[in]  aPrefix        A pointer to an IPv6 prefix.
      * @param[in]  aPrefixLength  The prefix length pointed to by @p aPrefix (in bits).
      *
-     * @returns A pointer to the Prefix TLV if one is found or nullptr if no matching Prefix TLV exists.
+     * @returns A pointer to the Prefix TLV if one is found or `nullptr` if no matching Prefix TLV exists.
      *
      */
     const PrefixTlv *FindPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength) const;
@@ -386,7 +428,7 @@
      *
      * @param[in]  aPrefix        An IPv6 prefix.
      *
-     * @returns A pointer to the Prefix TLV if one is found or nullptr if no matching Prefix TLV exists.
+     * @returns A pointer to the Prefix TLV if one is found or `nullptr` if no matching Prefix TLV exists.
      *
      */
     const PrefixTlv *FindPrefix(const Ip6::Prefix &aPrefix) const
@@ -401,7 +443,7 @@
      * @param[in]  aServiceData       A Service Data.
      * @param[in]  aServiceMatchMode  The Service Data match mode.
      *
-     * @returns A pointer to the Service TLV if one is found or nullptr if no matching Service TLV exists.
+     * @returns A pointer to the Service TLV if one is found or `nullptr` if no matching Service TLV exists.
      *
      */
     const ServiceTlv *FindService(uint32_t           aEnterpriseNumber,
@@ -413,14 +455,14 @@
      *
      * This method can be used to iterate over all Service TLVs that start with a given Service Data.
      *
-     * @param[in]  aPrevServiceTlv    Set to nullptr to start from the beginning of the TLVs (finding the first matching
-     *                                Service TLV), or a pointer to the previous Service TLV returned from this method
-     *                                to iterate to the next matching Service TLV.
+     * @param[in]  aPrevServiceTlv    Set to `nullptr` to start from the beginning of the TLVs (finding the first
+     *                                matching Service TLV), or a pointer to the previous Service TLV returned from
+     *                                this method to iterate to the next matching Service TLV.
      * @param[in]  aEnterpriseNumber  Enterprise Number.
      * @param[in]  aServiceData       A Service Data to match with Service TLVs.
      * @param[in]  aServiceMatchMode  The Service Data match mode.
      *
-     * @returns A pointer to the next matching Service TLV if one is found or nullptr if it cannot be found.
+     * @returns A pointer to the next matching Service TLV if one is found or `nullptr` if it cannot be found.
      *
      */
     const ServiceTlv *FindNextService(const ServiceTlv * aPrevServiceTlv,
@@ -433,13 +475,13 @@
      *
      * This method can be used to iterate over all Thread Service TLVs that start with a given Service Data.
      *
-     * @param[in]  aPrevServiceTlv    Set to nullptr to start from the beginning of the TLVs (finding the first matching
-     *                                Service TLV), or a pointer to the previous Service TLV returned from this method
-     *                                to iterate to the next matching Service TLV.
+     * @param[in]  aPrevServiceTlv    Set to `nullptr` to start from the beginning of the TLVs (finding the first
+     *                                matching Service TLV), or a pointer to the previous Service TLV returned from
+     *                                this method to iterate to the next matching Service TLV.
      * @param[in]  aServiceData       A Service Data to match with Service TLVs.
      * @param[in]  aServiceMatchMode  The Service Data match mode.
      *
-     * @returns A pointer to the next matching Thread Service TLV if one is found or nullptr if it cannot be found.
+     * @returns A pointer to the next matching Thread Service TLV if one is found or `nullptr` if it cannot be found.
      *
      */
     const ServiceTlv *FindNextThreadService(const ServiceTlv * aPrevServiceTlv,
@@ -633,7 +675,7 @@
      * @param[in]  aPrefix        A pointer to an IPv6 prefix.
      * @param[in]  aPrefixLength  The prefix length pointed to by @p aPrefix (in bits).
      *
-     * @returns A pointer to the Prefix TLV if one is found or nullptr if no matching Prefix TLV exists.
+     * @returns A pointer to the Prefix TLV if one is found or `nullptr` if no matching Prefix TLV exists.
      *
      */
     PrefixTlv *FindPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength)
@@ -646,7 +688,7 @@
      *
      * @param[in]  aPrefix        An IPv6 prefix.
      *
-     * @returns A pointer to the Prefix TLV if one is found or nullptr if no matching Prefix TLV exists.
+     * @returns A pointer to the Prefix TLV if one is found or `nullptr` if no matching Prefix TLV exists.
      *
      */
     PrefixTlv *FindPrefix(const Ip6::Prefix &aPrefix) { return FindPrefix(aPrefix.GetBytes(), aPrefix.GetLength()); }
@@ -660,7 +702,7 @@
      * @param[in]  aServiceData       A Service Data.
      * @param[in]  aServiceMatchMode  The Service Data match mode.
      *
-     * @returns A pointer to the Service TLV if one is found or nullptr if no matching Service TLV exists.
+     * @returns A pointer to the Service TLV if one is found or `nullptr` if no matching Service TLV exists.
      *
      */
     ServiceTlv *FindService(uint32_t           aEnterpriseNumber,
@@ -690,8 +732,8 @@
      *
      * @param[in]  aTlvSize  The size of TLV (total number of bytes including Type, Length, and Value fields)
      *
-     * @returns A pointer to the TLV if there is space to grow Network Data, or nullptr if no space to grow the Network
-     *          Data with requested @p aTlvSize number of bytes.
+     * @returns A pointer to the TLV if there is space to grow Network Data, or `nullptr` if no space to grow the
+     *          Network Data with requested @p aTlvSize number of bytes.
      *
      */
     NetworkDataTlv *AppendTlv(uint16_t aTlvSize);
diff --git a/src/core/thread/network_data_leader.cpp b/src/core/thread/network_data_leader.cpp
index fec66ce..0207c39 100644
--- a/src/core/thread/network_data_leader.cpp
+++ b/src/core/thread/network_data_leader.cpp
@@ -53,6 +53,8 @@
 namespace ot {
 namespace NetworkData {
 
+RegisterLogModule("NetworkData");
+
 void LeaderBase::Reset(void)
 {
     mVersion       = Random::NonCrypto::GetUint8();
@@ -87,6 +89,29 @@
     return error;
 }
 
+Error LeaderBase::GetPreferredNat64Prefix(ExternalRouteConfig &aConfig) const
+{
+    Error               error    = kErrorNotFound;
+    Iterator            iterator = kIteratorInit;
+    ExternalRouteConfig config;
+
+    while (GetNextExternalRoute(iterator, config) == kErrorNone)
+    {
+        if (!config.mNat64 || !config.GetPrefix().IsValidNat64())
+        {
+            continue;
+        }
+
+        if ((error == kErrorNotFound) || (config.mPreference > aConfig.mPreference))
+        {
+            aConfig = config;
+            error   = kErrorNone;
+        }
+    }
+
+    return error;
+}
+
 const PrefixTlv *LeaderBase::FindNextMatchingPrefix(const Ip6::Address &aAddress, const PrefixTlv *aPrevTlv) const
 {
     const PrefixTlv *prefixTlv;
@@ -346,7 +371,7 @@
 
 Error LeaderBase::SetNetworkData(uint8_t        aVersion,
                                  uint8_t        aStableVersion,
-                                 bool           aStableOnly,
+                                 Type           aType,
                                  const Message &aMessage,
                                  uint16_t       aMessageOffset)
 {
@@ -363,20 +388,19 @@
     mVersion       = aVersion;
     mStableVersion = aStableVersion;
 
-    if (aStableOnly)
+    if (aType == kStableSubset)
     {
         RemoveTemporaryData();
     }
 
 #if OPENTHREAD_FTD
-    // Synchronize internal 6LoWPAN Context ID Set with recently obtained Network Data.
     if (Get<Mle::MleRouter>().IsLeader())
     {
-        Get<Leader>().UpdateContextsAfterReset();
+        Get<Leader>().HandleNetworkDataRestoredAfterReset();
     }
 #endif
 
-    otDumpDebgNetData("SetNetworkData", GetBytes(), GetLength());
+    DumpDebg("SetNetworkData", GetBytes(), GetLength());
 
     Get<ot::Notifier>().Signal(kEventThreadNetdataChanged);
 
@@ -394,8 +418,7 @@
     if (aValueLength > 0)
     {
         VerifyOrExit(aValueLength <= kMaxSize - sizeof(CommissioningDataTlv), error = kErrorNoBufs);
-        commissioningDataTlv =
-            static_cast<CommissioningDataTlv *>(AppendTlv(sizeof(CommissioningDataTlv) + aValueLength));
+        commissioningDataTlv = As<CommissioningDataTlv>(AppendTlv(sizeof(CommissioningDataTlv) + aValueLength));
         VerifyOrExit(commissioningDataTlv != nullptr, error = kErrorNoBufs);
 
         commissioningDataTlv->Init();
@@ -471,7 +494,7 @@
     steeringDataTlv = GetCommissioningDataSubTlv(MeshCoP::Tlv::kSteeringData);
     VerifyOrExit(steeringDataTlv != nullptr, error = kErrorInvalidState);
 
-    static_cast<const MeshCoP::SteeringDataTlv *>(steeringDataTlv)->CopyTo(steeringData);
+    As<MeshCoP::SteeringDataTlv>(steeringDataTlv)->CopyTo(steeringData);
 
     VerifyOrExit(steeringData.Contains(aFilterIndexes), error = kErrorNotFound);
 
diff --git a/src/core/thread/network_data_leader.hpp b/src/core/thread/network_data_leader.hpp
index e5c6ee7..54765ef 100644
--- a/src/core/thread/network_data_leader.hpp
+++ b/src/core/thread/network_data_leader.hpp
@@ -85,20 +85,14 @@
     void Reset(void);
 
     /**
-     * This method returns the Thread Network Data version.
+     * This method returns the Data Version value for a type (full set or stable subset).
      *
-     * @returns The Thread Network Data version.
+     * @param[in] aType   The Network Data type (full set or stable subset).
+     *
+     * @returns The Data Version value for @p aType.
      *
      */
-    uint8_t GetVersion(void) const { return mVersion; }
-
-    /**
-     * This method returns the Thread Network Data stable version.
-     *
-     * @returns The Thread Network Data stable version.
-     *
-     */
-    uint8_t GetStableVersion(void) const { return mStableVersion; }
+    uint8_t GetVersion(Type aType) const { return (aType == kFullSet) ? mVersion : mStableVersion; }
 
     /**
      * This method retrieves the 6LoWPAN Context information based on a given IPv6 address.
@@ -157,7 +151,7 @@
      *
      * @param[in]  aVersion        The Version value.
      * @param[in]  aStableVersion  The Stable Version value.
-     * @param[in]  aStableOnly     TRUE if storing only the stable data, FALSE otherwise.
+     * @param[in]  aType           The Network Data type to set, the full set or stable subset.
      * @param[in]  aMessage        A reference to the MLE message.
      * @param[in]  aMessageOffset  The offset in @p aMessage for the Network Data TLV.
      *
@@ -167,14 +161,14 @@
      */
     Error SetNetworkData(uint8_t        aVersion,
                          uint8_t        aStableVersion,
-                         bool           aStableOnly,
+                         Type           aType,
                          const Message &aMessage,
                          uint16_t       aMessageOffset);
 
     /**
      * This method returns a pointer to the Commissioning Data.
      *
-     * @returns A pointer to the Commissioning Data or nullptr if no Commissioning Data exists.
+     * @returns A pointer to the Commissioning Data or `nullptr` if no Commissioning Data exists.
      *
      */
     CommissioningDataTlv *GetCommissioningData(void) { return AsNonConst(AsConst(this)->GetCommissioningData()); }
@@ -182,7 +176,7 @@
     /**
      * This method returns a pointer to the Commissioning Data.
      *
-     * @returns A pointer to the Commissioning Data or nullptr if no Commissioning Data exists.
+     * @returns A pointer to the Commissioning Data or `nullptr` if no Commissioning Data exists.
      *
      */
     const CommissioningDataTlv *GetCommissioningData(void) const;
@@ -192,7 +186,7 @@
      *
      * @param[in]  aType  The TLV type value.
      *
-     * @returns A pointer to the Commissioning Data Sub-TLV or nullptr if no Sub-TLV exists.
+     * @returns A pointer to the Commissioning Data Sub-TLV or `nullptr` if no Sub-TLV exists.
      *
      */
     MeshCoP::Tlv *GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType)
@@ -205,7 +199,7 @@
      *
      * @param[in]  aType  The TLV type value.
      *
-     * @returns A pointer to the Commissioning Data Sub-TLV or nullptr if no Sub-TLV exists.
+     * @returns A pointer to the Commissioning Data Sub-TLV or `nullptr` if no Sub-TLV exists.
      *
      */
     const MeshCoP::Tlv *GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType) const;
@@ -273,6 +267,20 @@
                        bool               aServerStable,
                        uint8_t &          aServiceId) const;
 
+    /**
+     * This methods gets the preferred NAT64 prefix from network data.
+     *
+     * The returned prefix is the highest preference external route entry in Network Data with NAT64 flag set. If there
+     * are multiple such entries the first one is returned.
+     *
+     * @param[out] aConfig      A reference to an `ExternalRouteConfig` to return the prefix.
+     *
+     * @retval kErrorNone       Found the NAT64 prefix and updated @p aConfig.
+     * @retval kErrorNotFound   Could not find any NAT64 entry.
+     *
+     */
+    Error GetPreferredNat64Prefix(ExternalRouteConfig &aConfig) const;
+
 protected:
     uint8_t mStableVersion;
     uint8_t mVersion;
diff --git a/src/core/thread/network_data_leader_ftd.cpp b/src/core/thread/network_data_leader_ftd.cpp
index 2921f21..dac504d 100644
--- a/src/core/thread/network_data_leader_ftd.cpp
+++ b/src/core/thread/network_data_leader_ftd.cpp
@@ -42,7 +42,7 @@
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/message.hpp"
 #include "common/timer.hpp"
 #include "mac/mac_types.hpp"
@@ -56,8 +56,11 @@
 namespace ot {
 namespace NetworkData {
 
+RegisterLogModule("NetworkData");
+
 Leader::Leader(Instance &aInstance)
     : LeaderBase(aInstance)
+    , mWaitingForNetDataSync(false)
     , mTimer(aInstance, Leader::HandleTimer)
     , mServerData(UriPath::kServerData, &Leader::HandleServerData, this)
     , mCommissioningDataGet(UriPath::kCommissionerGet, &Leader::HandleCommissioningGet, this)
@@ -75,8 +78,15 @@
     mContextIdReuseDelay = kContextIdReuseDelay;
 }
 
-void Leader::Start(void)
+void Leader::Start(Mle::LeaderStartMode aStartMode)
 {
+    mWaitingForNetDataSync = (aStartMode == Mle::kRestoringLeaderRoleAfterReset);
+
+    if (mWaitingForNetDataSync)
+    {
+        mTimer.Start(kMaxNetDataSyncWait);
+    }
+
     Get<Tmf::Agent>().AddResource(mServerData);
     Get<Tmf::Agent>().AddResource(mCommissioningDataGet);
     Get<Tmf::Agent>().AddResource(mCommissioningDataSet);
@@ -142,7 +152,9 @@
     ThreadNetworkDataTlv networkDataTlv;
     uint16_t             rloc16;
 
-    otLogInfoNetData("Received network data registration");
+    LogInfo("Received network data registration");
+
+    VerifyOrExit(!mWaitingForNetDataSync);
 
     VerifyOrExit(aMessageInfo.GetPeerAddr().GetIid().IsRoutingLocator());
 
@@ -170,7 +182,7 @@
 
     SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMessage, aMessageInfo));
 
-    otLogInfoNetData("Sent network data registration acknowledgment");
+    LogInfo("Sent network data registration acknowledgment");
 
 exit:
     return;
@@ -223,7 +235,7 @@
         }
         else if (type == MeshCoP::Tlv::kCommissionerSessionId)
         {
-            MeshCoP::CommissionerSessionIdTlv *tlv = static_cast<MeshCoP::CommissionerSessionIdTlv *>(cur);
+            MeshCoP::CommissionerSessionIdTlv *tlv = As<MeshCoP::CommissionerSessionIdTlv>(cur);
 
             VerifyOrExit(tlv->IsValid());
             sessionId    = tlv->GetCommissionerSessionId();
@@ -255,8 +267,7 @@
         {
             if (cur->GetType() == MeshCoP::Tlv::kCommissionerSessionId)
             {
-                VerifyOrExit(sessionId ==
-                             static_cast<MeshCoP::CommissionerSessionIdTlv *>(cur)->GetCommissionerSessionId());
+                VerifyOrExit(sessionId == As<MeshCoP::CommissionerSessionIdTlv>(cur)->GetCommissionerSessionId());
             }
             else if (cur->GetType() == MeshCoP::Tlv::kBorderAgentLocator)
             {
@@ -306,10 +317,8 @@
     uint8_t *             data   = nullptr;
     uint8_t               length = 0;
 
-    VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityResponseMessage(aRequest);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     commDataTlv = GetCommissioningData();
 
@@ -347,7 +356,7 @@
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, aMessageInfo));
 
-    otLogInfoMeshCoP("sent commissioning dataset get response");
+    LogInfo("sent commissioning dataset get response");
 
 exit:
     FreeMessageOnError(message, error);
@@ -360,16 +369,14 @@
     Error          error = kErrorNone;
     Coap::Message *message;
 
-    VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityResponseMessage(aRequest);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = Tlv::Append<MeshCoP::StateTlv>(*message, aState));
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, aMessageInfo));
 
-    otLogInfoMeshCoP("sent commissioning dataset set response");
+    LogInfo("sent commissioning dataset set response");
 
 exit:
     FreeMessageOnError(message, error);
@@ -412,7 +419,7 @@
         {
         case NetworkDataTlv::kTypePrefix:
         {
-            const PrefixTlv *prefix = static_cast<const PrefixTlv *>(cur);
+            const PrefixTlv *prefix = As<PrefixTlv>(cur);
 
             VerifyOrExit(prefix->IsValid(), error = kErrorParse);
 
@@ -426,7 +433,7 @@
 
         case NetworkDataTlv::kTypeService:
         {
-            const ServiceTlv *service = static_cast<const ServiceTlv *>(cur);
+            const ServiceTlv *service = As<ServiceTlv>(cur);
             ServiceData       serviceData;
 
             VerifyOrExit(service->IsValid(), error = kErrorParse);
@@ -473,7 +480,7 @@
         {
         case NetworkDataTlv::kTypeBorderRouter:
         {
-            const BorderRouterTlv *borderRouter = static_cast<const BorderRouterTlv *>(subCur);
+            const BorderRouterTlv *borderRouter = As<BorderRouterTlv>(subCur);
 
             // Ensure Prefix TLV contains at most one stable and one
             // temporary Border Router sub-TLV and the sub-TLVs have
@@ -497,7 +504,7 @@
 
         case NetworkDataTlv::kTypeHasRoute:
         {
-            const HasRouteTlv *hasRoute = static_cast<const HasRouteTlv *>(subCur);
+            const HasRouteTlv *hasRoute = As<HasRouteTlv>(subCur);
 
             // Ensure Prefix TLV contains at most one stable and one
             // temporary Has Route sub-TLV and the sub-TLVs have a
@@ -550,7 +557,7 @@
         {
         case NetworkDataTlv::kTypeServer:
         {
-            const ServerTlv *server = static_cast<const ServerTlv *>(subCur);
+            const ServerTlv *server = As<ServerTlv>(subCur);
 
             VerifyOrExit(!foundServer);
             foundServer = true;
@@ -716,11 +723,11 @@
         switch (cur->GetType())
         {
         case NetworkDataTlv::kTypePrefix:
-            SuccessOrExit(error = AddPrefix(*static_cast<const PrefixTlv *>(cur), flags));
+            SuccessOrExit(error = AddPrefix(*As<PrefixTlv>(cur), flags));
             break;
 
         case NetworkDataTlv::kTypeService:
-            SuccessOrExit(error = AddService(*static_cast<const ServiceTlv *>(cur), flags));
+            SuccessOrExit(error = AddService(*As<ServiceTlv>(cur), flags));
             break;
 
         default:
@@ -730,13 +737,13 @@
 
     IncrementVersions(flags);
 
-    otDumpDebgNetData("Register", GetBytes(), GetLength());
+    DumpDebg("Register", GetBytes(), GetLength());
 
 exit:
 
     if (error != kErrorNone)
     {
-        otLogNoteNetData("Failed to register network data: %s", ErrorToString(error));
+        LogNote("Failed to register network data: %s", ErrorToString(error));
     }
 }
 
@@ -747,7 +754,7 @@
 
     if (dstPrefix == nullptr)
     {
-        dstPrefix = static_cast<PrefixTlv *>(AppendTlv(PrefixTlv::CalculateSize(aPrefix.GetPrefixLength())));
+        dstPrefix = As<PrefixTlv>(AppendTlv(PrefixTlv::CalculateSize(aPrefix.GetPrefixLength())));
         VerifyOrExit(dstPrefix != nullptr, error = kErrorNoBufs);
 
         dstPrefix->Init(aPrefix.GetDomainId(), aPrefix.GetPrefixLength(), aPrefix.GetPrefix());
@@ -758,12 +765,11 @@
         switch (subCur->GetType())
         {
         case NetworkDataTlv::kTypeHasRoute:
-            SuccessOrExit(error = AddHasRoute(*static_cast<const HasRouteTlv *>(subCur), *dstPrefix, aChangedFlags));
+            SuccessOrExit(error = AddHasRoute(*As<HasRouteTlv>(subCur), *dstPrefix, aChangedFlags));
             break;
 
         case NetworkDataTlv::kTypeBorderRouter:
-            SuccessOrExit(
-                error = AddBorderRouter(*static_cast<const BorderRouterTlv *>(subCur), *dstPrefix, aChangedFlags));
+            SuccessOrExit(error = AddBorderRouter(*As<BorderRouterTlv>(subCur), *dstPrefix, aChangedFlags));
             break;
 
         default:
@@ -802,7 +808,7 @@
 
         SuccessOrExit(error = AllocateServiceId(serviceId));
 
-        dstService = static_cast<ServiceTlv *>(
+        dstService = As<ServiceTlv>(
             AppendTlv(ServiceTlv::CalculateSize(aService.GetEnterpriseNumber(), serviceData.GetLength())));
         VerifyOrExit(dstService != nullptr, error = kErrorNoBufs);
 
@@ -840,7 +846,7 @@
         // Ensure there is space for `HasRouteTlv` and a single entry.
         VerifyOrExit(CanInsert(sizeof(HasRouteTlv) + sizeof(HasRouteEntry)), error = kErrorNoBufs);
 
-        dstHasRoute = static_cast<HasRouteTlv *>(aDstPrefix.GetNext());
+        dstHasRoute = As<HasRouteTlv>(aDstPrefix.GetNext());
         Insert(dstHasRoute, sizeof(HasRouteTlv));
         aDstPrefix.IncreaseLength(sizeof(HasRouteTlv));
         dstHasRoute->Init();
@@ -890,7 +896,7 @@
                                ((dstContext == nullptr) ? sizeof(ContextTlv) : 0)),
                      error = kErrorNoBufs);
 
-        dstBorderRouter = static_cast<BorderRouterTlv *>(aDstPrefix.GetNext());
+        dstBorderRouter = As<BorderRouterTlv>(aDstPrefix.GetNext());
         Insert(dstBorderRouter, sizeof(BorderRouterTlv));
         aDstPrefix.IncreaseLength(sizeof(BorderRouterTlv));
         dstBorderRouter->Init();
@@ -906,7 +912,7 @@
         // Ensure there is space for a `ContextTlv` and a single entry.
         VerifyOrExit(CanInsert(sizeof(BorderRouterEntry) + sizeof(ContextTlv)), error = kErrorNoBufs);
 
-        dstContext = static_cast<ContextTlv *>(aDstPrefix.GetNext());
+        dstContext = As<ContextTlv>(aDstPrefix.GetNext());
         Insert(dstContext, sizeof(ContextTlv));
         aDstPrefix.IncreaseLength(sizeof(ContextTlv));
         dstContext->Init(static_cast<uint8_t>(contextId), aDstPrefix.GetPrefixLength());
@@ -947,7 +953,7 @@
 
     aServer.GetServerData(serverData);
 
-    dstServer = static_cast<ServerTlv *>(aDstService.GetNext());
+    dstServer = As<ServerTlv>(aDstService.GetNext());
     Insert(dstServer, tlvSize);
     dstServer->Init(aServer.GetServer16(), serverData);
 
@@ -974,7 +980,7 @@
         {
             aServiceId = serviceId;
             error      = kErrorNone;
-            otLogInfoNetData("Allocated Service ID = %d", serviceId);
+            LogInfo("Allocated Service ID = %d", serviceId);
             break;
         }
     }
@@ -1009,7 +1015,7 @@
             mContextUsed |= (1 << contextId);
             aContextId = contextId;
             error      = kErrorNone;
-            otLogInfoNetData("Allocated Context ID = %d", contextId);
+            LogInfo("Allocated Context ID = %d", contextId);
             break;
         }
     }
@@ -1019,7 +1025,7 @@
 
 void Leader::FreeContextId(uint8_t aContextId)
 {
-    otLogInfoNetData("Free Context Id = %d", aContextId);
+    LogInfo("Free Context Id = %d", aContextId);
     RemoveContext(aContextId);
     mContextUsed &= ~(1 << aContextId);
     IncrementVersions(/* aIncludeStable */ true);
@@ -1068,7 +1074,7 @@
         {
         case NetworkDataTlv::kTypePrefix:
         {
-            PrefixTlv *      prefix = static_cast<PrefixTlv *>(cur);
+            PrefixTlv *      prefix = As<PrefixTlv>(cur);
             const PrefixTlv *excludePrefix =
                 aExcludeNetworkData.FindPrefix(prefix->GetPrefix(), prefix->GetPrefixLength());
 
@@ -1085,7 +1091,7 @@
 
         case NetworkDataTlv::kTypeService:
         {
-            ServiceTlv *      service = static_cast<ServiceTlv *>(cur);
+            ServiceTlv *      service = As<ServiceTlv>(cur);
             ServiceData       serviceData;
             const ServiceTlv *excludeService;
 
@@ -1130,8 +1136,7 @@
         switch (cur->GetType())
         {
         case NetworkDataTlv::kTypeHasRoute:
-            RemoveRlocInHasRoute(aPrefix, *static_cast<HasRouteTlv *>(cur), aRloc16, aMatchMode, aExcludePrefix,
-                                 aChangedFlags);
+            RemoveRlocInHasRoute(aPrefix, *As<HasRouteTlv>(cur), aRloc16, aMatchMode, aExcludePrefix, aChangedFlags);
 
             if (cur->GetLength() == 0)
             {
@@ -1143,7 +1148,7 @@
             break;
 
         case NetworkDataTlv::kTypeBorderRouter:
-            RemoveRlocInBorderRouter(aPrefix, *static_cast<BorderRouterTlv *>(cur), aRloc16, aMatchMode, aExcludePrefix,
+            RemoveRlocInBorderRouter(aPrefix, *As<BorderRouterTlv>(cur), aRloc16, aMatchMode, aExcludePrefix,
                                      aChangedFlags);
 
             if (cur->GetLength() == 0)
@@ -1301,11 +1306,16 @@
     }
 }
 
-void Leader::UpdateContextsAfterReset(void)
+void Leader::HandleNetworkDataRestoredAfterReset(void)
 {
     const PrefixTlv *prefix;
     TlvIterator      tlvIterator(GetTlvsStart(), GetTlvsEnd());
 
+    mWaitingForNetDataSync = false;
+
+    // Synchronize internal 6LoWPAN Context ID Set with the
+    // recently obtained Network Data.
+
     while ((prefix = tlvIterator.Iterate<PrefixTlv>()) != nullptr)
     {
         const ContextTlv *context = prefix->FindSubTlv<ContextTlv>();
@@ -1337,6 +1347,13 @@
 {
     bool contextsWaiting = false;
 
+    if (mWaitingForNetDataSync)
+    {
+        LogInfo("Timed out waiting for netdata on restoring leader role after reset");
+        IgnoreError(Get<Mle::MleRouter>().BecomeDetached());
+        ExitNow();
+    }
+
     for (uint8_t i = 0; i < kNumContextIds; i++)
     {
         if (mContextLastUsed[i].GetValue() == 0)
@@ -1358,6 +1375,9 @@
     {
         mTimer.Start(kStateUpdatePeriod);
     }
+
+exit:
+    return;
 }
 
 Error Leader::RemoveStaleChildEntries(Coap::ResponseHandler aHandler, void *aContext)
@@ -1383,6 +1403,45 @@
     return error;
 }
 
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+bool Leader::ContainsOmrPrefix(const Ip6::Prefix &aPrefix)
+{
+    PrefixTlv *prefixTlv;
+    bool       contains = false;
+
+    VerifyOrExit(BorderRouter::RoutingManager::IsValidOmrPrefix(aPrefix));
+
+    prefixTlv = FindPrefix(aPrefix);
+    VerifyOrExit(prefixTlv != nullptr);
+
+    for (int i = 0; i < 2; i++)
+    {
+        const BorderRouterTlv *borderRouter = prefixTlv->FindSubTlv<BorderRouterTlv>(/* aStable */ (i == 0));
+
+        if (borderRouter == nullptr)
+        {
+            continue;
+        }
+
+        for (const BorderRouterEntry *entry = borderRouter->GetFirstEntry(); entry <= borderRouter->GetLastEntry();
+             entry                          = entry->GetNext())
+        {
+            OnMeshPrefixConfig config;
+
+            config.SetFrom(*prefixTlv, *borderRouter, *entry);
+
+            if (BorderRouter::RoutingManager::IsValidOmrPrefix(config))
+            {
+                ExitNow(contains = true);
+            }
+        }
+    }
+
+exit:
+    return contains;
+}
+#endif
+
 } // namespace NetworkData
 } // namespace ot
 
diff --git a/src/core/thread/network_data_leader_ftd.hpp b/src/core/thread/network_data_leader_ftd.hpp
index 2fecf38..1ca969f 100644
--- a/src/core/thread/network_data_leader_ftd.hpp
+++ b/src/core/thread/network_data_leader_ftd.hpp
@@ -95,8 +95,15 @@
     /**
      * This method starts the Leader services.
      *
+     * The start mode indicates whether device is starting normally as leader or restoring its role as leader after
+     * reset. In the latter case, we do not accept any new registrations (`HandleServerData()`) and wait for
+     * `HandleNetworkDataRestoredAfterReset()` to indicate that the leader has successfully recovered the Network Data
+     * before allowing new Network Data registrations.
+     *
+     * @param[in] aStartMode   The start mode.
+     *
      */
-    void Start(void);
+    void Start(Mle::LeaderStartMode aStartMode);
 
     /**
      * This method stops the Leader services.
@@ -149,7 +156,7 @@
      * Note that this method should be called only by the Leader once after reset.
      *
      */
-    void UpdateContextsAfterReset(void);
+    void HandleNetworkDataRestoredAfterReset(void);
 
     /**
      * This method scans network data for given Service ID and returns pointer to the respective TLV, if present.
@@ -173,6 +180,19 @@
      */
     Error RemoveStaleChildEntries(Coap::ResponseHandler aHandler, void *aContext);
 
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+    /**
+     * This method indicates whether a given Prefix can act as a valid OMR prefix and exists in the network data.
+     *
+     * @param[in]  aPrefix   The OMR prefix to check.
+     *
+     * @retval TRUE  If @p aPrefix is a valid OMR prefix and Network Data contains @p aPrefix.
+     * @retval FALSE Otherwise.
+     *
+     */
+    bool ContainsOmrPrefix(const Ip6::Prefix &aPrefix);
+#endif
+
 private:
     class ChangedFlags
     {
@@ -292,7 +312,9 @@
     static constexpr uint8_t  kNumContextIds       = 15;           // Maximum Context ID
     static constexpr uint32_t kContextIdReuseDelay = 48 * 60 * 60; // in seconds
     static constexpr uint32_t kStateUpdatePeriod   = 60 * 1000;    // State update period in milliseconds
+    static constexpr uint32_t kMaxNetDataSyncWait  = 60 * 1000;    // Maximum time to wait for netdata sync.
 
+    bool       mWaitingForNetDataSync;
     uint16_t   mContextUsed;
     TimeMilli  mContextLastUsed[kNumContextIds];
     uint32_t   mContextIdReuseDelay;
diff --git a/src/core/thread/network_data_local.cpp b/src/core/thread/network_data_local.cpp
index 9cc7c57..7299bef 100644
--- a/src/core/thread/network_data_local.cpp
+++ b/src/core/thread/network_data_local.cpp
@@ -39,7 +39,7 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "mac/mac_types.hpp"
 #include "thread/mle_types.hpp"
 #include "thread/thread_netif.hpp"
@@ -47,6 +47,8 @@
 namespace ot {
 namespace NetworkData {
 
+RegisterLogModule("NetworkData");
+
 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
 
 Error Local::AddOnMeshPrefix(const OnMeshPrefixConfig &aConfig)
@@ -62,9 +64,18 @@
     return error;
 }
 
-Error Local::RemoveOnMeshPrefix(const Ip6::Prefix &aPrefix)
+bool Local::ContainsOnMeshPrefix(const Ip6::Prefix &aPrefix) const
 {
-    return RemovePrefix(aPrefix, NetworkDataTlv::kTypeBorderRouter);
+    const PrefixTlv *tlv;
+    bool             contains = false;
+
+    VerifyOrExit((tlv = FindPrefix(aPrefix)) != nullptr);
+    VerifyOrExit(tlv->FindSubTlv(NetworkDataTlv::kTypeBorderRouter) != nullptr);
+
+    contains = true;
+
+exit:
+    return contains;
 }
 
 Error Local::AddHasRoutePrefix(const ExternalRouteConfig &aConfig)
@@ -79,24 +90,19 @@
     return error;
 }
 
-Error Local::RemoveHasRoutePrefix(const Ip6::Prefix &aPrefix)
-{
-    return RemovePrefix(aPrefix, NetworkDataTlv::kTypeHasRoute);
-}
-
 Error Local::AddPrefix(const Ip6::Prefix &aPrefix, NetworkDataTlv::Type aSubTlvType, uint16_t aFlags, bool aStable)
 {
     Error      error = kErrorNone;
     uint8_t    subTlvLength;
     PrefixTlv *prefixTlv;
 
-    IgnoreError(RemovePrefix(aPrefix, aSubTlvType));
+    IgnoreError(RemovePrefix(aPrefix));
 
     subTlvLength = (aSubTlvType == NetworkDataTlv::kTypeBorderRouter)
                        ? sizeof(BorderRouterTlv) + sizeof(BorderRouterEntry)
                        : sizeof(HasRouteTlv) + sizeof(HasRouteEntry);
 
-    prefixTlv = static_cast<PrefixTlv *>(AppendTlv(sizeof(PrefixTlv) + aPrefix.GetBytesSize() + subTlvLength));
+    prefixTlv = As<PrefixTlv>(AppendTlv(sizeof(PrefixTlv) + aPrefix.GetBytesSize() + subTlvLength));
     VerifyOrExit(prefixTlv != nullptr, error = kErrorNoBufs);
 
     prefixTlv->Init(0, aPrefix);
@@ -104,7 +110,7 @@
 
     if (aSubTlvType == NetworkDataTlv::kTypeBorderRouter)
     {
-        BorderRouterTlv *brTlv = static_cast<BorderRouterTlv *>(prefixTlv->GetSubTlvs());
+        BorderRouterTlv *brTlv = As<BorderRouterTlv>(prefixTlv->GetSubTlvs());
         brTlv->Init();
         brTlv->SetLength(brTlv->GetLength() + sizeof(BorderRouterEntry));
         brTlv->GetEntry(0)->Init();
@@ -112,7 +118,7 @@
     }
     else // aSubTlvType is NetworkDataTlv::kTypeHasRoute
     {
-        HasRouteTlv *hasRouteTlv = static_cast<HasRouteTlv *>(prefixTlv->GetSubTlvs());
+        HasRouteTlv *hasRouteTlv = As<HasRouteTlv>(prefixTlv->GetSubTlvs());
         hasRouteTlv->Init();
         hasRouteTlv->SetLength(hasRouteTlv->GetLength() + sizeof(HasRouteEntry));
         hasRouteTlv->GetEntry(0)->Init();
@@ -125,23 +131,22 @@
         prefixTlv->GetSubTlvs()->SetStable();
     }
 
-    otDumpDebgNetData("AddPrefix", GetBytes(), GetLength());
+    DumpDebg("AddPrefix", GetBytes(), GetLength());
 
 exit:
     return error;
 }
 
-Error Local::RemovePrefix(const Ip6::Prefix &aPrefix, NetworkDataTlv::Type aSubTlvType)
+Error Local::RemovePrefix(const Ip6::Prefix &aPrefix)
 {
     Error      error = kErrorNone;
     PrefixTlv *tlv;
 
     VerifyOrExit((tlv = FindPrefix(aPrefix)) != nullptr, error = kErrorNotFound);
-    VerifyOrExit(tlv->FindSubTlv(aSubTlvType) != nullptr, error = kErrorNotFound);
     RemoveTlv(tlv);
 
 exit:
-    otDumpDebgNetData("RmvPrefix", GetBytes(), GetLength());
+    DumpDebg("RmvPrefix", GetBytes(), GetLength());
     return error;
 }
 
@@ -154,11 +159,11 @@
         switch (cur->GetType())
         {
         case NetworkDataTlv::kTypeHasRoute:
-            static_cast<HasRouteTlv *>(cur)->GetEntry(0)->SetRloc(rloc16);
+            As<HasRouteTlv>(cur)->GetEntry(0)->SetRloc(rloc16);
             break;
 
         case NetworkDataTlv::kTypeBorderRouter:
-            static_cast<BorderRouterTlv *>(cur)->GetEntry(0)->SetRloc(rloc16);
+            As<BorderRouterTlv>(cur)->GetEntry(0)->SetRloc(rloc16);
             break;
 
         default:
@@ -168,18 +173,6 @@
     }
 }
 
-bool Local::IsOnMeshPrefixConsistent(void) const
-{
-    return (Get<Leader>().ContainsOnMeshPrefixes(*this, Get<Mle::MleRouter>().GetRloc16()) &&
-            ContainsOnMeshPrefixes(Get<Leader>(), Get<Mle::MleRouter>().GetRloc16()));
-}
-
-bool Local::IsExternalRouteConsistent(void) const
-{
-    return (Get<Leader>().ContainsExternalRoutes(*this, Get<Mle::MleRouter>().GetRloc16()) &&
-            ContainsExternalRoutes(Get<Leader>(), Get<Mle::MleRouter>().GetRloc16()));
-}
-
 #endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
 
 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
@@ -198,13 +191,13 @@
 
     VerifyOrExit(serviceTlvSize <= kMaxSize, error = kErrorNoBufs);
 
-    serviceTlv = static_cast<ServiceTlv *>(AppendTlv(serviceTlvSize));
+    serviceTlv = As<ServiceTlv>(AppendTlv(serviceTlvSize));
     VerifyOrExit(serviceTlv != nullptr, error = kErrorNoBufs);
 
     serviceTlv->Init(/* aServiceId */ 0, aEnterpriseNumber, aServiceData);
     serviceTlv->SetSubTlvsLength(sizeof(ServerTlv) + aServerData.GetLength());
 
-    serverTlv = static_cast<ServerTlv *>(serviceTlv->GetSubTlvs());
+    serverTlv = As<ServerTlv>(serviceTlv->GetSubTlvs());
     serverTlv->Init(Get<Mle::MleRouter>().GetRloc16(), aServerData);
 
     // According to Thread spec 1.1.1, section 5.18.6 Service TLV:
@@ -216,7 +209,7 @@
         serverTlv->SetStable();
     }
 
-    otDumpDebgNetData("AddService", GetBytes(), GetLength());
+    DumpDebg("AddService", GetBytes(), GetLength());
 
 exit:
     return error;
@@ -232,7 +225,7 @@
     RemoveTlv(tlv);
 
 exit:
-    otDumpDebgNetData("RmvService", GetBytes(), GetLength());
+    DumpDebg("RmvService", GetBytes(), GetLength());
     return error;
 }
 
@@ -245,7 +238,7 @@
         switch (cur->GetType())
         {
         case NetworkDataTlv::kTypeServer:
-            static_cast<ServerTlv *>(cur)->SetServer16(rloc16);
+            As<ServerTlv>(cur)->SetServer16(rloc16);
             break;
 
         default:
@@ -255,12 +248,6 @@
     }
 }
 
-bool Local::IsServiceConsistent(void) const
-{
-    return (Get<Leader>().ContainsServices(*this, Get<Mle::MleRouter>().GetRloc16()) &&
-            ContainsServices(Get<Leader>(), Get<Mle::MleRouter>().GetRloc16()));
-}
-
 #endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
 
 void Local::UpdateRloc(void)
@@ -271,14 +258,14 @@
         {
 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
         case NetworkDataTlv::kTypePrefix:
-            UpdateRloc(*static_cast<PrefixTlv *>(cur));
+            UpdateRloc(*As<PrefixTlv>(cur));
             break;
 #endif
 
 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
 
         case NetworkDataTlv::kTypeService:
-            UpdateRloc(*static_cast<ServiceTlv *>(cur));
+            UpdateRloc(*As<ServiceTlv>(cur));
             break;
 #endif
 
@@ -289,11 +276,16 @@
     }
 }
 
+bool Local::IsConsistent(void) const
+{
+    return Get<Leader>().ContainsEntriesFrom(*this, Get<Mle::MleRouter>().GetRloc16()) &&
+           ContainsEntriesFrom(Get<Leader>(), Get<Mle::MleRouter>().GetRloc16());
+}
+
 Error Local::UpdateInconsistentServerData(Coap::ResponseHandler aHandler, void *aContext)
 {
-    Error    error        = kErrorNone;
-    uint16_t rloc         = Get<Mle::MleRouter>().GetRloc16();
-    bool     isConsistent = true;
+    Error    error = kErrorNone;
+    uint16_t rloc  = Get<Mle::MleRouter>().GetRloc16();
 
 #if OPENTHREAD_FTD
     // Don't send this Server Data Notification if the device is going to upgrade to Router
@@ -305,14 +297,7 @@
 
     UpdateRloc();
 
-#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
-    isConsistent = isConsistent && IsOnMeshPrefixConsistent() && IsExternalRouteConsistent();
-#endif
-#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-    isConsistent = isConsistent && IsServiceConsistent();
-#endif
-
-    VerifyOrExit(!isConsistent, error = kErrorNotFound);
+    VerifyOrExit(!IsConsistent(), error = kErrorNotFound);
 
     if (mOldRloc == rloc)
     {
diff --git a/src/core/thread/network_data_local.hpp b/src/core/thread/network_data_local.hpp
index de82f68..ec274d1 100644
--- a/src/core/thread/network_data_local.hpp
+++ b/src/core/thread/network_data_local.hpp
@@ -95,7 +95,18 @@
      * @retval kErrorNotFound   Could not find the Border Router entry.
      *
      */
-    Error RemoveOnMeshPrefix(const Ip6::Prefix &aPrefix);
+    Error RemoveOnMeshPrefix(const Ip6::Prefix &aPrefix) { return RemovePrefix(aPrefix); }
+
+    /**
+     * This method indicates whether or not the Thread Network Data contains a given on mesh prefix.
+     *
+     * @param[in]  aPrefix   The on mesh prefix to check.
+     *
+     * @retval TRUE  if Network Data contains mesh prefix @p aPrefix.
+     * @retval FALSE if Network Data does not contain mesh prefix @p aPrefix.
+     *
+     */
+    bool ContainsOnMeshPrefix(const Ip6::Prefix &aPrefix) const;
 
     /**
      * This method adds a Has Route entry to the Thread Network data.
@@ -118,7 +129,7 @@
      * @retval kErrorNotFound   Could not find the Border Router entry.
      *
      */
-    Error RemoveHasRoutePrefix(const Ip6::Prefix &aPrefix);
+    Error RemoveHasRoutePrefix(const Ip6::Prefix &aPrefix) { return RemovePrefix(aPrefix); }
 #endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
 
 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
@@ -168,17 +179,16 @@
 
 private:
     void UpdateRloc(void);
+    bool IsConsistent(void) const;
+
 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
     Error AddPrefix(const Ip6::Prefix &aPrefix, NetworkDataTlv::Type aSubTlvType, uint16_t aFlags, bool aStable);
-    Error RemovePrefix(const Ip6::Prefix &aPrefix, NetworkDataTlv::Type aSubTlvType);
+    Error RemovePrefix(const Ip6::Prefix &aPrefix);
     void  UpdateRloc(PrefixTlv &aPrefixTlv);
-    bool  IsOnMeshPrefixConsistent(void) const;
-    bool  IsExternalRouteConsistent(void) const;
 #endif
 
 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
     void UpdateRloc(ServiceTlv &aService);
-    bool IsServiceConsistent(void) const;
 #endif
 
     uint8_t  mTlvBuffer[kMaxSize];
diff --git a/src/core/thread/network_data_notifier.cpp b/src/core/thread/network_data_notifier.cpp
index d82df76..00b15ce 100644
--- a/src/core/thread/network_data_notifier.cpp
+++ b/src/core/thread/network_data_notifier.cpp
@@ -38,24 +38,42 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
+#include "common/log.hpp"
 #include "thread/network_data_leader.hpp"
 #include "thread/network_data_local.hpp"
 
 namespace ot {
 namespace NetworkData {
 
+RegisterLogModule("NetworkData");
+
 Notifier::Notifier(Instance &aInstance)
     : InstanceLocator(aInstance)
-    , mTimer(aInstance, Notifier::HandleTimer)
+    , mTimer(aInstance, HandleTimer)
+    , mSynchronizeDataTask(aInstance, HandleSynchronizeDataTask)
     , mNextDelay(0)
     , mWaitingForResponse(false)
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
+    , mDidRequestRouterRoleUpgrade(false)
+    , mRouterRoleUpgradeTimeout(0)
+#endif
 {
 }
 
 void Notifier::HandleServerDataUpdated(void)
 {
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
+    mDidRequestRouterRoleUpgrade = false;
+    ScheduleRouterRoleUpgradeIfEligible();
+#endif
+
     mNextDelay = 0;
-    SynchronizeServerData();
+    mSynchronizeDataTask.Post();
+}
+
+void Notifier::HandleSynchronizeDataTask(Tasklet &aTasklet)
+{
+    aTasklet.Get<Notifier>().SynchronizeServerData();
 }
 
 void Notifier::SynchronizeServerData(void)
@@ -107,6 +125,18 @@
         mNextDelay = 0;
     }
 
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
+    if (aEvents.Contains(kEventThreadPartitionIdChanged))
+    {
+        mDidRequestRouterRoleUpgrade = false;
+    }
+
+    if (aEvents.ContainsAny(kEventThreadRoleChanged | kEventThreadNetdataChanged | kEventThreadPartitionIdChanged))
+    {
+        ScheduleRouterRoleUpgradeIfEligible();
+    }
+#endif
+
     if (aEvents.ContainsAny(kEventThreadNetdataChanged | kEventThreadRoleChanged | kEventThreadChildRemoved))
     {
         SynchronizeServerData();
@@ -152,6 +182,90 @@
     }
 }
 
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
+
+bool Notifier::IsEligibleForRouterRoleUpgradeAsBorderRouter(void) const
+{
+    bool     isEligible = false;
+    uint16_t rloc16     = Get<Mle::Mle>().GetRloc16();
+    uint8_t  activeRouterCount;
+
+    VerifyOrExit(Get<Mle::MleRouter>().IsRouterEligible());
+
+    // RouterUpgradeThreshold can be explicitly set to zero in some of
+    // cert tests to disallow device to become router.
+
+    VerifyOrExit(Get<Mle::MleRouter>().GetRouterUpgradeThreshold() != 0);
+
+    // Check that we are a border router providing IP connectivity and already
+    // in the leader's network data and therefore eligible to request router
+    // role upgrade with `kBorderRouterRequest` status.
+
+    VerifyOrExit(Get<Local>().ContainsBorderRouterWithRloc(rloc16) &&
+                 Get<Leader>().ContainsBorderRouterWithRloc(rloc16));
+
+    activeRouterCount = Get<RouterTable>().GetActiveRouterCount();
+    VerifyOrExit((activeRouterCount >= Get<Mle::MleRouter>().GetRouterUpgradeThreshold()) &&
+                 (activeRouterCount < Mle::kMaxRouters));
+
+    VerifyOrExit(Get<Leader>().CountBorderRouters(kRouterRoleOnly) < Mle::kRouterUpgradeBorderRouterRequestThreshold);
+    isEligible = true;
+
+exit:
+    return isEligible;
+}
+
+void Notifier::ScheduleRouterRoleUpgradeIfEligible(void)
+{
+    // We allow device to request router role upgrade using status
+    // reason `kBorderRouterRequest` once while its local network data
+    // remains unchanged. This ensures if the leader is running an
+    // older version of Thread stack which does not support
+    // `kBorderRouterRequest` reason, we do not keep trying (on no
+    // response). The boolean `mDidRequestRouterRoleUpgrade` tracks
+    // this. It is set to `false` when local network data gets changed
+    // or when partition ID gets changed (indicating a potential
+    // leader change).
+
+    VerifyOrExit(!mDidRequestRouterRoleUpgrade);
+
+    VerifyOrExit(Get<Mle::MleRouter>().IsChild());
+    VerifyOrExit(IsEligibleForRouterRoleUpgradeAsBorderRouter() && (mRouterRoleUpgradeTimeout == 0));
+
+    mRouterRoleUpgradeTimeout = Random::NonCrypto::GetUint8InRange(1, kRouterRoleUpgradeMaxTimeout + 1);
+    Get<TimeTicker>().RegisterReceiver(TimeTicker::kNetworkDataNotifier);
+
+exit:
+    return;
+}
+
+void Notifier::HandleTimeTick(void)
+{
+    VerifyOrExit(mRouterRoleUpgradeTimeout > 0);
+
+    mRouterRoleUpgradeTimeout--;
+
+    if (mRouterRoleUpgradeTimeout == 0)
+    {
+        Get<TimeTicker>().UnregisterReceiver(TimeTicker::kNetworkDataNotifier);
+
+        // Check that we are still eligible for requesting router role
+        // upgrade (note that state can change since the last time we
+        // checked and registered to receive time ticks).
+
+        if (Get<Mle::MleRouter>().IsChild() && IsEligibleForRouterRoleUpgradeAsBorderRouter())
+        {
+            LogInfo("Requesting router role as BR");
+            mDidRequestRouterRoleUpgrade = true;
+            IgnoreError(Get<Mle::MleRouter>().BecomeRouter(ThreadStatusTlv::kBorderRouterRequest));
+        }
+    }
+exit:
+    return;
+}
+#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE &&
+       // OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
+
 } // namespace NetworkData
 } // namespace ot
 
diff --git a/src/core/thread/network_data_notifier.hpp b/src/core/thread/network_data_notifier.hpp
index 7bd3134..2388da7 100644
--- a/src/core/thread/network_data_notifier.hpp
+++ b/src/core/thread/network_data_notifier.hpp
@@ -42,6 +42,8 @@
 #include "common/message.hpp"
 #include "common/non_copyable.hpp"
 #include "common/notifier.hpp"
+#include "common/tasklet.hpp"
+#include "common/time_ticker.hpp"
 
 namespace ot {
 namespace NetworkData {
@@ -53,6 +55,7 @@
 class Notifier : public InstanceLocator, private NonCopyable
 {
     friend class ot::Notifier;
+    friend class ot::TimeTicker;
 
 public:
     /**
@@ -66,13 +69,40 @@
     /**
      * Call this method to inform the notifier that new server data is available.
      *
+     * This method posts a tasklet to sync new server data with leader so if there are multiple changes within the same
+     * flow of execution (multiple calls to this method) they are all synchronized together and included in the same
+     * message to the leader.
+     *
      */
     void HandleServerDataUpdated(void);
 
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
+    /**
+     * This method indicates whether the device as border router is eligible for router role upgrade request using the
+     * status reason `kBorderRouterRequest`.
+     *
+     * This method checks whether device is providing IP connectivity and that there are fewer than two border routers
+     * in network data acting as router.  Device is considered to provide external IP connectivity if at least one of
+     * the below conditions hold:
+     *
+     * - It has added at least one external route entry.
+     * - It has added at least one prefix entry with default-route and on-mesh flags set.
+     * - It has added at least one domain prefix (domain and on-mesh flags set).
+     *
+     * This method does not check the current role of device.
+     *
+     * @retval TRUE    Device is eligible to request router role upgrade as a border router.
+     * @retval FALSE   Device is not eligible to request router role upgrade as a border router.
+     *
+     */
+    bool IsEligibleForRouterRoleUpgradeAsBorderRouter(void) const;
+#endif
+
 private:
-    static constexpr uint32_t kDelayNoBufs                = 1000;   // in msec
-    static constexpr uint32_t kDelayRemoveStaleChildren   = 5000;   // in msec
-    static constexpr uint32_t kDelaySynchronizeServerData = 300000; // in msec
+    static constexpr uint32_t kDelayNoBufs                 = 1000;   // in msec
+    static constexpr uint32_t kDelayRemoveStaleChildren    = 5000;   // in msec
+    static constexpr uint32_t kDelaySynchronizeServerData  = 300000; // in msec
+    static constexpr uint8_t  kRouterRoleUpgradeMaxTimeout = 10;     // in sec
 
     void HandleNotifierEvents(Events aEvents);
 
@@ -85,11 +115,23 @@
                                    Error                aResult);
     void        HandleCoapResponse(Error aResult);
 
+    static void HandleSynchronizeDataTask(Tasklet &aTasklet);
+
     void SynchronizeServerData(void);
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
+    void ScheduleRouterRoleUpgradeIfEligible(void);
+    void HandleTimeTick(void);
+#endif
 
     TimerMilli mTimer;
+    Tasklet    mSynchronizeDataTask;
     uint32_t   mNextDelay;
-    bool       mWaitingForResponse;
+    bool       mWaitingForResponse : 1;
+
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
+    bool    mDidRequestRouterRoleUpgrade : 1;
+    uint8_t mRouterRoleUpgradeTimeout;
+#endif
 };
 
 } // namespace NetworkData
diff --git a/src/core/thread/network_data_publisher.cpp b/src/core/thread/network_data_publisher.cpp
index 0ccb867..8141c76 100644
--- a/src/core/thread/network_data_publisher.cpp
+++ b/src/core/thread/network_data_publisher.cpp
@@ -36,11 +36,12 @@
 
 #if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
 
+#include "common/array.hpp"
 #include "common/code_utils.hpp"
 #include "common/const_cast.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/random.hpp"
 #include "thread/network_data_local.hpp"
 #include "thread/network_data_service.hpp"
@@ -48,6 +49,8 @@
 namespace ot {
 namespace NetworkData {
 
+RegisterLogModule("NetDataPublshr");
+
 //---------------------------------------------------------------------------------------------------------------------
 // Publisher
 
@@ -86,13 +89,15 @@
 
 Error Publisher::PublishOnMeshPrefix(const OnMeshPrefixConfig &aConfig)
 {
-    Error        error;
+    Error        error = kErrorNone;
     PrefixEntry *entry;
 
     VerifyOrExit(aConfig.IsValid(GetInstance()), error = kErrorInvalidArgs);
     VerifyOrExit(aConfig.mStable, error = kErrorInvalidArgs);
 
-    SuccessOrExit(error = AllocatePrefixEntry(aConfig.GetPrefix(), entry));
+    entry = FindOrAllocatePrefixEntry(aConfig.GetPrefix());
+    VerifyOrExit(entry != nullptr, error = kErrorNoBufs);
+
     entry->Publish(aConfig);
 
 exit:
@@ -101,13 +106,15 @@
 
 Error Publisher::PublishExternalRoute(const ExternalRouteConfig &aConfig)
 {
-    Error        error;
+    Error        error = kErrorNone;
     PrefixEntry *entry;
 
     VerifyOrExit(aConfig.IsValid(GetInstance()), error = kErrorInvalidArgs);
     VerifyOrExit(aConfig.mStable, error = kErrorInvalidArgs);
 
-    SuccessOrExit(error = AllocatePrefixEntry(aConfig.GetPrefix(), entry));
+    entry = FindOrAllocatePrefixEntry(aConfig.GetPrefix());
+    VerifyOrExit(entry != nullptr, error = kErrorNoBufs);
+
     entry->Publish(aConfig);
 
 exit:
@@ -142,23 +149,26 @@
     return error;
 }
 
-Error Publisher::AllocatePrefixEntry(const Ip6::Prefix &aPrefix, PrefixEntry *&aEntry)
+Publisher::PrefixEntry *Publisher::FindOrAllocatePrefixEntry(const Ip6::Prefix &aPrefix)
 {
-    Error error = kErrorNoBufs;
+    // Returns a matching prefix entry if found, otherwise tries
+    // to allocate a new entry.
 
-    VerifyOrExit(FindMatchingPrefixEntry(aPrefix) == nullptr, error = kErrorAlready);
+    PrefixEntry *prefixEntry = FindMatchingPrefixEntry(aPrefix);
+
+    VerifyOrExit(prefixEntry == nullptr);
 
     for (PrefixEntry &entry : mPrefixEntries)
     {
         if (!entry.IsInUse())
         {
-            aEntry = &entry;
-            ExitNow(error = kErrorNone);
+            prefixEntry = &entry;
+            ExitNow();
         }
     }
 
 exit:
-    return error;
+    return prefixEntry;
 }
 
 Publisher::PrefixEntry *Publisher::FindMatchingPrefixEntry(const Ip6::Prefix &aPrefix)
@@ -184,7 +194,7 @@
 
 bool Publisher::IsAPrefixEntry(const Entry &aEntry) const
 {
-    return (&mPrefixEntries[0] <= &aEntry) && (&aEntry < OT_ARRAY_END(mPrefixEntries));
+    return (&mPrefixEntries[0] <= &aEntry) && (&aEntry < GetArrayEnd(mPrefixEntries));
 }
 
 void Publisher::NotifyPrefixEntryChange(Event aEvent, const Ip6::Prefix &aPrefix) const
@@ -199,15 +209,8 @@
 
 void Publisher::HandleNotifierEvents(Events aEvents)
 {
-    OT_UNUSED_VARIABLE(aEvents);
-
-    bool registerWithLeader = false;
-
 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-    if (mDnsSrpServiceEntry.HandleNotifierEvents(aEvents))
-    {
-        registerWithLeader = true;
-    }
+    mDnsSrpServiceEntry.HandleNotifierEvents(aEvents);
 #endif
 
 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
@@ -216,11 +219,6 @@
         entry.HandleNotifierEvents(aEvents);
     }
 #endif
-
-    if (registerWithLeader)
-    {
-        Get<Notifier>().HandleServerDataUpdated();
-    }
 }
 
 void Publisher::HandleTimer(Timer &aTimer)
@@ -230,29 +228,16 @@
 
 void Publisher::HandleTimer(void)
 {
-    bool registerWithLeader = false;
-
 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-    if (mDnsSrpServiceEntry.HandleTimer())
-    {
-        registerWithLeader = true;
-    }
+    mDnsSrpServiceEntry.HandleTimer();
 #endif
 
 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
     for (PrefixEntry &entry : mPrefixEntries)
     {
-        if (entry.HandleTimer())
-        {
-            registerWithLeader = true;
-        }
+        entry.HandleTimer();
     }
 #endif
-
-    if (registerWithLeader)
-    {
-        Get<Notifier>().HandleServerDataUpdated();
-    }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -262,8 +247,8 @@
 {
     VerifyOrExit(mState != aState);
 
-    otLogInfoNetData("Publisher: %s - State: %s -> %s", ToString(/* aIncludeState */ false).AsCString(),
-                     StateToString(mState), StateToString(aState));
+    LogInfo("%s - State: %s -> %s", ToString(/* aIncludeState */ false).AsCString(), StateToString(mState),
+            StateToString(aState));
     mState = aState;
 
 exit:
@@ -290,8 +275,8 @@
     // entries we aim to have in the Network Data to decide whether or
     // not to take any action (add or remove our entry).
 
-    otLogInfoNetData("Publisher: %s in netdata - total:%d, preferred:%d, desired:%d", ToString().AsCString(),
-                     aNumEntries, aNumPreferredEntries, aDesiredNumEntries);
+    LogInfo("%s in netdata - total:%d, preferred:%d, desired:%d", ToString().AsCString(), aNumEntries,
+            aNumPreferredEntries, aDesiredNumEntries);
 
     switch (GetState())
     {
@@ -361,22 +346,25 @@
     }
 }
 
-bool Publisher::Entry::HandleTimer(void)
+void Publisher::Entry::HandleTimer(void)
 {
-    bool registerWithLeader = false;
-
     // Timer is used to delay adding/removing the entry. If we have
     // reached `mUpdateTime` add or remove the entry. Otherwise,
     // restart the timer (note that timer can be shared between
-    // different published entries). This method returns a `bool`
-    // indicating whether or not anything in local Network Data got
-    // changed so to notify the leader and register the changes.
+    // different published entries).
 
     VerifyOrExit((GetState() == kAdding) || (GetState() == kRemoving));
 
     if (mUpdateTime <= TimerMilli::GetNow())
     {
-        registerWithLeader = (GetState() == kAdding) ? Add() : Remove(/* aNextState */ kToAdd);
+        if (GetState() == kAdding)
+        {
+            Add();
+        }
+        else
+        {
+            Remove(/* aNextState */ kToAdd);
+        }
     }
     else
     {
@@ -384,55 +372,41 @@
     }
 
 exit:
-    return registerWithLeader;
+    return;
 }
 
-bool Publisher::Entry::Add(void)
+void Publisher::Entry::Add(void)
 {
-    bool registerWithLeader = false;
-
 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
     if (Get<Publisher>().IsADnsSrpServiceEntry(*this))
     {
-        registerWithLeader = static_cast<DnsSrpServiceEntry *>(this)->Add();
-        ExitNow();
+        static_cast<DnsSrpServiceEntry *>(this)->Add();
     }
 #endif
 
 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
     if (Get<Publisher>().IsAPrefixEntry(*this))
     {
-        registerWithLeader = static_cast<PrefixEntry *>(this)->Add();
-        ExitNow();
+        static_cast<PrefixEntry *>(this)->Add();
     }
 #endif
-
-exit:
-    return registerWithLeader;
 }
 
-bool Publisher::Entry::Remove(State aNextState)
+void Publisher::Entry::Remove(State aNextState)
 {
-    bool registerWithLeader = false;
-
 #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
     if (Get<Publisher>().IsADnsSrpServiceEntry(*this))
     {
-        registerWithLeader = static_cast<DnsSrpServiceEntry *>(this)->Remove(aNextState);
-        ExitNow();
+        static_cast<DnsSrpServiceEntry *>(this)->Remove(aNextState);
     }
 #endif
 
 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
     if (Get<Publisher>().IsAPrefixEntry(*this))
     {
-        registerWithLeader = static_cast<PrefixEntry *>(this)->Remove(aNextState);
-        ExitNow();
+        static_cast<PrefixEntry *>(this)->Remove(aNextState);
     }
 #endif
-
-exit:
-    return registerWithLeader;
 }
 
 Publisher::Entry::InfoString Publisher::Entry::ToString(bool aIncludeState) const
@@ -479,7 +453,7 @@
 
 void Publisher::Entry::LogUpdateTime(void) const
 {
-    otLogInfoNetData("Publisher: %s - update in %u msec", ToString().AsCString(), mUpdateTime - TimerMilli::GetNow());
+    LogInfo("%s - update in %u msec", ToString().AsCString(), mUpdateTime - TimerMilli::GetNow());
 }
 
 const char *Publisher::Entry::StateToString(State aState)
@@ -521,36 +495,33 @@
 
 void Publisher::DnsSrpServiceEntry::PublishAnycast(uint8_t aSequenceNumber)
 {
-    otLogInfoNetData("Publisher: Publishing DNS/SRP service anycast (seq-num:%d)", aSequenceNumber);
+    LogInfo("Publishing DNS/SRP service anycast (seq-num:%d)", aSequenceNumber);
     Publish(Info::InfoAnycast(aSequenceNumber));
 }
 
 void Publisher::DnsSrpServiceEntry::PublishUnicast(const Ip6::Address &aAddress, uint16_t aPort)
 {
-    otLogInfoNetData("Publisher: Publishing DNS/SRP service unicast (%s, port:%d)", aAddress.ToString().AsCString(),
-                     aPort);
+    LogInfo("Publishing DNS/SRP service unicast (%s, port:%d)", aAddress.ToString().AsCString(), aPort);
     Publish(Info::InfoUnicast(kTypeUnicast, aAddress, aPort));
 }
 
 void Publisher::DnsSrpServiceEntry::PublishUnicast(uint16_t aPort)
 {
-    otLogInfoNetData("Publisher: Publishing DNS/SRP service unicast (ml-eid, port:%d)", aPort);
+    LogInfo("Publishing DNS/SRP service unicast (ml-eid, port:%d)", aPort);
     Publish(Info::InfoUnicast(kTypeUnicastMeshLocalEid, Get<Mle::Mle>().GetMeshLocal64(), aPort));
 }
 
 void Publisher::DnsSrpServiceEntry::Publish(const Info &aInfo)
 {
-    bool registerWithLeader = false;
-
     if (GetState() != kNoEntry)
     {
         if (aInfo == mInfo)
         {
-            otLogInfoNetData("Publisher: %s is already being published", ToString().AsCString());
+            LogInfo("%s is already being published", ToString().AsCString());
             ExitNow();
         }
 
-        registerWithLeader = Remove(/* aNextState */ kNoEntry);
+        Remove(/* aNextState */ kNoEntry);
     }
 
     mInfo = aInfo;
@@ -558,33 +529,19 @@
 
     Process();
 
-    if (registerWithLeader)
-    {
-        Get<Notifier>().HandleServerDataUpdated();
-    }
-
 exit:
     return;
 }
 
 void Publisher::DnsSrpServiceEntry::Unpublish(void)
 {
-    bool registerWithLeader;
+    LogInfo("Unpublishing DNS/SRP service");
 
-    otLogInfoNetData("Publisher: Unpublishing DNS/SRP service");
-
-    registerWithLeader = Remove(/* aNextState */ kNoEntry);
-
-    if (registerWithLeader)
-    {
-        Get<Notifier>().HandleServerDataUpdated();
-    }
+    Remove(/* aNextState */ kNoEntry);
 }
 
-bool Publisher::DnsSrpServiceEntry::HandleNotifierEvents(Events aEvents)
+void Publisher::DnsSrpServiceEntry::HandleNotifierEvents(Events aEvents)
 {
-    bool registerWithLeader = false;
-
     if ((GetType() == kTypeUnicastMeshLocalEid) && aEvents.Contains(kEventThreadMeshLocalAddrChanged))
     {
         mInfo.SetAddress(Get<Mle::Mle>().GetMeshLocal64());
@@ -597,7 +554,7 @@
 
             Remove(/* aNextState */ kAdding);
             Add();
-            registerWithLeader = true;
+            Get<Notifier>().HandleServerDataUpdated();
         }
     }
 
@@ -605,16 +562,12 @@
     {
         Process();
     }
-
-    return registerWithLeader;
 }
 
-bool Publisher::DnsSrpServiceEntry::Add(void)
+void Publisher::DnsSrpServiceEntry::Add(void)
 {
     // Adds the service entry to the network data.
 
-    bool registerWithLeader = false;
-
     switch (GetType())
     {
     case kTypeAnycast:
@@ -633,20 +586,18 @@
         break;
     }
 
-    registerWithLeader = true;
+    Get<Notifier>().HandleServerDataUpdated();
     SetState(kAdded);
     Notify(kEventEntryAdded);
 
 exit:
-    return registerWithLeader;
+    return;
 }
 
-bool Publisher::DnsSrpServiceEntry::Remove(State aNextState)
+void Publisher::DnsSrpServiceEntry::Remove(State aNextState)
 {
     // Removes the service entry from network data (if it was added).
 
-    bool registerWithLeader = false;
-
     VerifyOrExit((GetState() == kAdded) || (GetState() == kRemoving));
 
     switch (GetType())
@@ -666,12 +617,11 @@
         break;
     }
 
-    registerWithLeader = true;
+    Get<Notifier>().HandleServerDataUpdated();
     Notify(kEventEntryRemoved);
 
 exit:
     SetState(aNextState);
-    return registerWithLeader;
 }
 
 void Publisher::DnsSrpServiceEntry::Notify(Event aEvent) const
@@ -836,47 +786,67 @@
 
 #endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
 
+#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
+
 //---------------------------------------------------------------------------------------------------------------------
 // Publisher::PrefixEntry
 
 void Publisher::PrefixEntry::Publish(const OnMeshPrefixConfig &aConfig)
 {
-    otLogInfoNetData("Publisher: Publishing OnMeshPrefix %s", aConfig.GetPrefix().ToString().AsCString());
+    LogInfo("Publishing OnMeshPrefix %s", aConfig.GetPrefix().ToString().AsCString());
 
-    mType   = kTypeOnMeshPrefix;
-    mPrefix = aConfig.GetPrefix();
-    mFlags  = aConfig.ConvertToTlvFlags();
-
-    SetState(kToAdd);
-
-    Process();
+    Publish(aConfig.GetPrefix(), aConfig.ConvertToTlvFlags(), kTypeOnMeshPrefix);
 }
 
 void Publisher::PrefixEntry::Publish(const ExternalRouteConfig &aConfig)
 {
-    otLogInfoNetData("Publisher: Publishing ExternalRoute %s", aConfig.GetPrefix().ToString().AsCString());
+    LogInfo("Publishing ExternalRoute %s", aConfig.GetPrefix().ToString().AsCString());
 
-    mType   = kTypeExternalRoute;
-    mPrefix = aConfig.GetPrefix();
-    mFlags  = aConfig.ConvertToTlvFlags();
+    Publish(aConfig.GetPrefix(), aConfig.ConvertToTlvFlags(), kTypeExternalRoute);
+}
+
+void Publisher::PrefixEntry::Publish(const Ip6::Prefix &aPrefix, uint16_t aNewFlags, Type aNewType)
+{
+    if (GetState() != kNoEntry)
+    {
+        // If this is an existing entry, first we check that there is
+        // a change in either type or flags. We remove the old entry
+        // from Network Data if it was added. If the only change is
+        // to flags (e.g., change to the preference level) and the
+        // entry was previously added in Network Data, we re-add it
+        // with the new flags. This ensures that changes to flags are
+        // immediately reflected in the Network Data.
+
+        State oldState = GetState();
+
+        VerifyOrExit((mType != aNewType) || (mFlags != aNewFlags));
+
+        Remove(/* aNextState */ kNoEntry);
+
+        if ((mType == aNewType) && ((oldState == kAdded) || (oldState == kRemoving)))
+        {
+            mFlags = aNewFlags;
+            Add();
+        }
+    }
+
+    VerifyOrExit(GetState() == kNoEntry);
+
+    mType   = aNewType;
+    mPrefix = aPrefix;
+    mFlags  = aNewFlags;
 
     SetState(kToAdd);
 
+exit:
     Process();
 }
 
 void Publisher::PrefixEntry::Unpublish(void)
 {
-    bool registerWithLeader = false;
+    LogInfo("Unpublishing %s", mPrefix.ToString().AsCString());
 
-    otLogInfoNetData("Publisher: Unpublishing %s", mPrefix.ToString().AsCString());
-
-    registerWithLeader = Remove(/* aNextState */ kNoEntry);
-
-    if (registerWithLeader)
-    {
-        Get<Notifier>().HandleServerDataUpdated();
-    }
+    Remove(/* aNextState */ kNoEntry);
 }
 
 void Publisher::PrefixEntry::HandleNotifierEvents(Events aEvents)
@@ -887,12 +857,10 @@
     }
 }
 
-bool Publisher::PrefixEntry::Add(void)
+void Publisher::PrefixEntry::Add(void)
 {
     // Adds the prefix entry to the network data.
 
-    bool registerWithLeader = false;
-
     switch (mType)
     {
     case kTypeOnMeshPrefix:
@@ -904,12 +872,12 @@
         break;
     }
 
-    registerWithLeader = true;
+    Get<Notifier>().HandleServerDataUpdated();
     SetState(kAdded);
     Get<Publisher>().NotifyPrefixEntryChange(kEventEntryAdded, mPrefix);
 
 exit:
-    return registerWithLeader;
+    return;
 }
 
 Error Publisher::PrefixEntry::AddOnMeshPrefix(void)
@@ -934,12 +902,10 @@
     return Get<Local>().AddHasRoutePrefix(config);
 }
 
-bool Publisher::PrefixEntry::Remove(State aNextState)
+void Publisher::PrefixEntry::Remove(State aNextState)
 {
     // Remove the prefix entry from the network data.
 
-    bool registerWithLeader = false;
-
     VerifyOrExit((GetState() == kAdded) || (GetState() == kRemoving));
 
     switch (mType)
@@ -953,12 +919,11 @@
         break;
     }
 
-    registerWithLeader = true;
+    Get<Notifier>().HandleServerDataUpdated();
     Get<Publisher>().NotifyPrefixEntryChange(kEventEntryRemoved, mPrefix);
 
 exit:
     SetState(aNextState);
-    return registerWithLeader;
 }
 
 void Publisher::PrefixEntry::Process(void)
@@ -1089,6 +1054,8 @@
     return;
 }
 
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
+
 } // namespace NetworkData
 } // namespace ot
 
diff --git a/src/core/thread/network_data_publisher.hpp b/src/core/thread/network_data_publisher.hpp
index 26cc919..7d11790 100644
--- a/src/core/thread/network_data_publisher.hpp
+++ b/src/core/thread/network_data_publisher.hpp
@@ -43,6 +43,12 @@
             "or OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE"
 #endif
 
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && (OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES < \
+                                                (OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES + 4))
+#error "OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES needs to support more entries when "\
+       "OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE is enabled to accommodate for max on-link prefixes"
+#endif
+
 #include <openthread/netdata_publisher.h>
 
 #include "common/clearable.hpp"
@@ -165,7 +171,7 @@
      * This method indicates whether or not currently the "DNS/SRP Service" entry is added to the Thread Network Data.
      *
      * @retval TRUE    The published DNS/SRP Service entry is added to the Thread Network Data.
-     * @retval FLASE   The entry is not added to Thread Network Data or there is no entry to publish.
+     * @retval FALSE   The entry is not added to Thread Network Data or there is no entry to publish.
      *
      */
     bool IsDnsSrpServiceAdded(void) const { return mDnsSrpServiceEntry.IsAdded(); }
@@ -208,6 +214,13 @@
      *
      * Only stable entries can be published (i.e.,`aConfig.mStable` MUST be `true`).
      *
+     * A subsequent call to this method will replace a previous request for the same prefix. In particular if the
+     * new call only changes the flags (e.g., preference level) and the prefix is already added in the Network Data,
+     * the change to flags is immediately reflected in the Network Data. This ensures that existing entries in the
+     * Network Data are not abruptly removed. Note that a change in the preference level can potentially later cause
+     * the entry to be removed from the Network Data after determining there are other nodes that are publishing the
+     * same prefix with the same or higher preference.
+     *
      * @param[in] aConfig         The on-mesh prefix config to publish.
      *
      * @retval kErrorNone         The on-mesh prefix is published successfully.
@@ -226,11 +239,17 @@
      *
      * Only stable entries can be published (i.e.,`aConfig.mStable` MUST be `true`).
      *
+     * A subsequent call to this method will replace a previous request for the same prefix. In particular if the
+     * new call only changes the flags (e.g., preference level) and the prefix is already added in the Network Data,
+     * the change to flags is immediately reflected in the Network Data. This ensures that existing entries in the
+     * Network Data are not abruptly removed. Note that a change in the preference level can potentially later cause
+     * the entry to be removed from the Network Data after determining there are other nodes that are publishing the
+     * same prefix with the same or higher preference.
+     *
      * @param[in] aConfig         The external route config to publish.
      *
      * @retval kErrorNone         The external route is published successfully.
      * @retval kErrorInvalidArgs  The @p aConfig is not valid (bad prefix, invalid flag combinations, or not stable).
-     * @retval kErrorAlready      An entry with the same prefix is already in the published list.
      * @retval kErrorNoBufs       Could not allocate an entry for the new request. Publisher supports a limited number
      *                            of entries (shared between on-mesh prefix and external route) determined by config
      *                            `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES`.
@@ -246,7 +265,7 @@
      * @param[in] aPrefix   The prefix to check.
      *
      * @retval TRUE    The published prefix entry is added to the Thread Network Data.
-     * @retval FLASE   The entry is not added to Thread Network Data or there is no matching entry to publish.
+     * @retval FALSE   The entry is not added to Thread Network Data or there is no matching entry to publish.
      *
      */
     bool IsPrefixAdded(const Ip6::Prefix &aPrefix) const;
@@ -297,15 +316,15 @@
         const TimeMilli &GetUpdateTime(void) const { return mUpdateTime; }
         bool             IsPreferred(uint16_t aRloc16) const;
         void             UpdateState(uint8_t aNumEntries, uint8_t aNumPreferredEntries, uint8_t aDesiredNumEntries);
-        bool             HandleTimer(void);
+        void             HandleTimer(void);
         InfoString       ToString(bool aIncludeState = true) const;
 
     public:
         bool IsAdded(void) const { return (mState == kAdded); }
 
     private:
-        bool               Add(void);
-        bool               Remove(State aNextState);
+        void               Add(void);
+        void               Remove(State aNextState);
         void               LogUpdateTime(void) const;
         static const char *StateToString(State aState);
 
@@ -325,8 +344,8 @@
         void PublishUnicast(const Ip6::Address &aAddress, uint16_t aPort);
         void PublishUnicast(uint16_t aPort);
         void Unpublish(void);
-        bool HandleTimer(void) { return Entry::HandleTimer(); }
-        bool HandleNotifierEvents(Events aEvents);
+        void HandleTimer(void) { Entry::HandleTimer(); }
+        void HandleNotifierEvents(Events aEvents);
 
     private:
         static constexpr uint8_t kDesiredNumAnycast =
@@ -368,8 +387,8 @@
 
         Type GetType(void) const { return mInfo.GetType(); }
         void Publish(const Info &aInfo);
-        bool Add(void);
-        bool Remove(State aNextState);
+        void Add(void);
+        void Remove(State aNextState);
         void Notify(Event aEvent) const;
         void Process(void);
         void CountAnycastEntries(uint8_t &aNumEntries, uint8_t &aNumPreferredEntries) const;
@@ -396,7 +415,7 @@
         void Publish(const OnMeshPrefixConfig &aConfig);
         void Publish(const ExternalRouteConfig &aConfig);
         void Unpublish(void);
-        bool HandleTimer(void) { return Entry::HandleTimer(); }
+        void HandleTimer(void) { Entry::HandleTimer(); }
         void HandleNotifierEvents(Events aEvents);
 
     private:
@@ -412,10 +431,11 @@
             kTypeExternalRoute,
         };
 
-        bool  Add(void);
+        void  Publish(const Ip6::Prefix &aPrefix, uint16_t aNewFlags, Type aNewType);
+        void  Add(void);
         Error AddOnMeshPrefix(void);
         Error AddExternalRoute(void);
-        bool  Remove(State aNextState);
+        void  Remove(State aNextState);
         void  Process(void);
         void  CountOnMeshPrefixEntries(uint8_t &aNumEntries, uint8_t &aNumPreferredEntries) const;
         void  CountExternalRouteEntries(uint8_t &aNumEntries, uint8_t &aNumPreferredEntries) const;
@@ -431,7 +451,7 @@
 #endif
 
 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
-    Error              AllocatePrefixEntry(const Ip6::Prefix &aPrefix, PrefixEntry *&aEntry);
+    PrefixEntry *      FindOrAllocatePrefixEntry(const Ip6::Prefix &aPrefix);
     PrefixEntry *      FindMatchingPrefixEntry(const Ip6::Prefix &aPrefix);
     const PrefixEntry *FindMatchingPrefixEntry(const Ip6::Prefix &aPrefix) const;
     bool               IsAPrefixEntry(const Entry &aEntry) const;
diff --git a/src/core/thread/network_data_service.cpp b/src/core/thread/network_data_service.cpp
index 878c027..618812b 100644
--- a/src/core/thread/network_data_service.cpp
+++ b/src/core/thread/network_data_service.cpp
@@ -195,20 +195,68 @@
 
 Error Manager::FindPreferredDnsSrpAnycastInfo(DnsSrpAnycast::Info &aInfo) const
 {
+    Error               error = kErrorNotFound;
     Iterator            iterator;
     DnsSrpAnycast::Info info;
-    bool                found = false;
+    DnsSrpAnycast::Info maxNumericalSeqNumInfo;
+
+    // Determine the entry with largest seq number in two ways:
+    // `aInfo` will track the largest using serial number arithmetic
+    // comparison, while `maxNumericalSeqNumInfo` tracks the largest
+    // using normal numerical comparison.
 
     while (GetNextDnsSrpAnycastInfo(iterator, info) == kErrorNone)
     {
-        if (!found || info.IsSequenceNumberAheadOf(aInfo))
+        if (error == kErrorNotFound)
+        {
+            aInfo                  = info;
+            maxNumericalSeqNumInfo = info;
+            error                  = kErrorNone;
+            continue;
+        }
+
+        if (SerialNumber::IsGreater(info.mSequenceNumber, aInfo.mSequenceNumber))
         {
             aInfo = info;
-            found = true;
+        }
+
+        if (info.mSequenceNumber > maxNumericalSeqNumInfo.mSequenceNumber)
+        {
+            maxNumericalSeqNumInfo = info;
         }
     }
 
-    return found ? kErrorNone : kErrorNotFound;
+    SuccessOrExit(error);
+
+    // Check that the largest seq number using serial number arithmetic is
+    // well-defined (i.e., the seq number is larger than all other seq
+    // numbers values). If it is not, we prefer `maxNumericalSeqNumInfo`.
+
+    iterator.Reset();
+
+    while (GetNextDnsSrpAnycastInfo(iterator, info) == kErrorNone)
+    {
+        constexpr uint8_t kMidValue = (NumericLimits<uint8_t>::kMax / 2) + 1;
+        uint8_t           seqNumber = info.mSequenceNumber;
+        uint8_t           diff;
+
+        if (seqNumber == aInfo.mSequenceNumber)
+        {
+            continue;
+        }
+
+        diff = seqNumber - aInfo.mSequenceNumber;
+
+        if ((diff == kMidValue) || !SerialNumber::IsGreater(aInfo.mSequenceNumber, seqNumber))
+        {
+            aInfo = maxNumericalSeqNumInfo;
+
+            break;
+        }
+    }
+
+exit:
+    return error;
 }
 
 Error Manager::GetNextDnsSrpUnicastInfo(Iterator &aIterator, DnsSrpUnicast::Info &aInfo) const
@@ -239,6 +287,7 @@
 
                 aInfo.mSockAddr.SetAddress(serverData->GetAddress());
                 aInfo.mSockAddr.SetPort(serverData->GetPort());
+                aInfo.mOrigin = DnsSrpUnicast::kFromServerData;
                 ExitNow();
             }
 
@@ -250,6 +299,7 @@
                 aInfo.mSockAddr.GetAddress().SetToRoutingLocator(Get<Mle::Mle>().GetMeshLocalPrefix(),
                                                                  aIterator.mServerSubTlv->GetServer16());
                 aInfo.mSockAddr.SetPort(Encoding::BigEndian::ReadUint16(data.GetBytes()));
+                aInfo.mOrigin = DnsSrpUnicast::kFromServerData;
                 ExitNow();
             }
         }
@@ -271,6 +321,7 @@
             dnsServiceData = reinterpret_cast<const DnsSrpUnicast::ServiceData *>(serviceData.GetBytes());
             aInfo.mSockAddr.SetAddress(dnsServiceData->GetAddress());
             aInfo.mSockAddr.SetPort(dnsServiceData->GetPort());
+            aInfo.mOrigin = DnsSrpUnicast::kFromServiceData;
             ExitNow();
         }
 
diff --git a/src/core/thread/network_data_service.hpp b/src/core/thread/network_data_service.hpp
index 954437e..bd41dc7 100644
--- a/src/core/thread/network_data_service.hpp
+++ b/src/core/thread/network_data_service.hpp
@@ -42,6 +42,7 @@
 #include "common/encoding.hpp"
 #include "common/locator.hpp"
 #include "common/non_copyable.hpp"
+#include "common/serial_number.hpp"
 #include "net/socket.hpp"
 #include "thread/network_data_tlvs.hpp"
 
@@ -173,25 +174,6 @@
      */
     struct Info
     {
-        /**
-         * This method indicates whether or not the sequence number from the current `Info` is ahead of (more recent
-         * than) the sequence number from another `Info`.
-         *
-         * The sequence numbers comparison follows the Serial Number Arithmetic logic from RFC-1982. It is semantically
-         * equivalent to `GetSequenceNumber() > aOther.GetSequenceNumber()` while handling roll-over of the `uint8_t`
-         * values.
-         *
-         * @param[in] aOther   The other `Info` to compare with.
-         *
-         * @retval TRUE  The `Info` is ahead of @p aOther.
-         * @retval FALSE The `Info` is not ahead of @p aOther.
-         *
-         */
-        bool IsSequenceNumberAheadOf(const Info &aOther) const
-        {
-            return (((aOther.mSequenceNumber - mSequenceNumber) & (1U << 7)) != 0);
-        }
-
         Ip6::Address mAnycastAddress; ///< The anycast address associated with the DNS/SRP servers.
         uint8_t      mSequenceNumber; ///< Sequence number used to notify SRP client if they need to re-register.
     };
@@ -259,12 +241,23 @@
     static const uint8_t kServiceData = kServiceNumber;
 
     /**
+     * This enumeration represents the origin a `DnsSrpUnicast` entry.
+     *
+     */
+    enum Origin : uint8_t
+    {
+        kFromServiceData, ///< Socket address is from service data.
+        kFromServerData,  ///< Socket address is from server data.
+    };
+
+    /**
      * This structure represents information about an DNS/SRP server parsed from related Network Data service entries.
      *
      */
     struct Info
     {
         Ip6::SockAddr mSockAddr; ///< The socket address (IPv6 address and port) of the DNS/SRP server.
+        Origin        mOrigin;   ///< The origin of the socket address (whether from service or server data).
     };
 
     /**
@@ -559,8 +552,8 @@
      * To get the first entry, @p aIterator should be cleared (e.g., a new instance of `Iterator` or calling `Clear()`
      * method).
      *
-     * @param[inout] aIterator     A reference to an iterator.
-     * @param[out]   aInfo         A reference to `DnsSrpAnycast::Info` to return the info.
+     * @param[in,out] aIterator    A reference to an iterator.
+     * @param[out]    aInfo        A reference to `DnsSrpAnycast::Info` to return the info.
      *
      * @retval kErrorNone       Successfully got the next info. @p aInfo and @p aIterator are updated.
      * @retval kErrorNotFound   No more matching entries in the Network Data.
@@ -589,8 +582,8 @@
      * To get the first entry @p aIterator should be cleared (e.g., a new instance of `Iterator` or calling `Clear()`
      * method).
      *
-     * @param[inout] aIterator     A reference to an iterator.
-     * @param[out]   aInfo         A reference to `DnsSrpUnicast::Info` to return the info.
+     * @param[in,out] aIterator    A reference to an iterator.
+     * @param[out]    aInfo        A reference to `DnsSrpUnicast::Info` to return the info.
      *
      * @retval kErrorNone       Successfully got the next info. @p aInfo and @p aIterator are updated.
      * @retval kErrorNotFound   No more matching entries in the Network Data.
diff --git a/src/core/thread/network_data_tlvs.hpp b/src/core/thread/network_data_tlvs.hpp
index 6561dcf..48568c7 100644
--- a/src/core/thread/network_data_tlvs.hpp
+++ b/src/core/thread/network_data_tlvs.hpp
@@ -61,6 +61,68 @@
  *
  */
 
+class NetworkDataTlv;
+
+/**
+ * This template method casts a `NetworkDataTlv` pointer to a given subclass `TlvType` pointer.
+ *
+ * @tparam TlvType  The TLV type to cast into. MUST be a subclass of `NetworkDataTlv`.
+ *
+ * @param[in] aTlv   A pointer to a `NetworkDataTlv` to convert/cast to a `TlvType`.
+ *
+ * @returns A `TlvType` pointer to `aTlv`.
+ *
+ */
+template <class TlvType> TlvType *As(NetworkDataTlv *aTlv)
+{
+    return static_cast<TlvType *>(aTlv);
+}
+
+/**
+ * This template method casts a `NetworkDataTlv` pointer to a given subclass `TlvType` pointer.
+ *
+ * @tparam TlvType  The TLV type to cast into. MUST be a subclass of `NetworkDataTlv`.
+ *
+ * @param[in] aTlv   A pointer to a `NetworkDataTlv` to convert/cast to a `TlvType`.
+ *
+ * @returns A `TlvType` pointer to `aTlv`.
+ *
+ */
+template <class TlvType> const TlvType *As(const NetworkDataTlv *aTlv)
+{
+    return static_cast<const TlvType *>(aTlv);
+}
+
+/**
+ * This template method casts a `NetworkDataTlv` reference to a given subclass `TlvType` reference.
+ *
+ * @tparam TlvType  The TLV type to cast into. MUST be a subclass of `NetworkDataTlv`.
+ *
+ * @param[in] aTlv   A reference to a `NetworkDataTlv` to convert/cast to a `TlvType`.
+ *
+ * @returns A `TlvType` reference to `aTlv`.
+ *
+ */
+template <class TlvType> TlvType &As(NetworkDataTlv &aTlv)
+{
+    return static_cast<TlvType &>(aTlv);
+}
+
+/**
+ * This template method casts a `NetworkDataTlv` reference to a given subclass `TlvType` reference.
+ *
+ * @tparam TlvType  The TLV type to cast into. MUST be a subclass of `NetworkDataTlv`.
+ *
+ * @param[in] aTlv   A reference to a `NetworkDataTlv` to convert/cast to a `TlvType`.
+ *
+ * @returns A `TlvType` reference to `aTlv`.
+ *
+ */
+template <class TlvType> const TlvType &As(const NetworkDataTlv &aTlv)
+{
+    return static_cast<const TlvType &>(aTlv);
+}
+
 /**
  * This class implements Thread Network Data TLV generation and parsing.
  *
@@ -217,7 +279,7 @@
      * @param[in]  aEnd    A pointer to the end of the sequence of TLVs.
      * @param[in]  aType   The TLV type to find.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     static NetworkDataTlv *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, Type aType)
@@ -232,7 +294,7 @@
      * @param[in]  aEnd    A pointer to the end of the sequence of TLVs.
      * @param[in]  aType   The TLV type to find.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     static const NetworkDataTlv *Find(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd, Type aType);
@@ -245,12 +307,12 @@
      * @param[in]  aStart  A pointer to the start of the sequence of TLVs to search within.
      * @param[in]  aEnd    A pointer to the end of the sequence of TLVs.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     template <typename TlvType> static TlvType *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd)
     {
-        return static_cast<TlvType *>(Find(aStart, aEnd, TlvType::kType));
+        return As<TlvType>(Find(aStart, aEnd, TlvType::kType));
     }
 
     /**
@@ -261,12 +323,12 @@
      * @param[in]  aStart  A pointer to the start of the sequence of TLVs to search within.
      * @param[in]  aEnd    A pointer to the end of the sequence of TLVs.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     template <typename TlvType> static const TlvType *Find(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd)
     {
-        return static_cast<const TlvType *>(Find(aStart, aEnd, TlvType::kType));
+        return As<TlvType>(Find(aStart, aEnd, TlvType::kType));
     }
 
     /**
@@ -278,7 +340,7 @@
      * @param[in]  aType   The TLV type to find.
      * @param[in]  aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     static NetworkDataTlv *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, Type aType, bool aStable)
@@ -295,7 +357,7 @@
      * @param[in]  aType   The TLV type to find.
      * @param[in]  aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     static const NetworkDataTlv *Find(const NetworkDataTlv *aStart,
@@ -313,12 +375,12 @@
      * @param[in]  aEnd    A pointer to the end of the sequence of TLVs.
      * @param[in]  aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     template <typename TlvType> static TlvType *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, bool aStable)
     {
-        return static_cast<TlvType *>(Find(aStart, aEnd, TlvType::kType, aStable));
+        return As<TlvType>(Find(aStart, aEnd, TlvType::kType, aStable));
     }
 
     /**
@@ -331,13 +393,13 @@
      * @param[in]  aEnd    A pointer to the end of the sequence of TLVs.
      * @param[in]  aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     template <typename TlvType>
     static const TlvType *Find(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd, bool aStable)
     {
-        return static_cast<const TlvType *>(Find(aStart, aEnd, TlvType::kType, aStable));
+        return As<TlvType>(Find(aStart, aEnd, TlvType::kType, aStable));
     }
 
 private:
@@ -733,12 +795,12 @@
      *
      * @tparam     SubTlvType    The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     template <typename SubTlvType> SubTlvType *FindSubTlv(void)
     {
-        return static_cast<SubTlvType *>(FindSubTlv(SubTlvType::kType));
+        return As<SubTlvType>(FindSubTlv(SubTlvType::kType));
     }
 
     /**
@@ -746,12 +808,12 @@
      *
      * @tparam     SubTlvType   The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     template <typename SubTlvType> const SubTlvType *FindSubTlv(void) const
     {
-        return static_cast<const SubTlvType *>(FindSubTlv(SubTlvType::kType));
+        return As<SubTlvType>(FindSubTlv(SubTlvType::kType));
     }
 
     /**
@@ -761,12 +823,12 @@
      *
      * @param[in]  aStable       TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     template <typename SubTlvType> SubTlvType *FindSubTlv(bool aStable)
     {
-        return static_cast<SubTlvType *>(FindSubTlv(static_cast<Type>(SubTlvType::kType), aStable));
+        return As<SubTlvType>(FindSubTlv(static_cast<Type>(SubTlvType::kType), aStable));
     }
 
     /**
@@ -776,12 +838,12 @@
      *
      * @param[in]  aStable      TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     template <typename SubTlvType> const SubTlvType *FindSubTlv(bool aStable) const
     {
-        return static_cast<const SubTlvType *>(FindSubTlv(static_cast<Type>(SubTlvType::kType), aStable));
+        return As<SubTlvType>(FindSubTlv(static_cast<Type>(SubTlvType::kType), aStable));
     }
 
     /**
@@ -789,7 +851,7 @@
      *
      * @param[in]  aType        The sub-TLV type to search for.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     NetworkDataTlv *FindSubTlv(Type aType) { return AsNonConst(AsConst(this)->FindSubTlv(aType)); }
@@ -799,7 +861,7 @@
      *
      * @param[in]  aType        The sub-TLV type to search for.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     const NetworkDataTlv *FindSubTlv(Type aType) const;
@@ -810,7 +872,7 @@
      * @param[in]  aType        The sub-TLV type to search for.
      * @param[in]  aStable      TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     NetworkDataTlv *FindSubTlv(Type aType, bool aStable)
@@ -824,7 +886,7 @@
      * @param[in]  aType        The sub-TLV type to search for.
      * @param[in]  aStable      TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
      *
-     * @returns A pointer to the TLV if found, or nullptr if not found.
+     * @returns A pointer to the TLV if found, or `nullptr` if not found.
      *
      */
     const NetworkDataTlv *FindSubTlv(Type aType, bool aStable) const;
@@ -1152,17 +1214,17 @@
     /**
      * This method initializes the Context TLV.
      *
-     * @param[in]  aConextId   The Context ID value.
-     * @param[in]  aLength     The Context Length value.
+     * @param[in]  aContextId      The Context ID value.
+     * @param[in]  aContextLength  The Context Length value.
      *
      */
-    void Init(uint8_t aContextId, uint8_t aConextLength)
+    void Init(uint8_t aContextId, uint8_t aContextLength)
     {
         NetworkDataTlv::Init();
         SetType(kTypeContext);
         SetLength(sizeof(ContextTlv) - sizeof(NetworkDataTlv));
         mFlags         = ((aContextId << kContextIdOffset) & kContextIdMask);
-        mContextLength = aConextLength;
+        mContextLength = aContextLength;
     }
 
     /**
@@ -1564,13 +1626,10 @@
      *
      * @tparam  TlvType The TLV Type to search for (MUST be a sub-class of `NetworkDataTlv`).
      *
-     * @returns A pointer to the next TLV, or nullptr if it can not be found.
+     * @returns A pointer to the next TLV, or `nullptr` if it can not be found.
      *
      */
-    template <typename TlvType> const TlvType *Iterate(void)
-    {
-        return static_cast<const TlvType *>(Iterate(TlvType::kType));
-    }
+    template <typename TlvType> const TlvType *Iterate(void) { return As<TlvType>(Iterate(TlvType::kType)); }
 
     /**
      * This template method iterates to the next TLV with a given type and stable flag.
@@ -1579,12 +1638,12 @@
      *
      * @param[in]  aStable      TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
      *
-     * @returns A pointer to the next TLV, or nullptr if it can not be found.
+     * @returns A pointer to the next TLV, or `nullptr` if it can not be found.
      *
      */
     template <typename TlvType> const TlvType *Iterate(bool aStable)
     {
-        return static_cast<const TlvType *>(Iterate(TlvType::kType, aStable));
+        return As<TlvType>(Iterate(TlvType::kType, aStable));
     }
 
 private:
diff --git a/src/core/thread/network_data_types.hpp b/src/core/thread/network_data_types.hpp
index 8773e4c..8215343 100644
--- a/src/core/thread/network_data_types.hpp
+++ b/src/core/thread/network_data_types.hpp
@@ -38,6 +38,7 @@
 
 #include <openthread/netdata.h>
 
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/data.hpp"
 #include "common/debug.hpp"
@@ -68,6 +69,16 @@
 class ServerTlv;
 
 /**
+ * This enumeration represents the Network Data type.
+ *
+ */
+enum Type : uint8_t
+{
+    kFullSet,      ///< Full Network Data set.
+    kStableSubset, ///< Stable Network Data subset.
+};
+
+/**
  * This enumeration type represents the route preference values as a signed integer (per RFC-4191).
  *
  */
@@ -79,6 +90,18 @@
 };
 
 /**
+ * This enumeration represents the border router RLOC role filter used when searching for border routers in the Network
+ * Data.
+ *
+ */
+enum RoleFilter : uint8_t
+{
+    kAnyRole,        ///< Include devices in any role.
+    kRouterRoleOnly, ///< Include devices that act as Thread router.
+    kChildRoleOnly,  ///< Include devices that act as Thread child (end-device).
+};
+
+/**
  * This function indicates whether a given `int8_t` preference value is a valid route preference (i.e., one of the
  * values from `RoutePreference` enumeration).
  *
@@ -146,6 +169,7 @@
                            public Equatable<OnMeshPrefixConfig>
 {
     friend class NetworkData;
+    friend class Leader;
     friend class Local;
     friend class Publisher;
 
@@ -156,7 +180,7 @@
      * @return The prefix.
      *
      */
-    const Ip6::Prefix &GetPrefix(void) const { return static_cast<const Ip6::Prefix &>(mPrefix); }
+    const Ip6::Prefix &GetPrefix(void) const { return AsCoreType(&mPrefix); }
 
     /**
      * This method gets the prefix.
@@ -164,7 +188,15 @@
      * @return The prefix.
      *
      */
-    Ip6::Prefix &GetPrefix(void) { return static_cast<Ip6::Prefix &>(mPrefix); }
+    Ip6::Prefix &GetPrefix(void) { return AsCoreType(&mPrefix); }
+
+    /**
+     * This method gets the preference.
+     *
+     * @return The preference.
+     *
+     */
+    RoutePreference GetPreference(void) const { return RoutePreferenceFromValue(RoutePreferenceToValue(mPreference)); }
 
 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
     /**
@@ -208,7 +240,7 @@
      * @return The prefix.
      *
      */
-    const Ip6::Prefix &GetPrefix(void) const { return static_cast<const Ip6::Prefix &>(mPrefix); }
+    const Ip6::Prefix &GetPrefix(void) const { return AsCoreType(&mPrefix); }
 
     /**
      * This method gets the prefix.
@@ -216,7 +248,7 @@
      * @return The prefix.
      *
      */
-    Ip6::Prefix &GetPrefix(void) { return static_cast<Ip6::Prefix &>(mPrefix); }
+    Ip6::Prefix &GetPrefix(void) { return AsCoreType(&mPrefix); }
 
     /**
      * This method sets the prefix.
@@ -348,6 +380,11 @@
 
 } // namespace NetworkData
 
+DefineCoreType(otBorderRouterConfig, NetworkData::OnMeshPrefixConfig);
+DefineCoreType(otExternalRouteConfig, NetworkData::ExternalRouteConfig);
+DefineCoreType(otServiceConfig, NetworkData::ServiceConfig);
+DefineCoreType(otServerConfig, NetworkData::ServiceConfig::ServerConfig);
+
 /**
  * @}
  */
diff --git a/src/core/thread/network_diagnostic.cpp b/src/core/thread/network_diagnostic.cpp
index 00eaa7b..738e904 100644
--- a/src/core/thread/network_diagnostic.cpp
+++ b/src/core/thread/network_diagnostic.cpp
@@ -36,13 +36,14 @@
 #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
 
 #include "coap/coap_message.hpp"
+#include "common/array.hpp"
 #include "common/as_core_type.hpp"
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "mac/mac.hpp"
 #include "net/netif.hpp"
 #include "thread/mesh_forwarder.hpp"
@@ -53,6 +54,8 @@
 
 namespace ot {
 
+RegisterLogModule("NetDiag");
+
 namespace NetworkDiagnostic {
 
 NetworkDiagnostic::NetworkDiagnostic(Instance &aInstance)
@@ -78,26 +81,21 @@
 {
     Error                 error;
     Coap::Message *       message = nullptr;
-    Ip6::MessageInfo      messageInfo;
+    Tmf::MessageInfo      messageInfo(GetInstance());
     otCoapResponseHandler handler = nullptr;
 
-    VerifyOrExit((message = Get<Tmf::Agent>().NewMessage()) != nullptr, error = kErrorNoBufs);
-
     if (aDestination.IsMulticast())
     {
-        SuccessOrExit(error = message->InitAsNonConfirmablePost(UriPath::kDiagnosticGetQuery));
+        message = Get<Tmf::Agent>().NewNonConfirmablePostMessage(UriPath::kDiagnosticGetQuery);
         messageInfo.SetMulticastLoop(true);
     }
     else
     {
         handler = &NetworkDiagnostic::HandleDiagnosticGetResponse;
-        SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kDiagnosticGetRequest));
+        message = Get<Tmf::Agent>().NewConfirmablePostMessage(UriPath::kDiagnosticGetRequest);
     }
 
-    if (aCount > 0)
-    {
-        SuccessOrExit(error = message->SetPayloadMarker());
-    }
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     if (aCount > 0)
     {
@@ -110,18 +108,17 @@
     }
     else
     {
-        messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
+        messageInfo.SetSockAddrToRloc();
     }
 
     messageInfo.SetPeerAddr(aDestination);
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, handler, this));
 
     mReceiveDiagnosticGetCallback        = aCallback;
     mReceiveDiagnosticGetCallbackContext = aCallbackContext;
 
-    otLogInfoNetDiag("Sent diagnostic get");
+    LogInfo("Sent diagnostic get");
 
 exit:
     FreeMessageOnError(message, error);
@@ -151,7 +148,7 @@
     }
     else
     {
-        otLogDebgNetDiag("Received diagnostic get response, error = %s", ErrorToString(aResult));
+        LogDebg("Received diagnostic get response, error = %s", ErrorToString(aResult));
     }
     return;
 }
@@ -168,7 +165,7 @@
 {
     VerifyOrExit(aMessage.IsConfirmablePostRequest());
 
-    otLogInfoNetDiag("Diagnostic get answer received");
+    LogInfo("Diagnostic get answer received");
 
     if (mReceiveDiagnosticGetCallback)
     {
@@ -177,7 +174,7 @@
 
     SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMessage, aMessageInfo));
 
-    otLogInfoNetDiag("Sent diagnostic answer acknowledgment");
+    LogInfo("Sent diagnostic answer acknowledgment");
 
 exit:
     return;
@@ -294,7 +291,7 @@
     {
         SuccessOrExit(error = aRequest.Read(offset, type));
 
-        otLogInfoNetDiag("Type %d", type);
+        LogInfo("Type %d", type);
 
         switch (type)
         {
@@ -346,8 +343,8 @@
             tlv.Init();
             tlv.SetPartitionId(leaderData.GetPartitionId());
             tlv.SetWeighting(leaderData.GetWeighting());
-            tlv.SetDataVersion(leaderData.GetDataVersion());
-            tlv.SetStableDataVersion(leaderData.GetStableDataVersion());
+            tlv.SetDataVersion(leaderData.GetDataVersion(NetworkData::kFullSet));
+            tlv.SetStableDataVersion(leaderData.GetDataVersion(NetworkData::kStableSubset));
             tlv.SetLeaderRouterId(leaderData.GetLeaderRouterId());
 
             SuccessOrExit(error = tlv.AppendTo(aResponse));
@@ -464,11 +461,11 @@
     Error                error   = kErrorNone;
     Coap::Message *      message = nullptr;
     NetworkDiagnosticTlv networkDiagnosticTlv;
-    Ip6::MessageInfo     messageInfo;
+    Tmf::MessageInfo     messageInfo(GetInstance());
 
     VerifyOrExit(aMessage.IsPostRequest(), error = kErrorDrop);
 
-    otLogInfoNetDiag("Received diagnostic get query");
+    LogInfo("Received diagnostic get query");
 
     SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), networkDiagnosticTlv));
 
@@ -479,36 +476,29 @@
     {
         if (Get<Tmf::Agent>().SendEmptyAck(aMessage, aMessageInfo) == kErrorNone)
         {
-            otLogInfoNetDiag("Sent diagnostic get query acknowledgment");
+            LogInfo("Sent diagnostic get query acknowledgment");
         }
     }
 
-    VerifyOrExit((message = Get<Tmf::Agent>().NewMessage()) != nullptr, error = kErrorNoBufs);
+    message = Get<Tmf::Agent>().NewConfirmablePostMessage(UriPath::kDiagnosticGetAnswer);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
-    SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kDiagnosticGetAnswer));
-
-    if (networkDiagnosticTlv.GetLength() > 0)
-    {
-        SuccessOrExit(error = message->SetPayloadMarker());
-    }
-
-    if (aMessageInfo.GetSockAddr().IsLinkLocal() || aMessageInfo.GetSockAddr().IsLinkLocalMulticast())
+    if (aMessageInfo.GetPeerAddr().IsLinkLocal())
     {
         messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetLinkLocalAddress());
     }
     else
     {
-        messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
+        messageInfo.SetSockAddrToRloc();
     }
 
     messageInfo.SetPeerAddr(aMessageInfo.GetPeerAddr());
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
 
     SuccessOrExit(error = FillRequestedTlvs(aMessage, *message, networkDiagnosticTlv));
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, nullptr, this));
 
-    otLogInfoNetDiag("Sent diagnostic get answer");
+    LogInfo("Sent diagnostic get answer");
 
 exit:
     FreeMessageOnError(message, error);
@@ -531,22 +521,20 @@
 
     VerifyOrExit(aMessage.IsConfirmablePostRequest(), error = kErrorDrop);
 
-    otLogInfoNetDiag("Received diagnostic get request");
+    LogInfo("Received diagnostic get request");
 
     SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), networkDiagnosticTlv));
 
     VerifyOrExit(networkDiagnosticTlv.GetType() == NetworkDiagnosticTlv::kTypeList, error = kErrorParse);
 
-    VerifyOrExit((message = Get<Tmf::Agent>().NewMessage()) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->SetDefaultResponseHeader(aMessage));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewResponseMessage(aMessage);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     SuccessOrExit(error = FillRequestedTlvs(aMessage, *message, networkDiagnosticTlv));
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
 
-    otLogInfoNetDiag("Sent diagnostic get response");
+    LogInfo("Sent diagnostic get response");
 
 exit:
     FreeMessageOnError(message, error);
@@ -558,16 +546,10 @@
 {
     Error            error;
     Coap::Message *  message = nullptr;
-    Ip6::MessageInfo messageInfo;
+    Tmf::MessageInfo messageInfo(GetInstance());
 
-    VerifyOrExit((message = Get<Tmf::Agent>().NewMessage()) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kDiagnosticReset));
-
-    if (aCount > 0)
-    {
-        SuccessOrExit(error = message->SetPayloadMarker());
-    }
+    message = Get<Tmf::Agent>().NewConfirmablePostMessage(UriPath::kDiagnosticReset);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     if (aCount > 0)
     {
@@ -580,15 +562,14 @@
     }
     else
     {
-        messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
+        messageInfo.SetSockAddrToRloc();
     }
 
     messageInfo.SetPeerAddr(aDestination);
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
 
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
 
-    otLogInfoNetDiag("Sent network diagnostic reset");
+    LogInfo("Sent network diagnostic reset");
 
 exit:
     FreeMessageOnError(message, error);
@@ -607,7 +588,7 @@
     uint8_t              type;
     NetworkDiagnosticTlv tlv;
 
-    otLogInfoNetDiag("Received diagnostic reset request");
+    LogInfo("Received diagnostic reset request");
 
     VerifyOrExit(aMessage.IsConfirmablePostRequest());
 
@@ -625,18 +606,18 @@
         {
         case NetworkDiagnosticTlv::kMacCounters:
             Get<Mac::Mac>().ResetCounters();
-            otLogInfoNetDiag("Received diagnostic reset type kMacCounters(9)");
+            LogInfo("Received diagnostic reset type kMacCounters(9)");
             break;
 
         default:
-            otLogInfoNetDiag("Received diagnostic reset other type %d not resetable", type);
+            LogInfo("Received diagnostic reset other type %d not resetable", type);
             break;
         }
     }
 
     SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMessage, aMessageInfo));
 
-    otLogInfoNetDiag("Sent diagnostic reset acknowledgment");
+    LogInfo("Sent diagnostic reset acknowledgment");
 
 exit:
     return;
@@ -646,7 +627,7 @@
 {
     aLinkModeConfig.mRxOnWhenIdle = aMode.IsRxOnWhenIdle();
     aLinkModeConfig.mDeviceType   = aMode.IsFullThreadDevice();
-    aLinkModeConfig.mNetworkData  = aMode.IsFullNetworkData();
+    aLinkModeConfig.mNetworkData  = (aMode.GetNetworkDataType() == NetworkData::kFullSet);
 }
 
 static inline void ParseConnectivity(const ConnectivityTlv &    aConnectivityTlv,
@@ -802,7 +783,7 @@
 
         case NetworkDiagnosticTlv::kIp6AddressList:
         {
-            Ip6AddressListTlv &ip6AddrList = static_cast<Ip6AddressListTlv &>(tlv);
+            Ip6AddressListTlv &ip6AddrList = As<Ip6AddressListTlv>(tlv);
 
             VerifyOrExit(ip6AddrList.IsValid(), error = kErrorParse);
             VerifyOrExit(sizeof(aNetworkDiagTlv.mData.mIp6AddrList.mList) >= ip6AddrList.GetLength(),
@@ -834,10 +815,10 @@
 
         case NetworkDiagnosticTlv::kChildTable:
         {
-            ChildTableTlv &childTable = static_cast<ChildTableTlv &>(tlv);
+            ChildTableTlv &childTable = As<ChildTableTlv>(tlv);
 
             VerifyOrExit(childTable.IsValid(), error = kErrorParse);
-            VerifyOrExit(childTable.GetNumEntries() <= OT_ARRAY_LENGTH(aNetworkDiagTlv.mData.mChildTable.mTable),
+            VerifyOrExit(childTable.GetNumEntries() <= GetArrayLength(aNetworkDiagTlv.mData.mChildTable.mTable),
                          error = kErrorParse);
 
             for (uint8_t i = 0; i < childTable.GetNumEntries(); ++i)
diff --git a/src/core/thread/network_diagnostic.hpp b/src/core/thread/network_diagnostic.hpp
index a475a09..ade893f 100644
--- a/src/core/thread/network_diagnostic.hpp
+++ b/src/core/thread/network_diagnostic.hpp
@@ -111,9 +111,10 @@
     /**
      * This static method gets the next Network Diagnostic TLV in a given message.
      *
-     * @param[in]     aMessage         A message.
-     * @param[inout]  aIterator        The Network Diagnostic iterator. To get the first TLV set it to `kIteratorInit`.
-     * @param[out]    aNetworkDiagTlv  A reference to a Network Diagnostic TLV to output the next TLV.
+     * @param[in]      aMessage         A message.
+     * @param[in,out]  aIterator        The Network Diagnostic iterator. To get the first TLV set it to
+     *                                  `kIteratorInit`.
+     * @param[out]     aNetworkDiagTlv  A reference to a Network Diagnostic TLV to output the next TLV.
      *
      * @retval kErrorNone       Successfully found the next Network Diagnostic TLV.
      * @retval kErrorNotFound   No subsequent Network Diagnostic TLV exists in the message.
diff --git a/src/core/thread/network_diagnostic_tlvs.hpp b/src/core/thread/network_diagnostic_tlvs.hpp
index f3b565a..8352634 100644
--- a/src/core/thread/network_diagnostic_tlvs.hpp
+++ b/src/core/thread/network_diagnostic_tlvs.hpp
@@ -1033,7 +1033,7 @@
     static constexpr uint8_t  kReservedOffset = 9;
     static constexpr uint16_t kTimeoutMask    = 0xf800;
     static constexpr uint16_t kReservedMask   = 0x0600;
-    static constexpr uint16_t kChildIdMask    = 0x1f;
+    static constexpr uint16_t kChildIdMask    = 0x1ff;
 
     uint16_t mTimeoutRsvChildId;
     uint8_t  mMode;
diff --git a/src/core/thread/panid_query_server.cpp b/src/core/thread/panid_query_server.cpp
index 0ba97a0..9c57e89 100644
--- a/src/core/thread/panid_query_server.cpp
+++ b/src/core/thread/panid_query_server.cpp
@@ -39,7 +39,7 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "meshcop/meshcop.hpp"
 #include "meshcop/meshcop_tlvs.hpp"
 #include "thread/thread_netif.hpp"
@@ -47,6 +47,8 @@
 
 namespace ot {
 
+RegisterLogModule("MeshCoP");
+
 PanIdQueryServer::PanIdQueryServer(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mChannelMask(0)
@@ -81,7 +83,7 @@
     if (aMessage.IsConfirmable() && !aMessageInfo.GetSockAddr().IsMulticast())
     {
         SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMessage, responseInfo));
-        otLogInfoMeshCoP("sent panid query response");
+        LogInfo("sent panid query response");
     }
 
 exit:
@@ -112,13 +114,11 @@
 {
     Error                   error = kErrorNone;
     MeshCoP::ChannelMaskTlv channelMask;
-    Ip6::MessageInfo        messageInfo;
+    Tmf::MessageInfo        messageInfo(GetInstance());
     Coap::Message *         message;
 
-    VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
-
-    SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kPanIdConflict));
-    SuccessOrExit(error = message->SetPayloadMarker());
+    message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(UriPath::kPanIdConflict);
+    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
 
     channelMask.Init();
     channelMask.SetChannelMask(mChannelMask);
@@ -126,12 +126,11 @@
 
     SuccessOrExit(error = Tlv::Append<MeshCoP::PanIdTlv>(*message, mPanId));
 
-    messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
-    messageInfo.SetPeerAddr(mCommissioner);
-    messageInfo.SetPeerPort(Tmf::kUdpPort);
+    messageInfo.SetSockAddrToRlocPeerAddrTo(mCommissioner);
+
     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
 
-    otLogInfoMeshCoP("sent panid conflict");
+    LogInfo("sent panid conflict");
 
 exit:
     FreeMessageOnError(message, error);
diff --git a/src/core/thread/radio_selector.cpp b/src/core/thread/radio_selector.cpp
index 74ea6bc..cb619a3 100644
--- a/src/core/thread/radio_selector.cpp
+++ b/src/core/thread/radio_selector.cpp
@@ -38,11 +38,13 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/random.hpp"
 
 namespace ot {
 
+RegisterLogModule("RadioSelector");
+
 // This array defines the order in which different radio link types are
 // selected for message tx (direct message).
 const Mac::RadioType RadioSelector::sRadioSelectionOrder[Mac::kNumRadioTypes] = {
@@ -80,7 +82,7 @@
 #endif
 }
 
-otLogLevel RadioSelector::UpdatePreference(Neighbor &aNeighbor, Mac::RadioType aRadioType, int16_t aDifference)
+LogLevel RadioSelector::UpdatePreference(Neighbor &aNeighbor, Mac::RadioType aRadioType, int16_t aDifference)
 {
     uint8_t old        = aNeighbor.GetRadioPreference(aRadioType);
     int16_t preferecne = static_cast<int16_t>(old);
@@ -104,12 +106,12 @@
     // return a suggested log level. If there is cross, suggest info
     // log level, otherwise debug log level.
 
-    return ((old >= kHighPreference) != (preferecne >= kHighPreference)) ? OT_LOG_LEVEL_INFO : OT_LOG_LEVEL_DEBG;
+    return ((old >= kHighPreference) != (preferecne >= kHighPreference)) ? kLogLevelInfo : kLogLevelDebg;
 }
 
 void RadioSelector::UpdateOnReceive(Neighbor &aNeighbor, Mac::RadioType aRadioType, bool aIsDuplicate)
 {
-    otLogLevel logLevel = OT_LOG_LEVEL_INFO;
+    LogLevel logLevel = kLogLevelInfo;
 
     if (aNeighbor.GetSupportedRadioTypes().Contains(aRadioType))
     {
@@ -129,7 +131,7 @@
 
 void RadioSelector::UpdateOnSendDone(Mac::TxFrame &aFrame, Error aTxError)
 {
-    otLogLevel     logLevel  = OT_LOG_LEVEL_INFO;
+    LogLevel       logLevel  = kLogLevelInfo;
     Mac::RadioType radioType = aFrame.GetRadioType();
     Mac::Address   macDest;
     Neighbor *     neighbor;
@@ -173,7 +175,7 @@
 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
 void RadioSelector::UpdateOnDeferredAck(Neighbor &aNeighbor, Error aTxError, bool &aAllowNeighborRemove)
 {
-    otLogLevel logLevel = OT_LOG_LEVEL_INFO;
+    LogLevel logLevel = kLogLevelInfo;
 
     aAllowNeighborRemove = true;
 
@@ -292,7 +294,7 @@
     selectedRadio = Select(neighbor->GetSupportedRadioTypes(), *neighbor);
     selections.Add(selectedRadio);
 
-    Log(OT_LOG_LEVEL_DEBG, "SelectRadio", selectedRadio, *neighbor);
+    Log(kLogLevelDebg, "SelectRadio", selectedRadio, *neighbor);
 
     aMessage.SetRadioType(selectedRadio);
 
@@ -316,7 +318,7 @@
         aTxFrames.SetRequiredRadioTypes(selections);
         selections.Add(Mac::kRadioTypeTrel);
 
-        Log(OT_LOG_LEVEL_DEBG, "Probe", Mac::kRadioTypeTrel, *neighbor);
+        Log(kLogLevelDebg, "Probe", Mac::kRadioTypeTrel, *neighbor);
     }
 #endif
 
@@ -353,9 +355,9 @@
 
 // LCOV_EXCL_START
 
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
-void RadioSelector::Log(otLogLevel      aLogLevel,
+void RadioSelector::Log(LogLevel        aLogLevel,
                         const char *    aActionText,
                         Mac::RadioType  aRadioType,
                         const Neighbor &aNeighbor)
@@ -363,7 +365,7 @@
     String<kRadioPreferenceStringSize> preferenceString;
     bool                               isFirstEntry = true;
 
-    VerifyOrExit(otLoggingGetLevel() >= aLogLevel);
+    VerifyOrExit(Instance::GetLogLevel() >= aLogLevel);
 
     for (Mac::RadioType radio : sRadioSelectionOrder)
     {
@@ -375,21 +377,21 @@
         }
     }
 
-    otLogMac(aLogLevel, "RadioSelector: %s %s - neighbor:[%s rloc16:0x%04x radio-pref:{%s} state:%s]", aActionText,
-             RadioTypeToString(aRadioType), aNeighbor.GetExtAddress().ToString().AsCString(), aNeighbor.GetRloc16(),
-             preferenceString.AsCString(), Neighbor::StateToString(aNeighbor.GetState()));
+    LogAt(aLogLevel, "RadioSelector: %s %s - neighbor:[%s rloc16:0x%04x radio-pref:{%s} state:%s]", aActionText,
+          RadioTypeToString(aRadioType), aNeighbor.GetExtAddress().ToString().AsCString(), aNeighbor.GetRloc16(),
+          preferenceString.AsCString(), Neighbor::StateToString(aNeighbor.GetState()));
 
 exit:
     return;
 }
 
-#else // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
+#else // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
-void RadioSelector::Log(otLogLevel, const char *, Mac::RadioType, const Neighbor &)
+void RadioSelector::Log(LogLevel, const char *, Mac::RadioType, const Neighbor &)
 {
 }
 
-#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
+#endif // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
 
 // LCOV_EXCL_STOP
 
diff --git a/src/core/thread/radio_selector.hpp b/src/core/thread/radio_selector.hpp
index c86f1c1..bf980cc 100644
--- a/src/core/thread/radio_selector.hpp
+++ b/src/core/thread/radio_selector.hpp
@@ -41,6 +41,7 @@
 #include <openthread/multi_radio.h>
 
 #include "common/locator.hpp"
+#include "common/log.hpp"
 #include "common/message.hpp"
 #include "mac/mac_frame.hpp"
 #include "mac/mac_links.hpp"
@@ -172,9 +173,9 @@
      * The `aMessage` will be updated to store the selected radio type (please see `Message::GetRadioType()`).
      * The `aTxFrames` will also be updated to indicate which radio links are to be used.
      *
-     * @param[inout] aMessage   The message to send.
-     * @param[in]    aMacDest   The MAC destination address.
-     * @param[inout] aTxFrames  The set of TxFrames for all radio links.
+     * @param[in,out] aMessage   The message to send.
+     * @param[in]     aMacDest   The MAC destination address.
+     * @param[in,out] aTxFrames  The set of TxFrames for all radio links.
      *
      * @returns  A reference to `mTxFrame` to use when preparing the frame for tx.
      *
@@ -198,9 +199,9 @@
 
     static constexpr uint16_t kRadioPreferenceStringSize = 75;
 
-    otLogLevel     UpdatePreference(Neighbor &aNeighbor, Mac::RadioType aRadioType, int16_t aDifference);
+    LogLevel       UpdatePreference(Neighbor &aNeighbor, Mac::RadioType aRadioType, int16_t aDifference);
     Mac::RadioType Select(Mac::RadioTypes aRadioOptions, const Neighbor &aNeighbor);
-    void           Log(otLogLevel aLogLevel, const char *aActionText, Mac::RadioType aType, const Neighbor &aNeighbor);
+    void           Log(LogLevel aLogLevel, const char *aActionText, Mac::RadioType aType, const Neighbor &aNeighbor);
 
     static const Mac::RadioType sRadioSelectionOrder[Mac::kNumRadioTypes];
 };
diff --git a/src/core/thread/router_table.cpp b/src/core/thread/router_table.cpp
index 8f777d9..722fadd 100644
--- a/src/core/thread/router_table.cpp
+++ b/src/core/thread/router_table.cpp
@@ -33,7 +33,7 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/timer.hpp"
 #include "thread/mle.hpp"
 #include "thread/mle_router.hpp"
@@ -42,6 +42,8 @@
 
 namespace ot {
 
+RegisterLogModule("RouterTable");
+
 RouterTable::Iterator::Iterator(Instance &aInstance)
     : InstanceLocator(aInstance)
     , ItemPtrIterator(Get<RouterTable>().GetFirstEntry())
@@ -58,6 +60,10 @@
     , mRouterIdSequenceLastUpdated(0)
     , mRouterIdSequence(Random::NonCrypto::GetUint8())
     , mActiveRouterCount(0)
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+    , mMinRouterId(0)
+    , mMaxRouterId(Mle::kMaxRouterId)
+#endif
 {
     for (Router &router : mRouters)
     {
@@ -204,7 +210,11 @@
     uint8_t freeBit;
 
     // count available router ids
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+    for (uint8_t routerId = mMinRouterId; routerId <= mMaxRouterId; routerId++)
+#else
     for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
+#endif
     {
         if (!IsAllocated(routerId) && mRouterIdReuseDelay[routerId] == 0)
         {
@@ -218,7 +228,11 @@
     freeBit = Random::NonCrypto::GetUint8InRange(0, numAvailable);
 
     // allocate router
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+    for (uint8_t routerId = mMinRouterId; routerId <= mMaxRouterId; routerId++)
+#else
     for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
+#endif
     {
         if (IsAllocated(routerId) || mRouterIdReuseDelay[routerId] > 0)
         {
@@ -256,7 +270,7 @@
     mRouterIdSequenceLastUpdated = TimerMilli::GetNow();
     Get<Mle::MleRouter>().ResetAdvertiseInterval();
 
-    otLogNoteMle("Allocate router id %d", aRouterId);
+    LogNote("Allocate router id %d", aRouterId);
 
 exit:
     return rval;
@@ -301,7 +315,7 @@
     Get<NetworkData::Leader>().RemoveBorderRouter(rloc16, NetworkData::Leader::kMatchModeRouterId);
     Get<Mle::MleRouter>().ResetAdvertiseInterval();
 
-    otLogNoteMle("Release router id %d", aRouterId);
+    LogNote("Release router id %d", aRouterId);
 
 exit:
     return error;
@@ -309,8 +323,11 @@
 
 void RouterTable::RemoveRouterLink(Router &aRouter)
 {
-    aRouter.SetLinkQualityOut(0);
-    aRouter.SetLastHeard(TimerMilli::GetNow());
+    if (aRouter.GetLinkQualityOut() != 0)
+    {
+        aRouter.SetLinkQualityOut(kLinkQuality0);
+        aRouter.SetLastHeard(TimerMilli::GetNow());
+    }
 
     for (Router *cur = GetFirstEntry(); cur != nullptr; cur = GetNextEntry(cur))
     {
@@ -529,6 +546,27 @@
     }
 }
 
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+void RouterTable::GetRouterIdRange(uint8_t &aMinRouterId, uint8_t &aMaxRouterId) const
+{
+    aMinRouterId = mMinRouterId;
+    aMaxRouterId = mMaxRouterId;
+}
+
+Error RouterTable::SetRouterIdRange(uint8_t aMinRouterId, uint8_t aMaxRouterId)
+{
+    Error error = kErrorNone;
+
+    VerifyOrExit(aMinRouterId <= aMaxRouterId, error = kErrorInvalidArgs);
+    VerifyOrExit(aMaxRouterId <= Mle::kMaxRouterId, error = kErrorInvalidArgs);
+    mMinRouterId = aMinRouterId;
+    mMaxRouterId = aMaxRouterId;
+
+exit:
+    return error;
+}
+#endif
+
 } // namespace ot
 
 #endif // OPENTHREAD_FTD
diff --git a/src/core/thread/router_table.hpp b/src/core/thread/router_table.hpp
index 06a280c..7fa6549 100644
--- a/src/core/thread/router_table.hpp
+++ b/src/core/thread/router_table.hpp
@@ -106,7 +106,7 @@
     /**
      * This method allocates a router with a random router id.
      *
-     * @returns A pointer to the allocated router or nullptr if a router ID is not available.
+     * @returns A pointer to the allocated router or `nullptr` if a router ID is not available.
      *
      */
     Router *Allocate(void);
@@ -114,7 +114,7 @@
     /**
      * This method allocates a router with a specified router id.
      *
-     * @returns A pointer to the allocated router or nullptr if the router id could not be allocated.
+     * @returns A pointer to the allocated router or `nullptr` if the router id could not be allocated.
      *
      */
     Router *Allocate(uint8_t aRouterId);
@@ -186,7 +186,7 @@
      *
      * @param[in]  aRloc16  The RLOC16 value.
      *
-     * @returns A pointer to the router or nullptr if the router could not be found.
+     * @returns A pointer to the router or `nullptr` if the router could not be found.
      *
      */
     Router *GetNeighbor(uint16_t aRloc16);
@@ -196,7 +196,7 @@
      *
      * @param[in]  aExtAddress  A reference to the IEEE Extended Address.
      *
-     * @returns A pointer to the router or nullptr if the router could not be found.
+     * @returns A pointer to the router or `nullptr` if the router could not be found.
      *
      */
     Router *GetNeighbor(const Mac::ExtAddress &aExtAddress);
@@ -206,7 +206,7 @@
      *
      * @param[in]  aMacAddress  A MAC address
      *
-     * @returns A pointer to the router or nullptr if the router could not be found.
+     * @returns A pointer to the router or `nullptr` if the router could not be found.
      *
      */
     Router *GetNeighbor(const Mac::Address &aMacAddress);
@@ -216,7 +216,7 @@
      *
      * @param[in]  aRouterId  The router id.
      *
-     * @returns A pointer to the router or nullptr if the router could not be found.
+     * @returns A pointer to the router or `nullptr` if the router could not be found.
      *
      */
     Router *GetRouter(uint8_t aRouterId) { return AsNonConst(AsConst(this)->GetRouter(aRouterId)); }
@@ -226,7 +226,7 @@
      *
      * @param[in]  aRouterId  The router id.
      *
-     * @returns A pointer to the router or nullptr if the router could not be found.
+     * @returns A pointer to the router or `nullptr` if the router could not be found.
      *
      */
     const Router *GetRouter(uint8_t aRouterId) const;
@@ -236,7 +236,7 @@
      *
      * @param[in]  aExtAddress  A reference to the IEEE Extended Address.
      *
-     * @returns A pointer to the router or nullptr if the router could not be found.
+     * @returns A pointer to the router or `nullptr` if the router could not be found.
      *
      */
     Router *GetRouter(const Mac::ExtAddress &aExtAddress);
@@ -338,6 +338,12 @@
      */
     IteratorBuilder Iterate(void) { return IteratorBuilder(GetInstance()); }
 
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+    void GetRouterIdRange(uint8_t &aMinRouterId, uint8_t &aMaxRouterId) const;
+
+    Error SetRouterIdRange(uint8_t aMinRouterId, uint8_t aMaxRouterId);
+#endif
+
 private:
     class IteratorBuilder : public InstanceLocator
     {
@@ -369,6 +375,10 @@
     TimeMilli        mRouterIdSequenceLastUpdated;
     uint8_t          mRouterIdSequence;
     uint8_t          mActiveRouterCount;
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+    uint8_t mMinRouterId;
+    uint8_t mMaxRouterId;
+#endif
 };
 
 } // namespace ot
diff --git a/src/core/thread/src_match_controller.cpp b/src/core/thread/src_match_controller.cpp
index 810118b..371405f 100644
--- a/src/core/thread/src_match_controller.cpp
+++ b/src/core/thread/src_match_controller.cpp
@@ -39,7 +39,7 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "mac/mac_types.hpp"
 #include "radio/radio.hpp"
 #include "thread/mesh_forwarder.hpp"
@@ -48,6 +48,8 @@
 
 namespace ot {
 
+RegisterLogModule("SrcMatchCtrl");
+
 SourceMatchController::SourceMatchController(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mEnabled(false)
@@ -69,7 +71,7 @@
 {
     if (aChild.GetIndirectMessageCount() == 0)
     {
-        otLogWarnMac("DecrementMessageCount(child 0x%04x) called when already at zero count.", aChild.GetRloc16());
+        LogWarn("DecrementMessageCount(child 0x%04x) called when already at zero count.", aChild.GetRloc16());
         ExitNow();
     }
 
@@ -113,14 +115,14 @@
 {
     Get<Radio>().ClearSrcMatchShortEntries();
     Get<Radio>().ClearSrcMatchExtEntries();
-    otLogDebgMac("SrcAddrMatch - Cleared all entries");
+    LogDebg("Cleared all entries");
 }
 
 void SourceMatchController::Enable(bool aEnable)
 {
     mEnabled = aEnable;
     Get<Radio>().EnableSrcMatch(mEnabled);
-    otLogDebgMac("SrcAddrMatch - %sabling", mEnabled ? "En" : "Dis");
+    LogDebg("%sabling", mEnabled ? "En" : "Dis");
 }
 
 void SourceMatchController::AddEntry(Child &aChild)
@@ -150,8 +152,7 @@
     {
         error = Get<Radio>().AddSrcMatchShortEntry(aChild.GetRloc16());
 
-        otLogDebgMac("SrcAddrMatch - Adding short addr: 0x%04x -- %s (%d)", aChild.GetRloc16(), ErrorToString(error),
-                     error);
+        LogDebg("Adding short addr: 0x%04x -- %s (%d)", aChild.GetRloc16(), ErrorToString(error), error);
     }
     else
     {
@@ -160,8 +161,8 @@
         address.Set(aChild.GetExtAddress().m8, Mac::ExtAddress::kReverseByteOrder);
         error = Get<Radio>().AddSrcMatchExtEntry(address);
 
-        otLogDebgMac("SrcAddrMatch - Adding addr: %s -- %s (%d)", aChild.GetExtAddress().ToString().AsCString(),
-                     ErrorToString(error), error);
+        LogDebg("Adding addr: %s -- %s (%d)", aChild.GetExtAddress().ToString().AsCString(), ErrorToString(error),
+                error);
     }
 
     return error;
@@ -173,7 +174,7 @@
 
     if (aChild.IsIndirectSourceMatchPending())
     {
-        otLogDebgMac("SrcAddrMatch - Clearing pending flag for 0x%04x", aChild.GetRloc16());
+        LogDebg("Clearing pending flag for 0x%04x", aChild.GetRloc16());
         aChild.SetIndirectSourceMatchPending(false);
         ExitNow();
     }
@@ -182,8 +183,7 @@
     {
         error = Get<Radio>().ClearSrcMatchShortEntry(aChild.GetRloc16());
 
-        otLogDebgMac("SrcAddrMatch - Clearing short addr: 0x%04x -- %s (%d)", aChild.GetRloc16(), ErrorToString(error),
-                     error);
+        LogDebg("Clearing short addr: 0x%04x -- %s (%d)", aChild.GetRloc16(), ErrorToString(error), error);
     }
     else
     {
@@ -192,8 +192,8 @@
         address.Set(aChild.GetExtAddress().m8, Mac::ExtAddress::kReverseByteOrder);
         error = Get<Radio>().ClearSrcMatchExtEntry(address);
 
-        otLogDebgMac("SrcAddrMatch - Clearing addr: %s -- %s (%d)", aChild.GetExtAddress().ToString().AsCString(),
-                     ErrorToString(error), error);
+        LogDebg("Clearing addr: %s -- %s (%d)", aChild.GetExtAddress().ToString().AsCString(), ErrorToString(error),
+                error);
     }
 
     SuccessOrExit(error);
diff --git a/src/core/thread/thread_netif.cpp b/src/core/thread/thread_netif.cpp
index b698e34..3866d0d 100644
--- a/src/core/thread/thread_netif.cpp
+++ b/src/core/thread/thread_netif.cpp
@@ -49,117 +49,7 @@
 
 ThreadNetif::ThreadNetif(Instance &aInstance)
     : Netif(aInstance)
-    , mTmfAgent(aInstance)
-#if OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
-    , mDhcp6Client(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
-    , mDhcp6Server(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
-    , mNeighborDiscoveryAgent(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
-    , mSlaac(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
-    , mDnsClient(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
-    , mSrpClient(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE
-    , mSrpClientBuffers(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
-    , mDnssdServer(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
-    , mSntpClient(aInstance)
-#endif
-    , mActiveDataset(aInstance)
-    , mPendingDataset(aInstance)
-    , mIp6Filter(aInstance)
-    , mKeyManager(aInstance)
-    , mLowpan(aInstance)
-    , mMac(aInstance)
-    , mMeshForwarder(aInstance)
-    , mMleRouter(aInstance)
-    , mDiscoverScanner(aInstance)
-#if OPENTHREAD_CONFIG_MULTI_RADIO
-    , mRadioSelector(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-    , mNetworkDataLocal(aInstance)
-#endif
-    , mNetworkDataLeader(aInstance)
-#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-    , mNetworkDataNotifier(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
-    , mNetworkDataPublisher(aInstance)
-#endif
-    , mNetworkDataServiceManager(aInstance)
-#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
-    , mNetworkDiagnostic(aInstance)
-#endif
     , mIsUp(false)
-#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
-    , mBorderAgent(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
-    , mCommissioner(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_DTLS_ENABLE
-    , mCoapSecure(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_JOINER_ENABLE
-    , mJoiner(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
-    , mJamDetector(aInstance)
-#endif
-#if OPENTHREAD_FTD
-    , mJoinerRouter(aInstance)
-    , mLeader(aInstance)
-    , mAddressResolver(aInstance)
-#endif
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-    , mBackboneRouterLeader(aInstance)
-#endif
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
-    , mBackboneRouterLocal(aInstance)
-    , mBackboneRouterManager(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)
-    , mMlrManager(aInstance)
-#endif
-
-#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
-    , mDuaManager(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
-    , mSrpServer(aInstance)
-#endif
-
-#if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
-#if OPENTHREAD_FTD
-    , mChildSupervisor(aInstance)
-#endif
-    , mSupervisionListener(aInstance)
-#endif
-    , mAnnounceBegin(aInstance)
-    , mPanIdQuery(aInstance)
-    , mEnergyScan(aInstance)
-#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
-    , mAnycastLocator(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-    , mTimeSync(aInstance)
-#endif
-#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
-    , mLinkMetrics(aInstance)
-#endif
 {
 }
 
@@ -228,6 +118,11 @@
     return;
 }
 
+Error ThreadNetif::SendMessage(Message &aMessage)
+{
+    return Get<MeshForwarder>().SendMessage(aMessage);
+}
+
 Error ThreadNetif::RouteLookup(const Ip6::Address &aSource, const Ip6::Address &aDestination, uint8_t *aPrefixMatch)
 {
     Error    error;
diff --git a/src/core/thread/thread_netif.hpp b/src/core/thread/thread_netif.hpp
index 15e9d76..e06e6b6 100644
--- a/src/core/thread/thread_netif.hpp
+++ b/src/core/thread/thread_netif.hpp
@@ -36,84 +36,8 @@
 
 #include "openthread-core-config.h"
 
-#include "coap/coap_secure.hpp"
-#include "mac/mac.hpp"
-#include "thread/tmf.hpp"
-
-#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
-#include "meshcop/border_agent.hpp"
-#endif
-#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
-#include "meshcop/commissioner.hpp"
-#endif // OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
-
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-#include "backbone_router/bbr_leader.hpp"
-#endif
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
-#include "backbone_router/backbone_tmf.hpp"
-#include "backbone_router/bbr_local.hpp"
-#include "backbone_router/bbr_manager.hpp"
-#endif
-
-#if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)
-#include "thread/mlr_manager.hpp"
-#endif
-
-#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
-#include "thread/dua_manager.hpp"
-#endif
-
-#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
-#include "net/srp_server.hpp"
-#endif
-
-#include "meshcop/dataset_manager.hpp"
-
-#if OPENTHREAD_CONFIG_JOINER_ENABLE
-#include "meshcop/joiner.hpp"
-#endif // OPENTHREAD_CONFIG_JOINER_ENABLE
-
-#include "meshcop/joiner_router.hpp"
-#include "meshcop/meshcop_leader.hpp"
-#include "net/dhcp6.hpp"
-#include "net/dhcp6_client.hpp"
-#include "net/dhcp6_server.hpp"
-#include "net/dns_client.hpp"
-#include "net/dnssd_server.hpp"
-#include "net/ip6_filter.hpp"
-#include "net/nd_agent.hpp"
+#include "net/ip6_address.hpp"
 #include "net/netif.hpp"
-#include "net/sntp_client.hpp"
-#include "net/srp_client.hpp"
-#include "thread/address_resolver.hpp"
-#include "thread/announce_begin_server.hpp"
-#include "thread/anycast_locator.hpp"
-#include "thread/discover_scanner.hpp"
-#include "thread/energy_scan_server.hpp"
-#include "thread/key_manager.hpp"
-#include "thread/link_metrics.hpp"
-#include "thread/mesh_forwarder.hpp"
-#include "thread/mle.hpp"
-#include "thread/mle_router.hpp"
-#include "thread/network_data_local.hpp"
-#include "thread/network_data_notifier.hpp"
-#include "thread/network_data_publisher.hpp"
-#include "thread/network_data_service.hpp"
-#include "thread/network_diagnostic.hpp"
-#include "thread/panid_query_server.hpp"
-#include "thread/radio_selector.hpp"
-#include "thread/time_sync_service.hpp"
-#include "utils/child_supervision.hpp"
-#include "utils/srp_client_buffers.hpp"
-
-#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
-#include "utils/slaac_address.hpp"
-#endif
-
-#if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
-#include "utils/jam_detector.hpp"
-#endif // OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
 
 namespace ot {
 
@@ -128,8 +52,6 @@
 
 class ThreadNetif : public Ip6::Netif
 {
-    friend class Instance;
-
 public:
     /**
      * This constructor initializes the Thread network interface.
@@ -168,7 +90,7 @@
      * @retval kErrorNone  Successfully submitted the message to the interface.
      *
      */
-    Error SendMessage(Message &aMessage) { return mMeshForwarder.SendMessage(aMessage); }
+    Error SendMessage(Message &aMessage);
 
     /**
      * This method performs a route lookup.
@@ -195,123 +117,7 @@
     bool IsOnMesh(const Ip6::Address &aAddress) const;
 
 private:
-    Tmf::Agent mTmfAgent;
-#if OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
-    Dhcp6::Client mDhcp6Client;
-#endif
-#if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
-    Dhcp6::Server mDhcp6Server;
-#endif
-#if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
-    NeighborDiscovery::Agent mNeighborDiscoveryAgent;
-#endif
-#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
-    Utils::Slaac mSlaac;
-#endif
-#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
-    Dns::Client mDnsClient;
-#endif
-#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
-    Srp::Client mSrpClient;
-#endif
-#if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE
-    Utils::SrpClientBuffers mSrpClientBuffers;
-#endif
-#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
-    Dns::ServiceDiscovery::Server mDnssdServer;
-#endif
-#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
-    Sntp::Client mSntpClient;
-#endif
-    MeshCoP::ActiveDataset  mActiveDataset;
-    MeshCoP::PendingDataset mPendingDataset;
-    Ip6::Filter             mIp6Filter;
-    KeyManager              mKeyManager;
-    Lowpan::Lowpan          mLowpan;
-    Mac::Mac                mMac;
-    MeshForwarder           mMeshForwarder;
-    Mle::MleRouter          mMleRouter;
-    Mle::DiscoverScanner    mDiscoverScanner;
-#if OPENTHREAD_CONFIG_MULTI_RADIO
-    RadioSelector mRadioSelector;
-#endif
-#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-    NetworkData::Local mNetworkDataLocal;
-#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-    NetworkData::Leader mNetworkDataLeader;
-#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-    NetworkData::Notifier mNetworkDataNotifier;
-#endif
-#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
-    NetworkData::Publisher mNetworkDataPublisher;
-#endif
-    NetworkData::Service::Manager mNetworkDataServiceManager;
-#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
-    NetworkDiagnostic::NetworkDiagnostic mNetworkDiagnostic;
-#endif // OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
     bool mIsUp;
-
-#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
-    MeshCoP::BorderAgent mBorderAgent;
-#endif
-#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
-    MeshCoP::Commissioner mCommissioner;
-#endif // OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
-
-#if OPENTHREAD_CONFIG_DTLS_ENABLE
-    Coap::CoapSecure mCoapSecure;
-#endif // OPENTHREAD_CONFIG_DTLS_ENABLE
-
-#if OPENTHREAD_CONFIG_JOINER_ENABLE
-    MeshCoP::Joiner mJoiner;
-#endif // OPENTHREAD_CONFIG_JOINER_ENABLE
-
-#if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
-    Utils::JamDetector mJamDetector;
-#endif // OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
-
-#if OPENTHREAD_FTD
-    MeshCoP::JoinerRouter mJoinerRouter;
-    MeshCoP::Leader       mLeader;
-    AddressResolver       mAddressResolver;
-#endif // OPENTHREAD_FTD
-
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-    BackboneRouter::Leader mBackboneRouterLeader;
-#endif
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
-    BackboneRouter::Local   mBackboneRouterLocal;
-    BackboneRouter::Manager mBackboneRouterManager;
-#endif
-#if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)
-    MlrManager mMlrManager;
-#endif
-#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
-    DuaManager mDuaManager;
-#endif
-#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
-    Srp::Server mSrpServer;
-#endif
-
-#if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
-#if OPENTHREAD_FTD
-    Utils::ChildSupervisor mChildSupervisor;
-#endif
-    Utils::SupervisionListener mSupervisionListener;
-#endif
-    AnnounceBeginServer mAnnounceBegin;
-    PanIdQueryServer    mPanIdQuery;
-    EnergyScanServer    mEnergyScan;
-#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
-    AnycastLocator mAnycastLocator;
-#endif
-
-#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-    TimeSync mTimeSync;
-#endif
-#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
-    LinkMetrics::LinkMetrics mLinkMetrics;
-#endif
 };
 
 /**
diff --git a/src/core/thread/thread_tlvs.hpp b/src/core/thread/thread_tlvs.hpp
index 0e5b5da..f092c5f 100644
--- a/src/core/thread/thread_tlvs.hpp
+++ b/src/core/thread/thread_tlvs.hpp
@@ -48,10 +48,6 @@
 using ot::Encoding::BigEndian::HostSwap16;
 using ot::Encoding::BigEndian::HostSwap32;
 
-// Thread 1.2.0 5.19.13 limits the number of IPv6 addresses should be [1, 15].
-constexpr uint8_t kIp6AddressesNumMin = 1;
-constexpr uint8_t kIp6AddressesNumMax = 15;
-
 /**
  * This class implements Network Layer TLV generation and parsing.
  *
@@ -166,6 +162,8 @@
         kTooFewRouters         = 2, ///< Address Solicit due to too few routers.
         kHaveChildIdRequest    = 3, ///< Address Solicit due to child ID request.
         kParentPartitionChange = 4, ///< Address Solicit due to parent partition change
+        kBorderRouterRequest   = 5, ///< Address Solicit from Border Router request.
+        kUnrecognizedStatus    = 6, ///< The requested status is unrecognized or not meaningful in a request.
     };
 
     /**
@@ -313,6 +311,10 @@
 class Ip6AddressesTlv : public ThreadTlv, public TlvInfo<ThreadTlv::kIp6Addresses>
 {
 public:
+    // Thread 1.2.0 5.19.13 limits the number of IPv6 addresses to [1, 15].
+    static constexpr uint8_t kMinAddresses = 1;
+    static constexpr uint8_t kMaxAddresses = OT_IP6_MAX_MLR_ADDRESSES;
+
     /**
      * This method initializes the TLV.
      *
@@ -328,8 +330,9 @@
      */
     bool IsValid(void) const
     {
-        return GetLength() >= sizeof(Ip6::Address) * kIp6AddressesNumMin &&
-               GetLength() <= sizeof(Ip6::Address) * kIp6AddressesNumMax && (GetLength() % sizeof(Ip6::Address)) == 0;
+        return GetLength() >= sizeof(Ip6::Address) * Ip6AddressesTlv::kMinAddresses &&
+               GetLength() <= sizeof(Ip6::Address) * Ip6AddressesTlv::kMaxAddresses &&
+               (GetLength() % sizeof(Ip6::Address)) == 0;
     }
 
     /**
diff --git a/src/core/thread/time_sync_service.cpp b/src/core/thread/time_sync_service.cpp
index 001997d..e938f38 100644
--- a/src/core/thread/time_sync_service.cpp
+++ b/src/core/thread/time_sync_service.cpp
@@ -43,12 +43,14 @@
 
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 
 #define ABS(value) (((value) >= 0) ? (value) : -(value))
 
 namespace ot {
 
+RegisterLogModule("TimeSync");
+
 TimeSync::TimeSync(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mTimeSyncRequired(false)
@@ -90,8 +92,7 @@
         // synchronized with the current sequence, so forward it.
         mTimeSyncRequired = true;
 
-        otLogInfoCore("Older time sync seq received:%u. Forwarding current seq:%u", aMessage.GetTimeSyncSeq(),
-                      mTimeSyncSeq);
+        LogInfo("Older time sync seq received:%u. Forwarding current seq:%u", aMessage.GetTimeSyncSeq(), mTimeSyncSeq);
     }
     else if (Get<Mle::MleRouter>().IsLeader() && timeSyncSeqDelta > 0)
     {
@@ -101,8 +102,8 @@
         mTimeSyncSeq      = aMessage.GetTimeSyncSeq() + 1;
         mTimeSyncRequired = true;
 
-        otLogInfoCore("Newer time sync seq:%u received by leader. Setting current seq to:%u and forwarding",
-                      aMessage.GetTimeSyncSeq(), mTimeSyncSeq);
+        LogInfo("Newer time sync seq:%u received by leader. Setting current seq to:%u and forwarding",
+                aMessage.GetTimeSyncSeq(), mTimeSyncSeq);
     }
     else if (!Get<Mle::MleRouter>().IsLeader())
     {
@@ -118,7 +119,7 @@
             mNetworkTimeOffset    = aMessage.GetNetworkTimeOffset();
             mTimeSyncRequired     = true;
 
-            otLogInfoCore("Newer time sync seq:%u received. Forwarding", mTimeSyncSeq);
+            LogInfo("Newer time sync seq:%u received. Forwarding", mTimeSyncSeq);
 
             // Only notify listeners of an update for network time offset jumps of more than
             // OPENTHREAD_CONFIG_TIME_SYNC_JUMP_NOTIF_MIN_US but notify listeners regardless if the status changes.
@@ -156,7 +157,7 @@
         IncrementTimeSyncSeq();
         mTimeSyncRequired = true;
 
-        otLogInfoCore("Leader seeding new time sync seq:%u", mTimeSyncSeq);
+        LogInfo("Leader seeding new time sync seq:%u", mTimeSyncSeq);
     }
 
     if (mTimeSyncRequired)
@@ -194,7 +195,7 @@
 
         stateChanged = true;
 
-        otLogInfoCore("Resetting time sync seq, partition changed");
+        LogInfo("Resetting time sync seq, partition changed");
     }
 
     if (stateChanged)
@@ -226,7 +227,7 @@
     case Mle::kRoleDisabled:
     case Mle::kRoleDetached:
         networkTimeStatus = OT_NETWORK_TIME_UNSYNCHRONIZED;
-        otLogInfoCore("Time sync status UNSYNCHRONIZED as role:DISABLED/DETACHED");
+        LogInfo("Time sync status UNSYNCHRONIZED as role:DISABLED/DETACHED");
         break;
 
     case Mle::kRoleChild:
@@ -235,26 +236,26 @@
         {
             // Haven't yet received any time sync
             networkTimeStatus = OT_NETWORK_TIME_UNSYNCHRONIZED;
-            otLogInfoCore("Time sync status UNSYNCHRONIZED as mLastTimeSyncReceived:0");
+            LogInfo("Time sync status UNSYNCHRONIZED as mLastTimeSyncReceived:0");
         }
         else if (timeSyncLastSyncMs > resyncNeededThresholdMs)
         {
             // The device hasn’t received time sync for more than two periods time.
             networkTimeStatus = OT_NETWORK_TIME_RESYNC_NEEDED;
-            otLogInfoCore("Time sync status RESYNC_NEEDED as timeSyncLastSyncMs:%u > resyncNeededThresholdMs:%u",
-                          timeSyncLastSyncMs, resyncNeededThresholdMs);
+            LogInfo("Time sync status RESYNC_NEEDED as timeSyncLastSyncMs:%u > resyncNeededThresholdMs:%u",
+                    timeSyncLastSyncMs, resyncNeededThresholdMs);
         }
         else
         {
             // Schedule a check 1 millisecond after two periods of time
             OT_ASSERT(resyncNeededThresholdMs >= timeSyncLastSyncMs);
             mTimer.Start(resyncNeededThresholdMs - timeSyncLastSyncMs + 1);
-            otLogInfoCore("Time sync status SYNCHRONIZED");
+            LogInfo("Time sync status SYNCHRONIZED");
         }
         break;
 
     case Mle::kRoleLeader:
-        otLogInfoCore("Time sync status SYNCHRONIZED as role:LEADER");
+        LogInfo("Time sync status SYNCHRONIZED as role:LEADER");
         break;
     }
 
diff --git a/src/core/thread/time_sync_service.hpp b/src/core/thread/time_sync_service.hpp
index d1c5511..4f2e144 100644
--- a/src/core/thread/time_sync_service.hpp
+++ b/src/core/thread/time_sync_service.hpp
@@ -66,7 +66,7 @@
     /**
      * Get the Thread network time.
      *
-     * @param[inout] aNetworkTime  The Thread network time in microseconds.
+     * @param[in,out] aNetworkTime  The Thread network time in microseconds.
      *
      * @returns The time synchronization status.
      *
diff --git a/src/core/thread/tmf.cpp b/src/core/thread/tmf.cpp
index 7dc5ea4..24a4ae9 100644
--- a/src/core/thread/tmf.cpp
+++ b/src/core/thread/tmf.cpp
@@ -38,35 +38,83 @@
 namespace ot {
 namespace Tmf {
 
+//----------------------------------------------------------------------------------------------------------------------
+// MessageInfo
+
+void MessageInfo::SetSockAddrToRloc(void)
+{
+    SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
+}
+
+Error MessageInfo::SetSockAddrToRlocPeerAddrToLeaderAloc(void)
+{
+    SetSockAddrToRloc();
+    return Get<Mle::MleRouter>().GetLeaderAloc(GetPeerAddr());
+}
+
+Error MessageInfo::SetSockAddrToRlocPeerAddrToLeaderRloc(void)
+{
+    SetSockAddrToRloc();
+    return Get<Mle::MleRouter>().GetLeaderAddress(GetPeerAddr());
+}
+
+void MessageInfo::SetSockAddrToRlocPeerAddrToRealmLocalAllRoutersMulticast(void)
+{
+    SetSockAddrToRloc();
+    GetPeerAddr().SetToRealmLocalAllRoutersMulticast();
+}
+
+void MessageInfo::SetSockAddrToRlocPeerAddrTo(uint16_t aRloc16)
+{
+    SetSockAddrToRloc();
+    SetPeerAddr(Get<Mle::MleRouter>().GetMeshLocal16());
+    GetPeerAddr().GetIid().SetLocator(aRloc16);
+}
+
+void MessageInfo::SetSockAddrToRlocPeerAddrTo(const Ip6::Address &aPeerAddress)
+{
+    SetSockAddrToRloc();
+    SetPeerAddr(aPeerAddress);
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+// Agent
+
 Error Agent::Start(void)
 {
     return Coap::Start(kUdpPort, OT_NETIF_THREAD);
 }
 
-Error Agent::Filter(const ot::Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext)
+Error Agent::Filter(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext)
 {
     OT_UNUSED_VARIABLE(aMessage);
 
-    return static_cast<Agent *>(aContext)->IsTmfMessage(aMessageInfo) ? kErrorNone : kErrorNotTmf;
+    return static_cast<Agent *>(aContext)->IsTmfMessage(aMessageInfo.GetPeerAddr(), aMessageInfo.GetSockAddr(),
+                                                        aMessageInfo.GetSockPort())
+               ? kErrorNone
+               : kErrorNotTmf;
 }
 
-bool Agent::IsTmfMessage(const Ip6::MessageInfo &aMessageInfo) const
+bool Agent::IsTmfMessage(const Ip6::Address &aSourceAddress, const Ip6::Address &aDestAddress, uint16_t aDestPort) const
 {
-    bool rval = true;
+    bool isTmf = false;
 
-    // A TMF message must comply with following rules:
-    // 1. The destination is a Mesh Local Address or a Link-Local Multicast Address or a Realm-Local Multicast Address,
-    //    and the source is a Mesh Local Address. Or
-    // 2. Both the destination and the source are Link-Local Addresses.
-    VerifyOrExit(
-        ((Get<Mle::MleRouter>().IsMeshLocalAddress(aMessageInfo.GetSockAddr()) ||
-          aMessageInfo.GetSockAddr().IsLinkLocalMulticast() || aMessageInfo.GetSockAddr().IsRealmLocalMulticast()) &&
-         Get<Mle::MleRouter>().IsMeshLocalAddress(aMessageInfo.GetPeerAddr())) ||
-            ((aMessageInfo.GetSockAddr().IsLinkLocal() || aMessageInfo.GetSockAddr().IsLinkLocalMulticast()) &&
-             aMessageInfo.GetPeerAddr().IsLinkLocal()),
-        rval = false);
+    VerifyOrExit(aDestPort == kUdpPort);
+
+    if (aSourceAddress.IsLinkLocal())
+    {
+        isTmf = aDestAddress.IsLinkLocal() || aDestAddress.IsLinkLocalMulticast();
+        ExitNow();
+    }
+
+    VerifyOrExit(Get<Mle::Mle>().IsMeshLocalAddress(aSourceAddress));
+    VerifyOrExit(Get<Mle::Mle>().IsMeshLocalAddress(aDestAddress) || aDestAddress.IsLinkLocalMulticast() ||
+                 aDestAddress.IsRealmLocalMulticast());
+
+    isTmf = true;
+
 exit:
-    return rval;
+    return isTmf;
 }
 
 } // namespace Tmf
diff --git a/src/core/thread/tmf.hpp b/src/core/thread/tmf.hpp
index 738f665..39e0185 100644
--- a/src/core/thread/tmf.hpp
+++ b/src/core/thread/tmf.hpp
@@ -37,12 +37,93 @@
 #include "openthread-core-config.h"
 
 #include "coap/coap.hpp"
+#include "common/locator.hpp"
 
 namespace ot {
 namespace Tmf {
 
 constexpr uint16_t kUdpPort = 61631; ///< TMF UDP Port
 
+typedef Coap::Message Message; ///< A TMF message.
+
+/**
+ * This class represents message information for a TMF message.
+ *
+ * This is sub-class of `Ip6::MessageInfo` intended for use when sending TMF messages.
+ *
+ */
+class MessageInfo : public InstanceLocator, public Ip6::MessageInfo
+{
+public:
+    /**
+     * This constructor initializes the `MessageInfo`.
+     *
+     * The peer port is set to `Tmf::kUdpPort` and all other properties are cleared (set to zero).
+     *
+     * @param[in] aInstance    The OpenThread instance.
+     *
+     */
+    explicit MessageInfo(Instance &aInstance)
+        : InstanceLocator(aInstance)
+    {
+        SetPeerPort(kUdpPort);
+    }
+
+    /**
+     * This method sets the local socket port to TMF port.
+     *
+     */
+    void SetSockPortToTmf(void) { SetSockPort(kUdpPort); }
+
+    /**
+     * This method sets the local socket address to mesh-local RLOC address.
+     *
+     */
+    void SetSockAddrToRloc(void);
+
+    /**
+     * This method sets the local socket address to RLOC address and the peer socket address to leader ALOC.
+     *
+     * @retval kErrorNone      Successfully set the addresses.
+     * @retval kErrorDetached  Cannot set leader ALOC since device is currently detached.
+     *
+     */
+    Error SetSockAddrToRlocPeerAddrToLeaderAloc(void);
+
+    /**
+     * This method sets the local socket address to RLOC address and the peer socket address to leader RLOC.
+     *
+     * @retval kErrorNone      Successfully set the addresses.
+     * @retval kErrorDetached  Cannot set leader RLOC since device is currently detached.
+     *
+     */
+    Error SetSockAddrToRlocPeerAddrToLeaderRloc(void);
+
+    /**
+     * This method sets the local socket address to RLOC address and the peer socket address to realm-local all
+     * routers multicast address.
+     *
+     */
+    void SetSockAddrToRlocPeerAddrToRealmLocalAllRoutersMulticast(void);
+
+    /**
+     * This method sets the local socket address to RLOC address and the peer socket address to a router RLOC based on
+     * a given RLOC16.
+     *
+     * @param[in] aRloc16     The RLOC16 to use for peer address.
+     *
+     */
+    void SetSockAddrToRlocPeerAddrTo(uint16_t aRloc16);
+
+    /**
+     * This method sets the local socket address to RLOC address and the peer socket address to a given address.
+     *
+     * @param[in] aPeerAddress  The peer address.
+     *
+     */
+    void SetSockAddrToRlocPeerAddrTo(const Ip6::Address &aPeerAddress);
+};
+
 /**
  * This class implements functionality of the Thread TMF agent.
  *
@@ -72,16 +153,26 @@
     Error Start(void);
 
     /**
-     * This method returns whether Thread Management Framework Addressing Rules are met.
+     * This method indicates whether or not a message meets TMF addressing rules.
      *
-     * @retval TRUE   if Thread Management Framework Addressing Rules are met.
-     * @retval FALSE  if Thread Management Framework Addressing Rules are not met.
+     * A TMF message MUST comply with following rules:
+     *
+     * - The destination port is `Tmf::kUdpPort`.
+     * - Both source and destination addresses are Link-Local, or
+     * - Source is Mesh Local and then destination is Mesh Local or Link-Local Multicast or Realm-Local Multicast.
+     *
+     * @param[in] aSourceAddress   Source IPv6 address.
+     * @param[in] aDestAddress     Destination IPv6 address.
+     * @param[in] aDestPort        Destination port number.
+     *
+     * @retval TRUE   if TMF addressing rules are met.
+     * @retval FALSE  if TMF addressing rules are not met.
      *
      */
-    bool IsTmfMessage(const Ip6::MessageInfo &aMessageInfo) const;
+    bool IsTmfMessage(const Ip6::Address &aSourceAddress, const Ip6::Address &aDestAddress, uint16_t aDestPort) const;
 
 private:
-    static Error Filter(const ot::Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext);
+    static Error Filter(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext);
 };
 
 } // namespace Tmf
diff --git a/src/core/thread/topology.cpp b/src/core/thread/topology.cpp
index c8ea45b..0eef0a0 100644
--- a/src/core/thread/topology.cpp
+++ b/src/core/thread/topology.cpp
@@ -33,11 +33,11 @@
 
 #include "topology.hpp"
 
+#include "common/array.hpp"
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
 
 namespace ot {
 
@@ -79,7 +79,7 @@
     mMessageErrorRate = aNeighbor.GetLinkInfo().GetMessageErrorRate();
     mRxOnWhenIdle     = aNeighbor.IsRxOnWhenIdle();
     mFullThreadDevice = aNeighbor.IsFullThreadDevice();
-    mFullNetworkData  = aNeighbor.IsFullNetworkData();
+    mFullNetworkData  = (aNeighbor.GetNetworkDataType() == NetworkData::kFullSet);
 }
 
 void Neighbor::Init(Instance &aInstance)
@@ -154,6 +154,19 @@
     return matches;
 }
 
+#if OPENTHREAD_CONFIG_MULTI_RADIO
+void Neighbor::SetLastRxFragmentTag(uint16_t aTag)
+{
+    mLastRxFragmentTag     = (aTag == 0) ? 0xffff : aTag;
+    mLastRxFragmentTagTime = TimerMilli::GetNow();
+}
+
+bool Neighbor::IsLastRxFragmentTagSet(void) const
+{
+    return (mLastRxFragmentTag != 0) && (TimerMilli::GetNow() <= mLastRxFragmentTagTime + kLastRxFragmentTagTimeout);
+}
+#endif
+
 void Neighbor::GenerateChallenge(void)
 {
     IgnoreError(
@@ -199,18 +212,27 @@
 
 const char *Neighbor::StateToString(State aState)
 {
-    static const char *kStateStrings[] = {
-        "Invalid",        // kStateInvalid
-        "Restored",       // kStateRestored
-        "ParentReq",      // kStateParentRequest
-        "ParentRes",      // kStateParentResponse
-        "ChildIdReq",     // kStateChildIdRequest
-        "LinkReq",        // kStateLinkRequest
-        "ChildUpdateReq", // kStateChildUpdateRequest
-        "Valid",          // kStateValid
+    static const char *const kStateStrings[] = {
+        "Invalid",        // (0) kStateInvalid
+        "Restored",       // (1) kStateRestored
+        "ParentReq",      // (2) kStateParentRequest
+        "ParentRes",      // (3) kStateParentResponse
+        "ChildIdReq",     // (4) kStateChildIdRequest
+        "LinkReq",        // (5) kStateLinkRequest
+        "ChildUpdateReq", // (6) kStateChildUpdateRequest
+        "Valid",          // (7) kStateValid
     };
 
-    return static_cast<uint8_t>(aState) < OT_ARRAY_LENGTH(kStateStrings) ? kStateStrings[aState] : "Unknown";
+    static_assert(0 == kStateInvalid, "kStateInvalid value is incorrect");
+    static_assert(1 == kStateRestored, "kStateRestored value is incorrect");
+    static_assert(2 == kStateParentRequest, "kStateParentRequest value is incorrect");
+    static_assert(3 == kStateParentResponse, "kStateParentResponse value is incorrect");
+    static_assert(4 == kStateChildIdRequest, "kStateChildIdRequest value is incorrect");
+    static_assert(5 == kStateLinkRequest, "kStateLinkRequest value is incorrect");
+    static_assert(6 == kStateChildUpdateRequest, "kStateChildUpdateRequest value is incorrect");
+    static_assert(7 == kStateValid, "kStateValid value is incorrect");
+
+    return kStateStrings[aState];
 }
 
 #if OPENTHREAD_FTD
@@ -233,7 +255,7 @@
     mVersion            = aChild.GetVersion();
     mRxOnWhenIdle       = aChild.IsRxOnWhenIdle();
     mFullThreadDevice   = aChild.IsFullThreadDevice();
-    mFullNetworkData    = aChild.IsFullNetworkData();
+    mFullNetworkData    = (aChild.GetNetworkDataType() == NetworkData::kFullSet);
     mIsStateRestoring   = aChild.IsStateRestoring();
 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
     mIsCslSynced = aChild.IsCslSynchronized();
@@ -465,7 +487,7 @@
 {
     uint16_t addressIndex;
 
-    OT_ASSERT(&mIp6Address[0] <= &aAddress && &aAddress < OT_ARRAY_END(mIp6Address));
+    OT_ASSERT(&mIp6Address[0] <= &aAddress && &aAddress < GetArrayEnd(mIp6Address));
 
     addressIndex = static_cast<uint16_t>(&aAddress - mIp6Address);
 
@@ -478,7 +500,7 @@
 {
     uint16_t addressIndex;
 
-    OT_ASSERT(&mIp6Address[0] <= &aAddress && &aAddress < OT_ARRAY_END(mIp6Address));
+    OT_ASSERT(&mIp6Address[0] <= &aAddress && &aAddress < GetArrayEnd(mIp6Address));
 
     addressIndex = static_cast<uint16_t>(&aAddress - mIp6Address);
 
diff --git a/src/core/thread/topology.hpp b/src/core/thread/topology.hpp
index cfcd199..7783565 100644
--- a/src/core/thread/topology.hpp
+++ b/src/core/thread/topology.hpp
@@ -38,12 +38,14 @@
 
 #include <openthread/thread_ftd.h>
 
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/equatable.hpp"
 #include "common/linked_list.hpp"
 #include "common/locator.hpp"
 #include "common/message.hpp"
 #include "common/random.hpp"
+#include "common/serial_number.hpp"
 #include "common/timer.hpp"
 #include "mac/mac_types.hpp"
 #include "net/ip6.hpp"
@@ -55,6 +57,7 @@
 #include "thread/link_quality.hpp"
 #include "thread/mle_tlvs.hpp"
 #include "thread/mle_types.hpp"
+#include "thread/network_data_types.hpp"
 #include "thread/radio_selector.hpp"
 
 namespace ot {
@@ -352,12 +355,12 @@
     bool IsFullThreadDevice(void) const { return GetDeviceMode().IsFullThreadDevice(); }
 
     /**
-     * This method indicates whether or not the device requests Full Network Data.
+     * This method gets the Network Data type (full set or stable subset) that the device requests.
      *
-     * @returns TRUE if requests Full Network Data, FALSE otherwise.
+     * @returns The Network Data type.
      *
      */
-    bool IsFullNetworkData(void) const { return GetDeviceMode().IsFullNetworkData(); }
+    NetworkData::Type GetNetworkDataType(void) const { return GetDeviceMode().GetNetworkDataType(); }
 
     /**
      * This method sets all bytes of the Extended Address to zero.
@@ -498,7 +501,7 @@
     /**
      * This method clears the last received fragment tag.
      *
-     * The last received fragment tag is used for detect duplicate frames (receievd over different radios) when
+     * The last received fragment tag is used for detect duplicate frames (received over different radios) when
      * multi-radio feature is enabled.
      *
      */
@@ -520,15 +523,15 @@
      * @param[in] aTag   The new tag value.
      *
      */
-    void SetLastRxFragmentTag(uint16_t aTag) { mLastRxFragmentTag = (aTag == 0) ? 0xffff : aTag; }
+    void SetLastRxFragmentTag(uint16_t aTag);
 
     /**
-     * This method indicates whether the last received fragment tag is set or not.
+     * This method indicates whether or not the last received fragment tag is set and valid (i.e., not yet timed out).
      *
-     * @returns TRUE if the last received fragment tag is set, FALSE otherwise.
+     * @returns TRUE if the last received fragment tag is set and valid, FALSE otherwise.
      *
      */
-    bool IsLastRxFragmentTagSet(void) const { return (mLastRxFragmentTag != 0); }
+    bool IsLastRxFragmentTagSet(void) const;
 
     /**
      * This method indicates whether the last received fragment tag is strictly after a given tag value.
@@ -544,25 +547,33 @@
      * before @p aTag.
      *
      */
-    bool IsLastRxFragmentTagAfter(uint16_t aTag) const { return ((aTag - mLastRxFragmentTag) & (1U << 15)) != 0; }
+    bool IsLastRxFragmentTagAfter(uint16_t aTag) const { return SerialNumber::IsGreater(mLastRxFragmentTag, aTag); }
 
 #endif // OPENTHREAD_CONFIG_MULTI_RADIO
 
     /**
-     * This method indicates whether or not it is a valid Thread 1.1 neighbor.
+     * This method indicates whether or not it is Thread 1.1.
      *
-     * @returns TRUE if it is a valid Thread 1.1 neighbor, FALSE otherwise.
+     * @returns TRUE if neighbors is Thread 1.1, FALSE otherwise.
      *
      */
     bool IsThreadVersion1p1(void) const { return mState != kStateInvalid && mVersion == OT_THREAD_VERSION_1_1; }
 
     /**
-     * This method indicates whether or not it is a valid Thread 1.2 neighbor.
+     * This method indicates whether or not neighbor is Thread 1.2 or higher..
      *
-     * @returns TRUE if it is a valid Thread 1.2 neighbor, FALSE otherwise.
+     * @returns TRUE if neighbor is Thread 1.2 or higher, FALSE otherwise.
      *
      */
-    bool IsThreadVersion1p2(void) const { return mState != kStateInvalid && mVersion == OT_THREAD_VERSION_1_2; }
+    bool IsThreadVersion1p2OrHigher(void) const { return mState != kStateInvalid && mVersion >= OT_THREAD_VERSION_1_2; }
+
+    /**
+     * This method indicates whether Thread version supports CSL.
+     *
+     * @returns TRUE if CSL is supported, FALSE otherwise.
+     *
+     */
+    bool IsThreadVersionCslCapable(void) const { return IsThreadVersion1p2OrHigher() && !IsRxOnWhenIdle(); }
 
     /**
      * This method indicates whether Enhanced Keep-Alive is supported or not.
@@ -683,7 +694,7 @@
     /**
      * This method adds a new LinkMetrics::SeriesInfo to the neighbor's list.
      *
-     * @param[in]    A reference to the new SeriesInfo.
+     * @param[in]  aSeriesInfo  A reference to the new SeriesInfo.
      *
      */
     void AddForwardTrackingSeriesInfo(LinkMetrics::SeriesInfo &aSeriesInfo);
@@ -767,6 +778,11 @@
     void Init(Instance &aInstance);
 
 private:
+    enum : uint32_t
+    {
+        kLastRxFragmentTagTimeout = OPENTHREAD_CONFIG_MULTI_RADIO_FRAG_TAG_TIMEOUT, ///< Frag tag timeout in msec.
+    };
+
     Mac::ExtAddress mMacAddr;   ///< The IEEE 802.15.4 Extended Address
     TimeMilli       mLastHeard; ///< Time when last heard.
     union
@@ -786,7 +802,8 @@
     } mValidPending;
 
 #if OPENTHREAD_CONFIG_MULTI_RADIO
-    uint16_t mLastRxFragmentTag; ///< Last received fragment tag
+    uint16_t  mLastRxFragmentTag;     ///< Last received fragment tag
+    TimeMilli mLastRxFragmentTagTime; ///< The time last fragment tag was received and set.
 #endif
 
     uint32_t mKeySequence; ///< Current key sequence
@@ -912,7 +929,7 @@
         /**
          * This method gets the current `Child` IPv6 Address to which the iterator is pointing.
          *
-         * @returns  A pointer to the associated IPv6 Address, or nullptr if iterator is done.
+         * @returns  A pointer to the associated IPv6 Address, or `nullptr` if iterator is done.
          *
          */
         const Ip6::Address *GetAddress(void) const;
@@ -1348,7 +1365,7 @@
         Neighbor::Init(aInstance);
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
         SetCslClockAccuracy(kCslWorstCrystalPpm);
-        SetCslClockUncertainty(kCslWorstUncertainty);
+        SetCslUncertainty(kCslWorstUncertainty);
 #endif
     }
 
@@ -1380,7 +1397,7 @@
      * @returns The link quality out value for this router.
      *
      */
-    uint8_t GetLinkQualityOut(void) const { return mLinkQualityOut; }
+    LinkQuality GetLinkQualityOut(void) const { return static_cast<LinkQuality>(mLinkQualityOut); }
 
     /**
      * This method sets the link quality out value for this router.
@@ -1388,7 +1405,7 @@
      * @param[in]  aLinkQuality  The link quality out value for this router.
      *
      */
-    void SetLinkQualityOut(uint8_t aLinkQuality) { mLinkQualityOut = aLinkQuality; }
+    void SetLinkQualityOut(LinkQuality aLinkQuality) { mLinkQualityOut = aLinkQuality; }
 
     /**
      * This method get the route cost to this router.
@@ -1418,7 +1435,7 @@
     /**
      * This method sets the CSL clock accuracy of this router.
      *
-     * @param[in]  aCost  The CSL clock accuracy of this router.
+     * @param[in]  aCslClockAccuracy  The CSL clock accuracy of this router.
      *
      */
     void SetCslClockAccuracy(uint8_t aCslClockAccuracy) { mCslClockAccuracy = aCslClockAccuracy; }
@@ -1429,15 +1446,15 @@
      * @returns The CSL clock uncertainty of this router.
      *
      */
-    uint8_t GetCslClockUncertainty(void) const { return mCslClockUncertainty; }
+    uint8_t GetCslUncertainty(void) const { return mCslUncertainty; }
 
     /**
      * This method sets the CSL clock uncertainty of this router.
      *
-     * @param[in]  aCost  The CSL clock uncertainty of this router.
+     * @param[in]  aCslUncertainty  The CSL clock uncertainty of this router.
      *
      */
-    void SetCslClockUncertainty(uint8_t aCslClockUncertainty) { mCslClockUncertainty = aCslClockUncertainty; }
+    void SetCslUncertainty(uint8_t aCslUncertainty) { mCslUncertainty = aCslUncertainty; }
 #endif
 
 private:
@@ -1450,11 +1467,17 @@
     uint8_t mCost : 4;     ///< The cost to this router via neighbor router
 #endif
 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-    uint8_t mCslClockAccuracy;    ///< Crystal accuracy, in units of ± ppm.
-    uint8_t mCslClockUncertainty; ///< Scheduling uncertainty, in units of 10 us.
+    uint8_t mCslClockAccuracy; ///< Crystal accuracy, in units of ± ppm.
+    uint8_t mCslUncertainty;   ///< Scheduling uncertainty, in units of 10 us.
 #endif
 };
 
+DefineCoreType(otNeighborInfo, Neighbor::Info);
+#if OPENTHREAD_FTD
+DefineCoreType(otChildInfo, Child::Info);
+#endif
+DefineCoreType(otRouterInfo, Router::Info);
+
 } // namespace ot
 
 #endif // TOPOLOGY_HPP_
diff --git a/src/core/utils/channel_manager.cpp b/src/core/utils/channel_manager.cpp
index 76fc0d7..93c24f5 100644
--- a/src/core/utils/channel_manager.cpp
+++ b/src/core/utils/channel_manager.cpp
@@ -39,14 +39,17 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/random.hpp"
+#include "common/string.hpp"
 #include "meshcop/dataset_updater.hpp"
 #include "radio/radio.hpp"
 
 namespace ot {
 namespace Utils {
 
+RegisterLogModule("ChannelManager");
+
 ChannelManager::ChannelManager(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mSupportedChannelMask(0)
@@ -63,11 +66,11 @@
 
 void ChannelManager::RequestChannelChange(uint8_t aChannel)
 {
-    otLogInfoUtil("ChannelManager: Request to change to channel %d with delay %d sec", aChannel, mDelay);
+    LogInfo("Request to change to channel %d with delay %d sec", aChannel, mDelay);
 
     if (aChannel == Get<Mac::Mac>().GetPanChannel())
     {
-        otLogInfoUtil("ChannelManager: Already operating on the requested channel %d", aChannel);
+        LogInfo("Already operating on the requested channel %d", aChannel);
         ExitNow();
     }
 
@@ -119,7 +122,7 @@
         break;
 
     case kErrorInvalidState:
-        otLogInfoUtil("ChannelManager: Request to change to channel %d failed. Device is disabled", mChannel);
+        LogInfo("Request to change to channel %d failed. Device is disabled", mChannel);
 
         OT_FALL_THROUGH;
 
@@ -139,12 +142,12 @@
 {
     if (aError == kErrorNone)
     {
-        otLogInfoUtil("ChannelManager: Channel changed to %d", mChannel);
+        LogInfo("Channel changed to %d", mChannel);
     }
     else
     {
-        otLogInfoUtil("ChannelManager: Canceling channel change to %d%s", mChannel,
-                      (aError == kErrorAlready) ? " since current ActiveDataset is more recent" : "");
+        LogInfo("Canceling channel change to %d%s", mChannel,
+                (aError == kErrorAlready) ? " since current ActiveDataset is more recent" : "");
     }
 
     mState = kStateIdle;
@@ -161,7 +164,7 @@
     switch (mState)
     {
     case kStateIdle:
-        otLogInfoUtil("ChannelManager: Auto-triggered channel select");
+        LogInfo("Auto-triggered channel select");
         IgnoreError(RequestChannelSelect(false));
         StartAutoSelectTimer();
         break;
@@ -188,8 +191,8 @@
 
     if (Get<ChannelMonitor>().GetSampleCount() <= kMinChannelMonitorSampleCount)
     {
-        otLogInfoUtil("ChannelManager: Too few samples (%d <= %d) to select channel",
-                      Get<ChannelMonitor>().GetSampleCount(), kMinChannelMonitorSampleCount);
+        LogInfo("Too few samples (%d <= %d) to select channel", Get<ChannelMonitor>().GetSampleCount(),
+                kMinChannelMonitorSampleCount);
         ExitNow(error = kErrorInvalidState);
     }
 
@@ -199,10 +202,8 @@
     favoredBest   = Get<ChannelMonitor>().FindBestChannels(favoredAndSupported, favoredOccupancy);
     supportedBest = Get<ChannelMonitor>().FindBestChannels(mSupportedChannelMask, supportedOccupancy);
 
-    otLogInfoUtil("ChannelManager: Best favored %s, occupancy 0x%04x", favoredBest.ToString().AsCString(),
-                  favoredOccupancy);
-    otLogInfoUtil("ChannelManager: Best overall %s, occupancy 0x%04x", supportedBest.ToString().AsCString(),
-                  supportedOccupancy);
+    LogInfo("Best favored %s, occupancy 0x%04x", favoredBest.ToString().AsCString(), favoredOccupancy);
+    LogInfo("Best overall %s, occupancy 0x%04x", supportedBest.ToString().AsCString(), supportedOccupancy);
 
     // Prefer favored channels unless there is no favored channel,
     // or the occupancy rate of the best favored channel is worse
@@ -213,7 +214,7 @@
     {
         if (!favoredBest.IsEmpty())
         {
-            otLogInfoUtil("ChannelManager: Preferring an unfavored channel due to high occupancy rate diff");
+            LogInfo("Preferring an unfavored channel due to high occupancy rate diff");
         }
 
         favoredBest      = supportedBest;
@@ -234,8 +235,8 @@
     uint16_t ccaFailureRate = Get<Mac::Mac>().GetCcaFailureRate();
     bool     shouldAttempt  = (ccaFailureRate >= mCcaFailureRateThreshold);
 
-    otLogInfoUtil("ChannelManager: CCA-err-rate: 0x%04x %s 0x%04x, selecting channel: %s", ccaFailureRate,
-                  shouldAttempt ? ">=" : "<", mCcaFailureRateThreshold, shouldAttempt ? "yes" : "no");
+    LogInfo("CCA-err-rate: 0x%04x %s 0x%04x, selecting channel: %s", ccaFailureRate, shouldAttempt ? ">=" : "<",
+            mCcaFailureRateThreshold, ToYesNo(shouldAttempt));
 
     return shouldAttempt;
 }
@@ -246,8 +247,7 @@
     uint8_t  curChannel, newChannel;
     uint16_t curOccupancy, newOccupancy;
 
-    otLogInfoUtil("ChannelManager: Request to select channel (skip quality check: %s)",
-                  aSkipQualityCheck ? "yes" : "no");
+    LogInfo("Request to select channel (skip quality check: %s)", ToYesNo(aSkipQualityCheck));
 
     VerifyOrExit(!Get<Mle::Mle>().IsDisabled(), error = kErrorInvalidState);
 
@@ -260,12 +260,12 @@
 
     if (newChannel == curChannel)
     {
-        otLogInfoUtil("ChannelManager: Already on best possible channel %d", curChannel);
+        LogInfo("Already on best possible channel %d", curChannel);
         ExitNow();
     }
 
-    otLogInfoUtil("ChannelManager: Cur channel %d, occupancy 0x%04x - Best channel %d, occupancy 0x%04x", curChannel,
-                  curOccupancy, newChannel, newOccupancy);
+    LogInfo("Cur channel %d, occupancy 0x%04x - Best channel %d, occupancy 0x%04x", curChannel, curOccupancy,
+            newChannel, newOccupancy);
 
     // Switch only if new channel's occupancy rate is better than current
     // channel's occupancy rate by threshold `kThresholdToChangeChannel`.
@@ -273,7 +273,7 @@
     if ((newOccupancy >= curOccupancy) ||
         (static_cast<uint16_t>(curOccupancy - newOccupancy) < kThresholdToChangeChannel))
     {
-        otLogInfoUtil("ChannelManager: Occupancy rate diff too small to change channel");
+        LogInfo("Occupancy rate diff too small to change channel");
         ExitNow();
     }
 
@@ -283,7 +283,7 @@
 
     if (error != kErrorNone)
     {
-        otLogInfoUtil("ChannelManager: Request to select better channel failed, error: %s", ErrorToString(error));
+        LogInfo("Request to select better channel failed, error: %s", ErrorToString(error));
     }
 
     return error;
@@ -339,21 +339,21 @@
 {
     mSupportedChannelMask.SetMask(aChannelMask & Get<Mac::Mac>().GetSupportedChannelMask().GetMask());
 
-    otLogInfoUtil("ChannelManager: Supported channels: %s", mSupportedChannelMask.ToString().AsCString());
+    LogInfo("Supported channels: %s", mSupportedChannelMask.ToString().AsCString());
 }
 
 void ChannelManager::SetFavoredChannels(uint32_t aChannelMask)
 {
     mFavoredChannelMask.SetMask(aChannelMask & Get<Mac::Mac>().GetSupportedChannelMask().GetMask());
 
-    otLogInfoUtil("ChannelManager: Favored channels: %s", mFavoredChannelMask.ToString().AsCString());
+    LogInfo("Favored channels: %s", mFavoredChannelMask.ToString().AsCString());
 }
 
 void ChannelManager::SetCcaFailureRateThreshold(uint16_t aThreshold)
 {
     mCcaFailureRateThreshold = aThreshold;
 
-    otLogInfoUtil("ChannelManager: CCA threshold: 0x%04x", mCcaFailureRateThreshold);
+    LogInfo("CCA threshold: 0x%04x", mCcaFailureRateThreshold);
 }
 
 } // namespace Utils
diff --git a/src/core/utils/channel_monitor.cpp b/src/core/utils/channel_monitor.cpp
index a6fe604..8925c64 100644
--- a/src/core/utils/channel_monitor.cpp
+++ b/src/core/utils/channel_monitor.cpp
@@ -37,12 +37,14 @@
 
 #include "common/code_utils.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/random.hpp"
 
 namespace ot {
 namespace Utils {
 
+RegisterLogModule("ChannelMonitor");
+
 const uint32_t ChannelMonitor::mScanChannelMasks[kNumChannelMasks] = {
 #if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
     OT_CHANNEL_1_MASK | OT_CHANNEL_5_MASK | OT_CHANNEL_9_MASK,
@@ -74,7 +76,7 @@
     VerifyOrExit(!IsRunning(), error = kErrorAlready);
     Clear();
     mTimer.Start(kTimerInterval);
-    otLogDebgUtil("ChannelMonitor: Starting");
+    LogDebg("Starting");
 
 exit:
     return error;
@@ -86,7 +88,7 @@
 
     VerifyOrExit(IsRunning(), error = kErrorAlready);
     mTimer.Stop();
-    otLogDebgUtil("ChannelMonitor: Stopping");
+    LogDebg("Stopping");
 
 exit:
     return error;
@@ -98,7 +100,7 @@
     mSampleCount      = 0;
     memset(mChannelOccupancy, 0, sizeof(mChannelOccupancy));
 
-    otLogDebgUtil("ChannelMonitor: Clearing data");
+    LogDebg("Clearing data");
 }
 
 uint16_t ChannelMonitor::GetChannelOccupancy(uint8_t aChannel) const
@@ -154,7 +156,7 @@
 
         OT_ASSERT(channelIndex < kNumChannels);
 
-        otLogDebgUtil("ChannelMonitor: channel: %d, rssi:%d", aResult->mChannel, aResult->mMaxRssi);
+        LogDebg("channel: %d, rssi:%d", aResult->mChannel, aResult->mMaxRssi);
 
         if (aResult->mMaxRssi != OT_RADIO_RSSI_INVALID)
         {
@@ -189,7 +191,7 @@
 
 void ChannelMonitor::LogResults(void)
 {
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_UTIL == 1)
+#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
     const size_t        kStringSize = 128;
     String<kStringSize> logString;
 
@@ -198,7 +200,7 @@
         logString.Append("%02x ", channel >> 8);
     }
 
-    otLogInfoUtil("ChannelMonitor: %u [%s]", mSampleCount, logString.AsCString());
+    LogInfo("%u [%s]", mSampleCount, logString.AsCString());
 #endif
 }
 
diff --git a/src/core/utils/child_supervision.cpp b/src/core/utils/child_supervision.cpp
index 3869113..b0f45bd 100644
--- a/src/core/utils/child_supervision.cpp
+++ b/src/core/utils/child_supervision.cpp
@@ -37,12 +37,14 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "thread/thread_netif.hpp"
 
 namespace ot {
 namespace Utils {
 
+RegisterLogModule("ChildSupervsn");
+
 #if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
 
 #if OPENTHREAD_FTD
@@ -80,7 +82,7 @@
 
     VerifyOrExit(aChild.GetIndirectMessageCount() == 0);
 
-    message = Get<MessagePool>().New(Message::kTypeSupervision, sizeof(uint8_t));
+    message = Get<MessagePool>().Allocate(Message::kTypeSupervision, sizeof(uint8_t));
     VerifyOrExit(message != nullptr);
 
     // Supervision message is an empty payload 15.4 data frame.
@@ -94,7 +96,7 @@
     SuccessOrExit(Get<ThreadNetif>().SendMessage(*message));
     message = nullptr;
 
-    otLogInfoUtil("Sending supervision message to child 0x%04x", aChild.GetRloc16());
+    LogInfo("Sending supervision message to child 0x%04x", aChild.GetRloc16());
 
 exit:
     FreeMessage(message);
@@ -132,13 +134,13 @@
     if (shouldRun && !Get<TimeTicker>().IsReceiverRegistered(TimeTicker::kChildSupervisor))
     {
         Get<TimeTicker>().RegisterReceiver(TimeTicker::kChildSupervisor);
-        otLogInfoUtil("Starting Child Supervision");
+        LogInfo("Starting Child Supervision");
     }
 
     if (!shouldRun && Get<TimeTicker>().IsReceiverRegistered(TimeTicker::kChildSupervisor))
     {
         Get<TimeTicker>().UnregisterReceiver(TimeTicker::kChildSupervisor);
-        otLogInfoUtil("Stopping Child Supervision");
+        LogInfo("Stopping Child Supervision");
     }
 }
 
@@ -213,7 +215,7 @@
 {
     VerifyOrExit(Get<Mle::MleRouter>().IsChild() && !Get<MeshForwarder>().GetRxOnWhenIdle());
 
-    otLogWarnUtil("Supervision timeout. No frame from parent in %d sec", mTimeout);
+    LogWarn("Supervision timeout. No frame from parent in %d sec", mTimeout);
 
     IgnoreError(Get<Mle::MleRouter>().SendChildUpdateRequest());
 
diff --git a/src/core/utils/child_supervision.hpp b/src/core/utils/child_supervision.hpp
index a919fb1..30b26f1 100644
--- a/src/core/utils/child_supervision.hpp
+++ b/src/core/utils/child_supervision.hpp
@@ -143,8 +143,8 @@
      *
      * @param[in] aMessage The message for which to get the destination.
      *
-     * @returns  A pointer to the destination child of the message, or nullptr if @p aMessage is not of supervision
-     * type.
+     * @returns  A pointer to the destination child of the message, or `nullptr` if @p aMessage is not of supervision
+     *           type.
      *
      */
     Child *GetDestination(const Message &aMessage) const;
diff --git a/src/core/utils/flash.cpp b/src/core/utils/flash.cpp
index 3e45586..243d7d5 100644
--- a/src/core/utils/flash.cpp
+++ b/src/core/utils/flash.cpp
@@ -118,7 +118,7 @@
 {
     Error        error       = kErrorNotFound;
     uint16_t     valueLength = 0;
-    int          index       = 0; // This must be initalized to 0. See [Note] in Delete().
+    int          index       = 0; // This must be initialized to 0. See [Note] in Delete().
     uint32_t     offset;
     RecordHeader record;
 
@@ -258,7 +258,7 @@
 Error Flash::Delete(uint16_t aKey, int aIndex)
 {
     Error        error = kErrorNotFound;
-    int          index = 0; // This must be initalized to 0. See [Note] below.
+    int          index = 0; // This must be initialized to 0. See [Note] below.
     RecordHeader record;
 
     for (uint32_t offset = kSwapMarkerSize; offset < mSwapUsed; offset += record.GetSize())
diff --git a/src/core/utils/flash.hpp b/src/core/utils/flash.hpp
index b21937a..795a47a 100644
--- a/src/core/utils/flash.hpp
+++ b/src/core/utils/flash.hpp
@@ -69,15 +69,15 @@
     /**
      * This method fetches the value identified by @p aKey.
      *
-     * @param[in]     aKey          The key associated with the requested value.
-     * @param[in]     aIndex        The index of the specific item to get.
-     * @param[out]    aValue        A pointer to where the value of the setting should be written.
-     *                              May be nullptr if just testing for the presence or length of a key.
-     * @param[inout]  aValueLength  A pointer to the length of the value.
-     *                              When called, this should point to an integer containing the maximum bytes that
-     *                              can be written to @p aValue.
-     *                              At return, the actual length of the setting is written.
-     *                              May be nullptr if performing a presence check.
+     * @param[in]      aKey          The key associated with the requested value.
+     * @param[in]      aIndex        The index of the specific item to get.
+     * @param[out]     aValue        A pointer to where the value of the setting should be written.
+     *                               May be `nullptr` if just testing for the presence or length of a key.
+     * @param[in,out]  aValueLength  A pointer to the length of the value.
+     *                               When called, this should point to an integer containing the maximum bytes that
+     *                               can be written to @p aValue.
+     *                               At return, the actual length of the setting is written.
+     *                               May be `nullptr` if performing a presence check.
      *
      * @retval kErrorNone       The value was fetched successfully.
      * @retval kErrorNotFound   The key was not found.
@@ -93,7 +93,7 @@
      *
      * @param[in]  aKey          The key associated with the value.
      * @param[in]  aValue        A pointer to where the new value of the setting should be read from.
-     *                           MUST NOT be nullptr if @p aValueLength is non-zero.
+     *                           MUST NOT be `nullptr` if @p aValueLength is non-zero.
      * @param[in]  aValueLength  The length of the data pointed to by @p aValue. May be zero.
      *
      * @retval kErrorNone     The value was changed.
@@ -107,7 +107,7 @@
      *
      * @param[in]  aKey          The key associated with the value.
      * @param[in]  aValue        A pointer to where the new value of the setting should be read from.
-     *                           MUST NOT be nullptr if @p aValueLength is non-zero.
+     *                           MUST NOT be `nullptr` if @p aValueLength is non-zero.
      * @param[in]  aValueLength  The length of the data pointed to by @p aValue. May be zero.
      *
      * @retval kErrorNone    The value was added.
diff --git a/src/core/utils/heap.hpp b/src/core/utils/heap.hpp
index c14c477..02b9a5e 100644
--- a/src/core/utils/heap.hpp
+++ b/src/core/utils/heap.hpp
@@ -32,8 +32,8 @@
  *
  */
 
-#ifndef OT_HEAP_HPP_
-#define OT_HEAP_HPP_
+#ifndef OT_UTILS_HEAP_HPP_
+#define OT_UTILS_HEAP_HPP_
 
 #include "openthread-core-config.h"
 
@@ -350,4 +350,4 @@
 
 #endif // !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
 
-#endif // OT_HEAP_HPP_
+#endif // OT_UTILS_HEAP_HPP_
diff --git a/src/core/utils/history_tracker.cpp b/src/core/utils/history_tracker.cpp
index 58266f5..1991465 100644
--- a/src/core/utils/history_tracker.cpp
+++ b/src/core/utils/history_tracker.cpp
@@ -42,6 +42,7 @@
 #include "common/locator_getters.hpp"
 #include "common/string.hpp"
 #include "common/timer.hpp"
+#include "net/ip6_headers.hpp"
 
 namespace ot {
 namespace Utils {
@@ -52,6 +53,9 @@
 HistoryTracker::HistoryTracker(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mTimer(aInstance, HandleTimer)
+#if OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
+    , mPreviousNetworkData(aInstance, mNetworkDataTlvBuffer, 0, sizeof(mNetworkDataTlvBuffer))
+#endif
 {
     mTimer.Start(kAgeCheckPeriod);
 }
@@ -75,33 +79,26 @@
 
 void HistoryTracker::RecordMessage(const Message &aMessage, const Mac::Address &aMacAddresss, MessageType aType)
 {
-    MessageInfo *     entry = nullptr;
-    Ip6::Header       ip6Header;
-    Ip6::Icmp::Header icmp6Header;
-    uint8_t           ip6Proto;
-    uint16_t          checksum;
-    uint16_t          sourcePort;
-    uint16_t          destPort;
+    MessageInfo *entry = nullptr;
+    Ip6::Headers headers;
 
     VerifyOrExit(aMessage.GetType() == Message::kTypeIp6);
 
-    SuccessOrExit(MeshForwarder::ParseIp6UdpTcpHeader(aMessage, ip6Header, checksum, sourcePort, destPort));
-
-    ip6Proto = ip6Header.GetNextHeader();
+    SuccessOrExit(headers.ParseFrom(aMessage));
 
 #if OPENTHREAD_CONFIG_HISTORY_TRACKER_EXCLUDE_THREAD_CONTROL_MESSAGES
-    if (ip6Proto == Ip6::kProtoUdp)
+    if (headers.IsUdp())
     {
         uint16_t port = 0;
 
         switch (aType)
         {
         case kRxMessage:
-            port = destPort;
+            port = headers.GetDestinationPort();
             break;
 
         case kTxMessage:
-            port = sourcePort;
+            port = headers.GetSourcePort();
             break;
         }
 
@@ -109,16 +106,6 @@
     }
 #endif
 
-    if (ip6Proto == Ip6::kProtoIcmp6)
-    {
-        SuccessOrExit(aMessage.Read(sizeof(Ip6::Header), icmp6Header));
-        checksum = icmp6Header.GetChecksum();
-    }
-    else
-    {
-        icmp6Header.Clear();
-    }
-
     switch (aType)
     {
     case kRxMessage:
@@ -132,15 +119,15 @@
 
     VerifyOrExit(entry != nullptr);
 
-    entry->mPayloadLength        = ip6Header.GetPayloadLength();
+    entry->mPayloadLength        = headers.GetIp6Header().GetPayloadLength();
     entry->mNeighborRloc16       = aMacAddresss.IsShort() ? aMacAddresss.GetShort() : kInvalidRloc16;
-    entry->mSource.mAddress      = ip6Header.GetSource();
-    entry->mSource.mPort         = sourcePort;
-    entry->mDestination.mAddress = ip6Header.GetDestination();
-    entry->mDestination.mPort    = destPort;
-    entry->mChecksum             = checksum;
-    entry->mIpProto              = ip6Proto;
-    entry->mIcmp6Type            = icmp6Header.GetType();
+    entry->mSource.mAddress      = headers.GetSourceAddress();
+    entry->mSource.mPort         = headers.GetSourcePort();
+    entry->mDestination.mAddress = headers.GetDestinationAddress();
+    entry->mDestination.mPort    = headers.GetDestinationPort();
+    entry->mChecksum             = headers.GetChecksum();
+    entry->mIpProto              = headers.GetIpProto();
+    entry->mIcmp6Type            = headers.IsIcmp6() ? headers.GetIcmpHeader().GetType() : 0;
     entry->mAveRxRss             = (aType == kRxMessage) ? aMessage.GetRssAverager().GetAverage() : kInvalidRss;
     entry->mLinkSecurity         = aMessage.IsLinkSecurityEnabled();
     entry->mTxSuccess            = (aType == kTxMessage) ? aMessage.GetTxSuccess() : true;
@@ -291,6 +278,86 @@
     return;
 }
 
+#if OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
+void HistoryTracker::RecordNetworkDataChange(void)
+{
+    NetworkData::Iterator            iterator;
+    NetworkData::OnMeshPrefixConfig  prefix;
+    NetworkData::ExternalRouteConfig route;
+
+    // On mesh prefix entries
+
+    iterator = NetworkData::kIteratorInit;
+
+    while (mPreviousNetworkData.GetNextOnMeshPrefix(iterator, prefix) == kErrorNone)
+    {
+        if (!Get<NetworkData::Leader>().ContainsOnMeshPrefix(prefix))
+        {
+            RecordOnMeshPrefixEvent(kNetDataEntryRemoved, prefix);
+        }
+    }
+
+    iterator = NetworkData::kIteratorInit;
+
+    while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefix) == kErrorNone)
+    {
+        if (!mPreviousNetworkData.ContainsOnMeshPrefix(prefix))
+        {
+            RecordOnMeshPrefixEvent(kNetDataEntryAdded, prefix);
+        }
+    }
+
+    // External route entries
+
+    iterator = NetworkData::kIteratorInit;
+
+    while (mPreviousNetworkData.GetNextExternalRoute(iterator, route) == kErrorNone)
+    {
+        if (!Get<NetworkData::Leader>().ContainsExternalRoute(route))
+        {
+            RecordExternalRouteEvent(kNetDataEntryRemoved, route);
+        }
+    }
+
+    iterator = NetworkData::kIteratorInit;
+
+    while (Get<NetworkData::Leader>().GetNextExternalRoute(iterator, route) == kErrorNone)
+    {
+        if (!mPreviousNetworkData.ContainsExternalRoute(route))
+        {
+            RecordExternalRouteEvent(kNetDataEntryAdded, route);
+        }
+    }
+
+    SuccessOrAssert(Get<NetworkData::Leader>().CopyNetworkData(NetworkData::kFullSet, mPreviousNetworkData));
+}
+
+void HistoryTracker::RecordOnMeshPrefixEvent(NetDataEvent aEvent, const NetworkData::OnMeshPrefixConfig &aPrefix)
+{
+    OnMeshPrefixInfo *entry = mOnMeshPrefixHistory.AddNewEntry();
+
+    VerifyOrExit(entry != nullptr);
+    entry->mPrefix = aPrefix;
+    entry->mEvent  = aEvent;
+
+exit:
+    return;
+}
+
+void HistoryTracker::RecordExternalRouteEvent(NetDataEvent aEvent, const NetworkData::ExternalRouteConfig &aRoute)
+{
+    ExternalRouteInfo *entry = mExternalRouteHistory.AddNewEntry();
+
+    VerifyOrExit(entry != nullptr);
+    entry->mRoute = aRoute;
+    entry->mEvent = aEvent;
+
+exit:
+    return;
+}
+
+#endif // OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
+
 void HistoryTracker::HandleNotifierEvents(Events aEvents)
 {
     if (aEvents.ContainsAny(kEventThreadRoleChanged | kEventThreadRlocAdded | kEventThreadRlocRemoved |
@@ -298,6 +365,13 @@
     {
         RecordNetworkInfo();
     }
+
+#if OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
+    if (aEvents.Contains(kEventThreadNetdataChanged))
+    {
+        RecordNetworkDataChange();
+    }
+#endif
 }
 
 void HistoryTracker::HandleTimer(Timer &aTimer)
@@ -313,6 +387,8 @@
     mRxHistory.UpdateAgedEntries();
     mTxHistory.UpdateAgedEntries();
     mNeighborHistory.UpdateAgedEntries();
+    mOnMeshPrefixHistory.UpdateAgedEntries();
+    mExternalRouteHistory.UpdateAgedEntries();
 
     mTimer.Start(kAgeCheckPeriod);
 }
@@ -323,21 +399,22 @@
 
     if (aEntryAge >= kMaxAge)
     {
-        writer.Append("more than %u days", kMaxAge / kOneDayInMsec);
+        writer.Append("more than %u days", kMaxAge / Time::kOneDayInMsec);
     }
     else
     {
-        uint32_t days = aEntryAge / kOneDayInMsec;
+        uint32_t days = aEntryAge / Time::kOneDayInMsec;
 
         if (days > 0)
         {
             writer.Append("%u day%s ", days, (days == 1) ? "" : "s");
-            aEntryAge -= days * kOneDayInMsec;
+            aEntryAge -= days * Time::kOneDayInMsec;
         }
 
-        writer.Append("%02u:%02u:%02u.%03u", (aEntryAge / kOneHourInMsec),
-                      (aEntryAge % kOneHourInMsec) / kOneMinuteInMsec,
-                      (aEntryAge % kOneMinuteInMsec) / kOneSecondInMsec, (aEntryAge % kOneSecondInMsec));
+        writer.Append("%02u:%02u:%02u.%03u", (aEntryAge / Time::kOneHourInMsec),
+                      (aEntryAge % Time::kOneHourInMsec) / Time::kOneMinuteInMsec,
+                      (aEntryAge % Time::kOneMinuteInMsec) / Time::kOneSecondInMsec,
+                      (aEntryAge % Time::kOneSecondInMsec));
     }
 }
 
diff --git a/src/core/utils/history_tracker.hpp b/src/core/utils/history_tracker.hpp
index 181b76f..3a0a2ee 100644
--- a/src/core/utils/history_tracker.hpp
+++ b/src/core/utils/history_tracker.hpp
@@ -41,6 +41,7 @@
 #include <openthread/history_tracker.h>
 #include <openthread/platform/radio.h>
 
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/locator.hpp"
 #include "common/non_copyable.hpp"
@@ -52,10 +53,20 @@
 #include "thread/mle.hpp"
 #include "thread/mle_types.hpp"
 #include "thread/neighbor_table.hpp"
+#include "thread/network_data.hpp"
 
 namespace ot {
 namespace Utils {
 
+#ifdef OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
+#error "OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA should not be defined directly." \
+       "It is derived from other configs: on-mesh prefix and external route history list sizes"
+#endif
+
+#define OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA                       \
+    ((OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_MESH_PREFIX_LIST_SIZE > 0) || \
+     (OPENTHREAD_CONFIG_HISTORY_TRACKER_EXTERNAL_ROUTE_LIST_SIZE > 0))
+
 /**
  * This class implements History Tracker.
  *
@@ -109,35 +120,13 @@
         void      SetInitTime(void) { mData32 = TimerMilli::GetNow().GetValue(); }
     };
 
-    /**
-     * This type represents Thread network info.
-     *
-     */
-    typedef otHistoryTrackerNetworkInfo NetworkInfo;
-
-    /**
-     * This structure represents a unicast IPv6 address info.
-     *
-     */
-    typedef otHistoryTrackerUnicastAddressInfo UnicastAddressInfo;
-
-    /**
-     * This structure represent a multicast IPv6 address info.
-     *
-     */
-    typedef otHistoryTrackerMulticastAddressInfo MulticastAddressInfo;
-
-    /**
-     * This type represents a RX/TX IPv6 message info.
-     *
-     */
-    typedef otHistoryTrackerMessageInfo MessageInfo;
-
-    /**
-     * This type represents a neighbor info.
-     *
-     */
-    typedef otHistoryTrackerNeighborInfo NeighborInfo;
+    typedef otHistoryTrackerNetworkInfo          NetworkInfo;          ///< Thread network info.
+    typedef otHistoryTrackerUnicastAddressInfo   UnicastAddressInfo;   ///< Unicast IPv6 address info.
+    typedef otHistoryTrackerMulticastAddressInfo MulticastAddressInfo; ///< Multicast IPv6 address info.
+    typedef otHistoryTrackerMessageInfo          MessageInfo;          ///< RX/TX IPv6 message info.
+    typedef otHistoryTrackerNeighborInfo         NeighborInfo;         ///< Neighbor info.
+    typedef otHistoryTrackerOnMeshPrefixInfo     OnMeshPrefixInfo;     ///< Network Data on mesh prefix info.
+    typedef otHistoryTrackerExternalRouteInfo    ExternalRouteInfo;    ///< Network Data external route info
 
     /**
      * This constructor initializes the `HistoryTracker`.
@@ -150,10 +139,11 @@
     /**
      * This method iterates over the entries in the network info history list.
      *
-     * @param[inout] aIterator  An iterator. MUST be initialized.
-     * @param[out]   aEntryAge  A reference to a variable to output the entry's age.
-     *                          Age is provided as the duration (in milliseconds) from when entry was recorded to
-     *                          @p aIterator initialization time. It is set to `kMaxAge` for entries older than max age.
+     * @param[in,out] aIterator  An iterator. MUST be initialized.
+     * @param[out]    aEntryAge  A reference to a variable to output the entry's age.
+     *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
+     *                           @p aIterator initialization time. It is set to `kMaxAge` for entries older than max
+     *                           age.
      *
      * @returns A pointer to `NetworkInfo` entry or `nullptr` if no more entries in the list.
      *
@@ -166,10 +156,11 @@
     /**
      * This method iterates over the entries in the unicast address history list.
      *
-     * @param[inout] aIterator  An iterator. MUST be initialized.
-     * @param[out]   aEntryAge  A reference to a variable to output the entry's age.
-     *                          Age is provided as the duration (in milliseconds) from when entry was recorded to
-     *                          @p aIterator initialization time. It is set to `kMaxAge` for entries older than max age.
+     * @param[in,out] aIterator  An iterator. MUST be initialized.
+     * @param[out]    aEntryAge  A reference to a variable to output the entry's age.
+     *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
+     *                           @p aIterator initialization time. It is set to `kMaxAge` for entries older than max
+     *                           age.
      *
      * @returns A pointer to `UnicastAddress` entry or `nullptr` if no more entries in the list.
      *
@@ -182,10 +173,11 @@
     /**
      * This method iterates over the entries in the multicast address history list.
      *
-     * @param[inout] aIterator  An iterator. MUST be initialized.
-     * @param[out]   aEntryAge  A reference to a variable to output the entry's age.
-     *                          Age is provided as the duration (in milliseconds) from when entry was recorded to
-     *                          @p aIterator initialization time. It is set to `kMaxAge` for entries older than max age.
+     * @param[in,out] aIterator  An iterator. MUST be initialized.
+     * @param[out]    aEntryAge  A reference to a variable to output the entry's age.
+     *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
+     *                           @p aIterator initialization time. It is set to `kMaxAge` for entries older than max
+     *                           age.
      *
      * @returns A pointer to `MulticastAddress` entry or `nullptr` if no more entries in the list.
      *
@@ -198,10 +190,11 @@
     /**
      * This method iterates over the entries in the RX history list.
      *
-     * @param[inout] aIterator  An iterator. MUST be initialized.
-     * @param[out]   aEntryAge  A reference to a variable to output the entry's age.
-     *                          Age is provided as the duration (in milliseconds) from when entry was recorded to
-     *                          @p aIterator initialization time. It is set to `kMaxAge` for entries older than max age.
+     * @param[in,out] aIterator  An iterator. MUST be initialized.
+     * @param[out]    aEntryAge  A reference to a variable to output the entry's age.
+     *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
+     *                           @p aIterator initialization time. It is set to `kMaxAge` for entries older than max
+     *                           age.
      *
      * @returns A pointer to `MessageInfo` entry or `nullptr` if no more entries in the list.
      *
@@ -214,10 +207,11 @@
     /**
      * This method iterates over the entries in the TX history list.
      *
-     * @param[inout] aIterator  An iterator. MUST be initialized.
-     * @param[out]   aEntryAge  A reference to a variable to output the entry's age.
-     *                          Age is provided as the duration (in milliseconds) from when entry was recorded to
-     *                          @p aIterator initialization time. It is set to `kMaxAge` for entries older than max age.
+     * @param[in,out] aIterator  An iterator. MUST be initialized.
+     * @param[out]    aEntryAge  A reference to a variable to output the entry's age.
+     *                           Age is provided as the duration (in milliseconds) from when entry was recorded to
+     *                           @p aIterator initialization time. It is set to `kMaxAge` for entries older than max
+     *                           age.
      *
      * @returns A pointer to `MessageInfo` entry or `nullptr` if no more entries in the list.
      *
@@ -232,6 +226,16 @@
         return mNeighborHistory.Iterate(aIterator, aEntryAge);
     }
 
+    const OnMeshPrefixInfo *IterateOnMeshPrefixHistory(Iterator &aIterator, uint32_t &aEntryAge) const
+    {
+        return mOnMeshPrefixHistory.Iterate(aIterator, aEntryAge);
+    }
+
+    const ExternalRouteInfo *IterateExternalRouteHistory(Iterator &aIterator, uint32_t &aEntryAge) const
+    {
+        return mExternalRouteHistory.Iterate(aIterator, aEntryAge);
+    }
+
     /**
      * This static method converts a given entry age to a human-readable string.
      *
@@ -249,16 +253,11 @@
     static void EntryAgeToString(uint32_t aEntryAge, char *aBuffer, uint16_t aSize);
 
 private:
-    static constexpr uint32_t kOneSecondInMsec = 1000;
-    static constexpr uint32_t kOneMinuteInMsec = 60 * kOneSecondInMsec;
-    static constexpr uint32_t kOneHourInMsec   = 60 * kOneMinuteInMsec;
-    static constexpr uint32_t kOneDayInMsec    = 24 * kOneHourInMsec;
-
     // `Timestamp` uses `uint32_t` value. `2^32` msec is 49 days, 17
     // hours, 2 minutes and 47 seconds and 296 msec. We use 49 days
     // as `kMaxAge` and check for aged entries every 16 hours.
 
-    static constexpr uint32_t kAgeCheckPeriod = 16 * kOneHourInMsec;
+    static constexpr uint32_t kAgeCheckPeriod = 16 * Time::kOneHourInMsec;
 
     static constexpr uint16_t kNetInfoListSize       = OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_INFO_LIST_SIZE;
     static constexpr uint16_t kUnicastAddrListSize   = OPENTHREAD_CONFIG_HISTORY_TRACKER_UNICAST_ADDRESS_LIST_SIZE;
@@ -266,6 +265,8 @@
     static constexpr uint16_t kRxListSize            = OPENTHREAD_CONFIG_HISTORY_TRACKER_RX_LIST_SIZE;
     static constexpr uint16_t kTxListSize            = OPENTHREAD_CONFIG_HISTORY_TRACKER_TX_LIST_SIZE;
     static constexpr uint16_t kNeighborListSize      = OPENTHREAD_CONFIG_HISTORY_TRACKER_NEIGHBOR_LIST_SIZE;
+    static constexpr uint16_t kOnMeshPrefixListSize  = OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_MESH_PREFIX_LIST_SIZE;
+    static constexpr uint16_t kExternalRouteListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_EXTERNAL_ROUTE_LIST_SIZE;
 
     typedef otHistoryTrackerAddressEvent AddressEvent;
 
@@ -282,6 +283,11 @@
     static constexpr NeighborEvent kNeighborChanged   = OT_HISTORY_TRACKER_NEIGHBOR_EVENT_CHANGED;
     static constexpr NeighborEvent kNeighborRestoring = OT_HISTORY_TRACKER_NEIGHBOR_EVENT_RESTORING;
 
+    typedef otHistoryTrackerNetDataEvent NetDataEvent;
+
+    static constexpr NetDataEvent kNetDataEntryAdded   = OT_HISTORY_TRACKER_NET_DATA_ENTRY_ADDED;
+    static constexpr NetDataEvent kNetDataEntryRemoved = OT_HISTORY_TRACKER_NET_DATA_ENTRY_REMOVED;
+
     class Timestamp
     {
     public:
@@ -383,6 +389,11 @@
     void        HandleNotifierEvents(Events aEvents);
     static void HandleTimer(Timer &aTimer);
     void        HandleTimer(void);
+#if OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
+    void RecordNetworkDataChange(void);
+    void RecordOnMeshPrefixEvent(NetDataEvent aEvent, const NetworkData::OnMeshPrefixConfig &aPrefix);
+    void RecordExternalRouteEvent(NetDataEvent aEvent, const NetworkData::ExternalRouteConfig &aRoute);
+#endif
 
     EntryList<NetworkInfo, kNetInfoListSize>                mNetInfoHistory;
     EntryList<UnicastAddressInfo, kUnicastAddrListSize>     mUnicastAddressHistory;
@@ -390,11 +401,27 @@
     EntryList<MessageInfo, kRxListSize>                     mRxHistory;
     EntryList<MessageInfo, kTxListSize>                     mTxHistory;
     EntryList<NeighborInfo, kNeighborListSize>              mNeighborHistory;
+    EntryList<OnMeshPrefixInfo, kOnMeshPrefixListSize>      mOnMeshPrefixHistory;
+    EntryList<ExternalRouteInfo, kExternalRouteListSize>    mExternalRouteHistory;
 
     TimerMilli mTimer;
+
+#if OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
+    NetworkData::MutableNetworkData mPreviousNetworkData;
+
+    uint8_t mNetworkDataTlvBuffer[NetworkData::NetworkData::kMaxSize];
+#endif
 };
 
 } // namespace Utils
+
+DefineCoreType(otHistoryTrackerIterator, Utils::HistoryTracker::Iterator);
+DefineCoreType(otHistoryTrackerNetworkInfo, Utils::HistoryTracker::NetworkInfo);
+DefineCoreType(otHistoryTrackerMessageInfo, Utils::HistoryTracker::MessageInfo);
+DefineCoreType(otHistoryTrackerNeighborInfo, Utils::HistoryTracker::NeighborInfo);
+DefineCoreType(otHistoryTrackerOnMeshPrefixInfo, Utils::HistoryTracker::OnMeshPrefixInfo);
+DefineCoreType(otHistoryTrackerExternalRouteInfo, Utils::HistoryTracker::ExternalRouteInfo);
+
 } // namespace ot
 
 #endif // OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
diff --git a/src/core/utils/jam_detector.cpp b/src/core/utils/jam_detector.cpp
index 62843f5..ce4a4bc 100644
--- a/src/core/utils/jam_detector.cpp
+++ b/src/core/utils/jam_detector.cpp
@@ -38,13 +38,15 @@
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/random.hpp"
 #include "thread/thread_netif.hpp"
 
 namespace ot {
 namespace Utils {
 
+RegisterLogModule("JamDetector");
+
 JamDetector::JamDetector(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mHandler(nullptr)
@@ -73,7 +75,7 @@
     mContext = aContext;
     mEnabled = true;
 
-    otLogInfoUtil("JamDetector - Started");
+    LogInfo("Started");
 
     CheckState();
 
@@ -92,7 +94,7 @@
 
     mTimer.Stop();
 
-    otLogInfoUtil("JamDetector - Stopped");
+    LogInfo("Stopped");
 
 exit:
     return error;
@@ -128,7 +130,7 @@
 void JamDetector::SetRssiThreshold(int8_t aThreshold)
 {
     mRssiThreshold = aThreshold;
-    otLogInfoUtil("JamDetector - RSSI threshold set to %d", mRssiThreshold);
+    LogInfo("RSSI threshold set to %d", mRssiThreshold);
 }
 
 Error JamDetector::SetWindow(uint8_t aWindow)
@@ -139,7 +141,7 @@
     VerifyOrExit(aWindow <= kMaxWindow, error = kErrorInvalidArgs);
 
     mWindow = aWindow;
-    otLogInfoUtil("JamDetector - window set to %d", mWindow);
+    LogInfo("window set to %d", mWindow);
 
 exit:
     return error;
@@ -153,7 +155,7 @@
     VerifyOrExit(aBusyPeriod <= mWindow, error = kErrorInvalidArgs);
 
     mBusyPeriod = aBusyPeriod;
-    otLogInfoUtil("JamDetector - busy period set to %d", mBusyPeriod);
+    LogInfo("busy period set to %d", mBusyPeriod);
 
 exit:
     return error;
@@ -218,7 +220,7 @@
 
     // If we reached end of current one second interval, update the history bitmap
 
-    if (interval >= kOneSecondInterval)
+    if (interval >= Time::kOneSecondInMsec)
     {
         mHistoryBitmap <<= 1;
 
@@ -229,7 +231,7 @@
 
         mAlwaysAboveThreshold = true;
 
-        mCurSecondStartTime += (interval / kOneSecondInterval) * kOneSecondInterval;
+        mCurSecondStartTime += (interval / Time::kOneSecondInMsec) * Time::kOneSecondInMsec;
 
         UpdateJamState();
     }
@@ -261,7 +263,7 @@
     {
         mJamState           = aNewState;
         shouldInvokeHandler = true;
-        otLogInfoUtil("JamDetector - jamming %s", mJamState ? "detected" : "cleared");
+        LogInfo("Jamming %s", mJamState ? "detected" : "cleared");
     }
 
     if (shouldInvokeHandler)
diff --git a/src/core/utils/jam_detector.hpp b/src/core/utils/jam_detector.hpp
index f1e84fc..98dc5e2 100644
--- a/src/core/utils/jam_detector.hpp
+++ b/src/core/utils/jam_detector.hpp
@@ -111,7 +111,7 @@
     /**
      * Set the Jam Detection RSSI Threshold (in dBm).
      *
-     * @param[in]  aRssiThreshold  The RSSI threshold.
+     * @param[in]  aThreshold  The RSSI threshold.
      *
      */
     void SetRssiThreshold(int8_t aThreshold);
@@ -181,10 +181,9 @@
     static constexpr uint8_t kMaxWindow            = 63; // Max window size
     static constexpr int8_t  kDefaultRssiThreshold = 0;
 
-    static constexpr uint16_t kMaxSampleInterval = 256;  // in ms
-    static constexpr uint16_t kMinSampleInterval = 2;    // in ms
-    static constexpr uint32_t kMaxRandomDelay    = 4;    // in ms
-    static constexpr uint32_t kOneSecondInterval = 1000; // in ms
+    static constexpr uint16_t kMaxSampleInterval = 256; // in ms
+    static constexpr uint16_t kMinSampleInterval = 2;   // in ms
+    static constexpr uint32_t kMaxRandomDelay    = 4;   // in ms
 
     void        CheckState(void);
     void        SetJamState(bool aNewState);
diff --git a/src/core/utils/lookup_table.hpp b/src/core/utils/lookup_table.hpp
deleted file mode 100644
index 6779588..0000000
--- a/src/core/utils/lookup_table.hpp
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- *  Copyright (c) 2020, The OpenThread Authors.
- *  All rights reserved.
- *
- *  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, 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
- *   This file includes definitions for lookup table (binary search) functionality.
- */
-
-#ifndef LOOKUP_TABLE_HPP_
-#define LOOKUP_TABLE_HPP_
-
-#include <stdint.h>
-
-#include "common/error.hpp"
-
-namespace ot {
-namespace Utils {
-
-/**
- * This class implements lookup table (using binary search) functionality.
- *
- */
-class LookupTable
-{
-public:
-    /**
-     * This struct represents an example of a lookup table entry.
-     *
-     */
-    struct Entry
-    {
-        /**
-         * This constructor initializes the entry with a given name.
-         *
-         * @param[in] aName   The null-terminated name string with which to initialize the entry.
-         *
-         */
-        constexpr explicit Entry(const char *aName)
-            : mName(aName)
-        {
-        }
-
-        const char *const mName;
-    };
-
-    /**
-     * This template method indicates whether a given entry table array is sorted based on entry's name string and in
-     * alphabetical order and contains not duplicate entries.
-     *
-     * This method is `constexpr` and is intended for use in `static_assert`s to verify that a `constexpr` lookup table
-     * array is sorted.
-     *
-     * @tparam EntryType   The table entry type. The `EntryType` MUST provide `mName` member variable as a `const
-     *                     char *`. For example, this can be realized by `EntryType` being a subclass of `Entry`.
-     * @tparam kLength     The array length (number of entries in the array).
-     *
-     * @note In the common use of this method as `IsSorted(sTable)` where sTable` is a fixed size array, the template
-     * types/parameters do not need to be explicitly specified and can be deduced from the passed-in argument.
-     *
-     * @param[in] aTable  A reference to an array of `kLength` entries on type `EntryType`
-     *
-     * @retval TRUE   If the entries in @p aTable are sorted (alphabetical order).
-     * @retval FALSE  If the entries in @p aTable are not sorted.
-     *
-     */
-    template <class EntryType, uint16_t kLength> static constexpr bool IsSorted(const EntryType (&aTable)[kLength])
-    {
-        return IsSorted(&aTable[0], kLength);
-    }
-
-    /**
-     * This template method performs binary search in a given sorted table array to find an entry matching a given name.
-     *
-     * @note This method requires the array to be sorted, otherwise its behavior is undefined.
-     *
-     * @tparam EntryType   The table entry type. The `EntryType` MUST provide `mName` member variable as a `const
-     *                     char *`. For example, this can be realized by `EntryType` being a subclass of `Entry`.
-     * @tparam kLength     The array length (number of entries in the array).
-     *
-     * @note In the common use of this method as `Find(name, sTable)` where sTable` is a fixed size array, the template
-     * types/parameters do not need to be explicitly specified and can be deduced from the passed-in argument.
-     *
-     * @param[in] aName   A name string to search for within the table.
-     * @param[in] aTable  A reference to an array of `kLength` entries on type `EntryType`
-     *
-     * @returns A pointer to the entry in the table if a match is found, otherwise nullptr (no match in table).
-     *
-     */
-    template <class EntryType, uint16_t kLength>
-    static const EntryType *Find(const char *aName, const EntryType (&aTable)[kLength])
-    {
-        return reinterpret_cast<const EntryType *>(
-            Find(aName, &aTable[0], kLength, sizeof(aTable[0]), GetName<EntryType>));
-    }
-
-private:
-    typedef const char *(&NameGetter)(const void *aPointer);
-
-    template <class EntryType> static const char *GetName(const void *aPointer)
-    {
-        return reinterpret_cast<const EntryType *>(aPointer)->mName;
-    }
-
-    template <class EntryType> static constexpr bool IsSorted(const EntryType *aTable, uint16_t aLength)
-    {
-        return (aLength <= 1) ? true
-                              : AreInOrder(aTable[0].mName, aTable[1].mName) && IsSorted(aTable + 1, aLength - 1);
-    }
-
-    constexpr static bool AreInOrder(const char *aFirst, const char *aSecond)
-    {
-        return (*aFirst < *aSecond)
-                   ? true
-                   : ((*aFirst > *aSecond) || (*aFirst == '\0') ? false : AreInOrder(aFirst + 1, aSecond + 1));
-    }
-
-    static const void *Find(const char *aName,
-                            const void *aTable,
-                            uint16_t    aLength,
-                            uint16_t    aTableEntrySize,
-                            NameGetter  aNameGetter);
-};
-
-} // namespace Utils
-} // namespace ot
-
-#endif // LOOKUP_TABLE_HPP_
diff --git a/src/core/utils/otns.cpp b/src/core/utils/otns.cpp
index 40f5a49..0030fba 100644
--- a/src/core/utils/otns.cpp
+++ b/src/core/utils/otns.cpp
@@ -38,11 +38,13 @@
 
 #include "common/debug.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 
 namespace ot {
 namespace Utils {
 
+RegisterLogModule("Otns");
+
 const int kMaxStatusStringLength = 128;
 
 void Otns::EmitShortAddress(uint16_t aShortAddress)
@@ -155,7 +157,7 @@
 void Otns::EmitDeviceMode(Mle::DeviceMode aMode)
 {
     EmitStatus("mode=%s%s%s", aMode.IsRxOnWhenIdle() ? "r" : "", aMode.IsFullThreadDevice() ? "d" : "",
-               aMode.IsFullNetworkData() ? "n" : "");
+               (aMode.GetNetworkDataType() == NetworkData::kFullSet) ? "n" : "");
 }
 
 void Otns::EmitCoapSend(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
@@ -170,7 +172,7 @@
 exit:
     if (error != kErrorNone)
     {
-        otLogWarnCore("Otns::EmitCoapSend failed: %s", ErrorToString(error));
+        LogWarn("EmitCoapSend failed: %s", ErrorToString(error));
     }
 }
 
@@ -186,7 +188,7 @@
 exit:
     if (error != kErrorNone)
     {
-        otLogWarnCore("Otns::EmitCoapReceive failed: %s", ErrorToString(error));
+        LogWarn("EmitCoapReceive failed: %s", ErrorToString(error));
     }
 }
 
@@ -203,7 +205,7 @@
 exit:
     if (error != kErrorNone)
     {
-        otLogWarnCore("Otns::EmitCoapSendFailure failed: %s", ErrorToString(error));
+        LogWarn("EmitCoapSendFailure failed: %s", ErrorToString(error));
     }
 }
 
diff --git a/src/core/utils/parse_cmdline.hpp b/src/core/utils/parse_cmdline.hpp
index 88b0cc8..6b9025f 100644
--- a/src/core/utils/parse_cmdline.hpp
+++ b/src/core/utils/parse_cmdline.hpp
@@ -249,10 +249,10 @@
  * This function correctly handles hex strings with even or odd length. For example, "AABBCCDD" (with even length) is
  * parsed as {0xaa, 0xbb, 0xcc, 0xdd} and "123" (with odd length) is parsed as {0x01, 0x23}.
  *
- * @param[in]     aString   The string to parse.
- * @param[inout]  aSize     On entry indicates the number of bytes in @p aBuffer (max size of @p aBuffer).
- *                          On exit provides number of bytes parsed and copied into @p aBuffer.
- * @param[out]    aBuffer   A pointer to a buffer to output the parsed byte sequence.
+ * @param[in]      aString   The string to parse.
+ * @param[in,out]  aSize     On entry indicates the number of bytes in @p aBuffer (max size of @p aBuffer).
+ *                           On exit provides number of bytes parsed and copied into @p aBuffer.
+ * @param[out]     aBuffer   A pointer to a buffer to output the parsed byte sequence.
  *
  * @retval kErrorNone        The string was parsed successfully.
  * @retval kErrorInvalidArgs The string does not contain valid format or too many bytes.
@@ -271,10 +271,10 @@
  * This function correctly handles hex strings with even or odd length. For example, "AABBCCDD" (with even length) is
  * parsed as {0xaa, 0xbb, 0xcc, 0xdd} and "123" (with odd length) is parsed as {0x01, 0x23}.
  *
- * @param[inout] aString     A reference to string to parse. On successful parse, updated to skip parsed digits.
- * @param[inout] aSize       On entry indicates the segment size (number of bytes in @p aBuffer).
+ * @param[in,out] aString    A reference to string to parse. On successful parse, updated to skip parsed digits.
+ * @param[in,out] aSize      On entry indicates the segment size (number of bytes in @p aBuffer).
  *                           On exit provides number of bytes parsed and copied into @p aBuffer.
- * @param[out]   aBuffer     A pointer to a buffer to output the parsed byte sequence.
+ * @param[out]    aBuffer    A pointer to a buffer to output the parsed byte sequence.
  *
  * @retval kErrorNone        The string was parsed successfully to the end of string.
  * @retval kErrorPedning     The string segment was parsed successfully, but there are additional bytes remaining
@@ -557,9 +557,9 @@
      *
      * This method verifies that the parsed hex string bytes fit in @p aBuffer with its given @p aSize.
      *
-     * @param[inout]  aSize     On entry indicates the number of bytes in @p aBuffer (max size of @p aBuffer).
+     * @param[in,out]  aSize    On entry indicates the number of bytes in @p aBuffer (max size of @p aBuffer).
      *                          On exit provides number of bytes parsed and copied into @p aBuffer.
-     * @param[out]    aBuffer   A pointer to a buffer to output the parsed byte sequence.
+     * @param[out]     aBuffer  A pointer to a buffer to output the parsed byte sequence.
      *
      * @retval kErrorNone        The argument was parsed successfully.
      * @retval kErrorInvalidArgs The argument does not contain valid format or too many bytes.
diff --git a/src/core/utils/ping_sender.hpp b/src/core/utils/ping_sender.hpp
index 9de352f..aae63c7 100644
--- a/src/core/utils/ping_sender.hpp
+++ b/src/core/utils/ping_sender.hpp
@@ -40,6 +40,7 @@
 
 #include <openthread/ping_sender.h>
 
+#include "common/as_core_type.hpp"
 #include "common/code_utils.hpp"
 #include "common/locator.hpp"
 #include "common/message.hpp"
@@ -100,7 +101,7 @@
          * @returns The ping source IPv6 address.
          *
          */
-        Ip6::Address &GetSource(void) { return static_cast<Ip6::Address &>(mSource); }
+        Ip6::Address &GetSource(void) { return AsCoreType(&mSource); }
 
         /**
          * This method gets the source IPv6 address of the ping.
@@ -108,7 +109,7 @@
          * @returns The ping source IPv6 address.
          *
          */
-        const Ip6::Address &GetSource(void) const { return static_cast<const Ip6::Address &>(mSource); }
+        const Ip6::Address &GetSource(void) const { return AsCoreType(&mSource); }
 
         /**
          * This method gets the destination IPv6 address to ping.
@@ -116,7 +117,7 @@
          * @returns The ping destination IPv6 address.
          *
          */
-        Ip6::Address &GetDestination(void) { return static_cast<Ip6::Address &>(mDestination); }
+        Ip6::Address &GetDestination(void) { return AsCoreType(&mDestination); }
 
         /**
          * This method gets the destination IPv6 address to ping.
@@ -124,7 +125,7 @@
          * @returns The ping destination IPv6 address.
          *
          */
-        const Ip6::Address &GetDestination(void) const { return static_cast<const Ip6::Address &>(mDestination); }
+        const Ip6::Address &GetDestination(void) const { return AsCoreType(&mDestination); }
 
     private:
         static constexpr uint16_t kDefaultSize     = OPENTHREAD_CONFIG_PING_SENDER_DEFAULT_SIZE;
@@ -184,6 +185,11 @@
 };
 
 } // namespace Utils
+
+DefineCoreType(otPingSenderReply, Utils::PingSender::Reply);
+DefineCoreType(otPingSenderConfig, Utils::PingSender::Config);
+DefineCoreType(otPingSenderStatistics, Utils::PingSender::Statistics);
+
 } // namespace ot
 
 #endif // OPENTHREAD_CONFIG_PING_SENDER_ENABLE
diff --git a/src/core/utils/slaac_address.cpp b/src/core/utils/slaac_address.cpp
index 6e162df..82cadfc 100644
--- a/src/core/utils/slaac_address.cpp
+++ b/src/core/utils/slaac_address.cpp
@@ -35,10 +35,11 @@
 
 #if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
 
+#include "common/array.hpp"
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "common/locator_getters.hpp"
-#include "common/logging.hpp"
+#include "common/log.hpp"
 #include "common/random.hpp"
 #include "common/settings.hpp"
 #include "crypto/sha256.hpp"
@@ -47,6 +48,8 @@
 namespace ot {
 namespace Utils {
 
+RegisterLogModule("Slaac");
+
 Slaac::Slaac(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mEnabled(true)
@@ -59,7 +62,7 @@
 {
     VerifyOrExit(!mEnabled);
 
-    otLogInfoUtil("SLAAC:: Enabling");
+    LogInfo("Enabling");
     mEnabled = true;
     Update(kModeAdd);
 
@@ -71,7 +74,7 @@
 {
     VerifyOrExit(mEnabled);
 
-    otLogInfoUtil("SLAAC:: Disabling");
+    LogInfo("Disabling");
     mEnabled = false;
     Update(kModeRemove);
 
@@ -84,7 +87,7 @@
     VerifyOrExit(aFilter != mFilter);
 
     mFilter = aFilter;
-    otLogInfoUtil("SLAAC: Filter %s", (mFilter != nullptr) ? "updated" : "disabled");
+    LogInfo("Filter %s", (mFilter != nullptr) ? "updated" : "disabled");
 
     VerifyOrExit(mEnabled);
     Update(kModeAdd | kModeRemove);
@@ -183,7 +186,7 @@
 
             if (!found)
             {
-                otLogInfoUtil("SLAAC: Removing address %s", slaacAddr.GetAddress().ToString().AsCString());
+                LogInfo("Removing address %s", slaacAddr.GetAddress().ToString().AsCString());
 
                 Get<ThreadNetif>().RemoveUnicastAddress(slaacAddr);
                 slaacAddr.mValid = false;
@@ -233,7 +236,7 @@
 
                     IgnoreError(GenerateIid(slaacAddr));
 
-                    otLogInfoUtil("SLAAC: Adding address %s", slaacAddr.GetAddress().ToString().AsCString());
+                    LogInfo("Adding address %s", slaacAddr.GetAddress().ToString().AsCString());
 
                     Get<ThreadNetif>().AddUnicastAddress(slaacAddr);
 
@@ -243,8 +246,8 @@
 
                 if (!added)
                 {
-                    otLogWarnUtil("SLAAC: Failed to add - max %d addresses supported and already in use",
-                                  OT_ARRAY_LENGTH(mAddresses));
+                    LogWarn("Failed to add - max %d addresses supported and already in use",
+                            GetArrayLength(mAddresses));
                 }
             }
         }
@@ -264,7 +267,7 @@
      *  - RID is random (but stable) Identifier.
      *  - For pseudo-random function `F()` SHA-256 is used in this method.
      *  - `Net_Iface` is set to constant string "wpan".
-     *  - `Network_ID` is not used if `aNetworkId` is nullptr (optional per RF-7217).
+     *  - `Network_ID` is not used if `aNetworkId` is `nullptr` (optional per RF-7217).
      *  - The `secret_key` is randomly generated on first use (using true
      *    random number generator) and saved in non-volatile settings for
      *    future use.
@@ -315,7 +318,7 @@
         ExitNow(error = kErrorNone);
     }
 
-    otLogWarnUtil("SLAAC: Failed to generate a non-reserved IID after %d attempts", kMaxIidCreationAttempts);
+    LogWarn("Failed to generate a non-reserved IID after %d attempts", kMaxIidCreationAttempts);
 
 exit:
     return error;
@@ -340,7 +343,7 @@
 
     IgnoreError(Get<Settings>().Save<Settings::SlaacIidSecretKey>(aKey));
 
-    otLogInfoUtil("SLAAC: Generated and saved secret key");
+    LogInfo("Generated and saved secret key");
 
 exit:
     return;
diff --git a/src/core/utils/slaac_address.hpp b/src/core/utils/slaac_address.hpp
index 23f3e61..db7913b 100644
--- a/src/core/utils/slaac_address.hpp
+++ b/src/core/utils/slaac_address.hpp
@@ -126,12 +126,12 @@
     /**
      * This method generates the IID of an IPv6 address.
      *
-     * @param[inout]  aAddress             A reference to the address that will be filled with the IID generated.
+     * @param[in,out]  aAddress            A reference to the address that will be filled with the IID generated.
      *                                     Note the prefix of the address must already be filled and will be used
      *                                     to generate the IID.
-     * @param[in]     aNetworkId           A pointer to a byte array of Network_ID to generate IID.
-     * @param[in]     aNetworkIdLength     The size of array @p aNetworkId.
-     * @param[inout]  aDadCounter          A pointer to the DAD_Counter that is employed to resolve Duplicate
+     * @param[in]      aNetworkId          A pointer to a byte array of Network_ID to generate IID.
+     * @param[in]      aNetworkIdLength    The size of array @p aNetworkId.
+     * @param[in,out]  aDadCounter         A pointer to the DAD_Counter that is employed to resolve Duplicate
      *                                     Address Detection connflicts.
      *
      * @retval kErrorNone    If successfully generated the IID.
diff --git a/src/core/utils/srp_client_buffers.hpp b/src/core/utils/srp_client_buffers.hpp
index f98c223..7746de8 100644
--- a/src/core/utils/srp_client_buffers.hpp
+++ b/src/core/utils/srp_client_buffers.hpp
@@ -36,8 +36,12 @@
 
 #include "openthread-core-config.h"
 
+#if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE
+
 #include <openthread/srp_client_buffers.h>
 
+#include "common/array.hpp"
+#include "common/as_core_type.hpp"
 #include "common/clearable.hpp"
 #include "common/locator.hpp"
 #include "common/non_copyable.hpp"
@@ -47,8 +51,6 @@
 namespace ot {
 namespace Utils {
 
-#if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE
-
 #if !OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
 #error "OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE requires OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE feature."
 #endif
@@ -164,7 +166,7 @@
          */
         const char **GetSubTypeLabelsArray(uint16_t &aArrayLength)
         {
-            aArrayLength = OT_ARRAY_LENGTH(mSubTypeLabels);
+            aArrayLength = GetArrayLength(mSubTypeLabels);
             return mSubTypeLabels;
         }
 
@@ -212,7 +214,7 @@
      */
     Ip6::Address *GetHostAddressesArray(uint8_t &aArrayLength)
     {
-        aArrayLength = OT_ARRAY_LENGTH(mHostAddresses);
+        aArrayLength = static_cast<uint8_t>(GetArrayLength(mHostAddresses));
         return &mHostAddresses[0];
     }
 
@@ -260,9 +262,12 @@
     Pool<ServiceEntry, kMaxServices> mServicePool;
 };
 
-#endif // OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE
-
 } // namespace Utils
+
+DefineCoreType(otSrpClientBuffersServiceEntry, Utils::SrpClientBuffers::ServiceEntry);
+
 } // namespace ot
 
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE
+
 #endif // SRP_CLIENT_BUFFERS_HPP_
diff --git a/src/lib/hdlc/hdlc.hpp b/src/lib/hdlc/hdlc.hpp
index ea97ce7..84581d1 100644
--- a/src/lib/hdlc/hdlc.hpp
+++ b/src/lib/hdlc/hdlc.hpp
@@ -39,6 +39,7 @@
 
 #include <openthread/error.h>
 
+#include "common/array.hpp"
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
 #include "common/encoding.hpp"
@@ -242,7 +243,7 @@
     {
         otError error = OT_ERROR_NO_BUFS;
 
-        if (GetFrame() + aLength <= OT_ARRAY_END(mBuffer))
+        if (GetFrame() + aLength <= GetArrayEnd(mBuffer))
         {
             mWritePointer    = GetFrame() + aLength;
             mRemainingLength = static_cast<uint16_t>(mBuffer + kSize - mWritePointer);
@@ -273,7 +274,7 @@
     {
         otError error = OT_ERROR_NO_BUFS;
 
-        if (mWriteFrameStart + kHeaderSize + aSkipLength <= OT_ARRAY_END(mBuffer))
+        if (mWriteFrameStart + kHeaderSize + aSkipLength <= GetArrayEnd(mBuffer))
         {
             Encoding::LittleEndian::WriteUint16(aSkipLength, mWriteFrameStart + kHeaderSkipLengthOffset);
             mWritePointer    = GetFrame();
@@ -352,11 +353,11 @@
     /**
      * This method iterates through previously saved frames in the buffer, getting a next frame in the queue.
      *
-     * @param[inout] aFrame   On entry, should point to a previous saved frame or nullptr to get the first frame.
-     *                        On exit, the pointer variable is updated to next frame or set to nullptr if there are
-     * none.
-     * @param[inout] aLength  On entry, should be a reference to the frame length of the previous saved frame.
-     *                        On exit, the reference is updated to the frame length (number of bytes) of next frame.
+     * @param[in,out] aFrame   On entry, should point to a previous saved frame or nullptr to get the first frame.
+     *                         On exit, the pointer variable is updated to next frame or set to nullptr if there are
+     *                         none.
+     * @param[in,out] aLength  On entry, should be a reference to the frame length of the previous saved frame.
+     *                         On exit, the reference is updated to the frame length (number of bytes) of next frame.
      *
      * @retval OT_ERROR_NONE       Updated @aFrame and @aLength successfully with the next saved frame.
      * @retval OT_ERROR_NOT_FOUND  No more saved frame in the buffer.
@@ -366,7 +367,7 @@
     {
         otError error = OT_ERROR_NONE;
 
-        OT_ASSERT(aFrame == nullptr || (mBuffer <= aFrame && aFrame < OT_ARRAY_END(mBuffer)));
+        OT_ASSERT(aFrame == nullptr || (mBuffer <= aFrame && aFrame < GetArrayEnd(mBuffer)));
 
         aFrame = (aFrame == nullptr) ? mBuffer : aFrame + aLength;
 
diff --git a/src/lib/platform/Makefile.am b/src/lib/platform/Makefile.am
index 70f8611..eb8d139 100644
--- a/src/lib/platform/Makefile.am
+++ b/src/lib/platform/Makefile.am
@@ -40,4 +40,8 @@
     exit_code.h                               \
     $(NULL)
 
+noinst_HEADERS                              = \
+    reset_util.h                              \
+    $(NULL)
+
 include $(abs_top_nlbuild_autotools_dir)/automake/post.am
diff --git a/src/lib/platform/exit_code.h b/src/lib/platform/exit_code.h
index 81a3321..ccb8f7c 100644
--- a/src/lib/platform/exit_code.h
+++ b/src/lib/platform/exit_code.h
@@ -36,6 +36,7 @@
 
 #include <stdint.h>
 #include <stdlib.h>
+#include <string.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -101,14 +102,17 @@
  * @param[in]   aExitCode   The exit code.
  *
  */
-#define VerifyOrDie(aCondition, aExitCode)                                                                   \
-    do                                                                                                       \
-    {                                                                                                        \
-        if (!(aCondition))                                                                                   \
-        {                                                                                                    \
-            otLogCritPlat("%s() at %s:%d: %s", __func__, __FILE__, __LINE__, otExitCodeToString(aExitCode)); \
-            exit(aExitCode);                                                                                 \
-        }                                                                                                    \
+#define VerifyOrDie(aCondition, aExitCode)                                                         \
+    do                                                                                             \
+    {                                                                                              \
+        if (!(aCondition))                                                                         \
+        {                                                                                          \
+            const char *start = strrchr(__FILE__, '/');                                            \
+            OT_UNUSED_VARIABLE(start);                                                             \
+            otLogCritPlat("%s() at %s:%d: %s", __func__, (start ? start + 1 : __FILE__), __LINE__, \
+                          otExitCodeToString(aExitCode));                                          \
+            exit(aExitCode);                                                                       \
+        }                                                                                          \
     } while (false)
 
 /**
diff --git a/src/lib/platform/reset_util.h b/src/lib/platform/reset_util.h
new file mode 100644
index 0000000..52f5681
--- /dev/null
+++ b/src/lib/platform/reset_util.h
@@ -0,0 +1,69 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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 OT_LIB_PLATFORM_RESET_UTIL_H_
+#define OT_LIB_PLATFORM_RESET_UTIL_H_
+
+#if defined(OPENTHREAD_ENABLE_COVERAGE) && OPENTHREAD_ENABLE_COVERAGE && defined(__GNUC__)
+#if __GNUC__ >= 11 || (defined(__clang__) && (defined(__APPLE__) && (__clang_major__ >= 13)) || \
+                       (!defined(__APPLE__) && (__clang_major__ >= 12)))
+void __gcov_dump();
+void __gcov_reset();
+
+static void flush_gcov(void)
+{
+    __gcov_dump();
+    __gcov_reset();
+}
+#else
+void __gcov_flush(void);
+#define flush_gcov __gcov_flush
+#endif /* __GNUC__ >= 11 || (defined(__clang__) && (defined(__APPLE__) && (__clang_major__ >= 13)) || \
+                             (!defined(__APPLE__) && (__clang_major__ >= 12))) */
+#else
+#define flush_gcov()
+#endif // defined(OPENTHREAD_ENABLE_COVERAGE) && OPENTHREAD_ENABLE_COVERAGE && defined(__GNUC__)
+
+#if defined(__linux__) || defined(__APPLE__)
+#include <setjmp.h>
+#include <unistd.h>
+jmp_buf gResetJump;
+
+#define OT_SETUP_RESET_JUMP(kArgv) \
+    if (setjmp(gResetJump))        \
+    {                              \
+        alarm(0);                  \
+        flush_gcov();              \
+        execvp(kArgv[0], kArgv);   \
+    }
+
+#else
+#define OT_SETUP_RESET_JUMP(ARGV)
+#endif // defined(__linux__) || defined(__APPLE__)
+
+#endif // OT_LIB_PLATFORM_RESET_UTIL_H_
diff --git a/src/lib/spinel/radio_spinel.hpp b/src/lib/spinel/radio_spinel.hpp
index 73dedfb..b0d3b46 100644
--- a/src/lib/spinel/radio_spinel.hpp
+++ b/src/lib/spinel/radio_spinel.hpp
@@ -37,6 +37,7 @@
 #include <openthread/platform/radio.h>
 
 #include "openthread-spinel-config.h"
+#include "radio_spinel_metrics.h"
 #include "spinel.h"
 #include "spinel_interface.hpp"
 #include "core/radio/max_power_table.hpp"
@@ -675,6 +676,54 @@
      */
     otError GetRadioRegion(uint16_t *aRegionCode);
 
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
+    /**
+     * Enable/disable or update Enhanced-ACK Based Probing in radio for a specific Initiator.
+     *
+     * After Enhanced-ACK Based Probing is configured by a specific Probing Initiator, the Enhanced-ACK sent to that
+     * node should include Vendor-Specific IE containing Link Metrics data. This method informs the radio to start/stop
+     * to collect Link Metrics data and include Vendor-Specific IE that containing the data in Enhanced-ACK sent to that
+     * Probing Initiator.
+     *
+     * @param[in]  aLinkMetrics   This parameter specifies what metrics to query. Per spec 4.11.3.4.4.6, at most 2
+     *                            metrics can be specified. The probing would be disabled if @p aLinkMetrics is
+     *                            bitwise 0.
+     * @param[in]  aShortAddress  The short address of the Probing Initiator.
+     * @param[in]  aExtAddress    The extended source address of the Probing Initiator. @p aExtAddress MUST NOT be
+     *                            nullptr.
+     *
+     * @retval  OT_ERROR_NONE            Successfully configured the Enhanced-ACK Based Probing.
+     * @retval  OT_ERROR_INVALID_ARGS    @p aExtAddress is nullptr.
+     * @retval  OT_ERROR_NOT_FOUND       The Initiator indicated by @p aShortAddress is not found when trying to clear.
+     * @retval  OT_ERROR_NO_BUFS         No more Initiator can be supported.
+     */
+    otError ConfigureEnhAckProbing(otLinkMetrics        aLinkMetrics,
+                                   const otShortAddress aShortAddress,
+                                   const otExtAddress & aExtAddress);
+#endif
+
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+    /**
+     * Get the current accuracy, in units of ± ppm, of the clock used for scheduling CSL operations.
+     *
+     * @note Platforms may optimize this value based on operational conditions (i.e.: temperature).
+     *
+     * @retval   The current CSL rx/tx scheduling drift, in units of ± ppm.
+     *
+     */
+    uint8_t GetCslAccuracy(void);
+#endif
+
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+    /**
+     * Get the current uncertainty, in units of 10 us, of the clock used for scheduling CSL operations.
+     *
+     * @retval  The current CSL Clock Uncertainty in units of 10 us.
+     *
+     */
+    uint8_t GetCslUncertainty(void);
+#endif
+
     /**
      * This method checks whether the spinel interface is radio-only.
      *
@@ -829,10 +878,18 @@
      */
     otError SendReset(uint8_t aResetType);
 
+    /**
+     * This method returns the radio Spinel metrics.
+     *
+     * @returns The radio Spinel metrics.
+     *
+     */
+    const otRadioSpinelMetrics *GetRadioSpinelMetrics(void) const { return &mRadioSpinelMetrics; }
+
 private:
     enum
     {
-        kMaxSpinelFrame        = SpinelInterface::kMaxFrameSize,
+        kMaxSpinelFrame        = SPINEL_FRAME_MAX_SIZE,
         kMaxWaitTime           = 2000, ///< Max time to wait for response in milliseconds.
         kVersionStringSize     = 128,  ///< Max size of version string.
         kCapsBufferSize        = 100,  ///< Max buffer size used to store `SPINEL_PROP_CAPS` value.
@@ -934,6 +991,10 @@
 #if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
     void RestoreProperties(void);
 #endif
+    void UpdateParseErrorCount(otError aError)
+    {
+        mRadioSpinelMetrics.mSpinelParseErrorCount += (aError == OT_ERROR_PARSE) ? 1 : 0;
+    }
 
     otInstance *mInstance;
 
@@ -1018,6 +1079,8 @@
     int64_t  mRadioTimeOffset;      ///< Time difference with estimated RCP time minus host time.
 
     MaxPowerTable mMaxPowerTable;
+
+    otRadioSpinelMetrics mRadioSpinelMetrics;
 };
 
 } // namespace Spinel
diff --git a/src/lib/spinel/radio_spinel_impl.hpp b/src/lib/spinel/radio_spinel_impl.hpp
index 2f67311..c9eda5c 100644
--- a/src/lib/spinel/radio_spinel_impl.hpp
+++ b/src/lib/spinel/radio_spinel_impl.hpp
@@ -37,13 +37,13 @@
 #include <stdlib.h>
 
 #include <openthread/dataset.h>
+#include <openthread/logging.h>
 #include <openthread/platform/diag.h>
 #include <openthread/platform/time.h>
 
 #include "common/code_utils.hpp"
 #include "common/encoding.hpp"
 #include "common/instance.hpp"
-#include "common/logging.hpp"
 #include "common/new.hpp"
 #include "common/settings.hpp"
 #include "lib/platform/exit_code.h"
@@ -160,7 +160,7 @@
     OT_UNUSED_VARIABLE(aText);
     OT_UNUSED_VARIABLE(aError);
 
-    if (aError != OT_ERROR_NONE)
+    if (aError != OT_ERROR_NONE && aError != OT_ERROR_NO_ACK)
     {
         otLogWarnPlat("%s: %s", aText, otThreadErrorToString(aError));
     }
@@ -218,6 +218,7 @@
     , mRadioTimeOffset(0)
 {
     mVersion[0] = '\0';
+    memset(&mRadioSpinelMetrics, 0, sizeof(mRadioSpinelMetrics));
 }
 
 template <typename InterfaceType, typename ProcessContextType>
@@ -239,6 +240,14 @@
     }
 
     SuccessOrExit(error = WaitResponse());
+
+#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
+    while (mRcpFailed)
+    {
+        RecoverFromRcpFailure();
+    }
+#endif
+
     VerifyOrExit(mIsReady, error = OT_ERROR_FAILED);
 
     SuccessOrExit(error = CheckSpinelVersion());
@@ -423,7 +432,7 @@
 {
     otError error = OT_ERROR_NONE;
 
-    Instance::Get().template Get<SettingsDriver>().Init();
+    Instance::Get().template Get<SettingsDriver>().Init(nullptr, 0);
 
     otLogInfoPlat("Trying to get saved dataset from NCP");
     SuccessOrExit(
@@ -474,6 +483,8 @@
         mRxFrameBuffer.DiscardFrame();
         otLogWarnPlat("Error handling hdlc frame: %s", otThreadErrorToString(error));
     }
+
+    UpdateParseErrorCount(error);
 }
 
 template <typename InterfaceType, typename ProcessContextType>
@@ -527,6 +538,7 @@
         aFrameBuffer.DiscardFrame();
     }
 
+    UpdateParseErrorCount(error);
     LogIfFail("Error processing notification", error);
 }
 
@@ -548,6 +560,7 @@
     HandleValueIs(key, data, static_cast<uint16_t>(len));
 
 exit:
+    UpdateParseErrorCount(error);
     LogIfFail("Error processing saved notification", error);
 }
 
@@ -589,6 +602,7 @@
     }
 
 exit:
+    UpdateParseErrorCount(error);
     LogIfFail("Error processing response", error);
 }
 
@@ -744,7 +758,7 @@
      * Initially set Active Timestamp to 0. This is to allow the node to join the network
      * yet retrieve the full Active Dataset from a neighboring device if one exists.
      */
-    opDataset.mActiveTimestamp                      = 0;
+    memset(&opDataset.mActiveTimestamp, 0, sizeof(opDataset.mActiveTimestamp));
     opDataset.mComponents.mIsActiveTimestampPresent = true;
 
     SuccessOrExit(error = dataset.SetFrom(static_cast<MeshCoP::Dataset::Info &>(opDataset)));
@@ -821,6 +835,7 @@
     }
 
 exit:
+    UpdateParseErrorCount(mError);
     LogIfFail("Error processing result", mError);
 }
 
@@ -928,6 +943,7 @@
     }
 
 exit:
+    UpdateParseErrorCount(error);
     LogIfFail("Failed to handle ValueIs", error);
 }
 
@@ -999,6 +1015,7 @@
     }
 
 exit:
+    UpdateParseErrorCount(error);
     LogIfFail("Handle radio frame failed", error);
     return error;
 }
@@ -1663,18 +1680,11 @@
     do
     {
         uint64_t now;
-        uint64_t remain;
 
         now = otPlatTimeGet();
-        if (end <= now)
+        if ((end <= now) || (mSpinelInterface.WaitForFrame(end - now) != OT_ERROR_NONE))
         {
-            HandleRcpTimeout();
-            ExitNow(mError = OT_ERROR_NONE);
-        }
-        remain = end - now;
-
-        if (mSpinelInterface.WaitForFrame(remain) != OT_ERROR_NONE)
-        {
+            otLogWarnPlat("Wait for response timeout");
             HandleRcpTimeout();
             ExitNow(mError = OT_ERROR_NONE);
         }
@@ -1691,15 +1701,25 @@
 template <typename InterfaceType, typename ProcessContextType>
 spinel_tid_t RadioSpinel<InterfaceType, ProcessContextType>::GetNextTid(void)
 {
-    spinel_tid_t tid = 0;
+    spinel_tid_t tid = mCmdNextTid;
 
-    if (((1 << mCmdNextTid) & mCmdTidsInUse) == 0)
+    while (((1 << tid) & mCmdTidsInUse) != 0)
     {
-        tid         = mCmdNextTid;
-        mCmdNextTid = SPINEL_GET_NEXT_TID(mCmdNextTid);
-        mCmdTidsInUse |= (1 << tid);
+        tid = SPINEL_GET_NEXT_TID(tid);
+
+        if (tid == mCmdNextTid)
+        {
+            // We looped back to `mCmdNextTid` indicating that all
+            // TIDs are in-use.
+
+            ExitNow(tid = 0);
+        }
     }
 
+    mCmdTidsInUse |= (1 << tid);
+    mCmdNextTid = SPINEL_GET_NEXT_TID(tid);
+
+exit:
     return tid;
 }
 
@@ -1913,6 +1933,7 @@
 exit:
     mState   = kStateTransmitDone;
     mTxError = error;
+    UpdateParseErrorCount(error);
     LogIfFail("Handle transmit done failed", error);
 }
 
@@ -2106,6 +2127,7 @@
     channelMask &= mMaxPowerTable.GetSupportedChannelMask();
 
 exit:
+    UpdateParseErrorCount(error);
     LogIfFail("Get radio channel mask failed", error);
     return channelMask;
 }
@@ -2200,6 +2222,7 @@
 {
     OT_UNUSED_VARIABLE(aStatus);
 
+    mRadioSpinelMetrics.mRcpUnexpectedResetCount++;
     otLogCritPlat("Unexpected RCP reset: %s", spinel_status_to_cstr(aStatus));
 
 #if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
@@ -2212,6 +2235,8 @@
 template <typename InterfaceType, typename ProcessContextType>
 void RadioSpinel<InterfaceType, ProcessContextType>::HandleRcpTimeout(void)
 {
+    mRadioSpinelMetrics.mRcpTimeoutCount++;
+
 #if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
     mRcpFailed = true;
 #else
@@ -2234,6 +2259,7 @@
 
     otLogWarnPlat("RCP failure detected");
 
+    ++mRadioSpinelMetrics.mRcpRestorationCount;
     ++mRcpFailureCount;
     if (mRcpFailureCount > kMaxFailureCount)
     {
@@ -2291,6 +2317,7 @@
     }
 
     --mRcpFailureCount;
+    otLogNotePlat("RCP recovery is done");
 
 exit:
     return;
@@ -2391,7 +2418,22 @@
 template <typename InterfaceType, typename ProcessContextType>
 otError RadioSpinel<InterfaceType, ProcessContextType>::SetRadioRegion(uint16_t aRegionCode)
 {
-    return Set(SPINEL_PROP_PHY_REGION_CODE, SPINEL_DATATYPE_UINT16_S, aRegionCode);
+    otError error;
+
+    error = Set(SPINEL_PROP_PHY_REGION_CODE, SPINEL_DATATYPE_UINT16_S, aRegionCode);
+
+    if (error == OT_ERROR_NONE)
+    {
+        otLogNotePlat("Set region code \"%c%c\" successfully", static_cast<char>(aRegionCode >> 8),
+                      static_cast<char>(aRegionCode));
+    }
+    else
+    {
+        otLogWarnPlat("Failed to set region code \"%c%c\": %s", static_cast<char>(aRegionCode >> 8),
+                      static_cast<char>(aRegionCode), otThreadErrorToString(error));
+    }
+
+    return error;
 }
 
 template <typename InterfaceType, typename ProcessContextType>
@@ -2406,5 +2448,66 @@
     return error;
 }
 
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
+template <typename InterfaceType, typename ProcessContextType>
+otError RadioSpinel<InterfaceType, ProcessContextType>::ConfigureEnhAckProbing(otLinkMetrics        aLinkMetrics,
+                                                                               const otShortAddress aShortAddress,
+                                                                               const otExtAddress & aExtAddress)
+{
+    otError error = OT_ERROR_NONE;
+    uint8_t flags = 0;
+
+    if (aLinkMetrics.mPduCount)
+    {
+        flags |= SPINEL_THREAD_LINK_METRIC_PDU_COUNT;
+    }
+
+    if (aLinkMetrics.mLqi)
+    {
+        flags |= SPINEL_THREAD_LINK_METRIC_LQI;
+    }
+
+    if (aLinkMetrics.mLinkMargin)
+    {
+        flags |= SPINEL_THREAD_LINK_METRIC_LINK_MARGIN;
+    }
+
+    if (aLinkMetrics.mRssi)
+    {
+        flags |= SPINEL_THREAD_LINK_METRIC_RSSI;
+    }
+
+    error =
+        Set(SPINEL_PROP_RCP_ENH_ACK_PROBING, SPINEL_DATATYPE_UINT16_S SPINEL_DATATYPE_EUI64_S SPINEL_DATATYPE_UINT8_S,
+            aShortAddress, aExtAddress.m8, flags);
+
+    return error;
+}
+#endif
+
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+template <typename InterfaceType, typename ProcessContextType>
+uint8_t RadioSpinel<InterfaceType, ProcessContextType>::GetCslAccuracy(void)
+{
+    uint8_t accuracy = UINT8_MAX;
+    otError error    = Get(SPINEL_PROP_RCP_CSL_ACCURACY, SPINEL_DATATYPE_UINT8_S, &accuracy);
+
+    LogIfFail("Get CSL Accuracy failed", error);
+    return accuracy;
+}
+#endif
+
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+template <typename InterfaceType, typename ProcessContextType>
+uint8_t RadioSpinel<InterfaceType, ProcessContextType>::GetCslUncertainty(void)
+{
+    uint8_t uncertainty = UINT8_MAX;
+    otError error       = Get(SPINEL_PROP_RCP_CSL_UNCERTAINTY, SPINEL_DATATYPE_UINT8_S, &uncertainty);
+
+    LogIfFail("Get CSL Uncertainty failed", error);
+    return uncertainty;
+}
+#endif
+
 } // namespace Spinel
 } // namespace ot
diff --git a/include/openthread/entropy.h b/src/lib/spinel/radio_spinel_metrics.h
similarity index 70%
rename from include/openthread/entropy.h
rename to src/lib/spinel/radio_spinel_metrics.h
index bc07c30..438e14c 100644
--- a/include/openthread/entropy.h
+++ b/src/lib/spinel/radio_spinel_metrics.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2019, The OpenThread Authors.
+ *  Copyright (c) 2022, The OpenThread Authors.
  *  All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -29,42 +29,30 @@
 /**
  * @file
  * @brief
- *  This file defines the OpenThread entropy source API.
+ *   This file includes the definitions of the radio spinel metrics.
  */
 
-#ifndef OPENTHREAD_ENTROPY_H_
-#define OPENTHREAD_ENTROPY_H_
-
-#include <mbedtls/entropy.h>
+#ifndef RADIO_SPINEL_METRICS_H_
+#define RADIO_SPINEL_METRICS_H_
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /**
- * @addtogroup api-entropy
- *
- * @brief
- *   This module includes functions that manages entropy source.
- *
- * @{
+ * This structure represents the radio spinel metrics.
  *
  */
-
-/**
- * This function returns initialized mbedtls_entropy_context.
- *
- * @returns  A pointer to initialized mbedtls_entropy_context.
- */
-mbedtls_entropy_context *otEntropyMbedTlsContextGet(void);
-
-/**
- * @}
- *
- */
+typedef struct otRadioSpinelMetrics
+{
+    uint32_t mRcpTimeoutCount;         ///< The number of RCP timeouts.
+    uint32_t mRcpUnexpectedResetCount; ///< The number of RCP unexcepted resets.
+    uint32_t mRcpRestorationCount;     ///< The number of RCP restorations.
+    uint32_t mSpinelParseErrorCount;   ///< The number of spinel frame parse errors.
+} otRadioSpinelMetrics;
 
 #ifdef __cplusplus
-} // extern "C"
+} // end of extern "C"
 #endif
 
-#endif // OPENTHREAD_ENTROPY_H_
+#endif // RADIO_SPINEL_METRICS_H_
diff --git a/src/lib/spinel/spinel.c b/src/lib/spinel/spinel.c
index edce57a..190381d 100644
--- a/src/lib/spinel/spinel.c
+++ b/src/lib/spinel/spinel.c
@@ -1400,6 +1400,9 @@
         {SPINEL_PROP_CHILD_SUPERVISION_INTERVAL, "CHILD_SUPERVISION_INTERVAL"},
         {SPINEL_PROP_CHILD_SUPERVISION_CHECK_TIMEOUT, "CHILD_SUPERVISION_CHECK_TIMEOUT"},
         {SPINEL_PROP_RCP_VERSION, "RCP_VERSION"},
+        {SPINEL_PROP_RCP_ENH_ACK_PROBING, "ENH_ACK_PROBING"},
+        {SPINEL_PROP_RCP_CSL_ACCURACY, "CSL_ACCURACY"},
+        {SPINEL_PROP_RCP_CSL_UNCERTAINTY, "CSL_UNCERTAINTY"},
         {SPINEL_PROP_PARENT_RESPONSE_INFO, "PARENT_RESPONSE_INFO"},
         {SPINEL_PROP_SLAAC_ENABLED, "SLAAC_ENABLED"},
         {SPINEL_PROP_SUPPORTED_RADIO_LINKS, "SUPPORTED_RADIO_LINKS"},
diff --git a/src/lib/spinel/spinel.h b/src/lib/spinel/spinel.h
index 845349b..bc1b8d5 100644
--- a/src/lib/spinel/spinel.h
+++ b/src/lib/spinel/spinel.h
@@ -377,7 +377,7 @@
  * Please see section "Spinel definition compatibility guideline" for more details.
  *
  */
-#define SPINEL_RCP_API_VERSION 4
+#define SPINEL_RCP_API_VERSION 6
 
 /**
  * @def SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION
@@ -706,7 +706,7 @@
     SPINEL_NCP_LOG_REGION_OT_UTIL     = 17,
     SPINEL_NCP_LOG_REGION_OT_BBR      = 18,
     SPINEL_NCP_LOG_REGION_OT_MLR      = 19,
-    SPINEL_NCP_LOG_REGION_OT_DUA      = 10,
+    SPINEL_NCP_LOG_REGION_OT_DUA      = 20,
     SPINEL_NCP_LOG_REGION_OT_BR       = 21,
     SPINEL_NCP_LOG_REGION_OT_SRP      = 22,
     SPINEL_NCP_LOG_REGION_OT_DNS      = 23,
@@ -752,6 +752,7 @@
 // @ref SPINEL_PROP_THREAD_LINK_METRICS_QUERY_RESULT
 // @ref SPINEL_PROP_THREAD_LINK_METRICS_MGMT_ENH_ACK
 // @ref SPINEL_PROP_THREAD_LINK_METRICS_MGMT_FORWARD
+// @ref SPINEL_PROP_RCP_ENH_ACK_PROBING
 enum
 {
     SPINEL_THREAD_LINK_METRIC_PDU_COUNT   = (1 << 0),
@@ -4709,6 +4710,45 @@
      */
     SPINEL_PROP_RCP_TIMESTAMP = SPINEL_PROP_RCP_EXT__BEGIN + 2,
 
+    /// Configure Enhanced ACK probing
+    /** Format: `SEC` (Write-only).
+     *
+     * `S`: Short address
+     * `E`: Extended address
+     * `C`: List of requested metric ids encoded as bit fields in single byte
+     *
+     *   +---------------+----+
+     *   |    Metric     | Id |
+     *   +---------------+----+
+     *   | Received PDUs |  0 |
+     *   | LQI           |  1 |
+     *   | Link margin   |  2 |
+     *   | RSSI          |  3 |
+     *   +---------------+----+
+     *
+     * Enable/disable or update Enhanced-ACK Based Probing in radio for a specific Initiator.
+     *
+     */
+    SPINEL_PROP_RCP_ENH_ACK_PROBING = SPINEL_PROP_RCP_EXT__BEGIN + 3,
+
+    /// CSL Accuracy
+    /** Format: `C`
+     * Required capability: `SPINEL_CAP_NET_THREAD_1_2`
+     *
+     * The current CSL rx/tx scheduling drift, in units of ± ppm.
+     *
+     */
+    SPINEL_PROP_RCP_CSL_ACCURACY = SPINEL_PROP_RCP_EXT__BEGIN + 4,
+
+    /// CSL Uncertainty
+    /** Format: `C`
+     * Required capability: `SPINEL_CAP_NET_THREAD_1_2`
+     *
+     * The current uncertainty, in units of 10 us, of the clock used for scheduling CSL operations.
+     *
+     */
+    SPINEL_PROP_RCP_CSL_UNCERTAINTY = SPINEL_PROP_RCP_EXT__BEGIN + 5,
+
     SPINEL_PROP_RCP_EXT__END = 0x900,
 
     SPINEL_PROP_NEST__BEGIN = 0x3BC0,
diff --git a/src/lib/spinel/spinel_buffer.hpp b/src/lib/spinel/spinel_buffer.hpp
index 056034b..6377a1f 100644
--- a/src/lib/spinel/spinel_buffer.hpp
+++ b/src/lib/spinel/spinel_buffer.hpp
@@ -61,8 +61,8 @@
      */
     enum Priority
     {
-        kPriorityLow  = 0, //< Indicates low/normal priority for a frame.
-        kPriorityHigh = 1, //< Indicates high priority for a frame.
+        kPriorityLow  = 0, ///< Indicates low/normal priority for a frame.
+        kPriorityHigh = 1, ///< Indicates high priority for a frame.
     };
 
     /**
@@ -98,8 +98,8 @@
         }
 
     private:
-        uint8_t *mPosition;    //< Pointer into buffer corresponding to saved write position.
-        uint8_t *mSegmentHead; //< Pointer to segment head.
+        uint8_t *mPosition;    // Pointer into buffer corresponding to saved write position.
+        uint8_t *mSegmentHead; // Pointer to segment head.
 
         friend class Buffer;
     };
diff --git a/src/lib/spinel/spinel_decoder.hpp b/src/lib/spinel/spinel_decoder.hpp
index 77328d7..bdd3861 100644
--- a/src/lib/spinel/spinel_decoder.hpp
+++ b/src/lib/spinel/spinel_decoder.hpp
@@ -471,7 +471,7 @@
      *
      * @param[out] aData                Reference to pointer variable to output the data.
      *                                  On success, the pointer variable is updated.
-     * @param[out] aDataLength          Reference to variable to output the data length (number of bytes).
+     * @param[out] aDataLen             Reference to variable to output the data length (number of bytes).
      *
      * @retval OT_ERROR_NONE            Successfully read the value.
      * @retval OT_ERROR_PARSE           Failed to parse/decode the value.
@@ -488,7 +488,7 @@
      *
      * @param[out] aData                Reference to pointer variable to output the data.
      *                                  On success, the pointer variable is updated.
-     * @param[out] aDataLength          Reference to variable to out the data length (number of bytes).
+     * @param[out] aDataLen             Reference to variable to out the data length (number of bytes).
      *
      * @retval OT_ERROR_NONE            Successfully read the value.
      * @retval OT_ERROR_PARSE           Failed to parse/decode the value.
diff --git a/src/lib/spinel/spinel_encoder.hpp b/src/lib/spinel/spinel_encoder.hpp
index 44ea078..0790054 100644
--- a/src/lib/spinel/spinel_encoder.hpp
+++ b/src/lib/spinel/spinel_encoder.hpp
@@ -435,7 +435,7 @@
      * If no buffer space is available, this method will discard and clear the current input frame and return the
      * error status `OT_ERROR_NO_BUFS`.
      *
-     * @param[in]  aExtAddress          A pointer to a buffer containing the EUI64 value.
+     * @param[in]  aEui64               A pointer to a buffer containing the EUI64 value.
      *
      * @retval OT_ERROR_NONE            Successfully added given value to the frame.
      * @retval OT_ERROR_NO_BUFS         Insufficient buffer space available to add the EUI64 value.
diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp
index 65b3456..0f922a3 100644
--- a/src/ncp/ncp_base.cpp
+++ b/src/ncp/ncp_base.cpp
@@ -261,9 +261,6 @@
     , mRxSpinelOutOfOrderTidCounter(0)
     , mTxSpinelFrameCounter(0)
     , mDidInitialUpdates(false)
-#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
-    , mTrelTestModeEnable(true)
-#endif
     , mLogTimestampBase(0)
 {
     OT_ASSERT(mInstance != nullptr);
@@ -1550,6 +1547,20 @@
     return error;
 }
 
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_RCP_CSL_ACCURACY>(void)
+{
+    return mEncoder.WriteUint8(otPlatRadioGetCslAccuracy(mInstance));
+}
+#endif
+
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_RCP_CSL_UNCERTAINTY>(void)
+{
+    return mEncoder.WriteUint8(otPlatRadioGetCslUncertainty(mInstance));
+}
+#endif
+
 otError NcpBase::EncodeChannelMask(uint32_t aChannelMask)
 {
     otError error = OT_ERROR_NONE;
@@ -2541,6 +2552,40 @@
 }
 #endif
 
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
+otError NcpBase::DecodeLinkMetrics(otLinkMetrics *aMetrics, bool aAllowPduCount)
+{
+    otError error   = OT_ERROR_NONE;
+    uint8_t metrics = 0;
+
+    SuccessOrExit(error = mDecoder.ReadUint8(metrics));
+
+    if (metrics & SPINEL_THREAD_LINK_METRIC_PDU_COUNT)
+    {
+        VerifyOrExit(aAllowPduCount, error = OT_ERROR_INVALID_ARGS);
+        aMetrics->mPduCount = true;
+    }
+
+    if (metrics & SPINEL_THREAD_LINK_METRIC_LQI)
+    {
+        aMetrics->mLqi = true;
+    }
+
+    if (metrics & SPINEL_THREAD_LINK_METRIC_LINK_MARGIN)
+    {
+        aMetrics->mLinkMargin = true;
+    }
+
+    if (metrics & SPINEL_THREAD_LINK_METRIC_RSSI)
+    {
+        aMetrics->mRssi = true;
+    }
+
+exit:
+    return error;
+}
+#endif
+
 } // namespace Ncp
 } // namespace ot
 
@@ -2599,14 +2644,4 @@
     va_end(args);
 }
 
-extern "C" void otPlatLogLine(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aLogLine)
-{
-    ot::Ncp::NcpBase *ncp = ot::Ncp::NcpBase::GetNcpInstance();
-
-    if (ncp != nullptr)
-    {
-        ncp->Log(aLogLevel, aLogRegion, aLogLine);
-    }
-}
-
 #endif // (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_APP)
diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp
index fc024c7..f4e9f64 100644
--- a/src/ncp/ncp_base.hpp
+++ b/src/ncp/ncp_base.hpp
@@ -389,8 +389,6 @@
 #endif
 
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
-    otError DecodeLinkMetrics(otLinkMetrics *aMetrics, bool aAllowPduCount);
-
     otError EncodeLinkMetricsValues(const otLinkMetricsValues *aMetricsValues);
 #endif
 
@@ -404,6 +402,10 @@
 #endif // OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
 
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
+    otError DecodeLinkMetrics(otLinkMetrics *aMetrics, bool aAllowPduCount);
+#endif
+
     otError CommandHandler_NOOP(uint8_t aHeader);
     otError CommandHandler_RESET(uint8_t aHeader);
     // Combined command handler for `VALUE_GET`, `VALUE_SET`, `VALUE_INSERT` and `VALUE_REMOVE`.
@@ -675,10 +677,6 @@
 
     bool mDidInitialUpdates;
 
-#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
-    bool mTrelTestModeEnable;
-#endif
-
     uint64_t mLogTimestampBase; // Timestamp base used for logging
 };
 
diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp
index 51fbcec..89b1f61 100644
--- a/src/ncp/ncp_base_dispatcher.cpp
+++ b/src/ncp/ncp_base_dispatcher.cpp
@@ -210,6 +210,12 @@
 #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
         OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_RCP_TIMESTAMP),
 #endif
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+        OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_RCP_CSL_ACCURACY),
+#endif
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+        OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_RCP_CSL_UNCERTAINTY),
+#endif
 #if OPENTHREAD_MTD || OPENTHREAD_FTD
         OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_UNSOL_UPDATE_FILTER),
         OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_UNSOL_UPDATE_LIST),
@@ -479,7 +485,10 @@
 #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
         OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_RCP_MAC_KEY),
         OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_RCP_MAC_FRAME_COUNTER),
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
+        OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_RCP_ENH_ACK_PROBING),
 #endif
+#endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
 #if OPENTHREAD_MTD || OPENTHREAD_FTD
         OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_UNSOL_UPDATE_FILTER),
 #if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp
index 0ed2096..e2dbb53 100644
--- a/src/ncp/ncp_base_mtd.cpp
+++ b/src/ncp/ncp_base_mtd.cpp
@@ -67,7 +67,7 @@
 #include <openthread/srp_client_buffers.h>
 #endif
 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
-#include <openthread/platform/trel-udp6.h>
+#include <openthread/trel.h>
 #endif
 
 #include "common/code_utils.hpp"
@@ -215,38 +215,6 @@
 }
 
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
-otError NcpBase::DecodeLinkMetrics(otLinkMetrics *aMetrics, bool aAllowPduCount)
-{
-    otError error   = OT_ERROR_NONE;
-    uint8_t metrics = 0;
-
-    SuccessOrExit(error = mDecoder.ReadUint8(metrics));
-
-    if (metrics & SPINEL_THREAD_LINK_METRIC_PDU_COUNT)
-    {
-        VerifyOrExit(aAllowPduCount, error = OT_ERROR_INVALID_ARGS);
-        aMetrics->mPduCount = true;
-    }
-
-    if (metrics & SPINEL_THREAD_LINK_METRIC_LQI)
-    {
-        aMetrics->mLqi = true;
-    }
-
-    if (metrics & SPINEL_THREAD_LINK_METRIC_LINK_MARGIN)
-    {
-        aMetrics->mLinkMargin = true;
-    }
-
-    if (metrics & SPINEL_THREAD_LINK_METRIC_RSSI)
-    {
-        aMetrics->mRssi = true;
-    }
-
-exit:
-    return error;
-}
-
 otError NcpBase::EncodeLinkMetricsValues(const otLinkMetricsValues *aMetricsValues)
 {
     otError error = OT_ERROR_NONE;
@@ -352,7 +320,7 @@
 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_MLR_REQUEST>(void)
 {
     otError      error = OT_ERROR_NONE;
-    otIp6Address addresses[kIp6AddressesNumMax];
+    otIp6Address addresses[OT_IP6_MAX_MLR_ADDRESSES];
     uint8_t      addressesCount = 0U;
     bool         timeoutPresent = false;
     uint32_t     timeout;
@@ -361,7 +329,7 @@
 
     while (mDecoder.GetRemainingLengthInStruct())
     {
-        VerifyOrExit(addressesCount < kIp6AddressesNumMax, error = OT_ERROR_NO_BUFS);
+        VerifyOrExit(addressesCount < Ip6AddressesTlv::kMaxAddresses, error = OT_ERROR_NO_BUFS);
         SuccessOrExit(error = mDecoder.ReadIp6Address(addresses[addressesCount]));
         ++addressesCount;
     }
@@ -1260,17 +1228,21 @@
 
     if (aDataset.mComponents.mIsActiveTimestampPresent)
     {
+        const otTimestamp &activeTimestamp = aDataset.mActiveTimestamp;
+
         SuccessOrExit(error = mEncoder.OpenStruct());
         SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_PROP_DATASET_ACTIVE_TIMESTAMP));
-        SuccessOrExit(error = mEncoder.WriteUint64(aDataset.mActiveTimestamp));
+        SuccessOrExit(error = mEncoder.WriteUint64(activeTimestamp.mSeconds));
         SuccessOrExit(error = mEncoder.CloseStruct());
     }
 
     if (aDataset.mComponents.mIsPendingTimestampPresent)
     {
+        const otTimestamp &pendingTimestamp = aDataset.mPendingTimestamp;
+
         SuccessOrExit(error = mEncoder.OpenStruct());
         SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_PROP_DATASET_PENDING_TIMESTAMP));
-        SuccessOrExit(error = mEncoder.WriteUint64(aDataset.mPendingTimestamp));
+        SuccessOrExit(error = mEncoder.WriteUint64(pendingTimestamp.mSeconds));
         SuccessOrExit(error = mEncoder.CloseStruct());
     }
 
@@ -1432,7 +1404,9 @@
 
             if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
             {
-                SuccessOrExit(error = mDecoder.ReadUint64(aDataset.mActiveTimestamp));
+                SuccessOrExit(error = mDecoder.ReadUint64(aDataset.mActiveTimestamp.mSeconds));
+                aDataset.mActiveTimestamp.mTicks         = 0;
+                aDataset.mActiveTimestamp.mAuthoritative = false;
             }
 
             aDataset.mComponents.mIsActiveTimestampPresent = true;
@@ -1442,7 +1416,9 @@
 
             if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
             {
-                SuccessOrExit(error = mDecoder.ReadUint64(aDataset.mPendingTimestamp));
+                SuccessOrExit(error = mDecoder.ReadUint64(aDataset.mPendingTimestamp.mSeconds));
+                aDataset.mPendingTimestamp.mTicks         = 0;
+                aDataset.mPendingTimestamp.mAuthoritative = false;
             }
 
             aDataset.mComponents.mIsPendingTimestampPresent = true;
@@ -2714,27 +2690,28 @@
 
 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MSG_BUFFER_COUNTERS>(void)
 {
-    otError      error;
+    otError      error = OT_ERROR_NONE;
     otBufferInfo bufferInfo;
 
     otMessageGetBufferInfo(mInstance, &bufferInfo);
 
     SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mTotalBuffers));
     SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mFreeBuffers));
-    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.m6loSendMessages));
-    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.m6loSendBuffers));
-    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.m6loReassemblyMessages));
-    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.m6loReassemblyBuffers));
-    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mIp6Messages));
-    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mIp6Buffers));
-    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mMplMessages));
-    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mMplBuffers));
-    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mMleMessages));
-    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mMleBuffers));
-    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mArpMessages));
-    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mArpBuffers));
-    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mCoapMessages));
-    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mCoapBuffers));
+
+    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.m6loSendQueue.mNumMessages));
+    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.m6loSendQueue.mNumBuffers));
+    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.m6loReassemblyQueue.mNumMessages));
+    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.m6loReassemblyQueue.mNumBuffers));
+    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mIp6Queue.mNumMessages));
+    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mIp6Queue.mNumBuffers));
+    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mMplQueue.mNumMessages));
+    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mMplQueue.mNumBuffers));
+    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mMleQueue.mNumMessages));
+    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mMleQueue.mNumBuffers));
+    SuccessOrExit(error = mEncoder.WriteUint16(0)); // Write zero for ARP for backward compatibility.
+    SuccessOrExit(error = mEncoder.WriteUint16(0));
+    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mCoapQueue.mNumMessages));
+    SuccessOrExit(error = mEncoder.WriteUint16(bufferInfo.mCoapQueue.mNumBuffers));
 
 exit:
     return error;
@@ -3151,11 +3128,11 @@
     otError             error = OT_ERROR_NONE;
     struct otIp6Address address;
     uint8_t             seriesId;
-    otLinkMetrics       linkMetrics = {};
+    otLinkMetrics       linkMetrics = {false, false, false, false, false};
 
     SuccessOrExit(error = mDecoder.ReadIp6Address(address));
     SuccessOrExit(error = mDecoder.ReadUint8(seriesId));
-    SuccessOrExit(error = DecodeLinkMetrics(&linkMetrics, true));
+    SuccessOrExit(error = DecodeLinkMetrics(&linkMetrics, /* aAllowPduCount */ true));
 
     error =
         otLinkMetricsQuery(mInstance, &address, seriesId, &linkMetrics, &NcpBase::HandleLinkMetricsReport_Jump, this);
@@ -3186,11 +3163,11 @@
     otError             error = OT_ERROR_NONE;
     struct otIp6Address address;
     uint8_t             controlFlags;
-    otLinkMetrics       linkMetrics = {};
+    otLinkMetrics       linkMetrics = {false, false, false, false, false};
 
     SuccessOrExit(error = mDecoder.ReadIp6Address(address));
     SuccessOrExit(error = mDecoder.ReadUint8(controlFlags));
-    SuccessOrExit(error = DecodeLinkMetrics(&linkMetrics, false));
+    SuccessOrExit(error = DecodeLinkMetrics(&linkMetrics, /* aAllowPduCount */ false));
 
     error = otLinkMetricsConfigEnhAckProbing(mInstance, &address, static_cast<otLinkMetricsEnhAckFlags>(controlFlags),
                                              controlFlags ? &linkMetrics : nullptr,
@@ -3207,14 +3184,14 @@
     struct otIp6Address      address;
     uint8_t                  seriesId;
     uint8_t                  types;
-    otLinkMetrics            linkMetrics = {};
-    otLinkMetricsSeriesFlags seriesFlags = {};
+    otLinkMetrics            linkMetrics = {false, false, false, false, false};
+    otLinkMetricsSeriesFlags seriesFlags = {false, false, false, false};
 
     SuccessOrExit(error = mDecoder.ReadIp6Address(address));
     SuccessOrExit(error = mDecoder.ReadUint8(seriesId));
     SuccessOrExit(error = mDecoder.ReadUint8(types));
 
-    SuccessOrExit(error = DecodeLinkMetrics(&linkMetrics, true));
+    SuccessOrExit(error = DecodeLinkMetrics(&linkMetrics, /* aAllowPduCount */ true));
 
     if (types & SPINEL_THREAD_FRAME_TYPE_MLE_LINK_PROBE)
     {
@@ -4078,15 +4055,21 @@
 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
 template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_DEBUG_TREL_TEST_MODE_ENABLE>(void)
 {
-    return mEncoder.WriteBool(mTrelTestModeEnable);
+    return mEncoder.WriteBool(!otTrelIsFilterEnabled(mInstance));
 }
 
 template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_DEBUG_TREL_TEST_MODE_ENABLE>(void)
 {
     otError error = OT_ERROR_NONE;
+    bool    testMode;
 
-    SuccessOrExit(error = mDecoder.ReadBool(mTrelTestModeEnable));
-    error = otPlatTrelUdp6SetTestMode(mInstance, mTrelTestModeEnable);
+    SuccessOrExit(error = mDecoder.ReadBool(testMode));
+
+    // Note that `TEST_MODE` being `true` indicates that the TREL
+    // interface should be enabled and functional, so filtering
+    // should be disabled.
+
+    otTrelSetFilterEnabled(mInstance, !testMode);
 
 exit:
     return error;
@@ -4247,11 +4230,6 @@
     {
         uint8_t flags = static_cast<uint8_t>(aResult->mVersion << SPINEL_BEACON_THREAD_FLAG_VERSION_SHIFT);
 
-        if (aResult->mIsJoinable)
-        {
-            flags |= SPINEL_BEACON_THREAD_FLAG_JOINABLE;
-        }
-
         if (aResult->mIsNative)
         {
             flags |= SPINEL_BEACON_THREAD_FLAG_NATIVE;
diff --git a/src/ncp/ncp_base_radio.cpp b/src/ncp/ncp_base_radio.cpp
index b53a0db..975cc3f 100644
--- a/src/ncp/ncp_base_radio.cpp
+++ b/src/ncp/ncp_base_radio.cpp
@@ -512,6 +512,25 @@
     return error;
 }
 
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_RCP_ENH_ACK_PROBING>(void)
+{
+    otError             error = OT_ERROR_NONE;
+    uint16_t            shortAddress;
+    const otExtAddress *extAddress;
+    otLinkMetrics       linkMetrics = {false, false, false, false, false};
+
+    SuccessOrExit(error = mDecoder.ReadUint16(shortAddress));
+    SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
+    SuccessOrExit(error = DecodeLinkMetrics(&linkMetrics, /* aAllowPduCount */ true));
+
+    error = otPlatRadioConfigureEnhAckProbing(mInstance, linkMetrics, shortAddress, extAddress);
+
+exit:
+    return error;
+}
+#endif
+
 } // namespace Ncp
 } // namespace ot
 
diff --git a/src/posix/CMakeLists.txt b/src/posix/CMakeLists.txt
index 1353ce0..2563451 100644
--- a/src/posix/CMakeLists.txt
+++ b/src/posix/CMakeLists.txt
@@ -85,7 +85,7 @@
 
 if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
     set(CPACK_GENERATOR "DEB")
-    set(CPACK_DEBIAN_PACKAGE_MAINTAINER "OpenThread Authors <openthread-users@googlegroups.com")
-    set(CPACK_PACKAGE_CONTACT "OpenThread Authors <openthread-users@googlegroups.com")
+    set(CPACK_DEBIAN_PACKAGE_MAINTAINER "OpenThread Authors (https://github.com/openthread/openthread)")
+    set(CPACK_PACKAGE_CONTACT "OpenThread Authors (https://github.com/openthread/openthread)")
     include(CPack)
 endif()
diff --git a/src/posix/main.c b/src/posix/main.c
index ebecb47..df014ea 100644
--- a/src/posix/main.c
+++ b/src/posix/main.c
@@ -64,14 +64,11 @@
 #include "cli/cli_config.h"
 #endif
 #include <common/code_utils.hpp>
-#include <common/logging.hpp>
 #include <lib/platform/exit_code.h>
 #include <openthread/openthread-system.h>
 #include <openthread/platform/misc.h>
 
-#ifndef OPENTHREAD_ENABLE_COVERAGE
-#define OPENTHREAD_ENABLE_COVERAGE 0
-#endif
+#include "lib/platform/reset_util.h"
 
 /**
  * This function initializes NCP app.
@@ -90,7 +87,7 @@
 /**
  * This function updates the file descriptor sets with file descriptors used by console.
  *
- * @param[inout]    aMainloop   A pointer to the mainloop context.
+ * @param[in,out]   aMainloop   A pointer to the mainloop context.
  *
  */
 void otAppNcpProcess(const otSysMainloopContext *aContext);
@@ -112,7 +109,7 @@
 /**
  * This function updates the file descriptor sets with file descriptors used by console.
  *
- * @param[inout]    aMainloop   A pointer to the mainloop context.
+ * @param[in,out]   aMainloop   A pointer to the mainloop context.
  *
  */
 void otAppCliUpdate(otSysMainloopContext *aMainloop);
@@ -133,10 +130,6 @@
     bool             mIsVerbose;         ///< Whether to print log to stderr.
 } PosixConfig;
 
-static jmp_buf gResetJump;
-
-void __gcov_flush();
-
 /**
  * This enumeration defines the argument return values.
  *
@@ -371,14 +364,7 @@
     prctl(PR_SET_PDEATHSIG, SIGHUP);
 #endif
 
-    if (setjmp(gResetJump))
-    {
-        alarm(0);
-#if OPENTHREAD_ENABLE_COVERAGE
-        __gcov_flush();
-#endif
-        execvp(argv[0], argv);
-    }
+    OT_SETUP_RESET_JUMP(argv);
 
     ParseArg(argc, argv, &config);
     openlog(argv[0], LOG_PID | (config.mIsVerbose ? LOG_PERROR : 0), LOG_DAEMON);
diff --git a/src/posix/platform/CMakeLists.txt b/src/posix/platform/CMakeLists.txt
index 0e06d4e..701eb21 100644
--- a/src/posix/platform/CMakeLists.txt
+++ b/src/posix/platform/CMakeLists.txt
@@ -37,6 +37,17 @@
     )
 endif()
 
+option(OT_POSIX_INSTALL_EXTERNAL_ROUTES "Install External Routes as IPv6 routes" ON)
+if(OT_POSIX_INSTALL_EXTERNAL_ROUTES)
+    target_compile_definitions(ot-posix-config
+        INTERFACE "OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE=1"
+    )
+else()
+    target_compile_definitions(ot-posix-config
+        INTERFACE "OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE=0"
+    )
+endif()
+
 option(OT_POSIX_VIRTUAL_TIME "enable virtual time" OFF)
 if(OT_POSIX_VIRTUAL_TIME)
     target_compile_definitions(ot-posix-config
@@ -51,6 +62,13 @@
     )
 endif()
 
+option(OT_POSIX_SECURE_SETTINGS "enable secure settings" OFF)
+if (OT_POSIX_SECURE_SETTINGS)
+    target_compile_definitions(ot-posix-config
+        INTERFACE "OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE=1"
+    )
+endif()
+
 set(OT_POSIX_CONFIG_RCP_BUS "" CACHE STRING "RCP bus type")
 if(OT_POSIX_CONFIG_RCP_BUS)
     target_compile_definitions(ot-posix-config
@@ -62,11 +80,15 @@
     set(OT_CONFIG "openthread-core-posix-config.h" PARENT_SCOPE)
 endif()
 
+set(OT_POSIX_CONFIG_RCP_VENDOR_INTERFACE "vendor_interface_example.cpp"
+       CACHE STRING "vendor interface implementation")
+
 add_library(openthread-posix
     alarm.cpp
     backbone.cpp
     daemon.cpp
     entropy.cpp
+    firewall.cpp
     hdlc_interface.cpp
     infra_if.cpp
     logging.cpp
@@ -80,9 +102,11 @@
     settings.cpp
     spi_interface.cpp
     system.cpp
-    trel_udp6.cpp
+    trel.cpp
     udp.cpp
+    utils.cpp
     virtual_time.cpp
+    ${OT_POSIX_CONFIG_RCP_VENDOR_INTERFACE}
 )
 
 target_link_libraries(openthread-posix
diff --git a/src/posix/platform/Makefile.am b/src/posix/platform/Makefile.am
index 7a2c723..ab7ae85 100644
--- a/src/posix/platform/Makefile.am
+++ b/src/posix/platform/Makefile.am
@@ -48,6 +48,7 @@
     backbone.cpp                            \
     daemon.cpp                              \
     entropy.cpp                             \
+    firewall.cpp                            \
     hdlc_interface.cpp                      \
     infra_if.cpp                            \
     logging.cpp                             \
@@ -61,8 +62,9 @@
     settings.cpp                            \
     spi_interface.cpp                       \
     system.cpp                              \
-    trel_udp6.cpp                           \
+    trel.cpp                                \
     udp.cpp                                 \
+    utils.cpp                               \
     virtual_time.cpp                        \
     $(NULL)
 
diff --git a/src/posix/platform/backbone.cpp b/src/posix/platform/backbone.cpp
index 4a29d0c..c5f1f95 100644
--- a/src/posix/platform/backbone.cpp
+++ b/src/posix/platform/backbone.cpp
@@ -48,7 +48,11 @@
 
 void platformBackboneInit(const char *aInterfaceName)
 {
-    VerifyOrExit(aInterfaceName != nullptr && aInterfaceName[0] != '\0');
+    if (aInterfaceName == nullptr || aInterfaceName[0] == '\0')
+    {
+        otLogWarnPlat("Backbone Router feature is disabled: infra/backbone interface is missing");
+        ExitNow();
+    }
 
     VerifyOrDie(strnlen(aInterfaceName, sizeof(gBackboneNetifName)) < sizeof(gBackboneNetifName),
                 OT_EXIT_INVALID_ARGUMENTS);
diff --git a/src/posix/platform/firewall.cpp b/src/posix/platform/firewall.cpp
new file mode 100644
index 0000000..19ad8c5
--- /dev/null
+++ b/src/posix/platform/firewall.cpp
@@ -0,0 +1,134 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ * @brief
+ *   This file includes the implementation of OTBR firewall.
+ */
+
+#include "firewall.hpp"
+
+#include <string.h>
+
+#include <openthread/logging.h>
+#include <openthread/netdata.h>
+
+#include "common/code_utils.hpp"
+#include "posix/platform/utils.hpp"
+
+namespace ot {
+namespace Posix {
+
+#if defined(__linux__) && OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE
+
+#if !OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || !OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
+#error Configurations 'OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE' and 'OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE' are required.
+#endif
+
+static const char kIpsetCommand[]             = OPENTHREAD_POSIX_CONFIG_IPSET_BINARY;
+static const char kIngressDenySrcIpSet[]      = "otbr-ingress-deny-src";
+static const char kIngressDenySrcSwapIpSet[]  = "otbr-ingress-deny-src-swap";
+static const char kIngressAllowDstIpSet[]     = "otbr-ingress-allow-dst";
+static const char kIngressAllowDstSwapIpSet[] = "otbr-ingress-allow-dst-swap";
+
+class IpSetManager
+{
+public:
+    otError FlushIpSet(const char *aName);
+    otError AddToIpSet(const char *aSetName, const char *aAddress);
+    otError SwapIpSets(const char *aSetName1, const char *aSetName2);
+};
+
+inline otError IpSetManager::FlushIpSet(const char *aName)
+{
+    return ExecuteCommand("%s flush %s", kIpsetCommand, aName);
+}
+
+inline otError IpSetManager::AddToIpSet(const char *aSetName, const char *aAddress)
+{
+    return ExecuteCommand("%s add %s %s -exist", kIpsetCommand, aSetName, aAddress);
+}
+
+inline otError IpSetManager::SwapIpSets(const char *aSetName1, const char *aSetName2)
+{
+    return ExecuteCommand("%s swap %s %s", kIpsetCommand, aSetName1, aSetName2);
+}
+
+void UpdateIpSets(otInstance *aInstance)
+{
+    otError               error    = OT_ERROR_NONE;
+    otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
+    otBorderRouterConfig  config;
+    otIp6Prefix           prefix;
+    char                  prefixBuf[OT_IP6_PREFIX_STRING_SIZE];
+    IpSetManager          ipSetManager;
+
+    // 1. Flush the '*-swap' ipsets
+    SuccessOrExit(error = ipSetManager.FlushIpSet(kIngressAllowDstSwapIpSet));
+    SuccessOrExit(error = ipSetManager.FlushIpSet(kIngressDenySrcSwapIpSet));
+
+    // 2. Update otbr-deny-src-swap
+    while (otNetDataGetNextOnMeshPrefix(aInstance, &iterator, &config) == OT_ERROR_NONE)
+    {
+        if (config.mDp)
+        {
+            continue;
+        }
+        otIp6PrefixToString(&config.mPrefix, prefixBuf, sizeof(prefixBuf));
+        SuccessOrExit(error = ipSetManager.AddToIpSet(kIngressDenySrcSwapIpSet, prefixBuf));
+    }
+    memcpy(prefix.mPrefix.mFields.m8, otThreadGetMeshLocalPrefix(aInstance)->m8,
+           sizeof(otThreadGetMeshLocalPrefix(aInstance)->m8));
+    prefix.mLength = OT_IP6_PREFIX_BITSIZE;
+    otIp6PrefixToString(&prefix, prefixBuf, sizeof(prefixBuf));
+    SuccessOrExit(error = ipSetManager.AddToIpSet(kIngressDenySrcSwapIpSet, prefixBuf));
+
+    // 3. Update otbr-allow-dst-swap
+    iterator = OT_NETWORK_DATA_ITERATOR_INIT;
+    while (otNetDataGetNextOnMeshPrefix(aInstance, &iterator, &config) == OT_ERROR_NONE)
+    {
+        otIp6PrefixToString(&config.mPrefix, prefixBuf, sizeof(prefixBuf));
+        SuccessOrExit(error = ipSetManager.AddToIpSet(kIngressAllowDstSwapIpSet, prefixBuf));
+    }
+
+    // 4. Swap ipsets to let them take effect
+    SuccessOrExit(error = ipSetManager.SwapIpSets(kIngressDenySrcSwapIpSet, kIngressDenySrcIpSet));
+    SuccessOrExit(error = ipSetManager.SwapIpSets(kIngressAllowDstSwapIpSet, kIngressAllowDstIpSet));
+
+exit:
+    if (error != OT_ERROR_NONE)
+    {
+        otLogWarnPlat("Failed to update ipsets: %s", otThreadErrorToString(error));
+    }
+}
+
+#endif // defined(__linux__) && OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE
+
+} // namespace Posix
+} // namespace ot
diff --git a/etc/cmake/openthread-config-generic.h.in b/src/posix/platform/firewall.hpp
similarity index 76%
rename from etc/cmake/openthread-config-generic.h.in
rename to src/posix/platform/firewall.hpp
index 95c23b8..a564c56 100644
--- a/etc/cmake/openthread-config-generic.h.in
+++ b/src/posix/platform/firewall.hpp
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2019, The OpenThread Authors.
+ *  Copyright (c) 2021, The OpenThread Authors.
  *  All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -25,3 +25,23 @@
  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  *  POSSIBILITY OF SUCH DAMAGE.
  */
+
+#ifndef OT_POSIX_PLATFORM_FIREWALL_HPP_
+#define OT_POSIX_PLATFORM_FIREWALL_HPP_
+
+#include "posix/platform/openthread-posix-config.h"
+
+#if OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE
+
+#include "openthread/thread.h"
+
+namespace ot {
+namespace Posix {
+
+void UpdateIpSets(otInstance *aInstance);
+
+} // namespace Posix
+} // namespace ot
+
+#endif // OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE
+#endif // OT_POSIX_PLATFORM_FIREWALL_HPP_
diff --git a/src/posix/platform/hdlc_interface.cpp b/src/posix/platform/hdlc_interface.cpp
index 264a123..ffbc206 100644
--- a/src/posix/platform/hdlc_interface.cpp
+++ b/src/posix/platform/hdlc_interface.cpp
@@ -57,8 +57,9 @@
 #include <termios.h>
 #include <unistd.h>
 
+#include <openthread/logging.h>
+
 #include "common/code_utils.hpp"
-#include "common/logging.hpp"
 
 #ifdef __APPLE__
 
@@ -134,6 +135,8 @@
     , mHdlcDecoder(aFrameBuffer, HandleHdlcFrame, this)
     , mRadioUrl(nullptr)
 {
+    memset(&mInterfaceMetrics, 0, sizeof(mInterfaceMetrics));
+    mInterfaceMetrics.mRcpInterfaceType = OT_POSIX_RCP_BUS_UART;
 }
 
 void HdlcInterface::OnRcpReset(void)
@@ -251,6 +254,19 @@
 
 exit:
 #endif // OPENTHREAD_POSIX_VIRTUAL_TIME
+
+    mInterfaceMetrics.mTransferredFrameCount++;
+    if (error == OT_ERROR_NONE)
+    {
+        mInterfaceMetrics.mTxFrameCount++;
+        mInterfaceMetrics.mTxFrameByteCount += aLength;
+        mInterfaceMetrics.mTransferredValidFrameCount++;
+    }
+    else
+    {
+        mInterfaceMetrics.mTransferredGarbageFrameCount++;
+    }
+
     return error;
 }
 
@@ -653,12 +669,18 @@
 
 void HdlcInterface::HandleHdlcFrame(otError aError)
 {
+    mInterfaceMetrics.mTransferredFrameCount++;
+
     if (aError == OT_ERROR_NONE)
     {
+        mInterfaceMetrics.mRxFrameCount++;
+        mInterfaceMetrics.mRxFrameByteCount += mReceiveFrameBuffer.GetLength();
+        mInterfaceMetrics.mTransferredValidFrameCount++;
         mReceiveFrameCallback(mReceiveFrameContext);
     }
     else
     {
+        mInterfaceMetrics.mTransferredGarbageFrameCount++;
         mReceiveFrameBuffer.DiscardFrame();
         otLogWarnPlat("Error decoding hdlc frame: %s", otThreadErrorToString(aError));
     }
diff --git a/src/posix/platform/hdlc_interface.hpp b/src/posix/platform/hdlc_interface.hpp
index 73c1a39..4fa2ba0 100644
--- a/src/posix/platform/hdlc_interface.hpp
+++ b/src/posix/platform/hdlc_interface.hpp
@@ -120,10 +120,10 @@
     /**
      * This method updates the file descriptor sets with file descriptors used by the radio driver.
      *
-     * @param[inout]  aReadFdSet   A reference to the read file descriptors.
-     * @param[inout]  aWriteFdSet  A reference to the write file descriptors.
-     * @param[inout]  aMaxFd       A reference to the max file descriptor.
-     * @param[inout]  aTimeout     A reference to the timeout.
+     * @param[in,out]  aReadFdSet   A reference to the read file descriptors.
+     * @param[in,out]  aWriteFdSet  A reference to the write file descriptors.
+     * @param[in,out]  aMaxFd       A reference to the max file descriptor.
+     * @param[in,out]  aTimeout     A reference to the timeout.
      *
      */
     void UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, int &aMaxFd, struct timeval &aTimeout);
@@ -169,6 +169,14 @@
      */
     otError ResetConnection(void);
 
+    /**
+     * This method returns the RCP interface metrics.
+     *
+     * @returns The RCP interface metrics.
+     *
+     */
+    const otRcpInterfaceMetrics *GetRcpInterfaceMetrics(void) const { return &mInterfaceMetrics; }
+
 private:
     /**
      * This method instructs `HdlcInterface` to read and decode data from radio over the socket.
@@ -258,6 +266,8 @@
     Hdlc::Decoder   mHdlcDecoder;
     const Url::Url *mRadioUrl;
 
+    otRcpInterfaceMetrics mInterfaceMetrics;
+
     // Non-copyable, intentionally not implemented.
     HdlcInterface(const HdlcInterface &);
     HdlcInterface &operator=(const HdlcInterface &);
diff --git a/src/posix/platform/include/openthread/openthread-system.h b/src/posix/platform/include/openthread/openthread-system.h
index 7b2a1f2..9a1a666 100644
--- a/src/posix/platform/include/openthread/openthread-system.h
+++ b/src/posix/platform/include/openthread/openthread-system.h
@@ -45,6 +45,8 @@
 #include <openthread/instance.h>
 #include <openthread/platform/misc.h>
 
+#include "lib/spinel/radio_spinel_metrics.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -83,6 +85,22 @@
 } otPlatformConfig;
 
 /**
+ * This structure represents RCP interface metrics.
+ *
+ */
+typedef struct otRcpInterfaceMetrics
+{
+    uint8_t  mRcpInterfaceType;             ///< The RCP interface type.
+    uint64_t mTransferredFrameCount;        ///< The number of transferred frames.
+    uint64_t mTransferredValidFrameCount;   ///< The number of transferred valid frames.
+    uint64_t mTransferredGarbageFrameCount; ///< The number of transferred garbage frames.
+    uint64_t mRxFrameCount;                 ///< The number of received frames.
+    uint64_t mRxFrameByteCount;             ///< The number of received bytes.
+    uint64_t mTxFrameCount;                 ///< The number of transmitted frames.
+    uint64_t mTxFrameByteCount;             ///< The number of transmitted bytes.
+} otRcpInterfaceMetrics;
+
+/**
  * This function performs all platform-specific initialization of OpenThread's drivers and initializes the OpenThread
  * instance.
  *
@@ -123,7 +141,7 @@
  * This function updates the file descriptor sets with file descriptors used by OpenThread drivers.
  *
  * @param[in]       aInstance   The OpenThread instance structure.
- * @param[inout]    aMainloop   A pointer to the mainloop context.
+ * @param[in,out]   aMainloop   A pointer to the mainloop context.
  *
  */
 void otSysMainloopUpdate(otInstance *aInstance, otSysMainloopContext *aMainloop);
@@ -131,7 +149,7 @@
 /**
  * This function polls OpenThread's mainloop.
  *
- * @param[inout]    aMainloop   A pointer to the mainloop context.
+ * @param[in,out]   aMainloop   A pointer to the mainloop context.
  *
  * @returns value returned from select().
  *
@@ -176,6 +194,30 @@
  */
 unsigned int otSysGetThreadNetifIndex(void);
 
+/**
+ * This method returns the infrastructure network interface name.
+ *
+ * @returns The infrastructure network interface name, or `nullptr` if not specified.
+ *
+ */
+const char *otSysGetInfraNetifName(void);
+
+/**
+ * This method returns the radio spinel metrics.
+ *
+ * @returns The radio spinel metrics.
+ *
+ */
+const otRadioSpinelMetrics *otSysGetRadioSpinelMetrics(void);
+
+/**
+ * This method returns the RCP interface metrics.
+ *
+ * @returns The RCP interface metrics.
+ *
+ */
+const otRcpInterfaceMetrics *otSysGetRcpInterfaceMetrics(void);
+
 #ifdef __cplusplus
 } // end of extern "C"
 #endif
diff --git a/src/posix/platform/include/openthread/platform/secure_settings.h b/src/posix/platform/include/openthread/platform/secure_settings.h
index 90ce5c3..d206c26 100644
--- a/src/posix/platform/include/openthread/platform/secure_settings.h
+++ b/src/posix/platform/include/openthread/platform/secure_settings.h
@@ -79,15 +79,15 @@
  * Note that the underlying storage implementation is not required to maintain the order of settings with multiple
  * values. The order of such values MAY change after ANY write operation to the store.
  *
- * @param[in]     aInstance     The OpenThread instance structure.
- * @param[in]     aKey          The key associated with the requested setting.
- * @param[in]     aIndex        The index of the specific item to get.
- * @param[out]    aValue        A pointer to where the value of the setting should be written. May be set to NULL if
- *                              just testing for the presence or length of a setting.
- * @param[inout]  aValueLength  A pointer to the length of the value. When called, this pointer should point to an
- *                              integer containing the maximum value size that can be written to aValue. At return,
- *                              the actual length of the setting is written. This may be set to NULL if performing
- *                              a presence check.
+ * @param[in]      aInstance     The OpenThread instance structure.
+ * @param[in]      aKey          The key associated with the requested setting.
+ * @param[in]      aIndex        The index of the specific item to get.
+ * @param[out]     aValue        A pointer to where the value of the setting should be written. May be set to NULL if
+ *                               just testing for the presence or length of a setting.
+ * @param[in,out]  aValueLength  A pointer to the length of the value. When called, this pointer should point to an
+ *                               integer containing the maximum value size that can be written to aValue. At return,
+ *                               the actual length of the setting is written. This may be set to NULL if performing
+ *                               a presence check.
  *
  * @retval OT_ERROR_NONE             The given setting was found and fetched successfully.
  * @retval OT_ERROR_NOT_FOUND        The given setting was not found in the setting store.
diff --git a/src/posix/platform/infra_if.cpp b/src/posix/platform/infra_if.cpp
index 859967c..11f1562 100644
--- a/src/posix/platform/infra_if.cpp
+++ b/src/posix/platform/infra_if.cpp
@@ -101,6 +101,11 @@
     return ot::Posix::InfraNetif::Get().IsRunning();
 }
 
+const char *otSysGetInfraNetifName(void)
+{
+    return ot::Posix::InfraNetif::Get().GetNetifName();
+}
+
 namespace ot {
 namespace Posix {
 namespace {
@@ -304,7 +309,11 @@
     ssize_t  rval;
     uint32_t ifIndex = 0;
 
-    VerifyOrExit(aIfName != nullptr && aIfName[0] != '\0');
+    if (aIfName == nullptr || aIfName[0] == '\0')
+    {
+        otLogWarnPlat("Border Routing feature is disabled: infra/backbone interface is missing");
+        ExitNow();
+    }
 
     VerifyOrDie(strnlen(aIfName, sizeof(mInfraIfName)) <= sizeof(mInfraIfName) - 1, OT_EXIT_INVALID_ARGUMENTS);
     strcpy(mInfraIfName, aIfName);
@@ -313,7 +322,7 @@
     ifIndex = if_nametoindex(aIfName);
     if (ifIndex == 0)
     {
-        otLogCritPlat("failed to get the index for infra interface %s", aIfName);
+        otLogCritPlat("Failed to get the index for infra interface %s", aIfName);
         DieNow(OT_EXIT_INVALID_ARGUMENTS);
     }
     mInfraIfIndex = ifIndex;
@@ -322,7 +331,7 @@
 #ifdef __linux__
     rval = setsockopt(mInfraIfIcmp6Socket, SOL_SOCKET, SO_BINDTODEVICE, mInfraIfName, strlen(mInfraIfName));
 #else  // __NetBSD__ || __FreeBSD__ || __APPLE__
-    rval = setsockopt(mInfraIfIcmp6Socket, IPPROTO_IP, IP_BOUND_IF, &mInfraIfIndex, sizeof(mInfraIfIndex));
+    rval = setsockopt(mInfraIfIcmp6Socket, IPPROTO_IPV6, IPV6_BOUND_IF, &mInfraIfIndex, sizeof(mInfraIfIndex));
 #endif // __linux__
     VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
 
@@ -399,7 +408,7 @@
     len = recv(mNetLinkSocket, msgBuffer.mBuffer, sizeof(msgBuffer.mBuffer), 0);
     if (len < 0)
     {
-        otLogCritPlat("failed to receive netlink message: %s", strerror(errno));
+        otLogCritPlat("Failed to receive netlink message: %s", strerror(errno));
         ExitNow();
     }
 
@@ -466,7 +475,7 @@
     rval = recvmsg(mInfraIfIcmp6Socket, &msg, 0);
     if (rval < 0)
     {
-        otLogWarnPlat("failed to receive ICMPv6 message: %s", strerror(errno));
+        otLogWarnPlat("Failed to receive ICMPv6 message: %s", strerror(errno));
         ExitNow(error = OT_ERROR_DROP);
     }
 
@@ -502,7 +511,7 @@
 exit:
     if (error != OT_ERROR_NONE)
     {
-        otLogDebgPlat("failed to handle ICMPv6 message: %s", otThreadErrorToString(error));
+        otLogDebgPlat("Failed to handle ICMPv6 message: %s", otThreadErrorToString(error));
     }
 }
 
diff --git a/src/posix/platform/infra_if.hpp b/src/posix/platform/infra_if.hpp
index f638047..ccd2b12 100644
--- a/src/posix/platform/infra_if.hpp
+++ b/src/posix/platform/infra_if.hpp
@@ -53,7 +53,7 @@
     /**
      * This method updates the fd_set and timeout for mainloop.
      *
-     * @param[inout]    aContext    A reference to the mainloop context.
+     * @param[in,out]   aContext    A reference to the mainloop context.
      *
      */
     void Update(otSysMainloopContext &aContext) override;
@@ -128,10 +128,20 @@
                         const otIp6Address &aDestAddress,
                         const uint8_t *     aBuffer,
                         uint16_t            aBufferLength);
+
+    /**
+     * This method gets the infrastructure network interface name.
+     *
+     * @returns The infrastructure network interface name, or `nullptr` if not specified.
+     *
+     */
+    const char *GetNetifName(void) const { return (mInfraIfIndex != 0) ? mInfraIfName : nullptr; }
+
     /**
      * This function gets the infrastructure network interface singleton.
      *
      * @returns The singleton object.
+     *
      */
     static InfraNetif &Get(void);
 
diff --git a/src/posix/platform/logging.cpp b/src/posix/platform/logging.cpp
index 717156d..8dd2a5b 100644
--- a/src/posix/platform/logging.cpp
+++ b/src/posix/platform/logging.cpp
@@ -36,7 +36,7 @@
 #include <openthread/platform/logging.h>
 
 #if OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED
-void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
+OT_TOOL_WEAK void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
 {
     OT_UNUSED_VARIABLE(aLogRegion);
 
diff --git a/src/posix/platform/mainloop.hpp b/src/posix/platform/mainloop.hpp
index e6e7e25..4f0fa7c 100644
--- a/src/posix/platform/mainloop.hpp
+++ b/src/posix/platform/mainloop.hpp
@@ -52,7 +52,7 @@
     /**
      * This method registers events in the mainloop.
      *
-     * @param[inout]    aContext    A reference to the mainloop context.
+     * @param[in,out]   aContext    A reference to the mainloop context.
      *
      */
     virtual void Update(otSysMainloopContext &aContext) = 0;
@@ -65,6 +65,12 @@
      */
     virtual void Process(const otSysMainloopContext &aContext) = 0;
 
+    /**
+     * This method marks desturctor virtual method.
+     *
+     */
+    virtual ~Source() = default;
+
 private:
     Source *mNext = nullptr;
 };
@@ -79,7 +85,7 @@
     /**
      * This method updates event polls in the mainloop context.
      *
-     * @param[inout]    aContext    A reference to the mainloop context.
+     * @param[in,out]   aContext    A reference to the mainloop context.
      *
      */
     void Update(otSysMainloopContext &aContext);
diff --git a/src/posix/platform/misc.cpp b/src/posix/platform/misc.cpp
index 5de8b9d..77ef07a 100644
--- a/src/posix/platform/misc.cpp
+++ b/src/posix/platform/misc.cpp
@@ -35,10 +35,10 @@
 #include <sys/socket.h>
 #include <unistd.h>
 
+#include <openthread/logging.h>
 #include <openthread/platform/misc.h>
 
 #include "common/code_utils.hpp"
-#include "common/logging.hpp"
 
 otPlatResetReason          gPlatResetReason   = OT_PLAT_RESET_REASON_POWER_ON;
 static otPlatMcuPowerState gPlatMcuPowerState = OT_PLAT_MCU_POWER_STATE_ON;
diff --git a/src/posix/platform/multicast_routing.cpp b/src/posix/platform/multicast_routing.cpp
index a5ef307..6580782 100644
--- a/src/posix/platform/multicast_routing.cpp
+++ b/src/posix/platform/multicast_routing.cpp
@@ -34,6 +34,7 @@
 #include <net/if.h>
 #include <netinet/icmp6.h>
 #include <netinet/in.h>
+#include <stdio.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/types.h>
@@ -45,13 +46,29 @@
 #endif
 
 #include <openthread/backbone_router_ftd.h>
+#include <openthread/logging.h>
 
+#include "core/common/arg_macros.hpp"
 #include "core/common/debug.hpp"
-#include "core/common/logging.hpp"
 
 namespace ot {
 namespace Posix {
 
+#define LogResult(aError, ...)                                                                                      \
+    do                                                                                                              \
+    {                                                                                                               \
+        otError _err = (aError);                                                                                    \
+                                                                                                                    \
+        if (_err == OT_ERROR_NONE)                                                                                  \
+        {                                                                                                           \
+            otLogInfoPlat(OT_FIRST_ARG(__VA_ARGS__) ": %s" OT_REST_ARGS(__VA_ARGS__), otThreadErrorToString(_err)); \
+        }                                                                                                           \
+        else                                                                                                        \
+        {                                                                                                           \
+            otLogWarnPlat(OT_FIRST_ARG(__VA_ARGS__) ": %s" OT_REST_ARGS(__VA_ARGS__), otThreadErrorToString(_err)); \
+        }                                                                                                           \
+    } while (false)
+
 void MulticastRoutingManager::SetUp(void)
 {
     OT_ASSERT(gInstance != nullptr);
@@ -97,7 +114,7 @@
 
     InitMulticastRouterSock();
 
-    otLogResultPlat(OT_ERROR_NONE, "MulticastRoutingManager: %s", __FUNCTION__);
+    LogResult(OT_ERROR_NONE, "MulticastRoutingManager: %s", __FUNCTION__);
 exit:
     return;
 }
@@ -106,7 +123,7 @@
 {
     FinalizeMulticastRouterSock();
 
-    otLogResultPlat(OT_ERROR_NONE, "MulticastRoutingManager: %s", __FUNCTION__);
+    LogResult(OT_ERROR_NONE, "MulticastRoutingManager: %s", __FUNCTION__);
 }
 
 void MulticastRoutingManager::Add(const Ip6::Address &aAddress)
@@ -114,7 +131,9 @@
     VerifyOrExit(IsEnabled());
 
     UnblockInboundMulticastForwardingCache(aAddress);
-    otLogResultPlat(OT_ERROR_NONE, "MulticastRoutingManager: %s: %s", __FUNCTION__, aAddress.ToString().AsCString());
+    UpdateMldReport(aAddress, true);
+
+    LogResult(OT_ERROR_NONE, "MulticastRoutingManager: %s: %s", __FUNCTION__, aAddress.ToString().AsCString());
 
 exit:
     return;
@@ -127,12 +146,30 @@
     VerifyOrExit(IsEnabled());
 
     RemoveInboundMulticastForwardingCache(aAddress);
-    otLogResultPlat(error, "MulticastRoutingManager: %s: %s", __FUNCTION__, aAddress.ToString().AsCString());
+    UpdateMldReport(aAddress, false);
+
+    LogResult(error, "MulticastRoutingManager: %s: %s", __FUNCTION__, aAddress.ToString().AsCString());
 
 exit:
     return;
 }
 
+void MulticastRoutingManager::UpdateMldReport(const Ip6::Address &aAddress, bool isAdd)
+{
+    struct ipv6_mreq ipv6mr;
+    otError          error = OT_ERROR_NONE;
+
+    ipv6mr.ipv6mr_interface = if_nametoindex(gBackboneNetifName);
+    memcpy(&ipv6mr.ipv6mr_multiaddr, aAddress.GetBytes(), sizeof(ipv6mr.ipv6mr_multiaddr));
+    error = (setsockopt(mMulticastRouterSock, IPPROTO_IPV6, (isAdd ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP),
+                        (void *)&ipv6mr, sizeof(ipv6mr))
+                 ? OT_ERROR_FAILED
+                 : OT_ERROR_NONE);
+
+    LogResult(error, "MulticastRoutingManager: %s: address %s %s", __FUNCTION__, aAddress.ToString().AsCString(),
+              (isAdd ? "Added" : "Removed"));
+}
+
 bool MulticastRoutingManager::HasMulticastListener(const Ip6::Address &aAddress) const
 {
     bool                                      found = false;
@@ -246,7 +283,7 @@
     error = AddMulticastForwardingCache(src, dst, static_cast<MifIndex>(mrt6msg->im6_mif));
 
 exit:
-    otLogResultPlat(error, "MulticastRoutingManager: %s", __FUNCTION__);
+    LogResult(error, "MulticastRoutingManager: %s", __FUNCTION__);
 }
 
 otError MulticastRoutingManager::AddMulticastForwardingCache(const Ip6::Address &aSrcAddr,
@@ -301,9 +338,9 @@
 
     SaveMulticastForwardingCache(aSrcAddr, aGroupAddr, aIif, forwardMif);
 exit:
-    otLogResultPlat(error, "MulticastRoutingManager: %s: add dynamic route: %s %s => %s %s", __FUNCTION__,
-                    MifIndexToString(aIif), aSrcAddr.ToString().AsCString(), aGroupAddr.ToString().AsCString(),
-                    MifIndexToString(forwardMif));
+    LogResult(error, "MulticastRoutingManager: %s: add dynamic route: %s %s => %s %s", __FUNCTION__,
+              MifIndexToString(aIif), aSrcAddr.ToString().AsCString(), aGroupAddr.ToString().AsCString(),
+              MifIndexToString(forwardMif));
 
     return error;
 }
@@ -338,9 +375,9 @@
 
         mfc.Set(kMifIndexBackbone, kMifIndexThread);
 
-        otLogResultPlat(error, "MulticastRoutingManager: %s: %s %s => %s %s", __FUNCTION__, MifIndexToString(mfc.mIif),
-                        mfc.mSrcAddr.ToString().AsCString(), mfc.mGroupAddr.ToString().AsCString(),
-                        MifIndexToString(kMifIndexThread));
+        LogResult(error, "MulticastRoutingManager: %s: %s %s => %s %s", __FUNCTION__, MifIndexToString(mfc.mIif),
+                  mfc.mSrcAddr.ToString().AsCString(), mfc.mGroupAddr.ToString().AsCString(),
+                  MifIndexToString(kMifIndexThread));
     }
 }
 
@@ -443,7 +480,7 @@
 
 void MulticastRoutingManager::DumpMulticastForwardingCache(void) const
 {
-#if OPENTHREAD_CONFIG_LOG_PLATFORM && OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_DEBG
+#if OPENTHREAD_CONFIG_LOG_PLATFORM && (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_DEBG)
     otLogDebgPlat("MulticastRoutingManager: ==================== MFC ENTRIES ====================");
 
     for (const MulticastForwardingCache &mfc : mMulticastForwardingCacheTable)
@@ -566,9 +603,9 @@
                 ? OT_ERROR_NONE
                 : OT_ERROR_FAILED;
 
-    otLogResultPlat(error, "MulticastRoutingManager: %s: %s %s => %s %s", __FUNCTION__, MifIndexToString(aMfc.mIif),
-                    aMfc.mSrcAddr.ToString().AsCString(), aMfc.mGroupAddr.ToString().AsCString(),
-                    MifIndexToString(aMfc.mOif));
+    LogResult(error, "MulticastRoutingManager: %s: %s %s => %s %s", __FUNCTION__, MifIndexToString(aMfc.mIif),
+              aMfc.mSrcAddr.ToString().AsCString(), aMfc.mGroupAddr.ToString().AsCString(),
+              MifIndexToString(aMfc.mOif));
 
     aMfc.Erase();
 }
diff --git a/src/posix/platform/multicast_routing.hpp b/src/posix/platform/multicast_routing.hpp
index ec48d4c..72177d8 100644
--- a/src/posix/platform/multicast_routing.hpp
+++ b/src/posix/platform/multicast_routing.hpp
@@ -108,6 +108,7 @@
     void    Disable(void);
     void    Add(const Ip6::Address &aAddress);
     void    Remove(const Ip6::Address &aAddress);
+    void    UpdateMldReport(const Ip6::Address &aAddress, bool isAdd);
     bool    HasMulticastListener(const Ip6::Address &aAddress) const;
     bool    IsEnabled(void) const { return mMulticastRouterSock >= 0; }
     void    InitMulticastRouterSock(void);
diff --git a/src/posix/platform/netif.cpp b/src/posix/platform/netif.cpp
index 9d886d7..2d761ce 100644
--- a/src/posix/platform/netif.cpp
+++ b/src/posix/platform/netif.cpp
@@ -137,16 +137,17 @@
 
 #endif // defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
 
+#include <openthread/border_router.h>
 #include <openthread/icmp6.h>
 #include <openthread/instance.h>
 #include <openthread/ip6.h>
+#include <openthread/logging.h>
 #include <openthread/message.h>
 #include <openthread/netdata.h>
 #include <openthread/platform/misc.h>
 
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
-#include "common/logging.hpp"
 #include "net/ip6_address.hpp"
 
 unsigned int gNetifIndex = 0;
@@ -163,6 +164,9 @@
 }
 
 #if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
+#if OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE
+#include "firewall.hpp"
+#endif
 #include "posix/platform/ip6_utils.hpp"
 
 using namespace ot::Posix::Ip6Utils;
@@ -190,15 +194,18 @@
 static uint32_t sNetlinkSequence = 0; ///< Netlink message sequence.
 #endif
 
-#if OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
-#if defined(__linux__)
+#if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE && __linux__
+static constexpr uint32_t kOmrRoutesPriority = OPENTHREAD_POSIX_CONFIG_OMR_ROUTES_PRIORITY;
+static constexpr uint8_t  kMaxOmrRoutesNum   = OPENTHREAD_POSIX_CONFIG_MAX_OMR_ROUTES_NUM;
+static uint8_t            sAddedOmrRoutesNum = 0;
+static otIp6Prefix        sAddedOmrRoutes[kMaxOmrRoutesNum];
+#endif
+
+#if OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE && __linux__
 static constexpr uint32_t kExternalRoutePriority  = OPENTHREAD_POSIX_CONFIG_EXTERNAL_ROUTE_PRIORITY;
 static constexpr uint8_t  kMaxExternalRoutesNum   = OPENTHREAD_POSIX_CONFIG_MAX_EXTERNAL_ROUTE_NUM;
 static uint8_t            sAddedExternalRoutesNum = 0;
 static otIp6Prefix        sAddedExternalRoutes[kMaxExternalRoutesNum];
-#else
-#error "OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE only works on Linux platform"
-#endif // defined(__linux__)
 #endif
 
 #if defined(RTM_NEWMADDR) || defined(__NetBSD__)
@@ -323,10 +330,42 @@
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wcast-align"
 
-static void UpdateUnicastLinux(const otIp6AddressInfo &aAddressInfo, bool aIsAdded)
+void AddRtAttr(struct nlmsghdr *aHeader, uint32_t aMaxLen, uint8_t aType, const void *aData, uint8_t aLen)
 {
+    uint8_t        len = RTA_LENGTH(aLen);
     struct rtattr *rta;
 
+    assert(NLMSG_ALIGN(aHeader->nlmsg_len) + RTA_ALIGN(len) <= aMaxLen);
+    OT_UNUSED_VARIABLE(aMaxLen);
+
+    rta           = (struct rtattr *)((char *)(aHeader) + NLMSG_ALIGN((aHeader)->nlmsg_len));
+    rta->rta_type = aType;
+    rta->rta_len  = len;
+    if (aLen)
+    {
+        memcpy(RTA_DATA(rta), aData, aLen);
+    }
+    aHeader->nlmsg_len = NLMSG_ALIGN(aHeader->nlmsg_len) + RTA_ALIGN(len);
+}
+
+void AddRtAttrUint32(struct nlmsghdr *aHeader, uint32_t aMaxLen, uint8_t aType, uint32_t aData)
+{
+    AddRtAttr(aHeader, aMaxLen, aType, &aData, sizeof(aData));
+}
+
+#if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE
+static bool IsOmrAddress(otInstance *aInstance, const otIp6AddressInfo &aAddressInfo)
+{
+    otIp6Prefix addressPrefix{*aAddressInfo.mAddress, aAddressInfo.mPrefixLength};
+
+    return otNetDataContainsOmrPrefix(aInstance, &addressPrefix);
+}
+#endif
+
+static void UpdateUnicastLinux(otInstance *aInstance, const otIp6AddressInfo &aAddressInfo, bool aIsAdded)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
     struct
     {
         struct nlmsghdr  nh;
@@ -348,28 +387,37 @@
     req.ifa.ifa_scope     = aAddressInfo.mScope;
     req.ifa.ifa_index     = gNetifIndex;
 
-    rta           = reinterpret_cast<struct rtattr *>((reinterpret_cast<char *>(&req)) + NLMSG_ALIGN(req.nh.nlmsg_len));
-    rta->rta_type = IFA_LOCAL;
-    rta->rta_len  = RTA_LENGTH(sizeof(*aAddressInfo.mAddress));
-
-    memcpy(RTA_DATA(rta), aAddressInfo.mAddress, sizeof(*aAddressInfo.mAddress));
-
-    req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) + rta->rta_len;
+    AddRtAttr(&req.nh, sizeof(req), IFA_LOCAL, aAddressInfo.mAddress, sizeof(*aAddressInfo.mAddress));
 
     if (!aAddressInfo.mPreferred)
     {
         struct ifa_cacheinfo cacheinfo;
 
-        rta           = reinterpret_cast<struct rtattr *>((reinterpret_cast<char *>(rta)) + rta->rta_len);
-        rta->rta_type = IFA_CACHEINFO;
-        rta->rta_len  = RTA_LENGTH(sizeof(cacheinfo));
-
         memset(&cacheinfo, 0, sizeof(cacheinfo));
         cacheinfo.ifa_valid = UINT32_MAX;
 
-        memcpy(RTA_DATA(rta), &cacheinfo, sizeof(cacheinfo));
+        AddRtAttr(&req.nh, sizeof(req), IFA_CACHEINFO, &cacheinfo, sizeof(cacheinfo));
+    }
 
-        req.nh.nlmsg_len += rta->rta_len;
+#if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE
+    if (IsOmrAddress(aInstance, aAddressInfo))
+    {
+        // Remove prefix route for OMR address if `OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE` is enabled to
+        // avoid having two routes.
+        if (aIsAdded)
+        {
+            AddRtAttrUint32(&req.nh, sizeof(req), IFA_FLAGS, IFA_F_NOPREFIXROUTE);
+        }
+    }
+    else
+#endif
+    {
+#if OPENTHREAD_POSIX_CONFIG_NETIF_PREFIX_ROUTE_METRIC > 0
+        if (aAddressInfo.mScope > ot::Ip6::Address::kLinkLocalScope)
+        {
+            AddRtAttrUint32(&req.nh, sizeof(req), IFA_RT_PRIORITY, OPENTHREAD_POSIX_CONFIG_NETIF_PREFIX_ROUTE_METRIC);
+        }
+#endif
     }
 
     if (send(sNetlinkFd, &req, req.nh.nlmsg_len, 0) != -1)
@@ -395,7 +443,7 @@
     assert(sIpFd >= 0);
 
 #if defined(__linux__)
-    UpdateUnicastLinux(aAddressInfo, aIsAdded);
+    UpdateUnicastLinux(aInstance, aAddressInfo, aIsAdded);
 #elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
     {
         int                 rval;
@@ -516,31 +564,10 @@
     }
 }
 
-#if OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
-void AddRtAttr(struct nlmsghdr *aHeader, uint32_t aMaxLen, uint8_t aType, const void *aData, uint8_t aLen)
-{
-    uint8_t        len = RTA_LENGTH(aLen);
-    struct rtattr *rta;
+#if __linux__ && \
+    (OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE || OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE)
 
-    assert(NLMSG_ALIGN(aHeader->nlmsg_len) + RTA_ALIGN(len) <= aMaxLen);
-    OT_UNUSED_VARIABLE(aMaxLen);
-
-    rta           = (struct rtattr *)((char *)(aHeader) + NLMSG_ALIGN((aHeader)->nlmsg_len));
-    rta->rta_type = aType;
-    rta->rta_len  = len;
-    if (aLen)
-    {
-        memcpy(RTA_DATA(rta), aData, aLen);
-    }
-    aHeader->nlmsg_len = NLMSG_ALIGN(aHeader->nlmsg_len) + RTA_ALIGN(len);
-}
-
-void AddRtAttrUint32(struct nlmsghdr *aHeader, uint32_t aMaxLen, uint8_t aType, uint32_t aData)
-{
-    AddRtAttr(aHeader, aMaxLen, aType, &aData, sizeof(aData));
-}
-
-static otError AddExternalRoute(const otIp6Prefix &aPrefix)
+static otError AddRoute(const otIp6Prefix &aPrefix, uint32_t aPriority)
 {
     constexpr unsigned int kBufSize = 128;
     struct
@@ -556,7 +583,6 @@
 
     VerifyOrExit(netifIdx > 0, error = OT_ERROR_INVALID_STATE);
     VerifyOrExit(sNetlinkFd >= 0, error = OT_ERROR_INVALID_STATE);
-    VerifyOrExit(sAddedExternalRoutesNum < kMaxExternalRoutesNum, error = OT_ERROR_NO_BUFS);
 
     req.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
 
@@ -578,7 +604,7 @@
     otIp6AddressToString(&aPrefix.mPrefix, addrBuf, OT_IP6_ADDRESS_STRING_SIZE);
     inet_pton(AF_INET6, addrBuf, data);
     AddRtAttr(reinterpret_cast<nlmsghdr *>(&req), sizeof(req), RTA_DST, data, sizeof(data));
-    AddRtAttrUint32(&req.header, sizeof(req), RTA_PRIORITY, kExternalRoutePriority);
+    AddRtAttrUint32(&req.header, sizeof(req), RTA_PRIORITY, aPriority);
     AddRtAttrUint32(&req.header, sizeof(req), RTA_OIF, netifIdx);
 
     if (send(sNetlinkFd, &req, sizeof(req), 0) < 0)
@@ -590,7 +616,7 @@
     return error;
 }
 
-static otError DeleteExternalRoute(const otIp6Prefix &aPrefix)
+static otError DeleteRoute(const otIp6Prefix &aPrefix)
 {
     constexpr unsigned int kBufSize = 512;
     struct
@@ -639,6 +665,105 @@
     return error;
 }
 
+#endif // __linux__ && (OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE ||
+       // OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE)
+
+#if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE && __linux__
+
+static bool HasAddedOmrRoute(const otIp6Prefix &aOmrPrefix)
+{
+    bool found = false;
+
+    for (uint8_t i = 0; i < sAddedOmrRoutesNum; ++i)
+    {
+        if (otIp6ArePrefixesEqual(&sAddedOmrRoutes[i], &aOmrPrefix))
+        {
+            found = true;
+            break;
+        }
+    }
+
+    return found;
+}
+
+static otError AddOmrRoute(const otIp6Prefix &aPrefix)
+{
+    otError error;
+
+    VerifyOrExit(sAddedOmrRoutesNum < kMaxOmrRoutesNum, error = OT_ERROR_NO_BUFS);
+
+    error = AddRoute(aPrefix, kOmrRoutesPriority);
+exit:
+    return error;
+}
+
+static void UpdateOmrRoutes(otInstance *aInstance)
+{
+    otError               error;
+    otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
+    otBorderRouterConfig  config;
+    char                  prefixString[OT_IP6_PREFIX_STRING_SIZE];
+
+    // Remove kernel routes if the OMR prefix is removed
+    for (int i = 0; i < static_cast<int>(sAddedOmrRoutesNum); ++i)
+    {
+        if (otNetDataContainsOmrPrefix(aInstance, &sAddedOmrRoutes[i]))
+        {
+            continue;
+        }
+
+        otIp6PrefixToString(&sAddedOmrRoutes[i], prefixString, sizeof(prefixString));
+        if ((error = DeleteRoute(sAddedOmrRoutes[i])) != OT_ERROR_NONE)
+        {
+            otLogWarnPlat("[netif] Failed to delete an OMR route %s in kernel: %s", prefixString,
+                          otThreadErrorToString(error));
+        }
+        else
+        {
+            sAddedOmrRoutes[i] = sAddedOmrRoutes[sAddedOmrRoutesNum - 1];
+            --sAddedOmrRoutesNum;
+            --i;
+            otLogInfoPlat("[netif] Successfully deleted an OMR route %s in kernel", prefixString);
+        }
+    }
+
+    // Add kernel routes for OMR prefixes in Network Data
+    while (otNetDataGetNextOnMeshPrefix(aInstance, &iterator, &config) == OT_ERROR_NONE)
+    {
+        if (HasAddedOmrRoute(config.mPrefix))
+        {
+            continue;
+        }
+
+        otIp6PrefixToString(&config.mPrefix, prefixString, sizeof(prefixString));
+        if ((error = AddOmrRoute(config.mPrefix)) != OT_ERROR_NONE)
+        {
+            otLogWarnPlat("[netif] Failed to add an OMR route %s in kernel: %s", prefixString,
+                          otThreadErrorToString(error));
+        }
+        else
+        {
+            sAddedOmrRoutes[sAddedOmrRoutesNum++] = config.mPrefix;
+            otLogInfoPlat("[netif] Successfully added an OMR route %s in kernel: %s", prefixString);
+        }
+    }
+}
+
+#endif // OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE && __linux__
+
+#if OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE && __linux__
+
+static otError AddExternalRoute(const otIp6Prefix &aPrefix)
+{
+    otError error;
+
+    VerifyOrExit(sAddedExternalRoutesNum < kMaxExternalRoutesNum, error = OT_ERROR_NO_BUFS);
+
+    error = AddRoute(aPrefix, kExternalRoutePriority);
+exit:
+    return error;
+}
+
 bool HasExternalRouteInNetData(otInstance *aInstance, const otIp6Prefix &aExternalRoute)
 {
     otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
@@ -684,9 +809,10 @@
         {
             continue;
         }
-        if ((error = DeleteExternalRoute(sAddedExternalRoutes[i])) != OT_ERROR_NONE)
+
+        otIp6PrefixToString(&sAddedExternalRoutes[i], prefixString, sizeof(prefixString));
+        if ((error = DeleteRoute(sAddedExternalRoutes[i])) != OT_ERROR_NONE)
         {
-            otIp6PrefixToString(&sAddedExternalRoutes[i], prefixString, sizeof(prefixString));
             otLogWarnPlat("[netif] Failed to delete an external route %s in kernel: %s", prefixString,
                           otThreadErrorToString(error));
         }
@@ -695,6 +821,7 @@
             sAddedExternalRoutes[i] = sAddedExternalRoutes[sAddedExternalRoutesNum - 1];
             --sAddedExternalRoutesNum;
             --i;
+            otLogWarnPlat("[netif] Successfully deleted an external route %s in kernel", prefixString);
         }
     }
 
@@ -706,21 +833,23 @@
         }
         VerifyOrExit(sAddedExternalRoutesNum < kMaxExternalRoutesNum,
                      otLogWarnPlat("[netif] No buffer to add more external routes in kernel"));
+
+        otIp6PrefixToString(&config.mPrefix, prefixString, sizeof(prefixString));
         if ((error = AddExternalRoute(config.mPrefix)) != OT_ERROR_NONE)
         {
-            otIp6PrefixToString(&config.mPrefix, prefixString, sizeof(prefixString));
             otLogWarnPlat("[netif] Failed to add an external route %s in kernel: %s", prefixString,
                           otThreadErrorToString(error));
         }
         else
         {
             sAddedExternalRoutes[sAddedExternalRoutesNum++] = config.mPrefix;
+            otLogWarnPlat("[netif] Successfully added an external route %s in kernel: %s", prefixString);
         }
     }
 exit:
     return;
 }
-#endif // OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
+#endif // OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE && __linux__
 
 static void processAddressChange(const otIp6AddressInfo *aAddressInfo, bool aIsAdded, void *aContext)
 {
@@ -740,12 +869,18 @@
     {
         UpdateLink(aInstance);
     }
-#if OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
     if (OT_CHANGED_THREAD_NETDATA & aFlags)
     {
-        UpdateExternalRoutes(aInstance);
-    }
+#if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE && __linux__
+        UpdateOmrRoutes(aInstance);
 #endif
+#if OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE && __linux__
+        UpdateExternalRoutes(aInstance);
+#endif
+#if OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE
+        ot::Posix::UpdateIpSets(aInstance);
+#endif
+    }
 }
 
 static void processReceive(otMessage *aMessage, void *aContext)
@@ -771,7 +906,7 @@
 
 #if OPENTHREAD_POSIX_LOG_TUN_PACKETS
     otLogInfoPlat("[netif] Packet from NCP (%u bytes)", static_cast<uint16_t>(length));
-    otDumpInfo(OT_LOG_REGION_PLATFORM, "", &packet[offset], length);
+    otDumpInfoPlat("", &packet[offset], length);
 #endif
 
 #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
@@ -826,7 +961,7 @@
 
 #if OPENTHREAD_POSIX_LOG_TUN_PACKETS
     otLogInfoPlat("[netif] Packet to NCP (%hu bytes)", static_cast<uint16_t>(rval));
-    otDumpInfo(OT_LOG_REGION_PLATFORM, "", &packet[offset], static_cast<size_t>(rval));
+    otDumpInfoPlat("", &packet[offset], static_cast<size_t>(rval));
 #endif
 
     SuccessOrExit(error = otMessageAppend(message, &packet[offset], static_cast<uint16_t>(rval)));
@@ -842,32 +977,35 @@
 
     if (error != OT_ERROR_NONE)
     {
-        otLogWarnPlat("[netif] Failed to transmit, error:%s", otThreadErrorToString(error));
+        if (error == OT_ERROR_DROP)
+        {
+            otLogInfoPlat("[netif] Message dropped by Thread", otThreadErrorToString(error));
+        }
+        else
+        {
+            otLogWarnPlat("[netif] Failed to transmit, error:%s", otThreadErrorToString(error));
+        }
     }
 }
 
-static void logAddrEvent(bool isAdd, bool isUnicast, struct sockaddr_in6 &addr6, otError error)
+static void logAddrEvent(bool isAdd, const ot::Ip6::Address &aAddress, otError error)
 {
-    char addressString[INET6_ADDRSTRLEN + 1];
+    OT_UNUSED_VARIABLE(aAddress);
 
-    // these parameters may not be used if logging is disabled at compile time
-    OT_UNUSED_VARIABLE(isUnicast);
-    OT_UNUSED_VARIABLE(addr6);
-    OT_UNUSED_VARIABLE(addressString);
-
-    if ((error == OT_ERROR_NONE) || ((isAdd) && (error == OT_ERROR_ALREADY)) ||
-        ((!isAdd) && (error == OT_ERROR_NOT_FOUND)))
+    if ((error == OT_ERROR_NONE) || ((isAdd) && (error == OT_ERROR_ALREADY || error == OT_ERROR_REJECTED)) ||
+        ((!isAdd) && (error == OT_ERROR_NOT_FOUND || error == OT_ERROR_REJECTED)))
     {
-        otLogNotePlat("[netif] %s [%s] %s%s", isAdd ? "ADD" : "DEL", isUnicast ? "U" : "M",
-                      inet_ntop(AF_INET6, addr6.sin6_addr.s6_addr, addressString, sizeof(addressString)),
-                      error == OT_ERROR_ALREADY ? " (already subscribed, ignored)"
-                                                : error == OT_ERROR_NOT_FOUND ? " (not found, ignored)" : "");
+        otLogInfoPlat("[netif] %s [%s] %s%s", isAdd ? "ADD" : "DEL", aAddress.IsMulticast() ? "M" : "U",
+                      aAddress.ToString().AsCString(),
+                      error == OT_ERROR_ALREADY
+                          ? " (already subscribed, ignored)"
+                          : error == OT_ERROR_REJECTED ? " (rejected)"
+                                                       : error == OT_ERROR_NOT_FOUND ? " (not found, ignored)" : "");
     }
     else
     {
-        otLogWarnPlat("[netif] %s [%s] %s failed (%s)", isAdd ? "ADD" : "DEL", isUnicast ? "U" : "M",
-                      inet_ntop(AF_INET6, addr6.sin6_addr.s6_addr, addressString, sizeof(addressString)),
-                      otThreadErrorToString(error));
+        otLogWarnPlat("[netif] %s [%s] %s failed (%s)", isAdd ? "ADD" : "DEL", aAddress.IsMulticast() ? "M" : "U",
+                      aAddress.ToString().AsCString(), otThreadErrorToString(error));
     }
 }
 
@@ -922,8 +1060,8 @@
                     error = otIp6SubscribeMulticastAddress(aInstance, &addr);
                 }
 
-                logAddrEvent(/* isAdd */ true, !addr.IsMulticast(), addr6, error);
-                if (error == OT_ERROR_ALREADY)
+                logAddrEvent(/* isAdd */ true, addr, error);
+                if (error == OT_ERROR_ALREADY || error == OT_ERROR_REJECTED)
                 {
                     error = OT_ERROR_NONE;
                 }
@@ -941,8 +1079,8 @@
                     error = otIp6UnsubscribeMulticastAddress(aInstance, &addr);
                 }
 
-                logAddrEvent(/* isAdd */ false, !addr.IsMulticast(), addr6, error);
-                if (error == OT_ERROR_NOT_FOUND)
+                logAddrEvent(/* isAdd */ false, addr, error);
+                if (error == OT_ERROR_NOT_FOUND || error == OT_ERROR_REJECTED)
                 {
                     error = OT_ERROR_NONE;
                 }
@@ -957,7 +1095,7 @@
         }
 
         default:
-            otLogWarnPlat("[netif] Unexpected address type (%d).", (int)rta->rta_type);
+            otLogDebgPlat("[netif] Unexpected address type (%d).", (int)rta->rta_type);
             break;
         }
     }
@@ -1032,12 +1170,10 @@
     struct sockaddr_in6 addr6;
     struct sockaddr_in6 netmask;
     uint8_t *           addrbuf;
-    unsigned int        addrlen;
     unsigned int        addrmask = 0;
     unsigned int        i;
     struct sockaddr *   sa;
     bool                is_link_local;
-    size_t              buffer_len = rtm->rtm_msglen;
 
     addr6.sin6_family   = 0;
     netmask.sin6_family = 0;
@@ -1062,7 +1198,6 @@
         addrmask = (unsigned int)ifmam->ifmam_addrs;
     }
 #endif
-    addrlen = (unsigned int)buffer_len;
 
     if (addrmask != 0)
     {
@@ -1080,7 +1215,6 @@
                     if (i == RTAX_NETMASK)
                         memcpy(&netmask, sa, sizeof(sockaddr_in6));
                 }
-                addrlen -= SA_SIZE(sa);
                 addrbuf += SA_SIZE(sa);
             }
         }
@@ -1121,7 +1255,7 @@
 
                 if (subscribed)
                 {
-                    logAddrEvent(/* isAdd */ true, /* isUnicast */ true, addr6, OT_ERROR_ALREADY);
+                    logAddrEvent(/* isAdd */ true, addr, OT_ERROR_ALREADY);
                     error = OT_ERROR_NONE;
                 }
                 else
@@ -1171,7 +1305,7 @@
                     else
                     {
                         error = otIp6AddUnicastAddress(aInstance, &netAddr);
-                        logAddrEvent(/* isAdd */ true, /* isUnicast */ true, addr6, error);
+                        logAddrEvent(/* isAdd */ true, addr, error);
                         if (error == OT_ERROR_ALREADY)
                         {
                             error = OT_ERROR_NONE;
@@ -1186,8 +1320,8 @@
                 netAddr.mAddress = addr;
 
                 error = otIp6SubscribeMulticastAddress(aInstance, &addr);
-                logAddrEvent(/* isAdd */ true, /* isUnicast */ false, addr6, error);
-                if (error == OT_ERROR_ALREADY)
+                logAddrEvent(/* isAdd */ true, addr, error);
+                if (error == OT_ERROR_ALREADY || error == OT_ERROR_REJECTED)
                 {
                     error = OT_ERROR_NONE;
                 }
@@ -1203,7 +1337,7 @@
             if (!addr.IsMulticast())
             {
                 error = otIp6RemoveUnicastAddress(aInstance, &addr);
-                logAddrEvent(/* isAdd */ false, /* isUnicast */ true, addr6, error);
+                logAddrEvent(/* isAdd */ false, addr, error);
                 if (error == OT_ERROR_NOT_FOUND)
                 {
                     error = OT_ERROR_NONE;
@@ -1212,7 +1346,7 @@
             else
             {
                 error = otIp6UnsubscribeMulticastAddress(aInstance, &addr);
-                logAddrEvent(/* isAdd */ false, /* isUnicast */ false, addr6, error);
+                logAddrEvent(/* isAdd */ false, addr, error);
                 if (error == OT_ERROR_NOT_FOUND)
                 {
                     error = OT_ERROR_NONE;
@@ -1401,42 +1535,20 @@
         {
             MLDv2Record *record = reinterpret_cast<MLDv2Record *>(&buffer[offset]);
 
-            otError      err;
-            otIp6Address address;
+            otError          err;
+            ot::Ip6::Address address;
 
             memcpy(&address.mFields.m8, &record->mMulticastAddress, sizeof(address.mFields.m8));
             inet_ntop(AF_INET6, &record->mMulticastAddress, addressString, sizeof(addressString));
             if (record->mRecordType == kICMPv6MLDv2RecordChangeToIncludeType)
             {
                 err = otIp6SubscribeMulticastAddress(aInstance, &address);
-                if (err == OT_ERROR_ALREADY)
-                {
-                    otLogNotePlat(
-                        "[netif] Will not subscribe duplicate multicast address %s",
-                        inet_ntop(AF_INET6, &record->mMulticastAddress, addressString, sizeof(addressString)));
-                }
-                else if (err != OT_ERROR_NONE)
-                {
-                    otLogWarnPlat("[netif] Failed to subscribe multicast address %s: %s", addressString,
-                                  otThreadErrorToString(err));
-                }
-                else
-                {
-                    otLogDebgPlat("[netif] Subscribed multicast address %s", addressString);
-                }
+                logAddrEvent(/* isAdd */ true, address, err);
             }
             else if (record->mRecordType == kICMPv6MLDv2RecordChangeToExcludeType)
             {
                 err = otIp6UnsubscribeMulticastAddress(aInstance, &address);
-                if (err != OT_ERROR_NONE)
-                {
-                    otLogWarnPlat("[netif] Failed to unsubscribe multicast address %s: %s", addressString,
-                                  otThreadErrorToString(err));
-                }
-                else
-                {
-                    otLogDebgPlat("[netif] Unsubscribed multicast address %s", addressString);
-                }
+                logAddrEvent(/* isAdd */ false, address, err);
             }
 
             offset += sizeof(MLDv2Record) + sizeof(in6_addr) * ntohs(record->mNumSources);
@@ -1448,8 +1560,6 @@
     {
         freeifaddrs(ifAddrs);
     }
-
-    return;
 }
 #endif
 
@@ -1639,7 +1749,11 @@
     OT_ASSERT(gInstance != nullptr);
 
     otIp6SetReceiveFilterEnabled(gInstance, true);
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+    otIcmp6SetEchoMode(gInstance, OT_ICMP6_ECHO_HANDLER_ALL);
+#else
     otIcmp6SetEchoMode(gInstance, OT_ICMP6_ECHO_HANDLER_DISABLED);
+#endif
     otIp6SetReceiveCallback(gInstance, processReceive, gInstance);
     otIp6SetAddressCallback(gInstance, processAddressChange, gInstance);
 #if OPENTHREAD_POSIX_MULTICAST_PROMISCUOUS_REQUIRED
diff --git a/src/posix/platform/openthread-core-posix-config.h b/src/posix/platform/openthread-core-posix-config.h
index a975465..6708751 100644
--- a/src/posix/platform/openthread-core-posix-config.h
+++ b/src/posix/platform/openthread-core-posix-config.h
@@ -287,4 +287,16 @@
 #define OPENTHREAD_CONFIG_LOG_PREPEND_UPTIME 1
 #endif
 
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_SERVICES
+ *
+ * Specifies number of service entries in the SRP client service pool.
+ *
+ * This config is applicable only when `OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE` is enabled.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_SERVICES
+#define OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_SERVICES 20
+#endif
+
 #endif // OPENTHREAD_CORE_POSIX_CONFIG_H_
diff --git a/src/posix/platform/openthread-posix-config.h b/src/posix/platform/openthread-posix-config.h
index 9bd6d70..191f5a0 100644
--- a/src/posix/platform/openthread-posix-config.h
+++ b/src/posix/platform/openthread-posix-config.h
@@ -48,35 +48,6 @@
 #endif
 
 /**
- * @def OPENTHREAD_CONFIG_POSIX_APP_TREL_INTERFACE_NAME
- *
- * Defines the default interface name used for TREL UDP6 platform. Empty string disables TREL platform.
- *
- */
-#ifndef OPENTHREAD_CONFIG_POSIX_APP_TREL_INTERFACE_NAME
-#define OPENTHREAD_CONFIG_POSIX_APP_TREL_INTERFACE_NAME ""
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
- *
- * Defines whether the TREL UDP6 platform uses netlink socket to add/remove addresses on the TREL netif or `ioctl()`
- * command.
- *
- * When netlink is used Duplicate Address Detection (DAD) is disabled when a new address is added on the netif.
- *
- * Use of netlink is enabled by default on linux-based platforms.
- *
- */
-#ifndef OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
-#ifdef __linux__
-#define OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET 1
-#else
-#define OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET 0
-#endif
-#endif
-
-/**
  * @def OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME
  *
  * Define socket basename used by POSIX app daemon.
@@ -115,6 +86,12 @@
 #define OT_POSIX_RCP_BUS_SPI 2
 
 /**
+ * RCP bus defined by vendors.
+ *
+ */
+#define OT_POSIX_RCP_BUS_VENDOR 3
+
+/**
  * @def OPENTHREAD_POSIX_CONFIG_RCP_BUS
  *
  * This setting configures what type of RCP bus to use.
@@ -156,25 +133,75 @@
 #endif
 
 /**
+ * @def OPENTHREAD_POSIX_CONFIG_NETIF_PREFIX_ROUTE_METRIC
+ *
+ * This setting configures the prefix route metric on the Thread network interface.
+ * Define as 0 to use use the default prefix route metric.
+ *
+ * Note: The feature works on Linux kernel v4.18+.
+ *
+ */
+#ifndef OPENTHREAD_POSIX_CONFIG_NETIF_PREFIX_ROUTE_METRIC
+#define OPENTHREAD_POSIX_CONFIG_NETIF_PREFIX_ROUTE_METRIC 0
+#endif
+
+/**
+ * @def OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE
+ *
+ * Define as 1 to add OMR routes to POSIX kernel when OMR prefixes are changed in netdata.
+ *
+ * Note: This feature can be used to add OMR routes with non-default priority. Unlike
+ * `OPENTHREAD_POSIX_CONFIG_NETIF_PREFIX_ROUTE_METRIC`, it works on Linux kernels before v4.18.
+ * However, `OPENTHREAD_POSIX_CONFIG_NETIF_PREFIX_ROUTE_METRIC` should be preferred on Linux kernel v4.18+.
+ *
+ */
+#ifndef OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE
+#define OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE 0
+#endif
+
+/**
+ * @def OPENTHREAD_POSIX_CONFIG_OMR_ROUTES_PRIORITY
+ *
+ * This macro defines the priority of OMR routes added to kernel. The larger the number, the lower the priority. We
+ * need to assign a high priority to such routes so that kernel prefers the Thread link rather than infrastructure.
+ * Otherwise we may unnecessarily transmit packets via infrastructure, which potentially causes looping issue.
+ *
+ */
+#ifndef OPENTHREAD_POSIX_CONFIG_OMR_ROUTES_PRIORITY
+#define OPENTHREAD_POSIX_CONFIG_OMR_ROUTES_PRIORITY 1
+#endif
+
+/**
+ * @def OPENTHREAD_POSIX_CONFIG_MAX_OMR_ROUTES_NUM
+ *
+ * This macro defines the max number of OMR routes that can be added to kernel.
+ *
+ */
+#ifndef OPENTHREAD_POSIX_CONFIG_MAX_OMR_ROUTES_NUM
+#define OPENTHREAD_POSIX_CONFIG_MAX_OMR_ROUTES_NUM OPENTHREAD_CONFIG_IP6_SLAAC_NUM_ADDRESSES
+#endif
+
+/**
  * @def OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
  *
  * Define as 1 to add external routes to POSIX kernel when external routes are changed in netdata.
  *
  */
-#ifdef __linux__
 #ifndef OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
 #define OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE 1
 #endif
-#endif
 
 /**
  * @def OPENTHREAD_POSIX_CONFIG_EXTERNAL_ROUTE_PRIORITY
  *
- * This macro defines the priority of external routes added to kernel.
+ * This macro defines the priority of external routes added to kernel. The larger the number, the lower the priority. We
+ * need to assign a low priority to such routes so that kernel prefers the infra link rather than thread. Otherwise we
+ * may unnecessarily transmit packets via thread, which potentially causes performance issue. In linux, normally infra
+ * link routes' metric value is not greater than 1024, hence 65535 should be big enough.
  *
  */
 #ifndef OPENTHREAD_POSIX_CONFIG_EXTERNAL_ROUTE_PRIORITY
-#define OPENTHREAD_POSIX_CONFIG_EXTERNAL_ROUTE_PRIORITY 512
+#define OPENTHREAD_POSIX_CONFIG_EXTERNAL_ROUTE_PRIORITY 65535
 #endif
 
 /**
@@ -187,6 +214,30 @@
 #define OPENTHREAD_POSIX_CONFIG_MAX_EXTERNAL_ROUTE_NUM 8
 #endif
 
+/**
+ * @def OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE
+ *
+ * Define as 1 to enable firewall.
+ *
+ * The rules are implemented using ip6tables and ipset. The rules are as follows.
+ *
+ * ip6tables -A $OTBR_FORWARD_INGRESS_CHAIN -m pkttype --pkt-type unicast -i $THREAD_IF -p ip -j DROP
+ * ip6tables -A $OTBR_FORWARD_INGRESS_CHAIN -m set --match-set otbr-ingress-deny-src src -p ip -j DROP
+ * ip6tables -A $OTBR_FORWARD_INGRESS_CHAIN -m set --match-set otbr-ingress-allow-dst dst -p ip -j ACCEPT
+ * ip6tables -A $OTBR_FORWARD_INGRESS_CHAIN -m pkttype --pkt-type unicast -p ip -j DROP
+ * ip6tables -A $OTBR_FORWARD_INGRESS_CHAIN -p ip -j ACCEPT
+ *
+ */
+#ifndef OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE
+#define OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE 0
+#endif
+
+#if OPENTHREAD_POSIX_CONFIG_FIREWALL_ENABLE
+#ifndef OPENTHREAD_POSIX_CONFIG_IPSET_BINARY
+#define OPENTHREAD_POSIX_CONFIG_IPSET_BINARY "ipset"
+#endif
+#endif
+
 #ifdef __APPLE__
 
 /**
@@ -211,4 +262,26 @@
 
 #endif // __APPLE__
 
+//---------------------------------------------------------------------------------------------------------------------
+// Removed or renamed POSIX specific configs.
+
+#ifdef OPENTHREAD_CONFIG_POSIX_APP_TREL_INTERFACE_NAME
+#error "OPENTHREAD_CONFIG_POSIX_APP_TREL_INTERFACE_NAME was removed (no longer applicable with TREL over DNS-SD)."
+#endif
+
+#ifdef OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
+#error "OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET was removed (no longer applicable with TREL over DNS-SD)."
+#endif
+
+/**
+ * @def OPENTHREAD_POSIX_CONFIG_TREL_UDP_PORT
+ *
+ * This setting configures the TREL UDP port number.
+ * Define as 0 to use an ephemeral port number.
+ *
+ */
+#ifndef OPENTHREAD_POSIX_CONFIG_TREL_UDP_PORT
+#define OPENTHREAD_POSIX_CONFIG_TREL_UDP_PORT 0
+#endif
+
 #endif // OPENTHREAD_PLATFORM_CONFIG_H_
diff --git a/src/posix/platform/platform-posix.h b/src/posix/platform/platform-posix.h
index 9eadc68..919a319 100644
--- a/src/posix/platform/platform-posix.h
+++ b/src/posix/platform/platform-posix.h
@@ -48,11 +48,10 @@
 #include <openthread/error.h>
 #include <openthread/instance.h>
 #include <openthread/ip6.h>
+#include <openthread/logging.h>
 #include <openthread/openthread-system.h>
 #include <openthread/platform/time.h>
 
-#include "common/logging.hpp"
-
 #include "lib/platform/exit_code.h"
 #include "lib/url/url.hpp"
 
@@ -184,10 +183,10 @@
 /**
  * This function updates the file descriptor sets with file descriptors used by the radio driver.
  *
- * @param[inout]  aReadFdSet   A pointer to the read file descriptors.
- * @param[inout]  aWriteFdSet  A pointer to the write file descriptors.
- * @param[inout]  aMaxFd       A pointer to the max file descriptor.
- * @param[inout]  aTimeout     A pointer to the timeout.
+ * @param[in,out]  aReadFdSet   A pointer to the read file descriptors.
+ * @param[in,out]  aWriteFdSet  A pointer to the write file descriptors.
+ * @param[in,out]  aMaxFd       A pointer to the max file descriptor.
+ * @param[in,out]  aTimeout     A pointer to the timeout.
  *
  */
 void platformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd, struct timeval *aTimeout);
@@ -219,9 +218,9 @@
 /**
  * This function updates the file descriptor sets with file descriptors used by the UART driver.
  *
- * @param[inout]  aReadFdSet   A pointer to the read file descriptors.
- * @param[inout]  aWriteFdSet  A pointer to the write file descriptors.
- * @param[inout]  aMaxFd       A pointer to the max file descriptor.
+ * @param[in,out]  aReadFdSet   A pointer to the read file descriptors.
+ * @param[in,out]  aWriteFdSet  A pointer to the write file descriptors.
+ * @param[in,out]  aMaxFd       A pointer to the max file descriptor.
  *
  */
 void platformUartUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSet, int *aMaxFd);
@@ -275,10 +274,10 @@
 /**
  * This function updates the file descriptor sets with file descriptors used by platform netif module.
  *
- * @param[inout]  aReadFdSet    A pointer to the read file descriptors.
- * @param[inout]  aWriteFdSet   A pointer to the write file descriptors.
- * @param[inout]  aErrorFdSet   A pointer to the error file descriptors.
- * @param[inout]  aMaxFd        A pointer to the max file descriptor.
+ * @param[in,out]  aReadFdSet    A pointer to the read file descriptors.
+ * @param[in,out]  aWriteFdSet   A pointer to the write file descriptors.
+ * @param[in,out]  aErrorFdSet   A pointer to the error file descriptors.
+ * @param[in,out]  aMaxFd        A pointer to the max file descriptor.
  *
  */
 void platformNetifUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSet, int *aMaxFd);
@@ -333,11 +332,11 @@
  * This function updates the file descriptor sets with file descriptors
  * used by the virtual time simulation.
  *
- * @param[inout]  aReadFdSet   A pointer to the read file descriptors.
- * @param[inout]  aWriteFdSet  A pointer to the write file descriptors.
- * @param[inout]  aErrorFdSet  A pointer to the error file descriptors.
- * @param[inout]  aMaxFd       A pointer to the max file descriptor.
- * @param[inout]  aTimeout     A pointer to the timeout.
+ * @param[in,out]  aReadFdSet   A pointer to the read file descriptors.
+ * @param[in,out]  aWriteFdSet  A pointer to the write file descriptors.
+ * @param[in,out]  aErrorFdSet  A pointer to the error file descriptors.
+ * @param[in,out]  aMaxFd       A pointer to the max file descriptor.
+ * @param[in,out]  aTimeout     A pointer to the timeout.
  *
  */
 void virtualTimeUpdateFdSet(fd_set *        aReadFdSet,
@@ -389,10 +388,10 @@
 /**
  * This function initializes platform TREL UDP6 driver.
  *
- * @param[in]   aInterfaceName   The name of network interface.
+ * @param[in]   aTrelUrl   The TREL URL (configuration for TREL platform).
  *
  */
-void platformTrelInit(const char *aInterfaceName);
+void platformTrelInit(const char *aTrelUrl);
 
 /**
  * This function shuts down the platform TREL UDP6 platform driver.
@@ -403,10 +402,10 @@
 /**
  * This function updates the file descriptor sets with file descriptors used by the TREL driver.
  *
- * @param[inout]  aReadFdSet   A pointer to the read file descriptors.
- * @param[inout]  aWriteFdSet  A pointer to the write file descriptors.
- * @param[inout]  aMaxFd       A pointer to the max file descriptor.
- * @param[inout]  aTimeout     A pointer to the timeout.
+ * @param[in,out]  aReadFdSet   A pointer to the read file descriptors.
+ * @param[in,out]  aWriteFdSet  A pointer to the write file descriptors.
+ * @param[in,out]  aMaxFd       A pointer to the max file descriptor.
+ * @param[in,out]  aTimeout     A pointer to the timeout.
  *
  */
 void platformTrelUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd, struct timeval *aTimeout);
diff --git a/src/posix/platform/radio.cpp b/src/posix/platform/radio.cpp
index b14e4e2..8fb63bf 100644
--- a/src/posix/platform/radio.cpp
+++ b/src/posix/platform/radio.cpp
@@ -35,6 +35,7 @@
 
 #include <string.h>
 
+#include "common/code_utils.hpp"
 #include "common/new.hpp"
 #include "lib/spinel/radio_spinel.hpp"
 #include "posix/platform/radio.hpp"
@@ -51,8 +52,13 @@
 #include "spi_interface.hpp"
 
 static ot::Spinel::RadioSpinel<ot::Posix::SpiInterface, RadioProcessContext> sRadioSpinel;
+#elif OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR
+#include "vendor_interface.hpp"
+
+static ot::Spinel::RadioSpinel<ot::Posix::VendorInterface, RadioProcessContext> sRadioSpinel;
 #else
-#error "OPENTHREAD_POSIX_CONFIG_RCP_BUS only allows OT_POSIX_RCP_BUS_UART and OT_POSIX_RCP_BUS_SPI!"
+#error "OPENTHREAD_POSIX_CONFIG_RCP_BUS only allows OT_POSIX_RCP_BUS_UART, OT_POSIX_RCP_BUS_SPI and " \
+    "OT_POSIX_RCP_BUS_VENDOR!"
 #endif
 
 namespace ot {
@@ -166,6 +172,15 @@
         VerifyOrDie(str == nullptr, OT_EXIT_INVALID_ARGUMENTS);
     }
 #endif // OPENTHREAD_POSIX_CONFIG_MAX_POWER_TABLE_ENABLE
+#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
+    {
+        const char *enableCoex = mRadioUrl.GetValue("enable-coex");
+        if (enableCoex != nullptr)
+        {
+            SuccessOrDie(sRadioSpinel.SetCoexEnabled(enableCoex[0] != '0'));
+        }
+    }
+#endif // OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
 }
 
 } // namespace Posix
@@ -594,12 +609,23 @@
     return sRadioSpinel.GetBusSpeed();
 }
 
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
 uint8_t otPlatRadioGetCslAccuracy(otInstance *aInstance)
 {
     OT_UNUSED_VARIABLE(aInstance);
 
-    return 0;
+    return sRadioSpinel.GetCslAccuracy();
 }
+#endif
+
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+uint8_t otPlatRadioGetCslUncertainty(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    return sRadioSpinel.GetCslUncertainty();
+}
+#endif
 
 otError otPlatRadioSetChannelMaxTransmitPower(otInstance *aInstance, uint8_t aChannel, int8_t aMaxPower)
 {
@@ -619,6 +645,18 @@
     return sRadioSpinel.GetRadioRegion(aRegionCode);
 }
 
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
+otError otPlatRadioConfigureEnhAckProbing(otInstance *         aInstance,
+                                          otLinkMetrics        aLinkMetrics,
+                                          const otShortAddress aShortAddress,
+                                          const otExtAddress * aExtAddress)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    return sRadioSpinel.ConfigureEnhAckProbing(aLinkMetrics, aShortAddress, *aExtAddress);
+}
+#endif
+
 otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel, uint32_t aStart, uint32_t aDuration)
 {
     OT_UNUSED_VARIABLE(aInstance);
@@ -627,3 +665,13 @@
     OT_UNUSED_VARIABLE(aDuration);
     return OT_ERROR_NOT_IMPLEMENTED;
 }
+
+const otRadioSpinelMetrics *otSysGetRadioSpinelMetrics(void)
+{
+    return sRadioSpinel.GetRadioSpinelMetrics();
+}
+
+const otRcpInterfaceMetrics *otSysGetRcpInterfaceMetrics(void)
+{
+    return sRadioSpinel.GetSpinelInterface().GetRcpInterfaceMetrics();
+}
diff --git a/src/posix/platform/radio_url.cpp b/src/posix/platform/radio_url.cpp
index b8ae8c5..c126663 100644
--- a/src/posix/platform/radio_url.cpp
+++ b/src/posix/platform/radio_url.cpp
@@ -89,8 +89,11 @@
 #endif
 
     return "RadioURL:\n" OT_RADIO_URL_HELP_BUS OT_RADIO_URL_HELP_MAX_POWER_TABLE
-           "    region[=region-code]          Set the radio's region code.\n"
+           "    region[=region-code]          Set the radio's region code. The region code must be an\n"
+           "                                  ISO 3166 alpha-2 code.\n"
            "    cca-threshold[=dbm]           Set the radio's CCA ED threshold in dBm measured at antenna connector.\n"
+           "    enable-coex[=1|0]             If not specified, RCP coex operates with its default configuration.\n"
+           "                                  Disable coex with 0, and enable it with other values.\n"
            "    fem-lnagain[=dbm]             Set the Rx LNA gain in dBm of the external FEM.\n"
            "    ncp-dataset                   Retrieve dataset from ncp.\n"
            "    no-reset                      Do not send Spinel reset command to RCP on initialization.\n"
diff --git a/src/posix/platform/settings.cpp b/src/posix/platform/settings.cpp
index eac81c2..7ea03ab 100644
--- a/src/posix/platform/settings.cpp
+++ b/src/posix/platform/settings.cpp
@@ -44,6 +44,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
+#include <openthread/logging.h>
 #include <openthread/platform/misc.h>
 #include <openthread/platform/radio.h>
 #include <openthread/platform/settings.h>
@@ -53,6 +54,7 @@
 
 #include "common/code_utils.hpp"
 #include "common/encoding.hpp"
+#include "posix/platform/settings.hpp"
 
 #include "system.hpp"
 
@@ -60,29 +62,19 @@
 
 static int sSettingsFd = -1;
 
-static otError platformSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex, int *aSwapFd);
-
 #if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
-static const uint16_t *sKeys       = nullptr;
-static uint16_t        sKeysLength = 0;
+static const uint16_t *sSensitiveKeys       = nullptr;
+static uint16_t        sSensitiveKeysLength = 0;
 
-void otPlatSettingsSetCriticalKeys(otInstance *aInstance, const uint16_t *aKeys, uint16_t aKeysLength)
-{
-    OT_UNUSED_VARIABLE(aInstance);
-
-    sKeys       = aKeys;
-    sKeysLength = aKeysLength;
-}
-
-static bool isCriticalKey(uint16_t aKey)
+static bool isSensitiveKey(uint16_t aKey)
 {
     bool ret = false;
 
-    VerifyOrExit(sKeys != nullptr);
+    VerifyOrExit(sSensitiveKeys != nullptr);
 
-    for (uint16_t i = 0; i < sKeysLength; i++)
+    for (uint16_t i = 0; i < sSensitiveKeysLength; i++)
     {
-        VerifyOrExit(aKey != sKeys[i], ret = true);
+        VerifyOrExit(aKey != sSensitiveKeys[i], ret = true);
     }
 
 exit:
@@ -166,23 +158,29 @@
     VerifyOrDie(0 == unlink(swapFileName), OT_EXIT_ERROR_ERRNO);
 }
 
-void otPlatSettingsInit(otInstance *aInstance)
+void otPlatSettingsInit(otInstance *aInstance, const uint16_t *aSensitiveKeys, uint16_t aSensitiveKeysLength)
 {
+#if !OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+    OT_UNUSED_VARIABLE(aSensitiveKeys);
+    OT_UNUSED_VARIABLE(aSensitiveKeysLength);
+#endif
+
     otError error = OT_ERROR_NONE;
 
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+    sSensitiveKeys       = aSensitiveKeys;
+    sSensitiveKeysLength = aSensitiveKeysLength;
+#endif
+
     // Don't touch the settings file the system runs in dry-run mode.
     VerifyOrExit(!IsSystemDryRun());
 
-#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
-    otPosixSecureSettingsInit(aInstance);
-#endif
-
     {
         struct stat st;
 
         if (stat(OPENTHREAD_CONFIG_POSIX_SETTINGS_PATH, &st) == -1)
         {
-            mkdir(OPENTHREAD_CONFIG_POSIX_SETTINGS_PATH, 0755);
+            VerifyOrDie(mkdir(OPENTHREAD_CONFIG_POSIX_SETTINGS_PATH, 0755) == 0, OT_EXIT_ERROR_ERRNO);
         }
     }
 
@@ -211,6 +209,10 @@
         VerifyOrExit(offset == lseek(sSettingsFd, length, SEEK_CUR), error = OT_ERROR_PARSE);
     }
 
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+    otPosixSecureSettingsInit(aInstance);
+#endif
+
 exit:
     if (error == OT_ERROR_PARSE)
     {
@@ -222,29 +224,118 @@
 {
     OT_UNUSED_VARIABLE(aInstance);
 
+    VerifyOrExit(!IsSystemDryRun());
+
 #if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
     otPosixSecureSettingsDeinit(aInstance);
 #endif
 
-    assert(sSettingsFd != -1);
+    VerifyOrExit(sSettingsFd != -1);
     VerifyOrDie(close(sSettingsFd) == 0, OT_EXIT_ERROR_ERRNO);
+
+exit:
+    return;
 }
 
 otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength)
 {
     OT_UNUSED_VARIABLE(aInstance);
 
-    otError     error  = OT_ERROR_NOT_FOUND;
-    const off_t size   = lseek(sSettingsFd, 0, SEEK_END);
-    off_t       offset = lseek(sSettingsFd, 0, SEEK_SET);
+    otError error = OT_ERROR_NOT_FOUND;
 
     VerifyOrExit(!IsSystemDryRun());
 #if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
-    if (isCriticalKey(aKey))
+    if (isSensitiveKey(aKey))
     {
-        ExitNow(error = otPosixSecureSettingsGet(aInstance, aKey, aIndex, aValue, aValueLength));
+        error = otPosixSecureSettingsGet(aInstance, aKey, aIndex, aValue, aValueLength);
     }
+    else
 #endif
+    {
+        error = ot::Posix::PlatformSettingsGet(aInstance, aKey, aIndex, aValue, aValueLength);
+    }
+
+exit:
+    VerifyOrDie(error != OT_ERROR_PARSE, OT_EXIT_FAILURE);
+    return error;
+}
+
+otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
+{
+    otError error = OT_ERROR_NONE;
+
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+    if (isSensitiveKey(aKey))
+    {
+        error = otPosixSecureSettingsSet(aInstance, aKey, aValue, aValueLength);
+    }
+    else
+#endif
+    {
+        ot::Posix::PlatformSettingsSet(aInstance, aKey, aValue, aValueLength);
+    }
+
+    return error;
+}
+
+otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    otError error = OT_ERROR_NONE;
+
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+    if (isSensitiveKey(aKey))
+    {
+        error = otPosixSecureSettingsAdd(aInstance, aKey, aValue, aValueLength);
+    }
+    else
+#endif
+    {
+        ot::Posix::PlatformSettingsAdd(aInstance, aKey, aValue, aValueLength);
+    }
+
+    return error;
+}
+
+otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex)
+{
+    otError error;
+
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+    if (isSensitiveKey(aKey))
+    {
+        error = otPosixSecureSettingsDelete(aInstance, aKey, aIndex);
+    }
+    else
+#endif
+    {
+        error = ot::Posix::PlatformSettingsDelete(aInstance, aKey, aIndex, nullptr);
+    }
+
+    return error;
+}
+
+void otPlatSettingsWipe(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+    otPosixSecureSettingsWipe(aInstance);
+#endif
+
+    VerifyOrDie(0 == ftruncate(sSettingsFd, 0), OT_EXIT_ERROR_ERRNO);
+}
+
+namespace ot {
+namespace Posix {
+
+otError PlatformSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    otError     error  = OT_ERROR_NOT_FOUND;
+    const off_t size   = lseek(sSettingsFd, 0, SEEK_END);
+    off_t       offset = lseek(sSettingsFd, 0, SEEK_SET);
 
     VerifyOrExit(offset == 0 && size >= 0, error = OT_ERROR_PARSE);
 
@@ -291,23 +382,14 @@
     }
 
 exit:
-    VerifyOrDie(error != OT_ERROR_PARSE, OT_EXIT_FAILURE);
     return error;
 }
 
-otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
+void PlatformSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
 {
-    int     swapFd = -1;
-    otError error  = OT_ERROR_NONE;
+    int swapFd = -1;
 
-#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
-    if (isCriticalKey(aKey))
-    {
-        ExitNow(error = otPosixSecureSettingsSet(aInstance, aKey, aValue, aValueLength));
-    }
-#endif
-
-    switch (platformSettingsDelete(aInstance, aKey, -1, &swapFd))
+    switch (PlatformSettingsDelete(aInstance, aKey, -1, &swapFd))
     {
     case OT_ERROR_NONE:
     case OT_ERROR_NOT_FOUND:
@@ -324,27 +406,12 @@
                 OT_EXIT_FAILURE);
 
     swapPersist(aInstance, swapFd);
-
-#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
-exit:
-#endif
-    return error;
 }
 
-otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
+void PlatformSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
 {
-    OT_UNUSED_VARIABLE(aInstance);
-
-    otError error  = OT_ERROR_NONE;
-    off_t   size   = lseek(sSettingsFd, 0, SEEK_END);
-    int     swapFd = swapOpen(aInstance);
-
-#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
-    if (isCriticalKey(aKey))
-    {
-        ExitNow(error = otPosixSecureSettingsAdd(aInstance, aKey, aValue, aValueLength));
-    }
-#endif
+    off_t size   = lseek(sSettingsFd, 0, SEEK_END);
+    int   swapFd = swapOpen(aInstance);
 
     if (size > 0)
     {
@@ -358,51 +425,10 @@
                 OT_EXIT_FAILURE);
 
     swapPersist(aInstance, swapFd);
-
-#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
-exit:
-#endif
-    return error;
 }
 
-otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex)
+otError PlatformSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex, int *aSwapFd)
 {
-    otError error;
-
-#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
-    if (isCriticalKey(aKey))
-    {
-        error = otPosixSecureSettingsDelete(aInstance, aKey, aIndex);
-    }
-    else
-#endif
-    {
-        error = platformSettingsDelete(aInstance, aKey, aIndex, nullptr);
-    }
-
-    return error;
-}
-
-/**
- * This function removes a setting either from swap file or persisted file.
- *
- * @param[in]  aInstance  The OpenThread instance structure.
- * @param[in]  aKey       The key associated with the requested setting.
- * @param[in]  aIndex     The index of the value to be removed. If set to -1, all values for this aKey will be removed.
- * @param[out] aSwapFd    A optional pointer to receive file descriptor of the generated swap file descriptor.
- *
- * @note
- *   If @p aSwapFd is null, operate deleting on the setting file.
- *   If @p aSwapFd is not null, operate on the swap file, and aSwapFd will point to the swap file descriptor.
- *
- * @retval OT_ERROR_NONE        The given key and index was found and removed successfully.
- * @retval OT_ERROR_NOT_FOUND   The given key or index was not found in the setting store.
- *
- */
-static otError platformSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex, int *aSwapFd)
-{
-    OT_UNUSED_VARIABLE(aInstance);
-
     otError error  = OT_ERROR_NOT_FOUND;
     off_t   size   = lseek(sSettingsFd, 0, SEEK_END);
     off_t   offset = lseek(sSettingsFd, 0, SEEK_SET);
@@ -477,15 +503,21 @@
     return error;
 }
 
-void otPlatSettingsWipe(otInstance *aInstance)
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+void PlatformSettingsGetSensitiveKeys(otInstance *aInstance, const uint16_t **aKeys, uint16_t *aKeysLength)
 {
     OT_UNUSED_VARIABLE(aInstance);
-#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
-    otPosixSecureSettingsWipe(aInstance);
+
+    assert(aKeys != nullptr);
+    assert(aKeysLength != nullptr);
+
+    *aKeys       = sSensitiveKeys;
+    *aKeysLength = sSensitiveKeysLength;
+}
 #endif
 
-    VerifyOrDie(0 == ftruncate(sSettingsFd, 0), OT_EXIT_ERROR_ERRNO);
-}
+} // namespace Posix
+} // namespace ot
 
 #ifndef SELF_TEST
 #define SELF_TEST 0
@@ -493,6 +525,17 @@
 
 #if SELF_TEST
 
+void otLogCritPlat(const char *aFormat, ...)
+{
+    OT_UNUSED_VARIABLE(aFormat);
+}
+
+const char *otExitCodeToString(uint8_t aExitCode)
+{
+    OT_UNUSED_VARIABLE(aExitCode);
+    return "";
+}
+
 void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64)
 {
     OT_UNUSED_VARIABLE(aInstance);
@@ -516,7 +559,7 @@
         data[i] = i;
     }
 
-    otPlatSettingsInit(instance);
+    otPlatSettingsInit(instance, nullptr, 0);
 
     // verify empty situation
     otPlatSettingsWipe(instance);
diff --git a/src/posix/platform/settings.hpp b/src/posix/platform/settings.hpp
new file mode 100644
index 0000000..6afb0f7
--- /dev/null
+++ b/src/posix/platform/settings.hpp
@@ -0,0 +1,103 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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 POSIX_PLATFORM_SETTINGS_HPP_
+#define POSIX_PLATFORM_SETTINGS_HPP_
+
+namespace ot {
+namespace Posix {
+
+/**
+ * This function gets a setting from the persisted file.
+ *
+ * @param[in]      aInstance     The OpenThread instance structure.
+ * @param[in]      aKey          The key associated with the requested setting.
+ * @param[in]      aIndex        The index of the specific item to get.
+ * @param[out]     aValue        A pointer to where the value of the setting should be written.
+ * @param[in,out]  aValueLength  A pointer to the length of the value.
+ *
+ * @retval OT_ERROR_NONE        The given setting was found and fetched successfully.
+ * @retval OT_ERROR_NOT_FOUND   The given key or index was not found in the setting store.
+ *
+ */
+otError PlatformSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength);
+
+/**
+ * This function sets a setting in the persisted file.
+ *
+ * @param[in]  aInstance     The OpenThread instance structure.
+ * @param[in]  aKey          The key associated with the requested setting.
+ * @param[in]  aValue        A pointer to where the new value of the setting should be read from.
+ * @param[in]  aValueLength  The length of the data pointed to by aValue.
+ *
+ */
+void PlatformSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
+
+/**
+ * This function adds a setting to the persisted file.
+ *
+ * @param[in]  aInstance     The OpenThread instance structure.
+ * @param[in]  aKey          The key associated with the requested setting.
+ * @param[in]  aValue        A pointer to where the new value of the setting should be read from.
+ * @param[in]  aValueLength  The length of the data pointed to by aValue.
+ *
+ */
+void PlatformSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
+
+/**
+ * This function removes a setting either from swap file or persisted file.
+ *
+ * @param[in]  aInstance  The OpenThread instance structure.
+ * @param[in]  aKey       The key associated with the requested setting.
+ * @param[in]  aIndex     The index of the value to be removed. If set to -1, all values for this aKey will be removed.
+ * @param[out] aSwapFd    A optional pointer to receive file descriptor of the generated swap file descriptor.
+ *
+ * @note
+ *   If @p aSwapFd is null, operate deleting on the setting file.
+ *   If @p aSwapFd is not null, operate on the swap file, and aSwapFd will point to the swap file descriptor.
+ *
+ * @retval OT_ERROR_NONE        The given key and index was found and removed successfully.
+ * @retval OT_ERROR_NOT_FOUND   The given key or index was not found in the setting store.
+ *
+ */
+otError PlatformSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex, int *aSwapFd);
+
+/**
+ * This function gets the sensitive keys that should be stored in the secure area.
+ *
+ * @param[in]   aInstance    The OpenThread instance structure.
+ * @param[out]  aKeys        A pointer to where the pointer to the array containing sensitive keys should be written.
+ * @param[out]  aKeysLength  A pointer to where the count of sensitive keys should be written.
+ *
+ */
+void PlatformSettingsGetSensitiveKeys(otInstance *aInstance, const uint16_t **aKeys, uint16_t *aKeysLength);
+
+} // namespace Posix
+} // namespace ot
+
+#endif // POSIX_PLATFORM_SETTINGS_HPP_
diff --git a/src/posix/platform/spi_interface.cpp b/src/posix/platform/spi_interface.cpp
index d1a366c..33f6d0c 100644
--- a/src/posix/platform/spi_interface.cpp
+++ b/src/posix/platform/spi_interface.cpp
@@ -74,32 +74,27 @@
     , mResetGpioValueFd(-1)
     , mIntGpioValueFd(-1)
     , mSlaveResetCount(0)
-    , mSpiFrameCount(0)
-    , mSpiValidFrameCount(0)
-    , mSpiGarbageFrameCount(0)
     , mSpiDuplexFrameCount(0)
     , mSpiUnresponsiveFrameCount(0)
-    , mSpiRxFrameCount(0)
-    , mSpiRxFrameByteCount(0)
-    , mSpiTxFrameCount(0)
-    , mSpiTxFrameByteCount(0)
     , mSpiTxIsReady(false)
     , mSpiTxRefusedCount(0)
     , mSpiTxPayloadSize(0)
     , mDidPrintRateLimitLog(false)
     , mSpiSlaveDataLen(0)
+    , mDidRxFrame(false)
 {
 }
 
 void SpiInterface::OnRcpReset(void)
 {
-    mSpiValidFrameCount   = 0;
     mSpiTxIsReady         = false;
     mSpiTxRefusedCount    = 0;
     mSpiTxPayloadSize     = 0;
     mDidPrintRateLimitLog = false;
     mSpiSlaveDataLen      = 0;
     memset(mSpiTxFrameBuffer, 0, sizeof(mSpiTxFrameBuffer));
+    memset(&mInterfaceMetrics, 0, sizeof(mInterfaceMetrics));
+    mInterfaceMetrics.mRcpInterfaceType = OT_POSIX_RCP_BUS_SPI;
 
     TriggerReset();
     usleep(static_cast<useconds_t>(mSpiResetDelay) * kUsecPerMsec);
@@ -285,7 +280,7 @@
 
     otLogDebgPlat("InitResetPin: charDev=%s, line=%" PRIu8, aCharDev, aLine);
 
-    VerifyOrDie((aCharDev != nullptr) && (aLine < GPIOHANDLES_MAX), OT_EXIT_INVALID_ARGUMENTS);
+    VerifyOrDie(aCharDev != nullptr, OT_EXIT_INVALID_ARGUMENTS);
     VerifyOrDie((fd = open(aCharDev, O_RDWR)) != -1, OT_EXIT_ERROR_ERRNO);
     mResetGpioValueFd = SetupGpioHandle(fd, aLine, GPIOHANDLE_REQUEST_OUTPUT, label);
 
@@ -299,7 +294,7 @@
 
     otLogDebgPlat("InitIntPin: charDev=%s, line=%" PRIu8, aCharDev, aLine);
 
-    VerifyOrDie((aCharDev != nullptr) && (aLine < GPIOHANDLES_MAX), OT_EXIT_INVALID_ARGUMENTS);
+    VerifyOrDie(aCharDev != nullptr, OT_EXIT_INVALID_ARGUMENTS);
     VerifyOrDie((fd = open(aCharDev, O_RDWR)) != -1, OT_EXIT_ERROR_ERRNO);
 
     mIntGpioValueFd = SetupGpioEvent(fd, aLine, GPIOHANDLE_REQUEST_INPUT, GPIOEVENT_REQUEST_FALLING_EDGE, label);
@@ -398,10 +393,10 @@
 
     if (ret != -1)
     {
-        otDumpDebg(OT_LOG_REGION_PLATFORM, "SPI-TX", mSpiTxFrameBuffer, transfer[1].len);
-        otDumpDebg(OT_LOG_REGION_PLATFORM, "SPI-RX", aSpiRxFrameBuffer, transfer[1].len);
+        otDumpDebgPlat("SPI-TX", mSpiTxFrameBuffer, static_cast<uint16_t>(transfer[1].len));
+        otDumpDebgPlat("SPI-RX", aSpiRxFrameBuffer, static_cast<uint16_t>(transfer[1].len));
 
-        mSpiFrameCount++;
+        mInterfaceMetrics.mTransferredFrameCount++;
     }
 
     return (ret < 0) ? OT_ERROR_FAILED : OT_ERROR_NONE;
@@ -420,7 +415,7 @@
     Ncp::SpiFrame txFrame(mSpiTxFrameBuffer);
     uint16_t      skipAlignAllowanceLength;
 
-    if (mSpiValidFrameCount == 0)
+    if (mInterfaceMetrics.mTransferredValidFrameCount == 0)
     {
         // Set the reset flag to indicate to our slave that we are coming up from scratch.
         txFrame.SetHeaderFlagByte(true);
@@ -445,29 +440,20 @@
         // Go ahead and try to immediately send a frame if we have it queued up.
         txFrame.SetHeaderDataLen(mSpiTxPayloadSize);
 
-        if (mSpiTxPayloadSize > spiTransferBytes)
-        {
-            spiTransferBytes = mSpiTxPayloadSize;
-        }
+        spiTransferBytes = OT_MAX(spiTransferBytes, mSpiTxPayloadSize);
     }
 
     if (mSpiSlaveDataLen != 0)
     {
         // In a previous transaction the slave indicated it had something to send us. Make sure our transaction
         // is large enough to handle it.
-        if (mSpiSlaveDataLen > spiTransferBytes)
-        {
-            spiTransferBytes = mSpiSlaveDataLen;
-        }
+        spiTransferBytes = OT_MAX(spiTransferBytes, mSpiSlaveDataLen);
     }
     else
     {
         // Set up a minimum transfer size to allow small frames the slave wants to send us to be handled in a
         // single transaction.
-        if (spiTransferBytes < mSpiSmallPacketSize)
-        {
-            spiTransferBytes = mSpiSmallPacketSize;
-        }
+        spiTransferBytes = OT_MAX(spiTransferBytes, mSpiSmallPacketSize);
     }
 
     txFrame.SetHeaderAcceptLen(spiTransferBytes);
@@ -533,12 +519,12 @@
             else
             {
                 // Header is full of garbage
-                mSpiGarbageFrameCount++;
+                mInterfaceMetrics.mTransferredGarbageFrameCount++;
 
                 otLogWarnPlat("Garbage in header : %02X %02X %02X %02X %02X", spiRxFrame[0], spiRxFrame[1],
                               spiRxFrame[2], spiRxFrame[3], spiRxFrame[4]);
-                otDumpWarn(OT_LOG_REGION_PLATFORM, "SPI-TX", mSpiTxFrameBuffer, spiTransferBytes);
-                otDumpWarn(OT_LOG_REGION_PLATFORM, "SPI-RX", spiRxFrameBuffer, spiTransferBytes);
+                otDumpDebgPlat("SPI-TX", mSpiTxFrameBuffer, spiTransferBytes);
+                otDumpDebgPlat("SPI-RX", spiRxFrameBuffer, spiTransferBytes);
             }
 
             mSpiTxRefusedCount++;
@@ -550,19 +536,19 @@
 
         if (!rxFrame.IsValid() || (slaveAcceptLen > kMaxFrameSize) || (mSpiSlaveDataLen > kMaxFrameSize))
         {
-            mSpiGarbageFrameCount++;
+            mInterfaceMetrics.mTransferredGarbageFrameCount++;
             mSpiTxRefusedCount++;
             mSpiSlaveDataLen = 0;
 
             otLogWarnPlat("Garbage in header : %02X %02X %02X %02X %02X", spiRxFrame[0], spiRxFrame[1], spiRxFrame[2],
                           spiRxFrame[3], spiRxFrame[4]);
-            otDumpWarn(OT_LOG_REGION_PLATFORM, "SPI-TX", mSpiTxFrameBuffer, spiTransferBytes);
-            otDumpWarn(OT_LOG_REGION_PLATFORM, "SPI-RX", spiRxFrameBuffer, spiTransferBytes);
+            otDumpDebgPlat("SPI-TX", mSpiTxFrameBuffer, spiTransferBytes);
+            otDumpDebgPlat("SPI-RX", spiRxFrameBuffer, spiTransferBytes);
 
             ExitNow();
         }
 
-        mSpiValidFrameCount++;
+        mInterfaceMetrics.mTransferredValidFrameCount++;
 
         if (rxFrame.IsResetFlagSet())
         {
@@ -575,9 +561,9 @@
         // Handle received packet, if any.
         if ((mSpiSlaveDataLen != 0) && (mSpiSlaveDataLen <= txFrame.GetHeaderAcceptLen()))
         {
-            mSpiRxFrameByteCount += mSpiSlaveDataLen;
+            mInterfaceMetrics.mRxFrameByteCount += mSpiSlaveDataLen;
             mSpiSlaveDataLen = 0;
-            mSpiRxFrameCount++;
+            mInterfaceMetrics.mRxFrameCount++;
             successfulExchanges++;
 
             // Set the skip length to skip align bytes and SPI frame header.
@@ -588,6 +574,7 @@
             // Upper layer will free the frame buffer.
             discardRxFrame = false;
 
+            mDidRxFrame = true;
             mReceiveFrameCallback(mReceiveFrameContext);
         }
     }
@@ -601,8 +588,8 @@
             // that uplayer can pull another packet for us to send.
             successfulExchanges++;
 
-            mSpiTxFrameCount++;
-            mSpiTxFrameByteCount += mSpiTxPayloadSize;
+            mInterfaceMetrics.mTxFrameCount++;
+            mInterfaceMetrics.mTxFrameByteCount += mSpiTxPayloadSize;
 
             mSpiTxIsReady      = false;
             mSpiTxPayloadSize  = 0;
@@ -740,7 +727,14 @@
 
 void SpiInterface::Process(const RadioProcessContext &aContext)
 {
-    if (FD_ISSET(mIntGpioValueFd, aContext.mReadFdSet))
+    Process(aContext.mReadFdSet, aContext.mWriteFdSet);
+}
+
+void SpiInterface::Process(const fd_set *aReadFdSet, const fd_set *aWriteFdSet)
+{
+    OT_UNUSED_VARIABLE(aWriteFdSet);
+
+    if (FD_ISSET(mIntGpioValueFd, aReadFdSet))
     {
         struct gpioevent_data event;
 
@@ -760,68 +754,48 @@
 
 otError SpiInterface::WaitForFrame(uint64_t aTimeoutUs)
 {
-    otError        error      = OT_ERROR_NONE;
-    struct timeval spiTimeout = {kSecPerDay, 0};
-    struct timeval timeout;
-    fd_set         readFdSet;
-    int            ret;
-    bool           isDataReady = false;
+    otError  error = OT_ERROR_NONE;
+    uint64_t now   = otPlatTimeGet();
+    uint64_t end   = now + aTimeoutUs;
 
-    timeout.tv_sec  = static_cast<time_t>(aTimeoutUs / US_PER_S);
-    timeout.tv_usec = static_cast<suseconds_t>(aTimeoutUs % US_PER_S);
+    mDidRxFrame = false;
 
-    FD_ZERO(&readFdSet);
-
-    if (mIntGpioValueFd >= 0)
+    while (now < end)
     {
-        if ((isDataReady = CheckInterrupt()))
+        fd_set         readFdSet;
+        fd_set         writeFdSet;
+        int            maxFds = -1;
+        struct timeval timeout;
+        int            ret;
+
+        timeout.tv_sec  = static_cast<time_t>((end - now) / US_PER_S);
+        timeout.tv_usec = static_cast<suseconds_t>((end - now) % US_PER_S);
+
+        FD_ZERO(&readFdSet);
+        FD_ZERO(&writeFdSet);
+
+        UpdateFdSet(readFdSet, writeFdSet, maxFds, timeout);
+
+        ret = select(maxFds + 1, &readFdSet, &writeFdSet, nullptr, &timeout);
+
+        if (ret >= 0)
         {
-            // Interrupt pin is asserted, set the timeout to be 0.
-            spiTimeout.tv_sec  = 0;
-            spiTimeout.tv_usec = 0;
+            Process(&readFdSet, &writeFdSet);
+
+            if (mDidRxFrame)
+            {
+                ExitNow();
+            }
         }
-        else
+        else if (errno != EINTR)
         {
-            // The interrupt pin was not asserted, so we wait for the interrupt pin to be asserted by adding it to the
-            // read set.
-            FD_SET(mIntGpioValueFd, &readFdSet);
+            DieNow(OT_EXIT_ERROR_ERRNO);
         }
-    }
-    else
-    {
-        // In this case we don't have an interrupt, so we revert to SPI polling.
-        spiTimeout.tv_sec  = 0;
-        spiTimeout.tv_usec = kSpiPollPeriodUs;
+
+        now = otPlatTimeGet();
     }
 
-    if (timercmp(&spiTimeout, &timeout, <))
-    {
-        timeout = spiTimeout;
-    }
-
-    ret = select(mIntGpioValueFd + 1, &readFdSet, nullptr, nullptr, &timeout);
-
-    if (ret > 0 && FD_ISSET(mIntGpioValueFd, &readFdSet))
-    {
-        struct gpioevent_data event;
-
-        // Read event data to clear interrupt.
-        VerifyOrDie(read(mIntGpioValueFd, &event, sizeof(event)) != -1, OT_EXIT_FAILURE);
-        isDataReady = true;
-    }
-
-    if (isDataReady)
-    {
-        IgnoreError(PushPullSpi());
-    }
-    else if (ret == 0)
-    {
-        ExitNow(error = OT_ERROR_RESPONSE_TIMEOUT);
-    }
-    else if (errno != EINTR)
-    {
-        DieNow(OT_EXIT_ERROR_ERRNO);
-    }
+    error = OT_ERROR_RESPONSE_TIMEOUT;
 
 exit:
     return error;
@@ -853,16 +827,16 @@
 
 void SpiInterface::LogStats(void)
 {
-    otLogInfoPlat("INFO: mSlaveResetCount=%" PRIu64, mSlaveResetCount);
-    otLogInfoPlat("INFO: mSpiFrameCount=%" PRIu64, mSpiFrameCount);
-    otLogInfoPlat("INFO: mSpiValidFrameCount=%" PRIu64, mSpiValidFrameCount);
-    otLogInfoPlat("INFO: mSpiDuplexFrameCount=%" PRIu64, mSpiDuplexFrameCount);
-    otLogInfoPlat("INFO: mSpiUnresponsiveFrameCount=%" PRIu64, mSpiUnresponsiveFrameCount);
-    otLogInfoPlat("INFO: mSpiGarbageFrameCount=%" PRIu64, mSpiGarbageFrameCount);
-    otLogInfoPlat("INFO: mSpiRxFrameCount=%" PRIu64, mSpiRxFrameCount);
-    otLogInfoPlat("INFO: mSpiRxFrameByteCount=%" PRIu64, mSpiRxFrameByteCount);
-    otLogInfoPlat("INFO: mSpiTxFrameCount=%" PRIu64, mSpiTxFrameCount);
-    otLogInfoPlat("INFO: mSpiTxFrameByteCount=%" PRIu64, mSpiTxFrameByteCount);
+    otLogInfoPlat("INFO: SlaveResetCount=%" PRIu64, mSlaveResetCount);
+    otLogInfoPlat("INFO: SpiDuplexFrameCount=%" PRIu64, mSpiDuplexFrameCount);
+    otLogInfoPlat("INFO: SpiUnresponsiveFrameCount=%" PRIu64, mSpiUnresponsiveFrameCount);
+    otLogInfoPlat("INFO: TransferredFrameCount=%" PRIu64, mInterfaceMetrics.mTransferredFrameCount);
+    otLogInfoPlat("INFO: TransferredValidFrameCount=%" PRIu64, mInterfaceMetrics.mTransferredValidFrameCount);
+    otLogInfoPlat("INFO: TransferredGarbageFrameCount=%" PRIu64, mInterfaceMetrics.mTransferredGarbageFrameCount);
+    otLogInfoPlat("INFO: RxFrameCount=%" PRIu64, mInterfaceMetrics.mRxFrameCount);
+    otLogInfoPlat("INFO: RxFrameByteCount=%" PRIu64, mInterfaceMetrics.mRxFrameByteCount);
+    otLogInfoPlat("INFO: TxFrameCount=%" PRIu64, mInterfaceMetrics.mTxFrameCount);
+    otLogInfoPlat("INFO: TxFrameByteCount=%" PRIu64, mInterfaceMetrics.mTxFrameByteCount);
 }
 } // namespace Posix
 } // namespace ot
diff --git a/src/posix/platform/spi_interface.hpp b/src/posix/platform/spi_interface.hpp
index cff2bca..b2e8a02 100644
--- a/src/posix/platform/spi_interface.hpp
+++ b/src/posix/platform/spi_interface.hpp
@@ -122,10 +122,10 @@
     /**
      * This method updates the file descriptor sets with file descriptors used by the radio driver.
      *
-     * @param[inout]  aReadFdSet   A reference to the read file descriptors.
-     * @param[inout]  aWriteFdSet  A reference to the write file descriptors.
-     * @param[inout]  aMaxFd       A reference to the max file descriptor.
-     * @param[inout]  aTimeout     A reference to the timeout.
+     * @param[in,out]  aReadFdSet   A reference to the read file descriptors.
+     * @param[in,out]  aWriteFdSet  A reference to the write file descriptors.
+     * @param[in,out]  aMaxFd       A reference to the max file descriptor.
+     * @param[in,out]  aTimeout     A reference to the timeout.
      *
      */
     void UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, int &aMaxFd, struct timeval &aTimeout);
@@ -159,6 +159,14 @@
      */
     otError ResetConnection(void) { return OT_ERROR_NONE; }
 
+    /**
+     * This method returns the RCP interface metrics.
+     *
+     * @returns The RCP interface metrics.
+     *
+     */
+    const otRcpInterfaceMetrics *GetRcpInterfaceMetrics(void) const { return &mInterfaceMetrics; }
+
 private:
     int     SetupGpioHandle(int aFd, uint8_t aLine, uint32_t aHandleFlags, const char *aLabel);
     int     SetupGpioEvent(int aFd, uint8_t aLine, uint32_t aHandleFlags, uint32_t aEventFlags, const char *aLabel);
@@ -173,6 +181,7 @@
     uint8_t *GetRealRxFrameStart(uint8_t *aSpiRxFrameBuffer, uint8_t aAlignAllowance, uint16_t &aSkipLength);
     otError  DoSpiTransfer(uint8_t *aSpiRxFrameBuffer, uint32_t aTransferLength);
     otError  PushPullSpi(void);
+    void     Process(const fd_set *aReadFdSet, const fd_set *aWriteFdSet);
 
     bool CheckInterrupt(void);
     void LogStats(void);
@@ -227,15 +236,8 @@
     uint32_t mSpiSpeedHz;
 
     uint64_t mSlaveResetCount;
-    uint64_t mSpiFrameCount;
-    uint64_t mSpiValidFrameCount;
-    uint64_t mSpiGarbageFrameCount;
     uint64_t mSpiDuplexFrameCount;
     uint64_t mSpiUnresponsiveFrameCount;
-    uint64_t mSpiRxFrameCount;
-    uint64_t mSpiRxFrameByteCount;
-    uint64_t mSpiTxFrameCount;
-    uint64_t mSpiTxFrameByteCount;
 
     bool     mSpiTxIsReady;
     uint16_t mSpiTxRefusedCount;
@@ -245,6 +247,10 @@
     bool     mDidPrintRateLimitLog;
     uint16_t mSpiSlaveDataLen;
 
+    bool mDidRxFrame;
+
+    otRcpInterfaceMetrics mInterfaceMetrics;
+
     // Non-copyable, intentionally not implemented.
     SpiInterface(const SpiInterface &);
     SpiInterface &operator=(const SpiInterface &);
diff --git a/src/posix/platform/system.cpp b/src/posix/platform/system.cpp
index 8b78f9b..c3e176a 100644
--- a/src/posix/platform/system.cpp
+++ b/src/posix/platform/system.cpp
@@ -49,6 +49,7 @@
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
 #include "posix/platform/daemon.hpp"
+#include "posix/platform/firewall.hpp"
 #include "posix/platform/infra_if.hpp"
 #include "posix/platform/mainloop.hpp"
 #include "posix/platform/radio_url.hpp"
@@ -160,6 +161,8 @@
 
 void platformSetUp(void)
 {
+    VerifyOrExit(!gDryRun);
+
 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
     platformBackboneSetUp();
 #endif
@@ -183,6 +186,9 @@
 #if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE || OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
     SuccessOrDie(otSetStateChangedCallback(gInstance, processStateChange, gInstance));
 #endif
+
+exit:
+    return;
 }
 
 otInstance *otSysInit(otPlatformConfig *aPlatformConfig)
@@ -202,6 +208,8 @@
 
 void platformTearDown(void)
 {
+    VerifyOrExit(!gDryRun);
+
 #if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
     ot::Posix::Daemon::Get().TearDown();
 #endif
@@ -221,6 +229,9 @@
 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
     platformBackboneTearDown();
 #endif
+
+exit:
+    return;
 }
 
 void platformDeinit(void)
@@ -229,6 +240,10 @@
     virtualTimeDeinit();
 #endif
     platformRadioDeinit();
+
+    // For Dry-Run option, only the radio is initialized.
+    VerifyOrExit(!gDryRun);
+
 #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
     ot::Posix::Udp::Get().Deinit();
 #endif
@@ -246,6 +261,9 @@
 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
     platformBackboneDeinit();
 #endif
+
+exit:
+    return;
 }
 
 void otSysDeinit(void)
@@ -262,9 +280,9 @@
 /**
  * This function try selecting the given file descriptors in nonblocking mode.
  *
- * @param[inout]    aReadFdSet   A pointer to the read file descriptors.
- * @param[inout]    aWriteFdSet  A pointer to the write file descriptors.
- * @param[inout]    aErrorFdSet  A pointer to the error file descriptors.
+ * @param[in,out]   aReadFdSet   A pointer to the read file descriptors.
+ * @param[in,out]   aWriteFdSet  A pointer to the write file descriptors.
+ * @param[in,out]   aErrorFdSet  A pointer to the error file descriptors.
  * @param[in]       aMaxFd       The max file descriptor.
  *
  * @returns The value returned from select().
@@ -378,15 +396,6 @@
 #endif
 }
 
-#if OPENTHREAD_CONFIG_OTNS_ENABLE
-
-void otPlatOtnsStatus(const char *aStatus)
-{
-    otLogOtns("[OTNS] %s", aStatus);
-}
-
-#endif
-
 bool IsSystemDryRun(void)
 {
     return gDryRun;
diff --git a/src/posix/platform/trel.cpp b/src/posix/platform/trel.cpp
new file mode 100644
index 0000000..f3ec6cf
--- /dev/null
+++ b/src/posix/platform/trel.cpp
@@ -0,0 +1,572 @@
+/*
+ *  Copyright (c) 2019-2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file implements platform for TREL using IPv6/UDP socket under POSIX.
+ */
+
+#include "openthread-posix-config.h"
+
+#include "platform-posix.h"
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <openthread/logging.h>
+#include <openthread/platform/trel.h>
+
+#include "radio_url.hpp"
+#include "system.hpp"
+#include "common/code_utils.hpp"
+
+#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
+
+#define TREL_MAX_PACKET_SIZE 1400
+#define TREL_PACKET_POOL_SIZE 5
+
+typedef struct TxPacket
+{
+    struct TxPacket *mNext;
+    uint8_t          mBuffer[TREL_MAX_PACKET_SIZE];
+    uint16_t         mLength;
+    otSockAddr       mDestSockAddr;
+} TxPacket;
+
+static uint8_t   sRxPacketBuffer[TREL_MAX_PACKET_SIZE];
+static uint16_t  sRxPacketLength;
+static TxPacket  sTxPacketPool[TREL_PACKET_POOL_SIZE];
+static TxPacket *sFreeTxPacketHead;  // A singly linked list of free/available `TxPacket` from pool.
+static TxPacket *sTxPacketQueueTail; // A circular linked list for queued tx packets.
+
+static char sInterfaceName[IFNAMSIZ + 1];
+static bool sInitialized = false;
+static bool sEnabled     = false;
+static int  sSocket      = -1;
+
+static const char *Ip6AddrToString(const void *aAddress)
+{
+    static char string[INET6_ADDRSTRLEN];
+    return inet_ntop(AF_INET6, aAddress, string, sizeof(string));
+}
+
+static const char *BufferToString(const uint8_t *aBuffer, uint16_t aLength)
+{
+    const uint16_t kMaxWrite = 16;
+    static char    string[1600];
+
+    uint16_t num = 0;
+    char *   cur = &string[0];
+    char *   end = &string[sizeof(string) - 1];
+
+    cur += snprintf(cur, (uint16_t)(end - cur), "[(len:%d) ", aLength);
+    VerifyOrExit(cur < end);
+
+    while (aLength-- && (num < kMaxWrite))
+    {
+        cur += snprintf(cur, (uint16_t)(end - cur), "%02x ", *aBuffer++);
+        VerifyOrExit(cur < end);
+
+        num++;
+    }
+
+    if (aLength != 0)
+    {
+        cur += snprintf(cur, (uint16_t)(end - cur), "... ");
+        VerifyOrExit(cur < end);
+    }
+
+    *cur++ = ']';
+    VerifyOrExit(cur < end);
+
+    *cur = '\0';
+
+exit:
+    *end = '\0';
+    return string;
+}
+
+static void PrepareSocket(uint16_t &aUdpPort)
+{
+    int                 val;
+    struct sockaddr_in6 sockAddr;
+    socklen_t           sockLen;
+
+    otLogDebgPlat("[trel] PrepareSocket()");
+
+    sSocket = SocketWithCloseExec(AF_INET6, SOCK_DGRAM, 0, kSocketNonBlock);
+    VerifyOrDie(sSocket >= 0, OT_EXIT_ERROR_ERRNO);
+
+    // Make the socket non-blocking to allow immediate tx attempt.
+    val = fcntl(sSocket, F_GETFL, 0);
+    VerifyOrDie(val != -1, OT_EXIT_ERROR_ERRNO);
+    val = val | O_NONBLOCK;
+    VerifyOrDie(fcntl(sSocket, F_SETFL, val) == 0, OT_EXIT_ERROR_ERRNO);
+
+    // Bind the socket.
+
+    memset(&sockAddr, 0, sizeof(sockAddr));
+    sockAddr.sin6_family = AF_INET6;
+    sockAddr.sin6_addr   = in6addr_any;
+    sockAddr.sin6_port   = OPENTHREAD_POSIX_CONFIG_TREL_UDP_PORT;
+
+    if (bind(sSocket, (struct sockaddr *)&sockAddr, sizeof(sockAddr)) == -1)
+    {
+        otLogCritPlat("[trel] Failed to bind socket");
+        DieNow(OT_EXIT_ERROR_ERRNO);
+    }
+
+    sockLen = sizeof(sockAddr);
+
+    if (getsockname(sSocket, (struct sockaddr *)&sockAddr, &sockLen) == -1)
+    {
+        otLogCritPlat("[trel] Failed to get the socket name");
+        DieNow(OT_EXIT_ERROR_ERRNO);
+    }
+
+    aUdpPort = ntohs(sockAddr.sin6_port);
+}
+
+static otError SendPacket(const uint8_t *aBuffer, uint16_t aLength, const otSockAddr *aDestSockAddr)
+{
+    otError             error = OT_ERROR_NONE;
+    struct sockaddr_in6 sockAddr;
+    ssize_t             ret;
+
+    VerifyOrExit(sSocket >= 0, error = OT_ERROR_INVALID_STATE);
+
+    memset(&sockAddr, 0, sizeof(sockAddr));
+    sockAddr.sin6_family = AF_INET6;
+    sockAddr.sin6_port   = htons(aDestSockAddr->mPort);
+    memcpy(&sockAddr.sin6_addr, &aDestSockAddr->mAddress, sizeof(otIp6Address));
+
+    ret = sendto(sSocket, aBuffer, aLength, 0, (struct sockaddr *)&sockAddr, sizeof(sockAddr));
+
+    if (ret != aLength)
+    {
+        otLogDebgPlat("[trel] SendPacket() -- sendto() failed errno %d", errno);
+
+        switch (errno)
+        {
+        case ENETUNREACH:
+        case ENETDOWN:
+        case EHOSTUNREACH:
+            error = OT_ERROR_ABORT;
+            break;
+
+        default:
+            error = OT_ERROR_INVALID_STATE;
+        }
+    }
+
+exit:
+    otLogDebgPlat("[trel] SendPacket([%s]:%u) err:%s pkt:%s", Ip6AddrToString(&aDestSockAddr->mAddress),
+                  aDestSockAddr->mPort, otThreadErrorToString(error), BufferToString(aBuffer, aLength));
+
+    return error;
+}
+
+static void ReceivePacket(int aSocket, otInstance *aInstance)
+{
+    struct sockaddr_in6 sockAddr;
+    socklen_t           sockAddrLen = sizeof(sockAddr);
+    ssize_t             ret;
+
+    memset(&sockAddr, 0, sizeof(sockAddr));
+
+    ret = recvfrom(aSocket, (char *)sRxPacketBuffer, sizeof(sRxPacketBuffer), 0, (struct sockaddr *)&sockAddr,
+                   &sockAddrLen);
+    VerifyOrDie(ret >= 0, OT_EXIT_ERROR_ERRNO);
+
+    sRxPacketLength = (uint16_t)(ret);
+
+    if (sRxPacketLength > sizeof(sRxPacketBuffer))
+    {
+        sRxPacketLength = sizeof(sRxPacketLength);
+    }
+
+    otLogDebgPlat("[trel] ReceivePacket() - received from [%s]:%d, id:%d, pkt:%s", Ip6AddrToString(&sockAddr.sin6_addr),
+                  ntohs(sockAddr.sin6_port), sockAddr.sin6_scope_id, BufferToString(sRxPacketBuffer, sRxPacketLength));
+
+    if (sEnabled)
+    {
+        otPlatTrelHandleReceived(aInstance, sRxPacketBuffer, sRxPacketLength);
+    }
+}
+
+static void InitPacketQueue(void)
+{
+    sTxPacketQueueTail = NULL;
+
+    // Chain all the packets in pool in the free linked list.
+    sFreeTxPacketHead = NULL;
+
+    for (uint16_t index = 0; index < OT_ARRAY_LENGTH(sTxPacketPool); index++)
+    {
+        TxPacket *packet = &sTxPacketPool[index];
+
+        packet->mNext     = sFreeTxPacketHead;
+        sFreeTxPacketHead = packet;
+    }
+}
+
+static void SendQueuedPackets(void)
+{
+    while (sTxPacketQueueTail != NULL)
+    {
+        TxPacket *packet = sTxPacketQueueTail->mNext; // tail->mNext is the head of the list.
+
+        if (SendPacket(packet->mBuffer, packet->mLength, &packet->mDestSockAddr) == OT_ERROR_INVALID_STATE)
+        {
+            otLogDebgPlat("[trel] SendQueuedPackets() - SendPacket() would block");
+            break;
+        }
+
+        // Remove the `packet` from the packet queue (circular
+        // linked list).
+
+        if (packet == sTxPacketQueueTail)
+        {
+            sTxPacketQueueTail = NULL;
+        }
+        else
+        {
+            sTxPacketQueueTail->mNext = packet->mNext;
+        }
+
+        // Add the `packet` to the free packet singly linked list.
+
+        packet->mNext     = sFreeTxPacketHead;
+        sFreeTxPacketHead = packet;
+    }
+}
+
+static void EnqueuePacket(const uint8_t *aBuffer, uint16_t aLength, const otSockAddr *aDestSockAddr)
+{
+    TxPacket *packet;
+
+    // Allocate an available packet entry (from the free packet list)
+    // and copy the packet content into it.
+
+    VerifyOrExit(sFreeTxPacketHead != NULL, otLogWarnPlat("[trel] EnqueuePacket failed, queue is full"));
+    packet            = sFreeTxPacketHead;
+    sFreeTxPacketHead = sFreeTxPacketHead->mNext;
+
+    memcpy(packet->mBuffer, aBuffer, aLength);
+    packet->mLength       = aLength;
+    packet->mDestSockAddr = *aDestSockAddr;
+
+    // Add packet to the tail of TxPacketQueue circular linked-list.
+
+    if (sTxPacketQueueTail == NULL)
+    {
+        packet->mNext      = packet;
+        sTxPacketQueueTail = packet;
+    }
+    else
+    {
+        packet->mNext             = sTxPacketQueueTail->mNext;
+        sTxPacketQueueTail->mNext = packet;
+        sTxPacketQueueTail        = packet;
+    }
+
+    otLogDebgPlat("[trel] EnqueuePacket([%s]:%u) - %s", Ip6AddrToString(&aDestSockAddr->mAddress), aDestSockAddr->mPort,
+                  BufferToString(aBuffer, aLength));
+
+exit:
+    return;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+// trelDnssd
+//
+// The functions below are tied to mDNS or DNS-SD library being used on
+// a device and need to be implemented per project/platform. A weak empty
+// implementation is provided here which describes the expected
+// behavior. They need to be overridden during project/platform
+// integration.
+
+OT_TOOL_WEAK void trelDnssdInitialize(const char *aTrelNetif)
+{
+    // This function initialize the TREL DNS-SD module on the given
+    // TREL Network Interface.
+
+    OT_UNUSED_VARIABLE(aTrelNetif);
+}
+
+OT_TOOL_WEAK void trelDnssdStartBrowse(void)
+{
+    // This function initiates an ongoing DNS-SD browse on the service
+    // name "_trel._udp" within the local browsing domain to discover
+    // other devices supporting TREL. The ongoing browse will produce
+    // two different types of events: `add` events and `remove` events.
+    // When the browse is started, it should produce an `add` event for
+    // every TREL peer currently present on the network. Whenever a
+    // TREL peer goes offline, a "remove" event should be produced.
+    // `Remove` events are not guaranteed, however. When a TREL service
+    // instance is discovered, a new ongoing DNS-SD query for an AAAA
+    // record MUST be started on the hostname indicated in the SRV
+    // record of the discovered instance. If multiple host IPv6
+    // addressees are discovered for a peer, one with highest scope
+    // among all addresses MUST be reported (if there are multiple
+    // address at same scope, one must be selected randomly).
+    //
+    // The platform MUST signal back the discovered peer info using
+    // `otPlatTrelHandleDiscoveredPeerInfo()` callback. This callback
+    // MUST be invoked when a new peer is discovered, or when there is
+    // a change in an existing entry (e.g., new TXT record or new port
+    // number or new IPv6 address), or when the peer is removed.
+}
+
+OT_TOOL_WEAK void trelDnssdStopBrowse(void)
+{
+    // This function stops the ongoing DNS-SD browse started from an
+    // earlier call to `trelDnssdStartBrowse()`.
+}
+
+OT_TOOL_WEAK void trelDnssdRegisterService(uint16_t aPort, const uint8_t *aTxtData, uint8_t aTxtLength)
+{
+    // This function registers a new service to be advertised using
+    // DNS-SD.
+    //
+    // The service name is "_trel._udp". The platform should use its own
+    // hostname, which when combined with the service name and the
+    // local DNS-SD domain name will produce the full service instance
+    // name, for example "example-host._trel._udp.local.".
+    //
+    // The domain under which the service instance name appears will
+    // be 'local' for mDNS, and will be whatever domain is used for
+    // service registration in the case of a non-mDNS local DNS-SD
+    // service.
+    //
+    // A subsequent call to this function updates the previous service.
+    // It is used to update the TXT record data and/or the port
+    // number.
+    //
+    // The `aTxtData` buffer is not persisted after the return from this
+    // function. The platform layer MUST not keep the pointer and
+    // instead copy the content if needed.
+
+    OT_UNUSED_VARIABLE(aPort);
+    OT_UNUSED_VARIABLE(aTxtData);
+    OT_UNUSED_VARIABLE(aTxtLength);
+}
+
+OT_TOOL_WEAK void trelDnssdRemoveService(void)
+{
+    // This function removes any previously registered "_trel._udp"
+    // service using `platTrelRegisterService()`. Device must stop
+    // advertising TREL service after this call.
+}
+
+OT_TOOL_WEAK void trelDnssdUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd, struct timeval *aTimeout)
+{
+    // This function can be used to update the file descriptor sets
+    // by DNS-SD layer (if needed).
+
+    OT_UNUSED_VARIABLE(aReadFdSet);
+    OT_UNUSED_VARIABLE(aWriteFdSet);
+    OT_UNUSED_VARIABLE(aMaxFd);
+    OT_UNUSED_VARIABLE(aTimeout);
+}
+
+OT_TOOL_WEAK void trelDnssdProcess(otInstance *aInstance, const fd_set *aReadFdSet, const fd_set *aWriteFdSet)
+{
+    // This function performs processing by DNS-SD (if needed).
+
+    OT_UNUSED_VARIABLE(aInstance);
+    OT_UNUSED_VARIABLE(aReadFdSet);
+    OT_UNUSED_VARIABLE(aWriteFdSet);
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+// otPlatTrel
+
+void otPlatTrelEnable(otInstance *aInstance, uint16_t *aUdpPort)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    VerifyOrExit(!IsSystemDryRun());
+
+    assert(sInitialized);
+
+    VerifyOrExit(!sEnabled);
+
+    PrepareSocket(*aUdpPort);
+    trelDnssdStartBrowse();
+
+    sEnabled = true;
+
+exit:
+    return;
+}
+
+void otPlatTrelDisable(otInstance *aInstance)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    VerifyOrExit(!IsSystemDryRun());
+
+    assert(sInitialized);
+    VerifyOrExit(sEnabled);
+
+    close(sSocket);
+    sSocket = -1;
+    trelDnssdStopBrowse();
+    trelDnssdRemoveService();
+    sEnabled = false;
+
+exit:
+    return;
+}
+
+void otPlatTrelSend(otInstance *      aInstance,
+                    const uint8_t *   aUdpPayload,
+                    uint16_t          aUdpPayloadLen,
+                    const otSockAddr *aDestSockAddr)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    VerifyOrExit(!IsSystemDryRun());
+
+    VerifyOrExit(sEnabled);
+
+    assert(aUdpPayloadLen <= TREL_MAX_PACKET_SIZE);
+
+    // We try to send the packet immediately. If it fails (e.g.,
+    // network is down) `SendPacket()` returns `OT_ERROR_ABORT`. If
+    // the send operation would block (e.g., socket is not yet ready
+    // or is out of buffer) we get `OT_ERROR_INVALID_STATE`. In that
+    // case we enqueue the packet to send it later when socket becomes
+    // ready.
+
+    if ((sTxPacketQueueTail != NULL) ||
+        (SendPacket(aUdpPayload, aUdpPayloadLen, aDestSockAddr) == OT_ERROR_INVALID_STATE))
+    {
+        EnqueuePacket(aUdpPayload, aUdpPayloadLen, aDestSockAddr);
+    }
+
+exit:
+    return;
+}
+
+void otPlatTrelRegisterService(otInstance *aInstance, uint16_t aPort, const uint8_t *aTxtData, uint8_t aTxtLength)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+    VerifyOrExit(!IsSystemDryRun());
+
+    trelDnssdRegisterService(aPort, aTxtData, aTxtLength);
+
+exit:
+    return;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+// platformTrel system
+
+void platformTrelInit(const char *aTrelUrl)
+{
+    otLogDebgPlat("[trel] platformTrelInit(aTrelUrl:\"%s\")", aTrelUrl != nullptr ? aTrelUrl : "");
+
+    assert(!sInitialized);
+
+    if (aTrelUrl != nullptr)
+    {
+        ot::Posix::RadioUrl url(aTrelUrl);
+        strncpy(sInterfaceName, url.GetPath(), sizeof(sInterfaceName) - 1);
+        sInterfaceName[sizeof(sInterfaceName) - 1] = '\0';
+    }
+
+    trelDnssdInitialize(sInterfaceName);
+
+    InitPacketQueue();
+    sInitialized = true;
+}
+
+void platformTrelDeinit(void)
+{
+    VerifyOrExit(sInitialized);
+
+    otPlatTrelDisable(nullptr);
+    sInterfaceName[0] = '\0';
+    sInitialized      = false;
+    otLogDebgPlat("[trel] platformTrelDeinit()");
+
+exit:
+    return;
+}
+
+void platformTrelUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd, struct timeval *aTimeout)
+{
+    assert((aReadFdSet != NULL) && (aWriteFdSet != NULL) && (aMaxFd != NULL) && (aTimeout != NULL));
+
+    VerifyOrExit(sEnabled);
+
+    FD_SET(sSocket, aReadFdSet);
+
+    if (sTxPacketQueueTail != NULL)
+    {
+        FD_SET(sSocket, aWriteFdSet);
+    }
+
+    if (*aMaxFd < sSocket)
+    {
+        *aMaxFd = sSocket;
+    }
+
+    trelDnssdUpdateFdSet(aReadFdSet, aWriteFdSet, aMaxFd, aTimeout);
+
+exit:
+    return;
+}
+
+void platformTrelProcess(otInstance *aInstance, const fd_set *aReadFdSet, const fd_set *aWriteFdSet)
+{
+    VerifyOrExit(sEnabled);
+
+    if (FD_ISSET(sSocket, aWriteFdSet))
+    {
+        SendQueuedPackets();
+    }
+
+    if (FD_ISSET(sSocket, aReadFdSet))
+    {
+        ReceivePacket(sSocket, aInstance);
+    }
+
+    trelDnssdProcess(aInstance, aReadFdSet, aWriteFdSet);
+
+exit:
+    return;
+}
+
+#endif // #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
diff --git a/src/posix/platform/trel_udp6.cpp b/src/posix/platform/trel_udp6.cpp
deleted file mode 100644
index babf524..0000000
--- a/src/posix/platform/trel_udp6.cpp
+++ /dev/null
@@ -1,934 +0,0 @@
-/*
- *  Copyright (c) 2019, The OpenThread Authors.
- *  All rights reserved.
- *
- *  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, 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
- *   This file implements platform for TREL using IPv6/UDP socket under POSIX.
- */
-
-#include "openthread-posix-config.h"
-
-#include "platform-posix.h"
-
-#if OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET && !defined(__linux__)
-#error "netlink socket use is only supported on linux platform"
-#endif
-
-#include <arpa/inet.h>
-#include <assert.h>
-#include <fcntl.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#if OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
-#include <linux/if_tun.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#endif
-
-#include <openthread/platform/trel-udp6.h>
-
-#include "common/code_utils.hpp"
-#include "common/logging.hpp"
-#include "posix/platform/radio_url.hpp"
-
-#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
-
-#define TREL_MAX_PACKET_SIZE 1400
-#define TREL_PACKET_POOL_SIZE 5
-
-#define USEC_PER_MSEC 1000u
-#define TREL_SOCKET_BIND_MAX_WAIT_TIME_MSEC 4000u
-
-#define TREL_UNICAST_ADDRESS_PREFIX_LEN 64
-#define TREL_UNICAST_ADDRESS_SCOPE 2 // The unicast address is link-local
-
-typedef struct TxPacket
-{
-    struct TxPacket *mNext;
-    uint8_t          mBuffer[TREL_MAX_PACKET_SIZE];
-    uint16_t         mLength;
-    otIp6Address     mDestAddress;
-} TxPacket;
-
-static uint8_t      sRxPacketBuffer[TREL_MAX_PACKET_SIZE];
-static uint16_t     sRxPacketLength;
-static TxPacket     sTxPacketPool[TREL_PACKET_POOL_SIZE];
-static TxPacket *   sFreeTxPacketHead;  // A singly linked list of free/available `TxPacket` from pool.
-static TxPacket *   sTxPacketQueueTail; // A circular linked list for queued tx packets.
-static char         sInterfaceName[IFNAMSIZ + 1];
-static bool         sInitialized     = false;
-static bool         sEnabled         = false;
-static int          sInterfaceIndex  = -1;
-static int          sMulticastSocket = -1;
-static int          sSocket          = -1;
-static uint16_t     sUdpPort         = 0;
-static otIp6Address sInterfaceAddress;
-
-#if OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
-constexpr static uint64_t kAddInterfaceAddressTimeoutSecs = 10;
-
-static int sNetlinkSocket                = -1;
-uint64_t   sAddInterfaceAddressRetryTime = 0;
-#endif
-
-#if OPENTHREAD_CONFIG_LOG_PLATFORM
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_CRIT)
-static const char *Ip6AddrToString(const void *aAddress)
-{
-    static char string[INET6_ADDRSTRLEN];
-    return inet_ntop(AF_INET6, aAddress, string, sizeof(string));
-}
-#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_CRIT)
-
-#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_DEBG)
-static const char *BufferToString(const uint8_t *aBuffer, uint16_t aLength)
-{
-    const uint16_t kMaxWrite = 16;
-    static char    string[1600];
-
-    uint16_t num = 0;
-    char *   cur = &string[0];
-    char *   end = &string[sizeof(string) - 1];
-
-    cur += snprintf(cur, (uint16_t)(end - cur), "[(len:%d) ", aLength);
-    VerifyOrExit(cur < end);
-
-    while (aLength-- && (num < kMaxWrite))
-    {
-        cur += snprintf(cur, (uint16_t)(end - cur), "%02x ", *aBuffer++);
-        VerifyOrExit(cur < end);
-
-        num++;
-    }
-
-    if (aLength != 0)
-    {
-        cur += snprintf(cur, (uint16_t)(end - cur), "... ");
-        VerifyOrExit(cur < end);
-    }
-
-    *cur++ = ']';
-    VerifyOrExit(cur < end);
-
-    *cur++ = '\0';
-
-exit:
-    *end = '\0';
-    return string;
-}
-#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_DEBG)
-#endif // OPENTHREAD_CONFIG_LOG_PLATFORM
-
-#if OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
-
-static void UpdateUnicastAddress(const otIp6Address *aUnicastAddress, bool aToAdd)
-{
-    int            ret;
-    struct rtattr *rta;
-
-    struct
-    {
-        struct nlmsghdr  nh;
-        struct ifaddrmsg ifa;
-        char             buf[64];
-    } request;
-
-    memset(&request, 0, sizeof(request));
-
-    request.nh.nlmsg_len   = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
-    request.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
-    request.nh.nlmsg_type  = aToAdd ? RTM_NEWADDR : RTM_DELADDR;
-    request.nh.nlmsg_pid   = 0;
-    request.nh.nlmsg_seq   = 0;
-
-    request.ifa.ifa_family    = AF_INET6;
-    request.ifa.ifa_prefixlen = TREL_UNICAST_ADDRESS_PREFIX_LEN;
-    request.ifa.ifa_flags     = IFA_F_NODAD;
-    request.ifa.ifa_scope     = TREL_UNICAST_ADDRESS_SCOPE;
-    request.ifa.ifa_index     = (unsigned int)(sInterfaceIndex);
-
-    rta = reinterpret_cast<struct rtattr *>((reinterpret_cast<char *>(&request)) + NLMSG_ALIGN(request.nh.nlmsg_len));
-    rta->rta_type = IFA_LOCAL;
-    rta->rta_len  = RTA_LENGTH(sizeof(otIp6Address));
-
-    memcpy(RTA_DATA(rta), aUnicastAddress, sizeof(otIp6Address));
-
-    request.nh.nlmsg_len = NLMSG_ALIGN(request.nh.nlmsg_len) + rta->rta_len;
-
-    ret = send(sNetlinkSocket, &request, request.nh.nlmsg_len, 0);
-    VerifyOrDie(ret != -1, OT_EXIT_ERROR_ERRNO);
-}
-
-static void AddUnicastAddress(const otIp6Address *aUnicastAddress)
-{
-    otLogDebgPlat("[trel] AddUnicastAddress(%s)", Ip6AddrToString(aUnicastAddress));
-    UpdateUnicastAddress(aUnicastAddress, /* aToAdd */ true);
-    sAddInterfaceAddressRetryTime = otPlatTimeGet() + kAddInterfaceAddressTimeoutSecs * US_PER_S;
-}
-
-static void RemoveUnicastAddress(const otIp6Address *aUnicastAddress)
-{
-    otLogDebgPlat("[trel] RemoveUnicastAddress(%s)", Ip6AddrToString(aUnicastAddress));
-    UpdateUnicastAddress(aUnicastAddress, /* aToAdd */ false);
-}
-
-static void HandleAddInterfaceAddressTimeout(void)
-{
-    otLogWarnPlat("[trel] Failed to add TREL interface address after %d seconds. Trying to add again.",
-                  kAddInterfaceAddressTimeoutSecs);
-    RemoveUnicastAddress(&sInterfaceAddress);
-    AddUnicastAddress(&sInterfaceAddress);
-    sAddInterfaceAddressRetryTime = otPlatTimeGet() + kAddInterfaceAddressTimeoutSecs * US_PER_S;
-}
-
-static void ProcessNetifAddrEvent(struct nlmsghdr *aNetlinkMessage)
-{
-    struct ifaddrmsg *ifaddr = reinterpret_cast<struct ifaddrmsg *>(NLMSG_DATA(aNetlinkMessage));
-    size_t            rtaLength;
-
-    VerifyOrExit(ifaddr->ifa_index == static_cast<unsigned int>(sInterfaceIndex) && ifaddr->ifa_family == AF_INET6);
-
-    rtaLength = IFA_PAYLOAD(aNetlinkMessage);
-
-    for (struct rtattr *rta = reinterpret_cast<struct rtattr *>(IFA_RTA(ifaddr)); RTA_OK(rta, rtaLength);
-         rta                = RTA_NEXT(rta, rtaLength))
-    {
-        if (rta->rta_type != IFA_ADDRESS)
-        {
-            continue;
-        }
-
-        if (memcmp(&sInterfaceAddress, RTA_DATA(rta), sizeof(sInterfaceAddress)) != 0)
-        {
-            continue;
-        }
-
-        if (aNetlinkMessage->nlmsg_type == RTM_NEWADDR)
-        {
-            otLogInfoPlat("[trel] Interface address added successfully.");
-            sAddInterfaceAddressRetryTime = 0;
-        }
-        else if (aNetlinkMessage->nlmsg_type == RTM_DELADDR)
-        {
-            if (sAddInterfaceAddressRetryTime == 0)
-            {
-                otLogWarnPlat("[trel] Interface address removed unexpectedly.");
-                sAddInterfaceAddressRetryTime = otPlatTimeGet() + kAddInterfaceAddressTimeoutSecs * US_PER_S;
-            }
-        }
-    }
-
-exit:
-    return;
-}
-
-static void ReceiveNetlinkMessage(void)
-{
-    const size_t kMaxNetLinkBufSize = 8192;
-    ssize_t      len;
-    union
-    {
-        nlmsghdr mHeader;
-        uint8_t  mBuffer[kMaxNetLinkBufSize];
-    } msgBuffer;
-
-    len = recv(sNetlinkSocket, msgBuffer.mBuffer, sizeof(msgBuffer.mBuffer), 0);
-    if (len < 0)
-    {
-        otLogCritPlat("failed to receive netlink message: %s", strerror(errno));
-        ExitNow();
-    }
-
-    for (struct nlmsghdr *header = &msgBuffer.mHeader; NLMSG_OK(header, static_cast<size_t>(len));
-         header                  = NLMSG_NEXT(header, len))
-    {
-        switch (header->nlmsg_type)
-        {
-        case RTM_NEWADDR:
-        case RTM_DELADDR:
-            ProcessNetifAddrEvent(header);
-            break;
-        case NLMSG_ERROR:
-        {
-            struct nlmsgerr *errMsg = reinterpret_cast<struct nlmsgerr *>(NLMSG_DATA(header));
-
-            if (errMsg->error != 0)
-            {
-                otLogWarnPlat("netlink NLMSG_ERROR response: seq=%u, error=%d", header->nlmsg_seq, errMsg->error);
-            }
-        }
-        default:
-            break;
-        }
-    }
-
-exit:
-    return;
-}
-
-#else // OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
-
-static void AddUnicastAddress(const otIp6Address *aUnicastAddress)
-{
-    int mgmtFd;
-    int ret;
-    struct in6_ifreq
-    {
-        struct in6_addr ifr6_addr;
-        uint32_t        ifr6_prefixlen;
-        int             ifr6_ifindex;
-    } ifr6;
-
-    otLogDebgPlat("[trel] AddUnicastAddress(%s)", Ip6AddrToString(aUnicastAddress));
-
-    mgmtFd = SocketWithCloseExec(AF_INET6, SOCK_DGRAM, IPPROTO_IP, kSocketNonBlock);
-    VerifyOrDie(mgmtFd >= 0, OT_EXIT_ERROR_ERRNO);
-
-    memcpy(&ifr6.ifr6_addr, aUnicastAddress, sizeof(otIp6Address));
-    ifr6.ifr6_prefixlen = 64;
-    ifr6.ifr6_ifindex   = sInterfaceIndex;
-
-    ret = ioctl(mgmtFd, SIOCSIFADDR, &ifr6);
-
-    if (!(ret == 0 || errno == EALREADY || errno == EEXIST))
-    {
-        otLogCritPlat("[trel] Failed to add unicast address %s on TREL netif \"%s\"", Ip6AddrToString(aUnicastAddress),
-                      sInterfaceName);
-        DieNow(OT_EXIT_ERROR_ERRNO);
-    }
-
-    close(mgmtFd);
-}
-
-static void RemoveUnicastAddress(const otIp6Address *aUnicastAddress)
-{
-    int mgmtFd;
-    int ret;
-    struct in6_ifreq
-    {
-        struct in6_addr ifr6_addr;
-        uint32_t        ifr6_prefixlen;
-        int             ifr6_ifindex;
-    } ifr6;
-
-    otLogDebgPlat("[trel] RemoveUnicastAddress(%s)", Ip6AddrToString(aUnicastAddress));
-
-    mgmtFd = SocketWithCloseExec(AF_INET6, SOCK_DGRAM, IPPROTO_IP, kSocketNonBlock);
-    VerifyOrDie(mgmtFd >= 0, OT_EXIT_ERROR_ERRNO);
-
-    memcpy(&ifr6.ifr6_addr, aUnicastAddress, sizeof(otIp6Address));
-    ifr6.ifr6_prefixlen = 64;
-    ifr6.ifr6_ifindex   = sInterfaceIndex;
-
-    ret = ioctl(mgmtFd, SIOCDIFADDR, &ifr6);
-
-    VerifyOrDie(ret == 0, OT_EXIT_ERROR_ERRNO);
-
-    close(mgmtFd);
-}
-
-#endif // OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
-
-static void PrepareSocket(void)
-{
-    int                 val;
-    struct sockaddr_in6 sockAddr;
-    uint64_t            startTime;
-    bool                isSocketBound = false;
-
-    otLogDebgPlat("[trel] PrepareSocket()");
-
-    sSocket = SocketWithCloseExec(AF_INET6, SOCK_DGRAM, 0, kSocketNonBlock);
-    VerifyOrDie(sSocket >= 0, OT_EXIT_ERROR_ERRNO);
-
-    // Set the multicast interface index (for tx), disable loop back
-    // of multicast tx and set the multicast hop limit to 1 to reach
-    // a single sub-net.
-
-    val = sInterfaceIndex;
-    VerifyOrDie(setsockopt(sSocket, IPPROTO_IPV6, IPV6_MULTICAST_IF, &val, sizeof(val)) == 0, OT_EXIT_ERROR_ERRNO);
-
-    val = 0;
-    VerifyOrDie(setsockopt(sSocket, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &val, sizeof(val)) == 0, OT_EXIT_ERROR_ERRNO);
-
-    val = 1;
-    VerifyOrDie(setsockopt(sSocket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) == 0, OT_EXIT_ERROR_ERRNO);
-    VerifyOrDie(setsockopt(sSocket, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)) == 0, OT_EXIT_ERROR_ERRNO);
-
-    val = 1;
-    VerifyOrDie(setsockopt(sSocket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val, sizeof(val)) == 0, OT_EXIT_ERROR_ERRNO);
-
-    // Make the socket non-blocking to allow immediate tx attempt.
-    val = fcntl(sSocket, F_GETFL, 0);
-    VerifyOrDie(val != -1, OT_EXIT_ERROR_ERRNO);
-    val = val | O_NONBLOCK;
-    VerifyOrDie(fcntl(sSocket, F_SETFL, val) == 0, OT_EXIT_ERROR_ERRNO);
-
-    // Bind the socket. The address to which we want to bind the
-    // socket, is itself added earlier above. The address therefore
-    // may not be immediately available/ready on the interface and the
-    // socket `bind()` call may fail with `EADDRNOTAVAIL` error. In
-    // such a case, we keep trying up to a maximum wait time.
-
-    memset(&sockAddr, 0, sizeof(sockAddr));
-    sockAddr.sin6_family = AF_INET6;
-    sockAddr.sin6_port   = htons(sUdpPort);
-    memcpy(&sockAddr.sin6_addr, &sInterfaceAddress, sizeof(otIp6Address));
-    sockAddr.sin6_scope_id = (uint32_t)sInterfaceIndex;
-
-    startTime = otPlatTimeGet();
-
-    while (otPlatTimeGet() - startTime < TREL_SOCKET_BIND_MAX_WAIT_TIME_MSEC * USEC_PER_MSEC)
-    {
-        if (bind(sSocket, (struct sockaddr *)&sockAddr, sizeof(sockAddr)) != -1)
-        {
-            isSocketBound = true;
-            break;
-        }
-
-        if (errno == EADDRNOTAVAIL)
-        {
-            continue;
-        }
-
-        otLogCritPlat("[trel] Failed to bind socket to %s (port %d) on TREL netif \"%s\"",
-                      Ip6AddrToString(&sInterfaceAddress), sUdpPort, sInterfaceName);
-        DieNow(OT_EXIT_ERROR_ERRNO);
-    }
-
-    if (!isSocketBound)
-    {
-        otLogCritPlat("[trel] Timed out waiting for address %s to become available for binding on TREL "
-                      "netif \"%s\" - timeout %lu (ms)",
-                      Ip6AddrToString(&sInterfaceAddress), sInterfaceName, TREL_SOCKET_BIND_MAX_WAIT_TIME_MSEC);
-        DieNow(OT_EXIT_ERROR_ERRNO);
-    }
-}
-
-static otError SendPacket(const uint8_t *aBuffer, uint16_t aLength, const otIp6Address *aDestAddress)
-{
-    otError             error = OT_ERROR_NONE;
-    struct sockaddr_in6 sockAddr;
-    ssize_t             ret;
-
-    VerifyOrExit(sSocket >= 0, error = OT_ERROR_INVALID_STATE);
-
-    memset(&sockAddr, 0, sizeof(sockAddr));
-    sockAddr.sin6_family = AF_INET6;
-    sockAddr.sin6_port   = htons(sUdpPort);
-    memcpy(&sockAddr.sin6_addr, aDestAddress, sizeof(otIp6Address));
-
-    ret = sendto(sSocket, aBuffer, aLength, 0, (struct sockaddr *)&sockAddr, sizeof(sockAddr));
-
-    if (ret != aLength)
-    {
-        otLogDebgPlat("[trel] SendPacket() -- sendto() failed errno %d", errno);
-
-        switch (errno)
-        {
-        case ENETUNREACH:
-        case ENETDOWN:
-        case EHOSTUNREACH:
-            error = OT_ERROR_ABORT;
-            break;
-
-        default:
-            error = OT_ERROR_INVALID_STATE;
-        }
-    }
-
-exit:
-    otLogDebgPlat("[trel] SendPacket(%s) err:%s pkt:%s", Ip6AddrToString(aDestAddress), otThreadErrorToString(error),
-                  BufferToString(aBuffer, aLength));
-
-    return error;
-}
-
-static void ReceivePacket(int aSocket, otInstance *aInstance)
-{
-    struct sockaddr_in6 sockAddr;
-    socklen_t           sockAddrLen = sizeof(sockAddr);
-    ssize_t             ret;
-
-    memset(&sockAddr, 0, sizeof(sockAddr));
-
-    ret = recvfrom(aSocket, (char *)sRxPacketBuffer, sizeof(sRxPacketBuffer), 0, (struct sockaddr *)&sockAddr,
-                   &sockAddrLen);
-    VerifyOrDie(ret >= 0, OT_EXIT_ERROR_ERRNO);
-
-    sRxPacketLength = (uint16_t)(ret);
-
-    if (sRxPacketLength > sizeof(sRxPacketBuffer))
-    {
-        sRxPacketLength = sizeof(sRxPacketLength);
-    }
-
-    otLogDebgPlat("[trel] ReceivePacket() - received from %s port:%d, id:%d, pkt:%s",
-                  Ip6AddrToString(&sockAddr.sin6_addr), ntohs(sockAddr.sin6_port), sockAddr.sin6_scope_id,
-                  BufferToString(sRxPacketBuffer, sRxPacketLength));
-
-    if (sEnabled)
-    {
-        otPlatTrelUdp6HandleReceived(aInstance, sRxPacketBuffer, sRxPacketLength);
-    }
-}
-
-static void InitPacketQueue(void)
-{
-    sTxPacketQueueTail = NULL;
-
-    // Chain all the packets in pool in the free linked list.
-    sFreeTxPacketHead = NULL;
-
-    for (uint16_t index = 0; index < OT_ARRAY_LENGTH(sTxPacketPool); index++)
-    {
-        TxPacket *packet = &sTxPacketPool[index];
-
-        packet->mNext     = sFreeTxPacketHead;
-        sFreeTxPacketHead = packet;
-    }
-}
-
-static void SendQueuedPackets(void)
-{
-    while (sTxPacketQueueTail != NULL)
-    {
-        TxPacket *packet = sTxPacketQueueTail->mNext; // tail->mNext is the head of the list.
-
-        if (SendPacket(packet->mBuffer, packet->mLength, &packet->mDestAddress) == OT_ERROR_INVALID_STATE)
-        {
-            otLogDebgPlat("[trel] SendQueuedPackets() - SendPacket() would block");
-            break;
-        }
-
-        // Remove the `packet` from the packet queue (circular
-        // linked list).
-
-        if (packet == sTxPacketQueueTail)
-        {
-            sTxPacketQueueTail = NULL;
-        }
-        else
-        {
-            sTxPacketQueueTail->mNext = packet->mNext;
-        }
-
-        // Add the `packet` to the free packet singly linked list.
-
-        packet->mNext     = sFreeTxPacketHead;
-        sFreeTxPacketHead = packet;
-    }
-}
-
-static otError EnqueuePacket(const uint8_t *aBuffer, uint16_t aLength, const otIp6Address *aDestAddress)
-{
-    otError   error = OT_ERROR_NONE;
-    TxPacket *packet;
-
-    // Allocate an available packet entry (from the free packet list)
-    // and copy the packet content into it.
-
-    VerifyOrExit(sFreeTxPacketHead != NULL, error = OT_ERROR_NO_BUFS);
-    packet            = sFreeTxPacketHead;
-    sFreeTxPacketHead = sFreeTxPacketHead->mNext;
-
-    memcpy(packet->mBuffer, aBuffer, aLength);
-    packet->mLength      = aLength;
-    packet->mDestAddress = *aDestAddress;
-
-    // Add packet to the tail of TxPacketQueue circular linked-list.
-
-    if (sTxPacketQueueTail == NULL)
-    {
-        packet->mNext      = packet;
-        sTxPacketQueueTail = packet;
-    }
-    else
-    {
-        packet->mNext             = sTxPacketQueueTail->mNext;
-        sTxPacketQueueTail->mNext = packet;
-        sTxPacketQueueTail        = packet;
-    }
-
-    otLogDebgPlat("[trel] EnqueuePacket(%s) - %s", Ip6AddrToString(aDestAddress), BufferToString(aBuffer, aLength));
-
-exit:
-    return error;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-// otPlatTrelUdp6
-
-void otPlatTrelUdp6Init(otInstance *aInstance, const otIp6Address *aUnicastAddress, uint16_t aUdpPort)
-{
-    OT_UNUSED_VARIABLE(aInstance);
-
-    int                 val;
-    struct sockaddr_in6 sockAddr;
-
-    VerifyOrExit(sEnabled);
-
-    otLogDebgPlat("[trel] otPlatTrelUdp6Init(%s, port:%d)", Ip6AddrToString(aUnicastAddress), aUdpPort);
-
-    sUdpPort          = aUdpPort;
-    sInterfaceAddress = *aUnicastAddress;
-    sInterfaceIndex   = (int)if_nametoindex(sInterfaceName);
-
-    if (sInterfaceIndex <= 0)
-    {
-        otLogCritPlat("[trel] Failed to find index of TREL netif \"%s\"", sInterfaceName);
-        DieNow(OT_EXIT_ERROR_ERRNO);
-    }
-
-#if OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
-    {
-        struct sockaddr_nl addr;
-
-        sNetlinkSocket = SocketWithCloseExec(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE, kSocketNonBlock);
-        VerifyOrDie(sNetlinkSocket >= 0, OT_EXIT_ERROR_ERRNO);
-
-        memset(&addr, 0, sizeof(addr));
-        addr.nl_family = AF_NETLINK;
-        addr.nl_groups = RTMGRP_IPV6_IFADDR;
-
-        VerifyOrDie(bind(sNetlinkSocket, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)) == 0,
-                    OT_EXIT_ERROR_ERRNO);
-    }
-#endif
-
-    RemoveUnicastAddress(aUnicastAddress);
-    AddUnicastAddress(aUnicastAddress);
-
-    sMulticastSocket = socket(AF_INET6, SOCK_DGRAM, 0);
-    VerifyOrDie(sMulticastSocket >= 0, OT_EXIT_ERROR_ERRNO);
-
-    val = 1;
-    VerifyOrDie(setsockopt(sMulticastSocket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) == 0, OT_EXIT_ERROR_ERRNO);
-    VerifyOrDie(setsockopt(sMulticastSocket, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)) == 0, OT_EXIT_ERROR_ERRNO);
-
-    // To receive from multicast addresses, the socket need to be
-    // bound to `in6addr_any` address.
-    memset(&sockAddr, 0, sizeof(sockAddr));
-    sockAddr.sin6_family   = AF_INET6;
-    sockAddr.sin6_port     = htons(sUdpPort);
-    sockAddr.sin6_addr     = in6addr_any;
-    sockAddr.sin6_scope_id = (uint32_t)sInterfaceIndex;
-
-    if (bind(sMulticastSocket, (struct sockaddr *)&sockAddr, sizeof(sockAddr)) == -1)
-    {
-        otLogCritPlat("[trel] Failed to bind multicast socket to any address on TREL netif \"%s\"", sInterfaceName);
-        DieNow(OT_EXIT_ERROR_ERRNO);
-    }
-
-    PrepareSocket();
-
-exit:
-    return;
-}
-
-void otPlatTrelUdp6UpdateAddress(otInstance *aInstance, const otIp6Address *aUnicastAddress)
-{
-    OT_UNUSED_VARIABLE(aInstance);
-
-    VerifyOrExit(sEnabled);
-
-    assert(sSocket >= 0);
-
-    otLogDebgPlat("[trel] otPlatTrelUdp6UpdateAddress(%s)", Ip6AddrToString(aUnicastAddress));
-
-    VerifyOrExit(memcmp(aUnicastAddress, &sInterfaceAddress, sizeof(otIp6Address)) != 0);
-
-    close(sSocket);
-    RemoveUnicastAddress(&sInterfaceAddress);
-
-    sInterfaceAddress = *aUnicastAddress;
-    AddUnicastAddress(aUnicastAddress);
-
-    PrepareSocket();
-
-exit:
-    return;
-}
-
-void otPlatTrelUdp6SubscribeMulticastAddress(otInstance *aInstance, const otIp6Address *aMulticastAddress)
-{
-    OT_UNUSED_VARIABLE(aInstance);
-
-    struct ipv6_mreq mr;
-
-    VerifyOrExit(sEnabled);
-
-    assert(sMulticastSocket != -1);
-
-    memcpy(&mr.ipv6mr_multiaddr, aMulticastAddress, sizeof(otIp6Address));
-    mr.ipv6mr_interface = (unsigned int)sInterfaceIndex;
-    VerifyOrDie(setsockopt(sMulticastSocket, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mr, sizeof(mr)) == 0, OT_EXIT_ERROR_ERRNO);
-
-    otLogDebgPlat("[trel] otPlatTrelUdp6SubscribeMulticastAddress(%s)", Ip6AddrToString(aMulticastAddress));
-
-exit:
-    return;
-}
-
-otError otPlatTrelUdp6SendTo(otInstance *        aInstance,
-                             const uint8_t *     aBuffer,
-                             uint16_t            aLength,
-                             const otIp6Address *aDestAddress)
-{
-    OT_UNUSED_VARIABLE(aInstance);
-
-    otError error = OT_ERROR_NONE;
-
-    VerifyOrExit(sEnabled);
-
-    assert(aLength <= TREL_MAX_PACKET_SIZE);
-
-    otLogDebgPlat("[trel] otPlatTrelUdp6SendTo(%s) %s", Ip6AddrToString(aDestAddress),
-                  BufferToString(aBuffer, aLength));
-
-    // We try to send the packet immediately. If it fails (e.g.,
-    // network is down) `SendPacket()` returns `OT_ERROR_ABORT`. If
-    // the send operation would block (e.g., socket is not yet ready
-    // or is out of buffer) we get `OT_ERROR_INVALID_STATE`. In that
-    // case we enqueue the packet to send it later when socket becomes
-    // ready.
-
-    error = SendPacket(aBuffer, aLength, aDestAddress);
-
-    if (error == OT_ERROR_INVALID_STATE)
-    {
-        error = EnqueuePacket(aBuffer, aLength, aDestAddress);
-
-        if (error != OT_ERROR_NONE)
-        {
-            error = OT_ERROR_ABORT;
-        }
-    }
-
-exit:
-    return error;
-}
-
-otError otPlatTrelUdp6SetTestMode(otInstance *aInstance, bool aEnable)
-{
-    OT_UNUSED_VARIABLE(aInstance);
-
-    otError error = OT_ERROR_NONE;
-
-    VerifyOrExit(aEnable != sEnabled);
-
-    if (aEnable)
-    {
-        VerifyOrExit(sInitialized, error = OT_ERROR_FAILED);
-    }
-
-    sEnabled = aEnable;
-
-    if (!sEnabled)
-    {
-        InitPacketQueue();
-    }
-
-exit:
-    return error;
-}
-
-//---------------------------------------------------------------------------------------------------------------------
-// platformTrel system
-
-void platformTrelInit(const char *aTrelUrl)
-{
-    assert(!sInitialized);
-
-    if (aTrelUrl != NULL)
-    {
-        ot::Posix::RadioUrl url(aTrelUrl);
-
-        strncpy(sInterfaceName, url.GetPath(), sizeof(sInterfaceName) - 1);
-    }
-    else
-    {
-        strncpy(sInterfaceName, OPENTHREAD_CONFIG_POSIX_APP_TREL_INTERFACE_NAME, sizeof(sInterfaceName) - 1);
-    }
-
-    sInterfaceName[sizeof(sInterfaceName) - 1] = 0;
-    otLogDebgPlat("[trel] platformTrelInit(InterfaceName:\"%s\")", sInterfaceName);
-
-    InitPacketQueue();
-
-    // Disable trel platform when interface name is empty.
-    sInitialized = (sInterfaceName[0] != '\0');
-    sEnabled     = sInitialized;
-}
-
-void platformTrelDeinit(void)
-{
-    VerifyOrExit(sInitialized);
-
-    if (sSocket != -1)
-    {
-        close(sSocket);
-    }
-
-    if (sMulticastSocket != -1)
-    {
-        close(sMulticastSocket);
-    }
-
-    if (!otIp6IsAddressUnspecified(&sInterfaceAddress))
-    {
-        RemoveUnicastAddress(&sInterfaceAddress);
-    }
-
-#if OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
-    if (sNetlinkSocket != -1)
-    {
-        close(sNetlinkSocket);
-        sNetlinkSocket = -1;
-    }
-#endif
-
-    sInitialized = false;
-    sEnabled     = false;
-
-    otLogDebgPlat("[trel] platformTrelDeinit()");
-exit:
-    return;
-}
-
-void platformTrelUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd, struct timeval *aTimeout)
-{
-    assert((aReadFdSet != NULL) && (aWriteFdSet != NULL) && (aMaxFd != NULL) && (aTimeout != NULL));
-    VerifyOrExit((sSocket >= 0) && (sMulticastSocket >= 0));
-#if OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
-    VerifyOrExit(sNetlinkSocket >= 0);
-#endif
-
-    FD_SET(sMulticastSocket, aReadFdSet);
-    FD_SET(sSocket, aReadFdSet);
-#if OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
-    FD_SET(sNetlinkSocket, aReadFdSet);
-#endif
-
-    if (sTxPacketQueueTail != NULL)
-    {
-        FD_SET(sSocket, aWriteFdSet);
-    }
-
-    if (*aMaxFd < sMulticastSocket)
-    {
-        *aMaxFd = sMulticastSocket;
-    }
-
-    if (*aMaxFd < sSocket)
-    {
-        *aMaxFd = sSocket;
-    }
-
-#if OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
-    if (*aMaxFd < sNetlinkSocket)
-    {
-        *aMaxFd = sNetlinkSocket;
-    }
-
-    if (sAddInterfaceAddressRetryTime > 0)
-    {
-        uint64_t now = otPlatTimeGet();
-
-        if (sAddInterfaceAddressRetryTime > now)
-        {
-            uint64_t remain = sAddInterfaceAddressRetryTime - now;
-
-            if (remain <
-                (static_cast<uint64_t>(aTimeout->tv_sec) * US_PER_S + static_cast<uint64_t>(aTimeout->tv_usec)))
-            {
-                aTimeout->tv_sec  = static_cast<time_t>(remain / US_PER_S);
-                aTimeout->tv_usec = static_cast<suseconds_t>(remain % US_PER_S);
-            }
-        }
-        else
-        {
-            aTimeout->tv_sec  = 0;
-            aTimeout->tv_usec = 0;
-        }
-    }
-#endif
-
-exit:
-    return;
-}
-
-void platformTrelProcess(otInstance *aInstance, const fd_set *aReadFdSet, const fd_set *aWriteFdSet)
-{
-    VerifyOrExit((sSocket >= 0) && (sMulticastSocket >= 0));
-#if OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
-    VerifyOrExit(sNetlinkSocket >= 0);
-#endif
-
-    if (FD_ISSET(sSocket, aWriteFdSet))
-    {
-        SendQueuedPackets();
-    }
-
-    if (FD_ISSET(sSocket, aReadFdSet))
-    {
-        ReceivePacket(sSocket, aInstance);
-    }
-
-    if (FD_ISSET(sMulticastSocket, aReadFdSet))
-    {
-        ReceivePacket(sMulticastSocket, aInstance);
-    }
-
-#if OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
-    if (FD_ISSET(sNetlinkSocket, aReadFdSet))
-    {
-        ReceiveNetlinkMessage();
-    }
-
-    if (sAddInterfaceAddressRetryTime > 0)
-    {
-        uint64_t now = otPlatTimeGet();
-
-        if (sAddInterfaceAddressRetryTime <= now)
-        {
-            sAddInterfaceAddressRetryTime = 0;
-
-            HandleAddInterfaceAddressTimeout();
-        }
-    }
-#endif
-
-exit:
-    return;
-}
-
-#endif // #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
diff --git a/src/posix/platform/utils.cpp b/src/posix/platform/utils.cpp
new file mode 100644
index 0000000..e497404
--- /dev/null
+++ b/src/posix/platform/utils.cpp
@@ -0,0 +1,89 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   The file implements POSIX system utilities.
+ */
+
+#include "utils.hpp"
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openthread/logging.h>
+
+#include "common/code_utils.hpp"
+
+namespace ot {
+namespace Posix {
+
+enum
+{
+    kSystemCommandMaxLength = 1024, ///< Max length of a system call command.
+    kOutputBufferSize       = 1024, ///< Buffer size of command output.
+};
+
+otError ExecuteCommand(const char *aFormat, ...)
+{
+    char    cmd[kSystemCommandMaxLength];
+    char    buf[kOutputBufferSize];
+    va_list args;
+    FILE *  file;
+    int     exitCode;
+    otError error = OT_ERROR_NONE;
+
+    va_start(args, aFormat);
+    vsnprintf(cmd, sizeof(cmd), aFormat, args);
+    va_end(args);
+
+    file = popen(cmd, "r");
+    VerifyOrExit(file != nullptr, error = OT_ERROR_FAILED);
+    while (fgets(buf, sizeof(buf), file))
+    {
+        size_t length = strlen(buf);
+        if (buf[length] == '\n')
+        {
+            buf[length] = '\0';
+        }
+        otLogInfoPlat("%s", buf);
+    }
+    exitCode = pclose(file);
+    otLogInfoPlat("Execute command `%s` = %d", cmd, exitCode);
+    VerifyOrExit(exitCode == 0, error = OT_ERROR_FAILED);
+exit:
+    if (error != OT_ERROR_NONE && errno != 0)
+    {
+        otLogInfoPlat("Got an error when executing command `%s`: `%s`", cmd, strerror(errno));
+    }
+    return error;
+}
+
+} // namespace Posix
+} // namespace ot
diff --git a/src/core/api/entropy_api.cpp b/src/posix/platform/utils.hpp
similarity index 71%
copy from src/core/api/entropy_api.cpp
copy to src/posix/platform/utils.hpp
index 469e55d..c3f9dda 100644
--- a/src/core/api/entropy_api.cpp
+++ b/src/posix/platform/utils.hpp
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2019, The OpenThread Authors.
+ *  Copyright (c) 2021, The OpenThread Authors.
  *  All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -26,18 +26,27 @@
  *  POSSIBILITY OF SUCH DAMAGE.
  */
 
+#ifndef OT_POSIX_PLATFORM_UTILS_HPP_
+#define OT_POSIX_PLATFORM_UTILS_HPP_
+
+#include "openthread/error.h"
+
+namespace ot {
+namespace Posix {
+
 /**
- * @file
- *   This file implements the OpenThread entropy source management API.
+ * This method formats a system command to execute.
+ *
+ * @param[in] aFormat  A pointer to the format string.
+ * @param[in] ...      Arguments for the format specification.
+ *
+ * @retval OT_ERROR_NONE    The command was executed successfully.
+ * @retval OT_ERROR_FAILED  It failed to execute the command.
+ *
  */
+otError ExecuteCommand(const char *aFormat, ...);
 
-#include <openthread/entropy.h>
+} // namespace Posix
+} // namespace ot
 
-#include "common/random_manager.hpp"
-
-using namespace ot;
-
-mbedtls_entropy_context *otEntropyMbedTlsContextGet(void)
-{
-    return RandomManager::GetMbedTlsEntropyContext();
-}
+#endif // OT_POSIX_PLATFORM_UTILS_HPP_
diff --git a/src/posix/platform/vendor_interface.hpp b/src/posix/platform/vendor_interface.hpp
new file mode 100644
index 0000000..7ece234
--- /dev/null
+++ b/src/posix/platform/vendor_interface.hpp
@@ -0,0 +1,174 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file includes definitions for the vendor interface to radio (RCP).
+ */
+
+#ifndef POSIX_APP_VENDOR_INTERFACE_HPP_
+#define POSIX_APP_VENDOR_INTERFACE_HPP_
+
+#include "openthread-posix-config.h"
+
+#include <openthread/openthread-system.h>
+
+#include "platform-posix.h"
+#include "lib/spinel/spinel_interface.hpp"
+
+#if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR
+
+namespace ot {
+namespace Posix {
+
+/**
+ * This class defines a vendor interface to the Radio Co-processor (RCP).
+ *
+ */
+class VendorInterface
+{
+public:
+    /**
+     * This constructor initializes the object.
+     *
+     * @param[in] aCallback         A reference to a `Callback` object.
+     * @param[in] aCallbackContext  The context pointer passed to the callback.
+     * @param[in] aFrameBuffer      A reference to a `RxFrameBuffer` object.
+     *
+     */
+    VendorInterface(Spinel::SpinelInterface::ReceiveFrameCallback aCallback,
+                    void *                                        aCallbackContext,
+                    Spinel::SpinelInterface::RxFrameBuffer &      aFrameBuffer);
+
+    /**
+     * This destructor deinitializes the object.
+     *
+     */
+    ~VendorInterface(void);
+
+    /**
+     * This method initializes the interface to the Radio Co-processor (RCP).
+     *
+     * @note This method should be called before reading and sending spinel frames to the interface.
+     *
+     * @param[in] aRadioUrl  Arguments parsed from radio url.
+     *
+     * @retval OT_ERROR_NONE          The interface is initialized successfully.
+     * @retval OT_ERROR_ALREADY       The interface is already initialized.
+     * @retval OT_ERROR_INVALID_ARGS  The UART device or executable cannot be found or failed to open/run.
+     *
+     */
+    otError Init(const Url::Url &aRadioUrl);
+
+    /**
+     * This method deinitializes the interface to the RCP.
+     *
+     */
+    void Deinit(void);
+
+    /**
+     * This method encodes and sends a spinel frame to Radio Co-processor (RCP) over the socket.
+     *
+     * @param[in] aFrame   A pointer to buffer containing the spinel frame to send.
+     * @param[in] aLength  The length (number of bytes) in the frame.
+     *
+     * @retval OT_ERROR_NONE     Successfully encoded and sent the spinel frame.
+     * @retval OT_ERROR_BUSY     Failed due to another operation is on going.
+     * @retval OT_ERROR_NO_BUFS  Insufficient buffer space available to encode the frame.
+     * @retval OT_ERROR_FAILED   Failed to call the SPI driver to send the frame.
+     *
+     */
+    otError SendFrame(const uint8_t *aFrame, uint16_t aLength);
+
+    /**
+     * This method waits for receiving part or all of spinel frame within specified interval.
+     *
+     * @param[in] aTimeoutUs  The timeout value in microseconds.
+     *
+     * @retval OT_ERROR_NONE             Part or all of spinel frame is received.
+     * @retval OT_ERROR_RESPONSE_TIMEOUT No spinel frame is received within @p aTimeout.
+     *
+     */
+    otError WaitForFrame(uint64_t aTimeoutUs);
+
+    /**
+     * This method updates the file descriptor sets with file descriptors used by the radio driver.
+     *
+     * @param[inout] aReadFdSet   A reference to the read file descriptors.
+     * @param[inout] aWriteFdSet  A reference to the write file descriptors.
+     * @param[inout] aMaxFd       A reference to the max file descriptor.
+     * @param[inout] aTimeout     A reference to the timeout.
+     *
+     */
+    void UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, int &aMaxFd, struct timeval &aTimeout);
+
+    /**
+     * This method performs radio driver processing.
+     *
+     * @param[in] aContext  The context containing fd_sets.
+     *
+     */
+    void Process(const RadioProcessContext &aContext);
+
+    /**
+     * This method returns the bus speed between the host and the radio.
+     *
+     * @returns  Bus speed in bits/second.
+     *
+     */
+    uint32_t GetBusSpeed(void) const;
+
+    /**
+     * This method is called when RCP failure detected and resets internal states of the interface.
+     *
+     */
+    void OnRcpReset(void);
+
+    /**
+     * This method is called when RCP is reset to recreate the connection with it.
+     *
+     * @retval OT_ERROR_NONE    Reset the connection successfully.
+     * @retval OT_ERROR_FAILED  Failed to reset the connection.
+     *
+     */
+    otError ResetConnection(void);
+
+    /**
+     * This method returns the RCP interface metrics.
+     *
+     * @returns The RCP interface metrics.
+     *
+     */
+    const otRcpInterfaceMetrics *GetRcpInterfaceMetrics(void);
+};
+
+} // namespace Posix
+} // namespace ot
+
+#endif // OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR
+#endif // POSIX_APP_VENDOR_INTERFACE_HPP_
diff --git a/src/posix/platform/vendor_interface_example.cpp b/src/posix/platform/vendor_interface_example.cpp
new file mode 100644
index 0000000..12121d3
--- /dev/null
+++ b/src/posix/platform/vendor_interface_example.cpp
@@ -0,0 +1,167 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file provides an example on how to implement an OpenThread vendor interface to RCP.
+ */
+
+#include "openthread-posix-config.h"
+
+#if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR
+
+#include "vendor_interface.hpp"
+#include "common/new.hpp"
+
+namespace ot {
+namespace Posix {
+using ot::Spinel::SpinelInterface;
+
+/**
+ * This class defines the vendor implementation object.
+ *
+ */
+class VendorInterfaceImpl
+{
+public:
+    explicit VendorInterfaceImpl(SpinelInterface::ReceiveFrameCallback aCallback,
+                                 void *                                aCallbackContext,
+                                 SpinelInterface::RxFrameBuffer &      aFrameBuffer)
+        : mReceiveFrameCallback(aCallback)
+        , mReceiveFrameContext(aCallbackContext)
+        , mRxFrameBuffer(aFrameBuffer)
+    {
+        OT_UNUSED_VARIABLE(mReceiveFrameCallback);
+        OT_UNUSED_VARIABLE(mReceiveFrameContext);
+        OT_UNUSED_VARIABLE(mRxFrameBuffer);
+    }
+
+    // TODO: Add vendor code (add methods and/or member variables).
+
+private:
+    SpinelInterface::ReceiveFrameCallback mReceiveFrameCallback;
+    void *                                mReceiveFrameContext;
+    SpinelInterface::RxFrameBuffer &      mRxFrameBuffer;
+};
+
+// ----------------------------------------------------------------------------
+// `VendorInterface` API
+// ----------------------------------------------------------------------------
+
+static OT_DEFINE_ALIGNED_VAR(sVendorInterfaceImplRaw, sizeof(VendorInterfaceImpl), uint64_t);
+
+VendorInterface::VendorInterface(SpinelInterface::ReceiveFrameCallback aCallback,
+                                 void *                                aCallbackContext,
+                                 SpinelInterface::RxFrameBuffer &      aFrameBuffer)
+{
+    new (&sVendorInterfaceImplRaw) VendorInterfaceImpl(aCallback, aCallbackContext, aFrameBuffer);
+    OT_UNUSED_VARIABLE(sVendorInterfaceImplRaw);
+}
+
+VendorInterface::~VendorInterface(void)
+{
+    Deinit();
+}
+
+otError VendorInterface::Init(const Url::Url &aRadioUrl)
+{
+    OT_UNUSED_VARIABLE(aRadioUrl);
+
+    // TODO: Implement vendor code here.
+
+    return OT_ERROR_NONE;
+}
+
+void VendorInterface::Deinit(void)
+{
+    // TODO: Implement vendor code here.
+}
+
+uint32_t VendorInterface::GetBusSpeed(void) const
+{
+    return 1000000;
+}
+
+void VendorInterface::OnRcpReset(void)
+{
+    // TODO: Implement vendor code here.
+}
+
+void VendorInterface::UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, int &aMaxFd, struct timeval &aTimeout)
+{
+    OT_UNUSED_VARIABLE(aReadFdSet);
+    OT_UNUSED_VARIABLE(aWriteFdSet);
+    OT_UNUSED_VARIABLE(aMaxFd);
+    OT_UNUSED_VARIABLE(aTimeout);
+
+    // TODO: Implement vendor code here.
+}
+
+void VendorInterface::Process(const RadioProcessContext &aContext)
+{
+    OT_UNUSED_VARIABLE(aContext);
+
+    // TODO: Implement vendor code here.
+}
+
+otError VendorInterface::WaitForFrame(uint64_t aTimeoutUs)
+{
+    OT_UNUSED_VARIABLE(aTimeoutUs);
+
+    // TODO: Implement vendor code here.
+
+    return OT_ERROR_NONE;
+}
+
+otError VendorInterface::SendFrame(const uint8_t *aFrame, uint16_t aLength)
+{
+    OT_UNUSED_VARIABLE(aFrame);
+    OT_UNUSED_VARIABLE(aLength);
+
+    // TODO: Implement vendor code here.
+
+    return OT_ERROR_NONE;
+}
+
+otError VendorInterface::ResetConnection(void)
+{
+    // TODO: Implement vendor code here.
+
+    return OT_ERROR_NONE;
+}
+
+const otRcpInterfaceMetrics *VendorInterface::GetRcpInterfaceMetrics(void)
+{
+    // TODO: Implement vendor code here.
+
+    return nullptr;
+}
+} // namespace Posix
+} // namespace ot
+
+#endif // OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_VENDOR
diff --git a/tests/fuzz/fuzzer_platform.cpp b/tests/fuzz/fuzzer_platform.cpp
index a8ae28b..7449937 100644
--- a/tests/fuzz/fuzzer_platform.cpp
+++ b/tests/fuzz/fuzzer_platform.cpp
@@ -441,9 +441,11 @@
     return OT_ERROR_NONE;
 }
 
-void otPlatSettingsInit(otInstance *aInstance)
+void otPlatSettingsInit(otInstance *aInstance, const uint16_t *aSensitiveKeys, uint16_t aSensitiveKeysLength)
 {
     OT_UNUSED_VARIABLE(aInstance);
+    OT_UNUSED_VARIABLE(aSensitiveKeys);
+    OT_UNUSED_VARIABLE(aSensitiveKeysLength);
 }
 
 void otPlatSettingsDeinit(otInstance *aInstance)
diff --git a/tests/scripts/expect/cli-commissioner-multiple-ftds.exp b/tests/scripts/expect/cli-commissioner-multiple-ftds.exp
new file mode 100755
index 0000000..a212ae1
--- /dev/null
+++ b/tests/scripts/expect/cli-commissioner-multiple-ftds.exp
@@ -0,0 +1,139 @@
+#!/usr/bin/expect -f
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+source "tests/scripts/expect/_common.exp"
+source "tests/scripts/expect/_multinode.exp"
+
+spawn_node 3
+spawn_node 2
+spawn_node 1
+
+setup_leader
+setup_node 3 "rdn" "router"
+setup_node 2 "rdn" "router"
+
+sleep 15
+
+###########################################
+# Verify topology and commissioners
+
+switch_node 3
+send "state\n"
+expect "router"
+send "commissioner state\n"
+expect "disabled"
+
+switch_node 2
+send "state\n"
+expect "router"
+send "commissioner state\n"
+expect "disabled"
+
+switch_node 1
+send "state\n"
+expect "leader"
+send "commissioner state\n"
+expect "active"
+
+###########################################
+# Starting a commissioner on the same partition with the same ID makes
+# the active commissioner resign and become disabled.
+
+switch_node 2
+send "commissioner start\n"
+expect "Done"
+wait_for "commissioner state" "active"
+switch_node 1
+sleep 5
+wait_for "commissioner state" "disabled"
+
+switch_node 3
+send "commissioner start\n"
+expect "Done"
+wait_for "commissioner state" "active"
+sleep 5
+switch_node 2
+wait_for "commissioner state" "disabled"
+
+switch_node 1
+send "commissioner start\n"
+expect "Done"
+wait_for "commissioner state" "active"
+sleep 5
+switch_node 3
+wait_for "commissioner state" "disabled"
+
+###########################################
+# Starting another commissioner on the same partition, using a different ID avoids
+# the previous problem of overriding the active commissioner.
+
+switch_node 2
+send "commissioner id COMMISSIONER_2\n"
+expect "Done"
+send "commissioner start\n"
+expect "Done"
+wait_for "commissioner state" "petitioning"
+wait_for "commissioner state" "disabled"
+
+switch_node 1
+send "commissioner state\n"
+expect "active"
+
+switch_node 3
+send "commissioner id COMMISSIONER_3\n"
+expect "Done"
+send "commissioner start\n"
+expect "Done"
+wait_for "commissioner state" "petitioning"
+wait_for "commissioner state" "disabled"
+
+switch_node 1
+send "commissioner state\n"
+expect "active"
+
+###########################################
+# Stop active commissioner and start another one
+send "commissioner stop\n"
+
+switch_node 2
+send "commissioner id COMMISSIONER_2\n"
+expect "Done"
+send "commissioner start\n"
+expect "Done"
+wait_for "commissioner state" "petitioning"
+wait_for "commissioner state" "active"
+
+switch_node 1
+send "commissioner start\n"
+expect "Done"
+wait_for "commissioner state" "petitioning"
+wait_for "commissioner state" "disabled"
+
+###########################################
+dispose_all
diff --git a/tests/scripts/expect/cli-commissioner.exp b/tests/scripts/expect/cli-commissioner.exp
index 1474d2f..2c6737e 100755
--- a/tests/scripts/expect/cli-commissioner.exp
+++ b/tests/scripts/expect/cli-commissioner.exp
@@ -41,16 +41,34 @@
 expect_line "Done"
 wait_for "netdata steeringdata check $eui64" "NotFound"
 
+# Stop commissioner so node 2 can start a new one with different id
+send "commissioner stop\n"
+expect "Done"
+
 switch_node 2
 send "commissioner state\n"
 expect "disabled"
 expect_line "Done"
+send "commissioner id\n"
+expect "OpenThread Commissioner"
+expect_line "Done"
+send "commissioner id reallyAndUnnecessaryLongOpenthreadComisionerCustomIdShouldNotFit\n"
+expect "Error 7: InvalidArgs"
+send "commissioner id reallyAndUnnecessaryLongOpenthreadCommissionerCustomIdShouldFit\n"
+expect "Done"
+send "commissioner id customId\n"
+expect "Done"
+send "commissioner id\n"
+expect "customId"
+expect_line "Done"
 send "commissioner start\n"
 expect_line "Done"
 expect "Commissioner: active"
 send "commissioner state\n"
 expect "active"
 expect_line "Done"
+send "commissioner id AnotherCustomId\n"
+expect_line "Error 13: InvalidState"
 send "commissioner provisioningurl openthread.io\n"
 expect_line "Done"
 send "commissioner joiner add * J01NME 1\n"
@@ -65,7 +83,7 @@
 expect_line "Done"
 send "commissioner mgmtset sessionid $sessionid locator 0x0100\n"
 expect_line "Done"
-send "commissioner mgmtget sessionid steeringdata joinerudpport locator binary 0b081209\n"
+send "commissioner mgmtget sessionid steeringdata joinerudpport locator -x 0b081209\n"
 expect_line "Done"
 send "commissioner stop\n"
 expect "Commissioner: disabled"
diff --git a/tests/scripts/expect/cli-dataset.exp b/tests/scripts/expect/cli-dataset.exp
index a660c44..0b75300 100755
--- a/tests/scripts/expect/cli-dataset.exp
+++ b/tests/scripts/expect/cli-dataset.exp
@@ -102,10 +102,10 @@
 send "dataset pskc\n"
 expect "00112233445566778899aabbccddeeff"
 expect_line "Done"
-send "dataset securitypolicy 678 onrcb\n"
+send "dataset securitypolicy 678 onrc\n"
 expect_line "Done"
 send "dataset securitypolicy\n"
-expect "678 onrcb"
+expect "678 onrc"
 expect_line "Done"
 send "dataset pendingtimestamp 100\n"
 expect_line "Done"
@@ -135,7 +135,7 @@
 expect "Network Name: OT-network"
 expect "PAN ID: 0xface"
 expect "PSKc: 00112233445566778899aabbccddeeff"
-expect "Security Policy: 678 onrcb"
+expect "Security Policy: 678 onrc"
 expect_line "Done"
 send "dataset pending -x\n"
 expect "dataset pending -x"
@@ -161,7 +161,7 @@
 expect "Network Name: OT-network"
 expect "PAN ID: 0xface"
 expect "PSKc: 00112233445566778899aabbccddeeff"
-expect "Security Policy: 678 onrcb"
+expect "Security Policy: 678 onrc"
 expect_line "Done"
 
 sleep 30
@@ -183,7 +183,7 @@
 expect "Network Name: OT-network"
 expect "PAN ID: 0xface"
 expect "PSKc: 00112233445566778899aabbccddeeff"
-expect "Security Policy: 678 onrcb"
+expect "Security Policy: 678 onrc"
 expect_line "Done"
 send "dataset clear\n"
 expect_line "Done"
@@ -203,7 +203,7 @@
 expect "Network Name: OT-network"
 expect "PAN ID: 0xface"
 expect "PSKc: 00112233445566778899aabbccddeeff"
-expect "Security Policy: 678 onrcb"
+expect "Security Policy: 678 onrc"
 expect_line "Done"
 send "dataset init pending\n"
 expect "Error 23: NotFound"
diff --git a/tests/scripts/expect/cli-misc.exp b/tests/scripts/expect/cli-misc.exp
index 89da807..8b8b4d5 100755
--- a/tests/scripts/expect/cli-misc.exp
+++ b/tests/scripts/expect/cli-misc.exp
@@ -180,6 +180,13 @@
 send "ba state\n"
 expect "Done"
 
+send "prefix meshlocal fd00:dead:beef:cafe::/96\n"
+expect_line "Error 7: InvalidArgs"
+send "prefix meshlocal fd00:dead:beef:cafe::/64\n"
+expect_line "Done"
+send "prefix meshlocal\n"
+expect_line "fd00:dead:beef:cafe::/64"
+
 send "invalidcommand\n"
 expect_line "Error 35: InvalidCommand"
 
diff --git a/tests/scripts/expect/cli-networkname.exp b/tests/scripts/expect/cli-networkname.exp
index 20c09c6..fc4edb1 100755
--- a/tests/scripts/expect/cli-networkname.exp
+++ b/tests/scripts/expect/cli-networkname.exp
@@ -43,7 +43,9 @@
 expect_line "Done"
 
 switch_node 2
-send "scan\n"
+send "ifconfig up\n"
+expect_line "Done"
+send "discover\n"
 expect "Thread Network"
 expect_line "Done"
 
@@ -58,7 +60,7 @@
 expect_line "Done"
 
 switch_node 2
-send "scan\n"
+send "discover\n"
 expect "Thread 网络"
 expect_line "Done"
 
@@ -73,7 +75,7 @@
 expect_line "Done"
 
 switch_node 2
-send "scan\n"
+send "discover\n"
 expect "スレッド"
 expect_line "Done"
 
diff --git a/tests/scripts/expect/cli-reset.exp b/tests/scripts/expect/cli-reset.exp
index dc29441..6442088 100755
--- a/tests/scripts/expect/cli-reset.exp
+++ b/tests/scripts/expect/cli-reset.exp
@@ -38,7 +38,7 @@
 send "thread start\n"
 expect_line "Done"
 
-sleep 3
+sleep 10
 
 send "reset\n"
 sleep 3
diff --git a/tests/scripts/expect/cli-scan-discover.exp b/tests/scripts/expect/cli-scan-discover.exp
index 3c1d193..78226c7 100755
--- a/tests/scripts/expect/cli-scan-discover.exp
+++ b/tests/scripts/expect/cli-scan-discover.exp
@@ -60,9 +60,9 @@
 
 switch_node 3
 send "scan $channel\n"
-expect "| J | Network Name     | Extended PAN     | PAN  | MAC Address      | Ch | dBm | LQI |"
-expect "+---+------------------+------------------+------+------------------+----+-----+-----+"
-wait_for "" "\\| \\d \\| $network +\\| $extpan \\| $pan \\| $extaddr \\| +$channel \\| +-?\\d+ \\| +\\d \\|"
+expect "| PAN  | MAC Address      | Ch | dBm | LQI |"
+expect "+------+------------------+----+-----+-----+"
+wait_for "" "\\| $pan \\| $extaddr \\| +$channel \\| +-?\\d+ \\| +\\d \\|"
 wait_for "" "Done"
 send "scan energy 100\n"
 expect "| Ch | RSSI |"
@@ -83,9 +83,9 @@
 send "ifconfig up\n"
 expect_line "Done"
 send "discover $channel\n"
-expect "| J | Network Name     | Extended PAN     | PAN  | MAC Address      | Ch | dBm | LQI |"
-expect "+---+------------------+------------------+------+------------------+----+-----+-----+"
-wait_for "" "\\| \\d \\| $network +\\| $extpan \\| $pan \\| $extaddr \\| +$channel \\| +-?\\d+ \\| +\\d \\|"
+expect "| Network Name     | Extended PAN     | PAN  | MAC Address      | Ch | dBm | LQI |"
+expect "+------------------+------------------+------+------------------+----+-----+-----+"
+wait_for "" "\\| $network +\\| $extpan \\| $pan \\| $extaddr \\| +$channel \\| +-?\\d+ \\| +\\d \\|"
 wait_for "" "Done"
 send "discover something_invalid\n"
 expect "Error 7: InvalidArgs"
diff --git a/tests/scripts/expect/cli-tcp.exp b/tests/scripts/expect/cli-tcp.exp
new file mode 100755
index 0000000..838730d
--- /dev/null
+++ b/tests/scripts/expect/cli-tcp.exp
@@ -0,0 +1,93 @@
+#!/usr/bin/expect -f
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+source "tests/scripts/expect/_common.exp"
+source "tests/scripts/expect/_multinode.exp"
+
+setup_two_nodes
+
+switch_node 1
+send "tcp init\n"
+expect_line "Done"
+
+switch_node 2
+send "tcp init\n"
+expect_line "Done"
+set addr_2 [get_ipaddr mleid]
+send "tcp listen :: 30000\n"
+expect_line "Done"
+
+switch_node 1
+set addr_1 [get_ipaddr mleid]
+send "tcp bind $addr_1 25000\n"
+expect_line "Done"
+send "tcp connect $addr_2 30000\n"
+expect_line "Done"
+expect "TCP: Connection established"
+
+switch_node 2
+expect "Accepted connection from \\\[$addr_1\\\]:25000"
+expect "TCP: Connection established"
+
+switch_node 1
+send "tcp send hello\n"
+expect_line "Done"
+
+switch_node 2
+expect "TCP: Received 5 bytes: hello"
+send "tcp send world\n"
+expect_line "Done"
+
+switch_node 1
+expect "TCP: Received 5 bytes: world"
+send "tcp sendend\n"
+expect_line "Done"
+send "tcp send more\n"
+expect_line "Error 1: Failed"
+
+switch_node 2
+expect "TCP: Reached end of stream"
+send "tcp send goodbye\n"
+expect_line "Done"
+
+switch_node 1
+expect "TCP: Received 7 bytes: goodbye"
+
+switch_node 2
+send "tcp sendend\n"
+expect_line "Done"
+expect "TCP: Disconnected"
+
+switch_node 1
+expect "TCP: Reached end of stream"
+expect "TCP: Entered TIME-WAIT state"
+set timeout 130
+expect "TCP: Disconnected"
+
+dispose_all
diff --git a/tests/scripts/expect/posix-diag-rcp.exp b/tests/scripts/expect/posix-diag-rcp.exp
index 2e4732e..08b9553 100755
--- a/tests/scripts/expect/posix-diag-rcp.exp
+++ b/tests/scripts/expect/posix-diag-rcp.exp
@@ -53,5 +53,17 @@
 expect_line "Done"
 send "diag rcp power 10\n"
 expect_line "Done"
+send "diag rcp echo\n"
+expect "failed"
+expect "status 0x7"
+expect_line "Done"
+send "diag rcp echo 0123456789\n"
+expect_line "0123456789"
+expect_line "Done"
+send "diag rcp echo -n 0\n"
+expect_line "Done"
+send "diag rcp echo -n 253\n"
+expect_line {[0-9]{253}}
+expect_line "Done"
 
 dispose_all
diff --git a/etc/cmake/checks.cmake b/tests/scripts/expect/posix-rcp-energy-scan.exp
old mode 100644
new mode 100755
similarity index 76%
copy from etc/cmake/checks.cmake
copy to tests/scripts/expect/posix-rcp-energy-scan.exp
index ab7bb88..93a7a2a
--- a/etc/cmake/checks.cmake
+++ b/tests/scripts/expect/posix-rcp-energy-scan.exp
@@ -1,5 +1,6 @@
+#!/usr/bin/expect -f
 #
-#  Copyright (c) 2019, The OpenThread Authors.
+#  Copyright (c) 2022, The OpenThread Authors.
 #  All rights reserved.
 #
 #  Redistribution and use in source and binary forms, with or without
@@ -26,4 +27,16 @@
 #  POSSIBILITY OF SUCH DAMAGE.
 #
 
-configure_file(${PROJECT_SOURCE_DIR}/etc/cmake/openthread-config-generic.h.in ${PROJECT_BINARY_DIR}/etc/cmake/openthread-config-generic.h)
+source "tests/scripts/expect/_common.exp"
+
+spawn_node 1 "rcp" "spinel+hdlc+forkpty://$::env(OT_SIMULATION_APPS)/ncp/ot-rcp?forkpty-arg=1&forkpty-arg=-E&no-reset=1"
+
+send "ifconfig up\n"
+expect_line "Done"
+# Actually returns last otPlatRadioGetRssi
+send "scan energy 0\n"
+expect_line "Done"
+# Actually performs energy scan on RCP
+send "scan energy 100\n"
+expect_line "Done"
+dispose_all
diff --git a/tests/scripts/expect/posix-scan-tx-to-sleep.exp b/tests/scripts/expect/posix-scan-tx-to-sleep.exp
index a613737..2ac44a8 100755
--- a/tests/scripts/expect/posix-scan-tx-to-sleep.exp
+++ b/tests/scripts/expect/posix-scan-tx-to-sleep.exp
@@ -49,17 +49,6 @@
 expect -re {([0-9a-f]{4})}
 set pan $expect_out(1,string)
 expect_line "Done"
-send "extpanid\n"
-expect "extpanid"
-expect -re {([0-9a-f]{16})}
-set extpan $expect_out(1,string)
-expect_line "Done"
-expect "> "
-send "networkname\n"
-expect "networkname"
-expect -re {[\r\n]([^\r\n]+)[\r\n]}
-set network $expect_out(1,string)
-expect_line "Done"
 send "channel\n"
 expect "channel"
 expect -re {(\d+)}
@@ -68,9 +57,9 @@
 
 spawn_node 2 "rcp" "spinel+hdlc+uart://$env(OT_SIMULATION_APPS)/ncp/ot-rcp?forkpty-arg=--sleep-to-tx&forkpty-arg=2"
 send "scan\n"
-expect "| J | Network Name     | Extended PAN     | PAN  | MAC Address      | Ch | dBm | LQI |"
-expect "+---+------------------+------------------+------+------------------+----+-----+-----+"
-wait_for "" "\\| \\d \\| $network +\\| $extpan \\| $pan \\| $extaddr \\| +$channel \\| +-?\\d+ \\| +\\d \\|"
+expect "| PAN  | MAC Address      | Ch | dBm | LQI |"
+expect "+------+------------------+----+-----+-----+"
+wait_for "" "\\| $pan \\| $extaddr \\| +$channel \\| +-?\\d+ \\| +\\d \\|"
 wait_for "" "Done"
 
 dispose_all
diff --git a/etc/cmake/checks.cmake b/tests/scripts/expect/posix-url-enable-coex.exp
old mode 100644
new mode 100755
similarity index 76%
copy from etc/cmake/checks.cmake
copy to tests/scripts/expect/posix-url-enable-coex.exp
index ab7bb88..2fa3fb7
--- a/etc/cmake/checks.cmake
+++ b/tests/scripts/expect/posix-url-enable-coex.exp
@@ -1,5 +1,6 @@
+#!/usr/bin/expect -f
 #
-#  Copyright (c) 2019, The OpenThread Authors.
+#  Copyright (c) 2022, The OpenThread Authors.
 #  All rights reserved.
 #
 #  Redistribution and use in source and binary forms, with or without
@@ -26,4 +27,16 @@
 #  POSSIBILITY OF SUCH DAMAGE.
 #
 
-configure_file(${PROJECT_SOURCE_DIR}/etc/cmake/openthread-config-generic.h.in ${PROJECT_BINARY_DIR}/etc/cmake/openthread-config-generic.h)
+source "tests/scripts/expect/_common.exp"
+
+spawn_node 1 "rcp" "spinel+hdlc+uart://$env(OT_SIMULATION_APPS)/ncp/ot-rcp?enable-coex&forkpty-arg=1"
+send "coex\n"
+expect_line "Enabled"
+expect_line "Done"
+dispose_node 1
+
+spawn_node 1 "rcp" "spinel+hdlc+uart://$env(OT_SIMULATION_APPS)/ncp/ot-rcp?enable-coex=0&forkpty-arg=1"
+send "coex\n"
+expect_line "Disabled"
+expect_line "Done"
+dispose_node 1
diff --git a/tests/scripts/expect/tun-dns-client.exp b/tests/scripts/expect/tun-dns-client.exp
index 36909ba..3a2ac64 100755
--- a/tests/scripts/expect/tun-dns-client.exp
+++ b/tests/scripts/expect/tun-dns-client.exp
@@ -40,8 +40,18 @@
 wait_for "state" "leader"
 expect_line "Done"
 
+send "route add 2001:dead:beef:cafe::/64 s n med\n"
+expect_line "Done"
+
+send "netdata register\n"
+expect_line "Done"
+
 send "dns resolve ipv6.google.com ::1 53\n"
 expect "DNS response for ipv6.google.com"
 expect_line "Done"
 
+send "dns resolve4 ipv6.google.com ::1 53\n"
+expect "DNS response for ipv6.google.com"
+expect_line "Done"
+
 dispose_all
diff --git a/tests/scripts/thread-cert/Cert_5_1_01_RouterAttach.py b/tests/scripts/thread-cert/Cert_5_1_01_RouterAttach.py
index a3f7926..1e4c326 100755
--- a/tests/scripts/thread-cert/Cert_5_1_01_RouterAttach.py
+++ b/tests/scripts/thread-cert/Cert_5_1_01_RouterAttach.py
@@ -75,11 +75,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(7)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.collect_rloc16s()
diff --git a/tests/scripts/thread-cert/Cert_5_1_02_ChildAddressTimeout.py b/tests/scripts/thread-cert/Cert_5_1_02_ChildAddressTimeout.py
index ae03a24..abb9e8c 100755
--- a/tests/scripts/thread-cert/Cert_5_1_02_ChildAddressTimeout.py
+++ b/tests/scripts/thread-cert/Cert_5_1_02_ChildAddressTimeout.py
@@ -93,11 +93,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[MED].start()
diff --git a/tests/scripts/thread-cert/Cert_5_1_03_RouterAddressReallocation.py b/tests/scripts/thread-cert/Cert_5_1_03_RouterAddressReallocation.py
index ffa9914..e7c443e 100755
--- a/tests/scripts/thread-cert/Cert_5_1_03_RouterAddressReallocation.py
+++ b/tests/scripts/thread-cert/Cert_5_1_03_RouterAddressReallocation.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import mle
 import network_layer
 import thread_cert
@@ -80,15 +81,15 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
         self.nodes[ROUTER2].set_network_id_timeout(110)
diff --git a/tests/scripts/thread-cert/Cert_5_1_04_RouterAddressReallocation.py b/tests/scripts/thread-cert/Cert_5_1_04_RouterAddressReallocation.py
index 76d07d7..1837102 100755
--- a/tests/scripts/thread-cert/Cert_5_1_04_RouterAddressReallocation.py
+++ b/tests/scripts/thread-cert/Cert_5_1_04_RouterAddressReallocation.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import mle
 import network_layer
 import thread_cert
@@ -82,15 +83,15 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
         self.nodes[ROUTER2].set_network_id_timeout(200)
diff --git a/tests/scripts/thread-cert/Cert_5_1_05_RouterAddressTimeout.py b/tests/scripts/thread-cert/Cert_5_1_05_RouterAddressTimeout.py
index 46cb5dc..3eef9c9 100755
--- a/tests/scripts/thread-cert/Cert_5_1_05_RouterAddressTimeout.py
+++ b/tests/scripts/thread-cert/Cert_5_1_05_RouterAddressTimeout.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import mle
 import network_layer
 import thread_cert
@@ -78,11 +79,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ROUTER1].reset()
diff --git a/tests/scripts/thread-cert/Cert_5_1_06_RemoveRouterId.py b/tests/scripts/thread-cert/Cert_5_1_06_RemoveRouterId.py
index 73c4c4e..05a77b7 100755
--- a/tests/scripts/thread-cert/Cert_5_1_06_RemoveRouterId.py
+++ b/tests/scripts/thread-cert/Cert_5_1_06_RemoveRouterId.py
@@ -75,11 +75,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
         rloc16 = self.nodes[ROUTER1].get_addr16()
         self.collect_rloc16s()
diff --git a/tests/scripts/thread-cert/Cert_5_1_07_MaxChildCount.py b/tests/scripts/thread-cert/Cert_5_1_07_MaxChildCount.py
index b6364d9..d65e176 100755
--- a/tests/scripts/thread-cert/Cert_5_1_07_MaxChildCount.py
+++ b/tests/scripts/thread-cert/Cert_5_1_07_MaxChildCount.py
@@ -152,11 +152,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         for i in range(3, 13):
diff --git a/tests/scripts/thread-cert/Cert_5_1_08_RouterAttachConnectivity.py b/tests/scripts/thread-cert/Cert_5_1_08_RouterAttachConnectivity.py
index bf1f0a1..3aac58c 100755
--- a/tests/scripts/thread-cert/Cert_5_1_08_RouterAttachConnectivity.py
+++ b/tests/scripts/thread-cert/Cert_5_1_08_RouterAttachConnectivity.py
@@ -93,13 +93,13 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         for i in range(2, 5):
             self.nodes[i].start()
 
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
 
         for i in range(2, 5):
             self.assertEqual(self.nodes[i].get_state(), 'router')
@@ -107,7 +107,7 @@
         self.simulator.go(config.MAX_ADVERTISEMENT_INTERVAL)
 
         self.nodes[ROUTER4].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER4].get_state(), 'router')
 
     def verify(self, pv):
diff --git a/tests/scripts/thread-cert/Cert_5_1_09_REEDAttachConnectivity.py b/tests/scripts/thread-cert/Cert_5_1_09_REEDAttachConnectivity.py
index 33bad5c..ba18b31 100755
--- a/tests/scripts/thread-cert/Cert_5_1_09_REEDAttachConnectivity.py
+++ b/tests/scripts/thread-cert/Cert_5_1_09_REEDAttachConnectivity.py
@@ -95,13 +95,13 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         for i in range(2, 5):
             self.nodes[i].start()
 
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
 
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
         self.assertEqual(self.nodes[REED1].get_state(), 'child')
@@ -110,7 +110,7 @@
         self.simulator.go(config.MAX_ADVERTISEMENT_INTERVAL)
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(10)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
         self.assertEqual(self.nodes[REED1].get_state(), 'router')
 
diff --git a/tests/scripts/thread-cert/Cert_5_1_10_RouterAttachLinkQuality.py b/tests/scripts/thread-cert/Cert_5_1_10_RouterAttachLinkQuality.py
index 5c60106..af5076e 100755
--- a/tests/scripts/thread-cert/Cert_5_1_10_RouterAttachLinkQuality.py
+++ b/tests/scripts/thread-cert/Cert_5_1_10_RouterAttachLinkQuality.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import mle
 import thread_cert
 from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_REQUEST, MLE_PARENT_RESPONSE, MLE_CHILD_ID_REQUEST, SOURCE_ADDRESS_TLV, MODE_TLV, TIMEOUT_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, ADDRESS16_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, TLV_REQUEST_TLV, SCAN_MASK_TLV, CONNECTIVITY_TLV, LINK_MARGIN_TLV, VERSION_TLV, ADDRESS_REGISTRATION_TLV
@@ -86,19 +87,19 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
         self.nodes[ROUTER3].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER3].get_state(), 'router')
 
     def verify(self, pv):
diff --git a/tests/scripts/thread-cert/Cert_5_1_11_REEDAttachLinkQuality.py b/tests/scripts/thread-cert/Cert_5_1_11_REEDAttachLinkQuality.py
index 0da95cd..3973f71 100755
--- a/tests/scripts/thread-cert/Cert_5_1_11_REEDAttachLinkQuality.py
+++ b/tests/scripts/thread-cert/Cert_5_1_11_REEDAttachLinkQuality.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import mle
 import thread_cert
 from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_REQUEST, MLE_PARENT_RESPONSE, MLE_CHILD_ID_REQUEST, SOURCE_ADDRESS_TLV, MODE_TLV, TIMEOUT_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, ADDRESS16_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, TLV_REQUEST_TLV, SCAN_MASK_TLV, CONNECTIVITY_TLV, LINK_MARGIN_TLV, VERSION_TLV, ADDRESS_REGISTRATION_TLV
@@ -88,19 +89,19 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[REED].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[REED].get_state(), 'child')
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(10)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
         self.assertEqual(self.nodes[REED].get_state(), 'router')
 
diff --git a/tests/scripts/thread-cert/Cert_5_1_12_NewRouterNeighborSync.py b/tests/scripts/thread-cert/Cert_5_1_12_NewRouterNeighborSync.py
index 5c2917c..69470a4 100755
--- a/tests/scripts/thread-cert/Cert_5_1_12_NewRouterNeighborSync.py
+++ b/tests/scripts/thread-cert/Cert_5_1_12_NewRouterNeighborSync.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import mle
 import thread_cert
 from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_REQUEST, MLE_PARENT_RESPONSE, MLE_CHILD_UPDATE_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, MLE_LINK_REQUEST, MLE_LINK_ACCEPT, MLE_LINK_ACCEPT_AND_REQUEST, ADDR_SOL_URI, SOURCE_ADDRESS_TLV, MODE_TLV, TIMEOUT_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, ROUTE64_TLV, ADDRESS16_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, TLV_REQUEST_TLV, SCAN_MASK_TLV, CONNECTIVITY_TLV, LINK_MARGIN_TLV, VERSION_TLV, ADDRESS_REGISTRATION_TLV, NL_MAC_EXTENDED_ADDRESS_TLV, NL_RLOC16_TLV, NL_STATUS_TLV, NL_ROUTER_MASK_TLV, COAP_CODE_ACK
@@ -77,15 +78,15 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
         self.simulator.go(10)
diff --git a/tests/scripts/thread-cert/Cert_5_1_13_RouterReset.py b/tests/scripts/thread-cert/Cert_5_1_13_RouterReset.py
index 5455501..a1c55ac 100755
--- a/tests/scripts/thread-cert/Cert_5_1_13_RouterReset.py
+++ b/tests/scripts/thread-cert/Cert_5_1_13_RouterReset.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import mle
 import thread_cert
 from pktverify.consts import MLE_ADVERTISEMENT, MLE_LINK_REQUEST, MLE_LINK_ACCEPT, MLE_LINK_ACCEPT_AND_REQUEST, SOURCE_ADDRESS_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, ROUTE64_TLV, ADDRESS16_TLV, LEADER_DATA_TLV, TLV_REQUEST_TLV, VERSION_TLV, MLE_MAX_RESPONSE_DELAY
@@ -79,11 +80,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
         self.collect_rloc16s()
 
@@ -92,7 +93,7 @@
         self.simulator.go(5)
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
     def verify(self, pv):
diff --git a/tests/scripts/thread-cert/Cert_5_2_01_REEDAttach.py b/tests/scripts/thread-cert/Cert_5_2_01_REEDAttach.py
index ae0cc6e..27f4e5e 100755
--- a/tests/scripts/thread-cert/Cert_5_2_01_REEDAttach.py
+++ b/tests/scripts/thread-cert/Cert_5_2_01_REEDAttach.py
@@ -92,15 +92,15 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[DUT_ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[DUT_ROUTER1].get_state(), 'router')
 
         self.nodes[REED1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[REED1].get_state(), 'child')
 
         self.nodes[MED1].start()
diff --git a/tests/scripts/thread-cert/Cert_5_2_03_LeaderReject2Hops.py b/tests/scripts/thread-cert/Cert_5_2_03_LeaderReject2Hops.py
index e91509a..6a261bf 100755
--- a/tests/scripts/thread-cert/Cert_5_2_03_LeaderReject2Hops.py
+++ b/tests/scripts/thread-cert/Cert_5_2_03_LeaderReject2Hops.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import mle
 import network_layer
 import thread_cert
@@ -310,21 +311,21 @@
 
     def test(self):
         self.nodes[DUT_LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[DUT_LEADER].get_state(), 'leader')
 
         for i in range(2, 32):
             self.nodes[i].start()
-            self.simulator.go(5)
+            self.simulator.go(config.ROUTER_STARTUP_DELAY)
             self.assertEqual(self.nodes[i].get_state(), 'router')
         self.collect_rlocs()
 
         self.nodes[ROUTER_31].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER_31].get_state(), 'router')
 
         self.nodes[ROUTER_32].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
 
     def verify(self, pv: PacketVerifier):
         pkts = pv.pkts
diff --git a/tests/scripts/thread-cert/Cert_5_2_04_REEDUpgrade.py b/tests/scripts/thread-cert/Cert_5_2_04_REEDUpgrade.py
index 20aafa2..241c9bb 100755
--- a/tests/scripts/thread-cert/Cert_5_2_04_REEDUpgrade.py
+++ b/tests/scripts/thread-cert/Cert_5_2_04_REEDUpgrade.py
@@ -169,16 +169,16 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         for i in range(2, 17):
             self.nodes[i].start()
-            self.simulator.go(5)
+            self.simulator.go(config.ROUTER_STARTUP_DELAY)
             self.assertEqual(self.nodes[i].get_state(), 'router')
 
         self.nodes[DUT_REED].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.simulator.go(ROUTER_SELECTION_JITTER)
 
         self.collect_rloc16s()
@@ -187,7 +187,7 @@
         self.simulator.go(REED_ADVERTISEMENT_INTERVAL + REED_ADVERTISEMENT_MAX_JITTER)
 
         self.nodes[MED].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.collect_ipaddrs()
 
         mleid = self.nodes[LEADER].get_ip6_address(config.ADDRESS_TYPE.ML_EID)
@@ -352,43 +352,45 @@
         #              - TLV Request TLV: Link Margin
         #              - Version TLV
 
-        pkts.filter_wpan_src64(REED).\
-            filter_LLARMA().\
-            filter_mle_cmd(MLE_LINK_REQUEST).\
-            filter(lambda p: {
-                              CHALLENGE_TLV,
-                              LEADER_DATA_TLV,
-                              SOURCE_ADDRESS_TLV,
-                              VERSION_TLV,
-                              TLV_REQUEST_TLV,
-                              LINK_MARGIN_TLV
-                              } <= set(p.mle.tlv.type)
-                   ).\
-            must_next()
+        with pkts.save_index():
+            pkts.filter_wpan_src64(REED).\
+                filter_LLARMA().\
+                filter_mle_cmd(MLE_LINK_REQUEST).\
+                filter(lambda p: {
+                                 CHALLENGE_TLV,
+                                 LEADER_DATA_TLV,
+                                 SOURCE_ADDRESS_TLV,
+                                 VERSION_TLV,
+                                 TLV_REQUEST_TLV,
+                                 LINK_MARGIN_TLV
+                                 } <= set(p.mle.tlv.type)
+                       ).\
+                must_next()
 
         # Step 11: The REED MLE Child ID Response MUST be properly
         #          formatted with MED_1’s new 16-bit address.
 
-        pkts.filter_wpan_src64(REED).\
-            filter_wpan_dst64(MED).\
-            filter_mle_cmd(MLE_CHILD_ID_RESPONSE).\
-            filter(lambda p: {
-                              ADDRESS16_TLV,
-                              LEADER_DATA_TLV,
-                              NETWORK_DATA_TLV,
-                              SOURCE_ADDRESS_TLV,
-                              ROUTE64_TLV
-                              } <= set(p.mle.tlv.type) or\
-                             {
-                              ADDRESS16_TLV,
-                              LEADER_DATA_TLV,
-                              NETWORK_DATA_TLV,
-                              SOURCE_ADDRESS_TLV
-                              } <= set(p.mle.tlv.type) and\
-                   p.mle.tlv.source_addr != REED_RLOC16 and\
-                   p.mle.tlv.addr16 != MED_RLOC16
-                   ).\
-                   must_next()
+        with pkts.save_index():
+            pkts.filter_wpan_src64(REED).\
+                filter_wpan_dst64(MED).\
+                filter_mle_cmd(MLE_CHILD_ID_RESPONSE).\
+                filter(lambda p: {
+                                 ADDRESS16_TLV,
+                                 LEADER_DATA_TLV,
+                                 NETWORK_DATA_TLV,
+                                 SOURCE_ADDRESS_TLV,
+                                 ROUTE64_TLV
+                                 } <= set(p.mle.tlv.type) or\
+                                 {
+                                 ADDRESS16_TLV,
+                                 LEADER_DATA_TLV,
+                                 NETWORK_DATA_TLV,
+                                 SOURCE_ADDRESS_TLV
+                                 } <= set(p.mle.tlv.type) and\
+                       p.mle.tlv.source_addr != REED_RLOC16 and\
+                       p.mle.tlv.addr16 != MED_RLOC16
+                       ).\
+                must_next()
 
         # Step 12: The Leader MUST respond with an ICMPv6 Echo Reply
 
diff --git a/tests/scripts/thread-cert/Cert_5_2_05_AddressQuery.py b/tests/scripts/thread-cert/Cert_5_2_05_AddressQuery.py
index d6f352a..903650a 100755
--- a/tests/scripts/thread-cert/Cert_5_2_05_AddressQuery.py
+++ b/tests/scripts/thread-cert/Cert_5_2_05_AddressQuery.py
@@ -177,14 +177,14 @@
     def test(self):
         # 1. LEADER: DHCPv6 Server for prefix 2001::/64.
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
         self.nodes[LEADER].add_prefix('2001::/64', 'pdros')
         self.nodes[LEADER].register_netdata()
 
         # 2. BR: SLAAC Server for prefix 2002::/64.
         self.nodes[BR].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[BR].get_state(), 'router')
         self.nodes[BR].add_prefix('2002::/64', 'paros')
         self.nodes[BR].register_netdata()
@@ -194,7 +194,7 @@
             if i == BR:
                 continue
             self.nodes[i].start()
-            self.simulator.go(5)
+            self.simulator.go(config.ROUTER_STARTUP_DELAY)
             self.assertEqual(self.nodes[i].get_state(), 'router')
 
         self.nodes[MED].start()
@@ -203,7 +203,7 @@
 
         # 4. Bring up DUT_REED.
         self.nodes[DUT_REED].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.simulator.go(ROUTER_SELECTION_JITTER)
 
         # 5. Enable a link between the DUT and BR to create a one-way link.
diff --git a/tests/scripts/thread-cert/Cert_5_2_06_RouterDowngrade.py b/tests/scripts/thread-cert/Cert_5_2_06_RouterDowngrade.py
index 32bf038..a8576e2 100755
--- a/tests/scripts/thread-cert/Cert_5_2_06_RouterDowngrade.py
+++ b/tests/scripts/thread-cert/Cert_5_2_06_RouterDowngrade.py
@@ -211,12 +211,12 @@
     def test(self):
         # 1 Ensure topology is formed correctly without ROUTER23.
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         for i in range(2, 24):
             self.nodes[i].start()
-            self.simulator.go(5)
+            self.simulator.go(config.ROUTER_STARTUP_DELAY)
             self.assertEqual(self.nodes[i].get_state(), 'router')
         self.collect_rloc16s()
 
@@ -224,7 +224,7 @@
         # so we don't need to ensure ROUTER23 has a better link quality on
         # posix.
         self.nodes[ROUTER23].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER23].get_state(), 'router')
 
         self.simulator.go(10)
diff --git a/tests/scripts/thread-cert/Cert_5_2_07_REEDSynchronization.py b/tests/scripts/thread-cert/Cert_5_2_07_REEDSynchronization.py
index bc1a251..038fe6f 100755
--- a/tests/scripts/thread-cert/Cert_5_2_07_REEDSynchronization.py
+++ b/tests/scripts/thread-cert/Cert_5_2_07_REEDSynchronization.py
@@ -146,12 +146,12 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         for i in range(2, 17):
             self.nodes[i].start()
-        self.simulator.go(10)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
 
         for i in range(2, 17):
             self.assertEqual(self.nodes[i].get_state(), 'router')
diff --git a/tests/scripts/thread-cert/Cert_5_3_01_LinkLocal.py b/tests/scripts/thread-cert/Cert_5_3_01_LinkLocal.py
index dc0b7ca..fbb14df 100755
--- a/tests/scripts/thread-cert/Cert_5_3_01_LinkLocal.py
+++ b/tests/scripts/thread-cert/Cert_5_3_01_LinkLocal.py
@@ -71,11 +71,11 @@
     def test(self):
         # 1
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[DUT_ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[DUT_ROUTER1].get_state(), 'router')
 
         self.collect_rlocs()
diff --git a/tests/scripts/thread-cert/Cert_5_3_02_RealmLocal.py b/tests/scripts/thread-cert/Cert_5_3_02_RealmLocal.py
index 9ff9bfd..9e2184f 100755
--- a/tests/scripts/thread-cert/Cert_5_3_02_RealmLocal.py
+++ b/tests/scripts/thread-cert/Cert_5_3_02_RealmLocal.py
@@ -89,15 +89,15 @@
     def test(self):
         # 1
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[DUT_ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[DUT_ROUTER2].get_state(), 'router')
 
         self.nodes[SED1].start()
diff --git a/tests/scripts/thread-cert/Cert_5_3_03_AddressQuery.py b/tests/scripts/thread-cert/Cert_5_3_03_AddressQuery.py
index 2490e9a..233764d 100755
--- a/tests/scripts/thread-cert/Cert_5_3_03_AddressQuery.py
+++ b/tests/scripts/thread-cert/Cert_5_3_03_AddressQuery.py
@@ -96,14 +96,14 @@
     def test(self):
         # 1
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
         self.nodes[DUT_ROUTER2].start()
         self.nodes[ROUTER3].start()
         self.nodes[MED1].start()
-        self.simulator.go(10)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
 
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
         self.assertEqual(self.nodes[DUT_ROUTER2].get_state(), 'router')
diff --git a/tests/scripts/thread-cert/Cert_5_3_04_AddressMapCache.py b/tests/scripts/thread-cert/Cert_5_3_04_AddressMapCache.py
index 06a81e7..66e1d1e 100755
--- a/tests/scripts/thread-cert/Cert_5_3_04_AddressMapCache.py
+++ b/tests/scripts/thread-cert/Cert_5_3_04_AddressMapCache.py
@@ -113,11 +113,11 @@
     def test(self):
         # 1
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[DUT_ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[DUT_ROUTER1].get_state(), 'router')
 
         for i in MTDS:
diff --git a/tests/scripts/thread-cert/Cert_5_3_05_RoutingLinkQuality.py b/tests/scripts/thread-cert/Cert_5_3_05_RoutingLinkQuality.py
index 5cb8d7e..ce267a6 100755
--- a/tests/scripts/thread-cert/Cert_5_3_05_RoutingLinkQuality.py
+++ b/tests/scripts/thread-cert/Cert_5_3_05_RoutingLinkQuality.py
@@ -86,12 +86,12 @@
     def test(self):
         # 1
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         for router in range(DUT_ROUTER1, ROUTER3 + 1):
             self.nodes[router].start()
-        self.simulator.go(10)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
 
         for router in range(DUT_ROUTER1, ROUTER3 + 1):
             self.assertEqual(self.nodes[router].get_state(), 'router')
diff --git a/tests/scripts/thread-cert/Cert_5_3_06_RouterIdMask.py b/tests/scripts/thread-cert/Cert_5_3_06_RouterIdMask.py
index 71ecf82..1f57e9f 100755
--- a/tests/scripts/thread-cert/Cert_5_3_06_RouterIdMask.py
+++ b/tests/scripts/thread-cert/Cert_5_3_06_RouterIdMask.py
@@ -86,15 +86,15 @@
     def test(self):
         # 1
         self.nodes[DUT_LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[DUT_LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
         self.collect_rloc16s()
@@ -114,7 +114,7 @@
         # 5
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
         self.simulator.go(config.MAX_ADVERTISEMENT_INTERVAL)
@@ -179,10 +179,16 @@
                 filter_LLANMA().\
                 filter_mle_cmd(MLE_ADVERTISEMENT).\
                 must_next()
+            # Time between MLE Advertisements after reset can be up to 3.5 seconds
+            # 0.0s: Reset Interval, reset interval to 1 seconds, random interval at 0.5 second
+            # 0.5s: Transmit MLE Advertisement
+            # 1.0s: Set interval to 2 seconds, random interval at 2 seconds
+            # 3.0s: Receive MLE Advertisement, reset interval to 1 second, random interval at 1.0 second
+            # 4.0s: Transmit MLE Advertisement
             pkts.filter_wpan_src64(LEADER).\
                 filter_LLANMA().\
                 filter_mle_cmd(MLE_ADVERTISEMENT).\
-                filter(lambda p: p.sniff_timestamp - _pkt.sniff_timestamp <= 3).\
+                filter(lambda p: p.sniff_timestamp - _pkt.sniff_timestamp <= 4).\
                 must_next()
         # check router cost before and after the re-attach
         pkts.filter_wpan_src64(LEADER).\
diff --git a/tests/scripts/thread-cert/Cert_5_3_07_DuplicateAddress.py b/tests/scripts/thread-cert/Cert_5_3_07_DuplicateAddress.py
index 669fcfd..0fd38b6 100755
--- a/tests/scripts/thread-cert/Cert_5_3_07_DuplicateAddress.py
+++ b/tests/scripts/thread-cert/Cert_5_3_07_DuplicateAddress.py
@@ -111,7 +111,7 @@
 
     def test(self):
         self.nodes[DUT_LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[DUT_LEADER].get_state(), 'leader')
 
         for i in range(ROUTER1, MED2 + 1):
diff --git a/tests/scripts/thread-cert/Cert_5_3_08_ChildAddressSet.py b/tests/scripts/thread-cert/Cert_5_3_08_ChildAddressSet.py
index 4f7fe00..c1d4f4b 100755
--- a/tests/scripts/thread-cert/Cert_5_3_08_ChildAddressSet.py
+++ b/tests/scripts/thread-cert/Cert_5_3_08_ChildAddressSet.py
@@ -96,11 +96,11 @@
 
     def test(self):
         self.nodes[DUT_LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[DUT_LEADER].get_state(), 'leader')
 
         self.nodes[BR].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[BR].get_state(), 'router')
 
         # 1 BR: Configure BR to be a DHCPv6 server
diff --git a/tests/scripts/thread-cert/Cert_5_3_09_AddressQuery.py b/tests/scripts/thread-cert/Cert_5_3_09_AddressQuery.py
index 1f51345..6e1ca9d 100755
--- a/tests/scripts/thread-cert/Cert_5_3_09_AddressQuery.py
+++ b/tests/scripts/thread-cert/Cert_5_3_09_AddressQuery.py
@@ -109,7 +109,7 @@
     def test(self):
         # 1 & 2 ALL: Build and verify the topology
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         # Configure the LEADER to be a DHCPv6 Border Router for prefixes
@@ -118,15 +118,15 @@
         self.nodes[LEADER].register_netdata()
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[DUT_ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[DUT_ROUTER2].get_state(), 'router')
 
         self.nodes[ROUTER3].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER3].get_state(), 'router')
 
         self.nodes[SED1].start()
diff --git a/tests/scripts/thread-cert/Cert_5_3_10_AddressQuery.py b/tests/scripts/thread-cert/Cert_5_3_10_AddressQuery.py
index 8c3b164..775ee5f 100755
--- a/tests/scripts/thread-cert/Cert_5_3_10_AddressQuery.py
+++ b/tests/scripts/thread-cert/Cert_5_3_10_AddressQuery.py
@@ -109,11 +109,11 @@
     def test(self):
         # 1 & 2
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[BR].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[BR].get_state(), 'router')
 
         # Configure two On-Mesh Prefixes on the BR
@@ -122,11 +122,11 @@
         self.nodes[BR].register_netdata()
 
         self.nodes[DUT_ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[DUT_ROUTER2].get_state(), 'router')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[MED1].start()
diff --git a/tests/scripts/thread-cert/Cert_5_3_11_AddressQueryTimeoutIntervals.py b/tests/scripts/thread-cert/Cert_5_3_11_AddressQueryTimeoutIntervals.py
index a7f0fec..7e0f304 100755
--- a/tests/scripts/thread-cert/Cert_5_3_11_AddressQueryTimeoutIntervals.py
+++ b/tests/scripts/thread-cert/Cert_5_3_11_AddressQueryTimeoutIntervals.py
@@ -85,11 +85,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[DUT_ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[DUT_ROUTER1].get_state(), 'router')
 
         self.nodes[MED1].start()
diff --git a/tests/scripts/thread-cert/Cert_5_5_01_LeaderReboot.py b/tests/scripts/thread-cert/Cert_5_5_01_LeaderReboot.py
index 70239e0..af4ce87 100755
--- a/tests/scripts/thread-cert/Cert_5_5_01_LeaderReboot.py
+++ b/tests/scripts/thread-cert/Cert_5_5_01_LeaderReboot.py
@@ -79,11 +79,11 @@
 
     def test(self):
         self.nodes[DUT_LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[DUT_LEADER].get_state(), 'leader')
 
         self.nodes[DUT_ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[DUT_ROUTER1].get_state(), 'router')
 
         leader_rloc = self.nodes[DUT_LEADER].get_ip6_address(config.ADDRESS_TYPE.RLOC)
@@ -97,7 +97,7 @@
 
         self.nodes[DUT_LEADER].start()
 
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[DUT_LEADER].get_state(), 'leader')
         self.assertEqual(self.nodes[DUT_LEADER].get_addr16(), leader_rloc16)
 
diff --git a/tests/scripts/thread-cert/Cert_5_5_02_LeaderReboot.py b/tests/scripts/thread-cert/Cert_5_5_02_LeaderReboot.py
index 5c0f95e..6aff3cf 100755
--- a/tests/scripts/thread-cert/Cert_5_5_02_LeaderReboot.py
+++ b/tests/scripts/thread-cert/Cert_5_5_02_LeaderReboot.py
@@ -67,11 +67,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[ED].start()
@@ -80,11 +80,11 @@
 
         self.nodes[LEADER].reset()
         self._setUpLeader()
-        self.simulator.go(140)
+        self.simulator.go(150)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'leader')
 
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'router')
 
         addrs = self.nodes[ED].get_addrs()
diff --git a/tests/scripts/thread-cert/Cert_5_5_03_SplitMergeChildren.py b/tests/scripts/thread-cert/Cert_5_5_03_SplitMergeChildren.py
index d316b37..92040d0 100755
--- a/tests/scripts/thread-cert/Cert_5_5_03_SplitMergeChildren.py
+++ b/tests/scripts/thread-cert/Cert_5_5_03_SplitMergeChildren.py
@@ -85,15 +85,15 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ED2].start()
@@ -108,13 +108,13 @@
         self._setUpLeader()
         self.nodes[ROUTER2].set_preferred_partition_id(0xffffffff)
 
-        self.simulator.go(140)
+        self.simulator.go(150)
 
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'leader')
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'leader')
 
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'router')
 
         self.simulator.go(30)
diff --git a/tests/scripts/thread-cert/Cert_5_5_04_SplitMergeRouters.py b/tests/scripts/thread-cert/Cert_5_5_04_SplitMergeRouters.py
index 1473ac4..8c08d1e 100755
--- a/tests/scripts/thread-cert/Cert_5_5_04_SplitMergeRouters.py
+++ b/tests/scripts/thread-cert/Cert_5_5_04_SplitMergeRouters.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_REQUEST, MLE_CHILD_ID_RESPONSE, SOURCE_ADDRESS_TLV, ROUTE64_TLV, LEADER_DATA_TLV
 from pktverify.packet_verifier import PacketVerifier
@@ -77,23 +78,23 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
         self.nodes[ROUTER3].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER3].get_state(), 'router')
 
         self.nodes[ROUTER4].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER4].get_state(), 'router')
 
         self.nodes[LEADER].reset()
diff --git a/tests/scripts/thread-cert/Cert_5_5_05_SplitMergeREED.py b/tests/scripts/thread-cert/Cert_5_5_05_SplitMergeREED.py
index 154b069..abfab51 100755
--- a/tests/scripts/thread-cert/Cert_5_5_05_SplitMergeREED.py
+++ b/tests/scripts/thread-cert/Cert_5_5_05_SplitMergeREED.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_ADVERTISEMENT, MLE_LINK_REQUEST, MLE_PARENT_REQUEST, MLE_PARENT_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, ADDR_SOL_URI, VERSION_TLV, TLV_REQUEST_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, CHALLENGE_TLV, LINK_MARGIN_TLV, NL_MAC_EXTENDED_ADDRESS_TLV, NL_STATUS_TLV
 from pktverify.packet_verifier import PacketVerifier
@@ -120,16 +121,16 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         for i in range(ROUTER2, ROUTER15 + 1):
             self.nodes[i].start()
-            self.simulator.go(5)
+            self.simulator.go(config.ROUTER_STARTUP_DELAY)
             self.assertEqual(self.nodes[i].get_state(), 'router')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[REED1].start()
@@ -175,10 +176,10 @@
         router1_pkts.range(_start_idx).must_next()
         router1_pkts.filter_mle_cmd(MLE_PARENT_REQUEST).must_next()
 
-        # filter MLE_ADVERTISEMENT with 15 routing table entry:
-        # 1 byte ID Sequence + 8 bytes ID Mask + 15 bytes Routing Table Entry =
-        # 24 (Router64 tlv length)
-        pkts.range(_start_idx).filter_mle_cmd(MLE_ADVERTISEMENT).filter(lambda p: 24 in p.mle.tlv.len).must_next()
+        # filter MLE_ADVERTISEMENT with 16 routing table entry:
+        # 1 byte ID Sequence + 8 bytes ID Mask + 16 bytes Routing Table Entry =
+        # 25 (Router64 tlv length)
+        pkts.range(_start_idx).filter_mle_cmd(MLE_ADVERTISEMENT).filter(lambda p: 25 in p.mle.tlv.len).must_next()
         _end_idx = pkts.index
 
         # Step 2: The DUT MUST NOT attempt to become an active router by sending an Address Solicit Request
diff --git a/tests/scripts/thread-cert/Cert_5_5_07_SplitMergeThreeWay.py b/tests/scripts/thread-cert/Cert_5_5_07_SplitMergeThreeWay.py
index df8f2e5..3b6e201 100755
--- a/tests/scripts/thread-cert/Cert_5_5_07_SplitMergeThreeWay.py
+++ b/tests/scripts/thread-cert/Cert_5_5_07_SplitMergeThreeWay.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_REQUEST, MLE_PARENT_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ROUTE64_TLV, MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV, LINK_LAYER_FRAME_COUNTER_TLV, RESPONSE_TLV, LINK_MARGIN_TLV, CONNECTIVITY_TLV, TIMEOUT_TLV, TLV_REQUEST_TLV, ADDRESS16_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV
 from pktverify.packet_verifier import PacketVerifier
@@ -72,19 +73,19 @@
 
     def test(self):
         self.nodes[LEADER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER1].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
         self.nodes[ROUTER3].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER3].get_state(), 'router')
 
         self.nodes[LEADER1].reset()
diff --git a/tests/scripts/thread-cert/Cert_5_6_01_NetworkDataRegisterBeforeAttachLeader.py b/tests/scripts/thread-cert/Cert_5_6_01_NetworkDataRegisterBeforeAttachLeader.py
index a76bac5..044df48 100755
--- a/tests/scripts/thread-cert/Cert_5_6_01_NetworkDataRegisterBeforeAttachLeader.py
+++ b/tests/scripts/thread-cert/Cert_5_6_01_NetworkDataRegisterBeforeAttachLeader.py
@@ -72,7 +72,7 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(4)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[LEADER].add_prefix('2001:2:0:1::/64', 'paros')
@@ -86,7 +86,7 @@
         self.simulator.go(5)
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[ED1].start()
diff --git a/tests/scripts/thread-cert/Cert_5_6_02_NetworkDataRegisterBeforeAttachRouter.py b/tests/scripts/thread-cert/Cert_5_6_02_NetworkDataRegisterBeforeAttachRouter.py
index 2836279..cfb983c 100755
--- a/tests/scripts/thread-cert/Cert_5_6_02_NetworkDataRegisterBeforeAttachRouter.py
+++ b/tests/scripts/thread-cert/Cert_5_6_02_NetworkDataRegisterBeforeAttachRouter.py
@@ -72,11 +72,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(4)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[ROUTER].add_prefix('2001:2:0:1::/64', 'paros')
diff --git a/tests/scripts/thread-cert/Cert_5_6_03_NetworkDataRegisterAfterAttachLeader.py b/tests/scripts/thread-cert/Cert_5_6_03_NetworkDataRegisterAfterAttachLeader.py
index ea331ce..e5c6667 100755
--- a/tests/scripts/thread-cert/Cert_5_6_03_NetworkDataRegisterAfterAttachLeader.py
+++ b/tests/scripts/thread-cert/Cert_5_6_03_NetworkDataRegisterAfterAttachLeader.py
@@ -72,11 +72,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(4)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[ED1].start()
diff --git a/tests/scripts/thread-cert/Cert_5_6_04_NetworkDataRegisterAfterAttachRouter.py b/tests/scripts/thread-cert/Cert_5_6_04_NetworkDataRegisterAfterAttachRouter.py
index ef32030..ab3d9ca 100755
--- a/tests/scripts/thread-cert/Cert_5_6_04_NetworkDataRegisterAfterAttachRouter.py
+++ b/tests/scripts/thread-cert/Cert_5_6_04_NetworkDataRegisterAfterAttachRouter.py
@@ -72,11 +72,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(4)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[ED1].start()
diff --git a/tests/scripts/thread-cert/Cert_5_6_05_NetworkDataRegisterAfterAttachRouter.py b/tests/scripts/thread-cert/Cert_5_6_05_NetworkDataRegisterAfterAttachRouter.py
index ad395dd..232ee23 100755
--- a/tests/scripts/thread-cert/Cert_5_6_05_NetworkDataRegisterAfterAttachRouter.py
+++ b/tests/scripts/thread-cert/Cert_5_6_05_NetworkDataRegisterAfterAttachRouter.py
@@ -72,11 +72,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(4)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[ED1].start()
diff --git a/tests/scripts/thread-cert/Cert_5_6_06_NetworkDataExpiration.py b/tests/scripts/thread-cert/Cert_5_6_06_NetworkDataExpiration.py
index d1b2564..5452f20 100755
--- a/tests/scripts/thread-cert/Cert_5_6_06_NetworkDataExpiration.py
+++ b/tests/scripts/thread-cert/Cert_5_6_06_NetworkDataExpiration.py
@@ -72,11 +72,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(4)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[ED1].start()
diff --git a/tests/scripts/thread-cert/Cert_5_6_07_NetworkDataRequestREED.py b/tests/scripts/thread-cert/Cert_5_6_07_NetworkDataRequestREED.py
index 2e51c79..fd66ef9 100755
--- a/tests/scripts/thread-cert/Cert_5_6_07_NetworkDataRequestREED.py
+++ b/tests/scripts/thread-cert/Cert_5_6_07_NetworkDataRequestREED.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_ADVERTISEMENT, MLE_CHILD_ID_RESPONSE, MLE_DATA_REQUEST, MLE_DATA_RESPONSE, TLV_REQUEST_TLV, NETWORK_DATA_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV
 from pktverify.packet_verifier import PacketVerifier
@@ -119,12 +120,12 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(4)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         for i in range(ROUTER1, ROUTER15 + 1):
             self.nodes[i].start()
-            self.simulator.go(5)
+            self.simulator.go(config.ROUTER_STARTUP_DELAY)
             self.assertEqual(self.nodes[i].get_state(), 'router')
 
         self.nodes[REED1].start()
diff --git a/tests/scripts/thread-cert/Cert_5_6_09_NetworkDataForwarding.py b/tests/scripts/thread-cert/Cert_5_6_09_NetworkDataForwarding.py
index 224b06e..6199996 100755
--- a/tests/scripts/thread-cert/Cert_5_6_09_NetworkDataForwarding.py
+++ b/tests/scripts/thread-cert/Cert_5_6_09_NetworkDataForwarding.py
@@ -78,15 +78,15 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(4)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
         self.nodes[ED].start()
diff --git a/tests/scripts/thread-cert/Cert_5_7_01_CoapDiagCommands.py b/tests/scripts/thread-cert/Cert_5_7_01_CoapDiagCommands.py
index 0fd6ddc..a2b0c40 100755
--- a/tests/scripts/thread-cert/Cert_5_7_01_CoapDiagCommands.py
+++ b/tests/scripts/thread-cert/Cert_5_7_01_CoapDiagCommands.py
@@ -110,11 +110,11 @@
     def test(self):
         # 1 - Form topology
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         for i in range(3, 7):
diff --git a/tests/scripts/thread-cert/Cert_5_7_02_CoapDiagCommands.py b/tests/scripts/thread-cert/Cert_5_7_02_CoapDiagCommands.py
index ee80050..0e89e83 100755
--- a/tests/scripts/thread-cert/Cert_5_7_02_CoapDiagCommands.py
+++ b/tests/scripts/thread-cert/Cert_5_7_02_CoapDiagCommands.py
@@ -159,12 +159,12 @@
     def test(self):
         # 1 - Form topology
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         for i in range(2, 17):
             self.nodes[i].start()
-            self.simulator.go(10)
+            self.simulator.go(config.ROUTER_STARTUP_DELAY)
             self.assertEqual(self.nodes[i].get_state(), 'router')
 
         self.nodes[REED].start()
diff --git a/tests/scripts/thread-cert/Cert_5_7_03_CoapDiagCommands.py b/tests/scripts/thread-cert/Cert_5_7_03_CoapDiagCommands.py
index 1b4e7a2..36b5b98 100755
--- a/tests/scripts/thread-cert/Cert_5_7_03_CoapDiagCommands.py
+++ b/tests/scripts/thread-cert/Cert_5_7_03_CoapDiagCommands.py
@@ -104,11 +104,11 @@
     def test(self):
         # 1 - Form topology
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         for i in range(3, 6):
diff --git a/tests/scripts/thread-cert/Cert_5_8_02_KeyIncrement.py b/tests/scripts/thread-cert/Cert_5_8_02_KeyIncrement.py
index 967a33a..af305c6 100755
--- a/tests/scripts/thread-cert/Cert_5_8_02_KeyIncrement.py
+++ b/tests/scripts/thread-cert/Cert_5_8_02_KeyIncrement.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_ADVERTISEMENT, MLE_CHILD_ID_RESPONSE
 from pktverify.packet_verifier import PacketVerifier
@@ -55,11 +56,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(4)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), "leader")
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), "router")
 
         self.collect_ipaddrs()
diff --git a/tests/scripts/thread-cert/Cert_5_8_03_KeyIncrementRollOver.py b/tests/scripts/thread-cert/Cert_5_8_03_KeyIncrementRollOver.py
index 3bb6e72..382c247 100755
--- a/tests/scripts/thread-cert/Cert_5_8_03_KeyIncrementRollOver.py
+++ b/tests/scripts/thread-cert/Cert_5_8_03_KeyIncrementRollOver.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_ADVERTISEMENT, MLE_CHILD_ID_RESPONSE
 from pktverify.packet_verifier import PacketVerifier
@@ -56,11 +57,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(4)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.collect_ipaddrs()
diff --git a/tests/scripts/thread-cert/Cert_5_8_04_SecurityPolicyTLV.py b/tests/scripts/thread-cert/Cert_5_8_04_SecurityPolicyTLV.py
index 2bf8674..37f5506 100755
--- a/tests/scripts/thread-cert/Cert_5_8_04_SecurityPolicyTLV.py
+++ b/tests/scripts/thread-cert/Cert_5_8_04_SecurityPolicyTLV.py
@@ -30,6 +30,7 @@
 import unittest
 
 from mesh_cop import TlvType
+import config
 import thread_cert
 from pktverify.consts import MLE_DATA_RESPONSE, MGMT_ACTIVE_SET_URI, MGMT_ACTIVE_GET_URI, LEADER_ALOC, NM_COMMISSIONER_SESSION_ID_TLV, NM_ACTIVE_TIMESTAMP_TLV, NM_SECURITY_POLICY_TLV, NM_NETWORK_KEY_TLV, MLE_DISCOVERY_RESPONSE
 from pktverify.packet_verifier import PacketVerifier
@@ -77,7 +78,7 @@
                 'timestamp': 1,
                 'channel': 19,
                 'network_key': '00112233445566778899aabbccddeeff',
-                'security_policy': [3600, 'onrcb']
+                'security_policy': [3600, 'onrc']
             },
             'mode': 'rdn',
         },
@@ -87,7 +88,7 @@
                 'timestamp': 1,
                 'channel': 19,
                 'network_key': '00112233445566778899aabbccddeeff',
-                'security_policy': [3600, 'onrcb']
+                'security_policy': [3600, 'onrc']
             },
             'mode': 'rdn',
             'allowlist': [LEADER]
@@ -103,7 +104,7 @@
                 'timestamp': 1,
                 'channel': 19,
                 'network_key': '00112233445566778899aabbccddeeff',
-                'security_policy': [3600, 'onrcb']
+                'security_policy': [3600, 'onrc']
             },
             'mode': 'rdn',
         },
@@ -111,11 +112,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER_1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER_1].get_state(), 'router')
 
         self.nodes[COMMISSIONER_1].commissioner_start()
@@ -130,10 +131,10 @@
         self.simulator.go(5)
 
         # Step 5
-        # Disabling O-Bit security_policy = [3600, 0b01111000]
+        # Disabling O-Bit security_policy = [3600, 0b01110000]
         self.nodes[COMMISSIONER_1].send_mgmt_active_set(
             active_timestamp=15,
-            security_policy=[3600, 'nrcb'],
+            security_policy=[3600, 'nrc'],
         )
         self.simulator.go(5)
 
@@ -143,10 +144,10 @@
         self.simulator.go(5)
 
         # Step 9
-        # Disabling N-Bit security_policy = [3600, 0b10111000]
+        # Disabling N-Bit security_policy = [3600, 0b10110000]
         self.nodes[COMMISSIONER_1].send_mgmt_active_set(
             active_timestamp=20,
-            security_policy=[3600, 'orcb'],
+            security_policy=[3600, 'orc'],
         )
         self.simulator.go(5)
 
@@ -173,10 +174,10 @@
         self.simulator.go(20)
 
         # Step 17
-        # Disabling R-Bit security_policy = [3600, 0b11011000]
+        # Disabling R-Bit security_policy = [3600, 0b11010000]
         self.nodes[COMMISSIONER_1].send_mgmt_active_set(
             active_timestamp=30,
-            security_policy=[3600, 'oncb'],
+            security_policy=[3600, 'onc'],
         )
         self.simulator.go(5)
 
@@ -209,7 +210,7 @@
         #             2.04 Changed
         #         CoAP Payload
         #             Security Policy TLV
-        #                 Bits “O”,”N”,”R”,”C”,”B” should be set to 1
+        #                 Bits “O”,”N”,”R”,”C” should be set to 1
         pkts.filter_wpan_src64(LEADER).\
             filter_ipv6_dst(COMMISSIONER_1_RLOC).\
             filter_coap_ack(MGMT_ACTIVE_GET_URI).\
@@ -217,9 +218,8 @@
                              p.thread_meshcop.tlv.sec_policy_o == 1 and
                              p.thread_meshcop.tlv.sec_policy_n == 1 and
                              p.thread_meshcop.tlv.sec_policy_r == 1 and
-                             p.thread_meshcop.tlv.sec_policy_c == 1 and
-                             p.thread_meshcop.tlv.sec_policy_b == 1) or
-                            (p.thread_meshcop.tlv.unknown == '0e10ff')).\
+                             p.thread_meshcop.tlv.sec_policy_c == 1) or
+                            (p.thread_meshcop.tlv.unknown == '0e10f7')).\
             must_next()
 
         # Step 5: Commissioner_1 sends MGMT_ACTIVE_SET.req to Leader
@@ -239,7 +239,7 @@
                              }  == set(p.thread_meshcop.tlv.type) and\
                    p.thread_meshcop.tlv.active_tstamp == 15 and\
                    (p.thread_meshcop.tlv.sec_policy_o == 0 or
-                    p.thread_meshcop.tlv.unknown == '0e107f')).\
+                    p.thread_meshcop.tlv.unknown == '0e1077')).\
             must_next()
 
         # Step 6: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner_1
@@ -292,7 +292,7 @@
                              }  == set(p.thread_meshcop.tlv.type) and\
                    p.thread_meshcop.tlv.active_tstamp == 20 and\
                    (p.thread_meshcop.tlv.sec_policy_n == 0 or
-                    p.thread_meshcop.tlv.unknown == '0e10bf')).\
+                    p.thread_meshcop.tlv.unknown == '0e10b7')).\
             must_next()
 
         # Step 10: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner_1
@@ -376,7 +376,7 @@
                              }  == set(p.thread_meshcop.tlv.type) and\
                    p.thread_meshcop.tlv.active_tstamp == 30 and\
                    (p.thread_meshcop.tlv.sec_policy_r == 0 or
-                    p.thread_meshcop.tlv.unknown == '0e10df')).\
+                    p.thread_meshcop.tlv.unknown == '0e10d7')).\
             must_next()
 
         # Step 18: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner_1
@@ -407,7 +407,7 @@
             filter(lambda p:
                    p.mle.tlv.active_tstamp == 30 and\
                    (p.thread_meshcop.tlv.sec_policy_r == 0 or
-                    p.thread_meshcop.tlv.unknown == '0e10df')).\
+                    p.thread_meshcop.tlv.unknown == '0e10d7')).\
             must_next()
 
 
diff --git a/tests/scripts/thread-cert/Cert_6_1_01_RouterAttach.py b/tests/scripts/thread-cert/Cert_6_1_01_RouterAttach.py
index 4867947..59e1895 100755
--- a/tests/scripts/thread-cert/Cert_6_1_01_RouterAttach.py
+++ b/tests/scripts/thread-cert/Cert_6_1_01_RouterAttach.py
@@ -75,7 +75,7 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ED].start()
diff --git a/tests/scripts/thread-cert/Cert_6_1_02_REEDAttach.py b/tests/scripts/thread-cert/Cert_6_1_02_REEDAttach.py
index ce63831..1bbb2d9 100755
--- a/tests/scripts/thread-cert/Cert_6_1_02_REEDAttach.py
+++ b/tests/scripts/thread-cert/Cert_6_1_02_REEDAttach.py
@@ -84,7 +84,7 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[REED].start()
diff --git a/tests/scripts/thread-cert/Cert_6_1_03_RouterAttachConnectivity.py b/tests/scripts/thread-cert/Cert_6_1_03_RouterAttachConnectivity.py
index e5d2dce..3da6d06 100755
--- a/tests/scripts/thread-cert/Cert_6_1_03_RouterAttachConnectivity.py
+++ b/tests/scripts/thread-cert/Cert_6_1_03_RouterAttachConnectivity.py
@@ -73,13 +73,13 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         for i in range(2, 5):
             self.nodes[i].start()
 
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
 
         for i in range(2, 5):
             self.assertEqual(self.nodes[i].get_state(), 'router')
diff --git a/tests/scripts/thread-cert/Cert_6_1_04_REEDAttachConnectivity.py b/tests/scripts/thread-cert/Cert_6_1_04_REEDAttachConnectivity.py
index a073cde..34be7e9 100755
--- a/tests/scripts/thread-cert/Cert_6_1_04_REEDAttachConnectivity.py
+++ b/tests/scripts/thread-cert/Cert_6_1_04_REEDAttachConnectivity.py
@@ -96,11 +96,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         for i in (3, 4):
diff --git a/tests/scripts/thread-cert/Cert_6_1_05_REEDAttachConnectivity.py b/tests/scripts/thread-cert/Cert_6_1_05_REEDAttachConnectivity.py
index 7264fb1..10ed131 100755
--- a/tests/scripts/thread-cert/Cert_6_1_05_REEDAttachConnectivity.py
+++ b/tests/scripts/thread-cert/Cert_6_1_05_REEDAttachConnectivity.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_CHILD_ID_REQUEST, MLE_PARENT_REQUEST, MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, TIMEOUT_TLV, ADDRESS_REGISTRATION_TLV, TLV_REQUEST_TLV, LINK_LOCAL_ALL_ROUTERS_MULTICAST_ADDRESS
 from pktverify.packet_verifier import PacketVerifier
@@ -74,11 +75,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[REED1].start()
@@ -94,6 +95,8 @@
         self.assertEqual(self.nodes[ED].get_state(), 'child')
         self.assertEqual(self.nodes[REED1].get_state(), 'router')
 
+        self.num_parent_requests = 1 if self.nodes[ED].version in ['1.1', '1.2'] else 2
+
         self.collect_ipaddrs()
         addrs = self.nodes[ED].get_addrs()
         for addr in addrs:
@@ -108,12 +111,14 @@
         _reed1_pkts = pkts.filter_wpan_src64(REED_1)
         _ed_pkts = pkts.filter_wpan_src64(ED)
 
-        # Step 2: The DUT MUST send a MLE Parent Request to the
+        # Step 2: The DUT MUST send MLE Parent Requests to the
         # All-Routers multicast address
-        _ed_pkts.filter_mle_cmd(MLE_PARENT_REQUEST).filter_ipv6_dst(
-            LINK_LOCAL_ALL_ROUTERS_MULTICAST_ADDRESS).must_next().must_verify(
-                lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} == set(p.mle.tlv.type
-                                                                                      ) and p.mle.tlv.scan_mask.r == 1)
+
+        for num in range(self.num_parent_requests):
+            _ed_pkts.filter_mle_cmd(MLE_PARENT_REQUEST).filter_ipv6_dst(
+                LINK_LOCAL_ALL_ROUTERS_MULTICAST_ADDRESS).must_next().must_verify(
+                    lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} == set(
+                        p.mle.tlv.type) and p.mle.tlv.scan_mask.r == 1)
 
         # Step 3: REED_1 and REED_2 No response to Parent Request
         # Step 4: DUT Send MLE Parent Request with Scan Mask set to Routers AND REEDs
diff --git a/tests/scripts/thread-cert/Cert_6_1_06_REEDAttachLinkQuality.py b/tests/scripts/thread-cert/Cert_6_1_06_REEDAttachLinkQuality.py
index 73b897a..7b9a23d 100755
--- a/tests/scripts/thread-cert/Cert_6_1_06_REEDAttachLinkQuality.py
+++ b/tests/scripts/thread-cert/Cert_6_1_06_REEDAttachLinkQuality.py
@@ -91,7 +91,7 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[REED].start()
@@ -99,7 +99,7 @@
         self.assertEqual(self.nodes[REED].get_state(), 'child')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[MTD].start()
diff --git a/tests/scripts/thread-cert/Cert_6_1_07_RouterAttachLinkQuality.py b/tests/scripts/thread-cert/Cert_6_1_07_RouterAttachLinkQuality.py
index 75a7aed..64cba50 100755
--- a/tests/scripts/thread-cert/Cert_6_1_07_RouterAttachLinkQuality.py
+++ b/tests/scripts/thread-cert/Cert_6_1_07_RouterAttachLinkQuality.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_CHILD_ID_REQUEST, MLE_PARENT_REQUEST, MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, TIMEOUT_TLV, ADDRESS_REGISTRATION_TLV, TLV_REQUEST_TLV, LINK_LOCAL_ALL_ROUTERS_MULTICAST_ADDRESS
 from pktverify.packet_verifier import PacketVerifier
@@ -66,15 +67,15 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
         self.nodes[ED].start()
diff --git a/tests/scripts/thread-cert/Cert_6_2_01_NewPartition.py b/tests/scripts/thread-cert/Cert_6_2_01_NewPartition.py
index 03d36d7..754cf71 100755
--- a/tests/scripts/thread-cert/Cert_6_2_01_NewPartition.py
+++ b/tests/scripts/thread-cert/Cert_6_2_01_NewPartition.py
@@ -83,11 +83,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[MTD].start()
@@ -95,7 +95,7 @@
         self.assertEqual(self.nodes[MTD].get_state(), 'child')
 
         self.nodes[LEADER].stop()
-        self.simulator.go(140)
+        self.simulator.go(150)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'leader')
         self.assertEqual(self.nodes[MTD].get_state(), 'child')
 
diff --git a/tests/scripts/thread-cert/Cert_6_2_02_NewPartition.py b/tests/scripts/thread-cert/Cert_6_2_02_NewPartition.py
index 5be9b7b..a7fc7a6 100755
--- a/tests/scripts/thread-cert/Cert_6_2_02_NewPartition.py
+++ b/tests/scripts/thread-cert/Cert_6_2_02_NewPartition.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_CHILD_ID_REQUEST, MLE_ADVERTISEMENT, MLE_CHILD_UPDATE_REQUEST, SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV
 from pktverify.packet_verifier import PacketVerifier
@@ -67,15 +68,15 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
         self.nodes[ED].start()
diff --git a/tests/scripts/thread-cert/Cert_6_3_01_OrphanReattach.py b/tests/scripts/thread-cert/Cert_6_3_01_OrphanReattach.py
index fd4887e..216199a 100755
--- a/tests/scripts/thread-cert/Cert_6_3_01_OrphanReattach.py
+++ b/tests/scripts/thread-cert/Cert_6_3_01_OrphanReattach.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_PARENT_REQUEST, MLE_CHILD_ID_REQUEST, MLE_CHILD_UPDATE_REQUEST, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, MODE_TLV
 from pktverify.packet_verifier import PacketVerifier
@@ -61,11 +62,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[ED].start()
diff --git a/tests/scripts/thread-cert/Cert_6_3_02_NetworkDataUpdate.py b/tests/scripts/thread-cert/Cert_6_3_02_NetworkDataUpdate.py
index db0badb..4d8ba34 100755
--- a/tests/scripts/thread-cert/Cert_6_3_02_NetworkDataUpdate.py
+++ b/tests/scripts/thread-cert/Cert_6_3_02_NetworkDataUpdate.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_CHILD_ID_RESPONSE, MLE_DATA_REQUEST, MLE_CHILD_UPDATE_REQUEST, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV, MODE_TLV, TIMEOUT_TLV, TLV_REQUEST_TLV, NETWORK_DATA_TLV
 from pktverify.packet_verifier import PacketVerifier
@@ -55,7 +56,7 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ED].start()
diff --git a/tests/scripts/thread-cert/Cert_6_4_01_LinkLocal.py b/tests/scripts/thread-cert/Cert_6_4_01_LinkLocal.py
index 3faa013..2524e6d 100755
--- a/tests/scripts/thread-cert/Cert_6_4_01_LinkLocal.py
+++ b/tests/scripts/thread-cert/Cert_6_4_01_LinkLocal.py
@@ -75,7 +75,7 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[MTD].start()
diff --git a/tests/scripts/thread-cert/Cert_6_4_02_RealmLocal.py b/tests/scripts/thread-cert/Cert_6_4_02_RealmLocal.py
index e7a47ad..addccfb 100755
--- a/tests/scripts/thread-cert/Cert_6_4_02_RealmLocal.py
+++ b/tests/scripts/thread-cert/Cert_6_4_02_RealmLocal.py
@@ -80,11 +80,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[MTD].start()
diff --git a/tests/scripts/thread-cert/Cert_6_5_01_ChildResetReattach.py b/tests/scripts/thread-cert/Cert_6_5_01_ChildResetReattach.py
index 12a4559..df62743 100755
--- a/tests/scripts/thread-cert/Cert_6_5_01_ChildResetReattach.py
+++ b/tests/scripts/thread-cert/Cert_6_5_01_ChildResetReattach.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_CHILD_ID_REQUEST, MLE_CHILD_UPDATE_REQUEST, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV, ADDRESS_REGISTRATION_TLV, TLV_REQUEST_TLV
 from pktverify.packet_verifier import PacketVerifier
@@ -58,7 +59,7 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ED].start()
diff --git a/tests/scripts/thread-cert/Cert_6_5_02_ChildResetReattach.py b/tests/scripts/thread-cert/Cert_6_5_02_ChildResetReattach.py
index 21ea2e1..05e4355 100755
--- a/tests/scripts/thread-cert/Cert_6_5_02_ChildResetReattach.py
+++ b/tests/scripts/thread-cert/Cert_6_5_02_ChildResetReattach.py
@@ -91,11 +91,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[MTD].start()
diff --git a/tests/scripts/thread-cert/Cert_6_5_03_ChildResetSynchronize.py b/tests/scripts/thread-cert/Cert_6_5_03_ChildResetSynchronize.py
index 0bca598..d925390 100755
--- a/tests/scripts/thread-cert/Cert_6_5_03_ChildResetSynchronize.py
+++ b/tests/scripts/thread-cert/Cert_6_5_03_ChildResetSynchronize.py
@@ -60,7 +60,7 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ED].start()
diff --git a/tests/scripts/thread-cert/Cert_6_6_01_KeyIncrement.py b/tests/scripts/thread-cert/Cert_6_6_01_KeyIncrement.py
index 33343a0..6ad6e6e 100755
--- a/tests/scripts/thread-cert/Cert_6_6_01_KeyIncrement.py
+++ b/tests/scripts/thread-cert/Cert_6_6_01_KeyIncrement.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_ADVERTISEMENT, MLE_CHILD_ID_REQUEST
 from pktverify.packet_verifier import PacketVerifier
@@ -56,7 +57,7 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), "leader")
 
         self.nodes[ED].start()
diff --git a/tests/scripts/thread-cert/Cert_6_6_02_KeyIncrementRollOver.py b/tests/scripts/thread-cert/Cert_6_6_02_KeyIncrementRollOver.py
index d6f8939..d7e0785 100755
--- a/tests/scripts/thread-cert/Cert_6_6_02_KeyIncrementRollOver.py
+++ b/tests/scripts/thread-cert/Cert_6_6_02_KeyIncrementRollOver.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_ADVERTISEMENT, MLE_CHILD_ID_REQUEST
 from pktverify.packet_verifier import PacketVerifier
@@ -57,7 +58,7 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ED].start()
diff --git a/tests/scripts/thread-cert/Cert_7_1_01_BorderRouterAsLeader.py b/tests/scripts/thread-cert/Cert_7_1_01_BorderRouterAsLeader.py
index 83ee5db..7b90d12 100755
--- a/tests/scripts/thread-cert/Cert_7_1_01_BorderRouterAsLeader.py
+++ b/tests/scripts/thread-cert/Cert_7_1_01_BorderRouterAsLeader.py
@@ -98,7 +98,7 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[LEADER].add_prefix(PREFIX_2001, 'paros')
@@ -106,7 +106,7 @@
         self.nodes[LEADER].register_netdata()
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[SED1].start()
diff --git a/tests/scripts/thread-cert/Cert_7_1_02_BorderRouterAsRouter.py b/tests/scripts/thread-cert/Cert_7_1_02_BorderRouterAsRouter.py
index 58323af..61495ea 100755
--- a/tests/scripts/thread-cert/Cert_7_1_02_BorderRouterAsRouter.py
+++ b/tests/scripts/thread-cert/Cert_7_1_02_BorderRouterAsRouter.py
@@ -72,11 +72,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[ROUTER].add_prefix('2001:2:0:1::/64', 'paros')
diff --git a/tests/scripts/thread-cert/Cert_7_1_03_BorderRouterAsLeader.py b/tests/scripts/thread-cert/Cert_7_1_03_BorderRouterAsLeader.py
index c506d7c..03d440e 100755
--- a/tests/scripts/thread-cert/Cert_7_1_03_BorderRouterAsLeader.py
+++ b/tests/scripts/thread-cert/Cert_7_1_03_BorderRouterAsLeader.py
@@ -99,11 +99,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[SED1].start()
diff --git a/tests/scripts/thread-cert/Cert_7_1_04_BorderRouterAsRouter.py b/tests/scripts/thread-cert/Cert_7_1_04_BorderRouterAsRouter.py
index 420fbff..c5490a4 100755
--- a/tests/scripts/thread-cert/Cert_7_1_04_BorderRouterAsRouter.py
+++ b/tests/scripts/thread-cert/Cert_7_1_04_BorderRouterAsRouter.py
@@ -72,11 +72,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[ED2].start()
diff --git a/tests/scripts/thread-cert/Cert_7_1_05_BorderRouterAsRouter.py b/tests/scripts/thread-cert/Cert_7_1_05_BorderRouterAsRouter.py
index ea7b411..3ee96e1 100755
--- a/tests/scripts/thread-cert/Cert_7_1_05_BorderRouterAsRouter.py
+++ b/tests/scripts/thread-cert/Cert_7_1_05_BorderRouterAsRouter.py
@@ -97,11 +97,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[MED].start()
diff --git a/tests/scripts/thread-cert/Cert_7_1_06_BorderRouterAsLeader.py b/tests/scripts/thread-cert/Cert_7_1_06_BorderRouterAsLeader.py
index ad25b4f..f6053cb 100755
--- a/tests/scripts/thread-cert/Cert_7_1_06_BorderRouterAsLeader.py
+++ b/tests/scripts/thread-cert/Cert_7_1_06_BorderRouterAsLeader.py
@@ -113,12 +113,12 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         for i in (2, 3):
             self.nodes[i].start()
-            self.simulator.go(5)
+            self.simulator.go(config.ROUTER_STARTUP_DELAY)
             self.assertEqual(self.nodes[i].get_state(), 'router')
 
         self.nodes[MED].start()
@@ -143,7 +143,7 @@
         self.simulator.go(720)
 
         self.nodes[ROUTER_1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER_1].get_state(), 'router')
         self.collect_rloc16s()
 
diff --git a/tests/scripts/thread-cert/Cert_7_1_07_BorderRouterAsLeader.py b/tests/scripts/thread-cert/Cert_7_1_07_BorderRouterAsLeader.py
index be98014..617fb58 100755
--- a/tests/scripts/thread-cert/Cert_7_1_07_BorderRouterAsLeader.py
+++ b/tests/scripts/thread-cert/Cert_7_1_07_BorderRouterAsLeader.py
@@ -113,12 +113,12 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         for i in (2, 3):
             self.nodes[i].start()
-            self.simulator.go(5)
+            self.simulator.go(config.ROUTER_STARTUP_DELAY)
             self.assertEqual(self.nodes[i].get_state(), 'router')
 
         self.nodes[MED].start()
@@ -146,7 +146,7 @@
 
         # Wait for NETWORK_ID_TIMEOUT taking effect
         # Router_2 creates a new partition
-        self.simulator.go(60)
+        self.simulator.go(80)
         self.assertEqual(self.nodes[ROUTER_2].get_state(), 'leader')
         self.nodes[ROUTER_2].remove_domain_prefix(PREFIX_1)
         self.nodes[ROUTER_2].add_prefix(PREFIX_2, 'paros')
diff --git a/tests/scripts/thread-cert/Cert_7_1_08_BorderRouterAsFED.py b/tests/scripts/thread-cert/Cert_7_1_08_BorderRouterAsFED.py
index a885e65..a431984 100755
--- a/tests/scripts/thread-cert/Cert_7_1_08_BorderRouterAsFED.py
+++ b/tests/scripts/thread-cert/Cert_7_1_08_BorderRouterAsFED.py
@@ -92,11 +92,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[FED].start()
diff --git a/tests/scripts/thread-cert/Cert_8_1_01_Commissioning.py b/tests/scripts/thread-cert/Cert_8_1_01_Commissioning.py
index 1862d70..447ebbb 100755
--- a/tests/scripts/thread-cert/Cert_8_1_01_Commissioning.py
+++ b/tests/scripts/thread-cert/Cert_8_1_01_Commissioning.py
@@ -30,6 +30,7 @@
 import unittest
 
 import command
+import config
 import dtls
 import thread_cert
 from pktverify.consts import MLE_DISCOVERY_REQUEST, MLE_DISCOVERY_RESPONSE, HANDSHAKE_CLIENT_HELLO, HANDSHAKE_SERVER_HELLO, HANDSHAKE_SERVER_KEY_EXCHANGE, HANDSHAKE_SERVER_HELLO_DONE, HANDSHAKE_CLIENT_KEY_EXCHANGE, HANDSHAKE_HELLO_VERIFY_REQUEST, CONTENT_APPLICATION_DATA, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_NAME_TLV, NM_STEERING_DATA_TLV, NM_COMMISSIONER_UDP_PORT_TLV, NM_JOINER_UDP_PORT_TLV, NM_DISCOVERY_REQUEST_TLV, NM_DISCOVERY_RESPONSE_TLV, THREAD_DISCOVERY_TLV, CONTENT_CHANGE_CIPHER_SPEC, CONTENT_HANDSHAKE, CONTENT_ALERT
@@ -77,7 +78,7 @@
     def test(self):
         self.nodes[COMMISSIONER].interface_up()
         self.nodes[COMMISSIONER].thread_start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'leader')
         self.nodes[COMMISSIONER].commissioner_start()
         self.simulator.go(3)
diff --git a/tests/scripts/thread-cert/Cert_8_1_02_Commissioning.py b/tests/scripts/thread-cert/Cert_8_1_02_Commissioning.py
index ca39205..a807700 100755
--- a/tests/scripts/thread-cert/Cert_8_1_02_Commissioning.py
+++ b/tests/scripts/thread-cert/Cert_8_1_02_Commissioning.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_DISCOVERY_RESPONSE, HANDSHAKE_CLIENT_HELLO, HANDSHAKE_SERVER_HELLO, HANDSHAKE_SERVER_KEY_EXCHANGE, HANDSHAKE_SERVER_HELLO_DONE, HANDSHAKE_CLIENT_KEY_EXCHANGE, HANDSHAKE_HELLO_VERIFY_REQUEST, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_NAME_TLV, NM_STEERING_DATA_TLV, NM_COMMISSIONER_UDP_PORT_TLV, NM_JOINER_UDP_PORT_TLV, NM_DISCOVERY_RESPONSE_TLV, CONTENT_CHANGE_CIPHER_SPEC, CONTENT_ALERT, CONTENT_HANDSHAKE
 from pktverify.packet_verifier import PacketVerifier
@@ -56,7 +57,7 @@
     def test(self):
         self.nodes[COMMISSIONER].interface_up()
         self.nodes[COMMISSIONER].thread_start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'leader')
         self.nodes[COMMISSIONER].commissioner_start()
         self.simulator.go(3)
diff --git a/tests/scripts/thread-cert/Cert_8_1_06_Commissioning.py b/tests/scripts/thread-cert/Cert_8_1_06_Commissioning.py
index 249d590..d000929 100755
--- a/tests/scripts/thread-cert/Cert_8_1_06_Commissioning.py
+++ b/tests/scripts/thread-cert/Cert_8_1_06_Commissioning.py
@@ -30,6 +30,7 @@
 import unittest
 
 import command
+import config
 from mesh_cop import MeshCopState
 import thread_cert
 from pktverify.consts import MLE_DISCOVERY_REQUEST, MLE_DISCOVERY_RESPONSE, HANDSHAKE_CLIENT_HELLO, HANDSHAKE_SERVER_HELLO, HANDSHAKE_SERVER_KEY_EXCHANGE, HANDSHAKE_SERVER_HELLO_DONE, HANDSHAKE_CLIENT_KEY_EXCHANGE, HANDSHAKE_HELLO_VERIFY_REQUEST, CONTENT_APPLICATION_DATA, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_NAME_TLV, NM_STEERING_DATA_TLV, NM_COMMISSIONER_UDP_PORT_TLV, NM_JOINER_UDP_PORT_TLV, NM_DISCOVERY_REQUEST_TLV, NM_DISCOVERY_RESPONSE_TLV, THREAD_DISCOVERY_TLV, CONTENT_CHANGE_CIPHER_SPEC, CONTENT_HANDSHAKE, CONTENT_ALERT
@@ -76,7 +77,7 @@
     def test(self):
         self.nodes[COMMISSIONER].interface_up()
         self.nodes[COMMISSIONER].thread_start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'leader')
         self.nodes[COMMISSIONER].commissioner_set_provisioning_url(URL_1)
         self.nodes[COMMISSIONER].commissioner_start()
diff --git a/tests/scripts/thread-cert/Cert_8_2_01_JoinerRouter.py b/tests/scripts/thread-cert/Cert_8_2_01_JoinerRouter.py
index a29f79d..b2951ee 100755
--- a/tests/scripts/thread-cert/Cert_8_2_01_JoinerRouter.py
+++ b/tests/scripts/thread-cert/Cert_8_2_01_JoinerRouter.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_CHILD_ID_RESPONSE, MLE_DISCOVERY_RESPONSE, HANDSHAKE_CLIENT_HELLO, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_NAME_TLV, NM_STEERING_DATA_TLV, NM_COMMISSIONER_UDP_PORT_TLV, NM_JOINER_UDP_PORT_TLV, NM_DISCOVERY_RESPONSE_TLV, RLY_RX_URI, RLY_TX_URI
 from pktverify.packet_verifier import PacketVerifier
@@ -62,7 +63,7 @@
     def test(self):
         self.nodes[COMMISSIONER].interface_up()
         self.nodes[COMMISSIONER].thread_start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].commissioner_start()
diff --git a/tests/scripts/thread-cert/Cert_8_2_02_JoinerRouter.py b/tests/scripts/thread-cert/Cert_8_2_02_JoinerRouter.py
index 8c66444..7ef880b 100755
--- a/tests/scripts/thread-cert/Cert_8_2_02_JoinerRouter.py
+++ b/tests/scripts/thread-cert/Cert_8_2_02_JoinerRouter.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_CHILD_ID_RESPONSE, MLE_DISCOVERY_RESPONSE, HANDSHAKE_CLIENT_HELLO, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_NAME_TLV, NM_STEERING_DATA_TLV, NM_COMMISSIONER_UDP_PORT_TLV, NM_JOINER_UDP_PORT_TLV, NM_DISCOVERY_RESPONSE_TLV, RLY_RX_URI, RLY_TX_URI
 from pktverify.packet_verifier import PacketVerifier
@@ -62,7 +63,7 @@
     def test(self):
         self.nodes[COMMISSIONER].interface_up()
         self.nodes[COMMISSIONER].thread_start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].commissioner_start()
diff --git a/tests/scripts/thread-cert/Cert_8_2_05_JoinerRouter.py b/tests/scripts/thread-cert/Cert_8_2_05_JoinerRouter.py
index 7ef829c..a8f01b2 100755
--- a/tests/scripts/thread-cert/Cert_8_2_05_JoinerRouter.py
+++ b/tests/scripts/thread-cert/Cert_8_2_05_JoinerRouter.py
@@ -30,6 +30,7 @@
 import unittest
 
 import command
+import config
 from mesh_cop import MeshCopState
 import thread_cert
 from pktverify.consts import MLE_CHILD_ID_RESPONSE, MLE_DISCOVERY_RESPONSE, HANDSHAKE_CLIENT_HELLO, HANDSHAKE_HELLO_VERIFY_REQUEST, HANDSHAKE_SERVER_HELLO, HANDSHAKE_SERVER_KEY_EXCHANGE, HANDSHAKE_SERVER_HELLO_DONE, HANDSHAKE_CLIENT_KEY_EXCHANGE, CONTENT_CHANGE_CIPHER_SPEC, CONTENT_HANDSHAKE, CONTENT_APPLICATION_DATA, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_NAME_TLV, NM_STEERING_DATA_TLV, NM_COMMISSIONER_UDP_PORT_TLV, NM_JOINER_UDP_PORT_TLV, NM_DISCOVERY_RESPONSE_TLV, NM_JOINER_DTLS_ENCAPSULATION_TLV, NM_JOINER_UDP_PORT_TLV, NM_JOINER_IID_TLV, NM_JOINER_ROUTER_LOCATOR_TLV, NM_JOINER_ROUTER_KEK_TLV, RLY_RX_URI, RLY_TX_URI
@@ -88,7 +89,7 @@
     def test(self):
         self.nodes[COMMISSIONER].interface_up()
         self.nodes[COMMISSIONER].thread_start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].commissioner_set_provisioning_url(URL_1)
diff --git a/tests/scripts/thread-cert/Cert_8_3_01_CommissionerPetition.py b/tests/scripts/thread-cert/Cert_8_3_01_CommissionerPetition.py
index 03b0564..4c30bfc 100755
--- a/tests/scripts/thread-cert/Cert_8_3_01_CommissionerPetition.py
+++ b/tests/scripts/thread-cert/Cert_8_3_01_CommissionerPetition.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_DATA_RESPONSE, LEAD_PET_URI, LEAD_KA_URI, MGMT_COMMISSIONER_SET_URI, NM_COMMISSIONER_ID_TLV, NM_COMMISSIONER_SESSION_ID_TLV, NM_STATE_TLV, NM_STEERING_DATA_TLV, NM_BORDER_AGENT_LOCATOR_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, SOURCE_ADDRESS_TLV, NWD_COMMISSIONING_DATA_TLV, MESHCOP_ACCEPT, MESHCOP_REJECT
 from pktverify.packet_verifier import PacketVerifier
@@ -77,10 +78,10 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
         self.nodes[COMMISSIONER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
 
         self.collect_rlocs()
diff --git a/tests/scripts/thread-cert/Cert_9_2_01_MGMTCommissionerGet.py b/tests/scripts/thread-cert/Cert_9_2_01_MGMTCommissionerGet.py
index a2ea7c0..9dd8120 100755
--- a/tests/scripts/thread-cert/Cert_9_2_01_MGMTCommissionerGet.py
+++ b/tests/scripts/thread-cert/Cert_9_2_01_MGMTCommissionerGet.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_DATA_RESPONSE, MGMT_COMMISSIONER_GET_URI, NM_CHANNEL_TLV, NM_COMMISSIONER_ID_TLV, NM_COMMISSIONER_SESSION_ID_TLV, NM_STEERING_DATA_TLV, NM_BORDER_AGENT_LOCATOR_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, SOURCE_ADDRESS_TLV, NWD_COMMISSIONING_DATA_TLV, NM_PAN_ID_TLV, NM_NETWORK_NAME_TLV
 from pktverify.packet_verifier import PacketVerifier
@@ -73,11 +74,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
 
         self.collect_leader_aloc(LEADER)
diff --git a/tests/scripts/thread-cert/Cert_9_2_02_MGMTCommissionerSet.py b/tests/scripts/thread-cert/Cert_9_2_02_MGMTCommissionerSet.py
index 9d35f3f..7ece17a 100755
--- a/tests/scripts/thread-cert/Cert_9_2_02_MGMTCommissionerSet.py
+++ b/tests/scripts/thread-cert/Cert_9_2_02_MGMTCommissionerSet.py
@@ -30,6 +30,7 @@
 import unittest
 
 import command
+import config
 import mesh_cop
 import thread_cert
 from pktverify.consts import MLE_DATA_RESPONSE, LEAD_PET_URI, LEAD_KA_URI, MGMT_COMMISSIONER_SET_URI, NM_CHANNEL_TLV, NM_COMMISSIONER_ID_TLV, NM_COMMISSIONER_SESSION_ID_TLV, NM_STATE_TLV, NM_STEERING_DATA_TLV, NM_BORDER_AGENT_LOCATOR_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, SOURCE_ADDRESS_TLV, NWD_COMMISSIONING_DATA_TLV, MESHCOP_ACCEPT, MESHCOP_REJECT, LEADER_ALOC
@@ -74,11 +75,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
         self.simulator.get_messages_sent_by(LEADER)
 
diff --git a/tests/scripts/thread-cert/Cert_9_2_03_ActiveDatasetGet.py b/tests/scripts/thread-cert/Cert_9_2_03_ActiveDatasetGet.py
index b294f89..66ac7d8 100755
--- a/tests/scripts/thread-cert/Cert_9_2_03_ActiveDatasetGet.py
+++ b/tests/scripts/thread-cert/Cert_9_2_03_ActiveDatasetGet.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import mesh_cop
 import thread_cert
 from pktverify.consts import MLE_DATA_RESPONSE, MGMT_ACTIVE_GET_URI, NM_CHANNEL_TLV, NM_COMMISSIONER_ID_TLV, NM_COMMISSIONER_SESSION_ID_TLV, NM_STEERING_DATA_TLV, NM_BORDER_AGENT_LOCATOR_TLV, NM_PAN_ID_TLV, NM_NETWORK_NAME_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_PSKC_TLV, NM_SCAN_DURATION, NM_ENERGY_LIST_TLV, NM_ACTIVE_TIMESTAMP_TLV, NM_CHANNEL_MASK_TLV, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_KEY_TLV, NM_SECURITY_POLICY_TLV, LEADER_ALOC
@@ -74,11 +75,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
 
         self.collect_rlocs()
diff --git a/tests/scripts/thread-cert/Cert_9_2_04_ActiveDataset.py b/tests/scripts/thread-cert/Cert_9_2_04_ActiveDataset.py
index ed1033f..01f1f22 100755
--- a/tests/scripts/thread-cert/Cert_9_2_04_ActiveDataset.py
+++ b/tests/scripts/thread-cert/Cert_9_2_04_ActiveDataset.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_CHILD_ID_RESPONSE, MGMT_ACTIVE_SET_URI, MGMT_ACTIVE_GET_URI
 from pktverify.packet_verifier import PacketVerifier
@@ -64,11 +65,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
 
         self.nodes[COMMISSIONER].commissioner_start()
diff --git a/tests/scripts/thread-cert/Cert_9_2_05_ActiveDataset.py b/tests/scripts/thread-cert/Cert_9_2_05_ActiveDataset.py
index d9af874..3c54cf0 100755
--- a/tests/scripts/thread-cert/Cert_9_2_05_ActiveDataset.py
+++ b/tests/scripts/thread-cert/Cert_9_2_05_ActiveDataset.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_DATA_RESPONSE, MGMT_ACTIVE_SET_URI, NETWORK_DATA_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ACTIVE_TIMESTAMP_TLV, ACTIVE_OPERATION_DATASET_TLV, NM_CHANNEL_TLV, NM_CHANNEL_MASK_TLV, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_NETWORK_KEY_TLV, NM_NETWORK_NAME_TLV, NM_PAN_ID_TLV, NM_PSKC_TLV, NM_SECURITY_POLICY_TLV
 from pktverify.packet_verifier import PacketVerifier
@@ -75,11 +76,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[ROUTER].commissioner_start()
diff --git a/tests/scripts/thread-cert/Cert_9_2_06_DatasetDissemination.py b/tests/scripts/thread-cert/Cert_9_2_06_DatasetDissemination.py
index 1656ea7..a4ff24b 100755
--- a/tests/scripts/thread-cert/Cert_9_2_06_DatasetDissemination.py
+++ b/tests/scripts/thread-cert/Cert_9_2_06_DatasetDissemination.py
@@ -143,11 +143,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
         self.simulator.get_messages_sent_by(LEADER)
         self.nodes[COMMISSIONER].commissioner_start()
@@ -156,7 +156,7 @@
         leader_messages = self.simulator.get_messages_sent_by(LEADER)
         msg = leader_messages.next_coap_message('2.04', assert_enabled=True)
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[MED].start()
diff --git a/tests/scripts/thread-cert/Cert_9_2_07_DelayTimer.py b/tests/scripts/thread-cert/Cert_9_2_07_DelayTimer.py
index d8f4dce..0460f1d 100755
--- a/tests/scripts/thread-cert/Cert_9_2_07_DelayTimer.py
+++ b/tests/scripts/thread-cert/Cert_9_2_07_DelayTimer.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_CHILD_ID_RESPONSE, MLE_DATA_RESPONSE, MGMT_PENDING_SET_URI, MGMT_ACTIVE_SET_URI, MGMT_DATASET_CHANGED_URI, COAP_CODE_ACK, ACTIVE_OPERATION_DATASET_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV, NM_CHANNEL_TLV, NM_CHANNEL_MASK_TLV, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_KEY_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_NETWORK_NAME_TLV, NM_PAN_ID_TLV, NM_PSKC_TLV, NM_SECURITY_POLICY_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ACTIVE_TIMESTAMP_TLV, NETWORK_DATA_TLV, NM_BORDER_AGENT_LOCATOR_TLV, NM_COMMISSIONER_SESSION_ID_TLV, NM_DELAY_TIMER_TLV, PENDING_OPERATION_DATASET_TLV
 from pktverify.packet_verifier import PacketVerifier
@@ -76,11 +77,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
         self.nodes[COMMISSIONER].commissioner_start()
         self.simulator.go(3)
@@ -89,12 +90,12 @@
         self.simulator.go(5)
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'leader')
 
         self.nodes[LEADER].add_allowlist(self.nodes[ROUTER].get_addr64())
         self.nodes[ROUTER].add_allowlist(self.nodes[LEADER].get_addr64())
-        self.simulator.go(20)
+        self.simulator.go(35)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
diff --git a/tests/scripts/thread-cert/Cert_9_2_08_PersistentDatasets.py b/tests/scripts/thread-cert/Cert_9_2_08_PersistentDatasets.py
index 4894388..d64ff04 100755
--- a/tests/scripts/thread-cert/Cert_9_2_08_PersistentDatasets.py
+++ b/tests/scripts/thread-cert/Cert_9_2_08_PersistentDatasets.py
@@ -111,15 +111,15 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
 
         self.nodes[DUT].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         if self.TOPOLOGY[DUT]['mode'] == 'rdn':
             self.assertEqual(self.nodes[DUT].get_state(), 'router')
         else:
@@ -156,7 +156,7 @@
 
         self.assertEqual(self.nodes[DUT].get_panid(), PANID_INIT)
         self.assertEqual(self.nodes[DUT].get_channel(), CHANNEL_INIT)
-        self.simulator.go(30)
+        self.simulator.go(60)
 
         self.assertEqual(self.nodes[DUT].get_panid(), COMMISSIONER_PENDING_PANID)
         self.assertEqual(self.nodes[DUT].get_channel(), COMMISSIONER_PENDING_CHANNEL)
diff --git a/tests/scripts/thread-cert/Cert_9_2_09_PendingPartition.py b/tests/scripts/thread-cert/Cert_9_2_09_PendingPartition.py
index 3452891..a56c47d 100755
--- a/tests/scripts/thread-cert/Cert_9_2_09_PendingPartition.py
+++ b/tests/scripts/thread-cert/Cert_9_2_09_PendingPartition.py
@@ -131,21 +131,21 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
         self.nodes[COMMISSIONER].commissioner_start()
         self.simulator.go(3)
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
         self.nodes[COMMISSIONER].send_mgmt_pending_set(
@@ -643,6 +643,15 @@
                    ).\
             must_next()
 
+        #
+        # Disable steps 32, 33, and 34 until a solution is
+        # found. Depending on timing, there may be one MLE Data
+        # Request/Response exchange for both Active and Pending
+        # Operational Datasets or individual MLE Data Request/Response
+        # exchange for each Active and Pending Operational Dataset
+        # separately.
+        #
+
         # Step 32: Leader sends a MLE Data Response to Commissioner including the following TLVs:
         #             - Source Address TLV
         #             - Leader Data TLV
@@ -656,30 +665,30 @@
         #                 - Channel TLV : ‘Primary’
         #                 - PAN ID TLV : 0xABCD
         #                 - Network Name TLV : 'TEST'
-        with pkts.save_index():
-            pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
-                filter_wpan_src64(LEADER).\
-                filter_wpan_dst64(COMMISSIONER).\
-                filter(lambda p: {
-                                  SOURCE_ADDRESS_TLV,
-                                  LEADER_DATA_TLV,
-                                  ACTIVE_TIMESTAMP_TLV,
-                                  PENDING_TIMESTAMP_TLV,
-                                  PENDING_OPERATION_DATASET_TLV
-                                  } <= set(p.mle.tlv.type) and\
-                       p.thread_nwd.tlv.stable == [0] and\
-                       NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and\
-                       NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and\
-                       NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type and\
-                       p.mle.tlv.active_tstamp == ROUTER2_ACTIVE_TIMESTAMP and\
-                       p.mle.tlv.pending_tstamp == ROUTER2_PENDING_TIMESTAMP and\
-                       p.thread_meshcop.tlv.net_name == [ROUTER2_NET_NAME, ROUTER2_NET_NAME] and\
-                       p.thread_meshcop.tlv.delay_timer < ROUTER2_DELAY_TIMER and\
-                       p.thread_meshcop.tlv.active_tstamp == ROUTER2_PENDING_ACTIVE_TIMESTAMP and\
-                       p.thread_meshcop.tlv.channel == [CHANNEL_INIT, CHANNEL_FINAL] and\
-                       p.thread_meshcop.tlv.pan_id == [PANID_INIT, PANID_FINAL]
-                       ).\
-                must_next()
+        #with pkts.save_index():
+        #    pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
+        #        filter_wpan_src64(LEADER).\
+        #        filter_wpan_dst64(COMMISSIONER).\
+        #        filter(lambda p: {
+        #                          SOURCE_ADDRESS_TLV,
+        #                          LEADER_DATA_TLV,
+        #                          ACTIVE_TIMESTAMP_TLV,
+        #                          PENDING_TIMESTAMP_TLV,
+        #                          PENDING_OPERATION_DATASET_TLV
+        #                          } <= set(p.mle.tlv.type) and\
+        #               p.thread_nwd.tlv.stable == [0] and\
+        #               NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and\
+        #               NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and\
+        #               NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type and\
+        #               p.mle.tlv.active_tstamp == ROUTER2_ACTIVE_TIMESTAMP and\
+        #               p.mle.tlv.pending_tstamp == ROUTER2_PENDING_TIMESTAMP and\
+        #               p.thread_meshcop.tlv.net_name == [ROUTER2_NET_NAME, ROUTER2_NET_NAME] and\
+        #               p.thread_meshcop.tlv.delay_timer < ROUTER2_DELAY_TIMER and\
+        #               p.thread_meshcop.tlv.active_tstamp == ROUTER2_PENDING_ACTIVE_TIMESTAMP and\
+        #               p.thread_meshcop.tlv.channel == [CHANNEL_INIT, CHANNEL_FINAL] and\
+        #               p.thread_meshcop.tlv.pan_id == [PANID_INIT, PANID_FINAL]
+        #               ).\
+        #        must_next()
 
         # Step 33: Router_1 MUST send a unicast MLE Data Request to the Leader, including the
         #          following TLVs:
@@ -687,19 +696,19 @@
         #                - Network Data TLV
         #             - Active Timestamp TLV (10s)
         #             - Pending Timestamp TLV (30s)
-        pkts.filter_wpan_src64(ROUTER_1).\
-            filter_wpan_dst64(LEADER).\
-            filter_mle_cmd(MLE_DATA_REQUEST).\
-            filter(lambda p: {
-                              TLV_REQUEST_TLV,
-                              NETWORK_DATA_TLV,
-                              ACTIVE_TIMESTAMP_TLV
-                              } <= set(p.mle.tlv.type) and\
-                   p.mle.tlv.active_tstamp == TIMESTAMP_INIT and\
-                   p.mle.tlv.pending_tstamp == COMM_PENDING_TIMESTAMP and\
-                   p.thread_meshcop.tlv.type is nullField
-                   ).\
-            must_next()
+        #pkts.filter_wpan_src64(ROUTER_1).\
+        #    filter_wpan_dst64(LEADER).\
+        #    filter_mle_cmd(MLE_DATA_REQUEST).\
+        #    filter(lambda p: {
+        #                      TLV_REQUEST_TLV,
+        #                      NETWORK_DATA_TLV,
+        #                      ACTIVE_TIMESTAMP_TLV
+        #                      } <= set(p.mle.tlv.type) and\
+        #           p.mle.tlv.active_tstamp == TIMESTAMP_INIT and\
+        #           p.mle.tlv.pending_tstamp == COMM_PENDING_TIMESTAMP and\
+        #           p.thread_meshcop.tlv.type is nullField
+        #           ).\
+        #    must_next()
 
         # Step 34: Leader sends a MLE Data Response to Router_1 including the following TLVs:
         #             - Source Address TLV
@@ -713,24 +722,24 @@
         #                 - Delay Timer TLV <~ 200s>
         #                 - Channel TLV : ‘Primary’
         #                 - PAN ID TLV : 0xABCD
-        pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
-            filter_wpan_src64(LEADER).\
-            filter_wpan_dst64(ROUTER_1).\
-            filter(lambda p: {
-                              SOURCE_ADDRESS_TLV,
-                              LEADER_DATA_TLV,
-                              ACTIVE_TIMESTAMP_TLV,
-                              PENDING_TIMESTAMP_TLV,
-                              PENDING_OPERATION_DATASET_TLV
-                              } <= set(p.mle.tlv.type) and\
-                   p.mle.tlv.active_tstamp == ROUTER2_ACTIVE_TIMESTAMP and\
-                   p.mle.tlv.pending_tstamp == ROUTER2_PENDING_TIMESTAMP and\
-                   p.thread_meshcop.tlv.delay_timer < ROUTER2_DELAY_TIMER and\
-                   p.thread_meshcop.tlv.active_tstamp == ROUTER2_PENDING_ACTIVE_TIMESTAMP and\
-                   p.thread_meshcop.tlv.channel == [CHANNEL_INIT, CHANNEL_FINAL] and\
-                   p.thread_meshcop.tlv.pan_id == [PANID_INIT, PANID_FINAL]
-                   ).\
-            must_next()
+        #pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
+        #    filter_wpan_src64(LEADER).\
+        #    filter_wpan_dst64(ROUTER_1).\
+        #    filter(lambda p: {
+        #                      SOURCE_ADDRESS_TLV,
+        #                      LEADER_DATA_TLV,
+        #                      ACTIVE_TIMESTAMP_TLV,
+        #                      PENDING_TIMESTAMP_TLV,
+        #                      PENDING_OPERATION_DATASET_TLV
+        #                      } <= set(p.mle.tlv.type) and\
+        #           p.mle.tlv.active_tstamp == ROUTER2_ACTIVE_TIMESTAMP and\
+        #           p.mle.tlv.pending_tstamp == ROUTER2_PENDING_TIMESTAMP and\
+        #           p.thread_meshcop.tlv.delay_timer < ROUTER2_DELAY_TIMER and\
+        #           p.thread_meshcop.tlv.active_tstamp == ROUTER2_PENDING_ACTIVE_TIMESTAMP and\
+        #           p.thread_meshcop.tlv.channel == [CHANNEL_INIT, CHANNEL_FINAL] and\
+        #           p.thread_meshcop.tlv.pan_id == [PANID_INIT, PANID_FINAL]
+        #           ).\
+        #    must_next()
 
         # Step 36: The DUT MUST respond with an ICMPv6 Echo Reply
         _pkt = pkts.filter_ping_request().\
diff --git a/tests/scripts/thread-cert/Cert_9_2_10_PendingPartition.py b/tests/scripts/thread-cert/Cert_9_2_10_PendingPartition.py
index 3479a9b..c5c6345 100755
--- a/tests/scripts/thread-cert/Cert_9_2_10_PendingPartition.py
+++ b/tests/scripts/thread-cert/Cert_9_2_10_PendingPartition.py
@@ -100,17 +100,17 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
         self.nodes[COMMISSIONER].commissioner_start()
         self.simulator.go(3)
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ED1].start()
diff --git a/tests/scripts/thread-cert/Cert_9_2_11_NetworkKey.py b/tests/scripts/thread-cert/Cert_9_2_11_NetworkKey.py
index 514f5b3..e63a860 100755
--- a/tests/scripts/thread-cert/Cert_9_2_11_NetworkKey.py
+++ b/tests/scripts/thread-cert/Cert_9_2_11_NetworkKey.py
@@ -135,17 +135,17 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
         self.nodes[COMMISSIONER].commissioner_start()
         self.simulator.go(3)
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ED1].start()
diff --git a/tests/scripts/thread-cert/Cert_9_2_12_Announce.py b/tests/scripts/thread-cert/Cert_9_2_12_Announce.py
index ec2d4f2..f0dd65e 100755
--- a/tests/scripts/thread-cert/Cert_9_2_12_Announce.py
+++ b/tests/scripts/thread-cert/Cert_9_2_12_Announce.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_CHILD_ID_REQUEST, MLE_PARENT_REQUEST, MLE_CHILD_ID_RESPONSE, MLE_ANNOUNCE, CHANNEL_TLV, PAN_ID_TLV, ACTIVE_TIMESTAMP_TLV, LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS
 from pktverify.packet_verifier import PacketVerifier
@@ -93,13 +94,13 @@
 
     def test(self):
         self.nodes[LEADER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER1].get_state(), 'leader')
         self.nodes[LEADER1].commissioner_start()
         self.simulator.go(3)
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[LEADER2].start()
diff --git a/tests/scripts/thread-cert/Cert_9_2_13_EnergyScan.py b/tests/scripts/thread-cert/Cert_9_2_13_EnergyScan.py
index 667610e..3e9df47 100755
--- a/tests/scripts/thread-cert/Cert_9_2_13_EnergyScan.py
+++ b/tests/scripts/thread-cert/Cert_9_2_13_EnergyScan.py
@@ -67,17 +67,17 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
         self.nodes[COMMISSIONER].commissioner_start()
         self.simulator.go(5)
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ED].start()
diff --git a/tests/scripts/thread-cert/Cert_9_2_14_PanIdQuery.py b/tests/scripts/thread-cert/Cert_9_2_14_PanIdQuery.py
index bc2c0e0..e97a720 100755
--- a/tests/scripts/thread-cert/Cert_9_2_14_PanIdQuery.py
+++ b/tests/scripts/thread-cert/Cert_9_2_14_PanIdQuery.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_CHILD_ID_REQUEST, MGMT_PANID_QUERY, MGMT_PANID_CONFLICT, MGMT_ED_REPORT, NM_COMMISSIONER_SESSION_ID_TLV, NM_CHANNEL_MASK_TLV, NM_PAN_ID_TLV, REALM_LOCAL_All_THREAD_NODES_MULTICAST_ADDRESS
 from pktverify.packet_verifier import PacketVerifier
@@ -68,21 +69,21 @@
 
     def test(self):
         self.nodes[LEADER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER1].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
         self.nodes[COMMISSIONER].commissioner_start()
         self.simulator.go(3)
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[LEADER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER2].get_state(), 'leader')
 
         self.collect_rlocs()
diff --git a/tests/scripts/thread-cert/Cert_9_2_15_PendingPartition.py b/tests/scripts/thread-cert/Cert_9_2_15_PendingPartition.py
index f73e99f..13d3e2b 100755
--- a/tests/scripts/thread-cert/Cert_9_2_15_PendingPartition.py
+++ b/tests/scripts/thread-cert/Cert_9_2_15_PendingPartition.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_REQUEST, MLE_CHILD_ID_RESPONSE, MLE_CHILD_ID_REQUEST, MGMT_ACTIVE_SET_URI, MGMT_ACTIVE_GET_URI, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV, TLV_REQUEST_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, ADDRESS_REGISTRATION_TLV
 from pktverify.packet_verifier import PacketVerifier
@@ -98,17 +99,17 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
         self.nodes[COMMISSIONER].commissioner_start()
         self.simulator.go(3)
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[COMMISSIONER].send_mgmt_pending_set(
@@ -120,7 +121,7 @@
         self.simulator.go(5)
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
         self.nodes[ROUTER2].reset()
@@ -137,7 +138,7 @@
         self.simulator.go(100)
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
         self.simulator.go(100)
 
diff --git a/tests/scripts/thread-cert/Cert_9_2_16_ActivePendingPartition.py b/tests/scripts/thread-cert/Cert_9_2_16_ActivePendingPartition.py
index d2044d5..e257f28 100755
--- a/tests/scripts/thread-cert/Cert_9_2_16_ActivePendingPartition.py
+++ b/tests/scripts/thread-cert/Cert_9_2_16_ActivePendingPartition.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_REQUEST, MLE_CHILD_ID_RESPONSE, MLE_CHILD_ID_REQUEST, MGMT_ACTIVE_SET_URI, MGMT_ACTIVE_GET_URI, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV, TLV_REQUEST_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, ADDRESS_REGISTRATION_TLV
 from pktverify.packet_verifier import PacketVerifier
@@ -99,17 +100,17 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
         self.nodes[COMMISSIONER].commissioner_start()
         self.simulator.go(3)
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[COMMISSIONER].send_mgmt_pending_set(
@@ -121,7 +122,7 @@
         self.simulator.go(5)
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
         self.nodes[ROUTER2].reset()
@@ -141,7 +142,7 @@
         self.simulator.go(100)
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
         self.assertEqual(self.nodes[COMMISSIONER].get_network_name(), NETWORK_NAME_FINAL)
diff --git a/tests/scripts/thread-cert/Cert_9_2_17_Orphan.py b/tests/scripts/thread-cert/Cert_9_2_17_Orphan.py
index c9faea1..9fce65e 100755
--- a/tests/scripts/thread-cert/Cert_9_2_17_Orphan.py
+++ b/tests/scripts/thread-cert/Cert_9_2_17_Orphan.py
@@ -82,7 +82,7 @@
 
     def test(self):
         self.nodes[LEADER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER1].get_state(), 'leader')
 
         self.nodes[LEADER2].start()
@@ -116,10 +116,10 @@
 
         # Step 1: Ensure the topology is formed correctly
         # Verify that Leader_1 & Leader_2 are sending MLE Advertisements on separate channels.
+        pkts.copy().filter_wpan_src64(LEADER_1).filter_mle_cmd(MLE_ADVERTISEMENT).must_next()
+        pkts.copy().filter_wpan_src64(LEADER_2).filter_mle_cmd(MLE_ADVERTISEMENT).must_next()
         pkts.filter_wpan_src64(LEADER_1).filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next().must_verify(
             lambda p: p.wpan.dst64 == ED and p.thread_meshcop.tlv.channel == [CHANNEL1])
-        pkts.filter_wpan_src64(LEADER_1).filter_mle_cmd(MLE_ADVERTISEMENT).must_next()
-        pkts.copy().filter_wpan_src64(LEADER_2).filter_mle_cmd(MLE_ADVERTISEMENT).must_next()
 
         # Step 4: powers-down Leader_1 and enables connectivity between the ED and Leader_2
         # ED MUST send a MLE Parent Request
diff --git a/tests/scripts/thread-cert/Cert_9_2_18_RollBackActiveTimestamp.py b/tests/scripts/thread-cert/Cert_9_2_18_RollBackActiveTimestamp.py
index 8e7ba54..5c809ea 100755
--- a/tests/scripts/thread-cert/Cert_9_2_18_RollBackActiveTimestamp.py
+++ b/tests/scripts/thread-cert/Cert_9_2_18_RollBackActiveTimestamp.py
@@ -111,17 +111,17 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
         self.nodes[COMMISSIONER].commissioner_start()
         self.simulator.go(3)
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ED1].start()
diff --git a/tests/scripts/thread-cert/Cert_9_2_19_PendingDatasetGet.py b/tests/scripts/thread-cert/Cert_9_2_19_PendingDatasetGet.py
index 0a1d792..ab0842d 100755
--- a/tests/scripts/thread-cert/Cert_9_2_19_PendingDatasetGet.py
+++ b/tests/scripts/thread-cert/Cert_9_2_19_PendingDatasetGet.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import mesh_cop
 import thread_cert
 from pktverify.consts import MGMT_PENDING_GET_URI, MGMT_PENDING_SET_URI, NM_CHANNEL_TLV, NM_PAN_ID_TLV, NM_NETWORK_NAME_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_PSKC_TLV, NM_ACTIVE_TIMESTAMP_TLV, NM_CHANNEL_MASK_TLV, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_KEY_TLV, NM_SECURITY_POLICY_TLV, NM_PENDING_TIMESTAMP_TLV, NM_DELAY_TIMER_TLV, LEADER_ALOC
@@ -73,11 +74,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[COMMISSIONER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
         self.simulator.get_messages_sent_by(LEADER)
 
diff --git a/tests/scripts/thread-cert/Makefile.am b/tests/scripts/thread-cert/Makefile.am
index 43356a1..d6e4210 100644
--- a/tests/scripts/thread-cert/Makefile.am
+++ b/tests/scripts/thread-cert/Makefile.am
@@ -153,6 +153,7 @@
     sniffer_transport.py                                             \
     test_anycast.py                                                  \
     test_anycast_locator.py                                          \
+    test_br_upgrade_router_role.py                                   \
     test_coap.py                                                     \
     test_coap_block.py                                               \
     test_coap_observe.py                                             \
@@ -160,9 +161,11 @@
     test_common.py                                                   \
     test_crypto.py                                                   \
     test_dataset_updater.py                                          \
+    test_detach.py                                                   \
     test_diag.py                                                     \
     test_dns_client_config_auto_start.py                             \
     test_dnssd.py                                                    \
+    test_dnssd_name_with_special_chars.py                            \
     test_history_tracker.py                                          \
     test_inform_previous_parent_on_reattach.py                       \
     test_ipv6.py                                                     \
@@ -170,28 +173,35 @@
     test_ipv6_source_selection.py                                    \
     test_lowpan.py                                                   \
     test_mac802154.py                                                \
+    test_mac_scan.py                                                 \
     test_mle.py                                                      \
+    test_mle_msg_key_seq_jump.py                                     \
     test_netdata_publisher.py                                        \
     test_network_data.py                                             \
     test_network_layer.py                                            \
     test_on_mesh_prefix.py                                           \
     test_pbbr_aloc.py                                                \
     test_ping.py                                                     \
+    test_radio_filter.py                                             \
     test_reed_address_solicit_rejected.py                            \
     test_reset.py                                                    \
     test_route_table.py                                              \
     test_router_reattach.py                                          \
+    test_router_upgrade.py                                           \
     test_service.py                                                  \
     test_set_mliid.py                                                \
+    test_srp_auto_host_address.py                                    \
     test_srp_auto_start_mode.py                                      \
     test_srp_client_remove_host.py                                   \
     test_srp_client_save_server_info.py                              \
     test_srp_lease.py                                                \
+    test_srp_many_services_mtu_check.py                              \
     test_srp_name_conflicts.py                                       \
     test_srp_register_single_service.py                              \
     test_srp_server_anycast_mode.py                                  \
     test_srp_server_reboot_port.py                                   \
     test_srp_sub_type.py                                             \
+    test_srp_ttl.py                                                  \
     test_zero_len_external_route.py                                  \
     thread_cert.py                                                   \
     tlvs_parsing.py                                                  \
@@ -224,6 +234,7 @@
 check_SCRIPTS                                                      = \
     test_anycast.py                                                  \
     test_anycast_locator.py                                          \
+    test_br_upgrade_router_role.py                                   \
     test_coap.py                                                     \
     test_coap_block.py                                               \
     test_coap_observe.py                                             \
@@ -231,9 +242,11 @@
     test_common.py                                                   \
     test_crypto.py                                                   \
     test_dataset_updater.py                                          \
+    test_detach.py                                                   \
     test_diag.py                                                     \
     test_dns_client_config_auto_start.py                             \
     test_dnssd.py                                                    \
+    test_dnssd_name_with_special_chars.py                            \
     test_history_tracker.py                                          \
     test_inform_previous_parent_on_reattach.py                       \
     test_ipv6.py                                                     \
@@ -241,27 +254,34 @@
     test_ipv6_source_selection.py                                    \
     test_lowpan.py                                                   \
     test_mac802154.py                                                \
+    test_mac_scan.py                                                 \
     test_mle.py                                                      \
+    test_mle_msg_key_seq_jump.py                                     \
     test_netdata_publisher.py                                        \
     test_network_data.py                                             \
     test_network_layer.py                                            \
     test_on_mesh_prefix.py                                           \
     test_pbbr_aloc.py                                                \
     test_ping.py                                                     \
+    test_radio_filter.py                                             \
     test_reed_address_solicit_rejected.py                            \
     test_reset.py                                                    \
     test_route_table.py                                              \
     test_router_reattach.py                                          \
+    test_router_upgrade.py                                           \
     test_service.py                                                  \
+    test_srp_auto_host_address.py                                    \
     test_srp_auto_start_mode.py                                      \
     test_srp_client_remove_host.py                                   \
     test_srp_client_save_server_info.py                              \
     test_srp_lease.py                                                \
+    test_srp_many_services_mtu_check.py                              \
     test_srp_name_conflicts.py                                       \
     test_srp_register_single_service.py                              \
     test_srp_server_anycast_mode.py                                  \
     test_srp_server_reboot_port.py                                   \
     test_srp_sub_type.py                                             \
+    test_srp_ttl.py                                                  \
     test_zero_len_external_route.py                                  \
     Cert_5_1_01_RouterAttach.py                                      \
     Cert_5_1_02_ChildAddressTimeout.py                               \
diff --git a/tests/scripts/thread-cert/backbone/bbr_5_11_01.py b/tests/scripts/thread-cert/backbone/bbr_5_11_01.py
index d0adf59..63d2b08 100755
--- a/tests/scripts/thread-cert/backbone/bbr_5_11_01.py
+++ b/tests/scripts/thread-cert/backbone/bbr_5_11_01.py
@@ -81,7 +81,7 @@
         self.nodes[ROUTER1].set_weight(72)
         self.nodes[ROUTER1].start()
 
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', self.nodes[ROUTER1].get_state())
 
         self.nodes[ROUTER2].start()
diff --git a/tests/scripts/thread-cert/backbone/test_bmlr.py b/tests/scripts/thread-cert/backbone/test_bmlr.py
index 1d2ccce..990038c 100644
--- a/tests/scripts/thread-cert/backbone/test_bmlr.py
+++ b/tests/scripts/thread-cert/backbone/test_bmlr.py
@@ -39,6 +39,7 @@
 import unittest
 
 import thread_cert
+import config
 from pktverify.packet_verifier import PacketVerifier
 
 PBBR = 1
@@ -87,7 +88,7 @@
 
     def test(self):
         self.nodes[PBBR].start()
-        self.wait_node_state(PBBR, 'leader', 5)
+        self.wait_node_state(PBBR, 'leader', 10)
         self.nodes[PBBR].set_backbone_router(reg_delay=REREG_DELAY, mlr_timeout=MLR_TIMEOUT)
         self.nodes[PBBR].enable_backbone_router()
         self.wait_until(lambda: self.nodes[PBBR].is_primary_backbone_router, 5)
@@ -189,11 +190,12 @@
             thread_meshcop.tlv.ipv6_addr == ['{MA5}']
             and thread_nm.tlv.timeout == 0
         """)
-        # Verify PBBR not sends `/b/bmr` on the Backbone link for MA5.
-        pkts.filter_eth_src(PBBR_ETH).filter_coap_request('/b/bmr').filter(f"""
+        # Verify PBBR sends `/b/bmr` on the Backbone link for MA5 with timeout equal to zero.
+        pkts.filter_eth_src(PBBR_ETH).filter_coap_request('/b/bmr').must_next().must_verify(f"""
             thread_meshcop.tlv.ipv6_addr == ['{MA5}']
+            and thread_bl.tlv.timeout == 0
             and ipv6.src.is_link_local
-        """).must_not_next()
+        """)
 
 
 if __name__ == '__main__':
diff --git a/tests/scripts/thread-cert/backbone/test_dua_dad.py b/tests/scripts/thread-cert/backbone/test_dua_dad.py
index 9239978..9fe2a87 100644
--- a/tests/scripts/thread-cert/backbone/test_dua_dad.py
+++ b/tests/scripts/thread-cert/backbone/test_dua_dad.py
@@ -121,9 +121,9 @@
 
         # Bring up PBBR
         self.nodes[PBBR].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', self.nodes[PBBR].get_state())
-        self.wait_node_state(PBBR, 'leader', 5)
+        self.wait_node_state(PBBR, 'leader', 10)
 
         self.nodes[PBBR].set_backbone_router(reg_delay=REREG_DELAY, mlr_timeout=MLR_TIMEOUT)
         self.nodes[PBBR].enable_backbone_router()
@@ -152,9 +152,9 @@
 
         # Bring up PBBR2
         self.nodes[PBBR2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', self.nodes[PBBR2].get_state())
-        self.wait_node_state(PBBR2, 'leader', 5)
+        self.wait_node_state(PBBR2, 'leader', 10)
 
         self.nodes[PBBR2].set_backbone_router(reg_delay=REREG_DELAY, mlr_timeout=MLR_TIMEOUT)
         self.nodes[PBBR2].enable_backbone_router()
diff --git a/tests/scripts/thread-cert/backbone/test_dua_routing.py b/tests/scripts/thread-cert/backbone/test_dua_routing.py
index 11cd8e5..3c3c249 100644
--- a/tests/scripts/thread-cert/backbone/test_dua_routing.py
+++ b/tests/scripts/thread-cert/backbone/test_dua_routing.py
@@ -70,6 +70,7 @@
             'is_otbr': True,
             'version': '1.2',
             'channel': CH1,
+            'router_id_range': [0, 30],
         },
         SBBR: {
             'name': 'SBBR',
@@ -93,6 +94,7 @@
             'is_otbr': True,
             'version': '1.2',
             'channel': CH2,
+            'router_id_range': [31, 60],
         },
         ROUTER2: {
             'name': 'ROUTER2',
@@ -107,9 +109,9 @@
 
         # Bring up PBBR
         self.nodes[PBBR].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', self.nodes[PBBR].get_state())
-        self.wait_node_state(PBBR, 'leader', 5)
+        self.wait_node_state(PBBR, 'leader', 10)
 
         self.nodes[PBBR].set_backbone_router(reg_delay=REREG_DELAY, mlr_timeout=MLR_TIMEOUT)
         self.nodes[PBBR].enable_backbone_router()
@@ -137,9 +139,9 @@
 
         # Bring up PBBR2
         self.nodes[PBBR2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', self.nodes[PBBR2].get_state())
-        self.wait_node_state(PBBR2, 'leader', 5)
+        self.wait_node_state(PBBR2, 'leader', 10)
 
         self.nodes[PBBR2].set_backbone_router(reg_delay=REREG_DELAY, mlr_timeout=MLR_TIMEOUT)
         self.nodes[PBBR2].enable_backbone_router()
diff --git a/tests/scripts/thread-cert/backbone/test_dua_routing_med.py b/tests/scripts/thread-cert/backbone/test_dua_routing_med.py
new file mode 100644
index 0000000..fd908b8
--- /dev/null
+++ b/tests/scripts/thread-cert/backbone/test_dua_routing_med.py
@@ -0,0 +1,275 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2021, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+# This test verifies that PBBR sets DUA routes correctly.
+#
+import ipaddress
+import unittest
+
+import config
+import thread_cert
+from pktverify.consts import ADDR_QRY_URI, BACKBONE_QUERY_URI, BACKBONE_ANSWER_URI, ADDR_NTF_URI
+from pktverify.packet_verifier import PacketVerifier
+
+# Use two channels
+CH1 = 11
+CH2 = 22
+
+PBBR = 1
+ROUTER1 = 2
+MED1 = 3
+HOST = 4
+PBBR2 = 5
+MED2 = 6
+
+REREG_DELAY = 5  # Seconds
+MLR_TIMEOUT = 300  # Seconds
+WAIT_REDUNDANCE = 3
+
+
+class TestDuaRoutingMed(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+
+    # Topology:
+    #    ------(eth)----------------------
+    #       |        |       |
+    #      PBBR     HOST   PBBR2
+    #     / CH1\            | CH2
+    #   MED1  ROUTER1      MED2
+    #
+    # PBBR2 is in the secondary channel
+    #
+    TOPOLOGY = {
+        PBBR: {
+            'name': 'PBBR',
+            'allowlist': [MED1, ROUTER1],
+            'is_otbr': True,
+            'version': '1.2',
+            'channel': CH1,
+        },
+        ROUTER1: {
+            'name': 'ROUTER1',
+            'allowlist': [PBBR],
+            'version': '1.2',
+            'channel': CH1,
+        },
+        MED1: {
+            'name': 'MED1',
+            'allowlist': [PBBR],
+            'version': '1.2',
+            'channel': CH1,
+            'mode': 'rn',
+        },
+        HOST: {
+            'name': 'HOST',
+            'is_host': True
+        },
+        PBBR2: {
+            'name': 'PBBR2',
+            'is_otbr': True,
+            'version': '1.2',
+            'channel': CH2,
+        },
+        MED2: {
+            'name': 'MED2',
+            'version': '1.2',
+            'channel': CH2,
+            'mode': 'rn',
+        },
+    }
+
+    def _bootstrap(self):
+        # Bring up HOST
+        self.nodes[HOST].start()
+
+        # Bring up PBBR
+        self.nodes[PBBR].start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual('leader', self.nodes[PBBR].get_state())
+        self.wait_node_state(PBBR, 'leader', 10)
+
+        self.nodes[PBBR].set_backbone_router(reg_delay=REREG_DELAY, mlr_timeout=MLR_TIMEOUT)
+        self.nodes[PBBR].enable_backbone_router()
+        self.nodes[PBBR].set_domain_prefix(config.DOMAIN_PREFIX, 'prosD')
+        self.simulator.go(5)
+        self.assertTrue(self.nodes[PBBR].is_primary_backbone_router)
+        self.assertIsNotNone(self.nodes[PBBR].get_ip6_address(config.ADDRESS_TYPE.DUA))
+
+        # Bring up ROUTER1
+        self.nodes[ROUTER1].start()
+        self.simulator.go(5)
+        self.assertEqual('router', self.nodes[ROUTER1].get_state())
+        self.assertIsNotNone(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.DUA))
+
+        # Bring up MED1
+        self.nodes[MED1].start()
+        self.simulator.go(5)
+        self.assertEqual('child', self.nodes[MED1].get_state())
+        self.assertIsNotNone(self.nodes[MED1].get_ip6_address(config.ADDRESS_TYPE.DUA))
+
+        # Bring up PBBR2
+        self.nodes[PBBR2].start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual('leader', self.nodes[PBBR2].get_state())
+        self.wait_node_state(PBBR2, 'leader', 10)
+
+        self.nodes[PBBR2].set_backbone_router(reg_delay=REREG_DELAY, mlr_timeout=MLR_TIMEOUT)
+        self.nodes[PBBR2].enable_backbone_router()
+        self.nodes[PBBR2].set_domain_prefix(config.DOMAIN_PREFIX, 'prosD')
+        self.simulator.go(5)
+        self.assertTrue(self.nodes[PBBR2].is_primary_backbone_router)
+        self.assertIsNotNone(self.nodes[PBBR2].get_ip6_address(config.ADDRESS_TYPE.DUA))
+
+        # Bring up MED2
+        self.nodes[MED2].start()
+        self.simulator.go(5)
+        self.assertEqual('child', self.nodes[MED2].get_state())
+        self.assertIsNotNone(self.nodes[MED2].get_ip6_address(config.ADDRESS_TYPE.DUA))
+
+    def test(self):
+        self._bootstrap()
+
+        self.collect_ipaddrs()
+        self.collect_rloc16s()
+
+        self.simulator.go(10)
+
+        # PBBR2 pings MED2
+        self.assertTrue(self.nodes[PBBR2].ping(self.nodes[MED2].get_ip6_address(config.ADDRESS_TYPE.DUA)))
+        self.simulator.go(WAIT_REDUNDANCE)
+
+        # MED2 pings PBBR2
+        self.assertTrue(self.nodes[MED2].ping(self.nodes[PBBR2].get_ip6_address(config.ADDRESS_TYPE.DUA)))
+        self.simulator.go(WAIT_REDUNDANCE)
+
+        # PBBR pings PBBR2
+        self.nodes[PBBR].ping(self.nodes[PBBR2].get_ip6_address(config.ADDRESS_TYPE.DUA))
+        self.simulator.go(WAIT_REDUNDANCE)
+
+        # MED1 pings ROUTER1 should succeed
+        self.assertTrue(self.nodes[MED1].ping(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.DUA)))
+        self.simulator.go(WAIT_REDUNDANCE)
+
+        # MED1 pings MED2 which should succeed
+        MED2_DUA = self.nodes[MED2].get_ip6_address(config.ADDRESS_TYPE.DUA)
+        self.assertTrue(self.nodes[MED1].ping(MED2_DUA))
+        self.simulator.go(WAIT_REDUNDANCE)
+
+    def _get_mliid(self, nodeid: int) -> str:
+        mleid = self.nodes[nodeid].get_ip6_address(config.ADDRESS_TYPE.ML_EID)
+        mliid = ipaddress.IPv6Address(mleid).packed[-8:]
+        return ''.join(['%02x' % b for b in mliid])
+
+    def verify(self, pv: PacketVerifier):
+        pkts = pv.pkts
+        pv.add_common_vars()
+        pv.summary.show()
+
+        PBBR = pv.vars['PBBR']
+        ROUTER1 = pv.vars['ROUTER1']
+        PBBR2 = pv.vars['PBBR2']
+        MED1 = pv.vars['MED1']
+        MED2 = pv.vars['MED2']
+        MED1_DUA = pv.vars['MED1_DUA']
+        ROUTER1_DUA = pv.vars['ROUTER1_DUA']
+        PBBR_DUA = pv.vars['PBBR_DUA']
+        PBBR2_DUA = pv.vars['PBBR2_DUA']
+        MED2_DUA = pv.vars['MED2_DUA']
+        PBBR_ETH = pv.vars['PBBR_ETH']
+        PBBR2_ETH = pv.vars['PBBR2_ETH']
+
+        # PBBR should never send Address Query for MED1 (Child)
+        pkts.filter_wpan_src64(PBBR).filter_RLARMA().filter_coap_request(ADDR_QRY_URI) \
+            .filter('thread_address.tlv.target_eid == {eid}', eid=MED1_DUA) \
+            .must_not_next()
+
+        # PBBR2 should never send Address Query for MED2 (Child)
+        pkts.filter_wpan_src64(PBBR2).filter_RLARMA().filter_coap_request(ADDR_QRY_URI) \
+            .filter('thread_address.tlv.target_eid == {eid}', eid=MED2_DUA) \
+            .must_not_next()
+
+        # MEDs should never send Address Query
+        pkts.filter_wpan_src64(MED1).filter_RLARMA().filter_coap_request(ADDR_QRY_URI).must_not_next()
+        pkts.filter_wpan_src64(MED2).filter_RLARMA().filter_coap_request(ADDR_QRY_URI).must_not_next()
+
+        # PBBR pings PBBR2 should succeed
+        ping_id = pkts.filter_ipv6_src_dst(
+            PBBR_DUA, PBBR2_DUA).filter_eth_src(PBBR_ETH).filter_ping_request().must_next().icmpv6.echo.identifier
+        pkts.filter_ipv6_src_dst(PBBR2_DUA,
+                                 PBBR_DUA).filter_eth_src(PBBR2_ETH).filter_ping_reply(identifier=ping_id).must_next()
+
+        # MED1 pings ROUTER1
+        ping_request_pkts = pkts.filter_ipv6_src_dst(MED1_DUA, ROUTER1_DUA)
+        # MED1 sends the Ping Request
+        ping_pkt = ping_request_pkts.filter_wpan_src64(MED1).filter_ping_request().must_next()
+        ping_id = ping_pkt.icmpv6.echo.identifier
+        # PBBR sends Address Query for ROUTER1_DUA
+        pkts.filter_wpan_src64(PBBR).filter_RLARMA().filter_coap_request(ADDR_QRY_URI) \
+            .filter('thread_address.tlv.target_eid == {eid}', eid=ROUTER1_DUA) \
+            .must_next()
+        # PBBR sends Backbone Query for ROUTER1_DUA
+        pkts.filter_eth_src(PBBR_ETH).filter_coap_request(BACKBONE_QUERY_URI) \
+            .filter('thread_bl.tlv.target_eid == {eid}', eid=ROUTER1_DUA) \
+            .must_next()
+        # ROUTER1 sends Address Answer for ROUTER1_DUA
+        pkts.filter_wpan_src64(ROUTER1).filter_coap_request(ADDR_NTF_URI, confirmable=True) \
+            .filter('thread_address.tlv.target_eid == {eid}', eid=ROUTER1_DUA) \
+            .must_next()
+        # PBBR forwards Ping Request to ROUTER1, decreasing TTL by 1
+        ping_request_pkts.filter_wpan_src64(PBBR).filter_ping_request(identifier=ping_id).must_next().must_verify(
+            'ipv6.hlim == {hlim}', hlim=ping_pkt.ipv6.hlim - 1)
+
+        # MED1 pings MED2
+        # Verify Ping Request: MED1 -> PBBR -> PBBR2 -> MED2
+        ping_request_pkts = pkts.filter_ipv6_src_dst(MED1_DUA, MED2_DUA)
+        # MED1 sends the Ping Request
+        ping_pkt = ping_request_pkts.filter_wpan_src64(MED1).filter_ping_request().must_next()
+        ping_id = ping_pkt.icmpv6.echo.identifier
+        # PBBR sends Address Query for MED2_DUA
+        pkts.filter_wpan_src64(PBBR).filter_RLARMA().filter_coap_request(ADDR_QRY_URI) \
+            .filter('thread_address.tlv.target_eid == {eid}', eid=MED2_DUA) \
+            .must_next()
+        # PBBR sends Backbone Query for MED2_DUA
+        pkts.filter_eth_src(PBBR_ETH).filter_coap_request(BACKBONE_QUERY_URI) \
+            .filter('thread_bl.tlv.target_eid == {eid}', eid=MED2_DUA) \
+            .must_next()
+        # PBBR2 sends Backbone Answer for MED2_DUA
+        pkts.filter_eth_src(PBBR2_ETH).filter_coap_request(BACKBONE_ANSWER_URI, confirmable=True) \
+            .filter('thread_bl.tlv.target_eid == {eid}', eid=MED2_DUA) \
+            .must_next()
+        # PBBR forwards Ping Request to Backbone link, decreasing TTL by 1
+        ping_request_pkts.filter_eth_src(PBBR_ETH).filter_ping_request(identifier=ping_id).must_next().must_verify(
+            'ipv6.hlim == {hlim}', hlim=ping_pkt.ipv6.hlim - 1)
+        ping_request_pkts.filter_wpan_src64(PBBR2).filter_ping_request(identifier=ping_id).must_next()
+        # Verify Ping Reply: MED2 -> PBBR2 -> PBBR -> MED1
+        ping_reply_pkts = pkts.filter_ipv6_src_dst(MED2_DUA, MED1_DUA).filter_ping_reply(identifier=ping_id)
+        ping_reply_pkts.filter_eth_src(PBBR2_ETH).must_next()
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/backbone/test_mle_must_not_send_icmpv6_destination_unreachable.py b/tests/scripts/thread-cert/backbone/test_mle_must_not_send_icmpv6_destination_unreachable.py
index bb6d09c..40221fd 100644
--- a/tests/scripts/thread-cert/backbone/test_mle_must_not_send_icmpv6_destination_unreachable.py
+++ b/tests/scripts/thread-cert/backbone/test_mle_must_not_send_icmpv6_destination_unreachable.py
@@ -31,6 +31,7 @@
 import unittest
 
 import thread_cert
+import config
 from pktverify.consts import ICMPV6_TYPE_DESTINATION_UNREACHABLE
 from pktverify.packet_verifier import PacketVerifier
 
@@ -63,7 +64,7 @@
 
     def test(self):
         self.nodes[PBBR].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', self.nodes[PBBR].get_state())
         self.nodes[PBBR].enable_backbone_router()
         self.simulator.go(3)
diff --git a/tests/scripts/thread-cert/backbone/test_mlr_multicast_routing.py b/tests/scripts/thread-cert/backbone/test_mlr_multicast_routing.py
index cd8cb70..762ce13 100644
--- a/tests/scripts/thread-cert/backbone/test_mlr_multicast_routing.py
+++ b/tests/scripts/thread-cert/backbone/test_mlr_multicast_routing.py
@@ -128,7 +128,7 @@
 
         # Bring up Leader
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', self.nodes[LEADER].get_state())
 
         # Bring up Router
@@ -212,9 +212,6 @@
         self.nodes[nodeid].del_ipmaddr(ma)
         self.simulator.go(1)
 
-        # Verify MA is not reachable from Host after unsubscribed
-        self.assertFalse(self.nodes[HOST].ping(ma, backbone=True, ttl=10))
-
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/scripts/thread-cert/backbone/test_mlr_multicast_routing_across_thread_pans.py b/tests/scripts/thread-cert/backbone/test_mlr_multicast_routing_across_thread_pans.py
index 1abb932..8da0c1c 100644
--- a/tests/scripts/thread-cert/backbone/test_mlr_multicast_routing_across_thread_pans.py
+++ b/tests/scripts/thread-cert/backbone/test_mlr_multicast_routing_across_thread_pans.py
@@ -102,7 +102,7 @@
 
         # Bring up PBBR1
         self.nodes[PBBR1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', self.nodes[PBBR1].get_state())
 
         self.nodes[PBBR1].enable_backbone_router()
@@ -121,7 +121,7 @@
 
         # Bring up PBBR2
         self.nodes[PBBR2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', self.nodes[PBBR2].get_state())
 
         self.nodes[PBBR2].enable_backbone_router()
diff --git a/tests/scripts/thread-cert/backbone/test_mlr_multicast_routing_commissioner_timeout.py b/tests/scripts/thread-cert/backbone/test_mlr_multicast_routing_commissioner_timeout.py
index 4ba2b7b..1ced307 100644
--- a/tests/scripts/thread-cert/backbone/test_mlr_multicast_routing_commissioner_timeout.py
+++ b/tests/scripts/thread-cert/backbone/test_mlr_multicast_routing_commissioner_timeout.py
@@ -29,6 +29,7 @@
 # This test verifies that the MLR timeout configured by Commissioner works for multicast routing.
 #
 import unittest
+import config
 
 from pktverify.consts import NM_COMMISSIONER_SESSION_ID_TLV
 from pktverify.packet_verifier import PacketVerifier
@@ -66,12 +67,12 @@
         self.simulator.go(WAIT_REDUNDANCE)
 
         # Ping 2: PBBR should forward to Thread network
-        self.assertFalse(self.nodes[HOST].ping(MA1, backbone=True, ttl=10))
+        self.nodes[HOST].ping(MA1, backbone=True, ttl=10)
 
         self.simulator.go(MLR_TIMEOUT + WAIT_REDUNDANCE)
 
         # Ping 3: PBBR should forward to Thread network
-        self.assertFalse(self.nodes[HOST].ping(MA1, backbone=True, ttl=10))
+        self.nodes[HOST].ping(MA1, backbone=True, ttl=10)
 
         self.simulator.go(COMMISSIONER_MLR_TIMEOUT - MLR_TIMEOUT)
 
diff --git a/tests/scripts/thread-cert/backbone/test_mlr_multicast_routing_timeout.py b/tests/scripts/thread-cert/backbone/test_mlr_multicast_routing_timeout.py
index a443ede..fcedbde 100644
--- a/tests/scripts/thread-cert/backbone/test_mlr_multicast_routing_timeout.py
+++ b/tests/scripts/thread-cert/backbone/test_mlr_multicast_routing_timeout.py
@@ -81,7 +81,7 @@
 
         # Bring up PBBR
         self.nodes[PBBR].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', self.nodes[PBBR].get_state())
         self.nodes[PBBR].enable_backbone_router()
         self.nodes[PBBR].set_backbone_router(reg_delay=REG_DELAY, mlr_timeout=MLR_TIMEOUT)
@@ -116,7 +116,7 @@
 
         # Verify MA is not reachable from Host after unsubscribed
         # But PBBR should still forward the Ping Requests to Thread network
-        self.assertFalse(self.nodes[HOST].ping(MA1, backbone=True, ttl=10))
+        self.nodes[HOST].ping(MA1, backbone=True, ttl=10)
 
         self.simulator.go(MLR_TIMEOUT + WAIT_REDUNDANCE)
 
diff --git a/tests/scripts/thread-cert/backbone/test_ndproxy.py b/tests/scripts/thread-cert/backbone/test_ndproxy.py
index dbb2274..bab1c71 100644
--- a/tests/scripts/thread-cert/backbone/test_ndproxy.py
+++ b/tests/scripts/thread-cert/backbone/test_ndproxy.py
@@ -88,9 +88,9 @@
 
         # Bring up PBBR
         self.nodes[PBBR].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', self.nodes[PBBR].get_state())
-        self.wait_node_state(PBBR, 'leader', 5)
+        self.wait_node_state(PBBR, 'leader', 10)
 
         self.nodes[PBBR].set_backbone_router(reg_delay=REREG_DELAY, mlr_timeout=MLR_TIMEOUT)
         self.nodes[PBBR].enable_backbone_router()
diff --git a/etc/cmake/checks.cmake b/tests/scripts/thread-cert/border_router/LowPower/v1_2_LowPower_5_3_01_SSEDAttachment_BR.py
similarity index 81%
rename from etc/cmake/checks.cmake
rename to tests/scripts/thread-cert/border_router/LowPower/v1_2_LowPower_5_3_01_SSEDAttachment_BR.py
index ab7bb88..56f0c09 100644
--- a/etc/cmake/checks.cmake
+++ b/tests/scripts/thread-cert/border_router/LowPower/v1_2_LowPower_5_3_01_SSEDAttachment_BR.py
@@ -1,5 +1,6 @@
+#!/usr/bin/env python3
 #
-#  Copyright (c) 2019, The OpenThread Authors.
+#  Copyright (c) 2022, The OpenThread Authors.
 #  All rights reserved.
 #
 #  Redistribution and use in source and binary forms, with or without
@@ -26,4 +27,12 @@
 #  POSSIBILITY OF SUCH DAMAGE.
 #
 
-configure_file(${PROJECT_SOURCE_DIR}/etc/cmake/openthread-config-generic.h.in ${PROJECT_BINARY_DIR}/etc/cmake/openthread-config-generic.h)
+import unittest
+
+from v1_2_LowPower_5_3_01_SSEDAttachment import LowPower_5_3_01_SSEDAttachment
+from v1_2_LowPower_5_3_01_SSEDAttachment import LEADER
+
+LowPower_5_3_01_SSEDAttachment.TOPOLOGY[LEADER]['is_otbr'] = True
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/etc/cmake/checks.cmake b/tests/scripts/thread-cert/border_router/LowPower/v1_2_LowPower_7_1_01_SingleProbeLinkMetricsWithEnhancedAcks_BR.py
old mode 100644
new mode 100755
similarity index 79%
copy from etc/cmake/checks.cmake
copy to tests/scripts/thread-cert/border_router/LowPower/v1_2_LowPower_7_1_01_SingleProbeLinkMetricsWithEnhancedAcks_BR.py
index ab7bb88..cadf8e3
--- a/etc/cmake/checks.cmake
+++ b/tests/scripts/thread-cert/border_router/LowPower/v1_2_LowPower_7_1_01_SingleProbeLinkMetricsWithEnhancedAcks_BR.py
@@ -1,5 +1,6 @@
+#!/usr/bin/env python3
 #
-#  Copyright (c) 2019, The OpenThread Authors.
+#  Copyright (c) 2022, The OpenThread Authors.
 #  All rights reserved.
 #
 #  Redistribution and use in source and binary forms, with or without
@@ -13,7 +14,7 @@
 #     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"
+#  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
@@ -26,4 +27,12 @@
 #  POSSIBILITY OF SUCH DAMAGE.
 #
 
-configure_file(${PROJECT_SOURCE_DIR}/etc/cmake/openthread-config-generic.h.in ${PROJECT_BINARY_DIR}/etc/cmake/openthread-config-generic.h)
+import unittest
+
+from v1_2_LowPower_7_1_01_SingleProbeLinkMetricsWithEnhancedAcks import LowPower_7_1_01
+from v1_2_LowPower_7_1_01_SingleProbeLinkMetricsWithEnhancedAcks import LEADER
+
+LowPower_7_1_01.TOPOLOGY[LEADER]['is_otbr'] = True
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/etc/cmake/checks.cmake b/tests/scripts/thread-cert/border_router/LowPower/v1_2_LowPower_7_2_01_ForwardTrackingSeries_BR.py
old mode 100644
new mode 100755
similarity index 80%
copy from etc/cmake/checks.cmake
copy to tests/scripts/thread-cert/border_router/LowPower/v1_2_LowPower_7_2_01_ForwardTrackingSeries_BR.py
index ab7bb88..92c7dd9
--- a/etc/cmake/checks.cmake
+++ b/tests/scripts/thread-cert/border_router/LowPower/v1_2_LowPower_7_2_01_ForwardTrackingSeries_BR.py
@@ -1,5 +1,6 @@
+#!/usr/bin/env python3
 #
-#  Copyright (c) 2019, The OpenThread Authors.
+#  Copyright (c) 2022, The OpenThread Authors.
 #  All rights reserved.
 #
 #  Redistribution and use in source and binary forms, with or without
@@ -26,4 +27,11 @@
 #  POSSIBILITY OF SUCH DAMAGE.
 #
 
-configure_file(${PROJECT_SOURCE_DIR}/etc/cmake/openthread-config-generic.h.in ${PROJECT_BINARY_DIR}/etc/cmake/openthread-config-generic.h)
+import unittest
+
+from v1_2_LowPower_7_2_01_ForwardTrackingSeries import LEADER
+from v1_2_LowPower_7_2_01_ForwardTrackingSeries import LowPower_7_2_01_ForwardTrackingSeries
+
+LowPower_7_2_01_ForwardTrackingSeries.TOPOLOGY[LEADER]['is_otbr'] = True
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/border_router/MATN_02_MLRFirstUse.py b/tests/scripts/thread-cert/border_router/MATN/MATN_02_MLRFirstUse.py
similarity index 99%
rename from tests/scripts/thread-cert/border_router/MATN_02_MLRFirstUse.py
rename to tests/scripts/thread-cert/border_router/MATN/MATN_02_MLRFirstUse.py
index 1994025..db215e6 100644
--- a/tests/scripts/thread-cert/border_router/MATN_02_MLRFirstUse.py
+++ b/tests/scripts/thread-cert/border_router/MATN/MATN_02_MLRFirstUse.py
@@ -97,7 +97,7 @@
         host = self.nodes[HOST]
 
         br1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br1.get_state())
         self.assertTrue(br1.is_primary_backbone_router)
 
diff --git a/tests/scripts/thread-cert/border_router/MATN_03_InvalidCommissionerDeregistration.py b/tests/scripts/thread-cert/border_router/MATN/MATN_03_InvalidCommissionerDeregistration.py
similarity index 98%
rename from tests/scripts/thread-cert/border_router/MATN_03_InvalidCommissionerDeregistration.py
rename to tests/scripts/thread-cert/border_router/MATN/MATN_03_InvalidCommissionerDeregistration.py
index 272f794..1d9de65 100644
--- a/tests/scripts/thread-cert/border_router/MATN_03_InvalidCommissionerDeregistration.py
+++ b/tests/scripts/thread-cert/border_router/MATN/MATN_03_InvalidCommissionerDeregistration.py
@@ -90,7 +90,7 @@
         host = self.nodes[HOST]
 
         br1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br1.get_state())
         self.assertTrue(br1.is_primary_backbone_router)
 
diff --git a/tests/scripts/thread-cert/border_router/MATN_04_MulticastListenerTimeout.py b/tests/scripts/thread-cert/border_router/MATN/MATN_04_MulticastListenerTimeout.py
similarity index 99%
rename from tests/scripts/thread-cert/border_router/MATN_04_MulticastListenerTimeout.py
rename to tests/scripts/thread-cert/border_router/MATN/MATN_04_MulticastListenerTimeout.py
index b24a708..119529f 100644
--- a/tests/scripts/thread-cert/border_router/MATN_04_MulticastListenerTimeout.py
+++ b/tests/scripts/thread-cert/border_router/MATN/MATN_04_MulticastListenerTimeout.py
@@ -94,7 +94,7 @@
 
         br1.set_backbone_router(reg_delay=REG_DELAY, mlr_timeout=consts.MLR_TIMEOUT_MIN)
         br1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br1.get_state())
         self.assertTrue(br1.is_primary_backbone_router)
 
diff --git a/tests/scripts/thread-cert/border_router/MATN_05_ReregistrationToSameMulticastGroup.py b/tests/scripts/thread-cert/border_router/MATN/MATN_05_ReregistrationToSameMulticastGroup.py
similarity index 99%
rename from tests/scripts/thread-cert/border_router/MATN_05_ReregistrationToSameMulticastGroup.py
rename to tests/scripts/thread-cert/border_router/MATN/MATN_05_ReregistrationToSameMulticastGroup.py
index 7eaa590..e931127 100644
--- a/tests/scripts/thread-cert/border_router/MATN_05_ReregistrationToSameMulticastGroup.py
+++ b/tests/scripts/thread-cert/border_router/MATN/MATN_05_ReregistrationToSameMulticastGroup.py
@@ -95,7 +95,7 @@
 
         br1.set_backbone_router(reg_delay=REG_DELAY, mlr_timeout=consts.MLR_TIMEOUT_MIN)
         br1.start()
-        self.simulator.go(10)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br1.get_state())
         self.assertTrue(br1.is_primary_backbone_router)
 
diff --git a/tests/scripts/thread-cert/border_router/MATN_09_DefaultBRMulticastForwarding.py b/tests/scripts/thread-cert/border_router/MATN/MATN_09_DefaultBRMulticastForwarding.py
similarity index 98%
rename from tests/scripts/thread-cert/border_router/MATN_09_DefaultBRMulticastForwarding.py
rename to tests/scripts/thread-cert/border_router/MATN/MATN_09_DefaultBRMulticastForwarding.py
index 3f2bf08..5e92a37 100644
--- a/tests/scripts/thread-cert/border_router/MATN_09_DefaultBRMulticastForwarding.py
+++ b/tests/scripts/thread-cert/border_router/MATN/MATN_09_DefaultBRMulticastForwarding.py
@@ -87,7 +87,7 @@
         router1 = self.nodes[ROUTER_1]
 
         br1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br1.get_state())
         self.assertTrue(br1.is_primary_backbone_router)
 
diff --git a/tests/scripts/thread-cert/border_router/MATN_12_HopLimitProcessing.py b/tests/scripts/thread-cert/border_router/MATN/MATN_12_HopLimitProcessing.py
similarity index 97%
rename from tests/scripts/thread-cert/border_router/MATN_12_HopLimitProcessing.py
rename to tests/scripts/thread-cert/border_router/MATN/MATN_12_HopLimitProcessing.py
index cf11ddd..c51c048 100644
--- a/tests/scripts/thread-cert/border_router/MATN_12_HopLimitProcessing.py
+++ b/tests/scripts/thread-cert/border_router/MATN/MATN_12_HopLimitProcessing.py
@@ -85,7 +85,7 @@
         host = self.nodes[HOST]
 
         br1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br1.get_state())
         self.assertTrue(br1.is_primary_backbone_router)
 
@@ -114,12 +114,11 @@
         # 4. Host multicasts a ping packet to the multicast address, MA1, with
         # the IPv6 Hop Limit field set to 1. The size of the payload is 130
         # bytes.
-        self.assertFalse(
-            host.ping(MA1,
-                      backbone=True,
-                      ttl=1,
-                      size=130,
-                      interface=host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0]))
+        host.ping(MA1,
+                  backbone=True,
+                  ttl=1,
+                  size=130,
+                  interface=host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0])
         self.simulator.go(5)
 
         # 6. Router_1 sends a ping packet encapsulated in an MPL packet to the
diff --git a/tests/scripts/thread-cert/border_router/MATN_15_ChangeOfPrimaryBBRTriggersRegistration.py b/tests/scripts/thread-cert/border_router/MATN/MATN_15_ChangeOfPrimaryBBRTriggersRegistration.py
similarity index 98%
rename from tests/scripts/thread-cert/border_router/MATN_15_ChangeOfPrimaryBBRTriggersRegistration.py
rename to tests/scripts/thread-cert/border_router/MATN/MATN_15_ChangeOfPrimaryBBRTriggersRegistration.py
index 8a75068..71c7da2 100644
--- a/tests/scripts/thread-cert/border_router/MATN_15_ChangeOfPrimaryBBRTriggersRegistration.py
+++ b/tests/scripts/thread-cert/border_router/MATN/MATN_15_ChangeOfPrimaryBBRTriggersRegistration.py
@@ -106,7 +106,7 @@
 
         br1.set_backbone_router(reg_delay=REG_DELAY, mlr_timeout=consts.MLR_TIMEOUT_MIN)
         br1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br1.get_state())
         self.assertTrue(br1.is_primary_backbone_router)
 
diff --git a/tests/scripts/thread-cert/border_router/MATN_16_LargeNumberOfMulticastGroupSubscriptionsToBBR.py b/tests/scripts/thread-cert/border_router/MATN/MATN_16_LargeNumberOfMulticastGroupSubscriptionsToBBR.py
similarity index 96%
rename from tests/scripts/thread-cert/border_router/MATN_16_LargeNumberOfMulticastGroupSubscriptionsToBBR.py
rename to tests/scripts/thread-cert/border_router/MATN/MATN_16_LargeNumberOfMulticastGroupSubscriptionsToBBR.py
index 44c4634..d5a2ae1 100644
--- a/tests/scripts/thread-cert/border_router/MATN_16_LargeNumberOfMulticastGroupSubscriptionsToBBR.py
+++ b/tests/scripts/thread-cert/border_router/MATN/MATN_16_LargeNumberOfMulticastGroupSubscriptionsToBBR.py
@@ -91,7 +91,7 @@
 
         br1.set_backbone_router(reg_delay=REG_DELAY, mlr_timeout=consts.MLR_TIMEOUT_MIN)
         br1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br1.get_state())
         self.assertTrue(br1.is_primary_backbone_router)
 
@@ -113,11 +113,10 @@
         for i in range(1, 6):
             # 5. Host sends a ping packet to the multicast address,
             # MASi[ 3 * i - 1], on the backbone link.
-            self.assertFalse(
-                host.ping(MAS[i][i * 3 - 1],
-                          backbone=True,
-                          ttl=64,
-                          interface=host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0]))
+            host.ping(MAS[i][i * 3 - 1],
+                      backbone=True,
+                      ttl=64,
+                      interface=host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0])
 
             self.simulator.go(3)
 
diff --git a/tests/scripts/thread-cert/border_router/nat64/test_multi_border_routers.py b/tests/scripts/thread-cert/border_router/nat64/test_multi_border_routers.py
new file mode 100644
index 0000000..8ce9e0d
--- /dev/null
+++ b/tests/scripts/thread-cert/border_router/nat64/test_multi_border_routers.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+import unittest
+
+import config
+import thread_cert
+
+# Test description:
+#   This test verifies that a single NAT64 prefix is advertised when there are
+#   multiple Border Routers in the same Thread and infrastructure network.
+#
+#   TODO: add checks for outbound connectivity from Thread device to IPv4 host
+#         after OTBR change is ready.
+#
+# Topology:
+#    ----------------(eth)--------------------------
+#           |                 |             |
+#          BR1 (Leader) ---- BR2           HOST
+#           |
+#        ROUTER
+#
+
+BR1 = 1
+ROUTER = 2
+BR2 = 3
+HOST = 4
+
+
+class Nat64MultiBorderRouter(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+
+    TOPOLOGY = {
+        BR1: {
+            'name': 'BR1',
+            'allowlist': [ROUTER, BR2],
+            'is_otbr': True,
+            'version': '1.2',
+        },
+        ROUTER: {
+            'name': 'Router',
+            'allowlist': [BR1],
+            'version': '1.2',
+        },
+        BR2: {
+            'name': 'BR2',
+            'allowlist': [BR1],
+            'is_otbr': True,
+            'version': '1.2'
+        },
+        HOST: {
+            'name': 'Host',
+            'is_host': True
+        },
+    }
+
+    def test(self):
+        br1 = self.nodes[BR1]
+        router = self.nodes[ROUTER]
+        br2 = self.nodes[BR2]
+        host = self.nodes[HOST]
+
+        host.start(start_radvd=False)
+        self.simulator.go(5)
+
+        br1.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual('leader', br1.get_state())
+
+        router.start()
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
+        self.assertEqual('router', router.get_state())
+
+        #
+        # Case 1. BR2 joins the network later and it will not add
+        #         its local nat64 prefix to Network Data.
+        #
+        br2.start()
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
+        self.assertEqual('router', br2.get_state())
+
+        # Only 1 NAT64 prefix in Network Data.
+        self.simulator.go(30)
+        self.assertEqual(len(br1.get_netdata_nat64_prefix()), 1)
+        self.assertEqual(len(br2.get_netdata_nat64_prefix()), 1)
+        self.assertEqual(br1.get_netdata_nat64_prefix()[0], br2.get_netdata_nat64_prefix()[0])
+        nat64_prefix = br1.get_netdata_nat64_prefix()[0]
+
+        # The NAT64 prefix in Network Data is same as BR1's local NAT64 prefix.
+        br1_nat64_prefix = br1.get_br_nat64_prefix()
+        br2_nat64_prefix = br2.get_br_nat64_prefix()
+        self.assertEqual(nat64_prefix, br1_nat64_prefix)
+        self.assertNotEqual(nat64_prefix, br2_nat64_prefix)
+
+        #
+        # Case 2. Disable and re-enable border routing on BR1.
+        #
+        br1.disable_br()
+        self.simulator.go(30)
+
+        # BR1 withdraws its prefix and BR2 advertises its prefix.
+        self.assertEqual(len(br1.get_netdata_nat64_prefix()), 1)
+        self.assertEqual(br2_nat64_prefix, br1.get_netdata_nat64_prefix()[0])
+        self.assertNotEqual(br1_nat64_prefix, br1.get_netdata_nat64_prefix()[0])
+
+        br1.enable_br()
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
+
+        # NAT64 prefix in Network Data is still advertised by BR2.
+        self.assertEqual(len(br1.get_netdata_nat64_prefix()), 1)
+        self.assertEqual(br2_nat64_prefix, br1.get_netdata_nat64_prefix()[0])
+        self.assertNotEqual(br1_nat64_prefix, br1.get_netdata_nat64_prefix()[0])
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/border_router/nat64/test_single_border_router.py b/tests/scripts/thread-cert/border_router/nat64/test_single_border_router.py
new file mode 100644
index 0000000..a301cda
--- /dev/null
+++ b/tests/scripts/thread-cert/border_router/nat64/test_single_border_router.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+import unittest
+
+import config
+import thread_cert
+
+# Test description:
+#   This test verifies the advertisement of NAT64 prefix in Thread network.
+#
+#   TODO: add checks for outbound connectivity from Thread device to IPv4 host
+#         after OTBR change is ready.
+#
+# Topology:
+#    ----------------(eth)--------------------
+#           |                 |
+#          BR (Leader)      HOST
+#           |
+#        ROUTER
+#
+
+BR = 1
+ROUTER = 2
+HOST = 3
+
+# The prefix is set small enough that a random-generated NAT64 prefix is very
+# likely greater than it. So that the BR will remove the random-generated one.
+SMALL_NAT64_PREFIX = "fd00:00:00:01:00:00::/96"
+
+
+class Nat64SingleBorderRouter(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+
+    TOPOLOGY = {
+        BR: {
+            'name': 'BR',
+            'allowlist': [ROUTER],
+            'is_otbr': True,
+            'version': '1.2',
+        },
+        ROUTER: {
+            'name': 'Router',
+            'allowlist': [BR],
+            'version': '1.2',
+        },
+        HOST: {
+            'name': 'Host',
+            'is_host': True
+        },
+    }
+
+    def test(self):
+        br = self.nodes[BR]
+        router = self.nodes[ROUTER]
+        host = self.nodes[HOST]
+
+        host.start(start_radvd=False)
+        self.simulator.go(5)
+
+        br.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual('leader', br.get_state())
+
+        router.start()
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
+        self.assertEqual('router', router.get_state())
+
+        #
+        # Case 1. Border router advertises its local NAT64 prefix.
+        #
+        self.simulator.go(5)
+        local_nat64_prefix = br.get_br_nat64_prefix()
+
+        self.assertEqual(len(br.get_netdata_nat64_prefix()), 1)
+        nat64_prefix = br.get_netdata_nat64_prefix()[0]
+        self.assertEqual(nat64_prefix, local_nat64_prefix)
+
+        #
+        # Case 2.
+        # User adds a smaller NAT64 prefix and the local prefix is withdrawn.
+        # User removes the smaller NAT64 prefix and the local prefix is re-added.
+        #
+        br.add_route(SMALL_NAT64_PREFIX, stable=False, nat64=True)
+        br.register_netdata()
+        self.simulator.go(5)
+
+        self.assertEqual(len(br.get_netdata_nat64_prefix()), 1)
+        self.assertNotEqual(local_nat64_prefix, br.get_netdata_nat64_prefix()[0])
+
+        br.remove_route(SMALL_NAT64_PREFIX)
+        br.register_netdata()
+        self.simulator.go(5)
+
+        self.assertEqual(len(br.get_netdata_nat64_prefix()), 1)
+        self.assertEqual(local_nat64_prefix, br.get_netdata_nat64_prefix()[0])
+
+        #
+        # Case 3. Disable and re-enable border routing on the border router.
+        #
+        br.disable_br()
+        self.simulator.go(5)
+
+        # NAT64 prefix is withdrawn from Network Data.
+        self.assertEqual(len(br.get_netdata_nat64_prefix()), 0)
+
+        br.enable_br()
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
+
+        # Same NAT64 prefix is advertised to Network Data.
+        self.assertEqual(len(br.get_netdata_nat64_prefix()), 1)
+        self.assertEqual(nat64_prefix, br.get_netdata_nat64_prefix()[0])
+
+        #
+        # Case 4. Disable and re-enable ethernet on the border router.
+        #
+        br.disable_ether()
+        self.simulator.go(5)
+
+        # NAT64 prefix is withdrawn from Network Data.
+        self.assertEqual(len(br.get_netdata_nat64_prefix()), 0)
+
+        br.enable_ether()
+        self.simulator.go(80)
+
+        # Same NAT64 prefix is advertised to Network Data.
+        self.assertEqual(len(br.get_netdata_nat64_prefix()), 1)
+        self.assertEqual(nat64_prefix, br.get_netdata_nat64_prefix()[0])
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/border_router/test_advertising_proxy.py b/tests/scripts/thread-cert/border_router/test_advertising_proxy.py
index a6cb689..0c088dc 100755
--- a/tests/scripts/thread-cert/border_router/test_advertising_proxy.py
+++ b/tests/scripts/thread-cert/border_router/test_advertising_proxy.py
@@ -85,12 +85,12 @@
         server.srp_server_set_enabled(True)
         server.srp_server_set_lease_range(LEASE, LEASE, KEY_LEASE, KEY_LEASE)
         server.start()
-        self.simulator.go(10)
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
         self.assertEqual('leader', server.get_state())
         self.assertEqual(server.srp_server_get_state(), 'running')
 
         client.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual('router', client.get_state())
 
         #
@@ -181,12 +181,21 @@
         #
 
         client.srp_client_remove_service('my-service-1', '_ipps._tcp')
-        self.simulator.go(5)
+
+        # We previously had self.simulator.go(5) but got the issue that the client is scheduling
+        # the refresh timer with half of the lease time (10 seconds) and there will be chances
+        # that the client will be just in status "kToRefresh" after self.simulator.go(5). This will
+        # fail the checks in self.check_host_and_service() so updated to wait for 2 seconds.
+        self.simulator.go(2)
 
         self.check_host_and_service(server, client, '2001::2', 'my-service')
         self.host_check_mdns_service(host, '2001::2', 'my-service')
         self.assertIsNone(host.discover_mdns_service('my-service-1', '_ipps._tcp', 'my-host'))
 
+        # Wait for KEY expiration of service 'my-service-1'.
+        # FIXME: workaround for https://github.com/openthread/ot-br-posix/issues/1071.
+        self.simulator.go(KEY_LEASE + 5)
+
         #
         # 8. Update both the host and the service in a loop and make sure the
         #    Advertising Proxy can follow.
@@ -197,7 +206,7 @@
             client.srp_client_clear_service('my-service', '_ipps._tcp')
             client.srp_client_set_host_address(host_address)
             client.srp_client_add_service('my-service', '_ipps._tcp', service_port)
-            self.simulator.go(5)
+            self.simulator.go(10)
 
             self.check_host_and_service(server, client, host_address, 'my-service', service_port)
             self.host_check_mdns_service(host, host_address, 'my-service', service_port)
@@ -271,5 +280,48 @@
         self.assertEqual(ipaddress.ip_address(server_host['addresses'][0]), ipaddress.ip_address(host_addr))
 
 
+class SrpClientRemoveNonExistingHost(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+
+    TOPOLOGY = {
+        BR: {
+            'name': 'BR',
+            'allowlist': [ROUTER],
+            'is_otbr': True,
+            'version': '1.2',
+        },
+        ROUTER: {
+            'name': 'Router',
+            'allowlist': [BR],
+            'version': '1.2',
+        }
+    }
+
+    def test(self):
+        server = self.nodes[BR]
+        client = self.nodes[ROUTER]
+
+        server.srp_server_set_enabled(True)
+        server.srp_server_set_lease_range(LEASE, LEASE, KEY_LEASE, KEY_LEASE)
+        server.start()
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
+        self.assertEqual('leader', server.get_state())
+        self.assertEqual(server.srp_server_get_state(), 'running')
+
+        client.start()
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
+        self.assertEqual('router', client.get_state())
+
+        # Immediately remove a non-existing host.
+
+        client.srp_client_enable_auto_start_mode()
+        client.srp_client_set_host_name('my-host')
+        self.assertEqual('ToAdd', client.srp_client_get_host_state())
+
+        client.srp_client_remove_host(remove_key=True, send_unreg_to_server=True)
+        self.simulator.go(2)
+        self.assertEqual('Removed', client.srp_client_get_host_state())
+
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/scripts/thread-cert/border_router/test_border_router_as_fed.py b/tests/scripts/thread-cert/border_router/test_border_router_as_fed.py
new file mode 100644
index 0000000..ec705c5
--- /dev/null
+++ b/tests/scripts/thread-cert/border_router/test_border_router_as_fed.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2021, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+import logging
+import unittest
+
+import config
+import thread_cert
+
+# Test description:
+#   This test verifies bi-directional connectivity between Thread end device
+#   and infra host via an Border Router (FED)
+#
+# Topology:
+#    ----------------(eth)--------------------
+#           |                 |
+#          BR (FED)          HOST
+#           |
+#        Leader
+#
+
+BR = 1
+LEADER = 2
+HOST = 3
+
+
+class TestBorderRouterAsFed(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+
+    TOPOLOGY = {
+        BR: {
+            'name': 'BR',
+            'allowlist': [LEADER],
+            'is_otbr': True,
+            'version': '1.2',
+            'router_eligible': False,
+        },
+        LEADER: {
+            'name': 'LEADER',
+            'allowlist': [BR],
+            'version': '1.2',
+        },
+        HOST: {
+            'name': 'Host',
+            'is_host': True
+        },
+    }
+
+    def test(self):
+        br = self.nodes[BR]
+        leader = self.nodes[LEADER]
+        host = self.nodes[HOST]
+
+        host.start(start_radvd=False)
+        self.simulator.go(5)
+
+        leader.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual('leader', leader.get_state())
+
+        br.start()
+        self.simulator.go(5)
+        self.assertEqual('child', br.get_state())
+
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
+        self.assertEqual('child', br.get_state())
+
+        # Leader can ping to/from the Host on infra link.
+        self.assertTrue(leader.ping(host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0]))
+        self.assertTrue(host.ping(leader.get_ip6_address(config.ADDRESS_TYPE.OMR)[0], backbone=True))
+
+        self.simulator.go(5)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/border_router/test_dnssd_instance_name_with_space.py b/tests/scripts/thread-cert/border_router/test_dnssd_instance_name_with_space.py
new file mode 100644
index 0000000..7c2cc99
--- /dev/null
+++ b/tests/scripts/thread-cert/border_router/test_dnssd_instance_name_with_space.py
@@ -0,0 +1,221 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2021, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+import ipaddress
+import json
+import logging
+import unittest
+
+import config
+import thread_cert
+
+# Test description:
+#   This test verifies DNS-SD server and Discovery Proxy can handle Instance names with whitespaces.
+#
+# Topology:
+#    ----------------(eth)--------------------
+#           |                 |         |
+#          BR1 (Server)------BR2       HOST
+#         /
+#      CLIENT1
+
+SERVER = BR1 = 1
+CLIENT = 2
+HOST = 3
+BR2 = 4
+
+DOMAIN = 'default.service.arpa.'
+SERVICE = '_testsrv._udp'
+SERVICE_FULL_NAME = f'{SERVICE}.{DOMAIN}'
+INSTANCE_NAME = 'O T B R'
+HOST_NAME = 'host1'
+HOST_FULL_NAME = f'{HOST_NAME}.{DOMAIN}'
+
+
+class TestDnssdInstanceNameWithSpace(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+
+    TOPOLOGY = {
+        BR1: {
+            'name': 'SERVER',
+            'is_otbr': True,
+            'version': '1.2',
+        },
+        BR2: {
+            'name': 'BR2',
+            'is_otbr': True,
+            'version': '1.2',
+        },
+        CLIENT: {
+            'name': 'CLIENT1',
+        },
+        HOST: {
+            'name': 'Host',
+            'is_host': True
+        },
+    }
+
+    def test(self):
+        server = br1 = self.nodes[BR1]
+        br2 = self.nodes[BR2]
+        client = self.nodes[CLIENT]
+        digger = host = self.nodes[HOST]
+
+        host.start(start_radvd=False)
+        self.simulator.go(5)
+
+        br1.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual('leader', br1.get_state())
+        server.srp_server_set_enabled(True)
+
+        br2.start()
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
+        self.assertEqual('router', br2.get_state())
+
+        client.start()
+
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
+        self.assertEqual('router', client.get_state())
+
+        self.simulator.go(10)
+
+        server_addr = server.get_ip6_address(config.ADDRESS_TYPE.OMR)[0]
+
+        client1_addrs = [client.get_mleid(), client.get_ip6_address(config.ADDRESS_TYPE.OMR)[0]]
+        self._config_srp_client_services(client, INSTANCE_NAME, HOST_NAME, 11111, 0, 0, client1_addrs)
+
+        full_instance_name = f'{INSTANCE_NAME}.{SERVICE_FULL_NAME}'
+        EMPTY_TXT = {}
+
+        self._verify_service_browse_result(client.dns_browse(SERVICE_FULL_NAME, server=br1.get_rloc()))
+        self._verify_service_browse_result(client.dns_browse(SERVICE_FULL_NAME, server=br2.get_rloc()))
+        self._verify_service_browse_result(client.dns_browse(SERVICE_FULL_NAME.lower(), server=br2.get_rloc()))
+
+        # check if PTR query works
+        dig_result = digger.dns_dig(server_addr, SERVICE_FULL_NAME, 'PTR')
+
+        self._assert_dig_result_matches(
+            dig_result, {
+                'QUESTION': [(SERVICE_FULL_NAME, 'IN', 'PTR')],
+                'ANSWER': [(SERVICE_FULL_NAME, 'IN', 'PTR', f'{INSTANCE_NAME}.{SERVICE_FULL_NAME}')],
+                'ADDITIONAL': [
+                    (full_instance_name, 'IN', 'SRV', 0, 0, 11111, HOST_FULL_NAME),
+                    (full_instance_name, 'IN', 'TXT', EMPTY_TXT),
+                ],
+            })
+
+        # check if SRV query works
+        dig_result = digger.dns_dig(server_addr, full_instance_name, 'SRV')
+        self._assert_dig_result_matches(
+            dig_result, {
+                'QUESTION': [(full_instance_name, 'IN', 'SRV')],
+                'ANSWER': [(full_instance_name, 'IN', 'SRV', 0, 0, 11111, HOST_FULL_NAME),],
+                'ADDITIONAL': [],
+            })
+
+    def _config_srp_client_services(self, client, instancename, hostname, port, priority, weight, addrs):
+        client.srp_client_enable_auto_start_mode()
+        client.srp_client_set_host_name(hostname)
+        client.srp_client_set_host_address(*addrs)
+        client.srp_client_add_service(instancename, SERVICE, port, priority, weight)
+
+        self.simulator.go(5)
+        self.assertEqual(client.srp_client_get_host_state(), 'Registered')
+
+    def _assert_have_question(self, dig_result, question):
+        for dig_question in dig_result['QUESTION']:
+            if self._match_record(dig_question, question):
+                return
+
+        self.fail((dig_result, question))
+
+    def _assert_have_answer(self, dig_result, record, additional=False):
+        for dig_answer in dig_result['ANSWER' if not additional else 'ADDITIONAL']:
+            dig_answer = list(dig_answer)
+            dig_answer[1:2] = []  # remove TTL from answer
+
+            record = list(record)
+
+            # convert IPv6 addresses to `ipaddress.IPv6Address` before matching
+            if dig_answer[2] == 'AAAA':
+                dig_answer[3] = ipaddress.IPv6Address(dig_answer[3])
+
+            if record[2] == 'AAAA':
+                record[3] = ipaddress.IPv6Address(record[3])
+
+            if self._match_record(dig_answer, record):
+                return
+
+            print('not match: ', dig_answer, record,
+                  list(a == b or (callable(b) and b(a)) for a, b in zip(dig_answer, record)))
+
+        self.fail((record, dig_result))
+
+    def _match_record(self, record, match):
+        assert not any(callable(elem) for elem in record), record
+
+        if record == match:
+            return True
+
+        return all(a == b or (callable(b) and b(a)) for a, b in zip(record, match))
+
+    def _assert_dig_result_matches(self, dig_result, expected_result):
+        self.assertEqual(dig_result['opcode'], expected_result.get('opcode', 'QUERY'), dig_result)
+        self.assertEqual(dig_result['status'], expected_result.get('status', 'NOERROR'), dig_result)
+
+        if 'QUESTION' in expected_result:
+            self.assertEqual(len(dig_result['QUESTION']), len(expected_result['QUESTION']), dig_result)
+
+            for question in expected_result['QUESTION']:
+                self._assert_have_question(dig_result, question)
+
+        if 'ANSWER' in expected_result:
+            self.assertEqual(len(dig_result['ANSWER']), len(expected_result['ANSWER']), dig_result)
+
+            for record in expected_result['ANSWER']:
+                self._assert_have_answer(dig_result, record, additional=False)
+
+        if 'ADDITIONAL' in expected_result:
+            self.assertGreaterEqual(len(dig_result['ADDITIONAL']), len(expected_result['ADDITIONAL']), dig_result)
+
+            for record in expected_result['ADDITIONAL']:
+                self._assert_have_answer(dig_result, record, additional=True)
+
+        logging.info("dig result matches:\r%s", json.dumps(dig_result, indent=True))
+
+    def _verify_service_browse_result(self, services):
+        assert len(services) == 1, services
+        assert INSTANCE_NAME in services, services
+        service = services[INSTANCE_NAME]
+        logging.info("Service Browse Result: %r", service)
+        self.assertEqual(service['host'], HOST_FULL_NAME)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/border_router/test_dnssd_server.py b/tests/scripts/thread-cert/border_router/test_dnssd_server.py
index 00da6f6..471c83e 100644
--- a/tests/scripts/thread-cert/border_router/test_dnssd_server.py
+++ b/tests/scripts/thread-cert/border_router/test_dnssd_server.py
@@ -94,17 +94,17 @@
         self.simulator.go(5)
 
         br1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br1.get_state())
         server.srp_server_set_enabled(True)
 
         client1.start()
 
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual('router', client1.get_state())
 
         client2.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual('router', client2.get_state())
 
         self.simulator.go(10)
@@ -239,7 +239,7 @@
                 'ADDITIONAL': [
                     (dp_instance_name, 'IN', 'SRV', 0, 0, check_border_agent_port, dp_hostname),
                     (dp_instance_name, 'IN', 'TXT', lambda txt: (isinstance(txt, dict) and txt.get(
-                        'nn') == network_name and 'xp' in txt and 'tv' in txt and 'dd' in txt)),
+                        'nn') == network_name and 'xp' in txt and 'tv' in txt and 'xa' in txt)),
                 ],
             })
 
@@ -259,7 +259,7 @@
                 'QUESTION': [(dp_instance_name, 'IN', 'SRV'),],
                 'ANSWER': [(dp_instance_name, 'IN', 'SRV', 0, 0, check_border_agent_port, dp_hostname),],
                 'ADDITIONAL': [(dp_instance_name, 'IN', 'TXT', lambda txt: (isinstance(txt, dict) and txt.get(
-                    'nn') == network_name and 'xp' in txt and 'tv' in txt and 'dd' in txt)),],
+                    'nn') == network_name and 'xp' in txt and 'tv' in txt and 'xa' in txt)),],
             })
 
         dig_result = digger.dns_dig(server_addr, dp_instance_name, 'TXT')
@@ -267,7 +267,7 @@
             dig_result, {
                 'QUESTION': [(dp_instance_name, 'IN', 'TXT'),],
                 'ANSWER': [(dp_instance_name, 'IN', 'TXT', lambda txt: (isinstance(txt, dict) and txt.get(
-                    'nn') == network_name and 'xp' in txt and 'tv' in txt and 'dd' in txt)),],
+                    'nn') == network_name and 'xp' in txt and 'tv' in txt and 'xa' in txt)),],
                 'ADDITIONAL': [(dp_instance_name, 'IN', 'SRV', 0, 0, check_border_agent_port, dp_hostname),],
             })
 
diff --git a/tests/scripts/thread-cert/border_router/test_dnssd_server_multi_border_routers.py b/tests/scripts/thread-cert/border_router/test_dnssd_server_multi_border_routers.py
new file mode 100644
index 0000000..3a09b72
--- /dev/null
+++ b/tests/scripts/thread-cert/border_router/test_dnssd_server_multi_border_routers.py
@@ -0,0 +1,379 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+import ipaddress
+import json
+import logging
+import unittest
+
+import config
+import thread_cert
+
+# Test description:
+#   This test verifies DNS-SD server can work well in a multiple border router scenario. The DNS-SD server can answer
+#   queries from the Host.
+#   BR1 is the SRP server and BR2 is the DNS-SD server.
+# Topology:
+#    ----------------(eth)-----------------------
+#           |              |         |
+#          BR1 ---------- BR2      HOST
+#           |
+#        +--+----+
+#        |       |
+#    CLIENT1  CLIENT2
+#
+
+BR1 = 1
+BR2 = 2
+ED1, ED2 = 3, 4
+HOST = 5
+
+DOMAIN = 'default.service.arpa.'
+SERVICE = '_testsrv._udp'
+SERVICE_FULL_NAME = f'{SERVICE}.{DOMAIN}'
+
+VALID_SERVICE_NAMES = [
+    '_abc._udp.default.service.arpa.',
+    '_abc._tcp.default.service.arpa.',
+]
+
+WRONG_SERVICE_NAMES = [
+    '_testsrv._udp.default.service.xxxx.',
+    '_testsrv._txp,default.service.arpa.',
+]
+
+
+class TestDnssdServerOnMultiBr(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+
+    TOPOLOGY = {
+        BR1: {
+            'name': 'BR1',
+            'is_otbr': True,
+            'version': '1.2',
+            'allowlist': [BR2, ED1, ED2],
+        },
+        BR2: {
+            'name': 'BR2',
+            'is_otbr': True,
+            'version': '1.2',
+            'allowlist': [BR1],
+        },
+        ED1: {
+            'name': 'ED1',
+            'mode': 'rn',
+            'allowlist': [BR1]
+        },
+        ED2: {
+            'name': 'ED2',
+            'mode': 'rn',
+            'allowlist': [BR1],
+        },
+        HOST: {
+            'name': 'Host',
+            'is_host': True
+        },
+    }
+
+    def test(self):
+        br1 = self.nodes[BR1]
+        br2 = self.nodes[BR2]
+        ed1 = self.nodes[ED1]
+        ed2 = self.nodes[ED2]
+        host = self.nodes[HOST]
+
+        host.start(start_radvd=False)
+        self.simulator.go(5)
+
+        br1.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual('leader', br1.get_state())
+        br1.srp_server_set_enabled(True)
+
+        br2.stop_mdns_service()
+        br2.stop_otbr_service()
+
+        ed1.start()
+        self.simulator.go(5)
+        self.assertEqual('child', ed1.get_state())
+
+        ed2.start()
+        self.simulator.go(5)
+        self.assertEqual('child', ed2.get_state())
+
+        self.simulator.go(10)
+
+        client1_addrs = [ed1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0], ed1.get_mleid()]
+        self._config_srp_client_services(ed1, 'ins1', 'host1', 11111, 1, 1, client1_addrs)
+
+        client2_addrs = [ed2.get_ip6_address(config.ADDRESS_TYPE.OMR)[0], ed2.get_mleid()]
+        self._config_srp_client_services(ed2, 'ins2', 'host2', 22222, 2, 2, client2_addrs)
+        self.simulator.go(5)
+
+        # start BR2 late to ensure it doesn't have mDNS cache
+        br2.start_mdns_service()
+        br2.start_otbr_service()
+        br2.start()
+
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
+
+        br2_addr = br2.get_ip6_address(config.ADDRESS_TYPE.OMR)[0]
+
+        ins1_full_name = f'ins1.{SERVICE_FULL_NAME}'
+        ins2_full_name = f'ins2.{SERVICE_FULL_NAME}'
+        host1_full_name = f'host1.{DOMAIN}'
+        host2_full_name = f'host2.{DOMAIN}'
+        EMPTY_TXT = {}
+
+        def is_int(x):
+            return isinstance(x, int)
+
+        # check if AAAA query works
+        dig_result = host.dns_dig(br2_addr, host1_full_name, 'AAAA')
+        self._assert_dig_result_matches(dig_result, {
+            'QUESTION': [(host1_full_name, 'IN', 'AAAA')],
+            'ANSWER': [(host1_full_name, 'IN', 'AAAA', client1_addrs[0]),],
+        })
+
+        dig_result = host.dns_dig(br2_addr, host2_full_name, 'AAAA')
+        self._assert_dig_result_matches(dig_result, {
+            'QUESTION': [(host2_full_name, 'IN', 'AAAA')],
+            'ANSWER': [(host2_full_name, 'IN', 'AAAA', client2_addrs[0]),],
+        })
+
+        # check if SRV query works
+        dig_result = host.dns_dig(br2_addr, ins1_full_name, 'SRV')
+        self._assert_dig_result_matches(
+            dig_result, {
+                'QUESTION': [(ins1_full_name, 'IN', 'SRV')],
+                'ANSWER': [(ins1_full_name, 'IN', 'SRV', is_int, is_int, 11111, host1_full_name),],
+                'ADDITIONAL': [(host1_full_name, 'IN', 'AAAA', client1_addrs[0]),],
+            })
+
+        dig_result = host.dns_dig(br2_addr, ins2_full_name, 'SRV')
+        self._assert_dig_result_matches(
+            dig_result, {
+                'QUESTION': [(ins2_full_name, 'IN', 'SRV')],
+                'ANSWER': [(ins2_full_name, 'IN', 'SRV', is_int, is_int, 22222, host2_full_name),],
+                'ADDITIONAL': [(host2_full_name, 'IN', 'AAAA', client2_addrs[0]),],
+            })
+
+        # check if TXT query works
+        dig_result = host.dns_dig(br2_addr, ins1_full_name, 'TXT')
+        self._assert_dig_result_matches(dig_result, {
+            'QUESTION': [(ins1_full_name, 'IN', 'TXT')],
+            'ANSWER': [(ins1_full_name, 'IN', 'TXT', EMPTY_TXT)],
+        })
+
+        dig_result = host.dns_dig(br2_addr, ins2_full_name, 'TXT')
+        self._assert_dig_result_matches(dig_result, {
+            'QUESTION': [(ins2_full_name, 'IN', 'TXT')],
+            'ANSWER': [(ins2_full_name, 'IN', 'TXT', EMPTY_TXT)],
+        })
+
+        # check if PTR query works
+        dig_result = host.dns_dig(br2_addr, SERVICE_FULL_NAME, 'PTR')
+
+        self._assert_dig_result_matches_any(dig_result, [{
+            'QUESTION': [(SERVICE_FULL_NAME, 'IN', 'PTR')],
+            'ANSWER': [(SERVICE_FULL_NAME, 'IN', 'PTR', f'ins1.{SERVICE_FULL_NAME}')],
+            'ADDITIONAL': [
+                (ins1_full_name, 'IN', 'SRV', is_int, is_int, 11111, host1_full_name),
+                (ins1_full_name, 'IN', 'TXT', EMPTY_TXT),
+                (host1_full_name, 'IN', 'AAAA', client1_addrs[0]),
+            ],
+        }, {
+            'QUESTION': [(SERVICE_FULL_NAME, 'IN', 'PTR')],
+            'ANSWER': [(SERVICE_FULL_NAME, 'IN', 'PTR', f'ins2.{SERVICE_FULL_NAME}')],
+            'ADDITIONAL': [
+                (ins2_full_name, 'IN', 'SRV', is_int, is_int, 22222, host2_full_name),
+                (ins2_full_name, 'IN', 'TXT', EMPTY_TXT),
+                (host2_full_name, 'IN', 'AAAA', client2_addrs[0]),
+            ],
+        }])
+
+        # check some invalid queries
+        for qtype in ['A', 'CNAME']:
+            dig_result = host.dns_dig(br2_addr, host1_full_name, qtype)
+            self._assert_dig_result_matches(dig_result, {
+                'status': 'NOTIMP',
+            })
+
+        for service_name in WRONG_SERVICE_NAMES:
+            dig_result = host.dns_dig(br2_addr, service_name, 'PTR')
+            self._assert_dig_result_matches(dig_result, {
+                'status': 'NXDOMAIN',
+            })
+
+        # verify Discovery Proxy works for _meshcop._udp
+        self._verify_discovery_proxy_meshcop(br2_addr, br2.get_network_name(), host)
+
+    def _verify_discovery_proxy_meshcop(self, server_addr, network_name, digger):
+        dp_service_name = '_meshcop._udp.default.service.arpa.'
+        dp_hostname = lambda x: x.endswith('.default.service.arpa.')
+
+        def check_border_agent_port(port):
+            return 0 < port <= 65535
+
+        dig_result = digger.dns_dig(server_addr, dp_service_name, 'PTR')
+        for answer in dig_result['ANSWER']:
+            if len(answer) >= 2 and answer[-2] == 'PTR':
+                dp_instance_name = answer[-1]
+                break
+        self._assert_dig_result_matches(
+            dig_result, {
+                'QUESTION': [(dp_service_name, 'IN', 'PTR'),],
+                'ANSWER': [(dp_service_name, 'IN', 'PTR', dp_instance_name),],
+                'ADDITIONAL': [
+                    (dp_instance_name, 'IN', 'SRV', 0, 0, check_border_agent_port, dp_hostname),
+                    (dp_instance_name, 'IN', 'TXT', lambda txt: (isinstance(txt, dict) and txt.get(
+                        'nn') == network_name and 'xp' in txt and 'tv' in txt and 'xa' in txt)),
+                ],
+            })
+
+        # Find the actual host name and IPv6 address
+        dp_ip6_address = None
+        for rr in dig_result['ADDITIONAL']:
+            if rr[3] == 'SRV':
+                dp_hostname = rr[7]
+            elif rr[3] == 'AAAA':
+                dp_ip6_address = rr[4]
+
+        assert isinstance(dp_hostname, str), dig_result
+
+        dig_result = digger.dns_dig(server_addr, dp_instance_name, 'SRV')
+        self._assert_dig_result_matches(
+            dig_result, {
+                'QUESTION': [(dp_instance_name, 'IN', 'SRV'),],
+                'ANSWER': [(dp_instance_name, 'IN', 'SRV', 0, 0, check_border_agent_port, dp_hostname),],
+                'ADDITIONAL': [(dp_instance_name, 'IN', 'TXT', lambda txt: (isinstance(txt, dict) and txt.get(
+                    'nn') == network_name and 'xp' in txt and 'tv' in txt and 'xa' in txt)),],
+            })
+
+        dig_result = digger.dns_dig(server_addr, dp_instance_name, 'TXT')
+        self._assert_dig_result_matches(
+            dig_result, {
+                'QUESTION': [(dp_instance_name, 'IN', 'TXT'),],
+                'ANSWER': [(dp_instance_name, 'IN', 'TXT', lambda txt: (isinstance(txt, dict) and txt.get(
+                    'nn') == network_name and 'xp' in txt and 'tv' in txt and 'xa' in txt)),],
+                'ADDITIONAL': [(dp_instance_name, 'IN', 'SRV', 0, 0, check_border_agent_port, dp_hostname),],
+            })
+
+        if dp_ip6_address is not None:
+            dig_result = digger.dns_dig(server_addr, dp_hostname, 'AAAA')
+
+            self._assert_dig_result_matches(dig_result, {
+                'QUESTION': [(dp_hostname, 'IN', 'AAAA'),],
+                'ANSWER': [(dp_hostname, 'IN', 'AAAA', dp_ip6_address),],
+            })
+
+    def _config_srp_client_services(self, client, instancename, hostname, port, priority, weight, addrs):
+        client.srp_client_enable_auto_start_mode()
+        client.srp_client_set_host_name(hostname)
+        client.srp_client_set_host_address(*addrs)
+        client.srp_client_add_service(instancename, SERVICE, port, priority, weight)
+
+        self.simulator.go(5)
+        self.assertEqual(client.srp_client_get_host_state(), 'Registered')
+
+    def _assert_have_question(self, dig_result, question):
+        for dig_question in dig_result['QUESTION']:
+            if self._match_record(dig_question, question):
+                return
+
+        self.fail((dig_result, question))
+
+    def _assert_have_answer(self, dig_result, record, additional=False):
+        for dig_answer in dig_result['ANSWER' if not additional else 'ADDITIONAL']:
+            dig_answer = list(dig_answer)
+            dig_answer[1:2] = []  # remove TTL from answer
+
+            record = list(record)
+
+            # convert IPv6 addresses to `ipaddress.IPv6Address` before matching
+            if dig_answer[2] == 'AAAA':
+                dig_answer[3] = ipaddress.IPv6Address(dig_answer[3])
+
+            if record[2] == 'AAAA':
+                record[3] = ipaddress.IPv6Address(record[3])
+
+            if self._match_record(dig_answer, record):
+                return
+
+            print('not match: ', dig_answer, record,
+                  list(a == b or (callable(b) and b(a)) for a, b in zip(dig_answer, record)))
+
+        self.fail((record, dig_result))
+
+    def _match_record(self, record, match):
+        assert not any(callable(elem) for elem in record), record
+
+        if record == match:
+            return True
+
+        return all(a == b or (callable(b) and b(a)) for a, b in zip(record, match))
+
+    def _assert_dig_result_matches(self, dig_result, expected_result):
+        self.assertEqual(dig_result['opcode'], expected_result.get('opcode', 'QUERY'), dig_result)
+        self.assertEqual(dig_result['status'], expected_result.get('status', 'NOERROR'), dig_result)
+
+        if 'QUESTION' in expected_result:
+            self.assertEqual(len(dig_result['QUESTION']), len(expected_result['QUESTION']), dig_result)
+
+            for question in expected_result['QUESTION']:
+                self._assert_have_question(dig_result, question)
+
+        if 'ANSWER' in expected_result:
+            self.assertEqual(len(dig_result['ANSWER']), len(expected_result['ANSWER']), dig_result)
+
+            for record in expected_result['ANSWER']:
+                self._assert_have_answer(dig_result, record, additional=False)
+
+        if 'ADDITIONAL' in expected_result:
+            self.assertGreaterEqual(len(dig_result['ADDITIONAL']), len(expected_result['ADDITIONAL']), dig_result)
+
+            for record in expected_result['ADDITIONAL']:
+                self._assert_have_answer(dig_result, record, additional=True)
+
+        logging.info("dig result matches:\r%s", json.dumps(dig_result, indent=True))
+
+    def _assert_dig_result_matches_any(self, dig_result, expected_results):
+        logging.info(f'dig_result = {dig_result}')
+        for expected_result in expected_results:
+            try:
+                self._assert_dig_result_matches(dig_result, expected_result)
+            except Exception:
+                continue
+            else:
+                return
+
+        self.fail("failed to find any matched result")
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/border_router/test_end_device_udp_reachability.py b/tests/scripts/thread-cert/border_router/test_end_device_udp_reachability.py
index 96455c7..2ad55c8 100644
--- a/tests/scripts/thread-cert/border_router/test_end_device_udp_reachability.py
+++ b/tests/scripts/thread-cert/border_router/test_end_device_udp_reachability.py
@@ -82,7 +82,7 @@
         self.simulator.go(5)
 
         br1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br1.get_state())
         br1.udp_start("::", PORT, bind_unspecified=True)
 
diff --git a/tests/scripts/thread-cert/border_router/test_external_route.py b/tests/scripts/thread-cert/border_router/test_external_route.py
index e06129a..cbb597b 100644
--- a/tests/scripts/thread-cert/border_router/test_external_route.py
+++ b/tests/scripts/thread-cert/border_router/test_external_route.py
@@ -93,11 +93,11 @@
         host = self.nodes[HOST]
 
         br1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br1.get_state())
 
         br2.start()
-        self.simulator.go(5)
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
         self.assertEqual('router', br2.get_state())
 
         router1.start()
diff --git a/tests/scripts/thread-cert/border_router/test_firewall.py b/tests/scripts/thread-cert/border_router/test_firewall.py
new file mode 100644
index 0000000..c1bd9ad
--- /dev/null
+++ b/tests/scripts/thread-cert/border_router/test_firewall.py
@@ -0,0 +1,270 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2021, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+import logging
+import unittest
+import ipaddress
+
+import config
+import pktverify
+import pktverify.packet_verifier
+from pktverify.consts import MA1
+import thread_cert
+
+# Test description:
+#   This test verifies the functionality of firewall. OTBR will only
+#   forward specific kinds of packets between the infra interface and the thread
+#   interface.
+#
+# Topology:
+#    ----------------(eth)----------------------
+#           |                  |
+#          BR1 (Leader)      HOST
+#           |
+#         ROUTER1
+
+BR1 = 1
+ROUTER1 = 2
+HOST = 3
+
+
+class Firewall(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+
+    TOPOLOGY = {
+        BR1: {
+            'name': 'BR_1',
+            'allowlist': [ROUTER1],
+            'is_otbr': True,
+            'version': '1.2',
+        },
+        ROUTER1: {
+            'name': 'Router_1',
+            'allowlist': [BR1],
+            'version': '1.2',
+        },
+        HOST: {
+            'name': 'Host',
+            'is_host': True,
+        }
+    }
+
+    def test(self):
+        br1 = self.nodes[BR1]
+        self.br1 = br1
+        router1 = self.nodes[ROUTER1]
+        host = self.nodes[HOST]
+
+        br1.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual('leader', br1.get_state())
+
+        router1.start()
+        host.start(start_radvd=True)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
+        self.assertEqual('router', router1.get_state())
+
+        br1.set_domain_prefix(config.DOMAIN_PREFIX, 'prosD')
+        br1.register_netdata()
+
+        router1.add_ipmaddr(MA1)
+        router1.register_netdata()
+
+        self.simulator.go(20)
+
+        def host_ping_ether(dest, interface, ttl=10, add_interface=False, add_route=False, gateway=None):
+            if add_interface:
+                host.bash(f'ip -6 addr add {interface}/64 dev {host.ETH_DEV} scope global')
+                route = str(ipaddress.IPv6Network(f'{interface}/64', strict=False))
+                host.bash(f'ip -6 route del {route} dev {host.ETH_DEV}')
+            if add_route:
+                host.bash(f'ip -6 route add {dest} dev {host.ETH_DEV} via {gateway}')
+            self.simulator.go(2)
+            result = host.ping_ether(dest, ttl=ttl, interface=interface)
+            if add_route:
+                host.bash(f'ip -6 route del {dest}')
+            if add_interface:
+                host.bash(f'ip -6 addr del {interface}/64 dev {host.ETH_DEV} scope global')
+            self.simulator.go(1)
+            return result
+
+        # 1. Host pings router1's OMR from host's infra address.
+        self.assertTrue(host_ping_ether(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0], interface=host.ETH_DEV))
+
+        # 2. Host pings router1's DUA from host's infra address.
+        self.assertTrue(host_ping_ether(router1.get_ip6_address(config.ADDRESS_TYPE.DUA), interface=host.ETH_DEV))
+
+        # 3. Host pings router1's OMR from router1's RLOC.
+        self.assertFalse(
+            host_ping_ether(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
+                            interface=router1.get_rloc(),
+                            add_interface=True))
+
+        # 4. Host pings router1's OMR from BR1's OMR.
+        self.assertFalse(
+            host_ping_ether(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
+                            interface=br1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
+                            add_interface=True))
+
+        # 5. Host pings router1's OMR from router1's MLE-ID.
+        self.assertFalse(
+            host_ping_ether(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
+                            interface=router1.get_mleid(),
+                            add_interface=True))
+
+        host.bash(f'ip -6 route add {config.MESH_LOCAL_PREFIX} dev {host.ETH_DEV}')
+        self.simulator.go(5)
+
+        # 6. Host pings router1's RLOC from host's ULA address.
+        self.assertFalse(
+            host_ping_ether(router1.get_rloc(),
+                            interface=host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0],
+                            add_route=True,
+                            gateway=br1.get_ip6_address(config.ADDRESS_TYPE.BACKBONE_GUA)))
+
+        # 7. Host pings router1's MLE-ID from host's ULA address.
+        self.assertFalse(
+            host_ping_ether(router1.get_mleid(),
+                            interface=host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0],
+                            add_route=True,
+                            gateway=br1.get_ip6_address(config.ADDRESS_TYPE.BACKBONE_GUA)))
+
+        # 8. Host pings router1's link-local address from host's infra address.
+        self.assertFalse(
+            host_ping_ether(router1.get_linklocal(),
+                            interface=host.ETH_DEV,
+                            add_route=True,
+                            gateway=br1.get_ip6_address(config.ADDRESS_TYPE.BACKBONE_GUA)))
+
+        # 9. Host pings MA1 from host's ULA address.
+        self.assertTrue(host_ping_ether(MA1, ttl=10,
+                                        interface=host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0]))
+
+        # 10. Host pings MA1 from router1's RLOC.
+        self.assertFalse(host_ping_ether(MA1, ttl=10, interface=router1.get_rloc(), add_interface=True))
+
+        # 11. Host pings MA1 from router1's OMR.
+        self.assertFalse(
+            host_ping_ether(MA1,
+                            ttl=10,
+                            interface=router1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
+                            add_interface=True))
+
+        # 12. Host pings MA1 from router1's MLE-ID.
+        self.assertFalse(host_ping_ether(MA1, ttl=10, interface=router1.get_mleid(), add_interface=True))
+
+        self.collect_ipaddrs()
+        self.collect_rlocs()
+        self.collect_rloc16s()
+        self.collect_extra_vars()
+        self.collect_omrs()
+        self.collect_duas()
+
+    def verify(self, pv: pktverify.packet_verifier.PacketVerifier):
+        pkts = pv.pkts
+        vars = pv.vars
+        pv.summary.show()
+        logging.info(f'vars = {vars}')
+
+        pv.verify_attached('Router_1', 'BR_1')
+
+        # 1. Host pings router1's OMR from host's infra address.
+        _pkt = pkts.filter_eth_src(vars['Host_ETH']).filter_ipv6_dst(
+            vars['Router_1_OMR'][0]).filter_ping_request().must_next()
+        pkts.filter_wpan_src64(vars['BR_1']).filter_wpan_dst16(
+            vars['Router_1_RLOC16']).filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).must_next()
+
+        # 2. Host pings router1's DUA from host's infra address.
+        _pkt = pkts.filter_eth_src(vars['Host_ETH']).filter_ipv6_dst(
+            vars['Router_1_DUA']).filter_ping_request().must_next()
+        pkts.filter_wpan_src64(vars['BR_1']).filter_wpan_dst16(
+            vars['Router_1_RLOC16']).filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).must_next()
+
+        # 3. Host pings router1's OMR from router1's RLOC.
+        _pkt = pkts.filter_eth_src(vars['Host_ETH']).filter_ipv6_src_dst(
+            vars['Router_1_RLOC'], vars['Router_1_OMR'][0]).filter_ping_request().must_next()
+        pkts.filter_wpan_src64(vars['BR_1']).filter_wpan_dst16(
+            vars['Router_1_RLOC16']).filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).must_not_next()
+
+        # 4. Host pings router1's OMR from BR1's OMR.
+        _pkt = pkts.filter_eth_src(vars['Host_ETH']).filter_ipv6_src_dst(
+            vars['BR_1_OMR'][0], vars['Router_1_OMR'][0]).filter_ping_request().must_next()
+        pkts.filter_wpan_src64(vars['BR_1']).filter_wpan_dst64(
+            vars['Router_1']).filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).must_not_next()
+
+        # 5. Host pings router1's OMR from router1's MLE-ID.
+        _pkt = pkts.filter_eth_src(vars['Host_ETH']).filter_ipv6_src_dst(
+            vars['Router_1_MLEID'], vars['Router_1_OMR'][0]).filter_ping_request().must_next()
+        pkts.filter_wpan_src64(vars['BR_1']).filter_wpan_dst16(
+            vars['Router_1_RLOC16']).filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).must_not_next()
+
+        # 6. Host pings router1's RLOC from host's ULA address.
+        _pkt = pkts.filter_eth_src(vars['Host_ETH']).filter_ipv6_dst(
+            vars['Router_1_RLOC']).filter_ping_request().must_next()
+        pkts.filter_wpan_src64(vars['BR_1']).filter_wpan_dst16(
+            vars['Router_1_RLOC16']).filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).must_not_next()
+
+        # 7. Host pings router1's MLE-ID from host's ULA address.
+        _pkt = pkts.filter_eth_src(vars['Host_ETH']).filter_ipv6_dst(
+            vars['Router_1_MLEID']).filter_ping_request().must_next()
+        pkts.filter_wpan_src64(vars['BR_1']).filter_wpan_dst16(
+            vars['Router_1_RLOC16']).filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).must_not_next()
+
+        # 8. Host pings router1's link-local address from host's infra address.
+        # Skip this scenario as for now
+        # _pkt = pkts.filter_eth_src(vars['Host_ETH']).filter_ipv6_dst(
+        #     vars['Router_1_LLA']).filter_ping_request().must_next()
+        pkts.filter_wpan_src64(vars['BR_1']).filter_wpan_dst16(
+            vars['Router_1_RLOC16']).filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).must_not_next()
+
+        # 9. Host pings MA1 from host's ULA address.
+        _pkt = pkts.filter_eth_src(vars['Host_ETH']).filter_ipv6_dst(MA1).filter_ping_request().must_next()
+        pkts.filter_wpan_src64(
+            vars['BR_1']).filter_AMPLFMA().filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).must_next()
+
+        # 10. Host pings MA1 from router1's RLOC.
+        _pkt = pkts.filter_eth_src(vars['Host_ETH']).filter_ipv6_src_dst(vars['Router_1_RLOC'],
+                                                                         MA1).filter_ping_request().must_next()
+        pkts.filter_wpan_src64(
+            vars['BR_1']).filter_AMPLFMA().filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).must_not_next()
+
+        # 11. Host pings MA1 from router1's OMR.
+        _pkt = pkts.filter_eth_src(vars['Host_ETH']).filter_ipv6_src_dst(vars['Router_1_OMR'][0],
+                                                                         MA1).filter_ping_request().must_next()
+        pkts.filter_wpan_src64(
+            vars['BR_1']).filter_AMPLFMA().filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).must_not_next()
+
+        # 12. Host pings MA1 from router1's MLE-ID.
+        _pkt = pkts.filter_eth_src(vars['Host_ETH']).filter_ipv6_src_dst(vars['Router_1_MLEID'],
+                                                                         MA1).filter_ping_request().must_next()
+        pkts.filter_wpan_src64(
+            vars['BR_1']).filter_AMPLFMA().filter_ping_request(identifier=_pkt.icmpv6.echo.identifier).must_not_next()
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/border_router/test_manual_address.py b/tests/scripts/thread-cert/border_router/test_manual_address.py
new file mode 100644
index 0000000..bc432fe
--- /dev/null
+++ b/tests/scripts/thread-cert/border_router/test_manual_address.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2021, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+import unittest
+
+import config
+import thread_cert
+
+# Test description:
+# The purpose of this test case is to verify that BR can manually configure addresses and comply
+# with the manual address configuration rules.
+#
+# Topology:
+#     BR_1 (Leader)
+#       |
+#       |
+#     ROUTER
+#
+
+BR_1 = 1
+ROUTER = 2
+
+PREFIX = '2002::/64'
+GUA_1 = '2002::a:b:c:d'
+GUA_2 = '2002::a:b:c:e'
+
+
+class ManualAddressConfig(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+
+    TOPOLOGY = {
+        BR_1: {
+            'name': 'BR_1',
+            'is_otbr': True,
+            'version': '1.2',
+        },
+        ROUTER: {
+            'name': 'ROUTER',
+            'version': '1.2',
+        },
+    }
+
+    def test(self):
+        br1 = self.nodes[BR_1]
+        router = self.nodes[ROUTER]
+
+        br1.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual('leader', br1.get_state())
+        self.assertTrue(br1.is_primary_backbone_router)
+
+        router.start()
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
+        self.assertEqual('router', router.get_state())
+
+        # Add prefix
+        br1.add_prefix(PREFIX, flags='po', prf='med')
+        br1.register_netdata()
+        self.simulator.go(5)
+
+        # Configure GUA addresses
+        br1.add_ipaddr(GUA_1)
+        router.add_ipaddr(GUA_2)
+
+        # BR_1 sends a ping packet to the GUA_2 address. Router should respond to the ping request.
+        self.assertTrue(br1.ping(GUA_2))
+        self.simulator.go(5)
+
+        # Router sends a ping packet to the GUA_1 address. BR_1 should respond to the ping request.
+        self.assertTrue(router.ping(GUA_1))
+        self.simulator.go(5)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/border_router/test_manual_maddress.py b/tests/scripts/thread-cert/border_router/test_manual_maddress.py
new file mode 100644
index 0000000..1bbe190
--- /dev/null
+++ b/tests/scripts/thread-cert/border_router/test_manual_maddress.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2021, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+import unittest
+import thread_cert
+import config
+
+import pktverify
+from pktverify.consts import MA1
+
+# Test description:
+# The purpose of this test case is to verify that a Border Router device is able to properly
+# forward traffic in response to multicast destination when it comes from another BBR.
+#
+# Topology:
+#    ----------------(eth)------------------
+#           |                  |     |
+#          BR1 (Leader) ------ TD   HOST
+#
+
+BR_1 = 1
+TD = 2
+HOST = 3
+
+
+class ManualMulticastAddressConfig(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+
+    TOPOLOGY = {
+        BR_1: {
+            'name': 'BR_1',
+            'is_otbr': True,
+            'version': '1.2',
+        },
+        TD: {
+            'name': 'TD',
+            'is_otbr': True,
+            'router_eligible': False,
+            'version': '1.2',
+        },
+        HOST: {
+            'name': 'Host',
+            'is_host': True,
+        },
+    }
+
+    def test(self):
+        br1 = self.nodes[BR_1]
+        td = self.nodes[TD]
+        host = self.nodes[HOST]
+
+        br1.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual('leader', br1.get_state())
+        self.assertTrue(br1.is_primary_backbone_router)
+
+        td.start()
+        self.simulator.go(5)
+        self.assertEqual('child', td.get_state())
+
+        # TD registers for multicast address, MA1, at BR_1.
+        td.add_ipmaddr_tun(MA1)
+        self.simulator.go(5)
+
+        # Host sends a ping packet to the multicast address, MA1. TD should
+        # respond to the ping request.
+        host.ping(MA1, backbone=True, ttl=10, interface=host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0])
+        self.simulator.go(5)
+
+    def verify(self, pv: pktverify.packet_verifier.PacketVerifier):
+        pkts = pv.pkts
+        vars = pv.vars
+        pv.summary.show()
+
+        # 1. Host sends a ping packet to the multicast address, MA1.
+        _pkt = pkts.filter_eth_src(vars['Host_ETH']) \
+            .filter_ipv6_dst(MA1) \
+            .filter_ping_request() \
+            .must_next()
+
+        # 1. TD receives the multicast ping packet and sends a ping response
+        # packet back to Host.
+        # TD receives the MPL packet containing an encapsulated ping packet to
+        # MA1, sent by Host, and unicasts a ping response packet back to Host.
+        pkts.filter_eth_src(vars['TD_ETH']) \
+            .filter_ipv6_dst(_pkt.ipv6.src) \
+            .filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier) \
+            .must_next()
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/border_router/test_manual_omr_prefix.py b/tests/scripts/thread-cert/border_router/test_manual_omr_prefix.py
new file mode 100644
index 0000000..259ce00
--- /dev/null
+++ b/tests/scripts/thread-cert/border_router/test_manual_omr_prefix.py
@@ -0,0 +1,147 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+import ipaddress
+import unittest
+
+import config
+import thread_cert
+from pktverify.consts import ICMPV6_RA_OPT_TYPE_RIO
+from pktverify.packet_verifier import PacketVerifier
+
+# Test description:
+# The purpose of this test case is to verify that BR can handle manually added OMR prefixes properly.
+#
+# Topology:
+#     BR_1 (Leader)
+#       |
+#       |
+#     BR_2
+#
+
+BR_1 = 1
+BR_2 = 2
+
+
+class ManualOmrsPrefix(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+
+    TOPOLOGY = {
+        BR_1: {
+            'name': 'BR_1',
+            'is_otbr': True,
+            'version': '1.2',
+        },
+        BR_2: {
+            'name': 'BR_2',
+            'is_otbr': True,
+            'version': '1.2',
+        },
+    }
+
+    def test(self):
+        br1 = self.nodes[BR_1]
+        br2 = self.nodes[BR_2]
+
+        br1.start()
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
+        self.assertEqual('leader', br1.get_state())
+
+        self.simulator.go(10)
+        self.assertEqual(br1.get_netdata_omr_prefixes(), [br1.get_br_omr_prefix()])
+
+        br2.disable_br()
+        br2.start()
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
+        self.assertEqual('router', br2.get_state())
+        self.assertEqual(br1.get_netdata_omr_prefixes(), [br1.get_br_omr_prefix()])
+
+        # Add a smaller OMR prefix. Verify BR_1 withdraws its OMR prefix.
+        self._test_manual_omr_prefix('2001::/64', 'paros', expect_withdraw=True, prf='low')
+        # Add a bigger OMR prefix. Verify BR_1 does not withdraw its OMR prefix.
+        self._test_manual_omr_prefix('fdff:ffff:1::/64', 'paros', expect_withdraw=False, prf='low')
+        # Add a high preference bigger OMR prefix. Verify BR_1 withdraws its OMR prefix.
+        self._test_manual_omr_prefix('fdff:ffff:2::/64', 'paros', expect_withdraw=True, prf='med')
+        # Add a smaller but invalid OMR prefix (P_on_mesh = 0). Verify BR_1 does not withdraw its OMR prefix.
+        self._test_manual_omr_prefix('2002::/64', 'pars', expect_withdraw=False)
+        # Add a smaller but invalid OMR prefix (P_stable = 0). Verify BR_1 does not withdraw its OMR prefix.
+        self._test_manual_omr_prefix('2003::/64', 'paro', expect_withdraw=False)
+        # Add a deprecating OMR prefix (P_preferred = 0). Verify BR_1 does not withdraw its OMR prefix.
+        self._test_manual_omr_prefix('2004::/64', 'aros', expect_withdraw=False)
+
+        self.collect_ipaddrs()
+        self.collect_extra_vars(BR_1_OMR_PREFIX=br1.get_br_omr_prefix())
+
+    def verify(self, pv: PacketVerifier):
+        pkts = pv.pkts
+        pv.summary.show()
+
+        BR_1_ETH = pv.vars['BR_1_ETH']
+
+        BR_1_OMR_PREFIX = pv.vars['BR_1_OMR_PREFIX']
+        assert BR_1_OMR_PREFIX.endswith('::/64')
+        BR_1_OMR_PREFIX = BR_1_OMR_PREFIX[:-3]
+
+        # Filter all ICMPv6 RA messages advertised by BR_1
+        ra_pkts = pkts.filter_eth_src(BR_1_ETH).filter_icmpv6_nd_ra()
+
+        # Verify BR_1 sends RA RIO for both BR OMR prefix and deprecating OMR prefix (i.e. 2004::/64)
+        ra_pkts.filter(lambda p: ICMPV6_RA_OPT_TYPE_RIO in p.icmpv6.opt.type and '2004::' in p.icmpv6.opt.prefix and
+                       BR_1_OMR_PREFIX in p.icmpv6.opt.prefix).must_next()
+
+    def _test_manual_omr_prefix(self, prefix, flags, expect_withdraw, prf='med'):
+        br1 = self.nodes[BR_1]
+        br2 = self.nodes[BR_2]
+
+        br2.add_prefix(prefix, flags, prf=prf)
+        br2.register_netdata()
+        self.simulator.go(10)
+
+        is_omr_prefix = ('a' in flags and 'o' in flags and 's' in flags and 'D' not in flags)
+
+        if expect_withdraw:
+            self._assert_prefixes_equal(br1.get_netdata_omr_prefixes(), [prefix])
+        elif is_omr_prefix:
+            self._assert_prefixes_equal(br1.get_netdata_omr_prefixes(), [br1.get_br_omr_prefix(), prefix])
+        else:
+            self._assert_prefixes_equal(br1.get_netdata_omr_prefixes(), [br1.get_br_omr_prefix()])
+
+        br2.remove_prefix(prefix)
+        br2.register_netdata()
+        self.simulator.go(10)
+        self._assert_prefixes_equal(br1.get_netdata_omr_prefixes(), [br1.get_br_omr_prefix()])
+        self.simulator.go(3)
+
+    def _assert_prefixes_equal(self, prefixes1, prefixes2):
+        prefixes1 = sorted([ipaddress.IPv6Network(p) for p in prefixes1])
+        prefixes2 = sorted([ipaddress.IPv6Network(p) for p in prefixes2])
+        self.assertEqual(prefixes1, prefixes2)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/border_router/test_mdns_restart.py b/tests/scripts/thread-cert/border_router/test_mdns_restart.py
new file mode 100755
index 0000000..6bcd908
--- /dev/null
+++ b/tests/scripts/thread-cert/border_router/test_mdns_restart.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+import logging
+import unittest
+from ipaddress import IPv6Network
+
+import config
+import thread_cert
+
+# Test description:
+#   This test verifies that Discovery Proxy and Advertising Proxy of otbr-agent work well after the mDNS daemon
+#   (mdns or avahi-daemon) restarts.
+#
+# Topology:
+#    ----------------(eth)------------------
+#           |                  |     |
+#          BR1 (Leader) ----- BR2   HOST
+#           |                  |
+#           ED1                ED2
+#
+
+BR1 = 1
+BR2 = 2
+HOST = 3
+ED1 = 4
+ED2 = 5
+
+LEASE = 200  # Seconds
+KEY_LEASE = 200  # Seconds
+
+
+class MdnsRestart(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+
+    TOPOLOGY = {
+        BR1: {
+            'name': 'BR1',
+            'allowlist': [BR2, ED1],
+            'is_otbr': True,
+            'version': '1.2',
+        },
+        BR2: {
+            'name': 'BR2',
+            'allowlist': [BR1, ED2],
+            'is_otbr': True,
+            'version': '1.2',
+        },
+        HOST: {
+            'name': 'Host',
+            'is_host': True,
+        },
+        ED1: {
+            'name': 'ED1',
+            'allowlist': [BR1],
+            'version': '1.2',
+            'mode': 'rn',
+        },
+        ED2: {
+            'name': 'ED2',
+            'allowlist': [BR2],
+            'version': '1.2',
+            'mode': 'rn',
+        },
+    }
+
+    def test(self):
+        br1 = self.nodes[BR1]
+        br2 = self.nodes[BR2]
+        host = self.nodes[HOST]
+        ed1 = self.nodes[ED1]
+        ed2 = self.nodes[ED2]
+
+        host.start(start_radvd=False)
+        self.simulator.go(5)
+
+        br1.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual('leader', br1.get_state())
+
+        self.simulator.go(5)
+
+        br2.start()
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
+        self.assertEqual('router', br2.get_state())
+
+        ed1.start()
+        ed2.start()
+        self.simulator.go(5)
+        self.assertEqual('child', ed1.get_state())
+        self.assertEqual('child', ed2.get_state())
+
+        br1.srp_server_set_enabled(True)
+        br1.srp_server_set_lease_range(LEASE, LEASE, KEY_LEASE, KEY_LEASE)
+        br2.srp_server_set_enabled(True)
+        br2.srp_server_set_lease_range(LEASE, LEASE, KEY_LEASE, KEY_LEASE)
+        self.simulator.go(3)
+        self.assertEqual(br1.srp_server_get_state(), 'running')
+        self.assertEqual(br2.srp_server_get_state(), 'running')
+
+        # ED1 and ED2 register a service by SRP respectively.
+
+        ed1.srp_client_set_host_name('ed1-host')
+        ed1.srp_client_set_host_address(ed1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0])
+        ed1.srp_client_add_service('ed1', '_ed1._tcp', 12345, txt_entries=['id=ed1'])
+        ed1.srp_client_enable_auto_start_mode()
+
+        ed2.srp_client_set_host_name('ed2-host')
+        ed2.srp_client_set_host_address(ed2.get_ip6_address(config.ADDRESS_TYPE.OMR)[0])
+        ed2.srp_client_add_service('ed2', '_ed2._tcp', 12345, txt_entries=['id=ed2'])
+        ed2.srp_client_enable_auto_start_mode()
+
+        self.simulator.go(10)
+
+        self.assertEqual(len(host.browse_mdns_services('_meshcop._udp')), 2)
+        self.assertEqual(len(host.browse_mdns_services('_ed1._tcp')), 1)
+        self.assertEqual(len(host.browse_mdns_services('_ed2._tcp')), 1)
+
+        # BR1's mdns restart
+        br1.stop_mdns_service()
+        br1.start_mdns_service()
+
+        self.simulator.go(10)
+
+        self.assertEqual(len(host.browse_mdns_services('_meshcop._udp')), 2)
+        self.assertEqual(len(host.browse_mdns_services('_ed1._tcp')), 1)
+        self.assertEqual(len(host.browse_mdns_services('_ed2._tcp')), 1)
+
+        ed1.dns_set_config(br1.get_ip6_address(config.ADDRESS_TYPE.ML_EID))
+        browsed_services = ed1.dns_browse('_ed2._tcp.default.service.arpa')
+        self.assertEqual(len(browsed_services), 1)
+        self.assertEqual(browsed_services['ed2']['port'], 12345)
+        self.assertEqual(browsed_services['ed2']['txt_data'], 'id=656432')
+
+        ed2.dns_set_config(br1.get_ip6_address(config.ADDRESS_TYPE.ML_EID))
+        browsed_services = ed2.dns_browse('_ed1._tcp.default.service.arpa')
+        self.assertEqual(len(browsed_services), 1)
+        self.assertEqual(browsed_services['ed1']['port'], 12345)
+        self.assertEqual(browsed_services['ed1']['txt_data'], 'id=656431')
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/border_router/test_multi_border_routers.py b/tests/scripts/thread-cert/border_router/test_multi_border_routers.py
index 8441ea0..2e5855b 100755
--- a/tests/scripts/thread-cert/border_router/test_multi_border_routers.py
+++ b/tests/scripts/thread-cert/border_router/test_multi_border_routers.py
@@ -102,21 +102,21 @@
         self.simulator.go(5)
 
         br1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br1.get_state())
 
         router1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual('router', router1.get_state())
 
         self.simulator.go(5)
 
         br2.start()
-        self.simulator.go(5)
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
         self.assertEqual('router', br2.get_state())
 
         router2.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual('router', router2.get_state())
 
         #
@@ -132,23 +132,23 @@
         logging.info("ROUTER2 addrs: %r", router2.get_addrs())
         logging.info("HOST    addrs: %r", host.get_addrs())
 
-        self.assertEqual(len(br1.get_prefixes()), 1)
-        self.assertEqual(len(router1.get_prefixes()), 1)
-        self.assertEqual(len(br2.get_prefixes()), 1)
-        self.assertEqual(len(router2.get_prefixes()), 1)
+        self.assertEqual(len(br1.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(router1.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(br2.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(router2.get_netdata_omr_prefixes()), 1)
 
-        br1_omr_prefix = br1.get_omr_prefix()
-        self.assertEqual(br1_omr_prefix, br1.get_prefixes()[0].split(' ')[0])
+        br1_omr_prefix = br1.get_br_omr_prefix()
+        self.assertEqual(br1_omr_prefix, br1.get_netdata_omr_prefixes()[0])
 
         # Each BR should independently register an external route for the on-link prefix.
-        self.assertEqual(len(br1.get_routes()), 2)
-        self.assertEqual(len(router1.get_routes()), 2)
-        self.assertEqual(len(br2.get_routes()), 2)
-        self.assertEqual(len(router2.get_routes()), 2)
+        self.assertEqual(len(br1.get_netdata_non_nat64_prefixes()), 2)
+        self.assertEqual(len(router1.get_netdata_non_nat64_prefixes()), 2)
+        self.assertEqual(len(br2.get_netdata_non_nat64_prefixes()), 2)
+        self.assertEqual(len(router2.get_netdata_non_nat64_prefixes()), 2)
 
-        br1_on_link_prefix = br1.get_on_link_prefix()
-        self.assertEqual(br1_on_link_prefix, br1.get_routes()[0].split(' ')[0])
-        self.assertEqual(br1_on_link_prefix, br1.get_routes()[1].split(' ')[0])
+        br1_on_link_prefix = br1.get_br_on_link_prefix()
+        self.assertEqual(br1_on_link_prefix, br1.get_netdata_non_nat64_prefixes()[0])
+        self.assertEqual(br1_on_link_prefix, br1.get_netdata_non_nat64_prefixes()[0])
 
         self.assertEqual(len(br1.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
         self.assertEqual(len(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
@@ -183,25 +183,24 @@
 
         self.assertGreaterEqual(len(host.get_addrs()), 3)
 
-        self.assertEqual(len(br1.get_prefixes()), 1)
-        self.assertEqual(len(router1.get_prefixes()), 1)
-        self.assertEqual(len(br2.get_prefixes()), 1)
-        self.assertEqual(len(router2.get_prefixes()), 1)
+        self.assertEqual(len(br1.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(router1.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(br2.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(router2.get_netdata_omr_prefixes()), 1)
 
-        br2_omr_prefix = br2.get_omr_prefix()
-        self.assertEqual(br2_omr_prefix, br2.get_prefixes()[0].split(' ')[0])
+        br2_omr_prefix = br2.get_br_omr_prefix()
+        self.assertEqual(br2_omr_prefix, br2.get_netdata_omr_prefixes()[0])
 
-        # Only BR2 will keep the route for BR1's on-link prefix
-        # and add route for on-link prefix of its own.
-        self.assertEqual(len(br1.get_routes()), 2)
-        self.assertEqual(len(router1.get_routes()), 2)
-        self.assertEqual(len(br2.get_routes()), 2)
-        self.assertEqual(len(router2.get_routes()), 2)
+        # There should be no changes to the external route for the
+        # on-link prefix, given that the on-link prefix is derived
+        # from the Extended PAN ID.
+        self.assertEqual(len(br1.get_netdata_non_nat64_prefixes()), 1)
+        self.assertEqual(len(router1.get_netdata_non_nat64_prefixes()), 1)
+        self.assertEqual(len(br2.get_netdata_non_nat64_prefixes()), 1)
+        self.assertEqual(len(router2.get_netdata_non_nat64_prefixes()), 1)
 
-        br2_external_routes = [route.split(' ')[0] for route in br2.get_routes()]
-
-        br2_on_link_prefix = br2.get_on_link_prefix()
-        self.assertEqual(set(map(IPv6Network, br2_external_routes)),
+        br2_on_link_prefix = br2.get_br_on_link_prefix()
+        self.assertEqual(set(map(IPv6Network, br2.get_netdata_non_nat64_prefixes())),
                          set(map(IPv6Network, [br1_on_link_prefix, br2_on_link_prefix])))
 
         self.assertEqual(len(br1.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
diff --git a/tests/scripts/thread-cert/border_router/test_multi_thread_networks.py b/tests/scripts/thread-cert/border_router/test_multi_thread_networks.py
index b0e9f92..34688af 100755
--- a/tests/scripts/thread-cert/border_router/test_multi_thread_networks.py
+++ b/tests/scripts/thread-cert/border_router/test_multi_thread_networks.py
@@ -93,21 +93,24 @@
         router2 = self.nodes[ROUTER2]
 
         br1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br1.get_state())
 
         router1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual('router', router1.get_state())
 
         br2.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br2.get_state())
 
         router2.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual('router', router2.get_state())
 
+        # Wait for network to stabilize
+        self.simulator.go(15)
+
         self.collect_ipaddrs()
 
         logging.info("BR1     addrs: %r", br1.get_addrs())
@@ -115,22 +118,22 @@
         logging.info("BR2     addrs: %r", br2.get_addrs())
         logging.info("ROUTER2 addrs: %r", router2.get_addrs())
 
-        self.assertTrue(len(br1.get_prefixes()) == 1)
-        self.assertTrue(len(router1.get_prefixes()) == 1)
-        self.assertTrue(len(br2.get_prefixes()) == 1)
-        self.assertTrue(len(router2.get_prefixes()) == 1)
+        self.assertTrue(len(br1.get_netdata_omr_prefixes()) == 1)
+        self.assertTrue(len(router1.get_netdata_omr_prefixes()) == 1)
+        self.assertTrue(len(br2.get_netdata_omr_prefixes()) == 1)
+        self.assertTrue(len(router2.get_netdata_omr_prefixes()) == 1)
 
-        br1_omr_prefix = br1.get_omr_prefix()
-        br2_omr_prefix = br2.get_omr_prefix()
+        br1_omr_prefix = br1.get_br_omr_prefix()
+        br2_omr_prefix = br2.get_br_omr_prefix()
 
         self.assertNotEqual(br1_omr_prefix, br2_omr_prefix)
 
         # Each BR should independently register an external route for the on-link prefix
         # and OMR prefix in another Thread Network.
-        self.assertTrue(len(br1.get_routes()) == 2)
-        self.assertTrue(len(router1.get_routes()) == 2)
-        self.assertTrue(len(br2.get_routes()) == 2)
-        self.assertTrue(len(router2.get_routes()) == 2)
+        self.assertTrue(len(br1.get_netdata_non_nat64_prefixes()) == 2)
+        self.assertTrue(len(router1.get_netdata_non_nat64_prefixes()) == 2)
+        self.assertTrue(len(br2.get_netdata_non_nat64_prefixes()) == 2)
+        self.assertTrue(len(router2.get_netdata_non_nat64_prefixes()) == 2)
 
         br1_external_routes = br1.get_routes()
         br2_external_routes = br2.get_routes()
diff --git a/tests/scripts/thread-cert/border_router/test_vicarious_router_solicit.py b/tests/scripts/thread-cert/border_router/test_on_link_prefix.py
similarity index 81%
rename from tests/scripts/thread-cert/border_router/test_vicarious_router_solicit.py
rename to tests/scripts/thread-cert/border_router/test_on_link_prefix.py
index ee56842..4ff831a 100755
--- a/tests/scripts/thread-cert/border_router/test_vicarious_router_solicit.py
+++ b/tests/scripts/thread-cert/border_router/test_on_link_prefix.py
@@ -34,7 +34,7 @@
 import thread_cert
 
 # Test description:
-#   This test verifies Vicarious Router Solicitation.
+#   This test verifies on-link prefix configuration.
 #
 # Topology:
 #    -------------(eth)----------------------------
@@ -67,6 +67,7 @@
             'version': '1.2',
             'channel': CHANNEL1,
             'router_selection_jitter': 1,
+            'extended_panid': '0001020304050607'
         },
         ROUTER1: {
             'name': 'Router_1',
@@ -74,6 +75,7 @@
             'version': '1.2',
             'channel': CHANNEL1,
             'router_selection_jitter': 1,
+            'extended_panid': '0001020304050607'
         },
         BR2: {
             'name': 'BR_2',
@@ -82,6 +84,7 @@
             'version': '1.2',
             'channel': CHANNEL2,
             'router_selection_jitter': 1,
+            'extended_panid': '08090a0b0c0d0e0f'
         },
         ROUTER2: {
             'name': 'Router_2',
@@ -89,6 +92,7 @@
             'version': '1.2',
             'channel': CHANNEL2,
             'router_selection_jitter': 1,
+            'extended_panid': '08090a0b0c0d0e0f'
         },
         HOST: {
             'name': 'Host',
@@ -108,11 +112,11 @@
         self.simulator.go(5)
 
         br1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br1.get_state())
 
         router1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual('router', router1.get_state())
 
         self.simulator.go(10)
@@ -122,11 +126,11 @@
         logging.info("ROUTER1 addrs: %r", router1.get_addrs())
         logging.info("HOST    addrs: %r", host.get_addrs())
 
-        self.assertEqual(len(br1.get_routes()), 1)
-        br1_on_link_prefix = br1.get_routes()[0].split(' ')[0]
-        self.assertEqual(IPv6Network(br1_on_link_prefix), IPv6Network(ON_LINK_PREFIX))
+        self.assertEqual(len(br1.get_netdata_non_nat64_prefixes()), 1)
+        on_link_prefix = br1.get_netdata_non_nat64_prefixes()[0]
+        self.assertEqual(IPv6Network(on_link_prefix), IPv6Network(ON_LINK_PREFIX))
 
-        host_on_link_addr = host.get_matched_ula_addresses(br1_on_link_prefix)[0]
+        host_on_link_addr = host.get_matched_ula_addresses(on_link_prefix)[0]
         self.assertTrue(router1.ping(host_on_link_addr))
         self.assertTrue(
             host.ping(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0], backbone=True, interface=host_on_link_addr))
@@ -135,7 +139,7 @@
         host.kill_radvd_service()
 
         br2.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br2.get_state())
 
         router2.start()
@@ -151,29 +155,27 @@
         logging.info("ROUTER2 addrs: %r", router2.get_addrs())
         logging.info("HOST    addrs: %r", host.get_addrs())
 
-        self.assertTrue(len(br1.get_prefixes()) == 1)
-        self.assertTrue(len(router1.get_prefixes()) == 1)
-        self.assertTrue(len(br2.get_prefixes()) == 1)
-        self.assertTrue(len(router2.get_prefixes()) == 1)
+        self.assertTrue(len(br1.get_netdata_omr_prefixes()) == 1)
+        self.assertTrue(len(router1.get_netdata_omr_prefixes()) == 1)
+        self.assertTrue(len(br2.get_netdata_omr_prefixes()) == 1)
+        self.assertTrue(len(router2.get_netdata_omr_prefixes()) == 1)
 
-        br1_omr_prefix = br1.get_omr_prefix()
-        br2_omr_prefix = br2.get_omr_prefix()
+        br1_omr_prefix = br1.get_br_omr_prefix()
+        br2_omr_prefix = br2.get_br_omr_prefix()
         self.assertNotEqual(br1_omr_prefix, br2_omr_prefix)
 
         # Verify that the Border Routers starts advertsing new on-link prefix
         # but don't remove the external routes for the radvd on-link prefix
         # immediately, because the SLAAC addresses are still valid.
-        self.assertEqual(len(br1.get_routes()), 3)
-        self.assertEqual(len(router1.get_routes()), 3)
-        self.assertEqual(len(br2.get_routes()), 2)
-        self.assertEqual(len(router2.get_routes()), 2)
+        self.assertEqual(len(br1.get_netdata_non_nat64_prefixes()), 3)
+        self.assertEqual(len(router1.get_netdata_non_nat64_prefixes()), 3)
+        self.assertEqual(len(br2.get_netdata_non_nat64_prefixes()), 2)
+        self.assertEqual(len(router2.get_netdata_non_nat64_prefixes()), 2)
 
-        br1_external_routes = [route.split(' ')[0] for route in br1.get_routes()]
-        br2_external_routes = [route.split(' ')[0] for route in br2.get_routes()]
-
-        on_link_prefixes = list(set(br1_external_routes).intersection(br2_external_routes))
+        on_link_prefixes = list(
+            set(br1.get_netdata_non_nat64_prefixes()).intersection(br2.get_netdata_non_nat64_prefixes()))
         self.assertEqual(len(on_link_prefixes), 1)
-        self.assertEqual(IPv6Network(on_link_prefixes[0]), IPv6Network(br2.get_on_link_prefix()))
+        self.assertEqual(IPv6Network(on_link_prefixes[0]), IPv6Network(br2.get_br_on_link_prefix()))
 
         router1_omr_addr = router1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0]
         router2_omr_addr = router2.get_ip6_address(config.ADDRESS_TYPE.OMR)[0]
diff --git a/tests/scripts/thread-cert/border_router/test_plat_udp_accessiblity.py b/tests/scripts/thread-cert/border_router/test_plat_udp_accessiblity.py
index 2bbcb62..5ed84bc 100644
--- a/tests/scripts/thread-cert/border_router/test_plat_udp_accessiblity.py
+++ b/tests/scripts/thread-cert/border_router/test_plat_udp_accessiblity.py
@@ -67,12 +67,12 @@
         router = self.nodes[ROUTER]
 
         br.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br.get_state())
         br.srp_server_set_enabled(True)
 
         router.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual('router', router.get_state())
 
         # Router1 can ping to/from the Host on infra link.
@@ -104,7 +104,7 @@
 
         reset_device.reset()
         reset_device.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertIn(reset_device.get_state(), ['leader', 'router'])
         self.simulator.go(5)
 
diff --git a/tests/scripts/thread-cert/border_router/test_publish_meshcop_service.py b/tests/scripts/thread-cert/border_router/test_publish_meshcop_service.py
index 395f8c7..25e5cd4 100755
--- a/tests/scripts/thread-cert/border_router/test_publish_meshcop_service.py
+++ b/tests/scripts/thread-cert/border_router/test_publish_meshcop_service.py
@@ -59,6 +59,7 @@
             'is_otbr': True,
             'version': '1.2',
             'network_name': 'ot-br1',
+            'boot_delay': 5,
         },
         BR2: {
             'name': 'BR_2',
@@ -66,6 +67,7 @@
             'is_otbr': True,
             'version': '1.2',
             'network_name': 'ot-br2',
+            'boot_delay': 5,
         },
         HOST: {
             'name': 'Host',
@@ -79,13 +81,18 @@
         br2 = self.nodes[BR2]
         br2.disable_br()
 
-        host.bash('service otbr-agent stop')
+        # Use different network names to distinguish meshcop services
+        br1.set_network_name('ot-br1')
+        br2.set_network_name('ot-br2')
+
         host.start(start_radvd=False)
         self.simulator.go(20)
 
         self.assertEqual(br1.get_state(), 'disabled')
+        # TODO enable this line when renaming with mDNSResponder is stable
+        # self.check_meshcop_service(br1, host)
         br1.start()
-        self.simulator.go(20)
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
         self.assertEqual('leader', br1.get_state())
         self.check_meshcop_service(br1, host)
 
@@ -96,20 +103,39 @@
         br1.stop()
         br1.set_network_name('ot-br1-1')
         br1.start()
-        self.simulator.go(10)
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
         self.check_meshcop_service(br1, host)
 
         # verify that there are two meshcop services
+        br2.set_network_name('ot-br2-1')
         br2.start()
         br2.disable_backbone_router()
         br2.enable_br()
-        self.simulator.go(25)
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
+
         service_instances = host.browse_mdns_services('_meshcop._udp')
         self.assertEqual(len(service_instances), 2)
         br1_service = self.check_meshcop_service(br1, host)
         br2_service = self.check_meshcop_service(br2, host)
         self.assertNotEqual(br1_service['host'], br2_service['host'])
 
+        br1.stop_otbr_service()
+        self.simulator.go(5)
+        br2.enable_backbone_router()
+        self.simulator.go(5)
+        self.assertEqual(len(host.browse_mdns_services('_meshcop._udp')), 1)
+        br1.start_otbr_service()
+        self.simulator.go(10)
+        self.assertEqual(len(host.browse_mdns_services('_meshcop._udp')), 2)
+        self.check_meshcop_service(br1, host)
+        self.check_meshcop_service(br2, host)
+
+        br1.factory_reset()
+        br1.set_network_name('ot-br-1-3')
+        self.assertEqual(len(host.browse_mdns_services('_meshcop._udp')), 2)
+        self.check_meshcop_service(br1, host)
+        self.check_meshcop_service(br2, host)
+
     def check_meshcop_service(self, br, host):
         services = self.discover_all_meshcop_services(host)
         for service in services:
@@ -135,7 +161,7 @@
         self.assertEqual((state_bitmap >> 8 & 1), br.get_backbone_router_state() == 'Primary')  # BBR is primary or not
         self.assertEqual(service_data['txt']['nn'], br.get_network_name())
         self.assertEqual(service_data['txt']['rv'], '1')
-        self.assertIn(service_data['txt']['tv'], ['1.1.0', '1.1.1', '1.2.0'])
+        self.assertIn(service_data['txt']['tv'], ['1.1.0', '1.1.1', '1.2.0', '1.3.0'])
 
     def discover_all_meshcop_services(self, host):
         instance_names = host.browse_mdns_services('_meshcop._udp')
diff --git a/tests/scripts/thread-cert/border_router/test_radvd_coexist.py b/tests/scripts/thread-cert/border_router/test_radvd_coexist.py
index 3c4f484..2fffd60 100755
--- a/tests/scripts/thread-cert/border_router/test_radvd_coexist.py
+++ b/tests/scripts/thread-cert/border_router/test_radvd_coexist.py
@@ -86,24 +86,24 @@
         self.simulator.go(5)
 
         br.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br.get_state())
 
         router.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual('router', router.get_state())
 
-        self.simulator.go(10)
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
         self.collect_ipaddrs()
 
         logging.info("BR      addrs: %r", br.get_addrs())
         logging.info("ROUTER  addrs: %r", router.get_addrs())
         logging.info("HOST    addrs: %r", host.get_addrs())
 
-        self.assertEqual(len(br.get_prefixes()), 1)
-        self.assertEqual(len(router.get_prefixes()), 1)
-        self.assertEqual(len(br.get_routes()), 1)
-        self.assertEqual(len(router.get_routes()), 1)
+        self.assertEqual(len(br.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(router.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 1)
+        self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 1)
 
         self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
         self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
@@ -120,10 +120,10 @@
         br.stop_radvd_service()
         self.simulator.go(15)
 
-        self.assertEqual(len(br.get_prefixes()), 1)
-        self.assertEqual(len(router.get_prefixes()), 1)
-        self.assertEqual(len(br.get_routes()), 1)
-        self.assertEqual(len(router.get_routes()), 1)
+        self.assertEqual(len(br.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(router.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 1)
+        self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 1)
 
         self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
         self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
diff --git a/tests/scripts/thread-cert/Test_MacScan.py b/tests/scripts/thread-cert/border_router/test_rcp_radio_version.py
similarity index 64%
copy from tests/scripts/thread-cert/Test_MacScan.py
copy to tests/scripts/thread-cert/border_router/test_rcp_radio_version.py
index bdc6228..a8042ba 100755
--- a/tests/scripts/thread-cert/Test_MacScan.py
+++ b/tests/scripts/thread-cert/border_router/test_rcp_radio_version.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-#  Copyright (c) 2016, The OpenThread Authors.
+#  Copyright (c) 2021, The OpenThread Authors.
 #  All rights reserved.
 #
 #  Redistribution and use in source and binary forms, with or without
@@ -14,7 +14,7 @@
 #     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"
+#  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
@@ -26,43 +26,44 @@
 #  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 #  POSSIBILITY OF SUCH DAMAGE.
 #
-
-import time
+import logging
 import unittest
 
 import thread_cert
 
-LEADER = 1
-ROUTER = 2
+# Test description:
+#   This test verifies `otbr-agent --radio-version` works.
+#
+# Topology:
+#    ----------------(eth)--------------------
+#           |
+#          BR
+#
+
+BR = 1
 
 
-class Test_MacScan(thread_cert.TestCase):
+class SingleBorderRouter(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+
     TOPOLOGY = {
-        LEADER: {
-            'channel': 12,
-            'mode': 'rdn',
-            'network_name': 'OpenThread',
-            'allowlist': [ROUTER]
-        },
-        ROUTER: {
-            'channel': 12,
-            'mode': 'rdn',
-            'network_name': 'OpenThread',
-            'allowlist': [LEADER]
+        BR: {
+            'name': 'BR',
+            'is_otbr': True,
+            'version': '1.2',
         },
     }
 
     def test(self):
-        self.nodes[LEADER].start()
-        self.nodes[LEADER].set_state('leader')
-        self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
+        br = self.nodes[BR]
+        rcp_version = br.get_rcp_version()
+        logging.info('RCP version: %s', rcp_version)
+        br.stop_otbr_service()
 
-        self.nodes[ROUTER].start()
-        time.sleep(5)
-        self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
-
-        results = self.nodes[LEADER].scan()
-        self.assertEqual(len(results), 16)
+        radio_version_output = br.bash("/usr/sbin/otbr-agent -d7 -v spinel+hdlc+uart:///dev/ttyUSB0 --radio-version")
+        logging.info("--radio-version output: %r", radio_version_output)
+        self.assertEqual(1, len(radio_version_output))
+        self.assertEqual(rcp_version, radio_version_output[0].strip())
 
 
 if __name__ == '__main__':
diff --git a/tests/scripts/thread-cert/border_router/test_single_border_router.py b/tests/scripts/thread-cert/border_router/test_single_border_router.py
index 756786c..577b73e 100755
--- a/tests/scripts/thread-cert/border_router/test_single_border_router.py
+++ b/tests/scripts/thread-cert/border_router/test_single_border_router.py
@@ -28,6 +28,7 @@
 #
 import logging
 import unittest
+from ipaddress import IPv6Network
 
 import config
 import thread_cert
@@ -84,11 +85,11 @@
         self.simulator.go(5)
 
         br.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', br.get_state())
 
         router.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual('router', router.get_state())
 
         #
@@ -102,13 +103,13 @@
         logging.info("ROUTER  addrs: %r", router.get_addrs())
         logging.info("HOST    addrs: %r", host.get_addrs())
 
-        self.assertEqual(len(br.get_prefixes()), 1)
-        self.assertEqual(len(router.get_prefixes()), 1)
-        self.assertEqual(len(br.get_routes()), 1)
-        self.assertEqual(len(router.get_routes()), 1)
+        self.assertEqual(len(br.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(router.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 1)
+        self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 1)
 
-        omr_prefix = br.get_prefixes()[0]
-        external_route = br.get_routes()[0]
+        omr_prefix = br.get_br_omr_prefix()
+        on_link_prefix = br.get_br_on_link_prefix()
 
         self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
         self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
@@ -142,10 +143,10 @@
 
         self.assertGreaterEqual(len(host.get_addrs()), 2)
 
-        self.assertEqual(len(br.get_prefixes()), 2)
-        self.assertEqual(len(router.get_prefixes()), 2)
-        self.assertEqual(len(br.get_routes()), 1)
-        self.assertEqual(len(router.get_routes()), 1)
+        self.assertEqual(len(br.get_netdata_omr_prefixes()), 2)
+        self.assertEqual(len(router.get_netdata_omr_prefixes()), 2)
+        self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 1)
+        self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 1)
 
         self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 2)
         self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 2)
@@ -168,16 +169,16 @@
         logging.info("ROUTER addrs: %r", router.get_addrs())
         logging.info("HOST    addrs: %r", host.get_addrs())
 
-        self.assertEqual(len(br.get_prefixes()), 1)
-        self.assertEqual(len(router.get_prefixes()), 1)
-        self.assertEqual(len(br.get_routes()), 1)
-        self.assertEqual(len(router.get_routes()), 1)
+        self.assertEqual(len(br.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(router.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 1)
+        self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 1)
 
         # The same local OMR and on-link prefix should be re-register.
-        self.assertEqual(br.get_prefixes(), [omr_prefix])
-        self.assertEqual(router.get_prefixes(), [omr_prefix])
-        self.assertEqual(br.get_routes(), [external_route])
-        self.assertEqual(router.get_routes(), [external_route])
+        self.assertEqual(br.get_netdata_omr_prefixes(), [omr_prefix])
+        self.assertEqual(router.get_netdata_omr_prefixes(), [omr_prefix])
+        self.assertEqual(br.get_netdata_non_nat64_prefixes(), [on_link_prefix])
+        self.assertEqual(router.get_netdata_non_nat64_prefixes(), [on_link_prefix])
 
         self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
         self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
@@ -215,23 +216,23 @@
         br.enable_br()
 
         # It takes around 10 seconds to start sending RA messages.
-        self.simulator.go(15)
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
         self.collect_ipaddrs()
 
         logging.info("BR     addrs: %r", br.get_addrs())
         logging.info("ROUTER addrs: %r", router.get_addrs())
         logging.info("HOST    addrs: %r", host.get_addrs())
 
-        self.assertEqual(len(br.get_prefixes()), 1)
-        self.assertEqual(len(router.get_prefixes()), 1)
-        self.assertEqual(len(br.get_routes()), 1)
-        self.assertEqual(len(router.get_routes()), 1)
+        self.assertEqual(len(br.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(router.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 1)
+        self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 1)
 
         # The same local OMR and on-link prefix should be re-registered.
-        self.assertEqual(br.get_prefixes(), [omr_prefix])
-        self.assertEqual(router.get_prefixes(), [omr_prefix])
-        self.assertEqual(br.get_routes(), [external_route])
-        self.assertEqual(router.get_routes(), [external_route])
+        self.assertEqual(br.get_netdata_omr_prefixes(), [omr_prefix])
+        self.assertEqual(router.get_netdata_omr_prefixes(), [omr_prefix])
+        self.assertEqual(br.get_netdata_non_nat64_prefixes(), [on_link_prefix])
+        self.assertEqual(router.get_netdata_non_nat64_prefixes(), [on_link_prefix])
 
         self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
         self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
@@ -267,25 +268,25 @@
 
         br.enable_ether()
 
-        # The routing manager may fail to send RS and will wait for 60 seconds
+        # The routing manager may fail to send RS and will wait for 4 seconds
         # before retrying.
-        self.simulator.go(80)
+        self.simulator.go(20)
         self.collect_ipaddrs()
 
         logging.info("BR     addrs: %r", br.get_addrs())
         logging.info("ROUTER addrs: %r", router.get_addrs())
         logging.info("HOST    addrs: %r", host.get_addrs())
 
-        self.assertEqual(len(br.get_prefixes()), 1)
-        self.assertEqual(len(router.get_prefixes()), 1)
-        self.assertEqual(len(br.get_routes()), 1)
-        self.assertEqual(len(router.get_routes()), 1)
+        self.assertEqual(len(br.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(router.get_netdata_omr_prefixes()), 1)
+        self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 1)
+        self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 1)
 
         # The same local OMR and on-link prefix should be re-registered.
-        self.assertEqual(br.get_prefixes(), [omr_prefix])
-        self.assertEqual(router.get_prefixes(), [omr_prefix])
-        self.assertEqual(br.get_routes(), [external_route])
-        self.assertEqual(router.get_routes(), [external_route])
+        self.assertEqual(br.get_netdata_omr_prefixes(), [omr_prefix])
+        self.assertEqual(router.get_netdata_omr_prefixes(), [omr_prefix])
+        self.assertEqual(br.get_netdata_non_nat64_prefixes(), [on_link_prefix])
+        self.assertEqual(router.get_netdata_non_nat64_prefixes(), [on_link_prefix])
 
         self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
         self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
@@ -319,13 +320,32 @@
         br.start_radvd_service(prefix=config.ONLINK_GUA_PREFIX, slaac=True)
         self.simulator.go(5)
 
-        self.assertEqual(len(br.get_routes()), 2)
-        self.assertEqual(len(router.get_routes()), 2)
+        self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 2)
+        self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 2)
 
         self.assertTrue(router.ping(host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_GUA)[0]))
         self.assertTrue(router.ping(host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0]))
         self.assertTrue(host.ping(router.get_ip6_address(config.ADDRESS_TYPE.OMR)[0], backbone=True))
 
+        #
+        # Case 7. Test if Border Router changes on-link prefix when
+        #         Extended PAN ID changes.
+        #
+
+        prefixA = br.get_br_on_link_prefix()
+
+        router.commissioner_start()
+        self.simulator.go(5)
+
+        router.send_mgmt_active_set(
+            active_timestamp=100,
+            extended_panid='0001020304050607',
+        )
+        self.simulator.go(10)
+
+        prefixB = br.get_br_on_link_prefix()
+        self.assertNotEqual(IPv6Network(prefixA), IPv6Network(prefixB))
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/scripts/thread-cert/border_router/test_trel_connectivity.py b/tests/scripts/thread-cert/border_router/test_trel_connectivity.py
new file mode 100644
index 0000000..7181138
--- /dev/null
+++ b/tests/scripts/thread-cert/border_router/test_trel_connectivity.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2021, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+import unittest
+
+import config
+import thread_cert
+
+# Test description:
+#   This test verifies TREL connectivity.
+#
+# Topology:
+#    ----------------(eth)--------------------------
+#                 |                  |
+#       FED1 --- BR1 (Leader) ----- BR2 --- ROUTER2
+#                /\
+#               /  \
+#             MED1 SED1
+#
+from config import PACKET_VERIFICATION_TREL
+from pktverify.packet_filter import PacketFilter
+from pktverify.packet_verifier import PacketVerifier
+
+BR1 = 1
+FED1 = 2
+MED1 = 3
+SED1 = 4
+BR2 = 5
+ROUTER2 = 6
+
+
+class TestTrelConnectivity(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+    PACKET_VERIFICATION = PACKET_VERIFICATION_TREL
+
+    TOPOLOGY = {
+        BR1: {
+            'name': 'BR1',
+            'allowlist': [BR2, FED1, MED1, SED1],
+            'is_otbr': True,
+            'version': '1.2',
+        },
+        FED1: {
+            'name': 'ROUTER1',
+            'allowlist': [BR1],
+            'version': '1.2',
+            'router_eligible': False,
+        },
+        MED1: {
+            'name': 'MED1',
+            'allowlist': [BR1],
+            'version': '1.2',
+            'mode': 'rn',
+        },
+        SED1: {
+            'name': 'SED1',
+            'allowlist': [BR1],
+            'version': '1.2',
+            'mode': 'n',
+        },
+        BR2: {
+            'name': 'BR2',
+            'allowlist': [BR1, ROUTER2],
+            'is_otbr': True,
+            'version': '1.2',
+        },
+        ROUTER2: {
+            'name': 'ROUTER2',
+            'allowlist': [BR2],
+            'version': '1.2',
+        },
+    }
+
+    def test(self):
+        br1 = self.nodes[BR1]
+        fed1 = self.nodes[FED1]
+        med1 = self.nodes[MED1]
+        sed1 = self.nodes[SED1]
+        br2 = self.nodes[BR2]
+        router2 = self.nodes[ROUTER2]
+
+        if br1.get_trel_state() is None:
+            self.skipTest("TREL is not enabled")
+
+        br1.start()
+        self.wait_node_state(br1, 'leader', 10)
+
+        fed1.start()
+        self.wait_node_state(fed1, 'child', 10)
+
+        med1.start()
+        self.wait_node_state(med1, 'child', 10)
+
+        sed1.start()
+        self.wait_node_state(sed1, 'child', 10)
+
+        br2.start()
+        self.wait_node_state(br2, 'router', 10)
+
+        router2.start()
+        self.wait_node_state(router2, 'router', 10)
+
+        # Allow the network to stabilize
+        self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY)
+
+        self.collect_ipaddrs()
+        self.collect_rloc16s()
+
+        router2_mleid = router2.get_mleid()
+        self.assertTrue(br1.ping(router2_mleid))
+        self.assertTrue(fed1.ping(router2_mleid))
+        self.assertTrue(med1.ping(router2_mleid))
+        self.assertTrue(sed1.ping(router2_mleid))
+
+    def verify(self, pv: PacketVerifier):
+        pkts: PacketFilter = pv.pkts
+        BR1_RLOC16 = pv.vars['BR1_RLOC16']
+        BR2_RLOC16 = pv.vars['BR2_RLOC16']
+
+        print('BR1_RLOC16:', hex(BR1_RLOC16))
+        print('BR2_RLOC16:', hex(BR2_RLOC16))
+
+        # Make sure BR1 and BR2 always use TREL for transmitting ping request and reply
+        pkts.filter_wpan_src16_dst16(BR1_RLOC16, BR2_RLOC16).filter_ping_request().must_not_next()
+        pkts.filter_wpan_src16_dst16(BR1_RLOC16, BR2_RLOC16).filter_ping_reply().must_not_next()
+
+        pkts.filter_wpan_src16_dst16(BR2_RLOC16, BR1_RLOC16).filter_ping_request().must_not_next()
+        pkts.filter_wpan_src16_dst16(BR2_RLOC16, BR1_RLOC16).filter_ping_reply().must_not_next()
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/config.py b/tests/scripts/thread-cert/config.py
index ed2dd88..3878d4e 100755
--- a/tests/scripts/thread-cert/config.py
+++ b/tests/scripts/thread-cert/config.py
@@ -44,8 +44,6 @@
 import sniffer
 from tlvs_parsing import SubTlvsFactory
 
-# This extended address will generate the MESH_LOCAL_PREFIX
-EXTENDED_PANID = '000db80000000000'
 MESH_LOCAL_PREFIX = 'fd00:db8::/64'
 MESH_LOCAL_PREFIX_REGEX_PATTERN = '^fd00:0?db8:0{0,4}:0{0,4}'
 ROUTING_LOCATOR = '64/:0:ff:fe00:/16'
@@ -69,6 +67,7 @@
 BACKBONE_PREFIX_REGEX_PATTERN = f'^{0x9100 + PORT_OFFSET:04x}:'
 BACKBONE_DOCKER_NETWORK_NAME = f'backbone{PORT_OFFSET}'
 BACKBONE_IFNAME = 'eth0'
+THREAD_IFNAME = 'wpan0'
 
 OTBR_DOCKER_IMAGE = os.getenv('OTBR_DOCKER_IMAGE', 'otbr-ot12-backbone-ci')
 OTBR_DOCKER_NAME_PREFIX = f'otbr_{PORT_OFFSET}_'
@@ -126,6 +125,9 @@
 SNIFFER_ID = int(os.getenv('SNIFFER_ID', 34))
 PANID = 0xface
 
+LEADER_STARTUP_DELAY = 12
+ROUTER_STARTUP_DELAY = 10
+BORDER_ROUTER_STARTUP_DELAY = 20
 MAX_NEIGHBOR_AGE = 100
 INFINITE_COST_TIMEOUT = 90
 
@@ -145,6 +147,11 @@
 
 THREAD_VERSION_1_1 = 2
 THREAD_VERSION_1_2 = 3
+THREAD_VERSION_1_3 = 4
+
+PACKET_VERIFICATION_NONE = 0
+PACKET_VERIFICATION_DEFAULT = 1
+PACKET_VERIFICATION_TREL = 2
 
 
 def create_default_network_data_prefix_sub_tlvs_factories():
diff --git a/tests/scripts/thread-cert/find_border_agents.py b/tests/scripts/thread-cert/find_border_agents.py
new file mode 100644
index 0000000..4351307
--- /dev/null
+++ b/tests/scripts/thread-cert/find_border_agents.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+
+import ipaddress
+import sys
+import time
+from zeroconf import IPVersion, ServiceBrowser, ServiceStateChange, Zeroconf, DNSAddress, DNSService, DNSText
+
+
+def on_service_state_change(zeroconf, service_type, name, state_change):
+    if state_change is ServiceStateChange.Added:
+        zeroconf.get_service_info(service_type, name)
+
+
+class BorderAgent(object):
+    alias = None
+    server_name = None
+    addr = None
+    port = None
+    thread_status = None
+
+    def __init__(self, alias):
+        self.alias = alias
+
+    def __repr__(self):
+        return str([self.alias, self.addr, self.port, self.thread_status])
+
+
+def get_ipaddr_priority(addr: ipaddress.IPv6Address):
+    # calculate the priority of IPv6 addresses in order: Global > non Global > Link local
+    if addr.is_link_local:
+        return 0
+
+    if not addr.is_global:
+        return 1
+
+    return 2
+
+
+def parse_cache(cache):
+    border_agents = []
+
+    # Find all border routers
+    for ptr in cache.get('_meshcop._udp.local.', []):
+        border_agents.append(BorderAgent(ptr.alias))
+
+    # Find server name, port and Thread Interface status for each border router
+    for ba in border_agents:
+        for record in cache.get(ba.alias.lower(), []):
+            if isinstance(record, DNSService):
+                ba.server_name = record.server
+                ba.port = record.port
+            elif isinstance(record, DNSText):
+                text = bytearray(record.text)
+                sb = text.split(b'sb=')[1][0:4]
+                ba.thread_status = (sb[3] & 0x18) >> 3
+
+    # Find IPv6 address for each border router
+    for ba in border_agents:
+        for record in cache.get(ba.server_name.lower(), []):
+            if isinstance(record, DNSAddress):
+                addr = ipaddress.ip_address(record.address)
+                if not isinstance(addr, ipaddress.IPv6Address) or addr.is_multicast or addr.is_loopback:
+                    continue
+
+                if not ba.addr or get_ipaddr_priority(addr) > get_ipaddr_priority(ipaddress.IPv6Address(ba.addr)):
+                    ba.addr = str(addr)
+
+    return border_agents
+
+
+def main():
+    # Browse border agents
+    zeroconf = Zeroconf(ip_version=IPVersion.V6Only)
+    ServiceBrowser(zeroconf, "_meshcop._udp.local.", handlers=[on_service_state_change])
+    time.sleep(2)
+    cache = zeroconf.cache.cache
+    zeroconf.close()
+
+    border_agents = parse_cache(cache)
+    for ba in border_agents:
+        print(ba)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/scripts/thread-cert/mcast6.py b/tests/scripts/thread-cert/mcast6.py
index 27548bc..b090fd9 100755
--- a/tests/scripts/thread-cert/mcast6.py
+++ b/tests/scripts/thread-cert/mcast6.py
@@ -68,13 +68,18 @@
     if args[0] == '-s':
         is_sender = True
         args.pop(0)
+    elif args[0] == '-u':
+        is_multicast_receiver = False
+        args.pop(0)
+    else:
+        is_multicast_receiver = True
 
     ifname, group = args
 
     if is_sender:
         sender(ifname, group)
     else:
-        receiver(ifname, group)
+        receiver(ifname, group, is_multicast_receiver=is_multicast_receiver)
 
 
 def sender(ifname, group):
@@ -94,7 +99,7 @@
         time.sleep(1)
 
 
-def receiver(ifname, group):
+def receiver(ifname, group, is_multicast_receiver=True):
     # Look up multicast group address in name server and find out IP version
     addrinfo = socket.getaddrinfo(group, None)[0]
     assert addrinfo[0] == socket.AF_INET6
@@ -110,11 +115,12 @@
     # Bind it to the port
     s.bind(('', MYPORT))
 
-    group_bin = socket.inet_pton(addrinfo[0], addrinfo[4][0])
-    # Join group
-    interface_index = if_nametoindex(ifname)
-    mreq = group_bin + struct.pack('@I', interface_index)
-    s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
+    if is_multicast_receiver:
+        group_bin = socket.inet_pton(addrinfo[0], addrinfo[4][0])
+        # Join group
+        interface_index = if_nametoindex(ifname)
+        mreq = group_bin + struct.pack('@I', interface_index)
+        s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
 
     # Loop, printing any data we receive
     while True:
diff --git a/tests/scripts/thread-cert/node.py b/tests/scripts/thread-cert/node.py
index 7b53bfa..d8b254c 100755
--- a/tests/scripts/thread-cert/node.py
+++ b/tests/scripts/thread-cert/node.py
@@ -37,6 +37,7 @@
 import sys
 import time
 import traceback
+import typing
 import unittest
 from ipaddress import IPv6Address, IPv6Network
 from typing import Union, Dict, Optional, List, Any
@@ -88,6 +89,14 @@
                                              stdout=subprocess.DEVNULL,
                                              stderr=subprocess.DEVNULL)
 
+        try:
+            self._ot_rcp_proc.wait(1)
+        except subprocess.TimeoutExpired:
+            # We expect ot-rcp not to quit in 1 second.
+            pass
+        else:
+            raise Exception(f"ot-rcp {nodeid} exited unexpectedly!")
+
     def _get_ot_rcp_path(self) -> str:
         srcdir = os.environ['top_builddir']
         path = '%s/examples/apps/ncp/ot-rcp' % srcdir
@@ -95,6 +104,7 @@
         return path
 
     def _launch_docker(self):
+        logging.info(f'Docker image: {config.OTBR_DOCKER_IMAGE}')
         subprocess.check_call(f"docker rm -f {self._docker_name} || true", shell=True)
         CI_ENV = os.getenv('CI_ENV', '').split()
         os.makedirs('/tmp/coverage/', exist_ok=True)
@@ -116,6 +126,8 @@
             config.OTBR_DOCKER_IMAGE,
             '-B',
             config.BACKBONE_IFNAME,
+            '--trel-url',
+            f'trel://{config.BACKBONE_IFNAME}',
         ],
                                              stdin=subprocess.DEVNULL,
                                              stdout=sys.stdout,
@@ -136,6 +148,29 @@
 
         assert launch_ok
 
+        self.start_ot_ctl()
+
+    def __repr__(self):
+        return f'OtbrDocker<{self.nodeid}>'
+
+    def start_otbr_service(self):
+        self.bash('service otbr-agent start')
+        self.simulator.go(3)
+        self.start_ot_ctl()
+
+    def stop_otbr_service(self):
+        self.stop_ot_ctl()
+        self.bash('service otbr-agent stop')
+
+    def stop_mdns_service(self):
+        self.bash('service avahi-daemon stop')
+        self.bash('service mdns stop')
+
+    def start_mdns_service(self):
+        self.bash('service avahi-daemon start')
+        self.bash('service mdns start')
+
+    def start_ot_ctl(self):
         cmd = f'docker exec -i {self._docker_name} ot-ctl'
         self.pexpect = pexpect.popen_spawn.PopenSpawn(cmd, timeout=30)
         if self.verbose:
@@ -151,8 +186,10 @@
             except pexpect.TIMEOUT:
                 timeout -= 0.1
 
-    def __repr__(self):
-        return f'OtbrDocker<{self.nodeid}>'
+    def stop_ot_ctl(self):
+        self.pexpect.sendeof()
+        self.pexpect.wait()
+        self.pexpect.proc.kill()
 
     def destroy(self):
         logging.info("Destroying %s", self)
@@ -161,14 +198,19 @@
         self._shutdown_socat()
 
     def _shutdown_docker(self):
-        if self._docker_proc is not None:
+        if self._docker_proc is None:
+            return
+
+        try:
             COVERAGE = int(os.getenv('COVERAGE', '0'))
             OTBR_COVERAGE = int(os.getenv('OTBR_COVERAGE', '0'))
+            test_name = os.getenv('TEST_NAME')
+            unique_node_id = f'{test_name}-{PORT_OFFSET}-{self.nodeid}'
+
             if COVERAGE or OTBR_COVERAGE:
                 self.bash('service otbr-agent stop')
 
-                test_name = os.getenv('TEST_NAME')
-                cov_file_path = f'/tmp/coverage/coverage-{test_name}-{PORT_OFFSET}-{self.nodeid}.info'
+                cov_file_path = f'/tmp/coverage/coverage-{unique_node_id}.info'
                 # Upload OTBR code coverage if OTBR_COVERAGE=1, otherwise OpenThread code coverage.
                 if OTBR_COVERAGE:
                     codecov_cmd = f'lcov --directory . --capture --output-file {cov_file_path}'
@@ -178,6 +220,12 @@
 
                 self.bash(codecov_cmd)
 
+            copyCore = subprocess.run(f'docker cp {self._docker_name}:/core ./coredump_{unique_node_id}', shell=True)
+            if copyCore.returncode == 0:
+                subprocess.check_call(
+                    f'docker cp {self._docker_name}:/usr/sbin/otbr-agent ./otbr-agent_{unique_node_id}', shell=True)
+
+        finally:
             subprocess.check_call(f"docker rm -f {self._docker_name}", shell=True)
             self._docker_proc.wait()
             del self._docker_proc
@@ -292,17 +340,47 @@
                     line = line[1:]
                 record = list(line.split())
 
-                if section != 'QUESTION':
+                if section == 'QUESTION':
+                    if record[2] in ('SRV', 'TXT'):
+                        record[0] = self.__unescape_dns_instance_name(record[0])
+                else:
                     record[1] = int(record[1])
                     if record[3] == 'SRV':
+                        record[0] = self.__unescape_dns_instance_name(record[0])
                         record[4], record[5], record[6] = map(int, [record[4], record[5], record[6]])
                     elif record[3] == 'TXT':
+                        record[0] = self.__unescape_dns_instance_name(record[0])
                         record[4:] = [self.__parse_dns_dig_txt(line)]
+                    elif record[3] == 'PTR':
+                        record[4] = self.__unescape_dns_instance_name(record[4])
 
                 dig_result[section].append(tuple(record))
 
         return dig_result
 
+    @staticmethod
+    def __unescape_dns_instance_name(name: str) -> str:
+        new_name = []
+        i = 0
+        while i < len(name):
+            c = name[i]
+
+            if c == '\\':
+                assert i + 1 < len(name), name
+                if name[i + 1].isdigit():
+                    assert i + 3 < len(name) and name[i + 2].isdigit() and name[i + 3].isdigit(), name
+                    new_name.append(chr(int(name[i + 1:i + 4])))
+                    i += 3
+                else:
+                    new_name.append(name[i + 1])
+                    i += 1
+            else:
+                new_name.append(c)
+
+            i += 1
+
+        return ''.join(new_name)
+
     def __parse_dns_dig_txt(self, line: str):
         # Example TXT entry:
         # "xp=\\000\\013\\184\\000\\000\\000\\000\\000"
@@ -363,7 +441,7 @@
         cmd = './ot-cli-%s' % (mode)
 
         # For Thread 1.2 MTD node, use ot-cli-mtd build regardless of OT_CLI_PATH
-        if self.version == '1.2' and mode == 'mtd' and 'top_builddir' in os.environ:
+        if self.version != '1.1' and mode == 'mtd' and 'top_builddir' in os.environ:
             srcdir = os.environ['top_builddir']
             cmd = '%s/examples/apps/cli/ot-cli-%s %d' % (srcdir, mode, nodeid)
 
@@ -371,11 +449,11 @@
         elif self.version == self.env_version:
             # Load Thread 1.2 BBR device when testing Thread 1.2 scenarios
             # which requires device with Backbone functionality.
-            if self.version == '1.2' and self.is_bbr:
-                if 'OT_CLI_PATH_1_2_BBR' in os.environ:
-                    cmd = os.environ['OT_CLI_PATH_1_2_BBR']
-                elif 'top_builddir_1_2_bbr' in os.environ:
-                    srcdir = os.environ['top_builddir_1_2_bbr']
+            if self.version != '1.1' and self.is_bbr:
+                if 'OT_CLI_PATH_BBR' in os.environ:
+                    cmd = os.environ['OT_CLI_PATH_BBR']
+                elif 'top_builddir_1_3_bbr' in os.environ:
+                    srcdir = os.environ['top_builddir_1_3_bbr']
                     cmd = '%s/examples/apps/cli/ot-cli-%s' % (srcdir, mode)
 
             # Load Thread device of the testing environment version (may be 1.1 or 1.2)
@@ -440,14 +518,14 @@
 
             # Load Thread 1.2 BBR device when testing Thread 1.2 scenarios
             # which requires device with Backbone functionality.
-            if self.version == '1.2' and self.is_bbr:
-                if 'OT_NCP_PATH_1_2_BBR' in os.environ:
+            if self.version != '1.1' and self.is_bbr:
+                if 'OT_NCP_PATH_1_3_BBR' in os.environ:
                     cmd = 'spinel-cli.py -p "%s%s" -n' % (
-                        os.environ['OT_NCP_PATH_1_2_BBR'],
+                        os.environ['OT_NCP_PATH_1_3_BBR'],
                         args,
                     )
-                elif 'top_builddir_1_2_bbr' in os.environ:
-                    srcdir = os.environ['top_builddir_1_2_bbr']
+                elif 'top_builddir_1_3_bbr' in os.environ:
+                    srcdir = os.environ['top_builddir_1_3_bbr']
                     cmd = '%s/examples/apps/ncp/ot-ncp-%s' % (srcdir, mode)
                     cmd = 'spinel-cli.py -p "%s%s" -n' % (
                         cmd,
@@ -536,7 +614,7 @@
 
         super().__init__(nodeid, **kwargs)
 
-        self.set_extpanid(config.EXTENDED_PANID)
+        self.set_mesh_local_prefix(config.MESH_LOCAL_PREFIX)
         self.set_addr64('%016x' % (thread_cert.EXTENDED_ADDRESS_BASE + nodeid))
 
     def _expect(self, pattern, timeout=-1, *args, **kwargs):
@@ -587,7 +665,7 @@
         if isinstance(pattern, str):
             pattern = re.compile(pattern)
 
-        if isinstance(pattern, re.Pattern):
+        if isinstance(pattern, typing.Pattern):
             return pattern.match(line)
         else:
             return any(NodeImpl._match_pattern(line, p) for p in pattern)
@@ -609,7 +687,7 @@
         return lines
 
     def __is_logging_line(self, line: str) -> bool:
-        return len(line) >= 6 and line[:6] in {'[DEBG]', '[INFO]', '[NOTE]', '[WARN]', '[CRIT]', '[NONE]'}
+        return len(line) >= 3 and line[:3] in {'[D]', '[I]', '[N]', '[W]', '[C]', '[-]'}
 
     def read_cert_messages_in_commissioning_log(self, timeout=-1):
         """Get the log of the traffic after DTLS handshake.
@@ -737,6 +815,30 @@
         self.send_command('thread stop')
         self._expect_done()
 
+    def detach(self, is_async=False):
+        cmd = 'detach'
+        if is_async:
+            cmd += ' async'
+
+        self.send_command(cmd)
+
+        if is_async:
+            self._expect_done()
+            return
+
+        end = self.simulator.now() + 4
+        while True:
+            self.simulator.go(1)
+            try:
+                self._expect_done(timeout=0.1)
+                return
+            except (pexpect.TIMEOUT, socket.timeout):
+                if self.simulator.now() > end:
+                    raise
+
+    def expect_finished_detaching(self):
+        self._expect('Finished detaching')
+
     def commissioner_start(self):
         cmd = 'commissioner start'
         self.send_command(cmd)
@@ -791,6 +893,21 @@
         self.send_command(cmd)
         self._expect_done()
 
+    def radiofilter_is_enabled(self) -> bool:
+        states = [r'Disabled', r'Enabled']
+        self.send_command('radiofilter')
+        return self._expect_result(states) == 'Enabled'
+
+    def radiofilter_enable(self):
+        cmd = 'radiofilter enable'
+        self.send_command(cmd)
+        self._expect_done()
+
+    def radiofilter_disable(self):
+        cmd = 'radiofilter disable'
+        self.send_command(cmd)
+        self._expect_done()
+
     def get_bbr_registration_jitter(self):
         self.send_command('bbr jitter')
         return int(self._expect_result(r'\d+'))
@@ -800,6 +917,11 @@
         self.send_command(cmd)
         self._expect_done()
 
+    def get_rcp_version(self) -> str:
+        self.send_command('rcp version')
+        rcp_version = self._expect_command_output()[0].strip()
+        return rcp_version
+
     def srp_server_get_state(self):
         states = ['disabled', 'running', 'stopped']
         self.send_command('srp server state')
@@ -831,6 +953,10 @@
         self.send_command(f'srp server lease {min_lease} {max_lease} {min_key_lease} {max_key_lease}')
         self._expect_done()
 
+    def srp_server_set_ttl_range(self, min_ttl, max_ttl):
+        self.send_command(f'srp server ttl {min_ttl} {max_ttl}')
+        self._expect_done()
+
     def srp_server_get_hosts(self):
         """Returns the host list on the SRP server as a list of property
            dictionary.
@@ -891,6 +1017,7 @@
                'port': '12345',
                'priority': '0',
                'weight': '0',
+               'ttl': '7200',
                'TXT': ['abc=010203'],
                'host_fullname': 'my-host.default.service.arpa.',
                'host': 'my-host',
@@ -917,8 +1044,8 @@
                 service_list.append(service)
                 continue
 
-            # 'subtypes', port', 'priority', 'weight'
-            for i in range(0, 4):
+            # 'subtypes', port', 'priority', 'weight', 'ttl'
+            for i in range(0, 5):
                 key_value = lines.pop(0).strip().split(':')
                 service[key_value[0].strip()] = key_value[1].strip()
 
@@ -1019,6 +1146,10 @@
         self.send_command(f'srp client host clear')
         self._expect_done()
 
+    def srp_client_enable_auto_host_address(self):
+        self.send_command(f'srp client host address auto')
+        self._expect_done()
+
     def srp_client_set_host_address(self, *addrs: str):
         self.send_command(f'srp client host address {" ".join(addrs)}')
         self._expect_done()
@@ -1029,6 +1160,7 @@
 
     def srp_client_add_service(self, instance_name, service_name, port, priority=0, weight=0, txt_entries=[]):
         txt_record = "".join(self._encode_txt_entry(entry) for entry in txt_entries)
+        instance_name = self._escape_escapable(instance_name)
         self.send_command(
             f'srp client service add {instance_name} {service_name} {port} {priority} {weight} {txt_record}')
         self._expect_done()
@@ -1047,6 +1179,41 @@
         service_lines = self._expect_command_output()
         return [self._parse_srp_client_service(line) for line in service_lines]
 
+    def srp_client_set_lease_interval(self, leaseinterval: int):
+        cmd = f'srp client leaseinterval {leaseinterval}'
+        self.send_command(cmd)
+        self._expect_done()
+
+    def srp_client_get_lease_interval(self) -> int:
+        cmd = 'srp client leaseinterval'
+        self.send_command(cmd)
+        return int(self._expect_result('\d+'))
+
+    def srp_client_set_ttl(self, ttl: int):
+        cmd = f'srp client ttl {ttl}'
+        self.send_command(cmd)
+        self._expect_done()
+
+    def srp_client_get_ttl(self) -> int:
+        cmd = 'srp client ttl'
+        self.send_command(cmd)
+        return int(self._expect_result('\d+'))
+
+    #
+    # TREL utilities
+    #
+
+    def get_trel_state(self) -> Union[None, bool]:
+        states = [r'Disabled', r'Enabled']
+        self.send_command('trel')
+        try:
+            return self._expect_result(states) == 'Enabled'
+        except Exception as ex:
+            if 'InvalidCommand' in str(ex):
+                return None
+
+            raise
+
     def _encode_txt_entry(self, entry):
         """Encodes the TXT entry to the DNS-SD TXT record format as a HEX string.
 
@@ -1289,6 +1456,18 @@
         self.send_command('extpanid %s' % extpanid)
         self._expect_done()
 
+    def get_extpanid(self):
+        self.send_command('extpanid')
+        return self._expect_result('[0-9a-fA-F]{16}')
+
+    def get_mesh_local_prefix(self):
+        self.send_command('prefix meshlocal')
+        return self._expect_command_output()[0]
+
+    def set_mesh_local_prefix(self, mesh_local_prefix):
+        self.send_command('prefix meshlocal %s' % mesh_local_prefix)
+        self._expect_done()
+
     def get_joiner_id(self):
         self.send_command('joiner id')
         return self._expect_result('[0-9a-fA-F]{16}')
@@ -1651,7 +1830,7 @@
         omr_addrs = []
         for addr in self.get_addrs():
             for prefix in prefixes:
-                if (addr.startswith(prefix)):
+                if (addr.startswith(prefix)) and (addr != self.__getDua()):
                     omr_addrs.append(addr)
                     break
 
@@ -1778,16 +1957,46 @@
         self.send_command('br disable')
         self._expect_done()
 
-    def get_omr_prefix(self):
+    def get_br_omr_prefix(self):
         cmd = 'br omrprefix'
         self.send_command(cmd)
         return self._expect_command_output()[0]
 
-    def get_on_link_prefix(self):
+    def get_netdata_omr_prefixes(self):
+        omr_prefixes = []
+        for prefix in self.get_prefixes():
+            prefix, flags = prefix.split()[:2]
+            if 'a' in flags and 'o' in flags and 's' in flags and 'D' not in flags:
+                omr_prefixes.append(prefix)
+
+        return omr_prefixes
+
+    def get_br_on_link_prefix(self):
         cmd = 'br onlinkprefix'
         self.send_command(cmd)
         return self._expect_command_output()[0]
 
+    def get_netdata_non_nat64_prefixes(self):
+        prefixes = []
+        routes = self.get_routes()
+        for route in routes:
+            if 'n' not in route.split(' ')[1]:
+                prefixes.append(route.split(' ')[0])
+        return prefixes
+
+    def get_br_nat64_prefix(self):
+        cmd = 'br nat64prefix'
+        self.send_command(cmd)
+        return self._expect_command_output()[0]
+
+    def get_netdata_nat64_prefix(self):
+        prefixes = []
+        routes = self.get_routes()
+        for route in routes:
+            if 'n' in route.split(' ')[1]:
+                prefixes.append(route.split(' ')[0])
+        return prefixes
+
     def get_prefixes(self):
         return self.get_netdata()['Prefixes']
 
@@ -1825,10 +2034,12 @@
 
         return netdata
 
-    def add_route(self, prefix, stable=False, prf='med'):
+    def add_route(self, prefix, stable=False, nat64=False, prf='med'):
         cmd = 'route add %s ' % prefix
         if stable:
             cmd += 's'
+        if nat64:
+            cmd += 'n'
         cmd += ' %s' % prf
         self.send_command(cmd)
         self._expect_done()
@@ -1922,12 +2133,38 @@
 
         self._expect('Conflict:', timeout=timeout)
 
-    def scan(self, result=1):
+    def scan(self, result=1, timeout=10):
         self.send_command('scan')
 
+        self.simulator.go(timeout)
+
         if result == 1:
-            return self._expect_results(
-                r'\|\s(\S+)\s+\|\s(\S+)\s+\|\s([0-9a-fA-F]{4})\s\|\s([0-9a-fA-F]{16})\s\|\s(\d+)')
+            networks = []
+            for line in self._expect_command_output()[2:]:
+                _, panid, extaddr, channel, dbm, lqi, _ = map(str.strip, line.split('|'))
+                panid = int(panid, 16)
+                channel, dbm, lqi = map(int, (channel, dbm, lqi))
+
+                networks.append({
+                    'panid': panid,
+                    'extaddr': extaddr,
+                    'channel': channel,
+                    'dbm': dbm,
+                    'lqi': lqi,
+                })
+            return networks
+
+    def scan_energy(self, timeout=10):
+        self.send_command('scan energy')
+        self.simulator.go(timeout)
+        rssi_list = []
+        for line in self._expect_command_output()[2:]:
+            _, channel, rssi, _ = line.split('|')
+            rssi_list.append({
+                'channel': int(channel.strip()),
+                'rssi': int(rssi.strip()),
+            })
+        return rssi_list
 
     def ping(self, ipaddr, num_responses=1, size=8, timeout=5, count=1, interval=1, hoplimit=64, interface=None):
         args = f'{ipaddr} {size} {count} {interval} {hoplimit} {timeout}'
@@ -1964,7 +2201,13 @@
         return result
 
     def reset(self):
-        self.send_command('reset', expect_command_echo=False)
+        self._reset('reset')
+
+    def factory_reset(self):
+        self._reset('factoryreset')
+
+    def _reset(self, cmd):
+        self.send_command(cmd, expect_command_echo=False)
         time.sleep(self.RESET_DELAY)
         # Send a "version" command and drain the CLI output after reset
         self.send_command('version', expect_command_echo=False)
@@ -2712,6 +2955,7 @@
                 'aaaa_ttl': 7100,
             }
         """
+        instance = self._escape_escapable(instance)
         cmd = f'dns service {instance} {service}'
         if server is not None:
             cmd += f' {server} {port}'
@@ -2932,6 +3176,17 @@
 
         return rxtx_list
 
+    def set_router_id_range(self, min_router_id: int, max_router_id: int):
+        cmd = f'routeridrange {min_router_id} {max_router_id}'
+        self.send_command(cmd)
+        self._expect_command_output()
+
+    def get_router_id_range(self):
+        cmd = 'routeridrange'
+        self.send_command(cmd)
+        line = self._expect_command_output()[0]
+        return [int(item) for item in line.split()]
+
 
 class Node(NodeImpl, OtCli):
     pass
@@ -2945,13 +3200,13 @@
         """Enable the ethernet interface.
         """
 
-        self.bash(f'ifconfig {self.ETH_DEV} up')
+        self.bash(f'ip link set {self.ETH_DEV} up')
 
     def disable_ether(self):
         """Disable the ethernet interface.
         """
 
-        self.bash(f'ifconfig {self.ETH_DEV} down')
+        self.bash(f'ip link set {self.ETH_DEV} down')
 
     def get_ether_addrs(self):
         output = self.bash(f'ip -6 addr list dev {self.ETH_DEV}')
@@ -3212,6 +3467,7 @@
 
 
 class OtbrNode(LinuxHost, NodeImpl, OtbrDocker):
+    TUN_DEV = config.THREAD_IFNAME
     is_otbr = True
     is_bbr = True  # OTBR is also BBR
     node_type = 'otbr-docker'
@@ -3224,6 +3480,14 @@
         self.set_log_level(5)
         super().start()
 
+    def add_ipaddr(self, addr):
+        cmd = f'ip -6 addr add {addr}/64 dev {self.TUN_DEV}'
+        self.bash(cmd)
+
+    def add_ipmaddr_tun(self, ip: str):
+        cmd = f'python3 /app/third_party/openthread/repo/tests/scripts/thread-cert/mcast6.py {self.TUN_DEV} {ip} &'
+        self.bash(cmd)
+
 
 class HostNode(LinuxHost, OtbrDocker):
     is_host = True
@@ -3232,6 +3496,7 @@
         self.nodeid = nodeid
         self.name = name or ('Host%d' % nodeid)
         super().__init__(nodeid, **kwargs)
+        self.bash('service otbr-agent stop')
 
     def start(self, start_radvd=True, prefix=config.DOMAIN_PREFIX, slaac=False):
         self._setup_sysctl()
diff --git a/tests/scripts/thread-cert/pktverify/consts.py b/tests/scripts/thread-cert/pktverify/consts.py
index 4266ad9..9afde5a 100644
--- a/tests/scripts/thread-cert/pktverify/consts.py
+++ b/tests/scripts/thread-cert/pktverify/consts.py
@@ -127,6 +127,8 @@
 LEAD_KA_URI = '/c/la'
 DIAG_GET_QRY_URI = '/d/dq'
 DIAG_GET_ANS_URI = '/d/da'
+BACKBONE_QUERY_URI = '/b/bq'
+BACKBONE_ANSWER_URI = '/b/ba'
 
 # ADDR SOL Status
 ADDR_SOL_SUCCESS = 0
@@ -308,6 +310,7 @@
     'dns',
     'igmp',
     'mdns',
+    'dns',
 }
 
 FAKE_LAYER_NAMES = {'thread_nwd', 'thread_meshcop', 'ipv6inner'}
@@ -335,6 +338,27 @@
 
 WIRESHARK_DECODE_AS_ENTRIES = {
     'udp.port==61631': 'coap',
+    # SRP server ports for dissecting SRP requests and responses
+    'udp.port==53535': 'dns',
+    'udp.port==53536': 'dns',
+    'udp.port==53537': 'dns',
+    'udp.port==53538': 'dns',
+    'udp.port==53539': 'dns',
+    'udp.port==53540': 'dns',
+    'udp.port==53541': 'dns',
+    'udp.port==53542': 'dns',
+    'udp.port==53543': 'dns',
+    'udp.port==53544': 'dns',
+    'udp.port==53545': 'dns',
+    'udp.port==53546': 'dns',
+    'udp.port==53547': 'dns',
+    'udp.port==53548': 'dns',
+    'udp.port==53549': 'dns',
+    'udp.port==53550': 'dns',
+    'udp.port==53551': 'dns',
+    'udp.port==53552': 'dns',
+    'udp.port==53553': 'dns',
+    'udp.port==53554': 'dns',
 }
 
 TIMEOUT_JOIN_NETWORK = 10
@@ -363,10 +387,28 @@
 CSL_DEFAULT_CHANNEL = 12
 
 # Thread Version TLV value
+THREAD_VERSION_1_1 = 2
 THREAD_VERSION_1_2 = 3
+THREAD_VERSION_1_3 = 4
 
 # ICMPv6 Types
 ICMPV6_TYPE_DESTINATION_UNREACHABLE = 1
+ICMPV6_TYPE_PACKET_TO_BIG = 2
+ICMPV6_TYPE_TIME_EXCEEDED = 3
+ICMPV6_TYPE_PARAMETER_PROBLEM = 4
+ICMPV6_TYPE_ECHO_REQUEST = 128
+ICMPV6_TYPE_ECHO_REPLY = 129
+
+ICMPV6_RA_OPT_TYPE_RIO = 24
+
+THREAD_ALLOWED_ICMPV6_TYPES = [
+    ICMPV6_TYPE_DESTINATION_UNREACHABLE,
+    ICMPV6_TYPE_PACKET_TO_BIG,
+    ICMPV6_TYPE_TIME_EXCEEDED,
+    ICMPV6_TYPE_PARAMETER_PROBLEM,
+    ICMPV6_TYPE_ECHO_REQUEST,
+    ICMPV6_TYPE_ECHO_REPLY,
+]
 
 # Link Metrics
 LINK_METRICS_STATUS_SUCCESS = 0
diff --git a/tests/scripts/thread-cert/pktverify/layer_fields.py b/tests/scripts/thread-cert/pktverify/layer_fields.py
index 8e65695..eb17e55 100644
--- a/tests/scripts/thread-cert/pktverify/layer_fields.py
+++ b/tests/scripts/thread-cert/pktverify/layer_fields.py
@@ -477,13 +477,7 @@
     'icmpv6.opt.route_lifetime': _auto,
     'icmpv6.opt.route_info.flag.route_preference': _auto,
     'icmpv6.opt.route_info.flag.reserved': _auto,
-    'icmpv6.opt.prefix.valid_lifetime': _auto,
-    'icmpv6.opt.prefix.preferred_lifetime': _auto,
-    'icmpv6.opt.prefix.length': _list(_auto),
-    'icmpv6.opt.prefix.flag.reserved': _auto,
-    'icmpv6.opt.prefix.flag.r': _auto,
-    'icmpv6.opt.prefix.flag.l': _auto,
-    'icmpv6.opt.prefix.flag.a': _auto,
+    'icmpv6.opt.prefix': _list(_ipv6_addr),
     'icmpv6.opt.length': _list(_auto),
     'icmpv6.opt.reserved': _str,
     'icmpv6.nd.ra.router_lifetime': _auto,
@@ -638,7 +632,11 @@
     # Thread Diagnostic
     'thread_diagnostic.tlv.type': _list(_auto),
     'thread_diagnostic.tlv.len8': _list(_auto),
-    'thread_diagnostic.tlv.general': _list(_str)
+    'thread_diagnostic.tlv.general': _list(_str),
+
+    # DNS
+    'dns.resp.ttl': _auto,
+    'dns.flags.response': _auto,
 }
 
 _layer_containers = set()
diff --git a/tests/scripts/thread-cert/pktverify/layers.py b/tests/scripts/thread-cert/pktverify/layers.py
index cd35f68..e8e3f38 100644
--- a/tests/scripts/thread-cert/pktverify/layers.py
+++ b/tests/scripts/thread-cert/pktverify/layers.py
@@ -179,3 +179,10 @@
     @property
     def is_ack(self) -> bool:
         return self.frame_type == 0x2
+
+
+class DnsLayer(Layer):
+    """
+    Represents the DNS layer of a packet.
+    """
+    pass
diff --git a/tests/scripts/thread-cert/pktverify/packet.py b/tests/scripts/thread-cert/pktverify/packet.py
index d4f340f..20e71bb 100644
--- a/tests/scripts/thread-cert/pktverify/packet.py
+++ b/tests/scripts/thread-cert/pktverify/packet.py
@@ -38,7 +38,7 @@
 from pktverify.coap import CoapLayer
 from pktverify.consts import VALID_LAYER_NAMES
 from pktverify.decorators import cached_property
-from pktverify.layers import Layer, ThreadMeshcopLayer, Icmpv6Layer, WpanLayer, ThreadNetworkDataLayer
+from pktverify.layers import Layer, ThreadMeshcopLayer, Icmpv6Layer, WpanLayer, ThreadNetworkDataLayer, DnsLayer
 from pktverify.utils import make_filter_func
 
 
@@ -102,6 +102,10 @@
     def thread_nwd(self) -> ThreadNetworkDataLayer:
         return ThreadNetworkDataLayer(self._packet, 'thread_nwd')
 
+    @cached_property
+    def dns(self) -> DnsLayer:
+        return DnsLayer(self._packet, 'dns')
+
     def __getattr__(self, layer_name: str) -> Layer:
 
         real_layer_name = layer_name
diff --git a/tests/scripts/thread-cert/pktverify/packet_filter.py b/tests/scripts/thread-cert/pktverify/packet_filter.py
index 7fc21b4..3073304 100644
--- a/tests/scripts/thread-cert/pktverify/packet_filter.py
+++ b/tests/scripts/thread-cert/pktverify/packet_filter.py
@@ -34,6 +34,7 @@
 from pktverify import consts, errors
 from pktverify.addrs import EthAddr, ExtAddr, Ipv6Addr
 from pktverify.bytes import Bytes
+from pktverify.consts import THREAD_ALLOWED_ICMPV6_TYPES
 from pktverify.packet import Packet
 from pktverify.utils import make_filter_func
 
@@ -618,6 +619,10 @@
     def filter_icmpv6_nd_ra(self):
         return self.filter(lambda p: p.icmpv6.is_router_advertisement)
 
+    def filter_thread_unallowed_icmpv6(self):
+        return self.filter('wpan and icmpv6 and icmpv6.type not in {THREAD_ALLOWED_ICMPV6_TYPES}',
+                           THREAD_ALLOWED_ICMPV6_TYPES=THREAD_ALLOWED_ICMPV6_TYPES)
+
     def filter_has_bbr_dataset(self):
         return self.filter("""
                 thread_nwd.tlv.server.has('16')
diff --git a/tests/scripts/thread-cert/pktverify/packet_verifier.py b/tests/scripts/thread-cert/pktverify/packet_verifier.py
index 5c02166..6873cf9 100644
--- a/tests/scripts/thread-cert/pktverify/packet_verifier.py
+++ b/tests/scripts/thread-cert/pktverify/packet_verifier.py
@@ -157,6 +157,14 @@
             key = self.test_info.get_node_name(i) + '_RLOC'
             self._vars[key] = rloc
 
+        for i, omr in self.test_info.omrs.items():
+            key = self.test_info.get_node_name(i) + '_OMR'
+            self._vars[key] = omr
+
+        for i, dua in self.test_info.duas.items():
+            key = self.test_info.get_node_name(i) + '_DUA'
+            self._vars[key] = dua
+
         if self.test_info.leader_aloc:
             self._vars['LEADER_ALOC'] = self.test_info.leader_aloc
 
@@ -168,7 +176,7 @@
         for i, topo in self.test_info.topology.items():
             name = self.test_info.get_node_name(i)
             if topo['version']:
-                self._vars[name + '_VERSION'] = {'1.1': 2, '1.2': 3}[topo['version']]
+                self._vars[name + '_VERSION'] = {'1.1': 2, '1.2': 3, '1.3': 4}[topo['version']]
 
     def verify_attached(self, child: str, parent: str = None, child_type: str = 'FTD', pkts=None) -> VerifyResult:
         """
diff --git a/tests/scripts/thread-cert/pktverify/test_info.py b/tests/scripts/thread-cert/pktverify/test_info.py
index c44f52a..937929b 100644
--- a/tests/scripts/thread-cert/pktverify/test_info.py
+++ b/tests/scripts/thread-cert/pktverify/test_info.py
@@ -53,6 +53,8 @@
             self.mleids = {int(k): Ipv6Addr(v) for k, v in test_info.get('mleids', {}).items()}
             self.rlocs = {int(k): Ipv6Addr(v) for k, v in test_info.get('rlocs', {}).items()}
             self.rloc16s = self._convert_hex_values(self._convert_keys_to_ints(test_info.get('rloc16s', {})))
+            self.omrs = {int(k): [Ipv6Addr(x) for x in l] for k, l in test_info.get('omrs', {}).items()}
+            self.duas = {int(k): Ipv6Addr(v) for k, v in test_info.get('duas', {}).items()}
             self.extra_vars = test_info.get('extra_vars', {})
             self.leader_aloc = Ipv6Addr(test_info.get('leader_aloc')) if 'leader_aloc' in test_info else ''
 
diff --git a/tests/scripts/thread-cert/pktverify/utils.py b/tests/scripts/thread-cert/pktverify/utils.py
index 6cf06bf..7d57ce0 100644
--- a/tests/scripts/thread-cert/pktverify/utils.py
+++ b/tests/scripts/thread-cert/pktverify/utils.py
@@ -72,6 +72,7 @@
                     'thread_nwd': p.thread_nwd,
                     'thread_address': p.thread_address,
                     'thread_bcn': p.thread_bcn,
+                    'dns': p.dns,
                     'null': nullField,
                 })
     else:
diff --git a/tests/scripts/thread-cert/run_cert_suite.py b/tests/scripts/thread-cert/run_cert_suite.py
index a3b7d57..6af09d8 100755
--- a/tests/scripts/thread-cert/run_cert_suite.py
+++ b/tests/scripts/thread-cert/run_cert_suite.py
@@ -94,10 +94,8 @@
 
 
 def setup_backbone_env():
-    bash('sudo modprobe ip6table_filter')
-
-    if THREAD_VERSION != '1.2':
-        raise RuntimeError('Backbone tests only work with THREAD_VERSION=1.2')
+    if THREAD_VERSION == '1.1':
+        raise RuntimeError('Backbone tests do not work with THREAD_VERSION=1.1')
 
     if VIRTUAL_TIME:
         raise RuntimeError('Backbone tests only work with VIRTUAL_TIME=0')
diff --git a/tests/scripts/thread-cert/test_anycast.py b/tests/scripts/thread-cert/test_anycast.py
index 70b50df..c557555 100755
--- a/tests/scripts/thread-cert/test_anycast.py
+++ b/tests/scripts/thread-cert/test_anycast.py
@@ -71,13 +71,13 @@
 
     def test(self):
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'leader')
         self.nodes[ROUTER1].udp_start('::', TEST_UDP_PORT)
 
         for i in range(ROUTER2, ROUTER5 + 1):
             self.nodes[i].start()
-            self.simulator.go(5)
+            self.simulator.go(config.ROUTER_STARTUP_DELAY)
             self.assertEqual(self.nodes[i].get_state(), 'router')
             self.nodes[i].udp_start('::', TEST_UDP_PORT)
 
diff --git a/tests/scripts/thread-cert/test_anycast_locator.py b/tests/scripts/thread-cert/test_anycast_locator.py
index c45da66..7d0883f 100755
--- a/tests/scripts/thread-cert/test_anycast_locator.py
+++ b/tests/scripts/thread-cert/test_anycast_locator.py
@@ -32,6 +32,7 @@
 import unittest
 
 import command
+import config
 import thread_cert
 
 # Test description:
@@ -98,12 +99,12 @@
         #
 
         leader.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(leader.get_state(), 'leader')
 
         for node in nodes[1:]:
             node.start()
-            self.simulator.go(5)
+            self.simulator.go(config.ROUTER_STARTUP_DELAY)
             self.assertEqual(node.get_state(), 'router')
 
         #
diff --git a/tests/scripts/thread-cert/test_br_upgrade_router_role.py b/tests/scripts/thread-cert/test_br_upgrade_router_role.py
new file mode 100755
index 0000000..91b1fa9
--- /dev/null
+++ b/tests/scripts/thread-cert/test_br_upgrade_router_role.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+import ipaddress
+import unittest
+
+import command
+import config
+import thread_cert
+
+# Test description:
+#
+# This test verifies behavior of Border Routers (which provide IP connectivity) requesting router role within Thread
+# mesh.
+
+# Topology:
+#
+#  5 FTD nodes, all connected.
+#
+#  Topology is expected to change during execution of test.
+#
+
+LEADER = 1
+ROUTER = 2
+BR1 = 3
+BR2 = 4
+BR3 = 5
+
+
+class BrUpgradeRouterRole(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+    SUPPORT_NCP = False
+
+    TOPOLOGY = {
+        LEADER: {
+            'name': 'leader',
+            'mode': 'rdn',
+        },
+        ROUTER: {
+            'name': 'reader',
+            'mode': 'rdn',
+        },
+        BR1: {
+            'name': 'br-1',
+            'mode': 'rdn',
+        },
+        BR2: {
+            'name': 'br-2',
+            'mode': 'rdn',
+        },
+        BR3: {
+            'name': 'br-3',
+            'mode': 'rdn',
+        },
+    }
+
+    def test(self):
+        leader = self.nodes[LEADER]
+        router = self.nodes[ROUTER]
+        br1 = self.nodes[BR1]
+        br2 = self.nodes[BR2]
+        br3 = self.nodes[BR3]
+
+        #-------------------------------------------------------------------------------------
+        # Set the router upgrade threshold to 2 on all nodes.
+
+        for node in [leader, router, br1, br2, br3]:
+            node.set_router_upgrade_threshold(2)
+
+        #-------------------------------------------------------------------------------------
+        # Start the leader and router.
+
+        leader.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual(leader.get_state(), 'leader')
+
+        router.start()
+        self.simulator.go(125)
+        self.assertEqual(router.get_state(), 'router')
+
+        #-------------------------------------------------------------------------------------
+        # Start all three BRs, we expect all to stay as child since there are already two
+        # routers in the Thread mesh.
+
+        br1.start()
+        br2.start()
+        br3.start()
+        self.simulator.go(125)
+        self.assertEqual(br1.get_state(), 'child')
+        self.assertEqual(br2.get_state(), 'child')
+        self.assertEqual(br3.get_state(), 'child')
+
+        #-------------------------------------------------------------------------------------
+        # Add an external route on `br1`, it should now try to become a router requesting
+        # with status BorderRouterRequest. Verify that leader allows it to become router.
+
+        br1.add_route('2001:dead:beef:cafe::/64', stable=True)
+        br1.register_netdata()
+        self.simulator.go(15)
+        self.assertEqual(br1.get_state(), 'router')
+
+        #-------------------------------------------------------------------------------------
+        # Add a prefix with default route on `br2`, it should also become a router.
+
+        br2.add_prefix('2001:dead:beef:2222::/64', 'paros')
+        br2.register_netdata()
+        self.simulator.go(15)
+        self.assertEqual(br2.get_state(), 'router')
+
+        #-------------------------------------------------------------------------------------
+        # Add an external route on `br3`, it should not become a router since we already have
+        # two that requested router role upgrade as border router reason.
+
+        br3.add_route('2001:dead:beef:cafe::/64', stable=True)
+        br3.register_netdata()
+        self.simulator.go(120)
+        self.assertEqual(br3.get_state(), 'child')
+
+        #-------------------------------------------------------------------------------------
+        # Remove the external route on `br1`. This should now trigger `br3` to request a
+        # router role upgrade since number of BRs acting as router in network data is now
+        # below the threshold of two.
+
+        br1.remove_route('2001:dead:beef:cafe::/64')
+        br1.register_netdata()
+        self.simulator.go(15)
+        self.assertEqual(br1.get_state(), 'router')
+        self.assertEqual(br3.get_state(), 'router')
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/test_coap_block.py b/tests/scripts/thread-cert/test_coap_block.py
index 0bc1333..561f8cf 100755
--- a/tests/scripts/thread-cert/test_coap_block.py
+++ b/tests/scripts/thread-cert/test_coap_block.py
@@ -57,11 +57,11 @@
 
     def _do_transfer_test(self, method):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         mleid = self.nodes[LEADER].get_ip6_address(config.ADDRESS_TYPE.ML_EID)
diff --git a/tests/scripts/thread-cert/test_coap_observe.py b/tests/scripts/thread-cert/test_coap_observe.py
index 13bfa8f..5aa89db 100755
--- a/tests/scripts/thread-cert/test_coap_observe.py
+++ b/tests/scripts/thread-cert/test_coap_observe.py
@@ -57,11 +57,11 @@
 
     def _do_notification_test(self, con):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         mleid = self.nodes[LEADER].get_ip6_address(config.ADDRESS_TYPE.ML_EID)
diff --git a/tests/scripts/thread-cert/test_coaps.py b/tests/scripts/thread-cert/test_coaps.py
index 46b43ae..50e3255 100755
--- a/tests/scripts/thread-cert/test_coaps.py
+++ b/tests/scripts/thread-cert/test_coaps.py
@@ -52,11 +52,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         mleid = self.nodes[LEADER].get_ip6_address(config.ADDRESS_TYPE.ML_EID)
diff --git a/tests/scripts/thread-cert/test_dataset_updater.py b/tests/scripts/thread-cert/test_dataset_updater.py
index 0ce709d..ba3bc9f 100755
--- a/tests/scripts/thread-cert/test_dataset_updater.py
+++ b/tests/scripts/thread-cert/test_dataset_updater.py
@@ -66,11 +66,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[MED].start()
diff --git a/tests/scripts/thread-cert/test_detach.py b/tests/scripts/thread-cert/test_detach.py
new file mode 100755
index 0000000..2c1693d
--- /dev/null
+++ b/tests/scripts/thread-cert/test_detach.py
@@ -0,0 +1,181 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+import unittest
+
+import thread_cert
+import config
+from pktverify.consts import MLE_CHILD_UPDATE_REQUEST, TIMEOUT_TLV, ADDR_REL_URI
+from pktverify.packet_verifier import PacketVerifier
+
+# Test description:
+#   This test verifies that detaching function can send correct "goodbye" messages.
+#
+# Topology:
+#
+#   CHILD_1 ----- ROUTER_1 ----- LEADER
+#
+#
+
+LEADER = 1
+ROUTER_1 = 2
+CHILD_1 = 3
+
+
+class TestDetach(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+    SUPPORT_NCP = False
+
+    TOPOLOGY = {
+        LEADER: {
+            'name': 'Leader',
+            'allowlist': [ROUTER_1],
+            'mode': 'rdn',
+        },
+        ROUTER_1: {
+            'name': 'Router_1',
+            'allowlist': [LEADER, CHILD_1],
+            'mode': 'rdn',
+        },
+        CHILD_1: {
+            'name': 'Child_1',
+            'is_mtd': True,
+            'allowlist': [ROUTER_1],
+            'mode': '-',
+            'timeout': 10,
+        },
+    }
+
+    def test(self):
+        leader = self.nodes[LEADER]
+        router1 = self.nodes[ROUTER_1]
+        child1 = self.nodes[CHILD_1]
+
+        leader.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual(leader.get_state(), 'leader')
+
+        router1.start()
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
+        self.assertEqual(router1.get_state(), 'router')
+        router1_rloc16 = router1.get_addr16()
+        self.assertTrue(list(filter(lambda x: x[1]['rloc16'] == router1_rloc16, leader.router_table().items())))
+
+        self.collect_rloc16s()
+
+        child1.start()
+        self.simulator.go(7)
+        self.assertEqual(child1.get_state(), 'child')
+        child_table = router1.get_child_table()
+        self.assertEqual(len(child_table), 1)
+        self.assertEqual(child_table[1]['timeout'], 10)
+
+        child1.detach()
+        self.assertEqual(child1.get_state(), 'disabled')
+        self.assertFalse(router1.get_child_table())
+
+        router1.detach()
+        self.assertEqual(router1.get_state(), 'disabled')
+        self.assertFalse(list(filter(lambda x: x[1]['rloc16'] == router1_rloc16, leader.router_table().items())))
+
+        router1.start()
+        self.simulator.go(5)
+        self.assertEqual(router1.get_state(), 'router')
+
+        child1.start()
+        self.simulator.go(7)
+        self.assertEqual(child1.get_state(), 'child')
+        child_table = router1.get_child_table()
+        self.assertEqual(len(child_table), 1)
+        self.assertEqual(child_table[2]['timeout'], 10)
+
+        router1.thread_stop()
+        self.assertEqual(router1.get_state(), 'disabled')
+        child1.detach()
+        self.assertEqual(child1.get_state(), 'disabled')
+
+        router1.start()
+        self.simulator.go(5)
+        self.assertEqual(router1.get_state(), 'router')
+
+        child1.start()
+        self.simulator.go(7)
+        self.assertEqual(child1.get_state(), 'child')
+
+        leader.detach()
+        self.assertEqual(leader.get_state(), 'disabled')
+
+        self.assertTrue(child1.ping(router1.get_mleid(), timeout=20))
+
+        router1.detach()
+        self.assertEqual(router1.get_state(), 'disabled')
+
+        leader.detach()
+        self.assertEqual(leader.get_state(), 'disabled')
+
+        leader.start()
+        self.assertEqual(leader.get_state(), 'detached')
+        leader.detach()
+        self.assertEqual(leader.get_state(), 'disabled')
+
+        leader.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual(leader.get_state(), 'leader')
+        router1.start()
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
+        self.assertEqual(router1.get_state(), 'router')
+
+        leader.thread_stop()
+        router1.detach(is_async=True)
+        self.assertEqual(router1.get_state(), 'router')
+        router1.thread_stop()
+        self.assertEqual(router1.get_state(), 'disabled')
+        router1.detach()
+        self.assertEqual(router1.get_state(), 'disabled')
+
+    def verify(self, pv: PacketVerifier):
+        pkts = pv.pkts
+        pv.summary.show()
+
+        leader = pv.vars['Leader']
+        router1 = pv.vars['Router_1']
+        child1 = pv.vars['Child_1']
+        leader_rloc16 = pv.vars['Leader_RLOC16']
+
+        pkts.filter_wpan_src64(child1).filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).filter_wpan_dst64(
+            router1).must_next().must_verify(lambda p: TIMEOUT_TLV in set(p.mle.tlv.type) and p.mle.tlv.timeout == 0)
+        pkts.filter_wpan_src64(router1).filter_coap_request(ADDR_REL_URI).filter_wpan_dst16(leader_rloc16).must_next()
+        pkts.filter_wpan_src64(child1).filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).filter_wpan_dst64(
+            router1).must_next().must_verify(lambda p: TIMEOUT_TLV in set(p.mle.tlv.type) and p.mle.tlv.timeout == 0)
+        pkts.filter_wpan_src64(leader).filter_coap_request(ADDR_REL_URI).must_not_next()
+        pkts.filter_wpan_src64(router1).filter_coap_request(ADDR_REL_URI).filter_wpan_dst16(leader_rloc16).must_next()
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/test_dns_client_config_auto_start.py b/tests/scripts/thread-cert/test_dns_client_config_auto_start.py
index c6b3807..9b9a2e7 100755
--- a/tests/scripts/thread-cert/test_dns_client_config_auto_start.py
+++ b/tests/scripts/thread-cert/test_dns_client_config_auto_start.py
@@ -30,6 +30,7 @@
 import unittest
 
 import command
+import config
 import thread_cert
 
 # Test description:
@@ -72,18 +73,18 @@
         # Form network.
 
         leader.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(leader.get_state(), 'leader')
 
         router.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(router.get_state(), 'router')
 
         # On leader set DNS config explicitly.
 
         leader.dns_set_config(DEFAULT_ADDRESS)
-        config = leader.dns_get_config()
-        self.assertEqual(config['Server'], '[{}]:53'.format(DEFAULT_ADDRESS))
+        dns_config = leader.dns_get_config()
+        self.assertEqual(dns_config['Server'], '[{}]:53'.format(DEFAULT_ADDRESS))
 
         # Start leader to act as SRP server.
 
@@ -101,27 +102,27 @@
         srp_server_address = router.srp_client_get_server_address()
         self.assertEqual(leader.srp_client_get_server_address(), srp_server_address)
 
-        config = router.dns_get_config()
-        self.assertEqual(config['Server'], '[{}]:53'.format(srp_server_address))
+        dns_config = router.dns_get_config()
+        self.assertEqual(dns_config['Server'], '[{}]:53'.format(srp_server_address))
 
         # Verify that on leader the default DNS config remains
         # as before (the address explicitly set earlier).
 
-        config = leader.dns_get_config()
-        self.assertEqual(config['Server'], '[{}]:53'.format(DEFAULT_ADDRESS))
+        dns_config = leader.dns_get_config()
+        self.assertEqual(dns_config['Server'], '[{}]:53'.format(DEFAULT_ADDRESS))
 
         # On leader clear DNS config (the explicitly set address)
         # and verify that it adopts the SRP server address.
 
         leader.dns_set_config("::")
-        config = leader.dns_get_config()
-        self.assertEqual(config['Server'], '[{}]:53'.format(srp_server_address))
+        dns_config = leader.dns_get_config()
+        self.assertEqual(dns_config['Server'], '[{}]:53'.format(srp_server_address))
 
         # On leader set DNS config explicitly again.
 
         leader.dns_set_config(DEFAULT_ADDRESS)
-        config = leader.dns_get_config()
-        self.assertEqual(config['Server'], '[{}]:53'.format(DEFAULT_ADDRESS))
+        dns_config = leader.dns_get_config()
+        self.assertEqual(dns_config['Server'], '[{}]:53'.format(DEFAULT_ADDRESS))
 
         # Stop SRP server on leader and start it on router.
 
@@ -137,12 +138,12 @@
         # Verify that config on router gets changed while on leader
         # it remains unchanged.
 
-        config = router.dns_get_config()
+        dns_config = router.dns_get_config()
         srp_server_address = router.srp_client_get_server_address()
-        self.assertEqual(config['Server'], '[{}]:53'.format(srp_server_address))
+        self.assertEqual(dns_config['Server'], '[{}]:53'.format(srp_server_address))
 
-        config = leader.dns_get_config()
-        self.assertEqual(config['Server'], '[{}]:53'.format(DEFAULT_ADDRESS))
+        dns_config = leader.dns_get_config()
+        self.assertEqual(dns_config['Server'], '[{}]:53'.format(DEFAULT_ADDRESS))
 
 
 if __name__ == '__main__':
diff --git a/tests/scripts/thread-cert/test_dnssd.py b/tests/scripts/thread-cert/test_dnssd.py
index 98dbb20..e3c88ba 100755
--- a/tests/scripts/thread-cert/test_dnssd.py
+++ b/tests/scripts/thread-cert/test_dnssd.py
@@ -30,6 +30,7 @@
 import typing
 import unittest
 
+import config
 import thread_cert
 
 # Test description:
@@ -83,14 +84,14 @@
         # Start the server & client devices.
 
         server.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(server.get_state(), 'leader')
         server.srp_server_set_enabled(True)
 
         client1.start()
         client2.start()
         client3.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(client1.get_state(), 'router')
         self.assertEqual(client2.get_state(), 'router')
         self.assertEqual(client3.get_state(), 'router')
@@ -103,13 +104,13 @@
         client3_addrs = [client3.get_mleid(), client2.get_rloc()]
 
         self._config_srp_client_services(client1, server, 'ins1', 'host1', 11111, 1, 1, client1_addrs, ",_s1,_s2")
-        self._config_srp_client_services(client2, server, 'ins2', 'host2', 22222, 2, 2, client2_addrs)
-        self._config_srp_client_services(client3, server, 'ins3', 'host3', 33333, 3, 3, client3_addrs, ",_s1")
+        self._config_srp_client_services(client2, server, 'ins2', 'HOST2', 22222, 2, 2, client2_addrs)
+        self._config_srp_client_services(client3, server, 'ins3', 'host3', 33333, 3, 3, client3_addrs, ",_S1")
 
         #---------------------------------------------------------------
         # Resolve address (AAAA records)
 
-        answers = client1.dns_resolve(f"host1.{DOMAIN}", server.get_mleid(), 53)
+        answers = client1.dns_resolve(f"host1.{DOMAIN}".upper(), server.get_mleid(), 53)
         self.assertEqual(set(ipaddress.IPv6Address(ip) for ip, _ in answers),
                          set(map(ipaddress.IPv6Address, client1_addrs)))
 
@@ -169,36 +170,36 @@
         }
 
         # Browse for main service
-        service_instances = client1.dns_browse(f'{SERVICE}.{DOMAIN}', server.get_mleid(), 53)
+        service_instances = client1.dns_browse(f'{SERVICE}.{DOMAIN}'.upper(), server.get_mleid(), 53)
         self.assertEqual({'ins1', 'ins2', 'ins3'}, set(service_instances.keys()))
         self._assert_service_instance_equal(service_instances['ins1'], instance1_verify_info)
         self._assert_service_instance_equal(service_instances['ins2'], instance2_verify_info)
         self._assert_service_instance_equal(service_instances['ins3'], instance3_verify_info)
 
         # Browse for service sub-type _s1.
-        service_instances = client1.dns_browse(f'_s1._sub.{SERVICE}.{DOMAIN}', server.get_mleid(), 53)
+        service_instances = client1.dns_browse(f'_s1._sub.{SERVICE}.{DOMAIN}'.upper(), server.get_mleid(), 53)
         self.assertEqual({'ins1', 'ins3'}, set(service_instances.keys()))
         self._assert_service_instance_equal(service_instances['ins1'], instance1_verify_info)
 
         # Browse for service sub-type _s2.
-        service_instances = client1.dns_browse(f'_s2._sub.{SERVICE}.{DOMAIN}', server.get_mleid(), 53)
+        service_instances = client1.dns_browse(f'_s2._sub.{SERVICE}.{DOMAIN}'.upper(), server.get_mleid(), 53)
         self.assertEqual({'ins1'}, set(service_instances.keys()))
         self._assert_service_instance_equal(service_instances['ins1'], instance1_verify_info)
 
         #---------------------------------------------------------------
         # Resolve service
 
-        service_instance = client1.dns_resolve_service('ins1', f'{SERVICE}.{DOMAIN}', server.get_mleid(), 53)
+        service_instance = client1.dns_resolve_service('ins1', f'{SERVICE}.{DOMAIN}'.upper(), server.get_mleid(), 53)
         self._assert_service_instance_equal(service_instance, instance1_verify_info)
 
-        service_instance = client1.dns_resolve_service('ins2', f'{SERVICE}.{DOMAIN}', server.get_mleid(), 53)
+        service_instance = client1.dns_resolve_service('ins2', f'{SERVICE}.{DOMAIN}'.upper(), server.get_mleid(), 53)
         self._assert_service_instance_equal(service_instance, instance2_verify_info)
 
         #---------------------------------------------------------------
         # Add another service with TXT entries to the existing host and
         # verify that it is properly merged.
 
-        client3.srp_client_add_service('ins4', SERVICE + ",_s1", 44444, 4, 4, txt_entries=['KEY=ABC'])
+        client3.srp_client_add_service('ins4', (SERVICE + ",_s1").upper(), 44444, 4, 4, txt_entries=['KEY=ABC'])
         self.simulator.go(5)
 
         service_instances = client1.dns_browse(f'{SERVICE}.{DOMAIN}', server.get_mleid(), 53)
@@ -209,7 +210,8 @@
         self._assert_service_instance_equal(service_instances['ins4'], instance4_verify_info)
 
     def _assert_service_instance_equal(self, instance, info):
-        for f in ('port', 'priority', 'weight', 'host', 'txt_data'):
+        self.assertEqual(instance['host'].lower(), info['host'].lower(), instance)
+        for f in ('port', 'priority', 'weight', 'txt_data'):
             self.assertEqual(instance[f], info[f], instance)
 
         verify_addresses = info['address']
diff --git a/tests/scripts/thread-cert/test_dnssd_name_with_special_chars.py b/tests/scripts/thread-cert/test_dnssd_name_with_special_chars.py
new file mode 100644
index 0000000..6adf538
--- /dev/null
+++ b/tests/scripts/thread-cert/test_dnssd_name_with_special_chars.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2021, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+import ipaddress
+import unittest
+import logging
+
+import command
+import config
+import thread_cert
+
+# Test description:
+#   This test verifies SRP/DNS client/server support for Service Instance names with special and unicode characters.
+#
+# Topology:
+#
+#     LEADER (SRP server)
+#       |
+#       |
+#     ROUTER (SRP client)
+#
+
+SERVER = 1
+CLIENT = 2
+
+# TODO: support Instance names with dots (.)
+SPECIAL_INSTANCE_NAME = 'O\\T 网关'
+
+
+class TestDnssdNameWithSpecialChars(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+    SUPPORT_NCP = False
+
+    TOPOLOGY = {
+        SERVER: {
+            'name': 'SERVER',
+            'mode': 'rdn',
+        },
+        CLIENT: {
+            'name': 'CLIENT',
+            'mode': 'rdn',
+        },
+    }
+
+    def test(self):
+        server = self.nodes[SERVER]
+        client = self.nodes[CLIENT]
+
+        # Start the server & client devices.
+
+        server.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual(server.get_state(), 'leader')
+
+        client.start()
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
+        self.assertEqual(client.get_state(), 'router')
+
+        server.srp_server_set_enabled(True)
+        client.srp_client_enable_auto_start_mode()
+        self.simulator.go(5)
+
+        # Register a single service with the instance name containing special chars
+        client.srp_client_set_host_name('host1')
+        client.srp_client_set_host_address('2001::1')
+        client.srp_client_add_service(SPECIAL_INSTANCE_NAME, '_srv._udp', 1977)
+        self.simulator.go(5)
+        self.__check_service_discovery(server, client)
+
+    def __check_service_discovery(self, server, client):
+        # Check the service on client
+        client.dns_set_config(server.get_rloc())
+        services = client.dns_browse('_srv._udp.default.service.arpa')
+        self.assertEqual(1, len(services))
+        self.assertIn(SPECIAL_INSTANCE_NAME, services)
+        self.__verify_service(services[SPECIAL_INSTANCE_NAME])
+
+        service = client.dns_resolve_service(SPECIAL_INSTANCE_NAME, '_srv._udp.default.service.arpa')
+        self.__verify_service(service)
+
+        service = client.dns_resolve_service(SPECIAL_INSTANCE_NAME.lower(), '_srv._udp.default.service.arpa')
+        self.__verify_service(service)
+
+    def __verify_service(self, service):
+        logging.info('service discovered: %r', service)
+        self.assertEqual(service['port'], 1977)
+        self.assertEqual(service['host'], 'host1.default.service.arpa.')
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/test_history_tracker.py b/tests/scripts/thread-cert/test_history_tracker.py
index 6d2efee..74bbc1b 100755
--- a/tests/scripts/thread-cert/test_history_tracker.py
+++ b/tests/scripts/thread-cert/test_history_tracker.py
@@ -30,6 +30,8 @@
 import os
 import unittest
 import sys
+
+import config
 import thread_cert
 
 # Test description:
@@ -74,7 +76,7 @@
         # is updated correctly.
 
         leader.start()
-        self.simulator.go(SHORT_WAIT)
+        self.simulator.go(SHORT_WAIT * 2)
         self.assertEqual(leader.get_state(), 'leader')
 
         netinfo = leader.history_netinfo()
@@ -126,7 +128,7 @@
         # Start leader and child
 
         leader.start()
-        self.simulator.go(SHORT_WAIT)
+        self.simulator.go(SHORT_WAIT * 2)
         self.assertEqual(leader.get_state(), 'leader')
 
         child.start()
diff --git a/tests/scripts/thread-cert/test_inform_previous_parent_on_reattach.py b/tests/scripts/thread-cert/test_inform_previous_parent_on_reattach.py
index 6809bc0..308bab3 100755
--- a/tests/scripts/thread-cert/test_inform_previous_parent_on_reattach.py
+++ b/tests/scripts/thread-cert/test_inform_previous_parent_on_reattach.py
@@ -81,11 +81,11 @@
             self.skipTest("skip for posix tests")
 
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(7)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[MED].start()
diff --git a/tests/scripts/thread-cert/test_ipv6_fragmentation.py b/tests/scripts/thread-cert/test_ipv6_fragmentation.py
index 2b5d8e2..46739d6 100755
--- a/tests/scripts/thread-cert/test_ipv6_fragmentation.py
+++ b/tests/scripts/thread-cert/test_ipv6_fragmentation.py
@@ -55,11 +55,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         mleid_leader = self.nodes[LEADER].get_ip6_address(config.ADDRESS_TYPE.ML_EID)
diff --git a/tests/scripts/thread-cert/test_ipv6_source_selection.py b/tests/scripts/thread-cert/test_ipv6_source_selection.py
index abaa7b1..0985e23 100755
--- a/tests/scripts/thread-cert/test_ipv6_source_selection.py
+++ b/tests/scripts/thread-cert/test_ipv6_source_selection.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import ipv6
 import thread_cert
 
@@ -54,11 +55,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         leader_aloc = self.nodes[LEADER].get_addr_leader_aloc()
diff --git a/tests/scripts/thread-cert/Test_MacScan.py b/tests/scripts/thread-cert/test_mac_scan.py
similarity index 81%
rename from tests/scripts/thread-cert/Test_MacScan.py
rename to tests/scripts/thread-cert/test_mac_scan.py
index bdc6228..7c023c4 100755
--- a/tests/scripts/thread-cert/Test_MacScan.py
+++ b/tests/scripts/thread-cert/test_mac_scan.py
@@ -26,26 +26,31 @@
 #  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 #  POSSIBILITY OF SUCH DAMAGE.
 #
-
-import time
+import logging
 import unittest
 
+import config
 import thread_cert
 
 LEADER = 1
 ROUTER = 2
 
+CHANNEL = 12
+
 
 class Test_MacScan(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+    SUPPORT_NCP = False
+
     TOPOLOGY = {
         LEADER: {
-            'channel': 12,
+            'channel': CHANNEL,
             'mode': 'rdn',
             'network_name': 'OpenThread',
             'allowlist': [ROUTER]
         },
         ROUTER: {
-            'channel': 12,
+            'channel': CHANNEL,
             'mode': 'rdn',
             'network_name': 'OpenThread',
             'allowlist': [LEADER]
@@ -58,11 +63,15 @@
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        time.sleep(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
-        results = self.nodes[LEADER].scan()
-        self.assertEqual(len(results), 16)
+        results = self.nodes[LEADER].scan(result=True)
+        logging.info('scan result: %r', results)
+        self.assertEqual(len(results), 1)
+        network = results[0]
+        self.assertEqual(network['extaddr'], self.nodes[ROUTER].get_addr64())
+        self.assertEqual(network['channel'], CHANNEL)
 
 
 if __name__ == '__main__':
diff --git a/tests/scripts/thread-cert/test_mle_msg_key_seq_jump.py b/tests/scripts/thread-cert/test_mle_msg_key_seq_jump.py
new file mode 100755
index 0000000..90f1b2e
--- /dev/null
+++ b/tests/scripts/thread-cert/test_mle_msg_key_seq_jump.py
@@ -0,0 +1,241 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+import ipaddress
+import unittest
+
+import command
+import config
+import thread_cert
+
+# Test description:
+#
+#   This test verifies behavior of MLE related to handling of received
+#   larger key sequence based on the MLE message class (authoritative,
+#   or peer).
+#
+#
+# Topology:
+#
+#   leader ---  router
+#    |    \
+#    |     \
+#  child   reed
+#
+
+LEADER = 1
+CHILD = 2
+REED = 3
+ROUTER = 4
+
+
+class MleMsgKeySeqJump(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+    SUPPORT_NCP = False
+
+    TOPOLOGY = {
+        LEADER: {
+            'name': 'LEADER',
+            'mode': 'rdn',
+        },
+        CHILD: {
+            'name': 'CHILD',
+            'is_mtd': True,
+            'mode': 'rn',
+        },
+        REED: {
+            'name': 'REED',
+            'mode': 'rn'
+        },
+        ROUTER: {
+            'name': 'ROUTER',
+            'mode': 'rdn',
+        },
+    }
+
+    def test(self):
+        leader = self.nodes[LEADER]
+        child = self.nodes[CHILD]
+        reed = self.nodes[REED]
+        router = self.nodes[ROUTER]
+
+        nodes = [leader, child, reed, router]
+
+        #-------------------------------------------------------------------
+        # Form the network.
+
+        for node in nodes:
+            node.set_key_sequence_counter(0)
+
+        leader.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual(leader.get_state(), 'leader')
+
+        child.start()
+        reed.start()
+        self.simulator.go(5)
+        self.assertEqual(child.get_state(), 'child')
+        self.assertEqual(reed.get_state(), 'child')
+
+        router.start()
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
+        self.assertEqual(router.get_state(), 'router')
+
+        #-------------------------------------------------------------------
+        # Validate the initial key seq counter on all nodes
+
+        for node in nodes:
+            self.assertEqual(node.get_key_sequence_counter(), 0)
+
+        #-------------------------------------------------------------------
+        # Manually increase the key seq on child. Then change MLE mode on
+        # child which triggers a "Child Update Request" to its parent
+        # (leader). The key jump noticed on parent side would trigger an
+        # authoritative MLE Child Update exchange (including challenge and
+        # response TLVs) and causes the parent (leader) to also adopt the
+        # larger key seq.
+
+        child.set_key_sequence_counter(5)
+        self.assertEqual(child.get_key_sequence_counter(), 5)
+
+        child.set_mode('r')
+        self.simulator.go(1)
+
+        self.assertEqual(child.get_key_sequence_counter(), 5)
+        self.assertEqual(leader.get_key_sequence_counter(), 5)
+
+        #-------------------------------------------------------------------
+        # Wait long enough for MLE Advertisement to be sent. This would
+        # trigger reed and router to also notice key seq jump and try to
+        # re-establish link again (using authoritative exchanges). Validate
+        # that all nodes are using the new key seq.
+
+        self.simulator.go(52)
+        for node in nodes:
+            self.assertEqual(node.get_key_sequence_counter(), 5)
+
+        #-------------------------------------------------------------------
+        # Manually increase the key seq on leader. Wait for max time between
+        # advertisements. This would trigger both reed and router
+        # to notice key seq jump and try to re-establish link (link
+        # request/accept exchange). Validate that they all adopt the new
+        # key seq.
+
+        leader.set_key_sequence_counter(10)
+        self.assertEqual(leader.get_key_sequence_counter(), 10)
+
+        self.simulator.go(52)
+
+        self.assertEqual(router.get_key_sequence_counter(), 10)
+        self.assertEqual(reed.get_key_sequence_counter(), 10)
+
+        #-------------------------------------------------------------------
+        # Change MLE mode on child to trigger a "Child Update Request" exchange
+        # which should then update the key seq on child as well.
+
+        child.set_mode('rn')
+        self.simulator.go(5)
+        self.assertEqual(child.get_key_sequence_counter(), 10)
+
+        #-------------------------------------------------------------------
+        # Stop all other nodes except for leader. Move the leader key seq
+        # forward and then restart all other node. Validate that router,
+        # reed and child all re-attach successfully and adopt the higher key
+        # sequence.
+
+        router.stop()
+        reed.stop()
+        child.stop()
+
+        leader.set_key_sequence_counter(15)
+        self.assertEqual(leader.get_key_sequence_counter(), 15)
+
+        child.start()
+        reed.start()
+        router.start()
+        self.simulator.go(5)
+
+        self.assertEqual(child.get_state(), 'child')
+        self.assertEqual(reed.get_state(), 'child')
+        self.assertEqual(router.get_state(), 'router')
+
+        for node in nodes:
+            self.assertEqual(node.get_key_sequence_counter(), 15)
+
+        #-------------------------------------------------------------------
+        # Stop all other nodes except for leader. Move the child key seq
+        # forward and then restart child. Ensure it re-attached successfully
+        # to leader and that leader adopts the higher key seq counter.
+
+        router.stop()
+        reed.stop()
+        child.stop()
+
+        child.set_key_sequence_counter(20)
+        self.assertEqual(child.get_key_sequence_counter(), 20)
+
+        child.start()
+        self.simulator.go(5)
+
+        self.assertEqual(child.get_state(), 'child')
+        self.assertEqual(leader.get_key_sequence_counter(), 20)
+
+        #-------------------------------------------------------------------
+        # Restart router and reed and ensure they are re-attached and get the
+        # higher key seq counter.
+
+        router.start()
+        reed.start()
+
+        self.simulator.go(5)
+        self.assertEqual(router.get_state(), 'router')
+        self.assertEqual(reed.get_state(), 'child')
+
+        self.assertEqual(router.get_key_sequence_counter(), 20)
+        self.assertEqual(reed.get_key_sequence_counter(), 20)
+
+        #-------------------------------------------------------------------
+        # Move forward the key seq counter by one on router. Wait for max
+        # time between advertisements. Validate that leader adopts the higher
+        # counter value.
+
+        router.set_key_sequence_counter(21)
+        self.assertEqual(router.get_key_sequence_counter(), 21)
+
+        self.simulator.go(52)
+        self.assertEqual(leader.get_key_sequence_counter(), 21)
+        self.assertEqual(reed.get_key_sequence_counter(), 21)
+
+        child.set_mode('r')
+        self.simulator.go(2)
+        self.assertEqual(child.get_key_sequence_counter(), 21)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/test_netdata_publisher.py b/tests/scripts/thread-cert/test_netdata_publisher.py
index df14a36..5485440 100755
--- a/tests/scripts/thread-cert/test_netdata_publisher.py
+++ b/tests/scripts/thread-cert/test_netdata_publisher.py
@@ -31,6 +31,7 @@
 import unittest
 
 import command
+import config
 import thread_cert
 
 # Test description:
@@ -56,10 +57,10 @@
 
 WAIT_TIME = 55
 
-ON_MESH_PREFIX = 'fd00:1234::/64'
+ON_MESH_PREFIX = 'fd00:1234:0:0::/64'
 ON_MESH_FLAGS = 'paso'
 
-EXTERNAL_ROUTE = 'fd00:abce::/64'
+EXTERNAL_ROUTE = 'fd00:abce:0:0::/64'
 EXTERNAL_FLAGS = 's'
 
 ANYCAST_SEQ_NUM = 4
@@ -206,12 +207,12 @@
         # Start the nodes
 
         leader.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(leader.get_state(), 'leader')
 
         for router in routers:
             router.start()
-            self.simulator.go(5)
+            self.simulator.go(config.ROUTER_STARTUP_DELAY)
             self.assertEqual(router.get_state(), 'router')
 
         for end_dev in end_devs:
@@ -443,6 +444,8 @@
         #---------------------------------------------------------------------------------
         # External route
 
+        # Publish same external route on all nodes with low preference.
+
         num = 0
         for node in nodes:
             node.netdata_publish_route(EXTERNAL_ROUTE, EXTERNAL_FLAGS, 'low')
@@ -451,12 +454,26 @@
             routes = leader.get_routes()
             self.check_num_of_routes(routes, num, 0, 0)
 
-        leader.netdata_unpublish_prefix(EXTERNAL_ROUTE)
+        # Change the preference level of the existing entry on leader to high.
+
         leader.netdata_publish_route(EXTERNAL_ROUTE, EXTERNAL_FLAGS, 'high')
         self.simulator.go(WAIT_TIME)
         routes = leader.get_routes()
         self.check_num_of_routes(routes, num - 1, 0, 1)
 
+        # Publish the same prefix on leader as an on-mesh prefix. Make
+        # sure it is removed from external routes and now seen in the
+        # prefix list.
+
+        leader.netdata_publish_prefix(EXTERNAL_ROUTE, ON_MESH_FLAGS, 'low')
+        self.simulator.go(WAIT_TIME)
+        routes = leader.get_routes()
+        self.check_num_of_routes(routes, num - 1, 0, 0)
+
+        prefixes = leader.get_prefixes()
+        print(prefixes)
+        self.assertIn(EXTERNAL_ROUTE, [prefix.split()[0] for prefix in prefixes])
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/scripts/thread-cert/test_on_mesh_prefix.py b/tests/scripts/thread-cert/test_on_mesh_prefix.py
index 16a3597..83dd732 100755
--- a/tests/scripts/thread-cert/test_on_mesh_prefix.py
+++ b/tests/scripts/thread-cert/test_on_mesh_prefix.py
@@ -65,11 +65,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(4)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[ED1].start()
diff --git a/tests/scripts/thread-cert/test_pbbr_aloc.py b/tests/scripts/thread-cert/test_pbbr_aloc.py
index 312681a..0a4ee71 100755
--- a/tests/scripts/thread-cert/test_pbbr_aloc.py
+++ b/tests/scripts/thread-cert/test_pbbr_aloc.py
@@ -29,6 +29,7 @@
 import re
 import unittest
 
+import config
 import thread_cert
 from config import MESH_LOCAL_PREFIX_REGEX_PATTERN, ROUTING_LOCATOR_REGEX_PATTERN
 from pktverify.packet_verifier import PacketVerifier
@@ -75,17 +76,17 @@
         router = self.nodes[ROUTER]
 
         leader.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', leader.get_state())
 
         pbbr.enable_backbone_router()
         pbbr.start()
-        self.simulator.go(10)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual('router', pbbr.get_state())
         self.assertTrue(pbbr.is_primary_backbone_router)
 
         router.start()
-        self.simulator.go(10)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual('router', router.get_state())
 
         for node in (leader, pbbr):
diff --git a/tests/scripts/thread-cert/test_ping.py b/tests/scripts/thread-cert/test_ping.py
index 13ee635..3494611 100755
--- a/tests/scripts/thread-cert/test_ping.py
+++ b/tests/scripts/thread-cert/test_ping.py
@@ -76,15 +76,15 @@
         router3 = self.nodes[ROUTER_3]
 
         router1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual('leader', router1.get_state())
 
         router2.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual('router', router2.get_state())
 
         router3.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual('router', router3.get_state())
 
         # 1. ROUTER_1 pings ROUTER_2.
diff --git a/tests/scripts/thread-cert/test_ping_lla_src.py b/tests/scripts/thread-cert/test_ping_lla_src.py
new file mode 100644
index 0000000..e6f9b26
--- /dev/null
+++ b/tests/scripts/thread-cert/test_ping_lla_src.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2021, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+import logging
+import unittest
+
+import pktverify
+from pktverify import packet_verifier
+import config
+import thread_cert
+
+# Test description:
+# The purpose of this test is to verify the Router's routing behavior using LLA as source address.
+#
+# Topology:
+#
+#
+#  ROUTER_2 ----- ROUTER_1 ---- ROUTER_3
+#
+#
+
+ROUTER_1 = 1
+ROUTER_2 = 2
+ROUTER_3 = 3
+
+
+class TestPing(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+    SUPPORT_NCP = False
+
+    TOPOLOGY = {
+        ROUTER_1: {
+            'name': 'Router_1',
+            'allowlist': [ROUTER_2, ROUTER_3],
+        },
+        ROUTER_2: {
+            'name': 'Router_2',
+            'allowlist': [ROUTER_1],
+        },
+        ROUTER_3: {
+            'name': 'Router_3',
+            'allowlist': [ROUTER_1],
+        },
+    }
+
+    def test(self):
+        router1 = self.nodes[ROUTER_1]
+        router2 = self.nodes[ROUTER_2]
+        router3 = self.nodes[ROUTER_3]
+
+        router1.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual('leader', router1.get_state())
+
+        router2.start()
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
+        self.assertEqual('router', router2.get_state())
+
+        router3.start()
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
+        self.assertEqual('router', router3.get_state())
+
+        self.simulator.go(10)
+
+        left, center, right = router2, router1, router3
+
+        left_lla = left.get_ip6_address(config.ADDRESS_TYPE.LINK_LOCAL)
+
+        # Ping a neighbor with LLA src should succeed.
+        self.assertTrue(left.ping(center.get_mleid(), interface=left_lla))
+        self.simulator.go(3)
+
+        # Ping a non-neighbor with LLA src should fail.
+        self.assertFalse(left.ping(right.get_mleid(), interface=left_lla))
+        self.simulator.go(3)
+
+        center.add_route('2001::/64', stable=True)
+        center.register_netdata()
+
+        self.simulator.go(3)
+
+        # Make sure external routes are not used for LLA src.
+        self.assertFalse(left.ping("2001::1", interface=left_lla))
+        self.simulator.go(3)
+
+    def verify(self, pv: pktverify.packet_verifier.PacketVerifier):
+        pkts = pv.pkts
+        # Make sure the Ping Request to 2001::1 was not sent
+        pkts.filter_ipv6_dst('2001::1').filter_ping_request().must_not_next()
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/test_radio_filter.py b/tests/scripts/thread-cert/test_radio_filter.py
new file mode 100755
index 0000000..7ce082b
--- /dev/null
+++ b/tests/scripts/thread-cert/test_radio_filter.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2021, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+import ipaddress
+import unittest
+
+import config
+import command
+import thread_cert
+
+# Test description:
+#
+# This test verifies the radio filter mechanism.
+#
+# Topology:
+#
+#   Leader -- Router
+#     |
+#     |
+#   Child
+#
+#
+
+LEADER = 1
+ROUTER = 2
+SED = 3
+
+WAIT_TIME = 5
+
+
+class RadioFilter(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+    SUPPORT_NCP = False
+
+    TOPOLOGY = {
+        LEADER: {
+            'mode': 'rdn',
+            'allowlist': [ROUTER, SED]
+        },
+        ROUTER: {
+            'mode': 'rdn',
+            'allowlist': [LEADER]
+        },
+        SED: {
+            'is_mtd': True,
+            'mode': '-',
+            'timeout': config.DEFAULT_CHILD_TIMEOUT,
+            'allowlist': [LEADER]
+        },
+    }
+
+    def test(self):
+        leader = self.nodes[LEADER]
+        router = self.nodes[ROUTER]
+        sed = self.nodes[SED]
+
+        nodes = [leader, router, sed]
+
+        leader.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual(leader.get_state(), 'leader')
+
+        router.start()
+        self.simulator.go(WAIT_TIME)
+        self.assertEqual(router.get_state(), 'router')
+
+        sed.start()
+        sed.set_pollperiod(40)
+        self.simulator.go(WAIT_TIME)
+        self.assertEqual(sed.get_state(), 'child')
+
+        # Validate initial state of `radiofilter` upon start
+        for node in nodes:
+            self.assertFalse(node.radiofilter_is_enabled())
+
+        leader_mleid = leader.get_mleid()
+        router_mleid = router.get_mleid()
+        sed_mleid = sed.get_mleid()
+
+        # Validate connections by pinging from leader, SED, and router
+        self.assertTrue(leader.ping(router_mleid))
+        self.assertTrue(sed.ping(leader_mleid))
+        self.assertTrue(router.ping(leader_mleid))
+
+        # Validate behavior when `radiofilter` is enabled on router
+        router.radiofilter_enable()
+        self.assertTrue(router.radiofilter_is_enabled())
+        self.assertFalse(leader.ping(router_mleid))
+        self.assertFalse(router.ping(leader_mleid))
+
+        # Validate behavior when `radiofilter` is disabled on router
+        router.radiofilter_disable()
+        self.assertFalse(router.radiofilter_is_enabled())
+        self.assertTrue(leader.ping(router_mleid))
+        self.assertTrue(router.ping(leader_mleid))
+
+        # Validate `radiofilter` behavior on sed.
+        self.assertTrue(sed.ping(leader_mleid))
+
+        sed.radiofilter_enable()
+        self.assertTrue(sed.radiofilter_is_enabled())
+        self.assertFalse(sed.ping(leader_mleid))
+
+        self.assertTrue(sed.radiofilter_is_enabled())
+        self.assertEqual(sed.get_state(), 'detached')
+
+        sed.radiofilter_disable()
+        self.assertFalse(sed.radiofilter_is_enabled())
+
+        self.simulator.go(WAIT_TIME)
+        self.assertEqual(sed.get_state(), 'child')
+        self.assertTrue(leader.ping(sed_mleid))
+        self.assertTrue(sed.ping(leader_mleid))
+
+        # Validate energy scan when `radiofilter` is enabled
+        scan_result = leader.scan_energy()
+        self.assertTrue(len(scan_result) > 0)
+        leader.radiofilter_enable()
+        self.assertTrue(leader.radiofilter_is_enabled())
+        scan_result = leader.scan_energy()
+        self.assertTrue(len(scan_result) == 0)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/test_reed_address_solicit_rejected.py b/tests/scripts/thread-cert/test_reed_address_solicit_rejected.py
index e1f36b3..508d0c9 100755
--- a/tests/scripts/thread-cert/test_reed_address_solicit_rejected.py
+++ b/tests/scripts/thread-cert/test_reed_address_solicit_rejected.py
@@ -61,7 +61,7 @@
     def testAddressSolicitRejectedBeforeSvrData(self):
         self.nodes[LEADER].start()
         self.nodes[LEADER].set_router_upgrade_threshold(1)
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[REED].start()
@@ -77,7 +77,7 @@
     def testAddressSolicitRejectedAfterSvrData(self):
         self.nodes[LEADER].start()
         self.nodes[LEADER].set_router_upgrade_threshold(1)
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[REED].set_router_selection_jitter(120)
diff --git a/tests/scripts/thread-cert/test_reset.py b/tests/scripts/thread-cert/test_reset.py
index 7c6305f..b23e58d 100755
--- a/tests/scripts/thread-cert/test_reset.py
+++ b/tests/scripts/thread-cert/test_reset.py
@@ -56,11 +56,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(7)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[ED].start()
@@ -73,12 +73,12 @@
 
         self.nodes[LEADER].reset()
         self.nodes[LEADER].start()
-        self.simulator.go(7)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].reset()
         self.nodes[ROUTER].start()
-        self.simulator.go(7)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[ED].reset()
diff --git a/tests/scripts/thread-cert/test_route_table.py b/tests/scripts/thread-cert/test_route_table.py
index 7333559..f213aaa 100755
--- a/tests/scripts/thread-cert/test_route_table.py
+++ b/tests/scripts/thread-cert/test_route_table.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 
 LEADER = 1
@@ -60,15 +61,15 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
 
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
         self.simulator.go(100)
diff --git a/tests/scripts/thread-cert/test_router_multicast_link_request.py b/tests/scripts/thread-cert/test_router_multicast_link_request.py
new file mode 100755
index 0000000..38e7681
--- /dev/null
+++ b/tests/scripts/thread-cert/test_router_multicast_link_request.py
@@ -0,0 +1,140 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+import logging
+import unittest
+
+import config
+import thread_cert
+from pktverify.consts import MLE_LINK_REQUEST, MLE_LINK_ACCEPT
+from pktverify.packet_verifier import PacketVerifier
+
+LEADER = 1
+REED = 2
+ROUTER1, ROUTER2, ROUTER3 = 3, 4, 5
+
+# Test Purpose and Description:
+# -----------------------------
+# This test verifies if a device can quickly and efficiently establish links with
+# neighboring routers by sending a multicast Link Request message after becoming
+# a router
+#
+# Test Topology:
+# -------------
+#     Leader------+
+#    |     \       \
+# Router1 Router2 Router3
+#    \     |        |
+#     +---REED-----+
+#
+
+# REED should establish links to the three Routers within the delay threshold.
+# The max delay consists:
+#   Leader may delay 1 second for MLE Advertisement
+#   Router may delay 1 second for MLE Advertisement
+#   Router may delay 1 second for MLE Link Accept after receiving MLE Link Request (multicast)
+LINK_ESTABLISH_DELAY_THRESHOLD = 3
+
+
+class TestRouterMulticastLinkRequest(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+
+    TOPOLOGY = {
+        LEADER: {
+            'name': 'LEADER',
+            'mode': 'rdn',
+            'allowlist': [ROUTER1, ROUTER2, ROUTER3]
+        },
+        ROUTER1: {
+            'name': 'ROUTER1',
+            'mode': 'rdn',
+            'allowlist': [LEADER, REED]
+        },
+        ROUTER2: {
+            'name': 'ROUTER2',
+            'mode': 'rdn',
+            'allowlist': [LEADER, REED]
+        },
+        ROUTER3: {
+            'name': 'ROUTER3',
+            'mode': 'rdn',
+            'allowlist': [LEADER, REED]
+        },
+        REED: {
+            'name': 'REED',
+            'mode': 'rdn',
+            'allowlist': [ROUTER1, ROUTER2, ROUTER3]
+        },
+    }
+
+    def test(self):
+        self.nodes[LEADER].start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
+
+        for routerid in (ROUTER1, ROUTER2, ROUTER3):
+            self.nodes[routerid].start()
+            self.simulator.go(config.ROUTER_STARTUP_DELAY)
+            self.assertEqual(self.nodes[routerid].get_state(), 'router')
+
+        # Wait for the network to stabilize
+        self.simulator.go(60)
+
+        self.nodes[REED].start()
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
+        self.assertEqual(self.nodes[REED].get_state(), 'router')
+        self.simulator.go(LINK_ESTABLISH_DELAY_THRESHOLD + 3)
+
+    def verify(self, pv: PacketVerifier):
+        pkts = pv.pkts
+        print(pv.vars)
+        pv.summary.show()
+
+        REED = pv.vars['REED']
+        as_pkt = pkts.filter_wpan_src64(REED).filter_coap_request('/a/as', confirmable=True).must_next()
+        parent_rloc16 = as_pkt.wpan.dst16
+        as_ack_pkt = pkts.filter_wpan_src16(parent_rloc16).filter_coap_ack('/a/as').must_next()
+        become_router_timestamp = as_ack_pkt.sniff_timestamp
+
+        # REED has just received `/a/as` and become a Router
+        # REED should send Multicast Link Request after becoming Router
+        link_request_pkt = pkts.filter_wpan_src64(REED).filter_mle_cmd(MLE_LINK_REQUEST).must_next()
+        link_request_pkt.must_verify('ipv6.dst == "ff02::2"')
+
+        # REED should send Link Accept to the three Routers
+        for router in ('ROUTER1', 'ROUTER2', 'ROUTER3'):
+            with pkts.save_index():
+                pkt = pkts.filter_wpan_src64(REED).filter_wpan_dst64(
+                    pv.vars[router]).filter_mle_cmd(MLE_LINK_ACCEPT).must_next()
+                link_establish_delay = pkt.sniff_timestamp - become_router_timestamp
+                logging.info("Link to %s established in %.3f seconds", router, link_establish_delay)
+                self.assertLess(link_establish_delay, LINK_ESTABLISH_DELAY_THRESHOLD)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/test_router_reattach.py b/tests/scripts/thread-cert/test_router_reattach.py
index 154a710..2cb4b5b 100755
--- a/tests/scripts/thread-cert/test_router_reattach.py
+++ b/tests/scripts/thread-cert/test_router_reattach.py
@@ -199,12 +199,12 @@
 
     def test(self):
         self.nodes[1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[1].get_state(), 'leader')
 
         for i in range(2, 33):
             self.nodes[i].start()
-            self.simulator.go(5)
+            self.simulator.go(config.ROUTER_STARTUP_DELAY)
             self.assertEqual(self.nodes[i].get_state(), 'router')
 
         self.nodes[2].reset()
diff --git a/tests/scripts/thread-cert/Test_MacScan.py b/tests/scripts/thread-cert/test_router_upgrade.py
similarity index 60%
copy from tests/scripts/thread-cert/Test_MacScan.py
copy to tests/scripts/thread-cert/test_router_upgrade.py
index bdc6228..a9c1e1a 100755
--- a/tests/scripts/thread-cert/Test_MacScan.py
+++ b/tests/scripts/thread-cert/test_router_upgrade.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-#  Copyright (c) 2016, The OpenThread Authors.
+#  Copyright (c) 2022, The OpenThread Authors.
 #  All rights reserved.
 #
 #  Redistribution and use in source and binary forms, with or without
@@ -27,42 +27,72 @@
 #  POSSIBILITY OF SUCH DAMAGE.
 #
 
-import time
 import unittest
 
+import config
+import mle
+import network_layer
 import thread_cert
 
 LEADER = 1
-ROUTER = 2
+REED = 2
+
+RSSI_LOW = -95
+RSSI_HIGH = -45
+
+ROUTER_UPGRADE_DELAY = 150
+
+# Test Purpose and Description:
+# -----------------------------
+# The purpose of this test case is to show that a REED does not
+# upgrade to router if it does not have a neighbor with link margin
+# above threshold.
+#
+# Test Topology:
+# -------------
+# Leader
+#    |
+# REED
+#
+# DUT Types:
+# ----------
+#  Leader
+#  REED
 
 
-class Test_MacScan(thread_cert.TestCase):
+class TestRouterUpgrade(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+
     TOPOLOGY = {
         LEADER: {
-            'channel': 12,
+            'name': 'LEADER',
             'mode': 'rdn',
-            'network_name': 'OpenThread',
-            'allowlist': [ROUTER]
+            'allowlist': [REED]
         },
-        ROUTER: {
-            'channel': 12,
+        REED: {
+            'name': 'REED',
             'mode': 'rdn',
-            'network_name': 'OpenThread',
             'allowlist': [LEADER]
         },
     }
 
     def test(self):
         self.nodes[LEADER].start()
-        self.nodes[LEADER].set_state('leader')
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
-        self.nodes[ROUTER].start()
-        time.sleep(5)
-        self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
+        self.nodes[REED].add_allowlist(self.nodes[LEADER].get_addr64(), rssi=RSSI_LOW)
+        self.nodes[REED].enable_allowlist()
 
-        results = self.nodes[LEADER].scan()
-        self.assertEqual(len(results), 16)
+        self.nodes[REED].start()
+        self.simulator.go(ROUTER_UPGRADE_DELAY)
+        self.assertEqual(self.nodes[REED].get_state(), 'child')
+
+        self.nodes[REED].add_allowlist(self.nodes[LEADER].get_addr64(), rssi=RSSI_HIGH)
+        self.nodes[REED].enable_allowlist()
+
+        self.simulator.go(ROUTER_UPGRADE_DELAY)
+        self.assertEqual(self.nodes[REED].get_state(), 'router')
 
 
 if __name__ == '__main__':
diff --git a/tests/scripts/thread-cert/test_service.py b/tests/scripts/thread-cert/test_service.py
index 4be617e..6032f6c 100755
--- a/tests/scripts/thread-cert/test_service.py
+++ b/tests/scripts/thread-cert/test_service.py
@@ -91,12 +91,12 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER1].start()
         self.nodes[ROUTER2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
         self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
 
diff --git a/tests/scripts/thread-cert/test_set_mliid.py b/tests/scripts/thread-cert/test_set_mliid.py
index e36b7f5..760f0da 100755
--- a/tests/scripts/thread-cert/test_set_mliid.py
+++ b/tests/scripts/thread-cert/test_set_mliid.py
@@ -50,7 +50,7 @@
         self.nodes[LEADER].set_mliid('1122334455667788')
 
         self.nodes[LEADER].start()
-        self.simulator.go(10)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         # Ensure set ML-IID was effective.
@@ -63,7 +63,7 @@
         self.nodes[LEADER].reset()
 
         self.nodes[LEADER].start()
-        self.simulator.go(10)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         # Ensure ML-IID is persistent after reset.
diff --git a/tests/scripts/thread-cert/test_srp_auto_host_address.py b/tests/scripts/thread-cert/test_srp_auto_host_address.py
new file mode 100755
index 0000000..bb9ac6e
--- /dev/null
+++ b/tests/scripts/thread-cert/test_srp_auto_host_address.py
@@ -0,0 +1,258 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+import ipaddress
+import unittest
+
+import command
+import config
+import thread_cert
+
+# Test description:
+#   This test verifies SRP client auto host address mode.
+#
+# Topology:
+#     SRP client (leader)
+#       |
+#       |
+#     SRP server (router)
+#
+
+CLIENT = 1
+SERVER = 2
+
+
+class SrpAutoHostAddress(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+    SUPPORT_NCP = False
+
+    TOPOLOGY = {
+        CLIENT: {
+            'name': 'SRP_CLIENT',
+            'mode': 'rdn',
+        },
+        SERVER: {
+            'name': 'SRP_SERVER',
+            'mode': 'rdn',
+        },
+    }
+
+    def test(self):
+        client = self.nodes[CLIENT]
+        server = self.nodes[SERVER]
+
+        #-------------------------------------------------------------------
+        # Form the network.
+
+        client.srp_server_set_enabled(False)
+        client.start()
+        self.simulator.go(15)
+        self.assertEqual(client.get_state(), 'leader')
+
+        server.start()
+        self.simulator.go(5)
+        self.assertEqual(server.get_state(), 'router')
+
+        #-------------------------------------------------------------------
+        # Enable SRP server
+
+        server.srp_server_set_enabled(True)
+        self.simulator.go(5)
+
+        #-------------------------------------------------------------------
+        # Enable auto start mode on SRP client
+
+        self.assertEqual(client.srp_client_get_state(), 'Disabled')
+        client.srp_client_enable_auto_start_mode()
+        self.assertEqual(client.srp_client_get_auto_start_mode(), 'Enabled')
+        self.simulator.go(2)
+
+        self.assertEqual(client.srp_client_get_state(), 'Enabled')
+
+        #-------------------------------------------------------------------
+        # Set host name and enable auto host address on client
+
+        client.srp_client_set_host_name('host')
+        client.srp_client_enable_auto_host_address()
+
+        #-------------------------------------------------------------------
+        # Register a service on client
+
+        client.srp_client_add_service('test_srv', '_test._udo', 12345, 0, 0)
+        self.simulator.go(2)
+        self.check_registered_addresses(client, server)
+
+        #-------------------------------------------------------------------
+        # Add an address and check the SRP client re-registered and updated
+        # server with new address.
+
+        client.add_ipaddr('fd00:1:2:3:4:5:6:7')
+
+        self.simulator.go(5)
+        client_addresses = [addr.strip() for addr in client.get_addrs()]
+        self.assertIn('fd00:1:2:3:4:5:6:7', client_addresses)
+        self.check_registered_addresses(client, server)
+
+        #-------------------------------------------------------------------
+        # Remove the address and check the SRP client re-registered and updated
+        # server.
+
+        client.del_ipaddr('fd00:1:2:3:4:5:6:7')
+
+        self.simulator.go(5)
+        client_addresses = [addr.strip() for addr in client.get_addrs()]
+        self.assertNotIn('fd00:1:2:3:4:5:6:7', client_addresses)
+        self.check_registered_addresses(client, server)
+
+        #-------------------------------------------------------------------
+        # Add an SLAAC on-mesh prefix (which will trigger an address to be
+        # added) and check that the SRP client re-registered and updated
+        # server with the new address.
+
+        client.add_prefix('fd00:abba:cafe:bee::/64', 'paos')
+        client.register_netdata()
+        self.simulator.go(5)
+
+        slaac_addr = [addr.strip() for addr in client.get_addrs() if addr.strip().startswith('fd00:abba:cafe:bee:')]
+        self.assertEqual(len(slaac_addr), 1)
+        self.check_registered_addresses(client, server)
+
+        #-------------------------------------------------------------------
+        # Add another SLAAC on-mesh prefix and check that the SRP client
+        # re-registered and updated server with all address.
+
+        client.add_prefix('fd00:9:8:7::/64', 'paos')
+        client.register_netdata()
+        self.simulator.go(5)
+
+        slaac_addr = [addr.strip() for addr in client.get_addrs() if addr.strip().startswith('fd00:9:8:7:')]
+        self.assertEqual(len(slaac_addr), 1)
+        self.check_registered_addresses(client, server)
+
+        #-------------------------------------------------------------------
+        # Remove the on-mesh prefix (which will trigger an address to be
+        # removed) and check that the SRP client re-registered and updated
+        # server with the remaining address.
+
+        client.remove_prefix('fd00:abba:cafe:bee::/64')
+        client.register_netdata()
+        self.simulator.go(5)
+
+        slaac_addr = [addr.strip() for addr in client.get_addrs() if addr.strip().startswith('fd00:abba:cafe:bee:')]
+        self.assertEqual(len(slaac_addr), 0)
+        self.check_registered_addresses(client, server)
+
+        #-------------------------------------------------------------------
+        # Remove the next on-mesh prefix. Check that SRP client re-registered
+        # now with only ML-EID.
+
+        client.remove_prefix('fd00:9:8:7::/64')
+        client.register_netdata()
+        self.simulator.go(5)
+
+        slaac_addr = [addr.strip() for addr in client.get_addrs() if addr.strip().startswith('fd00:9:8:7:')]
+        self.assertEqual(len(slaac_addr), 0)
+        self.check_registered_addresses(client, server)
+
+        #-------------------------------------------------------------------
+        # Explicitly set the host addresses (which disables the auto host
+        # address mode) and check that only the new addresses are registered.
+
+        client.srp_client_set_host_address('fd00:f:e:d:c:b:a:9')
+        self.simulator.go(5)
+
+        self.assertEqual(client.srp_client_get_host_state(), 'Registered')
+        server_hosts = server.srp_server_get_hosts()
+        self.assertEqual(len(server_hosts), 1)
+        server_host = server_hosts[0]
+        self.assertEqual(server_host['deleted'], 'false')
+        self.assertEqual(server_host['fullname'], 'host.default.service.arpa.')
+        host_addresses = [addr.strip() for addr in server_host['addresses']]
+        self.assertEqual(len(host_addresses), 1)
+        self.assertEqual(host_addresses[0], 'fd00:f:e:d:c:b:a:9')
+
+        #-------------------------------------------------------------------
+        # Re-enable auto host address mode and check that addresses are
+        # updated and registered properly.
+
+        client.srp_client_enable_auto_host_address()
+        self.simulator.go(5)
+        self.check_registered_addresses(client, server)
+
+    def check_registered_addresses(self, client, server):
+        # Ensure client has registered successfully.
+        self.assertEqual(client.srp_client_get_host_state(), 'Registered')
+
+        # Check the host info on server.
+        server_hosts = server.srp_server_get_hosts()
+        self.assertEqual(len(server_hosts), 1)
+        server_host = server_hosts[0]
+        self.assertEqual(server_host['deleted'], 'false')
+        self.assertEqual(server_host['fullname'], 'host.default.service.arpa.')
+
+        # Check the host addresses on server to match client.
+
+        host_addresses = [addr.strip() for addr in server_host['addresses']]
+        client_addresses = [addr.strip() for addr in client.get_addrs()]
+
+        # All registered addresses must be in client list of addresses.
+
+        for addr in host_addresses:
+            self.assertIn(addr, client_addresses)
+
+        # All addresses on client excluding link-local and mesh-local
+        # addresses must be seen on server side. But if there was
+        # no address, then mesh-local address should be the only
+        # one registered.
+
+        client_mleid = client.get_mleid()
+        checked_address = False
+
+        for addr in client_addresses:
+            if not self.is_address_link_local(addr) and not self.is_address_locator(addr) and addr != client_mleid:
+                self.assertIn(addr, host_addresses)
+                checked_address = True
+
+        if not checked_address:
+            self.assertEqual(len(host_addresses), 1)
+            self.assertIn(client_mleid, host_addresses)
+
+    def is_address_locator(self, addr):
+        # Checks if an IPv6 address is a locator (IID should match `0:ff:fe00:xxxx`)
+        u32s = addr.split(':')
+        self.assertEqual(len(u32s), 8)
+        return ':'.join(u32s[4:]).startswith('0:ff:fe00:')
+
+    def is_address_link_local(self, addr):
+        # Checks if an IPv6 address is link-local
+        return addr.startswith('fe80:')
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/test_srp_auto_start_mode.py b/tests/scripts/thread-cert/test_srp_auto_start_mode.py
index 2b18264..8fbcdda 100755
--- a/tests/scripts/thread-cert/test_srp_auto_start_mode.py
+++ b/tests/scripts/thread-cert/test_srp_auto_start_mode.py
@@ -31,23 +31,22 @@
 import unittest
 
 import command
+import config
 import thread_cert
 
 # Test description:
 #   This test verifies SRP client auto-start functionality that SRP client can
-#   correctly discover and connect to SRP server.
+#   correctly discovers and connects to SRP server.
 #
 # Topology:
 #
-#   CLIENT (leader) -- SERVER1 (router)
-#      |
-#      |
-#   SERVER2 (router)
+#   Four routers, one acting as SRP client, others as SRP server.
 #
 
 CLIENT = 1
 SERVER1 = 2
 SERVER2 = 3
+SERVER3 = 4
 
 
 class SrpAutoStartMode(thread_cert.TestCase):
@@ -57,17 +56,18 @@
     TOPOLOGY = {
         CLIENT: {
             'name': 'SRP_CLIENT',
-            'networkkey': '00112233445566778899aabbccddeeff',
             'mode': 'rdn',
         },
         SERVER1: {
             'name': 'SRP_SERVER1',
-            'networkkey': '00112233445566778899aabbccddeeff',
             'mode': 'rdn',
         },
         SERVER2: {
             'name': 'SRP_SERVER2',
-            'networkkey': '00112233445566778899aabbccddeeff',
+            'mode': 'rdn',
+        },
+        SERVER3: {
+            'name': 'SRP_SERVER3',
             'mode': 'rdn',
         },
     }
@@ -76,27 +76,38 @@
         client = self.nodes[CLIENT]
         server1 = self.nodes[SERVER1]
         server2 = self.nodes[SERVER2]
+        server3 = self.nodes[SERVER3]
 
-        #
-        # 0. Start the server & client devices.
-        #
+        #-------------------------------------------------------------------
+        # Form the network.
 
         client.srp_server_set_enabled(False)
         client.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(client.get_state(), 'leader')
 
-        server1.srp_server_set_enabled(True)
-        server2.srp_server_set_enabled(False)
         server1.start()
         server2.start()
-        self.simulator.go(5)
+        server3.start()
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(server1.get_state(), 'router')
         self.assertEqual(server2.get_state(), 'router')
+        self.assertEqual(server3.get_state(), 'router')
 
-        #
-        # 1. Enable auto start mode on client and check that server1 is used.
-        #
+        server1_mleid = server1.get_mleid()
+        server2_mleid = server2.get_mleid()
+        server3_mleid = server3.get_mleid()
+        anycast_port = 53
+
+        #-------------------------------------------------------------------
+        # Enable server1 with unicast address mode
+
+        server1.srp_server_set_addr_mode('unicast')
+        server1.srp_server_set_enabled(True)
+        self.simulator.go(5)
+
+        #-------------------------------------------------------------------
+        # Enable auto start mode on client and check that server1 is selected
 
         self.assertEqual(client.srp_client_get_state(), 'Disabled')
         client.srp_client_enable_auto_start_mode()
@@ -104,42 +115,174 @@
         self.simulator.go(2)
 
         self.assertEqual(client.srp_client_get_state(), 'Enabled')
-        self.assertTrue(server1.has_ipaddr(client.srp_client_get_server_address()))
+        self.assertEqual(client.srp_client_get_server_address(), server1_mleid)
 
-        #
-        # 2. Disable server1 and check client is stopped/disabled.
-        #
+        #-------------------------------------------------------------------
+        # Disable server1 and check client is stopped/disabled.
 
         server1.srp_server_set_enabled(False)
         self.simulator.go(5)
         self.assertEqual(client.srp_client_get_state(), 'Disabled')
 
-        #
-        # 3. Enable server2 and check client starts again.
-        #
+        #-------------------------------------------------------------------
+        # Enable server2 with unicast address mode and check client starts
+        # again.
 
+        server1.srp_server_set_addr_mode('unicast')
         server2.srp_server_set_enabled(True)
         self.simulator.go(5)
         self.assertEqual(client.srp_client_get_state(), 'Enabled')
-        server2_address = client.srp_client_get_server_address()
+        self.assertEqual(client.srp_client_get_server_address(), server2_mleid)
 
-        #
-        # 4. Enable both servers and check client stays with server2.
-        #
+        #-------------------------------------------------------------------
+        # Enable server1 and check that client stays with server2
 
         server1.srp_server_set_enabled(True)
         self.simulator.go(5)
         self.assertEqual(client.srp_client_get_state(), 'Enabled')
-        self.assertEqual(client.srp_client_get_server_address(), server2_address)
+        self.assertEqual(client.srp_client_get_server_address(), server2_mleid)
 
-        #
-        # 5. Disable server2 and check client switches to server1.
-        #
+        #-------------------------------------------------------------------
+        # Disable server2 and check client switches to server1.
 
         server2.srp_server_set_enabled(False)
         self.simulator.go(5)
         self.assertEqual(client.srp_client_get_state(), 'Enabled')
-        self.assertNotEqual(client.srp_client_get_server_address(), server2_address)
+        self.assertEqual(client.srp_client_get_server_address(), server1_mleid)
+
+        #-------------------------------------------------------------------
+        # Enable server2 with anycast mode seq-num 1, and check that client
+        # switched to it.
+
+        server2.srp_server_set_addr_mode('anycast')
+        server2.srp_server_set_anycast_seq_num(1)
+        server2.srp_server_set_enabled(True)
+        self.simulator.go(5)
+        server2_alocs = server2.get_ip6_address(config.ADDRESS_TYPE.ALOC)
+        self.assertEqual(server2.srp_server_get_anycast_seq_num(), 1)
+        self.assertEqual(client.srp_client_get_state(), 'Enabled')
+        self.assertIn(client.srp_client_get_server_address(), server2_alocs)
+        self.assertEqual(client.srp_client_get_server_port(), anycast_port)
+
+        #-------------------------------------------------------------------
+        # Enable server3 with anycast mode seq-num 2, and check that client
+        # switched to it since seq number is higher.
+
+        server3.srp_server_set_addr_mode('anycast')
+        server3.srp_server_set_anycast_seq_num(2)
+        server3.srp_server_set_enabled(True)
+        self.simulator.go(5)
+        server3_alocs = server3.get_ip6_address(config.ADDRESS_TYPE.ALOC)
+        self.assertEqual(server3.srp_server_get_anycast_seq_num(), 2)
+        self.assertEqual(client.srp_client_get_state(), 'Enabled')
+        self.assertIn(client.srp_client_get_server_address(), server3_alocs)
+        self.assertEqual(client.srp_client_get_server_port(), anycast_port)
+
+        #-------------------------------------------------------------------
+        # Disable server3 and check that client goes back to server2.
+
+        server3.srp_server_set_enabled(False)
+        self.simulator.go(5)
+        self.assertEqual(client.srp_client_get_state(), 'Enabled')
+        self.assertIn(client.srp_client_get_server_address(), server2_alocs)
+        self.assertEqual(client.srp_client_get_server_port(), anycast_port)
+
+        #-------------------------------------------------------------------
+        # Enable server3 with anycast mode seq-num 0 (which is smaller than
+        # server2 seq-num 1) and check that client stays with server2.
+
+        server3.srp_server_set_anycast_seq_num(0)
+        server3.srp_server_set_enabled(True)
+        self.simulator.go(5)
+        self.assertEqual(server3.srp_server_get_anycast_seq_num(), 0)
+        self.assertEqual(client.srp_client_get_state(), 'Enabled')
+        self.assertIn(client.srp_client_get_server_address(), server2_alocs)
+        self.assertEqual(client.srp_client_get_server_port(), anycast_port)
+
+        #-------------------------------------------------------------------
+        # Disable server2 and check that client goes back to server3.
+
+        server2.srp_server_set_enabled(False)
+        self.simulator.go(5)
+        self.assertEqual(client.srp_client_get_state(), 'Enabled')
+        server3_alocs = server3.get_ip6_address(config.ADDRESS_TYPE.ALOC)
+        self.assertIn(client.srp_client_get_server_address(), server3_alocs)
+        self.assertEqual(client.srp_client_get_server_port(), anycast_port)
+
+        #-------------------------------------------------------------------
+        # Disable server3 and check that client goes back to server1 with
+        # unicast address.
+
+        server3.srp_server_set_enabled(False)
+        self.simulator.go(5)
+        self.assertEqual(client.srp_client_get_state(), 'Enabled')
+        self.assertEqual(client.srp_client_get_server_address(), server1_mleid)
+
+        #-------------------------------------------------------------------
+        # Enable server2 with anycast mode seq-num 5, and check that client
+        # switched to it.
+
+        server2.srp_server_set_addr_mode('anycast')
+        server2.srp_server_set_anycast_seq_num(5)
+        server2.srp_server_set_enabled(True)
+        self.simulator.go(5)
+        server2_alocs = server2.get_ip6_address(config.ADDRESS_TYPE.ALOC)
+        self.assertEqual(server2.srp_server_get_anycast_seq_num(), 5)
+        self.assertEqual(client.srp_client_get_state(), 'Enabled')
+        self.assertIn(client.srp_client_get_server_address(), server2_alocs)
+        self.assertEqual(client.srp_client_get_server_port(), anycast_port)
+
+        #-------------------------------------------------------------------
+        # Publish an entry on server3 with specific unicast address
+        # This entry should be now preferred over anycast of server2.
+
+        unicast_addr3 = 'fd00:0:0:0:0:3333:beef:cafe'
+        unicast_port3 = 1234
+        server3.netdata_publish_dnssrp_unicast(unicast_addr3, unicast_port3)
+        self.simulator.go(65)
+        self.assertEqual(client.srp_client_get_state(), 'Enabled')
+        self.assertEqual(client.srp_client_get_server_address(), unicast_addr3)
+        self.assertEqual(client.srp_client_get_server_port(), unicast_port3)
+
+        #-------------------------------------------------------------------
+        # Publish an entry on server1 with specific unicast address
+        # Client should still stay with server3 which it originally selected.
+
+        unicast_addr1 = 'fd00:0:0:0:0:2222:beef:cafe'
+        unicast_port1 = 10203
+        server1.srp_server_set_enabled(False)
+        server1.netdata_publish_dnssrp_unicast(unicast_addr1, unicast_port1)
+        self.simulator.go(65)
+        self.assertEqual(client.srp_client_get_state(), 'Enabled')
+        self.assertEqual(client.srp_client_get_server_address(), unicast_addr3)
+        self.assertEqual(client.srp_client_get_server_port(), unicast_port3)
+
+        #-------------------------------------------------------------------
+        # Unpublish the entry on server3. Now client should switch to entry
+        # from server1.
+
+        server3.netdata_unpublish_dnssrp()
+        self.simulator.go(65)
+        self.assertEqual(client.srp_client_get_state(), 'Enabled')
+        self.assertEqual(client.srp_client_get_server_address(), unicast_addr1)
+        self.assertEqual(client.srp_client_get_server_port(), unicast_port1)
+
+        #-------------------------------------------------------------------
+        # Unpublish the entry on server1 and check client goes back to anycast
+        # entry from server2.
+
+        server1.netdata_unpublish_dnssrp()
+        self.simulator.go(65)
+        self.assertEqual(client.srp_client_get_state(), 'Enabled')
+        self.assertIn(client.srp_client_get_server_address(), server2_alocs)
+        self.assertEqual(client.srp_client_get_server_port(), anycast_port)
+
+        #-------------------------------------------------------------------
+        # Finally disable server2, and check that client is disabled.
+
+        server2.srp_server_set_enabled(False)
+        self.simulator.go(5)
+        self.assertEqual(client.srp_client_get_state(), 'Disabled')
 
 
 if __name__ == '__main__':
diff --git a/tests/scripts/thread-cert/test_srp_client_change_lease.py b/tests/scripts/thread-cert/test_srp_client_change_lease.py
new file mode 100755
index 0000000..37b03d3
--- /dev/null
+++ b/tests/scripts/thread-cert/test_srp_client_change_lease.py
@@ -0,0 +1,161 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2021, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+import unittest
+
+import config
+import thread_cert
+
+# Test description:
+#   This test verifies the SRP client lease changing works as expected.
+#
+# Topology:
+#     LEADER (SRP server)
+#       |
+#       |
+#     ROUTER (SRP client)
+#
+from pktverify.packet_filter import PacketFilter
+
+SERVER = 1
+CLIENT = 2
+
+DEFAULT_LEASE_TIME = 7200
+LEASE_TIME = 60
+NEW_LEASE_TIME = 120
+KEY_LEASE_TIME = 240
+NEW_TTL = 10
+
+assert LEASE_TIME < KEY_LEASE_TIME
+assert NEW_LEASE_TIME < KEY_LEASE_TIME
+assert NEW_TTL < NEW_LEASE_TIME
+
+
+class SrpClientChangeLeaseTime(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+    SUPPORT_NCP = False
+
+    TOPOLOGY = {
+        SERVER: {
+            'name': 'SRP_SERVER',
+            'networkkey': '00112233445566778899aabbccddeeff',
+            'mode': 'rdn',
+        },
+        CLIENT: {
+            'name': 'SRP_CLIENT',
+            'networkkey': '00112233445566778899aabbccddeeff',
+            'mode': 'rdn',
+        },
+    }
+
+    def test(self):
+        server = self.nodes[SERVER]
+        client = self.nodes[CLIENT]
+
+        #
+        # 0. Start the server and client devices.
+        #
+
+        server.srp_server_set_enabled(True)
+        server.srp_server_set_lease_range(LEASE_TIME, LEASE_TIME, KEY_LEASE_TIME, KEY_LEASE_TIME)
+        server.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual(server.get_state(), 'leader')
+        self.simulator.go(5)
+
+        client.srp_server_set_enabled(False)
+        client.start()
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
+        self.assertEqual(client.get_state(), 'router')
+
+        #
+        # 1. Register a single service and verify that it works.
+        #
+
+        client.srp_client_set_host_name('my-host')
+        client.srp_client_set_host_address('2001::1')
+        client.srp_client_start(server.get_addrs()[0], client.get_srp_server_port())
+        client.srp_client_add_service('my-service', '_ipps._tcp', 12345)
+        self.simulator.go(2)
+
+        self.check_host_and_service(server, client)
+
+        server.srp_server_set_lease_range(NEW_LEASE_TIME, NEW_LEASE_TIME, KEY_LEASE_TIME, KEY_LEASE_TIME)
+        client.srp_client_set_lease_interval(NEW_LEASE_TIME)
+        self.simulator.go(NEW_LEASE_TIME)
+        self.assertEqual(client.srp_client_get_host_state(), 'Registered')
+
+        self.simulator.go(KEY_LEASE_TIME * 2)
+        self.assertEqual(client.srp_client_get_host_state(), 'Registered')
+
+        client.srp_client_set_ttl(NEW_TTL)
+        self.simulator.go(NEW_LEASE_TIME)
+        self.assertEqual(client.srp_client_get_host_state(), 'Registered')
+
+        client.srp_client_set_ttl(0)
+        self.simulator.go(NEW_LEASE_TIME)
+        self.assertEqual(client.srp_client_get_host_state(), 'Registered')
+
+    def verify(self, pv):
+        pkts: PacketFilter = pv.pkts
+        pv.summary.show()
+
+        CLIENT_SRC64 = pv.vars['SRP_CLIENT']
+
+        pkts.filter_wpan_src64(CLIENT_SRC64).filter('dns.flags.response == 0 and dns.resp.ttl == {DEFAULT_LEASE_TIME}',
+                                                    DEFAULT_LEASE_TIME=DEFAULT_LEASE_TIME).must_next()
+        pkts.filter_wpan_src64(CLIENT_SRC64).filter('dns.flags.response == 0 and dns.resp.ttl == {NEW_LEASE_TIME}',
+                                                    NEW_LEASE_TIME=NEW_LEASE_TIME).must_next()
+        pkts.filter_wpan_src64(CLIENT_SRC64).filter('dns.flags.response == 0 and dns.resp.ttl == {NEW_TTL}',
+                                                    NEW_TTL=NEW_TTL).must_next()
+        pkts.filter_wpan_src64(CLIENT_SRC64).filter('dns.flags.response == 0 and dns.resp.ttl == {NEW_LEASE_TIME}',
+                                                    NEW_LEASE_TIME=NEW_LEASE_TIME).must_next()
+
+    def check_host_and_service(self, server, client):
+        """Check that we have properly registered host and service instance.
+        """
+
+        client_services = client.srp_client_get_services()
+        print(client_services)
+        self.assertEqual(len(client_services), 1)
+        client_service = client_services[0]
+
+        # Verify that the client possesses correct service resources.
+        self.assertEqual(client_service['instance'], 'my-service')
+        self.assertEqual(client_service['name'], '_ipps._tcp')
+        self.assertEqual(int(client_service['port']), 12345)
+        self.assertEqual(int(client_service['priority']), 0)
+        self.assertEqual(int(client_service['weight']), 0)
+
+        # Verify that the client received a SUCCESS response for the server.
+        self.assertEqual(client_service['state'], 'Registered')
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/test_srp_client_remove_host.py b/tests/scripts/thread-cert/test_srp_client_remove_host.py
index 78f158d..2980145 100755
--- a/tests/scripts/thread-cert/test_srp_client_remove_host.py
+++ b/tests/scripts/thread-cert/test_srp_client_remove_host.py
@@ -31,6 +31,7 @@
 import unittest
 
 import command
+import config
 import thread_cert
 
 # Test description:
@@ -71,11 +72,11 @@
         # Start the server & client devices.
 
         server.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(server.get_state(), 'leader')
 
         client.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(client.get_state(), 'router')
 
         server.srp_server_set_enabled(True)
diff --git a/tests/scripts/thread-cert/test_srp_client_save_server_info.py b/tests/scripts/thread-cert/test_srp_client_save_server_info.py
index 2f3bf2f..cb277e5 100755
--- a/tests/scripts/thread-cert/test_srp_client_save_server_info.py
+++ b/tests/scripts/thread-cert/test_srp_client_save_server_info.py
@@ -31,6 +31,7 @@
 import unittest
 
 import command
+import config
 import thread_cert
 
 # Test description:
@@ -87,7 +88,7 @@
         # Start the server & client devices.
 
         client.start()
-        self.simulator.go(WAIT_TIME)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(client.get_state(), 'leader')
 
         for node in [server1, server2, server3]:
diff --git a/tests/scripts/thread-cert/test_srp_lease.py b/tests/scripts/thread-cert/test_srp_lease.py
index b2252e6..946104c 100755
--- a/tests/scripts/thread-cert/test_srp_lease.py
+++ b/tests/scripts/thread-cert/test_srp_lease.py
@@ -31,6 +31,7 @@
 import unittest
 
 import command
+import config
 import thread_cert
 
 # Test description:
@@ -78,13 +79,13 @@
         server.srp_server_set_enabled(True)
         server.srp_server_set_lease_range(LEASE, LEASE, KEY_LEASE, KEY_LEASE)
         server.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(server.get_state(), 'leader')
         self.simulator.go(5)
 
         client.srp_server_set_enabled(False)
         client.start()
-        self.simulator.go(10)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(client.get_state(), 'router')
 
         #
diff --git a/tests/scripts/thread-cert/test_srp_many_services_mtu_check.py b/tests/scripts/thread-cert/test_srp_many_services_mtu_check.py
new file mode 100755
index 0000000..89a173f
--- /dev/null
+++ b/tests/scripts/thread-cert/test_srp_many_services_mtu_check.py
@@ -0,0 +1,124 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+import ipaddress
+import unittest
+
+import command
+import config
+import thread_cert
+
+# Test description:
+#
+#   This test verifies SRP client behavior when there are many services
+#   causing SRP Update message going over the IPv6 MTU size. In such
+#   a case the SRP client attempts to register a single service at
+#   a time.
+#
+# Topology:
+#
+#     LEADER (SRP server)
+#       |
+#       |
+#     ROUTER (SRP client)
+#
+
+SERVER = 1
+CLIENT = 2
+
+
+class SrpManyServicesMtuCheck(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+    SUPPORT_NCP = False
+
+    TOPOLOGY = {
+        SERVER: {
+            'name': 'SRP_SERVER',
+            'mode': 'rdn',
+        },
+        CLIENT: {
+            'name': 'SRP_CLIENT',
+            'mode': 'rdn',
+        },
+    }
+
+    def test(self):
+        server = self.nodes[SERVER]
+        client = self.nodes[CLIENT]
+
+        # Start the server & client devices.
+
+        server.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual(server.get_state(), 'leader')
+
+        client.start()
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
+        self.assertEqual(client.get_state(), 'router')
+
+        server.srp_server_set_enabled(True)
+        client.srp_client_enable_auto_start_mode()
+        self.simulator.go(5)
+
+        # Register 8 services with long name, 6 sub-types and long txt record.
+        # The 8 services won't be fit in a single MTU (1280 bytes) UDP message
+        # SRP Client would then register services one by one.
+
+        num_services = 8
+
+        client.srp_client_set_host_name('hosthosthosthosthosthosthosthosthosthosthosthosthosthosthosthos')
+        client.srp_client_set_host_address('2001::1')
+
+        txt_info = ["xyz=987654321", "uvw=abcdefghijklmnopqrstu", "qwp=564321abcdefghij"]
+
+        for num in range(num_services):
+            name = chr(ord('a') + num) * 63
+            client.srp_client_add_service(
+                name,
+                '_longsrvname._udp,_subtype1,_subtype2,_subtype3,_subtype4,_subtype5,_subtype6',
+                1977,
+                txt_entries=txt_info)
+
+        self.simulator.go(10)
+
+        # Make sure all services are successfully registered
+        # (from both client and server perspectives).
+
+        client_services = client.srp_client_get_services()
+        self.assertEqual(len(client_services), num_services)
+
+        for service in client_services:
+            self.assertEqual(service['state'], 'Registered')
+
+        server_services = server.srp_server_get_services()
+        self.assertEqual(len(server_services), num_services)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/test_srp_name_conflicts.py b/tests/scripts/thread-cert/test_srp_name_conflicts.py
index eb708fc..4451eab 100755
--- a/tests/scripts/thread-cert/test_srp_name_conflicts.py
+++ b/tests/scripts/thread-cert/test_srp_name_conflicts.py
@@ -31,6 +31,7 @@
 import unittest
 
 import command
+import config
 import thread_cert
 
 # Test description:
@@ -82,18 +83,18 @@
 
         server.srp_server_set_enabled(True)
         server.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(server.get_state(), 'leader')
         self.simulator.go(5)
 
         client_1.srp_server_set_enabled(False)
         client_1.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(client_1.get_state(), 'router')
 
         client_2.srp_server_set_enabled(False)
         client_2.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(client_2.get_state(), 'router')
 
         #
@@ -177,7 +178,35 @@
         client_2.srp_client_stop()
 
         #
-        # 4. Register with different host & service instance name, it should succeed.
+        # 4. Register the same service instance label with a different service name
+        # from the second client and it should pass.
+        #
+
+        client_2.srp_client_set_host_name('my-host-2')
+        client_2.srp_client_set_host_address('2001::2')
+        client_2.srp_client_start(server.get_addrs()[0], client_2.get_srp_server_port())
+        client_2.srp_client_add_service('my-service-1', '_ipps2._tcp', 12345)
+        self.simulator.go(2)
+
+        # It is expected that the registration will be accepted.
+        client_2_service = client_2.srp_client_get_services()[0]
+        self.assertEqual(client_2_service['state'], 'Registered')
+        self.assertEqual(client_2.srp_client_get_host_state(), 'Registered')
+
+        self.assertEqual(len(server.srp_server_get_services()), 2)
+        self.assertEqual(len(server.srp_server_get_hosts()), 2)
+        self.assertEqual(server.srp_server_get_host('my-host-2')['deleted'], 'false')
+        self.assertEqual(server.srp_server_get_service('my-service-1', '_ipps2._tcp')['deleted'], 'false')
+
+        # Remove the host and all services registered on the SRP server.
+        client_2.srp_client_remove_host(remove_key=True)
+        self.simulator.go(2)
+
+        client_2.srp_client_clear_host()
+        client_2.srp_client_stop()
+
+        #
+        # 5. Register with different host & service instance name, it should succeed.
         #
 
         client_2.srp_client_set_host_name('my-host-2')
@@ -204,7 +233,7 @@
         client_2.srp_client_stop()
 
         #
-        # 5. Register with the same service instance name before its KEY LEASE expires,
+        # 6. Register with the same service instance full name before its KEY LEASE expires,
         #    it is expected to fail.
         #
 
@@ -234,7 +263,7 @@
         client_2.srp_client_stop()
 
         #
-        # 6. The service instance name can be re-used by another client when
+        # 7. The service instance name can be re-used by another client when
         #    the service has been permanently removed (the KEY resource is
         #    removed) from the host.
         #
diff --git a/tests/scripts/thread-cert/test_srp_register_500_services.py b/tests/scripts/thread-cert/test_srp_register_500_services.py
index 8e41196..54719dd 100644
--- a/tests/scripts/thread-cert/test_srp_register_500_services.py
+++ b/tests/scripts/thread-cert/test_srp_register_500_services.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 
 # Test description:
@@ -112,13 +113,13 @@
         # Start the server & clients.
         server.srp_server_set_enabled(True)
         server.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(server.get_state(), 'leader')
 
         for router in routers():
             router.srp_server_set_enabled(False)
             router.start()
-            self.simulator.go(3)
+            self.simulator.go(config.ROUTER_STARTUP_DELAY)
 
         for router in routers():
             self.assertEqual(router.get_state(), 'router')
diff --git a/tests/scripts/thread-cert/test_srp_register_single_service.py b/tests/scripts/thread-cert/test_srp_register_single_service.py
index 55f757e..621ad57 100755
--- a/tests/scripts/thread-cert/test_srp_register_single_service.py
+++ b/tests/scripts/thread-cert/test_srp_register_single_service.py
@@ -31,6 +31,7 @@
 import unittest
 
 import command
+import config
 import thread_cert
 
 # Test description:
@@ -75,13 +76,13 @@
 
         server.srp_server_set_enabled(True)
         server.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(server.get_state(), 'leader')
         self.simulator.go(5)
 
         client.srp_server_set_enabled(False)
         client.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(client.get_state(), 'router')
 
         #
diff --git a/tests/scripts/thread-cert/test_srp_server_anycast_mode.py b/tests/scripts/thread-cert/test_srp_server_anycast_mode.py
index 0a9031d..38a8321 100755
--- a/tests/scripts/thread-cert/test_srp_server_anycast_mode.py
+++ b/tests/scripts/thread-cert/test_srp_server_anycast_mode.py
@@ -94,12 +94,12 @@
         # Form the network.
 
         server.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(server.get_state(), 'leader')
 
         client.start()
         browser.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(client.get_state(), 'router')
         self.assertEqual(browser.get_state(), 'router')
 
diff --git a/tests/scripts/thread-cert/test_srp_server_reboot_port.py b/tests/scripts/thread-cert/test_srp_server_reboot_port.py
index 9a63a21..411b598 100755
--- a/tests/scripts/thread-cert/test_srp_server_reboot_port.py
+++ b/tests/scripts/thread-cert/test_srp_server_reboot_port.py
@@ -32,6 +32,7 @@
 import unittest
 
 import command
+import config
 import thread_cert
 
 # Test description:
@@ -74,12 +75,12 @@
 
         client.srp_server_set_enabled(False)
         client.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(client.get_state(), 'leader')
 
         server.srp_server_set_enabled(True)
         server.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(server.get_state(), 'router')
 
         #
diff --git a/tests/scripts/thread-cert/test_srp_sub_type.py b/tests/scripts/thread-cert/test_srp_sub_type.py
index 817ff40..e9b6fdc 100755
--- a/tests/scripts/thread-cert/test_srp_sub_type.py
+++ b/tests/scripts/thread-cert/test_srp_sub_type.py
@@ -31,6 +31,7 @@
 import unittest
 
 import command
+import config
 import thread_cert
 
 # Test description:
@@ -70,11 +71,11 @@
         # Start the server & client devices.
 
         server.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(server.get_state(), 'leader')
 
         client.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(client.get_state(), 'router')
 
         server.srp_server_set_enabled(True)
diff --git a/tests/scripts/thread-cert/test_srp_ttl.py b/tests/scripts/thread-cert/test_srp_ttl.py
new file mode 100755
index 0000000..93cc818
--- /dev/null
+++ b/tests/scripts/thread-cert/test_srp_ttl.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+import ipaddress
+import unittest
+
+import command
+import config
+import thread_cert
+
+# Test description:
+#   This test verifies the SRP server and client properly handle SRP host
+#   and service instance TTLs.
+#
+# Topology:
+#     LEADER (SRP server)
+#       |
+#       |
+#     ROUTER (SRP client)
+#
+
+SERVER = 1
+CLIENT = 2
+KEY_LEASE = 240  # Seconds
+
+
+class SrpTtl(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
+    SUPPORT_NCP = False
+
+    TOPOLOGY = {
+        SERVER: {
+            'name': 'SRP_SERVER',
+            'mode': 'rdn',
+        },
+        CLIENT: {
+            'name': 'SRP_CLIENT',
+            'mode': 'rdn',
+        },
+    }
+
+    def test(self):
+        server = self.nodes[SERVER]
+        client = self.nodes[CLIENT]
+
+        #
+        # Start the server and client devices.
+        #
+
+        server.srp_server_set_enabled(True)
+        server.srp_server_set_lease_range(120, 240, KEY_LEASE, KEY_LEASE)
+        server.start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual(server.get_state(), 'leader')
+        self.simulator.go(5)
+
+        client.srp_server_set_enabled(False)
+        client.start()
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
+        self.assertEqual(client.get_state(), 'router')
+
+        client.srp_client_set_host_name('my-host')
+        client.srp_client_set_host_address('2001::1')
+        client.srp_client_start(server.get_addrs()[0], client.get_srp_server_port())
+        client.srp_client_add_service('my-service', '_ipps._tcp', 12345)
+        self.simulator.go(2)
+
+        #
+        # CLIENT_TTL < TTL_MIN < LEASE_MAX ==> TTL_MIN
+        #
+
+        client.srp_client_set_ttl(100)
+        server.srp_server_set_ttl_range(120, 240)
+        server.srp_server_set_lease_range(120, 240, KEY_LEASE, KEY_LEASE)
+        self.simulator.go(KEY_LEASE)
+        self.check_ttl(120)
+
+        #
+        # TTL_MIN < CLIENT_TTL < TTL_MAX < LEASE_MAX ==> CLIENT_TTL
+        #
+
+        client.srp_client_set_ttl(100)
+        server.srp_server_set_ttl_range(60, 120)
+        server.srp_server_set_lease_range(120, 240, KEY_LEASE, KEY_LEASE)
+        self.simulator.go(KEY_LEASE)
+        self.check_ttl(100)
+
+        #
+        # TTL_MAX < LEASE_MAX < CLIENT_TTL ==> TTL_MAX
+        #
+
+        client.srp_client_set_ttl(240)
+        server.srp_server_set_ttl_range(60, 120)
+        server.srp_server_set_lease_range(120, 240, KEY_LEASE, KEY_LEASE)
+        self.simulator.go(KEY_LEASE)
+        self.check_ttl(120)
+
+        #
+        # LEASE_MAX < TTL_MAX < CLIENT_TTL ==> LEASE_MAX
+        #
+
+        client.srp_client_set_ttl(240)
+        server.srp_server_set_ttl_range(60, 120)
+        server.srp_server_set_lease_range(30, 60, KEY_LEASE, KEY_LEASE)
+        self.simulator.go(KEY_LEASE)
+        self.check_ttl(60)
+
+    def check_ttl(self, ttl):
+        """Check that we have properly registered host and service instance.
+        """
+
+        server = self.nodes[SERVER]
+
+        server_services = server.srp_server_get_services()
+        print(server_services)
+        self.assertEqual(len(server_services), 1)
+        server_service = server_services[0]
+
+        # Verify that the server accepted the SRP registration and stored
+        # the same service resources.
+        self.assertEqual(int(server_service['ttl']), ttl)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/scripts/thread-cert/test_zero_len_external_route.py b/tests/scripts/thread-cert/test_zero_len_external_route.py
index b5f0af9..b48dff8 100755
--- a/tests/scripts/thread-cert/test_zero_len_external_route.py
+++ b/tests/scripts/thread-cert/test_zero_len_external_route.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 
 # Test description:
@@ -75,12 +76,12 @@
         # Start the nodes and form the network.
 
         leader.start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(leader.get_state(), 'leader')
 
         router1.start()
         router2.start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(router1.get_state(), 'router')
         self.assertEqual(router2.get_state(), 'router')
 
diff --git a/tests/scripts/thread-cert/thread_cert.py b/tests/scripts/thread-cert/thread_cert.py
index 0695e5f..369ed50 100755
--- a/tests/scripts/thread-cert/thread_cert.py
+++ b/tests/scripts/thread-cert/thread_cert.py
@@ -32,12 +32,13 @@
 import logging
 import os
 import signal
+import stat
 import subprocess
 import sys
 import time
 import traceback
 import unittest
-from typing import Optional, Callable
+from typing import Optional, Callable, Union, Any
 
 import config
 import debug
@@ -100,6 +101,7 @@
     TOPOLOGY = None
     CASE_WIRESHARK_PREFS = None
     SUPPORT_THREAD_1_1 = True
+    PACKET_VERIFICATION = config.PACKET_VERIFICATION_DEFAULT
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
@@ -107,9 +109,16 @@
         logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
 
         self._start_time = None
-        self._do_packet_verification = PACKET_VERIFICATION and hasattr(self, 'verify')
+        self._do_packet_verification = PACKET_VERIFICATION and hasattr(self, 'verify') \
+                                       and self.PACKET_VERIFICATION == PACKET_VERIFICATION
+
+    def skipTest(self, reason: Any) -> None:
+        self._testSkipped = True
+        super(TestCase, self).skipTest(reason)
 
     def setUp(self):
+        self._testSkipped = False
+
         if ENV_THREAD_VERSION == '1.1' and not self.SUPPORT_THREAD_1_1:
             self.skipTest('Thread 1.1 not supported.')
 
@@ -162,6 +171,8 @@
                 version=params['version'],
                 is_bbr=params['is_bbr'],
             )
+            if 'boot_delay' in params:
+                self.simulator.go(params['boot_delay'])
 
             self.nodes[i] = node
 
@@ -172,6 +183,8 @@
             self.nodes[i].set_panid(params['panid'])
             self.nodes[i].set_mode(params['mode'])
 
+            if 'extended_panid' in params:
+                self.nodes[i].set_extpanid(params['extended_panid'])
             if 'partition_id' in params:
                 self.nodes[i].set_preferred_partition_id(params['partition_id'])
             if 'channel' in params:
@@ -230,6 +243,9 @@
             if 'bbr_registration_jitter' in params:
                 self.nodes[i].set_bbr_registration_jitter(params['bbr_registration_jitter'])
 
+            if 'router_id_range' in params:
+                self.nodes[i].set_router_id_range(params['router_id_range'][0], params['router_id_range'][1])
+
         # we have to add allowlist after nodes are all created
         for i, params in initial_topology.items():
             allowlist = params['allowlist']
@@ -264,8 +280,12 @@
             self._stop_backbone_sniffer()
 
         for node in list(self.nodes.values()):
-            node.stop()
-            node.destroy()
+            try:
+                node.stop()
+            except:
+                traceback.print_exc()
+            finally:
+                node.destroy()
 
         self.simulator.stop()
 
@@ -280,7 +300,8 @@
             self._test_info['pcap'] = pcap_filename
 
             test_info_path = self._output_test_info()
-            self._verify_packets(test_info_path)
+            if not self._testSkipped:
+                self._verify_packets(test_info_path)
 
     def flush_all(self):
         """Flush away all captured messages of all nodes.
@@ -308,6 +329,7 @@
     def _verify_packets(self, test_info_path: str):
         pv = PacketVerifier(test_info_path, self.CASE_WIRESHARK_PREFS)
         pv.add_common_vars()
+        pv.pkts.filter_thread_unallowed_icmpv6().must_not_next()
         self.verify(pv)
         print("Packet verification passed: %s" % test_info_path, file=sys.stderr)
 
@@ -356,6 +378,32 @@
 
             test_info['rlocs'][i] = node.get_rloc()
 
+    def collect_omrs(self):
+        if not self._do_packet_verification:
+            return
+
+        test_info = self._test_info
+        test_info['omrs'] = {}
+
+        for i, node in self.nodes.items():
+            if node.is_host:
+                continue
+
+            test_info['omrs'][i] = node.get_ip6_address(config.ADDRESS_TYPE.OMR)
+
+    def collect_duas(self):
+        if not self._do_packet_verification:
+            return
+
+        test_info = self._test_info
+        test_info['duas'] = {}
+
+        for i, node in self.nodes.items():
+            if node.is_host:
+                continue
+
+            test_info['duas'][i] = node.get_ip6_address(config.ADDRESS_TYPE.DUA)
+
     def collect_leader_aloc(self, node):
         if not self._do_packet_verification:
             return
@@ -434,15 +482,20 @@
         params = params or {}
 
         if params.get('is_bbr') or params.get('is_otbr'):
-            # BBRs must use thread version 1.2
-            assert params.get('version', '1.2') == '1.2', params
-            params['version'] = '1.2'
+            # BBRs must not use thread version 1.1
+            version = params.get('version', '1.3')
+            assert version != '1.1', params
+            params['version'] = version
             params.setdefault('bbr_registration_jitter', config.DEFAULT_BBR_REGISTRATION_JITTER)
         elif params.get('is_host'):
             # Hosts must not specify thread version
             assert params.get('version', '') == '', params
             params['version'] = ''
 
+        # use 1.3 node for 1.2 tests
+        if params.get('version') == '1.2':
+            params['version'] = '1.3'
+
         is_ftd = (not params.get('is_mtd') and not params.get('is_host'))
 
         effective_params = DEFAULT_PARAMS.copy()
@@ -487,6 +540,7 @@
         time.sleep(0.2)
         assert self._dumpcap_proc.poll() is None, 'tshark terminated unexpectedly'
         logging.info('Backbone sniffer launched successfully: pid=%s', self._dumpcap_proc.pid)
+        os.chmod(pcap_file, stat.S_IWUSR | stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
 
     def _get_backbone_pcap_filename(self):
         backbone_pcap = self.test_name + '_backbone.pcap'
@@ -521,8 +575,9 @@
             if timeout <= 0:
                 raise RuntimeError(f'wait failed after {timeout} seconds')
 
-    def wait_node_state(self, nodeid: int, state: str, timeout: int):
-        self.wait_until(lambda: self.nodes[nodeid].get_state() == state, timeout)
+    def wait_node_state(self, node: Union[int, Node], state: str, timeout: int):
+        node = self.nodes[node] if isinstance(node, int) else node
+        self.wait_until(lambda: node.get_state() == state, timeout)
 
     def wait_route_established(self, node1: int, node2: int, timeout=10):
         node2_addr = self.nodes[node2].get_ip6_address(config.ADDRESS_TYPE.RLOC)
diff --git a/tests/scripts/thread-cert/v1_2_LowPower_5_3_01_SSEDAttachment.py b/tests/scripts/thread-cert/v1_2_LowPower_5_3_01_SSEDAttachment.py
index ec95f4c..66f547e 100755
--- a/tests/scripts/thread-cert/v1_2_LowPower_5_3_01_SSEDAttachment.py
+++ b/tests/scripts/thread-cert/v1_2_LowPower_5_3_01_SSEDAttachment.py
@@ -34,6 +34,7 @@
 from pktverify import consts
 from pktverify.packet_verifier import PacketVerifier
 
+import config
 import thread_cert
 
 LEADER = 1
@@ -42,6 +43,7 @@
 
 
 class LowPower_5_3_01_SSEDAttachment(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
     TOPOLOGY = {
         LEADER: {
             'version': '1.2',
@@ -66,11 +68,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
 
         self.nodes[SSED_1].set_csl_period(consts.CSL_DEFAULT_PERIOD)
diff --git a/tests/scripts/thread-cert/v1_2_LowPower_6_1_07_PreferringARouterOverAReed.py b/tests/scripts/thread-cert/v1_2_LowPower_6_1_07_PreferringARouterOverAReed.py
index 26bd58f..7e9c857 100755
--- a/tests/scripts/thread-cert/v1_2_LowPower_6_1_07_PreferringARouterOverAReed.py
+++ b/tests/scripts/thread-cert/v1_2_LowPower_6_1_07_PreferringARouterOverAReed.py
@@ -34,6 +34,7 @@
 from pktverify import consts
 from pktverify.packet_verifier import PacketVerifier
 
+import config
 import thread_cert
 
 LEADER = 1
@@ -43,7 +44,7 @@
 
 
 class LowPower_6_1_07_PreferringARouterOverAReed_Base(thread_cert.TestCase):
-
+    USE_MESSAGE_FACTORY = False
     TOPOLOGY = {
         LEADER: {
             'version': '1.2',
@@ -74,11 +75,11 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER_1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER_1].get_state(), 'router')
 
         self.nodes[REED_1].start()
@@ -117,7 +118,7 @@
             .filter_mle_cmd(consts.MLE_PARENT_REQUEST) \
             .filter_mle_has_tlv(TlvType.CHALLENGE, TlvType.MODE) \
             .filter(lambda p: p.mle.tlv.scan_mask.r == 1 and p.mle.tlv.scan_mask.e == 0) \
-            .filter(lambda p: p.mle.tlv.version == 3) \
+            .filter(lambda p: p.mle.tlv.version >= config.THREAD_VERSION_1_2) \
             .filter(lambda p: p.ipv6.hlim == 255) \
             .filter_LLARMA() \
             .must_next()
@@ -126,7 +127,7 @@
         pkts.filter_wpan_src64(ROUTER_1) \
             .filter_wpan_dst64(DUT) \
             .filter_mle_cmd(consts.MLE_PARENT_RESPONSE) \
-            .filter(lambda p: p.mle.tlv.version == 2) \
+            .filter(lambda p: p.mle.tlv.version == config.THREAD_VERSION_1_1) \
             .must_next()
 
         # Step 5 - DUT sends another multicast MLE Parent Request to the all-routers multicast with the Scan Mask TLV
@@ -135,7 +136,7 @@
             .filter_mle_cmd(consts.MLE_PARENT_REQUEST) \
             .filter_mle_has_tlv(TlvType.CHALLENGE, TlvType.MODE) \
             .filter(lambda p: p.mle.tlv.scan_mask.r == 1 and p.mle.tlv.scan_mask.e == 1) \
-            .filter(lambda p: p.mle.tlv.version == consts.THREAD_VERSION_1_2) \
+            .filter(lambda p: p.mle.tlv.version >= consts.THREAD_VERSION_1_2) \
             .filter(lambda p: p.ipv6.hlim == 255) \
             .filter_LLARMA() \
             .must_next()
@@ -151,7 +152,7 @@
             .filter_mle_cmd(consts.MLE_CHILD_ID_REQUEST) \
             .filter_wpan_dst64(ROUTER_1) \
             .filter_mle_has_tlv(TlvType.ADDRESS_REGISTRATION, TlvType.LINK_LAYER_FRAME_COUNTER, TlvType.MODE, TlvType.RESPONSE, TlvType.TIMEOUT, TlvType.TLV_REQUEST) \
-            .filter(lambda p: p.mle.tlv.version == consts.THREAD_VERSION_1_2) \
+            .filter(lambda p: p.mle.tlv.version >= consts.THREAD_VERSION_1_2) \
             .must_next()
 
 
diff --git a/tests/scripts/thread-cert/v1_2_LowPower_7_1_01_SingleProbeLinkMetricsWithEnhancedAcks.py b/tests/scripts/thread-cert/v1_2_LowPower_7_1_01_SingleProbeLinkMetricsWithEnhancedAcks.py
index 6f9a167..e14e49a 100755
--- a/tests/scripts/thread-cert/v1_2_LowPower_7_1_01_SingleProbeLinkMetricsWithEnhancedAcks.py
+++ b/tests/scripts/thread-cert/v1_2_LowPower_7_1_01_SingleProbeLinkMetricsWithEnhancedAcks.py
@@ -32,6 +32,7 @@
 from config import ADDRESS_TYPE
 from pktverify import consts
 
+import config
 import thread_cert
 
 LEADER = 1
@@ -42,6 +43,7 @@
 
 
 class LowPower_7_1_01(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
     TOPOLOGY = {
         LEADER: {
             'version': '1.2',
@@ -66,7 +68,7 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[SED_1].set_pollperiod(POLL_PERIOD)
diff --git a/tests/scripts/thread-cert/v1_2_LowPower_7_2_01_ForwardTrackingSeries.py b/tests/scripts/thread-cert/v1_2_LowPower_7_2_01_ForwardTrackingSeries.py
index adb1f5e..b9543cf 100755
--- a/tests/scripts/thread-cert/v1_2_LowPower_7_2_01_ForwardTrackingSeries.py
+++ b/tests/scripts/thread-cert/v1_2_LowPower_7_2_01_ForwardTrackingSeries.py
@@ -35,6 +35,7 @@
 from pktverify.null_field import nullField
 from pktverify.packet_verifier import PacketVerifier
 
+import config
 import thread_cert
 
 LEADER = 1
@@ -47,6 +48,7 @@
 
 
 class LowPower_7_2_01_ForwardTrackingSeries(thread_cert.TestCase):
+    USE_MESSAGE_FACTORY = False
     TOPOLOGY = {
         LEADER: {
             'version': '1.2',
@@ -71,7 +73,7 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[SED_1].set_pollperiod(POLL_PERIOD)
diff --git a/tests/scripts/thread-cert/v1_2_LowPower_test_forward_tracking_series.py b/tests/scripts/thread-cert/v1_2_LowPower_test_forward_tracking_series.py
index ffa7e3f..c1287fe 100755
--- a/tests/scripts/thread-cert/v1_2_LowPower_test_forward_tracking_series.py
+++ b/tests/scripts/thread-cert/v1_2_LowPower_test_forward_tracking_series.py
@@ -35,6 +35,7 @@
 from pktverify.null_field import nullField
 from pktverify.packet_verifier import PacketVerifier
 
+import config
 import thread_cert
 
 LEADER = 1
@@ -63,7 +64,7 @@
 
     def test(self):
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[CHILD].start()
diff --git a/tests/scripts/thread-cert/v1_2_router_5_1_1.py b/tests/scripts/thread-cert/v1_2_router_5_1_1.py
index 1520b39..20173f5 100755
--- a/tests/scripts/thread-cert/v1_2_router_5_1_1.py
+++ b/tests/scripts/thread-cert/v1_2_router_5_1_1.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import thread_cert
 import mle
 import network_layer
@@ -52,11 +53,11 @@
         self.nodes[ROUTER_1].set_router_selection_jitter(1)
 
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[ROUTER_1].start()
-        self.simulator.go(7)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER_1].get_state(), 'router')
 
         leader_messages = self.simulator.get_messages_sent_by(LEADER)
@@ -78,7 +79,7 @@
         msg.assertMleMessageContainsTlv(mle.Challenge)
         msg.assertMleMessageContainsTlv(mle.ScanMask)
         msg.assertMleMessageContainsTlv(mle.Version)
-        assert msg.get_mle_message_tlv(mle.Version).version == 3
+        assert msg.get_mle_message_tlv(mle.Version).version >= config.THREAD_VERSION_1_2
 
         scan_mask_tlv = msg.get_mle_message_tlv(mle.ScanMask)
         self.assertEqual(1, scan_mask_tlv.router)
@@ -96,7 +97,7 @@
         msg.assertMleMessageContainsTlv(mle.LinkMargin)
         msg.assertMleMessageContainsTlv(mle.Connectivity)
         msg.assertMleMessageContainsTlv(mle.Version)
-        assert msg.get_mle_message_tlv(mle.Version).version == 3
+        assert msg.get_mle_message_tlv(mle.Version).version >= config.THREAD_VERSION_1_2
 
         # 4 - Router_1 receives the MLE Parent Response and sends a Child ID Request
         msg = router_messages.next_mle_message(mle.CommandType.CHILD_ID_REQUEST)
@@ -109,7 +110,7 @@
         msg.assertMleMessageContainsTlv(mle.Version)
         msg.assertMleMessageContainsTlv(mle.TlvRequest)
         msg.assertMleMessageDoesNotContainTlv(mle.AddressRegistration)
-        assert msg.get_mle_message_tlv(mle.Version).version == 3
+        assert msg.get_mle_message_tlv(mle.Version).version >= config.THREAD_VERSION_1_2
 
         # 5 - Leader responds with a Child ID Response
         msg = leader_messages.next_mle_message(mle.CommandType.CHILD_ID_RESPONSE)
diff --git a/tests/scripts/thread-cert/v1_2_test_backbone_router_service.py b/tests/scripts/thread-cert/v1_2_test_backbone_router_service.py
index c538ec5..1a9d54d 100755
--- a/tests/scripts/thread-cert/v1_2_test_backbone_router_service.py
+++ b/tests/scripts/thread-cert/v1_2_test_backbone_router_service.py
@@ -92,7 +92,7 @@
 
         self.nodes[LEADER_1_1].start()
         WAIT_TIME = WAIT_ATTACH
-        self.simulator.go(WAIT_TIME)
+        self.simulator.go(WAIT_TIME * 2)
         self.assertEqual(self.nodes[LEADER_1_1].get_state(), 'leader')
         self.simulator.set_lowpan_context(1, config.DOMAIN_PREFIX)
 
diff --git a/tests/scripts/thread-cert/v1_2_test_csl_transmission.py b/tests/scripts/thread-cert/v1_2_test_csl_transmission.py
index c7e1ad1..fa358f4 100755
--- a/tests/scripts/thread-cert/v1_2_test_csl_transmission.py
+++ b/tests/scripts/thread-cert/v1_2_test_csl_transmission.py
@@ -29,6 +29,7 @@
 
 import unittest
 
+import config
 import mle
 import thread_cert
 from pktverify import consts
@@ -58,7 +59,7 @@
         self.nodes[SSED_1].get_csl_info()
 
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[SSED_1].start()
@@ -124,6 +125,23 @@
         ssed_messages = self.simulator.get_messages_sent_by(SSED_1)
         self.assertIsNotNone(ssed_messages.next_data_poll())
 
+        # Check if SSED is able to resynchronize with the parent after it is gone longer than the timeout
+        self.nodes[LEADER].start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.nodes[SSED_1].set_csl_timeout(8)
+        self.nodes[SSED_1].set_timeout(10)
+        self.simulator.go(2)
+        self.nodes[LEADER].stop()
+        self.simulator.go(25)
+        self.flush_all()
+        self.nodes[LEADER].start()
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
+        self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
+        self.simulator.go(5)
+        self.assertEqual(self.nodes[SSED_1].get_state(), 'child')
+        ssed_messages = self.simulator.get_messages_sent_by(SSED_1)
+        self.assertIsNotNone(ssed_messages.next_mle_message(mle.CommandType.CHILD_UPDATE_REQUEST))
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/scripts/thread-cert/v1_2_test_domain_unicast_address.py b/tests/scripts/thread-cert/v1_2_test_domain_unicast_address.py
index 54b9a5b..13c1950 100755
--- a/tests/scripts/thread-cert/v1_2_test_domain_unicast_address.py
+++ b/tests/scripts/thread-cert/v1_2_test_domain_unicast_address.py
@@ -160,7 +160,7 @@
         self.nodes[BBR_1].set_backbone_router(seqno=1)
         self.nodes[BBR_1].start()
         WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER
-        self.simulator.go(WAIT_TIME)
+        self.simulator.go(WAIT_TIME * 2)
         self.assertEqual(self.nodes[BBR_1].get_state(), 'leader')
         self.nodes[BBR_1].enable_backbone_router()
         WAIT_TIME = BBR_REGISTRATION_JITTER + WAIT_REDUNDANCE
diff --git a/tests/scripts/thread-cert/v1_2_test_domain_unicast_address_registration.py b/tests/scripts/thread-cert/v1_2_test_domain_unicast_address_registration.py
index 9dcc75d..dfbf314 100755
--- a/tests/scripts/thread-cert/v1_2_test_domain_unicast_address_registration.py
+++ b/tests/scripts/thread-cert/v1_2_test_domain_unicast_address_registration.py
@@ -188,7 +188,7 @@
         self.nodes[BBR_1].set_backbone_router(seqno=seq_num, reg_delay=BBR_REREGISTRATION_DELAY)
         self.nodes[BBR_1].start()
         WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER
-        self.simulator.go(WAIT_TIME)
+        self.simulator.go(WAIT_TIME * 2)
         self.assertEqual(self.nodes[BBR_1].get_state(), 'leader')
         self.nodes[BBR_1].enable_backbone_router()
         WAIT_TIME = BBR_REGISTRATION_JITTER + WAIT_REDUNDANCE
diff --git a/tests/scripts/thread-cert/v1_2_test_dua_handle_address_error.py b/tests/scripts/thread-cert/v1_2_test_dua_handle_address_error.py
index 60bb2a9..ea36c69 100755
--- a/tests/scripts/thread-cert/v1_2_test_dua_handle_address_error.py
+++ b/tests/scripts/thread-cert/v1_2_test_dua_handle_address_error.py
@@ -77,6 +77,7 @@
         },
         MED: {
             'version': '1.2',
+            'is_mtd': True,
             'allowlist': [ROUTER],
             'mode': 'rn',
         },
@@ -91,7 +92,7 @@
         self.nodes[BBR_1].set_backbone_router(seqno=1, reg_delay=REG_DELAY)
         self.nodes[BBR_1].start()
 
-        self.simulator.go(WAIT_ATTACH + config.DEFAULT_ROUTER_SELECTION_JITTER)
+        self.simulator.go(WAIT_ATTACH * 2 + config.DEFAULT_ROUTER_SELECTION_JITTER)
         self.assertEqual(self.nodes[BBR_1].get_state(), 'leader')
         self.nodes[BBR_1].enable_backbone_router()
         self.simulator.go(BBR_REGISTRATION_JITTER + WAIT_REDUNDANCE)
diff --git a/tests/scripts/thread-cert/v1_2_test_enhanced_frame_pending.py b/tests/scripts/thread-cert/v1_2_test_enhanced_frame_pending.py
index 92eb180..436cfa9 100755
--- a/tests/scripts/thread-cert/v1_2_test_enhanced_frame_pending.py
+++ b/tests/scripts/thread-cert/v1_2_test_enhanced_frame_pending.py
@@ -46,6 +46,7 @@
 import pexpect
 
 import thread_cert
+import config
 import common
 
 LEADER = 1
@@ -74,7 +75,7 @@
 
         # 1 - Set up topology
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[SED_1].start()
diff --git a/tests/scripts/thread-cert/v1_2_test_enhanced_keep_alive.py b/tests/scripts/thread-cert/v1_2_test_enhanced_keep_alive.py
index 80270d2..9bd10c3 100755
--- a/tests/scripts/thread-cert/v1_2_test_enhanced_keep_alive.py
+++ b/tests/scripts/thread-cert/v1_2_test_enhanced_keep_alive.py
@@ -30,6 +30,7 @@
 import unittest
 
 import thread_cert
+import config
 import mle
 
 LEADER = 1
@@ -61,7 +62,7 @@
         self.nodes[SED_1].set_pollperiod(USER_POLL_PERIOD * 1000)
 
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[SED_1].start()
@@ -87,7 +88,7 @@
         msg.assertMleMessageContainsTlv(mle.Challenge)
         msg.assertMleMessageContainsTlv(mle.ScanMask)
         msg.assertMleMessageContainsTlv(mle.Version)
-        self.assertEqual(msg.get_mle_message_tlv(mle.Version).version, 3)
+        self.assertGreaterEqual(msg.get_mle_message_tlv(mle.Version).version, config.THREAD_VERSION_1_2)
 
         scan_mask_tlv = msg.get_mle_message_tlv(mle.ScanMask)
         self.assertEqual(1, scan_mask_tlv.router)
@@ -105,7 +106,7 @@
         msg.assertMleMessageContainsTlv(mle.LinkMargin)
         msg.assertMleMessageContainsTlv(mle.Connectivity)
         msg.assertMleMessageContainsTlv(mle.Version)
-        self.assertEqual(msg.get_mle_message_tlv(mle.Version).version, 3)
+        self.assertGreaterEqual(msg.get_mle_message_tlv(mle.Version).version, config.THREAD_VERSION_1_2)
 
         # 4 - SED_1 receives the MLE Parent Response and sends a Child ID Request
         msg = sed_messages.next_mle_message(mle.CommandType.CHILD_ID_REQUEST)
@@ -117,7 +118,7 @@
         msg.assertMleMessageContainsTlv(mle.Timeout)
         msg.assertMleMessageContainsTlv(mle.Version)
         msg.assertMleMessageContainsTlv(mle.TlvRequest)
-        self.assertEqual(msg.get_mle_message_tlv(mle.Version).version, 3)
+        self.assertGreaterEqual(msg.get_mle_message_tlv(mle.Version).version, config.THREAD_VERSION_1_2)
 
         # 5 - Leader responds with a Child ID Response
         msg = leader_messages.next_mle_message(mle.CommandType.CHILD_ID_RESPONSE)
diff --git a/tests/scripts/thread-cert/v1_2_test_multicast_listener_registration.py b/tests/scripts/thread-cert/v1_2_test_multicast_listener_registration.py
index 33193b4..a424e99 100755
--- a/tests/scripts/thread-cert/v1_2_test_multicast_listener_registration.py
+++ b/tests/scripts/thread-cert/v1_2_test_multicast_listener_registration.py
@@ -114,7 +114,7 @@
             'mode': 'rdn',
             'version': '1.2',
             'allowlist': [ROUTER_1_2],
-            'router_upgrade_threshold': 0,
+            'router_eligible': False,
             'timeout': config.DEFAULT_CHILD_TIMEOUT,
         },
     }
@@ -134,7 +134,7 @@
         self.nodes[BBR_1].set_backbone_router(seqno=1, reg_delay=REREG_DELAY, mlr_timeout=MLR_TIMEOUT)
         self.nodes[BBR_1].start()
         WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER
-        self.simulator.go(WAIT_TIME)
+        self.simulator.go(WAIT_TIME * 2)
         self.assertEqual(self.nodes[BBR_1].get_state(), 'leader')
 
         if bbr_1_enable_backbone_router:
diff --git a/tests/scripts/thread-cert/v1_2_test_multicast_registration.py b/tests/scripts/thread-cert/v1_2_test_multicast_registration.py
index afed084..67537b7 100755
--- a/tests/scripts/thread-cert/v1_2_test_multicast_registration.py
+++ b/tests/scripts/thread-cert/v1_2_test_multicast_registration.py
@@ -177,7 +177,7 @@
         # 1) Bring up Leader_1_2.
         self.nodes[LEADER_1_2].start()
         WAIT_TIME = WAIT_ATTACH
-        self.simulator.go(WAIT_TIME)
+        self.simulator.go(WAIT_TIME * 2)
         self.assertEqual(self.nodes[LEADER_1_2].get_state(), 'leader')
 
         # 2) Bring up MED_1_2, which attaches to Thread 1.2 parent, only register MA with scope larger than realm local.
diff --git a/tests/scripts/thread-cert/v1_2_test_parent_selection.py b/tests/scripts/thread-cert/v1_2_test_parent_selection.py
index 154d400..7b55b91 100755
--- a/tests/scripts/thread-cert/v1_2_test_parent_selection.py
+++ b/tests/scripts/thread-cert/v1_2_test_parent_selection.py
@@ -30,6 +30,7 @@
 import unittest
 
 import thread_cert
+import config
 import mle
 
 LEADER_1_2 = 1
@@ -106,12 +107,12 @@
     def test(self):
 
         self.nodes[LEADER_1_2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER_1_2].get_state(), 'leader')
 
         self.nodes[ROUTER_1_1].set_router_selection_jitter(1)
         self.nodes[ROUTER_1_1].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER_1_1].get_state(), 'router')
 
         # Mesh Impacting Criteria - Highest Two-way link quality
@@ -157,7 +158,7 @@
         self.nodes[REED_1_2].set_link_quality(self.nodes[ROUTER_1_2].get_addr64(), 2)
         self.nodes[ROUTER_1_2].set_router_selection_jitter(1)
         self.nodes[ROUTER_1_2].start()
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[ROUTER_1_2].get_state(), 'router')
 
         # Check Parent Response
@@ -219,7 +220,7 @@
         # MED_1_1 would attach to LEADER_1_2
 
         self.nodes[REED_1_1].set_state('router')
-        self.simulator.go(5)
+        self.simulator.go(config.ROUTER_STARTUP_DELAY)
         self.assertEqual(self.nodes[REED_1_1].get_state(), 'router')
 
         # Flush relative message queues
@@ -259,7 +260,7 @@
 
         self.nodes[ROUTER_1_1].set_parent_priority(1)
         self.nodes[MED_1_2].start()
-        self.simulator.go(5)
+        self.simulator.go(15)
         self.assertEqual(self.nodes[MED_1_2].get_state(), 'child')
 
         # Check Parent Response
diff --git a/tests/scripts/thread-cert/v1_2_test_single_probe.py b/tests/scripts/thread-cert/v1_2_test_single_probe.py
index 899ee50..b929479 100755
--- a/tests/scripts/thread-cert/v1_2_test_single_probe.py
+++ b/tests/scripts/thread-cert/v1_2_test_single_probe.py
@@ -31,6 +31,7 @@
 
 import mle
 import thread_cert
+import config
 
 LEADER = 1
 SSED_1 = 2
@@ -57,7 +58,7 @@
         self.nodes[SSED_1].set_csl_timeout(CSL_TIMEOUT)
 
         self.nodes[LEADER].start()
-        self.simulator.go(5)
+        self.simulator.go(config.LEADER_STARTUP_DELAY)
         self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
 
         self.nodes[SSED_1].start()
diff --git a/tests/toranj/README.md b/tests/toranj/README.md
index 265cc7f..d7024f8 100644
--- a/tests/toranj/README.md
+++ b/tests/toranj/README.md
@@ -1,372 +1,25 @@
 # `toranj` test framework
 
-`toranj` is a test framework for OpenThread and `wpantund`.
+`toranj` is a test framework for OpenThread.
 
-- It enables testing of combined behavior of OpenThread (in NCP mode), spinel interface, and `wpantund` driver on linux.
+It provides two modes:
+
+- `toranj-cli` which enables testing of OpenThread using its CLI interface.
+- `toranj-ncp` which enables testing of the combined behavior of OpenThread (in NCP mode), spinel interface, and `wpantund` driver on linux.
+
+`toranj` features:
+
+- It is developed in Python.
 - It can be used to simulate multiple nodes forming complex network topologies.
 - It allows testing of network interactions between many nodes (IPv6 traffic exchanges).
+- `toranj` in NCP mode runs `wpantund` natively with OpenThread in NCP mode on simulation platform (real-time).
+- `toranj` in CLI mode runs `ot-cli-ftd` on simulation platform (real-time).
+- `toranj` tests run as part of GitHub Actions pull request validation in OpenThread and `wpantund` GitHub projects.
 
-`toranj` is developed in Python. `toranj` runs wpantund natively with OpenThread in NCP mode on POSIX simulation platform. `toranj` tests will run as part of GitHub Actions pull request validation in OpenThread and/or `wpantund` GitHub projects.
+## `toranj` modes
 
-## Setup
-
-`toranj` requires `wpantund` to be installed.
-
-- Please follow [`wpantund` installation guide](https://github.com/openthread/wpantund/blob/master/INSTALL.md#wpantund-installation-guide). Note that `toranj` expects `wpantund` installed from latest master branch.
-- Alternative way to install `wpantund` is to use the same commands from git workflow [Simulation](https://github.com/openthread/openthread/blob/4b55284bd20f99a88e8e2c617ba358a0a5547f5d/.github/workflows/simulation.yml#L336-L341) for build target `toranj-test-framework`.
-
-To run all tests, `start` script can be used. This script will build OpenThread with proper configuration options and starts running all test.
-
-```bash
-    cd tests/toranj/    # from OpenThread repo root
-    ./start.sh
-```
-
-Each test-case has its own script following naming model `test-nnn-name.py` (e.g., `test-001-get-set.py`).
-
-To run a specific test
-
-```bash
-    sudo python test-001-get-set.py
-```
-
-## `toranj` Components
-
-`wpan` python module defines the `toranj` test components.
-
-### `wpan.Node()` Class
-
-`wpan.Node()` class creates a Thread node instance. It creates a sub-process to run `wpantund` and OpenThread, and provides methods to control the node.
-
-```python
->>> import wpan
->>> node1 = wpan.Node()
->>> node1
-Node (index=1, interface_name=wpan1)
->>> node2 = wpan.Node()
->>> node2
-Node (index=2, interface_name=wpan2)
-```
-
-Note: You may need to run as `sudo` to allow `wpantund` to create tunnel interface (i.e., use `sudo python`).
-
-### `wpan.Node` methods providing `wpanctl` commands
-
-`wpan.Node()` provides methods matching all `wpanctl` commands.
-
-- Get the value of a `wpantund` property, set the value, or add/remove value to/from a list based property:
-
-```python
-    node.get(prop_name)
-    node.set(prop_name, value, binary_data=False)
-    node.add(prop_name, value, binary_data=False)
-    node.remove(prop_name, value, binary_data=False)
-```
-
-Example:
-
-```python
->>> node.get(wpan.WPAN_NAME)
-'"test-network"'
->>> node.set(wpan.WPAN_NAME, 'my-network')
->>> node.get(wpan.WPAN_NAME)
-'"my-network"'
->>> node.set(wpan.WPAN_KEY, '65F2C35C7B543BAC1F3E26BB9F866C1D', binary_data=True)
->>> node.get(wpan.WPAN_KEY)
-'[65F2C35C7B543BAC1F3E26BB9F866C1D]'
-```
-
-- Common network operations:
-
-```python
-    node.reset()            # Reset the NCP
-    node.status()           # Get current status
-    node.leave()            # Leave the current network, clear all persistent data
-
-    # Form a network in given channel (if none given use a random one)
-    node.form(name, channel=None)
-
-    # Join a network with given info.
-    # node_type can be JOIN_TYPE_ROUTER, JOIN_TYPE_END_DEVICE, JOIN_TYPE_SLEEPY_END_DEVICE
-    node.join(name, channel=None, node_type=None, panid=None, xpanid=None)
-```
-
-Example:
-
-```python
->>> result = node.status()
->>> print result
-wpan1 => [
-    "NCP:State" => "offline"
-    "Daemon:Enabled" => true
-    "NCP:Version" => "OPENTHREAD/20170716-00460-ga438cef0c-dirty; NONE; Feb 12 2018 11:47:01"
-    "Daemon:Version" => "0.08.00d (0.07.01-191-g63265f7; Feb  2 2018 18:05:47)"
-    "Config:NCP:DriverName" => "spinel"
-    "NCP:HardwareAddress" => [18B4300000000001]
-]
->>>
->>> node.form("test-network", channel=12)
-'Forming WPAN "test-network" as node type "router"\nSuccessfully formed!'
->>>
->>> print node.status()
-wpan1 => [
-    "NCP:State" => "associated"
-    "Daemon:Enabled" => true
-    "NCP:Version" => "OPENTHREAD/20170716-00460-ga438cef0c-dirty; NONE; Feb 12 2018 11:47:01"
-    "Daemon:Version" => "0.08.00d (0.07.01-191-g63265f7; Feb  2 2018 18:05:47)"
-    "Config:NCP:DriverName" => "spinel"
-    "NCP:HardwareAddress" => [18B4300000000001]
-    "NCP:Channel" => 12
-    "Network:NodeType" => "leader"
-    "Network:Name" => "test-network"
-    "Network:XPANID" => 0xA438CF5973FD86B2
-    "Network:PANID" => 0x9D81
-    "IPv6:MeshLocalAddress" => "fda4:38cf:5973:0:b899:3436:15c6:941d"
-    "IPv6:MeshLocalPrefix" => "fda4:38cf:5973::/64"
-    "com.nestlabs.internal:Network:AllowingJoin" => false
-]
-```
-
-- Scan:
-
-```python
-    node.active_scan(channel=None)
-    node.energy_scan(channel=None)
-    node.discover_scan(channel=None, joiner_only=False, enable_filtering=False, panid_filter=None)
-    node.permit_join(duration_sec=None, port=None, udp=True, tcp=True)
-```
-
-- On-mesh prefixes and off-mesh routes:
-
-```python
-    node.config_gateway(prefix, default_route=False)
-    node.add_route(route_prefix, prefix_len_in_bytes=None, priority=None)
-    node.remove_route(route_prefix, prefix_len_in_bytes=None, priority=None)
-```
-
-A direct `wpanctl` command can be issued using `node.wpanctl(command)` with a given `command` string.
-
-`wpan` module provides variables for different `wpantund` properties. Some commonly used are:
-
-- Network/NCP properties: WPAN_STATE, WPAN_NAME, WPAN_PANID, WPAN_XPANID, WPAN_KEY, WPAN_CHANNEL, WPAN_HW_ADDRESS, WPAN_EXT_ADDRESS, WPAN_POLL_INTERVAL, WPAN_NODE_TYPE, WPAN_ROLE, WPAN_PARTITION_ID
-
-- IPv6 Addresses: WPAN_IP6_LINK_LOCAL_ADDRESS, WPAN_IP6_MESH_LOCAL_ADDRESS, WPAN_IP6_MESH_LOCAL_PREFIX, WPAN_IP6_ALL_ADDRESSES, WPAN_IP6_MULTICAST_ADDRESSES
-
-- Thread Properties: WPAN_THREAD_RLOC16, WPAN_THREAD_ROUTER_ID, WPAN_THREAD_LEADER_ADDRESS, WPAN_THREAD_LEADER_ROUTER_ID, WPAN_THREAD_LEADER_WEIGHT, WPAN_THREAD_LEADER_NETWORK_DATA,
-
-        WPAN_THREAD_CHILD_TABLE, WPAN_THREAD_CHILD_TABLE_ADDRESSES, WPAN_THREAD_NEIGHBOR_TABLE,
-        WPAN_THREAD_ROUTER_TABLE
-
-Method `join_node()` can be used by a node to join another node:
-
-```python
-    # `node1` joining `node2`'s network as a router
-    node1.join_node(node2, node_type=JOIN_TYPE_ROUTER)
-```
-
-Method `allowlist_node()` can be used to add a given node to the allowlist of the device and enables allowlisting:
-
-```python
-    # `node2` is added to the allowlist of `node1` and allowlisting is enabled on `node1`
-    node1.allowlist_node(node2)
-```
-
-#### Example (simple 3-node topology)
-
-Script below shows how to create a 3-node network topology with `node1` and `node2` being routers, and `node3` an end-device connected to `node2`:
-
-```python
->>> import wpan
->>> node1 = wpan.Node()
->>> node2 = wpan.Node()
->>> node3 = wpan.Node()
-
->>> wpan.Node.init_all_nodes()
-
->>> node1.form("test-PAN")
-'Forming WPAN "test-PAN" as node type "router"\nSuccessfully formed!'
-
->>> node1.allowlist_node(node2)
->>> node2.allowlist_node(node1)
-
->>> node2.join_node(node1, wpan.JOIN_TYPE_ROUTER)
-'Joining "test-PAN" C474513CB487778D as node type "router"\nSuccessfully Joined!'
-
->>> node3.allowlist_node(node2)
->>> node2.allowlist_node(node3)
-
->>> node3.join_node(node2, wpan.JOIN_TYPE_END_DEVICE)
-'Joining "test-PAN" C474513CB487778D as node type "end-device"\nSuccessfully Joined!'
-
->>> print node2.get(wpan.WPAN_THREAD_NEIGHBOR_TABLE)
-[
-    "EAC1672C3EAB30A4, RLOC16:9401, LQIn:3, AveRssi:-20, LastRssi:-20, Age:30, LinkFC:6, MleFC:0, IsChild:yes, RxOnIdle:yes, FTD:yes, SecDataReq:yes, FullNetData:yes"
-    "A2042C8762576FD5, RLOC16:dc00, LQIn:3, AveRssi:-20, LastRssi:-20, Age:5, LinkFC:21, MleFC:18, IsChild:no, RxOnIdle:yes, FTD:yes, SecDataReq:no, FullNetData:yes"
-]
->>> print node1.get(wpan.WPAN_THREAD_NEIGHBOR_TABLE)
-[
-    "960947C53415DAA1, RLOC16:9400, LQIn:3, AveRssi:-20, LastRssi:-20, Age:18, LinkFC:15, MleFC:11, IsChild:no, RxOnIdle:yes, FTD:yes, SecDataReq:no, FullNetData:yes"
-]
-
-```
-
-### IPv6 Message Exchange
-
-`toranj` allows a test-case to define traffic patterns (IPv6 message exchange) between different nodes. Message exchanges (tx/rx) are prepared and then an async rx/tx operation starts. The success and failure of tx/rx operations can then be verified by the test case.
-
-`wpan.Node` method `prepare_tx()` prepares a UDP6 transmission from a node.
-
-```python
-    node1.prepare_tx(src, dst, data, count)
-```
-
-- `src` and `dst` can be
-
-  - either a string containing an IPv6 address
-  - or a tuple (ipv6 address as string, port). if no port is given, a random port number is used.
-
-- `data` can be
-
-  - either a string containing the message to be sent,
-  - or an int indicating size of the message (a random message with the given length will be generated).
-
-- `count` gives number of times the message will be sent (default is 1).
-
-`prepare_tx` returns a `wpan.AsyncSender` object. The sender object can be used to check success/failure of tx operation.
-
-`wpan.Node` method `prepare_rx()` prepares a node to listen for UDP messages from a sender.
-
-```python
-    node2.prepare_rx(sender)
-```
-
-- `sender` should be an `wpan.AsyncSender` object returned from previous `prepare_tx`.
-- `prepare_rx()` returns a `wpan.AsyncReceiver` object to help test to check success/failure of rx operation.
-
-After all exchanges are prepared, static method `perform_async_tx_rx()` should be used to start all previously prepared rx and tx operations.
-
-```python
-    wpan.Node.perform_async_tx_rx(timeout)
-```
-
-- `timeout` gives amount of time (in seconds) to wait for all operations to finish. (default is 20 seconds)
-
-After `perform_async_tx_rx()` is done, the `AsyncSender` and `AsyncReceiver` objects can check if operations were successful (using property `was_successful`)
-
-#### Example
-
-Sending 10 messages containing `"Hello there!"` from `node1` to `node2` using their mesh-local addresses:
-
-```python
-# `node1` and `node2` are already joined and are part of the same Thread network.
-
-# Get the mesh local addresses
->>> mladdr1 = node1.get(wpan.WPAN_IP6_MESH_LOCAL_ADDRESS)[1:-1]  # remove `"` from start/end of string
->>> mladdr2 = node2.get(wpan.WPAN_IP6_MESH_LOCAL_ADDRESS)[1:-1]
-
->>> print (mladdr1, mladdr2)
-('fda4:38cf:5973:0:b899:3436:15c6:941d', 'fda4:38cf:5973:0:5836:fa55:7394:6d4b')
-
-# prepare a `sender` and corresponding `recver`
->>> sender = node1.prepare_tx((mladdr1, 1234), (mladdr2, 2345), "Hello there!", 10)
->>> recver = node2.prepare_rx(sender)
-
-# perform async message transfer
->>> wpan.Node.perform_async_tx_rx()
-
-# check status of `sender` and `recver`
->>> sender.was_successful
-True
->>> recver.was_successful
-True
-
-# `sender` or `recver` can provide info about the exchange
-
->>> sender.src_addr
-'fda4:38cf:5973:0:b899:3436:15c6:941d'
->>> sender.src_port
-1234
->>> sender.dst_addr
-'fda4:38cf:5973:0:5836:fa55:7394:6d4b'
->>> sender.dst_port
-2345
->>> sender.msg
-'Hello there!'
->>> sender.count
-10
-
-# get all received msg by `recver` as list of tuples `(msg, (src_address, src_port))`
->>> recver.all_rx_msg
-[('Hello there!', ('fda4:38cf:5973:0:b899:3436:15c6:941d', 1234)), ...  ]
-```
-
-### Logs and Verbose mode
-
-Every `wpan.Node()` instance will save its corresponding `wpantund` logs. By default the logs are saved in a file `wpantun-log<node_index>.log`. By setting `wpan.Node__TUND_LOG_TO_FILE` to `False` the logs are written to `stdout` as the test-cases are executed.
-
-When `start.sh` script is used to run all test-cases, if any test fails, to help with debugging of the issue, the last 30 lines of `wpantund` logs of every node involved in the test-case is dumped to `stdout`.
-
-A `wpan.Node()` instance can also provide additional logs and info as the test-cases are run (verbose mode). It can be enabled for a node instance when it is created:
-
-```python
-    node = wpan.Node(verbose=True)     # `node` instance will provide extra logs.
-```
-
-Alternatively, `wpan.Node._VERBOSE` settings can be changed to enable verbose logging for all nodes. The default value of `wpan.Node._VERBOSE` is determined from environment variable `TORANJ_VERBOSE` (verbose mode is enabled when env variable is set to any of `1`, `True`, `Yes`, `Y`, `On` (case-insensitive)), otherwise it is disabled. When `TORANJ_VERBOSE` is enabled, the OpenThread logging is also enabled (and collected in `wpantund-log<node_index>.log`files) on all nodes.
-
-Here is example of small test script and its corresponding log output with `verbose` mode enabled:
-
-```python
-node1 = wpan.Node(verbose=True)
-node2 = wpan.Node(verbose=True)
-
-wpan.Node.init_all_nodes()
-
-node1.form("toranj-net")
-node2.active_scan()
-
-node2.join_node(node1)
-verify(node2.get(wpan.WPAN_STATE) == wpan.STATE_ASSOCIATED)
-
-lladdr1 = node1.get(wpan.WPAN_IP6_LINK_LOCAL_ADDRESS)[1:-1]
-lladdr2 = node2.get(wpan.WPAN_IP6_LINK_LOCAL_ADDRESS)[1:-1]
-
-sender = node1.prepare_tx(lladdr1, lladdr2, 20)
-recver = node2.prepare_rx(sender)
-
-wpan.Node.perform_async_tx_rx()
-
-```
-
-```
-$ Node1.__init__() cmd: /usr/local/sbin/wpantund -o Config:NCP:SocketPath "system:../../examples/apps/ncp/ot-ncp-ftd 1" -o Config:TUN:InterfaceName wpan1 -o Config:NCP:DriverName spinel -o Daemon:SyslogMask "all -debug"
-$ Node2.__init__() cmd: /usr/local/sbin/wpantund -o Config:NCP:SocketPath "system:../../examples/apps/ncp/ot-ncp-ftd 2" -o Config:TUN:InterfaceName wpan2 -o Config:NCP:DriverName spinel -o Daemon:SyslogMask "all -debug"
-$ Node1.wpanctl('leave') -> 'Leaving current WPAN. . .'
-$ Node2.wpanctl('leave') -> 'Leaving current WPAN. . .'
-$ Node1.wpanctl('form "toranj-net"'):
-     Forming WPAN "toranj-net" as node type "router"
-     Successfully formed!
-$ Node2.wpanctl('scan'):
-        | Joinable | NetworkName        | PAN ID | Ch | XPanID           | HWAddr           | RSSI
-     ---+----------+--------------------+--------+----+------------------+------------------+------
-      1 |       NO | "toranj-net"       | 0x9DEB | 16 | 8CC6CFC810F23E1B | BEECDAF3439DC931 |  -20
-$ Node1.wpanctl('get -v NCP:State') -> '"associated"'
-$ Node1.wpanctl('get -v Network:Name') -> '"toranj-net"'
-$ Node1.wpanctl('get -v Network:PANID') -> '0x9DEB'
-$ Node1.wpanctl('get -v Network:XPANID') -> '0x8CC6CFC810F23E1B'
-$ Node1.wpanctl('get -v Network:Key') -> '[BA2733A5D81EAB8FFB3C9A7383CB6045]'
-$ Node1.wpanctl('get -v NCP:Channel') -> '16'
-$ Node2.wpanctl('set Network:Key -d -v BA2733A5D81EAB8FFB3C9A7383CB6045') -> ''
-$ Node2.wpanctl('join "toranj-net" -c 16 -T r -p 0x9DEB -x 0x8CC6CFC810F23E1B'):
-     Joining "toranj-net" 8CC6CFC810F23E1B as node type "router"
-     Successfully Joined!
-$ Node2.wpanctl('get -v NCP:State') -> '"associated"'
-$ Node1.wpanctl('get -v IPv6:LinkLocalAddress') -> '"fe80::bcec:daf3:439d:c931"'
-$ Node2.wpanctl('get -v IPv6:LinkLocalAddress') -> '"fe80::ec08:f348:646f:d37d"'
-- Node1 sent 20 bytes (":YeQuNKjuOtd%H#ipM7P") to [fe80::ec08:f348:646f:d37d]:404 from [fe80::bcec:daf3:439d:c931]:12557
-- Node2 received 20 bytes (":YeQuNKjuOtd%H#ipM7P") on port 404 from [fe80::bcec:daf3:439d:c931]:12557
-
-```
+- [`toranj-cli` guide](README_CLI.md)
+- [`toranj-ncp` guide](README_NCP.md)
 
 ---
 
diff --git a/tests/toranj/README_CLI.md b/tests/toranj/README_CLI.md
new file mode 100644
index 0000000..024a321
--- /dev/null
+++ b/tests/toranj/README_CLI.md
@@ -0,0 +1,188 @@
+# `toranj-cli`
+
+`toranj-cli` is a test framework for OpenThread using its CLI interface.
+
+`toranj` features:
+
+- It is developed in Python.
+- It can be used to simulate multiple nodes forming complex network topologies.
+- It allows testing of network interactions between many nodes.
+- `toranj` in CLI mode runs `ot-cli-ftd` on simulation platform (real-time).
+
+## Setup
+
+To build OpenThread with `toranj` configuration, the `test/toranj/build.sh` script can be used:
+
+```bash
+$ ./tests/toranj/build.sh cmake
+====================================================================================================
+Building OpenThread (NCP/CLI for FTD/MTD/RCP mode) with simulation platform using cmake
+====================================================================================================
+-- OpenThread Source Directory: /Users/abtink/GitHub/openthread
+-- OpenThread CMake build type: Debug
+-- Package Name: OPENTHREAD
+...
+
+```
+
+Or to build using autoconf/make we can use:
+
+```bash
+$ ./tests/toranj/build.sh cli
+====================================================================================================
+Building OpenThread (NCP/CLI for FTD/MTD/RCP mode) with simulation platform using cmake
+====================================================================================================
+-- OpenThread Source Directory: /Users/abtink/GitHub/openthread
+-- OpenThread CMake build type: Debug
+-- Package Name: OPENTHREAD
+...
+
+```
+
+The `toranj-cli` tests are included in `tests/toranj/cli` folder. Each test-case has its own script following naming model `test-nnn-name.py` (e.g., `test-001-get-set.py`).
+
+To run a specific test:
+
+```bash
+$ cd tests/toranj/cli
+$ python3 test-001-get-set.py
+```
+
+To run all CLI tests, `start` script can be used. This script will build OpenThread with proper configuration options and starts running all tests.
+
+```bash
+# From OpenThread repo root folder
+$ top_builddir=($pwd) TORANJ_CLI=1 ./tests/toranj/start.sh
+```
+
+## `toranj-cli` Components
+
+`cli` python module defines the `toranj-cli` test components.
+
+### `cli.Node()` Class
+
+`cli.Node()` class creates a Thread node instance. It creates a sub-process to run `ot-cli-ftd` and provides methods to control the node and issue CLI commands.
+
+```python
+>>> import cli
+>>> node1 = cli.Node()
+>>> node1
+Node (index=1)
+>>> node2 = cli.Node()
+>>> node2
+Node (index=2)
+```
+
+Note: You may need to run as `sudo` to allow log file to be written (i.e., use `sudo python` or `sudo python3`).
+
+### `cli.Node` methods
+
+`cli.Node()` provides methods matching different CLI commands, in addition to some helper methods for common operations.
+
+Example:
+
+```python
+>>> node.get_state()
+'disabled'
+>>> node.get_channel()
+'11'
+>>> node.set_channel(12)
+>>> node.get_channel()
+'12'
+>>> node.set_network_key('11223344556677889900aabbccddeeff')
+>>> node.get_network_key()
+'11223344556677889900aabbccddeeff'
+```
+
+Common network operations:
+
+```python
+    # Form a Thread network with all the given parameters.
+    node.form(network_name=None, network_key=None, channel=None, panid=0x1234, xpanid=None):
+
+    # Try to join an existing network as specified by `another_node`.
+    # `type` can be `JOIN_TYPE_ROUTER`, `JOIN_TYPE_END_DEVICE, or `JOIN_TYPE_SLEEPY_END_DEVICE`
+    node.join(another_node, type=JOIN_TYPE_ROUTER):
+```
+
+A direct CLI command can be issued using `node.cli(command)` with a given `command` string.
+
+```python
+>>> node.cli('uptime')
+['00:36:18.778']
+```
+
+Method `allowlist_node()` can be used to add a given node to the allowlist of the device and enables allowlisting:
+
+```python
+    # `node2` is added to the allowlist of `node1` and allowlisting is enabled on `node1`
+    node1.allowlist_node(node2)
+```
+
+#### Example (simple 3-node topology)
+
+Script below shows how to create a 3-node network topology with `node1` and `node2` being routers, and `node3` an end-device connected to `node2`:
+
+```python
+>>> import cli
+>>> node1 = cli.Node()
+>>> node2 = cli.Node()
+>>> node3 = cli.Node()
+
+>>> node1.form('test')
+>>> node1.get_state()
+'leader'
+
+>>> node1.allowlist_node(node2)
+>>> node1.allowlist_node(node3)
+
+>>> node2.join(node1, cli.JOIN_TYPE_ROUTER)
+>>> node2.get_state()
+'router'
+
+>>> node3.join(node1, cli.JOIN_TYPE_END_DEVICE)
+>>> node3.get_state()
+'child'
+
+>>> node1.cli('neighbor list')
+['0x1c01 0x0400 ']
+```
+
+### Logs and Verbose mode
+
+Every `cli.Node()` instance will save its corresponding logs. By default the logs are saved in a file `ot-logs<node_index>.log`.
+
+When `start.sh` script is used to run all test-cases, if any test fails, to help with debugging of the issue, the last 30 lines of logs of every node involved in the test-case are dumped to `stdout`.
+
+A `cli.Node()` instance can also provide additional logs and info as the test-cases are run (verbose mode). It can be enabled for a node instance when it is created:
+
+```python
+>>> import cli
+>>> node = cli.Node(verbose=True)
+$ Node1.__init__() cmd: `../../../examples/apps/cli/ot-cli-ftd --time-speed=1 1`
+
+>>> node.get_state()
+$ Node1.cli('state') -> disabled
+'disabled'
+
+>>> node.form('test')
+$ Node1.cli('networkname test')
+$ Node1.cli('panid 4660')
+$ Node1.cli('ifconfig up')
+$ Node1.cli('thread start')
+$ Node1.cli('state') -> detached
+$ Node1.cli('state') -> detached
+...
+$ Node1.cli('state') -> leader
+```
+
+Alternatively, `cli.Node._VERBOSE` settings can be changed to enable verbose logging for all nodes. The default value of `cli.Node._VERBOSE` is determined from environment variable `TORANJ_VERBOSE` (verbose mode is enabled when env variable is set to any of `1`, `True`, `Yes`, `Y`, `On` (case-insensitive)), otherwise it is disabled.
+
+## `toranj-cli` and `thread-cert` test framework
+
+`toranj-cli` uses CLI commands to test the behavior of OpenThread with simulation platform. `thread-cert` scripts (in `tests/scripts/thread-cert`) also use CLI commands. However, these two test frameworks have certain differences and are intended for different situations. The `toranj` test cases run in real-time (though it is possible to run with a time speed-up factor) while the `thread-cert` scripts use virtual-time and event-based simulation model.
+
+- `toranj` test cases are useful to validate the real-time (non event-based) simulation platform implementation itself.
+- `toranj` test cases can be used in situations where the platform layer may not support event-based model.
+- `toranj` frameworks allows for more interactive testing (e.g., read–eval–print loop (REPL) model in python) and do not need a separate process to run to handle/dispatch events (which is required for the virtual-time simulation model).
+- `thread-cert` test cases can run quickly (due to virtual time emulation), but the test script itself needs to manage the flow and advancement of time.
diff --git a/tests/toranj/README_NCP.md b/tests/toranj/README_NCP.md
new file mode 100644
index 0000000..6262b7e
--- /dev/null
+++ b/tests/toranj/README_NCP.md
@@ -0,0 +1,369 @@
+# `toranj-ncp` test framework
+
+`toranj-ncp` is a test framework for OpenThread enabling testing of the combined behavior of OpenThread (in NCP mode), spinel interface, and `wpantund` driver on linux.
+
+`toranj` features:
+
+- It is developed in Python.
+- It can be used to simulate multiple nodes forming complex network topologies.
+- It allows testing of network interactions between many nodes (IPv6 traffic exchanges).
+- `toranj` in NCP mode runs `wpantund` natively with OpenThread in NCP mode on simulation platform (real-time).
+
+## Setup
+
+`toranj-ncp` requires `wpantund` to be installed.
+
+- Please follow [`wpantund` installation guide](https://github.com/openthread/wpantund/blob/master/INSTALL.md#wpantund-installation-guide). Note that `toranj` expects `wpantund` installed from latest master branch.
+- Alternative way to install `wpantund` is to use the same commands from git workflow [Simulation](https://github.com/openthread/openthread/blob/4b55284bd20f99a88e8e2c617ba358a0a5547f5d/.github/workflows/simulation.yml#L336-L341) for build target `toranj-test-framework`.
+
+To run all tests, `start` script can be used. This script will build OpenThread with proper configuration options and starts running all test.
+
+```bash
+    cd tests/toranj/    # from OpenThread repo root
+    TORANJ_CLI=0 ./start.sh
+```
+
+The `toranj-ncp` tests are included in `tests/toranj/ncp` folder. Each test-case has its own script following naming model `test-nnn-name.py` (e.g., `test-001-get-set.py`).
+
+To run a specific test
+
+```bash
+    sudo python ncp/test-001-get-set.py
+```
+
+## `toranj` Components
+
+`wpan` python module defines the `toranj` test components.
+
+### `wpan.Node()` Class
+
+`wpan.Node()` class creates a Thread node instance. It creates a sub-process to run `wpantund` and OpenThread, and provides methods to control the node.
+
+```python
+>>> import wpan
+>>> node1 = wpan.Node()
+>>> node1
+Node (index=1, interface_name=wpan1)
+>>> node2 = wpan.Node()
+>>> node2
+Node (index=2, interface_name=wpan2)
+```
+
+Note: You may need to run as `sudo` to allow `wpantund` to create tunnel interface (i.e., use `sudo python`).
+
+### `wpan.Node` methods providing `wpanctl` commands
+
+`wpan.Node()` provides methods matching all `wpanctl` commands.
+
+- Get the value of a `wpantund` property, set the value, or add/remove value to/from a list based property:
+
+```python
+    node.get(prop_name)
+    node.set(prop_name, value, binary_data=False)
+    node.add(prop_name, value, binary_data=False)
+    node.remove(prop_name, value, binary_data=False)
+```
+
+Example:
+
+```python
+>>> node.get(wpan.WPAN_NAME)
+'"test-network"'
+>>> node.set(wpan.WPAN_NAME, 'my-network')
+>>> node.get(wpan.WPAN_NAME)
+'"my-network"'
+>>> node.set(wpan.WPAN_KEY, '65F2C35C7B543BAC1F3E26BB9F866C1D', binary_data=True)
+>>> node.get(wpan.WPAN_KEY)
+'[65F2C35C7B543BAC1F3E26BB9F866C1D]'
+```
+
+- Common network operations:
+
+```python
+    node.reset()            # Reset the NCP
+    node.status()           # Get current status
+    node.leave()            # Leave the current network, clear all persistent data
+
+    # Form a network in given channel (if none given use a random one)
+    node.form(name, channel=None)
+
+    # Join a network with given info.
+    # node_type can be JOIN_TYPE_ROUTER, JOIN_TYPE_END_DEVICE, JOIN_TYPE_SLEEPY_END_DEVICE
+    node.join(name, channel=None, node_type=None, panid=None, xpanid=None)
+```
+
+Example:
+
+```python
+>>> result = node.status()
+>>> print result
+wpan1 => [
+    "NCP:State" => "offline"
+    "Daemon:Enabled" => true
+    "NCP:Version" => "OPENTHREAD/20170716-00460-ga438cef0c-dirty; NONE; Feb 12 2018 11:47:01"
+    "Daemon:Version" => "0.08.00d (0.07.01-191-g63265f7; Feb  2 2018 18:05:47)"
+    "Config:NCP:DriverName" => "spinel"
+    "NCP:HardwareAddress" => [18B4300000000001]
+]
+>>>
+>>> node.form("test-network", channel=12)
+'Forming WPAN "test-network" as node type "router"\nSuccessfully formed!'
+>>>
+>>> print node.status()
+wpan1 => [
+    "NCP:State" => "associated"
+    "Daemon:Enabled" => true
+    "NCP:Version" => "OPENTHREAD/20170716-00460-ga438cef0c-dirty; NONE; Feb 12 2018 11:47:01"
+    "Daemon:Version" => "0.08.00d (0.07.01-191-g63265f7; Feb  2 2018 18:05:47)"
+    "Config:NCP:DriverName" => "spinel"
+    "NCP:HardwareAddress" => [18B4300000000001]
+    "NCP:Channel" => 12
+    "Network:NodeType" => "leader"
+    "Network:Name" => "test-network"
+    "Network:XPANID" => 0xA438CF5973FD86B2
+    "Network:PANID" => 0x9D81
+    "IPv6:MeshLocalAddress" => "fda4:38cf:5973:0:b899:3436:15c6:941d"
+    "IPv6:MeshLocalPrefix" => "fda4:38cf:5973::/64"
+]
+```
+
+- Scan:
+
+```python
+    node.active_scan(channel=None)
+    node.energy_scan(channel=None)
+    node.discover_scan(channel=None, joiner_only=False, enable_filtering=False, panid_filter=None)
+    node.permit_join(duration_sec=None, port=None, udp=True, tcp=True)
+```
+
+- On-mesh prefixes and off-mesh routes:
+
+```python
+    node.config_gateway(prefix, default_route=False)
+    node.add_route(route_prefix, prefix_len_in_bytes=None, priority=None)
+    node.remove_route(route_prefix, prefix_len_in_bytes=None, priority=None)
+```
+
+A direct `wpanctl` command can be issued using `node.wpanctl(command)` with a given `command` string.
+
+`wpan` module provides variables for different `wpantund` properties. Some commonly used are:
+
+- Network/NCP properties: WPAN_STATE, WPAN_NAME, WPAN_PANID, WPAN_XPANID, WPAN_KEY, WPAN_CHANNEL, WPAN_HW_ADDRESS, WPAN_EXT_ADDRESS, WPAN_POLL_INTERVAL, WPAN_NODE_TYPE, WPAN_ROLE, WPAN_PARTITION_ID
+
+- IPv6 Addresses: WPAN_IP6_LINK_LOCAL_ADDRESS, WPAN_IP6_MESH_LOCAL_ADDRESS, WPAN_IP6_MESH_LOCAL_PREFIX, WPAN_IP6_ALL_ADDRESSES, WPAN_IP6_MULTICAST_ADDRESSES
+
+- Thread Properties: WPAN_THREAD_RLOC16, WPAN_THREAD_ROUTER_ID, WPAN_THREAD_LEADER_ADDRESS, WPAN_THREAD_LEADER_ROUTER_ID, WPAN_THREAD_LEADER_WEIGHT, WPAN_THREAD_LEADER_NETWORK_DATA,
+
+        WPAN_THREAD_CHILD_TABLE, WPAN_THREAD_CHILD_TABLE_ADDRESSES, WPAN_THREAD_NEIGHBOR_TABLE,
+        WPAN_THREAD_ROUTER_TABLE
+
+Method `join_node()` can be used by a node to join another node:
+
+```python
+    # `node1` joining `node2`'s network as a router
+    node1.join_node(node2, node_type=JOIN_TYPE_ROUTER)
+```
+
+Method `allowlist_node()` can be used to add a given node to the allowlist of the device and enables allowlisting:
+
+```python
+    # `node2` is added to the allowlist of `node1` and allowlisting is enabled on `node1`
+    node1.allowlist_node(node2)
+```
+
+#### Example (simple 3-node topology)
+
+Script below shows how to create a 3-node network topology with `node1` and `node2` being routers, and `node3` an end-device connected to `node2`:
+
+```python
+>>> import wpan
+>>> node1 = wpan.Node()
+>>> node2 = wpan.Node()
+>>> node3 = wpan.Node()
+
+>>> wpan.Node.init_all_nodes()
+
+>>> node1.form("test-PAN")
+'Forming WPAN "test-PAN" as node type "router"\nSuccessfully formed!'
+
+>>> node1.allowlist_node(node2)
+>>> node2.allowlist_node(node1)
+
+>>> node2.join_node(node1, wpan.JOIN_TYPE_ROUTER)
+'Joining "test-PAN" C474513CB487778D as node type "router"\nSuccessfully Joined!'
+
+>>> node3.allowlist_node(node2)
+>>> node2.allowlist_node(node3)
+
+>>> node3.join_node(node2, wpan.JOIN_TYPE_END_DEVICE)
+'Joining "test-PAN" C474513CB487778D as node type "end-device"\nSuccessfully Joined!'
+
+>>> print node2.get(wpan.WPAN_THREAD_NEIGHBOR_TABLE)
+[
+    "EAC1672C3EAB30A4, RLOC16:9401, LQIn:3, AveRssi:-20, LastRssi:-20, Age:30, LinkFC:6, MleFC:0, IsChild:yes, RxOnIdle:yes, FTD:yes, SecDataReq:yes, FullNetData:yes"
+    "A2042C8762576FD5, RLOC16:dc00, LQIn:3, AveRssi:-20, LastRssi:-20, Age:5, LinkFC:21, MleFC:18, IsChild:no, RxOnIdle:yes, FTD:yes, SecDataReq:no, FullNetData:yes"
+]
+>>> print node1.get(wpan.WPAN_THREAD_NEIGHBOR_TABLE)
+[
+    "960947C53415DAA1, RLOC16:9400, LQIn:3, AveRssi:-20, LastRssi:-20, Age:18, LinkFC:15, MleFC:11, IsChild:no, RxOnIdle:yes, FTD:yes, SecDataReq:no, FullNetData:yes"
+]
+
+```
+
+### IPv6 Message Exchange
+
+`toranj` allows a test-case to define traffic patterns (IPv6 message exchange) between different nodes. Message exchanges (tx/rx) are prepared and then an async rx/tx operation starts. The success and failure of tx/rx operations can then be verified by the test case.
+
+`wpan.Node` method `prepare_tx()` prepares a UDP6 transmission from a node.
+
+```python
+    node1.prepare_tx(src, dst, data, count)
+```
+
+- `src` and `dst` can be
+
+  - either a string containing an IPv6 address
+  - or a tuple (ipv6 address as string, port). if no port is given, a random port number is used.
+
+- `data` can be
+
+  - either a string containing the message to be sent,
+  - or an int indicating size of the message (a random message with the given length will be generated).
+
+- `count` gives number of times the message will be sent (default is 1).
+
+`prepare_tx` returns a `wpan.AsyncSender` object. The sender object can be used to check success/failure of tx operation.
+
+`wpan.Node` method `prepare_rx()` prepares a node to listen for UDP messages from a sender.
+
+```python
+    node2.prepare_rx(sender)
+```
+
+- `sender` should be an `wpan.AsyncSender` object returned from previous `prepare_tx`.
+- `prepare_rx()` returns a `wpan.AsyncReceiver` object to help test to check success/failure of rx operation.
+
+After all exchanges are prepared, static method `perform_async_tx_rx()` should be used to start all previously prepared rx and tx operations.
+
+```python
+    wpan.Node.perform_async_tx_rx(timeout)
+```
+
+- `timeout` gives amount of time (in seconds) to wait for all operations to finish. (default is 20 seconds)
+
+After `perform_async_tx_rx()` is done, the `AsyncSender` and `AsyncReceiver` objects can check if operations were successful (using property `was_successful`)
+
+#### Example
+
+Sending 10 messages containing `"Hello there!"` from `node1` to `node2` using their mesh-local addresses:
+
+```python
+# `node1` and `node2` are already joined and are part of the same Thread network.
+
+# Get the mesh local addresses
+>>> mladdr1 = node1.get(wpan.WPAN_IP6_MESH_LOCAL_ADDRESS)[1:-1]  # remove `"` from start/end of string
+>>> mladdr2 = node2.get(wpan.WPAN_IP6_MESH_LOCAL_ADDRESS)[1:-1]
+
+>>> print (mladdr1, mladdr2)
+('fda4:38cf:5973:0:b899:3436:15c6:941d', 'fda4:38cf:5973:0:5836:fa55:7394:6d4b')
+
+# prepare a `sender` and corresponding `recver`
+>>> sender = node1.prepare_tx((mladdr1, 1234), (mladdr2, 2345), "Hello there!", 10)
+>>> recver = node2.prepare_rx(sender)
+
+# perform async message transfer
+>>> wpan.Node.perform_async_tx_rx()
+
+# check status of `sender` and `recver`
+>>> sender.was_successful
+True
+>>> recver.was_successful
+True
+
+# `sender` or `recver` can provide info about the exchange
+
+>>> sender.src_addr
+'fda4:38cf:5973:0:b899:3436:15c6:941d'
+>>> sender.src_port
+1234
+>>> sender.dst_addr
+'fda4:38cf:5973:0:5836:fa55:7394:6d4b'
+>>> sender.dst_port
+2345
+>>> sender.msg
+'Hello there!'
+>>> sender.count
+10
+
+# get all received msg by `recver` as list of tuples `(msg, (src_address, src_port))`
+>>> recver.all_rx_msg
+[('Hello there!', ('fda4:38cf:5973:0:b899:3436:15c6:941d', 1234)), ...  ]
+```
+
+### Logs and Verbose mode
+
+Every `wpan.Node()` instance will save its corresponding `wpantund` logs. By default the logs are saved in a file `wpantun-log<node_index>.log`. By setting `wpan.Node__TUND_LOG_TO_FILE` to `False` the logs are written to `stdout` as the test-cases are executed.
+
+When `start.sh` script is used to run all test-cases, if any test fails, to help with debugging of the issue, the last 30 lines of `wpantund` logs of every node involved in the test-case is dumped to `stdout`.
+
+A `wpan.Node()` instance can also provide additional logs and info as the test-cases are run (verbose mode). It can be enabled for a node instance when it is created:
+
+```python
+    node = wpan.Node(verbose=True)     # `node` instance will provide extra logs.
+```
+
+Alternatively, `wpan.Node._VERBOSE` settings can be changed to enable verbose logging for all nodes. The default value of `wpan.Node._VERBOSE` is determined from environment variable `TORANJ_VERBOSE` (verbose mode is enabled when env variable is set to any of `1`, `True`, `Yes`, `Y`, `On` (case-insensitive)), otherwise it is disabled. When `TORANJ_VERBOSE` is enabled, the OpenThread logging is also enabled (and collected in `wpantund-log<node_index>.log`files) on all nodes.
+
+Here is example of small test script and its corresponding log output with `verbose` mode enabled:
+
+```python
+node1 = wpan.Node(verbose=True)
+node2 = wpan.Node(verbose=True)
+
+wpan.Node.init_all_nodes()
+
+node1.form("toranj-net")
+node2.active_scan()
+
+node2.join_node(node1)
+verify(node2.get(wpan.WPAN_STATE) == wpan.STATE_ASSOCIATED)
+
+lladdr1 = node1.get(wpan.WPAN_IP6_LINK_LOCAL_ADDRESS)[1:-1]
+lladdr2 = node2.get(wpan.WPAN_IP6_LINK_LOCAL_ADDRESS)[1:-1]
+
+sender = node1.prepare_tx(lladdr1, lladdr2, 20)
+recver = node2.prepare_rx(sender)
+
+wpan.Node.perform_async_tx_rx()
+
+```
+
+```
+$ Node1.__init__() cmd: /usr/local/sbin/wpantund -o Config:NCP:SocketPath "system:../../examples/apps/ncp/ot-ncp-ftd 1" -o Config:TUN:InterfaceName wpan1 -o Config:NCP:DriverName spinel -o Daemon:SyslogMask "all -debug"
+$ Node2.__init__() cmd: /usr/local/sbin/wpantund -o Config:NCP:SocketPath "system:../../examples/apps/ncp/ot-ncp-ftd 2" -o Config:TUN:InterfaceName wpan2 -o Config:NCP:DriverName spinel -o Daemon:SyslogMask "all -debug"
+$ Node1.wpanctl('leave') -> 'Leaving current WPAN. . .'
+$ Node2.wpanctl('leave') -> 'Leaving current WPAN. . .'
+$ Node1.wpanctl('form "toranj-net"'):
+     Forming WPAN "toranj-net" as node type "router"
+     Successfully formed!
+$ Node2.wpanctl('scan'):
+        | PAN ID | Ch | XPanID           | HWAddr           | RSSI
+     ---+--------+----+------------------+------------------+------
+      1 | 0x9DEB | 16 | 8CC6CFC810F23E1B | BEECDAF3439DC931 |  -20
+$ Node1.wpanctl('get -v NCP:State') -> '"associated"'
+$ Node1.wpanctl('get -v Network:Name') -> '"toranj-net"'
+$ Node1.wpanctl('get -v Network:PANID') -> '0x9DEB'
+$ Node1.wpanctl('get -v Network:XPANID') -> '0x8CC6CFC810F23E1B'
+$ Node1.wpanctl('get -v Network:Key') -> '[BA2733A5D81EAB8FFB3C9A7383CB6045]'
+$ Node1.wpanctl('get -v NCP:Channel') -> '16'
+$ Node2.wpanctl('set Network:Key -d -v BA2733A5D81EAB8FFB3C9A7383CB6045') -> ''
+$ Node2.wpanctl('join "toranj-net" -c 16 -T r -p 0x9DEB -x 0x8CC6CFC810F23E1B'):
+     Joining "toranj-net" 8CC6CFC810F23E1B as node type "router"
+     Successfully Joined!
+$ Node2.wpanctl('get -v NCP:State') -> '"associated"'
+$ Node1.wpanctl('get -v IPv6:LinkLocalAddress') -> '"fe80::bcec:daf3:439d:c931"'
+$ Node2.wpanctl('get -v IPv6:LinkLocalAddress') -> '"fe80::ec08:f348:646f:d37d"'
+- Node1 sent 20 bytes (":YeQuNKjuOtd%H#ipM7P") to [fe80::ec08:f348:646f:d37d]:404 from [fe80::bcec:daf3:439d:c931]:12557
+- Node2 received 20 bytes (":YeQuNKjuOtd%H#ipM7P") on port 404 from [fe80::bcec:daf3:439d:c931]:12557
+
+```
diff --git a/tests/toranj/build.sh b/tests/toranj/build.sh
index adcb71c..4c25b1a 100755
--- a/tests/toranj/build.sh
+++ b/tests/toranj/build.sh
@@ -38,6 +38,10 @@
     echo "        ncp-15.4        : Build OpenThread NCP FTD mode with simulation platform - 15.4 radio"
     echo "        ncp-trel        : Build OpenThread NCP FTD mode with simulation platform - TREL radio "
     echo "        ncp-15.4+trel   : Build OpenThread NCP FTD mode with simulation platform - multi radio (15.4+TREL)"
+    echo "        cli             : Build OpenThread CLI FTD mode with simulation platform"
+    echo "        cli-15.4        : Build OpenThread CLI FTD mode with simulation platform - 15.4 radio"
+    echo "        cli-trel        : Build OpenThread CLI FTD mode with simulation platform - TREL radio "
+    echo "        cli-15.4+trel   : Build OpenThread CLI FTD mode with simulation platform - multi radio (15.4+TREL)"
     echo "        rcp             : Build OpenThread RCP (NCP in radio mode) with simulation platform"
     echo "        posix           : Build OpenThread POSIX NCP"
     echo "        posix-15.4      : Build OpenThread POSIX NCP - 15.4 radio"
@@ -92,7 +96,7 @@
 
 build_config=$1
 
-configure_options=(
+ncp_configure_options=(
     "--disable-docs"
     "--enable-tests=$tests"
     "--enable-coverage=$coverage"
@@ -100,6 +104,14 @@
     "--enable-ncp"
 )
 
+cli_configure_options=(
+    "--disable-docs"
+    "--enable-tests=$tests"
+    "--enable-coverage=$coverage"
+    "--enable-ftd"
+    "--enable-cli"
+)
+
 posix_configure_options=(
     "--disable-docs"
     "--enable-tests=$tests"
@@ -127,7 +139,7 @@
         ${top_srcdir}/configure \
             CPPFLAGS="$cppflags_config" \
             --with-examples=simulation \
-            "${configure_options[@]}" || die
+            "${ncp_configure_options[@]}" || die
         make -j 8 || die
         ;;
 
@@ -143,7 +155,7 @@
         ${top_srcdir}/configure \
             CPPFLAGS="$cppflags_config" \
             --with-examples=simulation \
-            "${configure_options[@]}" || die
+            "${ncp_configure_options[@]}" || die
         make -j 8 || die
         cp -p ${top_builddir}/examples/apps/ncp/ot-ncp-ftd ${top_builddir}/examples/apps/ncp/ot-ncp-ftd-15.4
         ;;
@@ -160,7 +172,7 @@
         ${top_srcdir}/configure \
             CPPFLAGS="$cppflags_config" \
             --with-examples=simulation \
-            "${configure_options[@]}" || die
+            "${ncp_configure_options[@]}" || die
         make -j 8 || die
         cp -p ${top_builddir}/examples/apps/ncp/ot-ncp-ftd ${top_builddir}/examples/apps/ncp/ot-ncp-ftd-trel
         ;;
@@ -177,11 +189,76 @@
         ${top_srcdir}/configure \
             CPPFLAGS="$cppflags_config" \
             --with-examples=simulation \
-            "${configure_options[@]}" || die
+            "${ncp_configure_options[@]}" || die
         make -j 8 || die
         cp -p ${top_builddir}/examples/apps/ncp/ot-ncp-ftd ${top_builddir}/examples/apps/ncp/ot-ncp-ftd-15.4-trel
         ;;
 
+    cli | cli-)
+        echo "==================================================================================================="
+        echo "Building OpenThread CLI FTD mode with simulation platform (radios determined by config)"
+        echo "==================================================================================================="
+        ./bootstrap || die "bootstrap failed"
+        cd "${top_builddir}" || die "cd failed"
+        cppflags_config='-DOPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"../tests/toranj/openthread-core-toranj-config-simulation.h\"'
+        ${top_srcdir}/configure \
+            CPPFLAGS="$cppflags_config" \
+            --with-examples=simulation \
+            "${cli_configure_options[@]}" || die
+        make -j 8 || die
+        ;;
+
+    cli-15.4)
+        echo "==================================================================================================="
+        echo "Building OpenThread CLI FTD mode with simulation platform - 15.4 radio"
+        echo "==================================================================================================="
+        cppflags_config='-DOPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"../tests/toranj/openthread-core-toranj-config-simulation.h\"'
+        cppflags_config="${cppflags_config} -DOPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE=1"
+        cppflags_config="${cppflags_config} -DOPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE=0"
+        ./bootstrap || die "bootstrap failed"
+        cd "${top_builddir}" || die "cd failed"
+        ${top_srcdir}/configure \
+            CPPFLAGS="$cppflags_config" \
+            --with-examples=simulation \
+            "${cli_configure_options[@]}" || die
+        make -j 8 || die
+        cp -p ${top_builddir}/examples/apps/cli/ot-cli-ftd ${top_builddir}/examples/apps/cli/ot-cli-ftd-15.4
+        ;;
+
+    cli-trel)
+        echo "==================================================================================================="
+        echo "Building OpenThread CLI FTD mode with simulation platform - TREL radio"
+        echo "==================================================================================================="
+        cppflags_config='-DOPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"../tests/toranj/openthread-core-toranj-config-simulation.h\"'
+        cppflags_config="${cppflags_config} -DOPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE=0"
+        cppflags_config="${cppflags_config} -DOPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE=1"
+        ./bootstrap || die "bootstrap failed"
+        cd "${top_builddir}" || die "cd failed"
+        ${top_srcdir}/configure \
+            CPPFLAGS="$cppflags_config" \
+            --with-examples=simulation \
+            "${cli_configure_options[@]}" || die
+        make -j 8 || die
+        cp -p ${top_builddir}/examples/apps/cli/ot-cli-ftd ${top_builddir}/examples/apps/cli/ot-cli-ftd-trel
+        ;;
+
+    cli-15.4+trel | cli-trel+15.4)
+        echo "==================================================================================================="
+        echo "Building OpenThread NCP FTD mode with simulation platform - multi radio (15.4 + TREL)"
+        echo "==================================================================================================="
+        cppflags_config='-DOPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"../tests/toranj/openthread-core-toranj-config-simulation.h\"'
+        cppflags_config="${cppflags_config} -DOPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE=1"
+        cppflags_config="${cppflags_config} -DOPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE=1"
+        ./bootstrap || die "bootstrap failed"
+        cd "${top_builddir}" || die "cd failed"
+        ${top_srcdir}/configure \
+            CPPFLAGS="$cppflags_config" \
+            --with-examples=simulation \
+            "${cli_configure_options[@]}" || die
+        make -j 8 || die
+        cp -p ${top_builddir}/examples/apps/cli/ot-cli-ftd ${top_builddir}/examples/apps/cli/ot-cli-ftd-15.4-trel
+        ;;
+
     rcp)
         echo "===================================================================================================="
         echo "Building OpenThread RCP (NCP in radio mode) with simulation platform"
diff --git a/tests/toranj/cli/cli.py b/tests/toranj/cli/cli.py
new file mode 100644
index 0000000..3bfb7a8
--- /dev/null
+++ b/tests/toranj/cli/cli.py
@@ -0,0 +1,634 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2021, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+import sys
+import os
+import time
+import re
+import random
+import string
+import subprocess
+import pexpect
+import pexpect.popen_spawn
+import signal
+import inspect
+import weakref
+
+# ----------------------------------------------------------------------------------------------------------------------
+# Constants
+
+JOIN_TYPE_ROUTER = 'router'
+JOIN_TYPE_END_DEVICE = 'ed'
+JOIN_TYPE_SLEEPY_END_DEVICE = 'sed'
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+
+def _log(text, new_line=True, flush=True):
+    sys.stdout.write(text)
+    if new_line:
+        sys.stdout.write('\n')
+    if flush:
+        sys.stdout.flush()
+
+
+# ----------------------------------------------------------------------------------------------------------------------
+# CliError class
+
+
+class CliError(Exception):
+
+    def __init__(self, error_code, message):
+        self._error_code = error_code
+        self._message = message
+
+    @property
+    def error_code(self):
+        return self._error_code
+
+    @property
+    def message(self):
+        return self._message
+
+
+# ----------------------------------------------------------------------------------------------------------------------
+# Node class
+
+
+class Node(object):
+    """ An OT CLI instance """
+
+    # defines the default verbosity setting (can be changed per `Node`)
+    _VERBOSE = os.getenv('TORANJ_VERBOSE', 'no').lower() in ['true', '1', 't', 'y', 'yes', 'on']
+
+    _SPEED_UP_FACTOR = 1  # defines the default time speed up factor
+
+    # Determine whether to save logs in a file.
+    _SAVE_LOGS = True
+
+    # name of  log file (if _SAVE_LOGS is `True`)
+    _LOG_FNAME = 'ot-logs'
+
+    _OT_BUILDDIR = os.getenv('top_builddir', '../../..')
+
+    _OT_CLI_FTD = '%s/examples/apps/cli/ot-cli-ftd' % _OT_BUILDDIR
+
+    _WAIT_TIME = 10
+
+    _START_INDEX = 1
+    _cur_index = _START_INDEX
+
+    _all_nodes = weakref.WeakSet()
+
+    def __init__(self, verbose=_VERBOSE):
+        """Creates a new `Node` instance"""
+
+        index = Node._cur_index
+        Node._cur_index += 1
+
+        self._index = index
+        self._verbose = verbose
+
+        if Node._SAVE_LOGS:
+            self._log_file = open(self._LOG_FNAME + str(index) + '.log', 'wb')
+        else:
+            self._log_file = None
+
+        cmd = f'{self._OT_CLI_FTD} --time-speed={self._SPEED_UP_FACTOR} {self._index}'
+
+        if self._verbose:
+            _log(f'$ Node{index}.__init__() cmd: `{cmd}`')
+
+        self._cli_process = pexpect.popen_spawn.PopenSpawn(cmd, logfile=self._log_file)
+        Node._all_nodes.add(self)
+
+    def __del__(self):
+        self._finalize()
+
+    def __repr__(self):
+        return f'Node(index={self._index})'
+
+    @property
+    def index(self):
+        return self._index
+
+    # ------------------------------------------------------------------------------------------------------------------
+    # Executing a `cli` command
+
+    def cli(self, *args):
+        """ Issues a CLI command on the given node and returns the resulting output.
+
+            The returned result is a list of strings (with `\r\n` removed) as outputted by the CLI.
+            If executing the command fails, `CliError` is raised with error code and error message.
+        """
+
+        cmd = ' '.join([f'{arg}' for arg in args if arg is not None]).strip()
+
+        if self._verbose:
+            _log(f'$ Node{self._index}.cli(\'{cmd}\')', new_line=False)
+
+        self._cli_process.send(cmd + '\n')
+        index = self._cli_process.expect(['(.*)Done\r\n', '.*Error (\d+):(.*)\r\n'])
+
+        if index == 0:
+            result = [
+                line for line in self._cli_process.match.group(1).decode().splitlines()
+                if not self._is_ot_logg_line(line) if not line.strip().endswith(cmd)
+            ]
+
+            if self._verbose:
+                if len(result) > 1:
+                    _log(':')
+                    for line in result:
+                        _log('     ' + line)
+                elif len(result) == 1:
+                    _log(f' -> {result[0]}')
+                else:
+                    _log('')
+
+            return result
+        else:
+            match = self._cli_process.match
+            e = CliError(int(match.group(1).decode()), match.group(2).decode().strip())
+            if self._verbose:
+                _log(f': Error {e.message} ({e.error_code})')
+            raise e
+
+    def _is_ot_logg_line(self, line):
+        return any(level in line for level in [' [D] ', ' [I] ', ' [N] ', ' [W] ', ' [C] ', ' [-] '])
+
+    def _cli_no_output(self, cmd, *args):
+        outputs = self.cli(cmd, *args)
+        verify(len(outputs) == 0)
+
+    def _cli_single_output(self, cmd, expected_outputs=None):
+        outputs = self.cli(cmd)
+        verify(len(outputs) == 1)
+        verify((expected_outputs is None) or (outputs[0] in expected_outputs))
+        return outputs[0]
+
+    def _finalize(self):
+        if self._cli_process.proc.poll() is None:
+            if self._verbose:
+                _log(f'$ Node{self.index} terminating')
+            self._cli_process.send('exit\n')
+            self._cli_process.wait()
+
+    # ------------------------------------------------------------------------------------------------------------------
+    # cli commands
+
+    def get_state(self):
+        return self._cli_single_output('state', ['detached', 'child', 'router', 'leader', 'disabled'])
+
+    def get_channel(self):
+        return self._cli_single_output('channel')
+
+    def set_channel(self, channel):
+        self._cli_no_output('channel', channel)
+
+    def get_ext_addr(self):
+        return self._cli_single_output('extaddr')
+
+    def set_ext_addr(self, ext_addr):
+        self._cli_no_output('extaddr', ext_addr)
+
+    def get_ext_panid(self):
+        return self._cli_single_output('extpanid')
+
+    def set_ext_panid(self, ext_panid):
+        self._cli_no_output('extpanid', ext_panid)
+
+    def get_mode(self):
+        return self._cli_single_output('mode')
+
+    def set_mode(self, mode):
+        self._cli_no_output('mode', mode)
+
+    def get_network_key(self):
+        return self._cli_single_output('networkkey')
+
+    def set_network_key(self, networkkey):
+        self._cli_no_output('networkkey', networkkey)
+
+    def get_network_name(self):
+        return self._cli_single_output('networkname')
+
+    def set_network_name(self, network_name):
+        self._cli_no_output('networkname', network_name)
+
+    def get_panid(self):
+        return self._cli_single_output('panid')
+
+    def set_panid(self, panid):
+        self._cli_no_output('panid', panid)
+
+    def get_router_upgrade_threshold(self):
+        return self._cli_single_output('routerupgradethreshold')
+
+    def set_router_upgrade_threshold(self, threshold):
+        self._cli_no_output('routerupgradethreshold', threshold)
+
+    def get_router_selection_jitter(self):
+        return self._cli_single_output('routerselectionjitter')
+
+    def set_router_selection_jitter(self, jitter):
+        self._cli_no_output('routerselectionjitter', jitter)
+
+    def interface_up(self):
+        self._cli_no_output('ifconfig up')
+
+    def interface_down(self):
+        self._cli_no_output('ifconfig down')
+
+    def get_interface_state(self):
+        return self._cli_single_output('ifconfig')
+
+    def thread_start(self):
+        self._cli_no_output('thread start')
+
+    def thread_stop(self):
+        self._cli_no_output('thread stop')
+
+    def get_ip_addrs(self):
+        return self.cli('ipaddr')
+
+    def get_mleid_ip_addr(self):
+        return self._cli_single_output('ipaddr mleid')
+
+    def get_linklocal_ip_addr(self):
+        return self._cli_single_output('ipaddr linklocal')
+
+    def get_rloc_ip_addr(self):
+        return self._cli_single_output('ipaddr rloc')
+
+    #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    # SRP client
+
+    def srp_client_start(self, server_address, server_port):
+        self._cli_no_output('srp client start', server_address, server_port)
+
+    def srp_client_stop(self):
+        self._cli_no_output('srp client stop')
+
+    def srp_client_get_state(self):
+        return self._cli_single_output('srp client state', ['Enabled', 'Disabled'])
+
+    def srp_client_get_auto_start_mode(self):
+        return self._cli_single_output('srp client autostart', ['Enabled', 'Disabled'])
+
+    def srp_client_enable_auto_start_mode(self):
+        self._cli_no_output('srp client autostart enable')
+
+    def srp_client_disable_auto_start_mode(self):
+        self._cli_no_output('srp client autostart disable')
+
+    def srp_client_get_server_address(self):
+        return self._cli_single_output('srp client server address')
+
+    def srp_client_get_server_port(self):
+        return self._cli_single_output('srp client server port')
+
+    def srp_client_get_host_state(self):
+        return self._cli_single_output('srp client host state')
+
+    def srp_client_set_host_name(self, name):
+        self._cli_no_output('srp client host name', name)
+
+    def srp_client_get_host_name(self):
+        return self._cli_single_output('srp client host name')
+
+    def srp_client_remove_host(self, remove_key=False, send_unreg_to_server=False):
+        self._cli_no_output('srp client host remove', int(remove_key), int(send_unreg_to_server))
+
+    def srp_client_clear_host(self):
+        self._cli_no_output('srp client host clear')
+
+    def srp_client_enable_auto_host_address(self):
+        self._cli_no_output('srp client host address auto')
+
+    def srp_client_set_host_address(self, *addrs):
+        self._cli_no_output('srp client host address', *addrs)
+
+    def srp_client_get_host_address(self):
+        return self.cli('srp client host address')
+
+    def srp_client_add_service(self, instance_name, service_name, port, priority=0, weight=0, txt_entries=[]):
+        txt_record = "".join(self._encode_txt_entry(entry) for entry in txt_entries)
+        self._cli_no_output('srp client service add', instance_name, service_name, port, priority, weight, txt_record)
+
+    def srp_client_remove_service(self, instance_name, service_name):
+        self._cli_no_output('srp client service remove', instance_name, service_name)
+
+    def srp_client_clear_service(self, instance_name, service_name):
+        self._cli_no_output('srp client service clear', instance_name, service_name)
+
+    def srp_client_get_services(self):
+        outputs = self.cli('srp client service')
+        return [self._parse_srp_client_service(line) for line in outputs]
+
+    def _encode_txt_entry(self, entry):
+        """Encodes the TXT entry to the DNS-SD TXT record format as a HEX string.
+
+           Example usage:
+           self._encode_txt_entries(['abc'])     -> '03616263'
+           self._encode_txt_entries(['def='])    -> '046465663d'
+           self._encode_txt_entries(['xyz=XYZ']) -> '0778797a3d58595a'
+        """
+        return '{:02x}'.format(len(entry)) + "".join("{:02x}".format(ord(c)) for c in entry)
+
+    def _parse_srp_client_service(self, line):
+        """Parse one line of srp service list into a dictionary which
+           maps string keys to string values.
+
+           Example output for input
+           'instance:\"%s\", name:\"%s\", state:%s, port:%d, priority:%d, weight:%d"'
+           {
+               'instance': 'my-service',
+               'name': '_ipps._udp',
+               'state': 'ToAdd',
+               'port': '12345',
+               'priority': '0',
+               'weight': '0'
+           }
+
+           Note that value of 'port', 'priority' and 'weight' are represented
+           as strings but not integers.
+        """
+        key_values = [word.strip().split(':') for word in line.split(', ')]
+        return {key_value[0].strip(): key_value[1].strip('"') for key_value in key_values}
+
+    #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    # SRP server
+
+    def srp_server_get_state(self):
+        return self._cli_single_output('srp server state', ['disabled', 'running', 'stopped'])
+
+    def srp_server_get_addr_mode(self):
+        return self._cli_single_output('srp server addrmode', ['unicast', 'anycast'])
+
+    def srp_server_set_addr_mode(self, mode):
+        self._cli_no_output('srp server addrmode', mode)
+
+    def srp_server_get_anycast_seq_num(self):
+        return self._cli_single_output('srp server seqnum')
+
+    def srp_server_set_anycast_seq_num(self, seqnum):
+        self._cli_no_output('srp server seqnum', seqnum)
+
+    def srp_server_enable(self):
+        self._cli_no_output('srp server enable')
+
+    def srp_server_disable(self):
+        self._cli_no_output('srp server disable')
+
+    def srp_server_set_lease(self, min_lease, max_lease, min_key_lease, max_key_lease):
+        self._cli_no_output('srp server lease', min_lease, max_lease, min_key_lease, max_key_lease)
+
+    def srp_server_get_hosts(self):
+        """Returns the host list on the SRP server as a list of property
+           dictionary.
+
+           Example output:
+           [{
+               'fullname': 'my-host.default.service.arpa.',
+               'name': 'my-host',
+               'deleted': 'false',
+               'addresses': ['2001::1', '2001::2']
+           }]
+        """
+        outputs = self.cli('srp server host')
+        host_list = []
+        while outputs:
+            host = {}
+            host['fullname'] = outputs.pop(0).strip()
+            host['name'] = host['fullname'].split('.')[0]
+            host['deleted'] = outputs.pop(0).strip().split(':')[1].strip()
+            if host['deleted'] == 'true':
+                host_list.append(host)
+                continue
+            addresses = outputs.pop(0).strip().split('[')[1].strip(' ]').split(',')
+            map(str.strip, addresses)
+            host['addresses'] = [addr for addr in addresses if addr]
+            host_list.append(host)
+        return host_list
+
+    def srp_server_get_host(self, host_name):
+        """Returns host on the SRP server that matches given host name.
+
+           Example usage:
+           self.srp_server_get_host("my-host")
+        """
+        for host in self.srp_server_get_hosts():
+            if host_name == host['name']:
+                return host
+
+    def srp_server_get_services(self):
+        """Returns the service list on the SRP server as a list of property
+           dictionary.
+
+           Example output:
+           [{
+               'fullname': 'my-service._ipps._tcp.default.service.arpa.',
+               'instance': 'my-service',
+               'name': '_ipps._tcp',
+               'deleted': 'false',
+               'port': '12345',
+               'priority': '0',
+               'weight': '0',
+               'ttl': '7200',
+               'TXT': ['abc=010203'],
+               'host_fullname': 'my-host.default.service.arpa.',
+               'host': 'my-host',
+               'addresses': ['2001::1', '2001::2']
+           }]
+
+           Note that the TXT data is output as a HEX string.
+        """
+        outputs = self.cli('srp server service')
+        service_list = []
+        while outputs:
+            service = {}
+            service['fullname'] = outputs.pop(0).strip()
+            name_labels = service['fullname'].split('.')
+            service['instance'] = name_labels[0]
+            service['name'] = '.'.join(name_labels[1:3])
+            service['deleted'] = outputs.pop(0).strip().split(':')[1].strip()
+            if service['deleted'] == 'true':
+                service_list.append(service)
+                continue
+            # 'subtypes', port', 'priority', 'weight', 'ttl'
+            for i in range(0, 5):
+                key_value = outputs.pop(0).strip().split(':')
+                service[key_value[0].strip()] = key_value[1].strip()
+            txt_entries = outputs.pop(0).strip().split('[')[1].strip(' ]').split(',')
+            txt_entries = map(str.strip, txt_entries)
+            service['TXT'] = [txt for txt in txt_entries if txt]
+            service['host_fullname'] = outputs.pop(0).strip().split(':')[1].strip()
+            service['host'] = service['host_fullname'].split('.')[0]
+            addresses = outputs.pop(0).strip().split('[')[1].strip(' ]').split(',')
+            addresses = map(str.strip, addresses)
+            service['addresses'] = [addr for addr in addresses if addr]
+            service_list.append(service)
+        return service_list
+
+    def srp_server_get_service(self, instance_name, service_name):
+        """Returns service on the SRP server that matches given instance
+           name and service name.
+
+           Example usage:
+           self.srp_server_get_service("my-service", "_ipps._tcp")
+        """
+        for service in self.srp_server_get_services():
+            if (instance_name == service['instance'] and service_name == service['name']):
+                return service
+
+    # ------------------------------------------------------------------------------------------------------------------
+    # Helper methods
+
+    def form(self, network_name=None, network_key=None, channel=None, panid=0x1234, xpanid=None):
+        if network_name is not None:
+            self.set_network_name(network_name)
+        if network_key is not None:
+            self.set_network_key(network_key)
+        if channel is not None:
+            self.set_channel(channel)
+        if xpanid is not None:
+            self.set_ext_panid(xpanid)
+        self.set_panid(panid)
+        self.interface_up()
+        self.thread_start()
+        verify_within(_check_node_is_leader, self._WAIT_TIME, arg=self)
+
+    def join(self, node, type=JOIN_TYPE_ROUTER):
+        self.set_network_name(node.get_network_name())
+        self.set_network_key(node.get_network_key())
+        self.set_channel(node.get_channel())
+        self.set_panid(node.get_panid())
+        if type == JOIN_TYPE_END_DEVICE:
+            self.set_mode('rn')
+        elif type == JOIN_TYPE_SLEEPY_END_DEVICE:
+            self.set_mode('-')
+        else:
+            self.set_mode('rdn')
+            self.set_router_selection_jitter(1)
+        self.interface_up()
+        self.thread_start()
+        if type == JOIN_TYPE_ROUTER:
+            verify_within(_check_node_is_router, self._WAIT_TIME, arg=self)
+        else:
+            verify_within(_check_node_is_child, self._WAIT_TIME, arg=self)
+
+    def allowlist_node(self, node):
+        """Adds a given node to the allowlist of `self` and enables allowlisting on `self`"""
+        self._cli_no_output('macfilter addr add', node.get_ext_addr())
+        self._cli_no_output('macfilter addr allowlist')
+
+    def un_allowlist_node(self, node):
+        """Removes a given node (of node `Node) from the allowlist"""
+        self._cli_no_output('macfilter addr remove', node.get_ext_addr())
+
+    # ------------------------------------------------------------------------------------------------------------------
+    # class methods
+
+    @classmethod
+    def finalize_all_nodes(cls):
+        """Finalizes all previously created `Node` instances (stops the CLI process)"""
+        for node in Node._all_nodes:
+            node._finalize()
+
+    @classmethod
+    def set_time_speedup_factor(cls, factor):
+        """Sets up the time speed up factor - should be set before creating any `Node` objects"""
+        if len(Node._all_nodes) != 0:
+            raise Node._NodeError('set_time_speedup_factor() cannot be called after creating a `Node`')
+        Node._SPEED_UP_FACTOR = factor
+
+
+def _check_node_is_leader(node):
+    verify(node.get_state() == 'leader')
+
+
+def _check_node_is_router(node):
+    verify(node.get_state() == 'router')
+
+
+def _check_node_is_child(node):
+    verify(node.get_state() == 'child')
+
+
+# ----------------------------------------------------------------------------------------------------------------------
+
+
+class VerifyError(Exception):
+    pass
+
+
+_is_in_verify_within = False
+
+
+def verify(condition):
+    """Verifies that a `condition` is true, otherwise raises a VerifyError"""
+    global _is_in_verify_within
+    if not condition:
+        calling_frame = inspect.currentframe().f_back
+        error_message = 'verify() failed at line {} in "{}"'.format(calling_frame.f_lineno,
+                                                                    calling_frame.f_code.co_filename)
+        if not _is_in_verify_within:
+            print(error_message)
+        raise VerifyError(error_message)
+
+
+def verify_within(condition_checker_func, wait_time, arg=None, delay_time=0.1):
+    """Verifies that a given function `condition_checker_func` passes successfully within a given wait timeout.
+       `wait_time` is maximum time waiting for condition_checker to pass (in seconds).
+       `arg` is optional parameter and if it s not None, will be passed to `condition_checker_func()`
+       `delay_time` specifies a delay interval added between failed attempts (in seconds).
+    """
+    global _is_in_verify_within
+    start_time = time.time()
+    old_is_in_verify_within = _is_in_verify_within
+    _is_in_verify_within = True
+    while True:
+        try:
+            if arg is None:
+                condition_checker_func()
+            else:
+                condition_checker_func(arg)
+        except VerifyError as e:
+            if time.time() - start_time > wait_time:
+                print('Took too long to pass the condition ({}>{} sec)'.format(time.time() - start_time, wait_time))
+                print(e.message)
+                raise e
+        except BaseException:
+            raise
+        else:
+            break
+        if delay_time != 0:
+            time.sleep(delay_time)
+    _is_in_verify_within = old_is_in_verify_within
diff --git a/tests/toranj/test-008-permit-join.py b/tests/toranj/cli/test-001-get-set.py
old mode 100644
new mode 100755
similarity index 65%
copy from tests/toranj/test-008-permit-join.py
copy to tests/toranj/cli/test-001-get-set.py
index 63ded32..f64b05a
--- a/tests/toranj/test-008-permit-join.py
+++ b/tests/toranj/cli/test-001-get-set.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-#  Copyright (c) 2018, The OpenThread Authors.
+#  Copyright (c) 2021, The OpenThread Authors.
 #  All rights reserved.
 #
 #  Redistribution and use in source and binary forms, with or without
@@ -26,58 +26,65 @@
 #  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 #  POSSIBILITY OF SUCH DAMAGE.
 
-import time
-import wpan
-from wpan import verify
+from cli import verify
+import cli
+
+import sys
+
+print(sys.version)
 
 # -----------------------------------------------------------------------------------------------------------------------
-# Test description: check wpantund `permit-join` functionality and timeout
+# Test description: simple CLI get and set commands
 
 test_name = __file__[:-3] if __file__.endswith('.py') else __file__
 print('-' * 120)
 print('Starting \'{}\''.format(test_name))
 
 # -----------------------------------------------------------------------------------------------------------------------
-# Creating `wpan.Nodes` instances
+# Creating `Nodes` instances
 
-node = wpan.Node()
-
-# -----------------------------------------------------------------------------------------------------------------------
-# Init all nodes
-
-wpan.Node.init_all_nodes()
-
-# -----------------------------------------------------------------------------------------------------------------------
-# Build network topology
-
-node.form("permit-join-test")
+node = cli.Node()
 
 # -----------------------------------------------------------------------------------------------------------------------
 # Test implementation
 
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'false')
+node.set_channel(21)
+verify(node.get_channel() == '21')
 
-node.permit_join()
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'true')
+ext_addr = '1122334455667788'
+node.set_ext_addr(ext_addr)
+verify(node.get_ext_addr() == ext_addr)
 
-node.permit_join('0')
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'false')
+ext_panid = '1020031510006016'
+node.set_ext_panid(ext_panid)
+verify(node.get_ext_panid() == ext_panid)
 
-node.permit_join(port='1234')
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'true')
+key = '0123456789abcdeffecdba9876543210'
+node.set_network_key(key)
+verify(node.get_network_key() == key)
 
-node.permit_join('0')
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'false')
+panid = '0xabba'
+node.set_panid(panid)
+verify(node.get_panid() == panid)
 
-# check the timeout
-node.permit_join('1')
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'true')
-time.sleep(1.5)
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'false')
+mode = 'rd'
+node.set_mode(mode)
+verify(node.get_mode() == mode)
+
+threshold = '1'
+node.set_router_upgrade_threshold(threshold)
+verify(node.get_router_upgrade_threshold() == threshold)
+
+jitter = '100'
+node.set_router_selection_jitter(jitter)
+verify(node.get_router_selection_jitter() == jitter)
+
+verify(node.get_interface_state() == 'down')
+verify(node.get_state() == 'disabled')
 
 # -----------------------------------------------------------------------------------------------------------------------
 # Test finished
 
-wpan.Node.finalize_all_nodes()
+cli.Node.finalize_all_nodes()
 
 print('\'{}\' passed.'.format(test_name))
diff --git a/tests/toranj/test-008-permit-join.py b/tests/toranj/cli/test-002-form.py
old mode 100644
new mode 100755
similarity index 65%
copy from tests/toranj/test-008-permit-join.py
copy to tests/toranj/cli/test-002-form.py
index 63ded32..eea06d5
--- a/tests/toranj/test-008-permit-join.py
+++ b/tests/toranj/cli/test-002-form.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-#  Copyright (c) 2018, The OpenThread Authors.
+#  Copyright (c) 2021, The OpenThread Authors.
 #  All rights reserved.
 #
 #  Redistribution and use in source and binary forms, with or without
@@ -26,58 +26,53 @@
 #  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 #  POSSIBILITY OF SUCH DAMAGE.
 
-import time
-import wpan
-from wpan import verify
+from cli import verify
+from cli import verify_within
+import cli
 
 # -----------------------------------------------------------------------------------------------------------------------
-# Test description: check wpantund `permit-join` functionality and timeout
+# Test description: forming a Thread network
 
 test_name = __file__[:-3] if __file__.endswith('.py') else __file__
 print('-' * 120)
 print('Starting \'{}\''.format(test_name))
 
 # -----------------------------------------------------------------------------------------------------------------------
-# Creating `wpan.Nodes` instances
+# Creating `Nodes` instances
 
-node = wpan.Node()
+speedup = 4
+cli.Node.set_time_speedup_factor(speedup)
 
-# -----------------------------------------------------------------------------------------------------------------------
-# Init all nodes
-
-wpan.Node.init_all_nodes()
-
-# -----------------------------------------------------------------------------------------------------------------------
-# Build network topology
-
-node.form("permit-join-test")
+node = cli.Node()
 
 # -----------------------------------------------------------------------------------------------------------------------
 # Test implementation
 
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'false')
+WAIT_TIME = 5
 
-node.permit_join()
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'true')
+verify(node.get_state() == 'disabled')
+node.form('test')
 
-node.permit_join('0')
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'false')
+verify(node.get_network_name() == 'test')
 
-node.permit_join(port='1234')
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'true')
+node.interface_down()
+verify(node.get_state() == 'disabled')
 
-node.permit_join('0')
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'false')
+node.form('form-test',
+          channel=21,
+          panid=0x5678,
+          xpanid='1020031510006016',
+          network_key='0123456789abcdeffecdba9876543210')
 
-# check the timeout
-node.permit_join('1')
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'true')
-time.sleep(1.5)
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'false')
+verify(node.get_network_name() == 'form-test')
+verify(node.get_channel() == '21')
+verify(node.get_panid() == '0x5678')
+verify(node.get_ext_panid() == '1020031510006016')
+verify(node.get_network_key() == '0123456789abcdeffecdba9876543210')
 
 # -----------------------------------------------------------------------------------------------------------------------
 # Test finished
 
-wpan.Node.finalize_all_nodes()
+cli.Node.finalize_all_nodes()
 
 print('\'{}\' passed.'.format(test_name))
diff --git a/tests/toranj/test-008-permit-join.py b/tests/toranj/cli/test-003-join.py
old mode 100644
new mode 100755
similarity index 66%
rename from tests/toranj/test-008-permit-join.py
rename to tests/toranj/cli/test-003-join.py
index 63ded32..f1cc05a
--- a/tests/toranj/test-008-permit-join.py
+++ b/tests/toranj/cli/test-003-join.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-#  Copyright (c) 2018, The OpenThread Authors.
+#  Copyright (c) 2021, The OpenThread Authors.
 #  All rights reserved.
 #
 #  Redistribution and use in source and binary forms, with or without
@@ -26,58 +26,55 @@
 #  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 #  POSSIBILITY OF SUCH DAMAGE.
 
-import time
-import wpan
-from wpan import verify
+from cli import verify
+from cli import verify_within
+import cli
 
 # -----------------------------------------------------------------------------------------------------------------------
-# Test description: check wpantund `permit-join` functionality and timeout
+# Test description: joining (as router, end-device, sleepy) - two node network
 
 test_name = __file__[:-3] if __file__.endswith('.py') else __file__
 print('-' * 120)
 print('Starting \'{}\''.format(test_name))
 
 # -----------------------------------------------------------------------------------------------------------------------
-# Creating `wpan.Nodes` instances
+# Creating `cli.Nodes` instances
 
-node = wpan.Node()
+speedup = 4
+cli.Node.set_time_speedup_factor(speedup)
 
-# -----------------------------------------------------------------------------------------------------------------------
-# Init all nodes
+node1 = cli.Node()
+node2 = cli.Node()
 
-wpan.Node.init_all_nodes()
-
-# -----------------------------------------------------------------------------------------------------------------------
-# Build network topology
-
-node.form("permit-join-test")
+WAIT_TIME = 5
 
 # -----------------------------------------------------------------------------------------------------------------------
 # Test implementation
 
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'false')
+node1.allowlist_node(node2)
+node2.allowlist_node(node1)
 
-node.permit_join()
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'true')
+node1.form('join-net')
+verify(node1.get_state() == 'leader')
 
-node.permit_join('0')
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'false')
+node2.join(node1)
+verify(node2.get_state() == 'router')
 
-node.permit_join(port='1234')
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'true')
+node2.interface_down()
 
-node.permit_join('0')
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'false')
+node2.join(node1, cli.JOIN_TYPE_END_DEVICE)
+verify(node2.get_state() == 'child')
+verify(node2.get_mode() == 'rn')
 
-# check the timeout
-node.permit_join('1')
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'true')
-time.sleep(1.5)
-verify(node.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'false')
+node2.interface_down()
+
+node2.join(node1, cli.JOIN_TYPE_SLEEPY_END_DEVICE)
+verify(node2.get_state() == 'child')
+verify(node2.get_mode() == '-')
 
 # -----------------------------------------------------------------------------------------------------------------------
 # Test finished
 
-wpan.Node.finalize_all_nodes()
+cli.Node.finalize_all_nodes()
 
 print('\'{}\' passed.'.format(test_name))
diff --git a/tests/toranj/cli/test-400-srp-client-server.py b/tests/toranj/cli/test-400-srp-client-server.py
new file mode 100755
index 0000000..a74d261
--- /dev/null
+++ b/tests/toranj/cli/test-400-srp-client-server.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2021, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+
+from cli import verify
+from cli import verify_within
+import cli
+
+# -----------------------------------------------------------------------------------------------------------------------
+# Test description: joining (as router, end-device, sleepy) - two node network
+
+test_name = __file__[:-3] if __file__.endswith('.py') else __file__
+print('-' * 120)
+print('Starting \'{}\''.format(test_name))
+
+# -----------------------------------------------------------------------------------------------------------------------
+# Creating `cli.Nodes` instances
+
+speedup = 4
+cli.Node.set_time_speedup_factor(speedup)
+
+server = cli.Node()
+client = cli.Node()
+
+WAIT_TIME = 5
+
+# -----------------------------------------------------------------------------------------------------------------------
+# Test implementation
+
+server.form('srp-test')
+verify(server.get_state() == 'leader')
+
+client.join(server)
+verify(client.get_state() == 'router')
+
+# Check initial state of SRP client and server
+verify(server.srp_server_get_state() == 'disabled')
+verify(server.srp_server_get_addr_mode() == 'unicast')
+verify(client.srp_client_get_state() == 'Disabled')
+verify(client.srp_client_get_auto_start_mode() == 'Disabled')
+
+# Start server and client and register single service
+server.srp_server_enable()
+client.srp_client_enable_auto_start_mode()
+
+client.srp_client_set_host_name('host')
+client.srp_client_set_host_address('fd00::cafe')
+client.srp_client_add_service('ins', '_test._udp', 777, 2, 1)
+
+
+def check_server_has_service():
+    verify(len(server.srp_server_get_hosts()) > 0)
+
+
+verify_within(check_server_has_service, WAIT_TIME)
+
+# Check state and service/host info on client and server
+
+verify(client.srp_client_get_auto_start_mode() == 'Enabled')
+verify(client.srp_client_get_state() == 'Enabled')
+verify(client.srp_client_get_server_address() == server.get_mleid_ip_addr())
+
+verify(client.srp_client_get_host_state() == 'Registered')
+verify(client.srp_client_get_host_name() == 'host')
+addresses = client.srp_client_get_host_address()
+verify(len(addresses) == 1)
+verify(addresses[0] == 'fd00:0:0:0:0:0:0:cafe')
+
+services = client.srp_client_get_services()
+verify(len(services) == 1)
+service = services[0]
+verify(service['instance'] == 'ins')
+verify(service['name'] == '_test._udp')
+verify(service['state'] == 'Registered')
+verify(service['port'] == '777')
+verify(service['priority'] == '2')
+verify(service['weight'] == '1')
+
+verify(server.srp_server_get_state() == 'running')
+
+hosts = server.srp_server_get_hosts()
+verify(len(hosts) == 1)
+host = hosts[0]
+verify(host['name'] == 'host')
+verify(host['deleted'] == 'false')
+verify(host['addresses'] == ['fd00:0:0:0:0:0:0:cafe'])
+
+services = server.srp_server_get_services()
+verify(len(services) == 1)
+service = services[0]
+verify(service['instance'] == 'ins')
+verify(service['name'] == '_test._udp')
+verify(service['deleted'] == 'false')
+verify(service['subtypes'] == '(null)')
+verify(service['port'] == '777')
+verify(service['priority'] == '2')
+verify(service['weight'] == '1')
+verify(service['host'] == 'host')
+verify(service['addresses'] == ['fd00:0:0:0:0:0:0:cafe'])
+
+# -----------------------------------------------------------------------------------------------------------------------
+# Test finished
+
+cli.Node.finalize_all_nodes()
+
+print('\'{}\' passed.'.format(test_name))
diff --git a/tests/toranj/test-001-get-set.py b/tests/toranj/ncp/test-001-get-set.py
similarity index 99%
rename from tests/toranj/test-001-get-set.py
rename to tests/toranj/ncp/test-001-get-set.py
index 2daed01..6dde37a 100644
--- a/tests/toranj/test-001-get-set.py
+++ b/tests/toranj/ncp/test-001-get-set.py
@@ -101,7 +101,6 @@
     wpan.WPAN_PARTITION_ID,
     wpan.WPAN_NCP_VERSION,
     wpan.WPAN_NCP_MCU_POWER_STATE,
-    wpan.WPAN_NETWORK_ALLOW_JOIN,
     wpan.WPAN_NETWORK_PASSTHRU_PORT,
     wpan.WPAN_IP6_LINK_LOCAL_ADDRESS,
     wpan.WPAN_IP6_MESH_LOCAL_ADDRESS,
diff --git a/tests/toranj/test-002-form.py b/tests/toranj/ncp/test-002-form.py
similarity index 100%
rename from tests/toranj/test-002-form.py
rename to tests/toranj/ncp/test-002-form.py
diff --git a/tests/toranj/test-003-join.py b/tests/toranj/ncp/test-003-join.py
similarity index 100%
rename from tests/toranj/test-003-join.py
rename to tests/toranj/ncp/test-003-join.py
diff --git a/tests/toranj/test-004-scan.py b/tests/toranj/ncp/test-004-scan.py
similarity index 100%
rename from tests/toranj/test-004-scan.py
rename to tests/toranj/ncp/test-004-scan.py
diff --git a/tests/toranj/test-005-discover-scan.py b/tests/toranj/ncp/test-005-discover-scan.py
similarity index 100%
rename from tests/toranj/test-005-discover-scan.py
rename to tests/toranj/ncp/test-005-discover-scan.py
diff --git a/tests/toranj/test-006-traffic-router-end-device.py b/tests/toranj/ncp/test-006-traffic-router-end-device.py
similarity index 100%
rename from tests/toranj/test-006-traffic-router-end-device.py
rename to tests/toranj/ncp/test-006-traffic-router-end-device.py
diff --git a/tests/toranj/test-007-traffic-router-sleepy.py b/tests/toranj/ncp/test-007-traffic-router-sleepy.py
similarity index 100%
rename from tests/toranj/test-007-traffic-router-sleepy.py
rename to tests/toranj/ncp/test-007-traffic-router-sleepy.py
diff --git a/tests/toranj/test-009-insecure-traffic-join.py b/tests/toranj/ncp/test-009-insecure-traffic-join.py
similarity index 98%
rename from tests/toranj/test-009-insecure-traffic-join.py
rename to tests/toranj/ncp/test-009-insecure-traffic-join.py
index aa0dfe1..4026737 100644
--- a/tests/toranj/test-009-insecure-traffic-join.py
+++ b/tests/toranj/ncp/test-009-insecure-traffic-join.py
@@ -60,7 +60,6 @@
 
 # Make node1 joinable and set the insecure port
 node1.permit_join(duration_sec='100', port=str(insecure_port))
-verify(node1.get(wpan.WPAN_NETWORK_ALLOW_JOIN) == 'true')
 
 # Join node1 network from node2 without setting the key
 node2.join_node(node1, should_set_key=False)
diff --git a/tests/toranj/test-010-on-mesh-prefix-config-gateway.py b/tests/toranj/ncp/test-010-on-mesh-prefix-config-gateway.py
similarity index 100%
rename from tests/toranj/test-010-on-mesh-prefix-config-gateway.py
rename to tests/toranj/ncp/test-010-on-mesh-prefix-config-gateway.py
diff --git a/tests/toranj/test-011-child-table.py b/tests/toranj/ncp/test-011-child-table.py
similarity index 100%
rename from tests/toranj/test-011-child-table.py
rename to tests/toranj/ncp/test-011-child-table.py
diff --git a/tests/toranj/test-012-multi-hop-traffic.py b/tests/toranj/ncp/test-012-multi-hop-traffic.py
similarity index 100%
rename from tests/toranj/test-012-multi-hop-traffic.py
rename to tests/toranj/ncp/test-012-multi-hop-traffic.py
diff --git a/tests/toranj/test-013-off-mesh-route-traffic.py b/tests/toranj/ncp/test-013-off-mesh-route-traffic.py
similarity index 100%
rename from tests/toranj/test-013-off-mesh-route-traffic.py
rename to tests/toranj/ncp/test-013-off-mesh-route-traffic.py
diff --git a/tests/toranj/test-014-ip6-address-add.py b/tests/toranj/ncp/test-014-ip6-address-add.py
similarity index 100%
rename from tests/toranj/test-014-ip6-address-add.py
rename to tests/toranj/ncp/test-014-ip6-address-add.py
diff --git a/tests/toranj/test-015-same-prefix-on-multiple-nodes.py b/tests/toranj/ncp/test-015-same-prefix-on-multiple-nodes.py
similarity index 100%
rename from tests/toranj/test-015-same-prefix-on-multiple-nodes.py
rename to tests/toranj/ncp/test-015-same-prefix-on-multiple-nodes.py
diff --git a/tests/toranj/test-016-neighbor-table.py b/tests/toranj/ncp/test-016-neighbor-table.py
similarity index 100%
rename from tests/toranj/test-016-neighbor-table.py
rename to tests/toranj/ncp/test-016-neighbor-table.py
diff --git a/tests/toranj/test-017-parent-reset-child-recovery.py b/tests/toranj/ncp/test-017-parent-reset-child-recovery.py
similarity index 93%
rename from tests/toranj/test-017-parent-reset-child-recovery.py
rename to tests/toranj/ncp/test-017-parent-reset-child-recovery.py
index 6250390..ede43dc 100644
--- a/tests/toranj/test-017-parent-reset-child-recovery.py
+++ b/tests/toranj/ncp/test-017-parent-reset-child-recovery.py
@@ -81,7 +81,7 @@
 
 for child in sleepy_children:
     child.join_node(parent, wpan.JOIN_TYPE_SLEEPY_END_DEVICE)
-    child.set(wpan.WPAN_POLL_INTERVAL, '4000')
+    child.set(wpan.WPAN_POLL_INTERVAL, '10000')
 
 for child in rx_on_children:
     child.join_node(parent, wpan.JOIN_TYPE_END_DEVICE)
@@ -148,16 +148,19 @@
     verify(parent.is_associated())
 
 
-wpan.verify_within(check_parent_is_associated, 5)
+wpan.verify_within(check_parent_is_associated, 10)
 
 # Verify that all the children are recovered and present in the parent's
-# child table again (within 5 seconds).
-wpan.verify_within(check_child_table, 9)
+# child table again.
+wpan.verify_within(check_child_table, 15)
 
-# Verify that number of state changes on all children stays as before
+# Verify that number of state changes on at least one child stays as before
 # (indicating they did not get detached).
 for i in range(len(all_children)):
-    verify(child_num_state_changes[i] == len(wpan.parse_list(all_children[i].get("stat:ncp"))))
+    if child_num_state_changes[i] == len(wpan.parse_list(all_children[i].get("stat:ncp"))):
+        break
+else:
+    verify(False)
 
 # -----------------------------------------------------------------------------------------------------------------------
 # Test finished
diff --git a/tests/toranj/test-018-child-supervision.py b/tests/toranj/ncp/test-018-child-supervision.py
similarity index 99%
rename from tests/toranj/test-018-child-supervision.py
rename to tests/toranj/ncp/test-018-child-supervision.py
index b73f3ac..2fe2767 100644
--- a/tests/toranj/test-018-child-supervision.py
+++ b/tests/toranj/ncp/test-018-child-supervision.py
@@ -98,6 +98,8 @@
 verify(len(child_table) == 1)
 verify(int(child_table[0].timeout, 0) == CHILD_TIMEOUT)
 
+time.sleep(1)
+
 # Enabling allowlisting on parent
 #
 # Since child is not in parent's allowlist, the data polls from child
diff --git a/tests/toranj/test-019-inform-previous-parent.py b/tests/toranj/ncp/test-019-inform-previous-parent.py
similarity index 100%
rename from tests/toranj/test-019-inform-previous-parent.py
rename to tests/toranj/ncp/test-019-inform-previous-parent.py
diff --git a/tests/toranj/test-020-router-table.py b/tests/toranj/ncp/test-020-router-table.py
similarity index 100%
rename from tests/toranj/test-020-router-table.py
rename to tests/toranj/ncp/test-020-router-table.py
diff --git a/tests/toranj/test-021-address-cache-table.py b/tests/toranj/ncp/test-021-address-cache-table.py
similarity index 100%
rename from tests/toranj/test-021-address-cache-table.py
rename to tests/toranj/ncp/test-021-address-cache-table.py
diff --git a/tests/toranj/test-022-multicast-ip6-address.py b/tests/toranj/ncp/test-022-multicast-ip6-address.py
similarity index 100%
rename from tests/toranj/test-022-multicast-ip6-address.py
rename to tests/toranj/ncp/test-022-multicast-ip6-address.py
diff --git a/tests/toranj/test-023-multicast-traffic.py b/tests/toranj/ncp/test-023-multicast-traffic.py
similarity index 100%
rename from tests/toranj/test-023-multicast-traffic.py
rename to tests/toranj/ncp/test-023-multicast-traffic.py
diff --git a/tests/toranj/test-024-partition-merge.py b/tests/toranj/ncp/test-024-partition-merge.py
similarity index 100%
rename from tests/toranj/test-024-partition-merge.py
rename to tests/toranj/ncp/test-024-partition-merge.py
diff --git a/tests/toranj/test-025-network-data-timeout.py b/tests/toranj/ncp/test-025-network-data-timeout.py
similarity index 100%
rename from tests/toranj/test-025-network-data-timeout.py
rename to tests/toranj/ncp/test-025-network-data-timeout.py
diff --git a/tests/toranj/test-026-slaac-address-wpantund.py b/tests/toranj/ncp/test-026-slaac-address-wpantund.py
similarity index 100%
rename from tests/toranj/test-026-slaac-address-wpantund.py
rename to tests/toranj/ncp/test-026-slaac-address-wpantund.py
diff --git a/tests/toranj/test-027-child-mode-change.py b/tests/toranj/ncp/test-027-child-mode-change.py
similarity index 100%
rename from tests/toranj/test-027-child-mode-change.py
rename to tests/toranj/ncp/test-027-child-mode-change.py
diff --git a/tests/toranj/test-028-router-leader-reset-recovery.py b/tests/toranj/ncp/test-028-router-leader-reset-recovery.py
similarity index 100%
rename from tests/toranj/test-028-router-leader-reset-recovery.py
rename to tests/toranj/ncp/test-028-router-leader-reset-recovery.py
diff --git a/tests/toranj/test-029-data-poll-interval.py b/tests/toranj/ncp/test-029-data-poll-interval.py
similarity index 100%
rename from tests/toranj/test-029-data-poll-interval.py
rename to tests/toranj/ncp/test-029-data-poll-interval.py
diff --git a/tests/toranj/test-030-slaac-address-ncp.py b/tests/toranj/ncp/test-030-slaac-address-ncp.py
similarity index 100%
rename from tests/toranj/test-030-slaac-address-ncp.py
rename to tests/toranj/ncp/test-030-slaac-address-ncp.py
diff --git a/tests/toranj/test-031-meshcop-joiner-commissioner.py b/tests/toranj/ncp/test-031-meshcop-joiner-commissioner.py
similarity index 100%
rename from tests/toranj/test-031-meshcop-joiner-commissioner.py
rename to tests/toranj/ncp/test-031-meshcop-joiner-commissioner.py
diff --git a/tests/toranj/test-032-child-attach-with-multiple-ip-addresses.py b/tests/toranj/ncp/test-032-child-attach-with-multiple-ip-addresses.py
similarity index 100%
rename from tests/toranj/test-032-child-attach-with-multiple-ip-addresses.py
rename to tests/toranj/ncp/test-032-child-attach-with-multiple-ip-addresses.py
diff --git a/tests/toranj/test-033-mesh-local-prefix-change.py b/tests/toranj/ncp/test-033-mesh-local-prefix-change.py
similarity index 100%
rename from tests/toranj/test-033-mesh-local-prefix-change.py
rename to tests/toranj/ncp/test-033-mesh-local-prefix-change.py
diff --git a/tests/toranj/test-034-poor-link-parent-child-attach.py b/tests/toranj/ncp/test-034-poor-link-parent-child-attach.py
similarity index 100%
rename from tests/toranj/test-034-poor-link-parent-child-attach.py
rename to tests/toranj/ncp/test-034-poor-link-parent-child-attach.py
diff --git a/tests/toranj/test-035-child-timeout-large-data-poll.py b/tests/toranj/ncp/test-035-child-timeout-large-data-poll.py
similarity index 100%
rename from tests/toranj/test-035-child-timeout-large-data-poll.py
rename to tests/toranj/ncp/test-035-child-timeout-large-data-poll.py
diff --git a/tests/toranj/test-036-wpantund-host-route-management.py b/tests/toranj/ncp/test-036-wpantund-host-route-management.py
similarity index 100%
rename from tests/toranj/test-036-wpantund-host-route-management.py
rename to tests/toranj/ncp/test-036-wpantund-host-route-management.py
diff --git a/tests/toranj/test-037-wpantund-auto-add-route-for-on-mesh-prefix.py b/tests/toranj/ncp/test-037-wpantund-auto-add-route-for-on-mesh-prefix.py
similarity index 100%
rename from tests/toranj/test-037-wpantund-auto-add-route-for-on-mesh-prefix.py
rename to tests/toranj/ncp/test-037-wpantund-auto-add-route-for-on-mesh-prefix.py
diff --git a/tests/toranj/test-038-clear-address-cache-for-sed.py b/tests/toranj/ncp/test-038-clear-address-cache-for-sed.py
similarity index 100%
rename from tests/toranj/test-038-clear-address-cache-for-sed.py
rename to tests/toranj/ncp/test-038-clear-address-cache-for-sed.py
diff --git a/tests/toranj/test-039-address-cache-table-snoop.py b/tests/toranj/ncp/test-039-address-cache-table-snoop.py
similarity index 100%
rename from tests/toranj/test-039-address-cache-table-snoop.py
rename to tests/toranj/ncp/test-039-address-cache-table-snoop.py
diff --git a/tests/toranj/test-040-network-data-stable-full.py b/tests/toranj/ncp/test-040-network-data-stable-full.py
similarity index 100%
rename from tests/toranj/test-040-network-data-stable-full.py
rename to tests/toranj/ncp/test-040-network-data-stable-full.py
diff --git a/tests/toranj/test-041-lowpan-fragmentation.py b/tests/toranj/ncp/test-041-lowpan-fragmentation.py
similarity index 100%
rename from tests/toranj/test-041-lowpan-fragmentation.py
rename to tests/toranj/ncp/test-041-lowpan-fragmentation.py
diff --git a/tests/toranj/test-042-meshcop-joiner-discerner.py b/tests/toranj/ncp/test-042-meshcop-joiner-discerner.py
similarity index 100%
rename from tests/toranj/test-042-meshcop-joiner-discerner.py
rename to tests/toranj/ncp/test-042-meshcop-joiner-discerner.py
diff --git a/tests/toranj/test-043-meshcop-joiner-router.py b/tests/toranj/ncp/test-043-meshcop-joiner-router.py
similarity index 100%
rename from tests/toranj/test-043-meshcop-joiner-router.py
rename to tests/toranj/ncp/test-043-meshcop-joiner-router.py
diff --git a/tests/toranj/test-100-mcu-power-state.py b/tests/toranj/ncp/test-100-mcu-power-state.py
similarity index 100%
rename from tests/toranj/test-100-mcu-power-state.py
rename to tests/toranj/ncp/test-100-mcu-power-state.py
diff --git a/tests/toranj/test-600-channel-manager-properties.py b/tests/toranj/ncp/test-600-channel-manager-properties.py
similarity index 100%
rename from tests/toranj/test-600-channel-manager-properties.py
rename to tests/toranj/ncp/test-600-channel-manager-properties.py
diff --git a/tests/toranj/test-601-channel-manager-channel-change.py b/tests/toranj/ncp/test-601-channel-manager-channel-change.py
similarity index 100%
rename from tests/toranj/test-601-channel-manager-channel-change.py
rename to tests/toranj/ncp/test-601-channel-manager-channel-change.py
diff --git a/tests/toranj/test-602-channel-manager-channel-select.py b/tests/toranj/ncp/test-602-channel-manager-channel-select.py
similarity index 100%
rename from tests/toranj/test-602-channel-manager-channel-select.py
rename to tests/toranj/ncp/test-602-channel-manager-channel-select.py
diff --git a/tests/toranj/test-603-channel-manager-announce-recovery.py b/tests/toranj/ncp/test-603-channel-manager-announce-recovery.py
similarity index 100%
rename from tests/toranj/test-603-channel-manager-announce-recovery.py
rename to tests/toranj/ncp/test-603-channel-manager-announce-recovery.py
diff --git a/tests/toranj/test-700-multi-radio-join.py b/tests/toranj/ncp/test-700-multi-radio-join.py
similarity index 100%
rename from tests/toranj/test-700-multi-radio-join.py
rename to tests/toranj/ncp/test-700-multi-radio-join.py
diff --git a/tests/toranj/test-701-multi-radio-probe.py b/tests/toranj/ncp/test-701-multi-radio-probe.py
similarity index 100%
rename from tests/toranj/test-701-multi-radio-probe.py
rename to tests/toranj/ncp/test-701-multi-radio-probe.py
diff --git a/tests/toranj/test-702-multi-radio-discovery-by-rx.py b/tests/toranj/ncp/test-702-multi-radio-discovery-by-rx.py
similarity index 100%
rename from tests/toranj/test-702-multi-radio-discovery-by-rx.py
rename to tests/toranj/ncp/test-702-multi-radio-discovery-by-rx.py
diff --git a/tests/toranj/test-703-multi-radio-mesh-header-msg.py b/tests/toranj/ncp/test-703-multi-radio-mesh-header-msg.py
similarity index 100%
rename from tests/toranj/test-703-multi-radio-mesh-header-msg.py
rename to tests/toranj/ncp/test-703-multi-radio-mesh-header-msg.py
diff --git a/tests/toranj/test-704-multi-radio-scan.py b/tests/toranj/ncp/test-704-multi-radio-scan.py
similarity index 100%
rename from tests/toranj/test-704-multi-radio-scan.py
rename to tests/toranj/ncp/test-704-multi-radio-scan.py
diff --git a/tests/toranj/test-705-multi-radio-discover-scan.py b/tests/toranj/ncp/test-705-multi-radio-discover-scan.py
similarity index 100%
rename from tests/toranj/test-705-multi-radio-discover-scan.py
rename to tests/toranj/ncp/test-705-multi-radio-discover-scan.py
diff --git a/tests/toranj/test-nnn-template.py b/tests/toranj/ncp/test-nnn-template.py
similarity index 100%
rename from tests/toranj/test-nnn-template.py
rename to tests/toranj/ncp/test-nnn-template.py
diff --git a/tests/toranj/wpan.py b/tests/toranj/ncp/wpan.py
similarity index 98%
rename from tests/toranj/wpan.py
rename to tests/toranj/ncp/wpan.py
index 283df0a..1dc313a 100644
--- a/tests/toranj/wpan.py
+++ b/tests/toranj/ncp/wpan.py
@@ -56,7 +56,6 @@
 WPAN_PARTITION_ID = 'Network:PartitionId'
 WPAN_NCP_VERSION = 'NCP:Version'
 WPAN_NCP_MCU_POWER_STATE = "NCP:MCUPowerState"
-WPAN_NETWORK_ALLOW_JOIN = 'com.nestlabs.internal:Network:AllowingJoin'
 WPAN_NETWORK_PASSTHRU_PORT = 'com.nestlabs.internal:Network:PassthruPort'
 WPAN_RCP_VERSION = "POSIXApp:RCPVersion"
 
@@ -278,7 +277,7 @@
 RADIO_LINK_TREL_UDP6 = "TREL_UDP6"
 RADIO_LINK_TOBLE = "TOBLE"
 
-_OT_BUILDDIR = os.getenv('top_builddir', '../..')
+_OT_BUILDDIR = os.getenv('top_builddir', '../../..')
 _WPANTUND_PREFIX = os.getenv('WPANTUND_PREFIX', '/usr/local')
 
 # -----------------------------------------------------------------------------------------------------------------------
@@ -568,7 +567,6 @@
         """Checks if node is in the scan results
            `scan_result` must be an array of `ScanResult` object (see `parse_scan_result`).
         """
-        joinable = (self.get(WPAN_NETWORK_ALLOW_JOIN) == 'true')
         panid = self.get(WPAN_PANID)
         xpanid = self.get(WPAN_XPANID)[2:]
         name = self.get(WPAN_NAME)[1:-1]
@@ -576,11 +574,12 @@
         ext_address = self.get(WPAN_EXT_ADDRESS)[1:-1]
 
         for item in scan_result:
-            if all([
-                    item.network_name == name, item.panid == panid, item.xpanid == xpanid,
-                    item.channel == channel, item.ext_address == ext_address,
-                (item.type == ScanResult.TYPE_DISCOVERY_SCAN) or (item.joinable == joinable)
-            ]):
+            if all([item.panid == panid, item.channel == channel, item.ext_address == ext_address]):
+                if (item.type == ScanResult.TYPE_DISCOVERY_SCAN):
+                    if all([item.network_name == name, item.xpanid == xpanid]):
+                        return True
+                    else:
+                        continue
                 return True
 
         return False
@@ -1061,16 +1060,17 @@
 
         items = [item.strip() for item in result_text.split('|')]
 
-        if len(items) == 8:
+        if len(items) == 2:
+            self._type = ScanResult.TYPE_ENERGY_SCAN
+            self._channel = items[0]
+            self._rssi = items[1]
+        if len(items) == 7 and '------ NONE ------' in items[1]:
             self._type = ScanResult.TYPE_ACTIVE_SCAN
             self._index = items[0]
-            self._joinable = (items[1] == 'YES')
-            self._network_name = items[2][1:-1]
-            self._panid = items[3]
-            self._channel = items[4]
-            self._xpanid = items[5]
-            self._ext_address = items[6]
-            self._rssi = items[7]
+            self._panid = items[2]
+            self._channel = items[3]
+            self._ext_address = items[5]
+            self._rssi = items[6]
         elif len(items) == 7:
             self._type = ScanResult.TYPE_DISCOVERY_SCAN
             self._index = items[0]
@@ -1080,12 +1080,8 @@
             self._xpanid = items[4]
             self._ext_address = items[5]
             self._rssi = items[6]
-        elif len(items) == 2:
-            self._type = ScanResult.TYPE_ENERGY_SCAN
-            self._channel = items[0]
-            self._rssi = items[1]
         else:
-            raise ValueError('"{}" does not seem to be a valid scan result string'.result_text)
+            raise ValueError('"%s" does not seem to be a valid scan result string' % result_text)
 
     @property
     def type(self):
diff --git a/tests/toranj/openthread-core-toranj-config-posix.h b/tests/toranj/openthread-core-toranj-config-posix.h
index 8a2c58f..ecf3ba8 100644
--- a/tests/toranj/openthread-core-toranj-config-posix.h
+++ b/tests/toranj/openthread-core-toranj-config-posix.h
@@ -62,29 +62,6 @@
 #define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 1
 
 /**
- * @def OPENTHREAD_CONFIG_POSIX_APP_TREL_INTERFACE_NAME
- *
- * Defines the default interface name used for TREL UDP6 platform. Empty string disables TREL platform.
- *
- */
-#define OPENTHREAD_CONFIG_POSIX_APP_TREL_INTERFACE_NAME "trel"
-
-/**
- * @def OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
- *
- * Defines whether the TREL UDP6 platform uses netlink socket to add/remove addresses on the TREL netif or `ioctl()`
- * command.
- *
- * When netlink is used Duplicate Address Detection (DAD) is disabled when a new address is added on the netif.
- *
- */
-#ifdef __linux__
-#define OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET 1
-#else
-#define OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET 0
-#endif
-
-/**
  * @def OPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE
  *
  * Define as 1 to enable PTY device support in POSIX app.
diff --git a/tests/toranj/openthread-core-toranj-config-simulation.h b/tests/toranj/openthread-core-toranj-config-simulation.h
index ea97044..09d925d 100644
--- a/tests/toranj/openthread-core-toranj-config-simulation.h
+++ b/tests/toranj/openthread-core-toranj-config-simulation.h
@@ -67,4 +67,12 @@
  */
 #define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_APP
 
+/**
+ * @def OPENTHREAD_CONFIG_DNS_DSO_ENABLE
+ *
+ * Define to 1 to enable DSO support.
+ *
+ */
+#define OPENTHREAD_CONFIG_DNS_DSO_ENABLE 1
+
 #endif /* OPENTHREAD_CORE_TORANJ_CONFIG_SIMULATION_H_ */
diff --git a/tests/toranj/openthread-core-toranj-config.h b/tests/toranj/openthread-core-toranj-config.h
index d2d7ca3..508f605 100644
--- a/tests/toranj/openthread-core-toranj-config.h
+++ b/tests/toranj/openthread-core-toranj-config.h
@@ -68,6 +68,14 @@
 #define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 1
 
 /**
+ * @def OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ *
+ * Define to 1 to enable Border Routing support.
+ *
+ */
+#define OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE 1
+
+/**
  * @def OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
  *
  * Define to 1 to enable Commissioner support.
@@ -317,14 +325,6 @@
 #define OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL 1
 
 /**
- * @def OPENTHREAD_CONFIG_LOG_PREPEND_REGION
- *
- * Define to prepend the log region to all log messages
- *
- */
-#define OPENTHREAD_CONFIG_LOG_PREPEND_REGION 1
-
-/**
  * @def OPENTHREAD_CONFIG_LOG_SUFFIX
  *
  * Define suffix to append at the end of logs.
@@ -530,6 +530,14 @@
  */
 #define OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE 1
 
+/**
+ * @def OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
+ *
+ * Define to 1 to enable delay-aware queue management for the send queue.
+ *
+ */
+#define OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE 1
+
 #if OPENTHREAD_RADIO
 /**
  * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_ACK_TIMEOUT_ENABLE
diff --git a/tests/toranj/start.sh b/tests/toranj/start.sh
index be232bc..3831afc 100755
--- a/tests/toranj/start.sh
+++ b/tests/toranj/start.sh
@@ -69,8 +69,7 @@
 {
     counter=0
     while true; do
-
-        if sudo -E python "$1"; then
+        if sudo -E "${python_app}" "$1"; then
             cleanup
             return
         fi
@@ -85,7 +84,7 @@
         fi
 
         echo " *** TEST FAILED"
-        tail -n 40 wpantund-logs*.log
+        tail -n 40 "${log_file_name}"*.log
         exit 1
     done
 }
@@ -102,85 +101,103 @@
     coverage_option=""
 fi
 
+if [ "$TORANJ_CLI" = 1 ]; then
+    app_name="cli"
+    python_app="python3"
+    log_file_name="ot-logs"
+else
+    app_name="ncp"
+    python_app="python"
+    log_file_name="wpantund-logs"
+fi
+
 if [ "$TORANJ_RADIO" = "multi" ]; then
     # Build all combinations
-    ./build.sh "${coverage_option}" ncp-15.4 || die "ncp-15.4 build failed"
+    ./build.sh "${coverage_option}" "${app_name}"-15.4 || die "${app_name}-15.4 build failed"
     (cd ${top_builddir} && make clean) || die "cd and clean failed"
-    ./build.sh "${coverage_option}" ncp-trel || die "ncp-trel build failed"
+    ./build.sh "${coverage_option}" "${app_name}"-trel || die "${app_name}-trel build failed"
     (cd ${top_builddir} && make clean) || die "cd and clean failed"
-    ./build.sh "${coverage_option}" ncp-15.4+trel || die "ncp-15.4+trel build failed"
+    ./build.sh "${coverage_option}" "${app_name}"-15.4+trel || die "${app_name}-15.4+trel build failed"
     (cd ${top_builddir} && make clean) || die "cd and clean failed"
 else
-    ./build.sh "${coverage_option}" ncp-"${TORANJ_RADIO}" || die "ncp build failed"
+    ./build.sh "${coverage_option}" "${app_name}"-"${TORANJ_RADIO}" || die "build failed"
 fi
 
 cleanup
 
-if [ "$TORANJ_RADIO" = "multi" ]; then
-    run test-700-multi-radio-join.py
-    run test-701-multi-radio-probe.py
-    run test-702-multi-radio-discovery-by-rx.py
-    run test-703-multi-radio-mesh-header-msg.py
-    run test-704-multi-radio-scan.py
-    run test-705-multi-radio-discover-scan.py
+if [ "$TORANJ_CLI" = 1 ]; then
+    run cli/test-001-get-set.py
+    run cli/test-002-form.py
+    run cli/test-003-join.py
+    run cli/test-400-srp-client-server.py
 
     exit 0
 fi
 
-run test-001-get-set.py
-run test-002-form.py
-run test-003-join.py
-run test-004-scan.py
-run test-005-discover-scan.py
-run test-006-traffic-router-end-device.py
-run test-007-traffic-router-sleepy.py
-run test-008-permit-join.py
-run test-009-insecure-traffic-join.py
-run test-010-on-mesh-prefix-config-gateway.py
-run test-011-child-table.py
-run test-012-multi-hop-traffic.py
-run test-013-off-mesh-route-traffic.py
-run test-014-ip6-address-add.py
-run test-015-same-prefix-on-multiple-nodes.py
-run test-016-neighbor-table.py
-run test-017-parent-reset-child-recovery.py
-run test-018-child-supervision.py
-run test-019-inform-previous-parent.py
-run test-020-router-table.py
-run test-021-address-cache-table.py
-run test-022-multicast-ip6-address.py
-run test-023-multicast-traffic.py
-run test-024-partition-merge.py
-run test-025-network-data-timeout.py
-run test-026-slaac-address-wpantund.py
-run test-027-child-mode-change.py
-run test-028-router-leader-reset-recovery.py
-run test-029-data-poll-interval.py
-run test-030-slaac-address-ncp.py
-run test-031-meshcop-joiner-commissioner.py
-run test-032-child-attach-with-multiple-ip-addresses.py
-run test-033-mesh-local-prefix-change.py
-run test-034-poor-link-parent-child-attach.py
-run test-035-child-timeout-large-data-poll.py
-run test-036-wpantund-host-route-management.py
-run test-037-wpantund-auto-add-route-for-on-mesh-prefix.py
-run test-038-clear-address-cache-for-sed.py
-run test-039-address-cache-table-snoop.py
-run test-040-network-data-stable-full.py
-run test-041-lowpan-fragmentation.py
-run test-042-meshcop-joiner-discerner.py
-run test-043-meshcop-joiner-router.py
-run test-100-mcu-power-state.py
-run test-600-channel-manager-properties.py
-run test-601-channel-manager-channel-change.py
+if [ "$TORANJ_RADIO" = "multi" ]; then
+    run ncp/test-700-multi-radio-join.py
+    run ncp/test-701-multi-radio-probe.py
+    run ncp/test-702-multi-radio-discovery-by-rx.py
+    run ncp/test-703-multi-radio-mesh-header-msg.py
+    run ncp/test-704-multi-radio-scan.py
+    run ncp/test-705-multi-radio-discover-scan.py
+
+    exit 0
+fi
+
+run ncp/test-001-get-set.py
+run ncp/test-002-form.py
+run ncp/test-003-join.py
+run ncp/test-004-scan.py
+run ncp/test-005-discover-scan.py
+run ncp/test-006-traffic-router-end-device.py
+run ncp/test-007-traffic-router-sleepy.py
+run ncp/test-009-insecure-traffic-join.py
+run ncp/test-010-on-mesh-prefix-config-gateway.py
+run ncp/test-011-child-table.py
+run ncp/test-012-multi-hop-traffic.py
+run ncp/test-013-off-mesh-route-traffic.py
+run ncp/test-014-ip6-address-add.py
+run ncp/test-015-same-prefix-on-multiple-nodes.py
+run ncp/test-016-neighbor-table.py
+run ncp/test-017-parent-reset-child-recovery.py
+run ncp/test-018-child-supervision.py
+run ncp/test-019-inform-previous-parent.py
+run ncp/test-020-router-table.py
+run ncp/test-021-address-cache-table.py
+run ncp/test-022-multicast-ip6-address.py
+run ncp/test-023-multicast-traffic.py
+run ncp/test-024-partition-merge.py
+run ncp/test-025-network-data-timeout.py
+run ncp/test-026-slaac-address-wpantund.py
+run ncp/test-027-child-mode-change.py
+run ncp/test-028-router-leader-reset-recovery.py
+run ncp/test-029-data-poll-interval.py
+run ncp/test-030-slaac-address-ncp.py
+run ncp/test-031-meshcop-joiner-commissioner.py
+run ncp/test-032-child-attach-with-multiple-ip-addresses.py
+run ncp/test-033-mesh-local-prefix-change.py
+run ncp/test-034-poor-link-parent-child-attach.py
+run ncp/test-035-child-timeout-large-data-poll.py
+run ncp/test-036-wpantund-host-route-management.py
+run ncp/test-037-wpantund-auto-add-route-for-on-mesh-prefix.py
+run ncp/test-038-clear-address-cache-for-sed.py
+run ncp/test-039-address-cache-table-snoop.py
+run ncp/test-040-network-data-stable-full.py
+run ncp/test-041-lowpan-fragmentation.py
+run ncp/test-042-meshcop-joiner-discerner.py
+run ncp/test-043-meshcop-joiner-router.py
+run ncp/test-100-mcu-power-state.py
+run ncp/test-600-channel-manager-properties.py
+run ncp/test-601-channel-manager-channel-change.py
 
 # Skip the "channel-select" test on a TREL only radio link, since it
 # requires energy scan which is not supported in this case.
 
 if [ "$TORANJ_RADIO" != "trel" ]; then
-    run test-602-channel-manager-channel-select.py
+    run ncp/test-602-channel-manager-channel-select.py
 fi
 
-run test-603-channel-manager-announce-recovery.py
+run ncp/test-603-channel-manager-announce-recovery.py
 
 exit 0
diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt
index 4daacfd..9a68ecf 100644
--- a/tests/unit/CMakeLists.txt
+++ b/tests/unit/CMakeLists.txt
@@ -107,6 +107,27 @@
         ${COMMON_LIBS}
 )
 
+add_executable(ot-test-binary-search
+    test_binary_search.cpp
+)
+
+target_include_directories(ot-test-binary-search
+    PRIVATE
+        ${COMMON_INCLUDES}
+)
+
+target_compile_options(ot-test-binary-search
+    PRIVATE
+        ${COMMON_COMPILE_OPTIONS}
+)
+
+target_link_libraries(ot-test-binary-search
+    PRIVATE
+        ${COMMON_LIBS}
+)
+
+add_test(NAME ot-test-binary-search COMMAND ot-test-binary-search)
+
 add_executable(ot-test-child
     test_child.cpp
 )
@@ -234,6 +255,28 @@
 
 add_test(NAME ot-test-dns COMMAND ot-test-dns)
 
+add_executable(ot-test-dso
+    test_dso.cpp
+)
+
+target_include_directories(ot-test-dso
+    PRIVATE
+        ${COMMON_INCLUDES}
+)
+
+target_compile_options(ot-test-dso
+    PRIVATE
+        ${COMMON_COMPILE_OPTIONS}
+)
+
+target_link_libraries(ot-test-dso
+    PRIVATE
+        ${COMMON_LIBS}
+)
+
+add_test(NAME ot-test-dso COMMAND ot-test-dso)
+
+
 add_executable(ot-test-ecdsa
     test_ecdsa.cpp
 )
@@ -277,6 +320,27 @@
 
 add_test(NAME ot-test-flash COMMAND ot-test-flash)
 
+add_executable(ot-test-frame-builder
+    test_frame_builder.cpp
+)
+
+target_include_directories(ot-test-frame-builder
+    PRIVATE
+        ${COMMON_INCLUDES}
+)
+
+target_compile_options(ot-test-frame-builder
+    PRIVATE
+        ${COMMON_COMPILE_OPTIONS}
+)
+
+target_link_libraries(ot-test-frame-builder
+    PRIVATE
+        ${COMMON_LIBS}
+)
+
+add_test(NAME ot-test-frame_builder COMMAND ot-test-frame-builder)
+
 add_executable(ot-test-heap
     test_heap.cpp
 )
@@ -298,6 +362,27 @@
 
 add_test(NAME ot-test-heap COMMAND ot-test-heap)
 
+add_executable(ot-test-heap-array
+    test_heap_array.cpp
+)
+
+target_include_directories(ot-test-heap-array
+    PRIVATE
+        ${COMMON_INCLUDES}
+)
+
+target_compile_options(ot-test-heap-array
+    PRIVATE
+        ${COMMON_COMPILE_OPTIONS}
+)
+
+target_link_libraries(ot-test-heap-array
+    PRIVATE
+        ${COMMON_LIBS}
+)
+
+add_test(NAME ot-test-heap-array COMMAND ot-test-heap-array)
+
 add_executable(ot-test-heap-string
     test_heap_string.cpp
 )
@@ -367,6 +452,48 @@
 
 add_test(NAME ot-test-hmac-sha256 COMMAND ot-test-hmac-sha256)
 
+add_executable(ot-test-ip4-header
+    test_ip4_header.cpp
+)
+
+target_include_directories(ot-test-ip4-header
+    PRIVATE
+        ${COMMON_INCLUDES}
+)
+
+target_compile_options(ot-test-ip4-header
+    PRIVATE
+        ${COMMON_COMPILE_OPTIONS}
+)
+
+target_link_libraries(ot-test-ip4-header
+    PRIVATE
+        ${COMMON_LIBS}
+)
+
+add_test(NAME ot-test-ip4-header COMMAND ot-test-ip4-header)
+
+add_executable(ot-test-ip6-header
+    test_ip6_header.cpp
+)
+
+target_include_directories(ot-test-ip6-header
+    PRIVATE
+        ${COMMON_INCLUDES}
+)
+
+target_compile_options(ot-test-ip6-header
+    PRIVATE
+        ${COMMON_COMPILE_OPTIONS}
+)
+
+target_link_libraries(ot-test-ip6-header
+    PRIVATE
+        ${COMMON_LIBS}
+)
+
+add_test(NAME ot-test-ip6-header COMMAND ot-test-ip6-header)
+
 add_executable(ot-test-ip-address
     test_ip_address.cpp
 )
@@ -430,27 +557,6 @@
 
 add_test(NAME ot-test-linked-list COMMAND ot-test-linked-list)
 
-add_executable(ot-test-lookup-table
-    test_lookup_table.cpp
-)
-
-target_include_directories(ot-test-lookup-table
-    PRIVATE
-        ${COMMON_INCLUDES}
-)
-
-target_compile_options(ot-test-lookup-table
-    PRIVATE
-        ${COMMON_COMPILE_OPTIONS}
-)
-
-target_link_libraries(ot-test-lookup-table
-    PRIVATE
-        ${COMMON_LIBS}
-)
-
-add_test(NAME ot-test-lookup-table COMMAND ot-test-lookup-table)
-
 add_executable(ot-test-lowpan
     test_lowpan.cpp
 )
@@ -581,6 +687,27 @@
     test_ndproxy_table.cpp
 )
 
+add_executable(ot-test-network-name
+    test_network_name.cpp
+)
+
+target_include_directories(ot-test-network-name
+    PRIVATE
+        ${COMMON_INCLUDES}
+)
+
+target_compile_options(ot-test-network-name
+    PRIVATE
+        ${COMMON_COMPILE_OPTIONS}
+)
+
+target_link_libraries(ot-test-network-name
+    PRIVATE
+        ${COMMON_LIBS}
+)
+
+add_test(NAME ot-test-network-name COMMAND ot-test-network-name)
+
 target_include_directories(ot-test-ndproxy-table
     PRIVATE
         ${COMMON_INCLUDES}
@@ -705,6 +832,27 @@
 
 add_test(NAME ot-test-pskc COMMAND ot-test-pskc)
 
+add_executable(ot-test-smart-ptrs
+    test_smart_ptrs.cpp
+)
+
+target_include_directories(ot-test-smart-ptrs
+    PRIVATE
+        ${COMMON_INCLUDES}
+)
+
+target_compile_options(ot-test-smart-ptrs
+    PRIVATE
+        ${COMMON_COMPILE_OPTIONS}
+)
+
+target_link_libraries(ot-test-smart-ptrs
+    PRIVATE
+        ${COMMON_LIBS}
+)
+
+add_test(NAME ot-test-smart-ptrs COMMAND ot-test-smart-ptrs)
+
 add_executable(ot-test-meshcop
     test_meshcop.cpp
 )
@@ -726,6 +874,48 @@
 
 add_test(NAME ot-test-meshcop COMMAND ot-test-meshcop)
 
+add_executable(ot-test-serial-number
+    test_serial_number.cpp
+)
+
+add_executable(ot-test-routing-manager
+    test_routing_manager.cpp
+)
+
+target_include_directories(ot-test-routing-manager
+    PRIVATE
+        ${COMMON_INCLUDES}
+)
+
+target_compile_options(ot-test-routing-manager
+    PRIVATE
+        ${COMMON_COMPILE_OPTIONS}
+)
+
+target_link_libraries(ot-test-routing-manager
+    PRIVATE
+        ${COMMON_LIBS}
+)
+
+add_test(NAME ot-test-routing-manager COMMAND ot-test-routing-manager)
+
+target_include_directories(ot-test-serial-number
+    PRIVATE
+        ${COMMON_INCLUDES}
+)
+
+target_compile_options(ot-test-serial-number
+    PRIVATE
+        ${COMMON_COMPILE_OPTIONS}
+)
+
+target_link_libraries(ot-test-serial-number
+    PRIVATE
+        ${COMMON_LIBS}
+)
+
+add_test(NAME ot-test-serial-number COMMAND ot-test-serial-number)
+
 add_executable(ot-test-string
     test_string.cpp
 )
diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am
index a91ca5f..21316aa 100644
--- a/tests/unit/Makefile.am
+++ b/tests/unit/Makefile.am
@@ -28,6 +28,8 @@
 
 include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
 
+COMMON_LIBTOOLFLAGS = --preserve-dup-deps
+
 #
 # Local headers to build against and distribute but not to install
 # since they are not part of the package.
@@ -74,7 +76,6 @@
 endif
 
 COMMON_LDADD                                                        = \
-    $(top_builddir)/third_party/tcplp/libtcplp.a                      \
     $(NULL)
 
 if OPENTHREAD_ENABLE_NCP
@@ -85,6 +86,8 @@
 
 COMMON_LDADD                                                       += \
     $(top_builddir)/src/core/libopenthread-ftd.a                      \
+    $(top_builddir)/third_party/tcplp/libtcplp.a                      \
+    $(top_builddir)/src/core/libopenthread-ftd.a                      \
     -lpthread                                                         \
     $(NULL)
 
@@ -110,22 +113,27 @@
 check_PROGRAMS                                                     += \
     ot-test-aes                                                       \
     ot-test-array                                                     \
+    ot-test-binary-search                                             \
     ot-test-checksum                                                  \
     ot-test-child                                                     \
     ot-test-child-table                                               \
     ot-test-cmd-line-parser                                           \
     ot-test-data                                                      \
     ot-test-dns                                                       \
+    ot-test-dso                                                       \
     ot-test-ecdsa                                                     \
     ot-test-flash                                                     \
+    ot-test-frame-builder                                             \
     ot-test-heap                                                      \
+    ot-test-heap-array                                                \
     ot-test-heap-string                                               \
     ot-test-hkdf-sha256                                               \
     ot-test-hmac-sha256                                               \
+    ot-test-ip4-header                                                \
+    ot-test-ip6-header                                                \
     ot-test-ip-address                                                \
     ot-test-link-quality                                              \
     ot-test-linked-list                                               \
-    ot-test-lookup-table                                              \
     ot-test-lowpan                                                    \
     ot-test-mac-frame                                                 \
     ot-test-macros                                                    \
@@ -136,9 +144,13 @@
     ot-test-ndproxy-table                                             \
     ot-test-netif                                                     \
     ot-test-network-data                                              \
+    ot-test-network-name                                              \
     ot-test-pool                                                      \
     ot-test-priority-queue                                            \
     ot-test-pskc                                                      \
+    ot-test-serial-number                                             \
+    ot-test-routing-manager                                           \
+    ot-test-smart-ptrs                                                \
     ot-test-string                                                    \
     ot-test-timer                                                     \
     $(NULL)
@@ -181,119 +193,192 @@
 
 # Source, compiler, and linker options for test programs.
 
-ot_test_aes_LDADD               = $(COMMON_LDADD)
-ot_test_aes_SOURCES             = $(COMMON_SOURCES) test_aes.cpp
+ot_test_aes_LDADD                   = $(COMMON_LDADD)
+ot_test_aes_LIBTOOLFLAGS            = $(COMMON_LIBTOOLFLAGS)
+ot_test_aes_SOURCES                 = $(COMMON_SOURCES) test_aes.cpp
 
-ot_test_array_LDADD             = $(COMMON_LDADD)
-ot_test_array_SOURCES           = $(COMMON_SOURCES) test_array.cpp
+ot_test_array_LDADD                 = $(COMMON_LDADD)
+ot_test_array_LIBTOOLFLAGS          = $(COMMON_LIBTOOLFLAGS)
+ot_test_array_SOURCES               = $(COMMON_SOURCES) test_array.cpp
 
-ot_test_checksum_LDADD          = $(COMMON_LDADD)
-ot_test_checksum_SOURCES        = $(COMMON_SOURCES) test_checksum.cpp
+ot_test_binary_search_LDADD         = $(COMMON_LDADD)
+ot_test_binary_search_LIBTOOLFLAGS  = $(COMMON_LIBTOOLFLAGS)
+ot_test_binary_search_SOURCES       = $(COMMON_SOURCES) test_binary_search.cpp
 
-ot_test_child_LDADD             = $(COMMON_LDADD)
-ot_test_child_SOURCES           = $(COMMON_SOURCES) test_child.cpp
+ot_test_checksum_LDADD              = $(COMMON_LDADD)
+ot_test_checksum_LIBTOOLFLAGS       = $(COMMON_LIBTOOLFLAGS)
+ot_test_checksum_SOURCES            = $(COMMON_SOURCES) test_checksum.cpp
 
-ot_test_child_table_LDADD       = $(COMMON_LDADD)
-ot_test_child_table_SOURCES     = $(COMMON_SOURCES) test_child_table.cpp
+ot_test_child_LDADD                 = $(COMMON_LDADD)
+ot_test_child_LIBTOOLFLAGS          = $(COMMON_LIBTOOLFLAGS)
+ot_test_child_SOURCES               = $(COMMON_SOURCES) test_child.cpp
 
-ot_test_cmd_line_parser_LDADD   = $(COMMON_LDADD)
-ot_test_cmd_line_parser_SOURCES = $(COMMON_SOURCES) test_cmd_line_parser.cpp
+ot_test_child_table_LDADD           = $(COMMON_LDADD)
+ot_test_child_table_LIBTOOLFLAGS    = $(COMMON_LIBTOOLFLAGS)
+ot_test_child_table_SOURCES         = $(COMMON_SOURCES) test_child_table.cpp
 
-ot_test_data_LDADD              = $(COMMON_LDADD)
-ot_test_data_SOURCES            = $(COMMON_SOURCES) test_data.cpp
+ot_test_cmd_line_parser_LDADD       = $(COMMON_LDADD)
+ot_test_cmd_line_parser_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
+ot_test_cmd_line_parser_SOURCES     = $(COMMON_SOURCES) test_cmd_line_parser.cpp
 
-ot_test_dns_LDADD               = $(COMMON_LDADD)
-ot_test_dns_SOURCES             = $(COMMON_SOURCES) test_dns.cpp
+ot_test_data_LDADD                  = $(COMMON_LDADD)
+ot_test_data_LIBTOOLFLAGS           = $(COMMON_LIBTOOLFLAGS)
+ot_test_data_SOURCES                = $(COMMON_SOURCES) test_data.cpp
 
-ot_test_ecdsa_LDADD             = $(COMMON_LDADD)
-ot_test_ecdsa_SOURCES           = $(COMMON_SOURCES) test_ecdsa.cpp
+ot_test_dns_LDADD                   = $(COMMON_LDADD)
+ot_test_dns_LIBTOOLFLAGS            = $(COMMON_LIBTOOLFLAGS)
+ot_test_dns_SOURCES                 = $(COMMON_SOURCES) test_dns.cpp
 
-ot_test_flash_LDADD             = $(COMMON_LDADD)
-ot_test_flash_SOURCES           = $(COMMON_SOURCES) test_flash.cpp
+ot_test_dso_LDADD                   = $(COMMON_LDADD)
+ot_test_dso_LIBTOOLFLAGS            = $(COMMON_LIBTOOLFLAGS)
+ot_test_dso_SOURCES                 = $(COMMON_SOURCES) test_dso.cpp
 
-ot_test_hdlc_LDADD              = $(COMMON_LDADD)
-ot_test_hdlc_SOURCES            = $(COMMON_SOURCES) test_hdlc.cpp
+ot_test_ecdsa_LDADD                 = $(COMMON_LDADD)
+ot_test_ecdsa_LIBTOOLFLAGS          = $(COMMON_LIBTOOLFLAGS)
+ot_test_ecdsa_SOURCES               = $(COMMON_SOURCES) test_ecdsa.cpp
 
-ot_test_heap_LDADD              = $(COMMON_LDADD)
-ot_test_heap_SOURCES            = $(COMMON_SOURCES) test_heap.cpp
+ot_test_flash_LDADD                 = $(COMMON_LDADD)
+ot_test_flash_LIBTOOLFLAGS          = $(COMMON_LIBTOOLFLAGS)
+ot_test_flash_SOURCES               = $(COMMON_SOURCES) test_flash.cpp
 
-ot_test_heap_string_LDADD       = $(COMMON_LDADD)
-ot_test_heap_string_SOURCES     = $(COMMON_SOURCES) test_heap_string.cpp
+ot_test_frame_builder_LDADD         = $(COMMON_LDADD)
+ot_test_frame_builder_LIBTOOLFLAGS  = $(COMMON_LIBTOOLFLAGS)
+ot_test_frame_builder_SOURCES       = $(COMMON_SOURCES) test_frame_builder.cpp
 
-ot_test_hkdf_sha256_LDADD       = $(COMMON_LDADD)
-ot_test_hkdf_sha256_SOURCES     = $(COMMON_SOURCES) test_hkdf_sha256.cpp
+ot_test_hdlc_LDADD                  = $(COMMON_LDADD)
+ot_test_hdlc_LIBTOOLFLAGS           = $(COMMON_LIBTOOLFLAGS)
+ot_test_hdlc_SOURCES                = $(COMMON_SOURCES) test_hdlc.cpp
 
-ot_test_hmac_sha256_LDADD       = $(COMMON_LDADD)
-ot_test_hmac_sha256_SOURCES     = $(COMMON_SOURCES) test_hmac_sha256.cpp
+ot_test_heap_LDADD                  = $(COMMON_LDADD)
+ot_test_heap_LIBTOOLFLAGS           = $(COMMON_LIBTOOLFLAGS)
+ot_test_heap_SOURCES                = $(COMMON_SOURCES) test_heap.cpp
 
-ot_test_ip_address_LDADD        = $(COMMON_LDADD)
-ot_test_ip_address_SOURCES      = $(COMMON_SOURCES) test_ip_address.cpp
+ot_test_heap_array_LDADD           = $(COMMON_LDADD)
+ot_test_heap_array_LIBTOOLFLAGS    = $(COMMON_LIBTOOLFLAGS)
+ot_test_heap_array_SOURCES         = $(COMMON_SOURCES) test_heap_array.cpp
 
-ot_test_link_quality_LDADD      = $(COMMON_LDADD)
-ot_test_link_quality_SOURCES    = $(COMMON_SOURCES) test_link_quality.cpp
+ot_test_heap_string_LDADD           = $(COMMON_LDADD)
+ot_test_heap_string_LIBTOOLFLAGS    = $(COMMON_LIBTOOLFLAGS)
+ot_test_heap_string_SOURCES         = $(COMMON_SOURCES) test_heap_string.cpp
 
-ot_test_linked_list_LDADD       = $(COMMON_LDADD)
-ot_test_linked_list_SOURCES     = $(COMMON_SOURCES) test_linked_list.cpp
+ot_test_hkdf_sha256_LDADD           = $(COMMON_LDADD)
+ot_test_hkdf_sha256_LIBTOOLFLAGS    = $(COMMON_LIBTOOLFLAGS)
+ot_test_hkdf_sha256_SOURCES         = $(COMMON_SOURCES) test_hkdf_sha256.cpp
 
-ot_test_lookup_table_LDADD      = $(COMMON_LDADD)
-ot_test_lookup_table_SOURCES    = $(COMMON_SOURCES) test_lookup_table.cpp
+ot_test_hmac_sha256_LDADD           = $(COMMON_LDADD)
+ot_test_hmac_sha256_LIBTOOLFLAGS    = $(COMMON_LIBTOOLFLAGS)
+ot_test_hmac_sha256_SOURCES         = $(COMMON_SOURCES) test_hmac_sha256.cpp
 
-ot_test_lowpan_LDADD            = $(COMMON_LDADD)
-ot_test_lowpan_SOURCES          = $(COMMON_SOURCES) test_lowpan.cpp
+ot_test_ip4_header_LDADD            = $(COMMON_LDADD)
+ot_test_ip4_header_LIBTOOLFLAGS     = $(COMMON_LIBTOOLFLAGS)
+ot_test_ip4_header_SOURCES          = $(COMMON_SOURCES) test_ip4_header.cpp
 
-ot_test_mac_frame_LDADD         = $(COMMON_LDADD)
-ot_test_mac_frame_SOURCES       = $(COMMON_SOURCES) test_mac_frame.cpp
+ot_test_ip6_header_LDADD            = $(COMMON_LDADD)
+ot_test_ip6_header_LIBTOOLFLAGS     = $(COMMON_LIBTOOLFLAGS)
+ot_test_ip6_header_SOURCES          = $(COMMON_SOURCES) test_ip6_header.cpp
 
-ot_test_macros_LDADD            = $(COMMON_LDADD)
-ot_test_macros_SOURCES          = $(COMMON_SOURCES) test_macros.cpp
+ot_test_ip_address_LDADD            = $(COMMON_LDADD)
+ot_test_ip_address_LIBTOOLFLAGS     = $(COMMON_LIBTOOLFLAGS)
+ot_test_ip_address_SOURCES          = $(COMMON_SOURCES) test_ip_address.cpp
 
-ot_test_message_LDADD           = $(COMMON_LDADD)
-ot_test_message_SOURCES         = $(COMMON_SOURCES) test_message.cpp
+ot_test_link_quality_LDADD          = $(COMMON_LDADD)
+ot_test_link_quality_LIBTOOLFLAGS   = $(COMMON_LIBTOOLFLAGS)
+ot_test_link_quality_SOURCES        = $(COMMON_SOURCES) test_link_quality.cpp
 
-ot_test_message_queue_LDADD     = $(COMMON_LDADD)
-ot_test_message_queue_SOURCES   = $(COMMON_SOURCES) test_message_queue.cpp
+ot_test_linked_list_LDADD           = $(COMMON_LDADD)
+ot_test_linked_list_LIBTOOLFLAGS    = $(COMMON_LIBTOOLFLAGS)
+ot_test_linked_list_SOURCES         = $(COMMON_SOURCES) test_linked_list.cpp
 
-ot_test_multicast_listeners_table_LDADD   = $(COMMON_LDADD)
+ot_test_lowpan_LDADD                = $(COMMON_LDADD)
+ot_test_lowpan_LIBTOOLFLAGS         = $(COMMON_LIBTOOLFLAGS)
+ot_test_lowpan_SOURCES              = $(COMMON_SOURCES) test_lowpan.cpp
+
+ot_test_mac_frame_LDADD             = $(COMMON_LDADD)
+ot_test_mac_frame_LIBTOOLFLAGS      = $(COMMON_LIBTOOLFLAGS)
+ot_test_mac_frame_SOURCES           = $(COMMON_SOURCES) test_mac_frame.cpp
+
+ot_test_macros_LDADD                = $(COMMON_LDADD)
+ot_test_macros_LIBTOOLFLAGS         = $(COMMON_LIBTOOLFLAGS)
+ot_test_macros_SOURCES              = $(COMMON_SOURCES) test_macros.cpp
+
+ot_test_message_LDADD               = $(COMMON_LDADD)
+ot_test_message_LIBTOOLFLAGS        = $(COMMON_LIBTOOLFLAGS)
+ot_test_message_SOURCES             = $(COMMON_SOURCES) test_message.cpp
+
+ot_test_message_queue_LDADD         = $(COMMON_LDADD)
+ot_test_message_queue_LIBTOOLFLAGS  = $(COMMON_LIBTOOLFLAGS)
+ot_test_message_queue_SOURCES       = $(COMMON_SOURCES) test_message_queue.cpp
+
+ot_test_multicast_listeners_table_LDADD = $(COMMON_LDADD)
+ot_test_multicast_listeners_table_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
 ot_test_multicast_listeners_table_SOURCES = $(COMMON_SOURCES) test_multicast_listeners_table.cpp
 
-ot_test_spinel_buffer_LDADD     = $(COMMON_LDADD)
-ot_test_spinel_buffer_SOURCES   = $(COMMON_SOURCES) test_spinel_buffer.cpp
+ot_test_network_name_LDADD          = $(COMMON_LDADD)
+ot_test_network_name_LIBTOOLFLAGS   = $(COMMON_LIBTOOLFLAGS)
+ot_test_network_name_SOURCES        = $(COMMON_SOURCES) test_network_name.cpp
 
-ot_test_ndproxy_table_LDADD     = $(COMMON_LDADD)
-ot_test_ndproxy_table_SOURCES   = $(COMMON_SOURCES) test_ndproxy_table.cpp
+ot_test_spinel_buffer_LDADD         = $(COMMON_LDADD)
+ot_test_spinel_buffer_LIBTOOLFLAGS  = $(COMMON_LIBTOOLFLAGS)
+ot_test_spinel_buffer_SOURCES       = $(COMMON_SOURCES) test_spinel_buffer.cpp
 
-ot_test_netif_LDADD             = $(COMMON_LDADD)
-ot_test_netif_SOURCES           = $(COMMON_SOURCES) test_netif.cpp
+ot_test_ndproxy_table_LDADD         = $(COMMON_LDADD)
+ot_test_ndproxy_table_LIBTOOLFLAGS  = $(COMMON_LIBTOOLFLAGS)
+ot_test_ndproxy_table_SOURCES       = $(COMMON_SOURCES) test_ndproxy_table.cpp
 
-ot_test_network_data_LDADD      = $(COMMON_LDADD)
-ot_test_network_data_SOURCES    = $(COMMON_SOURCES) test_network_data.cpp
+ot_test_netif_LDADD                 = $(COMMON_LDADD)
+ot_test_netif_LIBTOOLFLAGS          = $(COMMON_LIBTOOLFLAGS)
+ot_test_netif_SOURCES               = $(COMMON_SOURCES) test_netif.cpp
 
-ot_test_pool_LDADD              = $(COMMON_LDADD)
-ot_test_pool_SOURCES            = $(COMMON_SOURCES) test_pool.cpp
+ot_test_network_data_LDADD          = $(COMMON_LDADD)
+ot_test_network_data_LIBTOOLFLAGS    = $(COMMON_LIBTOOLFLAGS)
+ot_test_network_data_SOURCES        = $(COMMON_SOURCES) test_network_data.cpp
 
-ot_test_priority_queue_LDADD    = $(COMMON_LDADD)
-ot_test_priority_queue_SOURCES  = $(COMMON_SOURCES) test_priority_queue.cpp
+ot_test_pool_LDADD                  = $(COMMON_LDADD)
+ot_test_pool_LIBTOOLFLAGS           = $(COMMON_LIBTOOLFLAGS)
+ot_test_pool_SOURCES                = $(COMMON_SOURCES) test_pool.cpp
 
-ot_test_pskc_LDADD              = $(COMMON_LDADD)
-ot_test_pskc_SOURCES            = $(COMMON_SOURCES) test_pskc.cpp
+ot_test_priority_queue_LDADD        = $(COMMON_LDADD)
+ot_test_priority_queue_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
+ot_test_priority_queue_SOURCES      = $(COMMON_SOURCES) test_priority_queue.cpp
 
-ot_test_meshcop_LDADD           = $(COMMON_LDADD)
-ot_test_meshcop_SOURCES         = $(COMMON_SOURCES) test_meshcop.cpp
+ot_test_pskc_LDADD                  = $(COMMON_LDADD)
+ot_test_pskc_LIBTOOLFLAGS           = $(COMMON_LIBTOOLFLAGS)
+ot_test_pskc_SOURCES                = $(COMMON_SOURCES) test_pskc.cpp
 
-ot_test_string_LDADD            = $(COMMON_LDADD)
-ot_test_string_SOURCES          = $(COMMON_SOURCES) test_string.cpp
+ot_test_smart_ptrs_LDADD            = $(COMMON_LDADD)
+ot_test_smart_ptrs_LIBTOOLFLAGS     = $(COMMON_LIBTOOLFLAGS)
+ot_test_smart_ptrs_SOURCES          = $(COMMON_SOURCES) test_smart_ptrs.cpp
 
-ot_test_spinel_decoder_LDADD    = $(COMMON_LDADD)
-ot_test_spinel_decoder_SOURCES  = $(COMMON_SOURCES) test_spinel_decoder.cpp
+ot_test_meshcop_LDADD               = $(COMMON_LDADD)
+ot_test_meshcop_LIBTOOLFLAGS        = $(COMMON_LIBTOOLFLAGS)
+ot_test_meshcop_SOURCES             = $(COMMON_SOURCES) test_meshcop.cpp
 
-ot_test_spinel_encoder_LDADD    = $(COMMON_LDADD)
-ot_test_spinel_encoder_SOURCES  = $(COMMON_SOURCES) test_spinel_encoder.cpp
+ot_test_routing_manager_LDADD        = $(COMMON_LDADD)
+ot_test_routing_manager_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
+ot_test_routing_manager_SOURCES      = $(COMMON_SOURCES) test_routing_manager.cpp
 
-ot_test_timer_LDADD             = $(COMMON_LDADD)
-ot_test_timer_SOURCES           = $(COMMON_SOURCES) test_timer.cpp
+ot_test_serial_number_LDADD         = $(COMMON_LDADD)
+ot_test_serial_number_LIBTOOLFLAGS  = $(COMMON_LIBTOOLFLAGS)
+ot_test_serial_number_SOURCES       = $(COMMON_SOURCES) test_serial_number.cpp
 
-ot_test_toolchain_LDADD         = $(NULL)
-ot_test_toolchain_SOURCES       = test_toolchain.cpp test_toolchain_c.c
+ot_test_string_LDADD                = $(COMMON_LDADD)
+ot_test_string_LIBTOOLFLAGS         = $(COMMON_LIBTOOLFLAGS)
+ot_test_string_SOURCES              = $(COMMON_SOURCES) test_string.cpp
+
+ot_test_spinel_decoder_LDADD        = $(COMMON_LDADD)
+ot_test_spinel_decoder_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
+ot_test_spinel_decoder_SOURCES      = $(COMMON_SOURCES) test_spinel_decoder.cpp
+
+ot_test_spinel_encoder_LDADD        = $(COMMON_LDADD)
+ot_test_spinel_encoder_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
+ot_test_spinel_encoder_SOURCES      = $(COMMON_SOURCES) test_spinel_encoder.cpp
+
+ot_test_timer_LDADD                 = $(COMMON_LDADD)
+ot_test_timer_LIBTOOLFLAGS          = $(COMMON_LIBTOOLFLAGS)
+ot_test_timer_SOURCES               = $(COMMON_SOURCES) test_timer.cpp
+
+ot_test_toolchain_LDADD             = $(NULL)
+ot_test_toolchain_SOURCES           = test_toolchain.cpp test_toolchain_c.c
 
 if OPENTHREAD_BUILD_COVERAGE
 CLEANFILES                   = $(wildcard *.gcda *.gcno)
diff --git a/tests/unit/test_aes.cpp b/tests/unit/test_aes.cpp
index 6a9f516..ce75b28 100644
--- a/tests/unit/test_aes.cpp
+++ b/tests/unit/test_aes.cpp
@@ -32,7 +32,7 @@
 #include "crypto/aes_ccm.hpp"
 
 #include "test_platform.h"
-#include "test_util.h"
+#include "test_util.hpp"
 
 /**
  * Verifies test vectors from IEEE 802.15.4-2006 Annex C Section C.2.1
@@ -88,7 +88,7 @@
 /**
  * Verifies test vectors from IEEE 802.15.4-2006 Annex C Section C.2.3
  */
-void TestMacCommandFrame()
+void TestMacCommandFrame(void)
 {
     uint8_t key[] = {
         0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
@@ -100,8 +100,9 @@
         0x00, 0x00, 0x01, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     };
 
-    uint32_t headerLength = 29, payloadLength = 1;
-    uint8_t  tagLength = 8;
+    static constexpr uint32_t kHeaderLength  = 29;
+    static constexpr uint32_t kPayloadLength = 1;
+    static constexpr uint8_t  kTagLength     = 8;
 
     uint8_t encrypted[] = {
         0x2B, 0xDC, 0x84, 0x21, 0x43, 0x02, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE, 0xAC,
@@ -119,28 +120,144 @@
         0xAC, 0xDE, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x06,
     };
 
+    uint8_t tag[kTagLength];
+
+    ot::Instance *     instance = testInitInstance();
+    ot::Message *      message;
     ot::Crypto::AesCcm aesCcm;
+
+    VerifyOrQuit(instance != nullptr);
+
     aesCcm.SetKey(key, sizeof(key));
-    aesCcm.Init(headerLength, payloadLength, tagLength, nonce, sizeof(nonce));
-    aesCcm.Header(test, headerLength);
-    aesCcm.Payload(test + headerLength, test + headerLength, payloadLength, ot::Crypto::AesCcm::kEncrypt);
-    VerifyOrQuit(aesCcm.GetTagLength() == tagLength);
-    aesCcm.Finalize(test + headerLength + payloadLength);
+    aesCcm.Init(kHeaderLength, kPayloadLength, kTagLength, nonce, sizeof(nonce));
+    aesCcm.Header(test, kHeaderLength);
+    aesCcm.Payload(test + kHeaderLength, test + kHeaderLength, kPayloadLength, ot::Crypto::AesCcm::kEncrypt);
+    VerifyOrQuit(aesCcm.GetTagLength() == kTagLength);
+    aesCcm.Finalize(test + kHeaderLength + kPayloadLength);
     VerifyOrQuit(memcmp(test, encrypted, sizeof(encrypted)) == 0);
 
-    aesCcm.Init(headerLength, payloadLength, tagLength, nonce, sizeof(nonce));
-    aesCcm.Header(test, headerLength);
-    aesCcm.Payload(test + headerLength, test + headerLength, payloadLength, ot::Crypto::AesCcm::kDecrypt);
-    VerifyOrQuit(aesCcm.GetTagLength() == tagLength);
-    aesCcm.Finalize(test + headerLength + payloadLength);
+    aesCcm.Init(kHeaderLength, kPayloadLength, kTagLength, nonce, sizeof(nonce));
+    aesCcm.Header(test, kHeaderLength);
+    aesCcm.Payload(test + kHeaderLength, test + kHeaderLength, kPayloadLength, ot::Crypto::AesCcm::kDecrypt);
+    VerifyOrQuit(aesCcm.GetTagLength() == kTagLength);
+    aesCcm.Finalize(test + kHeaderLength + kPayloadLength);
 
     VerifyOrQuit(memcmp(test, decrypted, sizeof(decrypted)) == 0);
+
+    // Verify encryption/decryption in place within a message.
+
+    message = instance->Get<ot::MessagePool>().Allocate(ot::Message::kTypeIp6);
+    VerifyOrQuit(message != nullptr);
+
+    SuccessOrQuit(message->AppendBytes(test, kHeaderLength + kPayloadLength));
+
+    aesCcm.Init(kHeaderLength, kPayloadLength, kTagLength, nonce, sizeof(nonce));
+    aesCcm.Header(test, kHeaderLength);
+
+    aesCcm.Payload(*message, kHeaderLength, kPayloadLength, ot::Crypto::AesCcm::kEncrypt);
+    VerifyOrQuit(aesCcm.GetTagLength() == kTagLength);
+    aesCcm.Finalize(tag);
+    SuccessOrQuit(message->Append(tag));
+    VerifyOrQuit(message->GetLength() == sizeof(encrypted));
+    VerifyOrQuit(message->Compare(0, encrypted));
+
+    aesCcm.Init(kHeaderLength, kPayloadLength, kTagLength, nonce, sizeof(nonce));
+    aesCcm.Header(test, kHeaderLength);
+    aesCcm.Payload(*message, kHeaderLength, kPayloadLength, ot::Crypto::AesCcm::kDecrypt);
+
+    VerifyOrQuit(message->GetLength() == sizeof(encrypted));
+    VerifyOrQuit(message->Compare(0, decrypted));
+
+    message->Free();
+    testFreeInstance(instance);
+}
+
+/**
+ * Verifies in-place encryption/decryption.
+ *
+ */
+void TestInPlaceAesCcmProcessing(void)
+{
+    static constexpr uint16_t kTagLength    = 4;
+    static constexpr uint32_t kHeaderLength = 19;
+
+    static const uint8_t kKey[] = {
+        0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+    };
+
+    static const uint8_t kNonce[] = {
+        0xac, 0xde, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x06,
+    };
+
+    static uint16_t kMessageLengths[] = {30, 400, 800};
+
+    uint8_t tag[kTagLength];
+    uint8_t header[kHeaderLength];
+
+    ot::Crypto::AesCcm aesCcm;
+    ot::Instance *     instance = testInitInstance();
+    ot::Message *      message;
+    ot::Message *      messageClone;
+
+    VerifyOrQuit(instance != nullptr);
+
+    message = instance->Get<ot::MessagePool>().Allocate(ot::Message::kTypeIp6);
+    VerifyOrQuit(message != nullptr);
+
+    aesCcm.SetKey(kKey, sizeof(kKey));
+
+    for (uint16_t msgLength : kMessageLengths)
+    {
+        printf("msgLength %d\n", msgLength);
+
+        SuccessOrQuit(message->SetLength(0));
+
+        for (uint16_t i = msgLength; i != 0; i--)
+        {
+            SuccessOrQuit(message->Append<uint8_t>(i & 0xff));
+        }
+
+        messageClone = message->Clone();
+        VerifyOrQuit(messageClone != nullptr);
+        VerifyOrQuit(messageClone->GetLength() == msgLength);
+
+        SuccessOrQuit(message->Read(0, header));
+
+        // Encrypt in place
+        aesCcm.Init(kHeaderLength, msgLength - kHeaderLength, kTagLength, kNonce, sizeof(kNonce));
+        aesCcm.Header(header);
+        aesCcm.Payload(*message, kHeaderLength, msgLength - kHeaderLength, ot::Crypto::AesCcm::kEncrypt);
+
+        // Append the tag
+        aesCcm.Finalize(tag);
+        SuccessOrQuit(message->Append(tag));
+
+        VerifyOrQuit(message->GetLength() == msgLength + kTagLength);
+
+        // Decrpt in place
+        aesCcm.Init(kHeaderLength, msgLength - kHeaderLength, kTagLength, kNonce, sizeof(kNonce));
+        aesCcm.Header(header);
+        aesCcm.Payload(*message, kHeaderLength, msgLength - kHeaderLength, ot::Crypto::AesCcm::kDecrypt);
+
+        // Check the tag against what is the message
+        aesCcm.Finalize(tag);
+        VerifyOrQuit(message->Compare(msgLength, tag));
+
+        // Check that decrypted message is the same as original (cloned) message
+        VerifyOrQuit(message->CompareBytes(0, *messageClone, 0, msgLength));
+
+        messageClone->Free();
+    }
+
+    message->Free();
+    testFreeInstance(instance);
 }
 
 int main(void)
 {
     TestMacBeaconFrame();
     TestMacCommandFrame();
+    TestInPlaceAesCcmProcessing();
     printf("All tests passed\n");
     return 0;
 }
diff --git a/tests/unit/test_array.cpp b/tests/unit/test_array.cpp
index 5b1e127..0840f99 100644
--- a/tests/unit/test_array.cpp
+++ b/tests/unit/test_array.cpp
@@ -35,6 +35,7 @@
 
 #include "common/array.hpp"
 #include "common/debug.hpp"
+#include "common/equatable.hpp"
 #include "common/instance.hpp"
 #include "common/type_traits.hpp"
 
@@ -175,7 +176,15 @@
 {
     constexpr uint16_t kMaxSize = 10;
 
-    struct Entry
+    enum MatchMode : uint8_t
+    {
+        kMatchAll,
+        kMatchNone,
+        kMatchOddYear,
+        kMatchEvenYear,
+    };
+
+    struct Entry : public Unequatable<Entry>
     {
         Entry(void) = default;
 
@@ -185,16 +194,48 @@
         {
         }
 
-        bool operator==(const Entry &aOther) { return (mName == aOther.mName) && (mYear == aOther.mYear); }
+        bool operator==(const Entry &aOther) const { return (mName == aOther.mName) && (mYear == aOther.mYear); }
         bool Matches(const char *aName) const { return strcmp(aName, mName) == 0; }
         bool Matches(uint16_t aYear) const { return aYear == mYear; }
 
+        bool Matches(MatchMode aMatchMode) const
+        {
+            bool matches = false;
+
+            switch (aMatchMode)
+            {
+            case kMatchAll:
+                matches = true;
+                break;
+            case kMatchNone:
+                matches = false;
+                break;
+            case kMatchOddYear:
+                matches = ((mYear % 2) != 0);
+                break;
+            case kMatchEvenYear:
+                matches = ((mYear % 2) == 0);
+                break;
+            }
+
+            return matches;
+        }
+
         const char *mName;
         uint16_t    mYear;
     };
 
+    static const MatchMode kMatchModes[] = {kMatchAll, kMatchNone, kMatchEvenYear, kMatchOddYear};
+
+    static const char *kMatchModeStrings[] = {
+        "kMatchAll",
+        "kMatchNone",
+        "kMatchOddYear",
+        "kMatchEvenYear",
+    };
+
     Entry ps1("PS", 1994);
-    Entry ps2("PS2", 2000);
+    Entry ps2("PS2", 1999);
     Entry ps3("PS3", 2006);
     Entry ps4("PS4", 2013);
     Entry ps5("PS5", 2020);
@@ -271,6 +312,98 @@
     VerifyOrQuit(array2.FindMatching(static_cast<uint16_t>(2001)) == nullptr);
     VerifyOrQuit(!array2.ContainsMatching(static_cast<uint16_t>(2001)));
 
+    // Test removing of entries at every index.
+
+    array1 = array2;
+
+    for (const Entry &entryToRemove : array1)
+    {
+        Entry *match;
+
+        // Test `Remove()`
+
+        array2 = array1;
+        match  = array2.Find(entryToRemove);
+        VerifyOrQuit(match != nullptr);
+        array2.Remove(*match);
+
+        VerifyOrQuit(array2.GetLength() == array1.GetLength() - 1);
+
+        for (const Entry &entry : array2)
+        {
+            VerifyOrQuit(entry != entryToRemove);
+            VerifyOrQuit(array1.Contains(entry));
+        }
+
+        // Test `RemoveMatching()`
+
+        array2 = array1;
+        array2.RemoveMatching(entryToRemove.mName);
+
+        printf("\n- - - - - - - - - - - - - - - - - - - - - - - - ");
+        printf("\nArray after `RemoveMatching()` on entry %s\n", entryToRemove.mName);
+
+        VerifyOrQuit(array2.GetLength() == array1.GetLength() - 1);
+
+        for (const Entry &entry : array2)
+        {
+            printf("- Name:%-3s Year:%d\n", entry.mName, entry.mYear);
+            VerifyOrQuit(entry != entryToRemove);
+            VerifyOrQuit(array1.Contains(entry));
+        }
+
+        // Test `RemoveMatchin()` with a non-existing match
+
+        array2.RemoveMatching(entryToRemove.mName);
+        VerifyOrQuit(array2.GetLength() == array1.GetLength() - 1);
+
+        // Test `RemoveAllMatching()` removing a single matching entry.
+
+        array2 = array1;
+        array2.RemoveAllMatching(entryToRemove.mName);
+
+        VerifyOrQuit(array2.GetLength() == array1.GetLength() - 1);
+
+        for (const Entry &entry : array2)
+        {
+            VerifyOrQuit(entry != entryToRemove);
+            VerifyOrQuit(array1.Contains(entry));
+        }
+
+        array2.RemoveAllMatching(entryToRemove.mName);
+        VerifyOrQuit(array2.GetLength() == array1.GetLength() - 1);
+
+        // Test `RemoveAllMatching()` using different match modes
+        // removing different subsets.
+
+        for (MatchMode matchMode : kMatchModes)
+        {
+            array3 = array2;
+
+            array3.RemoveAllMatching(matchMode);
+
+            printf("\nArray after `RemoveAllMatching(%s)\n", kMatchModeStrings[matchMode]);
+
+            for (const Entry &entry : array3)
+            {
+                VerifyOrQuit(!entry.Matches(matchMode));
+                VerifyOrQuit(array2.Contains(entry));
+                printf("- Name:%-3s Year:%d\n", entry.mName, entry.mYear);
+            }
+
+            for (const Entry &entry : array2)
+            {
+                if (!entry.Matches(matchMode))
+                {
+                    VerifyOrQuit(array2.Contains(entry));
+                }
+            }
+
+            array3.RemoveAllMatching(kMatchAll);
+            VerifyOrQuit(array3.IsEmpty());
+        }
+    }
+
     printf("\n");
 }
 
diff --git a/tests/unit/test_binary_search.cpp b/tests/unit/test_binary_search.cpp
new file mode 100644
index 0000000..bf05d9f
--- /dev/null
+++ b/tests/unit/test_binary_search.cpp
@@ -0,0 +1,97 @@
+/*
+ *  Copyright (c) 2020, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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 <string.h>
+
+#include "test_platform.h"
+#include "test_util.h"
+
+#include <openthread/config.h>
+
+#include "common/binary_search.hpp"
+#include "common/string.hpp"
+
+namespace ot {
+
+void TestBinarySearch(void)
+{
+    static constexpr uint16_t kMaxNameSize = 30;
+
+    struct Entry
+    {
+        int Compare(const char *aName) const { return strcmp(aName, mName); }
+
+        constexpr static bool AreInOrder(const Entry &aFirst, const Entry &aSecond)
+        {
+            return AreStringsInOrder(aFirst.mName, aSecond.mName);
+        }
+
+        const char *mName;
+        uint8_t     mRank;
+    };
+
+    constexpr Entry kTable[] = {
+        {"arkham city", 9}, {"arkham knight", 7}, {"bloodborne", 10}, {"god of war", 10},       {"horizon", 9},
+        {"infamous", 7},    {"last guardian", 7}, {"last of us", 11}, {"last of us part 2", 8}, {"mass effect", 8},
+        {"sekiro", 10},     {"tomb raider", 9},   {"uncharted", 9},
+    };
+
+    constexpr Entry kUnsortedTable[]       = {{"z", 0}, {"a", 0}, {"b", 0}};
+    constexpr Entry kDuplicateEntryTable[] = {{"duplicate", 1}, {"duplicate", 2}};
+
+    static_assert(BinarySearch::IsSorted(kTable), "IsSorted() failed");
+    static_assert(!BinarySearch::IsSorted(kUnsortedTable), "failed for unsorted table");
+    static_assert(!BinarySearch::IsSorted(kDuplicateEntryTable), "failed for table with duplicate entries");
+
+    for (const Entry &tableEntry : kTable)
+    {
+        const Entry *entry;
+        char         name[kMaxNameSize];
+
+        strcpy(name, tableEntry.mName);
+
+        entry = BinarySearch::Find(name, kTable);
+        VerifyOrQuit(entry == &tableEntry, "BinarySearch::Find() failed");
+
+        name[strlen(name) - 1] = '\0';
+
+        entry = BinarySearch::Find(name, kTable);
+        VerifyOrQuit(entry == nullptr, "BinarySearch::Find() failed with non-matching name");
+    }
+
+    VerifyOrQuit(BinarySearch::Find("dragon age", kTable) == nullptr, "failed with non-exiting match");
+}
+
+} // namespace ot
+
+int main(void)
+{
+    ot::TestBinarySearch();
+    printf("All tests passed\n");
+    return 0;
+}
diff --git a/tests/unit/test_checksum.cpp b/tests/unit/test_checksum.cpp
index 28b834e..101b885 100644
--- a/tests/unit/test_checksum.cpp
+++ b/tests/unit/test_checksum.cpp
@@ -32,6 +32,7 @@
 #include "common/random.hpp"
 #include "net/checksum.hpp"
 #include "net/icmp6.hpp"
+#include "net/ip4_types.hpp"
 #include "net/udp6.hpp"
 
 #include "test_platform.h"
@@ -75,11 +76,7 @@
                            const Message &     aMessage)
 {
     // This method calculates the checksum over an IPv6 message.
-
-    enum : uint16_t
-    {
-        kMaxPayload = 1024,
-    };
+    constexpr uint16_t kMaxPayload = 1024;
 
     OT_TOOL_PACKED_BEGIN
     struct PseudoHeader
@@ -112,6 +109,45 @@
     return CalculateChecksum(&data, sizeof(PseudoHeader) + payloadLength);
 }
 
+uint16_t CalculateChecksum(const Ip4::Address &aSource,
+                           const Ip4::Address &aDestination,
+                           uint8_t             aIpProto,
+                           const Message &     aMessage)
+{
+    // This method calculates the checksum over an IPv4 message.
+    constexpr uint16_t kMaxPayload = 1024;
+
+    OT_TOOL_PACKED_BEGIN
+    struct PseudoHeader
+    {
+        Ip4::Address mSource;
+        Ip4::Address mDestination;
+        uint16_t     mPayloadLength;
+        uint16_t     mProtocol;
+    } OT_TOOL_PACKED_END;
+
+    OT_TOOL_PACKED_BEGIN
+    struct ChecksumData
+    {
+        PseudoHeader mPseudoHeader;
+        uint8_t      mPayload[kMaxPayload];
+    } OT_TOOL_PACKED_END;
+
+    ChecksumData data;
+    uint16_t     payloadLength;
+
+    payloadLength = aMessage.GetLength() - aMessage.GetOffset();
+
+    data.mPseudoHeader.mSource        = aSource;
+    data.mPseudoHeader.mDestination   = aDestination;
+    data.mPseudoHeader.mProtocol      = Encoding::BigEndian::HostSwap16(aIpProto);
+    data.mPseudoHeader.mPayloadLength = Encoding::BigEndian::HostSwap16(payloadLength);
+
+    SuccessOrQuit(aMessage.Read(aMessage.GetOffset(), data.mPayload, payloadLength));
+
+    return CalculateChecksum(&data, sizeof(PseudoHeader) + payloadLength);
+}
+
 void CorruptMessage(Message &aMessage)
 {
     // Change a random bit in the message.
@@ -133,11 +169,8 @@
 
 void TestUdpMessageChecksum(void)
 {
-    enum : uint16_t
-    {
-        kMinSize = sizeof(Ip6::Udp::Header),
-        kMaxSize = kBufferSize * 3 + 24,
-    };
+    constexpr uint16_t kMinSize = sizeof(Ip6::Udp::Header);
+    constexpr uint16_t kMaxSize = kBufferSize * 3 + 24;
 
     const char *kSourceAddress = "fd00:1122:3344:5566:7788:99aa:bbcc:ddee";
     const char *kDestAddress   = "fd01:2345:6789:abcd:ef01:2345:6789:abcd";
@@ -204,11 +237,8 @@
 
 void TestIcmp6MessageChecksum(void)
 {
-    enum : uint16_t
-    {
-        kMinSize = sizeof(Ip6::Icmp::Header),
-        kMaxSize = kBufferSize * 3 + 24,
-    };
+    constexpr uint16_t kMinSize = sizeof(Ip6::Icmp::Header);
+    constexpr uint16_t kMaxSize = kBufferSize * 3 + 24;
 
     const char *kSourceAddress = "fd00:feef:dccd:baab:9889:7667:5444:3223";
     const char *kDestAddress   = "fd01:abab:beef:cafe:1234:5678:9abc:0";
@@ -274,6 +304,149 @@
     }
 }
 
+void TestTcp4MessageChecksum(void)
+{
+    constexpr size_t kMinSize = sizeof(Ip4::Tcp::Header);
+    constexpr size_t kMaxSize = kBufferSize * 3 + 24;
+
+    const char *kSourceAddress = "12.34.56.78";
+    const char *kDestAddress   = "87.65.43.21";
+
+    Ip4::Address sourceAddress;
+    Ip4::Address destAddress;
+
+    Instance *instance = static_cast<Instance *>(testInitInstance());
+
+    VerifyOrQuit(instance != nullptr);
+
+    SuccessOrQuit(sourceAddress.FromString(kSourceAddress));
+    SuccessOrQuit(destAddress.FromString(kDestAddress));
+
+    for (uint16_t size = kMinSize; size <= kMaxSize; size++)
+    {
+        Message *        message = instance->Get<Ip6::Ip6>().NewMessage(sizeof(Ip4::Tcp::Header));
+        Ip4::Tcp::Header tcpHeader;
+
+        VerifyOrQuit(message != nullptr, "Ip6::NewMesssage() failed");
+        SuccessOrQuit(message->SetLength(size));
+
+        // Write TCP header with a random payload.
+
+        Random::NonCrypto::FillBuffer(reinterpret_cast<uint8_t *>(&tcpHeader), sizeof(tcpHeader));
+        message->Write(0, tcpHeader);
+
+        if (size > sizeof(tcpHeader))
+        {
+            uint8_t  buffer[kMaxSize];
+            uint16_t payloadSize = size - sizeof(tcpHeader);
+
+            Random::NonCrypto::FillBuffer(buffer, payloadSize);
+            message->WriteBytes(sizeof(tcpHeader), &buffer[0], payloadSize);
+        }
+
+        // Verify that the `Checksum::UpdateMessageChecksum` correctly
+        // updates the checksum field in the UDP header on the message.
+
+        Checksum::UpdateMessageChecksum(*message, sourceAddress, destAddress, Ip4::kProtoTcp);
+
+        SuccessOrQuit(message->Read(message->GetOffset(), tcpHeader));
+        VerifyOrQuit(tcpHeader.GetChecksum() != 0);
+
+        // Verify that the calculated UDP checksum is valid.
+
+        VerifyOrQuit(CalculateChecksum(sourceAddress, destAddress, Ip4::kProtoTcp, *message) == 0xffff);
+        message->Free();
+    }
+}
+
+void TestUdp4MessageChecksum(void)
+{
+    constexpr uint16_t kMinSize = sizeof(Ip4::Udp::Header);
+    constexpr uint16_t kMaxSize = kBufferSize * 3 + 24;
+
+    const char *kSourceAddress = "12.34.56.78";
+    const char *kDestAddress   = "87.65.43.21";
+
+    Ip4::Address sourceAddress;
+    Ip4::Address destAddress;
+
+    Instance *instance = static_cast<Instance *>(testInitInstance());
+
+    SuccessOrQuit(sourceAddress.FromString(kSourceAddress));
+    SuccessOrQuit(destAddress.FromString(kDestAddress));
+
+    VerifyOrQuit(instance != nullptr);
+
+    for (uint16_t size = kMinSize; size <= kMaxSize; size++)
+    {
+        Message *        message = instance->Get<Ip6::Ip6>().NewMessage(sizeof(Ip4::Udp::Header));
+        Ip4::Udp::Header udpHeader;
+
+        VerifyOrQuit(message != nullptr, "Ip6::NewMesssage() failed");
+        SuccessOrQuit(message->SetLength(size));
+
+        // Write UDP header with a random payload.
+
+        Random::NonCrypto::FillBuffer(reinterpret_cast<uint8_t *>(&udpHeader), sizeof(udpHeader));
+        udpHeader.SetChecksum(0);
+        message->Write(0, udpHeader);
+
+        if (size > sizeof(udpHeader))
+        {
+            uint8_t  buffer[kMaxSize];
+            uint16_t payloadSize = size - sizeof(udpHeader);
+
+            Random::NonCrypto::FillBuffer(buffer, payloadSize);
+            message->WriteBytes(sizeof(udpHeader), &buffer[0], payloadSize);
+        }
+
+        // Verify that the `Checksum::UpdateMessageChecksum` correctly
+        // updates the checksum field in the UDP header on the message.
+
+        Checksum::UpdateMessageChecksum(*message, sourceAddress, destAddress, Ip4::kProtoUdp);
+
+        SuccessOrQuit(message->Read(message->GetOffset(), udpHeader));
+        VerifyOrQuit(udpHeader.GetChecksum() != 0);
+
+        // Verify that the calculated UDP checksum is valid.
+
+        VerifyOrQuit(CalculateChecksum(sourceAddress, destAddress, Ip4::kProtoUdp, *message) == 0xffff);
+        message->Free();
+    }
+}
+
+void TestIcmp4MessageChecksum(void)
+{
+    // A captured ICMP echo request (ping) message. Checksum field is set to zero.
+    const uint8_t kExampleIcmpMessage[] = "\x08\x00\x00\x00\x67\x2e\x00\x00\x62\xaf\xf1\x61\x00\x04\xfc\x24"
+                                          "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17"
+                                          "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27"
+                                          "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37";
+    uint16_t  kChecksumForExampleMessage = 0x5594;
+    Instance *instance                   = static_cast<Instance *>(testInitInstance());
+    Message * message                    = instance->Get<Ip6::Ip6>().NewMessage(sizeof(kExampleIcmpMessage));
+
+    Ip4::Address source;
+    Ip4::Address dest;
+
+    uint8_t           mPayload[sizeof(kExampleIcmpMessage)];
+    Ip4::Icmp::Header icmpHeader;
+
+    SuccessOrQuit(message->AppendBytes(kExampleIcmpMessage, sizeof(kExampleIcmpMessage)));
+
+    // Random IPv4 address, ICMP message checksum does not include a presudo header like TCP and UDP.
+    source.mFields.m32 = 0x12345678;
+    dest.mFields.m32   = 0x87654321;
+
+    Checksum::UpdateMessageChecksum(*message, source, dest, Ip4::kProtoIcmp);
+
+    SuccessOrQuit(message->Read(0, icmpHeader));
+    VerifyOrQuit(icmpHeader.GetChecksum() == kChecksumForExampleMessage);
+
+    SuccessOrQuit(message->Read(message->GetOffset(), mPayload, sizeof(mPayload)));
+    VerifyOrQuit(CalculateChecksum(mPayload, sizeof(mPayload)) == 0xffff);
+}
+
 class ChecksumTester
 {
 public:
@@ -300,6 +473,9 @@
     ot::ChecksumTester::TestExampleVector();
     ot::TestUdpMessageChecksum();
     ot::TestIcmp6MessageChecksum();
+    ot::TestTcp4MessageChecksum();
+    ot::TestUdp4MessageChecksum();
+    ot::TestIcmp4MessageChecksum();
     printf("All tests passed\n");
     return 0;
 }
diff --git a/tests/unit/test_child_table.cpp b/tests/unit/test_child_table.cpp
index 1ce75fc..3281baa 100644
--- a/tests/unit/test_child_table.cpp
+++ b/tests/unit/test_child_table.cpp
@@ -31,6 +31,7 @@
 #include <openthread/config.h>
 
 #include "test_util.h"
+#include "common/array.hpp"
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "thread/child_table.hpp"
@@ -290,7 +291,7 @@
         },
     };
 
-    const uint16_t testListLength = OT_ARRAY_LENGTH(testChildList);
+    const uint16_t testListLength = GetArrayLength(testChildList);
 
     uint16_t testNumAllowedChildren = 2;
 
diff --git a/tests/unit/test_data.cpp b/tests/unit/test_data.cpp
index d1c8948..bd401d9 100644
--- a/tests/unit/test_data.cpp
+++ b/tests/unit/test_data.cpp
@@ -45,8 +45,8 @@
     Data     data;
     Data     data2;
     uint8_t  buffer[sizeof(kData) + 1];
-    uint8_t  u8;
-    uint16_t u16;
+    uint8_t  u8  = 0x12;
+    uint16_t u16 = 0x3456;
 
     data.Clear();
     data2.Clear();
diff --git a/tests/unit/test_dns.cpp b/tests/unit/test_dns.cpp
index 36da5fa..074cb9c 100644
--- a/tests/unit/test_dns.cpp
+++ b/tests/unit/test_dns.cpp
@@ -33,6 +33,7 @@
 #include "test_platform.h"
 #include "test_util.hpp"
 
+#include "common/array.hpp"
 #include "common/instance.hpp"
 #include "net/dns_types.hpp"
 
@@ -64,6 +65,8 @@
     char         label[Dns::Name::kMaxLabelSize];
     uint8_t      labelLength;
     char         name[Dns::Name::kMaxNameSize];
+    const char * subDomain;
+    const char * domain;
 
     static const uint8_t kEncodedName1[] = {7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0};
     static const uint8_t kEncodedName2[] = {3, 'f', 'o', 'o', 1, 'a', 2, 'b', 'b', 3, 'e', 'd', 'u', 0};
@@ -140,46 +143,72 @@
     VerifyOrQuit(instance != nullptr, "Null OpenThread instance");
 
     messagePool = &instance->Get<MessagePool>();
-    VerifyOrQuit((message = messagePool->New(Message::kTypeIp6, 0)) != nullptr, "Message::New failed");
+    VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
 
     message->SetOffset(0);
 
     printf("----------------------------------------------------------------\n");
     printf("Verify domain name match:\n");
 
-    {
-        const char *subDomain;
-        const char *domain;
+    subDomain = "my-service._ipps._tcp.local.";
+    domain    = "local.";
+    VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
 
-        subDomain = "my-service._ipps._tcp.local.";
-        domain    = "local.";
-        VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
+    subDomain = "my-service._ipps._tcp.local";
+    domain    = "local.";
+    VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
 
-        subDomain = "my-service._ipps._tcp.local";
-        domain    = "local.";
-        VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
+    subDomain = "my-service._ipps._tcp.local.";
+    domain    = "local";
+    VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
 
-        subDomain = "my-service._ipps._tcp.local.";
-        domain    = "local";
-        VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
+    subDomain = "my-service._ipps._tcp.local";
+    domain    = "local";
+    VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
 
-        subDomain = "my-service._ipps._tcp.local";
-        domain    = "local";
-        VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
+    subDomain = "my-service._ipps._tcp.default.service.arpa.";
+    domain    = "default.service.arpa.";
+    VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
 
-        subDomain = "my-service._ipps._tcp.default.service.arpa.";
-        domain    = "default.service.arpa.";
-        VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
+    subDomain = "my-service._ipps._tcp.default.service.arpa.";
+    domain    = "service.arpa.";
+    VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
 
-        subDomain = "my-service._ipps._tcp.default.service.arpa.";
-        domain    = "service.arpa.";
-        VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
+    // Verify it doesn't match a portion of a label.
+    subDomain = "my-service._ipps._tcp.default.service.arpa.";
+    domain    = "vice.arpa.";
+    VerifyOrQuit(!Dns::Name::IsSubDomainOf(subDomain, domain));
 
-        // Verify it doesn't match a portion of a label.
-        subDomain = "my-service._ipps._tcp.default.service.arpa.";
-        domain    = "vice.arpa.";
-        VerifyOrQuit(!Dns::Name::IsSubDomainOf(subDomain, domain));
-    }
+    // Validate case does not matter
+
+    subDomain = "my-service._ipps._tcp.local.";
+    domain    = "LOCAL.";
+    VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
+
+    subDomain = "my-service._ipps._tcp.local";
+    domain    = "LOCAL.";
+    VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
+
+    subDomain = "my-service._ipps._tcp.local.";
+    domain    = "LOCAL";
+    VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
+
+    subDomain = "my-service._ipps._tcp.local";
+    domain    = "LOCAL";
+    VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
+
+    subDomain = "my-service._ipps._tcp.Default.Service.ARPA.";
+    domain    = "dEFAULT.Service.arpa.";
+    VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
+
+    subDomain = "my-service._ipps._tcp.default.service.ARpa.";
+    domain    = "SeRvIcE.arPA.";
+    VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain));
+
+    // Verify it doesn't match a portion of a label.
+    subDomain = "my-service._ipps._tcp.default.service.arpa.";
+    domain    = "Vice.arpa.";
+    VerifyOrQuit(!Dns::Name::IsSubDomainOf(subDomain, domain));
 
     printf("----------------------------------------------------------------\n");
     printf("Append names, check encoded bytes, parse name and read labels:\n");
@@ -247,18 +276,33 @@
         {
             uint16_t startOffset = offset;
 
-            SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, test.mLabels[index]));
+            strcpy(label, test.mLabels[index]);
+
+            SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, label));
             VerifyOrQuit(offset != startOffset, "Name::CompareLabel() did not change offset");
 
-            VerifyOrQuit(Dns::Name::CompareLabel(*message, startOffset, kBadLabel) == kErrorNotFound,
+            offset = startOffset;
+            VerifyOrQuit(Dns::Name::CompareLabel(*message, offset, kBadLabel) == kErrorNotFound,
                          "Name::CompareLabel() did not fail with incorrect label");
+
+            StringConvertToUppercase(label);
+
+            offset = startOffset;
+            SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, label));
         }
 
         // Compare the whole name.
+        strcpy(name, test.mExpectedReadName);
+
         offset = 0;
-        SuccessOrQuit(Dns::Name::CompareName(*message, offset, test.mExpectedReadName));
+        SuccessOrQuit(Dns::Name::CompareName(*message, offset, name));
         VerifyOrQuit(offset == len, "Name::CompareName() returned incorrect offset");
 
+        StringConvertToUppercase(name);
+
+        offset = 0;
+        SuccessOrQuit(Dns::Name::CompareName(*message, offset, name));
+
         offset = 0;
         VerifyOrQuit(Dns::Name::CompareName(*message, offset, kBadName) == kErrorNotFound,
                      "Name::CompareName() did not fail with incorrect name");
@@ -425,7 +469,7 @@
     VerifyOrQuit(instance != nullptr, "Null OpenThread instance");
 
     messagePool = &instance->Get<MessagePool>();
-    VerifyOrQuit((message = messagePool->New(Message::kTypeIp6, 0)) != nullptr);
+    VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
 
     // Append name1 "F.ISI.ARPA"
 
@@ -686,7 +730,7 @@
     printf("----------------------------------------------------------------\n");
     printf("Append names from one message to another\n");
 
-    VerifyOrQuit((message2 = messagePool->New(Message::kTypeIp6, 0)) != nullptr);
+    VerifyOrQuit((message2 = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
 
     dnsName1.SetFromMessage(*message, name1Offset);
     dnsName2.SetFromMessage(*message, name2Offset);
@@ -787,7 +831,7 @@
     VerifyOrQuit(instance != nullptr, "Null OpenThread instance");
 
     messagePool = &instance->Get<MessagePool>();
-    VerifyOrQuit((message = messagePool->New(Message::kTypeIp6, 0)) != nullptr);
+    VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
 
     printf("----------------------------------------------------------------\n");
     printf("Preparing the message\n");
@@ -1052,7 +1096,7 @@
     printf("Use FindRecord() to search for specific records:\n");
     printf(" Answer Section\n");
 
-    for (index = 0; index < OT_ARRAY_LENGTH(kInstanceNames); index++)
+    for (index = 0; index < GetArrayLength(kInstanceNames); index++)
     {
         offset = answerSectionOffset;
         SuccessOrQuit(
@@ -1185,14 +1229,15 @@
         {kEncodedTxt5, sizeof(kEncodedTxt5)}, {kEncodedTxt6, sizeof(kEncodedTxt6)},
         {kEncodedTxt7, sizeof(kEncodedTxt7)}};
 
-    Instance *              instance;
-    MessagePool *           messagePool;
-    Message *               message;
-    uint8_t                 txtData[kMaxTxtDataSize];
-    uint16_t                txtDataLength;
-    uint8_t                 index;
-    Dns::TxtEntry           txtEntry;
-    Dns::TxtEntry::Iterator iterator;
+    Instance *                     instance;
+    MessagePool *                  messagePool;
+    Message *                      message;
+    uint8_t                        txtData[kMaxTxtDataSize];
+    uint16_t                       txtDataLength;
+    uint8_t                        index;
+    Dns::TxtEntry                  txtEntry;
+    Dns::TxtEntry::Iterator        iterator;
+    MutableData<kWithUint16Length> data;
 
     printf("================================================================\n");
     printf("TestDnsTxtEntry()\n");
@@ -1201,16 +1246,19 @@
     VerifyOrQuit(instance != nullptr);
 
     messagePool = &instance->Get<MessagePool>();
-    VerifyOrQuit((message = messagePool->New(Message::kTypeIp6, 0)) != nullptr);
+    VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
 
-    SuccessOrQuit(Dns::TxtEntry::AppendEntries(kTxtEntries, OT_ARRAY_LENGTH(kTxtEntries), *message));
-
-    txtDataLength = message->GetLength();
+    data.Init(txtData, sizeof(txtData));
+    SuccessOrQuit(Dns::TxtEntry::AppendEntries(kTxtEntries, GetArrayLength(kTxtEntries), data));
+    VerifyOrQuit(data.GetBytes() == txtData);
+    txtDataLength = data.GetLength();
     VerifyOrQuit(txtDataLength < kMaxTxtDataSize, "TXT data is too long");
-
-    SuccessOrQuit(message->Read(0, txtData, txtDataLength));
     DumpBuffer("txt data", txtData, txtDataLength);
 
+    SuccessOrQuit(Dns::TxtEntry::AppendEntries(kTxtEntries, GetArrayLength(kTxtEntries), *message));
+    VerifyOrQuit(txtDataLength == message->GetLength());
+    VerifyOrQuit(message->CompareBytes(0, txtData, txtDataLength));
+
     index = 0;
     for (const EncodedTxtData &encodedData : kEncodedTxtData)
     {
@@ -1272,12 +1320,17 @@
     // Verify appending empty txt data
 
     SuccessOrQuit(message->SetLength(0));
-    SuccessOrQuit(Dns::TxtEntry::AppendEntries(nullptr, 0, *message), "AppendEntries() failed with empty array");
-    txtDataLength = message->GetLength();
+
+    data.Init(txtData, sizeof(txtData));
+    SuccessOrQuit(Dns::TxtEntry::AppendEntries(nullptr, 0, data), "AppendEntries() failed with empty array");
+    txtDataLength = data.GetLength();
     VerifyOrQuit(txtDataLength == sizeof(uint8_t), "Data length is incorrect with empty array");
-    SuccessOrQuit(message->Read(0, txtData, txtDataLength));
     VerifyOrQuit(txtData[0] == 0, "Data is invalid with empty array");
 
+    SuccessOrQuit(Dns::TxtEntry::AppendEntries(nullptr, 0, *message), "AppendEntries() failed with empty array");
+    VerifyOrQuit(message->GetLength() == txtDataLength);
+    VerifyOrQuit(message->CompareBytes(0, txtData, txtDataLength));
+
     SuccessOrQuit(message->SetLength(0));
     txtEntry.mKey         = nullptr;
     txtEntry.mValue       = nullptr;
diff --git a/tests/unit/test_dso.cpp b/tests/unit/test_dso.cpp
new file mode 100644
index 0000000..7b878e8
--- /dev/null
+++ b/tests/unit/test_dso.cpp
@@ -0,0 +1,1240 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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 <openthread/config.h>
+
+#include "test_platform.h"
+#include "test_util.hpp"
+
+#include "common/arg_macros.hpp"
+#include "common/array.hpp"
+#include "common/as_core_type.hpp"
+#include "common/instance.hpp"
+#include "net/dns_dso.hpp"
+
+#if OPENTHREAD_CONFIG_DNS_DSO_ENABLE
+
+extern "C" {
+
+static uint32_t    sNow = 0;
+static uint32_t    sAlarmTime;
+static bool        sAlarmOn = false;
+static otInstance *sInstance;
+
+// Logs a message and adds current time (sNow) as "<hours>:<min>:<secs>.<msec>"
+#define Log(...)                                                                                          \
+    printf("%02u:%02u:%02u.%03u " OT_FIRST_ARG(__VA_ARGS__) "\n", (sNow / 36000000), (sNow / 60000) % 60, \
+           (sNow / 1000) % 60, sNow % 1000 OT_REST_ARGS(__VA_ARGS__))
+
+void otPlatAlarmMilliStop(otInstance *)
+{
+    sAlarmOn = false;
+}
+
+void otPlatAlarmMilliStartAt(otInstance *, uint32_t aT0, uint32_t aDt)
+{
+    sAlarmOn   = true;
+    sAlarmTime = aT0 + aDt;
+
+    Log(" otPlatAlarmMilliStartAt(time:%u.%03u, dt:%u.%03u)", sAlarmTime / 1000, sAlarmTime % 1000,
+        (sAlarmTime - sNow) / 1000, (sAlarmTime - sNow) % 1000);
+}
+
+uint32_t otPlatAlarmMilliGetNow(void)
+{
+    return sNow;
+}
+
+} // extern "C"
+
+void AdvanceTime(uint32_t aDuration)
+{
+    uint32_t time = sNow + aDuration;
+
+    Log(" AdvanceTime for %u.%03u", aDuration / 1000, aDuration % 1000);
+
+    while (sAlarmTime <= time)
+    {
+        sNow = sAlarmTime;
+        otPlatAlarmMilliFired(sInstance);
+    }
+
+    sNow = time;
+}
+
+namespace ot {
+namespace Dns {
+
+OT_TOOL_PACKED_BEGIN
+class TestTlv : public Dso::Tlv
+{
+public:
+    static constexpr Type kType = 0xf800;
+
+    void Init(uint8_t aValue)
+    {
+        Tlv::Init(kType, sizeof(*this) - sizeof(Tlv));
+        mValue = aValue;
+    }
+
+    bool    IsValid(void) const { return GetSize() >= sizeof(*this); }
+    uint8_t GetValue(void) const { return mValue; }
+
+private:
+    uint8_t mValue;
+
+} OT_TOOL_PACKED_END;
+
+extern "C" void otPlatDsoSend(otPlatDsoConnection *aConnection, otMessage *aMessage);
+
+class Connection : public Dso::Connection
+{
+    friend void otPlatDsoSend(otPlatDsoConnection *aConnection, otMessage *aMessage);
+
+public:
+    explicit Connection(Instance &           aInstance,
+                        const char *         aName,
+                        const Ip6::SockAddr &aLocalSockAddr,
+                        const Ip6::SockAddr &aPeerSockAddr)
+        : Dso::Connection(aInstance, aPeerSockAddr, sCallbacks)
+        , mName(aName)
+        , mLocalSockAddr(aLocalSockAddr)
+    {
+        ClearTestFlags();
+    }
+
+    const char *         GetName(void) const { return mName; }
+    const Ip6::SockAddr &GetLocalSockAddr(void) const { return mLocalSockAddr; }
+
+    void ClearTestFlags(void)
+    {
+        mDidGetConnectedSignal          = false;
+        mDidGetSessionEstablishedSignal = false;
+        mDidGetDisconnectSignal         = false;
+        mDidSendMessage                 = false;
+        mDidReceiveMessage              = false;
+        mDidProcessRequest              = false;
+        mDidProcessUnidirectional       = false;
+        mDidProcessResponse             = false;
+    }
+
+    bool DidGetConnectedSignal(void) const { return mDidGetConnectedSignal; }
+    bool DidGetSessionEstablishedSignal(void) const { return mDidGetSessionEstablishedSignal; }
+    bool DidGetDisconnectSignal(void) const { return mDidGetDisconnectSignal; }
+    bool DidSendMessage(void) const { return mDidSendMessage; }
+    bool DidReceiveMessage(void) const { return mDidReceiveMessage; }
+    bool DidProcessRequest(void) const { return mDidProcessRequest; }
+    bool DidProcessUnidirectional(void) const { return mDidProcessUnidirectional; }
+    bool DidProcessResponse(void) const { return mDidProcessResponse; }
+
+    uint8_t               GetLastRxTestTlvValue(void) const { return mLastRxTestTlvValue; }
+    Dns::Header::Response GetLastRxResponseCode(void) const { return mLastRxResponseCode; }
+
+    void SendTestRequestMessage(uint8_t aValue = 0, uint32_t aResponseTimeout = Dso::kResponseTimeout)
+    {
+        MessageId messageId;
+
+        mLastTxTestTlvValue = aValue;
+        SuccessOrQuit(SendRequestMessage(PrepareTestMessage(aValue), messageId, aResponseTimeout));
+    }
+
+    void SendTestUnidirectionalMessage(uint8_t aValue = 0)
+    {
+        mLastTxTestTlvValue = aValue;
+        SuccessOrQuit(SendUnidirectionalMessage(PrepareTestMessage(aValue)));
+    }
+
+private:
+    Message &PrepareTestMessage(uint8_t aValue)
+    {
+        TestTlv  testTlv;
+        Message *message = NewMessage();
+
+        VerifyOrQuit(message != nullptr);
+        testTlv.Init(aValue);
+        SuccessOrQuit(message->Append(testTlv));
+
+        return *message;
+    }
+
+    void ParseTestMessage(const Message &aMessage)
+    {
+        TestTlv  testTlv;
+        Dso::Tlv tlv;
+        uint16_t offset = aMessage.GetOffset();
+
+        // Test message MUST only contain Test TLV and Encryption
+        // Padding TLV.
+
+        SuccessOrQuit(aMessage.Read(offset, testTlv));
+        VerifyOrQuit(testTlv.GetType() == TestTlv::kType);
+        VerifyOrQuit(testTlv.IsValid());
+        offset += testTlv.GetSize();
+        mLastRxTestTlvValue = testTlv.GetValue();
+
+        SuccessOrQuit(aMessage.Read(offset, tlv));
+        VerifyOrQuit(tlv.GetType() == Dso::Tlv::kEncryptionPaddingType);
+        offset += tlv.GetSize();
+
+        VerifyOrQuit(offset == aMessage.GetLength());
+    }
+
+    void SendTestResponseMessage(MessageId aResponseId, uint8_t aValue)
+    {
+        mLastTxTestTlvValue = aValue;
+        SuccessOrQuit(SendResponseMessage(PrepareTestMessage(aValue), aResponseId));
+    }
+
+    //---------------------------------------------------------------------
+    // Callback methods
+
+    void HandleConnected(void) { mDidGetConnectedSignal = true; }
+    void HandleSessionEstablished(void) { mDidGetSessionEstablishedSignal = true; }
+    void HandleDisconnected(void) { mDidGetDisconnectSignal = true; }
+
+    Error ProcessRequestMessage(MessageId aMessageId, const Message &aMessage, Dso::Tlv::Type aPrimaryTlvType)
+    {
+        Error error = kErrorNone;
+
+        Log(" ProcessRequestMessage(primaryTlv:0x%04x) on %s", aPrimaryTlvType, mName);
+        mDidProcessRequest = true;
+
+        VerifyOrExit(aPrimaryTlvType == TestTlv::kType, error = kErrorNotFound);
+        ParseTestMessage(aMessage);
+        SendTestResponseMessage(aMessageId, mLastRxTestTlvValue);
+
+    exit:
+        return error;
+    }
+
+    Error ProcessUnidirectionalMessage(const Message &aMessage, Dso::Tlv::Type aPrimaryTlvType)
+    {
+        Log(" ProcessUnidirectionalMessage(primaryTlv:0x%04x) on %s", aPrimaryTlvType, mName);
+        mDidProcessUnidirectional = true;
+
+        if (aPrimaryTlvType == TestTlv::kType)
+        {
+            ParseTestMessage(aMessage);
+        }
+
+        return kErrorNone;
+    }
+
+    Error ProcessResponseMessage(const Dns::Header &aHeader,
+                                 const Message &    aMessage,
+                                 Dso::Tlv::Type     aResponseTlvType,
+                                 Dso::Tlv::Type     aRequestTlvType)
+    {
+        Error error = kErrorNone;
+
+        mDidProcessResponse = true;
+        mLastRxResponseCode = aHeader.GetResponseCode();
+        Log(" ProcessResponseMessage(responseTlv:0x%04x) on %s (response-Code:%u) ", aResponseTlvType, mName,
+            mLastRxResponseCode);
+
+        VerifyOrExit(mLastRxResponseCode == Dns::Header::kResponseSuccess);
+
+        // During test we only expect a Test TLV response with
+        // a matching TLV value to what was sent last.
+
+        VerifyOrQuit(aResponseTlvType == TestTlv::kType);
+        VerifyOrQuit(aRequestTlvType == TestTlv::kType);
+        ParseTestMessage(aMessage);
+        VerifyOrQuit(mLastRxTestTlvValue == mLastTxTestTlvValue);
+
+    exit:
+        return error;
+    }
+
+    static void HandleConnected(Dso::Connection &aConnection)
+    {
+        static_cast<Connection &>(aConnection).HandleConnected();
+    }
+
+    static void HandleSessionEstablished(Dso::Connection &aConnection)
+    {
+        static_cast<Connection &>(aConnection).HandleSessionEstablished();
+    }
+
+    static void HandleDisconnected(Dso::Connection &aConnection)
+    {
+        static_cast<Connection &>(aConnection).HandleDisconnected();
+    }
+
+    static Error ProcessRequestMessage(Dso::Connection &aConnection,
+                                       MessageId        aMessageId,
+                                       const Message &  aMessage,
+                                       Dso::Tlv::Type   aPrimaryTlvType)
+    {
+        return static_cast<Connection &>(aConnection).ProcessRequestMessage(aMessageId, aMessage, aPrimaryTlvType);
+    }
+
+    static Error ProcessUnidirectionalMessage(Dso::Connection &aConnection,
+                                              const Message &  aMessage,
+                                              Dso::Tlv::Type   aPrimaryTlvType)
+    {
+        return static_cast<Connection &>(aConnection).ProcessUnidirectionalMessage(aMessage, aPrimaryTlvType);
+    }
+
+    static Error ProcessResponseMessage(Dso::Connection &  aConnection,
+                                        const Dns::Header &aHeader,
+                                        const Message &    aMessage,
+                                        Dso::Tlv::Type     aResponseTlvType,
+                                        Dso::Tlv::Type     aRequestTlvType)
+    {
+        return static_cast<Connection &>(aConnection)
+            .ProcessResponseMessage(aHeader, aMessage, aResponseTlvType, aRequestTlvType);
+    }
+
+    const char *          mName;
+    Ip6::SockAddr         mLocalSockAddr;
+    bool                  mDidGetConnectedSignal;
+    bool                  mDidGetSessionEstablishedSignal;
+    bool                  mDidGetDisconnectSignal;
+    bool                  mDidSendMessage;
+    bool                  mDidReceiveMessage;
+    bool                  mDidProcessRequest;
+    bool                  mDidProcessUnidirectional;
+    bool                  mDidProcessResponse;
+    uint8_t               mLastTxTestTlvValue;
+    uint8_t               mLastRxTestTlvValue;
+    Dns::Header::Response mLastRxResponseCode;
+
+    static Callbacks sCallbacks;
+};
+
+Dso::Connection::Callbacks Connection::sCallbacks(Connection::HandleConnected,
+                                                  Connection::HandleSessionEstablished,
+                                                  Connection::HandleDisconnected,
+                                                  Connection::ProcessRequestMessage,
+                                                  Connection::ProcessUnidirectionalMessage,
+                                                  Connection::ProcessResponseMessage);
+
+static constexpr uint16_t kMaxConnections = 5;
+
+static Array<Connection *, kMaxConnections> sConnections;
+
+static Connection *FindPeerConnection(const Connection &aConnetion)
+{
+    Connection *peerConn = nullptr;
+
+    for (Connection *conn : sConnections)
+    {
+        if (conn->GetLocalSockAddr() == aConnetion.GetPeerSockAddr())
+        {
+            peerConn = conn;
+            break;
+        }
+    }
+
+    return peerConn;
+}
+
+extern "C" {
+
+static bool sDsoListening = false;
+
+// This test flag indicates whether the `otPlatDso` API should
+// forward a sent message to the peer connection. It can be set to
+// `false` to drop the messages to test timeout behaviors on the
+// peer.
+static bool sTestDsoForwardMessageToPeer = true;
+
+// This test flag indicate whether when disconnecting a connection
+// (using `otPlatDsoDisconnect()` to signal the peer connection about
+// the disconnect. Default behavior is set to `true`. It can be set
+// to `false` to test certain timeout behavior on peer side.
+static bool sTestDsoSignalDisconnectToPeer = true;
+
+void otPlatDsoEnableListening(otInstance *, bool aEnable)
+{
+    Log(" otPlatDsoEnableListening(%s)", aEnable ? "true" : "false");
+    sDsoListening = aEnable;
+}
+
+void otPlatDsoConnect(otPlatDsoConnection *aConnection, const otSockAddr *aPeerSockAddr)
+{
+    Connection &         conn         = *static_cast<Connection *>(aConnection);
+    Connection *         peerConn     = nullptr;
+    const Ip6::SockAddr &peerSockAddr = AsCoreType(aPeerSockAddr);
+
+    Log(" otPlatDsoConnect(%s, aPeer:0x%04x)", conn.GetName(), peerSockAddr.GetPort());
+
+    VerifyOrQuit(conn.GetPeerSockAddr() == peerSockAddr);
+    VerifyOrQuit(conn.GetState() == Connection::kStateConnecting);
+
+    if (!sDsoListening)
+    {
+        Log("   Server is not listening");
+        ExitNow();
+    }
+
+    peerConn = static_cast<Connection *>(otPlatDsoAccept(otPlatDsoGetInstance(aConnection), aPeerSockAddr));
+
+    if (peerConn == nullptr)
+    {
+        Log("   Request rejected");
+        ExitNow();
+    }
+
+    Log("   Request accepted");
+    VerifyOrQuit(peerConn->GetState() == Connection::kStateConnecting);
+
+    Log("   Signalling `Connected` on peer connection (%s)", peerConn->GetName());
+    otPlatDsoHandleConnected(peerConn);
+
+    Log("   Signalling `Connected` on connection (%s)", conn.GetName());
+    otPlatDsoHandleConnected(aConnection);
+
+exit:
+    return;
+}
+
+void otPlatDsoSend(otPlatDsoConnection *aConnection, otMessage *aMessage)
+{
+    Connection &conn     = *static_cast<Connection *>(aConnection);
+    Connection *peerConn = nullptr;
+
+    Log(" otPlatDsoSend(%s), message-len:%u", conn.GetName(), AsCoreType(aMessage).GetLength());
+
+    VerifyOrQuit(conn.GetState() != Connection::kStateDisconnected);
+    VerifyOrQuit(conn.GetState() != Connection::kStateConnecting);
+    conn.mDidSendMessage = true;
+
+    if (sTestDsoForwardMessageToPeer)
+    {
+        peerConn = FindPeerConnection(conn);
+        VerifyOrQuit(peerConn != nullptr);
+
+        VerifyOrQuit(peerConn->GetState() != Connection::kStateDisconnected);
+        VerifyOrQuit(peerConn->GetState() != Connection::kStateConnecting);
+
+        Log("   Sending the message to peer connection (%s)", peerConn->GetName());
+
+        peerConn->mDidReceiveMessage = true;
+        otPlatDsoHandleReceive(peerConn, aMessage);
+    }
+    else
+    {
+        Log("   Dropping the message");
+    }
+}
+
+void otPlatDsoDisconnect(otPlatDsoConnection *aConnection, otPlatDsoDisconnectMode aMode)
+{
+    Connection &conn     = *static_cast<Connection *>(aConnection);
+    Connection *peerConn = nullptr;
+
+    Log(" otPlatDsoDisconnect(%s, mode:%s)", conn.GetName(),
+        (aMode == OT_PLAT_DSO_DISCONNECT_MODE_GRACEFULLY_CLOSE) ? "close" : "abort");
+
+    VerifyOrQuit(conn.GetState() == Connection::kStateDisconnected);
+
+    if (sTestDsoSignalDisconnectToPeer)
+    {
+        peerConn = FindPeerConnection(conn);
+
+        if (peerConn == nullptr)
+        {
+            Log("   No peer connection found");
+        }
+        else if (peerConn->GetState() == Connection::kStateDisconnected)
+        {
+            Log("   Peer connection (%s) already disconnected", peerConn->GetName());
+        }
+        else
+        {
+            Log("   Signaling `Disconnected` on peer connection (%s)", peerConn->GetName());
+            otPlatDsoHandleDisconnected(peerConn, aMode);
+        }
+    }
+}
+
+} // extern "C"
+
+Dso::Connection *AcceptConnection(Instance &aInstance, const Ip6::SockAddr &aPeerSockAddr)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+
+    Connection *rval = nullptr;
+
+    Log("  AcceptConnection(peer:0x%04x)", aPeerSockAddr.GetPort());
+
+    for (Connection *conn : sConnections)
+    {
+        if (conn->GetLocalSockAddr() == aPeerSockAddr)
+        {
+            VerifyOrQuit(conn->GetState() == Connection::kStateDisconnected);
+            rval = conn;
+            break;
+        }
+    }
+
+    if (rval != nullptr)
+    {
+        Log("   Accepting and returning connection %s", rval->GetName());
+    }
+    else
+    {
+        Log("   Rejecting");
+    }
+
+    return rval;
+}
+
+static constexpr uint8_t kKeepAliveTestIterations = 3;
+
+static void VerifyKeepAliveExchange(Connection &aClientConn,
+                                    Connection &aServerConn,
+                                    uint32_t    aKeepAliveInterval,
+                                    uint8_t     aNumIterations = kKeepAliveTestIterations)
+{
+    for (uint8_t n = 0; n < aNumIterations; n++)
+    {
+        Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+        Log("Test Keep Alive message exchange, iter %d", n + 1);
+
+        aClientConn.ClearTestFlags();
+        aServerConn.ClearTestFlags();
+
+        AdvanceTime(aKeepAliveInterval - 1);
+        VerifyOrQuit(!aClientConn.DidSendMessage());
+        VerifyOrQuit(!aServerConn.DidReceiveMessage());
+        Log("No message before keep alive timeout");
+
+        AdvanceTime(1);
+        VerifyOrQuit(aClientConn.DidSendMessage());
+        VerifyOrQuit(aServerConn.DidReceiveMessage());
+        Log("KeepAlive message exchanged after keep alive time elapses");
+    }
+}
+
+void TestDso(void)
+{
+    static constexpr uint16_t kPortA = 0xaaaa;
+    static constexpr uint16_t kPortB = 0xbbbb;
+
+    static constexpr Dso::Tlv::Type kUnknownTlvType = 0xf801;
+
+    static constexpr uint32_t kRetryDelayInterval  = TimeMilli::SecToMsec(3600);
+    static constexpr uint32_t kLongResponseTimeout = Dso::kResponseTimeout + TimeMilli::SecToMsec(17);
+
+    Instance &            instance = *static_cast<Instance *>(testInitInstance());
+    Ip6::SockAddr         serverSockAddr(kPortA);
+    Ip6::SockAddr         clientSockAddr(kPortB);
+    Connection            serverConn(instance, "serverConn", serverSockAddr, clientSockAddr);
+    Connection            clientConn(instance, "clinetConn", clientSockAddr, serverSockAddr);
+    Message *             message;
+    Dso::Tlv              tlv;
+    Connection::MessageId messageId;
+
+    sNow      = 0;
+    sInstance = &instance;
+
+    SuccessOrQuit(sConnections.PushBack(&serverConn));
+    SuccessOrQuit(sConnections.PushBack(&clientConn));
+
+    VerifyOrQuit(serverConn.GetPeerSockAddr() == clientSockAddr);
+    VerifyOrQuit(clientConn.GetPeerSockAddr() == serverSockAddr);
+
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
+
+    instance.Get<Dso>().StartListening(AcceptConnection);
+
+    VerifyOrQuit(instance.Get<Dso>().FindClientConnection(clientSockAddr) == nullptr);
+    VerifyOrQuit(instance.Get<Dso>().FindServerConnection(clientSockAddr) == nullptr);
+    VerifyOrQuit(instance.Get<Dso>().FindClientConnection(serverSockAddr) == nullptr);
+    VerifyOrQuit(instance.Get<Dso>().FindServerConnection(serverSockAddr) == nullptr);
+
+    Log("-------------------------------------------------------------------------------------------");
+    Log("Connect from client to server");
+
+    clientConn.Connect();
+
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateConnectedButSessionless);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateConnectedButSessionless);
+
+    VerifyOrQuit(clientConn.IsClient());
+    VerifyOrQuit(!clientConn.IsServer());
+
+    VerifyOrQuit(!serverConn.IsClient());
+    VerifyOrQuit(serverConn.IsServer());
+
+    // Note that we find connection with a peer address
+    VerifyOrQuit(instance.Get<Dso>().FindClientConnection(serverSockAddr) == &clientConn);
+    VerifyOrQuit(instance.Get<Dso>().FindServerConnection(serverSockAddr) == nullptr);
+    VerifyOrQuit(instance.Get<Dso>().FindClientConnection(clientSockAddr) == nullptr);
+    VerifyOrQuit(instance.Get<Dso>().FindServerConnection(clientSockAddr) == &serverConn);
+
+    VerifyOrQuit(clientConn.DidGetConnectedSignal());
+    VerifyOrQuit(!clientConn.DidGetSessionEstablishedSignal());
+    VerifyOrQuit(!clientConn.DidGetDisconnectSignal());
+
+    VerifyOrQuit(serverConn.DidGetConnectedSignal());
+    VerifyOrQuit(!serverConn.DidGetSessionEstablishedSignal());
+    VerifyOrQuit(!serverConn.DidGetDisconnectSignal());
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Send keep alive message to establish connection");
+
+    clientConn.ClearTestFlags();
+    serverConn.ClearTestFlags();
+
+    SuccessOrQuit(clientConn.SendKeepAliveMessage());
+
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    VerifyOrQuit(!clientConn.DidGetConnectedSignal());
+    VerifyOrQuit(clientConn.DidGetSessionEstablishedSignal());
+    VerifyOrQuit(!clientConn.DidGetDisconnectSignal());
+
+    VerifyOrQuit(!serverConn.DidGetConnectedSignal());
+    VerifyOrQuit(serverConn.DidGetSessionEstablishedSignal());
+    VerifyOrQuit(!serverConn.DidGetDisconnectSignal());
+
+    VerifyOrQuit(clientConn.GetKeepAliveInterval() == Dso::kDefaultTimeout);
+    VerifyOrQuit(clientConn.GetInactivityTimeout() == Dso::kDefaultTimeout);
+    VerifyOrQuit(serverConn.GetKeepAliveInterval() == Dso::kDefaultTimeout);
+    VerifyOrQuit(serverConn.GetInactivityTimeout() == Dso::kDefaultTimeout);
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Close connection");
+
+    clientConn.ClearTestFlags();
+    serverConn.ClearTestFlags();
+
+    clientConn.Disconnect(Connection::kGracefullyClose, Connection::kReasonInactivityTimeout);
+
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
+
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonPeerClosed);
+
+    VerifyOrQuit(!clientConn.DidGetConnectedSignal());
+    VerifyOrQuit(!clientConn.DidGetSessionEstablishedSignal());
+    VerifyOrQuit(!clientConn.DidGetDisconnectSignal());
+
+    VerifyOrQuit(!serverConn.DidGetConnectedSignal());
+    VerifyOrQuit(!serverConn.DidGetSessionEstablishedSignal());
+    VerifyOrQuit(serverConn.DidGetDisconnectSignal());
+
+    VerifyOrQuit(instance.Get<Dso>().FindClientConnection(clientSockAddr) == nullptr);
+    VerifyOrQuit(instance.Get<Dso>().FindServerConnection(clientSockAddr) == nullptr);
+    VerifyOrQuit(instance.Get<Dso>().FindClientConnection(serverSockAddr) == nullptr);
+    VerifyOrQuit(instance.Get<Dso>().FindServerConnection(serverSockAddr) == nullptr);
+
+    Log("-------------------------------------------------------------------------------------------");
+    Log("Connection timeout when server is not listening");
+
+    instance.Get<Dso>().StopListening();
+
+    clientConn.ClearTestFlags();
+
+    clientConn.Connect();
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateConnecting);
+    VerifyOrQuit(instance.Get<Dso>().FindClientConnection(serverSockAddr) == &clientConn);
+    VerifyOrQuit(instance.Get<Dso>().FindServerConnection(serverSockAddr) == nullptr);
+
+    AdvanceTime(Dso::kConnectingTimeout);
+
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonFailedToConnect);
+    VerifyOrQuit(instance.Get<Dso>().FindClientConnection(serverSockAddr) == nullptr);
+    VerifyOrQuit(instance.Get<Dso>().FindServerConnection(serverSockAddr) == nullptr);
+
+    VerifyOrQuit(!clientConn.DidGetConnectedSignal());
+    VerifyOrQuit(!clientConn.DidGetSessionEstablishedSignal());
+    VerifyOrQuit(clientConn.DidGetDisconnectSignal());
+
+    Log("-------------------------------------------------------------------------------------------");
+    Log("Keep Alive Timeout behavior");
+
+    // Keep Alive timeout smaller than min value should be rejected.
+    VerifyOrQuit(clientConn.SetTimeouts(Dso::kInfiniteTimeout, Dso::kMinKeepAliveInterval - 1) == kErrorInvalidArgs);
+
+    instance.Get<Dso>().StartListening(AcceptConnection);
+    SuccessOrQuit(serverConn.SetTimeouts(Dso::kInfiniteTimeout, Dso::kMinKeepAliveInterval));
+
+    VerifyOrQuit(serverConn.GetKeepAliveInterval() == Dso::kMinKeepAliveInterval);
+    VerifyOrQuit(serverConn.GetInactivityTimeout() == Dso::kInfiniteTimeout);
+
+    clientConn.Connect();
+    SuccessOrQuit(clientConn.SendKeepAliveMessage());
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    VerifyOrQuit(serverConn.GetKeepAliveInterval() == Dso::kMinKeepAliveInterval);
+    VerifyOrQuit(serverConn.GetInactivityTimeout() == Dso::kInfiniteTimeout);
+    VerifyOrQuit(clientConn.GetKeepAliveInterval() == Dso::kMinKeepAliveInterval);
+    VerifyOrQuit(clientConn.GetInactivityTimeout() == Dso::kInfiniteTimeout);
+
+    VerifyKeepAliveExchange(clientConn, serverConn, Dso::kMinKeepAliveInterval);
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Change Keep Alive interval on server");
+
+    clientConn.ClearTestFlags();
+    serverConn.ClearTestFlags();
+
+    SuccessOrQuit(serverConn.SetTimeouts(Dso::kInfiniteTimeout, Dso::kDefaultTimeout));
+
+    VerifyOrQuit(serverConn.DidSendMessage());
+    VerifyOrQuit(clientConn.DidReceiveMessage());
+    VerifyOrQuit(!clientConn.DidSendMessage());
+
+    VerifyOrQuit(serverConn.GetKeepAliveInterval() == Dso::kDefaultTimeout);
+    VerifyOrQuit(serverConn.GetInactivityTimeout() == Dso::kInfiniteTimeout);
+    VerifyOrQuit(clientConn.GetKeepAliveInterval() == Dso::kDefaultTimeout);
+    VerifyOrQuit(clientConn.GetInactivityTimeout() == Dso::kInfiniteTimeout);
+
+    VerifyKeepAliveExchange(clientConn, serverConn, Dso::kDefaultTimeout);
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Keep Alive timer clear on message send or receive");
+
+    clientConn.ClearTestFlags();
+    serverConn.ClearTestFlags();
+
+    AdvanceTime(Dso::kDefaultTimeout / 2);
+
+    clientConn.SendTestUnidirectionalMessage();
+    VerifyOrQuit(clientConn.DidSendMessage());
+    VerifyOrQuit(serverConn.DidReceiveMessage());
+    VerifyOrQuit(!serverConn.DidSendMessage());
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+    Log("Sent unidirectional message (client->server) at half the keep alive interval");
+    VerifyKeepAliveExchange(clientConn, serverConn, Dso::kDefaultTimeout, 1);
+
+    clientConn.ClearTestFlags();
+    serverConn.ClearTestFlags();
+
+    AdvanceTime(Dso::kDefaultTimeout / 2);
+
+    serverConn.SendTestUnidirectionalMessage();
+    VerifyOrQuit(serverConn.DidSendMessage());
+    VerifyOrQuit(clientConn.DidReceiveMessage());
+    VerifyOrQuit(!clientConn.DidSendMessage());
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+    Log("Sent unidirectional message (server->client) at half the keep alive interval");
+    VerifyKeepAliveExchange(clientConn, serverConn, Dso::kDefaultTimeout, 1);
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Keep Alive timeout on server");
+
+    clientConn.ClearTestFlags();
+    serverConn.ClearTestFlags();
+
+    Log("Drop all sent message (drop Keep Alive msg from client->server)");
+    sTestDsoForwardMessageToPeer = false;
+
+    AdvanceTime(Dso::kDefaultTimeout);
+    VerifyOrQuit(clientConn.DidSendMessage());
+    VerifyOrQuit(!serverConn.DidReceiveMessage());
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    Log("Sever waits for twice the interval before Keep Alive timeout");
+    AdvanceTime(Dso::kDefaultTimeout);
+
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonKeepAliveTimeout);
+
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonPeerAborted);
+    Log("Server aborted connection on Keep Alive timeout");
+    sTestDsoForwardMessageToPeer = true;
+
+    Log("-------------------------------------------------------------------------------------------");
+    Log("Inactivity Timeout behavior");
+
+    SuccessOrQuit(serverConn.SetTimeouts(Dso::kDefaultTimeout, Dso::kMinKeepAliveInterval));
+
+    VerifyOrQuit(serverConn.GetKeepAliveInterval() == Dso::kMinKeepAliveInterval);
+    VerifyOrQuit(serverConn.GetInactivityTimeout() == Dso::kDefaultTimeout);
+
+    clientConn.Connect();
+    SuccessOrQuit(clientConn.SendKeepAliveMessage());
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    VerifyOrQuit(serverConn.GetKeepAliveInterval() == Dso::kMinKeepAliveInterval);
+    VerifyOrQuit(serverConn.GetInactivityTimeout() == Dso::kDefaultTimeout);
+    VerifyOrQuit(clientConn.GetKeepAliveInterval() == Dso::kMinKeepAliveInterval);
+    VerifyOrQuit(clientConn.GetInactivityTimeout() == Dso::kDefaultTimeout);
+
+    Log("Sending a unidirectional message should clear inactivity timer");
+    AdvanceTime(Dso::kDefaultTimeout / 2);
+    clientConn.SendTestUnidirectionalMessage();
+
+    AdvanceTime(Dso::kDefaultTimeout - 1);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+    Log("Client keeps the connection up to the inactivity timeout");
+
+    AdvanceTime(1);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonPeerClosed);
+    Log("Client closes the connection gracefully on inactivity timeout");
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Increasing inactivity timeout in middle");
+
+    clientConn.Connect();
+    SuccessOrQuit(clientConn.SendKeepAliveMessage());
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    AdvanceTime(TimeMilli::SecToMsec(10));
+    Log("After 10 sec elapses, change the inactivity timeout from 15 to 20 sec");
+    SuccessOrQuit(serverConn.SetTimeouts(TimeMilli::SecToMsec(20), Dso::kMinKeepAliveInterval));
+
+    AdvanceTime(TimeMilli::SecToMsec(10) - 1);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+    Log("Client keeps the connection up to new 20 sec inactivity timeout");
+
+    AdvanceTime(1);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonPeerClosed);
+    Log("Client closes the connection gracefully on inactivity timeout of 20 sec");
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Decreasing inactivity timeout in middle");
+
+    clientConn.Connect();
+    SuccessOrQuit(clientConn.SendKeepAliveMessage());
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    AdvanceTime(TimeMilli::SecToMsec(10));
+    Log("After 10 sec elapses, change the inactivity timeout from 15 to 10 sec");
+    SuccessOrQuit(serverConn.SetTimeouts(TimeMilli::SecToMsec(10), Dso::kMinKeepAliveInterval));
+
+    AdvanceTime(0);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonPeerClosed);
+    Log("Client closes the connection gracefully on new shorter inactivity timeout of 10 sec");
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Changing inactivity timeout from infinite to finite");
+
+    SuccessOrQuit(serverConn.SetTimeouts(Dso::kDefaultTimeout, Dso::kInfiniteTimeout));
+    clientConn.Connect();
+    SuccessOrQuit(clientConn.SendKeepAliveMessage());
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    AdvanceTime(TimeMilli::SecToMsec(6));
+    Log("After 6 sec, change the inactivity to infinite");
+    SuccessOrQuit(serverConn.SetTimeouts(Dso::kInfiniteTimeout, Dso::kInfiniteTimeout));
+
+    AdvanceTime(TimeMilli::SecToMsec(4));
+    Log("After 4 sec, change the inactivity timeout from infinite to 20 sec");
+    SuccessOrQuit(serverConn.SetTimeouts(TimeMilli::SecToMsec(20), Dso::kInfiniteTimeout));
+
+    AdvanceTime(TimeMilli::SecToMsec(10) - 1);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    AdvanceTime(1);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonPeerClosed);
+    Log("Client closes the connection gracefully after 20 sec since last activity");
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Tracking activity while inactivity timeout is infinite");
+
+    SuccessOrQuit(serverConn.SetTimeouts(Dso::kInfiniteTimeout, Dso::kInfiniteTimeout));
+    clientConn.Connect();
+    SuccessOrQuit(clientConn.SendKeepAliveMessage());
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    AdvanceTime(TimeMilli::SecToMsec(7));
+    Log("After 7 sec, send a test message, this clears inactivity timer");
+    serverConn.SendTestUnidirectionalMessage();
+
+    AdvanceTime(TimeMilli::SecToMsec(10));
+    Log("After 10 sec, change the inactivity timeout from infinite to 15 sec");
+    SuccessOrQuit(serverConn.SetTimeouts(TimeMilli::SecToMsec(15), Dso::kInfiniteTimeout));
+
+    AdvanceTime(TimeMilli::SecToMsec(5) - 1);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    AdvanceTime(1);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonPeerClosed);
+    Log("Client closes the connection gracefully after 15 sec since last activity");
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Inactivity timeout on server");
+
+    clientConn.Connect();
+    SuccessOrQuit(clientConn.SendKeepAliveMessage());
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    SuccessOrQuit(serverConn.SetTimeouts(Dso::kDefaultTimeout, Dso::kInfiniteTimeout));
+
+    Log("Wait for inactivity timeout and ensure client disconnect");
+    Log("Configure test for client not to signal its disconnect to server");
+    sTestDsoSignalDisconnectToPeer = false;
+
+    AdvanceTime(Dso::kDefaultTimeout);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+    sTestDsoSignalDisconnectToPeer = true;
+
+    Log("Server should disconnect after twice the inactivity timeout");
+    AdvanceTime(Dso::kDefaultTimeout - 1);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+    AdvanceTime(1);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Server reducing inactivity timeout to expired (on server)");
+
+    clientConn.Connect();
+    SuccessOrQuit(clientConn.SendKeepAliveMessage());
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+    SuccessOrQuit(serverConn.SetTimeouts(Dso::kDefaultTimeout, Dso::kInfiniteTimeout));
+
+    AdvanceTime(TimeMilli::SecToMsec(10));
+    Log("After 11 sec elapses, change the inactivity timeout from 15 to 2 sec");
+    SuccessOrQuit(serverConn.SetTimeouts(TimeMilli::SecToMsec(2), Dso::kMinKeepAliveInterval));
+
+    sTestDsoSignalDisconnectToPeer = false;
+    AdvanceTime(0);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
+    sTestDsoSignalDisconnectToPeer = true;
+    Log("Client closes the connection gracefully on expired timeout");
+    Log("Configure test for client not to signal its disconnect to server");
+
+    AdvanceTime(Dso::kMinServerInactivityWaitTime - 1);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+    AdvanceTime(1);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
+    Log("Server wait for kMinServerInactivityWaitTime (5 sec) before closing on expired timeout");
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Long-lived operation");
+
+    clientConn.Connect();
+    SuccessOrQuit(clientConn.SendKeepAliveMessage());
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+    SuccessOrQuit(serverConn.SetTimeouts(Dso::kDefaultTimeout, Dso::kInfiniteTimeout));
+
+    clientConn.SetLongLivedOperation(true);
+    serverConn.SetLongLivedOperation(true);
+
+    AdvanceTime(2 * Dso::kDefaultTimeout);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    clientConn.SetLongLivedOperation(false);
+    AdvanceTime(0);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
+
+    Log("-------------------------------------------------------------------------------------------");
+    Log("Request, response, and unidirectional message exchange");
+
+    SuccessOrQuit(serverConn.SetTimeouts(Dso::kDefaultTimeout, Dso::kDefaultTimeout));
+    clientConn.Connect();
+
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateConnectedButSessionless);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateConnectedButSessionless);
+
+    clientConn.ClearTestFlags();
+    serverConn.ClearTestFlags();
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Establish connection using test message request/response");
+    clientConn.SendTestRequestMessage();
+
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.DidProcessRequest());
+    VerifyOrQuit(clientConn.DidProcessResponse());
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Send unidirectional test message");
+
+    serverConn.ClearTestFlags();
+    clientConn.SendTestUnidirectionalMessage(0x10);
+    VerifyOrQuit(serverConn.DidProcessUnidirectional());
+    VerifyOrQuit(serverConn.GetLastRxTestTlvValue() == 0x10);
+
+    clientConn.ClearTestFlags();
+    serverConn.SendTestUnidirectionalMessage(0x20);
+    VerifyOrQuit(clientConn.DidProcessUnidirectional());
+    VerifyOrQuit(clientConn.GetLastRxTestTlvValue() == 0x20);
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Exchange request and response");
+
+    clientConn.ClearTestFlags();
+    serverConn.ClearTestFlags();
+    serverConn.SendTestRequestMessage(0x30);
+    VerifyOrQuit(clientConn.DidProcessRequest());
+    VerifyOrQuit(!clientConn.DidProcessResponse());
+    VerifyOrQuit(!serverConn.DidProcessRequest());
+    VerifyOrQuit(serverConn.DidProcessResponse());
+    VerifyOrQuit(serverConn.GetLastRxTestTlvValue() == 0x30);
+    VerifyOrQuit(clientConn.GetLastRxTestTlvValue() == 0x30);
+
+    clientConn.ClearTestFlags();
+    serverConn.ClearTestFlags();
+    clientConn.SendTestRequestMessage(0x40);
+    VerifyOrQuit(!clientConn.DidProcessRequest());
+    VerifyOrQuit(clientConn.DidProcessResponse());
+    VerifyOrQuit(serverConn.DidProcessRequest());
+    VerifyOrQuit(!serverConn.DidProcessResponse());
+    VerifyOrQuit(serverConn.GetLastRxTestTlvValue() == 0x40);
+    VerifyOrQuit(clientConn.GetLastRxTestTlvValue() == 0x40);
+
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Send unknown TLV request");
+
+    clientConn.ClearTestFlags();
+    serverConn.ClearTestFlags();
+
+    message = clientConn.NewMessage();
+    VerifyOrQuit(message != nullptr);
+    tlv.Init(kUnknownTlvType, 0);
+    SuccessOrQuit(message->Append(tlv));
+    SuccessOrQuit(clientConn.SendRequestMessage(*message, messageId));
+
+    VerifyOrQuit(!clientConn.DidProcessRequest());
+    VerifyOrQuit(clientConn.DidProcessResponse());
+    VerifyOrQuit(serverConn.DidProcessRequest());
+    VerifyOrQuit(!serverConn.DidProcessResponse());
+    VerifyOrQuit(clientConn.GetLastRxResponseCode() == Dns::Header::kDsoTypeNotImplemented);
+    Log("Received a response with DSO Type Unknown error code");
+
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Send unknown TLV unidirectional");
+
+    clientConn.ClearTestFlags();
+    serverConn.ClearTestFlags();
+
+    message = clientConn.NewMessage();
+    VerifyOrQuit(message != nullptr);
+    tlv.Init(kUnknownTlvType, 0);
+    SuccessOrQuit(message->Append(tlv));
+    SuccessOrQuit(clientConn.SendUnidirectionalMessage(*message));
+    VerifyOrQuit(serverConn.DidProcessUnidirectional());
+    Log("Unknown TLV unidirectional is correctly ignored");
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Send malformed/invalid request");
+
+    clientConn.ClearTestFlags();
+    serverConn.ClearTestFlags();
+
+    message = clientConn.NewMessage();
+    VerifyOrQuit(message != nullptr);
+    tlv.Init(Dso::Tlv::kEncryptionPaddingType, 0);
+    SuccessOrQuit(message->Append(tlv));
+
+    SuccessOrQuit(serverConn.SendRequestMessage(*message, messageId));
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonPeerMisbehavior);
+    VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonPeerAborted);
+    VerifyOrQuit(clientConn.DidGetDisconnectSignal());
+    VerifyOrQuit(serverConn.DidGetDisconnectSignal());
+    Log("Client aborted on invalid request message");
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Response timeout during session establishment");
+
+    clientConn.ClearTestFlags();
+    serverConn.ClearTestFlags();
+
+    SuccessOrQuit(serverConn.SetTimeouts(Dso::kResponseTimeout, Dso::kInfiniteTimeout));
+    clientConn.Connect();
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateConnectedButSessionless);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateConnectedButSessionless);
+
+    sTestDsoForwardMessageToPeer = false;
+    clientConn.SendTestRequestMessage();
+    sTestDsoForwardMessageToPeer = true;
+
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateEstablishingSession);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateConnectedButSessionless);
+
+    sTestDsoSignalDisconnectToPeer = false;
+    AdvanceTime(Dso::kResponseTimeout);
+    sTestDsoSignalDisconnectToPeer = true;
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonResponseTimeout);
+    VerifyOrQuit(clientConn.DidGetDisconnectSignal());
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateConnectedButSessionless);
+    Log("Client disconnected after response timeout");
+
+    AdvanceTime(Dso::kResponseTimeout);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonInactivityTimeout);
+    VerifyOrQuit(serverConn.DidGetDisconnectSignal());
+    Log("Server disconnected after twice the inactivity timeout");
+
+    Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
+    Log("Response timeout after session establishment");
+
+    clientConn.ClearTestFlags();
+    serverConn.ClearTestFlags();
+
+    SuccessOrQuit(serverConn.SetTimeouts(Dso::kInfiniteTimeout, Dso::kInfiniteTimeout));
+    clientConn.Connect();
+    SuccessOrQuit(clientConn.SendKeepAliveMessage());
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    sTestDsoForwardMessageToPeer = false;
+    serverConn.SendTestRequestMessage();
+    sTestDsoForwardMessageToPeer = true;
+
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    AdvanceTime(Dso::kResponseTimeout - 1);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    AdvanceTime(1);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonResponseTimeout);
+    VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonPeerAborted);
+    VerifyOrQuit(serverConn.DidGetDisconnectSignal());
+    VerifyOrQuit(clientConn.DidGetDisconnectSignal());
+
+    clientConn.ClearTestFlags();
+    serverConn.ClearTestFlags();
+
+    SuccessOrQuit(serverConn.SetTimeouts(Dso::kInfiniteTimeout, Dso::kInfiniteTimeout));
+    clientConn.Connect();
+    SuccessOrQuit(clientConn.SendKeepAliveMessage());
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    sTestDsoForwardMessageToPeer = false;
+    serverConn.SendTestRequestMessage(0, kLongResponseTimeout);
+    sTestDsoForwardMessageToPeer = true;
+
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    AdvanceTime(kLongResponseTimeout - 1);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    AdvanceTime(1);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonResponseTimeout);
+    VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonPeerAborted);
+    VerifyOrQuit(serverConn.DidGetDisconnectSignal());
+    VerifyOrQuit(clientConn.DidGetDisconnectSignal());
+
+    Log("-------------------------------------------------------------------------------------------");
+    Log("Retry Delay message");
+
+    clientConn.ClearTestFlags();
+    serverConn.ClearTestFlags();
+
+    SuccessOrQuit(serverConn.SetTimeouts(Dso::kInfiniteTimeout, Dso::kInfiniteTimeout));
+    clientConn.Connect();
+    SuccessOrQuit(clientConn.SendKeepAliveMessage());
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateSessionEstablished);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateSessionEstablished);
+
+    SuccessOrQuit(serverConn.SendRetryDelayMessage(kRetryDelayInterval, Dns::Header::kResponseServerFailure));
+
+    VerifyOrQuit(clientConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(serverConn.GetState() == Connection::kStateDisconnected);
+    VerifyOrQuit(clientConn.DidGetDisconnectSignal());
+    VerifyOrQuit(serverConn.DidGetDisconnectSignal());
+    VerifyOrQuit(clientConn.GetDisconnectReason() == Connection::kReasonServerRetryDelayRequest);
+    VerifyOrQuit(serverConn.GetDisconnectReason() == Connection::kReasonPeerClosed);
+
+    VerifyOrQuit(clientConn.GetRetryDelay() == kRetryDelayInterval);
+    VerifyOrQuit(clientConn.GetRetryDelayErrorCode() == Dns::Header::kResponseServerFailure);
+
+    Log("End of test");
+
+    testFreeInstance(&instance);
+}
+
+} // namespace Dns
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_DNS_DSO_ENABLE
+
+int main(void)
+{
+#if OPENTHREAD_CONFIG_DNS_DSO_ENABLE
+    ot::Dns::TestDso();
+    printf("All tests passed\n");
+#else
+    printf("DSO feature is not enabled\n");
+#endif
+
+    return 0;
+}
diff --git a/tests/unit/test_ecdsa.cpp b/tests/unit/test_ecdsa.cpp
index 852c20b..533ebcc 100644
--- a/tests/unit/test_ecdsa.cpp
+++ b/tests/unit/test_ecdsa.cpp
@@ -129,7 +129,7 @@
 {
     Instance *instance = testInitInstance();
 
-    const char *kMessage = "You are not a drop in the ocean. You are the entire ocean in a drop.";
+    const char kMessage[] = "You are not a drop in the ocean. You are the entire ocean in a drop.";
 
     Ecdsa::P256::KeyPair   keyPair;
     Ecdsa::P256::PublicKey publicKey;
diff --git a/tests/unit/test_frame_builder.cpp b/tests/unit/test_frame_builder.cpp
new file mode 100644
index 0000000..cbc09c0
--- /dev/null
+++ b/tests/unit/test_frame_builder.cpp
@@ -0,0 +1,150 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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 <openthread/config.h>
+
+#include "test_platform.h"
+#include "test_util.hpp"
+
+#include "common/frame_builder.hpp"
+
+namespace ot {
+
+void TestFrameBuilder(void)
+{
+    const uint8_t kData1[] = {0x01, 0x02, 0x03, 0x04, 0x05};
+    const uint8_t kData2[] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa};
+
+    static constexpr uint16_t kMaxBufferSize = sizeof(kData1) * 2 + sizeof(kData2);
+
+    Instance *   instance;
+    Message *    message;
+    uint16_t     offset;
+    uint8_t      buffer[kMaxBufferSize];
+    uint8_t      zeroBuffer[kMaxBufferSize];
+    FrameBuilder frameBuilder;
+
+    printf("TestFrameBuilder\n");
+
+    instance = static_cast<Instance *>(testInitInstance());
+    VerifyOrQuit(instance != nullptr);
+
+    message = instance->Get<MessagePool>().Allocate(Message::kTypeIp6);
+    VerifyOrQuit(message != nullptr);
+
+    SuccessOrQuit(message->Append(kData1));
+    SuccessOrQuit(message->Append(kData2));
+
+    memset(buffer, 0, sizeof(buffer));
+    memset(zeroBuffer, 0, sizeof(zeroBuffer));
+
+    frameBuilder.Init(buffer, sizeof(buffer));
+
+    VerifyOrQuit(frameBuilder.GetBytes() == buffer);
+    VerifyOrQuit(frameBuilder.GetLength() == 0);
+    VerifyOrQuit(frameBuilder.GetMaxLength() == sizeof(buffer));
+    VerifyOrQuit(memcmp(buffer, zeroBuffer, sizeof(buffer)) == 0);
+    VerifyOrQuit(frameBuilder.CanAppend(sizeof(buffer)));
+    VerifyOrQuit(!frameBuilder.CanAppend(sizeof(buffer) + 1));
+
+    SuccessOrQuit(frameBuilder.Append(kData1));
+    VerifyOrQuit(frameBuilder.GetLength() == sizeof(kData1));
+    VerifyOrQuit(frameBuilder.GetBytes() == buffer);
+    VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
+    VerifyOrQuit(memcmp(buffer + sizeof(kData1), zeroBuffer, sizeof(buffer) - sizeof(kData1)) == 0);
+
+    SuccessOrQuit(frameBuilder.AppendUint8(0x01));
+    SuccessOrQuit(frameBuilder.AppendBigEndianUint16(0x0203));
+    SuccessOrQuit(frameBuilder.AppendLittleEndianUint16(0x0504));
+    VerifyOrQuit(frameBuilder.GetLength() == sizeof(kData1) * 2);
+    VerifyOrQuit(frameBuilder.GetBytes() == buffer);
+    VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
+    VerifyOrQuit(memcmp(buffer + sizeof(kData1), kData1, sizeof(kData1)) == 0);
+
+    SuccessOrQuit(frameBuilder.AppendBigEndianUint32(0x01020304));
+    SuccessOrQuit(frameBuilder.AppendUint8(0x05));
+    VerifyOrQuit(frameBuilder.GetLength() == sizeof(kData1) * 3);
+    VerifyOrQuit(frameBuilder.GetBytes() == buffer);
+    VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
+    VerifyOrQuit(memcmp(buffer + sizeof(kData1), kData1, sizeof(kData1)) == 0);
+    VerifyOrQuit(memcmp(buffer + 2 * sizeof(kData1), kData1, sizeof(kData1)) == 0);
+
+    frameBuilder.Init(buffer, sizeof(buffer));
+    VerifyOrQuit(frameBuilder.GetBytes() == buffer);
+    VerifyOrQuit(frameBuilder.GetLength() == 0);
+    VerifyOrQuit(frameBuilder.GetMaxLength() == sizeof(buffer));
+
+    offset = sizeof(kData1);
+    SuccessOrQuit(frameBuilder.AppendBytesFromMessage(*message, offset, sizeof(kData2)));
+    VerifyOrQuit(frameBuilder.GetLength() == sizeof(kData2));
+    VerifyOrQuit(frameBuilder.GetBytes() == buffer);
+    VerifyOrQuit(memcmp(buffer, kData2, sizeof(kData2)) == 0);
+
+    frameBuilder.Init(buffer, sizeof(buffer));
+    VerifyOrQuit(frameBuilder.GetBytes() == buffer);
+    VerifyOrQuit(frameBuilder.GetLength() == 0);
+    VerifyOrQuit(frameBuilder.GetMaxLength() == sizeof(buffer));
+
+    SuccessOrQuit(frameBuilder.AppendLittleEndianUint32(0x04030201));
+    SuccessOrQuit(frameBuilder.AppendUint8(0x05));
+    VerifyOrQuit(frameBuilder.GetLength() == sizeof(kData1));
+    VerifyOrQuit(frameBuilder.GetBytes() == buffer);
+    VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
+
+    SuccessOrQuit(frameBuilder.AppendBytes(zeroBuffer, sizeof(kData2)));
+    SuccessOrQuit(frameBuilder.Append(kData1));
+    VerifyOrQuit(frameBuilder.GetLength() == sizeof(buffer));
+    VerifyOrQuit(frameBuilder.GetBytes() == buffer);
+    VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
+    VerifyOrQuit(memcmp(buffer + sizeof(kData1), zeroBuffer, sizeof(kData2)) == 0);
+    VerifyOrQuit(memcmp(buffer + sizeof(kData1) + sizeof(kData2), kData1, sizeof(kData1)) == 0);
+
+    VerifyOrQuit(!frameBuilder.CanAppend(1));
+    VerifyOrQuit(frameBuilder.AppendUint8(0x00) == kErrorNoBufs);
+
+    offset = sizeof(kData1);
+    frameBuilder.Write(offset, kData2);
+    VerifyOrQuit(frameBuilder.GetLength() == sizeof(buffer));
+    VerifyOrQuit(frameBuilder.GetBytes() == buffer);
+    VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
+    VerifyOrQuit(memcmp(buffer + sizeof(kData1), kData2, sizeof(kData2)) == 0);
+    VerifyOrQuit(memcmp(buffer + sizeof(kData1) + sizeof(kData2), kData1, sizeof(kData1)) == 0);
+
+    message->Free();
+    testFreeInstance(instance);
+}
+
+} // namespace ot
+
+int main(void)
+{
+    ot::TestFrameBuilder();
+
+    printf("All tests passed\n");
+    return 0;
+}
diff --git a/tests/unit/test_heap_array.cpp b/tests/unit/test_heap_array.cpp
new file mode 100644
index 0000000..2ed9535
--- /dev/null
+++ b/tests/unit/test_heap_array.cpp
@@ -0,0 +1,494 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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 "test_platform.h"
+
+#include <string.h>
+
+#include <openthread/config.h>
+
+#include "test_util.hpp"
+
+#include "common/heap_array.hpp"
+#include "common/type_traits.hpp"
+
+namespace ot {
+
+// Counters tracking number of times `Entry` constructor and
+// destructor are invoked. These are used to verify that the `Array`
+// properly calls constructor/destructor when allocating and copying
+// array buffer.
+static uint16_t sConstructorCalls = 0;
+static uint16_t sDestructorCalls  = 0;
+
+class Entry
+{
+public:
+    Entry(void)
+        : mValue(0)
+        , mInitialized(true)
+    {
+        sConstructorCalls++;
+    }
+
+    explicit Entry(uint16_t aValue)
+        : mValue(aValue)
+        , mInitialized(true)
+    {
+        sConstructorCalls++;
+    }
+
+    Entry(const Entry &aEntry)
+        : mValue(aEntry.mValue)
+        , mInitialized(true)
+    {
+        sConstructorCalls++;
+    }
+
+    ~Entry(void) { sDestructorCalls++; }
+
+    uint16_t GetValue(void) const { return mValue; }
+    void     SetValue(uint16_t aValue) { mValue = aValue; }
+    bool     IsInitialized(void) const { return mInitialized; }
+    bool     operator==(const Entry &aOther) const { return mValue == aOther.mValue; }
+    bool     Matches(uint16_t aValue) const { return mValue == aValue; }
+
+private:
+    uint16_t mValue;
+    bool     mInitialized;
+};
+
+template <typename EntryType>
+void VerifyEntry(const EntryType &aEntry, const Heap::Array<EntryType, 2> &aArray, int aExpectedValue)
+{
+    // Verify the entry in a given array with an expected value.
+    // Specializations of this template are defined below for `EntryType`
+    // being `uint16_t` or `Entry` class.
+
+    OT_UNUSED_VARIABLE(aEntry);
+    OT_UNUSED_VARIABLE(aArray);
+    OT_UNUSED_VARIABLE(aExpectedValue);
+
+    VerifyOrQuit(false, "Specializations of this template method MUST be used instead");
+}
+
+template <> void VerifyEntry(const uint16_t &aEntry, const Heap::Array<uint16_t, 2> &aArray, int aExpectedValue)
+{
+    OT_UNUSED_VARIABLE(aArray);
+    VerifyOrQuit(aEntry == static_cast<uint16_t>(aExpectedValue));
+}
+
+template <> void VerifyEntry(const Entry &aEntry, const Heap::Array<Entry, 2> &aArray, int aExpectedValue)
+{
+    VerifyOrQuit(aEntry.IsInitialized());
+    VerifyOrQuit(aEntry.GetValue() == static_cast<uint16_t>(aExpectedValue));
+
+    VerifyOrQuit(aArray.ContainsMatching(aEntry.GetValue()));
+    VerifyOrQuit(aArray.FindMatching(aEntry.GetValue()) == &aEntry);
+}
+
+template <typename EntryType, typename... Args> void VerifyArray(const Heap::Array<EntryType, 2> &aArray, Args... aArgs)
+{
+    // Verify that array content matches the `aArgs` sequence
+    // (which can be empty).
+
+    constexpr uint16_t kUnusedValue = 0xffff;
+
+    int      values[] = {aArgs..., 0};
+    uint16_t index    = 0;
+
+    printf(" - Array (len:%u, capacity:%u) = { ", aArray.GetLength(), aArray.GetCapacity());
+
+    VerifyOrQuit(aArray.GetLength() == sizeof...(aArgs));
+
+    if (aArray.GetLength() == 0)
+    {
+        VerifyOrQuit(aArray.AsCArray() == nullptr);
+        VerifyOrQuit(aArray.Front() == nullptr);
+        VerifyOrQuit(aArray.Back() == nullptr);
+    }
+    else
+    {
+        VerifyOrQuit(aArray.AsCArray() != nullptr);
+    }
+
+    for (const EntryType &entry : aArray)
+    {
+        VerifyOrQuit(index < aArray.GetLength());
+
+        VerifyEntry(entry, aArray, values[index]);
+
+        VerifyOrQuit(aArray.Contains(entry));
+        VerifyOrQuit(aArray.Find(entry) == &entry);
+        VerifyOrQuit(aArray.IndexOf(entry) == index);
+
+        if (index == 0)
+        {
+            VerifyOrQuit(aArray.Front() == &entry);
+        }
+
+        if (index == aArray.GetLength())
+        {
+            VerifyOrQuit(aArray.Back() == &entry);
+        }
+
+        printf("%u ", values[index]);
+
+        index++;
+    }
+
+    VerifyOrQuit(index == aArray.GetLength());
+
+    VerifyOrQuit(!aArray.Contains(EntryType(kUnusedValue)));
+    VerifyOrQuit(aArray.Find(EntryType(kUnusedValue)) == nullptr);
+
+    if (TypeTraits::IsSame<EntryType, Entry>::kValue)
+    {
+        printf("} (constructor-calls:%u, destructor-calls:%u)\n", sConstructorCalls, sDestructorCalls);
+        VerifyOrQuit(sConstructorCalls - sDestructorCalls == aArray.GetLength());
+    }
+    else
+    {
+        printf("}\n");
+    }
+}
+
+void TestHeapArrayOfUint16(void)
+{
+    Heap::Array<uint16_t, 2> array;
+    Heap::Array<uint16_t, 2> array2;
+    uint16_t *               entry;
+
+    printf("\n\n====================================================================================\n");
+    printf("TestHeapArrayOfUint16\n\n");
+
+    printf("------------------------------------------------------------------------------------\n");
+    printf("After constructor\n");
+    VerifyOrQuit(array.GetCapacity() == 0);
+    VerifyArray(array);
+
+    printf("------------------------------------------------------------------------------------\n");
+    printf("PushBack(aEntry)\n");
+
+    SuccessOrQuit(array.PushBack(1));
+    VerifyArray(array, 1);
+    VerifyOrQuit(array.GetCapacity() == 2);
+
+    SuccessOrQuit(array.PushBack(2));
+    VerifyArray(array, 1, 2);
+    VerifyOrQuit(array.GetCapacity() == 2);
+
+    SuccessOrQuit(array.PushBack(3));
+    VerifyArray(array, 1, 2, 3);
+    VerifyOrQuit(array.GetCapacity() == 4);
+
+    printf("------------------------------------------------------------------------------------\n");
+    printf("entry = PushBack()\n");
+
+    entry = array.PushBack();
+    VerifyOrQuit(entry != nullptr);
+    *entry = 4;
+    VerifyArray(array, 1, 2, 3, 4);
+    VerifyOrQuit(array.GetCapacity() == 4);
+
+    entry = array.PushBack();
+    VerifyOrQuit(entry != nullptr);
+    *entry = 5;
+    VerifyArray(array, 1, 2, 3, 4, 5);
+    VerifyOrQuit(array.GetCapacity() == 6);
+
+    printf("------------------------------------------------------------------------------------\n");
+    printf("Clear()\n");
+
+    array.Clear();
+    VerifyArray(array);
+    VerifyOrQuit(array.GetCapacity() == 6);
+
+    *array.PushBack() = 11;
+    SuccessOrQuit(array.PushBack(22));
+    SuccessOrQuit(array.PushBack(33));
+    SuccessOrQuit(array.PushBack(44));
+    *array.PushBack() = 55;
+
+    VerifyArray(array, 11, 22, 33, 44, 55);
+    VerifyOrQuit(array.GetCapacity() == 6);
+
+    SuccessOrQuit(array.PushBack(66));
+    SuccessOrQuit(array.PushBack(77));
+    VerifyArray(array, 11, 22, 33, 44, 55, 66, 77);
+    VerifyOrQuit(array.GetCapacity() == 8);
+
+    printf("------------------------------------------------------------------------------------\n");
+    printf("PopBack()\n");
+
+    array.PopBack();
+    VerifyArray(array, 11, 22, 33, 44, 55, 66);
+    VerifyOrQuit(array.GetCapacity() == 8);
+
+    array.PopBack();
+    array.PopBack();
+    array.PopBack();
+    array.PopBack();
+    array.PopBack();
+    VerifyArray(array, 11);
+    VerifyOrQuit(array.GetCapacity() == 8);
+
+    array.PopBack();
+    VerifyArray(array);
+    VerifyOrQuit(array.GetCapacity() == 8);
+
+    array.PopBack();
+    VerifyArray(array);
+    VerifyOrQuit(array.GetCapacity() == 8);
+
+    for (uint16_t num = 0; num < 11; num++)
+    {
+        SuccessOrQuit(array.PushBack(num + 0x100));
+    }
+
+    VerifyArray(array, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a);
+    VerifyOrQuit(array.GetCapacity() == 12);
+
+    printf("------------------------------------------------------------------------------------\n");
+    printf("Free()\n");
+
+    array.Free();
+    VerifyArray(array);
+    VerifyOrQuit(array.GetCapacity() == 0);
+
+    array.Free();
+    VerifyArray(array);
+    VerifyOrQuit(array.GetCapacity() == 0);
+
+    printf("------------------------------------------------------------------------------------\n");
+    printf("ReserveCapacity()\n");
+
+    SuccessOrQuit(array.ReserveCapacity(5));
+    VerifyArray(array);
+    VerifyOrQuit(array.GetCapacity() == 5);
+
+    SuccessOrQuit(array.PushBack(0));
+    VerifyArray(array, 0);
+    VerifyOrQuit(array.GetCapacity() == 5);
+
+    for (uint16_t num = 1; num < 5; num++)
+    {
+        SuccessOrQuit(array.PushBack(num));
+    }
+
+    VerifyArray(array, 0, 1, 2, 3, 4);
+    VerifyOrQuit(array.GetCapacity() == 5);
+
+    SuccessOrQuit(array.PushBack(5));
+    VerifyArray(array, 0, 1, 2, 3, 4, 5);
+    VerifyOrQuit(array.GetCapacity() == 7);
+
+    SuccessOrQuit(array.ReserveCapacity(3));
+    VerifyArray(array, 0, 1, 2, 3, 4, 5);
+    VerifyOrQuit(array.GetCapacity() == 7);
+
+    SuccessOrQuit(array.ReserveCapacity(10));
+    VerifyArray(array, 0, 1, 2, 3, 4, 5);
+    VerifyOrQuit(array.GetCapacity() == 10);
+
+    printf("------------------------------------------------------------------------------------\n");
+    printf("TakeFrom()\n");
+
+    for (uint16_t num = 0; num < 7; num++)
+    {
+        SuccessOrQuit(array2.PushBack(num + 0x20));
+    }
+
+    VerifyArray(array2, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26);
+
+    array2.TakeFrom(static_cast<Heap::Array<uint16_t, 2> &&>(array));
+
+    VerifyArray(array);
+    VerifyOrQuit(array.GetCapacity() == 0);
+
+    VerifyArray(array2, 0, 1, 2, 3, 4, 5);
+    VerifyOrQuit(array2.GetCapacity() == 10);
+
+    printf("\n -- PASS\n");
+}
+
+void TestHeapArray(void)
+{
+    VerifyOrQuit(sConstructorCalls == 0);
+    VerifyOrQuit(sDestructorCalls == 0);
+
+    printf("\n\n====================================================================================\n");
+    printf("TestHeapArray\n\n");
+
+    {
+        Heap::Array<Entry, 2> array;
+        Heap::Array<Entry, 2> array2;
+        Entry *               entry;
+
+        printf("------------------------------------------------------------------------------------\n");
+        printf("After constructor\n");
+        VerifyOrQuit(array.GetCapacity() == 0);
+        VerifyArray(array);
+
+        printf("------------------------------------------------------------------------------------\n");
+        printf("PushBack(aEntry)\n");
+
+        SuccessOrQuit(array.PushBack(Entry(1)));
+        VerifyArray(array, 1);
+        VerifyOrQuit(array.GetCapacity() == 2);
+
+        SuccessOrQuit(array.PushBack(Entry(2)));
+        VerifyArray(array, 1, 2);
+        VerifyOrQuit(array.GetCapacity() == 2);
+
+        SuccessOrQuit(array.PushBack(Entry(3)));
+        VerifyArray(array, 1, 2, 3);
+        VerifyOrQuit(array.GetCapacity() == 4);
+
+        entry = array.PushBack();
+        VerifyOrQuit(entry != nullptr);
+        VerifyOrQuit(entry->IsInitialized());
+        VerifyOrQuit(entry->GetValue() == 0);
+        entry->SetValue(4);
+        VerifyArray(array, 1, 2, 3, 4);
+        VerifyOrQuit(array.GetCapacity() == 4);
+
+        entry = array.PushBack();
+        VerifyOrQuit(entry != nullptr);
+        VerifyOrQuit(entry->IsInitialized());
+        VerifyOrQuit(entry->GetValue() == 0);
+        entry->SetValue(5);
+        VerifyArray(array, 1, 2, 3, 4, 5);
+        VerifyOrQuit(array.GetCapacity() == 6);
+
+        printf("------------------------------------------------------------------------------------\n");
+        printf("PopBack()\n");
+
+        array.PopBack();
+        VerifyArray(array, 1, 2, 3, 4);
+        VerifyOrQuit(array.GetCapacity() == 6);
+
+        array.PopBack();
+        VerifyArray(array, 1, 2, 3);
+        VerifyOrQuit(array.GetCapacity() == 6);
+
+        SuccessOrQuit(array.PushBack(Entry(7)));
+        VerifyArray(array, 1, 2, 3, 7);
+        VerifyOrQuit(array.GetCapacity() == 6);
+
+        array.PopBack();
+        VerifyArray(array, 1, 2, 3);
+        VerifyOrQuit(array.GetCapacity() == 6);
+
+        printf("------------------------------------------------------------------------------------\n");
+        printf("Clear()\n");
+
+        array.Clear();
+        VerifyArray(array);
+        VerifyOrQuit(array.GetCapacity() == 6);
+
+        for (uint16_t num = 0; num < 11; num++)
+        {
+            SuccessOrQuit(array.PushBack(Entry(num)));
+        }
+
+        VerifyArray(array, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+        VerifyOrQuit(array.GetCapacity() == 12);
+
+        printf("------------------------------------------------------------------------------------\n");
+        printf("Free()\n");
+        array.Free();
+        VerifyArray(array);
+        VerifyOrQuit(array.GetCapacity() == 0);
+
+        printf("------------------------------------------------------------------------------------\n");
+        printf("ReserveCapacity()\n");
+
+        SuccessOrQuit(array.ReserveCapacity(5));
+        VerifyArray(array);
+        VerifyOrQuit(array.GetCapacity() == 5);
+
+        SuccessOrQuit(array.PushBack(Entry(0)));
+        VerifyArray(array, 0);
+        VerifyOrQuit(array.GetCapacity() == 5);
+
+        for (uint16_t num = 1; num < 5; num++)
+        {
+            SuccessOrQuit(array.PushBack(Entry(num)));
+        }
+
+        VerifyArray(array, 0, 1, 2, 3, 4);
+        VerifyOrQuit(array.GetCapacity() == 5);
+
+        SuccessOrQuit(array.PushBack(Entry(5)));
+        VerifyArray(array, 0, 1, 2, 3, 4, 5);
+        VerifyOrQuit(array.GetCapacity() == 7);
+
+        SuccessOrQuit(array.ReserveCapacity(3));
+        VerifyArray(array, 0, 1, 2, 3, 4, 5);
+        VerifyOrQuit(array.GetCapacity() == 7);
+
+        SuccessOrQuit(array.ReserveCapacity(10));
+        VerifyArray(array, 0, 1, 2, 3, 4, 5);
+        VerifyOrQuit(array.GetCapacity() == 10);
+
+        printf("------------------------------------------------------------------------------------\n");
+        printf("TakeFrom()\n");
+
+        for (uint16_t num = 0; num < 7; num++)
+        {
+            SuccessOrQuit(array2.PushBack(Entry(num + 0x20)));
+        }
+
+        array2.TakeFrom(static_cast<Heap::Array<Entry, 2> &&>(array));
+
+        VerifyOrQuit(array.GetLength() == 0);
+        VerifyOrQuit(array.GetCapacity() == 0);
+
+        VerifyArray(array2, 0, 1, 2, 3, 4, 5);
+        VerifyOrQuit(array2.GetCapacity() == 10);
+    }
+
+    printf("------------------------------------------------------------------------------------\n");
+    printf("Array destructor\n");
+    printf(" - (constructor-calls:%u, destructor-calls:%u)\n", sConstructorCalls, sDestructorCalls);
+    VerifyOrQuit(sConstructorCalls == sDestructorCalls,
+                 "Array destructor failed to invoke destructor on all its existing entries");
+
+    printf("\n -- PASS\n");
+}
+
+} // namespace ot
+
+int main(void)
+{
+    ot::TestHeapArrayOfUint16();
+    ot::TestHeapArray();
+    printf("\nAll tests passed.\n");
+    return 0;
+}
diff --git a/tests/unit/test_heap_string.cpp b/tests/unit/test_heap_string.cpp
index b61c424..b7973c2 100644
--- a/tests/unit/test_heap_string.cpp
+++ b/tests/unit/test_heap_string.cpp
@@ -34,11 +34,12 @@
 
 #include "test_util.hpp"
 #include "common/code_utils.hpp"
+#include "common/heap_data.hpp"
 #include "common/heap_string.hpp"
 
 namespace ot {
 
-void PrintString(const char *aName, const HeapString &aString)
+void PrintString(const char *aName, const Heap::String &aString)
 {
     if (aString.IsNull())
     {
@@ -50,7 +51,7 @@
     }
 }
 
-void VerifyString(const char *aName, const HeapString &aString, const char *aExpectedString)
+void VerifyString(const char *aName, const Heap::String &aString, const char *aExpectedString)
 {
     PrintString(aName, aString);
 
@@ -71,10 +72,10 @@
     VerifyOrQuit(aString == aExpectedString);
 }
 
-// Function returning a `HeapString` by value.
-HeapString GetName(void)
+// Function returning a `Heap::String` by value.
+Heap::String GetName(void)
 {
-    HeapString name;
+    Heap::String name;
 
     SuccessOrQuit(name.Set("name"));
 
@@ -83,9 +84,12 @@
 
 void TestHeapString(void)
 {
-    HeapString  str1;
-    HeapString  str2;
-    const char *oldBuffer;
+    Heap::String str1;
+    Heap::String str2;
+    const char * oldBuffer;
+
+    printf("====================================================================================\n");
+    printf("TestHeapString\n\n");
 
     printf("------------------------------------------------------------------------------------\n");
     printf("After constructor\n\n");
@@ -107,7 +111,7 @@
     printf("\tDid reuse its old buffer (same length): %s\n", str1.AsCString() == oldBuffer ? "yes" : "no");
 
     printf("------------------------------------------------------------------------------------\n");
-    printf("Set(const HeapString &)\n\n");
+    printf("Set(const Heap::String &)\n\n");
     SuccessOrQuit(str2.Set(str1));
     VerifyString("str2", str2, str1.AsCString());
 
@@ -146,11 +150,173 @@
     printf("\n -- PASS\n");
 }
 
+void PrintData(const Heap::Data &aData)
+{
+    DumpBuffer("data", aData.GetBytes(), aData.GetLength());
+}
+
+static const uint8_t kTestValue = 0x77;
+
+// Function returning a `Heap::Data` by value.
+Heap::Data GetData(void)
+{
+    Heap::Data data;
+
+    SuccessOrQuit(data.SetFrom(&kTestValue, sizeof(kTestValue)));
+
+    return data;
+}
+
+void VerifyData(const Heap::Data &aData, const uint8_t *aBytes, uint16_t aLength)
+{
+    static constexpr uint16_t kMaxLength = 100;
+    uint8_t                   buffer[kMaxLength];
+
+    PrintData(aData);
+
+    if (aLength == 0)
+    {
+        VerifyOrQuit(aData.IsNull());
+        VerifyOrQuit(aData.GetBytes() == nullptr);
+        VerifyOrQuit(aData.GetLength() == 0);
+    }
+    else
+    {
+        VerifyOrQuit(!aData.IsNull());
+        VerifyOrQuit(aData.GetBytes() != nullptr);
+        VerifyOrQuit(aData.GetLength() == aLength);
+        VerifyOrQuit(memcmp(aData.GetBytes(), aBytes, aLength) == 0, "Data content is incorrect");
+
+        aData.CopyBytesTo(buffer);
+        VerifyOrQuit(memcmp(buffer, aBytes, aLength) == 0, "CopyBytesTo() failed");
+    }
+}
+
+template <uint16_t kLength> void VerifyData(const Heap::Data &aData, const uint8_t (&aArray)[kLength])
+{
+    VerifyData(aData, &aArray[0], kLength);
+}
+
+void TestHeapData(void)
+{
+    Instance *     instance;
+    MessagePool *  messagePool;
+    Message *      message;
+    Heap::Data     data;
+    uint16_t       offset;
+    const uint8_t *oldBuffer;
+
+    static const uint8_t kData1[] = {10, 20, 3, 15, 100, 0, 60, 16};
+    static const uint8_t kData2[] = "OpenThread HeapData";
+    static const uint8_t kData3[] = {0xaa, 0xbb, 0xcc};
+    static const uint8_t kData4[] = {0x11, 0x22, 0x33};
+
+    instance = static_cast<Instance *>(testInitInstance());
+    VerifyOrQuit(instance != nullptr, "Null OpenThread instance");
+
+    messagePool = &instance->Get<MessagePool>();
+    VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
+
+    message->SetOffset(0);
+
+    printf("\n\n====================================================================================\n");
+    printf("TestHeapData\n\n");
+
+    printf("------------------------------------------------------------------------------------\n");
+    printf("After constructor\n");
+    VerifyData(data, nullptr, 0);
+
+    printf("------------------------------------------------------------------------------------\n");
+    printf("SetFrom(aBuffer, aLength)\n");
+
+    SuccessOrQuit(data.SetFrom(kData1, sizeof(kData1)));
+    VerifyData(data, kData1);
+
+    SuccessOrQuit(data.SetFrom(kData2, sizeof(kData2)));
+    VerifyData(data, kData2);
+
+    SuccessOrQuit(data.SetFrom(kData3, sizeof(kData3)));
+    VerifyData(data, kData3);
+    oldBuffer = data.GetBytes();
+
+    SuccessOrQuit(data.SetFrom(kData4, sizeof(kData4)));
+    VerifyData(data, kData4);
+    VerifyOrQuit(oldBuffer == data.GetBytes(), "did not reuse old buffer on same data length");
+
+    SuccessOrQuit(data.SetFrom(kData4, 0));
+    VerifyData(data, nullptr, 0);
+
+    printf("------------------------------------------------------------------------------------\n");
+    printf("SetFrom(aMessage)\n");
+
+    SuccessOrQuit(message->Append(kData2));
+    SuccessOrQuit(data.SetFrom(*message));
+    VerifyData(data, kData2);
+
+    SuccessOrQuit(message->Append(kData3));
+    SuccessOrQuit(data.SetFrom(*message));
+    PrintData(data);
+    VerifyOrQuit(data.GetLength() == message->GetLength());
+
+    message->SetOffset(sizeof(kData2));
+    SuccessOrQuit(data.SetFrom(*message));
+    VerifyData(data, kData3);
+
+    SuccessOrQuit(message->Append(kData4));
+
+    offset = 0;
+    SuccessOrQuit(data.SetFrom(*message, offset, sizeof(kData2)));
+    VerifyData(data, kData2);
+
+    offset = sizeof(kData2);
+    SuccessOrQuit(data.SetFrom(*message, offset, sizeof(kData3)));
+    VerifyData(data, kData3);
+
+    offset += sizeof(kData3);
+    SuccessOrQuit(data.SetFrom(*message, offset, sizeof(kData4)));
+    VerifyData(data, kData4);
+
+    VerifyOrQuit(data.SetFrom(*message, offset, sizeof(kData4) + 1) == kErrorParse);
+    VerifyOrQuit(data.SetFrom(*message, 0, message->GetLength() + 1) == kErrorParse);
+    VerifyOrQuit(data.SetFrom(*message, 1, message->GetLength()) == kErrorParse);
+
+    printf("------------------------------------------------------------------------------------\n");
+    printf("Free()\n");
+
+    data.Free();
+    VerifyData(data, nullptr, 0);
+
+    data.Free();
+    VerifyData(data, nullptr, 0);
+
+    printf("------------------------------------------------------------------------------------\n");
+    printf("CopyBytesTo(aMessage)\n");
+
+    SuccessOrQuit(message->SetLength(0));
+
+    SuccessOrQuit(data.CopyBytesTo(*message));
+    VerifyOrQuit(message->GetLength() == 0, "CopyBytesTo() failed");
+
+    SuccessOrQuit(data.SetFrom(kData1, sizeof(kData1)));
+    VerifyData(data, kData1);
+    SuccessOrQuit(data.CopyBytesTo(*message));
+    VerifyOrQuit(message->GetLength() == data.GetLength(), "CopyBytesTo() failed");
+    VerifyOrQuit(message->Compare(0, kData1), "CopyBytesTo() failed");
+
+    printf("------------------------------------------------------------------------------------\n");
+    printf("SetFrom() move semantics\n\n");
+    data.SetFrom(GetData());
+    VerifyData(data, &kTestValue, sizeof(kTestValue));
+
+    printf("\n -- PASS\n");
+}
+
 } // namespace ot
 
 int main(void)
 {
     ot::TestHeapString();
+    ot::TestHeapData();
     printf("\nAll tests passed.\n");
     return 0;
 }
diff --git a/tests/unit/test_hkdf_sha256.cpp b/tests/unit/test_hkdf_sha256.cpp
index 08cfb4b..ca12be6 100644
--- a/tests/unit/test_hkdf_sha256.cpp
+++ b/tests/unit/test_hkdf_sha256.cpp
@@ -28,13 +28,14 @@
 
 #include <openthread/config.h>
 
-#include "common/debug.hpp"
-#include "crypto/hkdf_sha256.hpp"
-
 #include "test_platform.h"
 #include "test_util.h"
 #include "test_util.hpp"
 
+#include "common/array.hpp"
+#include "common/debug.hpp"
+#include "crypto/hkdf_sha256.hpp"
+
 struct TestVector
 {
     const uint8_t *mInKey;
@@ -125,7 +126,7 @@
 
     VerifyOrQuit(instance != nullptr);
 
-    for (const TestVector *test = &kTestVectors[0]; test < OT_ARRAY_END(kTestVectors); test++)
+    for (const TestVector *test = &kTestVectors[0]; test < ot::GetArrayEnd(kTestVectors); test++)
     {
         ot::Crypto::HkdfSha256 hkdf;
         uint8_t                outKey[kMaxOuttKey];
diff --git a/tests/unit/test_hmac_sha256.cpp b/tests/unit/test_hmac_sha256.cpp
index 7e22978..5c9a978 100644
--- a/tests/unit/test_hmac_sha256.cpp
+++ b/tests/unit/test_hmac_sha256.cpp
@@ -28,6 +28,7 @@
 
 #include <openthread/config.h>
 
+#include "common/array.hpp"
 #include "common/debug.hpp"
 #include "common/message.hpp"
 #include "crypto/hmac_sha256.hpp"
@@ -87,13 +88,13 @@
     Instance *   instance = testInitInstance();
     MessagePool *messagePool;
     Message *    message;
-    uint16_t     offsets[OT_ARRAY_LENGTH(kTestCases)];
+    uint16_t     offsets[GetArrayLength(kTestCases)];
     uint8_t      index;
 
     VerifyOrQuit(instance != nullptr);
 
     messagePool = &instance->Get<MessagePool>();
-    VerifyOrQuit((message = messagePool->New(Message::kTypeIp6, 0)) != nullptr);
+    VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
 
     for (const TestCase &testCase : kTestCases)
     {
@@ -228,7 +229,7 @@
     Instance *   instance = testInitInstance();
     MessagePool *messagePool;
     Message *    message;
-    uint16_t     offsets[OT_ARRAY_LENGTH(kTestCases)];
+    uint16_t     offsets[GetArrayLength(kTestCases)];
     uint8_t      index;
 
     printf("TestHmacSha256\n");
@@ -236,7 +237,7 @@
     VerifyOrQuit(instance != nullptr);
 
     messagePool = &instance->Get<MessagePool>();
-    VerifyOrQuit((message = messagePool->New(Message::kTypeIp6, 0)) != nullptr);
+    VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
 
     for (const TestCase &testCase : kTestCases)
     {
diff --git a/tests/unit/test_ip4_header.cpp b/tests/unit/test_ip4_header.cpp
new file mode 100644
index 0000000..e9021a8
--- /dev/null
+++ b/tests/unit/test_ip4_header.cpp
@@ -0,0 +1,132 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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 "common/encoding.hpp"
+#include "net/ip4_types.hpp"
+
+#include "test_util.hpp"
+
+using ot::Encoding::BigEndian::ReadUint16;
+
+namespace ot {
+namespace Ip4 {
+
+void VerifyEcnDscp(const Header &aHeader, uint8_t aDscp, Ecn aEcn)
+{
+    uint8_t expectedDscpEcn = static_cast<uint8_t>((aDscp << 2) + aEcn);
+
+    printf("%02x {dscp:%d, ecn:%d}\n", aHeader.GetDscpEcn(), aHeader.GetDscp(), aHeader.GetEcn());
+
+    VerifyOrQuit(aHeader.GetDscp() == aDscp);
+    VerifyOrQuit(aHeader.GetEcn() == aEcn);
+    VerifyOrQuit(aHeader.GetDscpEcn() == expectedDscpEcn);
+}
+
+void TestIp4Header(void)
+{
+    static constexpr uint16_t kTotalLength = 84;
+    static constexpr uint8_t  kTtl         = 64;
+
+    const uint8_t kDscps[]            = {0x0, 0x1, 0x3, 0xf, 0x30, 0x2f, 0x3f};
+    const Ecn     kEcns[]             = {Ecn::kEcnNotCapable, Ecn::kEcnCapable0, Ecn::kEcnCapable1, Ecn::kEcnMarked};
+    const uint8_t kExampleIp4Header[] = "\x45\x00\x00\x54\x23\xed\x00\x00\x40\x01\x41\xd1\x0a\x00\x00\xeb"
+                                        "\x0a\x00\x00\x01";
+
+    Header         header;
+    Address        source;
+    Address        destination;
+    const uint8_t *headerBytes = reinterpret_cast<const uint8_t *>(&header);
+
+    SuccessOrQuit(source.FromString("10.0.0.235"), "Address::FromString() failed");
+    SuccessOrQuit(destination.FromString("10.0.0.1"), "Address::FromString() failed");
+
+    header.InitVersionIhl();
+
+    header.Clear();
+    header.InitVersionIhl();
+    VerifyOrQuit(header.IsValid());
+    VerifyOrQuit(header.GetTotalLength() == 0);
+    VerifyOrQuit(header.GetProtocol() == 0);
+    VerifyOrQuit(header.GetTtl() == 0);
+    VerifyOrQuit(header.GetSource().mFields.m32 == 0);
+    VerifyOrQuit(header.GetDestination().mFields.m32 == 0);
+    VerifyOrQuit(header.GetFragmentOffset() == 0);
+
+    header.SetTotalLength(kTotalLength);
+    header.SetProtocol(Ip4::kProtoIcmp);
+    header.SetTtl(kTtl);
+    header.SetSource(source);
+    header.SetDestination(destination);
+
+    VerifyOrQuit(header.IsValid());
+    VerifyOrQuit(header.GetProtocol() == kProtoIcmp);
+    VerifyOrQuit(header.GetTtl() == kTtl);
+    VerifyOrQuit(header.GetSource() == source);
+    VerifyOrQuit(header.GetDestination() == destination);
+
+    // Verify the offsets to different fields.
+
+    VerifyOrQuit(ReadUint16(headerBytes + Header::kTotalLengthOffset) == kTotalLength, "kTotalLength is incorrect");
+    VerifyOrQuit(headerBytes[Header::kProtocolOffset] == kProtoIcmp, "kProtocol is incorrect");
+    VerifyOrQuit(headerBytes[Header::kTtlOffset] == kTtl, "kTtl is incorrect");
+    VerifyOrQuit(memcmp(&headerBytes[Header::kSourceAddressOffset], &source, sizeof(source)) == 0,
+                 "Source address is incorrect");
+    VerifyOrQuit(memcmp(&headerBytes[Header::kDestinationAddressOffset], &destination, sizeof(destination)) == 0,
+                 "Destination address is incorrect");
+
+    for (uint8_t dscp : kDscps)
+    {
+        for (Ecn ecn : kEcns)
+        {
+            printf("Expecting {dscp:%-2d, ecn:%d} => ", dscp, ecn);
+            header.SetEcn(ecn);
+            header.SetDscp(dscp);
+            VerifyEcnDscp(header, dscp, ecn);
+        }
+    }
+
+    memcpy(&header, kExampleIp4Header, sizeof(header));
+    VerifyOrQuit(header.IsValid());
+    VerifyOrQuit(memcmp(&headerBytes[Header::kSourceAddressOffset], &source, sizeof(source)) == 0,
+                 "Source address is incorrect");
+    VerifyOrQuit(memcmp(&headerBytes[Header::kDestinationAddressOffset], &destination, sizeof(destination)) == 0,
+                 "Destination address is incorrect");
+    VerifyOrQuit(ReadUint16(headerBytes + Header::kTotalLengthOffset) == kTotalLength, "kTotalLength is incorrect");
+    VerifyOrQuit(headerBytes[Header::kProtocolOffset] == kProtoIcmp, "kProtocol is incorrect");
+    VerifyOrQuit(headerBytes[Header::kTtlOffset] == kTtl, "kTtl is incorrect");
+}
+
+} // namespace Ip4
+} // namespace ot
+
+int main(void)
+{
+    ot::Ip4::TestIp4Header();
+    printf("All tests passed\n");
+    return 0;
+}
diff --git a/tests/unit/test_ip6_header.cpp b/tests/unit/test_ip6_header.cpp
new file mode 100644
index 0000000..eab543d
--- /dev/null
+++ b/tests/unit/test_ip6_header.cpp
@@ -0,0 +1,142 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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 "common/encoding.hpp"
+#include "net/ip6_headers.hpp"
+
+#include "test_util.hpp"
+
+using ot::Encoding::BigEndian::ReadUint16;
+
+namespace ot {
+namespace Ip6 {
+
+void VerifyVersionTcFlow(const Header &aHeader, uint8_t aDscp, Ecn aEcn, uint32_t aFlow)
+{
+    uint8_t  expectedTc        = static_cast<uint8_t>((aDscp << 2) + aEcn);
+    uint32_t expectedVerTcFlow = 0x60000000 + (static_cast<uint32_t>(expectedTc) << 20) + aFlow;
+
+    printf("%08x {dscp:%d, ecn:%d, flow:%d}\n", aHeader.GetVerionTrafficClassFlow(), aHeader.GetDscp(),
+           aHeader.GetEcn(), aHeader.GetFlow());
+
+    VerifyOrQuit(aHeader.IsVersion6());
+    VerifyOrQuit(aHeader.GetDscp() == aDscp);
+    VerifyOrQuit(aHeader.GetEcn() == aEcn);
+    VerifyOrQuit(aHeader.GetFlow() == aFlow);
+    VerifyOrQuit(aHeader.GetTrafficClass() == expectedTc);
+    VerifyOrQuit(aHeader.GetVerionTrafficClassFlow() == expectedVerTcFlow);
+}
+
+void TestIp6Header(void)
+{
+    static constexpr uint16_t kPayloadLength = 650;
+    static constexpr uint8_t  kHopLimit      = 0xd1;
+
+    const uint32_t kFlows[] = {0x0, 0x1, 0xfff, 0xffff, 0xff000, 0xfffff};
+    const uint8_t  kDscps[] = {0x0, 0x1, 0x3, 0xf, 0x30, 0x2f, 0x3f};
+    const Ecn      kEcns[]  = {kEcnNotCapable, kEcnCapable0, kEcnCapable1, kEcnMarked};
+
+    Header         header;
+    Address        source;
+    Address        destination;
+    const uint8_t *headerBytes = reinterpret_cast<const uint8_t *>(&header);
+
+    SuccessOrQuit(source.FromString("0102:0304:0506:0708:090a:0b0c:0d0e:0f12"), "Address::FromString() failed");
+    SuccessOrQuit(destination.FromString("1122:3344:5566::7788:99aa:bbcc:ddee:ff23"), "Address::FromString() failed");
+
+    header.InitVersionTrafficClassFlow();
+    VerifyVersionTcFlow(header, kDscpCs0, kEcnNotCapable, 0);
+
+    header.Clear();
+    header.InitVersionTrafficClassFlow();
+    VerifyOrQuit(header.IsValid());
+    VerifyOrQuit(header.GetPayloadLength() == 0);
+    VerifyOrQuit(header.GetNextHeader() == 0);
+    VerifyOrQuit(header.GetHopLimit() == 0);
+    VerifyOrQuit(header.GetSource().IsUnspecified());
+    VerifyOrQuit(header.GetDestination().IsUnspecified());
+
+    header.SetPayloadLength(kPayloadLength);
+    header.SetNextHeader(kProtoUdp);
+    header.SetHopLimit(kHopLimit);
+    header.SetSource(source);
+    header.SetDestination(destination);
+
+    VerifyOrQuit(header.IsValid());
+    VerifyVersionTcFlow(header, kDscpCs0, kEcnNotCapable, 0);
+    VerifyOrQuit(header.GetPayloadLength() == kPayloadLength);
+    VerifyOrQuit(header.GetNextHeader() == kProtoUdp);
+    VerifyOrQuit(header.GetHopLimit() == kHopLimit);
+    VerifyOrQuit(header.GetSource() == source);
+    VerifyOrQuit(header.GetDestination() == destination);
+
+    // Verify the offsets to different fields.
+
+    VerifyOrQuit(ReadUint16(headerBytes + Header::kPayloadLengthFieldOffset) == kPayloadLength,
+                 "kPayloadLengthFieldOffset is incorrect");
+    VerifyOrQuit(headerBytes[Header::kNextHeaderFieldOffset] == kProtoUdp, "kNextHeaderFieldOffset is incorrect");
+    VerifyOrQuit(headerBytes[Header::kHopLimitFieldOffset] == kHopLimit, "kHopLimitFieldOffset is incorrect");
+    VerifyOrQuit(memcmp(&headerBytes[Header::kSourceFieldOffset], &source, sizeof(source)) == 0,
+                 "kSourceFieldOffset is incorrect");
+    VerifyOrQuit(memcmp(&headerBytes[Header::kDestinationFieldOffset], &destination, sizeof(destination)) == 0,
+                 "kSourceFieldOffset is incorrect");
+
+    for (uint32_t flow : kFlows)
+    {
+        for (uint8_t dscp : kDscps)
+        {
+            for (Ecn ecn : kEcns)
+            {
+                printf("Expecting {dscp:%-2d, ecn:%d, flow:%-7d} => ", dscp, ecn, flow);
+                header.SetEcn(ecn);
+                header.SetDscp(dscp);
+                header.SetFlow(flow);
+                VerifyVersionTcFlow(header, dscp, ecn, flow);
+            }
+        }
+    }
+
+    // Verify out of range values.
+    header.InitVersionTrafficClassFlow();
+
+    header.SetFlow(0xff000001);
+    VerifyVersionTcFlow(header, 0, kEcnNotCapable, 1);
+
+    header.SetDscp(0xef);
+    VerifyVersionTcFlow(header, 0x2f, kEcnNotCapable, 1);
+}
+
+} // namespace Ip6
+} // namespace ot
+
+int main(void)
+{
+    ot::Ip6::TestIp6Header();
+    printf("All tests passed\n");
+    return 0;
+}
diff --git a/tests/unit/test_ip_address.cpp b/tests/unit/test_ip_address.cpp
index b1642eb..b25cef9 100644
--- a/tests/unit/test_ip_address.cpp
+++ b/tests/unit/test_ip_address.cpp
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2019, The OpenThread Authors.
+ *  Copyright (c) 2019-2022, The OpenThread Authors.
  *  All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -29,14 +29,11 @@
 #include <limits.h>
 
 #include "common/encoding.hpp"
-#include "net/ip4_address.hpp"
+#include "net/ip4_types.hpp"
 #include "net/ip6_address.hpp"
-#include "net/ip6_headers.hpp"
 
 #include "test_util.h"
 
-using ot::Encoding::BigEndian::ReadUint16;
-
 template <typename AddressType> struct TestVector
 {
     const char *  mString;
@@ -278,6 +275,17 @@
     }
 }
 
+ot::Ip6::Prefix PrefixFrom(const char *aAddressString, uint8_t aPrefixLength)
+{
+    ot::Ip6::Prefix  prefix;
+    ot::Ip6::Address address;
+
+    SuccessOrQuit(address.FromString(aAddressString));
+    prefix.Set(address.GetBytes(), aPrefixLength);
+
+    return prefix;
+}
+
 void TestIp6Prefix(void)
 {
     const uint8_t kPrefixes[][OT_IP6_ADDRESS_SIZE] = {
@@ -355,6 +363,38 @@
             }
         }
     }
+
+    {
+        struct TestCase
+        {
+            ot::Ip6::Prefix mPrefixA;
+            ot::Ip6::Prefix mPrefixB;
+        };
+
+        TestCase kTestCases[] = {
+            {PrefixFrom("fd00::", 16), PrefixFrom("fd01::", 16)},
+            {PrefixFrom("fc00::", 16), PrefixFrom("fd00::", 16)},
+            {PrefixFrom("fd00::", 15), PrefixFrom("fd00::", 16)},
+            {PrefixFrom("fd00::", 16), PrefixFrom("fd00:0::", 32)},
+            {PrefixFrom("2001:0:0:0::", 64), PrefixFrom("fd00::", 8)},
+            {PrefixFrom("2001:dba::", 32), PrefixFrom("fd12:3456:1234:abcd::", 64)},
+            {PrefixFrom("910b:1000:0::", 48), PrefixFrom("910b:2000::", 32)},
+            {PrefixFrom("::", 0), PrefixFrom("fd00::", 8)},
+            {PrefixFrom("::", 0), PrefixFrom("::", 16)},
+            {PrefixFrom("fd00:2:2::", 33), PrefixFrom("fd00:2:2::", 35)},
+            {PrefixFrom("1:2:3:ffff::", 62), PrefixFrom("1:2:3:ffff::", 63)},
+        };
+
+        printf("\nCompare Prefixes:\n");
+
+        for (const TestCase &testCase : kTestCases)
+        {
+            printf(" %26s  <  %s\n", testCase.mPrefixA.ToString().AsCString(),
+                   testCase.mPrefixB.ToString().AsCString());
+            VerifyOrQuit(testCase.mPrefixA < testCase.mPrefixB);
+            VerifyOrQuit(!(testCase.mPrefixB < testCase.mPrefixA));
+        }
+    }
 }
 
 void TestIp4Ip6Translation(void)
@@ -405,61 +445,73 @@
 
         VerifyOrQuit(address == expectedAddress, "Ip6::SynthesizeFromIp4Address() failed");
     }
+
+    for (const TestCase &testCase : kTestCases)
+    {
+        const ot::Ip4::Address expectedAddress = ip4Address;
+        ot::Ip4::Address       address;
+        ot::Ip6::Address       ip6Address;
+
+        SuccessOrQuit(ip6Address.FromString(testCase.mIp6Address));
+
+        address.ExtractFromIp6Address(testCase.mLength, ip6Address);
+
+        printf("Ipv6Address: %-36s IPv4Addr: %-12s Expected: %s\n", testCase.mIp6Address,
+               address.ToString().AsCString(), expectedAddress.ToString().AsCString());
+
+        VerifyOrQuit(address == expectedAddress, "Ip4::ExtractFromIp6Address() failed");
+    }
 }
 
-void TestIp6Header(void)
+void TestIp4Cidr(void)
 {
-    ot::Ip6::Header  header;
-    ot::Ip6::Address source;
-    ot::Ip6::Address destination;
-    const uint8_t *  headerBytes = reinterpret_cast<const uint8_t *>(&header);
-
-    enum : uint16_t
+    using ot::Encoding::BigEndian::HostSwap32;
+    struct TestCase
     {
-        kPayloadLength = 650,
+        const char *   mNetwork;
+        const uint8_t  mLength;
+        const uint32_t mHost;
+        const char *   mOutcome;
     };
 
-    enum : uint8_t
-    {
-        kHopLimit = 0xd1,
+    const TestCase kTestCases[] = {
+        {"172.16.12.34", 32, 0x12345678, "172.16.12.34"},  {"172.16.12.34", 31, 0x12345678, "172.16.12.34"},
+        {"172.16.12.34", 30, 0x12345678, "172.16.12.32"},  {"172.16.12.34", 29, 0x12345678, "172.16.12.32"},
+        {"172.16.12.34", 28, 0x12345678, "172.16.12.40"},  {"172.16.12.34", 27, 0x12345678, "172.16.12.56"},
+        {"172.16.12.34", 26, 0x12345678, "172.16.12.56"},  {"172.16.12.34", 25, 0x12345678, "172.16.12.120"},
+        {"172.16.12.34", 24, 0x12345678, "172.16.12.120"}, {"172.16.12.34", 23, 0x12345678, "172.16.12.120"},
+        {"172.16.12.34", 22, 0x12345678, "172.16.14.120"}, {"172.16.12.34", 21, 0x12345678, "172.16.14.120"},
+        {"172.16.12.34", 20, 0x12345678, "172.16.6.120"},  {"172.16.12.34", 19, 0x12345678, "172.16.22.120"},
+        {"172.16.12.34", 18, 0x12345678, "172.16.22.120"}, {"172.16.12.34", 17, 0x12345678, "172.16.86.120"},
+        {"172.16.12.34", 16, 0x12345678, "172.16.86.120"}, {"172.16.12.34", 15, 0x12345678, "172.16.86.120"},
+        {"172.16.12.34", 14, 0x12345678, "172.16.86.120"}, {"172.16.12.34", 13, 0x12345678, "172.20.86.120"},
+        {"172.16.12.34", 12, 0x12345678, "172.20.86.120"}, {"172.16.12.34", 11, 0x12345678, "172.20.86.120"},
+        {"172.16.12.34", 10, 0x12345678, "172.52.86.120"}, {"172.16.12.34", 9, 0x12345678, "172.52.86.120"},
+        {"172.16.12.34", 8, 0x12345678, "172.52.86.120"},  {"172.16.12.34", 7, 0x12345678, "172.52.86.120"},
+        {"172.16.12.34", 6, 0x12345678, "174.52.86.120"},  {"172.16.12.34", 5, 0x12345678, "170.52.86.120"},
+        {"172.16.12.34", 4, 0x12345678, "162.52.86.120"},  {"172.16.12.34", 3, 0x12345678, "178.52.86.120"},
+        {"172.16.12.34", 2, 0x12345678, "146.52.86.120"},  {"172.16.12.34", 1, 0x12345678, "146.52.86.120"},
+        {"172.16.12.34", 0, 0x12345678, "18.52.86.120"},
     };
 
-    memset(&header, 0, sizeof(header));
+    for (const TestCase &testCase : kTestCases)
+    {
+        ot::Ip4::Address network;
+        ot::Ip4::Cidr    cidr;
+        ot::Ip4::Address generated;
 
-    SuccessOrQuit(source.FromString("0102:0304:0506:0708:090a:0b0c:0d0e:0f12"), "Address::FromString() failed");
-    SuccessOrQuit(destination.FromString("1122:3344:5566::7788:99aa:bbcc:ddee:ff23"), "Address::FromString() failed");
+        SuccessOrQuit(network.FromString(testCase.mNetwork));
+        cidr.mAddress = network;
+        cidr.mLength  = testCase.mLength;
 
-    header.Init();
-    VerifyOrQuit(header.IsVersion6(), "Header::Init() failed");
+        generated.SynthesizeFromCidrAndHost(cidr, testCase.mHost);
 
-    header.SetDscp(ot::Ip6::kDscpCs7);
-    header.SetPayloadLength(kPayloadLength);
-    header.SetNextHeader(ot::Ip6::kProtoUdp);
-    header.SetHopLimit(kHopLimit);
-    header.SetSource(source);
-    header.SetDestination(destination);
+        printf("CIDR: %-18s HostID: %-8x Host: %-14s Expected: %s\n", cidr.ToString().AsCString(), testCase.mHost,
+               generated.ToString().AsCString(), testCase.mOutcome);
 
-    VerifyOrQuit(header.IsValid());
-    VerifyOrQuit(header.IsVersion6());
-
-    VerifyOrQuit(header.GetDscp() == ot::Ip6::kDscpCs7);
-    VerifyOrQuit(header.GetPayloadLength() == kPayloadLength);
-    VerifyOrQuit(header.GetNextHeader() == ot::Ip6::kProtoUdp);
-    VerifyOrQuit(header.GetHopLimit() == kHopLimit);
-    VerifyOrQuit(header.GetSource() == source);
-    VerifyOrQuit(header.GetDestination() == destination);
-
-    // Verify the offsets to different fields.
-
-    VerifyOrQuit(ReadUint16(headerBytes + ot::Ip6::Header::kPayloadLengthFieldOffset) == kPayloadLength,
-                 "kPayloadLengthFieldOffset is incorrect");
-    VerifyOrQuit(headerBytes[ot::Ip6::Header::kNextHeaderFieldOffset] == ot::Ip6::kProtoUdp,
-                 "kNextHeaderFieldOffset is incorrect");
-    VerifyOrQuit(headerBytes[ot::Ip6::Header::kHopLimitFieldOffset] == kHopLimit, "kHopLimitFieldOffset is incorrect");
-    VerifyOrQuit(memcmp(&headerBytes[ot::Ip6::Header::kSourceFieldOffset], &source, sizeof(source)) == 0,
-                 "kSourceFieldOffset is incorrect");
-    VerifyOrQuit(memcmp(&headerBytes[ot::Ip6::Header::kDestinationFieldOffset], &destination, sizeof(destination)) == 0,
-                 "kSourceFieldOffset is incorrect");
+        VerifyOrQuit(strcmp(generated.ToString().AsCString(), testCase.mOutcome) == 0,
+                     "Ip4::Address::SynthesizeFromCidrAndHost() failed");
+    }
 }
 
 int main(void)
@@ -469,7 +521,7 @@
     TestIp6AddressFromString();
     TestIp6Prefix();
     TestIp4Ip6Translation();
-    TestIp6Header();
+    TestIp4Cidr();
     printf("All tests passed\n");
     return 0;
 }
diff --git a/tests/unit/test_link_quality.cpp b/tests/unit/test_link_quality.cpp
index e4c9261..f9162e3 100644
--- a/tests/unit/test_link_quality.cpp
+++ b/tests/unit/test_link_quality.cpp
@@ -26,12 +26,13 @@
  *  POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "common/code_utils.hpp"
-#include "thread/link_quality.hpp"
-
 #include "test_platform.h"
 #include "test_util.h"
 
+#include "common/array.hpp"
+#include "common/code_utils.hpp"
+#include "thread/link_quality.hpp"
+
 namespace ot {
 
 static ot::Instance *sInstance;
@@ -412,7 +413,7 @@
 
     // Adding success/failure at different rates and checking the RateTracker rate for every sample
 
-    for (uint16_t testRound = 0; testRound < OT_ARRAY_LENGTH(kWeightLimit) * 2; testRound++)
+    for (uint16_t testRound = 0; testRound < GetArrayLength(kWeightLimit) * 2; testRound++)
     {
         uint16_t weightLimit;
         bool     reverseLogic;
diff --git a/tests/unit/test_linked_list.cpp b/tests/unit/test_linked_list.cpp
index b0b2970..f84f63d 100644
--- a/tests/unit/test_linked_list.cpp
+++ b/tests/unit/test_linked_list.cpp
@@ -36,20 +36,31 @@
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/linked_list.hpp"
+#include "common/owning_list.hpp"
 
 #include "test_util.h"
 
+namespace ot {
+
 struct EntryBase
 {
     EntryBase *mNext;
 };
 
-struct Entry : public EntryBase, ot::LinkedListEntry<Entry>
+struct Entry : public EntryBase, LinkedListEntry<Entry>
 {
 public:
-    Entry(const char *aName, uint16_t aId)
+    enum class Type : uint8_t
+    {
+        kAlpha,
+        kBeta,
+    };
+
+    Entry(const char *aName, uint16_t aId, Type aType = Type::kAlpha)
         : mName(aName)
         , mId(aId)
+        , mType(aType)
+        , mWasFreed(false)
     {
     }
 
@@ -57,14 +68,24 @@
     uint16_t    GetId(void) const { return mId; }
     bool        Matches(const char *aName) const { return strcmp(mName, aName) == 0; }
     bool        Matches(uint16_t aId) const { return mId == aId; }
+    bool        Matches(Type aType) const { return mType == aType; }
+    void        Free(void) { mWasFreed = true; }
+
+    void ResetTestFlags(void) { mWasFreed = false; }
+    bool WasFreed(void) const { return mWasFreed; }
 
 private:
     const char *mName;
     uint16_t    mId;
+    Type        mType;
+    bool        mWasFreed;
 };
 
+constexpr Entry::Type kAlphaType = Entry::Type::kAlpha;
+constexpr Entry::Type kBetaType  = Entry::Type::kBeta;
+
 // This function verifies the content of the linked list matches a given list of entries.
-void VerifyLinkedListContent(const ot::LinkedList<Entry> *aList, ...)
+void VerifyLinkedListContent(const LinkedList<Entry> *aList, ...)
 {
     va_list      args;
     Entry *      argEntry;
@@ -92,6 +113,8 @@
         VerifyOrQuit(aList->FindMatching(argEntry->GetId(), prev) == argEntry);
         VerifyOrQuit(prev == argPrev, "List::FindMatching() returned prev entry is incorrect");
 
+        VerifyOrQuit(!argEntry->WasFreed());
+
         argPrev = argEntry;
     }
 
@@ -109,25 +132,29 @@
 
 void TestLinkedList(void)
 {
-    Entry                 a("a", 1), b("b", 2), c("c", 3), d("d", 4), e("e", 5);
-    Entry *               prev;
-    ot::LinkedList<Entry> list;
+    Entry             a("a", 1, kAlphaType), b("b", 2, kAlphaType), c("c", 3, kBetaType);
+    Entry             d("d", 4, kBetaType), e("e", 5, kAlphaType), f("f", 6, kBetaType);
+    Entry *           prev;
+    LinkedList<Entry> list;
+    LinkedList<Entry> removedList;
+
+    printf("TestLinkedList\n");
 
     VerifyOrQuit(list.IsEmpty(), "failed after init");
     VerifyOrQuit(list.GetHead() == nullptr, "failed after init");
     VerifyOrQuit(list.Pop() == nullptr, "failed when empty");
-    VerifyOrQuit(list.Find(a, prev) == ot::kErrorNotFound, "succeeded when empty");
+    VerifyOrQuit(list.Find(a, prev) == kErrorNotFound, "succeeded when empty");
 
     VerifyLinkedListContent(&list, nullptr);
 
     list.Push(a);
     VerifyOrQuit(!list.IsEmpty());
     VerifyLinkedListContent(&list, &a, nullptr);
-    VerifyOrQuit(list.Find(b, prev) == ot::kErrorNotFound, "succeeded for a missing entry");
+    VerifyOrQuit(list.Find(b, prev) == kErrorNotFound, "succeeded for a missing entry");
 
     SuccessOrQuit(list.Add(b));
     VerifyLinkedListContent(&list, &b, &a, nullptr);
-    VerifyOrQuit(list.Find(c, prev) == ot::kErrorNotFound, "succeeded for a missing entry");
+    VerifyOrQuit(list.Find(c, prev) == kErrorNotFound, "succeeded for a missing entry");
 
     list.Push(c);
     VerifyLinkedListContent(&list, &c, &b, &a, nullptr);
@@ -138,14 +165,14 @@
     SuccessOrQuit(list.Add(e));
     VerifyLinkedListContent(&list, &e, &d, &c, &b, &a, nullptr);
 
-    VerifyOrQuit(list.Add(a) == ot::kErrorAlready, "did not detect duplicate");
-    VerifyOrQuit(list.Add(b) == ot::kErrorAlready, "did not detect duplicate");
-    VerifyOrQuit(list.Add(d) == ot::kErrorAlready, "did not detect duplicate");
-    VerifyOrQuit(list.Add(e) == ot::kErrorAlready, "did not detect duplicate");
+    VerifyOrQuit(list.Add(a) == kErrorAlready, "did not detect duplicate");
+    VerifyOrQuit(list.Add(b) == kErrorAlready, "did not detect duplicate");
+    VerifyOrQuit(list.Add(d) == kErrorAlready, "did not detect duplicate");
+    VerifyOrQuit(list.Add(e) == kErrorAlready, "did not detect duplicate");
 
     VerifyOrQuit(list.Pop() == &e);
     VerifyLinkedListContent(&list, &d, &c, &b, &a, nullptr);
-    VerifyOrQuit(list.Find(e, prev) == ot::kErrorNotFound, "succeeded for a missing entry");
+    VerifyOrQuit(list.Find(e, prev) == kErrorNotFound, "succeeded for a missing entry");
 
     VerifyOrQuit(list.FindMatching(d.GetName(), prev) == &d);
     VerifyOrQuit(prev == nullptr);
@@ -164,17 +191,17 @@
     SuccessOrQuit(list.Remove(c));
     VerifyLinkedListContent(&list, &e, &d, &b, &a, nullptr);
 
-    VerifyOrQuit(list.Remove(c) == ot::kErrorNotFound);
+    VerifyOrQuit(list.Remove(c) == kErrorNotFound);
     VerifyLinkedListContent(&list, &e, &d, &b, &a, nullptr);
-    VerifyOrQuit(list.Find(c, prev) == ot::kErrorNotFound, "succeeded for a missing entry");
+    VerifyOrQuit(list.Find(c, prev) == kErrorNotFound, "succeeded for a missing entry");
 
     SuccessOrQuit(list.Remove(e));
     VerifyLinkedListContent(&list, &d, &b, &a, nullptr);
-    VerifyOrQuit(list.Find(e, prev) == ot::kErrorNotFound, "succeeded for a missing entry");
+    VerifyOrQuit(list.Find(e, prev) == kErrorNotFound, "succeeded for a missing entry");
 
     SuccessOrQuit(list.Remove(a));
     VerifyLinkedListContent(&list, &d, &b, nullptr);
-    VerifyOrQuit(list.Find(a, prev) == ot::kErrorNotFound, "succeeded for a missing entry");
+    VerifyOrQuit(list.Find(a, prev) == kErrorNotFound, "succeeded for a missing entry");
 
     list.Push(a);
     list.Push(c);
@@ -222,16 +249,188 @@
     VerifyOrQuit(list.IsEmpty(), "failed after Clear()");
     VerifyOrQuit(list.PopAfter(nullptr) == nullptr);
     VerifyLinkedListContent(&list, nullptr);
-    VerifyOrQuit(list.Find(a, prev) == ot::kErrorNotFound, "succeeded for a missing entry");
+    VerifyOrQuit(list.Find(a, prev) == kErrorNotFound, "succeeded for a missing entry");
     VerifyOrQuit(list.FindMatching(b.GetName(), prev) == nullptr, "succeeded when empty");
     VerifyOrQuit(list.FindMatching(c.GetId(), prev) == nullptr, "succeeded when empty");
     VerifyOrQuit(list.RemoveMatching(a.GetName()) == nullptr, "succeeded when empty");
-    VerifyOrQuit(list.Remove(a) == ot::kErrorNotFound, "succeeded when empty");
+    VerifyOrQuit(list.Remove(a) == kErrorNotFound, "succeeded when empty");
+
+    list.Clear();
+    removedList.Clear();
+    list.Push(f);
+    list.Push(e);
+    list.Push(d);
+    list.Push(c);
+    list.Push(b);
+    list.Push(a);
+    VerifyLinkedListContent(&list, &a, &b, &c, &d, &e, &f, nullptr);
+
+    list.RemoveAllMatching(kAlphaType, removedList);
+    VerifyLinkedListContent(&list, &c, &d, &f, nullptr);
+    VerifyLinkedListContent(&removedList, &e, &b, &a, nullptr);
+
+    removedList.Clear();
+    list.RemoveAllMatching(kAlphaType, removedList);
+    VerifyLinkedListContent(&list, &c, &d, &f, nullptr);
+    VerifyOrQuit(removedList.IsEmpty());
+
+    list.RemoveAllMatching(kBetaType, removedList);
+    VerifyOrQuit(list.IsEmpty());
+    VerifyLinkedListContent(&removedList, &f, &d, &c, nullptr);
+
+    removedList.Clear();
+    list.RemoveAllMatching(kAlphaType, removedList);
+    VerifyOrQuit(list.IsEmpty());
+    VerifyOrQuit(removedList.IsEmpty());
+
+    list.Push(f);
+    list.Push(e);
+    list.Push(d);
+    list.Push(c);
+    list.Push(b);
+    list.Push(a);
+    VerifyLinkedListContent(&list, &a, &b, &c, &d, &e, &f, nullptr);
+
+    list.RemoveAllMatching(kBetaType, removedList);
+    VerifyLinkedListContent(&list, &a, &b, &e, nullptr);
+    VerifyLinkedListContent(&removedList, &f, &d, &c, nullptr);
 }
 
+void TestOwningList(void)
+{
+    Entry             a("a", 1, kAlphaType), b("b", 2, kAlphaType), c("c", 3, kBetaType);
+    Entry             d("d", 4, kBetaType), e("e", 5, kAlphaType), f("f", 6, kBetaType);
+    OwningList<Entry> list;
+    OwningList<Entry> removedList;
+    OwnedPtr<Entry>   ptr;
+
+    printf("TestOwningList\n");
+
+    VerifyOrQuit(list.IsEmpty());
+    VerifyOrQuit(list.GetHead() == nullptr);
+    VerifyOrQuit(list.Pop().IsNull());
+
+    list.Free();
+    VerifyOrQuit(list.IsEmpty());
+    VerifyOrQuit(list.GetHead() == nullptr);
+    VerifyOrQuit(list.Pop().IsNull());
+
+    // Clear()
+
+    list.Push(a);
+    VerifyLinkedListContent(&list, &a, nullptr);
+    list.Free();
+    VerifyOrQuit(list.IsEmpty());
+    VerifyOrQuit(a.WasFreed());
+
+    // Test removing entry without taking back the ownership
+
+    a.ResetTestFlags();
+    list.Push(a);
+    list.Push(b);
+    list.Push(c);
+    list.Push(d);
+    list.Push(e);
+    VerifyLinkedListContent(&list, &e, &d, &c, &b, &a, nullptr);
+
+    list.Pop();
+    VerifyLinkedListContent(&list, &d, &c, &b, &a, nullptr);
+    VerifyOrQuit(e.WasFreed());
+
+    list.PopAfter(&c);
+    VerifyLinkedListContent(&list, &d, &c, &a, nullptr);
+    VerifyOrQuit(b.WasFreed());
+
+    list.RemoveMatching("c");
+    VerifyLinkedListContent(&list, &d, &a, nullptr);
+    VerifyOrQuit(c.WasFreed());
+
+    list.Free();
+    VerifyLinkedListContent(&list, nullptr);
+    VerifyOrQuit(d.WasFreed());
+    VerifyOrQuit(a.WasFreed());
+
+    // Test removing entry and taking ownership
+
+    a.ResetTestFlags();
+    b.ResetTestFlags();
+    c.ResetTestFlags();
+    d.ResetTestFlags();
+    e.ResetTestFlags();
+    list.Push(a);
+    list.Push(b);
+    list.Push(c);
+    list.Push(d);
+    list.Push(e);
+    VerifyLinkedListContent(&list, &e, &d, &c, &b, &a, nullptr);
+
+    ptr = list.PopAfter(&a);
+    VerifyLinkedListContent(&list, &e, &d, &c, &b, &a, nullptr);
+    VerifyOrQuit(ptr.IsNull());
+
+    ptr = list.PopAfter(&e);
+    VerifyLinkedListContent(&list, &e, &c, &b, &a, nullptr);
+    VerifyOrQuit(ptr.Get() == &d);
+    VerifyOrQuit(!d.WasFreed());
+
+    ptr = list.Pop();
+    VerifyLinkedListContent(&list, &c, &b, &a, nullptr);
+    VerifyOrQuit(ptr.Get() == &e);
+    VerifyOrQuit(!e.WasFreed());
+    VerifyOrQuit(d.WasFreed());
+
+    ptr = list.RemoveMatching<uint8_t>(1);
+    VerifyLinkedListContent(&list, &c, &b, nullptr);
+    VerifyOrQuit(ptr.Get() == &a);
+    VerifyOrQuit(!a.WasFreed());
+    VerifyOrQuit(e.WasFreed());
+
+    list.Clear();
+    VerifyOrQuit(c.WasFreed());
+    VerifyOrQuit(b.WasFreed());
+    VerifyOrQuit(!a.WasFreed());
+    a.Free();
+    VerifyOrQuit(a.WasFreed());
+
+    // Test `RemoveAllMatching()`
+
+    a.ResetTestFlags();
+    b.ResetTestFlags();
+    c.ResetTestFlags();
+    d.ResetTestFlags();
+    e.ResetTestFlags();
+    f.ResetTestFlags();
+    list.Push(a);
+    list.Push(b);
+    list.Push(c);
+    list.Push(d);
+    list.Push(e);
+    list.Push(f);
+    VerifyLinkedListContent(&list, &f, &e, &d, &c, &b, &a, nullptr);
+
+    list.RemoveAllMatching(kAlphaType, removedList);
+    VerifyLinkedListContent(&list, &f, &d, &c, nullptr);
+    VerifyLinkedListContent(&removedList, &a, &b, &e, nullptr);
+    VerifyOrQuit(!a.WasFreed());
+    VerifyOrQuit(!c.WasFreed());
+
+    removedList.Clear();
+    list.RemoveAllMatching(kAlphaType, removedList);
+    VerifyOrQuit(removedList.IsEmpty());
+    VerifyLinkedListContent(&list, &f, &d, &c, nullptr);
+
+    list.RemoveAllMatching(kBetaType, removedList);
+    VerifyOrQuit(list.IsEmpty());
+    VerifyLinkedListContent(&removedList, &c, &d, &f, nullptr);
+    VerifyOrQuit(!c.WasFreed());
+}
+
+} // namespace ot
+
 int main(void)
 {
-    TestLinkedList();
+    ot::TestLinkedList();
+    ot::TestOwningList();
     printf("All tests passed\n");
     return 0;
 }
diff --git a/tests/unit/test_lookup_table.cpp b/tests/unit/test_lookup_table.cpp
deleted file mode 100644
index b1310b6..0000000
--- a/tests/unit/test_lookup_table.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- *  Copyright (c) 2020, The OpenThread Authors.
- *  All rights reserved.
- *
- *  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, 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 <string.h>
-
-#include "test_platform.h"
-
-#include <openthread/config.h>
-
-#include "common/instance.hpp"
-#include "utils/lookup_table.hpp"
-
-#include "test_util.h"
-
-typedef ot::Utils::LookupTable::Entry Entry;
-
-struct TableEntryBase
-{
-    constexpr explicit TableEntryBase(uint8_t aValue)
-        : mValue(aValue)
-    {
-    }
-
-    uint8_t mValue;
-};
-
-struct TableEntry : public TableEntryBase, public Entry
-{
-    constexpr TableEntry(const char *aName, uint8_t aValue)
-        : TableEntryBase(aValue)
-        , Entry(aName)
-        , mUint16(0xabba)
-        , mUint8(aValue)
-    {
-    }
-
-    uint16_t mUint16;
-    uint8_t  mUint8;
-};
-
-void TestLookupTable(void)
-{
-    enum : uint16_t
-    {
-        kMaxNameSize = 30,
-    };
-
-    constexpr TableEntry kTable[] = {
-        {"arkham city", 9}, {"arkham knight", 7}, {"bloodborne", 10}, {"god of war", 10},       {"horizon", 9},
-        {"infamous", 7},    {"last guardian", 7}, {"last of us", 11}, {"last of us part 2", 8}, {"mass effect", 8},
-        {"sekiro", 10},     {"tomb raider", 9},   {"uncharted", 9},
-    };
-
-    constexpr Entry kUnsortedTable[]       = {Entry("z"), Entry("a"), Entry("b")};
-    constexpr Entry kDuplicateEntryTable[] = {Entry("duplicate"), Entry("duplicate")};
-
-    static_assert(ot::Utils::LookupTable::IsSorted(kTable), "LookupTable::IsSorted() failed");
-    static_assert(!ot::Utils::LookupTable::IsSorted(kUnsortedTable), "failed for unsorted table");
-    static_assert(!ot::Utils::LookupTable::IsSorted(kDuplicateEntryTable), "failed for table with duplicate entries");
-
-    for (const TableEntry &tableEntry : kTable)
-    {
-        const TableEntry *entry;
-        char              name[kMaxNameSize];
-
-        strcpy(name, tableEntry.mName);
-
-        entry = ot::Utils::LookupTable::Find(name, kTable);
-        VerifyOrQuit(entry == &tableEntry, "LookupTable::Find() failed");
-
-        name[strlen(name) - 1] = '\0';
-        entry                  = ot::Utils::LookupTable::Find(name, kTable);
-        VerifyOrQuit(entry == nullptr, "LookupTable::Find() failed with non-matching name");
-    }
-
-    VerifyOrQuit(ot::Utils::LookupTable::Find("dragon age", kTable) == nullptr, "failed with non-exiting match");
-}
-
-int main(void)
-{
-    TestLookupTable();
-    printf("All tests passed\n");
-    return 0;
-}
diff --git a/tests/unit/test_lowpan.cpp b/tests/unit/test_lowpan.cpp
index c7e9fc4..beb6981 100644
--- a/tests/unit/test_lowpan.cpp
+++ b/tests/unit/test_lowpan.cpp
@@ -106,7 +106,7 @@
 {
     otMeshLocalPrefix meshLocalPrefix = {{0xfd, 0x00, 0xca, 0xfe, 0xfa, 0xce, 0x12, 0x34}};
 
-    sInstance->Get<Mle::MleRouter>().SetMeshLocalPrefix(static_cast<Mle::MeshLocalPrefix &>(meshLocalPrefix));
+    sInstance->Get<Mle::MleRouter>().SetMeshLocalPrefix(static_cast<Ip6::NetworkPrefix &>(meshLocalPrefix));
 
     // Emulate global prefixes with contextes.
     uint8_t mockNetworkData[] = {
@@ -124,12 +124,12 @@
         0x02, 0x40                                                              // Context ID = 2, C = FALSE
     };
 
-    Message *message = sInstance->Get<MessagePool>().New(Message::kTypeIp6, 0);
+    Message *message = sInstance->Get<MessagePool>().Allocate(Message::kTypeIp6);
     VerifyOrQuit(message != nullptr, "Ip6::NewMessage failed");
 
     SuccessOrQuit(message->AppendBytes(mockNetworkData, sizeof(mockNetworkData)));
 
-    IgnoreError(sInstance->Get<NetworkData::Leader>().SetNetworkData(0, 0, true, *message, 0));
+    IgnoreError(sInstance->Get<NetworkData::Leader>().SetNetworkData(0, 0, NetworkData::kStableSubset, *message, 0));
 }
 
 /**
@@ -145,12 +145,14 @@
  */
 static void Test(TestIphcVector &aVector, bool aCompress, bool aDecompress)
 {
-    Message *message = nullptr;
-    uint8_t  result[512];
-    uint8_t  iphc[512];
-    uint8_t  ip6[512];
-    uint16_t iphcLength;
-    uint16_t ip6Length;
+    Message * message = nullptr;
+    uint8_t   result[512];
+    uint8_t   iphc[512];
+    uint8_t   ip6[512];
+    uint16_t  iphcLength;
+    uint16_t  ip6Length;
+    FrameData frameData;
+    Error     error;
 
     aVector.GetCompressedStream(iphc, iphcLength);
     aVector.GetUncompressedStream(ip6, ip6Length);
@@ -169,18 +171,22 @@
 
     if (aCompress)
     {
-        Lowpan::BufferWriter buffer(result, 127);
+        FrameBuilder frameBuilder;
+        Message *    compressedMsg;
+        Ip6::Ecn     ecn;
 
-        VerifyOrQuit((message = sInstance->Get<MessagePool>().New(Message::kTypeIp6, 0)) != nullptr);
+        frameBuilder.Init(result, 127);
+
+        VerifyOrQuit((message = sInstance->Get<MessagePool>().Allocate(Message::kTypeIp6)) != nullptr);
 
         aVector.GetUncompressedStream(*message);
 
-        VerifyOrQuit(sLowpan->Compress(*message, aVector.mMacSource, aVector.mMacDestination, buffer) ==
+        VerifyOrQuit(sLowpan->Compress(*message, aVector.mMacSource, aVector.mMacDestination, frameBuilder) ==
                      aVector.mError);
 
         if (aVector.mError == kErrorNone)
         {
-            uint8_t compressBytes = static_cast<uint8_t>(buffer.GetWritePointer() - result);
+            uint16_t compressBytes = frameBuilder.GetLength();
 
             // Append payload to the LOWPAN_IPHC.
             message->ReadBytes(message->GetOffset(), result + compressBytes,
@@ -192,6 +198,25 @@
             VerifyOrQuit(compressBytes == aVector.mIphcHeader.mLength, "Lowpan::Compress failed");
             VerifyOrQuit(message->GetOffset() == aVector.mPayloadOffset, "Lowpan::Compress failed");
             VerifyOrQuit(memcmp(iphc, result, iphcLength) == 0, "Lowpan::Compress failed");
+
+            // Validate `DecompressEcn()` and `MarkCompressedEcn()`
+
+            VerifyOrQuit((compressedMsg = sInstance->Get<MessagePool>().Allocate(Message::kTypeIp6)) != nullptr);
+            SuccessOrQuit(compressedMsg->AppendBytes(result, compressBytes));
+
+            ecn = sLowpan->DecompressEcn(*compressedMsg, /* aOffset */ 0);
+            VerifyOrQuit(ecn == aVector.GetIpHeader().GetEcn());
+            printf("Decompressed ECN is %d\n", ecn);
+
+            if (ecn != Ip6::kEcnNotCapable)
+            {
+                sLowpan->MarkCompressedEcn(*compressedMsg, /*a aOffset */ 0);
+                ecn = sLowpan->DecompressEcn(*compressedMsg, /* aOffset */ 0);
+                VerifyOrQuit(ecn == Ip6::kEcnMarked);
+                printf("ECN is updated to %d\n", ecn);
+            }
+
+            compressedMsg->Free();
         }
 
         message->Free();
@@ -200,30 +225,31 @@
 
     if (aDecompress)
     {
-        VerifyOrQuit((message = sInstance->Get<MessagePool>().New(Message::kTypeIp6, 0)) != nullptr);
+        VerifyOrQuit((message = sInstance->Get<MessagePool>().Allocate(Message::kTypeIp6)) != nullptr);
 
-        int decompressedBytes =
-            sLowpan->Decompress(*message, aVector.mMacSource, aVector.mMacDestination, iphc, iphcLength, 0);
+        frameData.Init(iphc, iphcLength);
+
+        error = sLowpan->Decompress(*message, aVector.mMacSource, aVector.mMacDestination, frameData, 0);
 
         message->ReadBytes(0, result, message->GetLength());
 
         if (aVector.mError == kErrorNone)
         {
+            SuccessOrQuit(error, "Lowpan::Decompress failed");
+
             // Append payload to the IPv6 Packet.
-            memcpy(result + message->GetLength(), iphc + decompressedBytes,
-                   iphcLength - static_cast<uint16_t>(decompressedBytes));
+            memcpy(result + message->GetLength(), frameData.GetBytes(), frameData.GetLength());
 
-            DumpBuffer("Resulted IPv6 uncompressed packet", result,
-                       message->GetLength() + iphcLength - static_cast<uint16_t>(decompressedBytes));
+            DumpBuffer("Resulted IPv6 uncompressed packet", result, message->GetLength() + frameData.GetLength());
 
-            VerifyOrQuit(decompressedBytes == aVector.mIphcHeader.mLength, "Lowpan::Decompress failed");
+            VerifyOrQuit((frameData.GetBytes() - iphc) == aVector.mIphcHeader.mLength, "Lowpan::Decompress failed");
             VerifyOrQuit(message->GetOffset() == aVector.mPayloadOffset, "Lowpan::Decompress failed");
             VerifyOrQuit(message->GetOffset() == message->GetLength(), "Lowpan::Decompress failed");
             VerifyOrQuit(memcmp(ip6, result, ip6Length) == 0, "Lowpan::Decompress failed");
         }
         else
         {
-            VerifyOrQuit(decompressedBytes < 0, "Lowpan::Decompress failed");
+            VerifyOrQuit(error == kErrorParse, "Lowpan::Decompress failed");
         }
 
         message->Free();
@@ -1843,7 +1869,7 @@
 
     uint8_t            frame[kMaxFrameSize];
     uint16_t           length;
-    uint16_t           headerLength;
+    FrameData          frameData;
     Lowpan::MeshHeader meshHeader;
 
     meshHeader.Init(kSourceAddr, kDestAddr, 1);
@@ -1857,14 +1883,17 @@
     VerifyOrQuit(memcmp(frame, kMeshHeader1, length) == 0, "MeshHeader::WriteTo() failed");
 
     memset(&meshHeader, 0, sizeof(meshHeader));
-    VerifyOrQuit(Lowpan::MeshHeader::IsMeshHeader(frame, length));
-    SuccessOrQuit(meshHeader.ParseFrom(frame, length, headerLength));
-    VerifyOrQuit(headerLength == length, "MeshHeader::ParseFrom() returned length is incorrect");
+    frameData.Init(frame, length);
+    VerifyOrQuit(Lowpan::MeshHeader::IsMeshHeader(frameData));
+    SuccessOrQuit(meshHeader.ParseFrom(frameData));
+    VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
+    VerifyOrQuit(frameData.GetBytes() - frame == length, "ParseFrom() did not skip over parsed content");
     VerifyOrQuit(meshHeader.GetSource() == kSourceAddr, "failed after ParseFrom()");
     VerifyOrQuit(meshHeader.GetDestination() == kDestAddr, "failed after ParseFrom()");
     VerifyOrQuit(meshHeader.GetHopsLeft() == 1, "failed after ParseFrom()");
 
-    VerifyOrQuit(meshHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
+    frameData.Init(frame, length - 1);
+    VerifyOrQuit(meshHeader.ParseFrom(frameData) == kErrorParse,
                  "MeshHeader::ParseFrom() did not fail with incorrect length");
 
     //- - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1880,27 +1909,34 @@
     VerifyOrQuit(memcmp(frame, kMeshHeader2, length) == 0, "MeshHeader::WriteTo() failed");
 
     memset(&meshHeader, 0, sizeof(meshHeader));
-    VerifyOrQuit(Lowpan::MeshHeader::IsMeshHeader(frame, length));
-    SuccessOrQuit(meshHeader.ParseFrom(frame, length, headerLength));
-    VerifyOrQuit(headerLength == length, "MeshHeader::ParseFrom() returned length is incorrect");
+    frameData.Init(frame, length);
+    VerifyOrQuit(Lowpan::MeshHeader::IsMeshHeader(frameData));
+    SuccessOrQuit(meshHeader.ParseFrom(frameData));
+    VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
+    VerifyOrQuit(frameData.GetBytes() - frame == length, "ParseFrom() did not skip over parsed content");
     VerifyOrQuit(meshHeader.GetSource() == kSourceAddr, "failed after ParseFrom()");
     VerifyOrQuit(meshHeader.GetDestination() == kDestAddr, "failed after ParseFrom()");
     VerifyOrQuit(meshHeader.GetHopsLeft() == 0x20, "failed after ParseFrom()");
 
-    VerifyOrQuit(meshHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
+    frameData.Init(frame, length - 1);
+    VerifyOrQuit(meshHeader.ParseFrom(frameData) == kErrorParse,
                  "MeshHeader::ParseFrom() did not fail with incorrect length");
 
     //- - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    SuccessOrQuit(meshHeader.ParseFrom(kMeshHeader3, sizeof(kMeshHeader3), headerLength));
-    VerifyOrQuit(headerLength == sizeof(kMeshHeader3), "MeshHeader::ParseFrom() returned length is incorrect");
+    length = sizeof(kMeshHeader3);
+    frameData.Init(kMeshHeader3, sizeof(kMeshHeader3));
+    SuccessOrQuit(meshHeader.ParseFrom(frameData));
+    VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
+    VerifyOrQuit(frameData.GetBytes() - kMeshHeader3 == length, "ParseFrom() did not skip over parsed content");
     VerifyOrQuit(meshHeader.GetSource() == kSourceAddr, "failed after ParseFrom()");
     VerifyOrQuit(meshHeader.GetDestination() == kDestAddr, "failed after ParseFrom()");
     VerifyOrQuit(meshHeader.GetHopsLeft() == 1, "failed after ParseFrom()");
 
     VerifyOrQuit(meshHeader.WriteTo(frame) == sizeof(kMeshHeader1));
 
-    VerifyOrQuit(meshHeader.ParseFrom(kMeshHeader3, sizeof(kMeshHeader3) - 1, headerLength) == kErrorParse,
+    frameData.Init(kMeshHeader3, sizeof(kMeshHeader3) - 1);
+    VerifyOrQuit(meshHeader.ParseFrom(frameData) == kErrorParse,
                  "MeshHeader::ParseFrom() did not fail with incorrect length");
 }
 
@@ -1924,7 +1960,7 @@
 
     uint8_t                frame[kMaxFrameSize];
     uint16_t               length;
-    uint16_t               headerLength;
+    FrameData              frameData;
     Lowpan::FragmentHeader fragHeader;
 
     fragHeader.InitFirstFragment(kSize, kTag);
@@ -1939,15 +1975,21 @@
     VerifyOrQuit(memcmp(frame, kFragHeader1, length) == 0, "FragmentHeader::WriteTo() failed");
 
     memset(&fragHeader, 0, sizeof(fragHeader));
-    VerifyOrQuit(Lowpan::FragmentHeader::IsFragmentHeader(frame, length));
-    SuccessOrQuit(fragHeader.ParseFrom(frame, length, headerLength));
-    VerifyOrQuit(headerLength == length, "FragmentHeader::ParseFrom() returned length is incorrect");
+
+    frameData.Init(frame, length);
+    VerifyOrQuit(Lowpan::FragmentHeader::IsFragmentHeader(frameData));
+    SuccessOrQuit(fragHeader.ParseFrom(frameData));
+    VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
+    VerifyOrQuit(frameData.GetBytes() - frame == length, "ParseFrom() did not skip over parsed content");
     VerifyOrQuit(fragHeader.GetDatagramSize() == kSize, "failed after ParseFrom()");
     VerifyOrQuit(fragHeader.GetDatagramTag() == kTag, "failed after ParseFrom()");
     VerifyOrQuit(fragHeader.GetDatagramOffset() == 0, "failed after ParseFrom()");
 
-    VerifyOrQuit(fragHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
+    frameData.Init(frame, length - 1);
+    VerifyOrQuit(fragHeader.ParseFrom(frameData) == kErrorParse,
                  "FragmentHeader::ParseFrom() did not fail with incorrect length");
+    VerifyOrQuit(frameData.GetLength() == length - 1);
+    VerifyOrQuit(frameData.GetBytes() == frame);
 
     //- - - - - - - - - - - - - - - - - - - - - - - - - -
 
@@ -1969,51 +2011,70 @@
     VerifyOrQuit(memcmp(frame, kFragHeader2, length) == 0, "FragmentHeader::WriteTo() failed");
 
     memset(&fragHeader, 0, sizeof(fragHeader));
-    VerifyOrQuit(Lowpan::FragmentHeader::IsFragmentHeader(frame, length));
-    SuccessOrQuit(fragHeader.ParseFrom(frame, length, headerLength));
-    VerifyOrQuit(headerLength == length, "FragmentHeader::ParseFrom() returned length is incorrect");
+    frameData.Init(frame, length);
+    VerifyOrQuit(Lowpan::FragmentHeader::IsFragmentHeader(frameData));
+    SuccessOrQuit(fragHeader.ParseFrom(frameData));
+    VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
+    VerifyOrQuit(frameData.GetBytes() - frame == length, "ParseFrom() did not skip over parsed content");
     VerifyOrQuit(fragHeader.GetDatagramSize() == kSize, "failed after ParseFrom()");
     VerifyOrQuit(fragHeader.GetDatagramTag() == kTag, "failed after ParseFrom()");
     VerifyOrQuit(fragHeader.GetDatagramOffset() == kOffset, "failed after ParseFrom()");
 
-    VerifyOrQuit(fragHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
+    frameData.Init(frame, length - 1);
+    VerifyOrQuit(fragHeader.ParseFrom(frameData) == kErrorParse,
                  "FragmentHeader::ParseFrom() did not fail with incorrect length");
+    VerifyOrQuit(frameData.GetLength() == length - 1);
+    VerifyOrQuit(frameData.GetBytes() == frame);
 
     //- - - - - - - - - - - - - - - - - - - - - - - - - -
 
     length = sizeof(kFragHeader3);
     memcpy(frame, kFragHeader3, length);
-    SuccessOrQuit(fragHeader.ParseFrom(frame, length, headerLength));
-    VerifyOrQuit(headerLength == length, "FragmentHeader::ParseFrom() returned length is incorrect");
+    frameData.Init(frame, length);
+    SuccessOrQuit(fragHeader.ParseFrom(frameData));
+    VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
+    VerifyOrQuit(frameData.GetBytes() - frame == length, "ParseFrom() did not skip over parsed content");
     VerifyOrQuit(fragHeader.GetDatagramSize() == kSize, "failed after ParseFrom()");
     VerifyOrQuit(fragHeader.GetDatagramTag() == kTag, "failed after ParseFrom()");
     VerifyOrQuit(fragHeader.GetDatagramOffset() == 0, "failed after ParseFrom()");
 
-    VerifyOrQuit(fragHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
+    frameData.Init(frame, length - 1);
+    VerifyOrQuit(fragHeader.ParseFrom(frameData) == kErrorParse,
                  "FragmentHeader::ParseFrom() did not fail with incorrect length");
+    VerifyOrQuit(frameData.GetLength() == length - 1);
+    VerifyOrQuit(frameData.GetBytes() == frame);
 
     //- - - - - - - - - - - - - - - - - - - - - - - - - -
 
     length = sizeof(kInvalidFragHeader1);
     memcpy(frame, kInvalidFragHeader1, length);
-    VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frame, length),
+    frameData.Init(frame, length);
+    VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frameData),
                  "IsFragmentHeader() did not detect invalid header");
-    VerifyOrQuit(fragHeader.ParseFrom(frame, length, headerLength) != kErrorNone,
+    VerifyOrQuit(fragHeader.ParseFrom(frameData) != kErrorNone,
                  "FragmentHeader::ParseFrom() did not fail with invalid header");
+    VerifyOrQuit(frameData.GetLength() == length);
+    VerifyOrQuit(frameData.GetBytes() == frame);
 
     length = sizeof(kInvalidFragHeader2);
     memcpy(frame, kInvalidFragHeader2, length);
-    VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frame, length),
+    frameData.Init(frame, length);
+    VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frameData),
                  "IsFragmentHeader() did not detect invalid header");
-    VerifyOrQuit(fragHeader.ParseFrom(frame, length, headerLength) != kErrorNone,
+    VerifyOrQuit(fragHeader.ParseFrom(frameData) != kErrorNone,
                  "FragmentHeader::ParseFrom() did not fail with invalid header");
+    VerifyOrQuit(frameData.GetLength() == length);
+    VerifyOrQuit(frameData.GetBytes() == frame);
 
     length = sizeof(kInvalidFragHeader3);
     memcpy(frame, kInvalidFragHeader3, length);
-    VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frame, length),
+    frameData.Init(frame, length);
+    VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frameData),
                  "IsFragmentHeader() did not detect invalid header");
-    VerifyOrQuit(fragHeader.ParseFrom(frame, length, headerLength) != kErrorNone,
+    VerifyOrQuit(fragHeader.ParseFrom(frameData) != kErrorNone,
                  "FragmentHeader::ParseFrom() did not fail with invalid header");
+    VerifyOrQuit(frameData.GetLength() == length);
+    VerifyOrQuit(frameData.GetBytes() == frame);
 }
 
 } // namespace ot
diff --git a/tests/unit/test_lowpan.hpp b/tests/unit/test_lowpan.hpp
index 64c52d7..b06fb07 100644
--- a/tests/unit/test_lowpan.hpp
+++ b/tests/unit/test_lowpan.hpp
@@ -100,6 +100,14 @@
     void SetMacDestination(uint16_t aAddress) { mMacDestination.SetShort(aAddress); }
 
     /**
+     * This method gets the IPv6 header
+     *
+     * @returns the IPv6 header.
+     *
+     */
+    const Ip6::Header &GetIpHeader(void) const { return mIpHeader; }
+
+    /**
      * This method initializes IPv6 Header.
      *
      * @param aVersionClassFlow Value of the Version, Traffic class and Flow control fields.
@@ -117,7 +125,7 @@
                      const char *aSource,
                      const char *aDestination)
     {
-        mIpHeader.Init(aVersionClassFlow);
+        mIpHeader.SetVerionTrafficClassFlow(aVersionClassFlow);
         mIpHeader.SetPayloadLength(aPayloadLength);
         mIpHeader.SetNextHeader(aNextHeader);
         mIpHeader.SetHopLimit(aHopLimit);
@@ -143,7 +151,7 @@
                              const char *aSource,
                              const char *aDestination)
     {
-        mIpTunneledHeader.Init(aVersionClassFlow);
+        mIpTunneledHeader.SetVerionTrafficClassFlow(aVersionClassFlow);
         mIpTunneledHeader.SetPayloadLength(aPayloadLength);
         mIpTunneledHeader.SetNextHeader(aNextHeader);
         mIpTunneledHeader.SetHopLimit(aHopLimit);
diff --git a/tests/unit/test_mac_frame.cpp b/tests/unit/test_mac_frame.cpp
index b5d5796..5aac167 100644
--- a/tests/unit/test_mac_frame.cpp
+++ b/tests/unit/test_mac_frame.cpp
@@ -154,85 +154,6 @@
     testFreeInstance(instance);
 }
 
-void CompareNetworkName(const Mac::NetworkName &aNetworkName, const char *aNameString)
-{
-    uint8_t len = static_cast<uint8_t>(strlen(aNameString));
-
-    VerifyOrQuit(strcmp(aNetworkName.GetAsCString(), aNameString) == 0);
-
-    VerifyOrQuit(aNetworkName.GetAsData().GetLength() == len);
-    VerifyOrQuit(memcmp(aNetworkName.GetAsData().GetBuffer(), aNameString, len) == 0);
-}
-
-void TestMacNetworkName(void)
-{
-    const char kEmptyName[]   = "";
-    const char kName1[]       = "network";
-    const char kName2[]       = "network-name";
-    const char kLongName[]    = "0123456789abcdef";
-    const char kTooLongName[] = "0123456789abcdef0";
-
-    char             buffer[sizeof(kTooLongName) + 2];
-    uint8_t          len;
-    Mac::NetworkName networkName;
-    Mac::NetworkName networkName2;
-
-    CompareNetworkName(networkName, kEmptyName);
-
-    SuccessOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1))));
-    CompareNetworkName(networkName, kName1);
-
-    VerifyOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1))) == kErrorAlready, "failed to detect duplicate");
-    CompareNetworkName(networkName, kName1);
-
-    VerifyOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1) - 1)) == kErrorAlready,
-                 "failed to detect duplicate");
-
-    SuccessOrQuit(networkName.Set(Mac::NameData(kName2, sizeof(kName2))));
-    CompareNetworkName(networkName, kName2);
-
-    VerifyOrQuit(networkName.Set(Mac::NameData(kEmptyName, 0)) == kErrorInvalidArgs);
-
-    SuccessOrQuit(networkName.Set(Mac::NameData(kLongName, sizeof(kLongName))));
-    CompareNetworkName(networkName, kLongName);
-
-    VerifyOrQuit(networkName.Set(Mac::NameData(kLongName, sizeof(kLongName) - 1)) == kErrorAlready,
-                 "failed to detect duplicate");
-
-    VerifyOrQuit(networkName.Set(kEmptyName) == kErrorInvalidArgs);
-
-    SuccessOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1))));
-
-    VerifyOrQuit(networkName.Set(Mac::NameData(kTooLongName, sizeof(kTooLongName))) == kErrorInvalidArgs,
-                 "accepted an invalid (too long) name");
-
-    CompareNetworkName(networkName, kName1);
-
-    memset(buffer, 'a', sizeof(buffer));
-    len = networkName.GetAsData().CopyTo(buffer, 1);
-    VerifyOrQuit(len == 1, "NameData::CopyTo() failed");
-    VerifyOrQuit(buffer[0] == kName1[0], "NameData::CopyTo() failed");
-    VerifyOrQuit(buffer[1] == 'a', "NameData::CopyTo() failed");
-
-    memset(buffer, 'a', sizeof(buffer));
-    len = networkName.GetAsData().CopyTo(buffer, sizeof(kName1) - 1);
-    VerifyOrQuit(len == sizeof(kName1) - 1, "NameData::CopyTo() failed");
-    VerifyOrQuit(memcmp(buffer, kName1, sizeof(kName1) - 1) == 0, "NameData::CopyTo() failed");
-    VerifyOrQuit(buffer[sizeof(kName1)] == 'a', "NameData::CopyTo() failed");
-
-    memset(buffer, 'a', sizeof(buffer));
-    len = networkName.GetAsData().CopyTo(buffer, sizeof(buffer));
-    VerifyOrQuit(len == sizeof(kName1) - 1, "NameData::CopyTo() failed");
-    VerifyOrQuit(memcmp(buffer, kName1, sizeof(kName1) - 1) == 0, "NameData::CopyTo() failed");
-    VerifyOrQuit(buffer[sizeof(kName1)] == 0, "NameData::CopyTo() failed");
-
-    SuccessOrQuit(networkName2.Set(Mac::NameData(kName1, sizeof(kName1))));
-    VerifyOrQuit(networkName == networkName2);
-
-    SuccessOrQuit(networkName2.Set(kName2));
-    VerifyOrQuit(networkName != networkName2);
-}
-
 void TestMacHeader(void)
 {
     static const struct
@@ -650,7 +571,6 @@
 int main(void)
 {
     ot::TestMacAddress();
-    ot::TestMacNetworkName();
     ot::TestMacHeader();
     ot::TestMacChannelMask();
     ot::TestMacFrameApi();
diff --git a/tests/unit/test_meshcop.cpp b/tests/unit/test_meshcop.cpp
index bcf823b..6dae027 100644
--- a/tests/unit/test_meshcop.cpp
+++ b/tests/unit/test_meshcop.cpp
@@ -139,7 +139,7 @@
     VerifyOrQuit(MeshCoP::Timestamp::Compare(&t1, &t2) == 0);
 
     t1.SetAuthoritative(true);
-    VerifyOrQuit(MeshCoP::Timestamp::Compare(&t1, &t2) == 0);
+    VerifyOrQuit(MeshCoP::Timestamp::Compare(&t1, &t2) > 0);
 
     t1.SetSeconds(1);
     VerifyOrQuit(t1.GetSeconds() == 1);
@@ -147,6 +147,7 @@
     VerifyOrQuit(MeshCoP::Timestamp::Compare(&t2, &t1) < 0);
 
     t2.SetSeconds(1);
+    t2.SetAuthoritative(true);
     VerifyOrQuit(MeshCoP::Timestamp::Compare(&t1, &t2) == 0);
 
     printf("TestTimestamp() passed\n");
diff --git a/tests/unit/test_message.cpp b/tests/unit/test_message.cpp
index 268620f..fe2ce3f 100644
--- a/tests/unit/test_message.cpp
+++ b/tests/unit/test_message.cpp
@@ -26,6 +26,7 @@
  *  POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "common/appender.hpp"
 #include "common/debug.hpp"
 #include "common/instance.hpp"
 #include "common/message.hpp"
@@ -53,6 +54,8 @@
     uint8_t      readBuffer[kMaxSize];
     uint8_t      zeroBuffer[kMaxSize];
 
+    printf("TestMessage\n");
+
     memset(zeroBuffer, 0, sizeof(zeroBuffer));
 
     instance = static_cast<Instance *>(testInitInstance());
@@ -62,7 +65,7 @@
 
     Random::NonCrypto::FillBuffer(writeBuffer, kMaxSize);
 
-    VerifyOrQuit((message = messagePool->New(Message::kTypeIp6, 0)) != nullptr);
+    VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
     SuccessOrQuit(message->SetLength(kMaxSize));
     message->WriteBytes(0, writeBuffer, kMaxSize);
     SuccessOrQuit(message->Read(0, readBuffer, kMaxSize));
@@ -133,7 +136,7 @@
 
     // Test `Message::CopyTo()` behavior.
 
-    VerifyOrQuit((message2 = messagePool->New(Message::kTypeIp6, 0)) != nullptr);
+    VerifyOrQuit((message2 = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
     SuccessOrQuit(message2->SetLength(kMaxSize));
 
     for (uint16_t srcOffset = 0; srcOffset < kMaxSize; srcOffset += kOffsetStep)
@@ -236,11 +239,101 @@
     testFreeInstance(instance);
 }
 
+void TestAppender(void)
+{
+    const uint8_t kData1[] = {0x01, 0x02, 0x03, 0x04};
+    const uint8_t kData2[] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa};
+
+    static constexpr uint16_t kMaxBufferSize = sizeof(kData1) * 2 + sizeof(kData2);
+
+    Instance *              instance;
+    Message *               message;
+    uint8_t                 buffer[kMaxBufferSize];
+    uint8_t                 zeroBuffer[kMaxBufferSize];
+    Appender                bufAppender(buffer, sizeof(buffer));
+    Data<kWithUint16Length> data;
+
+    printf("TestAppender\n");
+
+    instance = static_cast<Instance *>(testInitInstance());
+    VerifyOrQuit(instance != nullptr);
+
+    message = instance->Get<MessagePool>().Allocate(Message::kTypeIp6);
+    VerifyOrQuit(message != nullptr);
+
+    memset(buffer, 0, sizeof(buffer));
+    memset(zeroBuffer, 0, sizeof(zeroBuffer));
+
+    // Test Buffer Appender
+    VerifyOrQuit(bufAppender.GetType() == Appender::kBuffer);
+    VerifyOrQuit(bufAppender.GetBufferStart() == buffer);
+    VerifyOrQuit(bufAppender.GetAppendedLength() == 0);
+
+    SuccessOrQuit(bufAppender.AppendBytes(kData1, sizeof(kData1)));
+    DumpBuffer("Data1", buffer, sizeof(buffer));
+    VerifyOrQuit(bufAppender.GetAppendedLength() == sizeof(kData1));
+    VerifyOrQuit(bufAppender.GetBufferStart() == buffer);
+    VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
+    VerifyOrQuit(memcmp(buffer + sizeof(kData1), zeroBuffer, sizeof(buffer) - sizeof(kData1)) == 0);
+
+    SuccessOrQuit(bufAppender.AppendBytes(kData2, sizeof(kData2)));
+    DumpBuffer("Data1+Data2", buffer, sizeof(buffer));
+    VerifyOrQuit(bufAppender.GetAppendedLength() == sizeof(kData1) + sizeof(kData2));
+    VerifyOrQuit(bufAppender.GetBufferStart() == buffer);
+    VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
+    VerifyOrQuit(memcmp(buffer + sizeof(kData1), kData2, sizeof(kData2)) == 0);
+    VerifyOrQuit(memcmp(buffer + sizeof(kData1) + sizeof(kData2), zeroBuffer,
+                        sizeof(buffer) - sizeof(kData1) - sizeof(kData2)) == 0);
+
+    VerifyOrQuit(bufAppender.Append(kData2) == kErrorNoBufs);
+
+    SuccessOrQuit(bufAppender.AppendBytes(kData1, sizeof(kData1)));
+    DumpBuffer("Data1+Data2+Data1", buffer, sizeof(buffer));
+    VerifyOrQuit(bufAppender.GetAppendedLength() == sizeof(kData1) + sizeof(kData2) + sizeof(kData1));
+    VerifyOrQuit(bufAppender.GetBufferStart() == buffer);
+    VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
+    VerifyOrQuit(memcmp(buffer + sizeof(kData1), kData2, sizeof(kData2)) == 0);
+    VerifyOrQuit(memcmp(buffer + sizeof(kData1) + sizeof(kData2), kData1, sizeof(kData1)) == 0);
+
+    VerifyOrQuit(bufAppender.Append<uint8_t>(0) == kErrorNoBufs);
+
+    bufAppender.GetAsData(data);
+    VerifyOrQuit(data.GetBytes() == buffer);
+    VerifyOrQuit(data.GetLength() == sizeof(buffer));
+
+    // Test Message Appender
+
+    SuccessOrQuit(message->Append(kData2));
+    VerifyOrQuit(message->Compare(0, kData2));
+
+    {
+        Appender msgAppender(*message);
+        uint16_t offset = message->GetLength();
+
+        VerifyOrQuit(msgAppender.GetType() == Appender::kMessage);
+
+        SuccessOrQuit(msgAppender.AppendBytes(kData1, sizeof(kData1)));
+        VerifyOrQuit(msgAppender.GetAppendedLength() == sizeof(kData1));
+
+        VerifyOrQuit(message->GetLength() == sizeof(kData2) + sizeof(kData1));
+        VerifyOrQuit(message->Compare(offset, kData1));
+
+        SuccessOrQuit(msgAppender.AppendBytes(kData2, sizeof(kData2)));
+        VerifyOrQuit(msgAppender.GetAppendedLength() == sizeof(kData1) + sizeof(kData2));
+        VerifyOrQuit(message->Compare(offset, kData1));
+        VerifyOrQuit(message->Compare(offset + sizeof(kData1), kData2));
+    }
+
+    message->Free();
+    testFreeInstance(instance);
+}
+
 } // namespace ot
 
 int main(void)
 {
     ot::TestMessage();
+    ot::TestAppender();
     printf("All tests passed\n");
     return 0;
 }
diff --git a/tests/unit/test_message_queue.cpp b/tests/unit/test_message_queue.cpp
index e186a84..b8cedc6 100644
--- a/tests/unit/test_message_queue.cpp
+++ b/tests/unit/test_message_queue.cpp
@@ -46,9 +46,10 @@
 // This function verifies the content of the message queue to match the passed in messages
 void VerifyMessageQueueContent(ot::MessageQueue &aMessageQueue, int aExpectedLength, ...)
 {
-    va_list      args;
-    ot::Message *message;
-    ot::Message *msgArg;
+    const ot::MessageQueue &constQueue = aMessageQueue;
+    va_list                 args;
+    ot::Message *           message;
+    ot::Message *           msgArg;
 
     va_start(args, aExpectedLength);
 
@@ -69,17 +70,41 @@
             aExpectedLength--;
         }
 
-        VerifyOrQuit(aExpectedLength == 0, "less entries than expected");
+        VerifyOrQuit(aExpectedLength == 0, "fewer entries than expected");
     }
 
     va_end(args);
+
+    // Check range-based `for` loop iteration using non-const iterator
+
+    message = aMessageQueue.GetHead();
+
+    for (ot::Message &msg : aMessageQueue)
+    {
+        VerifyOrQuit(message == &msg, "`for` loop iteration does not match expected");
+        message = message->GetNext();
+    }
+
+    VerifyOrQuit(message == nullptr, "`for` loop iteration resulted in fewer entries than expected");
+
+    // Check  range-base `for` iteration using const iterator
+
+    message = aMessageQueue.GetHead();
+
+    for (const ot::Message &constMsg : constQueue)
+    {
+        VerifyOrQuit(message == &constMsg, "`for` loop iteration does not match expected");
+        message = message->GetNext();
+    }
+
+    VerifyOrQuit(message == nullptr, "`for` loop iteration resulted in fewer entries than expected");
 }
 
 void TestMessageQueue(void)
 {
-    ot::MessageQueue messageQueue;
-    ot::Message *    messages[kNumTestMessages];
-    uint16_t         msgCount, bufferCount;
+    ot::MessageQueue       messageQueue;
+    ot::Message *          messages[kNumTestMessages];
+    ot::MessageQueue::Info info;
 
     sInstance = testInitInstance();
     VerifyOrQuit(sInstance != nullptr);
@@ -88,8 +113,8 @@
 
     for (ot::Message *&msg : messages)
     {
-        msg = sMessagePool->New(ot::Message::kTypeIp6, 0);
-        VerifyOrQuit(msg != nullptr, "Message::New() failed");
+        msg = sMessagePool->Allocate(ot::Message::kTypeIp6);
+        VerifyOrQuit(msg != nullptr, "Message::Allocate() failed");
     }
 
     VerifyMessageQueueContent(messageQueue, 0);
@@ -119,8 +144,9 @@
     VerifyMessageQueueContent(messageQueue, 5, messages[0], messages[1], messages[2], messages[3], messages[4]);
 
     // Check the GetInfo()
-    messageQueue.GetInfo(msgCount, bufferCount);
-    VerifyOrQuit(msgCount == 5, "MessageQueue::GetInfo() failed.");
+    memset(&info, 0, sizeof(info));
+    messageQueue.GetInfo(info);
+    VerifyOrQuit(info.mNumMessages == 5, "MessageQueue::GetInfo() failed.");
 
     // Remove from head
     messageQueue.Dequeue(*messages[0]);
@@ -174,6 +200,47 @@
     messageQueue.Dequeue(*messages[0]);
     VerifyMessageQueueContent(messageQueue, 0);
 
+    // Range-based `for` and dequeue during iteration
+
+    for (uint16_t removeIndex = 0; removeIndex < 5; removeIndex++)
+    {
+        uint16_t index = 0;
+
+        messageQueue.Enqueue(*messages[0]);
+        messageQueue.Enqueue(*messages[1]);
+        messageQueue.Enqueue(*messages[2]);
+        messageQueue.Enqueue(*messages[3]);
+        messageQueue.Enqueue(*messages[4]);
+        VerifyMessageQueueContent(messageQueue, 5, messages[0], messages[1], messages[2], messages[3], messages[4]);
+
+        // While iterating over the queue remove the entry at `removeIndex`
+        for (ot::Message &message : messageQueue)
+        {
+            if (index == removeIndex)
+            {
+                messageQueue.Dequeue(message);
+            }
+
+            VerifyOrQuit(&message == messages[index++]);
+        }
+
+        index = 0;
+
+        // Iterate over the queue and remove all
+        for (ot::Message &message : messageQueue)
+        {
+            if (index == removeIndex)
+            {
+                index++;
+            }
+
+            VerifyOrQuit(&message == messages[index++]);
+            messageQueue.Dequeue(message);
+        }
+
+        VerifyMessageQueueContent(messageQueue, 0);
+    }
+
     testFreeInstance(sInstance);
 }
 
diff --git a/tests/unit/test_netif.cpp b/tests/unit/test_netif.cpp
index 121f4ac..d82b051 100644
--- a/tests/unit/test_netif.cpp
+++ b/tests/unit/test_netif.cpp
@@ -168,11 +168,11 @@
     VerifyMulticastAddressList(netif, &addresses[0], 8);
 
     IgnoreError(address.FromString(kTestAddress1)); // same as netifAddress (internal)
-    VerifyOrQuit(netif.UnsubscribeExternalMulticast(address) == kErrorInvalidArgs,
+    VerifyOrQuit(netif.UnsubscribeExternalMulticast(address) == kErrorRejected,
                  "UnsubscribeExternalMulticast() did not fail when address was not external");
 
     IgnoreError(address.FromString(kRealmLocalAllMpl));
-    VerifyOrQuit(netif.UnsubscribeExternalMulticast(address) == kErrorInvalidArgs,
+    VerifyOrQuit(netif.UnsubscribeExternalMulticast(address) == kErrorRejected,
                  "UnsubscribeExternalMulticast() did not fail when address was fixed address");
 
     netif.UnsubscribeAllRoutersMulticast();
@@ -200,7 +200,7 @@
 
     for (uint8_t i = 0; i < 5; i++)
     {
-        VerifyOrQuit(netif.SubscribeExternalMulticast(addresses[i]) == kErrorInvalidArgs,
+        VerifyOrQuit(netif.SubscribeExternalMulticast(addresses[i]) == kErrorRejected,
                      "SubscribeExternalMulticast() did not fail when address was a default/fixed address");
     }
 }
diff --git a/tests/unit/test_network_data.cpp b/tests/unit/test_network_data.cpp
index 31438a1..44df236 100644
--- a/tests/unit/test_network_data.cpp
+++ b/tests/unit/test_network_data.cpp
@@ -28,6 +28,7 @@
 
 #include <openthread/config.h>
 
+#include "common/array.hpp"
 #include "common/code_utils.hpp"
 #include "common/instance.hpp"
 #include "thread/network_data_leader.hpp"
@@ -42,7 +43,7 @@
 
 void PrintExternalRouteConfig(const ExternalRouteConfig &aConfig)
 {
-    printf("\nprefix:");
+    printf("\nroute-prefix:");
 
     for (uint8_t b : aConfig.mPrefix.mPrefix.mFields.m8)
     {
@@ -53,6 +54,19 @@
            aConfig.mRloc16, aConfig.mPreference, aConfig.mNat64, aConfig.mStable, aConfig.mNextHopIsThisDevice);
 }
 
+void PrintOnMeshPrefixConfig(const OnMeshPrefixConfig &aConfig)
+{
+    printf("\non-mesh-prefix:");
+
+    for (uint8_t b : aConfig.mPrefix.mPrefix.mFields.m8)
+    {
+        printf("%02x", b);
+    }
+
+    printf(", length:%d, rloc16:%04x, preference:%d, stable:%d, def-route:%d", aConfig.mPrefix.mLength, aConfig.mRloc16,
+           aConfig.mPreference, aConfig.mStable, aConfig.mDefaultRoute);
+}
+
 // Returns true if the two given ExternalRouteConfig match (intentionally ignoring mNextHopIsThisDevice).
 bool CompareExternalRouteConfig(const otExternalRouteConfig &aConfig1, const otExternalRouteConfig &aConfig2)
 {
@@ -62,11 +76,42 @@
            (aConfig1.mPreference == aConfig2.mPreference) && (aConfig1.mStable == aConfig2.mStable);
 }
 
+// Returns true if the two given OnMeshprefix match.
+bool CompareOnMeshPrefixConfig(const otBorderRouterConfig &aConfig1, const otBorderRouterConfig &aConfig2)
+{
+    return (memcmp(aConfig1.mPrefix.mPrefix.mFields.m8, aConfig2.mPrefix.mPrefix.mFields.m8,
+                   sizeof(aConfig1.mPrefix.mPrefix)) == 0) &&
+           (aConfig1.mPrefix.mLength == aConfig2.mPrefix.mLength) && (aConfig1.mRloc16 == aConfig2.mRloc16) &&
+           (aConfig1.mPreference == aConfig2.mPreference) && (aConfig1.mStable == aConfig2.mStable) &&
+           (aConfig1.mDefaultRoute == aConfig2.mDefaultRoute) && (aConfig1.mOnMesh == aConfig2.mOnMesh);
+}
+
+template <uint8_t kLength>
+void VerifyRlocsArray(const uint16_t *aRlocs, uint16_t aRlocsLength, const uint16_t (&aExpectedRlocs)[kLength])
+{
+    VerifyOrQuit(aRlocsLength == kLength);
+
+    printf("\nRLOCs: { ");
+
+    for (uint8_t index = 0; index < aRlocsLength; index++)
+    {
+        VerifyOrQuit(aRlocs[index] == aExpectedRlocs[index]);
+        printf("0x%04x ", aRlocs[index]);
+    }
+
+    printf("}");
+}
+
 void TestNetworkDataIterator(void)
 {
+    static constexpr uint8_t kMaxRlocsArray = 10;
+
     ot::Instance *      instance;
     Iterator            iter = kIteratorInit;
-    ExternalRouteConfig config;
+    ExternalRouteConfig rconfig;
+    OnMeshPrefixConfig  pconfig;
+    uint16_t            rlocs[kMaxRlocsArray];
+    uint8_t             rlocsLength;
 
     instance = testInitInstance();
     VerifyOrQuit(instance != nullptr);
@@ -104,6 +149,9 @@
             },
         };
 
+        const uint16_t kRlocs[]            = {0xc800, 0x5400};
+        const uint16_t kNonExistingRlocs[] = {0xc700, 0x0000, 0x5401};
+
         NetworkData netData(*instance, kNetworkData, sizeof(kNetworkData));
 
         iter = OT_NETWORK_DATA_ITERATOR_INIT;
@@ -113,9 +161,34 @@
 
         for (const auto &route : routes)
         {
-            SuccessOrQuit(netData.GetNextExternalRoute(iter, config));
-            PrintExternalRouteConfig(config);
-            VerifyOrQuit(CompareExternalRouteConfig(config, route));
+            SuccessOrQuit(netData.GetNextExternalRoute(iter, rconfig));
+            PrintExternalRouteConfig(rconfig);
+            VerifyOrQuit(CompareExternalRouteConfig(rconfig, route));
+        }
+
+        rlocsLength = GetArrayLength(rlocs);
+        SuccessOrQuit(netData.FindBorderRouters(kAnyRole, rlocs, rlocsLength));
+        VerifyRlocsArray(rlocs, rlocsLength, kRlocs);
+        VerifyOrQuit(netData.CountBorderRouters(kAnyRole) == GetArrayLength(kRlocs));
+
+        rlocsLength = GetArrayLength(rlocs);
+        SuccessOrQuit(netData.FindBorderRouters(kRouterRoleOnly, rlocs, rlocsLength));
+        VerifyRlocsArray(rlocs, rlocsLength, kRlocs);
+        VerifyOrQuit(netData.CountBorderRouters(kRouterRoleOnly) == GetArrayLength(kRlocs));
+
+        rlocsLength = GetArrayLength(rlocs);
+        SuccessOrQuit(netData.FindBorderRouters(kChildRoleOnly, rlocs, rlocsLength));
+        VerifyOrQuit(rlocsLength == 0);
+        VerifyOrQuit(netData.CountBorderRouters(kChildRoleOnly) == 0);
+
+        for (uint16_t rloc16 : kRlocs)
+        {
+            VerifyOrQuit(netData.ContainsBorderRouterWithRloc(rloc16));
+        }
+
+        for (uint16_t rloc16 : kNonExistingRlocs)
+        {
+            VerifyOrQuit(!netData.ContainsBorderRouterWithRloc(rloc16));
         }
     }
 
@@ -124,7 +197,7 @@
             0x08, 0x04, 0x0B, 0x02, 0x00, 0x00, 0x03, 0x1E, 0x00, 0x40, 0xFD, 0x00, 0x12, 0x34, 0x56, 0x78, 0x00, 0x00,
             0x07, 0x02, 0x11, 0x40, 0x00, 0x03, 0x10, 0x00, 0x40, 0x01, 0x03, 0x54, 0x00, 0x00, 0x05, 0x04, 0x54, 0x00,
             0x31, 0x00, 0x02, 0x0F, 0x00, 0x40, 0xFD, 0x00, 0xAB, 0xBA, 0xCD, 0xDC, 0x00, 0x00, 0x00, 0x03, 0x10, 0x00,
-            0x20, 0x03, 0x0E, 0x00, 0x20, 0xFD, 0x00, 0xAB, 0xBA, 0x01, 0x06, 0x54, 0x00, 0x00, 0x04, 0x00, 0x00,
+            0x20, 0x03, 0x0E, 0x00, 0x20, 0xFD, 0x00, 0xAB, 0xBA, 0x01, 0x06, 0x54, 0x00, 0x00, 0x04, 0x01, 0x00,
         };
 
         otExternalRouteConfig routes[] = {
@@ -182,7 +255,7 @@
                        0x00}}},
                     32,
                 },
-                0x0400, // mRloc16
+                0x0401, // mRloc16
                 0,      // mPreference
                 false,  // mNat64
                 true,   // mStable
@@ -190,6 +263,11 @@
             },
         };
 
+        const uint16_t kRlocsAnyRole[]     = {0x1000, 0x5400, 0x0401};
+        const uint16_t kRlocsRouterRole[]  = {0x1000, 0x5400};
+        const uint16_t kRlocsChildRole[]   = {0x0401};
+        const uint16_t kNonExistingRlocs[] = {0x6000, 0x0000, 0x0402};
+
         NetworkData netData(*instance, kNetworkData, sizeof(kNetworkData));
 
         iter = OT_NETWORK_DATA_ITERATOR_INIT;
@@ -199,9 +277,212 @@
 
         for (const auto &route : routes)
         {
-            SuccessOrQuit(netData.GetNextExternalRoute(iter, config));
-            PrintExternalRouteConfig(config);
-            VerifyOrQuit(CompareExternalRouteConfig(config, route));
+            SuccessOrQuit(netData.GetNextExternalRoute(iter, rconfig));
+            PrintExternalRouteConfig(rconfig);
+            VerifyOrQuit(CompareExternalRouteConfig(rconfig, route));
+        }
+
+        rlocsLength = GetArrayLength(rlocs);
+        SuccessOrQuit(netData.FindBorderRouters(kAnyRole, rlocs, rlocsLength));
+        VerifyRlocsArray(rlocs, rlocsLength, kRlocsAnyRole);
+        VerifyOrQuit(netData.CountBorderRouters(kAnyRole) == GetArrayLength(kRlocsAnyRole));
+
+        rlocsLength = GetArrayLength(rlocs);
+        SuccessOrQuit(netData.FindBorderRouters(kRouterRoleOnly, rlocs, rlocsLength));
+        VerifyRlocsArray(rlocs, rlocsLength, kRlocsRouterRole);
+        VerifyOrQuit(netData.CountBorderRouters(kRouterRoleOnly) == GetArrayLength(kRlocsRouterRole));
+
+        rlocsLength = GetArrayLength(rlocs);
+        SuccessOrQuit(netData.FindBorderRouters(kChildRoleOnly, rlocs, rlocsLength));
+        VerifyRlocsArray(rlocs, rlocsLength, kRlocsChildRole);
+        VerifyOrQuit(netData.CountBorderRouters(kChildRoleOnly) == GetArrayLength(kRlocsChildRole));
+
+        // Test failure case when given array is smaller than number of RLOCs.
+        rlocsLength = GetArrayLength(kRlocsAnyRole) - 1;
+        VerifyOrQuit(netData.FindBorderRouters(kAnyRole, rlocs, rlocsLength) == kErrorNoBufs);
+        VerifyOrQuit(rlocsLength == GetArrayLength(kRlocsAnyRole) - 1);
+        for (uint8_t index = 0; index < rlocsLength; index++)
+        {
+            VerifyOrQuit(rlocs[index] == kRlocsAnyRole[index]);
+        }
+
+        rlocsLength = GetArrayLength(kRlocsAnyRole);
+        SuccessOrQuit(netData.FindBorderRouters(kAnyRole, rlocs, rlocsLength));
+        VerifyRlocsArray(rlocs, rlocsLength, kRlocsAnyRole);
+
+        for (uint16_t rloc16 : kRlocsAnyRole)
+        {
+            VerifyOrQuit(netData.ContainsBorderRouterWithRloc(rloc16));
+        }
+
+        for (uint16_t rloc16 : kNonExistingRlocs)
+        {
+            VerifyOrQuit(!netData.ContainsBorderRouterWithRloc(rloc16));
+        }
+    }
+
+    {
+        const uint8_t kNetworkData[] = {
+            0x08, 0x04, 0x0b, 0x02, 0x36, 0xcc, 0x03, 0x1c, 0x00, 0x40, 0xfd, 0x00, 0xbe, 0xef, 0xca, 0xfe,
+            0x00, 0x00, 0x05, 0x0c, 0x28, 0x00, 0x33, 0x00, 0x28, 0x01, 0x33, 0x00, 0x4c, 0x00, 0x31, 0x00,
+            0x07, 0x02, 0x11, 0x40, 0x03, 0x14, 0x00, 0x40, 0xfd, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00,
+            0x05, 0x04, 0x28, 0x00, 0x73, 0x00, 0x07, 0x02, 0x12, 0x40, 0x03, 0x12, 0x00, 0x40, 0xfd, 0x00,
+            0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0xec, 0x00, 0x00, 0x28, 0x01, 0xc0,
+        };
+
+        otExternalRouteConfig routes[] = {
+            {
+                {
+                    {{{0xfd, 0x00, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00}}},
+                    64,
+                },
+                0xec00, // mRloc16
+                0,      // mPreference
+                false,  // mNat64
+                true,   // mStable
+                false,  // mNextHopIsThisDevice
+            },
+            {
+                {
+                    {{{0xfd, 0x00, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00}}},
+                    64,
+                },
+                0x2801, // mRloc16
+                -1,     // mPreference
+                false,  // mNat64
+                true,   // mStable
+                false,  // mNextHopIsThisDevice
+            },
+        };
+
+        otBorderRouterConfig prefixes[] = {
+            {
+                {
+                    {{{0xfd, 0x00, 0xbe, 0xef, 0xca, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00}}},
+                    64,
+                },
+                0,      // mPreference
+                true,   // mPreferred
+                true,   // mSlaac
+                false,  // mDhcp
+                true,   // mConfigure
+                true,   // mDefaultRoute
+                true,   // mOnMesh
+                true,   // mStable
+                false,  // mNdDns
+                false,  // mDp
+                0x2800, // mRloc16
+            },
+            {
+                {
+                    {{{0xfd, 0x00, 0xbe, 0xef, 0xca, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00}}},
+                    64,
+                },
+                0,      // mPreference
+                true,   // mPreferred
+                true,   // mSlaac
+                false,  // mDhcp
+                true,   // mConfigure
+                true,   // mDefaultRoute
+                true,   // mOnMesh
+                true,   // mStable
+                false,  // mNdDns
+                false,  // mDp
+                0x2801, // mRloc16
+            },
+            {
+                {
+                    {{{0xfd, 0x00, 0xbe, 0xef, 0xca, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00}}},
+                    64,
+                },
+                0,      // mPreference
+                true,   // mPreferred
+                true,   // mSlaac
+                false,  // mDhcp
+                true,   // mConfigure
+                false,  // mDefaultRoute
+                true,   // mOnMesh
+                true,   // mStable
+                false,  // mNdDns
+                false,  // mDp
+                0x4c00, // mRloc16
+            },
+            {
+                {
+                    {{{0xfd, 0x00, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00}}},
+                    64,
+                },
+                1,      // mPreference
+                true,   // mPreferred
+                true,   // mSlaac
+                false,  // mDhcp
+                true,   // mConfigure
+                true,   // mDefaultRoute
+                true,   // mOnMesh
+                true,   // mStable
+                false,  // mNdDns
+                false,  // mDp
+                0x2800, // mRloc16
+            },
+        };
+
+        const uint16_t kRlocsAnyRole[]     = {0xec00, 0x2801, 0x2800};
+        const uint16_t kRlocsRouterRole[]  = {0xec00, 0x2800};
+        const uint16_t kRlocsChildRole[]   = {0x2801};
+        const uint16_t kNonExistingRlocs[] = {0x6000, 0x0000, 0x2806, 0x4c00};
+
+        NetworkData netData(*instance, kNetworkData, sizeof(kNetworkData));
+
+        printf("\nTest #3: Network data 3");
+        printf("\n-------------------------------------------------");
+
+        iter = OT_NETWORK_DATA_ITERATOR_INIT;
+
+        for (const auto &route : routes)
+        {
+            SuccessOrQuit(netData.GetNextExternalRoute(iter, rconfig));
+            PrintExternalRouteConfig(rconfig);
+            VerifyOrQuit(CompareExternalRouteConfig(rconfig, route));
+        }
+
+        iter = OT_NETWORK_DATA_ITERATOR_INIT;
+
+        for (const auto &prefix : prefixes)
+        {
+            SuccessOrQuit(netData.GetNextOnMeshPrefix(iter, pconfig));
+            PrintOnMeshPrefixConfig(pconfig);
+            VerifyOrQuit(CompareOnMeshPrefixConfig(pconfig, prefix));
+        }
+
+        rlocsLength = GetArrayLength(rlocs);
+        SuccessOrQuit(netData.FindBorderRouters(kAnyRole, rlocs, rlocsLength));
+        VerifyRlocsArray(rlocs, rlocsLength, kRlocsAnyRole);
+        VerifyOrQuit(netData.CountBorderRouters(kAnyRole) == GetArrayLength(kRlocsAnyRole));
+
+        rlocsLength = GetArrayLength(rlocs);
+        SuccessOrQuit(netData.FindBorderRouters(kRouterRoleOnly, rlocs, rlocsLength));
+        VerifyRlocsArray(rlocs, rlocsLength, kRlocsRouterRole);
+        VerifyOrQuit(netData.CountBorderRouters(kRouterRoleOnly) == GetArrayLength(kRlocsRouterRole));
+
+        rlocsLength = GetArrayLength(rlocs);
+        SuccessOrQuit(netData.FindBorderRouters(kChildRoleOnly, rlocs, rlocsLength));
+        VerifyRlocsArray(rlocs, rlocsLength, kRlocsChildRole);
+        VerifyOrQuit(netData.CountBorderRouters(kChildRoleOnly) == GetArrayLength(kRlocsChildRole));
+
+        for (uint16_t rloc16 : kRlocsAnyRole)
+        {
+            VerifyOrQuit(netData.ContainsBorderRouterWithRloc(rloc16));
+        }
+
+        for (uint16_t rloc16 : kNonExistingRlocs)
+        {
+            VerifyOrQuit(!netData.ContainsBorderRouterWithRloc(rloc16));
         }
     }
 
@@ -318,6 +599,11 @@
 
 void TestNetworkDataDsnSrpServices(void)
 {
+    static const char *kOriginStrings[] = {
+        "service-data", // (0) Service::DnsSrpUnicast::kFromServiceData
+        "server-data",  // (1) Service::DnsSrpUnicast::kFromServerData
+    };
+
     class TestLeader : public Leader
     {
     public:
@@ -353,8 +639,9 @@
 
         struct UnicastEntry
         {
-            const char *mAddress;
-            uint16_t    mPort;
+            const char *                   mAddress;
+            uint16_t                       mPort;
+            Service::DnsSrpUnicast::Origin mOrigin;
 
             bool Matches(Service::DnsSrpUnicast::Info aInfo) const
             {
@@ -363,7 +650,7 @@
                 SuccessOrQuit(sockAddr.GetAddress().FromString(mAddress));
                 sockAddr.SetPort(mPort);
 
-                return (aInfo.mSockAddr == sockAddr);
+                return (aInfo.mSockAddr == sockAddr) && (aInfo.mOrigin == mOrigin);
             }
         };
 
@@ -384,9 +671,11 @@
         };
 
         const UnicastEntry kUnicastEntries[] = {
-            {"fdde:ad00:beef:0:2d0e:c627:5556:18d9", 0x1234}, {"fd00:aabb:ccdd:eeff:11:2233:4455:6677", 0xabcd},
-            {"fdde:ad00:beef:0:0:ff:fe00:2800", 0x5678},      {"fd00:1234:5678:9abc:def0:123:4567:89ab", 0x0e},
-            {"fdde:ad00:beef:0:0:ff:fe00:6c00", 0xcd12},
+            {"fdde:ad00:beef:0:2d0e:c627:5556:18d9", 0x1234, Service::DnsSrpUnicast::kFromServiceData},
+            {"fd00:aabb:ccdd:eeff:11:2233:4455:6677", 0xabcd, Service::DnsSrpUnicast::kFromServerData},
+            {"fdde:ad00:beef:0:0:ff:fe00:2800", 0x5678, Service::DnsSrpUnicast::kFromServerData},
+            {"fd00:1234:5678:9abc:def0:123:4567:89ab", 0x0e, Service::DnsSrpUnicast::kFromServerData},
+            {"fdde:ad00:beef:0:0:ff:fe00:6c00", 0xcd12, Service::DnsSrpUnicast::kFromServerData},
         };
 
         const uint8_t kPreferredAnycastEntryIndex = 2;
@@ -436,7 +725,8 @@
         for (const UnicastEntry &entry : kUnicastEntries)
         {
             SuccessOrQuit(manager.GetNextDnsSrpUnicastInfo(iterator, unicastInfo));
-            printf("\nunicastInfo %s", unicastInfo.mSockAddr.ToString().AsCString());
+            printf("\nunicastInfo { %s, origin:%s }", unicastInfo.mSockAddr.ToString().AsCString(),
+                   kOriginStrings[unicastInfo.mOrigin]);
 
             VerifyOrQuit(entry.Matches(unicastInfo), "GetNextDnsSrpUnicastInfo() returned incorrect info");
         }
@@ -450,6 +740,187 @@
     testFreeInstance(instance);
 }
 
+void TestNetworkDataDsnSrpAnycastSeqNumSelection(void)
+{
+    class TestLeader : public Leader
+    {
+    public:
+        void Populate(const uint8_t *aTlvs, uint8_t aTlvsLength)
+        {
+            memcpy(GetBytes(), aTlvs, aTlvsLength);
+            SetLength(aTlvsLength);
+        }
+    };
+
+    struct TestInfo
+    {
+        const uint8_t *mNetworkData;
+        uint8_t        mNetworkDataLength;
+        const uint8_t *mSeqNumbers;
+        uint8_t        mSeqNumbersLength;
+        uint8_t        mPreferredSeqNum;
+    };
+
+    ot::Instance *instance;
+
+    printf("\n\n-------------------------------------------------");
+    printf("\nTestNetworkDataDsnSrpAnycastSeqNumSelection()\n");
+
+    instance = testInitInstance();
+    VerifyOrQuit(instance != nullptr);
+
+    const uint8_t kNetworkData1[] = {
+        0x08, 0x04, 0x0b, 0x02, 0x50, 0xb0,                         // Service TLV
+        0x0b, 0x08, 0x80, 0x02, 0x5c, 0x01, 0x0d, 0x02, 0x50, 0x00, // Server sub-TLV
+        0x0b, 0x08, 0x81, 0x02, 0x5c, 0x81, 0x0d, 0x02, 0x50, 0x01, // Server sub-TLV
+    };
+    const uint8_t kSeqNumbers1[]    = {1, 129};
+    const uint8_t kPreferredSeqNum1 = 129;
+
+    const uint8_t kNetworkData2[] = {
+        0x08, 0x04, 0x0b, 0x02, 0x50, 0xb0,                         // Service TLV
+        0x0b, 0x08, 0x80, 0x02, 0x5c, 0x85, 0x0d, 0x02, 0x50, 0x00, // Server sub-TLV
+        0x0b, 0x08, 0x81, 0x02, 0x5c, 0x05, 0x0d, 0x02, 0x50, 0x01, // Server sub-TLV
+    };
+    const uint8_t kSeqNumbers2[]    = {133, 5};
+    const uint8_t kPreferredSeqNum2 = 133;
+
+    const uint8_t kNetworkData3[] = {
+        0x08, 0x04, 0x0b, 0x02, 0x50, 0xb0,                         // Service TLV
+        0x0b, 0x08, 0x80, 0x02, 0x5c, 0x01, 0x0d, 0x02, 0x50, 0x00, // Server sub-TLV
+        0x0b, 0x08, 0x81, 0x02, 0x5c, 0x02, 0x0d, 0x02, 0x50, 0x01, // Server sub-TLV
+        0x0b, 0x08, 0x82, 0x02, 0x5c, 0xff, 0x0d, 0x02, 0x50, 0x02, // Server sub-TLV
+    };
+    const uint8_t kSeqNumbers3[]    = {1, 2, 255};
+    const uint8_t kPreferredSeqNum3 = 2;
+
+    const uint8_t kNetworkData4[] = {
+        0x08, 0x04, 0x0b, 0x02, 0x50, 0xb0,                         // Service TLV
+        0x0b, 0x08, 0x80, 0x02, 0x5c, 0x0a, 0x0d, 0x02, 0x50, 0x00, // Server sub-TLV
+        0x0b, 0x08, 0x81, 0x02, 0x5c, 0x82, 0x0d, 0x02, 0x50, 0x01, // Server sub-TLV
+        0x0b, 0x08, 0x82, 0x02, 0x5c, 0xfa, 0x0d, 0x02, 0x50, 0x02, // Server sub-TLV
+    };
+    const uint8_t kSeqNumbers4[]    = {10, 130, 250};
+    const uint8_t kPreferredSeqNum4 = 250;
+
+    const uint8_t kNetworkData5[] = {
+        0x08, 0x04, 0x0b, 0x02, 0x50, 0xb0,                         // Service TLV
+        0x0b, 0x08, 0x80, 0x02, 0x5c, 0x82, 0x0d, 0x02, 0x50, 0x00, // Server sub-TLV
+        0x0b, 0x08, 0x81, 0x02, 0x5c, 0xfa, 0x0d, 0x02, 0x50, 0x01, // Server sub-TLV
+        0x0b, 0x08, 0x82, 0x02, 0x5c, 0x0a, 0x0d, 0x02, 0x50, 0x02, // Server sub-TLV
+    };
+    const uint8_t kSeqNumbers5[]    = {130, 250, 10};
+    const uint8_t kPreferredSeqNum5 = 250;
+
+    const uint8_t kNetworkData6[] = {
+        0x08, 0x04, 0x0b, 0x02, 0x50, 0xb0,                         // Service TLV
+        0x0b, 0x08, 0x80, 0x02, 0x5c, 0xfa, 0x0d, 0x02, 0x50, 0x00, // Server sub-TLV
+        0x0b, 0x08, 0x81, 0x02, 0x5c, 0x0a, 0x0d, 0x02, 0x50, 0x01, // Server sub-TLV
+        0x0b, 0x08, 0x82, 0x02, 0x5c, 0x82, 0x0d, 0x02, 0x50, 0x02, // Server sub-TLV
+    };
+    const uint8_t kSeqNumbers6[]    = {250, 10, 130};
+    const uint8_t kPreferredSeqNum6 = 250;
+
+    const uint8_t kNetworkData7[] = {
+        0x08, 0x04, 0x0b, 0x02, 0x50, 0xb0,                         // Service TLV
+        0x0b, 0x08, 0x80, 0x02, 0x5c, 0xfa, 0x0d, 0x02, 0x50, 0x00, // Server sub-TLV
+        0x0b, 0x08, 0x81, 0x02, 0x5c, 0x0a, 0x0d, 0x02, 0x50, 0x01, // Server sub-TLV
+        0x0b, 0x08, 0x82, 0x02, 0x5c, 0x8A, 0x0d, 0x02, 0x50, 0x02, // Server sub-TLV
+    };
+    const uint8_t kSeqNumbers7[]    = {250, 10, 138};
+    const uint8_t kPreferredSeqNum7 = 250;
+
+    const uint8_t kNetworkData8[] = {
+        0x08, 0x04, 0x0b, 0x02, 0x50, 0xb0,                         // Service TLV
+        0x0b, 0x08, 0x80, 0x02, 0x5c, 0x01, 0x0d, 0x02, 0x50, 0x00, // Server sub-TLV
+        0x0b, 0x08, 0x81, 0x02, 0x5c, 0x02, 0x0d, 0x02, 0x50, 0x01, // Server sub-TLV
+        0x0b, 0x08, 0x82, 0x02, 0x5c, 0xff, 0x0d, 0x02, 0x50, 0x02, // Server sub-TLV
+        0x0b, 0x08, 0x83, 0x02, 0x5c, 0xfe, 0x0d, 0x02, 0x50, 0x03, // Server sub-TLV
+
+    };
+    const uint8_t kSeqNumbers8[]    = {1, 2, 255, 254};
+    const uint8_t kPreferredSeqNum8 = 2;
+
+    const uint8_t kNetworkData9[] = {
+        0x08, 0x04, 0x0b, 0x02, 0x50, 0xb0,                         // Service TLV
+        0x0b, 0x08, 0x80, 0x02, 0x5c, 0x01, 0x0d, 0x02, 0x50, 0x00, // Server sub-TLV
+        0x0b, 0x08, 0x81, 0x02, 0x5c, 0x02, 0x0d, 0x02, 0x50, 0x01, // Server sub-TLV
+        0x0b, 0x08, 0x82, 0x02, 0x5c, 0xff, 0x0d, 0x02, 0x50, 0x02, // Server sub-TLV
+        0x0b, 0x08, 0x83, 0x02, 0x5c, 0xfe, 0x0d, 0x02, 0x50, 0x03, // Server sub-TLV
+
+    };
+    const uint8_t kSeqNumbers9[]    = {1, 2, 255, 254};
+    const uint8_t kPreferredSeqNum9 = 2;
+
+    const uint8_t kNetworkData10[] = {
+        0x08, 0x04, 0x0b, 0x02, 0x50, 0xb0,                         // Service TLV
+        0x0b, 0x08, 0x80, 0x02, 0x5c, 0xfe, 0x0d, 0x02, 0x50, 0x00, // Server sub-TLV
+        0x0b, 0x08, 0x81, 0x02, 0x5c, 0x02, 0x0d, 0x02, 0x50, 0x01, // Server sub-TLV
+        0x0b, 0x08, 0x82, 0x02, 0x5c, 0x78, 0x0d, 0x02, 0x50, 0x02, // Server sub-TLV
+        0x0b, 0x08, 0x83, 0x02, 0x5c, 0x01, 0x0d, 0x02, 0x50, 0x03, // Server sub-TLV
+
+    };
+    const uint8_t kSeqNumbers10[]    = {254, 2, 120, 1};
+    const uint8_t kPreferredSeqNum10 = 120;
+
+    const uint8_t kNetworkData11[] = {
+        0x08, 0x04, 0x0b, 0x02, 0x50, 0xb0,                         // Service TLV
+        0x0b, 0x08, 0x80, 0x02, 0x5c, 0xf0, 0x0d, 0x02, 0x50, 0x00, // Server sub-TLV
+        0x0b, 0x08, 0x81, 0x02, 0x5c, 0x02, 0x0d, 0x02, 0x50, 0x01, // Server sub-TLV
+        0x0b, 0x08, 0x82, 0x02, 0x5c, 0x78, 0x0d, 0x02, 0x50, 0x02, // Server sub-TLV
+        0x0b, 0x08, 0x83, 0x02, 0x5c, 0x01, 0x0d, 0x02, 0x50, 0x03, // Server sub-TLV
+
+    };
+    const uint8_t kSeqNumbers11[]    = {240, 2, 120, 1};
+    const uint8_t kPreferredSeqNum11 = 240;
+
+    const TestInfo kTests[] = {
+        {kNetworkData1, sizeof(kNetworkData1), kSeqNumbers1, sizeof(kSeqNumbers1), kPreferredSeqNum1},
+        {kNetworkData2, sizeof(kNetworkData2), kSeqNumbers2, sizeof(kSeqNumbers2), kPreferredSeqNum2},
+        {kNetworkData3, sizeof(kNetworkData3), kSeqNumbers3, sizeof(kSeqNumbers3), kPreferredSeqNum3},
+        {kNetworkData4, sizeof(kNetworkData4), kSeqNumbers4, sizeof(kSeqNumbers4), kPreferredSeqNum4},
+        {kNetworkData5, sizeof(kNetworkData5), kSeqNumbers5, sizeof(kSeqNumbers5), kPreferredSeqNum5},
+        {kNetworkData6, sizeof(kNetworkData6), kSeqNumbers6, sizeof(kSeqNumbers6), kPreferredSeqNum6},
+        {kNetworkData7, sizeof(kNetworkData7), kSeqNumbers7, sizeof(kSeqNumbers7), kPreferredSeqNum7},
+        {kNetworkData8, sizeof(kNetworkData8), kSeqNumbers8, sizeof(kSeqNumbers8), kPreferredSeqNum8},
+        {kNetworkData9, sizeof(kNetworkData9), kSeqNumbers9, sizeof(kSeqNumbers9), kPreferredSeqNum9},
+        {kNetworkData10, sizeof(kNetworkData10), kSeqNumbers10, sizeof(kSeqNumbers10), kPreferredSeqNum10},
+        {kNetworkData11, sizeof(kNetworkData11), kSeqNumbers11, sizeof(kSeqNumbers11), kPreferredSeqNum11},
+    };
+
+    Service::Manager &manager   = instance->Get<Service::Manager>();
+    uint8_t           testIndex = 0;
+
+    for (const TestInfo &test : kTests)
+    {
+        Service::Manager::Iterator   iterator;
+        Service::DnsSrpAnycast::Info anycastInfo;
+
+        reinterpret_cast<TestLeader &>(instance->Get<Leader>()).Populate(test.mNetworkData, test.mNetworkDataLength);
+
+        printf("\n- - - - - - - - - - - - - - - - - - - -");
+        printf("\nDNS/SRP Anycast Service entries for test %d", ++testIndex);
+
+        for (uint8_t index = 0; index < test.mSeqNumbersLength; index++)
+        {
+            SuccessOrQuit(manager.GetNextDnsSrpAnycastInfo(iterator, anycastInfo));
+
+            printf("\n { %s, seq:%d }", anycastInfo.mAnycastAddress.ToString().AsCString(),
+                   anycastInfo.mSequenceNumber);
+
+            VerifyOrQuit(anycastInfo.mSequenceNumber == test.mSeqNumbers[index]);
+        }
+
+        VerifyOrQuit(manager.GetNextDnsSrpAnycastInfo(iterator, anycastInfo) == kErrorNotFound);
+        SuccessOrQuit(manager.FindPreferredDnsSrpAnycastInfo(anycastInfo));
+
+        printf("\n preferred -> seq:%d ", anycastInfo.mSequenceNumber);
+        VerifyOrQuit(anycastInfo.mSequenceNumber == test.mPreferredSeqNum);
+    }
+
+    testFreeInstance(instance);
+}
+
 } // namespace NetworkData
 } // namespace ot
 
@@ -460,6 +931,7 @@
     ot::NetworkData::TestNetworkDataFindNextService();
 #endif
     ot::NetworkData::TestNetworkDataDsnSrpServices();
+    ot::NetworkData::TestNetworkDataDsnSrpAnycastSeqNumSelection();
 
     printf("\nAll tests passed\n");
     return 0;
diff --git a/tests/unit/test_network_name.cpp b/tests/unit/test_network_name.cpp
new file mode 100644
index 0000000..c1f448f
--- /dev/null
+++ b/tests/unit/test_network_name.cpp
@@ -0,0 +1,124 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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 "common/code_utils.hpp"
+#include "common/debug.hpp"
+#include "meshcop/network_name.hpp"
+
+#include "test_util.h"
+
+namespace ot {
+
+void CompareNetworkName(const MeshCoP::NetworkName &aNetworkName, const char *aNameString)
+{
+    uint8_t len = static_cast<uint8_t>(strlen(aNameString));
+
+    VerifyOrQuit(strcmp(aNetworkName.GetAsCString(), aNameString) == 0);
+
+    VerifyOrQuit(aNetworkName.GetAsData().GetLength() == len);
+    VerifyOrQuit(memcmp(aNetworkName.GetAsData().GetBuffer(), aNameString, len) == 0);
+}
+
+void TestNetworkName(void)
+{
+    const char kEmptyName[]   = "";
+    const char kName1[]       = "network";
+    const char kName2[]       = "network-name";
+    const char kLongName[]    = "0123456789abcdef";
+    const char kTooLongName[] = "0123456789abcdef0";
+
+    char                 buffer[sizeof(kTooLongName) + 2];
+    uint8_t              len;
+    MeshCoP::NetworkName networkName;
+    MeshCoP::NetworkName networkName2;
+
+    CompareNetworkName(networkName, kEmptyName);
+
+    SuccessOrQuit(networkName.Set(MeshCoP::NameData(kName1, sizeof(kName1))));
+    CompareNetworkName(networkName, kName1);
+
+    VerifyOrQuit(networkName.Set(MeshCoP::NameData(kName1, sizeof(kName1))) == kErrorAlready,
+                 "failed to detect duplicate");
+    CompareNetworkName(networkName, kName1);
+
+    VerifyOrQuit(networkName.Set(MeshCoP::NameData(kName1, sizeof(kName1) - 1)) == kErrorAlready,
+                 "failed to detect duplicate");
+
+    SuccessOrQuit(networkName.Set(MeshCoP::NameData(kName2, sizeof(kName2))));
+    CompareNetworkName(networkName, kName2);
+
+    VerifyOrQuit(networkName.Set(MeshCoP::NameData(kEmptyName, 0)) == kErrorInvalidArgs);
+
+    SuccessOrQuit(networkName.Set(MeshCoP::NameData(kLongName, sizeof(kLongName))));
+    CompareNetworkName(networkName, kLongName);
+
+    VerifyOrQuit(networkName.Set(MeshCoP::NameData(kLongName, sizeof(kLongName) - 1)) == kErrorAlready,
+                 "failed to detect duplicate");
+
+    VerifyOrQuit(networkName.Set(kEmptyName) == kErrorInvalidArgs);
+
+    SuccessOrQuit(networkName.Set(MeshCoP::NameData(kName1, sizeof(kName1))));
+
+    VerifyOrQuit(networkName.Set(MeshCoP::NameData(kTooLongName, sizeof(kTooLongName))) == kErrorInvalidArgs,
+                 "accepted an invalid (too long) name");
+
+    CompareNetworkName(networkName, kName1);
+
+    memset(buffer, 'a', sizeof(buffer));
+    len = networkName.GetAsData().CopyTo(buffer, 1);
+    VerifyOrQuit(len == 1, "NameData::CopyTo() failed");
+    VerifyOrQuit(buffer[0] == kName1[0], "NameData::CopyTo() failed");
+    VerifyOrQuit(buffer[1] == 'a', "NameData::CopyTo() failed");
+
+    memset(buffer, 'a', sizeof(buffer));
+    len = networkName.GetAsData().CopyTo(buffer, sizeof(kName1) - 1);
+    VerifyOrQuit(len == sizeof(kName1) - 1, "NameData::CopyTo() failed");
+    VerifyOrQuit(memcmp(buffer, kName1, sizeof(kName1) - 1) == 0, "NameData::CopyTo() failed");
+    VerifyOrQuit(buffer[sizeof(kName1)] == 'a', "NameData::CopyTo() failed");
+
+    memset(buffer, 'a', sizeof(buffer));
+    len = networkName.GetAsData().CopyTo(buffer, sizeof(buffer));
+    VerifyOrQuit(len == sizeof(kName1) - 1, "NameData::CopyTo() failed");
+    VerifyOrQuit(memcmp(buffer, kName1, sizeof(kName1) - 1) == 0, "NameData::CopyTo() failed");
+    VerifyOrQuit(buffer[sizeof(kName1)] == 0, "NameData::CopyTo() failed");
+
+    SuccessOrQuit(networkName2.Set(MeshCoP::NameData(kName1, sizeof(kName1))));
+    VerifyOrQuit(networkName == networkName2);
+
+    SuccessOrQuit(networkName2.Set(kName2));
+    VerifyOrQuit(networkName != networkName2);
+}
+
+} // namespace ot
+
+int main(void)
+{
+    ot::TestNetworkName();
+    printf("All tests passed\n");
+    return 0;
+}
diff --git a/tests/unit/test_platform.cpp b/tests/unit/test_platform.cpp
index 3189f26..9d01cd3 100644
--- a/tests/unit/test_platform.cpp
+++ b/tests/unit/test_platform.cpp
@@ -330,7 +330,7 @@
 {
 }
 
-OT_TOOL_WEAK void otPlatSettingsInit(otInstance *)
+OT_TOOL_WEAK void otPlatSettingsInit(otInstance *, const uint16_t *, uint16_t)
 {
 }
 
@@ -446,29 +446,21 @@
 #endif
 
 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
-
-OT_TOOL_WEAK void otPlatTrelUdp6Init(otInstance *, const otIp6Address *, uint16_t)
+OT_TOOL_WEAK void otPlatTrelEnable(otInstance *, uint16_t *)
 {
 }
 
-OT_TOOL_WEAK void otPlatTrelUdp6UpdateAddress(otInstance *, const otIp6Address *)
+OT_TOOL_WEAK void otPlatTrelDisable(otInstance *)
 {
 }
 
-OT_TOOL_WEAK void otPlatTrelUdp6SubscribeMulticastAddress(otInstance *, const otIp6Address *)
+OT_TOOL_WEAK void otPlatTrelSend(otInstance *, const uint8_t *, uint16_t, const otSockAddr *)
 {
 }
 
-OT_TOOL_WEAK otError otPlatTrelUdp6SendTo(otInstance *, const uint8_t *, uint16_t, const otIp6Address *)
+OT_TOOL_WEAK void otPlatTrelRegisterService(otInstance *, uint16_t, const uint8_t *, uint8_t)
 {
-    return OT_ERROR_ABORT;
 }
-
-OT_TOOL_WEAK otError otPlatTrelUdp6SetTestMode(otInstance *, bool)
-{
-    return OT_ERROR_NOT_IMPLEMENTED;
-}
-
 #endif
 
 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
@@ -557,4 +549,33 @@
 
     return OT_ERROR_NONE;
 }
+
+#if OPENTHREAD_CONFIG_DNS_DSO_ENABLE
+
+OT_TOOL_WEAK void otPlatDsoEnableListening(otInstance *aInstance, bool aEnable)
+{
+    OT_UNUSED_VARIABLE(aInstance);
+    OT_UNUSED_VARIABLE(aEnable);
+}
+
+OT_TOOL_WEAK void otPlatDsoConnect(otPlatDsoConnection *aConnection, const otSockAddr *aPeerSockAddr)
+{
+    OT_UNUSED_VARIABLE(aConnection);
+    OT_UNUSED_VARIABLE(aPeerSockAddr);
+}
+
+OT_TOOL_WEAK void otPlatDsoSend(otPlatDsoConnection *aConnection, otMessage *aMessage)
+{
+    OT_UNUSED_VARIABLE(aConnection);
+    OT_UNUSED_VARIABLE(aMessage);
+}
+
+OT_TOOL_WEAK void otPlatDsoDisconnect(otPlatDsoConnection *aConnection, otPlatDsoDisconnectMode aMode)
+{
+    OT_UNUSED_VARIABLE(aConnection);
+    OT_UNUSED_VARIABLE(aMode);
+}
+
+#endif // #if OPENTHREAD_CONFIG_DNS_DSO_ENABLE
+
 } // extern "C"
diff --git a/tests/unit/test_platform.h b/tests/unit/test_platform.h
index 07070b9..2944e52 100644
--- a/tests/unit/test_platform.h
+++ b/tests/unit/test_platform.h
@@ -33,6 +33,7 @@
 
 #include <openthread/config.h>
 #include <openthread/platform/alarm-milli.h>
+#include <openthread/platform/dso_transport.h>
 #include <openthread/platform/entropy.h>
 #include <openthread/platform/logging.h>
 #include <openthread/platform/misc.h>
diff --git a/tests/unit/test_priority_queue.cpp b/tests/unit/test_priority_queue.cpp
index db0aa08..51f6b72 100644
--- a/tests/unit/test_priority_queue.cpp
+++ b/tests/unit/test_priority_queue.cpp
@@ -42,15 +42,17 @@
 // This function verifies the content of the priority queue to match the passed in messages
 void VerifyPriorityQueueContent(ot::PriorityQueue &aPriorityQueue, int aExpectedLength, ...)
 {
-    va_list      args;
-    ot::Message *message;
-    ot::Message *msgArg;
-    int8_t       curPriority = ot::Message::kNumPriorities;
-    uint16_t     msgCount, bufCount;
+    const ot::PriorityQueue &constQueue = aPriorityQueue;
+    va_list                  args;
+    ot::Message *            message;
+    ot::Message *            msgArg;
+    int8_t                   curPriority = ot::Message::kNumPriorities;
+    ot::PriorityQueue::Info  info;
 
     // Check the `GetInfo`
-    aPriorityQueue.GetInfo(msgCount, bufCount);
-    VerifyOrQuit(msgCount == aExpectedLength, "GetInfo() result does not match expected len.");
+    memset(&info, 0, sizeof(info));
+    aPriorityQueue.GetInfo(info);
+    VerifyOrQuit(info.mNumMessages == aExpectedLength, "GetInfo() result does not match expected len.");
 
     va_start(args, aExpectedLength);
 
@@ -106,6 +108,30 @@
     }
 
     va_end(args);
+
+    // Check range-based `for` loop iteration using non-const iterator
+
+    message = aPriorityQueue.GetHead();
+
+    for (ot::Message &msg : aPriorityQueue)
+    {
+        VerifyOrQuit(message == &msg, "`for` loop iteration does not match expected");
+        message = message->GetNext();
+    }
+
+    VerifyOrQuit(message == nullptr, "`for` loop iteration resulted in fewer entries than expected");
+
+    // Check  range-base `for` iteration using const iterator
+
+    message = aPriorityQueue.GetHead();
+
+    for (const ot::Message &constMsg : constQueue)
+    {
+        VerifyOrQuit(message == &constMsg, "`for` loop iteration does not match expected");
+        message = message->GetNext();
+    }
+
+    VerifyOrQuit(message == nullptr, "`for` loop iteration resulted in fewer entries than expected");
 }
 
 // This function verifies the content of the message queue to match the passed in messages
@@ -156,32 +182,33 @@
 
     messagePool = &instance->Get<ot::MessagePool>();
 
-    // Use the function "New()" to allocate messages with different priorities
+    // Use the function "Allocate()" to allocate messages with different priorities
     for (int i = 0; i < kNumNewPriorityTestMessages; i++)
     {
-        msgNet[i] = messagePool->New(ot::Message::kTypeIp6, 0, ot::Message::kPriorityNet);
+        msgNet[i] = messagePool->Allocate(ot::Message::kTypeIp6, 0, ot::Message::Settings(ot::Message::kPriorityNet));
         VerifyOrQuit(msgNet[i] != nullptr);
-        msgHigh[i] = messagePool->New(ot::Message::kTypeIp6, 0, ot::Message::kPriorityHigh);
+        msgHigh[i] = messagePool->Allocate(ot::Message::kTypeIp6, 0, ot::Message::Settings(ot::Message::kPriorityHigh));
         VerifyOrQuit(msgHigh[i] != nullptr);
-        msgNor[i] = messagePool->New(ot::Message::kTypeIp6, 0, ot::Message::kPriorityNormal);
+        msgNor[i] =
+            messagePool->Allocate(ot::Message::kTypeIp6, 0, ot::Message::Settings(ot::Message::kPriorityNormal));
         VerifyOrQuit(msgNor[i] != nullptr);
-        msgLow[i] = messagePool->New(ot::Message::kTypeIp6, 0, ot::Message::kPriorityLow);
+        msgLow[i] = messagePool->Allocate(ot::Message::kTypeIp6, 0, ot::Message::Settings(ot::Message::kPriorityLow));
         VerifyOrQuit(msgLow[i] != nullptr);
     }
 
     // Use the function "SetPriority()" to allocate messages with different priorities
     for (int i = kNumNewPriorityTestMessages; i < kNumTestMessages; i++)
     {
-        msgNet[i] = messagePool->New(ot::Message::kTypeIp6, 0);
+        msgNet[i] = messagePool->Allocate(ot::Message::kTypeIp6);
         VerifyOrQuit(msgNet[i] != nullptr);
         SuccessOrQuit(msgNet[i]->SetPriority(ot::Message::kPriorityNet));
-        msgHigh[i] = messagePool->New(ot::Message::kTypeIp6, 0);
+        msgHigh[i] = messagePool->Allocate(ot::Message::kTypeIp6);
         VerifyOrQuit(msgHigh[i] != nullptr);
         SuccessOrQuit(msgHigh[i]->SetPriority(ot::Message::kPriorityHigh));
-        msgNor[i] = messagePool->New(ot::Message::kTypeIp6, 0);
+        msgNor[i] = messagePool->Allocate(ot::Message::kTypeIp6);
         VerifyOrQuit(msgNor[i] != nullptr);
         SuccessOrQuit(msgNor[i]->SetPriority(ot::Message::kPriorityNormal));
-        msgLow[i] = messagePool->New(ot::Message::kTypeIp6, 0);
+        msgLow[i] = messagePool->Allocate(ot::Message::kTypeIp6);
         VerifyOrQuit(msgLow[i] != nullptr);
         SuccessOrQuit(msgLow[i]->SetPriority(ot::Message::kPriorityLow));
     }
@@ -289,6 +316,56 @@
     VerifyPriorityQueueContent(queue, 1, msgNor[0]);
     VerifyMsgQueueContent(messageQueue, 1, msgNor[1]);
 
+    queue.Dequeue(*msgNor[0]);
+    VerifyPriorityQueueContent(queue, 0);
+    messageQueue.Dequeue(*msgNor[1]);
+    VerifyMsgQueueContent(messageQueue, 0);
+
+    for (ot::Message *message : msgNor)
+    {
+        SuccessOrQuit(message->SetPriority(ot::Message::kPriorityNormal));
+    }
+
+    // Range-based `for` and dequeue during iteration
+
+    for (uint16_t removeIndex = 0; removeIndex < 4; removeIndex++)
+    {
+        uint16_t index = 0;
+
+        queue.Enqueue(*msgNor[0]);
+        queue.Enqueue(*msgNor[1]);
+        queue.Enqueue(*msgNor[2]);
+        queue.Enqueue(*msgNor[3]);
+        VerifyPriorityQueueContent(queue, 4, msgNor[0], msgNor[1], msgNor[2], msgNor[3]);
+
+        // While iterating over the queue remove the entry at `removeIndex`
+        for (ot::Message &message : queue)
+        {
+            if (index == removeIndex)
+            {
+                queue.Dequeue(message);
+            }
+
+            VerifyOrQuit(&message == msgNor[index++]);
+        }
+
+        index = 0;
+
+        // Iterate over the queue and remove all
+        for (ot::Message &message : queue)
+        {
+            if (index == removeIndex)
+            {
+                index++;
+            }
+
+            VerifyOrQuit(&message == msgNor[index++]);
+            queue.Dequeue(message);
+        }
+
+        VerifyPriorityQueueContent(queue, 0);
+    }
+
     testFreeInstance(instance);
 }
 
diff --git a/tests/unit/test_pskc.cpp b/tests/unit/test_pskc.cpp
index 19dbed6..3eedad9 100644
--- a/tests/unit/test_pskc.cpp
+++ b/tests/unit/test_pskc.cpp
@@ -27,7 +27,6 @@
  */
 #include <openthread/config.h>
 
-#include "common/logging.hpp"
 #include "meshcop/commissioner.hpp"
 #include "meshcop/meshcop.hpp"
 
@@ -44,8 +43,9 @@
     const otExtendedPanId xpanid         = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}};
     const char            passphrase[]   = "123456";
     otInstance *          instance       = testInitInstance();
-    SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase, *reinterpret_cast<const ot::Mac::NetworkName *>("OpenThread"),
-                                            static_cast<const ot::Mac::ExtendedPanId &>(xpanid), pskc));
+    SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase,
+                                            *reinterpret_cast<const ot::MeshCoP::NetworkName *>("OpenThread"),
+                                            static_cast<const ot::MeshCoP::ExtendedPanId &>(xpanid), pskc));
     VerifyOrQuit(memcmp(pskc.m8, expectedPskc, OT_PSKC_MAX_SIZE) == 0);
     testFreeInstance(instance);
 }
@@ -74,8 +74,9 @@
                               "123456781234567";
 
     otInstance *instance = testInitInstance();
-    SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase, *reinterpret_cast<const ot::Mac::NetworkName *>("OpenThread"),
-                                            static_cast<const ot::Mac::ExtendedPanId &>(xpanid), pskc));
+    SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase,
+                                            *reinterpret_cast<const ot::MeshCoP::NetworkName *>("OpenThread"),
+                                            static_cast<const ot::MeshCoP::ExtendedPanId &>(xpanid), pskc));
     VerifyOrQuit(memcmp(pskc.m8, expectedPskc, sizeof(pskc.m8)) == 0);
     testFreeInstance(instance);
 }
@@ -89,8 +90,9 @@
     const char            passphrase[]   = "12SECRETPASSWORD34";
 
     otInstance *instance = testInitInstance();
-    SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase, *reinterpret_cast<const ot::Mac::NetworkName *>("Test Network"),
-                                            static_cast<const ot::Mac::ExtendedPanId &>(xpanid), pskc));
+    SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase,
+                                            *reinterpret_cast<const ot::MeshCoP::NetworkName *>("Test Network"),
+                                            static_cast<const ot::MeshCoP::ExtendedPanId &>(xpanid), pskc));
     VerifyOrQuit(memcmp(pskc.m8, expectedPskc, sizeof(pskc.m8)) == 0);
     testFreeInstance(instance);
 }
diff --git a/tests/unit/test_routing_manager.cpp b/tests/unit/test_routing_manager.cpp
new file mode 100644
index 0000000..56085d0
--- /dev/null
+++ b/tests/unit/test_routing_manager.cpp
@@ -0,0 +1,888 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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 <openthread/config.h>
+
+#include "test_platform.h"
+#include "test_util.hpp"
+
+#include <openthread/thread.h>
+
+#include "border_router/routing_manager.hpp"
+#include "common/arg_macros.hpp"
+#include "common/instance.hpp"
+#include "net/icmp6.hpp"
+#include "net/nd6.hpp"
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+
+using namespace ot;
+
+// Logs a message and adds current time (sNow) as "<hours>:<min>:<secs>.<msec>"
+#define Log(...)                                                                                          \
+    printf("%02u:%02u:%02u.%03u " OT_FIRST_ARG(__VA_ARGS__) "\n", (sNow / 36000000), (sNow / 60000) % 60, \
+           (sNow / 1000) % 60, sNow % 1000 OT_REST_ARGS(__VA_ARGS__))
+
+static constexpr uint32_t kInfraIfIndex     = 1;
+static const char         kInfraIfAddress[] = "fe80::1";
+
+static constexpr uint32_t kValidLitime       = 2000;
+static constexpr uint32_t kPreferredLifetime = 1800;
+
+static otInstance *sInstance;
+
+static uint32_t sNow = 0;
+static uint32_t sAlarmTime;
+static bool     sAlarmOn = false;
+
+static otRadioFrame sRadioTxFrame;
+static uint8_t      sRadioTxFramePsdu[OT_RADIO_FRAME_MAX_SIZE];
+static bool         sRadioTxOngoing = false;
+
+using Icmp6Packet = Ip6::Nd::RouterAdvertMessage::Icmp6Packet;
+
+enum ExpectedPio
+{
+    kNoPio,                     // Expect to see no PIO in RA.
+    kPioAdvertisingLocalOnLink, // Expect to see local on-link prefix advertised (non-zero preferred lifetime).
+    kPioDeprecatingLocalOnLink, // Expect to see local on-link prefix deprecated (zero preferred lifetime).
+};
+
+static Ip6::Address sInfraIfAddress;
+
+bool        sRsEmitted;         // Indicates if an RS message was emitted by BR.
+bool        sRaValidated;       // Indicates if an RA was emitted by BR and successfully validated.
+bool        sSawExpectedRio;    // Indicates if the emitted RA by BR contained an RIO with `sExpectedRioPrefix`
+ExpectedPio sExpectedPio;       // Expected PIO in the emitted RA by BR (MUST be seen in RA to set `sRaValidated`).
+Ip6::Prefix sExpectedRioPrefix; // Expected RIO prefix to see in RA (MUST be seen to set `sSawExpectedRio`).
+
+//----------------------------------------------------------------------------------------------------------------------
+// Function prototypes
+
+void        ProcessRadioTxAndTasklets(void);
+void        AdvanceTime(uint32_t aDuration);
+void        LogRouterAdvert(const Icmp6Packet &aPacket);
+void        ValidateRouterAdvert(const Icmp6Packet &aPacket);
+const char *PreferenceToString(uint8_t aPreference);
+void        SendRouterAdvert(const Ip6::Address &aAddress, const Icmp6Packet &aPacket);
+
+//----------------------------------------------------------------------------------------------------------------------
+// `otPlatRadio
+
+extern "C" {
+
+otError otPlatRadioTransmit(otInstance *, otRadioFrame *)
+{
+    sRadioTxOngoing = true;
+
+    return OT_ERROR_NONE;
+}
+
+otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *)
+{
+    return &sRadioTxFrame;
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+// `otPlatAlaram
+
+void otPlatAlarmMilliStop(otInstance *)
+{
+    sAlarmOn = false;
+}
+
+void otPlatAlarmMilliStartAt(otInstance *, uint32_t aT0, uint32_t aDt)
+{
+    sAlarmOn   = true;
+    sAlarmTime = aT0 + aDt;
+}
+
+uint32_t otPlatAlarmMilliGetNow(void)
+{
+    return sNow;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+// otPlatInfraIf
+
+bool otPlatInfraIfHasAddress(uint32_t aInfraIfIndex, const otIp6Address *aAddress)
+{
+    VerifyOrQuit(aInfraIfIndex == kInfraIfIndex);
+
+    return AsCoreType(aAddress) == sInfraIfAddress;
+}
+
+otError otPlatInfraIfSendIcmp6Nd(uint32_t            aInfraIfIndex,
+                                 const otIp6Address *aDestAddress,
+                                 const uint8_t *     aBuffer,
+                                 uint16_t            aBufferLength)
+{
+    Icmp6Packet packet;
+
+    Log("otPlatInfraIfSendIcmp6Nd(aDestAddr: %s, aBufferLength:%u)", AsCoreType(aDestAddress).ToString().AsCString(),
+        aBufferLength);
+
+    VerifyOrQuit(aInfraIfIndex == kInfraIfIndex);
+
+    packet.Init(aBuffer, aBufferLength);
+
+    VerifyOrQuit(aBufferLength >= sizeof(Ip6::Icmp::Header));
+
+    switch (reinterpret_cast<const Ip6::Icmp::Header *>(aBuffer)->GetType())
+    {
+    case Ip6::Icmp::Header::kTypeRouterSolicit:
+        Log("  Router Solicit message");
+        sRsEmitted = true;
+        break;
+
+    case Ip6::Icmp::Header::kTypeRouterAdvert:
+        Log("  Router Advertisement message");
+        LogRouterAdvert(packet);
+        ValidateRouterAdvert(packet);
+        sRaValidated = true;
+        break;
+
+    default:
+        VerifyOrQuit(false, "Bad ICMP6 type");
+    }
+
+    return OT_ERROR_NONE;
+}
+
+} // extern "C"
+
+//---------------------------------------------------------------------------------------------------------------------
+
+void ProcessRadioTxAndTasklets(void)
+{
+    do
+    {
+        if (sRadioTxOngoing)
+        {
+            sRadioTxOngoing = false;
+            otPlatRadioTxStarted(sInstance, &sRadioTxFrame);
+            otPlatRadioTxDone(sInstance, &sRadioTxFrame, nullptr, OT_ERROR_NONE);
+        }
+
+        otTaskletsProcess(sInstance);
+    } while (otTaskletsArePending(sInstance));
+}
+
+void AdvanceTime(uint32_t aDuration)
+{
+    uint32_t time = sNow + aDuration;
+
+    Log("AdvanceTime for %u.%03u", aDuration / 1000, aDuration % 1000);
+
+    while (sAlarmTime <= time)
+    {
+        ProcessRadioTxAndTasklets();
+        sNow = sAlarmTime;
+        otPlatAlarmMilliFired(sInstance);
+    }
+
+    ProcessRadioTxAndTasklets();
+    sNow = time;
+}
+
+void ValidateRouterAdvert(const Icmp6Packet &aPacket)
+{
+    Ip6::Nd::RouterAdvertMessage raMsg(aPacket);
+
+    VerifyOrQuit(raMsg.IsValid());
+
+    for (const Ip6::Nd::Option &option : raMsg)
+    {
+        switch (option.GetType())
+        {
+        case Ip6::Nd::Option::kTypePrefixInfo:
+        {
+            const Ip6::Nd::PrefixInfoOption &pio = static_cast<const Ip6::Nd::PrefixInfoOption &>(option);
+            Ip6::Prefix                      prefix;
+            Ip6::Prefix                      localOnLink;
+
+            VerifyOrQuit(pio.IsValid());
+            pio.GetPrefix(prefix);
+
+            VerifyOrQuit(sExpectedPio != kNoPio, "Received RA contain an unexpected PIO");
+
+            SuccessOrQuit(otBorderRoutingGetOnLinkPrefix(sInstance, &localOnLink));
+            VerifyOrQuit(prefix == localOnLink);
+
+            if (sExpectedPio == kPioAdvertisingLocalOnLink)
+            {
+                VerifyOrQuit(pio.GetPreferredLifetime() > 0, "On link prefix is deprecated unexpectedly");
+            }
+            else
+            {
+                VerifyOrQuit(pio.GetPreferredLifetime() == 0, "On link prefix is not deprecated");
+            }
+
+            break;
+        }
+
+        case Ip6::Nd::Option::kTypeRouteInfo:
+        {
+            const Ip6::Nd::RouteInfoOption &rio = static_cast<const Ip6::Nd::RouteInfoOption &>(option);
+            Ip6::Prefix                     prefix;
+
+            VerifyOrQuit(rio.IsValid());
+            rio.GetPrefix(prefix);
+
+            if (prefix == sExpectedRioPrefix)
+            {
+                sSawExpectedRio = true;
+            }
+
+            break;
+        }
+
+        default:
+            VerifyOrQuit(false, "Unexpected option type in RA msg");
+        }
+    }
+}
+
+void LogRouterAdvert(const Icmp6Packet &aPacket)
+{
+    Ip6::Nd::RouterAdvertMessage raMsg(aPacket);
+
+    VerifyOrQuit(raMsg.IsValid());
+
+    Log("     RA header - lifetime %u, prf:%s", raMsg.GetHeader().GetRouterLifetime(),
+        PreferenceToString(raMsg.GetHeader().GetDefaultRouterPreference()));
+
+    for (const Ip6::Nd::Option &option : raMsg)
+    {
+        switch (option.GetType())
+        {
+        case Ip6::Nd::Option::kTypePrefixInfo:
+        {
+            const Ip6::Nd::PrefixInfoOption &pio = static_cast<const Ip6::Nd::PrefixInfoOption &>(option);
+            Ip6::Prefix                      prefix;
+
+            VerifyOrQuit(pio.IsValid());
+            pio.GetPrefix(prefix);
+            Log("     PIO - %s, flags:%s%s, valid:%u, preferred:%u", prefix.ToString().AsCString(),
+                pio.IsOnLinkFlagSet() ? "L" : "", pio.IsAutoAddrConfigFlagSet() ? "A" : "", pio.GetValidLifetime(),
+                pio.GetPreferredLifetime());
+            break;
+        }
+
+        case Ip6::Nd::Option::kTypeRouteInfo:
+        {
+            const Ip6::Nd::RouteInfoOption &rio = static_cast<const Ip6::Nd::RouteInfoOption &>(option);
+            Ip6::Prefix                     prefix;
+
+            VerifyOrQuit(rio.IsValid());
+            rio.GetPrefix(prefix);
+            Log("     RIO - %s, prf:%s, lifetime:%u", prefix.ToString().AsCString(),
+                PreferenceToString(rio.GetPreference()), rio.GetRouteLifetime());
+            break;
+        }
+
+        default:
+            VerifyOrQuit(false, "Bad option type in RA msg");
+        }
+    }
+}
+
+const char *PreferenceToString(uint8_t aPreference)
+{
+    const char *str = "";
+
+    switch (aPreference)
+    {
+    case NetworkData::kRoutePreferenceLow:
+        str = "low";
+        break;
+
+    case NetworkData::kRoutePreferenceMedium:
+        str = "med";
+        break;
+
+    case NetworkData::kRoutePreferenceHigh:
+        str = "high";
+        break;
+
+    default:
+        break;
+    }
+
+    return str;
+}
+
+void SendRouterAdvert(const Ip6::Address &aAddress, const Icmp6Packet &aPacket)
+{
+    otPlatInfraIfRecvIcmp6Nd(sInstance, kInfraIfIndex, &aAddress, aPacket.GetBytes(), aPacket.GetLength());
+}
+
+Ip6::Prefix PrefixFromString(const char *aString, uint8_t aPrefixLength)
+{
+    Ip6::Prefix prefix;
+
+    SuccessOrQuit(AsCoreType(&prefix.mPrefix).FromString(aString));
+    prefix.mLength = aPrefixLength;
+
+    return prefix;
+}
+
+Ip6::Address AddressFromString(const char *aString)
+{
+    Ip6::Address address;
+
+    SuccessOrQuit(address.FromString(aString));
+
+    return address;
+}
+
+void TestRoutingManager(void)
+{
+    Instance &                                        instance = *static_cast<Instance *>(testInitInstance());
+    BorderRouter::RoutingManager &                    rm       = instance.Get<BorderRouter::RoutingManager>();
+    Ip6::Prefix                                       localOnLink;
+    Ip6::Prefix                                       localOmr;
+    Ip6::Prefix                                       onLinkPrefix   = PrefixFromString("2000:abba:baba::", 64);
+    Ip6::Prefix                                       routePrefix    = PrefixFromString("2000:1234:5678::", 64);
+    Ip6::Prefix                                       omrPrefix      = PrefixFromString("2000:0000:1111:4444::", 64);
+    Ip6::Address                                      routerAddressA = AddressFromString("fd00::aaaa");
+    Ip6::Address                                      routerAddressB = AddressFromString("fd00::bbbb");
+    BorderRouter::RoutingManager::PrefixTableIterator iter;
+    BorderRouter::RoutingManager::PrefixTableEntry    entry;
+    NetworkData::Iterator                             iterator;
+    NetworkData::OnMeshPrefixConfig                   prefixConfig;
+    NetworkData::ExternalRouteConfig                  routeConfig;
+    uint8_t                                           counter;
+    uint8_t                                           buffer[800];
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Initialize OT instance.
+
+    sNow      = 0;
+    sInstance = &instance;
+
+    memset(&sRadioTxFrame, 0, sizeof(sRadioTxFrame));
+    sRadioTxFrame.mPsdu = sRadioTxFramePsdu;
+
+    SuccessOrQuit(sInfraIfAddress.FromString(kInfraIfAddress));
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Initialize Border Router and start Thread operation.
+
+    SuccessOrQuit(otBorderRoutingInit(sInstance, kInfraIfIndex, /* aInfraIfIsRunning */ true));
+
+    SuccessOrQuit(otLinkSetPanId(sInstance, 0x1234));
+    SuccessOrQuit(otIp6SetEnabled(sInstance, true));
+    SuccessOrQuit(otThreadSetEnabled(sInstance, true));
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Ensure device starts as leader.
+
+    AdvanceTime(10000);
+
+    VerifyOrQuit(otThreadGetDeviceRole(sInstance) == OT_DEVICE_ROLE_LEADER);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Start Routing Manager. Check emitted RS and RA messages.
+
+    sRsEmitted      = false;
+    sRaValidated    = false;
+    sSawExpectedRio = false;
+    sExpectedPio    = kPioAdvertisingLocalOnLink;
+
+    Log("Starting RoutingManager");
+
+    SuccessOrQuit(rm.SetEnabled(true));
+
+    SuccessOrQuit(rm.GetOnLinkPrefix(localOnLink));
+    SuccessOrQuit(rm.GetOmrPrefix(localOmr));
+
+    Log("Local on-link prefix is %s", localOnLink.ToString().AsCString());
+    Log("Local OMR prefix is %s", localOmr.ToString().AsCString());
+
+    sExpectedRioPrefix = localOmr;
+
+    AdvanceTime(30000);
+
+    VerifyOrQuit(sRsEmitted);
+    VerifyOrQuit(sRaValidated);
+    VerifyOrQuit(sSawExpectedRio);
+    Log("Received RA was validated");
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Check Network Data to include the local OMR and on-link prefix.
+
+    iterator = NetworkData::kIteratorInit;
+
+    // We expect to see OMR prefix in net data as on-mesh prefix.
+    SuccessOrQuit(instance.Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig));
+    VerifyOrQuit(prefixConfig.GetPrefix() == localOmr);
+    VerifyOrQuit(prefixConfig.mStable == true);
+    VerifyOrQuit(prefixConfig.mSlaac == true);
+    VerifyOrQuit(prefixConfig.mPreferred == true);
+    VerifyOrQuit(prefixConfig.mOnMesh == true);
+    VerifyOrQuit(prefixConfig.mDefaultRoute == false);
+
+    VerifyOrQuit(instance.Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNotFound);
+
+    iterator = NetworkData::kIteratorInit;
+
+    // We expect to see local on-link prefix in net data as external route.
+    SuccessOrQuit(instance.Get<NetworkData::Leader>().GetNextExternalRoute(iterator, routeConfig));
+    VerifyOrQuit(routeConfig.GetPrefix() == localOnLink);
+    VerifyOrQuit(routeConfig.mStable == true);
+    VerifyOrQuit(routeConfig.mPreference == NetworkData::kRoutePreferenceMedium);
+
+    VerifyOrQuit(instance.Get<NetworkData::Leader>().GetNextExternalRoute(iterator, routeConfig) == kErrorNotFound);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Send an RA from router A with a new on-link (PIO) and route prefix (RIO).
+
+    {
+        Ip6::Nd::RouterAdvertMessage raMsg(Ip6::Nd::RouterAdvertMessage::Header(), buffer);
+
+        SuccessOrQuit(raMsg.AppendPrefixInfoOption(onLinkPrefix, kValidLitime, kPreferredLifetime));
+        SuccessOrQuit(raMsg.AppendRouteInfoOption(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium));
+
+        SendRouterAdvert(routerAddressA, raMsg.GetAsPacket());
+
+        Log("Send RA from router A");
+        LogRouterAdvert(raMsg.GetAsPacket());
+    }
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Check that the local on-link prefix is now deprecating in the new RA.
+
+    sRaValidated    = false;
+    sSawExpectedRio = false;
+    sExpectedPio    = kPioDeprecatingLocalOnLink;
+
+    AdvanceTime(10000);
+    VerifyOrQuit(sRaValidated);
+    VerifyOrQuit(sSawExpectedRio);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Check the discovered prefix table and ensure info from router A
+    // is present in the table.
+
+    counter = 0;
+
+    rm.InitPrefixTableIterator(iter);
+
+    while (rm.GetNextPrefixTableEntry(iter, entry) == kErrorNone)
+    {
+        counter++;
+        VerifyOrQuit(AsCoreType(&entry.mRouterAddress) == routerAddressA);
+
+        if (entry.mIsOnLink)
+        {
+            VerifyOrQuit(AsCoreType(&entry.mPrefix) == onLinkPrefix);
+            VerifyOrQuit(entry.mValidLifetime = kValidLitime);
+            VerifyOrQuit(entry.mPreferredLifetime = kPreferredLifetime);
+        }
+        else
+        {
+            VerifyOrQuit(AsCoreType(&entry.mPrefix) == routePrefix);
+            VerifyOrQuit(entry.mValidLifetime = kValidLitime);
+            VerifyOrQuit(static_cast<int8_t>(entry.mRoutePreference) == NetworkData::kRoutePreferenceMedium);
+        }
+    }
+
+    VerifyOrQuit(counter == 2);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Check Network Data to include new prefixes from router A.
+
+    iterator = NetworkData::kIteratorInit;
+
+    // We expect to see OMR prefix in net data as on-mesh prefix.
+    SuccessOrQuit(instance.Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig));
+    VerifyOrQuit(prefixConfig.GetPrefix() == localOmr);
+    VerifyOrQuit(prefixConfig.mStable == true);
+    VerifyOrQuit(prefixConfig.mSlaac == true);
+    VerifyOrQuit(prefixConfig.mPreferred == true);
+    VerifyOrQuit(prefixConfig.mOnMesh == true);
+    VerifyOrQuit(prefixConfig.mDefaultRoute == false);
+
+    VerifyOrQuit(instance.Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNotFound);
+
+    iterator = NetworkData::kIteratorInit;
+
+    counter = 0;
+
+    // We expect to see 3 entries, our local on link and new prefixes from router A.
+    while (instance.Get<NetworkData::Leader>().GetNextExternalRoute(iterator, routeConfig) == kErrorNone)
+    {
+        VerifyOrQuit((routeConfig.GetPrefix() == localOnLink) || (routeConfig.GetPrefix() == onLinkPrefix) ||
+                     (routeConfig.GetPrefix() == routePrefix));
+        VerifyOrQuit(static_cast<int8_t>(routeConfig.mPreference) == NetworkData::kRoutePreferenceMedium);
+        counter++;
+    }
+
+    VerifyOrQuit(counter == 3);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Send the same RA again from router A with the on-link (PIO) and route prefix (RIO).
+
+    {
+        Ip6::Nd::RouterAdvertMessage raMsg(Ip6::Nd::RouterAdvertMessage::Header(), buffer);
+
+        SuccessOrQuit(raMsg.AppendPrefixInfoOption(onLinkPrefix, kValidLitime, kPreferredLifetime));
+        SuccessOrQuit(raMsg.AppendRouteInfoOption(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium));
+
+        SendRouterAdvert(routerAddressA, raMsg.GetAsPacket());
+
+        Log("Send RA from router A");
+        LogRouterAdvert(raMsg.GetAsPacket());
+    }
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Check the discovered prefix table and ensure info from router A
+    // remains unchanged.
+
+    counter = 0;
+
+    rm.InitPrefixTableIterator(iter);
+
+    while (rm.GetNextPrefixTableEntry(iter, entry) == kErrorNone)
+    {
+        counter++;
+        VerifyOrQuit(AsCoreType(&entry.mRouterAddress) == routerAddressA);
+
+        if (entry.mIsOnLink)
+        {
+            VerifyOrQuit(AsCoreType(&entry.mPrefix) == onLinkPrefix);
+            VerifyOrQuit(entry.mValidLifetime = kValidLitime);
+            VerifyOrQuit(entry.mPreferredLifetime = kPreferredLifetime);
+        }
+        else
+        {
+            VerifyOrQuit(AsCoreType(&entry.mPrefix) == routePrefix);
+            VerifyOrQuit(entry.mValidLifetime = kValidLitime);
+            VerifyOrQuit(static_cast<int8_t>(entry.mRoutePreference) == NetworkData::kRoutePreferenceMedium);
+        }
+    }
+
+    VerifyOrQuit(counter == 2);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Send an RA from router B with same route prefix (RIO) but with
+    // high route preference.
+
+    {
+        Ip6::Nd::RouterAdvertMessage raMsg(Ip6::Nd::RouterAdvertMessage::Header(), buffer);
+
+        SuccessOrQuit(raMsg.AppendRouteInfoOption(routePrefix, kValidLitime, NetworkData::kRoutePreferenceHigh));
+
+        SendRouterAdvert(routerAddressB, raMsg.GetAsPacket());
+
+        Log("Send RA from router B");
+        LogRouterAdvert(raMsg.GetAsPacket());
+    }
+
+    AdvanceTime(10000);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Check the discovered prefix table and ensure info from router B
+    // is also included in the table.
+
+    counter = 0;
+
+    rm.InitPrefixTableIterator(iter);
+
+    while (rm.GetNextPrefixTableEntry(iter, entry) == kErrorNone)
+    {
+        const Ip6::Address &routerAddr = AsCoreType(&entry.mRouterAddress);
+        counter++;
+
+        if (routerAddr == routerAddressA)
+        {
+            if (entry.mIsOnLink)
+            {
+                VerifyOrQuit(AsCoreType(&entry.mPrefix) == onLinkPrefix);
+                VerifyOrQuit(entry.mValidLifetime = kValidLitime);
+                VerifyOrQuit(entry.mPreferredLifetime = kPreferredLifetime);
+            }
+            else
+            {
+                VerifyOrQuit(AsCoreType(&entry.mPrefix) == routePrefix);
+                VerifyOrQuit(entry.mValidLifetime = kValidLitime);
+                VerifyOrQuit(static_cast<int8_t>(entry.mRoutePreference) == NetworkData::kRoutePreferenceMedium);
+            }
+        }
+        else if (routerAddr == routerAddressB)
+        {
+            VerifyOrQuit(!entry.mIsOnLink);
+            VerifyOrQuit(AsCoreType(&entry.mPrefix) == routePrefix);
+            VerifyOrQuit(entry.mValidLifetime = kValidLitime);
+            VerifyOrQuit(static_cast<int8_t>(entry.mRoutePreference) == NetworkData::kRoutePreferenceHigh);
+        }
+        else
+        {
+            VerifyOrQuit(false, "Unexpected entry in prefix table with unknown router address");
+        }
+    }
+
+    VerifyOrQuit(counter == 3);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Check Network Data.
+
+    iterator = NetworkData::kIteratorInit;
+
+    // We expect to see OMR prefix in net data as on-mesh prefix
+    SuccessOrQuit(instance.Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig));
+    VerifyOrQuit(prefixConfig.GetPrefix() == localOmr);
+    VerifyOrQuit(prefixConfig.mStable == true);
+    VerifyOrQuit(prefixConfig.mSlaac == true);
+    VerifyOrQuit(prefixConfig.mPreferred == true);
+    VerifyOrQuit(prefixConfig.mOnMesh == true);
+    VerifyOrQuit(prefixConfig.mDefaultRoute == false);
+
+    VerifyOrQuit(instance.Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNotFound);
+
+    iterator = NetworkData::kIteratorInit;
+
+    counter = 0;
+
+    // We expect to see 3 entries, our local on link and new prefixes
+    // from router A and B. The `routePrefix` now should have high
+    // preference.
+
+    while (instance.Get<NetworkData::Leader>().GetNextExternalRoute(iterator, routeConfig) == kErrorNone)
+    {
+        counter++;
+
+        if (routeConfig.GetPrefix() == routePrefix)
+        {
+            VerifyOrQuit(static_cast<int8_t>(routeConfig.mPreference) == NetworkData::kRoutePreferenceHigh);
+        }
+        else
+        {
+            VerifyOrQuit((routeConfig.GetPrefix() == localOnLink) || (routeConfig.GetPrefix() == onLinkPrefix));
+            VerifyOrQuit(static_cast<int8_t>(routeConfig.mPreference) == NetworkData::kRoutePreferenceMedium);
+        }
+    }
+
+    VerifyOrQuit(counter == 3);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Send an RA from router B removing the route prefix.
+
+    {
+        Ip6::Nd::RouterAdvertMessage raMsg(Ip6::Nd::RouterAdvertMessage::Header(), buffer);
+
+        SuccessOrQuit(raMsg.AppendRouteInfoOption(routePrefix, 0, NetworkData::kRoutePreferenceHigh));
+
+        SendRouterAdvert(routerAddressB, raMsg.GetAsPacket());
+
+        Log("Send RA from router B");
+        LogRouterAdvert(raMsg.GetAsPacket());
+    }
+
+    AdvanceTime(10000);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Check the discovered prefix table and ensure info from router B
+    // is now removed from the table.
+
+    counter = 0;
+
+    rm.InitPrefixTableIterator(iter);
+
+    while (rm.GetNextPrefixTableEntry(iter, entry) == kErrorNone)
+    {
+        counter++;
+
+        VerifyOrQuit(AsCoreType(&entry.mRouterAddress) == routerAddressA);
+
+        if (entry.mIsOnLink)
+        {
+            VerifyOrQuit(AsCoreType(&entry.mPrefix) == onLinkPrefix);
+            VerifyOrQuit(entry.mValidLifetime = kValidLitime);
+            VerifyOrQuit(entry.mPreferredLifetime = kPreferredLifetime);
+        }
+        else
+        {
+            VerifyOrQuit(AsCoreType(&entry.mPrefix) == routePrefix);
+            VerifyOrQuit(entry.mValidLifetime = kValidLitime);
+            VerifyOrQuit(static_cast<int8_t>(entry.mRoutePreference) == NetworkData::kRoutePreferenceMedium);
+        }
+    }
+
+    VerifyOrQuit(counter == 2);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Check Network Data, all prefixes should be again at medium preference.
+
+    counter  = 0;
+    iterator = NetworkData::kIteratorInit;
+
+    while (instance.Get<NetworkData::Leader>().GetNextExternalRoute(iterator, routeConfig) == kErrorNone)
+    {
+        counter++;
+
+        VerifyOrQuit((routeConfig.GetPrefix() == localOnLink) || (routeConfig.GetPrefix() == onLinkPrefix) ||
+                     (routeConfig.GetPrefix() == routePrefix));
+        VerifyOrQuit(static_cast<int8_t>(routeConfig.mPreference) == NetworkData::kRoutePreferenceMedium);
+    }
+
+    VerifyOrQuit(counter == 3);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Add a new OMR prefix directly into net data. The new prefix should
+    // be favored over the local OMR prefix.
+
+    prefixConfig.Clear();
+    prefixConfig.mPrefix       = omrPrefix;
+    prefixConfig.mStable       = true;
+    prefixConfig.mSlaac        = true;
+    prefixConfig.mPreferred    = true;
+    prefixConfig.mOnMesh       = true;
+    prefixConfig.mDefaultRoute = false;
+    prefixConfig.mPreference   = NetworkData::kRoutePreferenceMedium;
+
+    SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig));
+    SuccessOrQuit(otBorderRouterRegister(sInstance));
+
+    AdvanceTime(100);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Make sure BR emits RA with new OMR prefix now.
+
+    sRaValidated       = false;
+    sSawExpectedRio    = false;
+    sExpectedRioPrefix = omrPrefix;
+
+    AdvanceTime(20000);
+
+    VerifyOrQuit(sRaValidated);
+    VerifyOrQuit(sSawExpectedRio);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Check Network Data. We should now see that the local OMR prefix
+    // is removed.
+
+    iterator = NetworkData::kIteratorInit;
+
+    // We expect to see new OMR prefix in net data.
+    SuccessOrQuit(instance.Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig));
+    VerifyOrQuit(prefixConfig.GetPrefix() == omrPrefix);
+    VerifyOrQuit(prefixConfig.mStable == true);
+    VerifyOrQuit(prefixConfig.mSlaac == true);
+    VerifyOrQuit(prefixConfig.mPreferred == true);
+    VerifyOrQuit(prefixConfig.mOnMesh == true);
+    VerifyOrQuit(prefixConfig.mDefaultRoute == false);
+
+    VerifyOrQuit(instance.Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNotFound);
+
+    counter  = 0;
+    iterator = NetworkData::kIteratorInit;
+
+    while (instance.Get<NetworkData::Leader>().GetNextExternalRoute(iterator, routeConfig) == kErrorNone)
+    {
+        counter++;
+
+        VerifyOrQuit((routeConfig.GetPrefix() == localOnLink) || (routeConfig.GetPrefix() == onLinkPrefix) ||
+                     (routeConfig.GetPrefix() == routePrefix));
+        VerifyOrQuit(static_cast<int8_t>(routeConfig.mPreference) == NetworkData::kRoutePreferenceMedium);
+    }
+
+    VerifyOrQuit(counter == 3);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Remove the OMR prefix previously added in net data.
+
+    SuccessOrQuit(otBorderRouterRemoveOnMeshPrefix(sInstance, &omrPrefix));
+    SuccessOrQuit(otBorderRouterRegister(sInstance));
+
+    AdvanceTime(100);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Make sure BR emits RA with local OMR prefix again.
+
+    sRaValidated       = false;
+    sSawExpectedRio    = false;
+    sExpectedRioPrefix = localOmr;
+
+    AdvanceTime(20000);
+
+    VerifyOrQuit(sRaValidated);
+    VerifyOrQuit(sSawExpectedRio);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    // Check Network Data. We should see that the local OMR prefix is
+    // added again.
+
+    iterator = NetworkData::kIteratorInit;
+
+    // We expect to see new OMR prefix in net data as on-mesh prefix.
+    SuccessOrQuit(instance.Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig));
+    VerifyOrQuit(prefixConfig.GetPrefix() == localOmr);
+    VerifyOrQuit(prefixConfig.mStable == true);
+    VerifyOrQuit(prefixConfig.mSlaac == true);
+    VerifyOrQuit(prefixConfig.mPreferred == true);
+    VerifyOrQuit(prefixConfig.mOnMesh == true);
+    VerifyOrQuit(prefixConfig.mDefaultRoute == false);
+
+    VerifyOrQuit(instance.Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNotFound);
+
+    counter  = 0;
+    iterator = NetworkData::kIteratorInit;
+
+    while (instance.Get<NetworkData::Leader>().GetNextExternalRoute(iterator, routeConfig) == kErrorNone)
+    {
+        counter++;
+
+        VerifyOrQuit((routeConfig.GetPrefix() == localOnLink) || (routeConfig.GetPrefix() == onLinkPrefix) ||
+                     (routeConfig.GetPrefix() == routePrefix));
+        VerifyOrQuit(static_cast<int8_t>(routeConfig.mPreference) == NetworkData::kRoutePreferenceMedium);
+    }
+
+    VerifyOrQuit(counter == 3);
+
+    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    Log("End of test");
+
+    testFreeInstance(&instance);
+}
+
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+
+int main(void)
+{
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+    TestRoutingManager();
+    printf("All tests passed\n");
+#else
+    printf("BORDER_ROUTING feature is not enabled\n");
+#endif
+
+    return 0;
+}
diff --git a/tests/unit/test_serial_number.cpp b/tests/unit/test_serial_number.cpp
new file mode 100644
index 0000000..dc8d7a1
--- /dev/null
+++ b/tests/unit/test_serial_number.cpp
@@ -0,0 +1,78 @@
+/*
+ *  Copyright (c) 2022, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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 "test_platform.h"
+
+#include <openthread/config.h>
+
+#include "test_util.h"
+#include "common/code_utils.hpp"
+#include "common/numeric_limits.hpp"
+#include "common/serial_number.hpp"
+
+namespace ot {
+
+template <typename UintType> void TestSerialNumber(const char *aName)
+{
+    static constexpr UintType kMax = NumericLimits<UintType>::kMax;
+    static constexpr UintType kMid = kMax / 2;
+
+    static const UintType kNumbers[] = {0, 1, 20, kMid - 1, kMid, kMid + 1, kMax - 20, kMax - 1, kMax};
+
+    for (UintType number : kNumbers)
+    {
+        VerifyOrQuit(!SerialNumber::IsGreater<UintType>(number, number));
+        VerifyOrQuit(!SerialNumber::IsLess<UintType>(number, number));
+
+        VerifyOrQuit(SerialNumber::IsGreater<UintType>(number + 1, number));
+        VerifyOrQuit(SerialNumber::IsGreater<UintType>(number + kMid - 1, number));
+        VerifyOrQuit(SerialNumber::IsGreater<UintType>(number + kMid, number));
+        VerifyOrQuit(!SerialNumber::IsGreater<UintType>(number + kMid + 2, number));
+        VerifyOrQuit(!SerialNumber::IsGreater<UintType>(number + kMax - 1, number));
+
+        VerifyOrQuit(SerialNumber::IsLess<UintType>(number - 1, number));
+        VerifyOrQuit(SerialNumber::IsLess<UintType>(number - kMid + 1, number));
+        VerifyOrQuit(SerialNumber::IsLess<UintType>(number - kMid, number));
+        VerifyOrQuit(!SerialNumber::IsLess<UintType>(number - kMid - 2, number));
+        VerifyOrQuit(!SerialNumber::IsLess<UintType>(number - kMax + 1, number));
+    }
+
+    printf("TestSerialNumber<%s>() passed\n", aName);
+}
+
+} // namespace ot
+
+int main(void)
+{
+    ot::TestSerialNumber<uint8_t>("uint8_t");
+    ot::TestSerialNumber<uint16_t>("uint16_t");
+    ot::TestSerialNumber<uint32_t>("uint32_t");
+    ot::TestSerialNumber<uint64_t>("uint64_t");
+    printf("\nAll tests passed.\n");
+    return 0;
+}
diff --git a/tests/unit/test_smart_ptrs.cpp b/tests/unit/test_smart_ptrs.cpp
new file mode 100644
index 0000000..273dc9d
--- /dev/null
+++ b/tests/unit/test_smart_ptrs.cpp
@@ -0,0 +1,482 @@
+/*
+ *  Copyright (c) 2021, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  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, 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 "test_platform.h"
+
+#include <string.h>
+
+#include <openthread/config.h>
+
+#include "test_util.hpp"
+#include "common/code_utils.hpp"
+#include "common/owned_ptr.hpp"
+#include "common/retain_ptr.hpp"
+
+namespace ot {
+
+class TestObject : public RetainCountable
+{
+public:
+    TestObject(void)
+        : mWasFreed(false)
+    {
+    }
+
+    void     Free(void) { mWasFreed = true; }
+    void     ResetTestFlags(void) { mWasFreed = false; }
+    uint16_t GetRetainCount(void) const { return RetainCountable::GetRetainCount(); }
+    bool     WasFreed(void) const { return mWasFreed && (GetRetainCount() == 0); }
+
+private:
+    bool mWasFreed;
+};
+
+static constexpr uint16_t kSkipRetainCountCheck = 0xffff;
+
+template <typename PointerType>
+void VerifyPointer(const PointerType &aPointer,
+                   const TestObject * aObject,
+                   uint16_t           aRetainCount = kSkipRetainCountCheck)
+{
+    if (aObject == nullptr)
+    {
+        VerifyOrQuit(aPointer.IsNull());
+        VerifyOrQuit(aPointer.Get() == nullptr);
+        VerifyOrQuit(aPointer == nullptr);
+    }
+    else
+    {
+        VerifyOrQuit(!aPointer.IsNull());
+        VerifyOrQuit(aPointer.Get() == aObject);
+        VerifyOrQuit(aPointer == aObject);
+        VerifyOrQuit(aPointer != nullptr);
+
+        VerifyOrQuit(!aPointer->WasFreed());
+        VerifyOrQuit(!(*aPointer).WasFreed());
+
+        if (aRetainCount != kSkipRetainCountCheck)
+        {
+            VerifyOrQuit(aObject->GetRetainCount() == aRetainCount);
+        }
+    }
+
+    VerifyOrQuit(aPointer == aPointer);
+}
+
+void TestOwnedPtr(void)
+{
+    TestObject obj1;
+    TestObject obj2;
+    TestObject obj3;
+
+    printf("\n====================================================================================\n");
+    printf("Testing `OwnedPtr`\n");
+
+    printf("\n - Default constructor (null pointer)");
+
+    {
+        OwnedPtr<TestObject> ptr;
+
+        VerifyPointer(ptr, nullptr);
+    }
+
+    printf("\n - Constructor taking ownership of an object");
+    obj1.ResetTestFlags();
+
+    {
+        OwnedPtr<TestObject> ptr(&obj1);
+
+        VerifyPointer(ptr, &obj1);
+    }
+
+    VerifyOrQuit(obj1.WasFreed());
+
+    printf("\n - Move constructor taking over from another");
+    obj1.ResetTestFlags();
+
+    {
+        OwnedPtr<TestObject> ptr1(&obj1);
+        OwnedPtr<TestObject> ptr2(ptr1.PassOwnership());
+
+        VerifyPointer(ptr1, nullptr);
+        VerifyPointer(ptr2, &obj1);
+    }
+
+    VerifyOrQuit(obj1.WasFreed());
+
+    printf("\n - `Free()` method");
+    obj1.ResetTestFlags();
+
+    {
+        OwnedPtr<TestObject> ptr(&obj1);
+
+        VerifyPointer(ptr, &obj1);
+
+        ptr.Free();
+
+        VerifyOrQuit(obj1.WasFreed());
+        VerifyPointer(ptr, nullptr);
+
+        ptr.Free();
+
+        VerifyOrQuit(obj1.WasFreed());
+        VerifyPointer(ptr, nullptr);
+    }
+
+    printf("\n - `Reset()` method");
+    obj1.ResetTestFlags();
+    obj2.ResetTestFlags();
+    obj3.ResetTestFlags();
+
+    {
+        OwnedPtr<TestObject> ptr(&obj1);
+
+        VerifyPointer(ptr, &obj1);
+
+        ptr.Reset(&obj2);
+
+        VerifyOrQuit(obj1.WasFreed());
+        VerifyOrQuit(!obj2.WasFreed());
+        VerifyPointer(ptr, &obj2);
+
+        ptr.Reset();
+        VerifyOrQuit(obj2.WasFreed());
+        VerifyPointer(ptr, nullptr);
+
+        ptr.Reset(&obj3);
+        VerifyPointer(ptr, &obj3);
+    }
+
+    VerifyOrQuit(obj1.WasFreed());
+    VerifyOrQuit(obj2.WasFreed());
+    VerifyOrQuit(obj3.WasFreed());
+
+    printf("\n - Self `Reset()`");
+    obj1.ResetTestFlags();
+
+    {
+        OwnedPtr<TestObject> ptr1(&obj1);
+        OwnedPtr<TestObject> ptr2;
+
+        VerifyPointer(ptr1, &obj1);
+
+        ptr1.Reset(&obj1);
+        VerifyPointer(ptr1, &obj1);
+
+        ptr2.Reset(nullptr);
+        VerifyPointer(ptr2, nullptr);
+    }
+
+    VerifyOrQuit(obj1.WasFreed());
+
+    printf("\n - Move assignment (operator `=`)");
+    obj1.ResetTestFlags();
+    obj2.ResetTestFlags();
+    obj3.ResetTestFlags();
+
+    {
+        OwnedPtr<TestObject> ptr1(&obj1);
+        OwnedPtr<TestObject> ptr2(&obj2);
+        OwnedPtr<TestObject> ptr3(&obj3);
+
+        VerifyPointer(ptr1, &obj1);
+        VerifyPointer(ptr2, &obj2);
+        VerifyPointer(ptr3, &obj3);
+
+        // Move from non-null (ptr1) to non-null (ptr2)
+        ptr2 = ptr1.PassOwnership();
+        VerifyPointer(ptr1, nullptr);
+        VerifyPointer(ptr2, &obj1);
+        VerifyOrQuit(!obj1.WasFreed());
+        VerifyOrQuit(obj2.WasFreed());
+
+        // Move from null (ptr1) to non-null (ptr3)
+        ptr3 = ptr1.PassOwnership();
+        VerifyPointer(ptr1, nullptr);
+        VerifyPointer(ptr3, nullptr);
+        VerifyOrQuit(obj3.WasFreed());
+
+        // Move from non-null (ptr2) to null (ptr1)
+        ptr1 = ptr2.PassOwnership();
+        VerifyPointer(ptr1, &obj1);
+        VerifyPointer(ptr2, nullptr);
+        VerifyOrQuit(!obj1.WasFreed());
+
+        // Move from null (ptr2) to null (ptr3)
+        ptr3 = ptr2.PassOwnership();
+        VerifyPointer(ptr2, nullptr);
+        VerifyPointer(ptr3, nullptr);
+        VerifyOrQuit(!obj1.WasFreed());
+    }
+
+    VerifyOrQuit(obj1.WasFreed());
+
+    printf("\n - Self move assignment (operator `=`)");
+    obj1.ResetTestFlags();
+
+    {
+        OwnedPtr<TestObject> ptr1(&obj1);
+        OwnedPtr<TestObject> ptr2;
+
+        VerifyPointer(ptr1, &obj1);
+        VerifyPointer(ptr2, nullptr);
+
+        // Move from non-null (ptr1) to itself
+        ptr1 = ptr1.PassOwnership();
+        VerifyPointer(ptr1, &obj1);
+
+        // Move from null (ptr2) to itself
+        ptr2 = ptr2.PassOwnership();
+        VerifyPointer(ptr2, nullptr);
+    }
+
+    VerifyOrQuit(obj1.WasFreed());
+
+    printf("\n - `Release()` method");
+    obj1.ResetTestFlags();
+
+    {
+        OwnedPtr<TestObject> ptr(&obj1);
+
+        VerifyPointer(ptr, &obj1);
+
+        VerifyOrQuit(ptr.Release() == &obj1);
+        VerifyOrQuit(!obj1.WasFreed());
+        VerifyPointer(ptr, nullptr);
+
+        VerifyOrQuit(ptr.Release() == nullptr);
+        VerifyOrQuit(!obj1.WasFreed());
+        VerifyPointer(ptr, nullptr);
+    }
+
+    printf("\n\n-- PASS\n");
+}
+
+void TestRetainPtr(void)
+{
+    TestObject obj1;
+    TestObject obj2;
+    TestObject obj3;
+
+    printf("\n====================================================================================\n");
+    printf("Testing `RetainPtr`\n");
+
+    VerifyOrQuit(obj1.GetRetainCount() == 0);
+    VerifyOrQuit(obj2.GetRetainCount() == 0);
+    VerifyOrQuit(obj3.GetRetainCount() == 0);
+
+    printf("\n - Default constructor (null pointer)");
+
+    {
+        RetainPtr<TestObject> ptr;
+
+        VerifyPointer(ptr, nullptr);
+    }
+
+    printf("\n - Constructor taking over management of an object");
+    obj1.ResetTestFlags();
+
+    {
+        RetainPtr<TestObject> ptr(&obj1);
+
+        VerifyPointer(ptr, &obj1, 1);
+    }
+
+    VerifyOrQuit(obj1.WasFreed());
+
+    printf("\n - Two constructed `RetainPtr`s of the same object");
+    obj1.ResetTestFlags();
+
+    {
+        RetainPtr<TestObject> ptr1(&obj1);
+        RetainPtr<TestObject> ptr2(&obj1);
+
+        VerifyPointer(ptr1, &obj1, 2);
+        VerifyPointer(ptr2, &obj1, 2);
+    }
+
+    VerifyOrQuit(obj1.WasFreed());
+
+    printf("\n - Copy constructor");
+    obj1.ResetTestFlags();
+
+    {
+        RetainPtr<TestObject> ptr1(&obj1);
+        RetainPtr<TestObject> ptr2(ptr1);
+
+        VerifyPointer(ptr1, &obj1, 2);
+        VerifyPointer(ptr2, &obj1, 2);
+    }
+
+    VerifyOrQuit(obj1.WasFreed());
+
+    printf("\n - `Reset()` method");
+    obj1.ResetTestFlags();
+    obj2.ResetTestFlags();
+    obj3.ResetTestFlags();
+
+    {
+        RetainPtr<TestObject> ptr(&obj1);
+
+        VerifyPointer(ptr, &obj1, 1);
+
+        ptr.Reset(&obj2);
+        VerifyOrQuit(obj1.WasFreed());
+        VerifyOrQuit(!obj2.WasFreed());
+        VerifyPointer(ptr, &obj2, 1);
+
+        ptr.Reset();
+        VerifyOrQuit(obj2.WasFreed());
+        VerifyPointer(ptr, nullptr);
+
+        ptr.Reset(&obj3);
+        VerifyPointer(ptr, &obj3, 1);
+    }
+
+    VerifyOrQuit(obj1.WasFreed());
+    VerifyOrQuit(obj2.WasFreed());
+    VerifyOrQuit(obj3.WasFreed());
+
+    printf("\n - Self `Reset()`");
+    obj1.ResetTestFlags();
+
+    {
+        RetainPtr<TestObject> ptr1(&obj1);
+        RetainPtr<TestObject> ptr2;
+
+        VerifyPointer(ptr1, &obj1, 1);
+
+        ptr1.Reset(&obj1);
+        VerifyPointer(ptr1, &obj1, 1);
+
+        ptr2.Reset(nullptr);
+        VerifyPointer(ptr2, nullptr);
+    }
+
+    VerifyOrQuit(obj1.WasFreed());
+
+    printf("\n - Assignment `=`");
+    obj1.ResetTestFlags();
+    obj2.ResetTestFlags();
+
+    {
+        RetainPtr<TestObject> ptr1(&obj1);
+        RetainPtr<TestObject> ptr2(&obj2);
+        RetainPtr<TestObject> ptr3;
+
+        VerifyPointer(ptr1, &obj1, 1);
+        VerifyPointer(ptr2, &obj2, 1);
+        VerifyPointer(ptr3, nullptr);
+
+        VerifyOrQuit(ptr1 != ptr2);
+        VerifyOrQuit(ptr1 != ptr3);
+        VerifyOrQuit(ptr2 != ptr3);
+
+        // Set from non-null (ptr1) to non-null (ptr2)
+        ptr2 = ptr1;
+        VerifyPointer(ptr1, &obj1, 2);
+        VerifyPointer(ptr2, &obj1, 2);
+        VerifyOrQuit(obj2.WasFreed());
+        VerifyOrQuit(ptr1 == ptr2);
+
+        // Set from null (ptr3) to non-null (ptr1)
+        ptr1 = ptr3;
+        VerifyPointer(ptr1, nullptr);
+        VerifyPointer(ptr3, nullptr);
+        VerifyPointer(ptr2, &obj1, 1);
+        VerifyOrQuit(ptr1 == ptr3);
+
+        // Move from null (ptr1) to null (ptr3)
+        ptr3 = ptr1;
+        VerifyPointer(ptr1, nullptr);
+        VerifyPointer(ptr3, nullptr);
+        VerifyOrQuit(ptr1 == ptr3);
+
+        // Move from non-null (ptr2) to null (ptr3)
+        ptr3 = ptr2;
+        VerifyPointer(ptr2, &obj1, 2);
+        VerifyPointer(ptr3, &obj1, 2);
+        VerifyOrQuit(ptr2 == ptr3);
+    }
+
+    VerifyOrQuit(obj1.WasFreed());
+    VerifyOrQuit(obj2.WasFreed());
+
+    printf("\n - Self assignment `=`");
+    obj1.ResetTestFlags();
+
+    {
+        RetainPtr<TestObject> ptr1(&obj1);
+        RetainPtr<TestObject> ptr2;
+
+        VerifyPointer(ptr1, &obj1, 1);
+        VerifyPointer(ptr2, nullptr);
+
+        // Set from non-null (ptr1) to itself. We use `*(&ptr1) to
+        // silence `clang` error/warning not allowing explicit self
+        // assignment to same variable.
+        ptr1 = *(&ptr1);
+        VerifyPointer(ptr1, &obj1, 1);
+
+        // Set from null (ptr2) to itself
+        ptr2 = *(&ptr2);
+        VerifyPointer(ptr2, nullptr);
+    }
+
+    VerifyOrQuit(obj1.WasFreed());
+
+    printf("\n - `Release()` method");
+    obj1.ResetTestFlags();
+
+    {
+        RetainPtr<TestObject> ptr(&obj1);
+
+        VerifyPointer(ptr, &obj1, 1);
+
+        VerifyOrQuit(ptr.Release() == &obj1);
+        VerifyPointer(ptr, nullptr);
+
+        VerifyOrQuit(ptr.Release() == nullptr);
+        VerifyPointer(ptr, nullptr);
+    }
+
+    VerifyOrQuit(!obj1.WasFreed());
+    VerifyOrQuit(obj1.GetRetainCount() == 1);
+
+    printf("\n\n-- PASS\n");
+}
+
+} // namespace ot
+
+int main(void)
+{
+    ot::TestOwnedPtr();
+    ot::TestRetainPtr();
+    printf("\nAll tests passed.\n");
+    return 0;
+}
diff --git a/tests/unit/test_spinel_buffer.cpp b/tests/unit/test_spinel_buffer.cpp
index 03ebdb9..4df9764 100644
--- a/tests/unit/test_spinel_buffer.cpp
+++ b/tests/unit/test_spinel_buffer.cpp
@@ -176,7 +176,7 @@
     Message *       message;
     CallbackContext oldContext;
 
-    message = sMessagePool->New(Message::kTypeIp6, 0);
+    message = sMessagePool->Allocate(Message::kTypeIp6);
     VerifyOrQuit(message != nullptr, "Null Message");
     SuccessOrQuit(message->SetLength(sizeof(sMottoText)));
     message->Write(0, sMottoText);
@@ -220,12 +220,12 @@
     Message *       message2;
     CallbackContext oldContext = sContext;
 
-    message1 = sMessagePool->New(Message::kTypeIp6, 0);
+    message1 = sMessagePool->Allocate(Message::kTypeIp6);
     VerifyOrQuit(message1 != nullptr, "Null Message");
     SuccessOrQuit(message1->SetLength(sizeof(sMysteryText)));
     message1->Write(0, sMysteryText);
 
-    message2 = sMessagePool->New(Message::kTypeIp6, 0);
+    message2 = sMessagePool->Allocate(Message::kTypeIp6);
     VerifyOrQuit(message2 != nullptr, "Null Message");
     SuccessOrQuit(message2->SetLength(sizeof(sHelloText)));
     message2->Write(0, sHelloText);
@@ -265,7 +265,7 @@
     Message *       message1;
     CallbackContext oldContext = sContext;
 
-    message1 = sMessagePool->New(Message::kTypeIp6, 0);
+    message1 = sMessagePool->Allocate(Message::kTypeIp6);
     VerifyOrQuit(message1 != nullptr, "Null Message");
 
     // An empty message with no content.
@@ -526,7 +526,7 @@
         ncpBuffer.InFrameBegin((j % 2) == 0 ? Spinel::Buffer::kPriorityHigh : Spinel::Buffer::kPriorityLow);
         SuccessOrQuit(ncpBuffer.InFrameFeedData(sHelloText, sizeof(sHelloText)));
 
-        message = sMessagePool->New(Message::kTypeIp6, 0);
+        message = sMessagePool->Allocate(Message::kTypeIp6);
         VerifyOrQuit(message != nullptr, "Null Message");
         SuccessOrQuit(message->SetLength(sizeof(sMysteryText)));
         message->Write(0, sMysteryText);
@@ -731,7 +731,7 @@
     VerifyOrQuit(ncpBuffer.InFrameFeedData(sOpenThreadText, 0) == OT_ERROR_INVALID_STATE);
     VerifyOrQuit(ncpBuffer.InFrameFeedData(sOpenThreadText, 0) == OT_ERROR_INVALID_STATE);
     VerifyOrQuit(ncpBuffer.InFrameEnd() == OT_ERROR_INVALID_STATE);
-    message = sMessagePool->New(Message::kTypeIp6, 0);
+    message = sMessagePool->Allocate(Message::kTypeIp6);
     VerifyOrQuit(message != nullptr, "Null Message");
     SuccessOrQuit(message->SetLength(sizeof(sMysteryText)));
     message->Write(0, sMysteryText);
diff --git a/tests/unit/test_string.cpp b/tests/unit/test_string.cpp
index c038460..b32a111 100644
--- a/tests/unit/test_string.cpp
+++ b/tests/unit/test_string.cpp
@@ -49,7 +49,7 @@
 void TestStringWriter(void)
 {
     String<kStringSize> str;
-    constexpr char      kLongString[] = "abcdefghijklmnopqratuvwxyzabcdefghijklmnopqratuvwxyz";
+    const char          kLongString[] = "abcdefghijklmnopqratuvwxyzabcdefghijklmnopqratuvwxyz";
 
     printf("\nTest 1: StringWriter constructor\n");
 
@@ -147,12 +147,12 @@
 void TestStringFind(void)
 {
     char emptyString[1] = {'\0'};
-    char testString[]   = "foo.bar.bar\\.";
+    char testString[]   = "Foo.bar.bar\\.";
     char testString2[]  = "abcabcabcdabc";
 
     printf("\nTest 6: StringFind() function\n");
 
-    VerifyOrQuit(StringFind(testString, 'f') == testString);
+    VerifyOrQuit(StringFind(testString, 'F') == testString);
     VerifyOrQuit(StringFind(testString, 'o') == &testString[1]);
     VerifyOrQuit(StringFind(testString, '.') == &testString[3]);
     VerifyOrQuit(StringFind(testString, 'r') == &testString[6]);
@@ -160,17 +160,19 @@
     VerifyOrQuit(StringFind(testString, 'x') == nullptr);
     VerifyOrQuit(StringFind(testString, ',') == nullptr);
 
-    VerifyOrQuit(StringFind(emptyString, 'f') == nullptr);
+    VerifyOrQuit(StringFind(emptyString, 'F') == nullptr);
     VerifyOrQuit(StringFind(emptyString, '.') == nullptr);
 
-    VerifyOrQuit(StringFind(testString, "foo") == &testString[0]);
+    VerifyOrQuit(StringFind(testString, "Foo") == &testString[0]);
     VerifyOrQuit(StringFind(testString, "oo") == &testString[1]);
     VerifyOrQuit(StringFind(testString, "bar") == &testString[4]);
     VerifyOrQuit(StringFind(testString, "bar\\") == &testString[8]);
     VerifyOrQuit(StringFind(testString, "\\.") == &testString[11]);
     VerifyOrQuit(StringFind(testString, testString) == testString);
-    VerifyOrQuit(StringFind(testString, "fooo") == nullptr);
-    VerifyOrQuit(StringFind(testString, "far") == nullptr);
+    VerifyOrQuit(StringFind(testString, "Fooo") == nullptr);
+    VerifyOrQuit(StringFind(testString, "Far") == nullptr);
+    VerifyOrQuit(StringFind(testString, "FOO") == nullptr);
+    VerifyOrQuit(StringFind(testString, "BAR") == nullptr);
     VerifyOrQuit(StringFind(testString, "bar\\..") == nullptr);
     VerifyOrQuit(StringFind(testString, "") == &testString[0]);
 
@@ -182,30 +184,138 @@
     VerifyOrQuit(StringFind(testString2, "abcabc") == &testString2[0]);
     VerifyOrQuit(StringFind(testString2, "abcabcd") == &testString2[3]);
 
+    VerifyOrQuit(StringFind(testString, "FOO", kStringCaseInsensitiveMatch) == &testString[0]);
+    VerifyOrQuit(StringFind(testString, "OO", kStringCaseInsensitiveMatch) == &testString[1]);
+    VerifyOrQuit(StringFind(testString, "BAR", kStringCaseInsensitiveMatch) == &testString[4]);
+    VerifyOrQuit(StringFind(testString, "BAR\\", kStringCaseInsensitiveMatch) == &testString[8]);
+    VerifyOrQuit(StringFind(testString, "\\.", kStringCaseInsensitiveMatch) == &testString[11]);
+    VerifyOrQuit(StringFind(testString, testString) == testString);
+    VerifyOrQuit(StringFind(testString, "FOOO", kStringCaseInsensitiveMatch) == nullptr);
+    VerifyOrQuit(StringFind(testString, "FAR", kStringCaseInsensitiveMatch) == nullptr);
+    VerifyOrQuit(StringFind(testString, "BAR\\..", kStringCaseInsensitiveMatch) == nullptr);
+    VerifyOrQuit(StringFind(testString, "", kStringCaseInsensitiveMatch) == &testString[0]);
+
+    VerifyOrQuit(StringFind(emptyString, "FOO", kStringCaseInsensitiveMatch) == nullptr);
+    VerifyOrQuit(StringFind(emptyString, "BAR", kStringCaseInsensitiveMatch) == nullptr);
+    VerifyOrQuit(StringFind(emptyString, "", kStringCaseInsensitiveMatch) == &emptyString[0]);
+
+    // Verify when sub-string has repeated patterns
+    VerifyOrQuit(StringFind(testString2, "ABCABC", kStringCaseInsensitiveMatch) == &testString2[0]);
+    VerifyOrQuit(StringFind(testString2, "ABCABCD", kStringCaseInsensitiveMatch) == &testString2[3]);
+
+    printf(" -- PASS\n");
+}
+
+void TestStringStartsWith(void)
+{
+    printf("\nTest 7: StringStartsWith() function\n");
+
+    VerifyOrQuit(StringStartsWith("FooBar", "Foo"));
+    VerifyOrQuit(!StringStartsWith("FooBar", "Ba"));
+    VerifyOrQuit(StringStartsWith("FooBar", "FooBar"));
+    VerifyOrQuit(!StringStartsWith("FooBar", "FooBarr"));
+    VerifyOrQuit(!StringStartsWith("FooBar", "foo"));
+    VerifyOrQuit(!StringStartsWith("FooBar", "FoO"));
+
+    VerifyOrQuit(!StringStartsWith("", "foo"));
+
+    VerifyOrQuit(StringStartsWith("FooBar", "FOO", kStringCaseInsensitiveMatch));
+    VerifyOrQuit(!StringStartsWith("FooBar", "BA", kStringCaseInsensitiveMatch));
+    VerifyOrQuit(StringStartsWith("FooBar", "FOOBAR", kStringCaseInsensitiveMatch));
+    VerifyOrQuit(!StringStartsWith("FooBar", "FooBarr", kStringCaseInsensitiveMatch));
+    VerifyOrQuit(StringStartsWith("FooBar", "foO", kStringCaseInsensitiveMatch));
+
+    VerifyOrQuit(!StringStartsWith("", "foo", kStringCaseInsensitiveMatch));
+
     printf(" -- PASS\n");
 }
 
 void TestStringEndsWith(void)
 {
-    printf("\nTest 7: StringEndsWith() function\n");
+    printf("\nTest 8: StringEndsWith() function\n");
 
-    VerifyOrQuit(StringEndsWith("foobar", 'r'));
-    VerifyOrQuit(!StringEndsWith("foobar", 'a'));
-    VerifyOrQuit(!StringEndsWith("foobar", '\0'));
+    VerifyOrQuit(StringEndsWith("FooBar", 'r'));
+    VerifyOrQuit(!StringEndsWith("FooBar", 'a'));
+    VerifyOrQuit(!StringEndsWith("FooBar", '\0'));
     VerifyOrQuit(StringEndsWith("a", 'a'));
     VerifyOrQuit(!StringEndsWith("a", 'b'));
 
-    VerifyOrQuit(StringEndsWith("foobar", "bar"));
-    VerifyOrQuit(!StringEndsWith("foobar", "ba"));
-    VerifyOrQuit(StringEndsWith("foobar", "foobar"));
-    VerifyOrQuit(!StringEndsWith("foobar", "foobarr"));
+    VerifyOrQuit(StringEndsWith("FooBar", "Bar"));
+    VerifyOrQuit(!StringEndsWith("FooBar", "Ba"));
+    VerifyOrQuit(StringEndsWith("FooBar", "FooBar"));
+    VerifyOrQuit(!StringEndsWith("FooBar", "FooBarr"));
 
     VerifyOrQuit(!StringEndsWith("", 'a'));
     VerifyOrQuit(!StringEndsWith("", "foo"));
 
+    VerifyOrQuit(StringEndsWith("FooBar", "baR", kStringCaseInsensitiveMatch));
+    VerifyOrQuit(!StringEndsWith("FooBar", "bA", kStringCaseInsensitiveMatch));
+    VerifyOrQuit(StringEndsWith("FooBar", "fOOBar", kStringCaseInsensitiveMatch));
+    VerifyOrQuit(!StringEndsWith("FooBar", "Foobarr", kStringCaseInsensitiveMatch));
+    VerifyOrQuit(!StringEndsWith("", "Foo", kStringCaseInsensitiveMatch));
+
     printf(" -- PASS\n");
 }
 
+void TestStringMatch(void)
+{
+    printf("\nTest 9: StringMatch() function\n");
+
+    VerifyOrQuit(StringMatch("", ""));
+    VerifyOrQuit(StringMatch("FooBar", "FooBar"));
+    VerifyOrQuit(!StringMatch("FooBar", "FooBa"));
+    VerifyOrQuit(!StringMatch("FooBa", "FooBar"));
+    VerifyOrQuit(!StringMatch("FooBa", "FooBar"));
+    VerifyOrQuit(!StringMatch("FooBar", "fooBar"));
+    VerifyOrQuit(!StringMatch("FooBaR", "FooBar"));
+
+    VerifyOrQuit(StringMatch("", "", kStringCaseInsensitiveMatch));
+    VerifyOrQuit(StringMatch("FooBar", "fOObAR", kStringCaseInsensitiveMatch));
+    VerifyOrQuit(!StringMatch("FooBar", "fOObA", kStringCaseInsensitiveMatch));
+    VerifyOrQuit(!StringMatch("FooBa", "FooBar", kStringCaseInsensitiveMatch));
+    VerifyOrQuit(!StringMatch("FooBa", "FooBar", kStringCaseInsensitiveMatch));
+    VerifyOrQuit(!StringMatch("Fooba", "fooBar", kStringCaseInsensitiveMatch));
+    VerifyOrQuit(StringMatch("FooBar", "FOOBAR", kStringCaseInsensitiveMatch));
+    VerifyOrQuit(StringMatch("FoobaR", "FooBar", kStringCaseInsensitiveMatch));
+    VerifyOrQuit(StringMatch("FOOBAR", "foobar", kStringCaseInsensitiveMatch));
+
+    printf(" -- PASS\n");
+}
+
+void TestStringToLowercase(void)
+{
+    const uint16_t kMaxSize = 100;
+
+    const char kTestString[]      = "!@#$%^&*()_+=[].,<>//;:\"'`~ \t\r\n";
+    const char kUppercaseString[] = "ABCDEFGHIJKLMNOPQRATUVWXYZABCDEFGHIJKLMNOPQRATUVWXYZ";
+    const char kLowercaseString[] = "abcdefghijklmnopqratuvwxyzabcdefghijklmnopqratuvwxyz";
+
+    char string[kMaxSize];
+
+    printf("\nTest 10: StringConvertToLowercase() function\n");
+
+    memcpy(string, kTestString, sizeof(kTestString));
+    StringConvertToLowercase(string);
+    VerifyOrQuit(memcmp(string, kTestString, sizeof(kTestString)) == 0);
+    StringConvertToUppercase(string);
+    VerifyOrQuit(memcmp(string, kTestString, sizeof(kTestString)) == 0);
+
+    memcpy(string, kUppercaseString, sizeof(kUppercaseString));
+    StringConvertToLowercase(string);
+    VerifyOrQuit(memcmp(string, kLowercaseString, sizeof(kLowercaseString)) == 0);
+    StringConvertToUppercase(string);
+    VerifyOrQuit(memcmp(string, kUppercaseString, sizeof(kUppercaseString)) == 0);
+
+    printf(" -- PASS\n");
+}
+
+static_assert(ot::AreStringsInOrder("a", "b"), "AreStringsInOrder() failed");
+static_assert(ot::AreStringsInOrder("aa", "aaa"), "AreStringsInOrder() failed");
+static_assert(ot::AreStringsInOrder("", "a"), "AreStringsInOrder() failed");
+static_assert(!ot::AreStringsInOrder("cd", "cd"), "AreStringsInOrder() failed");
+static_assert(!ot::AreStringsInOrder("z", "abcd"), "AreStringsInOrder() failed");
+static_assert(!ot::AreStringsInOrder("0", ""), "AreStringsInOrder() failed");
+
 } // namespace ot
 
 int main(void)
@@ -214,7 +324,10 @@
     ot::TestStringLength();
     ot::TestUtf8();
     ot::TestStringFind();
+    ot::TestStringStartsWith();
     ot::TestStringEndsWith();
+    ot::TestStringMatch();
+    ot::TestStringToLowercase();
     printf("\nAll tests passed.\n");
     return 0;
 }
diff --git a/tests/unit/test_timer.cpp b/tests/unit/test_timer.cpp
index 660b56c..00cc02e 100644
--- a/tests/unit/test_timer.cpp
+++ b/tests/unit/test_timer.cpp
@@ -28,6 +28,7 @@
 
 #include "test_platform.h"
 
+#include "common/array.hpp"
 #include "common/code_utils.hpp"
 #include "common/debug.hpp"
 #include "common/instance.hpp"
@@ -585,7 +586,7 @@
 
     size_t i;
 
-    for (i = 0; i < OT_ARRAY_LENGTH(kTimeShift); i++)
+    for (i = 0; i < ot::GetArrayLength(kTimeShift); i++)
     {
         TenTimers<TimerType>(kTimeShift[i]);
     }
diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt
index d57660f..7191432 100644
--- a/third_party/CMakeLists.txt
+++ b/third_party/CMakeLists.txt
@@ -30,4 +30,6 @@
     add_subdirectory(mbedtls)
 endif()
 
-add_subdirectory(tcplp)
+if(NOT OT_EXCLUDE_TCPLP_LIB)
+    add_subdirectory(tcplp)
+endif()
diff --git a/third_party/mbedtls/Makefile.am b/third_party/mbedtls/Makefile.am
index cf62031..4a6f4f6 100644
--- a/third_party/mbedtls/Makefile.am
+++ b/third_party/mbedtls/Makefile.am
@@ -67,6 +67,9 @@
     repo/library/cipher_wrap.c                  \
     repo/library/cmac.c                         \
     repo/library/common.h                       \
+    repo/library/constant_time.c                \
+    repo/library/constant_time_internal.h       \
+    repo/library/constant_time_invasive.h       \
     repo/library/ctr_drbg.c                     \
     repo/library/debug.c                        \
     repo/library/des.c                          \
@@ -76,6 +79,7 @@
     repo/library/ecjpake.c                      \
     repo/library/ecp.c                          \
     repo/library/ecp_curves.c                   \
+    repo/library/ecp_invasive.h                 \
     repo/library/entropy.c                      \
     repo/library/entropy_poll.c                 \
     repo/library/error.c                        \
@@ -87,6 +91,12 @@
     repo/library/md2.c                          \
     repo/library/md4.c                          \
     repo/library/md5.c                          \
+    repo/library/mps_common.h                   \
+    repo/library/mps_error.h                    \
+    repo/library/mps_reader.c                   \
+    repo/library/mps_reader.h                   \
+    repo/library/mps_trace.c                    \
+    repo/library/mps_trace.h                    \
     repo/library/memory_buffer_alloc.c          \
     repo/library/net_sockets.c                  \
     repo/library/nist_kw.c                      \
@@ -104,11 +114,25 @@
     repo/library/platform_util.c                \
     repo/library/poly1305.c                     \
     repo/library/psa_crypto.c                   \
+    repo/library/psa_crypto_aead.c              \
+    repo/library/psa_crypto_aead.h              \
     repo/library/psa_crypto_core.h              \
+    repo/library/psa_crypto_cipher.c            \
+    repo/library/psa_crypto_cipher.h            \
+    repo/library/psa_crypto_client.c            \
     repo/library/psa_crypto_driver_wrappers.c   \
     repo/library/psa_crypto_driver_wrappers.h   \
+    repo/library/psa_crypto_ecp.c               \
+    repo/library/psa_crypto_ecp.h               \
+    repo/library/psa_crypto_hash.c              \
+    repo/library/psa_crypto_hash.h              \
     repo/library/psa_crypto_invasive.h          \
     repo/library/psa_crypto_its.h               \
+    repo/library/psa_crypto_mac.c               \
+    repo/library/psa_crypto_mac.h               \
+    repo/library/psa_crypto_random_impl.h       \
+    repo/library/psa_crypto_rsa.c               \
+    repo/library/psa_crypto_rsa.h               \
     repo/library/psa_crypto_se.c                \
     repo/library/psa_crypto_se.h                \
     repo/library/psa_crypto_slot_management.c   \
@@ -126,7 +150,6 @@
     repo/library/ssl_ciphersuites.c             \
     repo/library/ssl_cli.c                      \
     repo/library/ssl_cookie.c                   \
-    repo/library/ssl_invasive.h                 \
     repo/library/ssl_msg.c                      \
     repo/library/ssl_srv.c                      \
     repo/library/ssl_ticket.c                   \
diff --git a/third_party/mbedtls/README.md b/third_party/mbedtls/README.md
index 48dec54..2af292d 100644
--- a/third_party/mbedtls/README.md
+++ b/third_party/mbedtls/README.md
@@ -2,11 +2,11 @@
 
 ## URL
 
-https://github.com/ARMmbed/mbedtls/releases/tag/mbedtls-2.25.0
+https://github.com/ARMmbed/mbedtls/releases/tag/mbedtls-2.28.0
 
 ## Version
 
-2.25.0
+2.28.0
 
 ## License
 
diff --git a/third_party/mbedtls/repo/.github/issue_template.md b/third_party/mbedtls/repo/.github/issue_template.md
index 18b87fc..370066f 100644
--- a/third_party/mbedtls/repo/.github/issue_template.md
+++ b/third_party/mbedtls/repo/.github/issue_template.md
@@ -1,7 +1,17 @@
-Note: This is just a template, so feel free to use/remove the unnecessary things
+_Note:_ this is a template, please remove the parts that are not
+applicable (these initial notes, and the "Bug" section for a Feature request
+and vice-versa).
 
+**Note:** to report a security vulnerability, see
+[SECURITY.md](../SECURITY.md). Please do not use github issues for
+vulnerabilities.
+
+_Note:_ to get support, see [SUPPORT.md](../SUPPORT.md). Please do not use
+github issues for questions.
+
+---------------------------------------------------------------
 ### Description
-- Type: Bug | Enhancement\Feature Request
+- Type: Bug | Enhancement / Feature Request
 - Priority: Blocker | Major | Minor
 
 ---------------------------------------------------------------
@@ -28,14 +38,9 @@
 **Steps to reproduce**  
 
 ----------------------------------------------------------------
-## Enhancement\Feature Request
-
-**Justification - why does the library need this feature?**  
+## Enhancement / Feature Request
 
 **Suggested enhancement**  
 
------------------------------------------------------------------
+**Justification - why does the library need this feature?**  
 
-## Question
-
-**Please first check for answers in the [Mbed TLS knowledge Base](https://tls.mbed.org/kb). If you can't find the answer you're looking for then please use the [Mbed TLS mailing list](https://lists.trustedfirmware.org/mailman/listinfo/mbed-tls)**
diff --git a/third_party/mbedtls/repo/.gitignore b/third_party/mbedtls/repo/.gitignore
index 39cdc4e..9b185c6 100644
--- a/third_party/mbedtls/repo/.gitignore
+++ b/third_party/mbedtls/repo/.gitignore
@@ -18,6 +18,7 @@
 Coverage
 *.gcno
 *.gcda
+coverage-summary.txt
 
 # generated by scripts/memory.sh
 massif-*
@@ -48,6 +49,9 @@
 # Generated documentation:
 /apidoc
 
+# PSA Crypto compliance test repo, cloned by test_psa_compliance.py
+/psa-arch-tests
+
 # Editor navigation files:
 /GPATH
 /GRTAGS
diff --git a/third_party/mbedtls/repo/.mypy.ini b/third_party/mbedtls/repo/.mypy.ini
new file mode 100644
index 0000000..6b831dd
--- /dev/null
+++ b/third_party/mbedtls/repo/.mypy.ini
@@ -0,0 +1,4 @@
+[mypy]
+mypy_path = scripts
+namespace_packages = True
+warn_unused_configs = True
diff --git a/third_party/mbedtls/repo/.pylintrc b/third_party/mbedtls/repo/.pylintrc
index ad25a7c..d217ff6 100644
--- a/third_party/mbedtls/repo/.pylintrc
+++ b/third_party/mbedtls/repo/.pylintrc
@@ -1,3 +1,6 @@
+[MASTER]
+init-hook='import sys; sys.path.append("scripts")'
+
 [BASIC]
 # We're ok with short funtion argument names.
 # [invalid-name]
@@ -12,9 +15,9 @@
 # [missing-docstring]
 docstring-min-length=10
 
-# Allow longer methods than the default.
+# No upper limit on method names. Pylint <2.1.0 has an upper limit of 30.
 # [invalid-name]
-method-rgx=[a-z_][a-z0-9_]{2,35}$
+method-rgx=[a-z_][a-z0-9_]{2,}$
 
 # Allow module names containing a dash (but no underscore or uppercase letter).
 # They are whole programs, not meant to be included by another module.
diff --git a/third_party/mbedtls/repo/.travis.yml b/third_party/mbedtls/repo/.travis.yml
index 76cb1c5..3354607 100644
--- a/third_party/mbedtls/repo/.travis.yml
+++ b/third_party/mbedtls/repo/.travis.yml
@@ -14,38 +14,25 @@
           - graphviz
           - gcc-arm-none-eabi
           - libnewlib-arm-none-eabi
+          - gcc-arm-linux-gnueabi
+          - libc6-dev-armel-cross
       language: python # Needed to get pip for Python 3
       python: 3.5 # version from Ubuntu 16.04
       install:
-        - pip install pylint==2.4.4
+        - scripts/min_requirements.py
       script:
         - tests/scripts/all.sh -k 'check_*'
         - tests/scripts/all.sh -k test_default_out_of_box
-        - tests/scripts/test-ref-configs.pl
-        - tests/scripts/all.sh -k build_arm_none_eabi_gcc_arm5vte build_arm_none_eabi_gcc_m0plus
+        - tests/scripts/all.sh -k test_ref_configs
+        - tests/scripts/all.sh -k build_arm_linux_gnueabi_gcc_arm5vte build_arm_none_eabi_gcc_m0plus
 
     - name: full configuration
       script:
         - tests/scripts/all.sh -k test_full_cmake_gcc_asan
 
-    - name: macOS
-      os: osx
-      compiler: clang
-      script:
-        - tests/scripts/all.sh -k test_default_out_of_box
-
     - name: Windows
       os: windows
-      before_install:
-        - choco install python --version=3.5.4
-      env:
-        # Add the directory where the Choco package goes
-        - PATH=/c/Python35:/c/Python35/Scripts:$PATH
       script:
-        - type python; python --version
-        - python scripts/generate_psa_constants.py
-        # Logs appear out of sequence on Windows. Give time to catch up.
-        - sleep 5
         - scripts/windows_msbuild.bat v141 # Visual Studio 2017
 
 after_failure:
diff --git a/third_party/mbedtls/repo/BRANCHES.md b/third_party/mbedtls/repo/BRANCHES.md
new file mode 100644
index 0000000..ee91f76
--- /dev/null
+++ b/third_party/mbedtls/repo/BRANCHES.md
@@ -0,0 +1,54 @@
+# Maintained branches
+
+At any point in time, we have a number of maintained branches consisting of:
+
+- The [`master`](https://github.com/ARMmbed/mbedtls/tree/master) branch:
+  this always contains the latest release, including all publicly available
+  security fixes.
+- The [`development`](https://github.com/ARMmbed/mbedtls/tree/development) branch:
+  this is where new features land,
+  as well as bug fixes and security fixes.
+- One or more long-time support (LTS) branches:
+  these only get bug fixes and security fixes.
+
+We use [Semantic Versioning](https://semver.org/). In particular, we maintain
+API compatibility in the `master` branch between major version changes. We
+also maintain ABI compatibility within LTS branches; see the next section for
+details.
+
+## Backwards Compatibility
+
+We maintain API compatibility in released versions of Mbed TLS. If you have
+code that's working and secure with Mbed TLS x.y.z and does not rely on
+undocumented features, then you should be able to re-compile it without
+modification with any later release x.y'.z' with the same major version
+number, and your code will still build, be secure, and work.
+
+There are rare exceptions: code that was relying on something that became
+insecure in the meantime (for example, crypto that was found to be weak) may
+need to be changed. In case security comes in conflict with backwards
+compatibility, we will put security first, but always attempt to provide a
+compatibility option.
+
+For the LTS branches, additionally we try very hard to also maintain ABI
+compatibility (same definition as API except with re-linking instead of
+re-compiling) and to avoid any increase in code size or RAM usage, or in the
+minimum version of tools needed to build the code. The only exception, as
+before, is in case those goals would conflict with fixing a security issue, we
+will put security first but provide a compatibility option. (So far we never
+had to break ABI compatibility in an LTS branch, but we occasionally had to
+increase code size for a security fix.)
+
+For contributors, see the [Backwards Compatibility section of
+CONTRIBUTING](CONTRIBUTING.md#cackwords-compatibility).
+
+## Current Branches
+
+The following branches are currently maintained:
+
+- [master](https://github.com/ARMmbed/mbedtls/tree/master)
+- [`development`](https://github.com/ARMmbed/mbedtls/)
+- [`mbedtls-2.28`](https://github.com/ARMmbed/mbedtls/tree/mbedtls-2.28)
+ maintained until at least the end of 2024.
+
+Users are urged to always use the latest version of a maintained branch.
diff --git a/third_party/mbedtls/repo/BUGS.md b/third_party/mbedtls/repo/BUGS.md
new file mode 100644
index 0000000..e8705ff
--- /dev/null
+++ b/third_party/mbedtls/repo/BUGS.md
@@ -0,0 +1,20 @@
+## Known issues
+
+Known issues in Mbed TLS are [tracked on GitHub](https://github.com/ARMmbed/mbedtls/issues).
+
+## Reporting a bug
+
+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`,
+   or a long-time support branch.
+2. Check [GitHub](https://github.com/ARMmbed/mbedtls/issues) to see if
+   your issue has already been reported. If not, …
+3. If the issue is a security risk (for example: buffer overflow,
+   data leak), please report it confidentially as described in
+   [`SECURITY.md`](SECURITY.md). If not, …
+4. Please [create an issue on on GitHub](https://github.com/ARMmbed/mbedtls/issues).
+
+Please do not use GitHub for support questions. If you want to know
+how to do something with Mbed TLS, please see [`SUPPORT.md`](SUPPORT.md) for available documentation and support channels.
diff --git a/third_party/mbedtls/repo/CMakeLists.txt b/third_party/mbedtls/repo/CMakeLists.txt
index ac24bf4..14ca7b6 100644
--- a/third_party/mbedtls/repo/CMakeLists.txt
+++ b/third_party/mbedtls/repo/CMakeLists.txt
@@ -21,6 +21,18 @@
 #
 
 cmake_minimum_required(VERSION 2.8.12)
+
+# https://cmake.org/cmake/help/latest/policy/CMP0011.html
+# Setting this policy is required in CMake >= 3.18.0, otherwise a warning is generated. The OLD
+# policy setting is deprecated, and will be removed in future versions.
+cmake_policy(SET CMP0011 NEW)
+# https://cmake.org/cmake/help/latest/policy/CMP0012.html
+# Setting the CMP0012 policy to NEW is required for FindPython3 to work with CMake 3.18.2
+# (there is a bug in this particular version), otherwise, setting the CMP0012 policy is required
+# for CMake versions >= 3.18.3 otherwise a deprecated warning is generated. The OLD policy setting
+# is deprecated and will be removed in future versions.
+cmake_policy(SET CMP0012 NEW)
+
 if(TEST_CPP)
     project("mbed TLS" C CXX)
 else()
@@ -167,6 +179,9 @@
     execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
                     OUTPUT_VARIABLE GCC_VERSION)
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wwrite-strings")
+    if (GCC_VERSION VERSION_GREATER 3.0 OR GCC_VERSION VERSION_EQUAL 3.0)
+        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat=2 -Wno-format-nonliteral")
+    endif()
     if (GCC_VERSION VERSION_GREATER 4.3 OR GCC_VERSION VERSION_EQUAL 4.3)
         set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wvla")
     endif()
@@ -182,6 +197,9 @@
             set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat-signedness")
         endif()
     endif()
+    if (GCC_VERSION VERSION_GREATER 7.0 OR GCC_VERSION VERSION_EQUAL 7.0)
+      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat-overflow=2 -Wformat-truncation")
+    endif()
     set(CMAKE_C_FLAGS_RELEASE     "-O2")
     set(CMAKE_C_FLAGS_DEBUG       "-O0 -g3")
     set(CMAKE_C_FLAGS_COVERAGE    "-O0 -g3 --coverage")
@@ -192,7 +210,7 @@
 endif(CMAKE_COMPILER_IS_GNU)
 
 if(CMAKE_COMPILER_IS_CLANG)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wwrite-strings -Wpointer-arith -Wimplicit-fallthrough -Wshadow -Wvla")
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wwrite-strings -Wpointer-arith -Wimplicit-fallthrough -Wshadow -Wvla -Wformat=2 -Wno-format-nonliteral")
     set(CMAKE_C_FLAGS_RELEASE     "-O2")
     set(CMAKE_C_FLAGS_DEBUG       "-O0 -g3")
     set(CMAKE_C_FLAGS_COVERAGE    "-O0 -g3 --coverage")
diff --git a/third_party/mbedtls/repo/CONTRIBUTING.md b/third_party/mbedtls/repo/CONTRIBUTING.md
index 9b02ba5..b3a9547 100644
--- a/third_party/mbedtls/repo/CONTRIBUTING.md
+++ b/third_party/mbedtls/repo/CONTRIBUTING.md
@@ -22,9 +22,10 @@
 1. All new files should include the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) standard license header where possible.
 1. Ensure that each commit has at least one `Signed-off-by:` line from the committer. If anyone else contributes to the commit, they should also add their own `Signed-off-by:` line. By adding this line, contributor(s) certify that the contribution is made under the terms of the [Developer Certificate of Origin](dco.txt). The contribution licensing is described in the [License section of the README](README.md#License).
 
-API/ABI Compatibility
----------------------
-The project aims to minimise the impact on users upgrading to newer versions of the library and it should not be necessary for a user to make any changes to their own code to work with a newer version of the library. Unless the user has made an active decision to use newer features, a newer generation of the library or a change has been necessary due to a security issue or other significant software defect, no modifications to their own code should be necessary. To achieve this, API compatibility is maintained between different versions of Mbed TLS on the main development branch and in LTS (Long Term Support) branches.
+Backwards Compatibility
+-----------------------
+
+The project aims to minimise the impact on users upgrading to newer versions of the library and it should not be necessary for a user to make any changes to their own code to work with a newer version of the library. Unless the user has made an active decision to use newer features, a newer generation of the library or a change has been necessary due to a security issue or other significant software defect, no modifications to their own code should be necessary. To achieve this, API compatibility is maintained between different versions of Mbed TLS on the main development branch and in LTS (Long Term Support) branches, as described in [BRANCHES.md](BRANCHES.md).
 
 To minimise such disruption to users, where a change to the interface is required, all changes to the ABI or API, even on the main development branch where new features are added, need to be justifiable by either being a significant enhancement, new feature or bug fix which is best resolved by an interface change.
 
@@ -48,6 +49,9 @@
 
 It would be highly appreciated if contributions are backported to LTS branches in addition to the [development branch](https://github.com/ARMmbed/mbedtls/tree/development) by contributors.
 
+The list of maintained branches can be found in the [Current Branches section
+of BRANCHES.md](BRANCHES.md#current-branches).
+
 Currently maintained LTS branches are:
 1. [mbedtls-2.7](https://github.com/ARMmbed/mbedtls/tree/mbedtls-2.7)
 1. [mbedtls-2.16](https://github.com/ARMmbed/mbedtls/tree/mbedtls-2.16)
diff --git a/third_party/mbedtls/repo/ChangeLog b/third_party/mbedtls/repo/ChangeLog
index fb231aa..021012a 100644
--- a/third_party/mbedtls/repo/ChangeLog
+++ b/third_party/mbedtls/repo/ChangeLog
@@ -1,5 +1,437 @@
 mbed TLS ChangeLog (Sorted per branch, date)
 
+= mbed TLS 2.28.0 branch released 2021-12-17
+
+API changes
+   * Some fields of mbedtls_ssl_session and mbedtls_ssl_config are in a
+     different order. This only affects applications that define such
+     structures directly or serialize them.
+
+Requirement changes
+   * Sign-magnitude and one's complement representations for signed integers are
+     not supported. Two's complement is the only supported representation.
+
+Removals
+   * Remove config option MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES,
+     which allowed SHA-1 in the default TLS configuration for certificate
+     signing. It was intended to facilitate the transition in environments
+     with SHA-1 certificates. SHA-1 is considered a weak message digest and
+     its use constitutes a security risk.
+   * Remove the partial support for running unit tests via Greentea on Mbed OS,
+     which had been unmaintained since 2018.
+
+Features
+   * The identifier of the CID TLS extension can be configured by defining
+     MBEDTLS_TLS_EXT_CID at compile time.
+   * Warn if errors from certain functions are ignored. This is currently
+     supported on GCC-like compilers and on MSVC and can be configured through
+     the macro MBEDTLS_CHECK_RETURN. The warnings are always enabled
+     (where supported) for critical functions where ignoring the return
+     value is almost always a bug. Enable the new configuration option
+     MBEDTLS_CHECK_RETURN_WARNING to get warnings for other functions. This
+     is currently implemented in the AES, DES and md modules, and will be
+     extended to other modules in the future.
+   * Add missing PSA macros declared by PSA Crypto API 1.0.0:
+     PSA_ALG_IS_SIGN_HASH, PSA_ALG_NONE, PSA_HASH_BLOCK_LENGTH, PSA_KEY_ID_NULL.
+   * Add new API mbedtls_ct_memcmp for constant time buffer comparison.
+   * Add PSA API definition for ARIA.
+
+Security
+   * Zeroize several intermediate variables used to calculate the expected
+     value when verifying a MAC or AEAD tag. This hardens the library in
+     case the value leaks through a memory disclosure vulnerability. For
+     example, a memory disclosure vulnerability could have allowed a
+     man-in-the-middle to inject fake ciphertext into a DTLS connection.
+   * In psa_cipher_generate_iv() and psa_cipher_encrypt(), do not read back
+     from the output buffer. This fixes a potential policy bypass or decryption
+     oracle vulnerability if the output buffer is in memory that is shared with
+     an untrusted application.
+   * Fix a double-free that happened after mbedtls_ssl_set_session() or
+     mbedtls_ssl_get_session() failed with MBEDTLS_ERR_SSL_ALLOC_FAILED
+     (out of memory). After that, calling mbedtls_ssl_session_free()
+     and mbedtls_ssl_free() would cause an internal session buffer to
+     be free()'d twice.
+
+Bugfix
+   * Stop using reserved identifiers as local variables. Fixes #4630.
+   * The GNU makefiles invoke python3 in preference to python except on Windows.
+     The check was accidentally not performed when cross-compiling for Windows
+     on Linux. Fix this. Fixes #4774.
+   * Prevent divide by zero if either of PSA_CIPHER_ENCRYPT_OUTPUT_SIZE() or
+     PSA_CIPHER_UPDATE_OUTPUT_SIZE() were called using an asymmetric key type.
+   * Fix a parameter set but unused in psa_crypto_cipher.c. Fixes #4935.
+   * Don't use the obsolete header path sys/fcntl.h in unit tests.
+     These header files cause compilation errors in musl.
+     Fixes #4969.
+   * Fix missing constraints on x86_64 and aarch64 assembly code
+     for bignum multiplication that broke some bignum operations with
+     (at least) Clang 12.
+     Fixes #4116, #4786, #4917, #4962.
+   * Fix mbedtls_cipher_crypt: AES-ECB when MBEDTLS_USE_PSA_CRYPTO is enabled.
+   * Failures of alternative implementations of AES or DES single-block
+     functions enabled with MBEDTLS_AES_ENCRYPT_ALT, MBEDTLS_AES_DECRYPT_ALT,
+     MBEDTLS_DES_CRYPT_ECB_ALT or MBEDTLS_DES3_CRYPT_ECB_ALT were ignored.
+     This does not concern the implementation provided with Mbed TLS,
+     where this function cannot fail, or full-module replacements with
+     MBEDTLS_AES_ALT or MBEDTLS_DES_ALT. Reported by Armelle Duboc in #1092.
+   * Some failures of HMAC operations were ignored. These failures could only
+     happen with an alternative implementation of the underlying hash module.
+   * Fix the error returned by psa_generate_key() for a public key. Fixes #4551.
+   * Fix the build of sample programs when neither MBEDTLS_ERROR_C nor
+     MBEDTLS_ERROR_STRERROR_DUMMY is enabled.
+   * Fix PSA_ALG_RSA_PSS verification accepting an arbitrary salt length.
+     This algorithm now accepts only the same salt length for verification
+     that it produces when signing, as documented. Use the new algorithm
+     PSA_ALG_RSA_PSS_ANY_SALT to accept any salt length. Fixes #4946.
+   * The existing predicate macro name PSA_ALG_IS_HASH_AND_SIGN is now reserved
+     for algorithm values that fully encode the hashing step, as per the PSA
+     Crypto API specification. This excludes PSA_ALG_RSA_PKCS1V15_SIGN_RAW and
+     PSA_ALG_ECDSA_ANY. The new predicate macro PSA_ALG_IS_SIGN_HASH covers
+     all algorithms that can be used with psa_{sign,verify}_hash(), including
+     these two.
+   * Fix issue in Makefile on Linux with SHARED=1, that caused shared libraries
+     not to list other shared libraries they need.
+   * Fix a bug in mbedtls_gcm_starts() when the bit length of the iv
+     exceeds 2^32. Fixes #4884.
+   * Fix an uninitialized variable warning in test_suite_ssl.function with GCC
+     version 11.
+   * Fix the build when no SHA2 module is included. Fixes #4930.
+   * Fix the build when only the bignum module is included. Fixes #4929.
+   * Fix a potential invalid pointer dereference and infinite loop bugs in
+     pkcs12 functions when the password is empty. Fix the documentation to
+     better describe the inputs to these functions and their possible values.
+     Fixes #5136.
+   * The key usage flags PSA_KEY_USAGE_SIGN_MESSAGE now allows the MAC
+     operations psa_mac_compute() and psa_mac_sign_setup().
+   * The key usage flags PSA_KEY_USAGE_VERIFY_MESSAGE now allows the MAC
+     operations psa_mac_verify() and psa_mac_verify_setup().
+
+Changes
+   * Set config option MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE to be
+     disabled by default.
+   * Improve the performance of base64 constant-flow code. The result is still
+     slower than the original non-constant-flow implementation, but much faster
+     than the previous constant-flow implementation. Fixes #4814.
+   * Indicate in the error returned if the nonce length used with
+     ChaCha20-Poly1305 is invalid, and not just unsupported.
+   * The mbedcrypto library includes a new source code module constant_time.c,
+     containing various functions meant to resist timing side channel attacks.
+     This module does not have a separate configuration option, and functions
+     from this module will be included in the build as required. Currently
+     most of the interface of this module is private and may change at any
+     time.
+
+= mbed TLS 2.27.0 branch released 2021-07-07
+
+API changes
+   * Update AEAD output size macros to bring them in line with the PSA Crypto
+     API version 1.0 spec. This version of the spec parameterizes them on the
+     key type used, as well as the key bit-size in the case of
+     PSA_AEAD_TAG_LENGTH.
+     The old versions of these macros were renamed and deprecated as follows:
+     - PSA_AEAD_TAG_LENGTH          -> PSA_AEAD_TAG_LENGTH_1_ARG
+     - PSA_AEAD_ENCRYPT_OUTPUT_SIZE -> PSA_AEAD_ENCRYPT_OUTPUT_SIZE_2_ARG
+     - PSA_AEAD_DECRYPT_OUTPUT_SIZE -> PSA_AEAD_DECRYPT_OUTPUT_SIZE_2_ARG
+     - PSA_AEAD_UPDATE_OUTPUT_SIZE  -> PSA_AEAD_UPDATE_OUTPUT_SIZE_2_ARG
+     - PSA_AEAD_FINISH_OUTPUT_SIZE  -> PSA_AEAD_FINISH_OUTPUT_SIZE_1_ARG
+     - PSA_AEAD_VERIFY_OUTPUT_SIZE  -> PSA_AEAD_VERIFY_OUTPUT_SIZE_1_ARG
+   * Implement one-shot cipher functions, psa_cipher_encrypt and
+     psa_cipher_decrypt, according to the PSA Crypto API 1.0.0
+     specification.
+
+Requirement changes
+   * The library now uses the %zu format specifier with the printf() family of
+     functions, so requires a toolchain that supports it. This change does not
+     affect the maintained LTS branches, so when contributing changes please
+     bear this in mind and do not add them to backported code.
+
+Features
+   * Add mbedtls_rsa_rsassa_pss_sign_ext() function allowing to generate a
+     signature with a specific salt length. This function allows to validate
+     test cases provided in the NIST's CAVP test suite. Contributed by Cédric
+     Meuter in PR #3183.
+   * Added support for built-in driver keys through the PSA opaque crypto
+     driver interface. Refer to the documentation of
+     MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS for more information.
+   * Implement psa_sign_message() and psa_verify_message().
+   * The new function mbedtls_mpi_random() generates a random value in a
+     given range uniformly.
+   * Implement psa_mac_compute() and psa_mac_verify() as defined in the
+     PSA Cryptograpy API 1.0.0 specification.
+   * MBEDTLS_ECP_MAX_BITS is now determined automatically from the configured
+     curves and no longer needs to be configured explicitly to save RAM.
+
+Security
+   * Fix a bias in the generation of finite-field Diffie-Hellman-Merkle (DHM)
+     private keys and of blinding values for DHM and elliptic curves (ECP)
+     computations. Reported by FlorianF89 in #4245.
+   * Fix a potential side channel vulnerability in ECDSA ephemeral key generation.
+     An adversary who is capable of very precise timing measurements could
+     learn partial information about the leading bits of the nonce used for the
+     signature, allowing the recovery of the private key after observing a
+     large number of signature operations. This completes a partial fix in
+     Mbed TLS 2.20.0.
+   * It was possible to configure MBEDTLS_ECP_MAX_BITS to a value that is
+     too small, leading to buffer overflows in ECC operations. Fail the build
+     in such a case.
+   * An adversary with access to precise enough information about memory
+     accesses (typically, an untrusted operating system attacking a secure
+     enclave) could recover an RSA private key after observing the victim
+     performing a single private-key operation. Found and reported by
+     Zili KOU, Wenjian HE, Sharad Sinha, and Wei ZHANG.
+   * An adversary with access to precise enough timing information (typically, a
+     co-located process) could recover a Curve25519 or Curve448 static ECDH key
+     after inputting a chosen public key and observing the victim performing the
+     corresponding private-key operation. Found and reported by Leila Batina,
+     Lukas Chmielewski, Björn Haase, Niels Samwel and Peter Schwabe.
+
+Bugfix
+   * Add printf function attributes to mbedtls_debug_print_msg to ensure we
+     get printf format specifier warnings.
+   * Fix premature fopen() call in mbedtls_entropy_write_seed_file which may
+     lead to seed file corruption in the case where the path to the seed file is
+     equal to MBEDTLS_PLATFORM_STD_NV_SEED_FILE. Contributed by Victor
+     Krasnoshchok in #3616.
+   * PSA functions other than psa_open_key now return PSA_ERROR_INVALID_HANDLE
+     rather than PSA_ERROR_DOES_NOT_EXIST for an invalid handle, bringing them
+     in line with version 1.0.0 of the specification. Fix #4162.
+   * PSA functions creating a key now return PSA_ERROR_INVALID_ARGUMENT rather
+     than PSA_ERROR_INVALID_HANDLE when the identifier specified for the key
+     to create is not valid, bringing them in line with version 1.0.0 of the
+     specification. Fix #4271.
+   * Fix some cases in the bignum module where the library constructed an
+     unintended representation of the value 0 which was not processed
+     correctly by some bignum operations. This could happen when
+     mbedtls_mpi_read_string() was called on "-0", or when
+     mbedtls_mpi_mul_mpi() and mbedtls_mpi_mul_int() was called with one of
+     the arguments being negative and the other being 0. Fixes #4643.
+   * Fix a bug in ECDSA that would cause it to fail when the hash is all-bits
+     zero. Fixes #1792
+   * Fix a compilation error when MBEDTLS_ECP_RANDOMIZE_MXZ_ALT is
+     defined. Fixes #4217.
+   * Fix an incorrect error code when parsing a PKCS#8 private key.
+   * In a TLS client, enforce the Diffie-Hellman minimum parameter size
+     set with mbedtls_ssl_conf_dhm_min_bitlen() precisely. Before, the
+     minimum size was rounded down to the nearest multiple of 8.
+   * In library/net_sockets.c, _POSIX_C_SOURCE and _XOPEN_SOURCE are
+     defined to specific values.  If the code is used in a context
+     where these are already defined, this can result in a compilation
+     error.  Instead, assume that if they are defined, the values will
+     be adequate to build Mbed TLS.
+   * The cipher suite TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384 was not available
+     when SHA-1 was disabled and was offered when SHA-1 was enabled but SHA-384
+     was disabled. Fix the dependency. Fixes #4472.
+   * Do not offer SHA384 cipher suites when SHA-384 is disabled. Fixes #4499.
+   * With MBEDTLS_PSA_CRYPTO_C disabled, some functions were getting built
+     nonetheless, resulting in undefined reference errors when building a
+     shared library. Reported by Guillermo Garcia M. in #4411.
+   * Fix test suite code on platforms where int32_t is not int, such as
+     Arm Cortex-M. Fixes #4530.
+   * Fix some issues affecting MBEDTLS_ARIA_ALT implementations: a misplaced
+     directive in a header and a missing initialization in the self-test.
+   * Fix a missing initialization in the Camellia self-test, affecting
+     MBEDTLS_CAMELLIA_ALT implementations.
+   * Restore the ability to configure PSA via Mbed TLS options to support RSA
+     key pair operations but exclude RSA key generation. When MBEDTLS_GENPRIME
+     is not defined PSA will no longer attempt to use mbedtls_rsa_gen_key().
+     Fixes #4512.
+   * Fix a regression introduced in 2.24.0 which broke (D)TLS CBC ciphersuites
+     (when the encrypt-then-MAC extension is not in use) with some ALT
+     implementations of the underlying hash (SHA-1, SHA-256, SHA-384), causing
+     the affected side to wrongly reject valid messages. Fixes #4118.
+   * Remove outdated check-config.h check that prevented implementing the
+     timing module on Mbed OS. Fixes #4633.
+   * Fix PSA_ALG_TLS12_PRF and PSA_ALG_TLS12_PSK_TO_MS being too permissive
+     about missing inputs.
+   * Fix mbedtls_net_poll() and mbedtls_net_recv_timeout() often failing with
+     MBEDTLS_ERR_NET_POLL_FAILED on Windows. Fixes #4465.
+   * Fix a resource leak in a test suite with an alternative AES
+     implementation. Fixes #4176.
+   * Fix a crash in mbedtls_mpi_debug_mpi on a bignum having 0 limbs. This
+     could notably be triggered by setting the TLS debug level to 3 or above
+     and using a Montgomery curve for the key exchange. Reported by lhuang04
+     in #4578. Fixes #4608.
+   * psa_verify_hash() was relying on implementation-specific behavior of
+     mbedtls_rsa_rsassa_pss_verify() and was causing failures in some _ALT
+     implementations. This reliance is now removed. Fixes #3990.
+   * Disallow inputs of length different from the corresponding hash when
+     signing or verifying with PSA_ALG_RSA_PSS (The PSA Crypto API mandates
+     that PSA_ALG_RSA_PSS uses the same hash throughout the algorithm.)
+   * Fix a null pointer dereference when mbedtls_mpi_exp_mod() was called with
+     A=0 represented with 0 limbs. Up to and including Mbed TLS 2.26, this bug
+     could not be triggered by code that constructed A with one of the
+     mbedtls_mpi_read_xxx functions (including in particular TLS code) since
+     those always built an mpi object with at least one limb.
+     Credit to OSS-Fuzz. Fixes #4641.
+   * Fix mbedtls_mpi_gcd(G,A,B) when the value of B is zero. This had no
+     effect on Mbed TLS's internal use of mbedtls_mpi_gcd(), but may affect
+     applications that call mbedtls_mpi_gcd() directly. Fixes #4642.
+   * The PSA API no longer allows the creation or destruction of keys with a
+     read-only lifetime. The persistence level PSA_KEY_PERSISTENCE_READ_ONLY
+     can now only be used as intended, for keys that cannot be modified through
+     normal use of the API.
+   * When MBEDTLS_PSA_CRYPTO_SPM is enabled, crypto_spe.h was not included
+     in all the right places. Include it from crypto_platform.h, which is
+     the natural place. Fixes #4649.
+   * mbedtls_pk_sign() and mbedtls_pk_verify() and their extended and
+     restartable variants now always honor the specified hash length if
+     nonzero. Before, for RSA, hash_len was ignored in favor of the length of
+     the specified hash algorithm.
+   * Fix which alert is sent in some cases to conform to the
+     applicable RFC: on an invalid Finished message value, an
+     invalid max_fragment_length extension, or an
+     unsupported extension used by the server.
+   * Correct (change from 12 to 13 bytes) the value of the macro describing the
+     maximum nonce length returned by psa_aead_generate_nonce().
+
+Changes
+   * Add extra printf compiler warning flags to builds.
+   * Fix memsan build false positive in x509_crt.c with Clang 11
+   * Fix the setting of the read timeout in the DTLS sample programs.
+   * Remove the AES sample application programs/aes/aescrypt2 which shows
+     bad cryptographic practice. Fix #1906.
+   * Alternative implementations of CMAC may now opt to not support 3DES as a
+     CMAC block cipher, and still pass the CMAC self test.
+   * Remove configs/config-psa-crypto.h, which was identical to the default
+     configuration except for having some extra cryptographic mechanisms
+     enabled and for unintended differences. This configuration was primarily
+     intended to demonstrate the PSA API, and lost most of its usefulness when
+     MBEDTLS_PSA_CRYPTO_C became enabled by default.
+   * When building the test suites with GNU make, invoke python3 or python, not
+     python2, which is no longer supported upstream.
+   * When using session cache based session resumption on the server,
+     double-check that custom session cache implementations return
+     sessions which are consistent with the negotiated ciphersuite
+     and compression method.
+   * Fix build failure on MinGW toolchain when __USE_MING_ANSI_STDIO is on.
+     When that flag is on, standard GNU C printf format specifiers
+     should be used.
+   * Reduce the default value of MBEDTLS_ECP_WINDOW_SIZE. This reduces RAM usage
+     during ECC operations at a negligible performance cost.
+   * mbedtls_mpi_read_binary(), mbedtls_mpi_read_binary_le() and
+     mbedtls_mpi_read_string() now construct an mbedtls_mpi object with 0 limbs
+     when their input has length 0. Note that this is an implementation detail
+     and can change at any time, so this change should be transparent, but it
+     may result in mbedtls_mpi_write_binary() or mbedtls_mpi_write_string()
+     now writing an empty string where it previously wrote one or more
+     zero digits when operating from values constructed with an mpi_read
+     function and some mpi operations.
+   * Implicitly add PSA_KEY_USAGE_SIGN_MESSAGE key usage policy flag when
+     PSA_KEY_USAGE_SIGN_HASH flag is set and PSA_KEY_USAGE_VERIFY_MESSAGE flag
+     when PSA_KEY_USAGE_VERIFY_HASH flag is set. This usage flag extension
+     is also applied when loading a key from storage.
+
+= mbed TLS 2.26.0 branch released 2021-03-08
+
+API changes
+   * Renamed the PSA Crypto API output buffer size macros to bring them in line
+     with version 1.0.0 of the specification.
+   * The API glue function mbedtls_ecc_group_of_psa() now takes the curve size
+     in bits rather than bytes, with an additional flag to indicate if the
+     size may have been rounded up to a whole number of bytes.
+   * Renamed the PSA Crypto API AEAD tag length macros to bring them in line
+     with version 1.0.0 of the specification.
+
+Default behavior changes
+   * In mbedtls_rsa_context objects, the ver field was formerly documented
+     as always 0. It is now reserved for internal purposes and may take
+     different values.
+
+New deprecations
+   * PSA_KEY_EXPORT_MAX_SIZE, PSA_HASH_SIZE, PSA_MAC_FINAL_SIZE,
+     PSA_BLOCK_CIPHER_BLOCK_SIZE, PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE and
+     PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN have been renamed, and the old names
+     deprecated.
+   * PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH and PSA_ALG_AEAD_WITH_TAG_LENGTH
+     have been renamed, and the old names deprecated.
+
+Features
+   * The PSA crypto subsystem can now use HMAC_DRBG instead of CTR_DRBG.
+     CTR_DRBG is used by default if it is available, but you can override
+     this choice by setting MBEDTLS_PSA_HMAC_DRBG_MD_TYPE at compile time.
+     Fix #3354.
+   * Automatic fallback to a software implementation of ECP when
+     MBEDTLS_ECP_xxx_ALT accelerator hooks are in use can now be turned off
+     through setting the new configuration flag MBEDTLS_ECP_NO_FALLBACK.
+   * The PSA crypto subsystem can now be configured to use less static RAM by
+     tweaking the setting for the maximum amount of keys simultaneously in RAM.
+     MBEDTLS_PSA_KEY_SLOT_COUNT sets the maximum number of volatile keys that
+     can exist simultaneously. It has a sensible default if not overridden.
+   * Partial implementation of the PSA crypto driver interface: Mbed TLS can
+     now use an external random generator instead of the library's own
+     entropy collection and DRBG code. Enable MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+     and see the documentation of mbedtls_psa_external_get_random() for details.
+   * Applications using both mbedtls_xxx and psa_xxx functions (for example,
+     applications using TLS and MBEDTLS_USE_PSA_CRYPTO) can now use the PSA
+     random generator with mbedtls_xxx functions. See the documentation of
+     mbedtls_psa_get_random() for details.
+   * In the PSA API, the policy for a MAC or AEAD algorithm can specify a
+     minimum MAC or tag length thanks to the new wildcards
+     PSA_ALG_AT_LEAST_THIS_LENGTH_MAC and
+     PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG.
+
+Security
+   * Fix a security reduction in CTR_DRBG when the initial seeding obtained a
+     nonce from entropy. Applications were affected if they called
+     mbedtls_ctr_drbg_set_nonce_len(), if they called
+     mbedtls_ctr_drbg_set_entropy_len() with a size that was 3/2 times the key
+     length, or when the entropy module uses SHA-256 and CTR_DRBG uses AES-256.
+     In such cases, a random nonce was necessary to achieve the advertised
+     security strength, but the code incorrectly used a constant instead of
+     entropy from the nonce.
+     Found by John Stroebel in #3819 and fixed in #3973.
+   * Fix a buffer overflow in mbedtls_mpi_sub_abs() when calculating
+     |A| - |B| where |B| is larger than |A| and has more limbs (so the
+     function should return MBEDTLS_ERR_MPI_NEGATIVE_VALUE). Only
+     applications calling mbedtls_mpi_sub_abs() directly are affected:
+     all calls inside the library were safe since this function is
+     only called with |A| >= |B|. Reported by Guido Vranken in #4042.
+   * Fix an errorneous estimation for an internal buffer in
+     mbedtls_pk_write_key_pem(). If MBEDTLS_MPI_MAX_SIZE is set to an odd
+     value the function might fail to write a private RSA keys of the largest
+     supported size.
+     Found by Daniel Otte, reported in #4093 and fixed in #4094.
+   * Fix a stack buffer overflow with mbedtls_net_poll() and
+     mbedtls_net_recv_timeout() when given a file descriptor that is
+     beyond FD_SETSIZE. Reported by FigBug in #4169.
+   * Guard against strong local side channel attack against base64 tables by
+     making access aceess to them use constant flow code.
+
+Bugfix
+   * Fix use-after-scope error in programs/ssl/ssl_client2.c and ssl_server2.c
+   * Fix memory leak that occured when calling psa_close_key() on a
+     wrapped key with MBEDTLS_PSA_CRYPTO_SE_C defined.
+   * Fix an incorrect error code if an RSA private operation glitched.
+   * Fix a memory leak in an error case in psa_generate_derived_key_internal().
+   * Fix a resource leak in CTR_DRBG and HMAC_DRBG when MBEDTLS_THREADING_C
+     is enabled, on platforms where initializing a mutex allocates resources.
+     This was a regression introduced in the previous release. Reported in
+     #4017, #4045 and #4071.
+   * Ensure that calling mbedtls_rsa_free() or mbedtls_entropy_free()
+     twice is safe. This happens for RSA when some Mbed TLS library functions
+     fail. Such a double-free was not safe when MBEDTLS_THREADING_C was
+     enabled on platforms where freeing a mutex twice is not safe.
+   * Fix a resource leak in a bad-arguments case of mbedtls_rsa_gen_key()
+     when MBEDTLS_THREADING_C is enabled on platforms where initializing
+     a mutex allocates resources.
+   * Fixes a bug where, if the library was configured to include support for
+     both the old SE interface and the new PSA driver interface, external keys were
+     not loaded from storage. This was fixed by #3996.
+   * This change makes 'mbedtls_x509write_crt_set_basic_constraints'
+     consistent with RFC 5280 4.2.1.9 which says: "Conforming CAs MUST
+     include this extension in all CA certificates that contain public keys
+     used to validate digital signatures on certificates and MUST mark the
+     extension as critical in such certificates." Previous to this change,
+     the extension was always marked as non-critical. This was fixed by
+     #3698.
+
+Changes
+   * A new library C file psa_crypto_client.c has been created to contain
+     the PSA code needed by a PSA crypto client when the PSA crypto
+     implementation is not included into the library.
+   * On recent enough versions of FreeBSD and DragonFlyBSD, the entropy module
+     now uses the getrandom syscall instead of reading from /dev/urandom.
+
 = mbed TLS 2.25.0 branch released 2020-12-11
 
 API changes
@@ -20,7 +452,7 @@
      warning on CMake 3.19.0. #3801
 
 New deprecations
-   * PSA_KEY_TYPE_CHACHA20 and PSA_KEY_TYPE_ARC4 have been deprecated.
+   * PSA_ALG_CHACHA20 and PSA_ALG_ARC4 have been deprecated.
      Use PSA_ALG_STREAM_CIPHER instead.
    * The functions mbedtls_cipher_auth_encrypt() and
      mbedtls_cipher_auth_decrypt() are deprecated in favour of the new
@@ -91,7 +523,7 @@
      Johan Malmgren and Johan Uppman Bruce from Sectra.
 
 Bugfix
-   * Fix an invalid (but nonzero) return code from mbedtls_pk_parse_subpubkey()
+   * Fix an invalid (but non-zero) return code from mbedtls_pk_parse_subpubkey()
      when the input has trailing garbage. Fixes #2512.
    * Fix build failure in configurations where MBEDTLS_USE_PSA_CRYPTO is
      enabled but ECDSA is disabled. Contributed by jdurkop. Fixes #3294.
diff --git a/third_party/mbedtls/repo/Makefile b/third_party/mbedtls/repo/Makefile
index 9344e71..6a8b230 100644
--- a/third_party/mbedtls/repo/Makefile
+++ b/third_party/mbedtls/repo/Makefile
@@ -138,11 +138,11 @@
 	tests/suites/*.function \
 )
 # Exuberant-ctags invocation. Other ctags implementations may require different options.
-CTAGS = ctags --langmap=c:+.h.function -o
+CTAGS = ctags --langmap=c:+.h.function --line-directives=no -o
 tags: $(C_SOURCE_FILES)
 	$(CTAGS) $@ $(C_SOURCE_FILES)
 TAGS: $(C_SOURCE_FILES)
-	etags -o $@ $(C_SOURCE_FILES)
+	etags --no-line-directive -o $@ $(C_SOURCE_FILES)
 global: GPATH GRTAGS GSYMS GTAGS
 GPATH GRTAGS GSYMS GTAGS: $(C_SOURCE_FILES)
 	ls $(C_SOURCE_FILES) | gtags -f - --gtagsconf .globalrc
diff --git a/third_party/mbedtls/repo/README.md b/third_party/mbedtls/repo/README.md
index ac2a6ab..eb3829c 100644
--- a/third_party/mbedtls/repo/README.md
+++ b/third_party/mbedtls/repo/README.md
@@ -25,6 +25,8 @@
 1. Run `make apidoc`.
 1. Browse `apidoc/index.html` or `apidoc/modules.html`.
 
+For other sources of documentation, see the [SUPPORT](SUPPORT.md) document.
+
 Compiling
 ---------
 
@@ -36,7 +38,7 @@
 
 The main systems used for development are CMake and GNU Make. Those systems are always complete and up-to-date. The others should reflect all changes present in the CMake and Make build system, although features may not be ported there automatically.
 
-The Make and CMake build systems create three libraries: libmbedcrypto, libmbedx509, and libmbedtls. Note that libmbedtls depends on libmbedx509 and libmbedcrypto, and libmbedx509 depends on libmbedcrypto. As a result, some linkers will expect flags to be in a specific order, for example the GNU linker wants `-lmbedtls -lmbedx509 -lmbedcrypto`. Also, when loading shared libraries using dlopen(), you'll need to load libmbedcrypto first, then libmbedx509, before you can load libmbedtls.
+The Make and CMake build systems create three libraries: libmbedcrypto, libmbedx509, and libmbedtls. Note that libmbedtls depends on libmbedx509 and libmbedcrypto, and libmbedx509 depends on libmbedcrypto. As a result, some linkers will expect flags to be in a specific order, for example the GNU linker wants `-lmbedtls -lmbedx509 -lmbedcrypto`.
 
 ### Tool versions
 
@@ -195,6 +197,14 @@
 -   [What external dependencies does Mbed TLS rely on?](https://tls.mbed.org/kb/development/what-external-dependencies-does-mbedtls-rely-on)
 -   [How do I configure Mbed TLS](https://tls.mbed.org/kb/compiling-and-building/how-do-i-configure-mbedtls)
 
+Mbed TLS is mostly written in portable C99; however, it has a few platform requirements that go beyond the standard, but are met by most modern architectures:
+
+- Bytes must be 8 bits.
+- All-bits-zero must be a valid representation of a null pointer.
+- Signed integers must be represented using two's complement.
+- `int` and `size_t` must be at least 32 bits wide.
+- The types `uint8_t`, `uint16_t`, `uint32_t` and their signed equivalents must be available.
+
 PSA cryptography API
 --------------------
 
@@ -245,3 +255,10 @@
 ------------
 
 We gratefully accept bug reports and contributions from the community. Please see the [contributing guidelines](CONTRIBUTING.md) for details on how to do this.
+
+Contact
+-------
+
+* To report a security vulnerability in Mbed TLS, please email <mbed-tls-security@lists.trustedfirmware.org>. For more information, see [`SECURITY.md`](SECURITY.md).
+* To report a bug or request a feature in Mbed TLS, please [file an issue on GitHub](https://github.com/ARMmbed/mbedtls/issues/new/choose).
+* Please see [`SUPPORT.md`](SUPPORT.md) for other channels for discussion and support about Mbed TLS.
diff --git a/third_party/mbedtls/repo/SECURITY.md b/third_party/mbedtls/repo/SECURITY.md
new file mode 100644
index 0000000..bd18f6c
--- /dev/null
+++ b/third_party/mbedtls/repo/SECURITY.md
@@ -0,0 +1,20 @@
+## Reporting Vulneratibilities
+
+If you think you have found an Mbed TLS security vulnerability, then please
+send an email to the security team at
+<mbed-tls-security@lists.trustedfirmware.org>.
+
+## Security Incident Handling Process
+
+Our security process is detailled in our
+[security
+center](https://developer.trustedfirmware.org/w/mbed-tls/security-center/).
+
+Its primary goal is to ensure fixes are ready to be deployed when the issue
+goes public.
+
+## Maintained branches
+
+Only the maintained branches, as listed in [`BRANCHES.md`](BRANCHES.md),
+get security fixes.
+Users are urged to always use the latest version of a maintained branch.
diff --git a/third_party/mbedtls/repo/SUPPORT.md b/third_party/mbedtls/repo/SUPPORT.md
new file mode 100644
index 0000000..1bc0695
--- /dev/null
+++ b/third_party/mbedtls/repo/SUPPORT.md
@@ -0,0 +1,15 @@
+## Documentation
+
+Here are some useful sources of information about using Mbed TLS:
+
+- API documentation, see the [Documentation section of the
+  README](README.md#License);
+- the `docs` directory in the source tree;
+- the [Mbed TLS knowledge Base](https://tls.mbed.org/kb);
+- the [Mbed TLS mailing-list
+  archives](https://lists.trustedfirmware.org/pipermail/mbed-tls/).
+
+## Asking Questions
+
+If you can't find your answer in the above sources, please use the [Mbed TLS
+mailing list](https://lists.trustedfirmware.org/mailman/listinfo/mbed-tls).
diff --git a/third_party/mbedtls/repo/configs/config-psa-crypto.h b/third_party/mbedtls/repo/configs/config-psa-crypto.h
deleted file mode 100644
index b98fc9c..0000000
--- a/third_party/mbedtls/repo/configs/config-psa-crypto.h
+++ /dev/null
@@ -1,3371 +0,0 @@
-/**
- * \file config.h
- *
- * \brief Configuration options (set of defines)
- *
- *  This set of compile-time options may be used to enable
- *  or disable features selectively, and reduce the global
- *  memory footprint.
- */
-/*
- *  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_CONFIG_H
-#define MBEDTLS_CONFIG_H
-
-#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
-#define _CRT_SECURE_NO_DEPRECATE 1
-#endif
-
-/**
- * \name SECTION: System support
- *
- * This section sets system specific settings.
- * \{
- */
-
-/**
- * \def MBEDTLS_HAVE_ASM
- *
- * The compiler has support for asm().
- *
- * Requires support for asm() in compiler.
- *
- * Used in:
- *      library/aria.c
- *      library/timing.c
- *      include/mbedtls/bn_mul.h
- *
- * Required by:
- *      MBEDTLS_AESNI_C
- *      MBEDTLS_PADLOCK_C
- *
- * Comment to disable the use of assembly code.
- */
-#define MBEDTLS_HAVE_ASM
-
-/**
- * \def MBEDTLS_NO_UDBL_DIVISION
- *
- * The platform lacks support for double-width integer division (64-bit
- * division on a 32-bit platform, 128-bit division on a 64-bit platform).
- *
- * Used in:
- *      include/mbedtls/bignum.h
- *      library/bignum.c
- *
- * The bignum code uses double-width division to speed up some operations.
- * Double-width division is often implemented in software that needs to
- * be linked with the program. The presence of a double-width integer
- * type is usually detected automatically through preprocessor macros,
- * but the automatic detection cannot know whether the code needs to
- * and can be linked with an implementation of division for that type.
- * By default division is assumed to be usable if the type is present.
- * Uncomment this option to prevent the use of double-width division.
- *
- * Note that division for the native integer type is always required.
- * Furthermore, a 64-bit type is always required even on a 32-bit
- * platform, but it need not support multiplication or division. In some
- * cases it is also desirable to disable some double-width operations. For
- * example, if double-width division is implemented in software, disabling
- * it can reduce code size in some embedded targets.
- */
-//#define MBEDTLS_NO_UDBL_DIVISION
-
-/**
- * \def MBEDTLS_NO_64BIT_MULTIPLICATION
- *
- * The platform lacks support for 32x32 -> 64-bit multiplication.
- *
- * Used in:
- *      library/poly1305.c
- *
- * Some parts of the library may use multiplication of two unsigned 32-bit
- * operands with a 64-bit result in order to speed up computations. On some
- * platforms, this is not available in hardware and has to be implemented in
- * software, usually in a library provided by the toolchain.
- *
- * Sometimes it is not desirable to have to link to that library. This option
- * removes the dependency of that library on platforms that lack a hardware
- * 64-bit multiplier by embedding a software implementation in Mbed TLS.
- *
- * Note that depending on the compiler, this may decrease performance compared
- * to using the library function provided by the toolchain.
- */
-//#define MBEDTLS_NO_64BIT_MULTIPLICATION
-
-/**
- * \def MBEDTLS_HAVE_SSE2
- *
- * CPU supports SSE2 instruction set.
- *
- * Uncomment if the CPU supports SSE2 (IA-32 specific).
- */
-//#define MBEDTLS_HAVE_SSE2
-
-/**
- * \def MBEDTLS_HAVE_TIME
- *
- * System has time.h and time().
- * The time does not need to be correct, only time differences are used,
- * by contrast with MBEDTLS_HAVE_TIME_DATE
- *
- * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT,
- * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and
- * MBEDTLS_PLATFORM_STD_TIME.
- *
- * Comment if your system does not support time functions
- */
-#define MBEDTLS_HAVE_TIME
-
-/**
- * \def MBEDTLS_HAVE_TIME_DATE
- *
- * System has time.h, time(), and an implementation for
- * mbedtls_platform_gmtime_r() (see below).
- * The time needs to be correct (not necessarily very accurate, but at least
- * the date should be correct). This is used to verify the validity period of
- * X.509 certificates.
- *
- * Comment if your system does not have a correct clock.
- *
- * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that
- * behaves similarly to the gmtime_r() function from the C standard. Refer to
- * the documentation for mbedtls_platform_gmtime_r() for more information.
- *
- * \note It is possible to configure an implementation for
- * mbedtls_platform_gmtime_r() at compile-time by using the macro
- * MBEDTLS_PLATFORM_GMTIME_R_ALT.
- */
-#define MBEDTLS_HAVE_TIME_DATE
-
-/**
- * \def MBEDTLS_PLATFORM_MEMORY
- *
- * Enable the memory allocation layer.
- *
- * By default mbed TLS uses the system-provided calloc() and free().
- * This allows different allocators (self-implemented or provided) to be
- * provided to the platform abstraction layer.
- *
- * Enabling MBEDTLS_PLATFORM_MEMORY without the
- * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide
- * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and
- * free() function pointer at runtime.
- *
- * Enabling MBEDTLS_PLATFORM_MEMORY and specifying
- * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the
- * alternate function at compile time.
- *
- * Requires: MBEDTLS_PLATFORM_C
- *
- * Enable this layer to allow use of alternative memory allocators.
- */
-//#define MBEDTLS_PLATFORM_MEMORY
-
-/**
- * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
- *
- * Do not assign standard functions in the platform layer (e.g. calloc() to
- * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF)
- *
- * This makes sure there are no linking errors on platforms that do not support
- * these functions. You will HAVE to provide alternatives, either at runtime
- * via the platform_set_xxx() functions or at compile time by setting
- * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a
- * MBEDTLS_PLATFORM_XXX_MACRO.
- *
- * Requires: MBEDTLS_PLATFORM_C
- *
- * Uncomment to prevent default assignment of standard functions in the
- * platform layer.
- */
-//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
-
-/**
- * \def MBEDTLS_PLATFORM_EXIT_ALT
- *
- * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the
- * function in the platform abstraction layer.
- *
- * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will
- * provide a function "mbedtls_platform_set_printf()" that allows you to set an
- * alternative printf function pointer.
- *
- * All these define require MBEDTLS_PLATFORM_C to be defined!
- *
- * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows;
- * it will be enabled automatically by check_config.h
- *
- * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as
- * MBEDTLS_PLATFORM_XXX_MACRO!
- *
- * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME
- *
- * Uncomment a macro to enable alternate implementation of specific base
- * platform function
- */
-//#define MBEDTLS_PLATFORM_EXIT_ALT
-//#define MBEDTLS_PLATFORM_TIME_ALT
-//#define MBEDTLS_PLATFORM_FPRINTF_ALT
-//#define MBEDTLS_PLATFORM_PRINTF_ALT
-//#define MBEDTLS_PLATFORM_SNPRINTF_ALT
-//#define MBEDTLS_PLATFORM_VSNPRINTF_ALT
-//#define MBEDTLS_PLATFORM_NV_SEED_ALT
-//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT
-
-/**
- * \def MBEDTLS_DEPRECATED_WARNING
- *
- * Mark deprecated functions so that they generate a warning if used.
- * Functions deprecated in one version will usually be removed in the next
- * version. You can enable this to help you prepare the transition to a new
- * major version by making sure your code is not using these functions.
- *
- * This only works with GCC and Clang. With other compilers, you may want to
- * use MBEDTLS_DEPRECATED_REMOVED
- *
- * Uncomment to get warnings on using deprecated functions.
- */
-//#define MBEDTLS_DEPRECATED_WARNING
-
-/**
- * \def MBEDTLS_DEPRECATED_REMOVED
- *
- * Remove deprecated functions so that they generate an error if used.
- * Functions deprecated in one version will usually be removed in the next
- * version. You can enable this to help you prepare the transition to a new
- * major version by making sure your code is not using these functions.
- *
- * Uncomment to get errors on using deprecated functions.
- */
-//#define MBEDTLS_DEPRECATED_REMOVED
-
-/**
- * \def MBEDTLS_CHECK_PARAMS
- *
- * This configuration option controls whether the library validates more of
- * the parameters passed to it.
- *
- * When this flag is not defined, the library only attempts to validate an
- * input parameter if: (1) they may come from the outside world (such as the
- * network, the filesystem, etc.) or (2) not validating them could result in
- * internal memory errors such as overflowing a buffer controlled by the
- * library. On the other hand, it doesn't attempt to validate parameters whose
- * values are fully controlled by the application (such as pointers).
- *
- * When this flag is defined, the library additionally attempts to validate
- * parameters that are fully controlled by the application, and should always
- * be valid if the application code is fully correct and trusted.
- *
- * For example, when a function accepts as input a pointer to a buffer that may
- * contain untrusted data, and its documentation mentions that this pointer
- * must not be NULL:
- * - the pointer is checked to be non-NULL only if this option is enabled
- * - the content of the buffer is always validated
- *
- * When this flag is defined, if a library function receives a parameter that
- * is invalid, it will:
- * - invoke the macro MBEDTLS_PARAM_FAILED() which by default expands to a
- *   call to the function mbedtls_param_failed()
- * - immediately return (with a specific error code unless the function
- *   returns void and can't communicate an error).
- *
- * When defining this flag, you also need to:
- * - either provide a definition of the function mbedtls_param_failed() in
- *   your application (see platform_util.h for its prototype) as the library
- *   calls that function, but does not provide a default definition for it,
- * - or provide a different definition of the macro MBEDTLS_PARAM_FAILED()
- *   below if the above mechanism is not flexible enough to suit your needs.
- *   See the documentation of this macro later in this file.
- *
- * Uncomment to enable validation of application-controlled parameters.
- */
-//#define MBEDTLS_CHECK_PARAMS
-
-/* \} name SECTION: System support */
-
-/**
- * \name SECTION: mbed TLS feature support
- *
- * This section sets support for features that are or are not needed
- * within the modules that are enabled.
- * \{
- */
-
-/**
- * \def MBEDTLS_TIMING_ALT
- *
- * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(),
- * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay()
- *
- * Only works if you have MBEDTLS_TIMING_C enabled.
- *
- * You will need to provide a header "timing_alt.h" and an implementation at
- * compile time.
- */
-//#define MBEDTLS_TIMING_ALT
-
-/**
- * \def MBEDTLS_AES_ALT
- *
- * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your
- * alternate core implementation of a symmetric crypto, an arithmetic or hash
- * module (e.g. platform specific assembly optimized implementations). Keep
- * in mind that the function prototypes should remain the same.
- *
- * This replaces the whole module. If you only want to replace one of the
- * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags.
- *
- * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer
- * provide the "struct mbedtls_aes_context" definition and omit the base
- * function declarations and implementations. "aes_alt.h" will be included from
- * "aes.h" to include the new function definitions.
- *
- * Uncomment a macro to enable alternate implementation of the corresponding
- * module.
- *
- * \warning   MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their
- *            use constitutes a security risk. If possible, we recommend
- *            avoiding dependencies on them, and considering stronger message
- *            digests and ciphers instead.
- *
- */
-//#define MBEDTLS_AES_ALT
-//#define MBEDTLS_ARC4_ALT
-//#define MBEDTLS_ARIA_ALT
-//#define MBEDTLS_BLOWFISH_ALT
-//#define MBEDTLS_CAMELLIA_ALT
-//#define MBEDTLS_CCM_ALT
-//#define MBEDTLS_CHACHA20_ALT
-//#define MBEDTLS_CHACHAPOLY_ALT
-//#define MBEDTLS_CMAC_ALT
-//#define MBEDTLS_DES_ALT
-//#define MBEDTLS_DHM_ALT
-//#define MBEDTLS_ECJPAKE_ALT
-//#define MBEDTLS_GCM_ALT
-//#define MBEDTLS_NIST_KW_ALT
-//#define MBEDTLS_MD2_ALT
-//#define MBEDTLS_MD4_ALT
-//#define MBEDTLS_MD5_ALT
-//#define MBEDTLS_POLY1305_ALT
-//#define MBEDTLS_RIPEMD160_ALT
-//#define MBEDTLS_RSA_ALT
-//#define MBEDTLS_SHA1_ALT
-//#define MBEDTLS_SHA256_ALT
-//#define MBEDTLS_SHA512_ALT
-//#define MBEDTLS_XTEA_ALT
-
-/*
- * When replacing the elliptic curve module, pleace consider, that it is
- * implemented with two .c files:
- *      - ecp.c
- *      - ecp_curves.c
- * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT
- * macros as described above. The only difference is that you have to make sure
- * that you provide functionality for both .c files.
- */
-//#define MBEDTLS_ECP_ALT
-
-/**
- * \def MBEDTLS_MD2_PROCESS_ALT
- *
- * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you
- * alternate core implementation of symmetric crypto or hash function. Keep in
- * mind that function prototypes should remain the same.
- *
- * This replaces only one function. The header file from mbed TLS is still
- * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags.
- *
- * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will
- * no longer provide the mbedtls_sha1_process() function, but it will still provide
- * the other function (using your mbedtls_sha1_process() function) and the definition
- * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible
- * with this definition.
- *
- * \note Because of a signature change, the core AES encryption and decryption routines are
- *       currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt,
- *       respectively. When setting up alternative implementations, these functions should
- *       be overridden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt
- *       must stay untouched.
- *
- * \note If you use the AES_xxx_ALT macros, then is is recommended to also set
- *       MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES
- *       tables.
- *
- * Uncomment a macro to enable alternate implementation of the corresponding
- * function.
- *
- * \warning   MD2, MD4, MD5, DES and SHA-1 are considered weak and their use
- *            constitutes a security risk. If possible, we recommend avoiding
- *            dependencies on them, and considering stronger message digests
- *            and ciphers instead.
- *
- */
-//#define MBEDTLS_MD2_PROCESS_ALT
-//#define MBEDTLS_MD4_PROCESS_ALT
-//#define MBEDTLS_MD5_PROCESS_ALT
-//#define MBEDTLS_RIPEMD160_PROCESS_ALT
-//#define MBEDTLS_SHA1_PROCESS_ALT
-//#define MBEDTLS_SHA256_PROCESS_ALT
-//#define MBEDTLS_SHA512_PROCESS_ALT
-//#define MBEDTLS_DES_SETKEY_ALT
-//#define MBEDTLS_DES_CRYPT_ECB_ALT
-//#define MBEDTLS_DES3_CRYPT_ECB_ALT
-//#define MBEDTLS_AES_SETKEY_ENC_ALT
-//#define MBEDTLS_AES_SETKEY_DEC_ALT
-//#define MBEDTLS_AES_ENCRYPT_ALT
-//#define MBEDTLS_AES_DECRYPT_ALT
-//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT
-//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT
-//#define MBEDTLS_ECDSA_VERIFY_ALT
-//#define MBEDTLS_ECDSA_SIGN_ALT
-//#define MBEDTLS_ECDSA_GENKEY_ALT
-
-/**
- * \def MBEDTLS_ECP_INTERNAL_ALT
- *
- * Expose a part of the internal interface of the Elliptic Curve Point module.
- *
- * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your
- * alternative core implementation of elliptic curve arithmetic. Keep in mind
- * that function prototypes should remain the same.
- *
- * This partially replaces one function. The header file from mbed TLS is still
- * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation
- * is still present and it is used for group structures not supported by the
- * alternative.
- *
- * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT
- * and implementing the following functions:
- *      unsigned char mbedtls_internal_ecp_grp_capable(
- *          const mbedtls_ecp_group *grp )
- *      int  mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp )
- *      void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp )
- * The mbedtls_internal_ecp_grp_capable function should return 1 if the
- * replacement functions implement arithmetic for the given group and 0
- * otherwise.
- * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are
- * called before and after each point operation and provide an opportunity to
- * implement optimized set up and tear down instructions.
- *
- * Example: In case you uncomment MBEDTLS_ECP_INTERNAL_ALT and
- * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac
- * function, but will use your mbedtls_internal_ecp_double_jac if the group is
- * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when
- * receives it as an argument). If the group is not supported then the original
- * implementation is used. The other functions and the definition of
- * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your
- * implementation of mbedtls_internal_ecp_double_jac and
- * mbedtls_internal_ecp_grp_capable must be compatible with this definition.
- *
- * Uncomment a macro to enable alternate implementation of the corresponding
- * function.
- */
-/* Required for all the functions in this section */
-//#define MBEDTLS_ECP_INTERNAL_ALT
-/* Support for Weierstrass curves with Jacobi representation */
-//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT
-//#define MBEDTLS_ECP_ADD_MIXED_ALT
-//#define MBEDTLS_ECP_DOUBLE_JAC_ALT
-//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT
-//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT
-/* Support for curves with Montgomery arithmetic */
-//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT
-//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT
-//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT
-
-/**
- * \def MBEDTLS_TEST_NULL_ENTROPY
- *
- * Enables testing and use of mbed TLS without any configured entropy sources.
- * This permits use of the library on platforms before an entropy source has
- * been integrated (see for example the MBEDTLS_ENTROPY_HARDWARE_ALT or the
- * MBEDTLS_ENTROPY_NV_SEED switches).
- *
- * WARNING! This switch MUST be disabled in production builds, and is suitable
- * only for development.
- * Enabling the switch negates any security provided by the library.
- *
- * Requires MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
- *
- */
-//#define MBEDTLS_TEST_NULL_ENTROPY
-
-/**
- * \def MBEDTLS_ENTROPY_HARDWARE_ALT
- *
- * Uncomment this macro to let mbed TLS use your own implementation of a
- * hardware entropy collector.
- *
- * Your function must be called \c mbedtls_hardware_poll(), have the same
- * prototype as declared in entropy_poll.h, and accept NULL as first argument.
- *
- * Uncomment to use your own hardware entropy collector.
- */
-//#define MBEDTLS_ENTROPY_HARDWARE_ALT
-
-/**
- * \def MBEDTLS_AES_ROM_TABLES
- *
- * Use precomputed AES tables stored in ROM.
- *
- * Uncomment this macro to use precomputed AES tables stored in ROM.
- * Comment this macro to generate AES tables in RAM at runtime.
- *
- * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb
- * (or ~2kb if \c MBEDTLS_AES_FEWER_TABLES is used) and reduces the
- * initialization time before the first AES operation can be performed.
- * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c
- * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded
- * performance if ROM access is slower than RAM access.
- *
- * This option is independent of \c MBEDTLS_AES_FEWER_TABLES.
- *
- */
-//#define MBEDTLS_AES_ROM_TABLES
-
-/**
- * \def MBEDTLS_AES_FEWER_TABLES
- *
- * Use less ROM/RAM for AES tables.
- *
- * Uncommenting this macro omits 75% of the AES tables from
- * ROM / RAM (depending on the value of \c MBEDTLS_AES_ROM_TABLES)
- * by computing their values on the fly during operations
- * (the tables are entry-wise rotations of one another).
- *
- * Tradeoff: Uncommenting this reduces the RAM / ROM footprint
- * by ~6kb but at the cost of more arithmetic operations during
- * runtime. Specifically, one has to compare 4 accesses within
- * different tables to 4 accesses with additional arithmetic
- * operations within the same table. The performance gain/loss
- * depends on the system and memory details.
- *
- * This option is independent of \c MBEDTLS_AES_ROM_TABLES.
- *
- */
-//#define MBEDTLS_AES_FEWER_TABLES
-
-/**
- * \def MBEDTLS_CAMELLIA_SMALL_MEMORY
- *
- * Use less ROM for the Camellia implementation (saves about 768 bytes).
- *
- * Uncomment this macro to use less memory for Camellia.
- */
-//#define MBEDTLS_CAMELLIA_SMALL_MEMORY
-
-/**
- * \def MBEDTLS_CIPHER_MODE_CBC
- *
- * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers.
- */
-#define MBEDTLS_CIPHER_MODE_CBC
-
-/**
- * \def MBEDTLS_CIPHER_MODE_CFB
- *
- * Enable Cipher Feedback mode (CFB) for symmetric ciphers.
- */
-#define MBEDTLS_CIPHER_MODE_CFB
-
-/**
- * \def MBEDTLS_CIPHER_MODE_CTR
- *
- * Enable Counter Block Cipher mode (CTR) for symmetric ciphers.
- */
-#define MBEDTLS_CIPHER_MODE_CTR
-
-/**
- * \def MBEDTLS_CIPHER_MODE_OFB
- *
- * Enable Output Feedback mode (OFB) for symmetric ciphers.
- */
-#define MBEDTLS_CIPHER_MODE_OFB
-
-/**
- * \def MBEDTLS_CIPHER_MODE_XTS
- *
- * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES.
- */
-#define MBEDTLS_CIPHER_MODE_XTS
-
-/**
- * \def MBEDTLS_CIPHER_NULL_CIPHER
- *
- * Enable NULL cipher.
- * Warning: Only do so when you know what you are doing. This allows for
- * encryption or channels without any security!
- *
- * Requires MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable
- * the following ciphersuites:
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA
- *      MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA
- *      MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384
- *      MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256
- *      MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA
- *      MBEDTLS_TLS_RSA_WITH_NULL_SHA256
- *      MBEDTLS_TLS_RSA_WITH_NULL_SHA
- *      MBEDTLS_TLS_RSA_WITH_NULL_MD5
- *      MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384
- *      MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256
- *      MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA
- *      MBEDTLS_TLS_PSK_WITH_NULL_SHA384
- *      MBEDTLS_TLS_PSK_WITH_NULL_SHA256
- *      MBEDTLS_TLS_PSK_WITH_NULL_SHA
- *
- * Uncomment this macro to enable the NULL cipher and ciphersuites
- */
-//#define MBEDTLS_CIPHER_NULL_CIPHER
-
-/**
- * \def MBEDTLS_CIPHER_PADDING_PKCS7
- *
- * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for
- * specific padding modes in the cipher layer with cipher modes that support
- * padding (e.g. CBC)
- *
- * If you disable all padding modes, only full blocks can be used with CBC.
- *
- * Enable padding modes in the cipher layer.
- */
-#define MBEDTLS_CIPHER_PADDING_PKCS7
-#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS
-#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
-#define MBEDTLS_CIPHER_PADDING_ZEROS
-
-/**
- * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES
- *
- * Enable weak ciphersuites in SSL / TLS.
- * Warning: Only do so when you know what you are doing. This allows for
- * channels with virtually no security at all!
- *
- * This enables the following ciphersuites:
- *      MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA
- *      MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA
- *
- * Uncomment this macro to enable weak ciphersuites
- *
- * \warning   DES is considered a weak cipher and its use constitutes a
- *            security risk. We recommend considering stronger ciphers instead.
- */
-//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES
-
-/**
- * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES
- *
- * Remove RC4 ciphersuites by default in SSL / TLS.
- * This flag removes the ciphersuites based on RC4 from the default list as
- * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to
- * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them
- * explicitly.
- *
- * Uncomment this macro to remove RC4 ciphersuites by default.
- */
-#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES
-
-/**
- * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED
- *
- * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve
- * module.  By default all supported curves are enabled.
- *
- * Comment macros to disable the curve and functions for it
- */
-#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
-#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
-#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
-#define MBEDTLS_ECP_DP_BP256R1_ENABLED
-#define MBEDTLS_ECP_DP_BP384R1_ENABLED
-#define MBEDTLS_ECP_DP_BP512R1_ENABLED
-#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
-#define MBEDTLS_ECP_DP_CURVE448_ENABLED
-
-/**
- * \def MBEDTLS_ECP_NIST_OPTIM
- *
- * Enable specific 'modulo p' routines for each NIST prime.
- * Depending on the prime and architecture, makes operations 4 to 8 times
- * faster on the corresponding curve.
- *
- * Comment this macro to disable NIST curves optimisation.
- */
-#define MBEDTLS_ECP_NIST_OPTIM
-
-/**
- * \def MBEDTLS_ECP_RESTARTABLE
- *
- * Enable "non-blocking" ECC operations that can return early and be resumed.
- *
- * This allows various functions to pause by returning
- * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module,
- * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in
- * order to further progress and eventually complete their operation. This is
- * controlled through mbedtls_ecp_set_max_ops() which limits the maximum
- * number of ECC operations a function may perform before pausing; see
- * mbedtls_ecp_set_max_ops() for more information.
- *
- * This is useful in non-threaded environments if you want to avoid blocking
- * for too long on ECC (and, hence, X.509 or SSL/TLS) operations.
- *
- * Uncomment this macro to enable restartable ECC computations.
- *
- * \note  This option only works with the default software implementation of
- *        elliptic curve functionality. It is incompatible with
- *        MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT and MBEDTLS_ECDSA_XXX_ALT.
- */
-//#define MBEDTLS_ECP_RESTARTABLE
-
-/**
- * \def MBEDTLS_ECDSA_DETERMINISTIC
- *
- * Enable deterministic ECDSA (RFC 6979).
- * Standard ECDSA is "fragile" in the sense that lack of entropy when signing
- * may result in a compromise of the long-term signing key. This is avoided by
- * the deterministic variant.
- *
- * Requires: MBEDTLS_HMAC_DRBG_C
- *
- * Comment this macro to disable deterministic ECDSA.
- */
-#define MBEDTLS_ECDSA_DETERMINISTIC
-
-/**
- * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
- *
- * Enable the PSK based ciphersuite modes in SSL / TLS.
- *
- * This enables the following ciphersuites (if other requisites are
- * enabled as well):
- *      MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384
- *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384
- *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384
- *      MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_PSK_WITH_RC4_128_SHA
- */
-#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
-
-/**
- * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
- *
- * Enable the DHE-PSK based ciphersuite modes in SSL / TLS.
- *
- * Requires: MBEDTLS_DHM_C
- *
- * This enables the following ciphersuites (if other requisites are
- * enabled as well):
- *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
- *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384
- *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
- *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA
- *
- * \warning    Using DHE constitutes a security risk as it
- *             is not possible to validate custom DH parameters.
- *             If possible, it is recommended users should consider
- *             preferring other methods of key exchange.
- *             See dhm.h for more details.
- *
- */
-#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
-
-/**
- * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
- *
- * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS.
- *
- * Requires: MBEDTLS_ECDH_C
- *
- * This enables the following ciphersuites (if other requisites are
- * enabled as well):
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA
- */
-#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
-
-/**
- * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
- *
- * Enable the RSA-PSK based ciphersuite modes in SSL / TLS.
- *
- * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,
- *           MBEDTLS_X509_CRT_PARSE_C
- *
- * This enables the following ciphersuites (if other requisites are
- * enabled as well):
- *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384
- *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384
- *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384
- *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA
- */
-#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
-
-/**
- * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
- *
- * Enable the RSA-only based ciphersuite modes in SSL / TLS.
- *
- * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,
- *           MBEDTLS_X509_CRT_PARSE_C
- *
- * This enables the following ciphersuites (if other requisites are
- * enabled as well):
- *      MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256
- *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
- *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
- *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
- *      MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
- *      MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_RSA_WITH_RC4_128_SHA
- *      MBEDTLS_TLS_RSA_WITH_RC4_128_MD5
- */
-#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
-
-/**
- * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
- *
- * Enable the DHE-RSA based ciphersuite modes in SSL / TLS.
- *
- * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,
- *           MBEDTLS_X509_CRT_PARSE_C
- *
- * This enables the following ciphersuites (if other requisites are
- * enabled as well):
- *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
- *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
- *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
- *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
- *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
- *      MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
- *
- * \warning    Using DHE constitutes a security risk as it
- *             is not possible to validate custom DH parameters.
- *             If possible, it is recommended users should consider
- *             preferring other methods of key exchange.
- *             See dhm.h for more details.
- *
- */
-#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
-
-/**
- * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
- *
- * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS.
- *
- * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,
- *           MBEDTLS_X509_CRT_PARSE_C
- *
- * This enables the following ciphersuites (if other requisites are
- * enabled as well):
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA
- */
-#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
-
-/**
- * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
- *
- * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS.
- *
- * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C,
- *
- * This enables the following ciphersuites (if other requisites are
- * enabled as well):
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
- */
-#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
-
-/**
- * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
- *
- * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS.
- *
- * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C
- *
- * This enables the following ciphersuites (if other requisites are
- * enabled as well):
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
- */
-#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
-
-/**
- * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
- *
- * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS.
- *
- * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C
- *
- * This enables the following ciphersuites (if other requisites are
- * enabled as well):
- *      MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA
- *      MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
- */
-#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
-
-/**
- * \def MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
- *
- * Enable the ECJPAKE based ciphersuite modes in SSL / TLS.
- *
- * \warning This is currently experimental. EC J-PAKE support is based on the
- * Thread v1.0.0 specification; incompatible changes to the specification
- * might still happen. For this reason, this is disabled by default.
- *
- * Requires: MBEDTLS_ECJPAKE_C
- *           MBEDTLS_SHA256_C
- *           MBEDTLS_ECP_DP_SECP256R1_ENABLED
- *
- * This enables the following ciphersuites (if other requisites are
- * enabled as well):
- *      MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8
- */
-//#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
-
-/**
- * \def MBEDTLS_PK_PARSE_EC_EXTENDED
- *
- * Enhance support for reading EC keys using variants of SEC1 not allowed by
- * RFC 5915 and RFC 5480.
- *
- * Currently this means parsing the SpecifiedECDomain choice of EC
- * parameters (only known groups are supported, not arbitrary domains, to
- * avoid validation issues).
- *
- * Disable if you only need to support RFC 5915 + 5480 key formats.
- */
-#define MBEDTLS_PK_PARSE_EC_EXTENDED
-
-/**
- * \def MBEDTLS_ERROR_STRERROR_DUMMY
- *
- * Enable a dummy error function to make use of mbedtls_strerror() in
- * third party libraries easier when MBEDTLS_ERROR_C is disabled
- * (no effect when MBEDTLS_ERROR_C is enabled).
- *
- * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're
- * not using mbedtls_strerror() or error_strerror() in your application.
- *
- * Disable if you run into name conflicts and want to really remove the
- * mbedtls_strerror()
- */
-#define MBEDTLS_ERROR_STRERROR_DUMMY
-
-/**
- * \def MBEDTLS_GENPRIME
- *
- * Enable the prime-number generation code.
- *
- * Requires: MBEDTLS_BIGNUM_C
- */
-#define MBEDTLS_GENPRIME
-
-/**
- * \def MBEDTLS_FS_IO
- *
- * Enable functions that use the filesystem.
- */
-#define MBEDTLS_FS_IO
-
-/**
- * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
- *
- * Do not add default entropy sources. These are the platform specific,
- * mbedtls_timing_hardclock and HAVEGE based poll functions.
- *
- * This is useful to have more control over the added entropy sources in an
- * application.
- *
- * Uncomment this macro to prevent loading of default entropy functions.
- */
-//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
-
-/**
- * \def MBEDTLS_NO_PLATFORM_ENTROPY
- *
- * Do not use built-in platform entropy functions.
- * This is useful if your platform does not support
- * standards like the /dev/urandom or Windows CryptoAPI.
- *
- * Uncomment this macro to disable the built-in platform entropy functions.
- */
-//#define MBEDTLS_NO_PLATFORM_ENTROPY
-
-/**
- * \def MBEDTLS_ENTROPY_FORCE_SHA256
- *
- * Force the entropy accumulator to use a SHA-256 accumulator instead of the
- * default SHA-512 based one (if both are available).
- *
- * Requires: MBEDTLS_SHA256_C
- *
- * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option
- * if you have performance concerns.
- *
- * This option is only useful if both MBEDTLS_SHA256_C and
- * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used.
- */
-//#define MBEDTLS_ENTROPY_FORCE_SHA256
-
-/**
- * \def MBEDTLS_ENTROPY_NV_SEED
- *
- * Enable the non-volatile (NV) seed file-based entropy source.
- * (Also enables the NV seed read/write functions in the platform layer)
- *
- * This is crucial (if not required) on systems that do not have a
- * cryptographic entropy source (in hardware or kernel) available.
- *
- * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C
- *
- * \note The read/write functions that are used by the entropy source are
- *       determined in the platform layer, and can be modified at runtime and/or
- *       compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used.
- *
- * \note If you use the default implementation functions that read a seedfile
- *       with regular fopen(), please make sure you make a seedfile with the
- *       proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at
- *       least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from
- *       and written to or you will get an entropy source error! The default
- *       implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE
- *       bytes from the file.
- *
- * \note The entropy collector will write to the seed file before entropy is
- *       given to an external source, to update it.
- */
-//#define MBEDTLS_ENTROPY_NV_SEED
-
-/* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
- *
- * Enable key identifiers that encode a key owner identifier.
- *
- * This is only meaningful when building the library as part of a
- * multi-client service. When you activate this option, you must provide an
- * implementation of the type mbedtls_key_owner_id_t and a translation from
- * mbedtls_svc_key_id_t to file name in all the storage backends that you
- * you wish to support.
- *
- * Note that this option is meant for internal use only and may be removed
- * without notice.
- */
-//#define MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
-
-/**
- * \def MBEDTLS_MEMORY_DEBUG
- *
- * Enable debugging of buffer allocator memory issues. Automatically prints
- * (to stderr) all (fatal) messages on memory allocation issues. Enables
- * function for 'debug output' of allocated memory.
- *
- * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C
- *
- * Uncomment this macro to let the buffer allocator print out error messages.
- */
-//#define MBEDTLS_MEMORY_DEBUG
-
-/**
- * \def MBEDTLS_MEMORY_BACKTRACE
- *
- * Include backtrace information with each allocated block.
- *
- * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C
- *           GLIBC-compatible backtrace() an backtrace_symbols() support
- *
- * Uncomment this macro to include backtrace information
- */
-//#define MBEDTLS_MEMORY_BACKTRACE
-
-/**
- * \def MBEDTLS_PK_RSA_ALT_SUPPORT
- *
- * Support external private RSA keys (eg from a HSM) in the PK layer.
- *
- * Comment this macro to disable support for external private RSA keys.
- */
-#define MBEDTLS_PK_RSA_ALT_SUPPORT
-
-/**
- * \def MBEDTLS_PKCS1_V15
- *
- * Enable support for PKCS#1 v1.5 encoding.
- *
- * Requires: MBEDTLS_RSA_C
- *
- * This enables support for PKCS#1 v1.5 operations.
- */
-#define MBEDTLS_PKCS1_V15
-
-/**
- * \def MBEDTLS_PKCS1_V21
- *
- * Enable support for PKCS#1 v2.1 encoding.
- *
- * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C
- *
- * This enables support for RSAES-OAEP and RSASSA-PSS operations.
- */
-#define MBEDTLS_PKCS1_V21
-
-/**
- * \def MBEDTLS_PSA_CRYPTO_SPM
- *
- * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is built for SPM (Secure
- * Partition Manager) integration which separates the code into two parts: a
- * NSPE (Non-Secure Process Environment) and an SPE (Secure Process
- * Environment).
- *
- * Module:  library/psa_crypto.c
- * Requires: MBEDTLS_PSA_CRYPTO_C
- *
- */
-//#define MBEDTLS_PSA_CRYPTO_SPM
-
-/**
- * \def MBEDTLS_PSA_INJECT_ENTROPY
- *
- * Enable support for entropy injection at first boot. This feature is
- * required on systems that do not have a built-in entropy source (TRNG).
- * This feature is currently not supported on systems that have a built-in
- * entropy source.
- *
- * Requires: MBEDTLS_PSA_CRYPTO_STORAGE_C, MBEDTLS_ENTROPY_NV_SEED
- *
- */
-//#define MBEDTLS_PSA_INJECT_ENTROPY
-
-/**
- * \def MBEDTLS_RSA_NO_CRT
- *
- * Do not use the Chinese Remainder Theorem
- * for the RSA private operation.
- *
- * Uncomment this macro to disable the use of CRT in RSA.
- *
- */
-//#define MBEDTLS_RSA_NO_CRT
-
-/**
- * \def MBEDTLS_SELF_TEST
- *
- * Enable the checkup functions (*_self_test).
- */
-#define MBEDTLS_SELF_TEST
-
-/**
- * \def MBEDTLS_SHA256_SMALLER
- *
- * Enable an implementation of SHA-256 that has lower ROM footprint but also
- * lower performance.
- *
- * The default implementation is meant to be a reasonnable compromise between
- * performance and size. This version optimizes more aggressively for size at
- * the expense of performance. Eg on Cortex-M4 it reduces the size of
- * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about
- * 30%.
- *
- * Uncomment to enable the smaller implementation of SHA256.
- */
-//#define MBEDTLS_SHA256_SMALLER
-
-/**
- * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES
- *
- * Enable sending of alert messages in case of encountered errors as per RFC.
- * If you choose not to send the alert messages, mbed TLS can still communicate
- * with other servers, only debugging of failures is harder.
- *
- * The advantage of not sending alert messages, is that no information is given
- * about reasons for failures thus preventing adversaries of gaining intel.
- *
- * Enable sending of all alert messages
- */
-#define MBEDTLS_SSL_ALL_ALERT_MESSAGES
-
-/**
- * \def MBEDTLS_SSL_ASYNC_PRIVATE
- *
- * Enable asynchronous external private key operations in SSL. This allows
- * you to configure an SSL connection to call an external cryptographic
- * module to perform private key operations instead of performing the
- * operation inside the library.
- *
- */
-//#define MBEDTLS_SSL_ASYNC_PRIVATE
-
-/**
- * \def MBEDTLS_SSL_DEBUG_ALL
- *
- * Enable the debug messages in SSL module for all issues.
- * Debug messages have been disabled in some places to prevent timing
- * attacks due to (unbalanced) debugging function calls.
- *
- * If you need all error reporting you should enable this during debugging,
- * but remove this for production servers that should log as well.
- *
- * Uncomment this macro to report all debug messages on errors introducing
- * a timing side-channel.
- *
- */
-//#define MBEDTLS_SSL_DEBUG_ALL
-
-/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC
- *
- * Enable support for Encrypt-then-MAC, RFC 7366.
- *
- * This allows peers that both support it to use a more robust protection for
- * ciphersuites using CBC, providing deep resistance against timing attacks
- * on the padding or underlying cipher.
- *
- * This only affects CBC ciphersuites, and is useless if none is defined.
- *
- * Requires: MBEDTLS_SSL_PROTO_TLS1    or
- *           MBEDTLS_SSL_PROTO_TLS1_1  or
- *           MBEDTLS_SSL_PROTO_TLS1_2
- *
- * Comment this macro to disable support for Encrypt-then-MAC
- */
-#define MBEDTLS_SSL_ENCRYPT_THEN_MAC
-
-/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET
- *
- * Enable support for Extended Master Secret, aka Session Hash
- * (draft-ietf-tls-session-hash-02).
- *
- * This was introduced as "the proper fix" to the Triple Handshake familiy of
- * attacks, but it is recommended to always use it (even if you disable
- * renegotiation), since it actually fixes a more fundamental issue in the
- * original SSL/TLS design, and has implications beyond Triple Handshake.
- *
- * Requires: MBEDTLS_SSL_PROTO_TLS1    or
- *           MBEDTLS_SSL_PROTO_TLS1_1  or
- *           MBEDTLS_SSL_PROTO_TLS1_2
- *
- * Comment this macro to disable support for Extended Master Secret.
- */
-#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET
-
-/**
- * \def MBEDTLS_SSL_FALLBACK_SCSV
- *
- * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00).
- *
- * For servers, it is recommended to always enable this, unless you support
- * only one version of TLS, or know for sure that none of your clients
- * implements a fallback strategy.
- *
- * For clients, you only need this if you're using a fallback strategy, which
- * is not recommended in the first place, unless you absolutely need it to
- * interoperate with buggy (version-intolerant) servers.
- *
- * Comment this macro to disable support for FALLBACK_SCSV
- */
-#define MBEDTLS_SSL_FALLBACK_SCSV
-
-/**
- * \def MBEDTLS_SSL_HW_RECORD_ACCEL
- *
- * Enable hooking functions in SSL module for hardware acceleration of
- * individual records.
- *
- * Uncomment this macro to enable hooking functions.
- */
-//#define MBEDTLS_SSL_HW_RECORD_ACCEL
-
-/**
- * \def MBEDTLS_SSL_CBC_RECORD_SPLITTING
- *
- * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0.
- *
- * This is a countermeasure to the BEAST attack, which also minimizes the risk
- * of interoperability issues compared to sending 0-length records.
- *
- * Comment this macro to disable 1/n-1 record splitting.
- */
-#define MBEDTLS_SSL_CBC_RECORD_SPLITTING
-
-/**
- * \def MBEDTLS_SSL_RENEGOTIATION
- *
- * Enable support for TLS renegotiation.
- *
- * The two main uses of renegotiation are (1) refresh keys on long-lived
- * connections and (2) client authentication after the initial handshake.
- * If you don't need renegotiation, it's probably better to disable it, since
- * it has been associated with security issues in the past and is easy to
- * misuse/misunderstand.
- *
- * Comment this to disable support for renegotiation.
- *
- * \note   Even if this option is disabled, both client and server are aware
- *         of the Renegotiation Indication Extension (RFC 5746) used to
- *         prevent the SSL renegotiation attack (see RFC 5746 Sect. 1).
- *         (See \c mbedtls_ssl_conf_legacy_renegotiation for the
- *          configuration of this extension).
- *
- */
-#define MBEDTLS_SSL_RENEGOTIATION
-
-/**
- * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
- *
- * Enable support for receiving and parsing SSLv2 Client Hello messages for the
- * SSL Server module (MBEDTLS_SSL_SRV_C).
- *
- * Uncomment this macro to enable support for SSLv2 Client Hello messages.
- */
-//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
-
-/**
- * \def MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE
- *
- * Pick the ciphersuite according to the client's preferences rather than ours
- * in the SSL Server module (MBEDTLS_SSL_SRV_C).
- *
- * Uncomment this macro to respect client's ciphersuite order
- */
-//#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE
-
-/**
- * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
- *
- * Enable support for RFC 6066 max_fragment_length extension in SSL.
- *
- * Comment this macro to disable support for the max_fragment_length extension
- */
-#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
-
-/**
- * \def MBEDTLS_SSL_PROTO_SSL3
- *
- * Enable support for SSL 3.0.
- *
- * Requires: MBEDTLS_MD5_C
- *           MBEDTLS_SHA1_C
- *
- * Comment this macro to disable support for SSL 3.0
- */
-//#define MBEDTLS_SSL_PROTO_SSL3
-
-/**
- * \def MBEDTLS_SSL_PROTO_TLS1
- *
- * Enable support for TLS 1.0.
- *
- * Requires: MBEDTLS_MD5_C
- *           MBEDTLS_SHA1_C
- *
- * Comment this macro to disable support for TLS 1.0
- */
-#define MBEDTLS_SSL_PROTO_TLS1
-
-/**
- * \def MBEDTLS_SSL_PROTO_TLS1_1
- *
- * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled).
- *
- * Requires: MBEDTLS_MD5_C
- *           MBEDTLS_SHA1_C
- *
- * Comment this macro to disable support for TLS 1.1 / DTLS 1.0
- */
-#define MBEDTLS_SSL_PROTO_TLS1_1
-
-/**
- * \def MBEDTLS_SSL_PROTO_TLS1_2
- *
- * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled).
- *
- * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C
- *           (Depends on ciphersuites)
- *
- * Comment this macro to disable support for TLS 1.2 / DTLS 1.2
- */
-#define MBEDTLS_SSL_PROTO_TLS1_2
-
-/**
- * \def MBEDTLS_SSL_PROTO_DTLS
- *
- * Enable support for DTLS (all available versions).
- *
- * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0,
- * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2.
- *
- * Requires: MBEDTLS_SSL_PROTO_TLS1_1
- *        or MBEDTLS_SSL_PROTO_TLS1_2
- *
- * Comment this macro to disable support for DTLS
- */
-#define MBEDTLS_SSL_PROTO_DTLS
-
-/**
- * \def MBEDTLS_SSL_ALPN
- *
- * Enable support for RFC 7301 Application Layer Protocol Negotiation.
- *
- * Comment this macro to disable support for ALPN.
- */
-#define MBEDTLS_SSL_ALPN
-
-/**
- * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY
- *
- * Enable support for the anti-replay mechanism in DTLS.
- *
- * Requires: MBEDTLS_SSL_TLS_C
- *           MBEDTLS_SSL_PROTO_DTLS
- *
- * \warning Disabling this is often a security risk!
- * See mbedtls_ssl_conf_dtls_anti_replay() for details.
- *
- * Comment this to disable anti-replay in DTLS.
- */
-#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
-
-/**
- * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY
- *
- * Enable support for HelloVerifyRequest on DTLS servers.
- *
- * This feature is highly recommended to prevent DTLS servers being used as
- * amplifiers in DoS attacks against other hosts. It should always be enabled
- * unless you know for sure amplification cannot be a problem in the
- * environment in which your server operates.
- *
- * \warning Disabling this can ba a security risk! (see above)
- *
- * Requires: MBEDTLS_SSL_PROTO_DTLS
- *
- * Comment this to disable support for HelloVerifyRequest.
- */
-#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
-
-/**
- * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
- *
- * Enable server-side support for clients that reconnect from the same port.
- *
- * Some clients unexpectedly close the connection and try to reconnect using the
- * same source port. This needs special support from the server to handle the
- * new connection securely, as described in section 4.2.8 of RFC 6347. This
- * flag enables that support.
- *
- * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY
- *
- * Comment this to disable support for clients reusing the source port.
- */
-#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
-
-/**
- * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT
- *
- * Enable support for a limit of records with bad MAC.
- *
- * See mbedtls_ssl_conf_dtls_badmac_limit().
- *
- * Requires: MBEDTLS_SSL_PROTO_DTLS
- */
-#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT
-
-/**
- * \def MBEDTLS_SSL_SESSION_TICKETS
- *
- * Enable support for RFC 5077 session tickets in SSL.
- * Client-side, provides full support for session tickets (maintenance of a
- * session store remains the responsibility of the application, though).
- * Server-side, you also need to provide callbacks for writing and parsing
- * tickets, including authenticated encryption and key management. Example
- * callbacks are provided by MBEDTLS_SSL_TICKET_C.
- *
- * Comment this macro to disable support for SSL session tickets
- */
-#define MBEDTLS_SSL_SESSION_TICKETS
-
-/**
- * \def MBEDTLS_SSL_EXPORT_KEYS
- *
- * Enable support for exporting key block and master secret.
- * This is required for certain users of TLS, e.g. EAP-TLS.
- *
- * Comment this macro to disable support for key export
- */
-#define MBEDTLS_SSL_EXPORT_KEYS
-
-/**
- * \def MBEDTLS_SSL_SERVER_NAME_INDICATION
- *
- * Enable support for RFC 6066 server name indication (SNI) in SSL.
- *
- * Requires: MBEDTLS_X509_CRT_PARSE_C
- *
- * Comment this macro to disable support for server name indication in SSL
- */
-#define MBEDTLS_SSL_SERVER_NAME_INDICATION
-
-/**
- * \def MBEDTLS_SSL_TRUNCATED_HMAC
- *
- * Enable support for RFC 6066 truncated HMAC in SSL.
- *
- * Comment this macro to disable support for truncated HMAC in SSL
- */
-#define MBEDTLS_SSL_TRUNCATED_HMAC
-
-/**
- * \def MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT
- *
- * Fallback to old (pre-2.7), non-conforming implementation of the truncated
- * HMAC extension which also truncates the HMAC key. Note that this option is
- * only meant for a transitory upgrade period and is likely to be removed in
- * a future version of the library.
- *
- * \warning The old implementation is non-compliant and has a security weakness
- *          (2^80 brute force attack on the HMAC key used for a single,
- *          uninterrupted connection). This should only be enabled temporarily
- *          when (1) the use of truncated HMAC is essential in order to save
- *          bandwidth, and (2) the peer is an Mbed TLS stack that doesn't use
- *          the fixed implementation yet (pre-2.7).
- *
- * \deprecated This option is deprecated and will likely be removed in a
- *             future version of Mbed TLS.
- *
- * Uncomment to fallback to old, non-compliant truncated HMAC implementation.
- *
- * Requires: MBEDTLS_SSL_TRUNCATED_HMAC
- */
-//#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT
-
-/**
- * \def MBEDTLS_THREADING_ALT
- *
- * Provide your own alternate threading implementation.
- *
- * Requires: MBEDTLS_THREADING_C
- *
- * Uncomment this to allow your own alternate threading implementation.
- */
-//#define MBEDTLS_THREADING_ALT
-
-/**
- * \def MBEDTLS_THREADING_PTHREAD
- *
- * Enable the pthread wrapper layer for the threading layer.
- *
- * Requires: MBEDTLS_THREADING_C
- *
- * Uncomment this to enable pthread mutexes.
- */
-//#define MBEDTLS_THREADING_PTHREAD
-
-/**
- * \def MBEDTLS_USE_PSA_CRYPTO
- *
- * Make the X.509 and TLS library use PSA for cryptographic operations, see
- * #MBEDTLS_PSA_CRYPTO_C.
- *
- * Note: this option is still in progress, the full X.509 and TLS modules are
- * not covered yet, but parts that are not ported to PSA yet will still work
- * as usual, so enabling this option should not break backwards compatibility.
- *
- * \warning  Support for PSA is still an experimental feature.
- *           Any public API that depends on this option may change
- *           at any time until this warning is removed.
- *
- * Requires: MBEDTLS_PSA_CRYPTO_C.
- */
-//#define MBEDTLS_USE_PSA_CRYPTO
-
-/**
- * \def MBEDTLS_VERSION_FEATURES
- *
- * Allow run-time checking of compile-time enabled features. Thus allowing users
- * to check at run-time if the library is for instance compiled with threading
- * support via mbedtls_version_check_feature().
- *
- * Requires: MBEDTLS_VERSION_C
- *
- * Comment this to disable run-time checking and save ROM space
- */
-#define MBEDTLS_VERSION_FEATURES
-
-/**
- * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3
- *
- * If set, the X509 parser will not break-off when parsing an X509 certificate
- * and encountering an extension in a v1 or v2 certificate.
- *
- * Uncomment to prevent an error.
- */
-//#define MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3
-
-/**
- * \def MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
- *
- * If set, the X509 parser will not break-off when parsing an X509 certificate
- * and encountering an unknown critical extension.
- *
- * \warning Depending on your PKI use, enabling this can be a security risk!
- *
- * Uncomment to prevent an error.
- */
-//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
-
-/**
- * \def MBEDTLS_X509_CHECK_KEY_USAGE
- *
- * Enable verification of the keyUsage extension (CA and leaf certificates).
- *
- * Disabling this avoids problems with mis-issued and/or misused
- * (intermediate) CA and leaf certificates.
- *
- * \warning Depending on your PKI use, disabling this can be a security risk!
- *
- * Comment to skip keyUsage checking for both CA and leaf certificates.
- */
-#define MBEDTLS_X509_CHECK_KEY_USAGE
-
-/**
- * \def MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
- *
- * Enable verification of the extendedKeyUsage extension (leaf certificates).
- *
- * Disabling this avoids problems with mis-issued and/or misused certificates.
- *
- * \warning Depending on your PKI use, disabling this can be a security risk!
- *
- * Comment to skip extendedKeyUsage checking for certificates.
- */
-#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
-
-/**
- * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT
- *
- * Enable parsing and verification of X.509 certificates, CRLs and CSRS
- * signed with RSASSA-PSS (aka PKCS#1 v2.1).
- *
- * Comment this macro to disallow using RSASSA-PSS in certificates.
- */
-#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
-
-/**
- * \def MBEDTLS_ZLIB_SUPPORT
- *
- * If set, the SSL/TLS module uses ZLIB to support compression and
- * decompression of packet data.
- *
- * \warning TLS-level compression MAY REDUCE SECURITY! See for example the
- * CRIME attack. Before enabling this option, you should examine with care if
- * CRIME or similar exploits may be applicable to your use case.
- *
- * \note Currently compression can't be used with DTLS.
- *
- * \deprecated This feature is deprecated and will be removed
- *             in the next major revision of the library.
- *
- * Used in: library/ssl_tls.c
- *          library/ssl_cli.c
- *          library/ssl_srv.c
- *
- * This feature requires zlib library and headers to be present.
- *
- * Uncomment to enable use of ZLIB
- */
-//#define MBEDTLS_ZLIB_SUPPORT
-/* \} name SECTION: mbed TLS feature support */
-
-/**
- * \name SECTION: mbed TLS modules
- *
- * This section enables or disables entire modules in mbed TLS
- * \{
- */
-
-/**
- * \def MBEDTLS_AESNI_C
- *
- * Enable AES-NI support on x86-64.
- *
- * Module:  library/aesni.c
- * Caller:  library/aes.c
- *
- * Requires: MBEDTLS_HAVE_ASM
- *
- * This modules adds support for the AES-NI instructions on x86-64
- */
-#define MBEDTLS_AESNI_C
-
-/**
- * \def MBEDTLS_AES_C
- *
- * Enable the AES block cipher.
- *
- * Module:  library/aes.c
- * Caller:  library/cipher.c
- *          library/pem.c
- *          library/ctr_drbg.c
- *
- * This module enables the following ciphersuites (if other requisites are
- * enabled as well):
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
- *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384
- *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256
- *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384
- *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA
- *      MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384
- *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384
- *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA
- *      MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256
- *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256
- *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA
- *
- * PEM_PARSE uses AES for decrypting encrypted keys.
- */
-#define MBEDTLS_AES_C
-
-/**
- * \def MBEDTLS_ARC4_C
- *
- * Enable the ARCFOUR stream cipher.
- *
- * Module:  library/arc4.c
- * Caller:  library/cipher.c
- *
- * This module enables the following ciphersuites (if other requisites are
- * enabled as well):
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
- *      MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA
- *      MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA
- *      MBEDTLS_TLS_RSA_WITH_RC4_128_SHA
- *      MBEDTLS_TLS_RSA_WITH_RC4_128_MD5
- *      MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA
- *      MBEDTLS_TLS_PSK_WITH_RC4_128_SHA
- *
- * \warning   ARC4 is considered a weak cipher and its use constitutes a
- *            security risk. If possible, we recommend avoidng dependencies on
- *            it, and considering stronger ciphers instead.
- *
- */
-#define MBEDTLS_ARC4_C
-
-/**
- * \def MBEDTLS_ASN1_PARSE_C
- *
- * Enable the generic ASN1 parser.
- *
- * Module:  library/asn1.c
- * Caller:  library/x509.c
- *          library/dhm.c
- *          library/pkcs12.c
- *          library/pkcs5.c
- *          library/pkparse.c
- */
-#define MBEDTLS_ASN1_PARSE_C
-
-/**
- * \def MBEDTLS_ASN1_WRITE_C
- *
- * Enable the generic ASN1 writer.
- *
- * Module:  library/asn1write.c
- * Caller:  library/ecdsa.c
- *          library/pkwrite.c
- *          library/x509_create.c
- *          library/x509write_crt.c
- *          library/x509write_csr.c
- */
-#define MBEDTLS_ASN1_WRITE_C
-
-/**
- * \def MBEDTLS_BASE64_C
- *
- * Enable the Base64 module.
- *
- * Module:  library/base64.c
- * Caller:  library/pem.c
- *
- * This module is required for PEM support (required by X.509).
- */
-#define MBEDTLS_BASE64_C
-
-/**
- * \def MBEDTLS_BIGNUM_C
- *
- * Enable the multi-precision integer library.
- *
- * Module:  library/bignum.c
- * Caller:  library/dhm.c
- *          library/ecp.c
- *          library/ecdsa.c
- *          library/rsa.c
- *          library/rsa_internal.c
- *          library/ssl_tls.c
- *
- * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support.
- */
-#define MBEDTLS_BIGNUM_C
-
-/**
- * \def MBEDTLS_BLOWFISH_C
- *
- * Enable the Blowfish block cipher.
- *
- * Module:  library/blowfish.c
- */
-#define MBEDTLS_BLOWFISH_C
-
-/**
- * \def MBEDTLS_CAMELLIA_C
- *
- * Enable the Camellia block cipher.
- *
- * Module:  library/camellia.c
- * Caller:  library/cipher.c
- *
- * This module enables the following ciphersuites (if other requisites are
- * enabled as well):
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
- *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
- *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
- *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
- *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
- *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
- *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
- *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
- *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
- *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
- *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384
- *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384
- *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256
- *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384
- *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384
- *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256
- *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256
- */
-#define MBEDTLS_CAMELLIA_C
-
-/**
- * \def MBEDTLS_ARIA_C
- *
- * Enable the ARIA block cipher.
- *
- * Module:  library/aria.c
- * Caller:  library/cipher.c
- *
- * This module enables the following ciphersuites (if other requisites are
- * enabled as well):
- *
- *      MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256
- *      MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384
- *      MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256
- *      MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384
- *      MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384
- *      MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256
- *      MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384
- *      MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256
- *      MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256
- *      MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384
- *      MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256
- *      MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384
- *      MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256
- *      MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384
- *      MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256
- *      MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384
- *      MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256
- *      MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384
- *      MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256
- *      MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384
- *      MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256
- *      MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384
- */
-//#define MBEDTLS_ARIA_C
-
-/**
- * \def MBEDTLS_CCM_C
- *
- * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher.
- *
- * Module:  library/ccm.c
- *
- * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C
- *
- * This module enables the AES-CCM ciphersuites, if other requisites are
- * enabled as well.
- */
-#define MBEDTLS_CCM_C
-
-/**
- * \def MBEDTLS_CERTS_C
- *
- * Enable the test certificates.
- *
- * Module:  library/certs.c
- * Caller:
- *
- * This module is used for testing (ssl_client/server).
- */
-#define MBEDTLS_CERTS_C
-
-/**
- * \def MBEDTLS_CHACHA20_C
- *
- * Enable the ChaCha20 stream cipher.
- *
- * Module:  library/chacha20.c
- */
-#define MBEDTLS_CHACHA20_C
-
-/**
- * \def MBEDTLS_CHACHAPOLY_C
- *
- * Enable the ChaCha20-Poly1305 AEAD algorithm.
- *
- * Module:  library/chachapoly.c
- *
- * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C
- */
-#define MBEDTLS_CHACHAPOLY_C
-
-/**
- * \def MBEDTLS_CIPHER_C
- *
- * Enable the generic cipher layer.
- *
- * Module:  library/cipher.c
- * Caller:  library/ssl_tls.c
- *
- * Uncomment to enable generic cipher wrappers.
- */
-#define MBEDTLS_CIPHER_C
-
-/**
- * \def MBEDTLS_CMAC_C
- *
- * Enable the CMAC (Cipher-based Message Authentication Code) mode for block
- * ciphers.
- *
- * Module:  library/cmac.c
- *
- * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C
- *
- */
-#define MBEDTLS_CMAC_C
-
-/**
- * \def MBEDTLS_CTR_DRBG_C
- *
- * Enable the CTR_DRBG AES-based random generator.
- * The CTR_DRBG generator uses AES-256 by default.
- * To use AES-128 instead, enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY below.
- *
- * Module:  library/ctr_drbg.c
- * Caller:
- *
- * Requires: MBEDTLS_AES_C
- *
- * This module provides the CTR_DRBG AES random number generator.
- */
-#define MBEDTLS_CTR_DRBG_C
-
-/**
- * \def MBEDTLS_DEBUG_C
- *
- * Enable the debug functions.
- *
- * Module:  library/debug.c
- * Caller:  library/ssl_cli.c
- *          library/ssl_srv.c
- *          library/ssl_tls.c
- *
- * This module provides debugging functions.
- */
-#define MBEDTLS_DEBUG_C
-
-/**
- * \def MBEDTLS_DES_C
- *
- * Enable the DES block cipher.
- *
- * Module:  library/des.c
- * Caller:  library/pem.c
- *          library/cipher.c
- *
- * This module enables the following ciphersuites (if other requisites are
- * enabled as well):
- *      MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA
- *      MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA
- *
- * PEM_PARSE uses DES/3DES for decrypting encrypted keys.
- *
- * \warning   DES is considered a weak cipher and its use constitutes a
- *            security risk. We recommend considering stronger ciphers instead.
- */
-#define MBEDTLS_DES_C
-
-/**
- * \def MBEDTLS_DHM_C
- *
- * Enable the Diffie-Hellman-Merkle module.
- *
- * Module:  library/dhm.c
- * Caller:  library/ssl_cli.c
- *          library/ssl_srv.c
- *
- * This module is used by the following key exchanges:
- *      DHE-RSA, DHE-PSK
- *
- * \warning    Using DHE constitutes a security risk as it
- *             is not possible to validate custom DH parameters.
- *             If possible, it is recommended users should consider
- *             preferring other methods of key exchange.
- *             See dhm.h for more details.
- *
- */
-#define MBEDTLS_DHM_C
-
-/**
- * \def MBEDTLS_ECDH_C
- *
- * Enable the elliptic curve Diffie-Hellman library.
- *
- * Module:  library/ecdh.c
- * Caller:  library/ssl_cli.c
- *          library/ssl_srv.c
- *
- * This module is used by the following key exchanges:
- *      ECDHE-ECDSA, ECDHE-RSA, DHE-PSK
- *
- * Requires: MBEDTLS_ECP_C
- */
-#define MBEDTLS_ECDH_C
-
-/**
- * \def MBEDTLS_ECDSA_C
- *
- * Enable the elliptic curve DSA library.
- *
- * Module:  library/ecdsa.c
- * Caller:
- *
- * This module is used by the following key exchanges:
- *      ECDHE-ECDSA
- *
- * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C
- */
-#define MBEDTLS_ECDSA_C
-
-/**
- * \def MBEDTLS_ECJPAKE_C
- *
- * Enable the elliptic curve J-PAKE library.
- *
- * \warning This is currently experimental. EC J-PAKE support is based on the
- * Thread v1.0.0 specification; incompatible changes to the specification
- * might still happen. For this reason, this is disabled by default.
- *
- * Module:  library/ecjpake.c
- * Caller:
- *
- * This module is used by the following key exchanges:
- *      ECJPAKE
- *
- * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C
- */
-//#define MBEDTLS_ECJPAKE_C
-
-/**
- * \def MBEDTLS_ECP_C
- *
- * Enable the elliptic curve over GF(p) library.
- *
- * Module:  library/ecp.c
- * Caller:  library/ecdh.c
- *          library/ecdsa.c
- *          library/ecjpake.c
- *
- * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED
- */
-#define MBEDTLS_ECP_C
-
-/**
- * \def MBEDTLS_ENTROPY_C
- *
- * Enable the platform-specific entropy code.
- *
- * Module:  library/entropy.c
- * Caller:
- *
- * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C
- *
- * This module provides a generic entropy pool
- */
-#define MBEDTLS_ENTROPY_C
-
-/**
- * \def MBEDTLS_ERROR_C
- *
- * Enable error code to error string conversion.
- *
- * Module:  library/error.c
- * Caller:
- *
- * This module enables mbedtls_strerror().
- */
-#define MBEDTLS_ERROR_C
-
-/**
- * \def MBEDTLS_GCM_C
- *
- * Enable the Galois/Counter Mode (GCM) for AES.
- *
- * Module:  library/gcm.c
- *
- * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C
- *
- * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other
- * requisites are enabled as well.
- */
-#define MBEDTLS_GCM_C
-
-/**
- * \def MBEDTLS_HAVEGE_C
- *
- * Enable the HAVEGE random generator.
- *
- * Warning: the HAVEGE random generator is not suitable for virtualized
- *          environments
- *
- * Warning: the HAVEGE random generator is dependent on timing and specific
- *          processor traits. It is therefore not advised to use HAVEGE as
- *          your applications primary random generator or primary entropy pool
- *          input. As a secondary input to your entropy pool, it IS able add
- *          the (limited) extra entropy it provides.
- *
- * Module:  library/havege.c
- * Caller:
- *
- * Requires: MBEDTLS_TIMING_C
- *
- * Uncomment to enable the HAVEGE random generator.
- */
-//#define MBEDTLS_HAVEGE_C
-
-/**
- * \def MBEDTLS_HKDF_C
- *
- * Enable the HKDF algorithm (RFC 5869).
- *
- * Module:  library/hkdf.c
- * Caller:
- *
- * Requires: MBEDTLS_MD_C
- *
- * This module adds support for the Hashed Message Authentication Code
- * (HMAC)-based key derivation function (HKDF).
- */
-#define MBEDTLS_HKDF_C
-
-/**
- * \def MBEDTLS_HMAC_DRBG_C
- *
- * Enable the HMAC_DRBG random generator.
- *
- * Module:  library/hmac_drbg.c
- * Caller:
- *
- * Requires: MBEDTLS_MD_C
- *
- * Uncomment to enable the HMAC_DRBG random number geerator.
- */
-#define MBEDTLS_HMAC_DRBG_C
-
-/**
- * \def MBEDTLS_NIST_KW_C
- *
- * Enable the Key Wrapping mode for 128-bit block ciphers,
- * as defined in NIST SP 800-38F. Only KW and KWP modes
- * are supported. At the moment, only AES is approved by NIST.
- *
- * Module:  library/nist_kw.c
- *
- * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C
- */
-//#define MBEDTLS_NIST_KW_C
-
-/**
- * \def MBEDTLS_MD_C
- *
- * Enable the generic message digest layer.
- *
- * Module:  library/md.c
- * Caller:
- *
- * Uncomment to enable generic message digest wrappers.
- */
-#define MBEDTLS_MD_C
-
-/**
- * \def MBEDTLS_MD2_C
- *
- * Enable the MD2 hash algorithm.
- *
- * Module:  library/md2.c
- * Caller:
- *
- * Uncomment to enable support for (rare) MD2-signed X.509 certs.
- *
- * \warning   MD2 is considered a weak message digest and its use constitutes a
- *            security risk. If possible, we recommend avoiding dependencies on
- *            it, and considering stronger message digests instead.
- *
- */
-//#define MBEDTLS_MD2_C
-
-/**
- * \def MBEDTLS_MD4_C
- *
- * Enable the MD4 hash algorithm.
- *
- * Module:  library/md4.c
- * Caller:
- *
- * Uncomment to enable support for (rare) MD4-signed X.509 certs.
- *
- * \warning   MD4 is considered a weak message digest and its use constitutes a
- *            security risk. If possible, we recommend avoiding dependencies on
- *            it, and considering stronger message digests instead.
- *
- */
-//#define MBEDTLS_MD4_C
-
-/**
- * \def MBEDTLS_MD5_C
- *
- * Enable the MD5 hash algorithm.
- *
- * Module:  library/md5.c
- * Caller:  library/md.c
- *          library/pem.c
- *          library/ssl_tls.c
- *
- * This module is required for SSL/TLS up to version 1.1, and for TLS 1.2
- * depending on the handshake parameters. Further, it is used for checking
- * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded
- * encrypted keys.
- *
- * \warning   MD5 is considered a weak message digest and its use constitutes a
- *            security risk. If possible, we recommend avoiding dependencies on
- *            it, and considering stronger message digests instead.
- *
- */
-#define MBEDTLS_MD5_C
-
-/**
- * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C
- *
- * Enable the buffer allocator implementation that makes use of a (stack)
- * based buffer to 'allocate' dynamic memory. (replaces calloc() and free()
- * calls)
- *
- * Module:  library/memory_buffer_alloc.c
- *
- * Requires: MBEDTLS_PLATFORM_C
- *           MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS)
- *
- * Enable this module to enable the buffer memory allocator.
- */
-//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
-
-/**
- * \def MBEDTLS_NET_C
- *
- * Enable the TCP and UDP over IPv6/IPv4 networking routines.
- *
- * \note This module only works on POSIX/Unix (including Linux, BSD and OS X)
- * and Windows. For other platforms, you'll want to disable it, and write your
- * own networking callbacks to be passed to \c mbedtls_ssl_set_bio().
- *
- * \note See also our Knowledge Base article about porting to a new
- * environment:
- * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS
- *
- * Module:  library/net_sockets.c
- *
- * This module provides networking routines.
- */
-#define MBEDTLS_NET_C
-
-/**
- * \def MBEDTLS_OID_C
- *
- * Enable the OID database.
- *
- * Module:  library/oid.c
- * Caller:  library/asn1write.c
- *          library/pkcs5.c
- *          library/pkparse.c
- *          library/pkwrite.c
- *          library/rsa.c
- *          library/x509.c
- *          library/x509_create.c
- *          library/x509_crl.c
- *          library/x509_crt.c
- *          library/x509_csr.c
- *          library/x509write_crt.c
- *          library/x509write_csr.c
- *
- * This modules translates between OIDs and internal values.
- */
-#define MBEDTLS_OID_C
-
-/**
- * \def MBEDTLS_PADLOCK_C
- *
- * Enable VIA Padlock support on x86.
- *
- * Module:  library/padlock.c
- * Caller:  library/aes.c
- *
- * Requires: MBEDTLS_HAVE_ASM
- *
- * This modules adds support for the VIA PadLock on x86.
- */
-#define MBEDTLS_PADLOCK_C
-
-/**
- * \def MBEDTLS_PEM_PARSE_C
- *
- * Enable PEM decoding / parsing.
- *
- * Module:  library/pem.c
- * Caller:  library/dhm.c
- *          library/pkparse.c
- *          library/x509_crl.c
- *          library/x509_crt.c
- *          library/x509_csr.c
- *
- * Requires: MBEDTLS_BASE64_C
- *
- * This modules adds support for decoding / parsing PEM files.
- */
-#define MBEDTLS_PEM_PARSE_C
-
-/**
- * \def MBEDTLS_PEM_WRITE_C
- *
- * Enable PEM encoding / writing.
- *
- * Module:  library/pem.c
- * Caller:  library/pkwrite.c
- *          library/x509write_crt.c
- *          library/x509write_csr.c
- *
- * Requires: MBEDTLS_BASE64_C
- *
- * This modules adds support for encoding / writing PEM files.
- */
-#define MBEDTLS_PEM_WRITE_C
-
-/**
- * \def MBEDTLS_PK_C
- *
- * Enable the generic public (asymetric) key layer.
- *
- * Module:  library/pk.c
- * Caller:  library/ssl_tls.c
- *          library/ssl_cli.c
- *          library/ssl_srv.c
- *
- * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C
- *
- * Uncomment to enable generic public key wrappers.
- */
-#define MBEDTLS_PK_C
-
-/**
- * \def MBEDTLS_PK_PARSE_C
- *
- * Enable the generic public (asymetric) key parser.
- *
- * Module:  library/pkparse.c
- * Caller:  library/x509_crt.c
- *          library/x509_csr.c
- *
- * Requires: MBEDTLS_PK_C
- *
- * Uncomment to enable generic public key parse functions.
- */
-#define MBEDTLS_PK_PARSE_C
-
-/**
- * \def MBEDTLS_PK_WRITE_C
- *
- * Enable the generic public (asymetric) key writer.
- *
- * Module:  library/pkwrite.c
- * Caller:  library/x509write.c
- *
- * Requires: MBEDTLS_PK_C
- *
- * Uncomment to enable generic public key write functions.
- */
-#define MBEDTLS_PK_WRITE_C
-
-/**
- * \def MBEDTLS_PKCS5_C
- *
- * Enable PKCS#5 functions.
- *
- * Module:  library/pkcs5.c
- *
- * Requires: MBEDTLS_MD_C
- *
- * This module adds support for the PKCS#5 functions.
- */
-#define MBEDTLS_PKCS5_C
-
-/**
- * \def MBEDTLS_PKCS11_C
- *
- * Enable wrapper for PKCS#11 smartcard support.
- *
- * Module:  library/pkcs11.c
- * Caller:  library/pk.c
- *
- * Requires: MBEDTLS_PK_C
- *
- * This module enables SSL/TLS PKCS #11 smartcard support.
- * Requires the presence of the PKCS#11 helper library (libpkcs11-helper)
- */
-//#define MBEDTLS_PKCS11_C
-
-/**
- * \def MBEDTLS_PKCS12_C
- *
- * Enable PKCS#12 PBE functions.
- * Adds algorithms for parsing PKCS#8 encrypted private keys
- *
- * Module:  library/pkcs12.c
- * Caller:  library/pkparse.c
- *
- * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C
- * Can use:  MBEDTLS_ARC4_C
- *
- * This module enables PKCS#12 functions.
- */
-#define MBEDTLS_PKCS12_C
-
-/**
- * \def MBEDTLS_PLATFORM_C
- *
- * Enable the platform abstraction layer that allows you to re-assign
- * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit().
- *
- * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT
- * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned
- * above to be specified at runtime or compile time respectively.
- *
- * \note This abstraction layer must be enabled on Windows (including MSYS2)
- * as other module rely on it for a fixed snprintf implementation.
- *
- * Module:  library/platform.c
- * Caller:  Most other .c files
- *
- * This module enables abstraction of common (libc) functions.
- */
-#define MBEDTLS_PLATFORM_C
-
-/**
- * \def MBEDTLS_POLY1305_C
- *
- * Enable the Poly1305 MAC algorithm.
- *
- * Module:  library/poly1305.c
- * Caller:  library/chachapoly.c
- */
-#define MBEDTLS_POLY1305_C
-
-/**
- * \def MBEDTLS_PSA_CRYPTO_C
- *
- * Enable the Platform Security Architecture cryptography API.
- *
- * Module:  library/psa_crypto.c
- *
- * Requires: MBEDTLS_CTR_DRBG_C, MBEDTLS_ENTROPY_C
- *
- */
-#define MBEDTLS_PSA_CRYPTO_C
-
-/**
- * \def MBEDTLS_PSA_CRYPTO_STORAGE_C
- *
- * Enable the Platform Security Architecture persistent key storage.
- *
- * Module:  library/psa_crypto_storage.c
- *
- * Requires: MBEDTLS_PSA_CRYPTO_C,
- *           either MBEDTLS_PSA_ITS_FILE_C or a native implementation of
- *           the PSA ITS interface
- */
-#define MBEDTLS_PSA_CRYPTO_STORAGE_C
-
-/**
- * \def MBEDTLS_PSA_ITS_FILE_C
- *
- * Enable the emulation of the Platform Security Architecture
- * Internal Trusted Storage (PSA ITS) over files.
- *
- * Module:  library/psa_its_file.c
- *
- * Requires: MBEDTLS_FS_IO
- */
-#define MBEDTLS_PSA_ITS_FILE_C
-
-/**
- * \def MBEDTLS_RIPEMD160_C
- *
- * Enable the RIPEMD-160 hash algorithm.
- *
- * Module:  library/ripemd160.c
- * Caller:  library/md.c
- *
- */
-#define MBEDTLS_RIPEMD160_C
-
-/**
- * \def MBEDTLS_RSA_C
- *
- * Enable the RSA public-key cryptosystem.
- *
- * Module:  library/rsa.c
- *          library/rsa_internal.c
- * Caller:  library/ssl_cli.c
- *          library/ssl_srv.c
- *          library/ssl_tls.c
- *          library/x509.c
- *
- * This module is used by the following key exchanges:
- *      RSA, DHE-RSA, ECDHE-RSA, RSA-PSK
- *
- * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C
- */
-#define MBEDTLS_RSA_C
-
-/**
- * \def MBEDTLS_SHA1_C
- *
- * Enable the SHA1 cryptographic hash algorithm.
- *
- * Module:  library/sha1.c
- * Caller:  library/md.c
- *          library/ssl_cli.c
- *          library/ssl_srv.c
- *          library/ssl_tls.c
- *          library/x509write_crt.c
- *
- * This module is required for SSL/TLS up to version 1.1, for TLS 1.2
- * depending on the handshake parameters, and for SHA1-signed certificates.
- *
- * \warning   SHA-1 is considered a weak message digest and its use constitutes
- *            a security risk. If possible, we recommend avoiding dependencies
- *            on it, and considering stronger message digests instead.
- *
- */
-#define MBEDTLS_SHA1_C
-
-/**
- * \def MBEDTLS_SHA256_C
- *
- * Enable the SHA-224 and SHA-256 cryptographic hash algorithms.
- *
- * Module:  library/sha256.c
- * Caller:  library/entropy.c
- *          library/md.c
- *          library/ssl_cli.c
- *          library/ssl_srv.c
- *          library/ssl_tls.c
- *
- * This module adds support for SHA-224 and SHA-256.
- * This module is required for the SSL/TLS 1.2 PRF function.
- */
-#define MBEDTLS_SHA256_C
-
-/**
- * \def MBEDTLS_SHA512_C
- *
- * Enable the SHA-384 and SHA-512 cryptographic hash algorithms.
- *
- * Module:  library/sha512.c
- * Caller:  library/entropy.c
- *          library/md.c
- *          library/ssl_cli.c
- *          library/ssl_srv.c
- *
- * This module adds support for SHA-384 and SHA-512.
- */
-#define MBEDTLS_SHA512_C
-
-/**
- * \def MBEDTLS_SSL_CACHE_C
- *
- * Enable simple SSL cache implementation.
- *
- * Module:  library/ssl_cache.c
- * Caller:
- *
- * Requires: MBEDTLS_SSL_CACHE_C
- */
-#define MBEDTLS_SSL_CACHE_C
-
-/**
- * \def MBEDTLS_SSL_COOKIE_C
- *
- * Enable basic implementation of DTLS cookies for hello verification.
- *
- * Module:  library/ssl_cookie.c
- * Caller:
- */
-#define MBEDTLS_SSL_COOKIE_C
-
-/**
- * \def MBEDTLS_SSL_TICKET_C
- *
- * Enable an implementation of TLS server-side callbacks for session tickets.
- *
- * Module:  library/ssl_ticket.c
- * Caller:
- *
- * Requires: MBEDTLS_CIPHER_C
- */
-#define MBEDTLS_SSL_TICKET_C
-
-/**
- * \def MBEDTLS_SSL_CLI_C
- *
- * Enable the SSL/TLS client code.
- *
- * Module:  library/ssl_cli.c
- * Caller:
- *
- * Requires: MBEDTLS_SSL_TLS_C
- *
- * This module is required for SSL/TLS client support.
- */
-#define MBEDTLS_SSL_CLI_C
-
-/**
- * \def MBEDTLS_SSL_SRV_C
- *
- * Enable the SSL/TLS server code.
- *
- * Module:  library/ssl_srv.c
- * Caller:
- *
- * Requires: MBEDTLS_SSL_TLS_C
- *
- * This module is required for SSL/TLS server support.
- */
-#define MBEDTLS_SSL_SRV_C
-
-/**
- * \def MBEDTLS_SSL_TLS_C
- *
- * Enable the generic SSL/TLS code.
- *
- * Module:  library/ssl_tls.c
- * Caller:  library/ssl_cli.c
- *          library/ssl_srv.c
- *
- * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C
- *           and at least one of the MBEDTLS_SSL_PROTO_XXX defines
- *
- * This module is required for SSL/TLS.
- */
-#define MBEDTLS_SSL_TLS_C
-
-/**
- * \def MBEDTLS_THREADING_C
- *
- * Enable the threading abstraction layer.
- * By default mbed TLS assumes it is used in a non-threaded environment or that
- * contexts are not shared between threads. If you do intend to use contexts
- * between threads, you will need to enable this layer to prevent race
- * conditions. See also our Knowledge Base article about threading:
- * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading
- *
- * Module:  library/threading.c
- *
- * This allows different threading implementations (self-implemented or
- * provided).
- *
- * You will have to enable either MBEDTLS_THREADING_ALT or
- * MBEDTLS_THREADING_PTHREAD.
- *
- * Enable this layer to allow use of mutexes within mbed TLS
- */
-//#define MBEDTLS_THREADING_C
-
-/**
- * \def MBEDTLS_TIMING_C
- *
- * Enable the semi-portable timing interface.
- *
- * \note The provided implementation only works on POSIX/Unix (including Linux,
- * BSD and OS X) and Windows. On other platforms, you can either disable that
- * module and provide your own implementations of the callbacks needed by
- * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide
- * your own implementation of the whole module by setting
- * \c MBEDTLS_TIMING_ALT in the current file.
- *
- * \note See also our Knowledge Base article about porting to a new
- * environment:
- * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS
- *
- * Module:  library/timing.c
- * Caller:  library/havege.c
- *
- * This module is used by the HAVEGE random number generator.
- */
-#define MBEDTLS_TIMING_C
-
-/**
- * \def MBEDTLS_VERSION_C
- *
- * Enable run-time version information.
- *
- * Module:  library/version.c
- *
- * This module provides run-time version information.
- */
-#define MBEDTLS_VERSION_C
-
-/**
- * \def MBEDTLS_X509_USE_C
- *
- * Enable X.509 core for using certificates.
- *
- * Module:  library/x509.c
- * Caller:  library/x509_crl.c
- *          library/x509_crt.c
- *          library/x509_csr.c
- *
- * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C,
- *           MBEDTLS_PK_PARSE_C
- *
- * This module is required for the X.509 parsing modules.
- */
-#define MBEDTLS_X509_USE_C
-
-/**
- * \def MBEDTLS_X509_CRT_PARSE_C
- *
- * Enable X.509 certificate parsing.
- *
- * Module:  library/x509_crt.c
- * Caller:  library/ssl_cli.c
- *          library/ssl_srv.c
- *          library/ssl_tls.c
- *
- * Requires: MBEDTLS_X509_USE_C
- *
- * This module is required for X.509 certificate parsing.
- */
-#define MBEDTLS_X509_CRT_PARSE_C
-
-/**
- * \def MBEDTLS_X509_CRL_PARSE_C
- *
- * Enable X.509 CRL parsing.
- *
- * Module:  library/x509_crl.c
- * Caller:  library/x509_crt.c
- *
- * Requires: MBEDTLS_X509_USE_C
- *
- * This module is required for X.509 CRL parsing.
- */
-#define MBEDTLS_X509_CRL_PARSE_C
-
-/**
- * \def MBEDTLS_X509_CSR_PARSE_C
- *
- * Enable X.509 Certificate Signing Request (CSR) parsing.
- *
- * Module:  library/x509_csr.c
- * Caller:  library/x509_crt_write.c
- *
- * Requires: MBEDTLS_X509_USE_C
- *
- * This module is used for reading X.509 certificate request.
- */
-#define MBEDTLS_X509_CSR_PARSE_C
-
-/**
- * \def MBEDTLS_X509_CREATE_C
- *
- * Enable X.509 core for creating certificates.
- *
- * Module:  library/x509_create.c
- *
- * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C
- *
- * This module is the basis for creating X.509 certificates and CSRs.
- */
-#define MBEDTLS_X509_CREATE_C
-
-/**
- * \def MBEDTLS_X509_CRT_WRITE_C
- *
- * Enable creating X.509 certificates.
- *
- * Module:  library/x509_crt_write.c
- *
- * Requires: MBEDTLS_X509_CREATE_C
- *
- * This module is required for X.509 certificate creation.
- */
-#define MBEDTLS_X509_CRT_WRITE_C
-
-/**
- * \def MBEDTLS_X509_CSR_WRITE_C
- *
- * Enable creating X.509 Certificate Signing Requests (CSR).
- *
- * Module:  library/x509_csr_write.c
- *
- * Requires: MBEDTLS_X509_CREATE_C
- *
- * This module is required for X.509 certificate request writing.
- */
-#define MBEDTLS_X509_CSR_WRITE_C
-
-/**
- * \def MBEDTLS_XTEA_C
- *
- * Enable the XTEA block cipher.
- *
- * Module:  library/xtea.c
- * Caller:
- */
-#define MBEDTLS_XTEA_C
-
-/* \} name SECTION: mbed TLS modules */
-
-/**
- * \name SECTION: Module configuration options
- *
- * This section allows for the setting of module specific sizes and
- * configuration options. The default values are already present in the
- * relevant header files and should suffice for the regular use cases.
- *
- * Our advice is to enable options and change their values here
- * only if you have a good reason and know the consequences.
- *
- * Please check the respective header file for documentation on these
- * parameters (to prevent duplicate documentation).
- * \{
- */
-
-/* MPI / BIGNUM options */
-//#define MBEDTLS_MPI_WINDOW_SIZE            6 /**< Maximum windows size used. */
-//#define MBEDTLS_MPI_MAX_SIZE            1024 /**< Maximum number of bytes for usable MPIs. */
-
-/* CTR_DRBG options */
-//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN               48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
-//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL        10000 /**< Interval before reseed is performed by default */
-//#define MBEDTLS_CTR_DRBG_MAX_INPUT                256 /**< Maximum number of additional input bytes */
-//#define MBEDTLS_CTR_DRBG_MAX_REQUEST             1024 /**< Maximum number of requested bytes per call */
-//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT           384 /**< Maximum size of (re)seed buffer */
-//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY              /**< Use 128-bit key for CTR_DRBG - may reduce security (see ctr_drbg.h) */
-
-/* HMAC_DRBG options */
-//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL   10000 /**< Interval before reseed is performed by default */
-//#define MBEDTLS_HMAC_DRBG_MAX_INPUT           256 /**< Maximum number of additional input bytes */
-//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST        1024 /**< Maximum number of requested bytes per call */
-//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT      384 /**< Maximum size of (re)seed buffer */
-
-/* ECP options */
-//#define MBEDTLS_ECP_MAX_BITS             521 /**< Maximum bit size of groups */
-//#define MBEDTLS_ECP_WINDOW_SIZE            6 /**< Maximum window size used */
-//#define MBEDTLS_ECP_FIXED_POINT_OPTIM      1 /**< Enable fixed-point speed-up */
-
-/* Entropy options */
-//#define MBEDTLS_ENTROPY_MAX_SOURCES                20 /**< Maximum number of sources supported */
-//#define MBEDTLS_ENTROPY_MAX_GATHER                128 /**< Maximum amount requested from entropy sources */
-//#define MBEDTLS_ENTROPY_MIN_HARDWARE               32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */
-
-/* Memory buffer allocator options */
-//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE      4 /**< Align on multiples of this value */
-
-/* Platform options */
-//#define MBEDTLS_PLATFORM_STD_MEM_HDR   <stdlib.h> /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */
-//#define MBEDTLS_PLATFORM_STD_CALLOC        calloc /**< Default allocator to use, can be undefined */
-//#define MBEDTLS_PLATFORM_STD_FREE            free /**< Default free to use, can be undefined */
-//#define MBEDTLS_PLATFORM_STD_EXIT            exit /**< Default exit to use, can be undefined */
-//#define MBEDTLS_PLATFORM_STD_TIME            time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
-//#define MBEDTLS_PLATFORM_STD_FPRINTF      fprintf /**< Default fprintf to use, can be undefined */
-//#define MBEDTLS_PLATFORM_STD_PRINTF        printf /**< Default printf to use, can be undefined */
-/* Note: your snprintf must correctly zero-terminate the buffer! */
-//#define MBEDTLS_PLATFORM_STD_SNPRINTF    snprintf /**< Default snprintf to use, can be undefined */
-//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS       0 /**< Default exit value to use, can be undefined */
-//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE       1 /**< Default exit value to use, can be undefined */
-//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ   mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
-//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE  mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
-//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE  "seedfile" /**< Seed file to read/write with default implementation */
-
-/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */
-/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */
-//#define MBEDTLS_PLATFORM_CALLOC_MACRO        calloc /**< Default allocator macro to use, can be undefined */
-//#define MBEDTLS_PLATFORM_FREE_MACRO            free /**< Default free macro to use, can be undefined */
-//#define MBEDTLS_PLATFORM_EXIT_MACRO            exit /**< Default exit macro to use, can be undefined */
-//#define MBEDTLS_PLATFORM_TIME_MACRO            time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
-//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO       time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
-//#define MBEDTLS_PLATFORM_FPRINTF_MACRO      fprintf /**< Default fprintf macro to use, can be undefined */
-//#define MBEDTLS_PLATFORM_PRINTF_MACRO        printf /**< Default printf macro to use, can be undefined */
-/* Note: your snprintf must correctly zero-terminate the buffer! */
-//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO    snprintf /**< Default snprintf macro to use, can be undefined */
-//#define MBEDTLS_PLATFORM_VSNPRINTF_MACRO    vsnprintf /**< Default vsnprintf macro to use, can be undefined */
-//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO   mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
-//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO  mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
-
-/**
- * \brief       This macro is invoked by the library when an invalid parameter
- *              is detected that is only checked with MBEDTLS_CHECK_PARAMS
- *              (see the documentation of that option for context).
- *
- *              When you leave this undefined here, a default definition is
- *              provided that invokes the function mbedtls_param_failed(),
- *              which is declared in platform_util.h for the benefit of the
- *              library, but that you need to define in your application.
- *
- *              When you define this here, this replaces the default
- *              definition in platform_util.h (which no longer declares the
- *              function mbedtls_param_failed()) and it is your responsibility
- *              to make sure this macro expands to something suitable (in
- *              particular, that all the necessary declarations are visible
- *              from within the library - you can ensure that by providing
- *              them in this file next to the macro definition).
- *
- *              Note that you may define this macro to expand to nothing, in
- *              which case you don't have to worry about declarations or
- *              definitions. However, you will then be notified about invalid
- *              parameters only in non-void functions, and void function will
- *              just silently return early on invalid parameters, which
- *              partially negates the benefits of enabling
- *              #MBEDTLS_CHECK_PARAMS in the first place, so is discouraged.
- *
- * \param cond  The expression that should evaluate to true, but doesn't.
- */
-//#define MBEDTLS_PARAM_FAILED( cond )               assert( cond )
-
-/* SSL Cache options */
-//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT       86400 /**< 1 day  */
-//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES      50 /**< Maximum entries in cache */
-
-/* SSL options */
-
-/** \def MBEDTLS_SSL_MAX_CONTENT_LEN
- *
- * Maximum length (in bytes) of incoming and outgoing plaintext fragments.
- *
- * This determines the size of both the incoming and outgoing TLS I/O buffers
- * in such a way that both are capable of holding the specified amount of
- * plaintext data, regardless of the protection mechanism used.
- *
- * To configure incoming and outgoing I/O buffers separately, use
- * #MBEDTLS_SSL_IN_CONTENT_LEN and #MBEDTLS_SSL_OUT_CONTENT_LEN,
- * which overwrite the value set by this option.
- *
- * \note When using a value less than the default of 16KB on the client, it is
- *       recommended to use the Maximum Fragment Length (MFL) extension to
- *       inform the server about this limitation. On the server, there
- *       is no supported, standardized way of informing the client about
- *       restriction on the maximum size of incoming messages, and unless
- *       the limitation has been communicated by other means, it is recommended
- *       to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN
- *       while keeping the default value of 16KB for the incoming buffer.
- *
- * Uncomment to set the maximum plaintext size of both
- * incoming and outgoing I/O buffers.
- */
-//#define MBEDTLS_SSL_MAX_CONTENT_LEN             16384
-
-/** \def MBEDTLS_SSL_IN_CONTENT_LEN
- *
- * Maximum length (in bytes) of incoming plaintext fragments.
- *
- * This determines the size of the incoming TLS I/O buffer in such a way
- * that it is capable of holding the specified amount of plaintext data,
- * regardless of the protection mechanism used.
- *
- * If this option is undefined, it inherits its value from
- * #MBEDTLS_SSL_MAX_CONTENT_LEN.
- *
- * \note When using a value less than the default of 16KB on the client, it is
- *       recommended to use the Maximum Fragment Length (MFL) extension to
- *       inform the server about this limitation. On the server, there
- *       is no supported, standardized way of informing the client about
- *       restriction on the maximum size of incoming messages, and unless
- *       the limitation has been communicated by other means, it is recommended
- *       to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN
- *       while keeping the default value of 16KB for the incoming buffer.
- *
- * Uncomment to set the maximum plaintext size of the incoming I/O buffer
- * independently of the outgoing I/O buffer.
- */
-//#define MBEDTLS_SSL_IN_CONTENT_LEN              16384
-
-/** \def MBEDTLS_SSL_OUT_CONTENT_LEN
- *
- * Maximum length (in bytes) of outgoing plaintext fragments.
- *
- * This determines the size of the outgoing TLS I/O buffer in such a way
- * that it is capable of holding the specified amount of plaintext data,
- * regardless of the protection mechanism used.
- *
- * If this option undefined, it inherits its value from
- * #MBEDTLS_SSL_MAX_CONTENT_LEN.
- *
- * It is possible to save RAM by setting a smaller outward buffer, while keeping
- * the default inward 16384 byte buffer to conform to the TLS specification.
- *
- * The minimum required outward buffer size is determined by the handshake
- * protocol's usage. Handshaking will fail if the outward buffer is too small.
- * The specific size requirement depends on the configured ciphers and any
- * certificate data which is sent during the handshake.
- *
- * Uncomment to set the maximum plaintext size of the outgoing I/O buffer
- * independently of the incoming I/O buffer.
- */
-//#define MBEDTLS_SSL_OUT_CONTENT_LEN             16384
-
-/** \def MBEDTLS_SSL_DTLS_MAX_BUFFERING
- *
- * Maximum number of heap-allocated bytes for the purpose of
- * DTLS handshake message reassembly and future message buffering.
- *
- * This should be at least 9/8 * MBEDTLSSL_IN_CONTENT_LEN
- * to account for a reassembled handshake message of maximum size,
- * together with its reassembly bitmap.
- *
- * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default)
- * should be sufficient for all practical situations as it allows
- * to reassembly a large handshake message (such as a certificate)
- * while buffering multiple smaller handshake messages.
- *
- */
-//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING             32768
-
-//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME     86400 /**< Lifetime of session tickets (if enabled) */
-//#define MBEDTLS_PSK_MAX_LEN               32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */
-//#define MBEDTLS_SSL_COOKIE_TIMEOUT        60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */
-
-/**
- * Complete list of ciphersuites to use, in order of preference.
- *
- * \warning No dependency checking is done on that field! This option can only
- * be used to restrict the set of available ciphersuites. It is your
- * responsibility to make sure the needed modules are active.
- *
- * Use this to save a few hundred bytes of ROM (default ordering of all
- * available ciphersuites) and a few to a few hundred bytes of RAM.
- *
- * The value below is only an example, not the default.
- */
-//#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
-
-/* X509 options */
-//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA   8   /**< Maximum number of intermediate CAs in a verification chain. */
-//#define MBEDTLS_X509_MAX_FILE_PATH_LEN     512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */
-
-/**
- * Allow SHA-1 in the default TLS configuration for certificate signing.
- * Without this build-time option, SHA-1 support must be activated explicitly
- * through mbedtls_ssl_conf_cert_profile. Turning on this option is not
- * recommended because of it is possible to generate SHA-1 collisions, however
- * this may be safe for legacy infrastructure where additional controls apply.
- *
- * \warning   SHA-1 is considered a weak message digest and its use constitutes
- *            a security risk. If possible, we recommend avoiding dependencies
- *            on it, and considering stronger message digests instead.
- *
- */
-// #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES
-
-/**
- * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake
- * signature and ciphersuite selection. Without this build-time option, SHA-1
- * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes.
- * The use of SHA-1 in TLS <= 1.1 and in HMAC-SHA-1 is always allowed by
- * default. At the time of writing, there is no practical attack on the use
- * of SHA-1 in handshake signatures, hence this option is turned on by default
- * to preserve compatibility with existing peers, but the general
- * warning applies nonetheless:
- *
- * \warning   SHA-1 is considered a weak message digest and its use constitutes
- *            a security risk. If possible, we recommend avoiding dependencies
- *            on it, and considering stronger message digests instead.
- *
- */
-#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE
-
-/**
- * Uncomment the macro to let mbed TLS use your alternate implementation of
- * mbedtls_platform_zeroize(). This replaces the default implementation in
- * platform_util.c.
- *
- * mbedtls_platform_zeroize() is a widely used function across the library to
- * zero a block of memory. The implementation is expected to be secure in the
- * sense that it has been written to prevent the compiler from removing calls
- * to mbedtls_platform_zeroize() as part of redundant code elimination
- * optimizations. However, it is difficult to guarantee that calls to
- * mbedtls_platform_zeroize() will not be optimized by the compiler as older
- * versions of the C language standards do not provide a secure implementation
- * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to
- * configure their own implementation of mbedtls_platform_zeroize(), for
- * example by using directives specific to their compiler, features from newer
- * C standards (e.g using memset_s() in C11) or calling a secure memset() from
- * their system (e.g explicit_bzero() in BSD).
- */
-//#define MBEDTLS_PLATFORM_ZEROIZE_ALT
-
-/**
- * Uncomment the macro to let Mbed TLS use your alternate implementation of
- * mbedtls_platform_gmtime_r(). This replaces the default implementation in
- * platform_util.c.
- *
- * gmtime() is not a thread-safe function as defined in the C standard. The
- * library will try to use safer implementations of this function, such as
- * gmtime_r() when available. However, if Mbed TLS cannot identify the target
- * system, the implementation of mbedtls_platform_gmtime_r() will default to
- * using the standard gmtime(). In this case, calls from the library to
- * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex
- * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the
- * library are also guarded with this mutex to avoid race conditions. However,
- * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will
- * unconditionally use the implementation for mbedtls_platform_gmtime_r()
- * supplied at compile time.
- */
-//#define MBEDTLS_PLATFORM_GMTIME_R_ALT
-
-/* \} name SECTION: Customisation configuration options */
-
-/* Target and application specific configurations
- *
- * Allow user to override any previous default.
- *
- */
-#if defined(MBEDTLS_USER_CONFIG_FILE)
-#include MBEDTLS_USER_CONFIG_FILE
-#endif
-
-#include "mbedtls/check_config.h"
-
-#endif /* MBEDTLS_CONFIG_H */
diff --git a/third_party/mbedtls/repo/configs/config-suite-b.h b/third_party/mbedtls/repo/configs/config-suite-b.h
index 6eb03a9..9cad382 100644
--- a/third_party/mbedtls/repo/configs/config-suite-b.h
+++ b/third_party/mbedtls/repo/configs/config-suite-b.h
@@ -80,8 +80,7 @@
 #define MBEDTLS_AES_ROM_TABLES
 
 /* Save RAM by adjusting to our exact needs */
-#define MBEDTLS_ECP_MAX_BITS   384
-#define MBEDTLS_MPI_MAX_SIZE    48 // 384 bits is 48 bytes
+#define MBEDTLS_MPI_MAX_SIZE    48 // 48 bytes for a 384-bit elliptic curve
 
 /* Save RAM at the expense of speed, see ecp.h */
 #define MBEDTLS_ECP_WINDOW_SIZE        2
diff --git a/third_party/mbedtls/repo/configs/config-thread.h b/third_party/mbedtls/repo/configs/config-thread.h
index 47dd5e2..8464fcb 100644
--- a/third_party/mbedtls/repo/configs/config-thread.h
+++ b/third_party/mbedtls/repo/configs/config-thread.h
@@ -81,8 +81,7 @@
 #define MBEDTLS_AES_ROM_TABLES
 
 /* Save RAM by adjusting to our exact needs */
-#define MBEDTLS_ECP_MAX_BITS             256
-#define MBEDTLS_MPI_MAX_SIZE              32 // 256 bits is 32 bytes
+#define MBEDTLS_MPI_MAX_SIZE              32 // 32 bytes for a 256-bit elliptic curve
 
 /* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */
 #define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8
diff --git a/third_party/mbedtls/repo/docs/.gitignore b/third_party/mbedtls/repo/docs/.gitignore
index 33ae5ac..23f832b 100644
--- a/third_party/mbedtls/repo/docs/.gitignore
+++ b/third_party/mbedtls/repo/docs/.gitignore
@@ -1,3 +1,2 @@
 *.html
 *.pdf
-!PSACryptoDriverModelSpec.pdf
diff --git a/third_party/mbedtls/repo/docs/PSACryptoDriverModelSpec.pdf b/third_party/mbedtls/repo/docs/PSACryptoDriverModelSpec.pdf
deleted file mode 100644
index cf11380..0000000
--- a/third_party/mbedtls/repo/docs/PSACryptoDriverModelSpec.pdf
+++ /dev/null
Binary files differ
diff --git a/third_party/mbedtls/repo/docs/architecture/psa-crypto-implementation-structure.md b/third_party/mbedtls/repo/docs/architecture/psa-crypto-implementation-structure.md
new file mode 100644
index 0000000..cd4d427
--- /dev/null
+++ b/third_party/mbedtls/repo/docs/architecture/psa-crypto-implementation-structure.md
@@ -0,0 +1,73 @@
+PSA Cryptograpy API implementation and PSA driver interface
+===========================================================
+
+## Introduction
+
+The [PSA Cryptography API specification](https://armmbed.github.io/mbed-crypto/psa/#application-programming-interface) defines an interface to cryptographic operations for which the Mbed TLS library provides a reference implementation. The PSA Cryptography API specification is complemented by the PSA driver interface specification which defines an interface for cryptoprocessor drivers.
+
+This document describes the high level organization of the Mbed TLS PSA Cryptography API implementation which is tightly related to the PSA driver interface.
+
+## High level organization of the Mbed TLS PSA Cryptography API implementation
+In one sentence, the Mbed TLS PSA Cryptography API implementation is made of a core and PSA drivers as defined in the PSA driver interface. The key point is that software cryptographic operations are organized as PSA drivers: they interact with the core through the PSA driver interface.
+
+### Rationale
+
+* Addressing software and hardware cryptographic implementations through the same C interface reduces the core code size and its call graph complexity. The core and its dispatching to software and hardware implementations are consequently easier to test and validate.
+* The organization of the software cryptographic implementations in drivers promotes modularization of those implementations.
+* As hardware capabilities, software cryptographic functionalities can be described by a JSON driver description file as defined in the PSA driver interface.
+* Along with JSON driver description files, the PSA driver specification defines the deliverables for a driver to be included into the Mbed TLS PSA Cryptography implementation. This provides a natural framework to integrate third party or alternative software implementations of cryptographic operations.
+
+## The Mbed TLS PSA Cryptography API implementation core
+
+The core implements all the APIs as defined in the PSA Cryptography API specification but does not perform on its own any cryptographic operation. The core relies on PSA drivers to actually
+perform the cryptographic operations. The core is responsible for:
+
+* the key store.
+* checking PSA API arguments and translating them into valid arguments for the necessary calls to the PSA driver interface.
+* dispatching the cryptographic operations to the appropriate PSA drivers.
+
+The sketch of an Mbed TLS PSA cryptographic API implementation is thus:
+```C                                                                            
+psa_status_t psa_api( ... )
+{
+    psa_status_t status;
+
+    /* Pre driver interface call processing: validation of arguments, building
+     * of arguments for the call to the driver interface, ... */
+
+    ...
+
+    /* Call to the driver interface */
+    status = psa_driver_wrapper_<entry_point>( ... );
+    if( status != PSA_SUCCESS )
+        return( status );
+
+    /* Post driver interface call processing: validation of the values returned
+     * by the driver, finalization of the values to return to the caller,
+     * clean-up in case of error ... */
+}
+```
+The code of most PSA APIs is expected to match precisely the above layout. However, it is likely that the code structure of some APIs will be more complicated with several calls to the driver interface, mainly to encompass a larger variety of hardware designs. For example, to encompass hardware accelerators that are capable of verifying a MAC and those that are only capable of computing a MAC, the psa_mac_verify() API could call first psa_driver_wrapper_mac_verify() and then fallback to psa_driver_wrapper_mac_compute().
+
+The implementations of `psa_driver_wrapper_<entry_point>` functions are generated by the build system based on the JSON driver description files of the various PSA drivers making up the Mbed TLS PSA Cryptography API implementation. The implementations are generated in a psa_crypto_driver_wrappers.c C file and the function prototypes declared in a psa_crypto_driver_wrappers.h header file.
+
+The psa_driver_wrapper_<entry_point>() functions dispatch cryptographic operations to accelerator drivers, secure element drivers as well as to the software implementations of cryptographic operations.
+
+Note that the implementation allows to build the library with only a C compiler by shipping a generated file corresponding to a pure software implementation. The driver entry points and their code in this generated file are guarded by pre-processor directives based on PSA_WANT_xyz macros (see [Conditional inclusion of cryptographic mechanism through the PSA API in Mbed TLS](psa-conditional-inclusion-c.html). That way, it is possible to compile and include in the library only the desired cryptographic operations.
+
+### Key creation
+
+Key creation implementation in Mbed TLS PSA core is articulated around three internal functions: psa_start_key_creation(), psa_finish_key_creation() and psa_fail_key_creation(). Implementations of key creation PSA APIs, namely psa_import_key(), psa_generate_key(), psa_key_derivation_output_key() and psa_copy_key() go by the following sequence:
+    1. Check the input parameters.
+    2. Call psa_start_key_creation() that allocates a key slot, prepares it with the specified key attributes, and in case of a volatile key assign it a volatile key identifier.
+    3. Generate or copy the key material into the key slot. This entails the allocation of the buffer to store the key material.
+    4. Call psa_finish_key_creation() that mostly saves persistent keys into persistent storage.
+
+In case of any error occurring at step 3 or 4, psa_fail_key_creation() is called. It wipes and cleans the slot especially the key material: reset to zero of the RAM memory that contained the key material, free the allocated buffer.
+
+
+## Mbed TLS PSA Cryptography API implementation drivers
+
+A driver of the Mbed TLS PSA Cryptography API implementation (Mbed TLS PSA driver in the following) is a driver in the sense that it is compliant with the PSA driver interface specification. But it is not an actual driver that drives some hardware. It implements cryptographic operations purely in software.
+
+An Mbed TLS PSA driver C file is named psa_crypto_<driver_name>.c and its associated header file psa_crypto_<driver_name>.h. The functions implementing a driver entry point as defined in the PSA driver interface specification are named as mbedtls_psa_<driver name>_<entry point>(). As an example, the psa_crypto_rsa.c and psa_crypto_rsa.h are the files containing the Mbed TLS PSA driver implementing RSA cryptographic operations. This RSA driver implements among other entry points the "import_key" entry point. The function implementing this entry point is named mbedtls_psa_rsa_import_key().
diff --git a/third_party/mbedtls/repo/docs/architecture/testing/driver-interface-test-strategy.md b/third_party/mbedtls/repo/docs/architecture/testing/driver-interface-test-strategy.md
index d6769da..086fc1a 100644
--- a/third_party/mbedtls/repo/docs/architecture/testing/driver-interface-test-strategy.md
+++ b/third_party/mbedtls/repo/docs/architecture/testing/driver-interface-test-strategy.md
@@ -4,9 +4,19 @@
 
 The driver interfaces are standardized through PSA Cryptography functional specifications.
 
-## Secure element driver interface
+## Secure element driver interface testing
 
-The secure element driver interface (SE interface for short) is defined by [`psa/crypto_se_driver.h`](../../../include/psa/crypto_se_driver.h). This is an interface between Mbed Crypto and one or more third-party drivers.
+### Secure element driver interfaces
+
+#### Opaque driver interface
+
+The [unified driver interface](../../proposed/psa-driver-interface.md) supports both transparent drivers (for accelerators) and opaque drivers (for secure elements).
+
+Drivers exposing this interface need to be registered at compile time by declaring their JSON description file.
+
+#### Dynamic secure element driver interface
+
+The dynamic secure element driver interface (SE interface for short) is defined by [`psa/crypto_se_driver.h`](../../../include/psa/crypto_se_driver.h). This is an interface between Mbed Crypto and one or more third-party drivers.
 
 The SE interface consists of one function provided by Mbed Crypto (`psa_register_se_driver`) and many functions that drivers must implement. To make a driver usable by Mbed Crypto, the initialization code must call `psa_register_se_driver` with a structure that describes the driver. The structure mostly contains function pointers, pointing to the driver's methods. All calls to a driver function are triggered by a call to a PSA crypto API function.
 
@@ -18,6 +28,8 @@
 
 #### SE driver registration
 
+This applies to dynamic drivers only.
+
 * Test `psa_register_se_driver` with valid and with invalid arguments.
 * Make at least one failing call to `psa_register_se_driver` followed by a successful call.
 * Make at least one test that successfully registers the maximum number of drivers and fails to register one more.
@@ -102,14 +114,20 @@
 
 A PKCS#11 driver would be a good candidate. It would be useful as part of our product offering.
 
-## Accelerator driver interface
+## Transparent driver interface testing
 
-The accelerator driver interface is defined by [`psa/crypto_accel_driver.h`](../../../include/psa/crypto_accel_driver.h).
+The [unified driver interface](../../proposed/psa-driver-interface.md) defines interfaces for accelerators.
 
-TODO
+### Test requirements
 
-## Entropy driver interface
+#### Requirements for transparent driver testing
 
-The entropy driver interface is defined by [`psa/crypto_entropy_driver.h`](../../../include/psa/crypto_entropy_driver.h).
+Every cryptographic mechanism for which a transparent driver interface exists (key creation, cryptographic operations, …) must be exercised in at least one build. The test must verify that the driver code is called.
+
+#### Requirements for fallback
+
+The driver interface includes a fallback mechanism so that a driver can reject a request at runtime and let another driver handle the request. For each entry point, there must be at least three test runs with two or more drivers available with driver A configured to fall back to driver B, with one run where A returns `PSA_SUCCESS`, one where A returns `PSA_ERROR_NOT_SUPPORTED` and B is invoked, and one where A returns a different error and B is not invoked.
+
+## Entropy and randomness interface testing
 
 TODO
diff --git a/third_party/mbedtls/repo/docs/architecture/testing/psa-storage-format-testing.md b/third_party/mbedtls/repo/docs/architecture/testing/psa-storage-format-testing.md
new file mode 100644
index 0000000..e293985
--- /dev/null
+++ b/third_party/mbedtls/repo/docs/architecture/testing/psa-storage-format-testing.md
@@ -0,0 +1,127 @@
+# Mbed TLS PSA keystore format stability testing strategy
+
+## Introduction
+
+The PSA crypto subsystem includes a persistent key store. It is possible to create a persistent key and read it back later. This must work even if Mbed TLS has been upgraded in the meantime (except for deliberate breaks in the backward compatibility of the storage).
+
+The goal of this document is to define a test strategy for the key store that not only validates that it's possible to load a key that was saved with the version of Mbed TLS under test, but also that it's possible to load a key that was saved with previous versions of Mbed TLS.
+
+Interoperability is not a goal: PSA crypto implementations are not intended to have compatible storage formats. Downgrading is not required to work.
+
+## General approach
+
+### Limitations of a direct approach
+
+The goal of storage format stability testing is: as a user of Mbed TLS, I want to store a key under version V and read it back under version W, with W ≥ V.
+
+Doing the testing this way would be difficult because we'd need to have version V of Mbed TLS available when testing version W.
+
+An alternative, semi-direct approach consists of generating test data under version V, and reading it back under version W. Done naively, this would require keeping a large amount of test data (full test coverage multiplied by the number of versions that we want to preserve backward compatibility with).
+
+### Save-and-compare approach
+
+Importing and saving a key is deterministic. Therefore we can ensure the stability of the storage format by creating test cases under a version V of Mbed TLS, where the test case parameters include both the parameters to pass to key creation and the expected state of the storage after the key is created. The test case creates a key as indicated by the parameters, then compares the actual state of the storage with the expected state.
+
+In addition, the test case also loads the key and checks that it has the expected data and metadata. Import-and-save testing and load-and-check testing can be split into separate test functions with the same payloads.
+
+If the test passes with version V, this means that the test data is consistent with what the implementation does. When the test later runs under version W ≥ V, it creates and reads back a storage state which is known to be identical to the state that V would have produced. Thus, this approach validates that W can read storage states created by V.
+
+Note that it is the combination of import-and-save passing on version V and load-and-check passing on version W with the same data that proves that version W can read back what version V wrote. From the perspective of a particular version of the library, the import-and-save tests guarantee forward compatibility while the load-and-check tests guarantee backward compatibility.
+
+Use a similar approach for files other than keys where possible and relevant.
+
+### Keeping up with storage format evolution
+
+Test cases should normally not be removed from the code base: if something has worked before, it should keep working in future versions, so we should keep testing it.
+
+This cannot be enforced solely by looking at a single version of Mbed TLS, since there would be no indication that more test cases used to exist. It can only be enforced through review of library changes. The review may be assisted by a tool that compares the old and the new version, in the same way that `abi-check.py` compares the library's API and ABI.
+
+If the way certain keys are stored changes, and we don't deliberately decide to stop supporting old keys (which should only be done by retiring a version of the storage format), then we should keep the corresponding test cases in load-only mode: create a file with the expected content, load it and check the data that it contains.
+
+## Storage architecture overview
+
+The PSA subsystem provides storage on top of the PSA trusted storage interface. The state of the storage is a mapping from file identifer (a 64-bit number) to file content (a byte array). These files include:
+
+* [Key files](#key-storage) (files containing one key's metadata and, except for some secure element keys, key material).
+* The [random generator injected seed or state file](#random-generator-state) (`PSA_CRYPTO_ITS_RANDOM_SEED_UID`).
+* [Storage transaction file](#storage-transaction-resumption).
+* [Driver state files](#driver-state-files).
+
+For a more detailed description, refer to the [Mbed Crypto storage specification](../mbed-crypto-storage-specification.md).
+
+In addition, Mbed TLS includes an implementation of the PSA trusted storage interface on top of C stdio. This document addresses the test strategy for [PSA ITS over file](#psa-its-over-file) in a separate section below.
+
+## Key storage testing
+
+This section describes the desired test cases for keys created with the current storage format version. When the storage format changes, if backward compatibility is desired, old test data should be kept as described under [“Keeping up with storage format evolution”](#keeping-up-with-storage-format-evolution).
+
+### Keystore layout
+
+Objective: test that the key file name corresponds to the key identifier.
+
+Method: Create a key with a given identifier (using `psa_import_key`) and verify that a file with the expected name is created, and no other. Repeat for different identifiers.
+
+### General key format
+
+Objective: test the format of the key file: which field goes where and how big it is.
+
+Method: Create a key with certain metadata with `psa_import_key`. Read the file content and validate that it has the expected layout, deduced from the storage specification. Repeat with different metadata. Ensure that there are test cases covering all fields.
+
+### Enumeration of test cases for keys
+
+Objective: ensure that the coverage is sufficient to have assurance that all keys are stored correctly. This requires a sufficient selection of key types, sizes, policies, etc.
+
+In particular, the tests must validate that each `PSA_xxx` constant that is stored in a key is covered by at least one test case:
+
+* Lifetimes: `PSA_KEY_LIFETIME_xxx`, `PSA_KEY_PERSISTENCE_xxx`, `PSA_KEY_LOCATION_xxx`.
+* Usage flags: `PSA_KEY_USAGE_xxx`.
+* Algorithms in policies: `PSA_ALG_xxx`.
+* Key types: `PSA_KEY_TYPE_xxx`, `PSA_ECC_FAMILY_xxx`, `PSA_DH_FAMILY_xxx`.
+
+In addition, the coverage of key material must ensure that any variation in key representation is detected. See [“Considerations on key material representations”](#Considerations-on-key-material-representations) for considerations regarding key types.
+
+Method: Each test case creates a key with `psa_import_key`, purges it from memory, then reads it back and exercises it.
+
+Generate test cases automatically based on an enumeration of available constants and some knowledge of what attributes (sizes, algorithms, …) and content to use for keys of a certain type.
+
+### Testing with alternative lifetime values
+
+Objective: have test coverage for lifetimes other than the default persistent lifetime (`PSA_KEY_LIFETIME_PERSISTENT`).
+
+Method:
+
+* For alternative locations: have tests conditional on the presence of a driver for that location.
+* For alternative persistence levels: have load-and-check tests for supported persistence levels. We may also want to have negative tests ensuring that keys with a not-supported persistence level are not accidentally created.
+
+### Considerations on key material representations
+
+The risks of incompatibilities in key representations depends on the key type and on the presence of drivers. Compatibility of and with drivers is currently out of scope of this document.
+
+Some types only have one plausible representation. Others admit alternative plausible representations (different encodings, or non-canonical representations).
+Here are some areas to watch for, with an identified risk of incompatibilities.
+
+* HMAC keys longer than the block size: pre-hashed or not?
+* DES keys: was parity enforced?
+* RSA keys: can invalid DER encodings (e.g. leading zeros, ignored sign bit) have been stored?
+* RSA private keys: can invalid CRT parameters have been stored?
+* Montgomery private keys: were they stored in masked form?
+
+## Random generator state
+
+TODO
+
+## Driver state files
+
+Not yet implemented.
+
+TODO
+
+## Storage transaction resumption
+
+Only relevant for secure element support. Not yet fully implemented.
+
+TODO
+
+## PSA ITS over file
+
+TODO
diff --git a/third_party/mbedtls/repo/docs/architecture/tls13-experimental.md b/third_party/mbedtls/repo/docs/architecture/tls13-experimental.md
index 3db16e0..10cbfa1 100644
--- a/third_party/mbedtls/repo/docs/architecture/tls13-experimental.md
+++ b/third_party/mbedtls/repo/docs/architecture/tls13-experimental.md
@@ -47,3 +47,22 @@
   Those functions are implemented in `library/ssl_tls13_keys.c` and
   tested in `test_suite_ssl` using test vectors from RFC 8448 and
   https://tls13.ulfheim.net/.
+
+- New TLS Message Processing Stack (MPS)
+
+  The TLS 1.3 prototype is developed alongside a rewrite of the TLS messaging layer,
+  encompassing low-level details such as record parsing, handshake reassembly, and
+  DTLS retransmission state machine.
+
+  MPS has the following components:
+  - Layer 1 (Datagram handling)
+  - Layer 2 (Record handling)
+  - Layer 3 (Message handling)
+  - Layer 4 (Retransmission State Machine)
+  - Reader  (Abstracted pointer arithmetic and reassembly logic for incoming data)
+  - Writer  (Abstracted pointer arithmetic and fragmentation logic for outgoing data)
+
+  Of those components, the following have been upstreamed
+  as part of `MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL`:
+
+  - Reader ([`library/mps_reader.h`](../../library/mps_reader.h))
diff --git a/third_party/mbedtls/repo/docs/getting_started.md b/third_party/mbedtls/repo/docs/getting_started.md
index 15d5a31..fdbf0e9 100644
--- a/third_party/mbedtls/repo/docs/getting_started.md
+++ b/third_party/mbedtls/repo/docs/getting_started.md
@@ -76,7 +76,7 @@
 {
     psa_status_t status;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_id_t key;
+    psa_key_id_t key_id;
 
     printf("Import an AES key...\t");
     fflush(stdout);
@@ -95,7 +95,7 @@
     psa_set_key_bits(&attributes, 128);
 
     /* Import the key */
-    status = psa_import_key(&attributes, key, key_len, &key);
+    status = psa_import_key(&attributes, key, key_len, &key_id);
     if (status != PSA_SUCCESS) {
         printf("Failed to import key\n");
         return;
@@ -106,7 +106,7 @@
     psa_reset_key_attributes(&attributes);
 
     /* Destroy the key */
-    psa_destroy_key(key);
+    psa_destroy_key(key_id);
 
     mbedtls_psa_crypto_free();
 }
@@ -135,7 +135,7 @@
                         0xa9, 0xe8, 0xcc, 0xac, 0xd0, 0xf6, 0x54, 0x5c};
     uint8_t signature[PSA_SIGNATURE_MAX_SIZE] = {0};
     size_t signature_length;
-    psa_key_id_t key;
+    psa_key_id_t key_id;
 
     printf("Sign a message...\t");
     fflush(stdout);
@@ -154,14 +154,14 @@
     psa_set_key_bits(&attributes, 1024);
 
     /* Import the key */
-    status = psa_import_key(&attributes, key, key_len, &key);
+    status = psa_import_key(&attributes, key, key_len, &key_id);
     if (status != PSA_SUCCESS) {
         printf("Failed to import key\n");
         return;
     }
 
     /* Sign message using the key */
-    status = psa_sign_hash(key, PSA_ALG_RSA_PKCS1V15_SIGN_RAW,
+    status = psa_sign_hash(key_id, PSA_ALG_RSA_PKCS1V15_SIGN_RAW,
                            hash, sizeof(hash),
                            signature, sizeof(signature),
                            &signature_length);
@@ -176,7 +176,7 @@
     psa_reset_key_attributes(&attributes);
 
     /* Destroy the key */
-    psa_destroy_key(key);
+    psa_destroy_key(key_id);
 
     mbedtls_psa_crypto_free();
 }
@@ -203,7 +203,7 @@
 void encrypt_with_symmetric_ciphers(const uint8_t *key, size_t key_len)
 {
     enum {
-        block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES),
+        block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES),
     };
     psa_status_t status;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -213,7 +213,7 @@
     size_t iv_len;
     uint8_t output[block_size];
     size_t output_len;
-    psa_key_id_t key;
+    psa_key_id_t key_id;
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
 
     printf("Encrypt with cipher...\t");
@@ -232,7 +232,7 @@
     psa_set_key_algorithm(&attributes, alg);
     psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
     psa_set_key_bits(&attributes, 128);
-    status = psa_import_key(&attributes, key, key_len, &key);
+    status = psa_import_key(&attributes, key, key_len, &key_id);
     if (status != PSA_SUCCESS) {
         printf("Failed to import a key\n");
         return;
@@ -240,7 +240,7 @@
     psa_reset_key_attributes(&attributes);
 
     /* Encrypt the plaintext */
-    status = psa_cipher_encrypt_setup(&operation, key, alg);
+    status = psa_cipher_encrypt_setup(&operation, key_id, alg);
     if (status != PSA_SUCCESS) {
         printf("Failed to begin cipher operation\n");
         return;
@@ -268,7 +268,7 @@
     psa_cipher_abort(&operation);
 
     /* Destroy the key */
-    psa_destroy_key(key);
+    psa_destroy_key(key_id);
 
     mbedtls_psa_crypto_free();
 }
@@ -288,7 +288,7 @@
 void decrypt_with_symmetric_ciphers(const uint8_t *key, size_t key_len)
 {
     enum {
-        block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES),
+        block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES),
     };
     psa_status_t status;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -298,7 +298,7 @@
     uint8_t iv[block_size] = ENCRYPTED_WITH_IV;
     uint8_t output[block_size];
     size_t output_len;
-    psa_key_id_t key;
+    psa_key_id_t key_id;
 
     printf("Decrypt with cipher...\t");
     fflush(stdout);
@@ -316,7 +316,7 @@
     psa_set_key_algorithm(&attributes, alg);
     psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
     psa_set_key_bits(&attributes, 128);
-    status = psa_import_key(&attributes, key, key_len, &key);
+    status = psa_import_key(&attributes, key, key_len, &key_id);
     if (status != PSA_SUCCESS) {
         printf("Failed to import a key\n");
         return;
@@ -324,7 +324,7 @@
     psa_reset_key_attributes(&attributes);
 
     /* Decrypt the ciphertext */
-    status = psa_cipher_decrypt_setup(&operation, key, alg);
+    status = psa_cipher_decrypt_setup(&operation, key_id, alg);
     if (status != PSA_SUCCESS) {
         printf("Failed to begin cipher operation\n");
         return;
@@ -352,7 +352,7 @@
     psa_cipher_abort(&operation);
 
     /* Destroy the key */
-    psa_destroy_key(key);
+    psa_destroy_key(key_id);
 
     mbedtls_psa_crypto_free();
 }
@@ -445,7 +445,7 @@
         0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
         0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
     };
-    size_t expected_hash_len = PSA_HASH_SIZE(alg);
+    size_t expected_hash_len = PSA_HASH_LENGTH(alg);
 
     printf("Verify a hash...\t");
     fflush(stdout);
@@ -482,7 +482,7 @@
     mbedtls_psa_crypto_free();
 ```
 
-The API provides the macro `PSA_HASH_SIZE`, which returns the expected hash length (in bytes) for the specified algorithm.
+The API provides the macro `PSA_HASH_LENGTH`, which returns the expected hash length (in bytes) for the specified algorithm.
 
 #### Handling hash operation contexts
 
@@ -702,7 +702,7 @@
     size_t output_length = 0;
     size_t tag_length = 16;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_id_t key;
+    psa_key_id_t key_id;
 
     printf("Authenticate encrypt...\t");
     fflush(stdout);
@@ -726,11 +726,11 @@
     psa_set_key_algorithm(&attributes, PSA_ALG_CCM);
     psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
     psa_set_key_bits(&attributes, 128);
-    status = psa_import_key(&attributes, key, sizeof(key), &key);
+    status = psa_import_key(&attributes, key, sizeof(key), &key_id);
     psa_reset_key_attributes(&attributes);
 
     /* Authenticate and encrypt */
-    status = psa_aead_encrypt(key, PSA_ALG_CCM,
+    status = psa_aead_encrypt(key_id, PSA_ALG_CCM,
                               nonce, sizeof(nonce),
                               additional_data, sizeof(additional_data),
                               input_data, sizeof(input_data),
@@ -747,7 +747,7 @@
     free(output_data);
 
     /* Destroy the key */
-    psa_destroy_key(key);
+    psa_destroy_key(key_id);
 
     mbedtls_psa_crypto_free();
 ```
@@ -773,7 +773,7 @@
     size_t output_size = 0;
     size_t output_length = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_id_t key;
+    psa_key_id_t key_id;
 
     printf("Authenticate decrypt...\t");
     fflush(stdout);
@@ -797,7 +797,7 @@
     psa_set_key_algorithm(&attributes, PSA_ALG_CCM);
     psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
     psa_set_key_bits(&attributes, 128);
-    status = psa_import_key(&attributes, key_data, sizeof(key_data), &key);
+    status = psa_import_key(&attributes, key_data, sizeof(key_data), &key_id);
     if (status != PSA_SUCCESS) {
         printf("Failed to import a key\n");
         return;
@@ -805,7 +805,7 @@
     psa_reset_key_attributes(&attributes);
 
     /* Authenticate and decrypt */
-    status = psa_aead_decrypt(key, PSA_ALG_CCM,
+    status = psa_aead_decrypt(key_id, PSA_ALG_CCM,
                               nonce, sizeof(nonce),
                               additional_data, sizeof(additional_data),
                               input_data, sizeof(input_data),
@@ -822,7 +822,7 @@
     free(output_data);
 
     /* Destroy the key */
-    psa_destroy_key(key);
+    psa_destroy_key(key_id);
 
     mbedtls_psa_crypto_free();
 ```
@@ -848,7 +848,7 @@
     size_t exported_length = 0;
     static uint8_t exported[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits)];
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_id_t key;
+    psa_key_id_t key_id;
 
     printf("Generate a key pair...\t");
     fflush(stdout);
@@ -867,14 +867,14 @@
     psa_set_key_type(&attributes,
                      PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
     psa_set_key_bits(&attributes, key_bits);
-    status = psa_generate_key(&attributes, &key);
+    status = psa_generate_key(&attributes, &key_id);
     if (status != PSA_SUCCESS) {
         printf("Failed to generate key\n");
         return;
     }
     psa_reset_key_attributes(&attributes);
 
-    status = psa_export_public_key(key, exported, sizeof(exported),
+    status = psa_export_public_key(key_id, exported, sizeof(exported),
                                    &exported_length);
     if (status != PSA_SUCCESS) {
         printf("Failed to export public key %ld\n", status);
@@ -884,7 +884,7 @@
     printf("Exported a public key\n");
 
     /* Destroy the key */
-    psa_destroy_key(key);
+    psa_destroy_key(key_id);
 
     mbedtls_psa_crypto_free();
 ```
diff --git a/third_party/mbedtls/repo/docs/proposed/psa-conditional-inclusion-c.md b/third_party/mbedtls/repo/docs/proposed/psa-conditional-inclusion-c.md
index 52138b1..2ddba7f 100644
--- a/third_party/mbedtls/repo/docs/proposed/psa-conditional-inclusion-c.md
+++ b/third_party/mbedtls/repo/docs/proposed/psa-conditional-inclusion-c.md
@@ -5,8 +5,6 @@
 
 This is currently a proposal for Mbed TLS. It is not currently on track for standardization in PSA.
 
-Time-stamp: "2020/11/26 09:30:50 GMT"
-
 ## Introduction
 
 ### Purpose of this specification
@@ -86,9 +84,17 @@
 
 For asymmetric cryptography, `PSA_WANT_KEY_TYPE_xxx_KEY_PAIR` determines whether private-key operations are desired, and `PSA_WANT_KEY_TYPE_xxx_PUBLIC_KEY` determines whether public-key operations are desired. `PSA_WANT_KEY_TYPE_xxx_KEY_PAIR` implicitly enables `PSA_WANT_KEY_TYPE_xxx_PUBLIC_KEY`: there is no way to only include private-key operations (which typically saves little code).
 
-#### Configuration symbols for curves
+#### Configuration symbols for elliptic curves
 
-For elliptic curve key types, only the specified curves are included. To include a curve, include a symbol of the form **`PSA_WANT_ECC_family_size`**. For example: `PSA_WANT_ECC_SECP_R1_256` for secp256r1, `PSA_WANT_ECC_MONTGOMERY_CURVE25519`. It is an error to require an ECC key type but no curve, and Mbed TLS will reject this at compile time.
+For elliptic curve key types, only the specified curves are included. To include a curve, include a symbol of the form **`PSA_WANT_ECC_family_size`**. For example: `PSA_WANT_ECC_SECP_R1_256` for secp256r1, `PSA_WANT_ECC_MONTGOMERY_255` for Curve25519. It is an error to require an ECC key type but no curve, and Mbed TLS will reject this at compile time.
+
+Rationale: this is a deviation of the general principle that `PSA_ECC_FAMILY_xxx` would have a corresponding symbol `PSA_WANT_ECC_FAMILY_xxx`. This deviation is justified by the fact that it is very common to wish to include only certain curves in a family, and that can lead to a significant gain in code size.
+
+#### Configuration symbols for Diffie-Hellman groups
+
+There are no configuration symbols for Diffie-Hellman groups (`PSA_DH_GROUP_xxx`).
+
+Rationale: Finite-field Diffie-Hellman code is usually not specialized for any particular group, so reducing the number of available groups at compile time only saves a little code space. Constrained implementations tend to omit FFDH anyway, so the small code size gain is not important.
 
 #### Configuration symbols for algorithms
 
@@ -195,7 +201,7 @@
 
 #### Naming of symbols
 
-The names of [elliptic curve symbols](#configuration-symbols-for-curves) are a bit weird: `SECP_R1_256` instead of `SECP256R1`. Should we make them more classical, but less systematic?
+The names of [elliptic curve symbols](#configuration-symbols-for-elliptic-curves) are a bit weird: `SECP_R1_256` instead of `SECP256R1`, `MONTGOMERY_255` instead of `CURVE25519`. Should we make them more classical, but less systematic?
 
 #### Impossible combinations
 
diff --git a/third_party/mbedtls/repo/docs/proposed/psa-driver-interface.md b/third_party/mbedtls/repo/docs/proposed/psa-driver-interface.md
index d825794..23274c7 100644
--- a/third_party/mbedtls/repo/docs/proposed/psa-driver-interface.md
+++ b/third_party/mbedtls/repo/docs/proposed/psa-driver-interface.md
@@ -5,8 +5,6 @@
 
 This specification is work in progress and should be considered to be in a beta stage. There is ongoing work to implement this interface in Mbed TLS, which is the reference implementation of the PSA Cryptography API. At this stage, Arm does not expect major changes, but minor changes are expected based on experience from the first implementation and on external feedback.
 
-Time-stamp: "2020/11/24 11:03:32 GMT"
-
 ## Introduction
 
 ### Purpose of the driver interface
@@ -136,7 +134,7 @@
     "entry_points": ["sign_hash"],
     "algorithms": ["PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)",
                    "PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384)"],
-    "key_types": ["PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1)"],
+    "key_types": ["PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)"],
     "key_sizes": [256, 384]
 }
 ```
@@ -166,7 +164,7 @@
 Valid examples:
 ```
 PSA_KEY_TYPE_AES
-PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1)
+PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)
 PSA_KEY_TYPE_ECC_KEY_PAIR(_)
 ```
 
@@ -196,6 +194,8 @@
 
 Some entry points are grouped in families that must be implemented as a whole. If a driver supports an entry point family, it must provide all the entry points in the family.
 
+Drivers can also have entry points related to random generation. A transparent driver can provide a [random generation interface](#random-generation-entry-points). Separately, transparent and opaque drivers can have [entropy collection entry points](#entropy-collection-entry-point).
+
 #### General considerations on driver entry point parameters
 
 Buffer parameters for driver entry points obey the following conventions:
@@ -375,6 +375,49 @@
 * For elliptic curve private keys (`PSA_KEY_TYPE_ECC_KEY_PAIR`), check the size and range. TODO: what else?
 * For elliptic curve public keys (`PSA_KEY_TYPE_ECC_PUBLIC_KEY`), check the size and range, and that the point is on the curve. TODO: what else?
 
+### Entropy collection entry point
+
+A driver can declare an entropy source by providing a `"get_entropy"` entry point. This entry point has the following prototype for a driver with the prefix `"acme"`:
+
+```
+psa_status_t acme_get_entropy(uint32_t flags,
+                              size_t *estimate_bits,
+                              uint8_t *output,
+                              size_t output_size);
+```
+
+The semantics of the parameters is as follows:
+
+* `flags`: a bit-mask of [entropy collection flags](#entropy-collection-flags).
+* `estimate_bits`: on success, an estimate of the amount of entropy that is present in the `output` buffer, in bits. This must be at least `1` on success. The value is ignored on failure. Drivers should return a conservative estimate, even in circumstances where the quality of the entropy source is degraded due to environmental conditions (e.g. undervolting, low temperature, etc.).
+* `output`: on success, this buffer contains non-deterministic data with an estimated entropy of at least `*estimate_bits` bits. When the entropy is coming from a hardware peripheral, this should preferably be raw or lightly conditioned measurements from a physical process, such that statistical tests run over a sufficiently large amount of output can confirm the entropy estimates. But this specification also permits entropy sources that are fully conditioned, for example when the PSA Cryptography system is running as an application in an operating system and `"get_entropy"` returns data from the random generator in the operating system's kernel.
+* `output_size`: the size of the `output` buffer in bytes. This size should be large enough to allow a driver to pass unconditioned data with a low density of entropy; for example a peripheral that returns eight bytes of data with an estimated one bit of entropy cannot provide meaningful output in less than 8 bytes.
+
+Note that there is no output parameter indicating how many bytes the driver wrote to the buffer. Such an output length indication is not necessary because the entropy may be located anywhere in the buffer, so the driver may write less than `output_size` bytes but the core does not need to know this. The output parameter `estimate_bits` contains the amount of entropy, expressed in bits, which may be significantly less than `output_size * 8`.
+
+The entry point may return the following statuses:
+
+* `PSA_SUCCESS`: success. The output buffer contains some entropy.
+* `PSA_ERROR_INSUFFICIENT_ENTROPY`: no entropy is available without blocking. This is only permitted if the `PSA_DRIVER_GET_ENTROPY_BLOCK` flag is clear. The core may call `get_entropy` again later, giving time for entropy to be gathered or for adverse environmental conditions to be rectified.
+* Other error codes indicate a transient or permanent failure of the entropy source.
+
+Unlike most other entry points, if multiple transparent drivers include a `"get_entropy"` point, the core will call all of them (as well as the entry points from opaque drivers). Fallback is not applicable to `"get_entropy"`.
+
+#### Entropy collection flags
+
+* `PSA_DRIVER_GET_ENTROPY_BLOCK`: If this flag is set, the driver should block until it has at least one bit of entropy. If this flag is clear, the driver should avoid blocking if no entropy is readily available.
+* `PSA_DRIVER_GET_ENTROPY_KEEPALIVE`: This flag is intended to help with energy management for entropy-generating peripherals. If this flag is set, the driver should expect another call to `acme_get_entropy` after a short time. If this flag is clear, the core is not expecting to call the `"get_entropy"` entry point again within a short amount of time (but it may do so nonetheless).
+
+#### Entropy collection and blocking
+
+The intent of the `BLOCK` and `KEEPALIVE` [flags](#entropy-collection-flags) is to support drivers for TRNG (True Random Number Generator, i.e. an entropy source peripheral) that have a long ramp-up time, especially on platforms with multiple entropy sources.
+
+Here is a suggested call sequence for entropy collection that leverages these flags:
+
+1. The core makes a first round of calls to `"get_entropy"` on every source with the `BLOCK` flag clear and the `KEEPALIVE` flag set, so that drivers can prepare the TRNG peripheral.
+2. The core makes a second round of calls with the `BLOCK` flag set and the `KEEPALIVE` flag clear to gather needed entropy.
+3. If the second round does not collect enough entropy, the core makes more similar rounds, until the total amount of collected entropy is sufficient.
+
 ### Miscellaneous driver entry points
 
 #### Driver initialization
@@ -428,6 +471,109 @@
 3. [Determine the key size](#key-size-determination-on-import) and output it through `*bits`.
 4. Copy the validated key data from `data` to `key_buffer`. The output must be in the canonical format documented for [`psa_export_key()`](https://armmbed.github.io/mbed-crypto/html/api/keys/management.html#c.psa_export_key) or [`psa_export_public_key()`](https://armmbed.github.io/mbed-crypto/html/api/keys/management.html#c.psa_export_public_key), so if the input is not in this format, the entry point must convert it.
 
+### Random generation entry points
+
+A transparent driver may provide an operation family that can be used as a cryptographic random number generator. The random generation mechanism must obey the following requirements:
+
+* The random output must be of cryptographic quality, with a uniform distribution. Therefore, if the random generator includes an entropy source, this entropy source must be fed through a CSPRNG (cryptographically secure pseudo-random number generator).
+* Random generation is expected to be fast. (If a device can provide entropy but is slow at generating random data, declare it as an [entropy driver](#entropy-collection-entry-point) instead.)
+* The random generator should be able to incorporate entropy provided by an outside source. If it isn't, the random generator can only be used if it's the only entropy source on the platform. (A random generator peripheral can be declared as an [entropy source](#entropy-collection-entry-point) instead of a random generator; this way the core will combine it with other entropy sources.)
+* The random generator may either be deterministic (in the sense that it always returns the same data when given the same entropy inputs) or non-deterministic (including its own entropy source). In other words, this interface is suitable both for PRNG (pseudo-random number generator, also known as DRBG (deterministic random bit generator)) and for NRBG (non-deterministic random bit generator).
+
+If no driver implements the random generation entry point family, the core provides an unspecified random generation mechanism.
+
+This operation family requires the following type, entry points and parameters (TODO: where exactly are the parameters in the JSON structure?):
+
+* Type `"random_context_t"`: the type of a random generation context.
+* `"init_random"` (entry point, optional): if this function is present, [the core calls it once](#random-generator-initialization) after allocating a `"random_context_t"` object.
+* `"add_entropy"` (entry point, optional): the core calls this function to [inject entropy](#entropy-injection). This entry point is optional if the driver is for a peripheral that includes an entropy source of its own, however [random generator drivers without entropy injection](#random-generator-drivers-without-entropy-injection) have limited portability since they can only be used on platforms with no other entropy source. This entry point is mandatory if `"initial_entropy_size"` is nonzero.
+* `"get_random"` (entry point, mandatory): the core calls this function whenever it needs to [obtain random data](#the-get_random-entry-point).
+* `"initial_entropy_size"` (integer, mandatory): the minimum number of bytes of entropy that the core must supply before the driver can output random data. This can be `0` if the driver is for a peripheral that includes an entropy source of its own.
+* `"reseed_entropy_size"` (integer, optional): the minimum number of bytes of entropy that the core should supply via [`"add_entropy"`](#entropy-injection) when the driver runs out of entropy. This value is also a hint for the size to supply if the core makes additional calls to `"add_entropy"`, for example to enforce prediction resistance. If omitted, the core should pass an amount of entropy corresponding to the expected security strength of the device (for example, pass 32 bytes of entropy when reseeding to achieve a security strength of 256 bits). If specified, the core should pass the larger of `"reseed_entropy_size"` and the amount corresponding to the security strength.
+
+Random generation is not parametrized by an algorithm. The choice of algorithm is up to the driver.
+
+#### Random generator initialization
+
+The `"init_random"` entry point has the following prototype for a driver with the prefix `"acme"`:
+
+```
+psa_status_t acme_init_random(acme_random_context_t *context);
+```
+
+The core calls this entry point once after allocating a random generation context. Initially, the context object is all-bits-zero.
+
+If a driver does not have an `"init_random"` entry point, the context object passed to the first call to `"add_entropy"` or `"get_random"` will be all-bits-zero.
+
+#### Entropy injection
+
+The `"add_entropy"` entry point has the following prototype for a driver with the prefix `"acme"`:
+
+```
+psa_status_t acme_add_entropy(acme_random_context_t *context,
+                              const uint8_t *entropy,
+                              size_t entropy_size);
+```
+
+The semantics of the parameters is as follows:
+
+* `context`: a random generation context. On the first call to `"add_entropy"`, this object has been initialized by a call to the driver's `"init_random"` entry point if one is present, and to all-bits-zero otherwise.
+* `entropy`: a buffer containing full-entropy data to seed the random generator. “Full-entropy” means that the data is uniformly distributed and independent of any other observable quantity.
+* `entropy_size`: the size of the `entropy` buffer in bytes. It is guaranteed to be at least `1`, but it may be smaller than the amount of entropy that the driver needs to deliver random data, in which case the core will call the `"add_entropy"` entry point again to supply more entropy.
+
+The core calls this function to supply entropy to the driver. The driver must mix this entropy into its internal state. The driver must mix the whole supplied entropy, even if there is more than what the driver requires, to ensure that all entropy sources are mixed into the random generator state. The driver may mix additional entropy of its own.
+
+The core may call this function at any time. For example, to enforce prediction resistance, the core can call `"add_entropy"` immediately after each call to `"get_random"`. The core must call this function in two circumstances:
+
+* Before the first call to the `"get_random"` entry point, to supply `"initial_entropy_size"` bytes of entropy.
+* After a call to the `"get_random"` entry point returns less than the required amount of random data, to supply at least `"reseed_entropy_size"` bytes of entropy.
+
+When the driver requires entropy, the core can supply it with one or more successive calls to the `"add_entropy"` entry point. If the required entropy size is zero, the core does not need to call `"add_entropy"`.
+
+#### Combining entropy sources with a random generation driver
+
+This section provides guidance on combining one or more [entropy sources](#entropy-collection-entry-point) (each having a `"get_entropy"` entry point) with a random generation driver (with an `"add_entropy"` entry point).
+
+Note that `"get_entropy"` returns data with an estimated amount of entropy that is in general less than the buffer size. The core must apply a mixing algorithm to the output of `"get_entropy"` to obtain full-entropy data.
+
+For example, the core may use a simple mixing scheme based on a pseudorandom function family $(F_k)$ with an $E$-bit output where $E = 8 \cdot \mathtt{entropy_size}$ and $\mathtt{entropy_size}$ is the desired amount of entropy in bytes (typically the random driver's `"initial_entropy_size"` property for the initial seeding and the `"reseed_entropy_size"` property for subsequent reseeding). The core calls the `"get_entropy"` points of the available entropy drivers, outputting a string $s_i$ and an entropy estimate $e_i$ on the $i$th call. It does so until the total entropy estimate $e_1 + e_2 + \ldots + e_n$ is at least $E$. The core then calculates $F_k(0)$ where $k = s_1 || s_2 || \ldots || s_n$. This value is a string of $\mathtt{entropy_size}$, and since $(F_k)$ is a pseudorandom function family, $F_k(0)$ is uniformly distributed over strings of $\mathtt{entropy_size}$ bytes. Therefore $F_k(0)$ is a suitable value to pass to `"add_entropy"`.
+
+Note that the mechanism above is only given as an example. Implementations may choose a different mechanism, for example involving multiple pools or intermediate compression functions.
+
+#### Random generator drivers without entropy injection
+
+Random generator drivers should have the capability to inject additional entropy through the `"add_entropy"` entry point. This ensures that the random generator depends on all the entropy sources that are available on the platform. A driver where a call to `"add_entropy"` does not affect the state of the random generator is not compliant with this specification.
+
+However, a driver may omit the `"add_entropy"` entry point. This limits the driver's portability: implementations of the PSA Cryptography specification may reject drivers without an `"add_entropy"` entry point, or only accept such drivers in certain configurations. In particular, the `"add_entropy"` entry point is required if:
+
+* the integration of PSA Cryptography includes an entropy source that is outside the driver; or
+* the core saves random data in persistent storage to be preserved across platform resets.
+
+#### The `"get_random"` entry point
+
+The `"get_random"` entry point has the following prototype for a driver with the prefix `"acme"`:
+
+```
+psa_status_t acme_get_random(acme_random_context_t *context,
+                             uint8_t *output,
+                             size_t output_size,
+                             size_t *output_length);
+```
+
+The semantics of the parameters is as follows:
+
+* `context`: a random generation context. If the driver's `"initial_entropy_size"` property is nonzero, the core must have called `"add_entropy"` at least once with a total of at least `"initial_entropy_size"` bytes of entropy before it calls `"get_random"`. Alternatively, if the driver's `"initial_entropy_size"` property is zero and the core did not call `"add_entropy"`, or if the driver has no `"add_entropy"` entry point, the core must have called `"init_random"` if present, and otherwise the context is all-bits zero.
+* `output`: on success (including partial success), the first `*output_length` bytes of this buffer contain cryptographic-quality random data. The output is not used on error.
+* `output_size`: the size of the `output` buffer in bytes.
+* `*output_length`: on success (including partial success), the number of bytes of random data that the driver has written to the `output` buffer. This is preferably `output_size`, but the driver is allowed to return less data if it runs out of entropy as described below. The core sets this value to 0 on entry. The value is not used on error.
+
+The driver may return the following status codes:
+
+* `PSA_SUCCESS`: the `output` buffer contains `*output_length` bytes of cryptographic-quality random data. Note that this may be less than `output_size`; in this case the core should call the driver's `"add_entropy"` method to supply at least `"reseed_entropy_size"` bytes of entropy before calling `"get_random"` again.
+* `PSA_ERROR_INSUFFICIENT_ENTROPY`: the core must supply additional entropy by calling the `"add_entropy"` entry point with at least `"reseed_entropy_size"` bytes.
+* `PSA_ERROR_NOT_SUPPORTED`: the random generator is not available. This is only permitted if the driver specification for random generation has the [fallback property](#fallback) enabled.
+* Other error codes such as `PSA_ERROR_COMMUNICATION_FAILURE` or `PSA_ERROR_HARDWARE_FAILURE` indicate a transient or permanent error.
+
 ### Fallback
 
 Sometimes cryptographic accelerators only support certain cryptographic mechanisms partially. The capability description language allows specifying some restrictions, including restrictions on key sizes, but it cannot cover all the possibilities that may arise in practice. Furthermore, it may be desirable to deploy the same binary image on different devices, only some of which have a cryptographic accelerators.
@@ -460,7 +606,8 @@
 * `"public_key_size"` (integer or string, optional): this many bytes are included in every key context for a public key. If omitted, this value defaults to 0.
 * `"symmetric_factor"` (integer or string, optional): every key context for a symmetric key includes this many times the key size. If omitted, this value defaults to 0.
 * `"store_public_key"` (boolean, optional): If specified and true, for a key pair, the key context includes space for the public key. If omitted or false, no additional space is added for the public key.
-* `"size_function"` (string, optional): the name of a function that returns the number of bytes that the driver needs in a key context for a key. This may be a pointer to function. This must be a C identifier; more complex expressions are not permitted. If the core uses this function, it supersedes all the other properties.
+* `"size_function"` (string, optional): the name of a function that returns the number of bytes that the driver needs in a key context for a key. This may be a pointer to function. This must be a C identifier; more complex expressions are not permitted. If the core uses this function, it supersedes all the other properties except for `"builtin_key_size"` (where applicable, if present).
+* `"builtin_key_size"` (integer or string, optional): If specified, this overrides all other methods (including the `"size_function"` entry point) to determine the size of the key context for [built-in keys](#built-in-keys). This allows drivers to efficiently represent application keys as wrapped key material, but built-in keys by an internal identifier that takes up less space.
 
 The integer properties must be C language constants. A typical value for `"base_size"` is `sizeof(acme_key_context_t)` where `acme_key_context_t` is a type defined in a driver header file.
 
@@ -516,6 +663,7 @@
 * `"generate_key"`: called by `psa_generate_key()`.
 * `"key_derivation_output_key"`: called by `psa_key_derivation_output_key()`.
 * `"copy_key"`: called by `psa_copy_key()` when copying a key within the same [location](#lifetimes-and-locations).
+* `"get_builtin_key"`: called by functions that access a key to retrieve information about a [built-in key](#built-in-keys).
 
 In addition, secure elements that store the key material internally must provide the following two entry points:
 
@@ -646,6 +794,37 @@
 
 In a multithreaded environment, the driver may only call these two functions from the thread that is executing the entry point.
 
+#### Built-in keys
+
+Opaque drivers may declare built-in keys. Built-in keys can be accessed, but not created, through the PSA Cryptography API.
+
+A built-in key is identified by its location and its **slot number**. Drivers that support built-in keys must provide a `"get_builtin_key"` entry point to retrieve the key data and metadata. The core calls this entry point when it needs to access the key, typically because the application requested an operation on the key. The core may keep information about the key in cache, and successive calls to access the same slot number should return the same data. This entry point has the following prototype:
+
+```
+psa_status_t acme_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);
+```
+
+If this function returns `PSA_SUCCESS` or `PSA_ERROR_BUFFER_TOO_SMALL`, it must fill `attributes` with the attributes of the key (except for the key identifier). On success, this function must also fill `key_buffer` with the key context.
+
+On entry, `psa_get_key_lifetime(attributes)` is the location at which the driver was declared and a persistence level with which the platform is attempting to register the key. The driver entry point may choose to change the lifetime (`psa_set_key_lifetime(attributes, lifetime)`) of the reported key attributes to one with the same location but a different persistence level, in case the driver has more specific knowledge about the actual persistence level of the key which is being retrieved. For example, if a driver knows it cannot delete a key, it may override the persistence level in the lifetime to `PSA_KEY_PERSISTENCE_READ_ONLY`. The standard attributes other than the key identifier and lifetime have the value conveyed by `PSA_KEY_ATTRIBUTES_INIT`.
+
+The output parameter `key_buffer` points to a writable buffer of `key_buffer_size` bytes. If the driver has a [`"builtin_key_size"` property](#key-format-for-opaque-drivers) property, `key_buffer_size` has this value, otherwise `key_buffer_size` has the value determined from the key type and size.
+
+Typically, for a built-in key, the key context is a reference to key material that is kept inside the secure element, similar to the format returned by [`"allocate_key"`](#key-management-in-a-secure-element-with-storage). A driver may have built-in keys even if it doesn't have an `"allocate_key"` entry point.
+
+This entry point may return the following status values:
+
+* `PSA_SUCCESS`: the requested key exists, and the output parameters `attributes` and `key_buffer` contain the key metadata and key context respectively, and `*key_buffer_length` contains the length of the data written to `key_buffer`.
+* `PSA_ERROR_BUFFER_TOO_SMALL`: `key_buffer_size` is insufficient. In this case, the driver must pass the key's attributes in `*attributes`. In particular, `get_builtin_key(slot_number, &attributes, NULL, 0)` is a way for the core to obtain the key's attributes.
+* `PSA_ERROR_DOES_NOT_EXIST`: the requested key does not exist.
+* Other error codes such as `PSA_ERROR_COMMUNICATION_FAILURE` or `PSA_ERROR_HARDWARE_FAILURE` indicate a transient or permanent error.
+
+The core will pass authorized requests to destroy a built-in key to the [`"destroy_key"`](#key-management-in-a-secure-element-with-storage) entry point if there is one. If built-in keys must not be destroyed, it is up to the driver to reject such requests.
+
 ## How to use drivers from an application
 
 ### Using transparent drivers
@@ -661,7 +840,7 @@
 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
         PSA_KEY_PERSISTENCE_DEFAULT, PSA_KEY_LOCATION_acme));
-psa_set_key_identifer(&attributes, 42);
+psa_set_key_identifier(&attributes, 42);
 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
 psa_set_key_size(&attributes, 128);
 psa_set_key_algorithm(&attributes, PSA_ALG_GCM);
@@ -704,6 +883,19 @@
 
 ## Open questions
 
+### Value representation
+
+#### Integers
+
+It would be better if there was a uniform requirement on integer values. Do they have to be JSON integers? C preprocessor integers (which could be e.g. a macro defined in some header file)? C compile-time constants (allowing `sizeof`)?
+
+This choice is partly driven by the use of the values, so they might not be uniform. Note that if the value can be zero and it's plausible that the core would want to statically allocate an array of the given size, the core needs to know whether the value is 0 so that it could use code like
+```
+#if ACME_FOO_SIZE != 0
+    uint8_t foo[ACME_FOO_SIZE];
+#endif
+```
+
 ### Driver declarations
 
 #### Declaring driver entry points
@@ -779,6 +971,26 @@
 
 `psa_crypto_driver_get_persistent_state` does not identify the calling driver, so the driver needs to remember which driver it's calling. This may require a thread-local variable in a multithreaded core. Is this ok?
 
+### Randomness
+
+#### Input to `"add_entropy"`
+
+Should the input to the [`"add_entropy"` entry point](#entropy-injection) be a full-entropy buffer (with data from all entropy sources already mixed), raw entropy direct from the entropy sources, or give the core a choice?
+
+* Raw data: drivers must implement entropy mixing. `"add_entropy"` needs an extra parameter to indicate the amount of entropy in the data. The core must not do any conditioning.
+* Choice: drivers must implement entropy mixing. `"add_entropy"` needs an extra parameter to indicate the amount of entropy in the data. The core may do conditioning if it wants, but doesn't have to.
+* Full entropy: drivers don't need to do entropy mixing.
+
+#### Flags for `"get_entropy"`
+
+Are the [entropy collection flags](#entropy-collection-flags) well-chosen?
+
+#### Random generator instantiations
+
+May the core instantiate a random generation context more than once? In other words, can there be multiple objects of type `acme_random_context_t`?
+
+Functionally, one RNG is as good as any. If the core wants some parts of the system to use a deterministic generator for reproducibility, it can't use this interface anyway, since the RNG is not necessarily deterministic. However, for performance on multiprocessor systems, a multithreaded core could prefer to use one RNG instance per thread.
+
 <!--
 Local Variables:
 time-stamp-line-limit: 40
diff --git a/third_party/mbedtls/repo/docs/use-psa-crypto.md b/third_party/mbedtls/repo/docs/use-psa-crypto.md
new file mode 100644
index 0000000..6ec2dca
--- /dev/null
+++ b/third_party/mbedtls/repo/docs/use-psa-crypto.md
@@ -0,0 +1,204 @@
+This document describes the compile-time configuration option
+`MBEDTLS_USE_PSA_CRYPTO` from a user's perspective, more specifically its
+current effects as well as the parts that aren't covered yet.
+
+Current effects
+===============
+
+General limitations
+-------------------
+
+Compile-time: enabling `MBEDTLS_USE_PSA_CRYPTO` requires
+`MBEDTLS_ECP_RESTARTABLE` and
+`MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER` to be disabled.
+
+Effect: `MBEDTLS_USE_PSA_CRYPTO` currently has no effect on TLS 1.3 (which is
+itself experimental and only partially supported so far): TLS 1.3 always uses
+the legacy APIs even when this option is set.
+
+Stability: any API that's only available when `MBEDTLS_USE_PSA_CRYPTO` is
+defined is considered experimental and may change in incompatible ways at any
+time. Said otherwise, these APIs are explicitly excluded from the usual API
+stability promises.
+
+New APIs / API extensions
+-------------------------
+
+Some of these APIs are meant for the application to use in place of
+pre-existing APIs, in order to get access to the benefits; in the sub-sections
+below these are indicated by "Use in (X.509 and) TLS: opt-in", meaning that
+this requires changes to the application code for the (X.509 and) TLS layers
+to pick up the improvements.
+
+Some of these APIs are mostly meant for internal use by the TLS (and X.509)
+layers; they are indicated below by "Use in (X.509 and) TLS: automatic",
+meaning that no changes to the application code are required for the TLS (and
+X.509) layers to pick up the improvements.
+
+### PSA-held (opaque) keys in the PK layer
+
+There is a new API function `mbedtls_pk_setup_opaque()` that can be used to
+wrap a PSA keypair into a PK context. The key can be used for private-key
+operations and its public part can be exported.
+
+Benefits: isolation of long-term secrets, use of PSA Crypto drivers.
+
+Limitations: only for private keys, only ECC. (That is, only ECDSA signature
+generation. Note: currently this will use randomized ECDSA while Mbed TLS uses
+deterministic ECDSA by default.) The following operations are not supported
+with a context set this way, while they would be available with a normal
+`ECKEY` context: `mbedtls_pk_verify()`, `mbedtls_pk_check_pair()`,
+`mbedtls_pk_debug()`.
+
+Use in X.509 and TLS: opt-in. The application needs to construct the PK context
+using the new API in order to get the benefits; it can then pass the
+resulting context to the following existing APIs:
+
+- `mbedtls_ssl_conf_own_cert()` or `mbedtls_ssl_set_hs_own_cert()` to use the
+  key together with a certificate for ECDSA-based key exchanges (note: while
+this is supported on both sides, it's currently only tested client-side);
+- `mbedtls_x509write_csr_set_key()` to generate a CSR (certificate signature
+  request).
+
+In the TLS and X.509 API, there are two other functions which accept a key or
+keypair as a PK context: `mbedtls_x509write_crt_set_subject_key()` and
+`mbedtls_x509write_crt_set_issuer_key()`. Use of opaque contexts here probably
+works but is so far untested.
+
+### PSA-held (opaque) keys for TLS pre-shared keys (PSK)
+
+There are two new API functions `mbedtls_ssl_conf_psk_opaque()` and
+`mbedtls_ssl_set_hs_psk_opaque()`. Call one of these from an application to
+register a PSA key for use with a PSK key exchange.
+
+Benefits: isolation of long-term secrets.
+
+Limitations: the key can only be used with "pure"
+PSK key exchanges (ciphersuites starting with `TLS_PSK_WITH_`), to the
+exclusion of RSA-PSK, DHE-PSK and ECDHE-PSK key exchanges. It is the responsibility of
+the user to make sure that when provisioning an opaque pre-shared key, the
+only PSK ciphersuites that can be negotiated are "pure" PSK; other XXX-PSK key
+exchanges will result in a handshake failure with the handshake function
+returning `MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE`.
+
+Use in TLS: opt-in. The application needs to register the key using the new
+APIs to get the benefits.
+
+### PSA-based operations in the Cipher layer
+
+There is a new API function `mbedtls_cipher_setup_psa()` to set up a context
+that will call PSA to store the key and perform the operations.
+
+Benefits: use of PSA Crypto drivers; partial isolation of short-term secrets
+(still generated outside of PSA, but then held by PSA).
+
+Limitations: the key is still passed in the clear by the application. The
+multi-part APIs are not supported, only the one-shot APIs. The only modes
+supported are ECB, CBC without padding, GCM and CCM (this excludes stream
+ciphers and ChachaPoly); the only cipher supported is AES (this excludes Aria,
+Camellia, and ChachaPoly). (Note: ECB is currently not tested.) (Note: it is
+possible to perform multiple one-shot operations with the same context;
+however this is not unit-tested, only tested via usage in TLS.)
+
+Use in TLS: automatic. Used when the cipher and mode is supported (with
+gracious fallback to the legacy API otherwise) in all places where a cipher is
+used. There are two such places: in `ssl_tls.c` for record protection, and in
+`ssl_ticket.c` for protecting tickets we issue.
+
+Internal changes
+----------------
+
+All of these internal changes are active as soon as `MBEDTLS_USE_PSA_CRYPTO`
+is enabled, no change required on the application side.
+
+### TLS: cipher operations based on PSA
+
+See "PSA-based operations in the Cipher layer" above.
+
+### PK layer: ECDSA verification based on PSA
+
+Scope: `mbedtls_pk_verify()` will call to PSA for ECDSA signature
+verification.
+
+Benefits: use of PSA Crypto drivers.
+
+Use in TLS and X.509: in all places where an ECDSA signature is verified.
+
+### TLS: ECDHE computation based on PSA
+
+Scope: Client-side, for ECDHE-RSA and ECDHE-ECDSA key exchanges, the
+computation of the ECDHE key exchange is done by PSA.
+
+Limitations: client-side only, ECDHE-PSK not covered
+
+Benefits: use of PSA Crypto drivers.
+
+### TLS: handshake hashes and PRF computed with PSA
+
+Scope: with TLS 1.2, the following are computed with PSA:
+- the running handshake hashes;
+- the hash of the ServerKeyExchange part that is signed;
+- the `verify_data` part of the Finished message;
+- the TLS PRF.
+
+Benefits: use of PSA Crypto drivers.
+
+### X.509: some hashes computed with PSA
+
+Scope: the following hashes are computed with PSA:
+- when verifying a certificate chain, hash of the child for verifying the
+  parent's signature;
+- when writing a CSR, hash of the request for self-signing the request.
+
+Benefits: use of PSA Crypto drivers.
+
+Parts that are not covered yet
+==============================
+
+This is only a high-level overview, grouped by theme
+
+TLS: 1.3 experimental support
+-----------------------------
+
+No part of the experimental support for TLS 1.3 is covered at the moment.
+
+TLS: key exchanges / asymmetric crypto
+--------------------------------------
+
+The following key exchanges are not covered at all:
+
+- RSA
+- DHE-RSA
+- DHE-PSK
+- RSA-PSK
+- ECDHE-PSK
+- ECDH-RSA
+- ECDH-ECDSA
+- ECJPAKE
+
+The following key exchanges are only partially covered:
+
+- ECDHE-RSA: RSA operations are not covered and, server-side, the ECDHE
+  operation isn't either
+- ECDHE-ECDSA: server-side, the ECDHE operation isn't covered. (ECDSA
+  signature generation is only covered if using `mbedtls_pk_setup_opaque()`.)
+
+PSK if covered when the application uses `mbedtls_ssl_conf_psk_opaque()` or
+`mbedtls_ssl_set_hs_psk_opaque()`.
+
+TLS: symmetric crypto
+---------------------
+
+- some ciphers not supported via PSA yet: ARIA, Camellia, ChachaPoly (silent
+  fallback to the legacy APIs)
+- the HMAC part of the CBC and NULL ciphersuites
+- the HMAC computation in `ssl_cookie.c`
+
+X.509
+-----
+
+- most hash operations are still done via the legacy API, except the few that
+  are documented above as using PSA
+- RSA PKCS#1 v1.5 signature generation (from PSA-held keys)
+- RSA PKCS#1 v1.5 signature verification
+- RSA-PSS signature verification
diff --git a/third_party/mbedtls/repo/doxygen/input/doc_mainpage.h b/third_party/mbedtls/repo/doxygen/input/doc_mainpage.h
index 5b51bd5..5a0f3ec 100644
--- a/third_party/mbedtls/repo/doxygen/input/doc_mainpage.h
+++ b/third_party/mbedtls/repo/doxygen/input/doc_mainpage.h
@@ -22,7 +22,7 @@
  */
 
 /**
- * @mainpage mbed TLS v2.25.0 source code documentation
+ * @mainpage mbed TLS v2.28.0 source code documentation
  *
  * This documentation describes the internal structure of mbed TLS.  It was
  * automatically generated from specially formatted comment blocks in
diff --git a/third_party/mbedtls/repo/doxygen/mbedtls.doxyfile b/third_party/mbedtls/repo/doxygen/mbedtls.doxyfile
index dd4237a..efd9ac6 100644
--- a/third_party/mbedtls/repo/doxygen/mbedtls.doxyfile
+++ b/third_party/mbedtls/repo/doxygen/mbedtls.doxyfile
@@ -28,7 +28,7 @@
 # identify the project. Note that if you do not use Doxywizard you need
 # to put quotes around the project name if it contains spaces.
 
-PROJECT_NAME           = "mbed TLS v2.25.0"
+PROJECT_NAME           = "mbed TLS v2.28.0"
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number.
 # This could be handy for archiving the generated documentation or
diff --git a/third_party/mbedtls/repo/include/mbedtls/aes.h b/third_party/mbedtls/repo/include/mbedtls/aes.h
index 052f47c..e280dbb 100644
--- a/third_party/mbedtls/repo/include/mbedtls/aes.h
+++ b/third_party/mbedtls/repo/include/mbedtls/aes.h
@@ -45,6 +45,7 @@
 #else
 #include MBEDTLS_CONFIG_FILE
 #endif
+#include "mbedtls/platform_util.h"
 
 #include <stddef.h>
 #include <stdint.h>
@@ -54,17 +55,22 @@
 #define MBEDTLS_AES_DECRYPT     0 /**< AES decryption. */
 
 /* Error codes in range 0x0020-0x0022 */
-#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH                -0x0020  /**< Invalid key length. */
-#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH              -0x0022  /**< Invalid data input length. */
+/** Invalid key length. */
+#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH                -0x0020
+/** Invalid data input length. */
+#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH              -0x0022
 
 /* Error codes in range 0x0021-0x0025 */
-#define MBEDTLS_ERR_AES_BAD_INPUT_DATA                    -0x0021  /**< Invalid input data. */
+/** Invalid input data. */
+#define MBEDTLS_ERR_AES_BAD_INPUT_DATA                    -0x0021
 
 /* MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE is deprecated and should not be used. */
-#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE               -0x0023  /**< Feature not available. For example, an unsupported AES key size. */
+/** Feature not available. For example, an unsupported AES key size. */
+#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE               -0x0023
 
 /* MBEDTLS_ERR_AES_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED                   -0x0025  /**< AES hardware accelerator failed. */
+/** AES hardware accelerator failed. */
+#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED                   -0x0025
 
 #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
     !defined(inline) && !defined(__cplusplus)
@@ -169,6 +175,7 @@
  * \return         \c 0 on success.
  * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
                     unsigned int keybits );
 
@@ -187,6 +194,7 @@
  * \return         \c 0 on success.
  * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
                     unsigned int keybits );
 
@@ -207,6 +215,7 @@
  * \return         \c 0 on success.
  * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
                                 const unsigned char *key,
                                 unsigned int keybits );
@@ -227,6 +236,7 @@
  * \return         \c 0 on success.
  * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
                                 const unsigned char *key,
                                 unsigned int keybits );
@@ -255,6 +265,7 @@
 
  * \return         \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
                     int mode,
                     const unsigned char input[16],
@@ -302,6 +313,7 @@
  * \return         #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
  *                 on failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
                     int mode,
                     size_t length,
@@ -346,6 +358,7 @@
  *                     smaller than an AES block in size (16 Bytes) or if \p
  *                     length is larger than 2^20 blocks (16 MiB).
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
                            int mode,
                            size_t length,
@@ -394,6 +407,7 @@
  *
  * \return         \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
                        int mode,
                        size_t length,
@@ -438,6 +452,7 @@
  *
  * \return         \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
                     int mode,
                     size_t length,
@@ -492,6 +507,7 @@
  *
  * \return         \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
                        size_t length,
                        size_t *iv_off,
@@ -506,10 +522,6 @@
  * \brief      This function performs an AES-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_aes_setkey_enc()
@@ -578,6 +590,7 @@
  *
  * \return                 \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
                        size_t length,
                        size_t *nc_off,
@@ -598,6 +611,7 @@
  *
  * \return          \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx,
                                   const unsigned char input[16],
                                   unsigned char output[16] );
@@ -613,6 +627,7 @@
  *
  * \return          \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx,
                                   const unsigned char input[16],
                                   unsigned char output[16] );
@@ -662,6 +677,7 @@
  * \return         \c 0 on success.
  * \return         \c 1 on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_aes_self_test( int verbose );
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/third_party/mbedtls/repo/include/mbedtls/arc4.h b/third_party/mbedtls/repo/include/mbedtls/arc4.h
index 17728f4..f4b0f9f 100644
--- a/third_party/mbedtls/repo/include/mbedtls/arc4.h
+++ b/third_party/mbedtls/repo/include/mbedtls/arc4.h
@@ -35,7 +35,8 @@
 #include <stddef.h>
 
 /* MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED                  -0x0019  /**< ARC4 hardware accelerator failed. */
+/** ARC4 hardware accelerator failed. */
+#define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED                  -0x0019
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/aria.h b/third_party/mbedtls/repo/include/mbedtls/aria.h
index a4b27b3..226e2db 100644
--- a/third_party/mbedtls/repo/include/mbedtls/aria.h
+++ b/third_party/mbedtls/repo/include/mbedtls/aria.h
@@ -50,25 +50,29 @@
 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
 #define MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH   MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x005C )
 #endif /* !MBEDTLS_DEPRECATED_REMOVED */
-#define MBEDTLS_ERR_ARIA_BAD_INPUT_DATA -0x005C /**< Bad input data. */
+/** Bad input data. */
+#define MBEDTLS_ERR_ARIA_BAD_INPUT_DATA -0x005C
 
-#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E /**< Invalid data input length. */
+/** Invalid data input length. */
+#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E
 
 /* MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE is deprecated and should not be used.
  */
-#define MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE  -0x005A  /**< Feature not available. For example, an unsupported ARIA key size. */
+/** Feature not available. For example, an unsupported ARIA key size. */
+#define MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE  -0x005A
 
 /* MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED      -0x0058  /**< ARIA hardware accelerator failed. */
-
-#if !defined(MBEDTLS_ARIA_ALT)
-// Regular implementation
-//
+/** ARIA hardware accelerator failed. */
+#define MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED      -0x0058
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if !defined(MBEDTLS_ARIA_ALT)
+// Regular implementation
+//
+
 /**
  * \brief The ARIA context-type definition.
  */
diff --git a/third_party/mbedtls/repo/include/mbedtls/asn1.h b/third_party/mbedtls/repo/include/mbedtls/asn1.h
index 6b79196..10f7905 100644
--- a/third_party/mbedtls/repo/include/mbedtls/asn1.h
+++ b/third_party/mbedtls/repo/include/mbedtls/asn1.h
@@ -46,13 +46,20 @@
  * ASN1 is a standard to specify data structures.
  * \{
  */
-#define MBEDTLS_ERR_ASN1_OUT_OF_DATA                      -0x0060  /**< Out of data when parsing an ASN1 data structure. */
-#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG                   -0x0062  /**< ASN1 tag was of an unexpected value. */
-#define MBEDTLS_ERR_ASN1_INVALID_LENGTH                   -0x0064  /**< Error when trying to determine the length or invalid length. */
-#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH                  -0x0066  /**< Actual length differs from expected length. */
-#define MBEDTLS_ERR_ASN1_INVALID_DATA                     -0x0068  /**< Data is invalid. */
-#define MBEDTLS_ERR_ASN1_ALLOC_FAILED                     -0x006A  /**< Memory allocation failed */
-#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL                    -0x006C  /**< Buffer too small when writing ASN.1 data structure. */
+/** Out of data when parsing an ASN1 data structure. */
+#define MBEDTLS_ERR_ASN1_OUT_OF_DATA                      -0x0060
+/** ASN1 tag was of an unexpected value. */
+#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG                   -0x0062
+/** Error when trying to determine the length or invalid length. */
+#define MBEDTLS_ERR_ASN1_INVALID_LENGTH                   -0x0064
+/** Actual length differs from expected length. */
+#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH                  -0x0066
+/** Data is invalid. */
+#define MBEDTLS_ERR_ASN1_INVALID_DATA                     -0x0068
+/** Memory allocation failed */
+#define MBEDTLS_ERR_ASN1_ALLOC_FAILED                     -0x006A
+/** Buffer too small when writing ASN.1 data structure. */
+#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL                    -0x006C
 
 /* \} name */
 
diff --git a/third_party/mbedtls/repo/include/mbedtls/base64.h b/third_party/mbedtls/repo/include/mbedtls/base64.h
index 7e73a8b..cf4149e 100644
--- a/third_party/mbedtls/repo/include/mbedtls/base64.h
+++ b/third_party/mbedtls/repo/include/mbedtls/base64.h
@@ -30,8 +30,10 @@
 
 #include <stddef.h>
 
-#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL               -0x002A  /**< Output buffer too small. */
-#define MBEDTLS_ERR_BASE64_INVALID_CHARACTER              -0x002C  /**< Invalid character in input. */
+/** Output buffer too small. */
+#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL               -0x002A
+/** Invalid character in input. */
+#define MBEDTLS_ERR_BASE64_INVALID_CHARACTER              -0x002C
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/bignum.h b/third_party/mbedtls/repo/include/mbedtls/bignum.h
index 637360e..9d2cff3 100644
--- a/third_party/mbedtls/repo/include/mbedtls/bignum.h
+++ b/third_party/mbedtls/repo/include/mbedtls/bignum.h
@@ -35,14 +35,22 @@
 #include <stdio.h>
 #endif
 
-#define MBEDTLS_ERR_MPI_FILE_IO_ERROR                     -0x0002  /**< An error occurred while reading from or writing to a file. */
-#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA                    -0x0004  /**< Bad input parameters to function. */
-#define MBEDTLS_ERR_MPI_INVALID_CHARACTER                 -0x0006  /**< There is an invalid character in the digit string. */
-#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL                  -0x0008  /**< The buffer is too small to write to. */
-#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE                    -0x000A  /**< The input arguments are negative or result in illegal output. */
-#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO                  -0x000C  /**< The input argument for division is zero, which is not allowed. */
-#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE                    -0x000E  /**< The input arguments are not acceptable. */
-#define MBEDTLS_ERR_MPI_ALLOC_FAILED                      -0x0010  /**< Memory allocation failed. */
+/** An error occurred while reading from or writing to a file. */
+#define MBEDTLS_ERR_MPI_FILE_IO_ERROR                     -0x0002
+/** Bad input parameters to function. */
+#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA                    -0x0004
+/** There is an invalid character in the digit string. */
+#define MBEDTLS_ERR_MPI_INVALID_CHARACTER                 -0x0006
+/** The buffer is too small to write to. */
+#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL                  -0x0008
+/** The input arguments are negative or result in illegal output. */
+#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE                    -0x000A
+/** The input argument for division is zero, which is not allowed. */
+#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO                  -0x000C
+/** The input arguments are not acceptable. */
+#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE                    -0x000E
+/** Memory allocation failed. */
+#define MBEDTLS_ERR_MPI_ALLOC_FAILED                      -0x0010
 
 #define MBEDTLS_MPI_CHK(f)       \
     do                           \
@@ -829,14 +837,14 @@
  * \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 _RR      A helper MPI depending solely on \p N which can be used to
+ * \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 _RR for reuse on
+ *                 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 _RR holds the helper value set by a
+ *                 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.
@@ -848,7 +856,7 @@
  */
 int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
                          const mbedtls_mpi *E, const mbedtls_mpi *N,
-                         mbedtls_mpi *_RR );
+                         mbedtls_mpi *prec_RR );
 
 /**
  * \brief          Fill an MPI with a number of random bytes.
@@ -871,6 +879,44 @@
                      int (*f_rng)(void *, unsigned char *, size_t),
                      void *p_rng );
 
+/** Generate a random number uniformly in a range.
+ *
+ * This function generates a random number between \p min inclusive and
+ * \p N exclusive.
+ *
+ * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)
+ * when the RNG is a suitably parametrized instance of HMAC_DRBG
+ * and \p min is \c 1.
+ *
+ * \note           There are `N - min` possible outputs. The lower bound
+ *                 \p min can be reached, but the upper bound \p N cannot.
+ *
+ * \param X        The destination MPI. This must point to an initialized MPI.
+ * \param min      The minimum value to return.
+ *                 It must be nonnegative.
+ * \param N        The upper bound of the range, exclusive.
+ *                 In other words, this is one plus the maximum value to return.
+ *                 \p N must be strictly larger than \p min.
+ * \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.
+ *
+ * \return         \c 0 if successful.
+ * \return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p min or \p N is invalid
+ *                 or if they are incompatible.
+ * \return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was
+ *                 unable to find a suitable value within a limited number
+ *                 of attempts. This has a negligible probability if \p N
+ *                 is significantly larger than \p min, which is the case
+ *                 for all usual cryptographic applications.
+ * \return         Another negative error code on failure.
+ */
+int mbedtls_mpi_random( mbedtls_mpi *X,
+                        mbedtls_mpi_sint min,
+                        const mbedtls_mpi *N,
+                        int (*f_rng)(void *, unsigned char *, size_t),
+                        void *p_rng );
+
 /**
  * \brief          Compute the greatest common divisor: G = gcd(A, B)
  *
diff --git a/third_party/mbedtls/repo/include/mbedtls/blowfish.h b/third_party/mbedtls/repo/include/mbedtls/blowfish.h
index c2a6ff9..77dca70 100644
--- a/third_party/mbedtls/repo/include/mbedtls/blowfish.h
+++ b/third_party/mbedtls/repo/include/mbedtls/blowfish.h
@@ -43,13 +43,16 @@
 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
 #define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH   MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0016 )
 #endif /* !MBEDTLS_DEPRECATED_REMOVED */
-#define MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA -0x0016 /**< Bad input data. */
+/** Bad input data. */
+#define MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA -0x0016
 
-#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */
+/** Invalid data input length. */
+#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018
 
 /* MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED is deprecated and should not be used.
  */
-#define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED                   -0x0017  /**< Blowfish hardware accelerator failed. */
+/** Blowfish hardware accelerator failed. */
+#define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED                   -0x0017
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/bn_mul.h b/third_party/mbedtls/repo/include/mbedtls/bn_mul.h
index 17d057f..31137cd 100644
--- a/third_party/mbedtls/repo/include/mbedtls/bn_mul.h
+++ b/third_party/mbedtls/repo/include/mbedtls/bn_mul.h
@@ -44,6 +44,46 @@
 
 #include "mbedtls/bignum.h"
 
+
+/*
+ * Conversion macros for embedded constants:
+ * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2
+ */
+#if defined(MBEDTLS_HAVE_INT32)
+
+#define MBEDTLS_BYTES_TO_T_UINT_4( a, b, c, d )               \
+    ( (mbedtls_mpi_uint) (a) <<  0 ) |                        \
+    ( (mbedtls_mpi_uint) (b) <<  8 ) |                        \
+    ( (mbedtls_mpi_uint) (c) << 16 ) |                        \
+    ( (mbedtls_mpi_uint) (d) << 24 )
+
+#define MBEDTLS_BYTES_TO_T_UINT_2( a, b )                   \
+    MBEDTLS_BYTES_TO_T_UINT_4( a, b, 0, 0 )
+
+#define MBEDTLS_BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
+    MBEDTLS_BYTES_TO_T_UINT_4( a, b, c, d ),                \
+    MBEDTLS_BYTES_TO_T_UINT_4( e, f, g, h )
+
+#else /* 64-bits */
+
+#define MBEDTLS_BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h )   \
+    ( (mbedtls_mpi_uint) (a) <<  0 ) |                        \
+    ( (mbedtls_mpi_uint) (b) <<  8 ) |                        \
+    ( (mbedtls_mpi_uint) (c) << 16 ) |                        \
+    ( (mbedtls_mpi_uint) (d) << 24 ) |                        \
+    ( (mbedtls_mpi_uint) (e) << 32 ) |                        \
+    ( (mbedtls_mpi_uint) (f) << 40 ) |                        \
+    ( (mbedtls_mpi_uint) (g) << 48 ) |                        \
+    ( (mbedtls_mpi_uint) (h) << 56 )
+
+#define MBEDTLS_BYTES_TO_T_UINT_4( a, b, c, d )             \
+    MBEDTLS_BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 )
+
+#define MBEDTLS_BYTES_TO_T_UINT_2( a, b )                   \
+    MBEDTLS_BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 )
+
+#endif /* bits in mbedtls_mpi_uint */
+
 #if defined(MBEDTLS_HAVE_ASM)
 
 #ifndef asm
@@ -189,9 +229,9 @@
         "addq   $8, %%rdi\n"
 
 #define MULADDC_STOP                        \
-        : "+c" (c), "+D" (d), "+S" (s)      \
-        : "b" (b)                           \
-        : "rax", "rdx", "r8"                \
+        : "+c" (c), "+D" (d), "+S" (s), "+m" (*(uint64_t (*)[16]) d) \
+        : "b" (b), "m" (*(const uint64_t (*)[16]) s)                 \
+        : "rax", "rdx", "r8"                                         \
     );
 
 #endif /* AMD64 */
@@ -204,18 +244,18 @@
 #define MULADDC_CORE                \
         "ldr x4, [%2], #8   \n\t"   \
         "ldr x5, [%1]       \n\t"   \
-        "mul x6, x4, %3     \n\t"   \
-        "umulh x7, x4, %3   \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"
 
-#define MULADDC_STOP                        \
-         : "+r" (c),  "+r" (d), "+r" (s)    \
-         : "r" (b)                          \
-         : "x4", "x5", "x6", "x7", "cc"     \
+#define MULADDC_STOP                                                    \
+         : "+r" (c),  "+r" (d), "+r" (s), "+m" (*(uint64_t (*)[16]) d)  \
+         : "r" (b), "m" (*(const uint64_t (*)[16]) s)                   \
+         : "x4", "x5", "x6", "x7", "cc"                                 \
     );
 
 #endif /* Aarch64 */
diff --git a/third_party/mbedtls/repo/include/mbedtls/camellia.h b/third_party/mbedtls/repo/include/mbedtls/camellia.h
index f7d2b23..925a623 100644
--- a/third_party/mbedtls/repo/include/mbedtls/camellia.h
+++ b/third_party/mbedtls/repo/include/mbedtls/camellia.h
@@ -39,13 +39,16 @@
 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
 #define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH   MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0024 )
 #endif /* !MBEDTLS_DEPRECATED_REMOVED */
-#define MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA -0x0024 /**< Bad input data. */
+/** Bad input data. */
+#define MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA -0x0024
 
-#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */
+/** Invalid data input length. */
+#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026
 
 /* MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED is deprecated and should not be used.
  */
-#define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED              -0x0027  /**< Camellia hardware accelerator failed. */
+/** Camellia hardware accelerator failed. */
+#define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED              -0x0027
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/ccm.h b/third_party/mbedtls/repo/include/mbedtls/ccm.h
index 7193863..ece5a90 100644
--- a/third_party/mbedtls/repo/include/mbedtls/ccm.h
+++ b/third_party/mbedtls/repo/include/mbedtls/ccm.h
@@ -55,11 +55,14 @@
 
 #include "mbedtls/cipher.h"
 
-#define MBEDTLS_ERR_CCM_BAD_INPUT       -0x000D /**< Bad input parameters to the function. */
-#define MBEDTLS_ERR_CCM_AUTH_FAILED     -0x000F /**< Authenticated decryption failed. */
+/** Bad input parameters to the function. */
+#define MBEDTLS_ERR_CCM_BAD_INPUT       -0x000D
+/** Authenticated decryption failed. */
+#define MBEDTLS_ERR_CCM_AUTH_FAILED     -0x000F
 
 /* MBEDTLS_ERR_CCM_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */
+/** CCM hardware accelerator failed. */
+#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/chacha20.h b/third_party/mbedtls/repo/include/mbedtls/chacha20.h
index e59dd1f..03b4871 100644
--- a/third_party/mbedtls/repo/include/mbedtls/chacha20.h
+++ b/third_party/mbedtls/repo/include/mbedtls/chacha20.h
@@ -41,15 +41,18 @@
 #include <stdint.h>
 #include <stddef.h>
 
-#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA         -0x0051 /**< Invalid input parameter(s). */
+/** Invalid input parameter(s). */
+#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA         -0x0051
 
 /* MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE is deprecated and should not be
  * used. */
-#define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE    -0x0053 /**< Feature not available. For example, s part of the API is not implemented. */
+/** Feature not available. For example, s part of the API is not implemented. */
+#define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE    -0x0053
 
 /* MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED is deprecated and should not be used.
  */
-#define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED        -0x0055  /**< Chacha20 hardware accelerator failed. */
+/** Chacha20 hardware accelerator failed. */
+#define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED        -0x0055
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/chachapoly.h b/third_party/mbedtls/repo/include/mbedtls/chachapoly.h
index 1007f95..c4ec7b5 100644
--- a/third_party/mbedtls/repo/include/mbedtls/chachapoly.h
+++ b/third_party/mbedtls/repo/include/mbedtls/chachapoly.h
@@ -41,8 +41,10 @@
 /* for shared error codes */
 #include "mbedtls/poly1305.h"
 
-#define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE            -0x0054 /**< The requested operation is not permitted in the current state. */
-#define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED          -0x0056 /**< Authenticated decryption failed: data was not authentic. */
+/** The requested operation is not permitted in the current state. */
+#define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE            -0x0054
+/** Authenticated decryption failed: data was not authentic. */
+#define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED          -0x0056
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/check_config.h b/third_party/mbedtls/repo/include/mbedtls/check_config.h
index 1ebb706..396fe7d 100644
--- a/third_party/mbedtls/repo/include/mbedtls/check_config.h
+++ b/third_party/mbedtls/repo/include/mbedtls/check_config.h
@@ -55,9 +55,8 @@
 #endif
 #endif /* _WIN32 */
 
-#if defined(TARGET_LIKE_MBED) && \
-    ( defined(MBEDTLS_NET_C) || defined(MBEDTLS_TIMING_C) )
-#error "The NET and TIMING modules are not available for mbed OS - please use the network and timing functions provided by mbed OS"
+#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"
 #endif
 
 #if defined(MBEDTLS_DEPRECATED_WARNING) && \
@@ -252,6 +251,10 @@
 #error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_ECP_NO_FALLBACK) && !defined(MBEDTLS_ECP_INTERNAL_ALT)
+#error "MBEDTLS_ECP_NO_FALLBACK defined, but no alternative implementation enabled"
+#endif
+
 #if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C)
 #error "MBEDTLS_HAVEGE_C defined, but not all prerequisites"
 #endif
@@ -506,10 +509,6 @@
 #error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites"
 #endif
 
-#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY)
-#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites"
-#endif
-
 #if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY)
 #error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites"
 #endif
@@ -572,10 +571,11 @@
 #error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously"
 #endif
 
-#if defined(MBEDTLS_PSA_CRYPTO_C) &&            \
-    !( defined(MBEDTLS_CTR_DRBG_C) &&           \
-       defined(MBEDTLS_ENTROPY_C) )
-#error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites"
+#if defined(MBEDTLS_PSA_CRYPTO_C) &&                                    \
+    !( ( ( defined(MBEDTLS_CTR_DRBG_C) || defined(MBEDTLS_HMAC_DRBG_C) ) && \
+         defined(MBEDTLS_ENTROPY_C) ) ||                                \
+       defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) )
+#error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites (missing RNG)"
 #endif
 
 #if defined(MBEDTLS_PSA_CRYPTO_SPM) && !defined(MBEDTLS_PSA_CRYPTO_C)
@@ -604,6 +604,11 @@
 #error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with actual entropy sources"
 #endif
 
+#if defined(MBEDTLS_PSA_INJECT_ENTROPY) &&              \
+    defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+#error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG"
+#endif
+
 #if defined(MBEDTLS_PSA_ITS_FILE_C) && \
     !defined(MBEDTLS_FS_IO)
 #error "MBEDTLS_PSA_ITS_FILE_C defined, but not all prerequisites"
@@ -880,6 +885,10 @@
 #error "MBEDTLS_SSL_DTLS_SRTP defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) && ( !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) )
+#error "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH defined, but not all prerequisites"
+#endif
+
 /*
  * 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/third_party/mbedtls/repo/include/mbedtls/cipher.h b/third_party/mbedtls/repo/include/mbedtls/cipher.h
index 1cafa6e..6d83da8 100644
--- a/third_party/mbedtls/repo/include/mbedtls/cipher.h
+++ b/third_party/mbedtls/repo/include/mbedtls/cipher.h
@@ -54,16 +54,24 @@
 #define inline __inline
 #endif
 
-#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE  -0x6080  /**< The selected feature is not available. */
-#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA       -0x6100  /**< Bad input parameters. */
-#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED         -0x6180  /**< Failed to allocate memory. */
-#define MBEDTLS_ERR_CIPHER_INVALID_PADDING      -0x6200  /**< Input data contains invalid padding and is rejected. */
-#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED  -0x6280  /**< Decryption of block requires a full block. */
-#define MBEDTLS_ERR_CIPHER_AUTH_FAILED          -0x6300  /**< Authentication failed (for AEAD modes). */
-#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT      -0x6380  /**< The context is invalid. For example, because it was freed. */
+/** The selected feature is not available. */
+#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE  -0x6080
+/** Bad input parameters. */
+#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA       -0x6100
+/** Failed to allocate memory. */
+#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED         -0x6180
+/** Input data contains invalid padding and is rejected. */
+#define MBEDTLS_ERR_CIPHER_INVALID_PADDING      -0x6200
+/** Decryption of block requires a full block. */
+#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED  -0x6280
+/** Authentication failed (for AEAD modes). */
+#define MBEDTLS_ERR_CIPHER_AUTH_FAILED          -0x6300
+/** The context is invalid. For example, because it was freed. */
+#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT      -0x6380
 
 /* MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED      -0x6400  /**< Cipher hardware accelerator failed. */
+/** Cipher hardware accelerator failed. */
+#define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED      -0x6400
 
 #define MBEDTLS_CIPHER_VARIABLE_IV_LEN     0x01    /**< Cipher accepts IVs of variable length. */
 #define MBEDTLS_CIPHER_VARIABLE_KEY_LEN    0x02    /**< Cipher accepts keys of variable length. */
diff --git a/third_party/mbedtls/repo/include/mbedtls/cmac.h b/third_party/mbedtls/repo/include/mbedtls/cmac.h
index cb538d0..8934886 100644
--- a/third_party/mbedtls/repo/include/mbedtls/cmac.h
+++ b/third_party/mbedtls/repo/include/mbedtls/cmac.h
@@ -39,7 +39,8 @@
 #endif
 
 /* MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED -0x007A  /**< CMAC hardware accelerator failed. */
+/** CMAC hardware accelerator failed. */
+#define MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED -0x007A
 
 #define MBEDTLS_AES_BLOCK_SIZE          16
 #define MBEDTLS_DES3_BLOCK_SIZE         8
@@ -73,9 +74,23 @@
 #endif /* !MBEDTLS_CMAC_ALT */
 
 /**
- * \brief               This function sets the CMAC key, and prepares to authenticate
+ * \brief               This function starts a new CMAC computation
+ *                      by setting the CMAC key, and preparing to authenticate
  *                      the input data.
- *                      Must be called with an initialized cipher context.
+ *                      It must be called with an initialized cipher context.
+ *
+ *                      Once this function has completed, data can be supplied
+ *                      to the CMAC computation by calling
+ *                      mbedtls_cipher_cmac_update().
+ *
+ *                      To start a CMAC computation using the same key as a previous
+ *                      CMAC computation, use mbedtls_cipher_cmac_finish().
+ *
+ * \note                When the CMAC implementation is supplied by an alternate
+ *                      implementation (through #MBEDTLS_CMAC_ALT), some ciphers
+ *                      may not be supported by that implementation, and thus
+ *                      return an error. Alternate implementations must support
+ *                      AES-128 and AES-256, and may support AES-192 and 3DES.
  *
  * \param ctx           The cipher context used for the CMAC operation, initialized
  *                      as one of the following types: MBEDTLS_CIPHER_AES_128_ECB,
@@ -95,9 +110,15 @@
  * \brief               This function feeds an input buffer into an ongoing CMAC
  *                      computation.
  *
- *                      It is called between mbedtls_cipher_cmac_starts() or
- *                      mbedtls_cipher_cmac_reset(), and mbedtls_cipher_cmac_finish().
- *                      Can be called repeatedly.
+ *                      The CMAC computation must have previously been started
+ *                      by calling mbedtls_cipher_cmac_starts() or
+ *                      mbedtls_cipher_cmac_reset().
+ *
+ *                      Call this function as many times as needed to input the
+ *                      data to be authenticated.
+ *                      Once all of the required data has been input,
+ *                      call mbedtls_cipher_cmac_finish() to obtain the result
+ *                      of the CMAC operation.
  *
  * \param ctx           The cipher context used for the CMAC operation.
  * \param input         The buffer holding the input data.
@@ -111,12 +132,13 @@
                                 const unsigned char *input, size_t ilen );
 
 /**
- * \brief               This function finishes the CMAC operation, and writes
- *                      the result to the output buffer.
+ * \brief               This function finishes an ongoing CMAC operation, and
+ *                      writes the result to the output buffer.
  *
- *                      It is called after mbedtls_cipher_cmac_update().
- *                      It can be followed by mbedtls_cipher_cmac_reset() and
- *                      mbedtls_cipher_cmac_update(), or mbedtls_cipher_free().
+ *                      It should be followed either by
+ *                      mbedtls_cipher_cmac_reset(), which starts another CMAC
+ *                      operation with the same key, or mbedtls_cipher_free(),
+ *                      which clears the cipher context.
  *
  * \param ctx           The cipher context used for the CMAC operation.
  * \param output        The output buffer for the CMAC checksum result.
@@ -129,12 +151,14 @@
                                 unsigned char *output );
 
 /**
- * \brief               This function prepares the authentication of another
- *                      message with the same key as the previous CMAC
- *                      operation.
+ * \brief               This function starts a new CMAC operation with the same
+ *                      key as the previous one.
  *
- *                      It is called after mbedtls_cipher_cmac_finish()
- *                      and before mbedtls_cipher_cmac_update().
+ *                      It should be called after finishing the previous CMAC
+ *                      operation with mbedtls_cipher_cmac_finish().
+ *                      After calling this function,
+ *                      call mbedtls_cipher_cmac_update() to supply the new
+ *                      CMAC operation with data.
  *
  * \param ctx           The cipher context used for the CMAC operation.
  *
@@ -154,6 +178,11 @@
  *                      The CMAC result is calculated as
  *                      output = generic CMAC(cmac key, input buffer).
  *
+ * \note                When the CMAC implementation is supplied by an alternate
+ *                      implementation (through #MBEDTLS_CMAC_ALT), some ciphers
+ *                      may not be supported by that implementation, and thus
+ *                      return an error. Alternate implementations must support
+ *                      AES-128 and AES-256, and may support AES-192 and 3DES.
  *
  * \param cipher_info   The cipher information.
  * \param key           The CMAC key.
@@ -198,6 +227,13 @@
 /**
  * \brief          The CMAC checkup routine.
  *
+ * \note           In case the CMAC routines are provided by an alternative
+ *                 implementation (i.e. #MBEDTLS_CMAC_ALT is defined), the
+ *                 checkup routine will succeed even if the implementation does
+ *                 not support the less widely used AES-192 or 3DES primitives.
+ *                 The self-test requires at least AES-128 and AES-256 to be
+ *                 supported by the underlying implementation.
+ *
  * \return         \c 0 on success.
  * \return         \c 1 on failure.
  */
diff --git a/third_party/mbedtls/repo/include/mbedtls/config.h b/third_party/mbedtls/repo/include/mbedtls/config.h
index 464b61e..87b4e91 100644
--- a/third_party/mbedtls/repo/include/mbedtls/config.h
+++ b/third_party/mbedtls/repo/include/mbedtls/config.h
@@ -427,7 +427,7 @@
  *       be overridden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt
  *       must stay untouched.
  *
- * \note If you use the AES_xxx_ALT macros, then is is recommended to also set
+ * \note If you use the AES_xxx_ALT macros, then it is recommended to also set
  *       MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES
  *       tables.
  *
@@ -484,6 +484,11 @@
  * is still present and it is used for group structures not supported by the
  * alternative.
  *
+ * The original implementation can in addition be removed by setting the
+ * MBEDTLS_ECP_NO_FALLBACK option, in which case any function for which the
+ * corresponding MBEDTLS_ECP__FUNCTION_NAME__ALT macro is defined will not be
+ * able to fallback to curves not supported by the alternative implementation.
+ *
  * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT
  * and implementing the following functions:
  *      unsigned char mbedtls_internal_ecp_grp_capable(
@@ -497,21 +502,28 @@
  * called before and after each point operation and provide an opportunity to
  * implement optimized set up and tear down instructions.
  *
- * Example: In case you uncomment MBEDTLS_ECP_INTERNAL_ALT and
- * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac
- * function, but will use your mbedtls_internal_ecp_double_jac if the group is
- * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when
- * receives it as an argument). If the group is not supported then the original
- * implementation is used. The other functions and the definition of
- * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your
- * implementation of mbedtls_internal_ecp_double_jac and
- * mbedtls_internal_ecp_grp_capable must be compatible with this definition.
+ * Example: In case you set MBEDTLS_ECP_INTERNAL_ALT and
+ * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac()
+ * function, but will use your mbedtls_internal_ecp_double_jac() if the group
+ * for the operation is supported by your implementation (i.e. your
+ * mbedtls_internal_ecp_grp_capable() function returns 1 for this group). If the
+ * group is not supported by your implementation, then the original mbed TLS
+ * implementation of ecp_double_jac() is used instead, unless this fallback
+ * behaviour is disabled by setting MBEDTLS_ECP_NO_FALLBACK (in which case
+ * ecp_double_jac() will return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE).
+ *
+ * The function prototypes and the definition of mbedtls_ecp_group and
+ * mbedtls_ecp_point will not change based on MBEDTLS_ECP_INTERNAL_ALT, so your
+ * implementation of mbedtls_internal_ecp__function_name__ must be compatible
+ * with their definitions.
  *
  * Uncomment a macro to enable alternate implementation of the corresponding
  * function.
  */
 /* Required for all the functions in this section */
 //#define MBEDTLS_ECP_INTERNAL_ALT
+/* Turn off software fallback for curves not supported in hardware */
+//#define MBEDTLS_ECP_NO_FALLBACK
 /* Support for Weierstrass curves with Jacobi representation */
 //#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT
 //#define MBEDTLS_ECP_ADD_MIXED_ALT
@@ -605,6 +617,29 @@
 //#define MBEDTLS_CAMELLIA_SMALL_MEMORY
 
 /**
+ * \def MBEDTLS_CHECK_RETURN_WARNING
+ *
+ * If this macro is defined, emit a compile-time warning if application code
+ * calls a function without checking its return value, but the return value
+ * should generally be checked in portable applications.
+ *
+ * This is only supported on platforms where #MBEDTLS_CHECK_RETURN is
+ * implemented. Otherwise this option has no effect.
+ *
+ * Uncomment to get warnings on using fallible functions without checking
+ * their return value.
+ *
+ * \note  This feature is a work in progress.
+ *        Warnings will be added to more functions in the future.
+ *
+ * \note  A few functions are considered critical, and ignoring the return
+ *        value of these functions will trigger a warning even if this
+ *        macro is not defined. To completely disable return value check
+ *        warnings, define #MBEDTLS_CHECK_RETURN with an empty expansion.
+ */
+//#define MBEDTLS_CHECK_RETURN_WARNING
+
+/**
  * \def MBEDTLS_CIPHER_MODE_CBC
  *
  * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers.
@@ -1326,6 +1361,38 @@
  */
 #define MBEDTLS_PKCS1_V21
 
+/** \def MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS
+ *
+ * Enable support for platform built-in keys. If you enable this feature,
+ * you must implement the function mbedtls_psa_platform_get_builtin_key().
+ * See the documentation of that function for more information.
+ *
+ * Built-in keys are typically derived from a hardware unique key or
+ * stored in a secure element.
+ *
+ * Requires: MBEDTLS_PSA_CRYPTO_C.
+ *
+ * \warning This interface is experimental and may change or be removed
+ * without notice.
+ */
+//#define MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS
+
+/** \def MBEDTLS_PSA_CRYPTO_CLIENT
+ *
+ * Enable support for PSA crypto client.
+ *
+ * \note This option allows to include the code necessary for a PSA
+ *       crypto client when the PSA crypto implementation is not included in
+ *       the library (MBEDTLS_PSA_CRYPTO_C disabled). The code included is the
+ *       code to set and get PSA key attributes.
+ *       The development of PSA drivers partially relying on the library to
+ *       fulfill the hardware gaps is another possible usage of this option.
+ *
+ * \warning This interface is experimental and may change or be removed
+ * without notice.
+ */
+//#define MBEDTLS_PSA_CRYPTO_CLIENT
+
 /** \def MBEDTLS_PSA_CRYPTO_DRIVERS
  *
  * Enable support for the experimental PSA crypto driver interface.
@@ -1337,6 +1404,44 @@
  */
 //#define MBEDTLS_PSA_CRYPTO_DRIVERS
 
+/** \def MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+ *
+ * Make the PSA Crypto module use an external random generator provided
+ * by a driver, instead of Mbed TLS's entropy and DRBG modules.
+ *
+ * \note This random generator must deliver random numbers with cryptographic
+ *       quality and high performance. It must supply unpredictable numbers
+ *       with a uniform distribution. The implementation of this function
+ *       is responsible for ensuring that the random generator is seeded
+ *       with sufficient entropy. If you have a hardware TRNG which is slow
+ *       or delivers non-uniform output, declare it as an entropy source
+ *       with mbedtls_entropy_add_source() instead of enabling this option.
+ *
+ * If you enable this option, you must configure the type
+ * ::mbedtls_psa_external_random_context_t in psa/crypto_platform.h
+ * and define a function called mbedtls_psa_external_get_random()
+ * with the following prototype:
+ * ```
+ * psa_status_t mbedtls_psa_external_get_random(
+ *     mbedtls_psa_external_random_context_t *context,
+ *     uint8_t *output, size_t output_size, size_t *output_length);
+ * );
+ * ```
+ * The \c context value is initialized to 0 before the first call.
+ * The function must fill the \c output buffer with \p output_size bytes
+ * of random data and set \c *output_length to \p output_size.
+ *
+ * Requires: MBEDTLS_PSA_CRYPTO_C
+ *
+ * \warning If you enable this option, code that uses the PSA cryptography
+ *          interface will not use any of the entropy sources set up for
+ *          the entropy module, nor the NV seed that MBEDTLS_ENTROPY_NV_SEED
+ *          enables.
+ *
+ * \note This option is experimental and may be removed without notice.
+ */
+//#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+
 /**
  * \def MBEDTLS_PSA_CRYPTO_SPM
  *
@@ -1815,7 +1920,7 @@
 /**
  * \def MBEDTLS_SSL_DTLS_SRTP
  *
- * Enable support for negotation of DTLS-SRTP (RFC 5764)
+ * Enable support for negotiation of DTLS-SRTP (RFC 5764)
  * through the use_srtp extension.
  *
  * \note This feature provides the minimum functionality required
@@ -1941,7 +2046,10 @@
 /**
  * \def MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH
  *
- * Enable modifying the maximum I/O buffer size.
+ * When this option is enabled, the SSL buffer will be resized automatically
+ * based on the negotiated maximum fragment length in each direction.
+ *
+ * Requires: MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
  */
 //#define MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH
 
@@ -2034,15 +2142,13 @@
  * will still continue to work as usual, so enabling this option should not
  * break backwards compatibility.
  *
- * \warning The PSA Crypto API is in beta stage. While you're welcome to
- * experiment using it, incompatible API changes are still possible, and some
- * parts may not have reached the same quality as the rest of Mbed TLS yet.
+ * \note See docs/use-psa-crypto.md for a complete description of what this
+ * option currently does, and of parts that are not affected by it so far.
  *
- * \warning This option enables new Mbed TLS APIs that are dependent on the
- * PSA Crypto API, so can't come with the same stability guarantees as the
- * rest of the Mbed TLS APIs. You're welcome to experiment with them, but for
- * now, access to these APIs is opt-in (via enabling the present option), in
- * order to clearly differentiate them from the stable Mbed TLS APIs.
+ * \warning This option enables new Mbed TLS APIs which are currently
+ * considered experimental and may change in incompatible ways at any time.
+ * That is, the APIs enabled by this option are not covered by the usual
+ * promises of API stability.
  *
  * Requires: MBEDTLS_PSA_CRYPTO_C.
  *
@@ -2546,6 +2652,11 @@
  * Enable the CMAC (Cipher-based Message Authentication Code) mode for block
  * ciphers.
  *
+ * \note When #MBEDTLS_CMAC_ALT is active, meaning that the underlying
+ *       implementation of the CMAC algorithm is provided by an alternate
+ *       implementation, that alternate implementation may opt to not support
+ *       AES-192 or 3DES as underlying block ciphers for the CMAC operation.
+ *
  * Module:  library/cmac.c
  *
  * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C
@@ -3109,13 +3220,11 @@
  *
  * Enable the Platform Security Architecture cryptography API.
  *
- * \warning The PSA Crypto API is still beta status. While you're welcome to
- * experiment using it, incompatible API changes are still possible, and some
- * parts may not have reached the same quality as the rest of Mbed TLS yet.
- *
  * Module:  library/psa_crypto.c
  *
- * Requires: MBEDTLS_CTR_DRBG_C, MBEDTLS_ENTROPY_C
+ * Requires: either MBEDTLS_CTR_DRBG_C and MBEDTLS_ENTROPY_C,
+ *           or MBEDTLS_HMAC_DRBG_C and MBEDTLS_ENTROPY_C,
+ *           or MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG.
  *
  */
 #define MBEDTLS_PSA_CRYPTO_C
@@ -3524,8 +3633,8 @@
 //#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT      384 /**< Maximum size of (re)seed buffer */
 
 /* ECP options */
-//#define MBEDTLS_ECP_MAX_BITS             521 /**< Maximum bit size of groups */
-//#define MBEDTLS_ECP_WINDOW_SIZE            6 /**< Maximum window size used */
+//#define MBEDTLS_ECP_MAX_BITS             521 /**< Maximum bit size of groups. Normally determined automatically from the configured curves. */
+//#define MBEDTLS_ECP_WINDOW_SIZE            4 /**< Maximum window size used */
 //#define MBEDTLS_ECP_FIXED_POINT_OPTIM      1 /**< Enable fixed-point speed-up */
 
 /* Entropy options */
@@ -3603,6 +3712,53 @@
  */
 //#define MBEDTLS_PARAM_FAILED( cond )               assert( cond )
 
+/** \def MBEDTLS_CHECK_RETURN
+ *
+ * This macro is used at the beginning of the declaration of a function
+ * to indicate that its return value should be checked. It should
+ * instruct the compiler to emit a warning or an error if the function
+ * is called without checking its return value.
+ *
+ * There is a default implementation for popular compilers in platform_util.h.
+ * You can override the default implementation by defining your own here.
+ *
+ * If the implementation here is empty, this will effectively disable the
+ * checking of functions' return values.
+ */
+//#define MBEDTLS_CHECK_RETURN __attribute__((__warn_unused_result__))
+
+/** \def MBEDTLS_IGNORE_RETURN
+ *
+ * This macro requires one argument, which should be a C function call.
+ * If that function call would cause a #MBEDTLS_CHECK_RETURN warning, this
+ * warning is suppressed.
+ */
+//#define MBEDTLS_IGNORE_RETURN( result ) ((void) !(result))
+
+/* PSA options */
+/**
+ * Use HMAC_DRBG with the specified hash algorithm for HMAC_DRBG for the
+ * PSA crypto subsystem.
+ *
+ * If this option is unset:
+ * - If CTR_DRBG is available, the PSA subsystem uses it rather than HMAC_DRBG.
+ * - Otherwise, the PSA subsystem uses HMAC_DRBG with either
+ *   #MBEDTLS_MD_SHA512 or #MBEDTLS_MD_SHA256 based on availability and
+ *   on unspecified heuristics.
+ */
+//#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256
+
+/** \def MBEDTLS_PSA_KEY_SLOT_COUNT
+ * Restrict the PSA library to supporting a maximum amount of simultaneously
+ * loaded keys. A loaded key is a key stored by the PSA Crypto core as a
+ * volatile key, or a persistent key which is loaded temporarily by the
+ * library as part of a crypto operation in flight.
+ *
+ * If this option is unset, the library will fall back to a default value of
+ * 32 keys.
+ */
+//#define MBEDTLS_PSA_KEY_SLOT_COUNT 32
+
 /* SSL Cache options */
 //#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT       86400 /**< 1 day  */
 //#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES      50 /**< Maximum entries in cache */
@@ -3736,7 +3892,7 @@
  * Maximum number of heap-allocated bytes for the purpose of
  * DTLS handshake message reassembly and future message buffering.
  *
- * This should be at least 9/8 * MBEDTLSSL_IN_CONTENT_LEN
+ * This should be at least 9/8 * MBEDTLS_SSL_IN_CONTENT_LEN
  * to account for a reassembled handshake message of maximum size,
  * together with its reassembly bitmap.
  *
@@ -3752,6 +3908,17 @@
 //#define MBEDTLS_PSK_MAX_LEN               32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */
 //#define MBEDTLS_SSL_COOKIE_TIMEOUT        60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */
 
+/** \def MBEDTLS_TLS_EXT_CID
+ *
+ * At the time of writing, the CID extension has not been assigned its
+ * final value. Set this configuration option to make Mbed TLS use a
+ * different value.
+ *
+ * A future minor revision of Mbed TLS may change the default value of
+ * this option to match evolving standards and usage.
+ */
+//#define MBEDTLS_TLS_EXT_CID                        254
+
 /**
  * Complete list of ciphersuites to use, in order of preference.
  *
@@ -3771,20 +3938,6 @@
 //#define MBEDTLS_X509_MAX_FILE_PATH_LEN     512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */
 
 /**
- * Allow SHA-1 in the default TLS configuration for certificate signing.
- * Without this build-time option, SHA-1 support must be activated explicitly
- * through mbedtls_ssl_conf_cert_profile. Turning on this option is not
- * recommended because of it is possible to generate SHA-1 collisions, however
- * this may be safe for legacy infrastructure where additional controls apply.
- *
- * \warning   SHA-1 is considered a weak message digest and its use constitutes
- *            a security risk. If possible, we recommend avoiding dependencies
- *            on it, and considering stronger message digests instead.
- *
- */
-//#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES
-
-/**
  * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake
  * signature and ciphersuite selection. Without this build-time option, SHA-1
  * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes.
@@ -3799,7 +3952,7 @@
  *            on it, and considering stronger message digests instead.
  *
  */
-#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE
+//#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE
 
 /**
  * Uncomment the macro to let mbed TLS use your alternate implementation of
diff --git a/third_party/mbedtls/repo/include/mbedtls/config_psa.h b/third_party/mbedtls/repo/include/mbedtls/config_psa.h
index 2b4c498..189f6c2 100644
--- a/third_party/mbedtls/repo/include/mbedtls/config_psa.h
+++ b/third_party/mbedtls/repo/include/mbedtls/config_psa.h
@@ -38,6 +38,36 @@
 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_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
+
+
+
+/****************************************************************/
+/* Require built-in implementations based on PSA requirements */
+/****************************************************************/
+
 #if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
 
 #if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)
@@ -63,6 +93,10 @@
 #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 */
 
@@ -205,6 +239,8 @@
 #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 */
 
@@ -217,9 +253,311 @@
 #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_XTS) && !defined(MBEDTLS_PSA_ACCEL_ALG_XTS)) || \
+    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_ARC4)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARC4)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARC4 1
+#define MBEDTLS_ARC4_C
+#endif /*!MBEDTLS_PSA_ACCEL_KEY_TYPE_ARC4 */
+#endif /* PSA_WANT_KEY_TYPE_ARC4 */
+
+#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_XTS)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_XTS) || \
+    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
+#define MBEDTLS_PSA_BUILTIN_ALG_XTS 1
+#define MBEDTLS_CIPHER_MODE_XTS
+#endif
+#endif /* PSA_WANT_ALG_XTS */
+
+#if defined(PSA_WANT_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_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_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)
+/*
+ * Curve448 is not yet supported via the PSA API in Mbed TLS
+ * (https://github.com/ARMmbed/mbedtls/issues/4249).
+ */
+#error "Curve448 is not yet supported via the PSA API in Mbed TLS."
+#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/ARMmbed/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 */
 
 /*
@@ -227,6 +565,16 @@
  * is not defined
  */
 
+#if defined(MBEDTLS_CCM_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_CCM 1
+#define PSA_WANT_ALG_CCM 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
@@ -235,6 +583,7 @@
 #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)
@@ -251,6 +600,11 @@
 #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 */
+
 #if defined(MBEDTLS_HKDF_C)
 #define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
 #define PSA_WANT_ALG_HMAC 1
@@ -261,6 +615,7 @@
 #if defined(MBEDTLS_MD_C)
 #define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
 #define PSA_WANT_ALG_HMAC 1
+#define PSA_WANT_KEY_TYPE_HMAC
 #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
@@ -293,7 +648,8 @@
 #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
-#endif /* MBEDTLSS_PKCS1_V15 */
+#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
@@ -314,6 +670,7 @@
 #if defined(MBEDTLS_SHA256_C)
 #define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1
 #define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1
+#define PSA_WANT_ALG_SHA_224 1
 #define PSA_WANT_ALG_SHA_256 1
 #endif
 
@@ -326,8 +683,152 @@
 #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_ARC4_C)
+#define PSA_WANT_KEY_TYPE_ARC4 1
+#define PSA_WANT_ALG_STREAM_CIPHER 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARC4 1
+#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 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_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_CIPHER_MODE_XTS)
+#define MBEDTLS_PSA_BUILTIN_ALG_XTS 1
+#define PSA_WANT_ALG_XTS 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
+
+/* Curve448 is not yet supported via the PSA API (https://github.com/ARMmbed/mbedtls/issues/4249) */
+#if 0 && 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
+
+/* SECP224K1 is buggy via the PSA API (https://github.com/ARMmbed/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
+
+#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1
+#define PSA_WANT_ECC_SECP_K1_256
+#endif
+
 #endif /* MBEDTLS_PSA_CRYPTO_CONFIG */
 
+/* These features are always enabled. */
+#define PSA_WANT_KEY_TYPE_DERIVE 1
+#define PSA_WANT_KEY_TYPE_RAW_DATA 1
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/third_party/mbedtls/repo/include/mbedtls/constant_time.h b/third_party/mbedtls/repo/include/mbedtls/constant_time.h
new file mode 100644
index 0000000..c5de57a
--- /dev/null
+++ b/third_party/mbedtls/repo/include/mbedtls/constant_time.h
@@ -0,0 +1,45 @@
+/**
+ *  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.
+ */
+
+#ifndef MBEDTLS_CONSTANT_TIME_H
+#define MBEDTLS_CONSTANT_TIME_H
+
+#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.
+ *
+ * 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.
+ *
+ * \return      Zero if the content of the two buffer is the same,
+ *              otherwise non-zero.
+ */
+int mbedtls_ct_memcmp( const void *a,
+                       const void *b,
+                       size_t n );
+
+#endif /* MBEDTLS_CONSTANT_TIME_H */
diff --git a/third_party/mbedtls/repo/include/mbedtls/ctr_drbg.h b/third_party/mbedtls/repo/include/mbedtls/ctr_drbg.h
index 7f1d232..dc4adc8 100644
--- a/third_party/mbedtls/repo/include/mbedtls/ctr_drbg.h
+++ b/third_party/mbedtls/repo/include/mbedtls/ctr_drbg.h
@@ -53,10 +53,14 @@
 #include "mbedtls/threading.h"
 #endif
 
-#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED        -0x0034  /**< The entropy source failed. */
-#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG              -0x0036  /**< The requested random buffer length is too big. */
-#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG                -0x0038  /**< The input (entropy + additional data) is too large. */
-#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR                -0x003A  /**< Read or write error in file. */
+/** The entropy source failed. */
+#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED        -0x0034
+/** The requested random buffer length is too big. */
+#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG              -0x0036
+/** The input (entropy + additional data) is too large. */
+#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG                -0x0038
+/** Read or write error in file. */
+#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR                -0x003A
 
 #define MBEDTLS_CTR_DRBG_BLOCKSIZE          16 /**< The block size used by the cipher. */
 
@@ -200,6 +204,13 @@
     void *p_entropy;            /*!< The context for the entropy function. */
 
 #if defined(MBEDTLS_THREADING_C)
+    /* Invariant: the mutex is initialized if and only if f_entropy != NULL.
+     * This means that the mutex is initialized during the initial seeding
+     * in mbedtls_ctr_drbg_seed() and freed in mbedtls_ctr_drbg_free().
+     *
+     * Note that this invariant may change without notice. Do not rely on it
+     * and do not access the mutex directly in application code.
+     */
     mbedtls_threading_mutex_t mutex;
 #endif
 }
@@ -264,6 +275,15 @@
  *   make a second call to \p f_entropy.
  */
 #endif
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note                When Mbed TLS is built with threading support,
+ *                      after this function returns successfully,
+ *                      it is safe to call mbedtls_ctr_drbg_random()
+ *                      from multiple threads. Other operations, including
+ *                      reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
 /**
  * - The \p custom string.
  *
@@ -290,6 +310,8 @@
  *                      the same context unless you call
  *                      mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init()
  *                      again first.
+ *                      After a failed call to mbedtls_ctr_drbg_seed(),
+ *                      you must call mbedtls_ctr_drbg_free().
  * \param f_entropy     The entropy callback, taking as arguments the
  *                      \p p_entropy context, the buffer to fill, and the
  *                      length of the buffer.
@@ -405,6 +427,11 @@
  * \brief               This function reseeds the CTR_DRBG context, that is
  *                      extracts data from the entropy source.
  *
+ * \note                This function is not thread-safe. It is not safe
+ *                      to call this function if another thread might be
+ *                      concurrently obtaining random numbers from the same
+ *                      context or updating or reseeding the same context.
+ *
  * \param ctx           The CTR_DRBG context.
  * \param additional    Additional data to add to the state. Can be \c NULL.
  * \param len           The length of the additional data.
@@ -422,6 +449,11 @@
 /**
  * \brief              This function updates the state of the CTR_DRBG context.
  *
+ * \note                This function is not thread-safe. It is not safe
+ *                      to call this function if another thread might be
+ *                      concurrently obtaining random numbers from the same
+ *                      context or updating or reseeding the same context.
+ *
  * \param ctx          The CTR_DRBG context.
  * \param additional   The data to update the state with. This must not be
  *                     \c NULL unless \p add_len is \c 0.
@@ -445,6 +477,11 @@
  * This function automatically reseeds if the reseed counter is exceeded
  * or prediction resistance is enabled.
  *
+ * \note                This function is not thread-safe. It is not safe
+ *                      to call this function if another thread might be
+ *                      concurrently obtaining random numbers from the same
+ *                      context or updating or reseeding the same context.
+ *
  * \param p_rng         The CTR_DRBG context. This must be a pointer to a
  *                      #mbedtls_ctr_drbg_context structure.
  * \param output        The buffer to fill.
@@ -473,8 +510,16 @@
  *
  * This function automatically reseeds if the reseed counter is exceeded
  * or prediction resistance is enabled.
- *
- *
+ */
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note                When Mbed TLS is built with threading support,
+ *                      it is safe to call mbedtls_ctr_drbg_random()
+ *                      from multiple threads. Other operations, including
+ *                      reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
+/**
  * \param p_rng         The CTR_DRBG context. This must be a pointer to a
  *                      #mbedtls_ctr_drbg_context structure.
  * \param output        The buffer to fill.
diff --git a/third_party/mbedtls/repo/include/mbedtls/debug.h b/third_party/mbedtls/repo/include/mbedtls/debug.h
index ab5b037..3c08244 100644
--- a/third_party/mbedtls/repo/include/mbedtls/debug.h
+++ b/third_party/mbedtls/repo/include/mbedtls/debug.h
@@ -80,6 +80,55 @@
 
 #endif /* MBEDTLS_DEBUG_C */
 
+/**
+ * \def MBEDTLS_PRINTF_ATTRIBUTE
+ *
+ * Mark a function as having printf attributes, and thus enable checking
+ * via -wFormat and other flags. This does nothing on builds with compilers
+ * that do not support the format attribute
+ *
+ * Module:  library/debug.c
+ * Caller:
+ *
+ * This module provides debugging functions.
+ */
+#if defined(__has_attribute)
+#if __has_attribute(format)
+#if defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 1
+#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check)    \
+    __attribute__((__format__ (gnu_printf, string_index, first_to_check)))
+#else /* defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 1 */
+#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check)    \
+    __attribute__((format(printf, string_index, first_to_check)))
+#endif
+#else /* __has_attribute(format) */
+#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check)
+#endif /* __has_attribute(format) */
+#else /* defined(__has_attribute) */
+#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check)
+#endif
+
+/**
+ * \def MBEDTLS_PRINTF_SIZET
+ *
+ * MBEDTLS_PRINTF_xxx: Due to issues with older window compilers
+ * and MinGW we need to define the printf specifier for size_t
+ * and long long per platform.
+ *
+ * Module:  library/debug.c
+ * Caller:
+ *
+ * This module provides debugging functions.
+ */
+#if (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800)
+   #include <inttypes.h>
+   #define MBEDTLS_PRINTF_SIZET     PRIuPTR
+   #define MBEDTLS_PRINTF_LONGLONG  "I64d"
+#else /* (defined(__MINGW32__)  && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) */
+   #define MBEDTLS_PRINTF_SIZET     "zu"
+   #define MBEDTLS_PRINTF_LONGLONG  "lld"
+#endif /* (defined(__MINGW32__)  && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) */
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -118,7 +167,7 @@
  */
 void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level,
                               const char *file, int line,
-                              const char *format, ... );
+                              const char *format, ... ) MBEDTLS_PRINTF_ATTRIBUTE(5, 6);
 
 /**
  * \brief   Print the return value of a function to the debug output. This
diff --git a/third_party/mbedtls/repo/include/mbedtls/des.h b/third_party/mbedtls/repo/include/mbedtls/des.h
index 549d19b..325aab5 100644
--- a/third_party/mbedtls/repo/include/mbedtls/des.h
+++ b/third_party/mbedtls/repo/include/mbedtls/des.h
@@ -32,6 +32,7 @@
 #else
 #include MBEDTLS_CONFIG_FILE
 #endif
+#include "mbedtls/platform_util.h"
 
 #include <stddef.h>
 #include <stdint.h>
@@ -39,10 +40,12 @@
 #define MBEDTLS_DES_ENCRYPT     1
 #define MBEDTLS_DES_DECRYPT     0
 
-#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH              -0x0032  /**< The data input has an invalid length. */
+/** The data input has an invalid length. */
+#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH              -0x0032
 
 /* MBEDTLS_ERR_DES_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_DES_HW_ACCEL_FAILED                   -0x0033  /**< DES hardware accelerator failed. */
+/** DES hardware accelerator failed. */
+#define MBEDTLS_ERR_DES_HW_ACCEL_FAILED                   -0x0033
 
 #define MBEDTLS_DES_KEY_SIZE    8
 
@@ -144,6 +147,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
 
 /**
@@ -157,6 +161,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
 
 /**
@@ -171,6 +176,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
 
 /**
@@ -185,6 +191,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
 
 /**
@@ -195,6 +202,7 @@
  *
  * \return         0
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
                       const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
 
@@ -206,6 +214,7 @@
  *
  * \return         0
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
                       const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
 
@@ -217,6 +226,7 @@
  *
  * \return         0
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
                       const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
 
@@ -228,6 +238,7 @@
  *
  * \return         0
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
                       const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
 
@@ -244,6 +255,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
                     const unsigned char input[8],
                     unsigned char output[8] );
@@ -271,6 +283,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
                     int mode,
                     size_t length,
@@ -288,6 +301,7 @@
  *
  * \return         0 if successful
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
                      const unsigned char input[8],
                      unsigned char output[8] );
@@ -313,6 +327,7 @@
  *
  * \return         0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
                      int mode,
                      size_t length,
@@ -343,6 +358,7 @@
  *
  * \return         0 if successful, or 1 if the test failed
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_des_self_test( int verbose );
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/third_party/mbedtls/repo/include/mbedtls/dhm.h b/third_party/mbedtls/repo/include/mbedtls/dhm.h
index c7830b9..c4b15a2 100644
--- a/third_party/mbedtls/repo/include/mbedtls/dhm.h
+++ b/third_party/mbedtls/repo/include/mbedtls/dhm.h
@@ -73,20 +73,31 @@
 /*
  * DHM Error codes
  */
-#define MBEDTLS_ERR_DHM_BAD_INPUT_DATA                    -0x3080  /**< Bad input parameters. */
-#define MBEDTLS_ERR_DHM_READ_PARAMS_FAILED                -0x3100  /**< Reading of the DHM parameters failed. */
-#define MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED                -0x3180  /**< Making of the DHM parameters failed. */
-#define MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED                -0x3200  /**< Reading of the public values failed. */
-#define MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED                -0x3280  /**< Making of the public value failed. */
-#define MBEDTLS_ERR_DHM_CALC_SECRET_FAILED                -0x3300  /**< Calculation of the DHM secret failed. */
-#define MBEDTLS_ERR_DHM_INVALID_FORMAT                    -0x3380  /**< The ASN.1 data is not formatted correctly. */
-#define MBEDTLS_ERR_DHM_ALLOC_FAILED                      -0x3400  /**< Allocation of memory failed. */
-#define MBEDTLS_ERR_DHM_FILE_IO_ERROR                     -0x3480  /**< Read or write of file failed. */
+/** Bad input parameters. */
+#define MBEDTLS_ERR_DHM_BAD_INPUT_DATA                    -0x3080
+/** Reading of the DHM parameters failed. */
+#define MBEDTLS_ERR_DHM_READ_PARAMS_FAILED                -0x3100
+/** Making of the DHM parameters failed. */
+#define MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED                -0x3180
+/** Reading of the public values failed. */
+#define MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED                -0x3200
+/** Making of the public value failed. */
+#define MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED                -0x3280
+/** Calculation of the DHM secret failed. */
+#define MBEDTLS_ERR_DHM_CALC_SECRET_FAILED                -0x3300
+/** The ASN.1 data is not formatted correctly. */
+#define MBEDTLS_ERR_DHM_INVALID_FORMAT                    -0x3380
+/** Allocation of memory failed. */
+#define MBEDTLS_ERR_DHM_ALLOC_FAILED                      -0x3400
+/** Read or write of file failed. */
+#define MBEDTLS_ERR_DHM_FILE_IO_ERROR                     -0x3480
 
 /* MBEDTLS_ERR_DHM_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_DHM_HW_ACCEL_FAILED                   -0x3500  /**< DHM hardware accelerator failed. */
+/** DHM hardware accelerator failed. */
+#define MBEDTLS_ERR_DHM_HW_ACCEL_FAILED                   -0x3500
 
-#define MBEDTLS_ERR_DHM_SET_GROUP_FAILED                  -0x3580  /**< Setting the modulus and generator failed. */
+/** Setting the modulus and generator failed. */
+#define MBEDTLS_ERR_DHM_SET_GROUP_FAILED                  -0x3580
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/ecp.h b/third_party/mbedtls/repo/include/mbedtls/ecp.h
index 34dd0ea..0924341 100644
--- a/third_party/mbedtls/repo/include/mbedtls/ecp.h
+++ b/third_party/mbedtls/repo/include/mbedtls/ecp.h
@@ -45,19 +45,29 @@
 /*
  * ECP error codes
  */
-#define MBEDTLS_ERR_ECP_BAD_INPUT_DATA                    -0x4F80  /**< Bad input parameters to function. */
-#define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL                  -0x4F00  /**< The buffer is too small to write to. */
-#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE               -0x4E80  /**< The requested feature is not available, for example, the requested curve is not supported. */
-#define MBEDTLS_ERR_ECP_VERIFY_FAILED                     -0x4E00  /**< The signature is not valid. */
-#define MBEDTLS_ERR_ECP_ALLOC_FAILED                      -0x4D80  /**< Memory allocation failed. */
-#define MBEDTLS_ERR_ECP_RANDOM_FAILED                     -0x4D00  /**< Generation of random value, such as ephemeral key, failed. */
-#define MBEDTLS_ERR_ECP_INVALID_KEY                       -0x4C80  /**< Invalid private or public key. */
-#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH                  -0x4C00  /**< The buffer contains a valid signature followed by more data. */
+/** Bad input parameters to function. */
+#define MBEDTLS_ERR_ECP_BAD_INPUT_DATA                    -0x4F80
+/** The buffer is too small to write to. */
+#define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL                  -0x4F00
+/** The requested feature is not available, for example, the requested curve is not supported. */
+#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE               -0x4E80
+/** The signature is not valid. */
+#define MBEDTLS_ERR_ECP_VERIFY_FAILED                     -0x4E00
+/** Memory allocation failed. */
+#define MBEDTLS_ERR_ECP_ALLOC_FAILED                      -0x4D80
+/** Generation of random value, such as ephemeral key, failed. */
+#define MBEDTLS_ERR_ECP_RANDOM_FAILED                     -0x4D00
+/** Invalid private or public key. */
+#define MBEDTLS_ERR_ECP_INVALID_KEY                       -0x4C80
+/** The buffer contains a valid signature followed by more data. */
+#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH                  -0x4C00
 
 /* MBEDTLS_ERR_ECP_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED                   -0x4B80  /**< The ECP hardware accelerator failed. */
+/** The ECP hardware accelerator failed. */
+#define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED                   -0x4B80
 
-#define MBEDTLS_ERR_ECP_IN_PROGRESS                       -0x4B00  /**< Operation in progress, call again with the same parameters to continue. */
+/** Operation in progress, call again with the same parameters to continue. */
+#define MBEDTLS_ERR_ECP_IN_PROGRESS                       -0x4B00
 
 /* Flags indicating whether to include code that is specific to certain
  * types of curves. These flags are for internal library use only. */
@@ -96,6 +106,7 @@
  * - Add it at the end of this enum, otherwise you'll break the ABI by
  *   changing the numerical value for existing curves.
  * - Increment MBEDTLS_ECP_DP_MAX below if needed.
+ * - Update the calculation of MBEDTLS_ECP_MAX_BITS_MIN below.
  * - Add the corresponding MBEDTLS_ECP_DP_xxx_ENABLED macro definition to
  *   config.h.
  * - List the curve as a dependency of MBEDTLS_ECP_C and
@@ -171,6 +182,40 @@
 }
 mbedtls_ecp_point;
 
+/* Determine the minimum safe value of MBEDTLS_ECP_MAX_BITS. */
+#if !defined(MBEDTLS_ECP_C)
+#define MBEDTLS_ECP_MAX_BITS_MIN 0
+/* Note: the curves must be listed in DECREASING size! */
+#elif defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 521
+#elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 512
+#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 448
+#elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 384
+#elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 384
+#elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 256
+#elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 256
+#elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 256
+#elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 255
+#elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 225 // n is slightly above 2^224
+#elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 224
+#elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 192
+#elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
+#define MBEDTLS_ECP_MAX_BITS_MIN 192
+#else
+#error "MBEDTLS_ECP_C enabled, but no curve?"
+#endif
+
 #if !defined(MBEDTLS_ECP_ALT)
 /*
  * default mbed TLS elliptic curve arithmetic implementation
@@ -245,11 +290,23 @@
  * \{
  */
 
-#if !defined(MBEDTLS_ECP_MAX_BITS)
+#if defined(MBEDTLS_ECP_MAX_BITS)
+
+#if MBEDTLS_ECP_MAX_BITS < MBEDTLS_ECP_MAX_BITS_MIN
+#error "MBEDTLS_ECP_MAX_BITS is smaller than the largest supported curve"
+#endif
+
+#elif defined(MBEDTLS_ECP_C)
 /**
  * The maximum size of the groups, that is, of \c N and \c P.
  */
-#define MBEDTLS_ECP_MAX_BITS     521   /**< The maximum size of groups, in bits. */
+#define MBEDTLS_ECP_MAX_BITS     MBEDTLS_ECP_MAX_BITS_MIN
+
+#else
+/* MBEDTLS_ECP_MAX_BITS is not relevant without MBEDTLS_ECP_C, but set it
+ * to a nonzero value so that code that unconditionally allocates an array
+ * of a size based on it keeps working if built without ECC support. */
+#define MBEDTLS_ECP_MAX_BITS 1
 #endif
 
 #define MBEDTLS_ECP_MAX_BYTES    ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 )
@@ -258,7 +315,8 @@
 #if !defined(MBEDTLS_ECP_WINDOW_SIZE)
 /*
  * Maximum "window" size used for point multiplication.
- * Default: 6.
+ * Default: a point where higher memory usage yields disminishing performance
+ *          returns.
  * Minimum value: 2. Maximum value: 7.
  *
  * Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
@@ -275,7 +333,7 @@
  *      224       475     475     453     398     342
  *      192       640     640     633     587     476
  */
-#define MBEDTLS_ECP_WINDOW_SIZE    6   /**< The maximum window size used. */
+#define MBEDTLS_ECP_WINDOW_SIZE    4   /**< The maximum window size used. */
 #endif /* MBEDTLS_ECP_WINDOW_SIZE */
 
 #if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM)
@@ -466,8 +524,7 @@
 
 /**
  * \brief           This function retrieves the information defined in
- *                  mbedtls_ecp_curve_info() for all supported curves in order
- *                  of preference.
+ *                  mbedtls_ecp_curve_info() for all supported curves.
  *
  * \note            This function returns information about all curves
  *                  supported by the library. Some curves may not be
@@ -1180,7 +1237,7 @@
  *
  * \param grp_id    The ECP group identifier.
  * \param key       The destination key.
- * \param buf       The the buffer containing the binary representation of the
+ * \param buf       The buffer containing the binary representation of the
  *                  key. (Big endian integer for Weierstrass curves, byte
  *                  string for Montgomery curves.)
  * \param buflen    The length of the buffer in bytes.
diff --git a/third_party/mbedtls/repo/include/mbedtls/entropy.h b/third_party/mbedtls/repo/include/mbedtls/entropy.h
index 5a9c11c..deb3c50 100644
--- a/third_party/mbedtls/repo/include/mbedtls/entropy.h
+++ b/third_party/mbedtls/repo/include/mbedtls/entropy.h
@@ -48,11 +48,16 @@
 #include "mbedtls/havege.h"
 #endif
 
-#define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED                 -0x003C  /**< Critical entropy source failure. */
-#define MBEDTLS_ERR_ENTROPY_MAX_SOURCES                   -0x003E  /**< No more sources can be added. */
-#define MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED            -0x0040  /**< No sources have been added to poll. */
-#define MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE              -0x003D  /**< No strong sources have been added to poll. */
-#define MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR                 -0x003F  /**< Read/write error in file. */
+/** Critical entropy source failure. */
+#define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED                 -0x003C
+/** No more sources can be added. */
+#define MBEDTLS_ERR_ENTROPY_MAX_SOURCES                   -0x003E
+/** No sources have been added to poll. */
+#define MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED            -0x0040
+/** No strong sources have been added to poll. */
+#define MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE              -0x003D
+/** Read/write error in file. */
+#define MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR                 -0x003F
 
 /**
  * \name SECTION: Module settings
@@ -120,13 +125,15 @@
  */
 typedef struct mbedtls_entropy_context
 {
-    int accumulator_started;
+    int accumulator_started; /* 0 after init.
+                              * 1 after the first update.
+                              * -1 after free. */
 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
     mbedtls_sha512_context  accumulator;
-#else
+#elif defined(MBEDTLS_ENTROPY_SHA256_ACCUMULATOR)
     mbedtls_sha256_context  accumulator;
 #endif
-    int             source_count;
+    int             source_count; /* Number of entries used in source. */
     mbedtls_entropy_source_state    source[MBEDTLS_ENTROPY_MAX_SOURCES];
 #if defined(MBEDTLS_HAVEGE_C)
     mbedtls_havege_state    havege_data;
diff --git a/third_party/mbedtls/repo/include/mbedtls/error.h b/third_party/mbedtls/repo/include/mbedtls/error.h
index cd7731e..50f2538 100644
--- a/third_party/mbedtls/repo/include/mbedtls/error.h
+++ b/third_party/mbedtls/repo/include/mbedtls/error.h
@@ -30,6 +30,11 @@
 
 #include <stddef.h>
 
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
 /**
  * Error code layout.
  *
@@ -111,8 +116,58 @@
 extern "C" {
 #endif
 
-#define MBEDTLS_ERR_ERROR_GENERIC_ERROR       -0x0001  /**< Generic error */
-#define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E  /**< This is a bug in the library */
+/** Generic error */
+#define MBEDTLS_ERR_ERROR_GENERIC_ERROR       -0x0001
+/** This is a bug in the library */
+#define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E
+
+/**
+ * \brief Combines a high-level and low-level error code together.
+ *
+ *        Wrapper macro for mbedtls_error_add(). See that function for
+ *        more details.
+ */
+#define MBEDTLS_ERROR_ADD( high, low ) \
+        mbedtls_error_add( high, low, __FILE__, __LINE__ )
+
+#if defined(MBEDTLS_TEST_HOOKS)
+/**
+ * \brief Testing hook called before adding/combining two error codes together.
+ *        Only used when invasive testing is enabled via MBEDTLS_TEST_HOOKS.
+ */
+extern void (*mbedtls_test_hook_error_add)( int, int, const char *, int );
+#endif
+
+/**
+ * \brief Combines a high-level and low-level error code together.
+ *
+ *        This function can be called directly however it is usually
+ *        called via the #MBEDTLS_ERROR_ADD macro.
+ *
+ *        While a value of zero is not a negative error code, it is still an
+ *        error code (that denotes success) and can be combined with both a
+ *        negative error code or another value of zero.
+ *
+ * \note  When invasive testing is enabled via #MBEDTLS_TEST_HOOKS, also try to
+ *        call \link mbedtls_test_hook_error_add \endlink.
+ *
+ * \param high      high-level error code. See error.h for more details.
+ * \param low       low-level error code. See error.h for more details.
+ * \param file      file where this error code addition occurred.
+ * \param line      line where this error code addition occurred.
+ */
+static inline int mbedtls_error_add( int high, int low,
+                                     const char *file, int line )
+{
+#if defined(MBEDTLS_TEST_HOOKS)
+    if( *mbedtls_test_hook_error_add != NULL )
+        ( *mbedtls_test_hook_error_add )( high, low, file, line );
+#endif
+    (void)file;
+    (void)line;
+
+    return( high + low );
+}
 
 /**
  * \brief Translate a mbed TLS error code into a string representation,
diff --git a/third_party/mbedtls/repo/include/mbedtls/gcm.h b/third_party/mbedtls/repo/include/mbedtls/gcm.h
index 6b67361..9723a17 100644
--- a/third_party/mbedtls/repo/include/mbedtls/gcm.h
+++ b/third_party/mbedtls/repo/include/mbedtls/gcm.h
@@ -44,12 +44,15 @@
 #define MBEDTLS_GCM_ENCRYPT     1
 #define MBEDTLS_GCM_DECRYPT     0
 
-#define MBEDTLS_ERR_GCM_AUTH_FAILED                       -0x0012  /**< Authenticated decryption failed. */
+/** Authenticated decryption failed. */
+#define MBEDTLS_ERR_GCM_AUTH_FAILED                       -0x0012
 
 /* MBEDTLS_ERR_GCM_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED                   -0x0013  /**< GCM hardware accelerator failed. */
+/** GCM hardware accelerator failed. */
+#define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED                   -0x0013
 
-#define MBEDTLS_ERR_GCM_BAD_INPUT                         -0x0014  /**< Bad input parameters to function. */
+/** Bad input parameters to function. */
+#define MBEDTLS_ERR_GCM_BAD_INPUT                         -0x0014
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/hkdf.h b/third_party/mbedtls/repo/include/mbedtls/hkdf.h
index 2e6b363..223004b 100644
--- a/third_party/mbedtls/repo/include/mbedtls/hkdf.h
+++ b/third_party/mbedtls/repo/include/mbedtls/hkdf.h
@@ -37,7 +37,8 @@
  *  \name HKDF Error codes
  *  \{
  */
-#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA  -0x5F80  /**< Bad input parameters to function. */
+/** Bad input parameters to function. */
+#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA  -0x5F80
 /* \} name */
 
 #ifdef __cplusplus
diff --git a/third_party/mbedtls/repo/include/mbedtls/hmac_drbg.h b/third_party/mbedtls/repo/include/mbedtls/hmac_drbg.h
index 9116541..79132d4 100644
--- a/third_party/mbedtls/repo/include/mbedtls/hmac_drbg.h
+++ b/third_party/mbedtls/repo/include/mbedtls/hmac_drbg.h
@@ -41,10 +41,14 @@
 /*
  * Error codes
  */
-#define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG              -0x0003  /**< Too many random requested in single call. */
-#define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG                -0x0005  /**< Input too large (Entropy + additional). */
-#define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR                -0x0007  /**< Read/write error in file. */
-#define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED        -0x0009  /**< The entropy source failed. */
+/** Too many random requested in single call. */
+#define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG              -0x0003
+/** Input too large (Entropy + additional). */
+#define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG                -0x0005
+/** Read/write error in file. */
+#define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR                -0x0007
+/** The entropy source failed. */
+#define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED        -0x0009
 
 /**
  * \name SECTION: Module settings
@@ -101,6 +105,14 @@
     void *p_entropy;            /*!< context for the entropy function        */
 
 #if defined(MBEDTLS_THREADING_C)
+    /* Invariant: the mutex is initialized if and only if
+     * md_ctx->md_info != NULL. This means that the mutex is initialized
+     * during the initial seeding in mbedtls_hmac_drbg_seed() or
+     * mbedtls_hmac_drbg_seed_buf() and freed in mbedtls_ctr_drbg_free().
+     *
+     * Note that this invariant may change without notice. Do not rely on it
+     * and do not access the mutex directly in application code.
+     */
     mbedtls_threading_mutex_t mutex;
 #endif
 } mbedtls_hmac_drbg_context;
@@ -150,7 +162,17 @@
  * \note                During the initial seeding, this function calls
  *                      the entropy source to obtain a nonce
  *                      whose length is half the entropy length.
- *
+ */
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note                When Mbed TLS is built with threading support,
+ *                      after this function returns successfully,
+ *                      it is safe to call mbedtls_hmac_drbg_random()
+ *                      from multiple threads. Other operations, including
+ *                      reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
+/**
  * \param ctx           HMAC_DRBG context to be seeded.
  * \param md_info       MD algorithm to use for HMAC_DRBG.
  * \param f_entropy     The entropy callback, taking as arguments the
@@ -189,7 +211,17 @@
  *
  * This function is meant for use in algorithms that need a pseudorandom
  * input such as deterministic ECDSA.
- *
+ */
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note                When Mbed TLS is built with threading support,
+ *                      after this function returns successfully,
+ *                      it is safe to call mbedtls_hmac_drbg_random()
+ *                      from multiple threads. Other operations, including
+ *                      reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
+/**
  * \param ctx           HMAC_DRBG context to be initialised.
  * \param md_info       MD algorithm to use for HMAC_DRBG.
  * \param data          Concatenation of the initial entropy string and
@@ -252,6 +284,11 @@
 /**
  * \brief               This function updates the state of the HMAC_DRBG context.
  *
+ * \note                This function is not thread-safe. It is not safe
+ *                      to call this function if another thread might be
+ *                      concurrently obtaining random numbers from the same
+ *                      context or updating or reseeding the same context.
+ *
  * \param ctx           The HMAC_DRBG context.
  * \param additional    The data to update the state with.
  *                      If this is \c NULL, there is no additional data.
@@ -268,6 +305,11 @@
  * \brief               This function reseeds the HMAC_DRBG context, that is
  *                      extracts data from the entropy source.
  *
+ * \note                This function is not thread-safe. It is not safe
+ *                      to call this function if another thread might be
+ *                      concurrently obtaining random numbers from the same
+ *                      context or updating or reseeding the same context.
+ *
  * \param ctx           The HMAC_DRBG context.
  * \param additional    Additional data to add to the state.
  *                      If this is \c NULL, there is no additional data
@@ -293,6 +335,11 @@
  * This function automatically reseeds if the reseed counter is exceeded
  * or prediction resistance is enabled.
  *
+ * \note                This function is not thread-safe. It is not safe
+ *                      to call this function if another thread might be
+ *                      concurrently obtaining random numbers from the same
+ *                      context or updating or reseeding the same context.
+ *
  * \param p_rng         The HMAC_DRBG context. This must be a pointer to a
  *                      #mbedtls_hmac_drbg_context structure.
  * \param output        The buffer to fill.
@@ -322,7 +369,16 @@
  *
  * This function automatically reseeds if the reseed counter is exceeded
  * or prediction resistance is enabled.
- *
+ */
+#if defined(MBEDTLS_THREADING_C)
+/**
+ * \note                When Mbed TLS is built with threading support,
+ *                      it is safe to call mbedtls_ctr_drbg_random()
+ *                      from multiple threads. Other operations, including
+ *                      reseeding, are not thread-safe.
+ */
+#endif /* MBEDTLS_THREADING_C */
+/**
  * \param p_rng         The HMAC_DRBG context. This must be a pointer to a
  *                      #mbedtls_hmac_drbg_context structure.
  * \param output        The buffer to fill.
diff --git a/third_party/mbedtls/repo/include/mbedtls/md.h b/third_party/mbedtls/repo/include/mbedtls/md.h
index e4354ba..84fafd2 100644
--- a/third_party/mbedtls/repo/include/mbedtls/md.h
+++ b/third_party/mbedtls/repo/include/mbedtls/md.h
@@ -32,14 +32,20 @@
 #else
 #include MBEDTLS_CONFIG_FILE
 #endif
+#include "mbedtls/platform_util.h"
 
-#define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE                -0x5080  /**< The selected feature is not available. */
-#define MBEDTLS_ERR_MD_BAD_INPUT_DATA                     -0x5100  /**< Bad input parameters to function. */
-#define MBEDTLS_ERR_MD_ALLOC_FAILED                       -0x5180  /**< Failed to allocate memory. */
-#define MBEDTLS_ERR_MD_FILE_IO_ERROR                      -0x5200  /**< Opening or reading of file failed. */
+/** The selected feature is not available. */
+#define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE                -0x5080
+/** Bad input parameters to function. */
+#define MBEDTLS_ERR_MD_BAD_INPUT_DATA                     -0x5100
+/** Failed to allocate memory. */
+#define MBEDTLS_ERR_MD_ALLOC_FAILED                       -0x5180
+/** Opening or reading of file failed. */
+#define MBEDTLS_ERR_MD_FILE_IO_ERROR                      -0x5200
 
 /* MBEDTLS_ERR_MD_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_MD_HW_ACCEL_FAILED                    -0x5280  /**< MD hardware accelerator failed. */
+/** MD hardware accelerator failed. */
+#define MBEDTLS_ERR_MD_HW_ACCEL_FAILED                    -0x5280
 
 #ifdef __cplusplus
 extern "C" {
@@ -205,6 +211,7 @@
  *                  failure.
  * \return          #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac );
 
 /**
@@ -226,6 +233,7 @@
  * \return          \c 0 on success.
  * \return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_md_clone( mbedtls_md_context_t *dst,
                       const mbedtls_md_context_t *src );
 
@@ -275,6 +283,7 @@
  * \return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
  *                  failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_md_starts( mbedtls_md_context_t *ctx );
 
 /**
@@ -293,6 +302,7 @@
  * \return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
  *                  failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen );
 
 /**
@@ -313,6 +323,7 @@
  * \return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
  *                  failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output );
 
 /**
@@ -333,6 +344,7 @@
  * \return         #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
  *                 failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen,
         unsigned char *output );
 
@@ -354,6 +366,7 @@
  *                 the file pointed by \p path.
  * \return         #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path,
                      unsigned char *output );
 #endif /* MBEDTLS_FS_IO */
@@ -376,6 +389,7 @@
  * \return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
  *                  failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key,
                     size_t keylen );
 
@@ -398,6 +412,7 @@
  * \return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
  *                  failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input,
                     size_t ilen );
 
@@ -419,6 +434,7 @@
  * \return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
  *                  failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output);
 
 /**
@@ -436,6 +452,7 @@
  * \return          #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
  *                  failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx );
 
 /**
@@ -460,11 +477,13 @@
  * \return         #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
  *                 failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen,
                 const unsigned char *input, size_t ilen,
                 unsigned char *output );
 
 /* Internal use */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data );
 
 #ifdef __cplusplus
diff --git a/third_party/mbedtls/repo/include/mbedtls/md2.h b/third_party/mbedtls/repo/include/mbedtls/md2.h
index 23c48f4..7f3d5cf 100644
--- a/third_party/mbedtls/repo/include/mbedtls/md2.h
+++ b/third_party/mbedtls/repo/include/mbedtls/md2.h
@@ -36,7 +36,8 @@
 #include <stddef.h>
 
 /* MBEDTLS_ERR_MD2_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED                   -0x002B  /**< MD2 hardware accelerator failed */
+/** MD2 hardware accelerator failed */
+#define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED                   -0x002B
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/md4.h b/third_party/mbedtls/repo/include/mbedtls/md4.h
index eeb1670..0238c67 100644
--- a/third_party/mbedtls/repo/include/mbedtls/md4.h
+++ b/third_party/mbedtls/repo/include/mbedtls/md4.h
@@ -37,7 +37,8 @@
 #include <stdint.h>
 
 /* MBEDTLS_ERR_MD4_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED                   -0x002D  /**< MD4 hardware accelerator failed */
+/** MD4 hardware accelerator failed */
+#define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED                   -0x002D
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/md5.h b/third_party/mbedtls/repo/include/mbedtls/md5.h
index aaca0f2..73e4dd2 100644
--- a/third_party/mbedtls/repo/include/mbedtls/md5.h
+++ b/third_party/mbedtls/repo/include/mbedtls/md5.h
@@ -36,7 +36,8 @@
 #include <stdint.h>
 
 /* MBEDTLS_ERR_MD5_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED                   -0x002F  /**< MD5 hardware accelerator failed */
+/** MD5 hardware accelerator failed */
+#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED                   -0x002F
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/net_sockets.h b/third_party/mbedtls/repo/include/mbedtls/net_sockets.h
index 55fd18b..ceb7d5f 100644
--- a/third_party/mbedtls/repo/include/mbedtls/net_sockets.h
+++ b/third_party/mbedtls/repo/include/mbedtls/net_sockets.h
@@ -49,19 +49,32 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#define MBEDTLS_ERR_NET_SOCKET_FAILED                     -0x0042  /**< Failed to open a socket. */
-#define MBEDTLS_ERR_NET_CONNECT_FAILED                    -0x0044  /**< The connection to the given server / port failed. */
-#define MBEDTLS_ERR_NET_BIND_FAILED                       -0x0046  /**< Binding of the socket failed. */
-#define MBEDTLS_ERR_NET_LISTEN_FAILED                     -0x0048  /**< Could not listen on the socket. */
-#define MBEDTLS_ERR_NET_ACCEPT_FAILED                     -0x004A  /**< Could not accept the incoming connection. */
-#define MBEDTLS_ERR_NET_RECV_FAILED                       -0x004C  /**< Reading information from the socket failed. */
-#define MBEDTLS_ERR_NET_SEND_FAILED                       -0x004E  /**< Sending information through the socket failed. */
-#define MBEDTLS_ERR_NET_CONN_RESET                        -0x0050  /**< Connection was reset by peer. */
-#define MBEDTLS_ERR_NET_UNKNOWN_HOST                      -0x0052  /**< Failed to get an IP address for the given hostname. */
-#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL                  -0x0043  /**< Buffer is too small to hold the data. */
-#define MBEDTLS_ERR_NET_INVALID_CONTEXT                   -0x0045  /**< The context is invalid, eg because it was free()ed. */
-#define MBEDTLS_ERR_NET_POLL_FAILED                       -0x0047  /**< Polling the net context failed. */
-#define MBEDTLS_ERR_NET_BAD_INPUT_DATA                    -0x0049  /**< Input invalid. */
+/** Failed to open a socket. */
+#define MBEDTLS_ERR_NET_SOCKET_FAILED                     -0x0042
+/** The connection to the given server / port failed. */
+#define MBEDTLS_ERR_NET_CONNECT_FAILED                    -0x0044
+/** Binding of the socket failed. */
+#define MBEDTLS_ERR_NET_BIND_FAILED                       -0x0046
+/** Could not listen on the socket. */
+#define MBEDTLS_ERR_NET_LISTEN_FAILED                     -0x0048
+/** Could not accept the incoming connection. */
+#define MBEDTLS_ERR_NET_ACCEPT_FAILED                     -0x004A
+/** Reading information from the socket failed. */
+#define MBEDTLS_ERR_NET_RECV_FAILED                       -0x004C
+/** Sending information through the socket failed. */
+#define MBEDTLS_ERR_NET_SEND_FAILED                       -0x004E
+/** Connection was reset by peer. */
+#define MBEDTLS_ERR_NET_CONN_RESET                        -0x0050
+/** Failed to get an IP address for the given hostname. */
+#define MBEDTLS_ERR_NET_UNKNOWN_HOST                      -0x0052
+/** Buffer is too small to hold the data. */
+#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL                  -0x0043
+/** The context is invalid, eg because it was free()ed. */
+#define MBEDTLS_ERR_NET_INVALID_CONTEXT                   -0x0045
+/** Polling the net context failed. */
+#define MBEDTLS_ERR_NET_POLL_FAILED                       -0x0047
+/** Input invalid. */
+#define MBEDTLS_ERR_NET_BAD_INPUT_DATA                    -0x0049
 
 #define MBEDTLS_NET_LISTEN_BACKLOG         10 /**< The backlog that listen() should use. */
 
@@ -124,6 +137,7 @@
  *
  * \return         0 if successful, or one of:
  *                      MBEDTLS_ERR_NET_SOCKET_FAILED,
+ *                      MBEDTLS_ERR_NET_UNKNOWN_HOST,
  *                      MBEDTLS_ERR_NET_BIND_FAILED,
  *                      MBEDTLS_ERR_NET_LISTEN_FAILED
  *
@@ -143,6 +157,8 @@
  *                  can be NULL if client_ip is null
  *
  * \return          0 if successful, or
+ *                  MBEDTLS_ERR_NET_SOCKET_FAILED,
+ *                  MBEDTLS_ERR_NET_BIND_FAILED,
  *                  MBEDTLS_ERR_NET_ACCEPT_FAILED, or
  *                  MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small,
  *                  MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to
@@ -155,6 +171,10 @@
 /**
  * \brief          Check and wait for the context to be ready for read/write
  *
+ * \note           The current implementation of this function uses
+ *                 select() and returns an error if the file descriptor
+ *                 is \c FD_SETSIZE or greater.
+ *
  * \param ctx      Socket to check
  * \param rw       Bitflag composed of MBEDTLS_NET_POLL_READ and
  *                 MBEDTLS_NET_POLL_WRITE specifying the events
@@ -236,16 +256,21 @@
  *                 'timeout' seconds. If no error occurs, the actual amount
  *                 read is returned.
  *
+ * \note           The current implementation of this function uses
+ *                 select() and returns an error if the file descriptor
+ *                 is \c FD_SETSIZE or greater.
+ *
  * \param ctx      Socket
  * \param buf      The buffer to write to
  * \param len      Maximum length of the buffer
  * \param timeout  Maximum number of milliseconds to wait for data
  *                 0 means no timeout (wait forever)
  *
- * \return         the number of bytes received,
- *                 or a non-zero error code:
- *                 MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out,
+ * \return         The number of bytes received if successful.
+ *                 MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out.
  *                 MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal.
+ *                 Another negative error code (MBEDTLS_ERR_NET_xxx)
+ *                 for other failures.
  *
  * \note           This function will block (until data becomes available or
  *                 timeout is reached) even if the socket is set to
diff --git a/third_party/mbedtls/repo/include/mbedtls/oid.h b/third_party/mbedtls/repo/include/mbedtls/oid.h
index e4c697b..1c39186 100644
--- a/third_party/mbedtls/repo/include/mbedtls/oid.h
+++ b/third_party/mbedtls/repo/include/mbedtls/oid.h
@@ -41,8 +41,10 @@
 #include "mbedtls/md.h"
 #endif
 
-#define MBEDTLS_ERR_OID_NOT_FOUND                         -0x002E  /**< OID is not found. */
-#define MBEDTLS_ERR_OID_BUF_TOO_SMALL                     -0x000B  /**< output buffer is too small */
+/** OID is not found. */
+#define MBEDTLS_ERR_OID_NOT_FOUND                         -0x002E
+/** output buffer is too small */
+#define MBEDTLS_ERR_OID_BUF_TOO_SMALL                     -0x000B
 
 /* This is for the benefit of X.509, but defined here in order to avoid
  * having a "backwards" include of x.509.h here */
diff --git a/third_party/mbedtls/repo/include/mbedtls/padlock.h b/third_party/mbedtls/repo/include/mbedtls/padlock.h
index 78dbeb6..624d02d 100644
--- a/third_party/mbedtls/repo/include/mbedtls/padlock.h
+++ b/third_party/mbedtls/repo/include/mbedtls/padlock.h
@@ -34,7 +34,8 @@
 
 #include "mbedtls/aes.h"
 
-#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED               -0x0030  /**< Input data should be aligned. */
+/** Input data should be aligned. */
+#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED               -0x0030
 
 #if defined(__has_feature)
 #if __has_feature(address_sanitizer)
@@ -71,7 +72,7 @@
  *
  * \param feature  The feature to detect
  *
- * \return         1 if CPU has support for the feature, 0 otherwise
+ * \return         non-zero if CPU has support for the feature, 0 otherwise
  */
 int mbedtls_padlock_has_support( int feature );
 
diff --git a/third_party/mbedtls/repo/include/mbedtls/pem.h b/third_party/mbedtls/repo/include/mbedtls/pem.h
index 4769bec..dfb4ff2 100644
--- a/third_party/mbedtls/repo/include/mbedtls/pem.h
+++ b/third_party/mbedtls/repo/include/mbedtls/pem.h
@@ -36,15 +36,24 @@
  * PEM data.
  * \{
  */
-#define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT          -0x1080  /**< No PEM header or footer found. */
-#define MBEDTLS_ERR_PEM_INVALID_DATA                      -0x1100  /**< PEM string is not as expected. */
-#define MBEDTLS_ERR_PEM_ALLOC_FAILED                      -0x1180  /**< Failed to allocate memory. */
-#define MBEDTLS_ERR_PEM_INVALID_ENC_IV                    -0x1200  /**< RSA IV is not in hex-format. */
-#define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG                   -0x1280  /**< Unsupported key encryption algorithm. */
-#define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED                 -0x1300  /**< Private key password can't be empty. */
-#define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH                 -0x1380  /**< Given private key password does not allow for correct decryption. */
-#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE               -0x1400  /**< Unavailable feature, e.g. hashing/encryption combination. */
-#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA                    -0x1480  /**< Bad input parameters to function. */
+/** No PEM header or footer found. */
+#define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT          -0x1080
+/** PEM string is not as expected. */
+#define MBEDTLS_ERR_PEM_INVALID_DATA                      -0x1100
+/** Failed to allocate memory. */
+#define MBEDTLS_ERR_PEM_ALLOC_FAILED                      -0x1180
+/** RSA IV is not in hex-format. */
+#define MBEDTLS_ERR_PEM_INVALID_ENC_IV                    -0x1200
+/** Unsupported key encryption algorithm. */
+#define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG                   -0x1280
+/** Private key password can't be empty. */
+#define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED                 -0x1300
+/** Given private key password does not allow for correct decryption. */
+#define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH                 -0x1380
+/** Unavailable feature, e.g. hashing/encryption combination. */
+#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE               -0x1400
+/** Bad input parameters to function. */
+#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA                    -0x1480
 /* \} name */
 
 #ifdef __cplusplus
diff --git a/third_party/mbedtls/repo/include/mbedtls/pk.h b/third_party/mbedtls/repo/include/mbedtls/pk.h
index 7d0f977..8f2abf2 100644
--- a/third_party/mbedtls/repo/include/mbedtls/pk.h
+++ b/third_party/mbedtls/repo/include/mbedtls/pk.h
@@ -52,23 +52,38 @@
 #define inline __inline
 #endif
 
-#define MBEDTLS_ERR_PK_ALLOC_FAILED        -0x3F80  /**< Memory allocation failed. */
-#define MBEDTLS_ERR_PK_TYPE_MISMATCH       -0x3F00  /**< Type mismatch, eg attempt to encrypt with an ECDSA key */
-#define MBEDTLS_ERR_PK_BAD_INPUT_DATA      -0x3E80  /**< Bad input parameters to function. */
-#define MBEDTLS_ERR_PK_FILE_IO_ERROR       -0x3E00  /**< Read/write of file failed. */
-#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80  /**< Unsupported key version */
-#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT  -0x3D00  /**< Invalid key tag or value. */
-#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG      -0x3C80  /**< Key algorithm is unsupported (only RSA and EC are supported). */
-#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED   -0x3C00  /**< Private key password can't be empty. */
-#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH   -0x3B80  /**< Given private key password does not allow for correct decryption. */
-#define MBEDTLS_ERR_PK_INVALID_PUBKEY      -0x3B00  /**< The pubkey tag or value is invalid (only RSA and EC are supported). */
-#define MBEDTLS_ERR_PK_INVALID_ALG         -0x3A80  /**< The algorithm tag or value is invalid. */
-#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00  /**< Elliptic curve is unsupported (only NIST curves are supported). */
-#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980  /**< Unavailable feature, e.g. RSA disabled for RSA key. */
-#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH    -0x3900  /**< The buffer contains a valid signature followed by more data. */
+/** Memory allocation failed. */
+#define MBEDTLS_ERR_PK_ALLOC_FAILED        -0x3F80
+/** Type mismatch, eg attempt to encrypt with an ECDSA key */
+#define MBEDTLS_ERR_PK_TYPE_MISMATCH       -0x3F00
+/** Bad input parameters to function. */
+#define MBEDTLS_ERR_PK_BAD_INPUT_DATA      -0x3E80
+/** Read/write of file failed. */
+#define MBEDTLS_ERR_PK_FILE_IO_ERROR       -0x3E00
+/** Unsupported key version */
+#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80
+/** Invalid key tag or value. */
+#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT  -0x3D00
+/** Key algorithm is unsupported (only RSA and EC are supported). */
+#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG      -0x3C80
+/** Private key password can't be empty. */
+#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED   -0x3C00
+/** Given private key password does not allow for correct decryption. */
+#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH   -0x3B80
+/** The pubkey tag or value is invalid (only RSA and EC are supported). */
+#define MBEDTLS_ERR_PK_INVALID_PUBKEY      -0x3B00
+/** The algorithm tag or value is invalid. */
+#define MBEDTLS_ERR_PK_INVALID_ALG         -0x3A80
+/** Elliptic curve is unsupported (only NIST curves are supported). */
+#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00
+/** Unavailable feature, e.g. RSA disabled for RSA key. */
+#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980
+/** The buffer contains a valid signature followed by more data. */
+#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH    -0x3900
 
 /* MBEDTLS_ERR_PK_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_PK_HW_ACCEL_FAILED     -0x3880  /**< PK hardware accelerator failed. */
+/** PK hardware accelerator failed. */
+#define MBEDTLS_ERR_PK_HW_ACCEL_FAILED     -0x3880
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/pkcs12.h b/third_party/mbedtls/repo/include/mbedtls/pkcs12.h
index 4b8ce7e..d9e85b1 100644
--- a/third_party/mbedtls/repo/include/mbedtls/pkcs12.h
+++ b/third_party/mbedtls/repo/include/mbedtls/pkcs12.h
@@ -34,10 +34,14 @@
 
 #include <stddef.h>
 
-#define MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA                 -0x1F80  /**< Bad input parameters to function. */
-#define MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE            -0x1F00  /**< Feature not available, e.g. unsupported encryption scheme. */
-#define MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT             -0x1E80  /**< PBE ASN.1 data not as expected. */
-#define MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH              -0x1E00  /**< Given private key password does not allow for correct decryption. */
+/** Bad input parameters to function. */
+#define MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA                 -0x1F80
+/** Feature not available, e.g. unsupported encryption scheme. */
+#define MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE            -0x1F00
+/** PBE ASN.1 data not as expected. */
+#define MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT             -0x1E80
+/** Given private key password does not allow for correct decryption. */
+#define MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH              -0x1E00
 
 #define MBEDTLS_PKCS12_DERIVE_KEY       1   /**< encryption/decryption key */
 #define MBEDTLS_PKCS12_DERIVE_IV        2   /**< initialization vector     */
@@ -75,11 +79,13 @@
  * \brief            PKCS12 Password Based function (encryption / decryption)
  *                   for cipher-based and mbedtls_md-based PBE's
  *
- * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure
- * \param mode       either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT
+ * \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        the password used (may be NULL if no password is 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 input      the input data
  * \param len        data length
@@ -100,18 +106,24 @@
  *                   to produce pseudo-random bits for a particular "purpose".
  *
  *                   Depending on the given id, this function can produce an
- *                   encryption/decryption key, an nitialization vector or an
+ *                   encryption/decryption key, an initialization vector or an
  *                   integrity key.
  *
  * \param data       buffer to store the derived data in
- * \param datalen    length to fill
- * \param pwd        password to use (may be NULL if no password is used)
- * \param pwdlen     length of the password (may be 0)
- * \param salt       salt buffer to use
- * \param saltlen    length of the salt
- * \param mbedtls_md         mbedtls_md type to use during the derivation
- * \param id         id that describes the purpose (can be MBEDTLS_PKCS12_DERIVE_KEY,
- *                   MBEDTLS_PKCS12_DERIVE_IV or MBEDTLS_PKCS12_DERIVE_MAC_KEY)
+ * \param datalen    length of buffer to fill
+ * \param pwd        The password to use. For compliance with PKCS#12 §B.1, this
+ *                   should be a BMPString, i.e. a Unicode string where each
+ *                   character is encoded as 2 bytes in big-endian order, with
+ *                   no byte order mark and with a null terminator (i.e. the
+ *                   last two bytes should be 0x00 0x00).
+ * \param pwdlen     length of the password (may be 0).
+ * \param salt       Salt buffer to use This may only be \c NULL when
+ *                   \p saltlen is 0.
+ * \param saltlen    length of the salt (may be zero)
+ * \param mbedtls_md mbedtls_md type to use during the derivation
+ * \param id         id that describes the purpose (can be
+ *                   #MBEDTLS_PKCS12_DERIVE_KEY, #MBEDTLS_PKCS12_DERIVE_IV or
+ *                   #MBEDTLS_PKCS12_DERIVE_MAC_KEY)
  * \param iterations number of iterations
  *
  * \return          0 if successful, or a MD, BIGNUM type error.
diff --git a/third_party/mbedtls/repo/include/mbedtls/pkcs5.h b/third_party/mbedtls/repo/include/mbedtls/pkcs5.h
index 8f348ce..696930f 100644
--- a/third_party/mbedtls/repo/include/mbedtls/pkcs5.h
+++ b/third_party/mbedtls/repo/include/mbedtls/pkcs5.h
@@ -36,10 +36,14 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#define MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA                  -0x2f80  /**< Bad input parameters to function. */
-#define MBEDTLS_ERR_PKCS5_INVALID_FORMAT                  -0x2f00  /**< Unexpected ASN.1 data. */
-#define MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE             -0x2e80  /**< Requested encryption or digest alg not available. */
-#define MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH               -0x2e00  /**< Given private key password does not allow for correct decryption. */
+/** Bad input parameters to function. */
+#define MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA                  -0x2f80
+/** Unexpected ASN.1 data. */
+#define MBEDTLS_ERR_PKCS5_INVALID_FORMAT                  -0x2f00
+/** Requested encryption or digest alg not available. */
+#define MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE             -0x2e80
+/** 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
diff --git a/third_party/mbedtls/repo/include/mbedtls/platform.h b/third_party/mbedtls/repo/include/mbedtls/platform.h
index fde5ee8..bdef074 100644
--- a/third_party/mbedtls/repo/include/mbedtls/platform.h
+++ b/third_party/mbedtls/repo/include/mbedtls/platform.h
@@ -41,8 +41,10 @@
 #include "mbedtls/platform_time.h"
 #endif
 
-#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED     -0x0070 /**< Hardware accelerator failed */
-#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 /**< The requested feature is not supported by the platform */
+/** Hardware accelerator failed */
+#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED     -0x0070
+/** The requested feature is not supported by the platform */
+#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/platform_util.h b/third_party/mbedtls/repo/include/mbedtls/platform_util.h
index fbc2a0d..f982db8 100644
--- a/third_party/mbedtls/repo/include/mbedtls/platform_util.h
+++ b/third_party/mbedtls/repo/include/mbedtls/platform_util.h
@@ -132,6 +132,95 @@
 #endif /* MBEDTLS_DEPRECATED_WARNING */
 #endif /* MBEDTLS_DEPRECATED_REMOVED */
 
+/* Implementation of the check-return facility.
+ * See the user documentation in config.h.
+ *
+ * Do not use this macro directly to annotate function: instead,
+ * use one of MBEDTLS_CHECK_RETURN_CRITICAL or MBEDTLS_CHECK_RETURN_TYPICAL
+ * depending on how important it is to check the return value.
+ */
+#if !defined(MBEDTLS_CHECK_RETURN)
+#if defined(__GNUC__)
+#define MBEDTLS_CHECK_RETURN __attribute__((__warn_unused_result__))
+#elif defined(_MSC_VER) && _MSC_VER >= 1700
+#include <sal.h>
+#define MBEDTLS_CHECK_RETURN _Check_return_
+#else
+#define MBEDTLS_CHECK_RETURN
+#endif
+#endif
+
+/** Critical-failure function
+ *
+ * This macro appearing at the beginning of the declaration of a function
+ * indicates that its return value should be checked in all applications.
+ * Omitting the check is very likely to indicate a bug in the application
+ * and will result in a compile-time warning if #MBEDTLS_CHECK_RETURN
+ * is implemented for the compiler in use.
+ *
+ * \note  The use of this macro is a work in progress.
+ *        This macro may be added to more functions in the future.
+ *        Such an extension is not considered an API break, provided that
+ *        there are near-unavoidable circumstances under which the function
+ *        can fail. For example, signature/MAC/AEAD verification functions,
+ *        and functions that require a random generator, are considered
+ *        return-check-critical.
+ */
+#define MBEDTLS_CHECK_RETURN_CRITICAL MBEDTLS_CHECK_RETURN
+
+/** Ordinary-failure function
+ *
+ * This macro appearing at the beginning of the declaration of a function
+ * indicates that its return value should be generally be checked in portable
+ * applications. Omitting the check will result in a compile-time warning if
+ * #MBEDTLS_CHECK_RETURN is implemented for the compiler in use and
+ * #MBEDTLS_CHECK_RETURN_WARNING is enabled in the compile-time configuration.
+ *
+ * You can use #MBEDTLS_IGNORE_RETURN to explicitly ignore the return value
+ * of a function that is annotated with #MBEDTLS_CHECK_RETURN.
+ *
+ * \note  The use of this macro is a work in progress.
+ *        This macro will be added to more functions in the future.
+ *        Eventually this should appear before most functions returning
+ *        an error code (as \c int in the \c mbedtls_xxx API or
+ *        as ::psa_status_t in the \c psa_xxx API).
+ */
+#if defined(MBEDTLS_CHECK_RETURN_WARNING)
+#define MBEDTLS_CHECK_RETURN_TYPICAL MBEDTLS_CHECK_RETURN
+#else
+#define MBEDTLS_CHECK_RETURN_TYPICAL
+#endif
+
+/** Benign-failure function
+ *
+ * This macro appearing at the beginning of the declaration of a function
+ * indicates that it is rarely useful to check its return value.
+ *
+ * This macro has an empty expansion. It exists for documentation purposes:
+ * a #MBEDTLS_CHECK_RETURN_OPTIONAL annotation indicates that the function
+ * has been analyzed for return-check usefuless, whereas the lack of
+ * an annotation indicates that the function has not been analyzed and its
+ * return-check usefulness is unknown.
+ */
+#define MBEDTLS_CHECK_RETURN_OPTIONAL
+
+/** \def MBEDTLS_IGNORE_RETURN
+ *
+ * Call this macro with one argument, a function call, to suppress a warning
+ * from #MBEDTLS_CHECK_RETURN due to that function call.
+ */
+#if !defined(MBEDTLS_IGNORE_RETURN)
+/* GCC doesn't silence the warning with just (void)(result).
+ * (void)!(result) is known to work up at least up to GCC 10, as well
+ * as with Clang and MSVC.
+ *
+ * https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Non_002dbugs.html
+ * https://stackoverflow.com/questions/40576003/ignoring-warning-wunused-result
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425#c34
+ */
+#define MBEDTLS_IGNORE_RETURN(result) ( (void) !( result ) )
+#endif
+
 /**
  * \brief       Securely zeroize a buffer
  *
diff --git a/third_party/mbedtls/repo/include/mbedtls/poly1305.h b/third_party/mbedtls/repo/include/mbedtls/poly1305.h
index 905c145..a69ede9 100644
--- a/third_party/mbedtls/repo/include/mbedtls/poly1305.h
+++ b/third_party/mbedtls/repo/include/mbedtls/poly1305.h
@@ -41,15 +41,18 @@
 #include <stdint.h>
 #include <stddef.h>
 
-#define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA         -0x0057 /**< Invalid input parameter(s). */
+/** Invalid input parameter(s). */
+#define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA         -0x0057
 
 /* MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE is deprecated and should not be
  * used. */
-#define MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE    -0x0059 /**< Feature not available. For example, s part of the API is not implemented. */
+/** Feature not available. For example, s part of the API is not implemented. */
+#define MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE    -0x0059
 
 /* MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED is deprecated and should not be used.
  */
-#define MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED        -0x005B  /**< Poly1305 hardware accelerator failed. */
+/** Poly1305 hardware accelerator failed. */
+#define MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED        -0x005B
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/psa_util.h b/third_party/mbedtls/repo/include/mbedtls/psa_util.h
index d8a32c5..af7a809 100644
--- a/third_party/mbedtls/repo/include/mbedtls/psa_util.h
+++ b/third_party/mbedtls/repo/include/mbedtls/psa_util.h
@@ -59,6 +59,9 @@
         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. */
@@ -86,14 +89,14 @@
         case MBEDTLS_MODE_ECB:
             return( PSA_ALG_ECB_NO_PADDING );
         case MBEDTLS_MODE_GCM:
-            return( PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, taglen ) );
+            return( PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, taglen ) );
         case MBEDTLS_MODE_CCM:
-            return( PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, taglen ) );
+            return( PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, taglen ) );
         case MBEDTLS_MODE_CBC:
             if( taglen == 0 )
                 return( PSA_ALG_CBC_NO_PADDING );
-            /* Intentional fallthrough for taglen != 0 */
-            /* fallthrough */
+            else
+                return( 0 );
         default:
             return( 0 );
     }
@@ -151,7 +154,8 @@
     case MBEDTLS_MD_RIPEMD160:
         return( PSA_ALG_RIPEMD160 );
 #endif
-    case MBEDTLS_MD_NONE:  /* Intentional fallthrough */
+    case MBEDTLS_MD_NONE:
+        return( 0 );
     default:
         return( 0 );
     }
@@ -419,4 +423,90 @@
 
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
+/* 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. */
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+/* 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 );
+
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+
+/** 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.
+ *
+ * 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 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.
+ *                      This function may fail if \p output_size is too
+ *                      large. It is guaranteed to accept any output size
+ *                      requested by Mbed TLS library functions. The
+ *                      maximum request size depends on the library
+ *                      configuration.
+ *
+ * \return              \c 0 on success.
+ * \return              An `MBEDTLS_ERR_ENTROPY_xxx`,
+ *                      `MBEDTLS_ERR_PLATFORM_xxx,
+ *                      `MBEDTLS_ERR_CTR_DRBG_xxx` or
+ *                      `MBEDTLS_ERR_HMAC_DRBG_xxx` on error.
+ */
+int mbedtls_psa_get_random( void *p_rng,
+                            unsigned char *output,
+                            size_t output_size );
+
+/** 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.
+ */
+#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 mbedtls_psa_random_state
+
+#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
 #endif /* MBEDTLS_PSA_UTIL_H */
diff --git a/third_party/mbedtls/repo/include/mbedtls/ripemd160.h b/third_party/mbedtls/repo/include/mbedtls/ripemd160.h
index 381c725..63270d1 100644
--- a/third_party/mbedtls/repo/include/mbedtls/ripemd160.h
+++ b/third_party/mbedtls/repo/include/mbedtls/ripemd160.h
@@ -33,7 +33,8 @@
 
 /* MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED is deprecated and should not be used.
  */
-#define MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED             -0x0031  /**< RIPEMD160 hardware accelerator failed */
+/** RIPEMD160 hardware accelerator failed */
+#define MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED             -0x0031
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/rsa.h b/third_party/mbedtls/repo/include/mbedtls/rsa.h
index 6a31514..3c481e1 100644
--- a/third_party/mbedtls/repo/include/mbedtls/rsa.h
+++ b/third_party/mbedtls/repo/include/mbedtls/rsa.h
@@ -44,22 +44,33 @@
 /*
  * RSA Error codes
  */
-#define MBEDTLS_ERR_RSA_BAD_INPUT_DATA                    -0x4080  /**< Bad input parameters to function. */
-#define MBEDTLS_ERR_RSA_INVALID_PADDING                   -0x4100  /**< Input data contains invalid padding and is rejected. */
-#define MBEDTLS_ERR_RSA_KEY_GEN_FAILED                    -0x4180  /**< Something failed during generation of a key. */
-#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED                  -0x4200  /**< Key failed to pass the validity check of the library. */
-#define MBEDTLS_ERR_RSA_PUBLIC_FAILED                     -0x4280  /**< The public key operation failed. */
-#define MBEDTLS_ERR_RSA_PRIVATE_FAILED                    -0x4300  /**< The private key operation failed. */
-#define MBEDTLS_ERR_RSA_VERIFY_FAILED                     -0x4380  /**< The PKCS#1 verification failed. */
-#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE                  -0x4400  /**< The output buffer for decryption is not large enough. */
-#define MBEDTLS_ERR_RSA_RNG_FAILED                        -0x4480  /**< The random generator failed to generate non-zeros. */
+/** Bad input parameters to function. */
+#define MBEDTLS_ERR_RSA_BAD_INPUT_DATA                    -0x4080
+/** Input data contains invalid padding and is rejected. */
+#define MBEDTLS_ERR_RSA_INVALID_PADDING                   -0x4100
+/** Something failed during generation of a key. */
+#define MBEDTLS_ERR_RSA_KEY_GEN_FAILED                    -0x4180
+/** Key failed to pass the validity check of the library. */
+#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED                  -0x4200
+/** The public key operation failed. */
+#define MBEDTLS_ERR_RSA_PUBLIC_FAILED                     -0x4280
+/** The private key operation failed. */
+#define MBEDTLS_ERR_RSA_PRIVATE_FAILED                    -0x4300
+/** The PKCS#1 verification failed. */
+#define MBEDTLS_ERR_RSA_VERIFY_FAILED                     -0x4380
+/** The output buffer for decryption is not large enough. */
+#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE                  -0x4400
+/** The random generator failed to generate non-zeros. */
+#define MBEDTLS_ERR_RSA_RNG_FAILED                        -0x4480
 
 /* MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION is deprecated and should not be used.
  */
-#define MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION             -0x4500  /**< The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */
+/** The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */
+#define MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION             -0x4500
 
 /* MBEDTLS_ERR_RSA_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_RSA_HW_ACCEL_FAILED                   -0x4580  /**< RSA hardware accelerator failed. */
+/** RSA hardware accelerator failed. */
+#define MBEDTLS_ERR_RSA_HW_ACCEL_FAILED                   -0x4580
 
 /*
  * RSA constants
@@ -97,7 +108,10 @@
  */
 typedef struct mbedtls_rsa_context
 {
-    int ver;                    /*!<  Always 0.*/
+    int ver;                    /*!<  Reserved for internal purposes.
+                                 *    Do not set this field in application
+                                 *    code. Its meaning might change without
+                                 *    notice. */
     size_t len;                 /*!<  The size of \p N in Bytes. */
 
     mbedtls_mpi N;              /*!<  The public modulus. */
@@ -127,6 +141,7 @@
                                      mask generating function used in the
                                      EME-OAEP and EMSA-PSS encodings. */
 #if defined(MBEDTLS_THREADING_C)
+    /* Invariant: the mutex is initialized iff ver != 0. */
     mbedtls_threading_mutex_t mutex;    /*!<  Thread-safety mutex. */
 #endif
 }
@@ -972,12 +987,69 @@
  * \brief          This function performs a PKCS#1 v2.1 PSS signature
  *                 operation (RSASSA-PSS-SIGN).
  *
- * \note           The \p hash_id in the RSA context is the one used for the
- *                 encoding. \p md_alg in the function call is the type of hash
- *                 that is encoded. According to <em>RFC-3447: Public-Key
+ * \note           The \c hash_id set in \p ctx (when calling
+ *                 mbedtls_rsa_init() or by calling mbedtls_rsa_set_padding()
+ *                 afterwards) selects the hash used for the
+ *                 encoding operation and for the mask generation function
+ *                 (MGF1). For more details on the encoding operation and the
+ *                 mask generation function, consult <em>RFC-3447: Public-Key
  *                 Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography
- *                 Specifications</em> it is advised to keep both hashes the
- *                 same.
+ *                 Specifications</em>.
+ *
+ * \note           This function enforces that the provided salt length complies
+ *                 with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1 v2.2) §9.1.1
+ *                 step 3. The constraint is that the hash length plus the salt
+ *                 length plus 2 bytes must be at most the key length. If this
+ *                 constraint is not met, this function returns
+ *                 #MBEDTLS_ERR_RSA_BAD_INPUT_DATA.
+ *
+ * \param ctx      The initialized RSA context to use.
+ * \param f_rng    The RNG function. It 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 argument.
+ * \param md_alg   The message-digest algorithm used to hash the original data.
+ *                 Use #MBEDTLS_MD_NONE for signing raw data.
+ * \param hashlen  The length of the message digest.
+ *                 Ths is only used if \p md_alg is #MBEDTLS_MD_NONE.
+ * \param hash     The buffer holding the message digest or raw data.
+ *                 If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable
+ *                 buffer of length \p hashlen Bytes. If \p md_alg is not
+ *                 #MBEDTLS_MD_NONE, it must be a readable buffer of length
+ *                 the size of the hash corresponding to \p md_alg.
+ * \param saltlen  The length of the salt that should be used.
+ *                 If passed #MBEDTLS_RSA_SALT_LEN_ANY, the function will use
+ *                 the largest possible salt length up to the hash length,
+ *                 which is the largest permitted by some standards including
+ *                 FIPS 186-4 §5.5.
+ * \param sig      The buffer to hold the signature. This must be a writable
+ *                 buffer of length \c ctx->len Bytes. For example, \c 256 Bytes
+ *                 for an 2048-bit RSA modulus. A buffer length of
+ *                 #MBEDTLS_MPI_MAX_SIZE is always safe.
+ *
+ * \return         \c 0 if the signing operation was successful.
+ * \return         An \c MBEDTLS_ERR_RSA_XXX error code on failure.
+ */
+int mbedtls_rsa_rsassa_pss_sign_ext( 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 );
+
+/**
+ * \brief          This function performs a PKCS#1 v2.1 PSS signature
+ *                 operation (RSASSA-PSS-SIGN).
+ *
+ * \note           The \c hash_id set in \p ctx (when calling
+ *                 mbedtls_rsa_init() or by calling mbedtls_rsa_set_padding()
+ *                 afterwards) selects the hash used for the
+ *                 encoding operation and for the mask generation function
+ *                 (MGF1). For more details on the encoding operation and the
+ *                 mask generation function, consult <em>RFC-3447: Public-Key
+ *                 Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography
+ *                 Specifications</em>.
  *
  * \note           This function always uses the maximum possible salt size,
  *                 up to the length of the payload hash. This choice of salt
@@ -1007,7 +1079,7 @@
  * \param md_alg   The message-digest algorithm used to hash the original data.
  *                 Use #MBEDTLS_MD_NONE for signing raw data.
  * \param hashlen  The length of the message digest.
- *                 Ths is only used if \p md_alg is #MBEDTLS_MD_NONE.
+ *                 This is only used if \p md_alg is #MBEDTLS_MD_NONE.
  * \param hash     The buffer holding the message digest or raw data.
  *                 If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable
  *                 buffer of length \p hashlen Bytes. If \p md_alg is not
@@ -1133,16 +1205,15 @@
  * \brief          This function performs a PKCS#1 v2.1 PSS verification
  *                 operation (RSASSA-PSS-VERIFY).
  *
- *                 The hash function for the MGF mask generating function
- *                 is that specified in the RSA context.
- *
- * \note           The \p hash_id in the RSA context is the one used for the
- *                 verification. \p md_alg in the function call is the type of
- *                 hash that is verified. According to <em>RFC-3447: Public-Key
+ * \note           The \c hash_id set in \p ctx (when calling
+ *                 mbedtls_rsa_init() or by calling mbedtls_rsa_set_padding()
+ *                 afterwards) selects the hash used for the
+ *                 encoding operation and for the mask generation function
+ *                 (MGF1). For more details on the encoding operation and the
+ *                 mask generation function, consult <em>RFC-3447: Public-Key
  *                 Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography
- *                 Specifications</em> it is advised to keep both hashes the
- *                 same. If \p hash_id in the RSA context is unset,
- *                 the \p md_alg from the function call is used.
+ *                 Specifications</em>. If the \c hash_id set in \p ctx is
+ *                 #MBEDTLS_MD_NONE, the \p md_alg parameter is used.
  *
  * \deprecated     It is deprecated and discouraged to call this function
  *                 in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library
@@ -1190,13 +1261,12 @@
  * \brief          This function performs a PKCS#1 v2.1 PSS verification
  *                 operation (RSASSA-PSS-VERIFY).
  *
- *                 The hash function for the MGF mask generating function
- *                 is that specified in \p mgf1_hash_id.
- *
  * \note           The \p sig buffer must be as large as the size
  *                 of \p ctx->N. For example, 128 Bytes if RSA-1024 is used.
  *
- * \note           The \p hash_id in the RSA context is ignored.
+ * \note           The \c hash_id set in \p ctx (when calling
+ *                 mbedtls_rsa_init() or by calling mbedtls_rsa_set_padding()
+ *                 afterwards) is ignored.
  *
  * \param ctx      The initialized RSA public key context to use.
  * \param f_rng    The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE,
@@ -1215,7 +1285,13 @@
  *                 buffer of length \p hashlen Bytes. If \p md_alg is not
  *                 #MBEDTLS_MD_NONE, it must be a readable buffer of length
  *                 the size of the hash corresponding to \p md_alg.
- * \param mgf1_hash_id      The message digest used for mask generation.
+ * \param mgf1_hash_id      The message digest algorithm used for the
+ *                          verification operation and the mask generation
+ *                          function (MGF1). For more details on the encoding
+ *                          operation and the mask generation function, consult
+ *                          <em>RFC-3447: Public-Key Cryptography Standards
+ *                          (PKCS) #1 v2.1: RSA Cryptography
+ *                          Specifications</em>.
  * \param expected_salt_len The length of the salt used in padding. Use
  *                          #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length.
  * \param sig      The buffer holding the signature. This must be a readable
diff --git a/third_party/mbedtls/repo/include/mbedtls/sha1.h b/third_party/mbedtls/repo/include/mbedtls/sha1.h
index 86a3d06..4c3251b 100644
--- a/third_party/mbedtls/repo/include/mbedtls/sha1.h
+++ b/third_party/mbedtls/repo/include/mbedtls/sha1.h
@@ -39,8 +39,10 @@
 #include <stdint.h>
 
 /* MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED                  -0x0035  /**< SHA-1 hardware accelerator failed */
-#define MBEDTLS_ERR_SHA1_BAD_INPUT_DATA                   -0x0073  /**< SHA-1 input data was malformed. */
+/** SHA-1 hardware accelerator failed */
+#define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED                  -0x0035
+/** SHA-1 input data was malformed. */
+#define MBEDTLS_ERR_SHA1_BAD_INPUT_DATA                   -0x0073
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/sha256.h b/third_party/mbedtls/repo/include/mbedtls/sha256.h
index 73d9544..5b54be2 100644
--- a/third_party/mbedtls/repo/include/mbedtls/sha256.h
+++ b/third_party/mbedtls/repo/include/mbedtls/sha256.h
@@ -35,8 +35,10 @@
 #include <stdint.h>
 
 /* MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED                -0x0037  /**< SHA-256 hardware accelerator failed */
-#define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA                 -0x0074  /**< SHA-256 input data was malformed. */
+/** SHA-256 hardware accelerator failed */
+#define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED                -0x0037
+/** SHA-256 input data was malformed. */
+#define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA                 -0x0074
 
 #ifdef __cplusplus
 extern "C" {
@@ -235,6 +237,9 @@
  *                 be a writable buffer of length \c 32 Bytes.
  * \param is224    Determines which function to use. This must be
  *                 either \c 0 for SHA-256, or \c 1 for SHA-224.
+ *
+ * \return         \c 0 on success.
+ * \return         A negative error code on failure.
  */
 int mbedtls_sha256_ret( const unsigned char *input,
                         size_t ilen,
diff --git a/third_party/mbedtls/repo/include/mbedtls/sha512.h b/third_party/mbedtls/repo/include/mbedtls/sha512.h
index 4a8ab42..cca47c2 100644
--- a/third_party/mbedtls/repo/include/mbedtls/sha512.h
+++ b/third_party/mbedtls/repo/include/mbedtls/sha512.h
@@ -34,8 +34,10 @@
 #include <stdint.h>
 
 /* MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED                -0x0039  /**< SHA-512 hardware accelerator failed */
-#define MBEDTLS_ERR_SHA512_BAD_INPUT_DATA                 -0x0075  /**< SHA-512 input data was malformed. */
+/** SHA-512 hardware accelerator failed */
+#define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED                -0x0039
+/** SHA-512 input data was malformed. */
+#define MBEDTLS_ERR_SHA512_BAD_INPUT_DATA                 -0x0075
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/mbedtls/ssl.h b/third_party/mbedtls/repo/include/mbedtls/ssl.h
index 7815ad9..209dbf6 100644
--- a/third_party/mbedtls/repo/include/mbedtls/ssl.h
+++ b/third_party/mbedtls/repo/include/mbedtls/ssl.h
@@ -75,64 +75,122 @@
 /*
  * SSL Error codes
  */
-#define MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE               -0x7080  /**< The requested feature is not available. */
-#define MBEDTLS_ERR_SSL_BAD_INPUT_DATA                    -0x7100  /**< Bad input parameters to function. */
-#define MBEDTLS_ERR_SSL_INVALID_MAC                       -0x7180  /**< Verification of the message MAC failed. */
-#define MBEDTLS_ERR_SSL_INVALID_RECORD                    -0x7200  /**< An invalid SSL record was received. */
-#define MBEDTLS_ERR_SSL_CONN_EOF                          -0x7280  /**< The connection indicated an EOF. */
-#define MBEDTLS_ERR_SSL_UNKNOWN_CIPHER                    -0x7300  /**< An unknown cipher was received. */
-#define MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN                  -0x7380  /**< The server has no ciphersuites in common with the client. */
-#define MBEDTLS_ERR_SSL_NO_RNG                            -0x7400  /**< No RNG was provided to the SSL module. */
-#define MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE             -0x7480  /**< No client certification received from the client, but required by the authentication mode. */
-#define MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE             -0x7500  /**< Our own certificate(s) is/are too large to send in an SSL message. */
-#define MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED              -0x7580  /**< The own certificate is not set, but needed by the server. */
-#define MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED              -0x7600  /**< The own private key or pre-shared key is not set, but needed. */
-#define MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED                 -0x7680  /**< No CA Chain is set, but required to operate. */
-#define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE                -0x7700  /**< An unexpected message was received from our peer. */
-#define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE               -0x7780  /**< A fatal alert message was received from our peer. */
-#define MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED                -0x7800  /**< Verification of our peer failed. */
-#define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY                 -0x7880  /**< The peer notified us that the connection is going to be closed. */
-#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO               -0x7900  /**< Processing of the ClientHello handshake message failed. */
-#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO               -0x7980  /**< Processing of the ServerHello handshake message failed. */
-#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE                -0x7A00  /**< Processing of the Certificate handshake message failed. */
-#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST        -0x7A80  /**< Processing of the CertificateRequest handshake message failed. */
-#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE        -0x7B00  /**< Processing of the ServerKeyExchange handshake message failed. */
-#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE          -0x7B80  /**< Processing of the ServerHelloDone handshake message failed. */
-#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE        -0x7C00  /**< Processing of the ClientKeyExchange handshake message failed. */
-#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP     -0x7C80  /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. */
-#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS     -0x7D00  /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. */
-#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY         -0x7D80  /**< Processing of the CertificateVerify handshake message failed. */
-#define MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC         -0x7E00  /**< Processing of the ChangeCipherSpec handshake message failed. */
-#define MBEDTLS_ERR_SSL_BAD_HS_FINISHED                   -0x7E80  /**< Processing of the Finished handshake message failed. */
-#define MBEDTLS_ERR_SSL_ALLOC_FAILED                      -0x7F00  /**< Memory allocation failed */
-#define MBEDTLS_ERR_SSL_HW_ACCEL_FAILED                   -0x7F80  /**< Hardware acceleration function returned with error */
-#define MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH              -0x6F80  /**< Hardware acceleration function skipped / left alone data */
-#define MBEDTLS_ERR_SSL_COMPRESSION_FAILED                -0x6F00  /**< Processing of the compression / decompression failed */
-#define MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION           -0x6E80  /**< Handshake protocol not within min/max boundaries */
-#define MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET         -0x6E00  /**< Processing of the NewSessionTicket handshake message failed. */
-#define MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED            -0x6D80  /**< Session ticket has expired. */
-#define MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH                  -0x6D00  /**< Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */
-#define MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY                  -0x6C80  /**< Unknown identity received (eg, PSK identity) */
-#define MBEDTLS_ERR_SSL_INTERNAL_ERROR                    -0x6C00  /**< Internal error (eg, unexpected failure in lower-level module) */
-#define MBEDTLS_ERR_SSL_COUNTER_WRAPPING                  -0x6B80  /**< A counter would wrap (eg, too many messages exchanged). */
-#define MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO       -0x6B00  /**< Unexpected message at ServerHello in renegotiation. */
-#define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED             -0x6A80  /**< DTLS client must retry for hello verification */
-#define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL                  -0x6A00  /**< A buffer is too small to receive or write a message */
-#define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE             -0x6980  /**< None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */
-#define MBEDTLS_ERR_SSL_WANT_READ                         -0x6900  /**< No data of requested type currently available on underlying transport. */
-#define MBEDTLS_ERR_SSL_WANT_WRITE                        -0x6880  /**< Connection requires a write call. */
-#define MBEDTLS_ERR_SSL_TIMEOUT                           -0x6800  /**< The operation timed out. */
-#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT                  -0x6780  /**< The client initiated a reconnect from the same port. */
-#define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD                 -0x6700  /**< Record header looks valid but is not expected. */
-#define MBEDTLS_ERR_SSL_NON_FATAL                         -0x6680  /**< The alert message received indicates a non-fatal error. */
-#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH               -0x6600  /**< Couldn't set the hash for verifying CertificateVerify */
-#define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING               -0x6580  /**< Internal-only message signaling that further message-processing should be done */
-#define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS                 -0x6500  /**< The asynchronous operation is not completed yet. */
-#define MBEDTLS_ERR_SSL_EARLY_MESSAGE                     -0x6480  /**< Internal-only message signaling that a message arrived early. */
-#define MBEDTLS_ERR_SSL_UNEXPECTED_CID                    -0x6000  /**< An encrypted DTLS-frame with an unexpected CID was received. */
-#define MBEDTLS_ERR_SSL_VERSION_MISMATCH                  -0x5F00  /**< An operation failed due to an unexpected version or configuration. */
-#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS                -0x7000  /**< A cryptographic operation is in progress. Try again later. */
-#define MBEDTLS_ERR_SSL_BAD_CONFIG                        -0x5E80  /**< Invalid value in SSL config */
+/** The requested feature is not available. */
+#define MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE               -0x7080
+/** Bad input parameters to function. */
+#define MBEDTLS_ERR_SSL_BAD_INPUT_DATA                    -0x7100
+/** Verification of the message MAC failed. */
+#define MBEDTLS_ERR_SSL_INVALID_MAC                       -0x7180
+/** An invalid SSL record was received. */
+#define MBEDTLS_ERR_SSL_INVALID_RECORD                    -0x7200
+/** The connection indicated an EOF. */
+#define MBEDTLS_ERR_SSL_CONN_EOF                          -0x7280
+/** An unknown cipher was received. */
+#define MBEDTLS_ERR_SSL_UNKNOWN_CIPHER                    -0x7300
+/** The server has no ciphersuites in common with the client. */
+#define MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN                  -0x7380
+/** No RNG was provided to the SSL module. */
+#define MBEDTLS_ERR_SSL_NO_RNG                            -0x7400
+/** No client certification received from the client, but required by the authentication mode. */
+#define MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE             -0x7480
+/** Our own certificate(s) is/are too large to send in an SSL message. */
+#define MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE             -0x7500
+/** The own certificate is not set, but needed by the server. */
+#define MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED              -0x7580
+/** The own private key or pre-shared key is not set, but needed. */
+#define MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED              -0x7600
+/** No CA Chain is set, but required to operate. */
+#define MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED                 -0x7680
+/** An unexpected message was received from our peer. */
+#define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE                -0x7700
+/** A fatal alert message was received from our peer. */
+#define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE               -0x7780
+/** Verification of our peer failed. */
+#define MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED                -0x7800
+/** The peer notified us that the connection is going to be closed. */
+#define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY                 -0x7880
+/** Processing of the ClientHello handshake message failed. */
+#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO               -0x7900
+/** Processing of the ServerHello handshake message failed. */
+#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO               -0x7980
+/** Processing of the Certificate handshake message failed. */
+#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE                -0x7A00
+/** Processing of the CertificateRequest handshake message failed. */
+#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST        -0x7A80
+/** Processing of the ServerKeyExchange handshake message failed. */
+#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE        -0x7B00
+/** Processing of the ServerHelloDone handshake message failed. */
+#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE          -0x7B80
+/** Processing of the ClientKeyExchange handshake message failed. */
+#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE        -0x7C00
+/** Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. */
+#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP     -0x7C80
+/** Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. */
+#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS     -0x7D00
+/** Processing of the CertificateVerify handshake message failed. */
+#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY         -0x7D80
+/** Processing of the ChangeCipherSpec handshake message failed. */
+#define MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC         -0x7E00
+/** Processing of the Finished handshake message failed. */
+#define MBEDTLS_ERR_SSL_BAD_HS_FINISHED                   -0x7E80
+/** Memory allocation failed */
+#define MBEDTLS_ERR_SSL_ALLOC_FAILED                      -0x7F00
+/** Hardware acceleration function returned with error */
+#define MBEDTLS_ERR_SSL_HW_ACCEL_FAILED                   -0x7F80
+/** Hardware acceleration function skipped / left alone data */
+#define MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH              -0x6F80
+/** Processing of the compression / decompression failed */
+#define MBEDTLS_ERR_SSL_COMPRESSION_FAILED                -0x6F00
+/** Handshake protocol not within min/max boundaries */
+#define MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION           -0x6E80
+/** Processing of the NewSessionTicket handshake message failed. */
+#define MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET         -0x6E00
+/** Session ticket has expired. */
+#define MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED            -0x6D80
+/** Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */
+#define MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH                  -0x6D00
+/** Unknown identity received (eg, PSK identity) */
+#define MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY                  -0x6C80
+/** Internal error (eg, unexpected failure in lower-level module) */
+#define MBEDTLS_ERR_SSL_INTERNAL_ERROR                    -0x6C00
+/** A counter would wrap (eg, too many messages exchanged). */
+#define MBEDTLS_ERR_SSL_COUNTER_WRAPPING                  -0x6B80
+/** Unexpected message at ServerHello in renegotiation. */
+#define MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO       -0x6B00
+/** DTLS client must retry for hello verification */
+#define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED             -0x6A80
+/** A buffer is too small to receive or write a message */
+#define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL                  -0x6A00
+/** None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */
+#define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE             -0x6980
+/** No data of requested type currently available on underlying transport. */
+#define MBEDTLS_ERR_SSL_WANT_READ                         -0x6900
+/** Connection requires a write call. */
+#define MBEDTLS_ERR_SSL_WANT_WRITE                        -0x6880
+/** The operation timed out. */
+#define MBEDTLS_ERR_SSL_TIMEOUT                           -0x6800
+/** The client initiated a reconnect from the same port. */
+#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT                  -0x6780
+/** Record header looks valid but is not expected. */
+#define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD                 -0x6700
+/** The alert message received indicates a non-fatal error. */
+#define MBEDTLS_ERR_SSL_NON_FATAL                         -0x6680
+/** Couldn't set the hash for verifying CertificateVerify */
+#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH               -0x6600
+/** Internal-only message signaling that further message-processing should be done */
+#define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING               -0x6580
+/** The asynchronous operation is not completed yet. */
+#define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS                 -0x6500
+/** Internal-only message signaling that a message arrived early. */
+#define MBEDTLS_ERR_SSL_EARLY_MESSAGE                     -0x6480
+/** An encrypted DTLS-frame with an unexpected CID was received. */
+#define MBEDTLS_ERR_SSL_UNEXPECTED_CID                    -0x6000
+/** An operation failed due to an unexpected version or configuration. */
+#define MBEDTLS_ERR_SSL_VERSION_MISMATCH                  -0x5F00
+/** A cryptographic operation is in progress. Try again later. */
+#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS                -0x7000
+/** Invalid value in SSL config */
+#define MBEDTLS_ERR_SSL_BAD_CONFIG                        -0x5E80
 
 /*
  * Various constants
@@ -412,8 +470,14 @@
 
 /* The value of the CID extension is still TBD as of
  * draft-ietf-tls-dtls-connection-id-05
- * (https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05) */
+ * (https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05).
+ *
+ * A future minor revision of Mbed TLS may change the default value of
+ * this option to match evolving standards and usage.
+ */
+#if !defined(MBEDTLS_TLS_EXT_CID)
 #define MBEDTLS_TLS_EXT_CID                        254 /* TBD */
+#endif
 
 #define MBEDTLS_TLS_EXT_ECJPAKE_KKPP               256 /* experimental */
 
@@ -536,10 +600,11 @@
  * \param buf      Buffer to write the received data to
  * \param len      Length of the receive buffer
  *
- * \return         The callback must return the number of bytes received,
- *                 or a non-zero error code.
- *                 If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_READ
+ * \returns        If data has been received, the positive number of bytes received.
+ * \returns        \c 0 if the connection has been closed.
+ * \returns        If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_READ
  *                 must be returned when the operation would block.
+ * \returns        Another negative error code on other kinds of failures.
  *
  * \note           The callback may receive fewer bytes than the length of the
  *                 buffer. It must always return the number of bytes actually
@@ -909,6 +974,10 @@
  */
 struct mbedtls_ssl_session
 {
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+    unsigned char mfl_code;     /*!< MaxFragmentLength negotiated by peer */
+#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+
 #if defined(MBEDTLS_HAVE_TIME)
     mbedtls_time_t start;       /*!< starting time      */
 #endif
@@ -937,10 +1006,6 @@
     uint32_t ticket_lifetime;   /*!< ticket lifetime hint    */
 #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
 
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-    unsigned char mfl_code;     /*!< MaxFragmentLength negotiated by peer */
-#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
-
 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
     int trunc_hmac;             /*!< flag for truncated hmac activation   */
 #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
@@ -955,7 +1020,98 @@
  */
 struct mbedtls_ssl_config
 {
-    /* Group items by size (largest first) to minimize padding overhead */
+    /* Group items by size and reorder them to maximize usage of immediate offset access.    */
+
+    /*
+     * Numerical settings (char)
+     */
+
+    unsigned char max_major_ver;    /*!< max. major version used            */
+    unsigned char max_minor_ver;    /*!< max. minor version used            */
+    unsigned char min_major_ver;    /*!< min. major version used            */
+    unsigned char min_minor_ver;    /*!< min. minor version used            */
+
+    /*
+     * Flags (could be bit-fields to save RAM, but separate bytes make
+     * the code smaller on architectures with an instruction for direct
+     * byte access).
+     */
+
+    uint8_t endpoint /*bool*/;      /*!< 0: client, 1: server               */
+    uint8_t transport /*bool*/;     /*!< stream (TLS) or datagram (DTLS)    */
+    uint8_t authmode /*2 bits*/;    /*!< MBEDTLS_SSL_VERIFY_XXX             */
+    /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE          */
+    uint8_t allow_legacy_renegotiation /*2 bits*/; /*!< MBEDTLS_LEGACY_XXX  */
+#if defined(MBEDTLS_ARC4_C)
+    uint8_t arc4_disabled /*bool*/; /*!< blacklist RC4 ciphersuites?        */
+#endif
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+    uint8_t mfl_code /*3 bits*/;    /*!< desired fragment length            */
+#endif
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+    uint8_t encrypt_then_mac /*bool*/;  /*!< negotiate encrypt-then-mac?    */
+#endif
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+    uint8_t extended_ms /*bool*/;   /*!< negotiate extended master secret?  */
+#endif
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+    uint8_t anti_replay /*bool*/;   /*!< detect and prevent replay?         */
+#endif
+#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
+    uint8_t cbc_record_splitting /*bool*/;  /*!< do cbc record splitting    */
+#endif
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    uint8_t disable_renegotiation /*bool*/; /*!< disable renegotiation?     */
+#endif
+#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
+    uint8_t trunc_hmac /*bool*/;    /*!< negotiate truncated hmac?          */
+#endif
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    uint8_t session_tickets /*bool*/;   /*!< use session tickets?           */
+#endif
+#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C)
+    uint8_t fallback /*bool*/;      /*!< is this a fallback?                */
+#endif
+#if defined(MBEDTLS_SSL_SRV_C)
+    uint8_t cert_req_ca_list /*bool*/;  /*!< enable sending CA list in
+                                          Certificate Request messages?     */
+#endif
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    uint8_t ignore_unexpected_cid /*bool*/; /*!< Determines whether DTLS
+                                             *   record with unexpected CID
+                                             *   should lead to failure.    */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+    uint8_t dtls_srtp_mki_support /*bool*/; /*!< support having mki_value
+                                                 in the use_srtp extension? */
+#endif
+
+    /*
+     * Numerical settings (int or larger)
+     */
+
+    uint32_t read_timeout;          /*!< timeout for mbedtls_ssl_read (ms)  */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    uint32_t hs_timeout_min;        /*!< initial value of the handshake
+                                         retransmission timeout (ms)        */
+    uint32_t hs_timeout_max;        /*!< maximum value of the handshake
+                                         retransmission timeout (ms)        */
+#endif
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    int renego_max_records;         /*!< grace period for renegotiation     */
+    unsigned char renego_period[8]; /*!< value of the record counters
+                                         that triggers renegotiation        */
+#endif
+
+#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
+    unsigned int badmac_limit;      /*!< limit of records with a bad MAC    */
+#endif
+
+#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C)
+    unsigned int dhm_min_bitlen;    /*!< min. bit length of the DHM prime   */
+#endif
 
     /*
      * Pointers
@@ -1109,91 +1265,6 @@
     /*! number of supported profiles */
     size_t dtls_srtp_profile_list_len;
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
-
-    /*
-     * Numerical settings (int then char)
-     */
-
-    uint32_t read_timeout;          /*!< timeout for mbedtls_ssl_read (ms)  */
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    uint32_t hs_timeout_min;        /*!< initial value of the handshake
-                                         retransmission timeout (ms)        */
-    uint32_t hs_timeout_max;        /*!< maximum value of the handshake
-                                         retransmission timeout (ms)        */
-#endif
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    int renego_max_records;         /*!< grace period for renegotiation     */
-    unsigned char renego_period[8]; /*!< value of the record counters
-                                         that triggers renegotiation        */
-#endif
-
-#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
-    unsigned int badmac_limit;      /*!< limit of records with a bad MAC    */
-#endif
-
-#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C)
-    unsigned int dhm_min_bitlen;    /*!< min. bit length of the DHM prime   */
-#endif
-
-    unsigned char max_major_ver;    /*!< max. major version used            */
-    unsigned char max_minor_ver;    /*!< max. minor version used            */
-    unsigned char min_major_ver;    /*!< min. major version used            */
-    unsigned char min_minor_ver;    /*!< min. minor version used            */
-
-    /*
-     * Flags (bitfields)
-     */
-
-    unsigned int endpoint : 1;      /*!< 0: client, 1: server               */
-    unsigned int transport : 1;     /*!< stream (TLS) or datagram (DTLS)    */
-    unsigned int authmode : 2;      /*!< MBEDTLS_SSL_VERIFY_XXX             */
-    /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE          */
-    unsigned int allow_legacy_renegotiation : 2 ; /*!< MBEDTLS_LEGACY_XXX   */
-#if defined(MBEDTLS_ARC4_C)
-    unsigned int arc4_disabled : 1; /*!< blacklist RC4 ciphersuites?        */
-#endif
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-    unsigned int mfl_code : 3;      /*!< desired fragment length            */
-#endif
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-    unsigned int encrypt_then_mac : 1 ; /*!< negotiate encrypt-then-mac?    */
-#endif
-#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-    unsigned int extended_ms : 1;   /*!< negotiate extended master secret?  */
-#endif
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-    unsigned int anti_replay : 1;   /*!< detect and prevent replay?         */
-#endif
-#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
-    unsigned int cbc_record_splitting : 1;  /*!< do cbc record splitting    */
-#endif
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    unsigned int disable_renegotiation : 1; /*!< disable renegotiation?     */
-#endif
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-    unsigned int trunc_hmac : 1;    /*!< negotiate truncated hmac?          */
-#endif
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    unsigned int session_tickets : 1;   /*!< use session tickets?           */
-#endif
-#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C)
-    unsigned int fallback : 1;      /*!< is this a fallback?                */
-#endif
-#if defined(MBEDTLS_SSL_SRV_C)
-    unsigned int cert_req_ca_list : 1;  /*!< enable sending CA list in
-                                          Certificate Request messages?     */
-#endif
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    unsigned int ignore_unexpected_cid : 1; /*!< Determines whether DTLS
-                                             *   record with unexpected CID
-                                             *   should lead to failure.    */
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-#if defined(MBEDTLS_SSL_DTLS_SRTP)
-    unsigned int dtls_srtp_mki_support : 1; /* support having mki_value
-                                               in the use_srtp extension     */
-#endif
 };
 
 struct mbedtls_ssl_context
@@ -2987,7 +3058,9 @@
 #if defined(MBEDTLS_ECP_C)
 /**
  * \brief          Set the allowed curves in order of preference.
- *                 (Default: all defined curves.)
+ *                 (Default: all defined curves in order of decreasing size,
+ *                 except that Montgomery curves come last. This order
+ *                 is likely to change in a future version.)
  *
  *                 On server: this only affects selection of the ECDHE curve;
  *                 the curves used for ECDH and ECDSA are determined by the
@@ -3019,7 +3092,9 @@
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
 /**
  * \brief          Set the allowed hashes for signatures during the handshake.
- *                 (Default: all available hashes except MD5.)
+ *                 (Default: all SHA-2 hashes, largest first. Also SHA-1 if
+ *                 the compile-time option
+ *                 `MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE` is enabled.)
  *
  * \note           This only affects which hashes are offered and can be used
  *                 for signatures during the handshake. Hashes for message
@@ -4327,7 +4402,7 @@
 /**
  * \brief          TLS-PRF function for key derivation.
  *
- * \param prf      The tls_prf type funtion type to be used.
+ * \param prf      The tls_prf type function type to be used.
  * \param secret   Secret for the key derivation function.
  * \param slen     Length of the secret.
  * \param label    String label for the key derivation function,
@@ -4337,7 +4412,7 @@
  * \param dstbuf   The buffer holding the derived key.
  * \param dlen     Length of the output buffer.
  *
- * \return         0 on sucess. An SSL specific error on failure.
+ * \return         0 on success. An SSL specific error on failure.
  */
 int  mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf,
                           const unsigned char *secret, size_t slen,
diff --git a/third_party/mbedtls/repo/include/mbedtls/ssl_internal.h b/third_party/mbedtls/repo/include/mbedtls/ssl_internal.h
index 577c959..6913dc0 100644
--- a/third_party/mbedtls/repo/include/mbedtls/ssl_internal.h
+++ b/third_party/mbedtls/repo/include/mbedtls/ssl_internal.h
@@ -275,26 +275,26 @@
 #endif
 
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
-static inline uint32_t mbedtls_ssl_get_output_buflen( const mbedtls_ssl_context *ctx )
+static inline size_t mbedtls_ssl_get_output_buflen( const mbedtls_ssl_context *ctx )
 {
 #if defined (MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    return (uint32_t) mbedtls_ssl_get_output_max_frag_len( ctx )
+    return mbedtls_ssl_get_output_max_frag_len( ctx )
                + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD
                + MBEDTLS_SSL_CID_OUT_LEN_MAX;
 #else
-    return (uint32_t) mbedtls_ssl_get_output_max_frag_len( ctx )
+    return mbedtls_ssl_get_output_max_frag_len( ctx )
                + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD;
 #endif
 }
 
-static inline uint32_t mbedtls_ssl_get_input_buflen( const mbedtls_ssl_context *ctx )
+static inline size_t mbedtls_ssl_get_input_buflen( const mbedtls_ssl_context *ctx )
 {
 #if defined (MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    return (uint32_t) mbedtls_ssl_get_input_max_frag_len( ctx )
+    return mbedtls_ssl_get_input_max_frag_len( ctx )
                + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD
                + MBEDTLS_SSL_CID_IN_LEN_MAX;
 #else
-    return (uint32_t) mbedtls_ssl_get_input_max_frag_len( ctx )
+    return mbedtls_ssl_get_input_max_frag_len( ctx )
                + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD;
 #endif
 }
@@ -430,13 +430,63 @@
      * Handshake specific crypto variables
      */
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
+    uint8_t max_major_ver;              /*!< max. major version client*/
+    uint8_t max_minor_ver;              /*!< max. minor version client*/
+    uint8_t resume;                     /*!<  session resume indicator*/
+    uint8_t cli_exts;                   /*!< client extension presence*/
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C) &&        \
+    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    uint8_t sni_authmode;               /*!< authmode from SNI callback     */
+#endif
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    uint8_t new_session_ticket;         /*!< use NewSessionTicket?    */
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+    uint8_t extended_ms;                /*!< use Extended Master Secret? */
+#endif
+
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+    uint8_t async_in_progress;          /*!< an asynchronous operation is in progress */
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    unsigned char retransmit_state;     /*!<  Retransmission state           */
+#endif
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    uint8_t ecrs_enabled;               /*!< Handshake supports EC restart? */
+    enum { /* this complements ssl->state with info on intra-state operations */
+        ssl_ecrs_none = 0,              /*!< nothing going on (yet)         */
+        ssl_ecrs_crt_verify,            /*!< Certificate: crt_verify()      */
+        ssl_ecrs_ske_start_processing,  /*!< ServerKeyExchange: pk_verify() */
+        ssl_ecrs_cke_ecdh_calc_secret,  /*!< ClientKeyExchange: ECDH step 2 */
+        ssl_ecrs_crt_vrfy_sign,         /*!< CertificateVerify: pk_sign()   */
+    } ecrs_state;                       /*!< current (or last) operation    */
+    mbedtls_x509_crt *ecrs_peer_cert;   /*!< The peer's CRT chain.          */
+    size_t ecrs_n;                      /*!< place for saving a length      */
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) &&                \
     defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
     mbedtls_ssl_sig_hash_set_t hash_algs;             /*!<  Set of suitable sig-hash pairs */
 #endif
+
+    size_t pmslen;                      /*!<  premaster length        */
+
+    mbedtls_ssl_ciphersuite_t const *ciphersuite_info;
+
+    void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t);
+    void (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *);
+    void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int);
+    mbedtls_ssl_tls_prf_cb *tls_prf;
+
 #if defined(MBEDTLS_DHM_C)
     mbedtls_dhm_context dhm_ctx;                /*!<  DHM key exchange        */
 #endif
+
 /* Adding guard for MBEDTLS_ECDSA_C to ensure no compile errors due
  * to guards also being in ssl_srv.c and ssl_cli.c. There is a gap
  * in functionality that access to ecdh_ctx structure is needed for
@@ -461,10 +511,12 @@
     size_t ecjpake_cache_len;                   /*!< Length of cached data */
 #endif
 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) ||      \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
     const mbedtls_ecp_curve_info **curves;      /*!<  Supported elliptic curves */
 #endif
+
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_key_id_t psk_opaque;            /*!< Opaque PSK from the callback   */
@@ -472,65 +524,26 @@
     unsigned char *psk;                 /*!<  PSK from the callback         */
     size_t psk_len;                     /*!<  Length of PSK from callback   */
 #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
     mbedtls_ssl_key_cert *key_cert;     /*!< chosen key/cert pair (server)  */
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-    int sni_authmode;                   /*!< authmode from SNI callback     */
     mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI         */
     mbedtls_x509_crt *sni_ca_chain;     /*!< trusted CAs from SNI callback  */
     mbedtls_x509_crl *sni_ca_crl;       /*!< trusted CAs CRLs from SNI      */
 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
+
 #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    int ecrs_enabled;                   /*!< Handshake supports EC restart? */
     mbedtls_x509_crt_restart_ctx ecrs_ctx;  /*!< restart context            */
-    enum { /* this complements ssl->state with info on intra-state operations */
-        ssl_ecrs_none = 0,              /*!< nothing going on (yet)         */
-        ssl_ecrs_crt_verify,            /*!< Certificate: crt_verify()      */
-        ssl_ecrs_ske_start_processing,  /*!< ServerKeyExchange: pk_verify() */
-        ssl_ecrs_cke_ecdh_calc_secret,  /*!< ClientKeyExchange: ECDH step 2 */
-        ssl_ecrs_crt_vrfy_sign,         /*!< CertificateVerify: pk_sign()   */
-    } ecrs_state;                       /*!< current (or last) operation    */
-    mbedtls_x509_crt *ecrs_peer_cert;   /*!< The peer's CRT chain.          */
-    size_t ecrs_n;                      /*!< place for saving a length      */
 #endif
-#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C) &&        \
     !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
     mbedtls_pk_context peer_pubkey;     /*!< The public key from the peer.  */
 #endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    unsigned int out_msg_seq;           /*!<  Outgoing handshake sequence number */
-    unsigned int in_msg_seq;            /*!<  Incoming handshake sequence number */
-
-    unsigned char *verify_cookie;       /*!<  Cli: HelloVerifyRequest cookie
-                                              Srv: unused                    */
-    unsigned char verify_cookie_len;    /*!<  Cli: cookie length
-                                              Srv: flag for sending a cookie */
-
-    uint32_t retransmit_timeout;        /*!<  Current value of timeout       */
-    unsigned char retransmit_state;     /*!<  Retransmission state           */
-    mbedtls_ssl_flight_item *flight;    /*!<  Current outgoing flight        */
-    mbedtls_ssl_flight_item *cur_msg;   /*!<  Current message in flight      */
-    unsigned char *cur_msg_p;           /*!<  Position in current message    */
-    unsigned int in_flight_start_seq;   /*!<  Minimum message sequence in the
-                                              flight being received          */
-    mbedtls_ssl_transform *alt_transform_out;   /*!<  Alternative transform for
-                                              resending messages             */
-    unsigned char alt_out_ctr[8];       /*!<  Alternative record epoch/counter
-                                              for resending messages         */
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    /* The state of CID configuration in this handshake. */
-
-    uint8_t cid_in_use; /*!< This indicates whether the use of the CID extension
-                         *   has been negotiated. Possible values are
-                         *   #MBEDTLS_SSL_CID_ENABLED and
-                         *   #MBEDTLS_SSL_CID_DISABLED. */
-    unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ]; /*! The peer's CID */
-    uint8_t peer_cid_len;                                  /*!< The length of
-                                                            *   \c peer_cid.  */
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
     struct
     {
         size_t total_bytes_buffered; /*!< Cumulative size of heap allocated
@@ -557,6 +570,37 @@
 
     } buffering;
 
+    unsigned int out_msg_seq;           /*!<  Outgoing handshake sequence number */
+    unsigned int in_msg_seq;            /*!<  Incoming handshake sequence number */
+
+    unsigned char *verify_cookie;       /*!<  Cli: HelloVerifyRequest cookie
+                                              Srv: unused                    */
+    unsigned char verify_cookie_len;    /*!<  Cli: cookie length
+                                              Srv: flag for sending a cookie */
+
+    uint32_t retransmit_timeout;        /*!<  Current value of timeout       */
+    mbedtls_ssl_flight_item *flight;    /*!<  Current outgoing flight        */
+    mbedtls_ssl_flight_item *cur_msg;   /*!<  Current message in flight      */
+    unsigned char *cur_msg_p;           /*!<  Position in current message    */
+    unsigned int in_flight_start_seq;   /*!<  Minimum message sequence in the
+                                              flight being received          */
+    mbedtls_ssl_transform *alt_transform_out;   /*!<  Alternative transform for
+                                              resending messages             */
+    unsigned char alt_out_ctr[8];       /*!<  Alternative record epoch/counter
+                                              for resending messages         */
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    /* The state of CID configuration in this handshake. */
+
+    uint8_t cid_in_use; /*!< This indicates whether the use of the CID extension
+                         *   has been negotiated. Possible values are
+                         *   #MBEDTLS_SSL_CID_ENABLED and
+                         *   #MBEDTLS_SSL_CID_DISABLED. */
+    unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ]; /*! The peer's CID */
+    uint8_t peer_cid_len;                                  /*!< The length of
+                                                            *   \c peer_cid.  */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
     uint16_t mtu;                       /*!<  Handshake mtu, used to fragment outgoing messages */
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
@@ -565,8 +609,8 @@
      */
 #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
     defined(MBEDTLS_SSL_PROTO_TLS1_1)
-       mbedtls_md5_context fin_md5;
-      mbedtls_sha1_context fin_sha1;
+    mbedtls_md5_context fin_md5;
+    mbedtls_sha1_context fin_sha1;
 #endif
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
 #if defined(MBEDTLS_SHA256_C)
@@ -585,35 +629,10 @@
 #endif
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
-    void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t);
-    void (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *);
-    void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int);
-    mbedtls_ssl_tls_prf_cb *tls_prf;
-
-    mbedtls_ssl_ciphersuite_t const *ciphersuite_info;
-
-    size_t pmslen;                      /*!<  premaster length        */
-
     unsigned char randbytes[64];        /*!<  random bytes            */
     unsigned char premaster[MBEDTLS_PREMASTER_SIZE];
                                         /*!<  premaster secret        */
 
-    int resume;                         /*!<  session resume indicator*/
-    int max_major_ver;                  /*!< max. major version client*/
-    int max_minor_ver;                  /*!< max. minor version client*/
-    int cli_exts;                       /*!< client extension presence*/
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    int new_session_ticket;             /*!< use NewSessionTicket?    */
-#endif /* MBEDTLS_SSL_SESSION_TICKETS */
-#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-    int extended_ms;                    /*!< use Extended Master Secret? */
-#endif
-
-#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
-    unsigned int async_in_progress : 1; /*!< an asynchronous operation is in progress */
-#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
-
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
     /** Asynchronous operation context. This field is meant for use by the
      * asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start,
@@ -1212,26 +1231,6 @@
 int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst,
                               const mbedtls_ssl_session *src );
 
-/* constant-time buffer comparison */
-static inline int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t n )
-{
-    size_t i;
-    volatile const unsigned char *A = (volatile const unsigned char *) a;
-    volatile const unsigned char *B = (volatile const unsigned char *) b;
-    volatile unsigned char diff = 0;
-
-    for( i = 0; i < n; i++ )
-    {
-        /* Read volatile data in order before computing diff.
-         * This avoids IAR compiler warning:
-         * 'the order of volatile accesses is undefined ..' */
-        unsigned char x = A[i], y = B[i];
-        diff |= x ^ y;
-    }
-
-    return( diff );
-}
-
 #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
     defined(MBEDTLS_SSL_PROTO_TLS1_1)
 int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl,
diff --git a/third_party/mbedtls/repo/include/mbedtls/ssl_ticket.h b/third_party/mbedtls/repo/include/mbedtls/ssl_ticket.h
index bf5fc97..a882eed 100644
--- a/third_party/mbedtls/repo/include/mbedtls/ssl_ticket.h
+++ b/third_party/mbedtls/repo/include/mbedtls/ssl_ticket.h
@@ -97,7 +97,7 @@
  *                  Recommended value: 86400 (one day).
  *
  * \note            It is highly recommended to select a cipher that is at
- *                  least as strong as the the strongest ciphersuite
+ *                  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.
diff --git a/third_party/mbedtls/repo/include/mbedtls/threading.h b/third_party/mbedtls/repo/include/mbedtls/threading.h
index 8baf15a..d147c73 100644
--- a/third_party/mbedtls/repo/include/mbedtls/threading.h
+++ b/third_party/mbedtls/repo/include/mbedtls/threading.h
@@ -36,16 +36,22 @@
 
 /* MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE is deprecated and should not be
  * used. */
-#define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE         -0x001A  /**< The selected feature is not available. */
+/** The selected feature is not available. */
+#define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE         -0x001A
 
-#define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA              -0x001C  /**< Bad input parameters to function. */
-#define MBEDTLS_ERR_THREADING_MUTEX_ERROR                 -0x001E  /**< Locking / unlocking / free failed with error code. */
+/** Bad input parameters to function. */
+#define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA              -0x001C
+/** Locking / unlocking / free failed with error code. */
+#define MBEDTLS_ERR_THREADING_MUTEX_ERROR                 -0x001E
 
 #if defined(MBEDTLS_THREADING_PTHREAD)
 #include <pthread.h>
 typedef struct mbedtls_threading_mutex_t
 {
     pthread_mutex_t 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 is_valid;
 } mbedtls_threading_mutex_t;
 #endif
diff --git a/third_party/mbedtls/repo/include/mbedtls/version.h b/third_party/mbedtls/repo/include/mbedtls/version.h
index 10c4316..b1a92b2 100644
--- a/third_party/mbedtls/repo/include/mbedtls/version.h
+++ b/third_party/mbedtls/repo/include/mbedtls/version.h
@@ -37,7 +37,7 @@
  * Major, Minor, Patchlevel
  */
 #define MBEDTLS_VERSION_MAJOR  2
-#define MBEDTLS_VERSION_MINOR  25
+#define MBEDTLS_VERSION_MINOR  28
 #define MBEDTLS_VERSION_PATCH  0
 
 /**
@@ -45,9 +45,9 @@
  *    MMNNPP00
  *    Major version | Minor version | Patch version
  */
-#define MBEDTLS_VERSION_NUMBER         0x02190000
-#define MBEDTLS_VERSION_STRING         "2.25.0"
-#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.25.0"
+#define MBEDTLS_VERSION_NUMBER         0x021C0000
+#define MBEDTLS_VERSION_STRING         "2.28.0"
+#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.28.0"
 
 #if defined(MBEDTLS_VERSION_C)
 
diff --git a/third_party/mbedtls/repo/include/mbedtls/x509.h b/third_party/mbedtls/repo/include/mbedtls/x509.h
index 08525e2..c177501 100644
--- a/third_party/mbedtls/repo/include/mbedtls/x509.h
+++ b/third_party/mbedtls/repo/include/mbedtls/x509.h
@@ -56,26 +56,46 @@
  * \name X509 Error codes
  * \{
  */
-#define MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE              -0x2080  /**< Unavailable feature, e.g. RSA hashing/encryption combination. */
-#define MBEDTLS_ERR_X509_UNKNOWN_OID                      -0x2100  /**< Requested OID is unknown. */
-#define MBEDTLS_ERR_X509_INVALID_FORMAT                   -0x2180  /**< The CRT/CRL/CSR format is invalid, e.g. different type expected. */
-#define MBEDTLS_ERR_X509_INVALID_VERSION                  -0x2200  /**< The CRT/CRL/CSR version element is invalid. */
-#define MBEDTLS_ERR_X509_INVALID_SERIAL                   -0x2280  /**< The serial tag or value is invalid. */
-#define MBEDTLS_ERR_X509_INVALID_ALG                      -0x2300  /**< The algorithm tag or value is invalid. */
-#define MBEDTLS_ERR_X509_INVALID_NAME                     -0x2380  /**< The name tag or value is invalid. */
-#define MBEDTLS_ERR_X509_INVALID_DATE                     -0x2400  /**< The date tag or value is invalid. */
-#define MBEDTLS_ERR_X509_INVALID_SIGNATURE                -0x2480  /**< The signature tag or value invalid. */
-#define MBEDTLS_ERR_X509_INVALID_EXTENSIONS               -0x2500  /**< The extension tag or value is invalid. */
-#define MBEDTLS_ERR_X509_UNKNOWN_VERSION                  -0x2580  /**< CRT/CRL/CSR has an unsupported version number. */
-#define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG                  -0x2600  /**< Signature algorithm (oid) is unsupported. */
-#define MBEDTLS_ERR_X509_SIG_MISMATCH                     -0x2680  /**< Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) */
-#define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED               -0x2700  /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */
-#define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT              -0x2780  /**< Format not recognized as DER or PEM. */
-#define MBEDTLS_ERR_X509_BAD_INPUT_DATA                   -0x2800  /**< Input invalid. */
-#define MBEDTLS_ERR_X509_ALLOC_FAILED                     -0x2880  /**< Allocation of memory failed. */
-#define MBEDTLS_ERR_X509_FILE_IO_ERROR                    -0x2900  /**< Read/write of file failed. */
-#define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL                 -0x2980  /**< Destination buffer is too small. */
-#define MBEDTLS_ERR_X509_FATAL_ERROR                      -0x3000  /**< A fatal error occurred, eg the chain is too long or the vrfy callback failed. */
+/** Unavailable feature, e.g. RSA hashing/encryption combination. */
+#define MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE              -0x2080
+/** Requested OID is unknown. */
+#define MBEDTLS_ERR_X509_UNKNOWN_OID                      -0x2100
+/** The CRT/CRL/CSR format is invalid, e.g. different type expected. */
+#define MBEDTLS_ERR_X509_INVALID_FORMAT                   -0x2180
+/** The CRT/CRL/CSR version element is invalid. */
+#define MBEDTLS_ERR_X509_INVALID_VERSION                  -0x2200
+/** The serial tag or value is invalid. */
+#define MBEDTLS_ERR_X509_INVALID_SERIAL                   -0x2280
+/** The algorithm tag or value is invalid. */
+#define MBEDTLS_ERR_X509_INVALID_ALG                      -0x2300
+/** The name tag or value is invalid. */
+#define MBEDTLS_ERR_X509_INVALID_NAME                     -0x2380
+/** The date tag or value is invalid. */
+#define MBEDTLS_ERR_X509_INVALID_DATE                     -0x2400
+/** The signature tag or value invalid. */
+#define MBEDTLS_ERR_X509_INVALID_SIGNATURE                -0x2480
+/** The extension tag or value is invalid. */
+#define MBEDTLS_ERR_X509_INVALID_EXTENSIONS               -0x2500
+/** CRT/CRL/CSR has an unsupported version number. */
+#define MBEDTLS_ERR_X509_UNKNOWN_VERSION                  -0x2580
+/** Signature algorithm (oid) is unsupported. */
+#define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG                  -0x2600
+/** Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) */
+#define MBEDTLS_ERR_X509_SIG_MISMATCH                     -0x2680
+/** Certificate verification failed, e.g. CRL, CA or signature check failed. */
+#define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED               -0x2700
+/** Format not recognized as DER or PEM. */
+#define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT              -0x2780
+/** Input invalid. */
+#define MBEDTLS_ERR_X509_BAD_INPUT_DATA                   -0x2800
+/** Allocation of memory failed. */
+#define MBEDTLS_ERR_X509_ALLOC_FAILED                     -0x2880
+/** Read/write of file failed. */
+#define MBEDTLS_ERR_X509_FILE_IO_ERROR                    -0x2900
+/** Destination buffer is too small. */
+#define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL                 -0x2980
+/** A fatal error occurred, eg the chain is too long or the vrfy callback failed. */
+#define MBEDTLS_ERR_X509_FATAL_ERROR                      -0x3000
 /* \} name */
 
 /**
diff --git a/third_party/mbedtls/repo/include/mbedtls/x509_crt.h b/third_party/mbedtls/repo/include/mbedtls/x509_crt.h
index 8e389f8..64ccb43 100644
--- a/third_party/mbedtls/repo/include/mbedtls/x509_crt.h
+++ b/third_party/mbedtls/repo/include/mbedtls/x509_crt.h
@@ -263,12 +263,21 @@
 /**
  * Default security profile. Should provide a good balance between security
  * and compatibility with current deployments.
+ *
+ * This profile permits:
+ * - SHA2 hashes.
+ * - All supported elliptic curves.
+ * - RSA with 2048 bits and above.
+ *
+ * New minor versions of Mbed TLS may extend this profile, for example if
+ * new curves are added to the library. New minor versions of Mbed TLS will
+ * not reduce this profile unless serious security concerns require it.
  */
 extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default;
 
 /**
  * Expected next default profile. Recommended for new deployments.
- * Currently targets a 128-bit security level, except for RSA-2048.
+ * Currently targets a 128-bit security level, except for allowing RSA-2048.
  */
 extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next;
 
diff --git a/third_party/mbedtls/repo/include/mbedtls/xtea.h b/third_party/mbedtls/repo/include/mbedtls/xtea.h
index 473dd4b..4bdc711 100644
--- a/third_party/mbedtls/repo/include/mbedtls/xtea.h
+++ b/third_party/mbedtls/repo/include/mbedtls/xtea.h
@@ -34,10 +34,12 @@
 #define MBEDTLS_XTEA_ENCRYPT     1
 #define MBEDTLS_XTEA_DECRYPT     0
 
-#define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH             -0x0028  /**< The data input has an invalid length. */
+/** The data input has an invalid length. */
+#define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH             -0x0028
 
 /* MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED is deprecated and should not be used. */
-#define MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED                  -0x0029  /**< XTEA hardware accelerator failed. */
+/** XTEA hardware accelerator failed. */
+#define MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED                  -0x0029
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/third_party/mbedtls/repo/include/psa/crypto.h b/third_party/mbedtls/repo/include/psa/crypto.h
index b41a20b..b0b57c3 100644
--- a/third_party/mbedtls/repo/include/psa/crypto.h
+++ b/third_party/mbedtls/repo/include/psa/crypto.h
@@ -90,10 +90,14 @@
  *
  * \retval #PSA_SUCCESS
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
  * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_DATA_CORRUPT
  */
 psa_status_t psa_crypto_init(void);
 
@@ -155,10 +159,10 @@
  * the owner of a key.
  *
  * \param[out] attributes  The attribute structure to write to.
- * \param owner_id         The key owner identifier.
+ * \param owner            The key owner identifier.
  */
 static void mbedtls_set_key_owner_id( psa_key_attributes_t *attributes,
-                                      mbedtls_key_owner_id_t owner_id );
+                                      mbedtls_key_owner_id_t owner );
 #endif
 
 /** Set the location of a persistent key.
@@ -260,6 +264,14 @@
  * - An algorithm value permits this particular algorithm.
  * - An algorithm wildcard built from #PSA_ALG_ANY_HASH allows the specified
  *   signature scheme with any hash algorithm.
+ * - An algorithm built from #PSA_ALG_AT_LEAST_THIS_LENGTH_MAC allows
+ *   any MAC algorithm from the same base class (e.g. CMAC) which
+ *   generates/verifies a MAC length greater than or equal to the length
+ *   encoded in the wildcard algorithm.
+ * - An algorithm built from #PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG
+ *   allows any AEAD algorithm from the same base class (e.g. CCM) which
+ *   generates/verifies a tag length greater than or equal to the length
+ *   encoded in the wildcard algorithm.
  *
  * This function overwrites any algorithm policy
  * previously set in \p attributes.
@@ -368,6 +380,8 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
  * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_DATA_CORRUPT
+ * \retval #PSA_ERROR_DATA_INVALID
  * \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
@@ -501,6 +515,8 @@
  * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_DATA_CORRUPT
  * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
  * \retval #PSA_ERROR_BAD_STATE
@@ -540,6 +556,10 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  *         There was an failure in communication with the cryptoprocessor.
  *         The key material may still be present in the cryptoprocessor.
+ * \retval #PSA_ERROR_DATA_INVALID
+ *         This error is typically a result of either storage corruption on a
+ *         cleartext storage backend, or an attempt to read data that was
+ *         written by an incompatible version of the library.
  * \retval #PSA_ERROR_STORAGE_FAILURE
  *         The storage is corrupted. Implementations shall make a best effort
  *         to erase key material even in this stage, however applications
@@ -625,6 +645,8 @@
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_DATA_CORRUPT
+ * \retval #PSA_ERROR_DATA_INVALID
  * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
@@ -687,6 +709,8 @@
  *   For Weierstrass curves, this is the content of the `privateKey` field of
  *   the `ECPrivateKey` format defined by RFC 5915.  For Montgomery curves,
  *   the format is defined by RFC 7748, and output is masked according to §5.
+ *   For twisted Edwards curves, the private key is as defined by RFC 8032
+ *   (a 32-byte string for Edwards25519, a 57-byte string for Edwards448).
  * - For Diffie-Hellman key exchange key pairs (key types for which
  *   #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the
  *   format is the representation of the private key `x` as a big-endian byte
@@ -713,7 +737,7 @@
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p data buffer is too small. You can determine a
  *         sufficient buffer size by calling
- *         #PSA_KEY_EXPORT_MAX_SIZE(\c type, \c bits)
+ *         #PSA_EXPORT_KEY_OUTPUT_SIZE(\c type, \c bits)
  *         where \c type is the key type
  *         and \c bits is the key size in bits.
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
@@ -752,7 +776,12 @@
  *      modulus            INTEGER,    -- n
  *      publicExponent     INTEGER  }  -- e
  *   ```
- * - For elliptic curve public keys (key types for which
+ * - For elliptic curve keys on a twisted Edwards curve (key types for which
+ *   #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true and #PSA_KEY_TYPE_ECC_GET_FAMILY
+ *   returns #PSA_ECC_FAMILY_TWISTED_EDWARDS), the public key is as defined
+ *   by RFC 8032
+ *   (a 32-byte string for Edwards25519, a 57-byte string for Edwards448).
+ * - For other elliptic curve public keys (key types for which
  *   #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed
  *   representation defined by SEC1 &sect;2.3.3 as the content of an ECPoint.
  *   Let `m` be the bit size associated with the curve, i.e. the bit size of
@@ -783,7 +812,7 @@
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p data buffer is too small. You can determine a
  *         sufficient buffer size by calling
- *         #PSA_KEY_EXPORT_MAX_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits)
+ *         #PSA_EXPORT_KEY_OUTPUT_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits)
  *         where \c type is the key type
  *         and \c bits is the key size in bits.
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
@@ -822,7 +851,7 @@
  * \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_SIZE(\p alg).
+ *                          #PSA_HASH_LENGTH(\p alg).
  *
  * \retval #PSA_SUCCESS
  *         Success.
@@ -1032,7 +1061,7 @@
  * \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_SIZE(\c alg) where \c alg is the
+ *                              #PSA_HASH_LENGTH(\c alg) where \c alg is the
  *                              hash algorithm that is calculated.
  *
  * \retval #PSA_SUCCESS
@@ -1041,7 +1070,7 @@
  *         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_SIZE(\c alg)
+ *         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
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
@@ -1479,7 +1508,7 @@
  * \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. This is always
- *                          #PSA_MAC_FINAL_SIZE(\c key_type, \c key_bits, \c alg)
+ *                          #PSA_MAC_LENGTH(\c key_type, \c key_bits, \c alg)
  *                          where \c key_type and \c key_bits are the type and
  *                          bit-size respectively of the key and \c alg is the
  *                          MAC algorithm that is calculated.
@@ -1491,7 +1520,7 @@
  *         operation).
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p mac buffer is too small. You can determine a
- *         sufficient buffer size by calling PSA_MAC_FINAL_SIZE().
+ *         sufficient buffer size by calling PSA_MAC_LENGTH().
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
@@ -2084,9 +2113,16 @@
  *                                authentication tag is appended to the
  *                                encrypted data.
  * \param ciphertext_size         Size of the \p ciphertext buffer in bytes.
- *                                This must be at least
- *                                #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\p alg,
- *                                \p plaintext_length).
+ *                                This must be appropriate for the selected
+ *                                algorithm and key:
+ *                                - A sufficient output size is
+ *                                  #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\c key_type,
+ *                                  \p alg, \p plaintext_length) where
+ *                                  \c key_type is the type of \p key.
+ *                                - #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p
+ *                                  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 \p ciphertext buffer.
  *
@@ -2100,7 +2136,11 @@
  *         \p alg is not supported or is not an AEAD algorithm.
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
- *         \p ciphertext_size is too small
+ *         \p ciphertext_size is too small.
+ *         #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\c key_type, \p alg,
+ *         \p plaintext_length) or
+ *         #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p plaintext_length) can be used to
+ *         determine the required buffer size.
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
@@ -2144,9 +2184,16 @@
  * \param ciphertext_length       Size of \p ciphertext in bytes.
  * \param[out] plaintext          Output buffer for the decrypted data.
  * \param plaintext_size          Size of the \p plaintext buffer in bytes.
- *                                This must be at least
- *                                #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\p alg,
- *                                \p ciphertext_length).
+ *                                This must be appropriate for the selected
+ *                                algorithm and key:
+ *                                - A sufficient output size is
+ *                                  #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\c key_type,
+ *                                  \p alg, \p ciphertext_length) where
+ *                                  \c key_type is the type of \p key.
+ *                                - #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p
+ *                                  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 \p plaintext buffer.
  *
@@ -2162,7 +2209,11 @@
  *         \p alg is not supported or is not an AEAD algorithm.
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
- *         \p plaintext_size or \p nonce_length is too small
+ *         \p plaintext_size is too small.
+ *         #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\c key_type, \p alg,
+ *         \p ciphertext_length) or
+ *         #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p ciphertext_length) can be used
+ *         to determine the required buffer size.
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
@@ -2583,10 +2634,18 @@
  * \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 at least
- *                              #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg,
- *                              \p input_length) where \c alg is the
- *                              algorithm that is being calculated.
+ *                              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.
  *
@@ -2597,9 +2656,9 @@
  *         set, and have lengths set if required by the algorithm).
  * \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_AEAD_UPDATE_OUTPUT_SIZE(\c alg, \p input_length)
- *         where \c alg is the algorithm that is being calculated.
+ *         #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.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         The total length of input to psa_aead_update_ad() so far is
  *         less than the additional data length that was previously
@@ -2636,9 +2695,7 @@
  * This function has two output buffers:
  * - \p ciphertext contains trailing ciphertext that was buffered from
  *   preceding calls to psa_aead_update().
- * - \p tag contains the authentication tag. Its length is always
- *   #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is the AEAD algorithm
- *   that the operation performs.
+ * - \p tag contains the authentication tag.
  *
  * When this function returns successfuly, the operation becomes inactive.
  * If this function returns an error status, the operation enters an error
@@ -2648,18 +2705,32 @@
  * \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 at least
- *                              #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) where
- *                              \c alg is the algorithm that is being
- *                              calculated.
+ *                              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 at least
- *                              #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is
- *                              the algorithm that is being calculated.
+ *                              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 is the
+ *                                algorithm that were used in the call to
+ *                                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.
  *
@@ -2670,11 +2741,11 @@
  *         operation with a nonce set).
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p ciphertext or \p tag buffer is too small.
- *         You can determine a sufficient buffer size for \p ciphertext by
- *         calling #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg)
- *         where \c alg is the algorithm that is being calculated.
- *         You can determine a sufficient buffer size for \p tag by
- *         calling #PSA_AEAD_TAG_LENGTH(\c alg).
+ *         #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type, \c alg) or
+ *         #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE can be used to determine the
+ *         required \p ciphertext buffer size. #PSA_AEAD_TAG_LENGTH(\c key_type,
+ *         \c key_bits, \c alg) or #PSA_AEAD_TAG_MAX_SIZE can be used to
+ *         determine the required \p tag buffer size.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         The total length of input to psa_aead_update_ad() so far is
  *         less than the additional data length that was previously
@@ -2733,10 +2804,15 @@
  *                              that could not be processed until the end
  *                              of the input.
  * \param plaintext_size        Size of the \p plaintext buffer in bytes.
- *                              This must be at least
- *                              #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) where
- *                              \c alg is the algorithm that is being
- *                              calculated.
+ *                              This must be appropriate for the selected algorithm and key:
+ *                              - A sufficient output size is
+ *                                #PSA_AEAD_VERIFY_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_VERIFY_OUTPUT_MAX_SIZE evaluates to
+ *                                the maximum output size of any supported AEAD
+ *                                algorithm.
  * \param[out] plaintext_length On success, the number of bytes of
  *                              returned plaintext.
  * \param[in] tag               Buffer containing the authentication tag.
@@ -2752,9 +2828,9 @@
  *         operation with a nonce set).
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p plaintext buffer is too small.
- *         You can determine a sufficient buffer size for \p plaintext by
- *         calling #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg)
- *         where \c alg is the algorithm that is being calculated.
+ *         #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c key_type, \c alg) or
+ *         #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE can be used to determine the
+ *         required buffer size.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         The total length of input to psa_aead_update_ad() so far is
  *         less than the additional data length that was previously
@@ -2814,18 +2890,138 @@
  */
 
 /**
+ * \brief Sign a message with a private key. For hash-and-sign algorithms,
+ *        this includes the hashing step.
+ *
+ * \note To perform a multi-part hash-and-sign signature algorithm, first use
+ *       a multi-part hash operation and then pass the resulting hash to
+ *       psa_sign_hash(). PSA_ALG_GET_HASH(\p alg) can be used to determine the
+ *       hash algorithm to use.
+ *
+ * \param[in]  key              Identifier of the key to use for the operation.
+ *                              It must be an asymmetric key pair. The key must
+ *                              allow the usage #PSA_KEY_USAGE_SIGN_MESSAGE.
+ * \param[in]  alg              An asymmetric signature algorithm (PSA_ALG_XXX
+ *                              value such that #PSA_ALG_IS_SIGN_MESSAGE(\p alg)
+ *                              is true), that is compatible with the type of
+ *                              \p 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. This
+ *                              must be appropriate for the selected
+ *                              algorithm and key:
+ *                              - The required signature size is
+ *                                #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 key.
+ *                              - #PSA_SIGNATURE_MAX_SIZE evaluates to the
+ *                                maximum signature size of any supported
+ *                                signature algorithm.
+ * \param[out] signature_length On success, the number of bytes that make up
+ *                              the returned signature value.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag,
+ *         or it does not permit the requested algorithm.
+ * \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
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_DATA_CORRUPT
+ * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ * \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_sign_message( mbedtls_svc_key_id_t key,
+                               psa_algorithm_t alg,
+                               const uint8_t * input,
+                               size_t input_length,
+                               uint8_t * signature,
+                               size_t signature_size,
+                               size_t * signature_length );
+
+/** \brief Verify the signature of a message with a public key, using
+ *         a hash-and-sign verification algorithm.
+ *
+ * \note To perform a multi-part hash-and-sign signature verification
+ *       algorithm, first use a multi-part hash operation to hash the message
+ *       and then pass the resulting hash to psa_verify_hash().
+ *       PSA_ALG_GET_HASH(\p alg) can be used to determine the hash algorithm
+ *       to use.
+ *
+ * \param[in]  key              Identifier of the key to use for the operation.
+ *                              It must be a public key or an asymmetric key
+ *                              pair. The key must allow the usage
+ *                              #PSA_KEY_USAGE_VERIFY_MESSAGE.
+ * \param[in]  alg              An asymmetric signature algorithm (PSA_ALG_XXX
+ *                              value such that #PSA_ALG_IS_SIGN_MESSAGE(\p alg)
+ *                              is true), that is compatible with the type of
+ *                              \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_length Size of the \p signature buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag,
+ *         or it does not permit the requested algorithm.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The calculation was performed successfully, but the passed signature
+ *         is not a valid signature.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_DATA_CORRUPT
+ * \retval #PSA_ERROR_DATA_INVALID
+ * \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_verify_message( mbedtls_svc_key_id_t key,
+                                 psa_algorithm_t alg,
+                                 const uint8_t * input,
+                                 size_t input_length,
+                                 const uint8_t * signature,
+                                 size_t signature_length );
+
+/**
  * \brief Sign a hash or short message with a private key.
  *
  * Note that to perform a hash-and-sign signature algorithm, you must
  * first calculate the hash by calling psa_hash_setup(), psa_hash_update()
- * and psa_hash_finish(). Then pass the resulting hash as the \p hash
+ * and psa_hash_finish(), or alternatively by calling psa_hash_compute().
+ * Then pass the resulting hash as the \p hash
  * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg)
  * to determine the hash algorithm to use.
  *
  * \param key                   Identifier of the key to use for the operation.
  *                              It must be an asymmetric key pair. The key must
  *                              allow the usage #PSA_KEY_USAGE_SIGN_HASH.
- * \param alg                   A signature algorithm that is compatible with
+ * \param alg                   A signature algorithm (PSA_ALG_XXX
+ *                              value such that #PSA_ALG_IS_SIGN_HASH(\p alg)
+ *                              is true), that is compatible with
  *                              the type of \p key.
  * \param[in] hash              The hash or message to sign.
  * \param hash_length           Size of the \p hash buffer in bytes.
@@ -2865,11 +3061,12 @@
                            size_t *signature_length);
 
 /**
- * \brief Verify the signature a hash or short message using a public key.
+ * \brief Verify the signature of a hash or short message using a public key.
  *
  * Note that to perform a hash-and-sign signature algorithm, you must
  * first calculate the hash by calling psa_hash_setup(), psa_hash_update()
- * and psa_hash_finish(). Then pass the resulting hash as the \p hash
+ * and psa_hash_finish(), or alternatively by calling psa_hash_compute().
+ * Then pass the resulting hash as the \p hash
  * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg)
  * to determine the hash algorithm to use.
  *
@@ -2877,7 +3074,9 @@
  *                          must be a public key or an asymmetric key pair. The
  *                          key must allow the usage
  *                          #PSA_KEY_USAGE_VERIFY_HASH.
- * \param alg               A signature algorithm that is compatible with
+ * \param alg               A signature algorithm (PSA_ALG_XXX
+ *                          value such that #PSA_ALG_IS_SIGN_HASH(\p alg)
+ *                          is true), that is compatible with
  *                          the type of \p key.
  * \param[in] hash          The hash or message whose signature is to be
  *                          verified.
@@ -3443,7 +3642,8 @@
  * state and must be aborted by calling psa_key_derivation_abort().
  *
  * How much output is produced and consumed from the operation, and how
- * the key is derived, depends on the key type:
+ * the key is derived, depends on the key type and on the key size
+ * (denoted \c bits below):
  *
  * - For key types for which the key is an arbitrary sequence of bytes
  *   of a given size, this function is functionally equivalent to
@@ -3453,11 +3653,12 @@
  *   if the implementation provides an isolation boundary then
  *   the key material is not exposed outside the isolation boundary.
  *   As a consequence, for these key types, this function always consumes
- *   exactly (\p bits / 8) bytes from the operation.
+ *   exactly (\c bits / 8) bytes from the operation.
  *   The following key types defined in this specification follow this scheme:
  *
  *     - #PSA_KEY_TYPE_AES;
  *     - #PSA_KEY_TYPE_ARC4;
+ *     - #PSA_KEY_TYPE_ARIA;
  *     - #PSA_KEY_TYPE_CAMELLIA;
  *     - #PSA_KEY_TYPE_DERIVE;
  *     - #PSA_KEY_TYPE_HMAC.
@@ -3474,8 +3675,8 @@
  *       string and process it as specified in RFC 7748 &sect;5.
  *
  * - For key types for which the key is represented by a single sequence of
- *   \p bits bits with constraints as to which bit sequences are acceptable,
- *   this function draws a byte string of length (\p bits / 8) bytes rounded
+ *   \c bits bits with constraints as to which bit sequences are acceptable,
+ *   this function draws a byte string of length (\c bits / 8) bytes rounded
  *   up to the nearest whole number of bytes. If the resulting byte string
  *   is acceptable, it becomes the key, otherwise the drawn bytes are discarded.
  *   This process is repeated until an acceptable byte string is drawn.
@@ -3556,6 +3757,8 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_DATA_CORRUPT
  * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
@@ -3721,6 +3924,8 @@
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
  * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
+ * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_DATA_CORRUPT
  * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
diff --git a/third_party/mbedtls/repo/include/psa/crypto_accel_driver.h b/third_party/mbedtls/repo/include/psa/crypto_accel_driver.h
deleted file mode 100644
index 4488ea8..0000000
--- a/third_party/mbedtls/repo/include/psa/crypto_accel_driver.h
+++ /dev/null
@@ -1,823 +0,0 @@
-/**
- * \file psa/crypto_accel_driver.h
- * \brief PSA cryptography accelerator driver module
- *
- * This header declares types and function signatures for cryptography
- * drivers that access key material directly. This is meant for
- * on-chip cryptography accelerators.
- *
- * This file is part of the PSA Crypto Driver Model, containing functions for
- * driver developers to implement to enable hardware to be called in a
- * standardized way by a PSA Cryptographic API implementation. The functions
- * comprising the driver model, which driver authors implement, are not
- * intended to be called by application developers.
- */
-
-/*
- *  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 PSA_CRYPTO_ACCEL_DRIVER_H
-#define PSA_CRYPTO_ACCEL_DRIVER_H
-
-#include "crypto_driver_common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** \defgroup driver_digest Hardware-Accelerated Message Digests
- *
- * Generation and authentication of Message Digests (aka hashes) must be done
- * in parts using the following sequence:
- * - `psa_drv_hash_setup_t`
- * - `psa_drv_hash_update_t`
- * - `psa_drv_hash_update_t`
- * - ...
- * - `psa_drv_hash_finish_t`
- *
- * If a previously started Message Digest operation needs to be terminated
- * before the `psa_drv_hash_finish_t` operation is complete, it should be aborted
- * by the `psa_drv_hash_abort_t`. Failure to do so may result in allocated
- * resources not being freed or in other undefined behavior.
- */
-/**@{*/
-
-/** \brief The hardware-specific hash context structure
- *
- * The contents of this structure are implementation dependent and are
- * therefore not described here
- */
-typedef struct psa_drv_hash_context_s psa_drv_hash_context_t;
-
-/** \brief The function prototype for the start operation of a hash (message
- * digest) operation
- *
- *  Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_hash_<ALGO>_setup
- * ~~~~~~~~~~~~~
- * Where `ALGO` is the name of the underlying hash function
- *
- * \param[in,out] p_context     A structure that will contain the
- * hardware-specific hash context
- *
- * \retval #PSA_SUCCESS     Success.
- */
-typedef psa_status_t (*psa_drv_hash_setup_t)(psa_drv_hash_context_t *p_context);
-
-/** \brief The function prototype for the update operation of a hash (message
- * digest) operation
- *
- * Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_hash_<ALGO>_update
- * ~~~~~~~~~~~~~
- * Where `ALGO` is the name of the underlying algorithm
- *
- * \param[in,out] p_context     A hardware-specific structure for the
- *                              previously-established hash operation to be
- *                              continued
- * \param[in] p_input           A buffer containing the message to be appended
- *                              to the hash operation
- * \param[in] input_length      The size in bytes of the input message buffer
- */
-typedef psa_status_t (*psa_drv_hash_update_t)(psa_drv_hash_context_t *p_context,
-                                              const uint8_t *p_input,
-                                              size_t input_length);
-
-/** \brief  The function prototype for the finish operation of a hash (message
- * digest) operation
- *
- * Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_hash_<ALGO>_finish
- * ~~~~~~~~~~~~~
- * Where `ALGO` is the name of the underlying algorithm
- *
- * \param[in,out] p_context     A hardware-specific structure for the
- *                              previously started hash operation to be
- *                              fiinished
- * \param[out] p_output         A buffer where the generated digest will be
- *                              placed
- * \param[in] output_size       The size in bytes of the buffer that has been
- *                              allocated for the `p_output` buffer
- * \param[out] p_output_length  The number of bytes placed in `p_output` after
- *                              success
- *
- * \retval #PSA_SUCCESS
- *          Success.
- */
-typedef psa_status_t (*psa_drv_hash_finish_t)(psa_drv_hash_context_t *p_context,
-                                              uint8_t *p_output,
-                                              size_t output_size,
-                                              size_t *p_output_length);
-
-/** \brief The function prototype for the abort operation of a hash (message
- * digest) operation
- *
- * Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_hash_<ALGO>_abort
- * ~~~~~~~~~~~~~
- * Where `ALGO` is the name of the underlying algorithm
- *
- * \param[in,out] p_context A hardware-specific structure for the previously
- *                          started hash operation to be aborted
- */
-typedef void (*psa_drv_hash_abort_t)(psa_drv_hash_context_t *p_context);
-
-/**@}*/
-
-/** \defgroup accel_mac Hardware-Accelerated Message Authentication Code
- * Generation and authentication of Message Authentication Codes (MACs) using
- * cryptographic accelerators can be done either as a single function call (via the
- * `psa_drv_accel_mac_generate_t` or `psa_drv_accel_mac_verify_t`
- * functions), or in parts using the following sequence:
- * - `psa_drv_accel_mac_setup_t`
- * - `psa_drv_accel_mac_update_t`
- * - `psa_drv_accel_mac_update_t`
- * - ...
- * - `psa_drv_accel_mac_finish_t` or `psa_drv_accel_mac_finish_verify_t`
- *
- * If a previously started MAC operation needs to be terminated, it
- * should be done so by the `psa_drv_accel_mac_abort_t`. Failure to do so may
- * result in allocated resources not being freed or in other undefined
- * behavior.
- *
- */
-/**@{*/
-
-/** \brief The hardware-accelerator-specific MAC context structure
- *
- * The contents of this structure are implementation dependent and are
- * therefore not described here.
- */
-typedef struct psa_drv_accel_mac_context_s psa_drv_accel_mac_context_t;
-
-/** \brief The function prototype for the setup operation of a
- * hardware-accelerated MAC operation
- *
- *  Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_mac_<ALGO>_<MAC_VARIANT>_setup
- * ~~~~~~~~~~~~~
- * Where `ALGO` is the name of the underlying primitive, and `MAC_VARIANT`
- * is the specific variant of a MAC operation (such as HMAC or CMAC)
- *
- * \param[in,out] p_context     A structure that will contain the
- *                              hardware-specific MAC context
- * \param[in] p_key             A buffer containing the cleartext key material
- *                              to be used in the operation
- * \param[in] key_length        The size in bytes of the key material
- *
- * \retval  #PSA_SUCCESS
- *          Success.
- */
-typedef psa_status_t (*psa_drv_accel_mac_setup_t)(psa_drv_accel_mac_context_t *p_context,
-                                                  const uint8_t *p_key,
-                                                  size_t key_length);
-
-/** \brief The function prototype for the update operation of a
- * hardware-accelerated MAC operation
- *
- * Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_mac_<ALGO>_<MAC_VARIANT>_update
- * ~~~~~~~~~~~~~
- * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT`
- * is the specific variant of a MAC operation (such as HMAC or CMAC)
- *
- * \param[in,out] p_context     A hardware-specific structure for the
- *                              previously-established MAC operation to be
- *                              continued
- * \param[in] p_input           A buffer containing the message to be appended
- *                              to the MAC operation
- * \param[in] input_length      The size in bytes of the input message buffer
- */
-typedef psa_status_t (*psa_drv_accel_mac_update_t)(psa_drv_accel_mac_context_t *p_context,
-                                                   const uint8_t *p_input,
-                                                   size_t input_length);
-
-/** \brief  The function prototype for the finish operation of a
- * hardware-accelerated MAC operation
- *
- * Functions that implement this prototype should be named in the following
- *  convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_mac_<ALGO>_<MAC_VARIANT>_finish
- * ~~~~~~~~~~~~~
- * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is
- * the specific variant of a MAC operation (such as HMAC or CMAC)
- *
- * \param[in,out] p_context     A hardware-specific structure for the
- *                              previously started MAC operation to be
- *                              finished
- * \param[out] p_mac            A buffer where the generated MAC will be placed
- * \param[in] mac_length        The size in bytes of the buffer that has been
- *                              allocated for the `p_mac` buffer
- *
- * \retval #PSA_SUCCESS
- *          Success.
- */
-typedef psa_status_t (*psa_drv_accel_mac_finish_t)(psa_drv_accel_mac_context_t *p_context,
-                                                   uint8_t *p_mac,
-                                                   size_t mac_length);
-
-/** \brief The function prototype for the finish and verify operation of a
- * hardware-accelerated MAC operation
- *
- * Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_mac_<ALGO>_<MAC_VARIANT>_finish_verify
- * ~~~~~~~~~~~~~
- * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is
- * the specific variant of a MAC operation (such as HMAC or CMAC)
- *
- * \param[in,out] p_context     A hardware-specific structure for the
- *                              previously started MAC operation to be
- *                              verified and finished
- * \param[in] p_mac             A buffer containing the MAC that will be used
- *                              for verification
- * \param[in] mac_length        The size in bytes of the data in the `p_mac`
- *                              buffer
- *
- * \retval #PSA_SUCCESS
- *          The operation completed successfully and the comparison matched
- */
-typedef psa_status_t (*psa_drv_accel_mac_finish_verify_t)(psa_drv_accel_mac_context_t *p_context,
-                                                          const uint8_t *p_mac,
-                                                          size_t mac_length);
-
-/** \brief The function prototype for the abort operation for a previously
- * started hardware-accelerated MAC operation
- *
- * Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_mac_<ALGO>_<MAC_VARIANT>_abort
- * ~~~~~~~~~~~~~
- * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is
- * the specific variant of a MAC operation (such as HMAC or CMAC)
- *
- * \param[in,out] p_context     A hardware-specific structure for the
- *                              previously started MAC operation to be
- *                              aborted
- *
- */
-typedef psa_status_t (*psa_drv_accel_mac_abort_t)(psa_drv_accel_mac_context_t *p_context);
-
-/** \brief The function prototype for the one-shot operation of a
- * hardware-accelerated MAC operation
- *
- * Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_mac_<ALGO>_<MAC_VARIANT>
- * ~~~~~~~~~~~~~
- * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is
- * the specific variant of a MAC operation (such as HMAC or CMAC)
- *
- * \param[in] p_input        A buffer containing the data to be MACed
- * \param[in] input_length   The length in bytes of the `p_input` data
- * \param[in] p_key          A buffer containing the key material to be used
- *                           for the MAC operation
- * \param[in] key_length     The length in bytes of the `p_key` data
- * \param[in] alg            The algorithm to be performed
- * \param[out] p_mac         The buffer where the resulting MAC will be placed
- *                           upon success
- * \param[in] mac_length     The length in bytes of the `p_mac` buffer
- */
-typedef psa_status_t (*psa_drv_accel_mac_t)(const uint8_t *p_input,
-                                            size_t input_length,
-                                            const uint8_t *p_key,
-                                            size_t key_length,
-                                            psa_algorithm_t alg,
-                                            uint8_t *p_mac,
-                                            size_t mac_length);
-
-/** \brief The function prototype for the one-shot hardware-accelerated MAC
- * Verify operation
- *
- * Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_mac_<ALGO>_<MAC_VARIANT>_verify
- * ~~~~~~~~~~~~~
- * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is
- * the specific variant of a MAC operation (such as HMAC or CMAC)
- *
- * \param[in] p_input        A buffer containing the data to be MACed
- * \param[in] input_length   The length in bytes of the `p_input` data
- * \param[in] p_key          A buffer containing the key material to be used
- *                           for the MAC operation
- * \param[in] key_length     The length in bytes of the `p_key` data
- * \param[in] alg            The algorithm to be performed
- * \param[in] p_mac          The MAC data to be compared
- * \param[in] mac_length     The length in bytes of the `p_mac` buffer
- *
- * \retval #PSA_SUCCESS
- *  The operation completed successfully and the comparison matched
- */
-typedef psa_status_t (*psa_drv_accel_mac_verify_t)(const uint8_t *p_input,
-                                                   size_t input_length,
-                                                   const uint8_t *p_key,
-                                                   size_t key_length,
-                                                   psa_algorithm_t alg,
-                                                   const uint8_t *p_mac,
-                                                   size_t mac_length);
-/**@}*/
-
-/** \defgroup accel_cipher Hardware-Accelerated Block Ciphers
- * Encryption and Decryption using hardware-acceleration in block modes other
- * than ECB must be done in multiple parts, using the following flow:
- * - `psa_drv_accel_ciphersetup_t`
- * - `psa_drv_accel_cipher_set_iv_t` (optional depending upon block mode)
- * - `psa_drv_accel_cipher_update_t`
- * - `psa_drv_accel_cipher_update_t`
- * - ...
- * - `psa_drv_accel_cipher_finish_t`
- *
- * If a previously started hardware-accelerated Cipher operation needs to be
- * terminated, it should be done so by the `psa_drv_accel_cipher_abort_t`.
- * Failure to do so may result in allocated resources not being freed or in
- * other undefined behavior.
- */
-/**@{*/
-
-/** \brief The hardware-accelerator-specific cipher context structure
- *
- * The contents of this structure are implementation dependent and are
- * therefore not described here.
- */
-typedef struct psa_drv_accel_cipher_context_s psa_drv_accel_cipher_context_t;
-
-/** \brief The function prototype for the setup operation of
- * hardware-accelerated block cipher operations.
- *  Functions that implement this prototype should be named in the following
- * conventions:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_cipher_setup_<CIPHER_NAME>_<MODE>
- * ~~~~~~~~~~~~~
- * Where
- * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES)
- * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR)
- *
- * For stream ciphers:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_cipher_setup_<CIPHER_NAME>
- * ~~~~~~~~~~~~~
- * Where `CIPHER_NAME` is the name of a stream cipher (i.e. RC4)
- *
- * \param[in,out] p_context     A structure that will contain the
- *                              hardware-specific cipher context
- * \param[in] direction         Indicates if the operation is an encrypt or a
- *                              decrypt
- * \param[in] p_key_data        A buffer containing the cleartext key material
- *                              to be used in the operation
- * \param[in] key_data_size     The size in bytes of the key material
- *
- * \retval #PSA_SUCCESS
- */
-typedef psa_status_t (*psa_drv_accel_cipher_setup_t)(psa_drv_accel_cipher_context_t *p_context,
-                                                     psa_encrypt_or_decrypt_t direction,
-                                                     const uint8_t *p_key_data,
-                                                     size_t key_data_size);
-
-/** \brief The function prototype for the set initialization vector operation
- * of hardware-accelerated block cipher operations
- * Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_cipher_set_iv_<CIPHER_NAME>_<MODE>
- * ~~~~~~~~~~~~~
- * Where
- * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES)
- * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR)
- *
- * \param[in,out] p_context     A structure that contains the previously setup
- *                              hardware-specific cipher context
- * \param[in] p_iv              A buffer containing the initialization vecotr
- * \param[in] iv_length         The size in bytes of the contents of `p_iv`
- *
- * \retval #PSA_SUCCESS
- */
-typedef psa_status_t (*psa_drv_accel_cipher_set_iv_t)(psa_drv_accel_cipher_context_t *p_context,
-                                                      const uint8_t *p_iv,
-                                                      size_t iv_length);
-
-/** \brief The function prototype for the update operation of
- * hardware-accelerated block cipher operations.
- *
- *  Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_cipher_update_<CIPHER_NAME>_<MODE>
- * ~~~~~~~~~~~~~
- * Where
- * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES)
- * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR)
- *
- * \param[in,out] p_context         A hardware-specific structure for the
- *                                  previously started cipher operation
- * \param[in] p_input               A buffer containing the data to be
- *                                  encrypted or decrypted
- * \param[in] input_size            The size in bytes of the `p_input` buffer
- * \param[out] p_output             A caller-allocated buffer where the
- *                                  generated output will be placed
- * \param[in] output_size           The size in bytes of the `p_output` buffer
- * \param[out] p_output_length      After completion, will contain the number
- *                                  of bytes placed in the `p_output` buffer
- *
- * \retval #PSA_SUCCESS
- */
-typedef psa_status_t (*psa_drv_accel_cipher_update_t)(psa_drv_accel_cipher_context_t *p_context,
-                                                      const uint8_t *p_input,
-                                                      size_t input_size,
-                                                      uint8_t *p_output,
-                                                      size_t output_size,
-                                                      size_t *p_output_length);
-
-/** \brief The function prototype for the finish operation of
- * hardware-accelerated block cipher operations.
- *
- *  Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_cipher_finish_<CIPHER_NAME>_<MODE>
- * ~~~~~~~~~~~~~
- * Where
- * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES)
- * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR)
- *
- * \param[in,out] p_context     A hardware-specific structure for the
- *                              previously started cipher operation
- * \param[out] p_output         A caller-allocated buffer where the generated
- *                              output will be placed
- * \param[in] output_size       The size in bytes of the `p_output` buffer
- * \param[out] p_output_length  After completion, will contain the number of
- *                              bytes placed in the `p_output` buffer
- *
- * \retval #PSA_SUCCESS
- */
-typedef psa_status_t (*psa_drv_accel_cipher_finish_t)(psa_drv_accel_cipher_context_t *p_context,
-                                                      uint8_t *p_output,
-                                                      size_t output_size,
-                                                      size_t *p_output_length);
-
-/** \brief The function prototype for the abort operation of
- * hardware-accelerated block cipher operations.
- *
- *  Functions that implement the following prototype should be named in the
- * following convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_cipher_abort_<CIPHER_NAME>_<MODE>
- * ~~~~~~~~~~~~~
- * Where
- * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES)
- * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR)
- *
- * \param[in,out] p_context     A hardware-specific structure for the
- *                              previously started cipher operation
- *
- * \retval #PSA_SUCCESS
- */
-typedef psa_status_t (*psa_drv_accel_cipher_abort_t)(psa_drv_accel_cipher_context_t *p_context);
-
-/**@}*/
-
-/** \defgroup accel_aead Hardware-Accelerated Authenticated Encryption with Additional Data
- *
- * Hardware-accelerated Authenticated Encryption with Additional Data (AEAD)
- * operations must be done in one function call. While this creates a burden
- * for implementers as there must be sufficient space in memory for the entire
- * message, it prevents decrypted data from being made available before the
- * authentication operation is complete and the data is known to be authentic.
- */
-/**@{*/
-
-/** \brief The function prototype for the hardware-accelerated authenticated
- * encryption operation.
- *
- * Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_aead_<ALGO>_encrypt
- * ~~~~~~~~~~~~~
- * Where `ALGO` is the name of the AEAD algorithm
- *
- * \param[in] p_key                     A pointer to the key material
- * \param[in] key_length                The size in bytes of the key material
- * \param[in] alg                       The AEAD algorithm to compute
- *                                      (\c PSA_ALG_XXX value such that
- *                                      #PSA_ALG_IS_AEAD(`alg`) is true)
- * \param[in] nonce                     Nonce or IV to use
- * \param[in] nonce_length              Size of the `nonce` buffer in bytes
- * \param[in] additional_data           Additional data that will be MACed
- *                                      but not encrypted.
- * \param[in] additional_data_length    Size of `additional_data` in bytes
- * \param[in] plaintext                 Data that will be MACed and
- *                                      encrypted.
- * \param[in] 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[in] ciphertext_size           Size of the `ciphertext` buffer in
- *                                      bytes
- *                                      This must be at least
- *                                      #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(`alg`,
- *                                      `plaintext_length`).
- * \param[out] ciphertext_length        On success, the size of the output in
- *                                      the `ciphertext` buffer
- *
- * \retval #PSA_SUCCESS
- *
- */
-typedef psa_status_t (*psa_drv_accel_aead_encrypt_t)(const uint8_t *p_key,
-                                                     size_t key_length,
-                                                     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 The function prototype for the hardware-accelerated authenticated
- * decryption operation.
- *
- * Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_aead_<ALGO>_decrypt
- * ~~~~~~~~~~~~~
- * Where `ALGO` is the name of the AEAD algorithm
- * \param[in] p_key                     A pointer to the key material
- * \param[in] key_length                The size in bytes of the key material
- * \param[in] alg                       The AEAD algorithm to compute
- *                                      (\c PSA_ALG_XXX value such that
- *                                      #PSA_ALG_IS_AEAD(`alg`) is true)
- * \param[in] nonce                     Nonce or IV to use
- * \param[in] nonce_length              Size of the `nonce` buffer in bytes
- * \param[in] additional_data           Additional data that has been MACed
- *                                      but not encrypted
- * \param[in] additional_data_length    Size of `additional_data` in bytes
- * \param[in] ciphertext                Data that has been MACed and
- *                                      encrypted
- *                                      For algorithms where the encrypted data
- *                                      and the authentication tag are defined
- *                                      as separate inputs, the buffer must
- *                                      contain the encrypted data followed by
- *                                      the authentication tag.
- * \param[in] ciphertext_length         Size of `ciphertext` in bytes
- * \param[out] plaintext                Output buffer for the decrypted data
- * \param[in] plaintext_size            Size of the `plaintext` buffer in
- *                                      bytes
- *                                      This must be at least
- *                                      #PSA_AEAD_DECRYPT_OUTPUT_SIZE(`alg`,
- *                                      `ciphertext_length`).
- * \param[out] plaintext_length         On success, the size of the output
- *                                      in the \b plaintext buffer
- *
- * \retval #PSA_SUCCESS
- *         Success.
- */
-typedef psa_status_t (*psa_drv_accel_aead_decrypt_t)(const uint8_t *p_key,
-                                                     size_t key_length,
-                                                     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);
-
-/**@}*/
-
-/** \defgroup accel_asymmetric Hardware-Accelerated Asymmetric Cryptography
- *
- * Since the amount of data that can (or should) be encrypted or signed using
- * asymmetric keys is limited by the key size, hardware-accelerated asymmetric
- * key operations must be done in single function calls.
- */
-/**@{*/
-
-
-/**
- * \brief The function prototype for the hardware-accelerated asymmetric sign
- * operation.
- *
- * Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_asymmetric_<ALGO>_sign
- * ~~~~~~~~~~~~~
- * Where `ALGO` is the name of the signing algorithm
- *
- * This function supports any asymmetric-key output from psa_export_key() as
- * the buffer in \p p_key. Refer to the documentation of \ref
- * psa_export_key() for the formats.
- *
- * \param[in] p_key                 A buffer containing the private key
- *                                  material
- * \param[in] key_size              The size in bytes of the `p_key` data
- * \param[in] alg                   A signature algorithm that is compatible
- *                                  with the type of `p_key`
- * \param[in] p_hash                The hash or message to sign
- * \param[in] hash_length           Size of the `p_hash` buffer in bytes
- * \param[out] p_signature          Buffer where the signature is to be written
- * \param[in] signature_size        Size of the `p_signature` buffer in bytes
- * \param[out] p_signature_length   On success, the number of bytes
- *                                  that make up the returned signature value
- *
- * \retval #PSA_SUCCESS
- */
-typedef psa_status_t (*psa_drv_accel_asymmetric_sign_t)(const uint8_t *p_key,
-                                                        size_t key_size,
-                                                        psa_algorithm_t alg,
-                                                        psa_key_type_t key_type,
-                                                        const uint8_t *p_hash,
-                                                        size_t hash_length,
-                                                        uint8_t *p_signature,
-                                                        size_t signature_size,
-                                                        size_t *p_signature_length);
-
-/**
- * \brief The function prototype for the hardware-accelerated signature verify
- * operation
- *
- * Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_asymmetric_<ALGO>_verify
- * ~~~~~~~~~~~~~
- * Where `ALGO` is the name of the signing algorithm
- *
- * This function supports any output from \ref psa_export_public_key() as the
- * buffer in \p p_key. Refer to the documentation of \ref
- * psa_export_public_key() for the format of public keys and to the
- * documentation of \ref psa_export_key() for the format for other key types.
- *
- * \param[in] p_key             A buffer containing the public key material
- * \param[in] key_size          The size in bytes of the `p_key` data
- * \param[in] alg               A signature algorithm that is compatible with
- *                              the type of `key`
- * \param[in] p_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] p_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.
- */
-typedef psa_status_t (*psa_drv_accel_asymmetric_verify_t)(const uint8_t *p_key,
-                                                          size_t key_size,
-                                                          psa_algorithm_t alg,
-                                                          psa_key_type_t key_type,
-                                                          const uint8_t *p_hash,
-                                                          size_t hash_length,
-                                                          const uint8_t *p_signature,
-                                                          size_t signature_length);
-
-/**
- * \brief The function prototype for the hardware-accelerated asymmetric
- * encrypt operation
- *
- * Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_asymmetric_<ALGO>_encrypt
- * ~~~~~~~~~~~~~
- * Where `ALGO` is the name of the encryption algorithm
- *
- * This function supports any output from \ref psa_export_public_key() as the
- * buffer in \p p_key. Refer to the documentation of \ref
- * psa_export_public_key() for the format of public keys and to the
- * documentation of \ref psa_export_key() for the format for other key types.
- *
- * \param[in] p_key             A buffer containing the public key material
- * \param[in] key_size          The size in bytes of the `p_key` data
- * \param[in] alg               An asymmetric encryption algorithm that is
- *                              compatible with the type of `key`
- * \param[in] p_input           The message to encrypt
- * \param[in] input_length      Size of the `p_input` buffer in bytes
- * \param[in] p_salt            A salt or label, if supported by the
- *                              encryption algorithm
- *                              If the algorithm does not support a
- *                              salt, pass `NULL`
- *                              If the algorithm supports an optional
- *                              salt and you do not want to pass a salt,
- *                              pass `NULL`.
- *                              For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is
- *                              supported.
- * \param[in] salt_length       Size of the `p_salt` buffer in bytes
- *                              If `p_salt` is `NULL`, pass 0.
- * \param[out] p_output         Buffer where the encrypted message is to
- *                              be written
- * \param[in] output_size       Size of the `p_output` buffer in bytes
- * \param[out] p_output_length  On success, the number of bytes
- *                              that make up the returned output
- *
- * \retval #PSA_SUCCESS
- */
-typedef psa_status_t (*psa_drv_accel_asymmetric_encrypt_t)(const uint8_t *p_key,
-                                                           size_t key_size,
-                                                           psa_algorithm_t alg,
-                                                           psa_key_type_t key_type,
-                                                           const uint8_t *p_input,
-                                                           size_t input_length,
-                                                           const uint8_t *p_salt,
-                                                           size_t salt_length,
-                                                           uint8_t *p_output,
-                                                           size_t output_size,
-                                                           size_t *p_output_length);
-
-/**
- * \brief The function prototype for the hardware=acce;erated asymmetric
- * decrypt operation
- *
- * Functions that implement this prototype should be named in the following
- * convention:
- * ~~~~~~~~~~~~~{.c}
- * psa_drv_accel_asymmetric_<ALGO>_decrypt
- * ~~~~~~~~~~~~~
- * Where `ALGO` is the name of the encryption algorithm
- *
- * This function supports any asymmetric-key output from psa_export_key() as
- * the buffer in \p p_key. Refer to the documentation of \ref
- * psa_export_key() for the formats.
- *
- * \param[in] p_key             A buffer containing the private key material
- * \param[in] key_size          The size in bytes of the `p_key` data
- * \param[in] alg               An asymmetric encryption algorithm that is
- *                              compatible with the type of `key`
- * \param[in] p_input           The message to decrypt
- * \param[in] input_length      Size of the `p_input` buffer in bytes
- * \param[in] p_salt            A salt or label, if supported by the
- *                              encryption algorithm
- *                              If the algorithm does not support a
- *                              salt, pass `NULL`.
- *                              If the algorithm supports an optional
- *                              salt and you do not want to pass a salt,
- *                              pass `NULL`.
- *                              For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is
- *                              supported
- * \param[in] salt_length       Size of the `p_salt` buffer in bytes
- *                              If `p_salt` is `NULL`, pass 0
- * \param[out] p_output         Buffer where the decrypted message is to
- *                              be written
- * \param[in] output_size       Size of the `p_output` buffer in bytes
- * \param[out] p_output_length  On success, the number of bytes
- *                              that make up the returned output
- *
- * \retval #PSA_SUCCESS
- */
-typedef psa_status_t (*psa_drv_accel_asymmetric_decrypt_t)(const uint8_t *p_key,
-                                                           size_t key_size,
-                                                           psa_algorithm_t alg,
-                                                           psa_key_type_t key_type,
-                                                           const uint8_t *p_input,
-                                                           size_t input_length,
-                                                           const uint8_t *p_salt,
-                                                           size_t salt_length,
-                                                           uint8_t *p_output,
-                                                           size_t output_size,
-                                                           size_t *p_output_length);
-
-/**@}*/
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* PSA_CRYPTO_ACCEL_DRIVER_H */
diff --git a/third_party/mbedtls/repo/include/psa/crypto_builtin_composites.h b/third_party/mbedtls/repo/include/psa/crypto_builtin_composites.h
new file mode 100644
index 0000000..a875b23
--- /dev/null
+++ b/third_party/mbedtls/repo/include/psa/crypto_builtin_composites.h
@@ -0,0 +1,79 @@
+/*
+ *  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 those algorithms which need to
+ *  rely on other algorithms, i.e. are 'composite' algorithms.
+ *
+ * \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
+ * 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
+ * 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.
+ */
+
+#ifndef PSA_CRYPTO_BUILTIN_COMPOSITES_H
+#define PSA_CRYPTO_BUILTIN_COMPOSITES_H
+
+#include <psa/crypto_driver_common.h>
+
+/*
+ * MAC multi-part operation definitions.
+ */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
+#define MBEDTLS_PSA_BUILTIN_MAC
+#endif
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || defined(PSA_CRYPTO_DRIVER_TEST)
+typedef struct
+{
+    /** The HMAC algorithm in use */
+    psa_algorithm_t alg;
+    /** The hash context. */
+    struct psa_hash_operation_s hash_ctx;
+    /** The HMAC part of the context. */
+    uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
+} mbedtls_psa_hmac_operation_t;
+
+#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 alg;
+    union
+    {
+        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || defined(PSA_CRYPTO_DRIVER_TEST)
+        mbedtls_psa_hmac_operation_t hmac;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) || defined(PSA_CRYPTO_DRIVER_TEST)
+        mbedtls_cipher_context_t cmac;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
+    } ctx;
+} mbedtls_psa_mac_operation_t;
+
+#define MBEDTLS_PSA_MAC_OPERATION_INIT {0, {0}}
+
+#endif /* PSA_CRYPTO_BUILTIN_COMPOSITES_H */
diff --git a/third_party/mbedtls/repo/include/psa/crypto_builtin_primitives.h b/third_party/mbedtls/repo/include/psa/crypto_builtin_primitives.h
new file mode 100644
index 0000000..62a0e6f
--- /dev/null
+++ b/third_party/mbedtls/repo/include/psa/crypto_builtin_primitives.h
@@ -0,0 +1,126 @@
+/*
+ *  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 those algorithms which do not
+ *  rely on other algorithms, i.e. are 'primitive' algorithms.
+ *
+ * \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
+ * 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
+ * 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.
+ */
+
+#ifndef PSA_CRYPTO_BUILTIN_PRIMITIVES_H
+#define PSA_CRYPTO_BUILTIN_PRIMITIVES_H
+
+#include <psa/crypto_driver_common.h>
+
+/*
+ * Hash multi-part operation definitions.
+ */
+
+#include "mbedtls/md2.h"
+#include "mbedtls/md4.h"
+#include "mbedtls/md5.h"
+#include "mbedtls/ripemd160.h"
+#include "mbedtls/sha1.h"
+#include "mbedtls/sha256.h"
+#include "mbedtls/sha512.h"
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_MD4) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) || \
+    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)
+#define MBEDTLS_PSA_BUILTIN_HASH
+#endif
+
+typedef struct
+{
+    psa_algorithm_t alg;
+    union
+    {
+        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2)
+        mbedtls_md2_context md2;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4)
+        mbedtls_md4_context md4;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
+        mbedtls_md5_context md5;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)
+        mbedtls_ripemd160_context ripemd160;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)
+        mbedtls_sha1_context sha1;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)
+        mbedtls_sha256_context sha256;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)
+        mbedtls_sha512_context sha512;
+#endif
+    } ctx;
+} mbedtls_psa_hash_operation_t;
+
+#define MBEDTLS_PSA_HASH_OPERATION_INIT {0, {0}}
+
+/*
+ * Cipher multi-part operation definitions.
+ */
+
+#include "mbedtls/cipher.h"
+
+#if 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_XTS) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
+#define MBEDTLS_PSA_BUILTIN_CIPHER  1
+#endif
+
+typedef struct {
+    /* Context structure for the Mbed TLS cipher implementation. */
+    psa_algorithm_t alg;
+    uint8_t iv_length;
+    uint8_t block_length;
+    union {
+        unsigned int dummy;
+        mbedtls_cipher_context_t cipher;
+    } ctx;
+} mbedtls_psa_cipher_operation_t;
+
+#define MBEDTLS_PSA_CIPHER_OPERATION_INIT {0, 0, 0, {0}}
+
+#endif /* PSA_CRYPTO_BUILTIN_PRIMITIVES_H */
diff --git a/third_party/mbedtls/repo/include/psa/crypto_compat.h b/third_party/mbedtls/repo/include/psa/crypto_compat.h
index 5bb5669..09ac488 100644
--- a/third_party/mbedtls/repo/include/psa/crypto_compat.h
+++ b/third_party/mbedtls/repo/include/psa/crypto_compat.h
@@ -44,7 +44,7 @@
 
 #define PSA_KEY_HANDLE_INIT MBEDTLS_SVC_KEY_ID_INIT
 
-/** Check wether an handle is null.
+/** Check whether an handle is null.
  *
  * \param handle  Handle
  *
@@ -110,6 +110,18 @@
     MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGNATURE_MAX_SIZE )
 #define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) \
     MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) )
+#define PSA_KEY_EXPORT_MAX_SIZE( key_type, key_bits ) \
+    MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_EXPORT_KEY_OUTPUT_SIZE( key_type, key_bits ) )
+#define PSA_BLOCK_CIPHER_BLOCK_SIZE( type ) \
+    MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_BLOCK_CIPHER_BLOCK_LENGTH( type ) )
+#define PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE \
+    MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE )
+#define PSA_HASH_SIZE( alg ) \
+    MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_HASH_LENGTH( alg ) )
+#define PSA_MAC_FINAL_SIZE( key_type, key_bits, alg ) \
+    MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_MAC_LENGTH( key_type, key_bits, alg ) )
+#define PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN \
+    MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE )
 
 /*
  * Deprecated PSA Crypto function names (PSA Crypto API  <= 1.0 beta3)
@@ -249,6 +261,161 @@
 #define PSA_ALG_CHACHA20 \
     MBEDTLS_DEPRECATED_CONSTANT( psa_algorithm_t, PSA_ALG_STREAM_CIPHER )
 
+/*
+ * Renamed AEAD tag length macros (PSA Crypto API  <= 1.0 beta3)
+ */
+#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH( aead_alg ) \
+    MBEDTLS_DEPRECATED_CONSTANT( psa_algorithm_t, PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG( aead_alg ) )
+#define PSA_ALG_AEAD_WITH_TAG_LENGTH( aead_alg, tag_length ) \
+    MBEDTLS_DEPRECATED_CONSTANT( psa_algorithm_t, PSA_ALG_AEAD_WITH_SHORTENED_TAG( aead_alg, tag_length ) )
+
+/*
+ * Deprecated PSA AEAD output size macros (PSA Crypto API  <= 1.0 beta3)
+ */
+
+/** The tag size for an AEAD algorithm, in bytes.
+ *
+ * \param alg                 An AEAD algorithm
+ *                            (\c PSA_ALG_XXX value such that
+ *                            #PSA_ALG_IS_AEAD(\p alg) is true).
+ *
+ * \return                    The tag size for the specified algorithm.
+ *                            If the AEAD algorithm does not have an identified
+ *                            tag that can be distinguished from the rest of
+ *                            the ciphertext, return 0.
+ *                            If the AEAD algorithm is not recognized, return 0.
+ */
+#define PSA_AEAD_TAG_LENGTH_1_ARG( alg )     \
+    MBEDTLS_DEPRECATED_CONSTANT( size_t,     \
+        PSA_ALG_IS_AEAD( alg ) ?             \
+        PSA_ALG_AEAD_GET_TAG_LENGTH( alg ) : \
+        0 )
+
+/** The maximum size of the output of psa_aead_encrypt(), in bytes.
+ *
+ * If the size of the ciphertext buffer is at least this large, it is
+ * guaranteed that psa_aead_encrypt() will not fail due to an
+ * insufficient buffer size. Depending on the algorithm, the actual size of
+ * the ciphertext may be smaller.
+ *
+ * \warning This macro may evaluate its arguments multiple times or
+ *          zero times, so you should not pass arguments that contain
+ *          side effects.
+ *
+ * \param alg                 An AEAD algorithm
+ *                            (\c PSA_ALG_XXX value such that
+ *                            #PSA_ALG_IS_AEAD(\p alg) is true).
+ * \param plaintext_length    Size of the plaintext in bytes.
+ *
+ * \return                    The AEAD ciphertext size for the specified
+ *                            algorithm.
+ *                            If the AEAD algorithm is not recognized, return 0.
+ */
+#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE_2_ARG( alg, plaintext_length ) \
+    MBEDTLS_DEPRECATED_CONSTANT( size_t,                            \
+        PSA_ALG_IS_AEAD( alg ) ?                                    \
+        (plaintext_length) + PSA_ALG_AEAD_GET_TAG_LENGTH( alg ) :   \
+        0 )
+
+/** The maximum size of the output of psa_aead_decrypt(), in bytes.
+ *
+ * If the size of the plaintext buffer is at least this large, it is
+ * guaranteed that psa_aead_decrypt() will not fail due to an
+ * insufficient buffer size. Depending on the algorithm, the actual size of
+ * the plaintext may be smaller.
+ *
+ * \warning This macro may evaluate its arguments multiple times or
+ *          zero times, so you should not pass arguments that contain
+ *          side effects.
+ *
+ * \param alg                 An AEAD algorithm
+ *                            (\c PSA_ALG_XXX value such that
+ *                            #PSA_ALG_IS_AEAD(\p alg) is true).
+ * \param ciphertext_length   Size of the plaintext in bytes.
+ *
+ * \return                    The AEAD ciphertext size for the specified
+ *                            algorithm.
+ *                            If the AEAD algorithm is not recognized, return 0.
+ */
+#define PSA_AEAD_DECRYPT_OUTPUT_SIZE_2_ARG( alg, ciphertext_length )   \
+    MBEDTLS_DEPRECATED_CONSTANT( size_t,                               \
+        PSA_ALG_IS_AEAD( alg ) &&                                      \
+            (ciphertext_length) > PSA_ALG_AEAD_GET_TAG_LENGTH( alg ) ? \
+            (ciphertext_length) - PSA_ALG_AEAD_GET_TAG_LENGTH( alg ) : \
+        0 )
+
+/** A sufficient output buffer size for psa_aead_update().
+ *
+ * If the size of the output buffer is at least this large, it is
+ * guaranteed that psa_aead_update() will not fail due to an
+ * insufficient buffer size. The actual size of the output may be smaller
+ * in any given call.
+ *
+ * \warning This macro may evaluate its arguments multiple times or
+ *          zero times, so you should not pass arguments that contain
+ *          side effects.
+ *
+ * \param alg                 An AEAD algorithm
+ *                            (\c PSA_ALG_XXX value such that
+ *                            #PSA_ALG_IS_AEAD(\p alg) is true).
+ * \param input_length        Size of the input in bytes.
+ *
+ * \return                    A sufficient output buffer size for the specified
+ *                            algorithm.
+ *                            If the AEAD algorithm is not recognized, return 0.
+ */
+/* For all the AEAD modes defined in this specification, it is possible
+ * to emit output without delay. However, hardware may not always be
+ * capable of this. So for modes based on a block cipher, allow the
+ * implementation to delay the output until it has a full block. */
+#define PSA_AEAD_UPDATE_OUTPUT_SIZE_2_ARG( alg, input_length )                        \
+    MBEDTLS_DEPRECATED_CONSTANT( size_t,                                              \
+        PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER( alg ) ?                                      \
+        PSA_ROUND_UP_TO_MULTIPLE( PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, (input_length) ) : \
+        (input_length) )
+
+/** A sufficient ciphertext buffer size for psa_aead_finish().
+ *
+ * If the size of the ciphertext buffer is at least this large, it is
+ * guaranteed that psa_aead_finish() will not fail due to an
+ * insufficient ciphertext buffer size. The actual size of the output may
+ * be smaller in any given call.
+ *
+ * \param alg                 An AEAD algorithm
+ *                            (\c PSA_ALG_XXX value such that
+ *                            #PSA_ALG_IS_AEAD(\p alg) is true).
+ *
+ * \return                    A sufficient ciphertext buffer size for the
+ *                            specified algorithm.
+ *                            If the AEAD algorithm is not recognized, return 0.
+ */
+#define PSA_AEAD_FINISH_OUTPUT_SIZE_1_ARG( alg )                        \
+    MBEDTLS_DEPRECATED_CONSTANT( size_t,                                \
+        PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER( alg ) ?                        \
+        PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE :                               \
+        0 )
+
+/** A sufficient plaintext buffer size for psa_aead_verify().
+ *
+ * If the size of the plaintext buffer is at least this large, it is
+ * guaranteed that psa_aead_verify() will not fail due to an
+ * insufficient plaintext buffer size. The actual size of the output may
+ * be smaller in any given call.
+ *
+ * \param alg                 An AEAD algorithm
+ *                            (\c PSA_ALG_XXX value such that
+ *                            #PSA_ALG_IS_AEAD(\p alg) is true).
+ *
+ * \return                    A sufficient plaintext buffer size for the
+ *                            specified algorithm.
+ *                            If the AEAD algorithm is not recognized, return 0.
+ */
+#define PSA_AEAD_VERIFY_OUTPUT_SIZE_1_ARG( alg )                        \
+    MBEDTLS_DEPRECATED_CONSTANT( size_t,                                \
+        PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER( alg ) ?                        \
+        PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE :                               \
+        0 )
+
 #endif /* MBEDTLS_DEPRECATED_REMOVED */
 
 /** Open a handle to an existing persistent key.
@@ -293,9 +460,9 @@
  *         number of open keys, the number of open key handles, or available
  *         memory.
  * \retval #PSA_ERROR_DOES_NOT_EXIST
- *         There is no persistent key with key identifier \p id.
+ *         There is no persistent key with key identifier \p key.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         \p id is not a valid persistent key identifier.
+ *         \p key is not a valid persistent key identifier.
  * \retval #PSA_ERROR_NOT_PERMITTED
  *         The specified key exists, but the application does not have the
  *         permission to access it. Note that this specification does not
@@ -304,6 +471,8 @@
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
  * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_DATA_CORRUPT
  * \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
diff --git a/third_party/mbedtls/repo/include/psa/crypto_config.h b/third_party/mbedtls/repo/include/psa/crypto_config.h
index cf7f63a..e2446cb 100644
--- a/third_party/mbedtls/repo/include/psa/crypto_config.h
+++ b/third_party/mbedtls/repo/include/psa/crypto_config.h
@@ -50,14 +50,29 @@
 #ifndef PSA_CRYPTO_CONFIG_H
 #define PSA_CRYPTO_CONFIG_H
 
+/*
+ * CBC-MAC is not yet supported via the PSA API in Mbed TLS.
+ */
+//#define PSA_WANT_ALG_CBC_MAC                    1
+#define PSA_WANT_ALG_CBC_NO_PADDING             1
+#define PSA_WANT_ALG_CBC_PKCS7                  1
+#define PSA_WANT_ALG_CCM                        1
+#define PSA_WANT_ALG_CMAC                       1
+#define PSA_WANT_ALG_CFB                        1
+#define PSA_WANT_ALG_CHACHA20_POLY1305          1
+#define PSA_WANT_ALG_CMAC                       1
+#define PSA_WANT_ALG_CTR                        1
 #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_ECDSA                      1
+#define PSA_WANT_ALG_GCM                        1
 #define PSA_WANT_ALG_HKDF                       1
 #define PSA_WANT_ALG_HMAC                       1
 #define PSA_WANT_ALG_MD2                        1
 #define PSA_WANT_ALG_MD4                        1
 #define PSA_WANT_ALG_MD5                        1
+#define PSA_WANT_ALG_OFB                        1
 #define PSA_WANT_ALG_RIPEMD160                  1
 #define PSA_WANT_ALG_RSA_OAEP                   1
 #define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT         1
@@ -68,10 +83,46 @@
 #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_STREAM_CIPHER              1
 #define PSA_WANT_ALG_TLS12_PRF                  1
 #define PSA_WANT_ALG_TLS12_PSK_TO_MS            1
+#define PSA_WANT_ALG_XTS                        1
+
+#define PSA_WANT_ECC_BRAINPOOL_P_R1_256         1
+#define PSA_WANT_ECC_BRAINPOOL_P_R1_384         1
+#define PSA_WANT_ECC_BRAINPOOL_P_R1_512         1
+#define PSA_WANT_ECC_MONTGOMERY_255             1
+/*
+ * Curve448 is not yet supported via the PSA API in Mbed TLS
+ * (https://github.com/ARMmbed/mbedtls/issues/4249). Thus, do not enable it by
+ * default.
+ */
+//#define PSA_WANT_ECC_MONTGOMERY_448             1
+#define PSA_WANT_ECC_SECP_K1_192                1
+/*
+ * SECP224K1 is buggy via the PSA API in Mbed TLS
+ * (https://github.com/ARMmbed/mbedtls/issues/3541). Thus, do not enable it by
+ * default.
+ */
+//#define PSA_WANT_ECC_SECP_K1_224                1
+#define PSA_WANT_ECC_SECP_K1_256                1
+#define PSA_WANT_ECC_SECP_R1_192                1
+#define PSA_WANT_ECC_SECP_R1_224                1
+#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_KEY_TYPE_DERIVE                1
+#define PSA_WANT_KEY_TYPE_HMAC                  1
+#define PSA_WANT_KEY_TYPE_AES                   1
+#define PSA_WANT_KEY_TYPE_ARC4                  1
+#define PSA_WANT_KEY_TYPE_ARIA                  1
+#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_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_PUBLIC_KEY        1
 
diff --git a/third_party/mbedtls/repo/include/psa/crypto_driver_common.h b/third_party/mbedtls/repo/include/psa/crypto_driver_common.h
index 2ce75d2..26363c6 100644
--- a/third_party/mbedtls/repo/include/psa/crypto_driver_common.h
+++ b/third_party/mbedtls/repo/include/psa/crypto_driver_common.h
@@ -5,9 +5,8 @@
  * This file contains common definitions shared by all PSA crypto drivers.
  * Do not include it directly: instead, include the header file(s) for
  * the type(s) of driver that you are implementing. For example, if
- * you are writing a driver for a chip that provides both a hardware
- * random generator and an accelerator for some cryptographic algorithms,
- * include `psa/crypto_entropy_driver.h` and `psa/crypto_accel_driver.h`.
+ * you are writing a dynamically registered driver for a secure element,
+ * include `psa/crypto_se_driver.h`.
  *
  * This file is part of the PSA Crypto Driver Model, containing functions for
  * driver developers to implement to enable hardware to be called in a
@@ -43,6 +42,9 @@
  * of these types. */
 #include "crypto_types.h"
 #include "crypto_values.h"
+/* Include size definitions which are used to size some arrays in operation
+ * structures. */
+#include <psa/crypto_sizes.h>
 
 /** For encrypt-decrypt functions, whether the operation is an encryption
  * or a decryption. */
diff --git a/third_party/mbedtls/repo/include/psa/crypto_driver_contexts_composites.h b/third_party/mbedtls/repo/include/psa/crypto_driver_contexts_composites.h
new file mode 100644
index 0000000..a722009
--- /dev/null
+++ b/third_party/mbedtls/repo/include/psa/crypto_driver_contexts_composites.h
@@ -0,0 +1,93 @@
+/*
+ *  Declaration of context structures for use with the PSA driver wrapper
+ *  interface. This file contains the context structures for 'composite'
+ *  operations, i.e. those operations which need to make use of other operations
+ *  from the primitives (crypto_driver_contexts_primitives.h)
+ *
+ *  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 is 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
+ * 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.
+ */
+
+#ifndef PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H
+#define PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H
+
+#include "psa/crypto_driver_common.h"
+
+/* Include the context structure definitions for the Mbed TLS software drivers */
+#include "psa/crypto_builtin_composites.h"
+
+/* Include the context structure definitions for those drivers that were
+ * declared during the autogeneration process. */
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+#include <libtestdriver1/include/psa/crypto.h>
+#endif
+
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC)
+typedef libtestdriver1_mbedtls_psa_mac_operation_t
+        mbedtls_transparent_test_driver_mac_operation_t;
+typedef libtestdriver1_mbedtls_psa_mac_operation_t
+        mbedtls_opaque_test_driver_mac_operation_t;
+
+#define MBEDTLS_TRANSPARENT_TEST_DRIVER_MAC_OPERATION_INIT \
+        LIBTESTDRIVER1_MBEDTLS_PSA_MAC_OPERATION_INIT
+#define MBEDTLS_OPAQUE_TEST_DRIVER_MAC_OPERATION_INIT \
+        LIBTESTDRIVER1_MBEDTLS_PSA_MAC_OPERATION_INIT
+
+#else
+typedef mbedtls_psa_mac_operation_t
+        mbedtls_transparent_test_driver_mac_operation_t;
+typedef mbedtls_psa_mac_operation_t
+        mbedtls_opaque_test_driver_mac_operation_t;
+
+#define MBEDTLS_TRANSPARENT_TEST_DRIVER_MAC_OPERATION_INIT \
+        MBEDTLS_PSA_MAC_OPERATION_INIT
+#define MBEDTLS_OPAQUE_TEST_DRIVER_MAC_OPERATION_INIT \
+        MBEDTLS_PSA_MAC_OPERATION_INIT
+
+#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 */
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+
+/* Define the context to be used for an operation that is executed through the
+ * PSA Driver wrapper layer as the union of all possible driver's contexts.
+ *
+ * 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 */
+
+typedef union {
+    unsigned dummy; /* Make sure this union is always non-empty */
+    mbedtls_psa_mac_operation_t mbedtls_ctx;
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+    mbedtls_transparent_test_driver_mac_operation_t transparent_test_driver_ctx;
+    mbedtls_opaque_test_driver_mac_operation_t opaque_test_driver_ctx;
+#endif
+} psa_driver_mac_context_t;
+
+#endif /* PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H */
+/* End of automatically generated file. */
diff --git a/third_party/mbedtls/repo/include/psa/crypto_driver_contexts_primitives.h b/third_party/mbedtls/repo/include/psa/crypto_driver_contexts_primitives.h
new file mode 100644
index 0000000..2bb01ed
--- /dev/null
+++ b/third_party/mbedtls/repo/include/psa/crypto_driver_contexts_primitives.h
@@ -0,0 +1,117 @@
+/*
+ *  Declaration of context structures for use with the PSA driver wrapper
+ *  interface. This file contains the context structures for 'primitive'
+ *  operations, i.e. those operations which do not rely on other contexts.
+ *
+ *  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 is 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
+ * 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.
+ */
+
+#ifndef PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H
+#define PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H
+
+#include "psa/crypto_driver_common.h"
+
+/* Include the context structure definitions for the Mbed TLS software drivers */
+#include "psa/crypto_builtin_primitives.h"
+
+/* Include the context structure definitions for those drivers that were
+ * declared during the autogeneration process. */
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+#include <libtestdriver1/include/psa/crypto.h>
+#endif
+
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)
+typedef libtestdriver1_mbedtls_psa_cipher_operation_t
+        mbedtls_transparent_test_driver_cipher_operation_t;
+
+#define MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT \
+        LIBTESTDRIVER1_MBEDTLS_PSA_CIPHER_OPERATION_INIT
+#else
+typedef mbedtls_psa_cipher_operation_t
+        mbedtls_transparent_test_driver_cipher_operation_t;
+
+#define MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT \
+        MBEDTLS_PSA_CIPHER_OPERATION_INIT
+#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 &&
+          LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER */
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)
+typedef libtestdriver1_mbedtls_psa_hash_operation_t
+        mbedtls_transparent_test_driver_hash_operation_t;
+
+#define MBEDTLS_TRANSPARENT_TEST_DRIVER_HASH_OPERATION_INIT \
+        LIBTESTDRIVER1_MBEDTLS_PSA_HASH_OPERATION_INIT
+#else
+typedef mbedtls_psa_hash_operation_t
+        mbedtls_transparent_test_driver_hash_operation_t;
+
+#define MBEDTLS_TRANSPARENT_TEST_DRIVER_HASH_OPERATION_INIT \
+        MBEDTLS_PSA_HASH_OPERATION_INIT
+#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 &&
+          LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH */
+
+typedef struct {
+    unsigned int initialised : 1;
+    mbedtls_transparent_test_driver_cipher_operation_t ctx;
+} mbedtls_opaque_test_driver_cipher_operation_t;
+
+#define MBEDTLS_OPAQUE_TEST_DRIVER_CIPHER_OPERATION_INIT \
+     { 0, MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT }
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+
+/* Define the context to be used for an operation that is executed through the
+ * PSA Driver wrapper layer as the union of all possible driver's contexts.
+ *
+ * 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 */
+
+typedef union {
+    unsigned dummy; /* Make sure this union is always non-empty */
+    mbedtls_psa_hash_operation_t mbedtls_ctx;
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+    mbedtls_transparent_test_driver_hash_operation_t test_driver_ctx;
+#endif
+} psa_driver_hash_context_t;
+
+typedef union {
+    unsigned dummy; /* Make sure this union is always non-empty */
+    mbedtls_psa_cipher_operation_t mbedtls_ctx;
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+    mbedtls_transparent_test_driver_cipher_operation_t transparent_test_driver_ctx;
+    mbedtls_opaque_test_driver_cipher_operation_t opaque_test_driver_ctx;
+#endif
+} psa_driver_cipher_context_t;
+
+#endif /* PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H */
+/* End of automatically generated file. */
diff --git a/third_party/mbedtls/repo/include/psa/crypto_entropy_driver.h b/third_party/mbedtls/repo/include/psa/crypto_entropy_driver.h
deleted file mode 100644
index 9b6546e..0000000
--- a/third_party/mbedtls/repo/include/psa/crypto_entropy_driver.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/**
- * \file psa/crypto_entropy_driver.h
- * \brief PSA entropy source driver module
- *
- * This header declares types and function signatures for entropy sources.
- *
- * This file is part of the PSA Crypto Driver Model, containing functions for
- * driver developers to implement to enable hardware to be called in a
- * standardized way by a PSA Cryptographic API implementation. The functions
- * comprising the driver model, which driver authors implement, are not
- * intended to be called by application developers.
- */
-
-/*
- *  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 PSA_CRYPTO_ENTROPY_DRIVER_H
-#define PSA_CRYPTO_ENTROPY_DRIVER_H
-
-#include "crypto_driver_common.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** \defgroup driver_rng Entropy Generation
- */
-/**@{*/
-
-/** \brief Initialize an entropy driver
- *
- *
- * \param[in,out] p_context             A hardware-specific structure
- *                                      containing any context information for
- *                                      the implementation
- *
- * \retval #PSA_SUCCESS
- */
-typedef psa_status_t (*psa_drv_entropy_init_t)(void *p_context);
-
-/** \brief Get a specified number of bits from the entropy source
- *
- * It retrives `buffer_size` bytes of data from the entropy source. The entropy
- * source will always fill the provided buffer to its full size, however, most
- * entropy sources have biases, and the actual amount of entropy contained in
- * the buffer will be less than the number of bytes.
- * The driver will return the actual number of bytes of entropy placed in the
- * buffer in `p_received_entropy_bytes`.
- * A PSA Crypto API implementation will likely feed the output of this function
- * into a Digital Random Bit Generator (DRBG), and typically has a minimum
- * amount of entropy that it needs.
- * To accomplish this, the PSA Crypto implementation should be designed to call
- * this function multiple times until it has received the required amount of
- * entropy from the entropy source.
- *
- * \param[in,out] p_context                 A hardware-specific structure
- *                                          containing any context information
- *                                          for the implementation
- * \param[out] p_buffer                     A caller-allocated buffer for the
- *                                          retrieved entropy to be placed in
- * \param[in] buffer_size                   The allocated size of `p_buffer`
- * \param[out] p_received_entropy_bits      The amount of entropy (in bits)
- *                                          actually provided in `p_buffer`
- *
- * \retval #PSA_SUCCESS
- */
-typedef psa_status_t (*psa_drv_entropy_get_bits_t)(void *p_context,
-                                                   uint8_t *p_buffer,
-                                                   uint32_t buffer_size,
-                                                   uint32_t *p_received_entropy_bits);
-
-/**
- * \brief A struct containing all of the function pointers needed to interface
- * to an entropy source
- *
- * PSA Crypto API implementations should populate instances of the table as
- * appropriate upon startup.
- *
- * If one of the functions is not implemented, it should be set to NULL.
- */
-typedef struct {
-    /** The driver-specific size of the entropy context */
-    const size_t                context_size;
-    /** Function that performs initialization for the entropy source */
-    psa_drv_entropy_init_t      p_init;
-    /** Function that performs the get_bits operation for the entropy source */
-    psa_drv_entropy_get_bits_t  p_get_bits;
-} psa_drv_entropy_t;
-/**@}*/
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* PSA_CRYPTO_ENTROPY_DRIVER_H */
diff --git a/third_party/mbedtls/repo/include/psa/crypto_extra.h b/third_party/mbedtls/repo/include/psa/crypto_extra.h
index f793a6c..3ee0482 100644
--- a/third_party/mbedtls/repo/include/psa/crypto_extra.h
+++ b/third_party/mbedtls/repo/include/psa/crypto_extra.h
@@ -30,6 +30,7 @@
 
 #include "mbedtls/platform_util.h"
 
+#include "crypto_types.h"
 #include "crypto_compat.h"
 
 #ifdef __cplusplus
@@ -39,6 +40,10 @@
 /* UID for secure storage seed */
 #define PSA_CRYPTO_ITS_RANDOM_SEED_UID 0xFFFFFF52
 
+/* See config.h for definition */
+#if !defined(MBEDTLS_PSA_KEY_SLOT_COUNT)
+#define MBEDTLS_PSA_KEY_SLOT_COUNT 32
+#endif
 
 /** \addtogroup attributes
  * @{
@@ -175,6 +180,9 @@
  *         The secure element driver for the specified lifetime does not
  *         support registering a key.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The identifier in \p attributes is invalid, namely the identifier is
+ *         not in the user range.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         \p attributes specifies a lifetime which is not located
  *         in a secure element.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
@@ -183,8 +191,10 @@
  * \retval #PSA_ERROR_NOT_PERMITTED
  *         The caller is not authorized to register the specified key slot.
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_DATA_CORRUPT
  * \retval #PSA_ERROR_CORRUPTION_DETECTED
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
@@ -401,10 +411,9 @@
 
 /* We need to expand the sample definition of this macro from
  * the API definition. */
-#undef PSA_ALG_IS_HASH_AND_SIGN
-#define PSA_ALG_IS_HASH_AND_SIGN(alg)                                   \
-    (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||    \
-     PSA_ALG_IS_DSA(alg) || PSA_ALG_IS_ECDSA(alg))
+#undef PSA_ALG_IS_VENDOR_HASH_AND_SIGN
+#define PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg)    \
+    PSA_ALG_IS_DSA(alg)
 
 /**@}*/
 
@@ -635,20 +644,174 @@
  *
  * \param curve         A PSA elliptic curve identifier
  *                      (`PSA_ECC_FAMILY_xxx`).
- * \param byte_length   The byte-length of a private key on \p curve.
+ * \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 byte_length is not
+ * \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 byte_length );
+                                               size_t bits,
+                                               int bits_is_sloppy );
 #endif /* MBEDTLS_ECP_C */
 
 /**@}*/
 
+/** \defgroup psa_external_rng External random generator
+ * @{
+ */
+
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+/** External random generator function, implemented by the platform.
+ *
+ * When the compile-time option #MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG is enabled,
+ * this function replaces Mbed TLS's entropy and DRBG modules for all
+ * random generation triggered via PSA crypto interfaces.
+ *
+ * \note This random generator must deliver random numbers with cryptographic
+ *       quality and high performance. It must supply unpredictable numbers
+ *       with a uniform distribution. The implementation of this function
+ *       is responsible for ensuring that the random generator is seeded
+ *       with sufficient entropy. If you have a hardware TRNG which is slow
+ *       or delivers non-uniform output, declare it as an entropy source
+ *       with mbedtls_entropy_add_source() instead of enabling this option.
+ *
+ * \param[in,out] context       Pointer to the random generator context.
+ *                              This is all-bits-zero on the first call
+ *                              and preserved between successive calls.
+ * \param[out] output           Output buffer. On success, this buffer
+ *                              contains random data with a uniform
+ *                              distribution.
+ * \param output_size           The size of the \p output buffer in bytes.
+ * \param[out] output_length    On success, set this value to \p output_size.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success. The output buffer contains \p output_size bytes of
+ *         cryptographic-quality random data, and \c *output_length is
+ *         set to \p output_size.
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ *         The random generator requires extra entropy and there is no
+ *         way to obtain entropy under current environment conditions.
+ *         This error should not happen under normal circumstances since
+ *         this function is responsible for obtaining as much entropy as
+ *         it needs. However implementations of this function may return
+ *         #PSA_ERROR_INSUFFICIENT_ENTROPY if there is no way to obtain
+ *         entropy without blocking indefinitely.
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ *         A failure of the random generator hardware that isn't covered
+ *         by #PSA_ERROR_INSUFFICIENT_ENTROPY.
+ */
+psa_status_t mbedtls_psa_external_get_random(
+    mbedtls_psa_external_random_context_t *context,
+    uint8_t *output, size_t output_size, size_t *output_length );
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
+/**@}*/
+
+/** \defgroup psa_builtin_keys Built-in keys
+ * @{
+ */
+
+/** The minimum value for a key identifier that is built into the
+ * implementation.
+ *
+ * The range of key identifiers from #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN
+ * to #MBEDTLS_PSA_KEY_ID_BUILTIN_MAX within the range from
+ * #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
+ * the values of built-in key identifiers in applications.
+ */
+#define MBEDTLS_PSA_KEY_ID_BUILTIN_MIN          ((psa_key_id_t)0x7fff0000)
+
+/** The maximum value for a key identifier that is built into the
+ * implementation.
+ *
+ * See #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN for more information.
+ */
+#define MBEDTLS_PSA_KEY_ID_BUILTIN_MAX          ((psa_key_id_t)0x7fffefff)
+
+/** A slot number identifying a key in a driver.
+ *
+ * Values of this type are used to identify built-in keys.
+ */
+typedef uint64_t psa_drv_slot_number_t;
+
+#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
+/** Test whether a key identifier belongs to the builtin key range.
+ *
+ * \param key_id  Key identifier to test.
+ *
+ * \retval 1
+ *         The key identifier is a builtin key identifier.
+ * \retval 0
+ *         The key identifier is not a builtin key identifier.
+ */
+static inline int psa_key_id_is_builtin( psa_key_id_t key_id )
+{
+    return( ( key_id >= MBEDTLS_PSA_KEY_ID_BUILTIN_MIN ) &&
+            ( key_id <= MBEDTLS_PSA_KEY_ID_BUILTIN_MAX ) );
+}
+
+/** Platform function to obtain the location and slot number of a built-in key.
+ *
+ * An application-specific implementation of this function must be provided if
+ * #MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS is enabled. This would typically be provided
+ * as part of a platform's system image.
+ *
+ * #MBEDTLS_SVC_KEY_ID_GET_KEY_ID(\p key_id) needs to be in the range from
+ * #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN to #MBEDTLS_PSA_KEY_ID_BUILTIN_MAX.
+ *
+ * In a multi-application configuration
+ * (\c MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER is defined),
+ * this function should check that #MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(\p key_id)
+ * is allowed to use the given key.
+ *
+ * \param key_id                The key ID for which to retrieve the
+ *                              location and slot attributes.
+ * \param[out] lifetime         On success, the lifetime associated with the key
+ *                              corresponding to \p key_id. Lifetime is a
+ *                              combination of which driver contains the key,
+ *                              and with what persistence level the key is
+ *                              intended to be used. If the platform
+ *                              implementation does not contain specific
+ *                              information about the intended key persistence
+ *                              level, the persistence level may be reported as
+ *                              #PSA_KEY_PERSISTENCE_DEFAULT.
+ * \param[out] slot_number      On success, the slot number known to the driver
+ *                              registered at the lifetime location reported
+ *                              through \p lifetime which corresponds to the
+ *                              requested built-in key.
+ *
+ * \retval #PSA_SUCCESS
+ *         The requested key identifier designates a built-in key.
+ *         In a multi-application configuration, the requested owner
+ *         is allowed to access it.
+ * \retval #PSA_ERROR_DOES_NOT_EXIST
+ *         The requested key identifier is not a built-in key which is known
+ *         to this function. If a key exists in the key storage with this
+ *         identifier, the data from the storage will be used.
+ * \return (any other error)
+ *         Any other error is propagated to the function that requested the key.
+ *         Common errors include:
+ *         - #PSA_ERROR_NOT_PERMITTED: the key exists but the requested owner
+ *           is not allowed to access it.
+ */
+psa_status_t mbedtls_psa_platform_get_builtin_key(
+    mbedtls_svc_key_id_t key_id,
+    psa_key_lifetime_t *lifetime,
+    psa_drv_slot_number_t *slot_number );
+#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
+
+/** @} */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/third_party/mbedtls/repo/include/psa/crypto_platform.h b/third_party/mbedtls/repo/include/psa/crypto_platform.h
index 567398d..66f4687 100644
--- a/third_party/mbedtls/repo/include/psa/crypto_platform.h
+++ b/third_party/mbedtls/repo/include/psa/crypto_platform.h
@@ -81,4 +81,31 @@
 
 #endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
 
+/*
+ * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is being built for SPM
+ * (Secure Partition Manager) integration which separates the code into two
+ * parts: NSPE (Non-Secure Processing Environment) and SPE (Secure Processing
+ * Environment). When building for the SPE, an additional header file should be
+ * included.
+ */
+#if defined(MBEDTLS_PSA_CRYPTO_SPM)
+#define PSA_CRYPTO_SECURE 1
+#include "crypto_spe.h"
+#endif // MBEDTLS_PSA_CRYPTO_SPM
+
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+/** The type of the context passed to mbedtls_psa_external_get_random().
+ *
+ * Mbed TLS initializes the context to all-bits-zero before calling
+ * mbedtls_psa_external_get_random() for the first time.
+ *
+ * The definition of this type in the Mbed TLS source code is for
+ * demonstration purposes. Implementers of mbedtls_psa_external_get_random()
+ * are expected to replace it with a custom definition.
+ */
+typedef struct {
+    uintptr_t opaque[2];
+} mbedtls_psa_external_random_context_t;
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
 #endif /* PSA_CRYPTO_PLATFORM_H */
diff --git a/third_party/mbedtls/repo/include/psa/crypto_se_driver.h b/third_party/mbedtls/repo/include/psa/crypto_se_driver.h
index 1fae575..1dc8f9b 100644
--- a/third_party/mbedtls/repo/include/psa/crypto_se_driver.h
+++ b/third_party/mbedtls/repo/include/psa/crypto_se_driver.h
@@ -1061,7 +1061,8 @@
  * \brief A function that generates a symmetric or asymmetric key on a secure
  * element
  *
- * If \p type is asymmetric (#PSA_KEY_TYPE_IS_ASYMMETRIC(\p type) = 1),
+ * If the key type \c type recorded in \p attributes
+ * is asymmetric (#PSA_KEY_TYPE_IS_ASYMMETRIC(\c type) = 1),
  * the driver may export the public key at the time of generation,
  * in the format documented for psa_export_public_key() by writing it
  * to the \p pubkey buffer.
@@ -1158,7 +1159,7 @@
  * can be problemmatic to manage on embedded platforms, the inputs are passed
  * to the driver via a function, `psa_drv_se_key_derivation_collateral`, that
  * is called multiple times with different `collateral_id`s. Thus, for a key
- * derivation algorithm that required 3 paramter inputs, the flow would look
+ * derivation algorithm that required 3 parameter inputs, the flow would look
  * something like:
  * ~~~~~~~~~~~~~{.c}
  * psa_drv_se_key_derivation_setup(kdf_algorithm, source_key, dest_key_size_bytes);
@@ -1206,7 +1207,7 @@
  * element key derivation or key agreement operation
  *
  * Since many key derivation algorithms require multiple parameters, it is
- * expeced that this function may be called multiple times for the same
+ * expected that this function may be called multiple times for the same
  * operation, each with a different algorithm-specific `collateral_id`
  *
  * \param[in,out] op_context    A hardware-specific structure containing any
@@ -1364,20 +1365,22 @@
  *
  * \return #PSA_SUCCESS
  *         The driver was successfully registered. Applications can now
- *         use \p lifetime to access keys through the methods passed to
+ *         use \p location to access keys through the methods passed to
  *         this function.
  * \return #PSA_ERROR_BAD_STATE
  *         This function was called after the initialization of the
  *         cryptography module, and this implementation does not support
  *         driver registration at this stage.
  * \return #PSA_ERROR_ALREADY_EXISTS
- *         There is already a registered driver for this value of \p lifetime.
+ *         There is already a registered driver for this value of \p location.
  * \return #PSA_ERROR_INVALID_ARGUMENT
- *         \p lifetime is a reserved value.
+ *         \p location is a reserved value.
  * \return #PSA_ERROR_NOT_SUPPORTED
  *         `methods->hal_version` is not supported by this implementation.
  * \return #PSA_ERROR_INSUFFICIENT_MEMORY
  * \return #PSA_ERROR_NOT_PERMITTED
+ * \return #PSA_ERROR_STORAGE_FAILURE
+ * \return #PSA_ERROR_DATA_CORRUPT
  */
 psa_status_t psa_register_se_driver(
     psa_key_location_t location,
diff --git a/third_party/mbedtls/repo/include/psa/crypto_sizes.h b/third_party/mbedtls/repo/include/psa/crypto_sizes.h
index 3df01b2..e2ae596 100644
--- a/third_party/mbedtls/repo/include/psa/crypto_sizes.h
+++ b/third_party/mbedtls/repo/include/psa/crypto_sizes.h
@@ -65,11 +65,9 @@
  *
  * \return The hash size for the specified hash algorithm.
  *         If the hash algorithm is not recognized, return 0.
- *         An implementation may return either 0 or the correct size
- *         for a hash algorithm that it recognizes, but does not support.
  */
-#define PSA_HASH_SIZE(alg)                                      \
-    (                                                           \
+#define PSA_HASH_LENGTH(alg)                                        \
+    (                                                               \
         PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD2 ? 16 :            \
         PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD4 ? 16 :            \
         PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16 :            \
@@ -87,18 +85,51 @@
         PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 :       \
         0)
 
+/** The input block size of a hash algorithm, in bytes.
+ *
+ * Hash algorithms process their input data in blocks. Hash operations will
+ * retain any partial blocks until they have enough input to fill the block or
+ * until the operation is finished.
+ * This affects the output from psa_hash_suspend().
+ *
+ * \param alg   A hash algorithm (\c PSA_ALG_XXX value such that
+ *              PSA_ALG_IS_HASH(\p alg) is true).
+ *
+ * \return      The block size in bytes for the specified hash algorithm.
+ *              If the hash algorithm is not recognized, return 0.
+ *              An implementation can return either 0 or the correct size for a
+ *              hash algorithm that it recognizes, but does not support.
+ */
+#define PSA_HASH_BLOCK_LENGTH(alg)                                  \
+    (                                                               \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD2 ? 16 :            \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD4 ? 64 :            \
+        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)
+
 /** \def PSA_HASH_MAX_SIZE
  *
  * Maximum size of a hash.
  *
- * This macro must expand to a compile-time constant integer. This value
- * should be the maximum size of a hash supported by the implementation,
- * in bytes, and must be no smaller than this maximum.
+ * 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,
  * 136 bytes for HMAC-SHA3-256, 104 bytes for SHA3-384, 72 bytes for
  * HMAC-SHA3-512. */
-#if defined(MBEDTLS_SHA512_C)
+#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
@@ -110,9 +141,8 @@
  *
  * Maximum size of a MAC.
  *
- * This macro must expand to a compile-time constant integer. This value
- * should be the maximum size of a MAC supported by the implementation,
- * in bytes, and must be no smaller than this maximum.
+ * This macro expands to a compile-time constant integer. This value
+ * is the maximum size of a MAC in bytes.
  */
 /* All non-HMAC MACs have a maximum size that's smaller than the
  * minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */
@@ -121,25 +151,37 @@
  */
 #define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE
 
-/** The tag size for an AEAD algorithm, in bytes.
+/** The length of a tag for an AEAD algorithm, in bytes.
  *
+ * This macro can be used to allocate a buffer of sufficient size to store the
+ * tag output from psa_aead_finish().
+ *
+ * See also #PSA_AEAD_TAG_MAX_SIZE.
+ *
+ * \param key_type            The type of the AEAD key.
+ * \param key_bits            The size of the AEAD key in bits.
  * \param alg                 An AEAD algorithm
  *                            (\c PSA_ALG_XXX value such that
  *                            #PSA_ALG_IS_AEAD(\p alg) is true).
  *
- * \return                    The tag size for the specified algorithm.
+ * \return                    The tag length for the specified algorithm and key.
  *                            If the AEAD algorithm does not have an identified
  *                            tag that can be distinguished from the rest of
  *                            the ciphertext, return 0.
- *                            If the AEAD algorithm is not recognized, return 0.
- *                            An implementation may return either 0 or a
- *                            correct size for an AEAD algorithm that it
- *                            recognizes, but does not support.
+ *                            If the key type or AEAD algorithm is not
+ *                            recognized, or the parameters are incompatible,
+ *                            return 0.
  */
-#define PSA_AEAD_TAG_LENGTH(alg)                                        \
-    (PSA_ALG_IS_AEAD(alg) ?                                             \
-     (((alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >> PSA_AEAD_TAG_LENGTH_OFFSET) : \
-     0)
+#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))
+
+/** 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
 
 /* The maximum size of an RSA key on this implementation, in bits.
  * This is a vendor-specific macro.
@@ -188,10 +230,11 @@
 #define PSA_VENDOR_ECC_MAX_CURVE_BITS 0
 #endif
 
-/** \def PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN
+/** This macro returns the maximum supported length of the PSK for the
+ * TLS-1.2 PSK-to-MS key derivation
+ * (#PSA_ALG_TLS12_PSK_TO_MS(\c hash_alg)).
  *
- * This macro returns the maximum length of the PSK supported
- * by the TLS-1.2 PSK-to-MS key derivation.
+ * The maximum supported length does not depend on the chosen hash algorithm.
  *
  * Quoting RFC 4279, Sect 5.3:
  * TLS implementations supporting these ciphersuites MUST support
@@ -200,17 +243,21 @@
  * keys is RECOMMENDED.
  *
  * Therefore, no implementation should define a value smaller than 64
- * for #PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN.
+ * for #PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE.
  */
-#define PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN 128
+#define PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE 128
 
-/** The maximum size of a block cipher supported by the implementation. */
-#define PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE 16
+/** The maximum size of a block cipher. */
+#define PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE 16
 
 /** The size of the output of psa_mac_sign_finish(), in bytes.
  *
  * This is also the MAC size that psa_mac_verify_finish() expects.
  *
+ * \warning This macro may evaluate its arguments multiple times or
+ *          zero times, so you should not pass arguments that contain
+ *          side effects.
+ *
  * \param key_type      The type of the MAC key.
  * \param key_bits      The size of the MAC key in bits.
  * \param alg           A MAC algorithm (\c PSA_ALG_XXX value such that
@@ -224,10 +271,10 @@
  * \return              Unspecified if the key parameters are not consistent
  *                      with the algorithm.
  */
-#define PSA_MAC_FINAL_SIZE(key_type, key_bits, alg)                     \
-    ((alg) & PSA_ALG_MAC_TRUNCATION_MASK ? PSA_MAC_TRUNCATED_LENGTH(alg) : \
-     PSA_ALG_IS_HMAC(alg) ? PSA_HASH_SIZE(PSA_ALG_HMAC_GET_HASH(alg)) : \
-     PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) : \
+#define PSA_MAC_LENGTH(key_type, key_bits, alg)                                   \
+    ((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))
 
 /** The maximum size of the output of psa_aead_encrypt(), in bytes.
@@ -237,6 +284,14 @@
  * insufficient buffer size. Depending on the algorithm, the actual size of
  * the ciphertext may be smaller.
  *
+ * See also #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p plaintext_length).
+ *
+ * \warning This macro may evaluate its arguments multiple times or
+ *          zero times, so you should not pass arguments that contain
+ *          side effects.
+ *
+ * \param key_type            A symmetric key type that is
+ *                            compatible with algorithm \p alg.
  * \param alg                 An AEAD algorithm
  *                            (\c PSA_ALG_XXX value such that
  *                            #PSA_ALG_IS_AEAD(\p alg) is true).
@@ -244,16 +299,37 @@
  *
  * \return                    The AEAD ciphertext size for the specified
  *                            algorithm.
- *                            If the AEAD algorithm is not recognized, return 0.
- *                            An implementation may return either 0 or a
- *                            correct size for an AEAD algorithm that it
- *                            recognizes, but does not support.
+ *                            If the key type or AEAD algorithm is not
+ *                            recognized, or the parameters are incompatible,
+ *                            return 0.
  */
-#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_length)       \
-    (PSA_AEAD_TAG_LENGTH(alg) != 0 ?                              \
-     (plaintext_length) + PSA_AEAD_TAG_LENGTH(alg) :              \
+#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)
 
+/** A sufficient output buffer size for psa_aead_encrypt(), for any of the
+ *  supported key types and AEAD algorithms.
+ *
+ * If the size of the ciphertext buffer is at least this large, it is guaranteed
+ * that psa_aead_encrypt() will not fail due to an insufficient buffer size.
+ *
+ * \note This macro returns a compile-time constant if its arguments are
+ *       compile-time constants.
+ *
+ * See also #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\p key_type, \p alg,
+ * \p plaintext_length).
+ *
+ * \param plaintext_length    Size of the plaintext in bytes.
+ *
+ * \return                    A sufficient output buffer size for any of the
+ *                            supported key types and AEAD algorithms.
+ *
+ */
+#define PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(plaintext_length)          \
+    ((plaintext_length) + PSA_AEAD_TAG_MAX_SIZE)
+
+
 /** The maximum size of the output of psa_aead_decrypt(), in bytes.
  *
  * If the size of the plaintext buffer is at least this large, it is
@@ -261,6 +337,14 @@
  * insufficient buffer size. Depending on the algorithm, the actual size of
  * the plaintext may be smaller.
  *
+ * See also #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p ciphertext_length).
+ *
+ * \warning This macro may evaluate its arguments multiple times or
+ *          zero times, so you should not pass arguments that contain
+ *          side effects.
+ *
+ * \param key_type            A symmetric key type that is
+ *                            compatible with algorithm \p alg.
  * \param alg                 An AEAD algorithm
  *                            (\c PSA_ALG_XXX value such that
  *                            #PSA_ALG_IS_AEAD(\p alg) is true).
@@ -268,16 +352,84 @@
  *
  * \return                    The AEAD ciphertext size for the specified
  *                            algorithm.
- *                            If the AEAD algorithm is not recognized, return 0.
- *                            An implementation may return either 0 or a
- *                            correct size for an AEAD algorithm that it
- *                            recognizes, but does not support.
+ *                            If the key type or AEAD algorithm is not
+ *                            recognized, or the parameters are incompatible,
+ *                            return 0.
  */
-#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length)      \
-    (PSA_AEAD_TAG_LENGTH(alg) != 0 ?                              \
-     (ciphertext_length) - PSA_AEAD_TAG_LENGTH(alg) :             \
+#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg, ciphertext_length) \
+    (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)
 
+/** A sufficient output buffer size for psa_aead_decrypt(), for any of the
+ *  supported key types and AEAD algorithms.
+ *
+ * If the size of the plaintext buffer is at least this large, it is guaranteed
+ * that psa_aead_decrypt() will not fail due to an insufficient buffer size.
+ *
+ * \note This macro returns a compile-time constant if its arguments are
+ *       compile-time constants.
+ *
+ * See also #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\p key_type, \p alg,
+ * \p ciphertext_length).
+ *
+ * \param ciphertext_length   Size of the ciphertext in bytes.
+ *
+ * \return                    A sufficient output buffer size for any of the
+ *                            supported key types and AEAD algorithms.
+ *
+ */
+#define PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(ciphertext_length)     \
+     (ciphertext_length)
+
+/** The default nonce size for an AEAD algorithm, in bytes.
+ *
+ * This macro can be used to allocate a buffer of sufficient size to
+ * store the nonce output from #psa_aead_generate_nonce().
+ *
+ * See also #PSA_AEAD_NONCE_MAX_SIZE.
+ *
+ * \note This is not the maximum size of nonce supported as input to
+ *       #psa_aead_set_nonce(), #psa_aead_encrypt() or #psa_aead_decrypt(),
+ *       just the default size that is generated by #psa_aead_generate_nonce().
+ *
+ * \warning This macro may evaluate its arguments multiple times or
+ *          zero times, so you should not pass arguments that contain
+ *          side effects.
+ *
+ * \param key_type  A symmetric key type that is compatible with
+ *                  algorithm \p alg.
+ *
+ * \param alg       An AEAD algorithm (\c PSA_ALG_XXX value such that
+ *                  #PSA_ALG_IS_AEAD(\p alg) is true).
+ *
+ * \return The default nonce size for the specified key type and algorithm.
+ *         If the key type or AEAD algorithm is not recognized,
+ *         or the parameters are incompatible, return 0.
+ */
+#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 : \
+     (key_type) == PSA_KEY_TYPE_CHACHA20 && \
+          MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CHACHA20_POLY1305) ? 12 : \
+     0)
+
+/** The maximum default nonce size among all supported pairs of key types and
+ *  AEAD algorithms, in bytes.
+ *
+ * This is equal to or greater than any value that #PSA_AEAD_NONCE_LENGTH()
+ * may return.
+ *
+ * \note This is not the maximum size of nonce supported as input to
+ *       #psa_aead_set_nonce(), #psa_aead_encrypt() or #psa_aead_decrypt(),
+ *       just the largest size that may be generated by
+ *       #psa_aead_generate_nonce().
+ */
+#define PSA_AEAD_NONCE_MAX_SIZE 13
+
 /** A sufficient output buffer size for psa_aead_update().
  *
  * If the size of the output buffer is at least this large, it is
@@ -285,6 +437,14 @@
  * insufficient buffer size. The actual size of the output may be smaller
  * in any given call.
  *
+ * See also #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length).
+ *
+ * \warning This macro may evaluate its arguments multiple times or
+ *          zero times, so you should not pass arguments that contain
+ *          side effects.
+ *
+ * \param key_type            A symmetric key type that is
+ *                            compatible with algorithm \p alg.
  * \param alg                 An AEAD algorithm
  *                            (\c PSA_ALG_XXX value such that
  *                            #PSA_ALG_IS_AEAD(\p alg) is true).
@@ -292,19 +452,33 @@
  *
  * \return                    A sufficient output buffer size for the specified
  *                            algorithm.
- *                            If the AEAD algorithm is not recognized, return 0.
- *                            An implementation may return either 0 or a
- *                            correct size for an AEAD algorithm that it
- *                            recognizes, but does not support.
+ *                            If the key type or AEAD algorithm is not
+ *                            recognized, or the parameters are incompatible,
+ *                            return 0.
  */
 /* For all the AEAD modes defined in this specification, it is possible
  * to emit output without delay. However, hardware may not always be
  * capable of this. So for modes based on a block cipher, allow the
  * implementation to delay the output until it has a full block. */
-#define PSA_AEAD_UPDATE_OUTPUT_SIZE(alg, input_length)                  \
-    (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ?                             \
-     PSA_ROUND_UP_TO_MULTIPLE(PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE, (input_length)) : \
-     (input_length))
+#define PSA_AEAD_UPDATE_OUTPUT_SIZE(key_type, alg, input_length)                             \
+    (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ?                                             \
+         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)
+
+/** A sufficient output buffer size for psa_aead_update(), for any of the
+ *  supported key types and AEAD algorithms.
+ *
+ * If the size of the output buffer is at least this large, it is guaranteed
+ * that psa_aead_update() will not fail due to an insufficient buffer size.
+ *
+ * See also #PSA_AEAD_UPDATE_OUTPUT_SIZE(\p key_type, \p alg, \p input_length).
+ *
+ * \param input_length      Size of the input in bytes.
+ */
+#define PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(input_length)                           \
+    (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, (input_length)))
 
 /** A sufficient ciphertext buffer size for psa_aead_finish().
  *
@@ -313,22 +487,33 @@
  * insufficient ciphertext buffer size. The actual size of the output may
  * be smaller in any given call.
  *
+ * See also #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE.
+ *
+ * \param key_type            A symmetric key type that is
+                              compatible with algorithm \p alg.
  * \param alg                 An AEAD algorithm
  *                            (\c PSA_ALG_XXX value such that
  *                            #PSA_ALG_IS_AEAD(\p alg) is true).
  *
  * \return                    A sufficient ciphertext buffer size for the
  *                            specified algorithm.
- *                            If the AEAD algorithm is not recognized, return 0.
- *                            An implementation may return either 0 or a
- *                            correct size for an AEAD algorithm that it
- *                            recognizes, but does not support.
+ *                            If the key type or AEAD algorithm is not
+ *                            recognized, or the parameters are incompatible,
+ *                            return 0.
  */
-#define PSA_AEAD_FINISH_OUTPUT_SIZE(alg)                                \
-    (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ?                             \
-     PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE :                                  \
+#define PSA_AEAD_FINISH_OUTPUT_SIZE(key_type, alg) \
+    (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 &&  \
+         PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ?    \
+         PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \
      0)
 
+/** A sufficient ciphertext buffer size for psa_aead_finish(), for any of the
+ *  supported key types and AEAD algorithms.
+ *
+ * See also #PSA_AEAD_FINISH_OUTPUT_SIZE(\p key_type, \p alg).
+ */
+#define PSA_AEAD_FINISH_OUTPUT_MAX_SIZE     (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE)
+
 /** A sufficient plaintext buffer size for psa_aead_verify().
  *
  * If the size of the plaintext buffer is at least this large, it is
@@ -336,25 +521,36 @@
  * insufficient plaintext buffer size. The actual size of the output may
  * be smaller in any given call.
  *
+ * See also #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE.
+ *
+ * \param key_type            A symmetric key type that is
+ *                            compatible with algorithm \p alg.
  * \param alg                 An AEAD algorithm
  *                            (\c PSA_ALG_XXX value such that
  *                            #PSA_ALG_IS_AEAD(\p alg) is true).
  *
  * \return                    A sufficient plaintext buffer size for the
  *                            specified algorithm.
- *                            If the AEAD algorithm is not recognized, return 0.
- *                            An implementation may return either 0 or a
- *                            correct size for an AEAD algorithm that it
- *                            recognizes, but does not support.
+ *                            If the key type or AEAD algorithm is not
+ *                            recognized, or the parameters are incompatible,
+ *                            return 0.
  */
-#define PSA_AEAD_VERIFY_OUTPUT_SIZE(alg)                                \
-    (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ?                             \
-     PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE :                                  \
+#define PSA_AEAD_VERIFY_OUTPUT_SIZE(key_type, alg) \
+    (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 &&  \
+         PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ?    \
+         PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \
      0)
 
+/** A sufficient plaintext buffer size for psa_aead_verify(), for any of the
+ *  supported key types and AEAD algorithms.
+ *
+ * See also #PSA_AEAD_VERIFY_OUTPUT_SIZE(\p key_type, \p alg).
+ */
+#define PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE     (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE)
+
 #define PSA_RSA_MINIMUM_PADDING_SIZE(alg)                         \
     (PSA_ALG_IS_RSA_OAEP(alg) ?                                   \
-     2 * PSA_HASH_SIZE(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 :      \
+     2 * PSA_HASH_LENGTH(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 :    \
      11 /*PKCS#1v1.5*/)
 
 /**
@@ -388,9 +584,8 @@
  *         a buffer size in bytes that guarantees that
  *         psa_sign_hash() 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 a valid combination that is not supported,
+ *         return either a sensible size or 0.
  *         If the parameters are not valid, the
  *         return value is unspecified.
  */
@@ -406,9 +601,8 @@
  *
  * Maximum size of an asymmetric signature.
  *
- * This macro must expand to a compile-time constant integer. This value
- * should be the maximum size of a signature supported by the implementation,
- * in bytes, and must be no smaller than this maximum.
+ * 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 ? \
@@ -435,9 +629,8 @@
  *         a buffer size in bytes that guarantees that
  *         psa_asymmetric_encrypt() 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 a valid combination that is not supported,
+ *         return either a sensible size or 0.
  *         If the parameters are not valid, the
  *         return value is unspecified.
  */
@@ -446,6 +639,15 @@
      ((void)alg, PSA_BITS_TO_BYTES(key_bits)) :                         \
      0)
 
+/** A sufficient output buffer size for psa_asymmetric_encrypt(), for any
+ *  supported asymmetric encryption.
+ *
+ * See also #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\p key_type, \p key_bits, \p alg).
+ */
+/* This macro assumes that RSA is the only supported asymmetric encryption. */
+#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_MAX_SIZE          \
+    (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS))
+
 /** Sufficient output buffer size for psa_asymmetric_decrypt().
  *
  * This macro returns a sufficient buffer size for a plaintext produced using
@@ -466,9 +668,8 @@
  *         a buffer size in bytes that guarantees that
  *         psa_asymmetric_decrypt() 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 a valid combination that is not supported,
+ *         return either a sensible size or 0.
  *         If the parameters are not valid, the
  *         return value is unspecified.
  */
@@ -477,6 +678,16 @@
      PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) :  \
      0)
 
+/** A sufficient output buffer size for psa_asymmetric_decrypt(), for any
+ *  supported asymmetric decryption.
+ *
+ * This macro assumes that RSA is the only supported asymmetric encryption.
+ *
+ * See also #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\p key_type, \p key_bits, \p alg).
+ */
+#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_MAX_SIZE          \
+    (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS))
+
 /* Maximum size of the ASN.1 encoding of an INTEGER with the specified
  * number of bits.
  *
@@ -587,12 +798,13 @@
 #define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits)   \
     (PSA_BITS_TO_BYTES(key_bits))
 
-/** Sufficient output buffer size for psa_export_key() or psa_export_public_key().
+/** Sufficient output buffer size for psa_export_key() or
+ * psa_export_public_key().
  *
  * This macro returns a compile-time constant if its arguments are
  * compile-time constants.
  *
- * \warning This function may call its arguments multiple times or
+ * \warning This macro may evaluate its arguments multiple times or
  *          zero times, so you should not pass arguments that contain
  *          side effects.
  *
@@ -605,7 +817,7 @@
  * if (status != PSA_SUCCESS) handle_error(...);
  * psa_key_type_t key_type = psa_get_key_type(&attributes);
  * size_t key_bits = psa_get_key_bits(&attributes);
- * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits);
+ * size_t buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits);
  * psa_reset_key_attributes(&attributes);
  * uint8_t *buffer = malloc(buffer_size);
  * if (buffer == NULL) handle_error(...);
@@ -614,18 +826,46 @@
  * if (status != PSA_SUCCESS) handle_error(...);
  * \endcode
  *
- * For psa_export_public_key(), calculate the buffer size from the
- * public key type. You can use the macro #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR
- * to convert a key pair type to the corresponding public key type.
+ * \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_export_key() or psa_export_public_key() will not fail with
+ *         #PSA_ERROR_BUFFER_TOO_SMALL.
+ *         If the parameters are a valid combination that is not supported,
+ *         return either a sensible size or 0.
+ *         If the parameters are not valid, the return value is unspecified.
+ */
+#define PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits)                                              \
+    (PSA_KEY_TYPE_IS_UNSTRUCTURED(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)
+
+/** Sufficient output buffer size for psa_export_public_key().
+ *
+ * This macro returns a compile-time constant if its arguments are
+ * compile-time constants.
+ *
+ * \warning This macro may evaluate its arguments multiple times or
+ *          zero times, so you should not pass arguments that contain
+ *          side effects.
+ *
+ * The following code illustrates how to allocate enough memory to export
+ * a public key by querying the key type and size at runtime.
  * \code{c}
  * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
  * psa_status_t status;
  * status = psa_get_key_attributes(key, &attributes);
  * if (status != PSA_SUCCESS) handle_error(...);
  * psa_key_type_t key_type = psa_get_key_type(&attributes);
- * psa_key_type_t public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type);
  * size_t key_bits = psa_get_key_bits(&attributes);
- * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(public_key_type, key_bits);
+ * size_t buffer_size = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, key_bits);
  * psa_reset_key_attributes(&attributes);
  * uint8_t *buffer = malloc(buffer_size);
  * if (buffer == NULL) handle_error(...);
@@ -634,71 +874,96 @@
  * if (status != PSA_SUCCESS) handle_error(...);
  * \endcode
  *
- * \param key_type  A supported key type.
- * \param key_bits  The size of the key in bits.
+ * \param key_type      A public key or key pair 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_sign_hash() 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.
+ * \return              If the parameters are valid and supported, return
+ *                      a buffer size in bytes that guarantees that
+ *                      psa_export_public_key() will not fail with
+ *                      #PSA_ERROR_BUFFER_TOO_SMALL.
+ *                      If the parameters are a valid combination that is not
+ *                      supported, return either a sensible size or 0.
+ *                      If the parameters are not valid,
+ *                      the return value is unspecified.
+ *
+ *                      If the parameters are valid and supported,
+ *                      return the same result as
+ *                      #PSA_EXPORT_KEY_OUTPUT_SIZE(
+ *                          \p #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\p key_type),
+ *                          \p key_bits).
  */
-#define PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits)                     \
-    (PSA_KEY_TYPE_IS_UNSTRUCTURED(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) : \
+#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)
 
-/** The default nonce size for an AEAD algorithm, in bytes.
+/** Sufficient buffer size for exporting any asymmetric key pair.
  *
- * This macro can be used to allocate a buffer of sufficient size to
- * store the nonce output from #psa_aead_generate_nonce().
+ * This macro expands to a compile-time constant integer. This value is
+ * a sufficient buffer size when calling psa_export_key() to export any
+ * asymmetric key pair, regardless of the exact key type and key size.
  *
- * See also #PSA_AEAD_NONCE_MAX_SIZE.
+ * 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))
+
+/** Sufficient buffer size for exporting any asymmetric public key.
  *
- * \note This is not the maximum size of nonce supported as input to #psa_aead_set_nonce(),
- *       #psa_aead_encrypt() or #psa_aead_decrypt(), just the default size that is generated by
- *       #psa_aead_generate_nonce().
+ * This macro expands to a compile-time constant integer. This value is
+ * a sufficient buffer size when calling psa_export_key() or
+ * psa_export_public_key() to export any asymmetric public key,
+ * regardless of the exact key type and key size.
+ *
+ * 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))
+
+/** Sufficient output buffer size for psa_raw_key_agreement().
+ *
+ * This macro returns a compile-time constant if its arguments are
+ * compile-time constants.
  *
  * \warning This macro may evaluate its arguments multiple times or
  *          zero times, so you should not pass arguments that contain
  *          side effects.
  *
- * \param key_type  A symmetric key type that is compatible with algorithm \p alg.
+ * See also #PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE.
  *
- * \param alg       An AEAD algorithm (\c PSA_ALG_XXX value such that #PSA_ALG_IS_AEAD(\p alg) is true).
+ * \param key_type      A supported key type.
+ * \param key_bits      The size of the key in bits.
  *
- * \return The default nonce size for the specified key type and algorithm.
- *         If the key type or AEAD algorithm is not recognized,
- *         or the parameters are incompatible, return 0.
- *         An implementation can return either 0 or a correct size for a key type
- *         and AEAD algorithm that it recognizes, but does not support.
+ * \return              If the parameters are valid and supported, return
+ *                      a buffer size in bytes that guarantees that
+ *                      psa_raw_key_agreement() will not fail with
+ *                      #PSA_ERROR_BUFFER_TOO_SMALL.
+ *                      If the parameters are a valid combination that
+ *                      is not supported, return either a sensible size or 0.
+ *                      If the parameters are not valid,
+ *                      the return value is unspecified.
  */
-#define PSA_AEAD_NONCE_LENGTH(key_type, alg) \
-    (PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) == 16 && \
-         (PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(alg) == PSA_ALG_CCM || \
-          PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(alg) == PSA_ALG_GCM) ? 12 : \
-     (key_type) == PSA_KEY_TYPE_CHACHA20 && \
-          PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(alg) == PSA_ALG_CHACHA20_POLY1305 ? 12 : \
+/* 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)
 
-/** The maximum default nonce size among all supported pairs of key types and AEAD algorithms, in bytes.
+/** Maximum size of the output from psa_raw_key_agreement().
  *
- * This is equal to or greater than any value that #PSA_AEAD_NONCE_LENGTH() may return.
+ * This macro expands to a compile-time constant integer. This value is the
+ * maximum size of the output any raw key agreement algorithm, in bytes.
  *
- * \note This is not the maximum size of nonce supported as input to #psa_aead_set_nonce(),
- *       #psa_aead_encrypt() or #psa_aead_decrypt(), just the largest size that may be generated by
- *       #psa_aead_generate_nonce().
+ * See also #PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(\p key_type, \p key_bits).
  */
-#define PSA_AEAD_NONCE_MAX_SIZE 12
+#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE   \
+    (PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS))
 
 /** The default IV size for a cipher algorithm, in bytes.
  *
@@ -723,17 +988,15 @@
  *         If the algorithm does not use an IV, return 0.
  *         If the key type or cipher algorithm is not recognized,
  *         or the parameters are incompatible, return 0.
- *         An implementation can return either 0 or a correct size for a key type
- *         and cipher algorithm that it recognizes, but does not support.
  */
 #define PSA_CIPHER_IV_LENGTH(key_type, alg) \
-    (PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) > 1 && \
+    (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) > 1 && \
         ((alg) == PSA_ALG_CTR || \
          (alg) == PSA_ALG_CFB || \
          (alg) == PSA_ALG_OFB || \
          (alg) == PSA_ALG_XTS || \
          (alg) == PSA_ALG_CBC_NO_PADDING || \
-         (alg) == PSA_ALG_CBC_PKCS7) ? PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) : \
+         (alg) == PSA_ALG_CBC_PKCS7) ? PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \
      (key_type) == PSA_KEY_TYPE_CHACHA20 && \
          (alg) == PSA_ALG_STREAM_CIPHER ? 12 : \
      0)
@@ -744,4 +1007,165 @@
  */
 #define PSA_CIPHER_IV_MAX_SIZE 16
 
+/** The maximum size of the output of psa_cipher_encrypt(), in bytes.
+ *
+ * If the size of the output buffer is at least this large, it is guaranteed
+ * that psa_cipher_encrypt() will not fail due to an insufficient buffer size.
+ * Depending on the algorithm, the actual size of the output might be smaller.
+ *
+ * See also #PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(\p input_length).
+ *
+ * \warning This macro may evaluate its arguments multiple times or
+ *          zero times, so you should not pass arguments that contain
+ *          side effects.
+ *
+ * \param key_type      A symmetric key type that is compatible with algorithm
+ *                      alg.
+ * \param alg           A cipher algorithm (\c PSA_ALG_XXX value such that
+ *                      #PSA_ALG_IS_CIPHER(\p alg) is true).
+ * \param input_length  Size of the input in bytes.
+ *
+ * \return              A sufficient output size for the specified key type and
+ *                      algorithm. If the key type or cipher algorithm is not
+ *                      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))
+
+/** A sufficient output buffer size for psa_cipher_encrypt(), for any of the
+ *  supported key types and cipher algorithms.
+ *
+ * If the size of the output buffer is at least this large, it is guaranteed
+ * that psa_cipher_encrypt() will not fail due to an insufficient buffer size.
+ *
+ * See also #PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(\p key_type, \p alg, \p input_length).
+ *
+ * \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) +                             \
+     PSA_CIPHER_IV_MAX_SIZE)
+
+/** The maximum size of the output of psa_cipher_decrypt(), in bytes.
+ *
+ * If the size of the output buffer is at least this large, it is guaranteed
+ * that psa_cipher_decrypt() will not fail due to an insufficient buffer size.
+ * Depending on the algorithm, the actual size of the output might be smaller.
+ *
+ * See also #PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(\p input_length).
+ *
+ * \param key_type      A symmetric key type that is compatible with algorithm
+ *                      alg.
+ * \param alg           A cipher algorithm (\c PSA_ALG_XXX value such that
+ *                      #PSA_ALG_IS_CIPHER(\p alg) is true).
+ * \param input_length  Size of the input in bytes.
+ *
+ * \return              A sufficient output size for the specified key type and
+ *                      algorithm. If the key type or cipher algorithm is not
+ *                      recognized, or the parameters are incompatible,
+ *                      return 0.
+ */
+#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)
+
+/** A sufficient output buffer size for psa_cipher_decrypt(), for any of the
+ *  supported key types and cipher algorithms.
+ *
+ * If the size of the output buffer is at least this large, it is guaranteed
+ * that psa_cipher_decrypt() will not fail due to an insufficient buffer size.
+ *
+ * See also #PSA_CIPHER_DECRYPT_OUTPUT_SIZE(\p key_type, \p alg, \p input_length).
+ *
+ * \param input_length  Size of the input in bytes.
+ */
+#define PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(input_length)    \
+    (input_length)
+
+/** A sufficient output buffer size for psa_cipher_update().
+ *
+ * If the size of the output buffer is at least this large, it is guaranteed
+ * that psa_cipher_update() will not fail due to an insufficient buffer size.
+ * The actual size of the output might be smaller in any given call.
+ *
+ * See also #PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(\p input_length).
+ *
+ * \param key_type      A symmetric key type that is compatible with algorithm
+ *                      alg.
+ * \param alg           A cipher algorithm (PSA_ALG_XXX value such that
+ *                      #PSA_ALG_IS_CIPHER(\p alg) is true).
+ * \param input_length  Size of the input in bytes.
+ *
+ * \return              A sufficient output size for the specified key type and
+ *                      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)
+
+/** A sufficient output buffer size for psa_cipher_update(), for any of the
+ *  supported key types and cipher algorithms.
+ *
+ * If the size of the output buffer is at least this large, it is guaranteed
+ * that psa_cipher_update() will not fail due to an insufficient buffer size.
+ *
+ * See also #PSA_CIPHER_UPDATE_OUTPUT_SIZE(\p key_type, \p alg, \p input_length).
+ *
+ * \param input_length  Size of the input in bytes.
+ */
+#define PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(input_length)     \
+    (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, input_length))
+
+/** A sufficient ciphertext buffer size for psa_cipher_finish().
+ *
+ * If the size of the ciphertext buffer is at least this large, it is
+ * guaranteed that psa_cipher_finish() will not fail due to an insufficient
+ * ciphertext buffer size. The actual size of the output might be smaller in
+ * any given call.
+ *
+ * See also #PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE().
+ *
+ * \param key_type      A symmetric key type that is compatible with algorithm
+ *                      alg.
+ * \param alg           A cipher algorithm (PSA_ALG_XXX value such that
+ *                      #PSA_ALG_IS_CIPHER(\p alg) is true).
+ * \return              A sufficient output size for the specified key type and
+ *                      algorithm. If the key type or cipher algorithm is not
+ *                      recognized, or the parameters are incompatible, return 0.
+ */
+#define PSA_CIPHER_FINISH_OUTPUT_SIZE(key_type, alg)    \
+    (PSA_ALG_IS_CIPHER(alg) ?                           \
+     (alg == PSA_ALG_CBC_PKCS7 ?                        \
+      PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) :         \
+      0) :                                              \
+     0)
+
+/** A sufficient ciphertext buffer size for psa_cipher_finish(), for any of the
+ *  supported key types and cipher algorithms.
+ *
+ * See also #PSA_CIPHER_FINISH_OUTPUT_SIZE(\p key_type, \p alg).
+ */
+#define PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE           \
+    (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE)
+
 #endif /* PSA_CRYPTO_SIZES_H */
diff --git a/third_party/mbedtls/repo/include/psa/crypto_struct.h b/third_party/mbedtls/repo/include/psa/crypto_struct.h
index 6a018e1..23a02a5 100644
--- a/third_party/mbedtls/repo/include/psa/crypto_struct.h
+++ b/third_party/mbedtls/repo/include/psa/crypto_struct.h
@@ -15,12 +15,20 @@
  *
  * <h3>Design notes about multipart operation structures</h3>
  *
- * Each multipart operation structure contains a `psa_algorithm_t alg`
- * field which indicates which specific algorithm the structure is for.
- * When the structure is not in use, `alg` is 0. Most of the structure
- * consists of a union which is discriminated by `alg`.
+ * For multipart operations without driver delegation support, each multipart
+ * operation structure contains a `psa_algorithm_t alg` field which indicates
+ * which specific algorithm the structure is for. When the structure is not in
+ * use, `alg` is 0. Most of the structure consists of a union which is
+ * discriminated by `alg`.
  *
- * Note that when `alg` is 0, the content of other fields is undefined.
+ * For multipart operations with driver delegation support, each multipart
+ * operation structure contains an `unsigned int id` field indicating which
+ * driver got assigned to do the operation. When the structure is not in use,
+ * 'id' is 0. The structure contains also a driver context which is the union
+ * of the contexts of all drivers able to handle the type of multipart
+ * operation.
+ *
+ * Note that when `alg` or `id` is 0, the content of other fields is undefined.
  * In particular, it is not guaranteed that a freshly-initialized structure
  * is all-zero: we initialize structures to something like `{0, 0}`, which
  * is only guaranteed to initializes the first member of the union;
@@ -65,56 +73,23 @@
 #include MBEDTLS_CONFIG_FILE
 #endif
 
-#include "mbedtls/cipher.h"
 #include "mbedtls/cmac.h"
 #include "mbedtls/gcm.h"
-#include "mbedtls/md.h"
-#include "mbedtls/md2.h"
-#include "mbedtls/md4.h"
-#include "mbedtls/md5.h"
-#include "mbedtls/ripemd160.h"
-#include "mbedtls/sha1.h"
-#include "mbedtls/sha256.h"
-#include "mbedtls/sha512.h"
 
-typedef struct {
-    /** 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.
-     * ID values are auto-generated in psa_driver_wrappers.h */
-    unsigned int id;
-    /** Context structure for the assigned driver, when id is not zero. */
-    void* ctx;
-} psa_operation_driver_context_t;
+/* 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
 {
-    psa_algorithm_t alg;
-    union
-    {
-        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
-#if defined(MBEDTLS_MD2_C)
-        mbedtls_md2_context md2;
-#endif
-#if defined(MBEDTLS_MD4_C)
-        mbedtls_md4_context md4;
-#endif
-#if defined(MBEDTLS_MD5_C)
-        mbedtls_md5_context md5;
-#endif
-#if defined(MBEDTLS_RIPEMD160_C)
-        mbedtls_ripemd160_context ripemd160;
-#endif
-#if defined(MBEDTLS_SHA1_C)
-        mbedtls_sha1_context sha1;
-#endif
-#if defined(MBEDTLS_SHA256_C)
-        mbedtls_sha256_context sha256;
-#endif
-#if defined(MBEDTLS_SHA512_C)
-        mbedtls_sha512_context sha512;
-#endif
-    } ctx;
+    /** 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.
+     * ID values are auto-generated in psa_driver_wrappers.h.
+     * ID value zero means the context is not valid or not assigned to
+     * any driver (i.e. the driver context is not active, in use). */
+    unsigned int id;
+    psa_driver_hash_context_t ctx;
 };
 
 #define PSA_HASH_OPERATION_INIT {0, {0}}
@@ -124,68 +99,56 @@
     return( v );
 }
 
-#if defined(MBEDTLS_MD_C)
-typedef struct
-{
-        /** The hash context. */
-        struct psa_hash_operation_s hash_ctx;
-        /** The HMAC part of the context. */
-        uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
-} psa_hmac_internal_data;
-#endif /* MBEDTLS_MD_C */
-
-struct psa_mac_operation_s
-{
-    psa_algorithm_t alg;
-    unsigned int key_set : 1;
-    unsigned int iv_required : 1;
-    unsigned int iv_set : 1;
-    unsigned int has_input : 1;
-    unsigned int is_sign : 1;
-    uint8_t mac_size;
-    union
-    {
-        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
-#if defined(MBEDTLS_MD_C)
-        psa_hmac_internal_data hmac;
-#endif
-#if defined(MBEDTLS_CMAC_C)
-        mbedtls_cipher_context_t cmac;
-#endif
-    } ctx;
-};
-
-#define PSA_MAC_OPERATION_INIT {0, 0, 0, 0, 0, 0, 0, {0}}
-static inline struct psa_mac_operation_s psa_mac_operation_init( void )
-{
-    const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT;
-    return( v );
-}
-
 struct psa_cipher_operation_s
 {
-    psa_algorithm_t alg;
-    unsigned int key_set : 1;
+    /** 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.
+     * ID values are auto-generated in psa_crypto_driver_wrappers.h
+     * ID value zero means the context is not valid or not assigned to
+     * any driver (i.e. none of the driver contexts are active). */
+    unsigned int id;
+
     unsigned int iv_required : 1;
     unsigned int iv_set : 1;
-    unsigned int mbedtls_in_use : 1; /* Indicates mbed TLS is handling the operation. */
-    uint8_t iv_size;
-    uint8_t block_size;
-    union
-    {
-        unsigned dummy; /* Enable easier initializing of the union. */
-        mbedtls_cipher_context_t cipher;
-        psa_operation_driver_context_t driver;
-    } ctx;
+
+    uint8_t default_iv_length;
+
+    psa_driver_cipher_context_t ctx;
 };
 
-#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, 0, 0, 0, 0, {0}}
+#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, 0, {0}}
 static inline struct psa_cipher_operation_s psa_cipher_operation_init( void )
 {
     const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT;
     return( v );
 }
 
+/* Include the context definition for the compiled-in drivers for the composite
+ * algorithms. */
+#include "psa/crypto_driver_contexts_composites.h"
+
+struct psa_mac_operation_s
+{
+    /** 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.
+     * ID values are auto-generated in psa_driver_wrappers.h
+     * ID value zero means the context is not valid or not assigned to
+     * any driver (i.e. none of the driver contexts are active). */
+    unsigned int id;
+    uint8_t mac_size;
+    unsigned int is_sign : 1;
+    psa_driver_mac_context_t ctx;
+};
+
+#define PSA_MAC_OPERATION_INIT {0, 0, 0, {0}}
+static inline struct psa_mac_operation_s psa_mac_operation_init( void )
+{
+    const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT;
+    return( v );
+}
+
 struct psa_aead_operation_s
 {
     psa_algorithm_t alg;
@@ -207,14 +170,11 @@
     return( v );
 }
 
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
 typedef struct
 {
     uint8_t *info;
     size_t info_length;
-    psa_hmac_internal_data hmac;
-    uint8_t prk[PSA_HASH_MAX_SIZE];
-    uint8_t output_block[PSA_HASH_MAX_SIZE];
 #if PSA_HASH_MAX_SIZE > 0xff
 #error "PSA_HASH_MAX_SIZE does not fit in uint8_t"
 #endif
@@ -222,17 +182,21 @@
     uint8_t block_number;
     unsigned int state : 2;
     unsigned int info_set : 1;
+    uint8_t output_block[PSA_HASH_MAX_SIZE];
+    uint8_t prk[PSA_HASH_MAX_SIZE];
+    struct psa_mac_operation_s hmac;
 } psa_hkdf_key_derivation_t;
-#endif /* MBEDTLS_MD_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */
 
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
 typedef enum
 {
-    TLS12_PRF_STATE_INIT,       /* no input provided */
-    TLS12_PRF_STATE_SEED_SET,   /* seed has been set */
-    TLS12_PRF_STATE_KEY_SET,    /* key has been set */
-    TLS12_PRF_STATE_LABEL_SET,  /* label has been set */
-    TLS12_PRF_STATE_OUTPUT      /* output has been started */
+    PSA_TLS12_PRF_STATE_INIT,       /* no input provided */
+    PSA_TLS12_PRF_STATE_SEED_SET,   /* seed has been set */
+    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
@@ -250,17 +214,20 @@
 
     psa_tls12_prf_key_derivation_state_t state;
 
+    uint8_t *secret;
+    size_t secret_length;
     uint8_t *seed;
     size_t seed_length;
     uint8_t *label;
     size_t label_length;
-    psa_hmac_internal_data hmac;
+
     uint8_t Ai[PSA_HASH_MAX_SIZE];
 
     /* `HMAC_hash( prk, A(i) + seed )` in the notation of RFC 5246, Sect. 5. */
     uint8_t output_block[PSA_HASH_MAX_SIZE];
 } psa_tls12_prf_key_derivation_t;
-#endif /* MBEDTLS_MD_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) ||
+        * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
 
 struct psa_key_derivation_s
 {
@@ -271,8 +238,11 @@
     {
         /* Make the union non-empty even with no supported algorithms. */
         uint8_t dummy;
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
         psa_hkdf_key_derivation_t 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 tls12_prf;
 #endif
     } ctx;
@@ -421,9 +391,19 @@
     return( attributes->core.lifetime );
 }
 
+static inline void psa_extend_key_usage_flags( psa_key_usage_t *usage_flags )
+{
+    if( *usage_flags & PSA_KEY_USAGE_SIGN_HASH )
+        *usage_flags |= PSA_KEY_USAGE_SIGN_MESSAGE;
+
+    if( *usage_flags & PSA_KEY_USAGE_VERIFY_HASH )
+        *usage_flags |= PSA_KEY_USAGE_VERIFY_MESSAGE;
+}
+
 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->core.policy.usage = usage_flags;
 }
 
diff --git a/third_party/mbedtls/repo/include/psa/crypto_types.h b/third_party/mbedtls/repo/include/psa/crypto_types.h
index 0a2ae54..386c7d7 100644
--- a/third_party/mbedtls/repo/include/psa/crypto_types.h
+++ b/third_party/mbedtls/repo/include/psa/crypto_types.h
@@ -35,6 +35,13 @@
 
 #include "crypto_platform.h"
 
+/* 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 */
+
 #include <stdint.h>
 
 /** \defgroup error Error codes
@@ -115,14 +122,14 @@
  *   whether the key is _volatile_ or _persistent_.
  *   See ::psa_key_persistence_t for more information.
  * - Bits 8-31 (#PSA_KEY_LIFETIME_GET_LOCATION(\c lifetime)):
- *   location indicator. This value indicates where the key is stored
- *   and where operations on the key are performed.
+ *   location indicator. This value indicates which part of the system
+ *   has access to the key material and can perform operations using the key.
  *   See ::psa_key_location_t for more information.
  *
  * Volatile keys are automatically destroyed when the application instance
  * terminates or on a power reset of the device. Persistent keys are
  * preserved until the application explicitly destroys them or until an
- * implementation-specific device management event occurs (for example,
+ * integration-specific device management event occurs (for example,
  * a factory reset).
  *
  * Persistent keys have a key identifier of type #mbedtls_svc_key_id_t.
@@ -131,12 +138,10 @@
  * The application can call psa_open_key() to open a persistent key that
  * it created previously.
  *
- * This specification defines two basic lifetime values:
- * - Keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE are volatile.
- *   All implementations should support this lifetime.
- * - Keys with the lifetime #PSA_KEY_LIFETIME_PERSISTENT are persistent.
- *   All implementations that have access to persistent storage with
- *   appropriate security guarantees should support this lifetime.
+ * The default lifetime of a key is #PSA_KEY_LIFETIME_VOLATILE. The lifetime
+ * #PSA_KEY_LIFETIME_PERSISTENT is supported if persistent storage is
+ * available. Other lifetime values may be supported depending on the
+ * library configuration.
  */
 typedef uint32_t psa_key_lifetime_t;
 
@@ -149,35 +154,21 @@
  * actually affect persistent keys at different levels is outside the
  * scope of the PSA Cryptography specification.
  *
- * This specification defines the following values of persistence levels:
+ * The PSA Cryptography specification defines the following values of
+ * persistence levels:
  * - \c 0 = #PSA_KEY_PERSISTENCE_VOLATILE: volatile key.
  *   A volatile key is automatically destroyed by the implementation when
  *   the application instance terminates. In particular, a volatile key
  *   is automatically destroyed on a power reset of the device.
  * - \c 1 = #PSA_KEY_PERSISTENCE_DEFAULT:
  *   persistent key with a default lifetime.
- *   Implementations should support this value if they support persistent
- *   keys at all.
- *   Applications should use this value if they have no specific needs that
- *   are only met by implementation-specific features.
- * - \c 2-127: persistent key with a PSA-specified lifetime.
- *   The PSA Cryptography specification does not define the meaning of these
- *   values, but other PSA specifications may do so.
- * - \c 128-254: persistent key with a vendor-specified lifetime.
- *   No PSA specification will define the meaning of these values, so
- *   implementations may choose the meaning freely.
- *   As a guideline, higher persistence levels should cause a key to survive
- *   more management events than lower levels.
+ * - \c 2-254: currently not supported by Mbed TLS.
  * - \c 255 = #PSA_KEY_PERSISTENCE_READ_ONLY:
  *   read-only or write-once key.
  *   A key with this persistence level cannot be destroyed.
- *   Implementations that support such keys may either allow their creation
- *   through the PSA Cryptography API, preferably only to applications with
- *   the appropriate privilege, or only expose keys created through
- *   implementation-specific means such as a factory ROM engraving process.
- *   Note that keys that are read-only due to policy restrictions
- *   rather than due to physical limitations should not have this
- *   persistence levels.
+ *   Mbed TLS does not currently offer a way to create such keys, but
+ *   integrations of Mbed TLS can use it for built-in keys that the
+ *   application cannot modify (for example, a hardware unique key (HUK)).
  *
  * \note Key persistence levels are 8-bit values. Key management
  *       interfaces operate on lifetimes (type ::psa_key_lifetime_t) which
@@ -187,28 +178,30 @@
 
 /** Encoding of key location indicators.
  *
- * If an implementation of this API can make calls to external
+ * If an integration of Mbed TLS can make calls to external
  * cryptoprocessors such as secure elements, the location of a key
  * indicates which secure element performs the operations on the key.
- * If an implementation offers multiple physical locations for persistent
- * storage, the location indicator reflects at which physical location
- * the key is stored.
+ * Depending on the design of the secure element, the key
+ * material may be stored either in the secure element, or
+ * in wrapped (encrypted) form alongside the key metadata in the
+ * primary local storage.
  *
- * This specification defines the following values of location indicators:
+ * The PSA Cryptography API specification defines the following values of
+ * location indicators:
  * - \c 0: primary local storage.
- *   All implementations should support this value.
+ *   This location is always available.
  *   The primary local storage is typically the same storage area that
  *   contains the key metadata.
  * - \c 1: primary secure element.
- *   Implementations should support this value if there is a secure element
- *   attached to the operating environment.
+ *   Integrations of Mbed TLS should support this value if there is a secure
+ *   element attached to the operating environment.
  *   As a guideline, secure elements may provide higher resistance against
  *   side channel and physical attacks than the primary local storage, but may
  *   have restrictions on supported key types, sizes, policies and operations
  *   and may have different performance characteristics.
  * - \c 2-0x7fffff: other locations defined by a PSA specification.
  *   The PSA Cryptography API does not currently assign any meaning to these
- *   locations, but future versions of this specification or other PSA
+ *   locations, but future versions of that specification or other PSA
  *   specifications may do so.
  * - \c 0x800000-0xffffff: vendor-defined locations.
  *   No PSA specification will assign a meaning to locations in this range.
@@ -223,7 +216,7 @@
  *
  * - Applications may freely choose key identifiers in the range
  *   #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX.
- * - Implementations may define additional key identifiers in the range
+ * - The implementation may define additional key identifiers in the range
  *   #PSA_KEY_ID_VENDOR_MIN to #PSA_KEY_ID_VENDOR_MAX.
  * - 0 is reserved as an invalid key identifier.
  * - Key identifiers outside these ranges are reserved for future use.
@@ -271,23 +264,18 @@
  * - The key's policy, comprising usage flags and a specification of
  *   the permitted algorithm(s).
  * - Information about the key itself: the key type and its size.
- * - Implementations may define additional attributes.
+ * - Additional implementation-defined attributes.
  *
  * The actual key material is not considered an attribute of a key.
  * Key attributes do not contain information that is generally considered
  * highly confidential.
  *
- * An attribute structure can be a simple data structure where each function
+ * An attribute structure works like a simple data structure where each function
  * `psa_set_key_xxx` sets a field and the corresponding function
  * `psa_get_key_xxx` retrieves the value of the corresponding field.
- * However, implementations may report values that are equivalent to the
- * original one, but have a different encoding. For example, an
- * implementation may use a more compact representation for types where
- * many bit-patterns are invalid or not supported, and store all values
- * that it does not support as a special marker value. In such an
- * implementation, after setting an invalid value, the corresponding
- * get function returns an invalid value which may not be the one that
- * was originally stored.
+ * However, a future version of the library  may report values that are
+ * equivalent to the original one, but have a different encoding. Invalid
+ * values may be mapped to different, also invalid values.
  *
  * An attribute structure may contain references to auxiliary resources,
  * for example pointers to allocated memory or indirect references to
diff --git a/third_party/mbedtls/repo/include/psa/crypto_values.h b/third_party/mbedtls/repo/include/psa/crypto_values.h
index f1b5c53..fafe93c 100644
--- a/third_party/mbedtls/repo/include/psa/crypto_values.h
+++ b/third_party/mbedtls/repo/include/psa/crypto_values.h
@@ -270,6 +270,46 @@
  */
 #define PSA_ERROR_INVALID_HANDLE        ((psa_status_t)-136)
 
+/** Stored data has been corrupted.
+ *
+ * This error indicates that some persistent storage has suffered corruption.
+ * It does not indicate the following situations, which have specific error
+ * codes:
+ *
+ * - A corruption of volatile memory - use #PSA_ERROR_CORRUPTION_DETECTED.
+ * - A communication error between the cryptoprocessor and its external
+ *   storage - use #PSA_ERROR_COMMUNICATION_FAILURE.
+ * - When the storage is in a valid state but is full - use
+ *   #PSA_ERROR_INSUFFICIENT_STORAGE.
+ * - When the storage fails for other reasons - use
+ *   #PSA_ERROR_STORAGE_FAILURE.
+ * - When the stored data is not valid - use #PSA_ERROR_DATA_INVALID.
+ *
+ * \note A storage corruption does not indicate that any data that was
+ * previously read is invalid. However this previously read data might no
+ * longer be readable from storage.
+ *
+ * When a storage failure occurs, it is no longer possible to ensure the
+ * global integrity of the keystore.
+ */
+#define PSA_ERROR_DATA_CORRUPT          ((psa_status_t)-152)
+
+/** Data read from storage is not valid for the implementation.
+ *
+ * This error indicates that some data read from storage does not have a valid
+ * format. It does not indicate the following situations, which have specific
+ * error codes:
+ *
+ * - When the storage or stored data is corrupted - use #PSA_ERROR_DATA_CORRUPT
+ * - When the storage fails for other reasons - use #PSA_ERROR_STORAGE_FAILURE
+ * - An invalid argument to the API - use #PSA_ERROR_INVALID_ARGUMENT
+ *
+ * This error is typically a result of either storage corruption on a
+ * cleartext storage backend, or an attempt to read data that was
+ * written by an incompatible version of the library.
+ */
+#define PSA_ERROR_DATA_INVALID          ((psa_status_t)-153)
+
 /**@}*/
 
 /** \defgroup crypto_types Key and algorithm types
@@ -363,7 +403,7 @@
  * used for.
  *
  * HMAC keys should generally have the same size as the underlying hash.
- * This size can be calculated with #PSA_HASH_SIZE(\c alg) where
+ * This size can be calculated with #PSA_HASH_LENGTH(\c alg) where
  * \c alg is the HMAC algorithm or the underlying hash algorithm. */
 #define PSA_KEY_TYPE_HMAC                           ((psa_key_type_t)0x1100)
 
@@ -381,10 +421,14 @@
  */
 #define PSA_KEY_TYPE_AES                            ((psa_key_type_t)0x2400)
 
+/** Key for a cipher, AEAD or MAC algorithm based on the
+ * ARIA block cipher. */
+#define PSA_KEY_TYPE_ARIA                           ((psa_key_type_t)0x2406)
+
 /** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES).
  *
- * The size of the key can be 8 bytes (single DES), 16 bytes (2-key 3DES) or
- * 24 bytes (3-key 3DES).
+ * The size of the key can be 64 bits (single DES), 128 bits (2-key 3DES) or
+ * 192 bits (3-key 3DES).
  *
  * Note that single DES and 2-key 3DES are weak and strongly
  * deprecated and should only be used to decrypt legacy data. 3-key 3DES
@@ -411,9 +455,15 @@
  */
 #define PSA_KEY_TYPE_CHACHA20                       ((psa_key_type_t)0x2004)
 
-/** RSA public key. */
+/** RSA public key.
+ *
+ * The size of an RSA key is the bit size of the modulus.
+ */
 #define PSA_KEY_TYPE_RSA_PUBLIC_KEY                 ((psa_key_type_t)0x4001)
-/** RSA key pair (private and public key). */
+/** RSA key pair (private and public key).
+ *
+ * The size of an RSA key is the bit size of the modulus.
+ */
 #define PSA_KEY_TYPE_RSA_KEY_PAIR                   ((psa_key_type_t)0x7001)
 /** Whether a key type is an RSA key (pair or public-only). */
 #define PSA_KEY_TYPE_IS_RSA(type)                                       \
@@ -424,6 +474,10 @@
 #define PSA_KEY_TYPE_ECC_CURVE_MASK                 ((psa_key_type_t)0x00ff)
 /** Elliptic curve key pair.
  *
+ * The size of an elliptic curve key is the bit size associated with the curve,
+ * i.e. the bit size of *q* for a curve over a field *F<sub>q</sub>*.
+ * See the documentation of `PSA_ECC_FAMILY_xxx` curve families for details.
+ *
  * \param curve     A value of type ::psa_ecc_family_t that
  *                  identifies the ECC curve to be used.
  */
@@ -431,6 +485,10 @@
     (PSA_KEY_TYPE_ECC_KEY_PAIR_BASE | (curve))
 /** Elliptic curve public key.
  *
+ * The size of an elliptic curve public key is the same as the corresponding
+ * private key (see #PSA_KEY_TYPE_ECC_KEY_PAIR and the documentation of
+ * `PSA_ECC_FAMILY_xxx` curve families).
+ *
  * \param curve     A value of type ::psa_ecc_family_t that
  *                  identifies the ECC curve to be used.
  */
@@ -529,6 +587,22 @@
  */
 #define PSA_ECC_FAMILY_MONTGOMERY        ((psa_ecc_family_t) 0x41)
 
+/** The twisted Edwards curves Ed25519 and Ed448.
+ *
+ * These curves are suitable for EdDSA (#PSA_ALG_PURE_EDDSA for both curves,
+ * #PSA_ALG_ED25519PH for the 255-bit curve,
+ * #PSA_ALG_ED448PH for the 448-bit curve).
+ *
+ * This family comprises the following twisted Edwards curves:
+ * - 255-bit: Edwards25519, the twisted Edwards curve birationally equivalent
+ *   to Curve25519.
+ *   Bernstein et al., _Twisted Edwards curves_, Africacrypt 2008.
+ * - 448-bit: Edwards448, the twisted Edwards curve birationally equivalent
+ *   to Curve448.
+ *   Hamburg, _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015.
+ */
+#define PSA_ECC_FAMILY_TWISTED_EDWARDS   ((psa_ecc_family_t) 0x42)
+
 #define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE             ((psa_key_type_t)0x4200)
 #define PSA_KEY_TYPE_DH_KEY_PAIR_BASE               ((psa_key_type_t)0x7200)
 #define PSA_KEY_TYPE_DH_GROUP_MASK                  ((psa_key_type_t)0x00ff)
@@ -594,9 +668,9 @@
  *
  * \warning This macro may evaluate its argument multiple times.
  */
-#define PSA_BLOCK_CIPHER_BLOCK_SIZE(type)            \
+#define PSA_BLOCK_CIPHER_BLOCK_LENGTH(type)                                     \
     (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \
-     1u << PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) :                 \
+     1u << PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) :                         \
      0u)
 
 /** Vendor-defined algorithm flag.
@@ -716,6 +790,9 @@
 #define PSA_ALG_IS_KEY_DERIVATION(alg)                                  \
     (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION)
 
+/** An invalid algorithm identifier value. */
+#define PSA_ALG_NONE                            ((psa_algorithm_t)0)
+
 #define PSA_ALG_HASH_MASK                       ((psa_algorithm_t)0x000000ff)
 /** MD2 */
 #define PSA_ALG_MD2                             ((psa_algorithm_t)0x02000001)
@@ -747,6 +824,13 @@
 #define PSA_ALG_SHA3_384                        ((psa_algorithm_t)0x02000012)
 /** SHA3-512 */
 #define PSA_ALG_SHA3_512                        ((psa_algorithm_t)0x02000013)
+/** The first 512 bits (64 bytes) of the SHAKE256 output.
+ *
+ * This is the prehashing for Ed448ph (see #PSA_ALG_ED448PH). For other
+ * scenarios where a hash function based on SHA3/SHAKE is desired, SHA3-512
+ * has the same output size and a (theoretically) higher security strength.
+ */
+#define PSA_ALG_SHAKE256_512                    ((psa_algorithm_t)0x02000015)
 
 /** In a hash-and-sign algorithm policy, allow any hash algorithm.
  *
@@ -756,7 +840,7 @@
  * algorithm parametrized with any supported hash.
  *
  * That is, suppose that `PSA_xxx_SIGNATURE` is one of the following macros:
- * - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS,
+ * - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS, #PSA_ALG_RSA_PSS_ANY_SALT,
  * - #PSA_ALG_ECDSA, #PSA_ALG_DETERMINISTIC_ECDSA.
  * Then you may create and use a key as follows:
  * - Set the key usage field using #PSA_ALG_ANY_HASH, for example:
@@ -826,6 +910,14 @@
 #define PSA_ALG_MAC_TRUNCATION_MASK             ((psa_algorithm_t)0x003f0000)
 #define PSA_MAC_TRUNCATION_OFFSET 16
 
+/* In the encoding of a MAC algorithm, the bit corresponding to
+ * #PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG encodes the fact that the algorithm
+ * is a wildcard algorithm. A key with such wildcard algorithm as permitted
+ * algorithm policy can be used with any algorithm corresponding to the
+ * same base class and having a (potentially truncated) MAC length greater or
+ * equal than the one encoded in #PSA_ALG_MAC_TRUNCATION_MASK. */
+#define PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG   ((psa_algorithm_t)0x00008000)
+
 /** Macro to build a truncated MAC algorithm.
  *
  * A truncated MAC algorithm is identical to the corresponding MAC
@@ -844,7 +936,7 @@
  *          for policy comparison purposes.
  *
  * \param mac_alg       A MAC algorithm identifier (value of type
- *                      #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg)
+ *                      #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg)
  *                      is true). This may be a truncated or untruncated
  *                      MAC algorithm.
  * \param mac_length    Desired length of the truncated MAC in bytes.
@@ -855,43 +947,73 @@
  *
  * \return              The corresponding MAC algorithm with the specified
  *                      length.
- * \return              Unspecified if \p alg is not a supported
+ * \return              Unspecified if \p mac_alg is not a supported
  *                      MAC algorithm or if \p mac_length is too small or
  *                      too large for the specified MAC algorithm.
  */
-#define PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length)                      \
-    (((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) |                       \
+#define PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length)              \
+    (((mac_alg) & ~(PSA_ALG_MAC_TRUNCATION_MASK |               \
+                    PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG)) |   \
      ((mac_length) << PSA_MAC_TRUNCATION_OFFSET & PSA_ALG_MAC_TRUNCATION_MASK))
 
 /** Macro to build the base MAC algorithm corresponding to a truncated
  * MAC algorithm.
  *
  * \param mac_alg       A MAC algorithm identifier (value of type
- *                      #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg)
+ *                      #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg)
  *                      is true). This may be a truncated or untruncated
  *                      MAC algorithm.
  *
  * \return              The corresponding base MAC algorithm.
- * \return              Unspecified if \p alg is not a supported
+ * \return              Unspecified if \p mac_alg is not a supported
  *                      MAC algorithm.
  */
-#define PSA_ALG_FULL_LENGTH_MAC(mac_alg)        \
-    ((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK)
+#define PSA_ALG_FULL_LENGTH_MAC(mac_alg)                        \
+    ((mac_alg) & ~(PSA_ALG_MAC_TRUNCATION_MASK |                \
+                   PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG))
 
 /** Length to which a MAC algorithm is truncated.
  *
  * \param mac_alg       A MAC algorithm identifier (value of type
- *                      #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg)
+ *                      #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg)
  *                      is true).
  *
  * \return              Length of the truncated MAC in bytes.
- * \return              0 if \p alg is a non-truncated MAC algorithm.
- * \return              Unspecified if \p alg is not a supported
+ * \return              0 if \p mac_alg is a non-truncated MAC algorithm.
+ * \return              Unspecified if \p mac_alg is not a supported
  *                      MAC algorithm.
  */
 #define PSA_MAC_TRUNCATED_LENGTH(mac_alg)                               \
     (((mac_alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET)
 
+/** Macro to build a MAC minimum-MAC-length wildcard algorithm.
+ *
+ * A minimum-MAC-length MAC wildcard algorithm permits all MAC algorithms
+ * sharing the same base algorithm, and where the (potentially truncated) MAC
+ * length of the specific algorithm is equal to or larger then the wildcard
+ * algorithm's minimum MAC length.
+ *
+ * \note    When setting the minimum required MAC length to less than the
+ *          smallest MAC length allowed by the base algorithm, this effectively
+ *          becomes an 'any-MAC-length-allowed' policy for that base algorithm.
+ *
+ * \param mac_alg         A MAC algorithm identifier (value of type
+ *                        #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg)
+ *                        is true).
+ * \param min_mac_length  Desired minimum length of the message authentication
+ *                        code in bytes. This must be at most the untruncated
+ *                        length of the MAC and must be at least 1.
+ *
+ * \return                The corresponding MAC wildcard algorithm with the
+ *                        specified minimum length.
+ * \return                Unspecified if \p mac_alg is not a supported MAC
+ *                        algorithm or if \p min_mac_length is less than 1 or
+ *                        too large for the specified MAC algorithm.
+ */
+#define PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(mac_alg, min_mac_length)   \
+    ( PSA_ALG_TRUNCATED_MAC(mac_alg, min_mac_length) |              \
+      PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG )
+
 #define PSA_ALG_CIPHER_MAC_BASE                 ((psa_algorithm_t)0x03c00000)
 /** The CBC-MAC construction over a block cipher
  *
@@ -1052,6 +1174,14 @@
 #define PSA_ALG_AEAD_TAG_LENGTH_MASK            ((psa_algorithm_t)0x003f0000)
 #define PSA_AEAD_TAG_LENGTH_OFFSET 16
 
+/* In the encoding of an AEAD algorithm, the bit corresponding to
+ * #PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG encodes the fact that the algorithm
+ * is a wildcard algorithm. A key with such wildcard algorithm as permitted
+ * algorithm policy can be used with any algorithm corresponding to the
+ * same base class and having a tag length greater than or equal to the one
+ * encoded in #PSA_ALG_AEAD_TAG_LENGTH_MASK. */
+#define PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG  ((psa_algorithm_t)0x00008000)
+
 /** Macro to build a shortened AEAD algorithm.
  *
  * A shortened AEAD algorithm is similar to the corresponding AEAD
@@ -1060,40 +1190,83 @@
  * of the ciphertext.
  *
  * \param aead_alg      An AEAD algorithm identifier (value of type
- *                      #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p alg)
+ *                      #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p aead_alg)
  *                      is true).
  * \param tag_length    Desired length of the authentication tag in bytes.
  *
  * \return              The corresponding AEAD algorithm with the specified
  *                      length.
- * \return              Unspecified if \p alg is not a supported
+ * \return              Unspecified if \p aead_alg is not a supported
  *                      AEAD algorithm or if \p tag_length is not valid
  *                      for the specified AEAD algorithm.
  */
-#define PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, tag_length)              \
-    (((aead_alg) & ~PSA_ALG_AEAD_TAG_LENGTH_MASK) |                     \
+#define PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, tag_length)           \
+    (((aead_alg) & ~(PSA_ALG_AEAD_TAG_LENGTH_MASK |                     \
+                     PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG)) |         \
      ((tag_length) << PSA_AEAD_TAG_LENGTH_OFFSET &                      \
       PSA_ALG_AEAD_TAG_LENGTH_MASK))
 
+/** Retrieve the tag length of a specified AEAD algorithm
+ *
+ * \param aead_alg      An AEAD algorithm identifier (value of type
+ *                      #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p aead_alg)
+ *                      is true).
+ *
+ * \return              The tag length specified by the input algorithm.
+ * \return              Unspecified if \p aead_alg is not a supported
+ *                      AEAD algorithm.
+ */
+#define PSA_ALG_AEAD_GET_TAG_LENGTH(aead_alg)                           \
+    (((aead_alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >>                     \
+      PSA_AEAD_TAG_LENGTH_OFFSET )
+
 /** Calculate the corresponding AEAD algorithm with the default tag length.
  *
  * \param aead_alg      An AEAD algorithm (\c PSA_ALG_XXX value such that
- *                      #PSA_ALG_IS_AEAD(\p alg) is true).
+ *                      #PSA_ALG_IS_AEAD(\p aead_alg) is true).
  *
  * \return              The corresponding AEAD algorithm with the default
  *                      tag length for that algorithm.
  */
-#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(aead_alg)                   \
+#define PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(aead_alg)                   \
     (                                                                    \
-        PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CCM) \
-        PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_GCM) \
-        PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CHACHA20_POLY1305) \
+        PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_CCM) \
+        PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_GCM) \
+        PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_CHACHA20_POLY1305) \
         0)
-#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, ref)         \
-    PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, 0) ==                         \
-    PSA_ALG_AEAD_WITH_TAG_LENGTH(ref, 0) ?                               \
+#define PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, ref)         \
+    PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, 0) ==                      \
+    PSA_ALG_AEAD_WITH_SHORTENED_TAG(ref, 0) ?                            \
     ref :
 
+/** Macro to build an AEAD minimum-tag-length wildcard algorithm.
+ *
+ * A minimum-tag-length AEAD wildcard algorithm permits all AEAD algorithms
+ * sharing the same base algorithm, and where the tag length of the specific
+ * algorithm is equal to or larger then the minimum tag length specified by the
+ * wildcard algorithm.
+ *
+ * \note    When setting the minimum required tag length to less than the
+ *          smallest tag length allowed by the base algorithm, this effectively
+ *          becomes an 'any-tag-length-allowed' policy for that base algorithm.
+ *
+ * \param aead_alg        An AEAD algorithm identifier (value of type
+ *                        #psa_algorithm_t such that
+ *                        #PSA_ALG_IS_AEAD(\p aead_alg) is true).
+ * \param min_tag_length  Desired minimum length of the authentication tag in
+ *                        bytes. This must be at least 1 and at most the largest
+ *                        allowed tag length of the algorithm.
+ *
+ * \return                The corresponding AEAD wildcard algorithm with the
+ *                        specified minimum length.
+ * \return                Unspecified if \p aead_alg is not a supported
+ *                        AEAD algorithm or if \p min_tag_length is less than 1
+ *                        or too large for the specified AEAD algorithm.
+ */
+#define PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(aead_alg, min_tag_length) \
+    ( PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, min_tag_length) |            \
+      PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG )
+
 #define PSA_ALG_RSA_PKCS1V15_SIGN_BASE          ((psa_algorithm_t)0x06000200)
 /** RSA PKCS#1 v1.5 signature with hashing.
  *
@@ -1123,6 +1296,7 @@
     (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE)
 
 #define PSA_ALG_RSA_PSS_BASE               ((psa_algorithm_t)0x06000300)
+#define PSA_ALG_RSA_PSS_ANY_SALT_BASE      ((psa_algorithm_t)0x06001300)
 /** RSA PSS signature with hashing.
  *
  * This is the signature scheme defined by RFC 8017
@@ -1143,9 +1317,72 @@
  */
 #define PSA_ALG_RSA_PSS(hash_alg)                               \
     (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
-#define PSA_ALG_IS_RSA_PSS(alg)                                 \
+
+/** RSA PSS signature with hashing with relaxed verification.
+ *
+ * This algorithm has the same behavior as #PSA_ALG_RSA_PSS when signing,
+ * but allows an arbitrary salt length (including \c 0) when verifying a
+ * signature.
+ *
+ * \param hash_alg      A hash algorithm (\c PSA_ALG_XXX value such that
+ *                      #PSA_ALG_IS_HASH(\p hash_alg) is true).
+ *                      This includes #PSA_ALG_ANY_HASH
+ *                      when specifying the algorithm in a usage policy.
+ *
+ * \return              The corresponding RSA PSS signature algorithm.
+ * \return              Unspecified if \p hash_alg is not a supported
+ *                      hash algorithm.
+ */
+#define PSA_ALG_RSA_PSS_ANY_SALT(hash_alg)                      \
+    (PSA_ALG_RSA_PSS_ANY_SALT_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+
+/** Whether the specified algorithm is RSA PSS with standard salt.
+ *
+ * \param alg           An algorithm value or an algorithm policy wildcard.
+ *
+ * \return              1 if \p alg is of the form
+ *                      #PSA_ALG_RSA_PSS(\c hash_alg),
+ *                      where \c hash_alg is a hash algorithm or
+ *                      #PSA_ALG_ANY_HASH. 0 otherwise.
+ *                      This macro may return either 0 or 1 if \p alg is not
+ *                      a supported algorithm identifier or policy.
+ */
+#define PSA_ALG_IS_RSA_PSS_STANDARD_SALT(alg)                   \
     (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE)
 
+/** Whether the specified algorithm is RSA PSS with any salt.
+ *
+ * \param alg           An algorithm value or an algorithm policy wildcard.
+ *
+ * \return              1 if \p alg is of the form
+ *                      #PSA_ALG_RSA_PSS_ANY_SALT_BASE(\c hash_alg),
+ *                      where \c hash_alg is a hash algorithm or
+ *                      #PSA_ALG_ANY_HASH. 0 otherwise.
+ *                      This macro may return either 0 or 1 if \p alg is not
+ *                      a supported algorithm identifier or policy.
+ */
+#define PSA_ALG_IS_RSA_PSS_ANY_SALT(alg)                                \
+    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_ANY_SALT_BASE)
+
+/** Whether the specified algorithm is RSA PSS.
+ *
+ * This includes any of the RSA PSS algorithm variants, regardless of the
+ * constraints on salt length.
+ *
+ * \param alg           An algorithm value or an algorithm policy wildcard.
+ *
+ * \return              1 if \p alg is of the form
+ *                      #PSA_ALG_RSA_PSS(\c hash_alg) or
+ *                      #PSA_ALG_RSA_PSS_ANY_SALT_BASE(\c hash_alg),
+ *                      where \c hash_alg is a hash algorithm or
+ *                      #PSA_ALG_ANY_HASH. 0 otherwise.
+ *                      This macro may return either 0 or 1 if \p alg is not
+ *                      a supported algorithm identifier or policy.
+ */
+#define PSA_ALG_IS_RSA_PSS(alg)                                 \
+    (PSA_ALG_IS_RSA_PSS_STANDARD_SALT(alg) ||                   \
+     PSA_ALG_IS_RSA_PSS_ANY_SALT(alg))
+
 #define PSA_ALG_ECDSA_BASE                      ((psa_algorithm_t)0x06000600)
 /** ECDSA signature with hashing.
  *
@@ -1215,12 +1452,149 @@
 #define PSA_ALG_IS_RANDOMIZED_ECDSA(alg)                                \
     (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg))
 
+/** Edwards-curve digital signature algorithm without prehashing (PureEdDSA),
+ * using standard parameters.
+ *
+ * Contexts are not supported in the current version of this specification
+ * because there is no suitable signature interface that can take the
+ * context as a parameter. A future version of this specification may add
+ * suitable functions and extend this algorithm to support contexts.
+ *
+ * PureEdDSA requires an elliptic curve key on a twisted Edwards curve.
+ * In this specification, the following curves are supported:
+ * - #PSA_ECC_FAMILY_TWISTED_EDWARDS, 255-bit: Ed25519 as specified
+ *   in RFC 8032.
+ *   The curve is Edwards25519.
+ *   The hash function used internally is SHA-512.
+ * - #PSA_ECC_FAMILY_TWISTED_EDWARDS, 448-bit: Ed448 as specified
+ *   in RFC 8032.
+ *   The curve is Edwards448.
+ *   The hash function used internally is the first 114 bytes of the
+ *   SHAKE256 output.
+ *
+ * This algorithm can be used with psa_sign_message() and
+ * psa_verify_message(). Since there is no prehashing, it cannot be used
+ * with psa_sign_hash() or psa_verify_hash().
+ *
+ * The signature format is the concatenation of R and S as defined by
+ * RFC 8032 §5.1.6 and §5.2.6 (a 64-byte string for Ed25519, a 114-byte
+ * string for Ed448).
+ */
+#define PSA_ALG_PURE_EDDSA                      ((psa_algorithm_t)0x06000800)
+
+#define PSA_ALG_HASH_EDDSA_BASE                 ((psa_algorithm_t)0x06000900)
+#define PSA_ALG_IS_HASH_EDDSA(alg)              \
+    (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HASH_EDDSA_BASE)
+
+/** Edwards-curve digital signature algorithm with prehashing (HashEdDSA),
+ * using SHA-512 and the Edwards25519 curve.
+ *
+ * See #PSA_ALG_PURE_EDDSA regarding context support and the signature format.
+ *
+ * This algorithm is Ed25519 as specified in RFC 8032.
+ * The curve is Edwards25519.
+ * The prehash is SHA-512.
+ * The hash function used internally is SHA-512.
+ *
+ * This is a hash-and-sign algorithm: to calculate a signature,
+ * you can either:
+ * - call psa_sign_message() on the message;
+ * - or calculate the SHA-512 hash of the message
+ *   with psa_hash_compute()
+ *   or with a multi-part hash operation started with psa_hash_setup(),
+ *   using the hash algorithm #PSA_ALG_SHA_512,
+ *   then sign the calculated hash with psa_sign_hash().
+ * Verifying a signature is similar, using psa_verify_message() or
+ * psa_verify_hash() instead of the signature function.
+ */
+#define PSA_ALG_ED25519PH                               \
+    (PSA_ALG_HASH_EDDSA_BASE | (PSA_ALG_SHA_512 & PSA_ALG_HASH_MASK))
+
+/** Edwards-curve digital signature algorithm with prehashing (HashEdDSA),
+ * using SHAKE256 and the Edwards448 curve.
+ *
+ * See #PSA_ALG_PURE_EDDSA regarding context support and the signature format.
+ *
+ * This algorithm is Ed448 as specified in RFC 8032.
+ * The curve is Edwards448.
+ * The prehash is the first 64 bytes of the SHAKE256 output.
+ * The hash function used internally is the first 114 bytes of the
+ * SHAKE256 output.
+ *
+ * This is a hash-and-sign algorithm: to calculate a signature,
+ * you can either:
+ * - call psa_sign_message() on the message;
+ * - or calculate the first 64 bytes of the SHAKE256 output of the message
+ *   with psa_hash_compute()
+ *   or with a multi-part hash operation started with psa_hash_setup(),
+ *   using the hash algorithm #PSA_ALG_SHAKE256_512,
+ *   then sign the calculated hash with psa_sign_hash().
+ * Verifying a signature is similar, using psa_verify_message() or
+ * psa_verify_hash() instead of the signature function.
+ */
+#define PSA_ALG_ED448PH                                 \
+    (PSA_ALG_HASH_EDDSA_BASE | (PSA_ALG_SHAKE256_512 & PSA_ALG_HASH_MASK))
+
+/* Default definition, to be overridden if the library is extended with
+ * more hash-and-sign algorithms that we want to keep out of this header
+ * file. */
+#define PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg) 0
+
+/** Whether the specified algorithm is a signature algorithm that can be used
+ * with psa_sign_hash() and psa_verify_hash().
+ *
+ * This encompasses all strict hash-and-sign algorithms categorized by
+ * PSA_ALG_IS_HASH_AND_SIGN(), as well as algorithms that follow the
+ * paradigm more loosely:
+ * - #PSA_ALG_RSA_PKCS1V15_SIGN_RAW (expects its input to be an encoded hash)
+ * - #PSA_ALG_ECDSA_ANY (doesn't specify what kind of hash the input is)
+ *
+ * \param alg An algorithm identifier (value of type psa_algorithm_t).
+ *
+ * \return 1 if alg is a signature algorithm that can be used to sign a
+ *         hash. 0 if alg is a signature algorithm that can only be used
+ *         to sign a message. 0 if alg is not a signature algorithm.
+ *         This macro can return either 0 or 1 if alg is not a
+ *         supported algorithm identifier.
+ */
+#define PSA_ALG_IS_SIGN_HASH(alg)                                       \
+    (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||    \
+     PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_HASH_EDDSA(alg) ||             \
+     PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg))
+
+/** Whether the specified algorithm is a signature algorithm that can be used
+ * with psa_sign_message() and psa_verify_message().
+ *
+ * \param alg An algorithm identifier (value of type #psa_algorithm_t).
+ *
+ * \return 1 if alg is a signature algorithm that can be used to sign a
+ *         message. 0 if \p alg is a signature algorithm that can only be used
+ *         to sign an already-calculated hash. 0 if \p alg is not a signature
+ *         algorithm. This macro can return either 0 or 1 if \p alg is not a
+ *         supported algorithm identifier.
+ */
+#define PSA_ALG_IS_SIGN_MESSAGE(alg)                                    \
+    (PSA_ALG_IS_SIGN_HASH(alg) || (alg) == PSA_ALG_PURE_EDDSA )
+
 /** Whether the specified algorithm is a hash-and-sign algorithm.
  *
  * Hash-and-sign algorithms are asymmetric (public-key) signature algorithms
  * structured in two parts: first the calculation of a hash in a way that
  * does not depend on the key, then the calculation of a signature from the
- * hash value and the key.
+ * hash value and the key. Hash-and-sign algorithms encode the hash
+ * used for the hashing step, and you can call #PSA_ALG_SIGN_GET_HASH
+ * to extract this algorithm.
+ *
+ * Thus, for a hash-and-sign algorithm,
+ * `psa_sign_message(key, alg, input, ...)` is equivalent to
+ * ```
+ * psa_hash_compute(PSA_ALG_SIGN_GET_HASH(alg), input, ..., hash, ...);
+ * psa_sign_hash(key, alg, hash, ..., signature, ...);
+ * ```
+ * Most usefully, separating the hash from the signature allows the hash
+ * to be calculated in multiple steps with psa_hash_setup(), psa_hash_update()
+ * and psa_hash_finish(). Likewise psa_verify_message() is equivalent to
+ * calculating the hash and then calling psa_verify_hash().
  *
  * \param alg An algorithm identifier (value of type #psa_algorithm_t).
  *
@@ -1229,8 +1603,8 @@
  *         algorithm identifier.
  */
 #define PSA_ALG_IS_HASH_AND_SIGN(alg)                                   \
-    (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||    \
-     PSA_ALG_IS_ECDSA(alg))
+    (PSA_ALG_IS_SIGN_HASH(alg) &&                                       \
+     ((alg) & PSA_ALG_HASH_MASK) != 0)
 
 /** Get the hash used by a hash-and-sign signature algorithm.
  *
@@ -1252,7 +1626,6 @@
  */
 #define PSA_ALG_SIGN_GET_HASH(alg)                                     \
     (PSA_ALG_IS_HASH_AND_SIGN(alg) ?                                   \
-     ((alg) & PSA_ALG_HASH_MASK) == 0 ? /*"raw" algorithm*/ 0 :        \
      ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH :             \
      0)
 
@@ -1540,9 +1913,13 @@
  * \return This macro may return either 0 or 1 if \c alg is not a supported
  *         algorithm identifier.
  */
-#define PSA_ALG_IS_WILDCARD(alg)                        \
-    (PSA_ALG_IS_HASH_AND_SIGN(alg) ?                    \
-     PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH :   \
+#define PSA_ALG_IS_WILDCARD(alg)                            \
+    (PSA_ALG_IS_HASH_AND_SIGN(alg) ?                        \
+     PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH :       \
+     PSA_ALG_IS_MAC(alg) ?                                  \
+     (alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0 :   \
+     PSA_ALG_IS_AEAD(alg) ?                                 \
+     (alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0 :  \
      (alg) == PSA_ALG_ANY_HASH)
 
 /**@}*/
@@ -1568,13 +1945,12 @@
  *
  * A persistent key remains in storage until it is explicitly destroyed or
  * until the corresponding storage area is wiped. This specification does
- * not define any mechanism to wipe a storage area, but implementations may
+ * not define any mechanism to wipe a storage area, but integrations may
  * provide their own mechanism (for example to perform a factory reset,
  * to prepare for device refurbishment, or to uninstall an application).
  *
  * This lifetime value is the default storage area for the calling
- * application. Implementations may offer other storage areas designated
- * by other lifetime values as implementation-specific extensions.
+ * application. Integrations of Mbed TLS may support other persistent lifetimes.
  * See ::psa_key_lifetime_t for more information.
  */
 #define PSA_KEY_LIFETIME_PERSISTENT             ((psa_key_lifetime_t)0x00000001)
@@ -1623,6 +1999,27 @@
     (PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) == \
      PSA_KEY_PERSISTENCE_VOLATILE)
 
+/** Whether a key lifetime indicates that the key is read-only.
+ *
+ * Read-only keys cannot be created or destroyed through the PSA Crypto API.
+ * They must be created through platform-specific means that bypass the API.
+ *
+ * Some platforms may offer ways to destroy read-only keys. For example,
+ * consider a platform with multiple levels of privilege, where a
+ * low-privilege application can use a key but is not allowed to destroy
+ * it, and the platform exposes the key to the application with a read-only
+ * lifetime. High-privilege code can destroy the key even though the
+ * application sees the key as read-only.
+ *
+ * \param lifetime      The lifetime value to query (value of type
+ *                      ::psa_key_lifetime_t).
+ *
+ * \return \c 1 if the key is read-only, otherwise \c 0.
+ */
+#define PSA_KEY_LIFETIME_IS_READ_ONLY(lifetime)  \
+    (PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) == \
+     PSA_KEY_PERSISTENCE_READ_ONLY)
+
 /** Construct a lifetime from a persistence level and a location.
  *
  * \param persistence   The persistence level
@@ -1646,6 +2043,9 @@
 
 #define PSA_KEY_LOCATION_VENDOR_FLAG            ((psa_key_location_t)0x800000)
 
+/** The null key identifier.
+ */
+#define PSA_KEY_ID_NULL                         ((psa_key_id_t)0)
 /** The minimum value for a key identifier chosen by the application.
  */
 #define PSA_KEY_ID_USER_MIN                     ((psa_key_id_t)0x00000001)
@@ -1743,7 +2143,7 @@
  */
 static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key )
 {
-    return( ( key.key_id == 0 ) && ( key.owner == 0 ) );
+    return( key.key_id == 0 );
 }
 
 #endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
@@ -1807,6 +2207,26 @@
 
 /** Whether the key may be used to sign a message.
  *
+ * This flag allows the key to be used for a MAC calculation operation or for
+ * an asymmetric message signature operation, if otherwise permitted by the
+ * key’s type and policy.
+ *
+ * For a key pair, this concerns the private key.
+ */
+#define PSA_KEY_USAGE_SIGN_MESSAGE              ((psa_key_usage_t)0x00000400)
+
+/** Whether the key may be used to verify a message.
+ *
+ * This flag allows the key to be used for a MAC verification operation or for
+ * an asymmetric message signature verification operation, if otherwise
+ * permitted by the key’s type and policy.
+ *
+ * For a key pair, this concerns the public key.
+ */
+#define PSA_KEY_USAGE_VERIFY_MESSAGE            ((psa_key_usage_t)0x00000800)
+
+/** Whether the key may be used to sign a message.
+ *
  * This flag allows the key to be used for a MAC calculation operation
  * or for an asymmetric signature operation,
  * if otherwise permitted by the key's type and policy.
@@ -1879,4 +2299,27 @@
 
 /**@}*/
 
+/** \defgroup helper_macros Helper macros
+ * @{
+ */
+
+/* Helper macros */
+
+/** Check if two AEAD algorithm identifiers refer to the same AEAD algorithm
+ *  regardless of the tag length they encode.
+ *
+ * \param aead_alg_1 An AEAD algorithm identifier.
+ * \param aead_alg_2 An AEAD algorithm identifier.
+ *
+ * \return           1 if both identifiers refer to the same AEAD algorithm,
+ *                   0 otherwise.
+ *                   Unspecified if neither \p aead_alg_1 nor \p aead_alg_2 are
+ *                   a supported AEAD algorithm.
+ */
+#define MBEDTLS_PSA_ALG_AEAD_EQUAL(aead_alg_1, aead_alg_2) \
+    (!(((aead_alg_1) ^ (aead_alg_2)) & \
+       ~(PSA_ALG_AEAD_TAG_LENGTH_MASK | PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG)))
+
+/**@}*/
+
 #endif /* PSA_CRYPTO_VALUES_H */
diff --git a/third_party/mbedtls/repo/library/CMakeLists.txt b/third_party/mbedtls/repo/library/CMakeLists.txt
index b309b6e..0a60067 100644
--- a/third_party/mbedtls/repo/library/CMakeLists.txt
+++ b/third_party/mbedtls/repo/library/CMakeLists.txt
@@ -26,6 +26,7 @@
     chachapoly.c
     cipher.c
     cipher_wrap.c
+    constant_time.c
     cmac.c
     ctr_drbg.c
     des.c
@@ -47,6 +48,8 @@
     md4.c
     md5.c
     memory_buffer_alloc.c
+    mps_reader.c
+    mps_trace.c
     nist_kw.c
     oid.c
     padlock.c
@@ -61,7 +64,14 @@
     platform_util.c
     poly1305.c
     psa_crypto.c
+    psa_crypto_aead.c
+    psa_crypto_cipher.c
+    psa_crypto_client.c
     psa_crypto_driver_wrappers.c
+    psa_crypto_ecp.c
+    psa_crypto_hash.c
+    psa_crypto_mac.c
+    psa_crypto_rsa.c
     psa_crypto_se.c
     psa_crypto_slot_management.c
     psa_crypto_storage.c
@@ -193,15 +203,15 @@
 
 if(USE_SHARED_MBEDTLS_LIBRARY)
     add_library(${mbedcrypto_target} SHARED ${src_crypto})
-    set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 2.25.0 SOVERSION 6)
+    set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 2.28.0 SOVERSION 7)
     target_link_libraries(${mbedcrypto_target} PUBLIC ${libs})
 
     add_library(${mbedx509_target} SHARED ${src_x509})
-    set_target_properties(${mbedx509_target} PROPERTIES VERSION 2.25.0 SOVERSION 1)
+    set_target_properties(${mbedx509_target} PROPERTIES VERSION 2.28.0 SOVERSION 1)
     target_link_libraries(${mbedx509_target} PUBLIC ${libs} ${mbedcrypto_target})
 
     add_library(${mbedtls_target} SHARED ${src_tls})
-    set_target_properties(${mbedtls_target} PROPERTIES VERSION 2.25.0 SOVERSION 13)
+    set_target_properties(${mbedtls_target} PROPERTIES VERSION 2.28.0 SOVERSION 14)
     target_link_libraries(${mbedtls_target} PUBLIC ${libs} ${mbedx509_target})
 endif(USE_SHARED_MBEDTLS_LIBRARY)
 
diff --git a/third_party/mbedtls/repo/library/Makefile b/third_party/mbedtls/repo/library/Makefile
index ae33bf2..54b0651 100644
--- a/third_party/mbedtls/repo/library/Makefile
+++ b/third_party/mbedtls/repo/library/Makefile
@@ -2,7 +2,7 @@
 # Also see "include/mbedtls/config.h"
 
 CFLAGS	?= -O2
-WARNING_CFLAGS ?=  -Wall -Wextra
+WARNING_CFLAGS ?=  -Wall -Wextra -Wformat=2 -Wno-format-nonliteral
 LDFLAGS ?=
 
 # Include ../include for public headers and . for private headers.
@@ -39,9 +39,9 @@
 endif
 endif
 
-SOEXT_TLS=so.13
+SOEXT_TLS=so.14
 SOEXT_X509=so.1
-SOEXT_CRYPTO=so.6
+SOEXT_CRYPTO=so.7
 
 # Set AR_DASH= (empty string) to use an ar implementation that does not accept
 # the - prefix for command line options (e.g. llvm-ar)
@@ -84,6 +84,7 @@
 	     cipher.o \
 	     cipher_wrap.o \
 	     cmac.o \
+	     constant_time.o \
 	     ctr_drbg.o \
 	     des.o \
 	     dhm.o \
@@ -104,6 +105,8 @@
 	     md4.o \
 	     md5.o \
 	     memory_buffer_alloc.o \
+	     mps_reader.o \
+	     mps_trace.o \
 	     nist_kw.o \
 	     oid.o \
 	     padlock.o \
@@ -118,7 +121,14 @@
 	     platform_util.o \
 	     poly1305.o \
 	     psa_crypto.o \
+	     psa_crypto_aead.o \
+	     psa_crypto_cipher.o \
+	     psa_crypto_client.o \
 	     psa_crypto_driver_wrappers.o \
+	     psa_crypto_ecp.o \
+	     psa_crypto_hash.o \
+	     psa_crypto_mac.o \
+	     psa_crypto_rsa.o \
 	     psa_crypto_se.o \
 	     psa_crypto_slot_management.o \
 	     psa_crypto_storage.o \
@@ -180,6 +190,14 @@
 
 shared: libmbedcrypto.$(DLEXT) libmbedx509.$(DLEXT) libmbedtls.$(DLEXT)
 
+# Windows builds under Mingw can fail if make tries to create archives in the same
+# directory at the same time - see https://bugs.launchpad.net/gcc-arm-embedded/+bug/1848002.
+# This forces builds of the .a files to be serialised.
+ifdef WINDOWS
+libmbedtls.a: | libmbedx509.a
+libmbedx509.a: | libmbedcrypto.a
+endif
+
 # tls
 libmbedtls.a: $(OBJS_TLS)
 	echo "  AR    $@"
@@ -193,7 +211,7 @@
 
 libmbedtls.$(SOEXT_TLS): $(OBJS_TLS) libmbedx509.so
 	echo "  LD    $@"
-	$(CC) -shared -Wl,-soname,$@ -L. -lmbedcrypto -lmbedx509 $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_TLS)
+	$(CC) -shared -Wl,-soname,$@ -o $@ $(OBJS_TLS) -L. -lmbedx509 -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS)
 
 libmbedtls.so: libmbedtls.$(SOEXT_TLS)
 	echo "  LN    $@ -> $<"
@@ -201,11 +219,11 @@
 
 libmbedtls.dylib: $(OBJS_TLS) libmbedx509.dylib
 	echo "  LD    $@"
-	$(CC) -dynamiclib -L. -lmbedcrypto -lmbedx509 $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_TLS)
+	$(CC) -dynamiclib -o $@ $(OBJS_TLS) -L. -lmbedx509 -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS)
 
 libmbedtls.dll: $(OBJS_TLS) libmbedx509.dll
 	echo "  LD    $@"
-	$(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_TLS) -lws2_32 -lwinmm -lgdi32 -L. -lmbedcrypto -lmbedx509 -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS)
+	$(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_TLS) -lws2_32 -lwinmm -lgdi32 -L. -lmbedx509 -lmbedcrypto -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS)
 
 # x509
 libmbedx509.a: $(OBJS_X509)
@@ -220,7 +238,7 @@
 
 libmbedx509.$(SOEXT_X509): $(OBJS_X509) libmbedcrypto.so
 	echo "  LD    $@"
-	$(CC) -shared -Wl,-soname,$@ -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509)
+	$(CC) -shared -Wl,-soname,$@ -o $@ $(OBJS_X509) -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS)
 
 libmbedx509.so: libmbedx509.$(SOEXT_X509)
 	echo "  LN    $@ -> $<"
@@ -228,7 +246,7 @@
 
 libmbedx509.dylib: $(OBJS_X509) libmbedcrypto.dylib
 	echo "  LD    $@"
-	$(CC) -dynamiclib -L. -lmbedcrypto  $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509)
+	$(CC) -dynamiclib -o $@ $(OBJS_X509) -L. -lmbedcrypto  $(LOCAL_LDFLAGS) $(LDFLAGS)
 
 libmbedx509.dll: $(OBJS_X509) libmbedcrypto.dll
 	echo "  LD    $@"
@@ -247,7 +265,7 @@
 
 libmbedcrypto.$(SOEXT_CRYPTO): $(OBJS_CRYPTO)
 	echo "  LD    $@"
-	$(CC) -shared -Wl,-soname,$@ $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_CRYPTO)
+	$(CC) -shared -Wl,-soname,$@ -o $@ $(OBJS_CRYPTO) $(LOCAL_LDFLAGS) $(LDFLAGS)
 
 libmbedcrypto.so: libmbedcrypto.$(SOEXT_CRYPTO)
 	echo "  LN    $@ -> $<"
@@ -255,7 +273,7 @@
 
 libmbedcrypto.dylib: $(OBJS_CRYPTO)
 	echo "  LD    $@"
-	$(CC) -dynamiclib $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_CRYPTO)
+	$(CC) -dynamiclib -o $@ $(OBJS_CRYPTO) $(LOCAL_LDFLAGS) $(LDFLAGS)
 
 libmbedcrypto.dll: $(OBJS_CRYPTO)
 	echo "  LD    $@"
diff --git a/third_party/mbedtls/repo/library/aes.c b/third_party/mbedtls/repo/library/aes.c
index 3f61642..31824e7 100644
--- a/third_party/mbedtls/repo/library/aes.c
+++ b/third_party/mbedtls/repo/library/aes.c
@@ -57,29 +57,6 @@
 #define AES_VALIDATE( cond )        \
     MBEDTLS_INTERNAL_VALIDATE( cond )
 
-/*
- * 32-bit integer manipulation macros (little endian)
- */
-#ifndef GET_UINT32_LE
-#define GET_UINT32_LE(n,b,i)                            \
-{                                                       \
-    (n) = ( (uint32_t) (b)[(i)    ]       )             \
-        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \
-        | ( (uint32_t) (b)[(i) + 2] << 16 )             \
-        | ( (uint32_t) (b)[(i) + 3] << 24 );            \
-}
-#endif
-
-#ifndef PUT_UINT32_LE
-#define PUT_UINT32_LE(n,b,i)                                    \
-{                                                               \
-    (b)[(i)    ] = (unsigned char) ( ( (n)       ) & 0xFF );    \
-    (b)[(i) + 1] = (unsigned char) ( ( (n) >>  8 ) & 0xFF );    \
-    (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF );    \
-    (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF );    \
-}
-#endif
-
 #if defined(MBEDTLS_PADLOCK_C) &&                      \
     ( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) )
 static int aes_padlock_ace = -1;
@@ -409,7 +386,7 @@
     {
         pow[i] = x;
         log[x] = i;
-        x = ( x ^ XTIME( x ) ) & 0xFF;
+        x = MBEDTLS_BYTE_0( x ^ XTIME( x ) );
     }
 
     /*
@@ -418,7 +395,7 @@
     for( i = 0, x = 1; i < 10; i++ )
     {
         RCON[i] = (uint32_t) x;
-        x = XTIME( x ) & 0xFF;
+        x = MBEDTLS_BYTE_0( XTIME( x ) );
     }
 
     /*
@@ -431,10 +408,10 @@
     {
         x = pow[255 - log[i]];
 
-        y  = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
-        x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
-        x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
-        x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
+        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 ) );
         x ^= y ^ 0x63;
 
         FSb[i] = (unsigned char) x;
@@ -447,8 +424,8 @@
     for( i = 0; i < 256; i++ )
     {
         x = FSb[i];
-        y = XTIME( x ) & 0xFF;
-        z =  ( y ^ x ) & 0xFF;
+        y = MBEDTLS_BYTE_0( XTIME( x ) );
+        z = MBEDTLS_BYTE_0( y ^ x );
 
         FT0[i] = ( (uint32_t) y       ) ^
                  ( (uint32_t) x <<  8 ) ^
@@ -590,7 +567,7 @@
 
     for( i = 0; i < ( keybits >> 5 ); i++ )
     {
-        GET_UINT32_LE( RK[i], key, i << 2 );
+        RK[i] = MBEDTLS_GET_UINT32_LE( key, i << 2 );
     }
 
     switch( ctx->nr )
@@ -600,10 +577,10 @@
             for( i = 0; i < 10; i++, RK += 4 )
             {
                 RK[4]  = RK[0] ^ RCON[i] ^
-                ( (uint32_t) FSb[ ( RK[3] >>  8 ) & 0xFF ]       ) ^
-                ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] <<  8 ) ^
-                ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
-                ( (uint32_t) FSb[ ( RK[3]       ) & 0xFF ] << 24 );
+                ( (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 ) ^
+                ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[3] ) ] << 24 );
 
                 RK[5]  = RK[1] ^ RK[4];
                 RK[6]  = RK[2] ^ RK[5];
@@ -616,10 +593,10 @@
             for( i = 0; i < 8; i++, RK += 6 )
             {
                 RK[6]  = RK[0] ^ RCON[i] ^
-                ( (uint32_t) FSb[ ( RK[5] >>  8 ) & 0xFF ]       ) ^
-                ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] <<  8 ) ^
-                ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
-                ( (uint32_t) FSb[ ( RK[5]       ) & 0xFF ] << 24 );
+                ( (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 ) ^
+                ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[5] ) ] << 24 );
 
                 RK[7]  = RK[1] ^ RK[6];
                 RK[8]  = RK[2] ^ RK[7];
@@ -634,20 +611,20 @@
             for( i = 0; i < 7; i++, RK += 8 )
             {
                 RK[8]  = RK[0] ^ RCON[i] ^
-                ( (uint32_t) FSb[ ( RK[7] >>  8 ) & 0xFF ]       ) ^
-                ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] <<  8 ) ^
-                ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
-                ( (uint32_t) FSb[ ( RK[7]       ) & 0xFF ] << 24 );
+                ( (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 ) ^
+                ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[7] ) ] << 24 );
 
                 RK[9]  = RK[1] ^ RK[8];
                 RK[10] = RK[2] ^ RK[9];
                 RK[11] = RK[3] ^ RK[10];
 
                 RK[12] = RK[4] ^
-                ( (uint32_t) FSb[ ( RK[11]       ) & 0xFF ]       ) ^
-                ( (uint32_t) FSb[ ( RK[11] >>  8 ) & 0xFF ] <<  8 ) ^
-                ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
-                ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
+                ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[11] ) ]       ) ^
+                ( (uint32_t) FSb[ MBEDTLS_BYTE_1( RK[11] ) ] <<  8 ) ^
+                ( (uint32_t) FSb[ MBEDTLS_BYTE_2( RK[11] ) ] << 16 ) ^
+                ( (uint32_t) FSb[ MBEDTLS_BYTE_3( RK[11] ) ] << 24 );
 
                 RK[13] = RK[5] ^ RK[12];
                 RK[14] = RK[6] ^ RK[13];
@@ -713,10 +690,10 @@
     {
         for( j = 0; j < 4; j++, SK++ )
         {
-            *RK++ = AES_RT0( FSb[ ( *SK       ) & 0xFF ] ) ^
-                    AES_RT1( FSb[ ( *SK >>  8 ) & 0xFF ] ) ^
-                    AES_RT2( FSb[ ( *SK >> 16 ) & 0xFF ] ) ^
-                    AES_RT3( FSb[ ( *SK >> 24 ) & 0xFF ] );
+            *RK++ = AES_RT0( FSb[ MBEDTLS_BYTE_0( *SK ) ] ) ^
+                    AES_RT1( FSb[ MBEDTLS_BYTE_1( *SK ) ] ) ^
+                    AES_RT2( FSb[ MBEDTLS_BYTE_2( *SK ) ] ) ^
+                    AES_RT3( FSb[ MBEDTLS_BYTE_3( *SK ) ] );
         }
     }
 
@@ -809,52 +786,52 @@
 }
 #endif /* MBEDTLS_CIPHER_MODE_XTS */
 
-#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)                     \
-    do                                                          \
-    {                                                           \
-        (X0) = *RK++ ^ AES_FT0( ( (Y0)       ) & 0xFF ) ^       \
-                       AES_FT1( ( (Y1) >>  8 ) & 0xFF ) ^       \
-                       AES_FT2( ( (Y2) >> 16 ) & 0xFF ) ^       \
-                       AES_FT3( ( (Y3) >> 24 ) & 0xFF );        \
-                                                                \
-        (X1) = *RK++ ^ AES_FT0( ( (Y1)       ) & 0xFF ) ^       \
-                       AES_FT1( ( (Y2) >>  8 ) & 0xFF ) ^       \
-                       AES_FT2( ( (Y3) >> 16 ) & 0xFF ) ^       \
-                       AES_FT3( ( (Y0) >> 24 ) & 0xFF );        \
-                                                                \
-        (X2) = *RK++ ^ AES_FT0( ( (Y2)       ) & 0xFF ) ^       \
-                       AES_FT1( ( (Y3) >>  8 ) & 0xFF ) ^       \
-                       AES_FT2( ( (Y0) >> 16 ) & 0xFF ) ^       \
-                       AES_FT3( ( (Y1) >> 24 ) & 0xFF );        \
-                                                                \
-        (X3) = *RK++ ^ AES_FT0( ( (Y3)       ) & 0xFF ) ^       \
-                       AES_FT1( ( (Y0) >>  8 ) & 0xFF ) ^       \
-                       AES_FT2( ( (Y1) >> 16 ) & 0xFF ) ^       \
-                       AES_FT3( ( (Y2) >> 24 ) & 0xFF );        \
+#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)                 \
+    do                                                      \
+    {                                                       \
+        (X0) = *RK++ ^ AES_FT0( MBEDTLS_BYTE_0( Y0 ) ) ^    \
+                       AES_FT1( MBEDTLS_BYTE_1( Y1 ) ) ^    \
+                       AES_FT2( MBEDTLS_BYTE_2( Y2 ) ) ^    \
+                       AES_FT3( MBEDTLS_BYTE_3( Y3 ) );     \
+                                                            \
+        (X1) = *RK++ ^ AES_FT0( MBEDTLS_BYTE_0( Y1 ) ) ^    \
+                       AES_FT1( MBEDTLS_BYTE_1( Y2 ) ) ^    \
+                       AES_FT2( MBEDTLS_BYTE_2( Y3 ) ) ^    \
+                       AES_FT3( MBEDTLS_BYTE_3( Y0 ) );     \
+                                                            \
+        (X2) = *RK++ ^ AES_FT0( MBEDTLS_BYTE_0( Y2 ) ) ^    \
+                       AES_FT1( MBEDTLS_BYTE_1( Y3 ) ) ^    \
+                       AES_FT2( MBEDTLS_BYTE_2( Y0 ) ) ^    \
+                       AES_FT3( MBEDTLS_BYTE_3( Y1 ) );     \
+                                                            \
+        (X3) = *RK++ ^ AES_FT0( MBEDTLS_BYTE_0( Y3 ) ) ^    \
+                       AES_FT1( MBEDTLS_BYTE_1( Y0 ) ) ^    \
+                       AES_FT2( MBEDTLS_BYTE_2( Y1 ) ) ^    \
+                       AES_FT3( MBEDTLS_BYTE_3( Y2 ) );     \
     } while( 0 )
 
 #define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)                 \
     do                                                      \
     {                                                       \
-        (X0) = *RK++ ^ AES_RT0( ( (Y0)       ) & 0xFF ) ^   \
-                       AES_RT1( ( (Y3) >>  8 ) & 0xFF ) ^   \
-                       AES_RT2( ( (Y2) >> 16 ) & 0xFF ) ^   \
-                       AES_RT3( ( (Y1) >> 24 ) & 0xFF );    \
+        (X0) = *RK++ ^ AES_RT0( MBEDTLS_BYTE_0( Y0 ) ) ^    \
+                       AES_RT1( MBEDTLS_BYTE_1( Y3 ) ) ^    \
+                       AES_RT2( MBEDTLS_BYTE_2( Y2 ) ) ^    \
+                       AES_RT3( MBEDTLS_BYTE_3( Y1 ) );     \
                                                             \
-        (X1) = *RK++ ^ AES_RT0( ( (Y1)       ) & 0xFF ) ^   \
-                       AES_RT1( ( (Y0) >>  8 ) & 0xFF ) ^   \
-                       AES_RT2( ( (Y3) >> 16 ) & 0xFF ) ^   \
-                       AES_RT3( ( (Y2) >> 24 ) & 0xFF );    \
+        (X1) = *RK++ ^ AES_RT0( MBEDTLS_BYTE_0( Y1 ) ) ^    \
+                       AES_RT1( MBEDTLS_BYTE_1( Y0 ) ) ^    \
+                       AES_RT2( MBEDTLS_BYTE_2( Y3 ) ) ^    \
+                       AES_RT3( MBEDTLS_BYTE_3( Y2 ) );     \
                                                             \
-        (X2) = *RK++ ^ AES_RT0( ( (Y2)       ) & 0xFF ) ^   \
-                       AES_RT1( ( (Y1) >>  8 ) & 0xFF ) ^   \
-                       AES_RT2( ( (Y0) >> 16 ) & 0xFF ) ^   \
-                       AES_RT3( ( (Y3) >> 24 ) & 0xFF );    \
+        (X2) = *RK++ ^ AES_RT0( MBEDTLS_BYTE_0( Y2 ) ) ^    \
+                       AES_RT1( MBEDTLS_BYTE_1( Y1 ) ) ^    \
+                       AES_RT2( MBEDTLS_BYTE_2( Y0 ) ) ^    \
+                       AES_RT3( MBEDTLS_BYTE_3( Y3 ) );     \
                                                             \
-        (X3) = *RK++ ^ AES_RT0( ( (Y3)       ) & 0xFF ) ^   \
-                       AES_RT1( ( (Y2) >>  8 ) & 0xFF ) ^   \
-                       AES_RT2( ( (Y1) >> 16 ) & 0xFF ) ^   \
-                       AES_RT3( ( (Y0) >> 24 ) & 0xFF );    \
+        (X3) = *RK++ ^ AES_RT0( MBEDTLS_BYTE_0( Y3 ) ) ^    \
+                       AES_RT1( MBEDTLS_BYTE_1( Y2 ) ) ^    \
+                       AES_RT2( MBEDTLS_BYTE_2( Y1 ) ) ^    \
+                       AES_RT3( MBEDTLS_BYTE_3( Y0 ) );     \
     } while( 0 )
 
 /*
@@ -873,10 +850,10 @@
         uint32_t Y[4];
     } t;
 
-    GET_UINT32_LE( t.X[0], input,  0 ); t.X[0] ^= *RK++;
-    GET_UINT32_LE( t.X[1], input,  4 ); t.X[1] ^= *RK++;
-    GET_UINT32_LE( t.X[2], input,  8 ); t.X[2] ^= *RK++;
-    GET_UINT32_LE( t.X[3], input, 12 ); t.X[3] ^= *RK++;
+    t.X[0] = MBEDTLS_GET_UINT32_LE( input,  0 ); t.X[0] ^= *RK++;
+    t.X[1] = MBEDTLS_GET_UINT32_LE( input,  4 ); t.X[1] ^= *RK++;
+    t.X[2] = MBEDTLS_GET_UINT32_LE( input,  8 ); t.X[2] ^= *RK++;
+    t.X[3] = MBEDTLS_GET_UINT32_LE( input, 12 ); t.X[3] ^= *RK++;
 
     for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
     {
@@ -887,33 +864,33 @@
     AES_FROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] );
 
     t.X[0] = *RK++ ^ \
-            ( (uint32_t) FSb[ ( t.Y[0]       ) & 0xFF ]       ) ^
-            ( (uint32_t) FSb[ ( t.Y[1] >>  8 ) & 0xFF ] <<  8 ) ^
-            ( (uint32_t) FSb[ ( t.Y[2] >> 16 ) & 0xFF ] << 16 ) ^
-            ( (uint32_t) FSb[ ( t.Y[3] >> 24 ) & 0xFF ] << 24 );
+            ( (uint32_t) FSb[ MBEDTLS_BYTE_0( t.Y[0] ) ]       ) ^
+            ( (uint32_t) FSb[ MBEDTLS_BYTE_1( t.Y[1] ) ] <<  8 ) ^
+            ( (uint32_t) FSb[ MBEDTLS_BYTE_2( t.Y[2] ) ] << 16 ) ^
+            ( (uint32_t) FSb[ MBEDTLS_BYTE_3( t.Y[3] ) ] << 24 );
 
     t.X[1] = *RK++ ^ \
-            ( (uint32_t) FSb[ ( t.Y[1]       ) & 0xFF ]       ) ^
-            ( (uint32_t) FSb[ ( t.Y[2] >>  8 ) & 0xFF ] <<  8 ) ^
-            ( (uint32_t) FSb[ ( t.Y[3] >> 16 ) & 0xFF ] << 16 ) ^
-            ( (uint32_t) FSb[ ( t.Y[0] >> 24 ) & 0xFF ] << 24 );
+            ( (uint32_t) FSb[ MBEDTLS_BYTE_0( t.Y[1] ) ]       ) ^
+            ( (uint32_t) FSb[ MBEDTLS_BYTE_1( t.Y[2] ) ] <<  8 ) ^
+            ( (uint32_t) FSb[ MBEDTLS_BYTE_2( t.Y[3] ) ] << 16 ) ^
+            ( (uint32_t) FSb[ MBEDTLS_BYTE_3( t.Y[0] ) ] << 24 );
 
     t.X[2] = *RK++ ^ \
-            ( (uint32_t) FSb[ ( t.Y[2]       ) & 0xFF ]       ) ^
-            ( (uint32_t) FSb[ ( t.Y[3] >>  8 ) & 0xFF ] <<  8 ) ^
-            ( (uint32_t) FSb[ ( t.Y[0] >> 16 ) & 0xFF ] << 16 ) ^
-            ( (uint32_t) FSb[ ( t.Y[1] >> 24 ) & 0xFF ] << 24 );
+            ( (uint32_t) FSb[ MBEDTLS_BYTE_0( t.Y[2] ) ]       ) ^
+            ( (uint32_t) FSb[ MBEDTLS_BYTE_1( t.Y[3] ) ] <<  8 ) ^
+            ( (uint32_t) FSb[ MBEDTLS_BYTE_2( t.Y[0] ) ] << 16 ) ^
+            ( (uint32_t) FSb[ MBEDTLS_BYTE_3( t.Y[1] ) ] << 24 );
 
     t.X[3] = *RK++ ^ \
-            ( (uint32_t) FSb[ ( t.Y[3]       ) & 0xFF ]       ) ^
-            ( (uint32_t) FSb[ ( t.Y[0] >>  8 ) & 0xFF ] <<  8 ) ^
-            ( (uint32_t) FSb[ ( t.Y[1] >> 16 ) & 0xFF ] << 16 ) ^
-            ( (uint32_t) FSb[ ( t.Y[2] >> 24 ) & 0xFF ] << 24 );
+            ( (uint32_t) FSb[ MBEDTLS_BYTE_0( t.Y[3] ) ]       ) ^
+            ( (uint32_t) FSb[ MBEDTLS_BYTE_1( t.Y[0] ) ] <<  8 ) ^
+            ( (uint32_t) FSb[ MBEDTLS_BYTE_2( t.Y[1] ) ] << 16 ) ^
+            ( (uint32_t) FSb[ MBEDTLS_BYTE_3( t.Y[2] ) ] << 24 );
 
-    PUT_UINT32_LE( t.X[0], output,  0 );
-    PUT_UINT32_LE( t.X[1], output,  4 );
-    PUT_UINT32_LE( t.X[2], output,  8 );
-    PUT_UINT32_LE( t.X[3], output, 12 );
+    MBEDTLS_PUT_UINT32_LE( t.X[0], output,  0 );
+    MBEDTLS_PUT_UINT32_LE( t.X[1], output,  4 );
+    MBEDTLS_PUT_UINT32_LE( t.X[2], output,  8 );
+    MBEDTLS_PUT_UINT32_LE( t.X[3], output, 12 );
 
     mbedtls_platform_zeroize( &t, sizeof( t ) );
 
@@ -926,7 +903,7 @@
                           const unsigned char input[16],
                           unsigned char output[16] )
 {
-    mbedtls_internal_aes_encrypt( ctx, input, output );
+    MBEDTLS_IGNORE_RETURN( mbedtls_internal_aes_encrypt( ctx, input, output ) );
 }
 #endif /* !MBEDTLS_DEPRECATED_REMOVED */
 
@@ -946,10 +923,10 @@
         uint32_t Y[4];
     } t;
 
-    GET_UINT32_LE( t.X[0], input,  0 ); t.X[0] ^= *RK++;
-    GET_UINT32_LE( t.X[1], input,  4 ); t.X[1] ^= *RK++;
-    GET_UINT32_LE( t.X[2], input,  8 ); t.X[2] ^= *RK++;
-    GET_UINT32_LE( t.X[3], input, 12 ); t.X[3] ^= *RK++;
+    t.X[0] = MBEDTLS_GET_UINT32_LE( input,  0 ); t.X[0] ^= *RK++;
+    t.X[1] = MBEDTLS_GET_UINT32_LE( input,  4 ); t.X[1] ^= *RK++;
+    t.X[2] = MBEDTLS_GET_UINT32_LE( input,  8 ); t.X[2] ^= *RK++;
+    t.X[3] = MBEDTLS_GET_UINT32_LE( input, 12 ); t.X[3] ^= *RK++;
 
     for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
     {
@@ -960,33 +937,33 @@
     AES_RROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] );
 
     t.X[0] = *RK++ ^ \
-            ( (uint32_t) RSb[ ( t.Y[0]       ) & 0xFF ]       ) ^
-            ( (uint32_t) RSb[ ( t.Y[3] >>  8 ) & 0xFF ] <<  8 ) ^
-            ( (uint32_t) RSb[ ( t.Y[2] >> 16 ) & 0xFF ] << 16 ) ^
-            ( (uint32_t) RSb[ ( t.Y[1] >> 24 ) & 0xFF ] << 24 );
+            ( (uint32_t) RSb[ MBEDTLS_BYTE_0( t.Y[0] ) ]       ) ^
+            ( (uint32_t) RSb[ MBEDTLS_BYTE_1( t.Y[3] ) ] <<  8 ) ^
+            ( (uint32_t) RSb[ MBEDTLS_BYTE_2( t.Y[2] ) ] << 16 ) ^
+            ( (uint32_t) RSb[ MBEDTLS_BYTE_3( t.Y[1] ) ] << 24 );
 
     t.X[1] = *RK++ ^ \
-            ( (uint32_t) RSb[ ( t.Y[1]       ) & 0xFF ]       ) ^
-            ( (uint32_t) RSb[ ( t.Y[0] >>  8 ) & 0xFF ] <<  8 ) ^
-            ( (uint32_t) RSb[ ( t.Y[3] >> 16 ) & 0xFF ] << 16 ) ^
-            ( (uint32_t) RSb[ ( t.Y[2] >> 24 ) & 0xFF ] << 24 );
+            ( (uint32_t) RSb[ MBEDTLS_BYTE_0( t.Y[1] ) ]       ) ^
+            ( (uint32_t) RSb[ MBEDTLS_BYTE_1( t.Y[0] ) ] <<  8 ) ^
+            ( (uint32_t) RSb[ MBEDTLS_BYTE_2( t.Y[3] ) ] << 16 ) ^
+            ( (uint32_t) RSb[ MBEDTLS_BYTE_3( t.Y[2] ) ] << 24 );
 
     t.X[2] = *RK++ ^ \
-            ( (uint32_t) RSb[ ( t.Y[2]       ) & 0xFF ]       ) ^
-            ( (uint32_t) RSb[ ( t.Y[1] >>  8 ) & 0xFF ] <<  8 ) ^
-            ( (uint32_t) RSb[ ( t.Y[0] >> 16 ) & 0xFF ] << 16 ) ^
-            ( (uint32_t) RSb[ ( t.Y[3] >> 24 ) & 0xFF ] << 24 );
+            ( (uint32_t) RSb[ MBEDTLS_BYTE_0( t.Y[2] ) ]       ) ^
+            ( (uint32_t) RSb[ MBEDTLS_BYTE_1( t.Y[1] ) ] <<  8 ) ^
+            ( (uint32_t) RSb[ MBEDTLS_BYTE_2( t.Y[0] ) ] << 16 ) ^
+            ( (uint32_t) RSb[ MBEDTLS_BYTE_3( t.Y[3] ) ] << 24 );
 
     t.X[3] = *RK++ ^ \
-            ( (uint32_t) RSb[ ( t.Y[3]       ) & 0xFF ]       ) ^
-            ( (uint32_t) RSb[ ( t.Y[2] >>  8 ) & 0xFF ] <<  8 ) ^
-            ( (uint32_t) RSb[ ( t.Y[1] >> 16 ) & 0xFF ] << 16 ) ^
-            ( (uint32_t) RSb[ ( t.Y[0] >> 24 ) & 0xFF ] << 24 );
+            ( (uint32_t) RSb[ MBEDTLS_BYTE_0( t.Y[3] ) ]       ) ^
+            ( (uint32_t) RSb[ MBEDTLS_BYTE_1( t.Y[2] ) ] <<  8 ) ^
+            ( (uint32_t) RSb[ MBEDTLS_BYTE_2( t.Y[1] ) ] << 16 ) ^
+            ( (uint32_t) RSb[ MBEDTLS_BYTE_3( t.Y[0] ) ] << 24 );
 
-    PUT_UINT32_LE( t.X[0], output,  0 );
-    PUT_UINT32_LE( t.X[1], output,  4 );
-    PUT_UINT32_LE( t.X[2], output,  8 );
-    PUT_UINT32_LE( t.X[3], output, 12 );
+    MBEDTLS_PUT_UINT32_LE( t.X[0], output,  0 );
+    MBEDTLS_PUT_UINT32_LE( t.X[1], output,  4 );
+    MBEDTLS_PUT_UINT32_LE( t.X[2], output,  8 );
+    MBEDTLS_PUT_UINT32_LE( t.X[3], output, 12 );
 
     mbedtls_platform_zeroize( &t, sizeof( t ) );
 
@@ -999,7 +976,7 @@
                           const unsigned char input[16],
                           unsigned char output[16] )
 {
-    mbedtls_internal_aes_decrypt( ctx, input, output );
+    MBEDTLS_IGNORE_RETURN( mbedtls_internal_aes_decrypt( ctx, input, output ) );
 }
 #endif /* !MBEDTLS_DEPRECATED_REMOVED */
 
@@ -1052,6 +1029,7 @@
                     unsigned char *output )
 {
     int i;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char temp[16];
 
     AES_VALIDATE_RET( ctx != NULL );
@@ -1081,7 +1059,9 @@
         while( length > 0 )
         {
             memcpy( temp, input, 16 );
-            mbedtls_aes_crypt_ecb( ctx, mode, input, output );
+            ret = mbedtls_aes_crypt_ecb( ctx, mode, input, output );
+            if( ret != 0 )
+                goto exit;
 
             for( i = 0; i < 16; i++ )
                 output[i] = (unsigned char)( output[i] ^ iv[i] );
@@ -1100,7 +1080,9 @@
             for( i = 0; i < 16; i++ )
                 output[i] = (unsigned char)( input[i] ^ iv[i] );
 
-            mbedtls_aes_crypt_ecb( ctx, mode, output, output );
+            ret = mbedtls_aes_crypt_ecb( ctx, mode, output, output );
+            if( ret != 0 )
+                goto exit;
             memcpy( iv, output, 16 );
 
             input  += 16;
@@ -1108,42 +1090,15 @@
             length -= 16;
         }
     }
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_CIPHER_MODE_XTS)
 
-/* Endianess with 64 bits values */
-#ifndef GET_UINT64_LE
-#define GET_UINT64_LE(n,b,i)                            \
-{                                                       \
-    (n) = ( (uint64_t) (b)[(i) + 7] << 56 )             \
-        | ( (uint64_t) (b)[(i) + 6] << 48 )             \
-        | ( (uint64_t) (b)[(i) + 5] << 40 )             \
-        | ( (uint64_t) (b)[(i) + 4] << 32 )             \
-        | ( (uint64_t) (b)[(i) + 3] << 24 )             \
-        | ( (uint64_t) (b)[(i) + 2] << 16 )             \
-        | ( (uint64_t) (b)[(i) + 1] <<  8 )             \
-        | ( (uint64_t) (b)[(i)    ]       );            \
-}
-#endif
-
-#ifndef PUT_UINT64_LE
-#define PUT_UINT64_LE(n,b,i)                            \
-{                                                       \
-    (b)[(i) + 7] = (unsigned char) ( (n) >> 56 );       \
-    (b)[(i) + 6] = (unsigned char) ( (n) >> 48 );       \
-    (b)[(i) + 5] = (unsigned char) ( (n) >> 40 );       \
-    (b)[(i) + 4] = (unsigned char) ( (n) >> 32 );       \
-    (b)[(i) + 3] = (unsigned char) ( (n) >> 24 );       \
-    (b)[(i) + 2] = (unsigned char) ( (n) >> 16 );       \
-    (b)[(i) + 1] = (unsigned char) ( (n) >>  8 );       \
-    (b)[(i)    ] = (unsigned char) ( (n)       );       \
-}
-#endif
-
 typedef unsigned char mbedtls_be128[16];
 
 /*
@@ -1159,14 +1114,14 @@
 {
     uint64_t a, b, ra, rb;
 
-    GET_UINT64_LE( a, x, 0 );
-    GET_UINT64_LE( b, x, 8 );
+    a = MBEDTLS_GET_UINT64_LE( x, 0 );
+    b = MBEDTLS_GET_UINT64_LE( x, 8 );
 
     ra = ( a << 1 )  ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) );
     rb = ( a >> 63 ) | ( b << 1 );
 
-    PUT_UINT64_LE( ra, r, 0 );
-    PUT_UINT64_LE( rb, r, 8 );
+    MBEDTLS_PUT_UINT64_LE( ra, r, 0 );
+    MBEDTLS_PUT_UINT64_LE( rb, r, 8 );
 }
 
 /*
@@ -1292,6 +1247,7 @@
                        unsigned char *output )
 {
     int c;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
 
     AES_VALIDATE_RET( ctx != NULL );
@@ -1312,7 +1268,11 @@
         while( length-- )
         {
             if( n == 0 )
-                mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+            {
+                ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+                if( ret != 0 )
+                    goto exit;
+            }
 
             c = *input++;
             *output++ = (unsigned char)( c ^ iv[n] );
@@ -1326,7 +1286,11 @@
         while( length-- )
         {
             if( n == 0 )
-                mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+            {
+                ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+                if( ret != 0 )
+                    goto exit;
+            }
 
             iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
 
@@ -1335,8 +1299,10 @@
     }
 
     *iv_off = n;
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 
 /*
@@ -1349,6 +1315,7 @@
                             const unsigned char *input,
                             unsigned char *output )
 {
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char c;
     unsigned char ov[17];
 
@@ -1361,7 +1328,9 @@
     while( length-- )
     {
         memcpy( ov, iv, 16 );
-        mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+        ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+        if( ret != 0 )
+            goto exit;
 
         if( mode == MBEDTLS_AES_DECRYPT )
             ov[16] = *input;
@@ -1373,8 +1342,10 @@
 
         memcpy( iv, ov + 1, 16 );
     }
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
@@ -1436,6 +1407,7 @@
                        unsigned char *output )
 {
     int c, i;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
 
     AES_VALIDATE_RET( ctx != NULL );
@@ -1453,7 +1425,9 @@
     while( length-- )
     {
         if( n == 0 ) {
-            mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block );
+            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 )
@@ -1466,8 +1440,10 @@
     }
 
     *nc_off = n;
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
diff --git a/third_party/mbedtls/repo/library/aria.c b/third_party/mbedtls/repo/library/aria.c
index 1875635..bc05c4a 100644
--- a/third_party/mbedtls/repo/library/aria.c
+++ b/third_party/mbedtls/repo/library/aria.c
@@ -56,29 +56,6 @@
     MBEDTLS_INTERNAL_VALIDATE( cond )
 
 /*
- * 32-bit integer manipulation macros (little endian)
- */
-#ifndef GET_UINT32_LE
-#define GET_UINT32_LE( n, b, i )                \
-{                                               \
-    (n) = ( (uint32_t) (b)[(i)    ]       )     \
-        | ( (uint32_t) (b)[(i) + 1] <<  8 )     \
-        | ( (uint32_t) (b)[(i) + 2] << 16 )     \
-        | ( (uint32_t) (b)[(i) + 3] << 24 );    \
-}
-#endif
-
-#ifndef PUT_UINT32_LE
-#define PUT_UINT32_LE( n, b, i )                                \
-{                                                               \
-    (b)[(i)    ] = (unsigned char) ( ( (n)       ) & 0xFF );    \
-    (b)[(i) + 1] = (unsigned char) ( ( (n) >>  8 ) & 0xFF );    \
-    (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF );    \
-    (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF );    \
-}
-#endif
-
-/*
  * modify byte order: ( A B C D ) -> ( B A D C ), i.e. swap pairs of bytes
  *
  * This is submatrix P1 in [1] Appendix B.1
@@ -235,22 +212,22 @@
                             const uint8_t sa[256], const uint8_t sb[256],
                             const uint8_t sc[256], const uint8_t sd[256] )
 {
-    *a = ( (uint32_t) sa[ *a        & 0xFF]       ) ^
-         (((uint32_t) sb[(*a >>  8) & 0xFF]) <<  8) ^
-         (((uint32_t) sc[(*a >> 16) & 0xFF]) << 16) ^
-         (((uint32_t) sd[ *a >> 24        ]) << 24);
-    *b = ( (uint32_t) sa[ *b        & 0xFF]       ) ^
-         (((uint32_t) sb[(*b >>  8) & 0xFF]) <<  8) ^
-         (((uint32_t) sc[(*b >> 16) & 0xFF]) << 16) ^
-         (((uint32_t) sd[ *b >> 24        ]) << 24);
-    *c = ( (uint32_t) sa[ *c        & 0xFF]       ) ^
-         (((uint32_t) sb[(*c >>  8) & 0xFF]) <<  8) ^
-         (((uint32_t) sc[(*c >> 16) & 0xFF]) << 16) ^
-         (((uint32_t) sd[ *c >> 24        ]) << 24);
-    *d = ( (uint32_t) sa[ *d        & 0xFF]       ) ^
-         (((uint32_t) sb[(*d >>  8) & 0xFF]) <<  8) ^
-         (((uint32_t) sc[(*d >> 16) & 0xFF]) << 16) ^
-         (((uint32_t) sd[ *d >> 24        ]) << 24);
+    *a = ( (uint32_t) sa[ MBEDTLS_BYTE_0( *a ) ]       ) ^
+         (((uint32_t) sb[ MBEDTLS_BYTE_1( *a ) ]) <<  8) ^
+         (((uint32_t) sc[ MBEDTLS_BYTE_2( *a ) ]) << 16) ^
+         (((uint32_t) sd[ MBEDTLS_BYTE_3( *a ) ]) << 24);
+    *b = ( (uint32_t) sa[ MBEDTLS_BYTE_0( *b ) ]       ) ^
+         (((uint32_t) sb[ MBEDTLS_BYTE_1( *b ) ]) <<  8) ^
+         (((uint32_t) sc[ MBEDTLS_BYTE_2( *b ) ]) << 16) ^
+         (((uint32_t) sd[ MBEDTLS_BYTE_3( *b ) ]) << 24);
+    *c = ( (uint32_t) sa[ MBEDTLS_BYTE_0( *c ) ]       ) ^
+         (((uint32_t) sb[ MBEDTLS_BYTE_1( *c ) ]) <<  8) ^
+         (((uint32_t) sc[ MBEDTLS_BYTE_2( *c ) ]) << 16) ^
+         (((uint32_t) sd[ MBEDTLS_BYTE_3( *c ) ]) << 24);
+    *d = ( (uint32_t) sa[ MBEDTLS_BYTE_0( *d ) ]       ) ^
+         (((uint32_t) sb[ MBEDTLS_BYTE_1( *d ) ]) <<  8) ^
+         (((uint32_t) sc[ MBEDTLS_BYTE_2( *d ) ]) << 16) ^
+         (((uint32_t) sd[ MBEDTLS_BYTE_3( *d ) ]) << 24);
 }
 
 /*
@@ -408,7 +385,8 @@
  * Big endian 128-bit rotation: r = a ^ (b <<< n), used only in key setup.
  *
  * We chose to store bytes into 32-bit words in little-endian format (see
- * GET/PUT_UINT32_LE) so we need to reverse bytes here.
+ * MBEDTLS_GET_UINT32_LE / MBEDTLS_PUT_UINT32_LE ) so we need to reverse
+ * bytes here.
  */
 static void aria_rot128( uint32_t r[4], const uint32_t a[4],
                          const uint32_t b[4], uint8_t n )
@@ -456,21 +434,21 @@
         return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA );
 
     /* Copy key to W0 (and potential remainder to W1) */
-    GET_UINT32_LE( w[0][0], key,  0 );
-    GET_UINT32_LE( w[0][1], key,  4 );
-    GET_UINT32_LE( w[0][2], key,  8 );
-    GET_UINT32_LE( w[0][3], key, 12 );
+    w[0][0] = MBEDTLS_GET_UINT32_LE( key,  0 );
+    w[0][1] = MBEDTLS_GET_UINT32_LE( key,  4 );
+    w[0][2] = MBEDTLS_GET_UINT32_LE( key,  8 );
+    w[0][3] = MBEDTLS_GET_UINT32_LE( key, 12 );
 
     memset( w[1], 0, 16 );
     if( keybits >= 192 )
     {
-        GET_UINT32_LE( w[1][0], key, 16 );  // 192 bit key
-        GET_UINT32_LE( w[1][1], key, 20 );
+        w[1][0] = MBEDTLS_GET_UINT32_LE( key, 16 );  // 192 bit key
+        w[1][1] = MBEDTLS_GET_UINT32_LE( key, 20 );
     }
     if( keybits == 256 )
     {
-        GET_UINT32_LE( w[1][2], key, 24 );  // 256 bit key
-        GET_UINT32_LE( w[1][3], key, 28 );
+        w[1][2] = MBEDTLS_GET_UINT32_LE( key, 24 );  // 256 bit key
+        w[1][3] = MBEDTLS_GET_UINT32_LE( key, 28 );
     }
 
     i = ( keybits - 128 ) >> 6;             // index: 0, 1, 2
@@ -547,10 +525,10 @@
     ARIA_VALIDATE_RET( input != NULL );
     ARIA_VALIDATE_RET( output != NULL );
 
-    GET_UINT32_LE( a, input,  0 );
-    GET_UINT32_LE( b, input,  4 );
-    GET_UINT32_LE( c, input,  8 );
-    GET_UINT32_LE( d, input, 12 );
+    a = MBEDTLS_GET_UINT32_LE( input,  0 );
+    b = MBEDTLS_GET_UINT32_LE( input,  4 );
+    c = MBEDTLS_GET_UINT32_LE( input,  8 );
+    d = MBEDTLS_GET_UINT32_LE( input, 12 );
 
     i = 0;
     while( 1 )
@@ -582,10 +560,10 @@
     c ^= ctx->rk[i][2];
     d ^= ctx->rk[i][3];
 
-    PUT_UINT32_LE( a, output,  0 );
-    PUT_UINT32_LE( b, output,  4 );
-    PUT_UINT32_LE( c, output,  8 );
-    PUT_UINT32_LE( d, output, 12 );
+    MBEDTLS_PUT_UINT32_LE( a, output,  0 );
+    MBEDTLS_PUT_UINT32_LE( b, output,  4 );
+    MBEDTLS_PUT_UINT32_LE( c, output,  8 );
+    MBEDTLS_PUT_UINT32_LE( d, output, 12 );
 
     return( 0 );
 }
@@ -921,7 +899,7 @@
         {                                   \
             if( verbose )                   \
                 mbedtls_printf( "failed\n" );       \
-            return( 1 );                    \
+            goto exit;                              \
         } else {                            \
             if( verbose )                   \
                 mbedtls_printf( "passed\n" );       \
@@ -935,6 +913,7 @@
     int i;
     uint8_t blk[MBEDTLS_ARIA_BLOCKSIZE];
     mbedtls_aria_context ctx;
+    int ret = 1;
 
 #if (defined(MBEDTLS_CIPHER_MODE_CFB) || defined(MBEDTLS_CIPHER_MODE_CTR))
     size_t j;
@@ -946,6 +925,8 @@
     uint8_t buf[48], iv[MBEDTLS_ARIA_BLOCKSIZE];
 #endif
 
+    mbedtls_aria_init( &ctx );
+
     /*
      * Test set 1
      */
@@ -1065,7 +1046,11 @@
         mbedtls_printf( "\n" );
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
-    return( 0 );
+    ret = 0;
+
+exit:
+    mbedtls_aria_free( &ctx );
+    return( ret );
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/third_party/mbedtls/repo/library/asn1write.c b/third_party/mbedtls/repo/library/asn1write.c
index deb1a2f..3811ef2 100644
--- a/third_party/mbedtls/repo/library/asn1write.c
+++ b/third_party/mbedtls/repo/library/asn1write.c
@@ -60,8 +60,8 @@
         if( *p - start < 3 )
             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
 
-        *--(*p) = ( len       ) & 0xFF;
-        *--(*p) = ( len >>  8 ) & 0xFF;
+        *--(*p) = MBEDTLS_BYTE_0( len );
+        *--(*p) = MBEDTLS_BYTE_1( len );
         *--(*p) = 0x82;
         return( 3 );
     }
@@ -71,9 +71,9 @@
         if( *p - start < 4 )
             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
 
-        *--(*p) = ( len       ) & 0xFF;
-        *--(*p) = ( len >>  8 ) & 0xFF;
-        *--(*p) = ( len >> 16 ) & 0xFF;
+        *--(*p) = MBEDTLS_BYTE_0( len );
+        *--(*p) = MBEDTLS_BYTE_1( len );
+        *--(*p) = MBEDTLS_BYTE_2( len );
         *--(*p) = 0x83;
         return( 4 );
     }
@@ -85,10 +85,10 @@
         if( *p - start < 5 )
             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
 
-        *--(*p) = ( len       ) & 0xFF;
-        *--(*p) = ( len >>  8 ) & 0xFF;
-        *--(*p) = ( len >> 16 ) & 0xFF;
-        *--(*p) = ( len >> 24 ) & 0xFF;
+        *--(*p) = MBEDTLS_BYTE_0( len );
+        *--(*p) = MBEDTLS_BYTE_1( len );
+        *--(*p) = MBEDTLS_BYTE_2( len );
+        *--(*p) = MBEDTLS_BYTE_3( len );
         *--(*p) = 0x84;
         return( 5 );
     }
diff --git a/third_party/mbedtls/repo/library/base64.c b/third_party/mbedtls/repo/library/base64.c
index d39474a..83daa0b 100644
--- a/third_party/mbedtls/repo/library/base64.c
+++ b/third_party/mbedtls/repo/library/base64.c
@@ -22,6 +22,7 @@
 #if defined(MBEDTLS_BASE64_C)
 
 #include "mbedtls/base64.h"
+#include "constant_time_internal.h"
 
 #include <stdint.h>
 
@@ -35,34 +36,6 @@
 #endif /* MBEDTLS_PLATFORM_C */
 #endif /* MBEDTLS_SELF_TEST */
 
-static const unsigned char base64_enc_map[64] =
-{
-    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
-    'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
-    'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
-    'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
-    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
-    'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
-    '8', '9', '+', '/'
-};
-
-static const unsigned char base64_dec_map[128] =
-{
-    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
-    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
-    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
-    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
-    127, 127, 127,  62, 127, 127, 127,  63,  52,  53,
-     54,  55,  56,  57,  58,  59,  60,  61, 127, 127,
-    127,  64, 127, 127, 127,   0,   1,   2,   3,   4,
-      5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
-     15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
-     25, 127, 127, 127, 127, 127, 127,  26,  27,  28,
-     29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
-     39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
-     49,  50,  51, 127, 127, 127, 127, 127
-};
-
 #define BASE64_SIZE_T_MAX   ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
 
 /*
@@ -105,10 +78,12 @@
         C2 = *src++;
         C3 = *src++;
 
-        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
-        *p++ = base64_enc_map[(((C1 &  3) << 4) + (C2 >> 4)) & 0x3F];
-        *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
-        *p++ = base64_enc_map[C3 & 0x3F];
+        *p++ = mbedtls_ct_base64_enc_char( ( C1 >> 2 ) & 0x3F );
+        *p++ = mbedtls_ct_base64_enc_char( ( ( ( C1 &  3 ) << 4 ) + ( C2 >> 4 ) )
+                                        & 0x3F );
+        *p++ = mbedtls_ct_base64_enc_char( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) )
+                                        & 0x3F );
+        *p++ = mbedtls_ct_base64_enc_char( C3 & 0x3F );
     }
 
     if( i < slen )
@@ -116,11 +91,12 @@
         C1 = *src++;
         C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
 
-        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
-        *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
+        *p++ = mbedtls_ct_base64_enc_char( ( C1 >> 2 ) & 0x3F );
+        *p++ = mbedtls_ct_base64_enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) )
+                                        & 0x3F );
 
         if( ( i + 1 ) < slen )
-             *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
+             *p++ = mbedtls_ct_base64_enc_char( ( ( C2 & 15 ) << 2 ) & 0x3F );
         else *p++ = '=';
 
         *p++ = '=';
@@ -138,19 +114,23 @@
 int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
                    const unsigned char *src, size_t slen )
 {
-    size_t i, n;
-    uint32_t j, x;
+    size_t i; /* index in source */
+    size_t n; /* number of digits or trailing = in source */
+    uint32_t x; /* value accumulator */
+    unsigned accumulated_digits = 0;
+    unsigned equals = 0;
+    int spaces_present = 0;
     unsigned char *p;
 
     /* First pass: check for validity and get output length */
-    for( i = n = j = 0; i < slen; i++ )
+    for( i = n = 0; i < slen; i++ )
     {
         /* Skip spaces before checking for EOL */
-        x = 0;
+        spaces_present = 0;
         while( i < slen && src[i] == ' ' )
         {
             ++i;
-            ++x;
+            spaces_present = 1;
         }
 
         /* Spaces at end of buffer are OK */
@@ -165,18 +145,24 @@
             continue;
 
         /* Space inside a line is an error */
-        if( x != 0 )
+        if( spaces_present )
             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
 
-        if( src[i] == '=' && ++j > 2 )
+        if( src[i] > 127 )
             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
 
-        if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
-            return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
-
-        if( base64_dec_map[src[i]] < 64 && j != 0 )
-            return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
-
+        if( src[i] == '=' )
+        {
+            if( ++equals > 2 )
+                return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+        }
+        else
+        {
+            if( equals != 0 )
+                return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+            if( mbedtls_ct_base64_dec_value( src[i] ) < 0 )
+                return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+        }
         n++;
     }
 
@@ -191,7 +177,7 @@
      *     n = ( ( n * 6 ) + 7 ) >> 3;
      */
     n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 );
-    n -= j;
+    n -= equals;
 
     if( dst == NULL || dlen < n )
     {
@@ -199,20 +185,24 @@
         return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
     }
 
-   for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
-   {
+    equals = 0;
+    for( x = 0, p = dst; i > 0; i--, src++ )
+    {
         if( *src == '\r' || *src == '\n' || *src == ' ' )
             continue;
 
-        j -= ( base64_dec_map[*src] == 64 );
-        x  = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
+        x = x << 6;
+        if( *src == '=' )
+            ++equals;
+        else
+            x |= mbedtls_ct_base64_dec_value( *src );
 
-        if( ++n == 4 )
+        if( ++accumulated_digits == 4 )
         {
-            n = 0;
-            if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
-            if( j > 1 ) *p++ = (unsigned char)( x >>  8 );
-            if( j > 2 ) *p++ = (unsigned char)( x       );
+            accumulated_digits = 0;
+            *p++ = MBEDTLS_BYTE_2( x );
+            if( equals <= 1 ) *p++ = MBEDTLS_BYTE_1( x );
+            if( equals <= 0 ) *p++ = MBEDTLS_BYTE_0( x );
         }
     }
 
diff --git a/third_party/mbedtls/repo/library/bignum.c b/third_party/mbedtls/repo/library/bignum.c
index 9cc5d66..62e7f76 100644
--- a/third_party/mbedtls/repo/library/bignum.c
+++ b/third_party/mbedtls/repo/library/bignum.c
@@ -41,7 +41,9 @@
 #include "mbedtls/bn_mul.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
+#include "constant_time_internal.h"
 
+#include <limits.h>
 #include <string.h>
 
 #if defined(MBEDTLS_PLATFORM_C)
@@ -181,8 +183,35 @@
     return( 0 );
 }
 
+/* Resize X to have exactly n limbs and set it to 0. */
+static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs )
+{
+    if( limbs == 0 )
+    {
+        mbedtls_mpi_free( X );
+        return( 0 );
+    }
+    else if( X->n == limbs )
+    {
+        memset( X->p, 0, limbs * ciL );
+        X->s = 1;
+        return( 0 );
+    }
+    else
+    {
+        mbedtls_mpi_free( X );
+        return( mbedtls_mpi_grow( X, limbs ) );
+    }
+}
+
 /*
- * Copy the contents of Y into X
+ * Copy the contents of Y into X.
+ *
+ * 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().
  */
 int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
 {
@@ -196,7 +225,11 @@
 
     if( Y->n == 0 )
     {
-        mbedtls_mpi_free( X );
+        if( X->n != 0 )
+        {
+            X->s = 1;
+            memset( X->p, 0, X->n * ciL );
+        }
         return( 0 );
     }
 
@@ -238,89 +271,6 @@
 }
 
 /*
- * Conditionally assign dest = src, without leaking information
- * about whether the assignment was made or not.
- * dest and src must be arrays of limbs of size n.
- * assign must be 0 or 1.
- */
-static void mpi_safe_cond_assign( size_t n,
-                                  mbedtls_mpi_uint *dest,
-                                  const mbedtls_mpi_uint *src,
-                                  unsigned char assign )
-{
-    size_t i;
-    for( i = 0; i < n; i++ )
-        dest[i] = dest[i] * ( 1 - assign ) + src[i] * assign;
-}
-
-/*
- * 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.)
- */
-int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
-{
-    int ret = 0;
-    size_t i;
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( Y != NULL );
-
-    /* make sure assign is 0 or 1 in a time-constant manner */
-    assign = (assign | (unsigned char)-assign) >> 7;
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
-
-    X->s = X->s * ( 1 - assign ) + Y->s * assign;
-
-    mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
-
-    for( i = Y->n; i < X->n; i++ )
-        X->p[i] *= ( 1 - assign );
-
-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 whould 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, s;
-    size_t i;
-    mbedtls_mpi_uint tmp;
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( Y != NULL );
-
-    if( X == Y )
-        return( 0 );
-
-    /* make sure swap is 0 or 1 in a time-constant manner */
-    swap = (swap | (unsigned char)-swap) >> 7;
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
-
-    s = X->s;
-    X->s = X->s * ( 1 - swap ) + Y->s * swap;
-    Y->s = Y->s * ( 1 - swap ) +    s * swap;
-
-
-    for( i = 0; i < X->n; i++ )
-    {
-        tmp = X->p[i];
-        X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap;
-        Y->p[i] = Y->p[i] * ( 1 - swap ) +     tmp * swap;
-    }
-
-cleanup:
-    return( ret );
-}
-
-/*
  * Set value from integer
  */
 int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
@@ -470,6 +420,7 @@
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i, j, slen, n;
+    int sign = 1;
     mbedtls_mpi_uint d;
     mbedtls_mpi T;
     MPI_VALIDATE_RET( X != NULL );
@@ -480,6 +431,18 @@
 
     mbedtls_mpi_init( &T );
 
+    if( s[0] == 0 )
+    {
+        mbedtls_mpi_free( X );
+        return( 0 );
+    }
+
+    if( s[0] == '-' )
+    {
+        ++s;
+        sign = -1;
+    }
+
     slen = strlen( s );
 
     if( radix == 16 )
@@ -494,12 +457,6 @@
 
         for( i = slen, j = 0; i > 0; i--, j++ )
         {
-            if( i == 1 && s[i - 1] == '-' )
-            {
-                X->s = -1;
-                break;
-            }
-
             MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
             X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
         }
@@ -510,26 +467,15 @@
 
         for( i = 0; i < slen; i++ )
         {
-            if( i == 0 && s[i] == '-' )
-            {
-                X->s = -1;
-                continue;
-            }
-
             MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
             MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
-
-            if( X->s == 1 )
-            {
-                MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
-            }
-            else
-            {
-                MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
-            }
+            MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
         }
     }
 
+    if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
+        X->s = -1;
+
 cleanup:
 
     mbedtls_mpi_free( &T );
@@ -848,14 +794,7 @@
     size_t const limbs = CHARS_TO_LIMBS( buflen );
 
     /* Ensure that target MPI has exactly the necessary number of limbs */
-    if( X->n != limbs )
-    {
-        mbedtls_mpi_free( X );
-        mbedtls_mpi_init( X );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
-    }
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
 
     for( i = 0; i < buflen; i++ )
         X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
@@ -884,17 +823,11 @@
     MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
 
     /* Ensure that target MPI has exactly the necessary number of limbs */
-    if( X->n != limbs )
-    {
-        mbedtls_mpi_free( X );
-        mbedtls_mpi_init( X );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
-    }
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
 
-    /* Avoid calling `memcpy` with NULL source argument,
+    /* Avoid calling `memcpy` with NULL source or destination argument,
      * even if buflen is 0. */
-    if( buf != NULL )
+    if( buflen != 0 )
     {
         Xp = (unsigned char*) X->p;
         memcpy( Xp + overhead, buf, buflen );
@@ -1159,107 +1092,6 @@
     return( 0 );
 }
 
-/** Decide if an integer is less than the other, without branches.
- *
- * \param x         First integer.
- * \param y         Second integer.
- *
- * \return          1 if \p x is less than \p y, 0 otherwise
- */
-static unsigned ct_lt_mpi_uint( 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.)
-     */
-    ret |= y & cond;
-
-
-    ret = ret >> ( biL - 1 );
-
-    return (unsigned) 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 = ct_lt_mpi_uint( 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 = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
-        *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
-        done |= cond;
-    }
-
-    return( 0 );
-}
-
 /*
  * Compare signed values
  */
@@ -1339,29 +1171,32 @@
 /**
  * Helper for mbedtls_mpi subtraction.
  *
- * Calculate d - s where d and s have the same size.
+ * Calculate l - r where l and r have the same size.
  * This function operates modulo (2^ciL)^n and returns the carry
- * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise).
+ * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
  *
- * \param n             Number of limbs of \p d and \p s.
- * \param[in,out] d     On input, the left operand.
- *                      On output, the result of the subtraction:
- * \param[in] s         The right operand.
+ * d may be aliased to l or r.
  *
- * \return              1 if `d < s`.
- *                      0 if `d >= s`.
+ * \param n             Number of limbs of \p d, \p l and \p r.
+ * \param[out] d        The result of the subtraction.
+ * \param[in] l         The left operand.
+ * \param[in] r         The right operand.
+ *
+ * \return              1 if `l < r`.
+ *                      0 if `l >= r`.
  */
 static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
                                      mbedtls_mpi_uint *d,
-                                     const mbedtls_mpi_uint *s )
+                                     const mbedtls_mpi_uint *l,
+                                     const mbedtls_mpi_uint *r )
 {
     size_t i;
-    mbedtls_mpi_uint c, z;
+    mbedtls_mpi_uint c = 0, t, z;
 
-    for( i = c = 0; i < n; i++, s++, d++ )
+    for( i = 0; i < n; i++ )
     {
-        z = ( *d <  c );     *d -=  c;
-        c = ( *d < *s ) + z; *d -= *s;
+        z = ( l[i] <  c );    t = l[i] - c;
+        c = ( t < r[i] ) + z; d[i] = t - r[i];
     }
 
     return( c );
@@ -1372,7 +1207,6 @@
  */
 int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
 {
-    mbedtls_mpi TB;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
     mbedtls_mpi_uint carry;
@@ -1380,29 +1214,27 @@
     MPI_VALIDATE_RET( A != NULL );
     MPI_VALIDATE_RET( B != NULL );
 
-    mbedtls_mpi_init( &TB );
-
-    if( X == B )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
-        B = &TB;
-    }
-
-    if( X != A )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
-
-    /*
-     * X should always be positive as a result of unsigned subtractions.
-     */
-    X->s = 1;
-
-    ret = 0;
-
     for( n = B->n; n > 0; n-- )
         if( B->p[n - 1] != 0 )
             break;
+    if( n > A->n )
+    {
+        /* B >= (2^ciL)^n > A */
+        ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
+        goto cleanup;
+    }
 
-    carry = mpi_sub_hlp( n, X->p, B->p );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) );
+
+    /* Set the high limbs of X to match A. Don't touch the lower limbs
+     * because X might be aliased to B, and we must not overwrite the
+     * significant digits of B. */
+    if( A->n > n )
+        memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL );
+    if( X->n > A->n )
+        memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );
+
+    carry = mpi_sub_hlp( n, X->p, A->p, B->p );
     if( carry != 0 )
     {
         /* Propagate the carry to the first nonzero limb of X. */
@@ -1418,10 +1250,10 @@
         --X->p[n];
     }
 
+    /* X should always be positive as a result of unsigned subtractions. */
+    X->s = 1;
+
 cleanup:
-
-    mbedtls_mpi_free( &TB );
-
     return( ret );
 }
 
@@ -1500,17 +1332,17 @@
  */
 int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
 {
-    mbedtls_mpi _B;
+    mbedtls_mpi B;
     mbedtls_mpi_uint p[1];
     MPI_VALIDATE_RET( X != NULL );
     MPI_VALIDATE_RET( A != NULL );
 
     p[0] = ( b < 0 ) ? -b : b;
-    _B.s = ( b < 0 ) ? -1 : 1;
-    _B.n = 1;
-    _B.p = p;
+    B.s = ( b < 0 ) ? -1 : 1;
+    B.n = 1;
+    B.p = p;
 
-    return( mbedtls_mpi_add_mpi( X, A, &_B ) );
+    return( mbedtls_mpi_add_mpi( X, A, &B ) );
 }
 
 /*
@@ -1518,21 +1350,34 @@
  */
 int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
 {
-    mbedtls_mpi _B;
+    mbedtls_mpi B;
     mbedtls_mpi_uint p[1];
     MPI_VALIDATE_RET( X != NULL );
     MPI_VALIDATE_RET( A != NULL );
 
     p[0] = ( b < 0 ) ? -b : b;
-    _B.s = ( b < 0 ) ? -1 : 1;
-    _B.n = 1;
-    _B.p = p;
+    B.s = ( b < 0 ) ? -1 : 1;
+    B.n = 1;
+    B.p = p;
 
-    return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
+    return( mbedtls_mpi_sub_mpi( X, A, &B ) );
 }
 
-/*
- * Helper for mbedtls_mpi multiplication
+/** Helper for mbedtls_mpi multiplication.
+ *
+ * Add \p b * \p s to \p d.
+ *
+ * \param i             The number of limbs of \p s.
+ * \param[in] s         A bignum to multiply, of size \p i.
+ *                      It may overlap with \p d, but only if
+ *                      \p d <= \p s.
+ *                      Its leading limb must not be \c 0.
+ * \param[in,out] d     The bignum to add to.
+ *                      It must be sufficiently large to store the
+ *                      result of the multiplication. This means
+ *                      \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
+ *                      is not known a priori.
+ * \param b             A scalar to multiply.
  */
 static
 #if defined(__APPLE__) && defined(__arm__)
@@ -1542,7 +1387,10 @@
  */
 __attribute__ ((noinline))
 #endif
-void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b )
+void mpi_mul_hlp( size_t i,
+                  const mbedtls_mpi_uint *s,
+                  mbedtls_mpi_uint *d,
+                  mbedtls_mpi_uint b )
 {
     mbedtls_mpi_uint c = 0, t = 0;
 
@@ -1597,10 +1445,10 @@
 
     t++;
 
-    do {
+    while( c != 0 )
+    {
         *d += c; c = ( *d < c ); d++;
     }
-    while( c != 0 );
 }
 
 /*
@@ -1611,6 +1459,7 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     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 );
@@ -1623,10 +1472,14 @@
     for( i = A->n; i > 0; i-- )
         if( A->p[i - 1] != 0 )
             break;
+    if( i == 0 )
+        result_is_zero = 1;
 
     for( j = B->n; j > 0; j-- )
         if( B->p[j - 1] != 0 )
             break;
+    if( j == 0 )
+        result_is_zero = 1;
 
     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
@@ -1634,7 +1487,14 @@
     for( ; j > 0; j-- )
         mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
 
-    X->s = A->s * B->s;
+    /* 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
+     * need to take care to set the sign bit properly since the library does
+     * not fully support an MPI object with a value of 0 and s == -1. */
+    if( result_is_zero )
+        X->s = 1;
+    else
+        X->s = A->s * B->s;
 
 cleanup:
 
@@ -1648,17 +1508,37 @@
  */
 int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
 {
-    mbedtls_mpi _B;
-    mbedtls_mpi_uint p[1];
     MPI_VALIDATE_RET( X != NULL );
     MPI_VALIDATE_RET( A != NULL );
 
-    _B.s = 1;
-    _B.n = 1;
-    _B.p = p;
-    p[0] = b;
+    /* mpi_mul_hlp can't deal with a leading 0. */
+    size_t n = A->n;
+    while( n > 0 && A->p[n - 1] == 0 )
+        --n;
 
-    return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
+    /* The general method below doesn't work if n==0 or b==0. By chance
+     * calculating the result is trivial in those cases. */
+    if( b == 0 || n == 0 )
+    {
+        return( mbedtls_mpi_lset( X, 0 ) );
+    }
+
+    /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    /* In general, A * b requires 1 limb more than b. If
+     * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
+     * number of limbs as A and the call to grow() is not required since
+     * copy() will take care of the growth if needed. However, experimentally,
+     * making the call to grow() unconditional causes slightly fewer
+     * calls to calloc() in ECP code, presumably because it reuses the
+     * same mpi for a while and this way the mpi is more likely to directly
+     * grow to its final size. */
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
+    mpi_mul_hlp( n, A->p, X->p, b - 1 );
+
+cleanup:
+    return( ret );
 }
 
 /*
@@ -1799,7 +1679,7 @@
 
     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z,  0 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) );
 
     k = mbedtls_mpi_bitlen( &Y ) % biL;
     if( k < biL - 1 )
@@ -1892,16 +1772,16 @@
                          const mbedtls_mpi *A,
                          mbedtls_mpi_sint b )
 {
-    mbedtls_mpi _B;
+    mbedtls_mpi B;
     mbedtls_mpi_uint p[1];
     MPI_VALIDATE_RET( A != NULL );
 
     p[0] = ( b < 0 ) ? -b : b;
-    _B.s = ( b < 0 ) ? -1 : 1;
-    _B.n = 1;
-    _B.p = p;
+    B.s = ( b < 0 ) ? -1 : 1;
+    B.n = 1;
+    B.p = p;
 
-    return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
+    return( mbedtls_mpi_div_mpi( Q, R, A, &B ) );
 }
 
 /*
@@ -2065,14 +1945,14 @@
      * do the calculation without using conditional tests. */
     /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
     d[n] += 1;
-    d[n] -= mpi_sub_hlp( n, d, N->p );
+    d[n] -= mpi_sub_hlp( n, d, d, N->p );
     /* If d0 < N then d < (2^biL)^n
      * so d[n] == 0 and we want to keep A as it is.
      * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
      * so d[n] == 1 and we want to set A to the result of the subtraction
      * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
      * This exactly corresponds to a conditional assignment. */
-    mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
+    mbedtls_ct_mpi_uint_cond_assign( n, A->p, d, (unsigned char) d[n] );
 }
 
 /*
@@ -2092,19 +1972,48 @@
     mpi_montmul( A, &U, 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 );
+}
+
 /*
  * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
  */
 int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
                          const mbedtls_mpi *E, const mbedtls_mpi *N,
-                         mbedtls_mpi *_RR )
+                         mbedtls_mpi *prec_RR )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t wbits, wsize, one = 1;
     size_t i, j, nblimbs;
     size_t bufsize, nbits;
     mbedtls_mpi_uint ei, mm, state;
-    mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
+    mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos;
     int neg;
 
     MPI_VALIDATE_RET( X != NULL );
@@ -2128,6 +2037,7 @@
     mpi_montg_init( &mm, N );
     mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
     mbedtls_mpi_init( &Apos );
+    mbedtls_mpi_init( &WW );
     memset( W, 0, sizeof( W ) );
 
     i = mbedtls_mpi_bitlen( E );
@@ -2141,6 +2051,11 @@
 #endif
 
     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( X, j ) );
     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1],  j ) );
     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
@@ -2159,26 +2074,34 @@
     /*
      * If 1st call, pre-compute R^2 mod N
      */
-    if( _RR == NULL || _RR->p == NULL )
+    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 ) );
 
-        if( _RR != NULL )
-            memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
+        if( prec_RR != NULL )
+            memcpy( prec_RR, &RR, sizeof( mbedtls_mpi ) );
     }
     else
-        memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
+        memcpy( &RR, prec_RR, sizeof( mbedtls_mpi ) );
 
     /*
      * W[1] = A * R^2 * R^-1 mod N = A * R mod N
      */
     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 );
 
     /*
@@ -2268,7 +2191,8 @@
             /*
              * X = X * W[wbits] R^-1 mod N
              */
-            mpi_montmul( X, &W[wbits], N, mm, &T );
+            MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
+            mpi_montmul( X, &WW, N, mm, &T );
 
             state--;
             nbits = 0;
@@ -2306,8 +2230,9 @@
         mbedtls_mpi_free( &W[i] );
 
     mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
+    mbedtls_mpi_free( &WW );
 
-    if( _RR == NULL || _RR->p == NULL )
+    if( prec_RR == NULL || prec_RR->p == NULL )
         mbedtls_mpi_free( &RR );
 
     return( ret );
@@ -2334,19 +2259,67 @@
     lz = mbedtls_mpi_lsb( &TA );
     lzt = mbedtls_mpi_lsb( &TB );
 
+    /* The loop below gives the correct result when A==0 but not when B==0.
+     * So have a special case for B==0. Leverage the fact that we just
+     * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
+     * slightly more efficient than cmp_int(). */
+    if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 )
+    {
+        ret = mbedtls_mpi_copy( G, A );
+        goto cleanup;
+    }
+
     if( lzt < lz )
         lz = lzt;
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
-
     TA.s = TB.s = 1;
 
+    /* We mostly follow the procedure described in HAC 14.54, but with some
+     * minor differences:
+     * - Sequences of multiplications or divisions by 2 are grouped into a
+     *   single shift operation.
+     * - The procedure in HAC assumes that 0 < TB <= TA.
+     *     - The condition TB <= TA is not actually necessary for correctness.
+     *       TA and TB have symmetric roles except for the loop termination
+     *       condition, and the shifts at the beginning of the loop body
+     *       remove any significance from the ordering of TA vs TB before
+     *       the shifts.
+     *     - If TA = 0, the loop goes through 0 iterations and the result is
+     *       correctly TB.
+     *     - The case TB = 0 was short-circuited above.
+     *
+     * For the correctness proof below, decompose the original values of
+     * A and B as
+     *   A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
+     *   B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
+     * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
+     * and gcd(A',B') is odd or 0.
+     *
+     * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
+     * The code maintains the following invariant:
+     *     gcd(A,B) = 2^k * gcd(TA,TB) for some k   (I)
+     */
+
+    /* Proof that the loop terminates:
+     * At each iteration, either the right-shift by 1 is made on a nonzero
+     * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
+     * by at least 1, or the right-shift by 1 is made on zero and then
+     * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
+     * since in that case TB is calculated from TB-TA with the condition TB>TA).
+     */
     while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
     {
+        /* Divisions by 2 preserve the invariant (I). */
         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
 
+        /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
+         * TA-TB is even so the division by 2 has an integer result.
+         * Invariant (I) is preserved since any odd divisor of both TA and TB
+         * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
+         * also divides TB, and any odd divisior of both TB and |TA-TB|/2 also
+         * divides TA.
+         */
         if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
         {
             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
@@ -2357,8 +2330,18 @@
             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
         }
+        /* Note that one of TA or TB is still odd. */
     }
 
+    /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
+     * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
+     * - If there was at least one loop iteration, then one of TA or TB is odd,
+     *   and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
+     *   lz = min(a,b) so gcd(A,B) = 2^lz * TB.
+     * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
+     *   In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
+     */
+
     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
 
@@ -2369,6 +2352,33 @@
     return( ret );
 }
 
+/* Fill X with n_bytes random bytes.
+ * X must already have room for those bytes.
+ * The ordering of the bytes returned from the RNG is suitable for
+ * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
+ * The size and sign of X are unchanged.
+ * n_bytes must not be 0.
+ */
+static int mpi_fill_random_internal(
+    mbedtls_mpi *X, size_t n_bytes,
+    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const size_t limbs = CHARS_TO_LIMBS( n_bytes );
+    const size_t overhead = ( limbs * ciL ) - n_bytes;
+
+    if( X->n < limbs )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+    memset( X->p, 0, overhead );
+    memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
+    MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
+    mpi_bigendian_to_host( X->p, limbs );
+
+cleanup:
+    return( ret );
+}
+
 /*
  * Fill X with size bytes of random.
  *
@@ -2382,30 +2392,96 @@
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t const limbs = CHARS_TO_LIMBS( size );
-    size_t const overhead = ( limbs * ciL ) - size;
-    unsigned char *Xp;
 
     MPI_VALIDATE_RET( X     != NULL );
     MPI_VALIDATE_RET( f_rng != NULL );
 
     /* Ensure that target MPI has exactly the necessary number of limbs */
-    if( X->n != limbs )
-    {
-        mbedtls_mpi_free( X );
-        mbedtls_mpi_init( X );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
-    }
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
+    if( size == 0 )
+        return( 0 );
 
-    Xp = (unsigned char*) X->p;
-    MBEDTLS_MPI_CHK( f_rng( p_rng, Xp + overhead, size ) );
-
-    mpi_bigendian_to_host( X->p, limbs );
+    ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
 
 cleanup:
     return( ret );
 }
 
+int mbedtls_mpi_random( mbedtls_mpi *X,
+                        mbedtls_mpi_sint min,
+                        const mbedtls_mpi *N,
+                        int (*f_rng)(void *, unsigned char *, size_t),
+                        void *p_rng )
+{
+    int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    int count;
+    unsigned lt_lower = 1, lt_upper = 0;
+    size_t n_bits = mbedtls_mpi_bitlen( N );
+    size_t n_bytes = ( n_bits + 7 ) / 8;
+    mbedtls_mpi lower_bound;
+
+    if( min < 0 )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+    if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+    /*
+     * When min == 0, each try has at worst a probability 1/2 of failing
+     * (the msb has a probability 1/2 of being 0, and then the result will
+     * be < N), so after 30 tries failure probability is a most 2**(-30).
+     *
+     * When N is just below a power of 2, as is the case when generating
+     * a random scalar on most elliptic curves, 1 try is enough with
+     * overwhelming probability. When N is just above a power of 2,
+     * as when generating a random scalar on secp224k1, each try has
+     * a probability of failing that is almost 1/2.
+     *
+     * The probabilities are almost the same if min is nonzero but negligible
+     * compared to N. This is always the case when N is crypto-sized, but
+     * it's convenient to support small N for testing purposes. When N
+     * is small, use a higher repeat count, otherwise the probability of
+     * failure is macroscopic.
+     */
+    count = ( n_bytes > 4 ? 30 : 250 );
+
+    mbedtls_mpi_init( &lower_bound );
+
+    /* Ensure that target MPI has exactly the same number of limbs
+     * as the upper bound, even if the upper bound has leading zeros.
+     * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
+    MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
+
+    /*
+     * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
+     * when f_rng is a suitably parametrized instance of HMAC_DRBG:
+     * - use the same byte ordering;
+     * - keep the leftmost n_bits bits of the generated octet string;
+     * - try until result is in the desired range.
+     * This also avoids any bias, which is especially important for ECDSA.
+     */
+    do
+    {
+        MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
+
+        if( --count == 0 )
+        {
+            ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
+            goto cleanup;
+        }
+
+        MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, &lt_lower ) );
+        MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &lt_upper ) );
+    }
+    while( lt_lower != 0 || lt_upper == 0 );
+
+cleanup:
+    mbedtls_mpi_free( &lower_bound );
+    return( ret );
+}
+
 /*
  * Modular inverse: X = A^-1 mod N  (HAC 14.61 / 14.64)
  */
diff --git a/third_party/mbedtls/repo/library/blowfish.c b/third_party/mbedtls/repo/library/blowfish.c
index 76da448..621e9f7 100644
--- a/third_party/mbedtls/repo/library/blowfish.c
+++ b/third_party/mbedtls/repo/library/blowfish.c
@@ -40,29 +40,6 @@
 #define BLOWFISH_VALIDATE( cond )                                           \
     MBEDTLS_INTERNAL_VALIDATE( cond )
 
-/*
- * 32-bit integer manipulation macros (big endian)
- */
-#ifndef GET_UINT32_BE
-#define GET_UINT32_BE(n,b,i)                            \
-{                                                       \
-    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
-        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
-        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
-        | ( (uint32_t) (b)[(i) + 3]       );            \
-}
-#endif
-
-#ifndef PUT_UINT32_BE
-#define PUT_UINT32_BE(n,b,i)                            \
-{                                                       \
-    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
-    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
-    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
-    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
-}
-#endif
-
 static const uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2] = {
         0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L,
         0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L,
@@ -79,13 +56,13 @@
    unsigned short a, b, c, d;
    uint32_t  y;
 
-   d = (unsigned short)(x & 0xFF);
+   d = MBEDTLS_BYTE_0( x );
    x >>= 8;
-   c = (unsigned short)(x & 0xFF);
+   c = MBEDTLS_BYTE_0( x );
    x >>= 8;
-   b = (unsigned short)(x & 0xFF);
+   b = MBEDTLS_BYTE_0( x );
    x >>= 8;
-   a = (unsigned short)(x & 0xFF);
+   a = MBEDTLS_BYTE_0( x );
    y = ctx->S[0][a] + ctx->S[1][b];
    y = y ^ ctx->S[2][c];
    y = y + ctx->S[3][d];
@@ -242,8 +219,8 @@
     BLOWFISH_VALIDATE_RET( input  != NULL );
     BLOWFISH_VALIDATE_RET( output != NULL );
 
-    GET_UINT32_BE( X0, input,  0 );
-    GET_UINT32_BE( X1, input,  4 );
+    X0 = MBEDTLS_GET_UINT32_BE( input,  0 );
+    X1 = MBEDTLS_GET_UINT32_BE( input,  4 );
 
     if( mode == MBEDTLS_BLOWFISH_DECRYPT )
     {
@@ -254,8 +231,8 @@
         blowfish_enc( ctx, &X0, &X1 );
     }
 
-    PUT_UINT32_BE( X0, output,  0 );
-    PUT_UINT32_BE( X1, output,  4 );
+    MBEDTLS_PUT_UINT32_BE( X0, output,  0 );
+    MBEDTLS_PUT_UINT32_BE( X1, output,  4 );
 
     return( 0 );
 }
diff --git a/third_party/mbedtls/repo/library/camellia.c b/third_party/mbedtls/repo/library/camellia.c
index d60f931..29d730a 100644
--- a/third_party/mbedtls/repo/library/camellia.c
+++ b/third_party/mbedtls/repo/library/camellia.c
@@ -49,29 +49,6 @@
 #define CAMELLIA_VALIDATE( cond )                                           \
     MBEDTLS_INTERNAL_VALIDATE( cond )
 
-/*
- * 32-bit integer manipulation macros (big endian)
- */
-#ifndef GET_UINT32_BE
-#define GET_UINT32_BE(n,b,i)                            \
-{                                                       \
-    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
-        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
-        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
-        | ( (uint32_t) (b)[(i) + 3]       );            \
-}
-#endif
-
-#ifndef PUT_UINT32_BE
-#define PUT_UINT32_BE(n,b,i)                            \
-{                                                       \
-    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
-    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
-    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
-    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
-}
-#endif
-
 static const unsigned char SIGMA_CHARS[6][8] =
 {
     { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b },
@@ -301,14 +278,14 @@
     I0 = x[0] ^ k[0];
     I1 = x[1] ^ k[1];
 
-    I0 = ((uint32_t) SBOX1((I0 >> 24) & 0xFF) << 24) |
-         ((uint32_t) SBOX2((I0 >> 16) & 0xFF) << 16) |
-         ((uint32_t) SBOX3((I0 >>  8) & 0xFF) <<  8) |
-         ((uint32_t) SBOX4((I0      ) & 0xFF)      );
-    I1 = ((uint32_t) SBOX2((I1 >> 24) & 0xFF) << 24) |
-         ((uint32_t) SBOX3((I1 >> 16) & 0xFF) << 16) |
-         ((uint32_t) SBOX4((I1 >>  8) & 0xFF) <<  8) |
-         ((uint32_t) SBOX1((I1      ) & 0xFF)      );
+    I0 = ((uint32_t) SBOX1( MBEDTLS_BYTE_3( I0 )) << 24) |
+         ((uint32_t) SBOX2( MBEDTLS_BYTE_2( I0 )) << 16) |
+         ((uint32_t) SBOX3( MBEDTLS_BYTE_1( I0 )) <<  8) |
+         ((uint32_t) SBOX4( MBEDTLS_BYTE_0( I0 ))      );
+    I1 = ((uint32_t) SBOX2( MBEDTLS_BYTE_3( I1 )) << 24) |
+         ((uint32_t) SBOX3( MBEDTLS_BYTE_2( I1 )) << 16) |
+         ((uint32_t) SBOX4( MBEDTLS_BYTE_1( I1 )) <<  8) |
+         ((uint32_t) SBOX1( MBEDTLS_BYTE_0( I1 ))      );
 
     I0 ^= (I1 << 8) | (I1 >> 24);
     I1 ^= (I0 << 16) | (I0 >> 16);
@@ -376,8 +353,8 @@
      * Prepare SIGMA values
      */
     for( i = 0; i < 6; i++ ) {
-        GET_UINT32_BE( SIGMA[i][0], SIGMA_CHARS[i], 0 );
-        GET_UINT32_BE( SIGMA[i][1], SIGMA_CHARS[i], 4 );
+        SIGMA[i][0] = MBEDTLS_GET_UINT32_BE( SIGMA_CHARS[i], 0 );
+        SIGMA[i][1] = MBEDTLS_GET_UINT32_BE( SIGMA_CHARS[i], 4 );
     }
 
     /*
@@ -388,7 +365,7 @@
 
     /* Store KL, KR */
     for( i = 0; i < 8; i++ )
-        GET_UINT32_BE( KC[i], t, i * 4 );
+        KC[i] = MBEDTLS_GET_UINT32_BE( t, i * 4 );
 
     /* Generate KA */
     for( i = 0; i < 4; ++i )
@@ -514,10 +491,10 @@
     NR = ctx->nr;
     RK = ctx->rk;
 
-    GET_UINT32_BE( X[0], input,  0 );
-    GET_UINT32_BE( X[1], input,  4 );
-    GET_UINT32_BE( X[2], input,  8 );
-    GET_UINT32_BE( X[3], input, 12 );
+    X[0] = MBEDTLS_GET_UINT32_BE( input,  0 );
+    X[1] = MBEDTLS_GET_UINT32_BE( input,  4 );
+    X[2] = MBEDTLS_GET_UINT32_BE( input,  8 );
+    X[3] = MBEDTLS_GET_UINT32_BE( input, 12 );
 
     X[0] ^= *RK++;
     X[1] ^= *RK++;
@@ -552,10 +529,10 @@
     X[0] ^= *RK++;
     X[1] ^= *RK++;
 
-    PUT_UINT32_BE( X[2], output,  0 );
-    PUT_UINT32_BE( X[3], output,  4 );
-    PUT_UINT32_BE( X[0], output,  8 );
-    PUT_UINT32_BE( X[1], output, 12 );
+    MBEDTLS_PUT_UINT32_BE( X[2], output,  0 );
+    MBEDTLS_PUT_UINT32_BE( X[3], output,  4 );
+    MBEDTLS_PUT_UINT32_BE( X[0], output,  8 );
+    MBEDTLS_PUT_UINT32_BE( X[1], output, 12 );
 
     return( 0 );
 }
@@ -942,9 +919,11 @@
     unsigned char nonce_counter[16];
     unsigned char stream_block[16];
 #endif
+    int ret = 1;
 
     mbedtls_camellia_context ctx;
 
+    mbedtls_camellia_init( &ctx );
     memset( key, 0, 32 );
 
     for( j = 0; j < 6; j++ ) {
@@ -974,8 +953,7 @@
         {
             if( verbose != 0 )
                 mbedtls_printf( "failed\n" );
-
-            return( 1 );
+            goto exit;
         }
     }
 
@@ -1027,8 +1005,7 @@
             {
                 if( verbose != 0 )
                     mbedtls_printf( "failed\n" );
-
-                return( 1 );
+                goto exit;
             }
         }
 
@@ -1071,8 +1048,7 @@
             {
                 if( verbose != 0 )
                     mbedtls_printf( "failed\n" );
-
-                return( 1 );
+                goto exit;
             }
         }
         else
@@ -1087,8 +1063,7 @@
             {
                 if( verbose != 0 )
                     mbedtls_printf( "failed\n" );
-
-                return( 1 );
+                goto exit;
             }
         }
 
@@ -1100,7 +1075,11 @@
         mbedtls_printf( "\n" );
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
-    return( 0 );
+    ret = 0;
+
+exit:
+    mbedtls_camellia_free( &ctx );
+    return( ret );
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/third_party/mbedtls/repo/library/ccm.c b/third_party/mbedtls/repo/library/ccm.c
index 424ee77..a21a37f 100644
--- a/third_party/mbedtls/repo/library/ccm.c
+++ b/third_party/mbedtls/repo/library/ccm.c
@@ -200,7 +200,7 @@
     memcpy( b + 1, iv, iv_len );
 
     for( i = 0, len_left = length; i < q; i++, len_left >>= 8 )
-        b[15-i] = (unsigned char)( len_left & 0xFF );
+        b[15-i] = MBEDTLS_BYTE_0( len_left );
 
     if( len_left > 0 )
         return( MBEDTLS_ERR_CCM_BAD_INPUT );
@@ -221,8 +221,7 @@
         src = add;
 
         memset( b, 0, 16 );
-        b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF );
-        b[1] = (unsigned char)( ( add_len      ) & 0xFF );
+        MBEDTLS_PUT_UINT16_BE( add_len, b, 0 );
 
         use_len = len_left < 16 - 2 ? len_left : 16 - 2;
         memcpy( b + 2, src, use_len );
diff --git a/third_party/mbedtls/repo/library/chacha20.c b/third_party/mbedtls/repo/library/chacha20.c
index 78467d3..658f046 100644
--- a/third_party/mbedtls/repo/library/chacha20.c
+++ b/third_party/mbedtls/repo/library/chacha20.c
@@ -54,13 +54,6 @@
 #define CHACHA20_VALIDATE( cond )                                           \
     MBEDTLS_INTERNAL_VALIDATE( cond )
 
-#define BYTES_TO_U32_LE( data, offset )                           \
-    ( (uint32_t) (data)[offset]                                   \
-      | (uint32_t) ( (uint32_t) (data)[( offset ) + 1] << 8 )     \
-      | (uint32_t) ( (uint32_t) (data)[( offset ) + 2] << 16 )    \
-      | (uint32_t) ( (uint32_t) (data)[( offset ) + 3] << 24 )    \
-    )
-
 #define ROTL32( value, amount ) \
     ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) )
 
@@ -171,10 +164,7 @@
     {
         size_t offset = i * 4U;
 
-        keystream[offset     ] = (unsigned char)( working_state[i]       );
-        keystream[offset + 1U] = (unsigned char)( working_state[i] >>  8 );
-        keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 );
-        keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 );
+        MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
     }
 
     mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
@@ -212,14 +202,14 @@
     ctx->state[3] = 0x6b206574;
 
     /* Set key */
-    ctx->state[4]  = BYTES_TO_U32_LE( key, 0 );
-    ctx->state[5]  = BYTES_TO_U32_LE( key, 4 );
-    ctx->state[6]  = BYTES_TO_U32_LE( key, 8 );
-    ctx->state[7]  = BYTES_TO_U32_LE( key, 12 );
-    ctx->state[8]  = BYTES_TO_U32_LE( key, 16 );
-    ctx->state[9]  = BYTES_TO_U32_LE( key, 20 );
-    ctx->state[10] = BYTES_TO_U32_LE( key, 24 );
-    ctx->state[11] = BYTES_TO_U32_LE( key, 28 );
+    ctx->state[4]  = MBEDTLS_GET_UINT32_LE( key, 0 );
+    ctx->state[5]  = MBEDTLS_GET_UINT32_LE( key, 4 );
+    ctx->state[6]  = MBEDTLS_GET_UINT32_LE( key, 8 );
+    ctx->state[7]  = MBEDTLS_GET_UINT32_LE( key, 12 );
+    ctx->state[8]  = MBEDTLS_GET_UINT32_LE( key, 16 );
+    ctx->state[9]  = MBEDTLS_GET_UINT32_LE( key, 20 );
+    ctx->state[10] = MBEDTLS_GET_UINT32_LE( key, 24 );
+    ctx->state[11] = MBEDTLS_GET_UINT32_LE( key, 28 );
 
     return( 0 );
 }
@@ -235,9 +225,9 @@
     ctx->state[12] = counter;
 
     /* Nonce */
-    ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 );
-    ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 );
-    ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 );
+    ctx->state[13] = MBEDTLS_GET_UINT32_LE( nonce, 0 );
+    ctx->state[14] = MBEDTLS_GET_UINT32_LE( nonce, 4 );
+    ctx->state[15] = MBEDTLS_GET_UINT32_LE( nonce, 8 );
 
     mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
 
diff --git a/third_party/mbedtls/repo/library/chachapoly.c b/third_party/mbedtls/repo/library/chachapoly.c
index 77d5477..dc75b20 100644
--- a/third_party/mbedtls/repo/library/chachapoly.c
+++ b/third_party/mbedtls/repo/library/chachapoly.c
@@ -263,22 +263,8 @@
     /* The lengths of the AAD and ciphertext are processed by
      * Poly1305 as the final 128-bit block, encoded as little-endian integers.
      */
-    len_block[ 0] = (unsigned char)( ctx->aad_len       );
-    len_block[ 1] = (unsigned char)( ctx->aad_len >>  8 );
-    len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 );
-    len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 );
-    len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 );
-    len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 );
-    len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 );
-    len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 );
-    len_block[ 8] = (unsigned char)( ctx->ciphertext_len       );
-    len_block[ 9] = (unsigned char)( ctx->ciphertext_len >>  8 );
-    len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 );
-    len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 );
-    len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 );
-    len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 );
-    len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 );
-    len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 );
+    MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0);
+    MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8);
 
     ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
     if( ret != 0 )
diff --git a/third_party/mbedtls/repo/library/check_crypto_config.h b/third_party/mbedtls/repo/library/check_crypto_config.h
index cac90a0..d7ad16a 100644
--- a/third_party/mbedtls/repo/library/check_crypto_config.h
+++ b/third_party/mbedtls/repo/library/check_crypto_config.h
@@ -28,6 +28,19 @@
 #ifndef MBEDTLS_CHECK_CRYPTO_CONFIG_H
 #define MBEDTLS_CHECK_CRYPTO_CONFIG_H
 
+#if defined(PSA_WANT_ALG_CCM) && \
+    !( defined(PSA_WANT_KEY_TYPE_AES) || \
+       defined(PSA_WANT_KEY_TYPE_CAMELLIA) )
+#error "PSA_WANT_ALG_CCM defined, but not all prerequisites"
+#endif
+
+#if defined(PSA_WANT_ALG_CMAC) && \
+    !( defined(PSA_WANT_KEY_TYPE_AES) || \
+       defined(PSA_WANT_KEY_TYPE_CAMELLIA) || \
+       defined(PSA_WANT_KEY_TYPE_DES) )
+#error "PSA_WANT_ALG_CMAC defined, but not all prerequisites"
+#endif
+
 #if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) && \
     !( defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) || \
        defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) )
@@ -40,6 +53,12 @@
 #error "PSA_WANT_ALG_ECDSA defined, but not all prerequisites"
 #endif
 
+#if defined(PSA_WANT_ALG_GCM) && \
+    !( defined(PSA_WANT_KEY_TYPE_AES) || \
+       defined(PSA_WANT_KEY_TYPE_CAMELLIA) )
+#error "PSA_WANT_ALG_GCM defined, but not all prerequisites"
+#endif
+
 #if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) && \
     !( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
        defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) )
diff --git a/third_party/mbedtls/repo/library/cipher.c b/third_party/mbedtls/repo/library/cipher.c
index 457f8f6..4ec40d2 100644
--- a/third_party/mbedtls/repo/library/cipher.c
+++ b/third_party/mbedtls/repo/library/cipher.c
@@ -29,6 +29,7 @@
 #include "mbedtls/cipher_internal.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
+#include "mbedtls/constant_time.h"
 
 #include <stdlib.h>
 #include <string.h>
@@ -74,27 +75,6 @@
 #define CIPHER_VALIDATE( cond )        \
     MBEDTLS_INTERNAL_VALIDATE( cond )
 
-#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
-/* Compare the contents of two buffers in constant time.
- * Returns 0 if the contents are bitwise identical, otherwise returns
- * a non-zero value.
- * This is currently only used by GCM and ChaCha20+Poly1305.
- */
-static int mbedtls_constant_time_memcmp( const void *v1, const void *v2,
-                                         size_t len )
-{
-    const unsigned char *p1 = (const unsigned char*) v1;
-    const unsigned char *p2 = (const unsigned char*) v2;
-    size_t i;
-    unsigned char diff;
-
-    for( diff = 0, i = 0; i < len; i++ )
-        diff |= p1[i] ^ p2[i];
-
-    return( (int)diff );
-}
-#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
-
 static int supported_init = 0;
 
 const int *mbedtls_cipher_list( void )
@@ -1145,6 +1125,12 @@
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
+    /* Status to return on a non-authenticated algorithm. It would make sense
+     * to return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT or perhaps
+     * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, but at the time I write this our
+     * unit tests assume 0. */
+    ret = 0;
+
 #if defined(MBEDTLS_GCM_C)
     if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
     {
@@ -1159,10 +1145,11 @@
         }
 
         /* Check the tag in "constant-time" */
-        if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
-            return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
-
-        return( 0 );
+        if( mbedtls_ct_memcmp( tag, check_tag, tag_len ) != 0 )
+        {
+            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+            goto exit;
+        }
     }
 #endif /* MBEDTLS_GCM_C */
 
@@ -1181,14 +1168,17 @@
         }
 
         /* Check the tag in "constant-time" */
-        if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
-            return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
-
-        return( 0 );
+        if( mbedtls_ct_memcmp( tag, check_tag, tag_len ) != 0 )
+        {
+            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+            goto exit;
+        }
     }
 #endif /* MBEDTLS_CHACHAPOLY_C */
 
-    return( 0 );
+exit:
+    mbedtls_platform_zeroize( check_tag, tag_len );
+    return( ret );
 }
 #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
 
@@ -1246,9 +1236,12 @@
         if( status != PSA_SUCCESS )
             return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
 
-        status = psa_cipher_set_iv( &cipher_op, iv, iv_len );
-        if( status != PSA_SUCCESS )
-            return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
+        if( ctx->cipher_info->mode != MBEDTLS_MODE_ECB )
+        {
+            status = psa_cipher_set_iv( &cipher_op, iv, iv_len );
+            if( status != PSA_SUCCESS )
+                return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
+        }
 
         status = psa_cipher_update( &cipher_op,
                                     input, ilen,
diff --git a/third_party/mbedtls/repo/library/cmac.c b/third_party/mbedtls/repo/library/cmac.c
index 59ece15..3cc49d1 100644
--- a/third_party/mbedtls/repo/library/cmac.c
+++ b/third_party/mbedtls/repo/library/cmac.c
@@ -45,22 +45,10 @@
 #include "mbedtls/cmac.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
+#include "mbedtls/platform.h"
 
 #include <string.h>
 
-
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc     calloc
-#define mbedtls_free       free
-#if defined(MBEDTLS_SELF_TEST)
-#include <stdio.h>
-#define mbedtls_printf     printf
-#endif /* MBEDTLS_SELF_TEST */
-#endif /* MBEDTLS_PLATFORM_C */
-
 #if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST)
 
 /*
@@ -793,6 +781,18 @@
         if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits,
                                        MBEDTLS_ENCRYPT ) ) != 0 )
         {
+            /* When CMAC is implemented by an alternative implementation, or
+             * the underlying primitive itself is implemented alternatively,
+             * AES-192 may be unavailable. This should not cause the selftest
+             * function to fail. */
+            if( ( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||
+                  ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) &&
+                  cipher_type == MBEDTLS_CIPHER_AES_192_ECB ) {
+                if( verbose != 0 )
+                    mbedtls_printf( "skipped\n" );
+                goto next_test;
+            }
+
             if( verbose != 0 )
                 mbedtls_printf( "test execution failed\n" );
 
@@ -820,6 +820,7 @@
         if( verbose != 0 )
             mbedtls_printf( "passed\n" );
 
+next_test:
         mbedtls_cipher_free( &ctx );
     }
 
@@ -864,6 +865,19 @@
         if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages,
                                          message_lengths[i], output ) ) != 0 )
         {
+            /* When CMAC is implemented by an alternative implementation, or
+             * the underlying primitive itself is implemented alternatively,
+             * AES-192 and/or 3DES may be unavailable. This should not cause
+             * the selftest function to fail. */
+            if( ( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||
+                  ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) &&
+                ( cipher_type == MBEDTLS_CIPHER_AES_192_ECB ||
+                  cipher_type == MBEDTLS_CIPHER_DES_EDE3_ECB ) ) {
+                if( verbose != 0 )
+                    mbedtls_printf( "skipped\n" );
+                continue;
+            }
+
             if( verbose != 0 )
                 mbedtls_printf( "failed\n" );
             goto exit;
diff --git a/third_party/mbedtls/repo/library/common.h b/third_party/mbedtls/repo/library/common.h
index 5845766..c064724 100644
--- a/third_party/mbedtls/repo/library/common.h
+++ b/third_party/mbedtls/repo/library/common.h
@@ -29,6 +29,8 @@
 #include "mbedtls/config.h"
 #endif
 
+#include <stdint.h>
+
 /** 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
@@ -50,4 +52,254 @@
 #define MBEDTLS_STATIC_TESTABLE static
 #endif
 
+/** Byte Reading Macros
+ *
+ * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th
+ * byte from x, where byte 0 is the least significant byte.
+ */
+#define MBEDTLS_BYTE_0( x ) ( (uint8_t) (   ( x )         & 0xff ) )
+#define MBEDTLS_BYTE_1( x ) ( (uint8_t) ( ( ( x ) >> 8  ) & 0xff ) )
+#define MBEDTLS_BYTE_2( x ) ( (uint8_t) ( ( ( x ) >> 16 ) & 0xff ) )
+#define MBEDTLS_BYTE_3( x ) ( (uint8_t) ( ( ( x ) >> 24 ) & 0xff ) )
+#define MBEDTLS_BYTE_4( x ) ( (uint8_t) ( ( ( x ) >> 32 ) & 0xff ) )
+#define MBEDTLS_BYTE_5( x ) ( (uint8_t) ( ( ( x ) >> 40 ) & 0xff ) )
+#define MBEDTLS_BYTE_6( x ) ( (uint8_t) ( ( ( x ) >> 48 ) & 0xff ) )
+#define MBEDTLS_BYTE_7( x ) ( (uint8_t) ( ( ( x ) >> 56 ) & 0xff ) )
+
+/**
+ * Get the unsigned 32 bits integer corresponding to four bytes in
+ * big-endian order (MSB first).
+ *
+ * \param   data    Base address of the memory to get the four bytes from.
+ * \param   offset  Offset from \p base of the first and most significant
+ *                  byte of the four bytes to build the 32 bits unsigned
+ *                  integer from.
+ */
+#ifndef MBEDTLS_GET_UINT32_BE
+#define MBEDTLS_GET_UINT32_BE( data , offset )                  \
+    (                                                           \
+          ( (uint32_t) ( data )[( offset )    ] << 24 )         \
+        | ( (uint32_t) ( data )[( offset ) + 1] << 16 )         \
+        | ( (uint32_t) ( data )[( offset ) + 2] <<  8 )         \
+        | ( (uint32_t) ( data )[( offset ) + 3]       )         \
+    )
+#endif
+
+/**
+ * Put in memory a 32 bits unsigned integer in big-endian order.
+ *
+ * \param   n       32 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 32
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p base where to put the most significant
+ *                  byte of the 32 bits unsigned integer \p n.
+ */
+#ifndef MBEDTLS_PUT_UINT32_BE
+#define MBEDTLS_PUT_UINT32_BE( n, data, offset )                \
+{                                                               \
+    ( data )[( offset )    ] = MBEDTLS_BYTE_3( n );             \
+    ( data )[( offset ) + 1] = MBEDTLS_BYTE_2( n );             \
+    ( data )[( offset ) + 2] = MBEDTLS_BYTE_1( n );             \
+    ( data )[( offset ) + 3] = MBEDTLS_BYTE_0( n );             \
+}
+#endif
+
+/**
+ * Get the unsigned 32 bits integer corresponding to four bytes in
+ * little-endian order (LSB first).
+ *
+ * \param   data    Base address of the memory to get the four bytes from.
+ * \param   offset  Offset from \p base of the first and least significant
+ *                  byte of the four bytes to build the 32 bits unsigned
+ *                  integer from.
+ */
+#ifndef MBEDTLS_GET_UINT32_LE
+#define MBEDTLS_GET_UINT32_LE( data, offset )                   \
+    (                                                           \
+          ( (uint32_t) ( data )[( offset )    ]       )         \
+        | ( (uint32_t) ( data )[( offset ) + 1] <<  8 )         \
+        | ( (uint32_t) ( data )[( offset ) + 2] << 16 )         \
+        | ( (uint32_t) ( data )[( offset ) + 3] << 24 )         \
+    )
+#endif
+
+/**
+ * Put in memory a 32 bits unsigned integer in little-endian order.
+ *
+ * \param   n       32 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 32
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p base where to put the least significant
+ *                  byte of the 32 bits unsigned integer \p n.
+ */
+#ifndef MBEDTLS_PUT_UINT32_LE
+#define MBEDTLS_PUT_UINT32_LE( n, data, offset )                \
+{                                                               \
+    ( data )[( offset )    ] = MBEDTLS_BYTE_0( n );             \
+    ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n );             \
+    ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n );             \
+    ( data )[( offset ) + 3] = MBEDTLS_BYTE_3( n );             \
+}
+#endif
+
+/**
+ * Get the unsigned 16 bits integer corresponding to two bytes in
+ * little-endian order (LSB first).
+ *
+ * \param   data    Base address of the memory to get the two bytes from.
+ * \param   offset  Offset from \p base of the first and least significant
+ *                  byte of the two bytes to build the 16 bits unsigned
+ *                  integer from.
+ */
+#ifndef MBEDTLS_GET_UINT16_LE
+#define MBEDTLS_GET_UINT16_LE( data, offset )                   \
+    (                                                           \
+          ( (uint16_t) ( data )[( offset )    ]       )         \
+        | ( (uint16_t) ( data )[( offset ) + 1] <<  8 )         \
+    )
+#endif
+
+/**
+ * Put in memory a 16 bits unsigned integer in little-endian order.
+ *
+ * \param   n       16 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 16
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p base where to put the least significant
+ *                  byte of the 16 bits unsigned integer \p n.
+ */
+#ifndef MBEDTLS_PUT_UINT16_LE
+#define MBEDTLS_PUT_UINT16_LE( n, data, offset )                \
+{                                                               \
+    ( data )[( offset )    ] = MBEDTLS_BYTE_0( n );             \
+    ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n );             \
+}
+#endif
+
+/**
+ * Get the unsigned 16 bits integer corresponding to two bytes in
+ * big-endian order (MSB first).
+ *
+ * \param   data    Base address of the memory to get the two bytes from.
+ * \param   offset  Offset from \p base of the first and most significant
+ *                  byte of the two bytes to build the 16 bits unsigned
+ *                  integer from.
+ */
+#ifndef MBEDTLS_GET_UINT16_BE
+#define MBEDTLS_GET_UINT16_BE( data, offset )                   \
+    (                                                           \
+          ( (uint16_t) ( data )[( offset )    ] << 8 )          \
+        | ( (uint16_t) ( data )[( offset ) + 1]      )          \
+    )
+#endif
+
+/**
+ * Put in memory a 16 bits unsigned integer in big-endian order.
+ *
+ * \param   n       16 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 16
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p base where to put the most significant
+ *                  byte of the 16 bits unsigned integer \p n.
+ */
+#ifndef MBEDTLS_PUT_UINT16_BE
+#define MBEDTLS_PUT_UINT16_BE( n, data, offset )                \
+{                                                               \
+    ( data )[( offset )    ] = MBEDTLS_BYTE_1( n );             \
+    ( data )[( offset ) + 1] = MBEDTLS_BYTE_0( n );             \
+}
+#endif
+
+/**
+ * Get the unsigned 64 bits integer corresponding to eight bytes in
+ * big-endian order (MSB first).
+ *
+ * \param   data    Base address of the memory to get the eight bytes from.
+ * \param   offset  Offset from \p base of the first and most significant
+ *                  byte of the eight bytes to build the 64 bits unsigned
+ *                  integer from.
+ */
+#ifndef MBEDTLS_GET_UINT64_BE
+#define MBEDTLS_GET_UINT64_BE( data, offset )                   \
+    (                                                           \
+          ( (uint64_t) ( data )[( offset )    ] << 56 )         \
+        | ( (uint64_t) ( data )[( offset ) + 1] << 48 )         \
+        | ( (uint64_t) ( data )[( offset ) + 2] << 40 )         \
+        | ( (uint64_t) ( data )[( offset ) + 3] << 32 )         \
+        | ( (uint64_t) ( data )[( offset ) + 4] << 24 )         \
+        | ( (uint64_t) ( data )[( offset ) + 5] << 16 )         \
+        | ( (uint64_t) ( data )[( offset ) + 6] <<  8 )         \
+        | ( (uint64_t) ( data )[( offset ) + 7]       )         \
+    )
+#endif
+
+/**
+ * Put in memory a 64 bits unsigned integer in big-endian order.
+ *
+ * \param   n       64 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 64
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p base where to put the most significant
+ *                  byte of the 64 bits unsigned integer \p n.
+ */
+#ifndef MBEDTLS_PUT_UINT64_BE
+#define MBEDTLS_PUT_UINT64_BE( n, data, offset )                \
+{                                                               \
+    ( data )[( offset )    ] = MBEDTLS_BYTE_7( n );             \
+    ( data )[( offset ) + 1] = MBEDTLS_BYTE_6( n );             \
+    ( data )[( offset ) + 2] = MBEDTLS_BYTE_5( n );             \
+    ( data )[( offset ) + 3] = MBEDTLS_BYTE_4( n );             \
+    ( data )[( offset ) + 4] = MBEDTLS_BYTE_3( n );             \
+    ( data )[( offset ) + 5] = MBEDTLS_BYTE_2( n );             \
+    ( data )[( offset ) + 6] = MBEDTLS_BYTE_1( n );             \
+    ( data )[( offset ) + 7] = MBEDTLS_BYTE_0( n );             \
+}
+#endif
+
+/**
+ * Get the unsigned 64 bits integer corresponding to eight bytes in
+ * little-endian order (LSB first).
+ *
+ * \param   data    Base address of the memory to get the eight bytes from.
+ * \param   offset  Offset from \p base of the first and least significant
+ *                  byte of the eight bytes to build the 64 bits unsigned
+ *                  integer from.
+ */
+#ifndef MBEDTLS_GET_UINT64_LE
+#define MBEDTLS_GET_UINT64_LE( data, offset )                   \
+    (                                                           \
+          ( (uint64_t) ( data )[( offset ) + 7] << 56 )         \
+        | ( (uint64_t) ( data )[( offset ) + 6] << 48 )         \
+        | ( (uint64_t) ( data )[( offset ) + 5] << 40 )         \
+        | ( (uint64_t) ( data )[( offset ) + 4] << 32 )         \
+        | ( (uint64_t) ( data )[( offset ) + 3] << 24 )         \
+        | ( (uint64_t) ( data )[( offset ) + 2] << 16 )         \
+        | ( (uint64_t) ( data )[( offset ) + 1] <<  8 )         \
+        | ( (uint64_t) ( data )[( offset )    ]       )         \
+    )
+#endif
+
+/**
+ * Put in memory a 64 bits unsigned integer in little-endian order.
+ *
+ * \param   n       64 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 64
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p base where to put the least significant
+ *                  byte of the 64 bits unsigned integer \p n.
+ */
+#ifndef MBEDTLS_PUT_UINT64_LE
+#define MBEDTLS_PUT_UINT64_LE( n, data, offset )                \
+{                                                               \
+    ( data )[( offset )    ] = MBEDTLS_BYTE_0( n );             \
+    ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n );             \
+    ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n );             \
+    ( data )[( offset ) + 3] = MBEDTLS_BYTE_3( n );             \
+    ( data )[( offset ) + 4] = MBEDTLS_BYTE_4( n );             \
+    ( data )[( offset ) + 5] = MBEDTLS_BYTE_5( n );             \
+    ( data )[( offset ) + 6] = MBEDTLS_BYTE_6( n );             \
+    ( data )[( offset ) + 7] = MBEDTLS_BYTE_7( n );             \
+}
+#endif
+
 #endif /* MBEDTLS_LIBRARY_COMMON_H */
diff --git a/third_party/mbedtls/repo/library/constant_time.c b/third_party/mbedtls/repo/library/constant_time.c
new file mode 100644
index 0000000..18f1b20
--- /dev/null
+++ b/third_party/mbedtls/repo/library/constant_time.c
@@ -0,0 +1,819 @@
+/**
+ *  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.
+ */
+
+ /*
+ * The following functions are implemented without using comparison operators, as those
+ * might be translated to branches by some compilers on some platforms.
+ */
+
+#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"
+#endif
+
+#if defined(MBEDTLS_SSL_TLS_C)
+#include "mbedtls/ssl_internal.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>
+
+int mbedtls_ct_memcmp( const void *a,
+                       const void *b,
+                       size_t n )
+{
+    size_t i;
+    volatile const unsigned char *A = (volatile const unsigned char *) a;
+    volatile const unsigned char *B = (volatile const unsigned char *) b;
+    volatile unsigned char diff = 0;
+
+    for( i = 0; i < n; i++ )
+    {
+        /* Read volatile data in order before computing diff.
+         * This avoids IAR compiler warning:
+         * 'the order of volatile accesses is undefined ..' */
+        unsigned char x = A[i], y = B[i];
+        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_TLS_CBC)
+
+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_TLS_CBC */
+
+#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.)
+     */
+    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 ) );
+}
+
+#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.
+ * \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 );
+
+    /* 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 )
+{
+    size_t i;
+
+    /* 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;
+
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+
+    for( i = 0; i < n; i++ )
+        dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask );
+}
+
+#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 );
+}
+
+#endif /* MBEDTLS_BASE64_C */
+
+#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 )
+{
+    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 );
+        /* 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++ )
+        {
+            unsigned char current = buf[n];
+            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 );
+    }
+}
+
+#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
+
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
+
+void mbedtls_ct_memcpy_if_eq( unsigned char *dest,
+                              const unsigned char *src,
+                              size_t len,
+                              size_t c1,
+                              size_t c2 )
+{
+    /* mask = c1 == c2 ? 0xff : 0x00 */
+    const size_t equal = mbedtls_ct_size_bool_eq( c1, c2 );
+    const unsigned char mask = (unsigned char) mbedtls_ct_size_mask( equal );
+
+    /* dest[i] = c1 == c2 ? src[i] : dest[i] */
+    for( size_t i = 0; i < len; i++ )
+        dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask );
+}
+
+void mbedtls_ct_memcpy_offset( unsigned char *dest,
+                               const unsigned char *src,
+                               size_t offset,
+                               size_t offset_min,
+                               size_t offset_max,
+                               size_t len )
+{
+    size_t offsetval;
+
+    for( offsetval = offset_min; offsetval <= offset_max; offsetval++ )
+    {
+        mbedtls_ct_memcpy_if_eq( dest, src + offsetval, len,
+                                 offsetval, offset );
+    }
+}
+
+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.0-1.2 only support 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 ) );
+
+    /* 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_SSL_SOME_SUITES_USE_TLS_CBC */
+
+#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.)
+ */
+int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X,
+                                  const mbedtls_mpi *Y,
+                                  unsigned char assign )
+{
+    int ret = 0;
+    size_t i;
+    mbedtls_mpi_uint limb_mask;
+    MPI_VALIDATE_RET( X != NULL );
+    MPI_VALIDATE_RET( Y != NULL );
+
+    /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
+    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_ct_mpi_uint_cond_assign( Y->n, X->p, Y->p, assign );
+
+    for( 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 whould 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, s;
+    size_t i;
+    mbedtls_mpi_uint limb_mask;
+    mbedtls_mpi_uint tmp;
+    MPI_VALIDATE_RET( X != NULL );
+    MPI_VALIDATE_RET( Y != NULL );
+
+    if( X == Y )
+        return( 0 );
+
+    /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
+    limb_mask = mbedtls_ct_mpi_uint_mask( 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_cond_select_sign( swap, Y->s, X->s );
+    Y->s = mbedtls_ct_cond_select_sign( swap, s, Y->s );
+
+
+    for( i = 0; i < X->n; i++ )
+    {
+        tmp = X->p[i];
+        X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
+        Y->p[i] = ( Y->p[i] & ~limb_mask ) | (     tmp & limb_mask );
+    }
+
+cleanup:
+    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( int mode,
+                                          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;
+    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];
+
+    if( mode == MBEDTLS_RSA_PRIVATE )
+    {
+        /* 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;
+        }
+    }
+    else
+    {
+        /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00
+         * where PS must be at least 8 bytes with the value 0xFF. */
+        bad |= input[1] ^ MBEDTLS_RSA_SIGN;
+
+        /* Read the whole buffer. Set pad_done to nonzero if we find
+         * the 0x00 byte and remember the padding length in pad_count.
+         * If there's a non-0xff byte in the padding, the padding is bad. */
+        for( i = 2; i < ilen; i++ )
+        {
+            pad_done |= mbedtls_ct_uint_if( input[i], 0, 1 );
+            pad_count += mbedtls_ct_uint_if( pad_done, 0, 1 );
+            bad |= mbedtls_ct_uint_if( pad_done, 0, input[i] ^ 0xFF );
+        }
+    }
+
+    /* 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;
+
+    /* 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 );
+
+    /* 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 */
diff --git a/third_party/mbedtls/repo/library/constant_time_internal.h b/third_party/mbedtls/repo/library/constant_time_internal.h
new file mode 100644
index 0000000..bbb3a90
--- /dev/null
+++ b/third_party/mbedtls/repo/library/constant_time_internal.h
@@ -0,0 +1,329 @@
+/**
+ *  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.
+ */
+
+#ifndef MBEDTLS_CONSTANT_TIME_INTERNAL_H
+#define MBEDTLS_CONSTANT_TIME_INTERNAL_H
+
+#include "common.h"
+
+#if defined(MBEDTLS_BIGNUM_C)
+#include "mbedtls/bignum.h"
+#endif
+
+#if defined(MBEDTLS_SSL_TLS_C)
+#include "mbedtls/ssl_internal.h"
+#endif
+
+#include <stddef.h>
+
+
+/** 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
+ *
+ * This function can be used to write constant-time code by replacing branches
+ * with bit operations using masks.
+ *
+ * \param value     The value to analyze.
+ *
+ * \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_TLS_CBC)
+
+/** 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
+ *
+ * This function can be used to write constant-time code by replacing branches
+ * with bit operations using masks.
+ *
+ * \param value     The value to analyze.
+ *
+ * \return          Zero if \p value is zero, otherwise all-bits-one.
+ */
+size_t mbedtls_ct_size_mask( size_t value );
+
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
+
+#if defined(MBEDTLS_BIGNUM_C)
+
+/** 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
+ *
+ * This function can be used to write constant-time code by replacing branches
+ * with bit operations using masks.
+ *
+ * \param value     The value to analyze.
+ *
+ * \return          Zero if \p value is zero, otherwise all-bits-one.
+ */
+mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask( mbedtls_mpi_uint value );
+
+#endif /* MBEDTLS_BIGNUM_C */
+
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
+
+/** 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
+ *
+ * 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 greater or equal than \p y,
+ *              otherwise zero.
+ */
+size_t mbedtls_ct_size_mask_ge( size_t x,
+                                size_t y );
+
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
+
+/** Constant-flow boolean "equal" 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 equals to \p y, otherwise 0.
+ */
+unsigned mbedtls_ct_size_bool_eq( size_t x,
+                                  size_t y );
+
+#if defined(MBEDTLS_BIGNUM_C)
+
+/** Decide if an integer is less than the other, without branches.
+ *
+ * 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 is less than \p y, otherwise 0.
+ */
+unsigned mbedtls_ct_mpi_uint_lt( const mbedtls_mpi_uint x,
+                                 const mbedtls_mpi_uint y );
+
+#endif /* MBEDTLS_BIGNUM_C */
+
+/** Choose between two integer values without branches.
+ *
+ * This is equivalent to `condition ? if1 : if0`, but is likely to be compiled
+ * to code using bitwise operation rather than a branch.
+ *
+ * \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.
+ *
+ * \return  \c if1 if \p condition is nonzero, otherwise \c if0.
+ */
+unsigned mbedtls_ct_uint_if( unsigned condition,
+                             unsigned if1,
+                             unsigned if0 );
+
+#if defined(MBEDTLS_BIGNUM_C)
+
+/** Conditionally assign a value without branches.
+ *
+ * This is equivalent to `if ( condition ) dest = src`, but is likely
+ * to be compiled to code using bitwise operation rather than a branch.
+ *
+ * \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.
+ */
+void mbedtls_ct_mpi_uint_cond_assign( size_t n,
+                                      mbedtls_mpi_uint *dest,
+                                      const mbedtls_mpi_uint *src,
+                                      unsigned char condition );
+
+#endif /* MBEDTLS_BIGNUM_C */
+
+#if defined(MBEDTLS_BASE64_C)
+
+/** 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_BASE64_C */
+
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
+
+/** Conditional memcpy without branches.
+ *
+ * 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.
+ *
+ * \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.
+ */
+void mbedtls_ct_memcpy_if_eq( unsigned char *dest,
+                              const unsigned char *src,
+                              size_t len,
+                              size_t c1, size_t c2 );
+
+/** Copy data from a secret position with constant flow.
+ *
+ * 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)`.
+ *
+ * \param dest          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
+ *                      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.
+ *                      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.
+ * \param offset_max    The maximal value of \p offset.
+ * \param len           The number of bytes to copy.
+ */
+void mbedtls_ct_memcpy_offset( unsigned char *dest,
+                               const unsigned char *src,
+                               size_t offset,
+                               size_t offset_min,
+                               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.
+ */
+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_SSL_SOME_SUITES_USE_TLS_CBC */
+
+#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 mode           The mode of operation. This must be either
+ *                       #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated).
+ * \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( int mode,
+                                          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 */
+
+#endif /* MBEDTLS_CONSTANT_TIME_INTERNAL_H */
diff --git a/third_party/mbedtls/repo/library/constant_time_invasive.h b/third_party/mbedtls/repo/library/constant_time_invasive.h
new file mode 100644
index 0000000..4620ca1
--- /dev/null
+++ b/third_party/mbedtls/repo/library/constant_time_invasive.h
@@ -0,0 +1,51 @@
+/**
+ * \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/third_party/mbedtls/repo/library/ctr_drbg.c b/third_party/mbedtls/repo/library/ctr_drbg.c
index 023aac5..a604ec0 100644
--- a/third_party/mbedtls/repo/library/ctr_drbg.c
+++ b/third_party/mbedtls/repo/library/ctr_drbg.c
@@ -56,10 +56,6 @@
     ctx->reseed_counter = -1;
 
     ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
-
-#if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_init( &ctx->mutex );
-#endif
 }
 
 /*
@@ -72,15 +68,14 @@
         return;
 
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_free( &ctx->mutex );
+    /* The mutex is initialized iff f_entropy is set. */
+    if( ctx->f_entropy != NULL )
+        mbedtls_mutex_free( &ctx->mutex );
 #endif
     mbedtls_aes_free( &ctx->aes_ctx );
     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
     ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
     ctx->reseed_counter = -1;
-#if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_init( &ctx->mutex );
-#endif
 }
 
 void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
@@ -157,11 +152,8 @@
      *     (Total is padded to a multiple of 16-bytes with zeroes)
      */
     p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
-    *p++ = ( data_len >> 24 ) & 0xff;
-    *p++ = ( data_len >> 16 ) & 0xff;
-    *p++ = ( data_len >> 8  ) & 0xff;
-    *p++ = ( data_len       ) & 0xff;
-    p += 3;
+    MBEDTLS_PUT_UINT32_BE( data_len, p, 0);
+    p += 4 + 3;
     *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
     memcpy( p, data, data_len );
     p[data_len] = 0x80;
@@ -394,7 +386,7 @@
     /* Gather entropy for a nonce if requested. */
     if( nonce_len != 0 )
     {
-        if( 0 != ctx->f_entropy( ctx->p_entropy, seed, nonce_len ) )
+        if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) )
         {
             return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
         }
@@ -464,6 +456,11 @@
 
     memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
 
+    /* The mutex is initialized iff f_entropy is set. */
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_init( &ctx->mutex );
+#endif
+
     mbedtls_aes_init( &ctx->aes_ctx );
 
     ctx->f_entropy = f_entropy;
@@ -684,54 +681,134 @@
 
 #if defined(MBEDTLS_SELF_TEST)
 
-static const unsigned char entropy_source_pr[96] =
-    { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
-      0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
-      0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
-      0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
-      0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
-      0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
-      0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
-      0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
-      0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
-      0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
-      0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
-      0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
-
-static const unsigned char entropy_source_nopr[64] =
-    { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
-      0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
-      0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
-      0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
-      0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
-      0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
-      0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
-      0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
-
-static const unsigned char nonce_pers_pr[16] =
-    { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
-      0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
-
-static const unsigned char nonce_pers_nopr[16] =
-    { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
-      0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
+/* The CTR_DRBG NIST test vectors used here are available at
+ * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip
+ *
+ * The parameters used to derive the test data are:
+ *
+ * [AES-128 use df]
+ * [PredictionResistance = True/False]
+ * [EntropyInputLen = 128]
+ * [NonceLen = 64]
+ * [PersonalizationStringLen = 128]
+ * [AdditionalInputLen = 0]
+ * [ReturnedBitsLen = 512]
+ *
+ * [AES-256 use df]
+ * [PredictionResistance = True/False]
+ * [EntropyInputLen = 256]
+ * [NonceLen = 128]
+ * [PersonalizationStringLen = 256]
+ * [AdditionalInputLen = 0]
+ * [ReturnedBitsLen = 512]
+ *
+ */
 
 #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
-static const unsigned char result_pr[16] =
-    { 0x95, 0x3c, 0xa5, 0xbd, 0x44, 0x1, 0x34, 0xb7,
-      0x13, 0x58, 0x3e, 0x6a, 0x6c, 0x7e, 0x88, 0x8a };
+static const unsigned char entropy_source_pr[] =
+    { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
+      0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
+      0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
+      0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
+      0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
+      0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
+      0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
 
-static const unsigned char result_nopr[16] =
-    { 0x6c, 0x25, 0x27, 0x95, 0xa3, 0x62, 0xd6, 0xdb,
-      0x90, 0xfd, 0x69, 0xb5, 0x42, 0x9, 0x4b, 0x84 };
+static const unsigned char entropy_source_nopr[] =
+    { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
+      0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
+      0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
+      0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
+      0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
+
+static const unsigned char pers_pr[] =
+    { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
+      0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
+
+static const unsigned char pers_nopr[] =
+    { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
+      0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
+
+static const unsigned char result_pr[] =
+    { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
+      0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
+      0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
+      0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
+      0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
+      0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
+      0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
+      0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
+
+static const unsigned char result_nopr[] =
+    { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
+      0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
+      0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
+      0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
+      0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
+      0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
+      0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
+      0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
 #else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
-static const unsigned char result_pr[16] =
-    { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
-      0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
 
-static const unsigned char result_nopr[16] =
-    { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
-      0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
+static const unsigned char entropy_source_pr[] =
+    { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
+      0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
+      0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
+      0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
+      0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
+      0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
+      0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
+      0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
+      0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
+      0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
+      0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
+      0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
+      0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
+      0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
+
+static const unsigned char entropy_source_nopr[] =
+    { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
+      0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
+      0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
+      0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
+      0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
+      0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
+      0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
+      0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
+      0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
+      0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
+
+static const unsigned char pers_pr[] =
+    { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
+      0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
+      0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
+      0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
+
+static const unsigned char pers_nopr[] =
+    { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
+      0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
+      0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
+      0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
+
+static const unsigned char result_pr[] =
+    { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
+      0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
+      0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
+      0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
+      0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
+      0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
+      0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
+      0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
+
+static const unsigned char result_nopr[] =
+    { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
+      0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
+      0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
+      0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
+      0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
+      0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
+      0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
+      0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
 #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
 
 static size_t test_offset;
@@ -751,13 +828,15 @@
                         return( 1 );                        \
                     }
 
+#define SELF_TEST_OUPUT_DISCARD_LENGTH 64
+
 /*
  * Checkup routine
  */
 int mbedtls_ctr_drbg_self_test( int verbose )
 {
     mbedtls_ctr_drbg_context ctx;
-    unsigned char buf[16];
+    unsigned char buf[ sizeof( result_pr ) ];
 
     mbedtls_ctr_drbg_init( &ctx );
 
@@ -768,16 +847,16 @@
         mbedtls_printf( "  CTR_DRBG (PR = TRUE) : " );
 
     test_offset = 0;
-    mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
-    mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
+    mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
+    mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
     CHK( mbedtls_ctr_drbg_seed( &ctx,
                                 ctr_drbg_self_test_entropy,
                                 (void *) entropy_source_pr,
-                                nonce_pers_pr, 16 ) );
+                                pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
     mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
-    CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
-    CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
-    CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
+    CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
+    CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
+    CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
 
     mbedtls_ctr_drbg_free( &ctx );
 
@@ -793,16 +872,16 @@
     mbedtls_ctr_drbg_init( &ctx );
 
     test_offset = 0;
-    mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
-    mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
+    mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
+    mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
     CHK( mbedtls_ctr_drbg_seed( &ctx,
                                 ctr_drbg_self_test_entropy,
                                 (void *) entropy_source_nopr,
-                                nonce_pers_nopr, 16 ) );
-    CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
+                                pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
     CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
-    CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
-    CHK( memcmp( buf, result_nopr, 16 ) );
+    CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
+    CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
+    CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
 
     mbedtls_ctr_drbg_free( &ctx );
 
diff --git a/third_party/mbedtls/repo/library/debug.c b/third_party/mbedtls/repo/library/debug.c
index c3384be..e108600 100644
--- a/third_party/mbedtls/repo/library/debug.c
+++ b/third_party/mbedtls/repo/library/debug.c
@@ -74,6 +74,7 @@
 #endif
 }
 
+MBEDTLS_PRINTF_ATTRIBUTE(5, 6)
 void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level,
                               const char *file, int line,
                               const char *format, ... )
@@ -219,8 +220,8 @@
                       const char *text, const mbedtls_mpi *X )
 {
     char str[DEBUG_BUF_SIZE];
-    int j, k, zeros = 1;
-    size_t i, n, idx = 0;
+    size_t bitlen;
+    size_t idx = 0;
 
     if( NULL == ssl              ||
         NULL == ssl->conf        ||
@@ -231,55 +232,43 @@
         return;
     }
 
-    for( n = X->n - 1; n > 0; n-- )
-        if( X->p[n] != 0 )
-            break;
+    bitlen = mbedtls_mpi_bitlen( X );
 
-    for( j = ( sizeof(mbedtls_mpi_uint) << 3 ) - 1; j >= 0; j-- )
-        if( ( ( X->p[n] >> j ) & 1 ) != 0 )
-            break;
-
-    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "value of '%s' (%d bits) is:\n",
-              text, (int) ( ( n * ( sizeof(mbedtls_mpi_uint) << 3 ) ) + j + 1 ) );
-
+    mbedtls_snprintf( str, sizeof( str ), "value of '%s' (%u bits) is:\n",
+                      text, (unsigned) bitlen );
     debug_send_line( ssl, level, file, line, str );
 
-    idx = 0;
-    for( i = n + 1, j = 0; i > 0; i-- )
+    if( bitlen == 0 )
     {
-        if( zeros && X->p[i - 1] == 0 )
-            continue;
-
-        for( k = sizeof( mbedtls_mpi_uint ) - 1; k >= 0; k-- )
+        str[0] = ' '; str[1] = '0'; str[2] = '0';
+        idx = 3;
+    }
+    else
+    {
+        int n;
+        for( n = (int) ( ( bitlen - 1 ) / 8 ); n >= 0; n-- )
         {
-            if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 )
-                continue;
-            else
-                zeros = 0;
-
-            if( j % 16 == 0 )
+            size_t limb_offset = n / sizeof( mbedtls_mpi_uint );
+            size_t offset_in_limb = n % sizeof( mbedtls_mpi_uint );
+            unsigned char octet =
+                ( X->p[limb_offset] >> ( offset_in_limb * 8 ) ) & 0xff;
+            mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", octet );
+            idx += 3;
+            /* Wrap lines after 16 octets that each take 3 columns */
+            if( idx >= 3 * 16 )
             {
-                if( j > 0 )
-                {
-                    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
-                    debug_send_line( ssl, level, file, line, str );
-                    idx = 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)
-                             ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF );
-
-            j++;
         }
-
     }
 
-    if( zeros == 1 )
-        idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " 00" );
-
-    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
-    debug_send_line( ssl, level, file, line, str );
+    if( idx != 0 )
+    {
+        mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
+        debug_send_line( ssl, level, file, line, str );
+    }
 }
 #endif /* MBEDTLS_BIGNUM_C */
 
diff --git a/third_party/mbedtls/repo/library/des.c b/third_party/mbedtls/repo/library/des.c
index eddf55e..91d22b5 100644
--- a/third_party/mbedtls/repo/library/des.c
+++ b/third_party/mbedtls/repo/library/des.c
@@ -28,6 +28,7 @@
 #if defined(MBEDTLS_DES_C)
 
 #include "mbedtls/des.h"
+#include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
 
 #include <string.h>
@@ -44,29 +45,6 @@
 #if !defined(MBEDTLS_DES_ALT)
 
 /*
- * 32-bit integer manipulation macros (big endian)
- */
-#ifndef GET_UINT32_BE
-#define GET_UINT32_BE(n,b,i)                            \
-{                                                       \
-    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
-        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
-        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
-        | ( (uint32_t) (b)[(i) + 3]       );            \
-}
-#endif
-
-#ifndef PUT_UINT32_BE
-#define PUT_UINT32_BE(n,b,i)                            \
-{                                                       \
-    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
-    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
-    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
-    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
-}
-#endif
-
-/*
  * Expanded DES S-boxes
  */
 static const uint32_t SB1[64] =
@@ -423,8 +401,8 @@
     int i;
     uint32_t X, Y, T;
 
-    GET_UINT32_BE( X, key, 0 );
-    GET_UINT32_BE( Y, key, 4 );
+    X = MBEDTLS_GET_UINT32_BE( key, 0 );
+    Y = MBEDTLS_GET_UINT32_BE( key, 4 );
 
     /*
      * Permuted Choice 1
@@ -633,8 +611,8 @@
 
     SK = ctx->sk;
 
-    GET_UINT32_BE( X, input, 0 );
-    GET_UINT32_BE( Y, input, 4 );
+    X = MBEDTLS_GET_UINT32_BE( input, 0 );
+    Y = MBEDTLS_GET_UINT32_BE( input, 4 );
 
     DES_IP( X, Y );
 
@@ -646,8 +624,8 @@
 
     DES_FP( Y, X );
 
-    PUT_UINT32_BE( Y, output, 0 );
-    PUT_UINT32_BE( X, output, 4 );
+    MBEDTLS_PUT_UINT32_BE( Y, output, 0 );
+    MBEDTLS_PUT_UINT32_BE( X, output, 4 );
 
     return( 0 );
 }
@@ -665,6 +643,7 @@
                     unsigned char *output )
 {
     int i;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char temp[8];
 
     if( length % 8 )
@@ -677,7 +656,9 @@
             for( i = 0; i < 8; i++ )
                 output[i] = (unsigned char)( input[i] ^ iv[i] );
 
-            mbedtls_des_crypt_ecb( ctx, output, output );
+            ret = mbedtls_des_crypt_ecb( ctx, output, output );
+            if( ret != 0 )
+                goto exit;
             memcpy( iv, output, 8 );
 
             input  += 8;
@@ -690,7 +671,9 @@
         while( length > 0 )
         {
             memcpy( temp, input, 8 );
-            mbedtls_des_crypt_ecb( ctx, input, output );
+            ret = mbedtls_des_crypt_ecb( ctx, input, output );
+            if( ret != 0 )
+                goto exit;
 
             for( i = 0; i < 8; i++ )
                 output[i] = (unsigned char)( output[i] ^ iv[i] );
@@ -702,8 +685,10 @@
             length -= 8;
         }
     }
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
@@ -720,8 +705,8 @@
 
     SK = ctx->sk;
 
-    GET_UINT32_BE( X, input, 0 );
-    GET_UINT32_BE( Y, input, 4 );
+    X = MBEDTLS_GET_UINT32_BE( input, 0 );
+    Y = MBEDTLS_GET_UINT32_BE( input, 4 );
 
     DES_IP( X, Y );
 
@@ -745,8 +730,8 @@
 
     DES_FP( Y, X );
 
-    PUT_UINT32_BE( Y, output, 0 );
-    PUT_UINT32_BE( X, output, 4 );
+    MBEDTLS_PUT_UINT32_BE( Y, output, 0 );
+    MBEDTLS_PUT_UINT32_BE( X, output, 4 );
 
     return( 0 );
 }
@@ -764,6 +749,7 @@
                      unsigned char *output )
 {
     int i;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char temp[8];
 
     if( length % 8 )
@@ -776,7 +762,9 @@
             for( i = 0; i < 8; i++ )
                 output[i] = (unsigned char)( input[i] ^ iv[i] );
 
-            mbedtls_des3_crypt_ecb( ctx, output, output );
+            ret = mbedtls_des3_crypt_ecb( ctx, output, output );
+            if( ret != 0 )
+                goto exit;
             memcpy( iv, output, 8 );
 
             input  += 8;
@@ -789,7 +777,9 @@
         while( length > 0 )
         {
             memcpy( temp, input, 8 );
-            mbedtls_des3_crypt_ecb( ctx, input, output );
+            ret = mbedtls_des3_crypt_ecb( ctx, input, output );
+            if( ret != 0 )
+                goto exit;
 
             for( i = 0; i < 8; i++ )
                 output[i] = (unsigned char)( output[i] ^ iv[i] );
@@ -801,8 +791,10 @@
             length -= 8;
         }
     }
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
@@ -895,39 +887,43 @@
         switch( i )
         {
         case 0:
-            mbedtls_des_setkey_dec( &ctx, des3_test_keys );
+            ret = mbedtls_des_setkey_dec( &ctx, des3_test_keys );
             break;
 
         case 1:
-            mbedtls_des_setkey_enc( &ctx, des3_test_keys );
+            ret = mbedtls_des_setkey_enc( &ctx, des3_test_keys );
             break;
 
         case 2:
-            mbedtls_des3_set2key_dec( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set2key_dec( &ctx3, des3_test_keys );
             break;
 
         case 3:
-            mbedtls_des3_set2key_enc( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set2key_enc( &ctx3, des3_test_keys );
             break;
 
         case 4:
-            mbedtls_des3_set3key_dec( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set3key_dec( &ctx3, des3_test_keys );
             break;
 
         case 5:
-            mbedtls_des3_set3key_enc( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set3key_enc( &ctx3, des3_test_keys );
             break;
 
         default:
             return( 1 );
         }
+        if( ret != 0 )
+            goto exit;
 
         for( j = 0; j < 100; j++ )
         {
             if( u == 0 )
-                mbedtls_des_crypt_ecb( &ctx, buf, buf );
+                ret = mbedtls_des_crypt_ecb( &ctx, buf, buf );
             else
-                mbedtls_des3_crypt_ecb( &ctx3, buf, buf );
+                ret = mbedtls_des3_crypt_ecb( &ctx3, buf, buf );
+            if( ret != 0 )
+                goto exit;
         }
 
         if( ( v == MBEDTLS_DES_DECRYPT &&
@@ -970,41 +966,45 @@
         switch( i )
         {
         case 0:
-            mbedtls_des_setkey_dec( &ctx, des3_test_keys );
+            ret = mbedtls_des_setkey_dec( &ctx, des3_test_keys );
             break;
 
         case 1:
-            mbedtls_des_setkey_enc( &ctx, des3_test_keys );
+            ret = mbedtls_des_setkey_enc( &ctx, des3_test_keys );
             break;
 
         case 2:
-            mbedtls_des3_set2key_dec( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set2key_dec( &ctx3, des3_test_keys );
             break;
 
         case 3:
-            mbedtls_des3_set2key_enc( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set2key_enc( &ctx3, des3_test_keys );
             break;
 
         case 4:
-            mbedtls_des3_set3key_dec( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set3key_dec( &ctx3, des3_test_keys );
             break;
 
         case 5:
-            mbedtls_des3_set3key_enc( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set3key_enc( &ctx3, des3_test_keys );
             break;
 
         default:
             return( 1 );
         }
+        if( ret != 0 )
+            goto exit;
 
         if( v == MBEDTLS_DES_DECRYPT )
         {
             for( j = 0; j < 100; j++ )
             {
                 if( u == 0 )
-                    mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+                    ret = mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
                 else
-                    mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+                    ret = mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+                if( ret != 0 )
+                    goto exit;
             }
         }
         else
@@ -1014,9 +1014,11 @@
                 unsigned char tmp[8];
 
                 if( u == 0 )
-                    mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+                    ret = mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
                 else
-                    mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+                    ret = mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+                if( ret != 0 )
+                    goto exit;
 
                 memcpy( tmp, prv, 8 );
                 memcpy( prv, buf, 8 );
@@ -1050,6 +1052,8 @@
     mbedtls_des_free( &ctx );
     mbedtls_des3_free( &ctx3 );
 
+    if( ret != 0 )
+        ret = 1;
     return( ret );
 }
 
diff --git a/third_party/mbedtls/repo/library/dhm.c b/third_party/mbedtls/repo/library/dhm.c
index f796812..88e148b 100644
--- a/third_party/mbedtls/repo/library/dhm.c
+++ b/third_party/mbedtls/repo/library/dhm.c
@@ -79,7 +79,7 @@
         return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
 
     if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 )
-        return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret ) );
 
     (*p) += n;
 
@@ -100,22 +100,21 @@
  */
 static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
 {
-    mbedtls_mpi L, U;
+    mbedtls_mpi U;
     int ret = 0;
 
-    mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U );
+    mbedtls_mpi_init( &U );
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) );
     MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
 
-    if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 ||
+    if( mbedtls_mpi_cmp_int( param, 2 ) < 0 ||
         mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
     {
         ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
     }
 
 cleanup:
-    mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U );
+    mbedtls_mpi_free( &U );
     return( ret );
 }
 
@@ -151,38 +150,44 @@
 }
 
 /*
- * Setup and write the ServerKeyExchange parameters
+ * Pick a random R in the range [2, M-2] for blinding or key generation.
  */
-int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
-                     unsigned char *output, size_t *olen,
-                     int (*f_rng)(void *, unsigned char *, size_t),
-                     void *p_rng )
+static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
+                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
 {
-    int ret, count = 0;
-    size_t n1, n2, n3;
-    unsigned char *p;
-    DHM_VALIDATE_RET( ctx != NULL );
-    DHM_VALIDATE_RET( output != NULL );
-    DHM_VALIDATE_RET( olen != NULL );
-    DHM_VALIDATE_RET( f_rng != NULL );
+    int ret;
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_random( R, 3, M, f_rng, p_rng ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( R, R, 1 ) );
+
+cleanup:
+    return( ret );
+}
+
+static int dhm_make_common( mbedtls_dhm_context *ctx, int x_size,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng )
+{
+    int ret = 0;
 
     if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
         return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
+    if( x_size < 0 )
+        return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
 
-    /*
-     * Generate X as large as possible ( < P )
-     */
-    do
+    if( (unsigned) x_size < mbedtls_mpi_size( &ctx->P ) )
     {
         MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
-
-        while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
-
-        if( count++ > 10 )
-            return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
     }
-    while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
+    else
+    {
+        /* Generate X as large as possible ( <= P - 2 ) */
+        ret = dhm_random_below( &ctx->X, &ctx->P, f_rng, p_rng );
+        if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
+            return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
+        if( ret != 0 )
+            return( ret );
+    }
 
     /*
      * Calculate GX = G^X mod P
@@ -193,16 +198,41 @@
     if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
         return( ret );
 
+cleanup:
+    return( ret );
+}
+
+/*
+ * Setup and write the ServerKeyExchange parameters
+ */
+int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
+                     unsigned char *output, size_t *olen,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng )
+{
+    int ret;
+    size_t n1, n2, n3;
+    unsigned char *p;
+    DHM_VALIDATE_RET( ctx != NULL );
+    DHM_VALIDATE_RET( output != NULL );
+    DHM_VALIDATE_RET( olen != NULL );
+    DHM_VALIDATE_RET( f_rng != NULL );
+
+    ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
+    if( ret != 0 )
+        goto cleanup;
+
     /*
-     * export P, G, GX
+     * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
+     * not required". We omit leading zeros for compactness.
      */
 #define DHM_MPI_EXPORT( X, n )                                          \
     do {                                                                \
         MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ),               \
                                                    p + 2,               \
                                                    ( n ) ) );           \
-        *p++ = (unsigned char)( ( n ) >> 8 );                           \
-        *p++ = (unsigned char)( ( n )      );                           \
+        *p++ = MBEDTLS_BYTE_1( n );                                     \
+        *p++ = MBEDTLS_BYTE_0( n );                                     \
         p += ( n );                                                     \
     } while( 0 )
 
@@ -220,11 +250,9 @@
     ctx->len = n1;
 
 cleanup:
-
-    if( ret != 0 )
-        return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
-
-    return( 0 );
+    if( ret != 0 && ret > -128 )
+        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret );
+    return( ret );
 }
 
 /*
@@ -242,7 +270,7 @@
     if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
         ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
     {
-        return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret ) );
     }
 
     ctx->len = mbedtls_mpi_size( &ctx->P );
@@ -263,7 +291,7 @@
         return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
 
     if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
-        return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret ) );
 
     return( 0 );
 }
@@ -276,7 +304,7 @@
                      int (*f_rng)(void *, unsigned char *, size_t),
                      void *p_rng )
 {
-    int ret, count = 0;
+    int ret;
     DHM_VALIDATE_RET( ctx != NULL );
     DHM_VALIDATE_RET( output != NULL );
     DHM_VALIDATE_RET( f_rng != NULL );
@@ -284,62 +312,17 @@
     if( olen < 1 || olen > ctx->len )
         return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
 
-    if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
-        return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
-
-    /*
-     * generate X and calculate GX = G^X mod P
-     */
-    do
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
-
-        while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
-
-        if( count++ > 10 )
-            return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
-    }
-    while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
-                          &ctx->P , &ctx->RP ) );
-
-    if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
-        return( ret );
+    ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
+    if( ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED )
+        return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
+    if( ret != 0 )
+        goto cleanup;
 
     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
 
 cleanup:
-
-    if( ret != 0 )
-        return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
-
-    return( 0 );
-}
-
-/*
- * Pick a random R in the range [2, M) for blinding purposes
- */
-static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
-                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
-{
-    int ret, count;
-
-    count = 0;
-    do
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) );
-
-        while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 )
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) );
-
-        if( count++ > 10 )
-            return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
-    }
-    while( mbedtls_mpi_cmp_int( R, 1 ) <= 0 );
-
-cleanup:
+    if( ret != 0 && ret > -128 )
+        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret );
     return( ret );
 }
 
@@ -390,7 +373,7 @@
      * We need to generate blinding values from scratch
      */
 
-    /* Vi = random( 2, P-1 ) */
+    /* Vi = random( 2, P-2 ) */
     MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
 
     /* Vf = Vi^-X mod P
@@ -454,15 +437,16 @@
         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
     }
 
+    /* Output the secret without any leading zero byte. This is mandatory
+     * for TLS per RFC 5246 §8.1.2. */
     *olen = mbedtls_mpi_size( &ctx->K );
-
     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
 
 cleanup:
     mbedtls_mpi_free( &GYb );
 
     if( ret != 0 )
-        return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret ) );
 
     return( 0 );
 }
@@ -544,7 +528,7 @@
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
     {
-        ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
+        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
         goto exit;
     }
 
@@ -553,7 +537,7 @@
     if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P  ) ) != 0 ||
         ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
     {
-        ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
+        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
         goto exit;
     }
 
@@ -567,13 +551,13 @@
         mbedtls_mpi_free( &rec );
         if ( ret != 0 )
         {
-            ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
+            ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
             goto exit;
         }
         if ( p != end )
         {
-            ret = MBEDTLS_ERR_DHM_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+            ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
             goto exit;
         }
     }
diff --git a/third_party/mbedtls/repo/library/ecdsa.c b/third_party/mbedtls/repo/library/ecdsa.c
index 22fb5e3..640eb24 100644
--- a/third_party/mbedtls/repo/library/ecdsa.c
+++ b/third_party/mbedtls/repo/library/ecdsa.c
@@ -217,6 +217,9 @@
 
 #endif /* MBEDTLS_ECP_RESTARTABLE */
 
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC) || \
+    !defined(MBEDTLS_ECDSA_SIGN_ALT)     || \
+    !defined(MBEDTLS_ECDSA_VERIFY_ALT)
 /*
  * Derive a suitable integer for group grp from a buffer of length len
  * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
@@ -239,6 +242,7 @@
 cleanup:
     return( ret );
 }
+#endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */
 
 #if !defined(MBEDTLS_ECDSA_SIGN_ALT)
 /*
@@ -466,6 +470,8 @@
 sign:
 #endif
 #if defined(MBEDTLS_ECDSA_SIGN_ALT)
+    (void) f_rng_blind;
+    (void) p_rng_blind;
     ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen,
                               mbedtls_hmac_drbg_random, p_rng );
 #else
@@ -720,7 +726,7 @@
                                     unsigned char *sig, size_t *slen )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char buf[MBEDTLS_ECDSA_MAX_LEN];
+    unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = {0};
     unsigned char *p = buf + sizeof( buf );
     size_t len = 0;
 
@@ -766,6 +772,8 @@
     (void) md_alg;
 
 #if defined(MBEDTLS_ECDSA_SIGN_ALT)
+    (void) rs_ctx;
+
     MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
                          hash, hlen, f_rng, p_rng ) );
 #else
@@ -862,8 +870,8 @@
 
     if( p + len != end )
     {
-        ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA +
-              MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+              MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
         goto cleanup;
     }
 
@@ -874,6 +882,8 @@
         goto cleanup;
     }
 #if defined(MBEDTLS_ECDSA_VERIFY_ALT)
+    (void) rs_ctx;
+
     if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen,
                                       &ctx->Q, &r, &s ) ) != 0 )
         goto cleanup;
diff --git a/third_party/mbedtls/repo/library/ecjpake.c b/third_party/mbedtls/repo/library/ecjpake.c
index 315da4a..368b6c7 100644
--- a/third_party/mbedtls/repo/library/ecjpake.c
+++ b/third_party/mbedtls/repo/library/ecjpake.c
@@ -166,10 +166,7 @@
     if( ret != 0 )
         return( ret );
 
-    (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF );
-    (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF );
-    (*p)[2] = (unsigned char)( ( len >>  8 ) & 0xFF );
-    (*p)[3] = (unsigned char)( ( len       ) & 0xFF );
+    MBEDTLS_PUT_UINT32_BE( len, *p, 0 );
 
     *p += 4 + len;
 
@@ -209,10 +206,8 @@
     if( end - p < 4 )
         return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
 
-    *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF );
-    *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF );
-    *p++ = (unsigned char)( ( id_len >>  8 ) & 0xFF );
-    *p++ = (unsigned char)( ( id_len       ) & 0xFF );
+    MBEDTLS_PUT_UINT32_BE( id_len, p, 0 );
+    p += 4;
 
     if( end < p || (size_t)( end - p ) < id_len )
         return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
@@ -273,7 +268,7 @@
 
     r_len = *(*p)++;
 
-    if( end < *p || (size_t)( end - *p ) < r_len )
+    if( end < *p || (size_t)( end - *p ) < r_len || r_len == 0 )
     {
         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
         goto cleanup;
@@ -352,7 +347,7 @@
         goto cleanup;
     }
 
-    *(*p)++ = (unsigned char)( len & 0xFF );
+    *(*p)++ = MBEDTLS_BYTE_0( len );
     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
     *p += len;
 
@@ -820,6 +815,8 @@
     0x65, 0x73, 0x74
 };
 
+#if !defined(MBEDTLS_ECJPAKE_ALT)
+
 static const unsigned char ecjpake_test_x1[] = {
     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
     0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
@@ -964,6 +961,8 @@
     return( ret );
 }
 
+#endif /* ! MBEDTLS_ECJPAKE_ALT */
+
 /* For tests we don't need a secure RNG;
  * use the LGC from Numerical Recipes for simplicity */
 static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
@@ -1059,6 +1058,12 @@
     if( verbose != 0 )
         mbedtls_printf( "passed\n" );
 
+#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
+     * implementation, so these tests are skipped in case the internal
+     * implementation is swapped out for an alternative one. */
     if( verbose != 0 )
         mbedtls_printf( "  ECJPAKE test #2 (reference handshake): " );
 
@@ -1107,6 +1112,7 @@
 
     if( verbose != 0 )
         mbedtls_printf( "passed\n" );
+#endif /* ! MBEDTLS_ECJPAKE_ALT */
 
 cleanup:
     mbedtls_ecjpake_free( &cli );
diff --git a/third_party/mbedtls/repo/library/ecp.c b/third_party/mbedtls/repo/library/ecp.c
index 05a0b01..7f9e104 100644
--- a/third_party/mbedtls/repo/library/ecp.c
+++ b/third_party/mbedtls/repo/library/ecp.c
@@ -76,6 +76,9 @@
 #include "mbedtls/threading.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
+#include "mbedtls/bn_mul.h"
+
+#include "ecp_invasive.h"
 
 #include <string.h>
 
@@ -1157,8 +1160,7 @@
     /*
      * Next two bytes are the namedcurve value
      */
-    buf[0] = curve_info->tls_id >> 8;
-    buf[1] = curve_info->tls_id & 0xFF;
+    MBEDTLS_PUT_UINT16_BE( curve_info->tls_id, buf, 0 );
 
     return( 0 );
 }
@@ -1243,6 +1245,13 @@
     while( (N).s < 0 && mbedtls_mpi_cmp_int( &(N), 0 ) != 0 )           \
         MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &(N), &(N), &grp->P ) )
 
+#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) ) )
 static inline int mbedtls_mpi_sub_mod( const mbedtls_ecp_group *grp,
                                        mbedtls_mpi *X,
                                        const mbedtls_mpi *A,
@@ -1254,6 +1263,7 @@
 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.
@@ -1276,6 +1286,10 @@
     return( ret );
 }
 
+#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) && \
+    !( defined(MBEDTLS_ECP_NO_FALLBACK) && \
+       defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && \
+       defined(MBEDTLS_ECP_ADD_MIXED_ALT) )
 static inline int mbedtls_mpi_shift_l_mod( const mbedtls_ecp_group *grp,
                                            mbedtls_mpi *X,
                                            size_t count )
@@ -1286,6 +1300,7 @@
 cleanup:
     return( ret );
 }
+#endif /* All functions referencing mbedtls_mpi_shift_l_mod() are alt-implemented without fallback */
 
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
 /*
@@ -1302,9 +1317,6 @@
  */
 static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_mpi Zi, ZZi;
-
     if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
         return( 0 );
 
@@ -1313,6 +1325,11 @@
         return( mbedtls_internal_ecp_normalize_jac( grp, pt ) );
 #endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
 
+#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
+    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+#else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_mpi Zi, ZZi;
     mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
 
     /*
@@ -1338,6 +1355,7 @@
     mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
 
     return( ret );
+#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) */
 }
 
 /*
@@ -1354,10 +1372,6 @@
 static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
                                    mbedtls_ecp_point *T[], size_t T_size )
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t i;
-    mbedtls_mpi *c, u, Zi, ZZi;
-
     if( T_size < 2 )
         return( ecp_normalize_jac( grp, *T ) );
 
@@ -1366,6 +1380,13 @@
         return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) );
 #endif
 
+#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
+    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+#else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t i;
+    mbedtls_mpi *c, u, Zi, ZZi;
+
     if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL )
         return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
 
@@ -1433,6 +1454,7 @@
     mbedtls_free( c );
 
     return( ret );
+#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) */
 }
 
 /*
@@ -1477,9 +1499,6 @@
 static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
                            const mbedtls_ecp_point *P )
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_mpi M, S, T, U;
-
 #if defined(MBEDTLS_SELF_TEST)
     dbl_count++;
 #endif
@@ -1489,6 +1508,12 @@
         return( mbedtls_internal_ecp_double_jac( grp, R, P ) );
 #endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
 
+#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
+    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+#else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_mpi M, S, T, U;
+
     mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U );
 
     /* Special case for A = -3 */
@@ -1550,6 +1575,7 @@
     mbedtls_mpi_free( &M ); mbedtls_mpi_free( &S ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &U );
 
     return( ret );
+#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) */
 }
 
 /*
@@ -1573,9 +1599,6 @@
 static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
                           const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
-
 #if defined(MBEDTLS_SELF_TEST)
     add_count++;
 #endif
@@ -1585,6 +1608,12 @@
         return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) );
 #endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
 
+#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_ADD_MIXED_ALT)
+    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+#else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
+
     /*
      * Trivial cases: P == 0 or Q == 0 (case 1)
      */
@@ -1649,6 +1678,7 @@
     mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
 
     return( ret );
+#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_ADD_MIXED_ALT) */
 }
 
 /*
@@ -1661,34 +1691,21 @@
 static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_mpi l, ll;
-    size_t p_size;
-    int count = 0;
-
 #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
     if( mbedtls_internal_ecp_grp_capable( grp ) )
         return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) );
 #endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
 
-    p_size = ( grp->pbits + 7 ) / 8;
+#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
+    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+#else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_mpi l, ll;
+
     mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
 
     /* Generate l such that 1 < l < p */
-    do
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
-
-        while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
-
-        if( count++ > 10 )
-        {
-            ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
-            goto cleanup;
-        }
-    }
-    while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_random( &l, 2, &grp->P, f_rng, p_rng ) );
 
     /* Z = l * Z */
     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Z,   &pt->Z,     &l  ) );
@@ -1704,7 +1721,10 @@
 cleanup:
     mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
 
+    if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
+        ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
     return( ret );
+#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) */
 }
 
 /*
@@ -2413,19 +2433,22 @@
  */
 static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
 #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
     if( mbedtls_internal_ecp_grp_capable( grp ) )
         return( mbedtls_internal_ecp_normalize_mxz( grp, P ) );
 #endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
 
+#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
+    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+#else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->X, &P->X, &P->Z ) );
     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
 
 cleanup:
     return( ret );
+#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) */
 }
 
 /*
@@ -2439,34 +2462,20 @@
 static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_mpi l;
-    size_t p_size;
-    int count = 0;
-
 #if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
     if( mbedtls_internal_ecp_grp_capable( grp ) )
-        return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
+        return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ) );
 #endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
 
-    p_size = ( grp->pbits + 7 ) / 8;
+#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
+    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+#else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_mpi l;
     mbedtls_mpi_init( &l );
 
     /* Generate l such that 1 < l < p */
-    do
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
-
-        while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
-
-        if( count++ > 10 )
-        {
-            ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
-            goto cleanup;
-        }
-    }
-    while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_random( &l, 2, &grp->P, f_rng, p_rng ) );
 
     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->X, &P->X, &l ) );
     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->Z, &P->Z, &l ) );
@@ -2474,7 +2483,10 @@
 cleanup:
     mbedtls_mpi_free( &l );
 
+    if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
+        ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
     return( ret );
+#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) */
 }
 
 /*
@@ -2497,14 +2509,17 @@
                                const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
                                const mbedtls_mpi *d )
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
-
 #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
     if( mbedtls_internal_ecp_grp_capable( grp ) )
         return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) );
 #endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
 
+#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
+    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+#else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
+
     mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
     mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
     mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
@@ -2534,6 +2549,7 @@
     mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
 
     return( ret );
+#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) */
 }
 
 /*
@@ -2768,7 +2784,7 @@
 
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
 /*
- * R = m * P with shortcuts for m == 1 and m == -1
+ * R = m * P with shortcuts for m == 0, m == 1 and m == -1
  * NOT constant-time - ONLY for short Weierstrass!
  */
 static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
@@ -2779,7 +2795,11 @@
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
+    if( mbedtls_mpi_cmp_int( m, 0 ) == 0 )
+    {
+        MBEDTLS_MPI_CHK( mbedtls_ecp_set_zero( R ) );
+    }
+    else if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
     {
         MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
     }
@@ -2915,6 +2935,97 @@
 #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
 
 #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)}
+#define ECP_MPI_INIT_ARRAY(x)   \
+    ECP_MPI_INIT(1, sizeof(x) / sizeof(mbedtls_mpi_uint), x)
+/*
+ * Constants for the two points other than 0, 1, -1 (mod p) in
+ * https://cr.yp.to/ecdh.html#validate
+ * See ecp_check_pubkey_x25519().
+ */
+static const mbedtls_mpi_uint x25519_bad_point_1[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8( 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae ),
+    MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a ),
+    MBEDTLS_BYTES_TO_T_UINT_8( 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd ),
+    MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00 ),
+};
+static const mbedtls_mpi_uint x25519_bad_point_2[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8( 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24 ),
+    MBEDTLS_BYTES_TO_T_UINT_8( 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b ),
+    MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86 ),
+    MBEDTLS_BYTES_TO_T_UINT_8( 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57 ),
+};
+static const mbedtls_mpi ecp_x25519_bad_point_1 = ECP_MPI_INIT_ARRAY(
+        x25519_bad_point_1 );
+static const mbedtls_mpi ecp_x25519_bad_point_2 = ECP_MPI_INIT_ARRAY(
+        x25519_bad_point_2 );
+#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
+
+/*
+ * Check that the input point is not one of the low-order points.
+ * This is recommended by the "May the Fourth" paper:
+ * https://eprint.iacr.org/2017/806.pdf
+ * Those points are never sent by an honest peer.
+ */
+static int ecp_check_bad_points_mx( const mbedtls_mpi *X, const mbedtls_mpi *P,
+                                    const mbedtls_ecp_group_id grp_id )
+{
+    int ret;
+    mbedtls_mpi XmP;
+
+    mbedtls_mpi_init( &XmP );
+
+    /* Reduce X mod P so that we only need to check values less than P.
+     * We know X < 2^256 so we can proceed by subtraction. */
+    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &XmP, X ) );
+    while( mbedtls_mpi_cmp_mpi( &XmP, P ) >= 0 )
+        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &XmP, &XmP, P ) );
+
+    /* Check against the known bad values that are less than P. For Curve448
+     * these are 0, 1 and -1. For Curve25519 we check the values less than P
+     * from the following list: https://cr.yp.to/ecdh.html#validate */
+    if( mbedtls_mpi_cmp_int( &XmP, 1 ) <= 0 ) /* takes care of 0 and 1 */
+    {
+        ret = MBEDTLS_ERR_ECP_INVALID_KEY;
+        goto cleanup;
+    }
+
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+    if( grp_id == MBEDTLS_ECP_DP_CURVE25519 )
+    {
+        if( mbedtls_mpi_cmp_mpi( &XmP, &ecp_x25519_bad_point_1 ) == 0 )
+        {
+            ret = MBEDTLS_ERR_ECP_INVALID_KEY;
+            goto cleanup;
+        }
+
+        if( mbedtls_mpi_cmp_mpi( &XmP, &ecp_x25519_bad_point_2 ) == 0 )
+        {
+            ret = MBEDTLS_ERR_ECP_INVALID_KEY;
+            goto cleanup;
+        }
+    }
+#else
+    (void) grp_id;
+#endif
+
+    /* Final check: check if XmP + 1 is P (final because it changes XmP!) */
+    MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &XmP, &XmP, 1 ) );
+    if( mbedtls_mpi_cmp_mpi( &XmP, P ) == 0 )
+    {
+        ret = MBEDTLS_ERR_ECP_INVALID_KEY;
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    mbedtls_mpi_free( &XmP );
+
+    return( ret );
+}
+
 /*
  * Check validity of a public key for Montgomery curves with x-only schemes
  */
@@ -2926,7 +3037,13 @@
     if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
         return( MBEDTLS_ERR_ECP_INVALID_KEY );
 
-    return( 0 );
+    /* Implicit in all standards (as they don't consider negative numbers):
+     * X must be non-negative. This is normally ensured by the way it's
+     * encoded for transmission, but let's be extra sure. */
+    if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 )
+        return( MBEDTLS_ERR_ECP_INVALID_KEY );
+
+    return( ecp_check_bad_points_mx( &pt->X, &grp->P, grp->id ) );
 }
 #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
 
@@ -2994,6 +3111,56 @@
     return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
 }
 
+#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_gen_privkey_mx( size_t high_bit,
+                                mbedtls_mpi *d,
+                                int (*f_rng)(void *, unsigned char *, size_t),
+                                void *p_rng )
+{
+    int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    size_t n_random_bytes = high_bit / 8 + 1;
+
+    /* [Curve25519] page 5 */
+    /* Generate a (high_bit+1)-bit random number by generating just enough
+     * random bytes, then shifting out extra bits from the top (necessary
+     * when (high_bit+1) is not a multiple of 8). */
+    MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_random_bytes,
+                                              f_rng, p_rng ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_random_bytes - high_bit - 1 ) );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, high_bit, 1 ) );
+
+    /* Make sure the last two bits are unset for Curve448, three bits for
+       Curve25519 */
+    MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
+    if( high_bit == 254 )
+    {
+        MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
+    }
+
+cleanup:
+    return( ret );
+}
+#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
+
+#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
+static int mbedtls_ecp_gen_privkey_sw(
+    const mbedtls_mpi *N, mbedtls_mpi *d,
+    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    int ret = mbedtls_mpi_random( d, 1, N, f_rng, p_rng );
+    switch( ret )
+    {
+        case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE:
+            return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
+        default:
+            return( ret );
+    }
+}
+#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
+
 /*
  * Generate a private key
  */
@@ -3002,89 +3169,21 @@
                      int (*f_rng)(void *, unsigned char *, size_t),
                      void *p_rng )
 {
-    int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
-    size_t n_size;
-
     ECP_VALIDATE_RET( grp   != NULL );
     ECP_VALIDATE_RET( d     != NULL );
     ECP_VALIDATE_RET( f_rng != NULL );
 
-    n_size = ( grp->nbits + 7 ) / 8;
-
 #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
     if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
-    {
-        /* [M225] page 5 */
-        size_t b;
-
-        do {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
-        } while( mbedtls_mpi_bitlen( d ) == 0);
-
-        /* Make sure the most significant bit is nbits */
-        b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
-        if( b > grp->nbits )
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
-        else
-            MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
-
-        /* Make sure the last two bits are unset for Curve448, three bits for
-           Curve25519 */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
-        if( grp->nbits == 254 )
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
-        }
-    }
+        return( mbedtls_ecp_gen_privkey_mx( grp->nbits, d, f_rng, p_rng ) );
 #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
 
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
     if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
-    {
-        /* SEC1 3.2.1: Generate d such that 1 <= n < N */
-        int count = 0;
-        unsigned cmp = 0;
-
-        /*
-         * Match the procedure given in RFC 6979 (deterministic ECDSA):
-         * - use the same byte ordering;
-         * - keep the leftmost nbits bits of the generated octet string;
-         * - try until result is in the desired range.
-         * This also avoids any biais, which is especially important for ECDSA.
-         */
-        do
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
-
-            /*
-             * Each try has at worst a probability 1/2 of failing (the msb has
-             * a probability 1/2 of being 0, and then the result will be < N),
-             * so after 30 tries failure probability is a most 2**(-30).
-             *
-             * For most curves, 1 try is enough with overwhelming probability,
-             * since N starts with a lot of 1s in binary, but some curves
-             * such as secp224k1 are actually very close to the worst case.
-             */
-            if( ++count > 30 )
-            {
-                ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
-                goto cleanup;
-            }
-
-            ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
-            if( ret != 0 )
-            {
-                goto cleanup;
-            }
-        }
-        while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
-    }
+        return( mbedtls_ecp_gen_privkey_sw( &grp->N, d, f_rng, p_rng ) );
 #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
 
-cleanup:
-    return( ret );
+    return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
 }
 
 /*
diff --git a/third_party/mbedtls/repo/library/ecp_curves.c b/third_party/mbedtls/repo/library/ecp_curves.c
index 839fb5e..ff26a18 100644
--- a/third_party/mbedtls/repo/library/ecp_curves.c
+++ b/third_party/mbedtls/repo/library/ecp_curves.c
@@ -24,6 +24,9 @@
 #include "mbedtls/ecp.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
+#include "mbedtls/bn_mul.h"
+
+#include "ecp_invasive.h"
 
 #include <string.h>
 
@@ -40,44 +43,10 @@
 #define inline __inline
 #endif
 
-/*
- * Conversion macros for embedded constants:
- * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2
- */
-#if defined(MBEDTLS_HAVE_INT32)
+#define ECP_MPI_INIT(s, n, p) {s, (n), (mbedtls_mpi_uint *)(p)}
 
-#define BYTES_TO_T_UINT_4( a, b, c, d )                       \
-    ( (mbedtls_mpi_uint) (a) <<  0 ) |                        \
-    ( (mbedtls_mpi_uint) (b) <<  8 ) |                        \
-    ( (mbedtls_mpi_uint) (c) << 16 ) |                        \
-    ( (mbedtls_mpi_uint) (d) << 24 )
-
-#define BYTES_TO_T_UINT_2( a, b )                   \
-    BYTES_TO_T_UINT_4( a, b, 0, 0 )
-
-#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
-    BYTES_TO_T_UINT_4( a, b, c, d ),                \
-    BYTES_TO_T_UINT_4( e, f, g, h )
-
-#else /* 64-bits */
-
-#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \
-    ( (mbedtls_mpi_uint) (a) <<  0 ) |                        \
-    ( (mbedtls_mpi_uint) (b) <<  8 ) |                        \
-    ( (mbedtls_mpi_uint) (c) << 16 ) |                        \
-    ( (mbedtls_mpi_uint) (d) << 24 ) |                        \
-    ( (mbedtls_mpi_uint) (e) << 32 ) |                        \
-    ( (mbedtls_mpi_uint) (f) << 40 ) |                        \
-    ( (mbedtls_mpi_uint) (g) << 48 ) |                        \
-    ( (mbedtls_mpi_uint) (h) << 56 )
-
-#define BYTES_TO_T_UINT_4( a, b, c, d )             \
-    BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 )
-
-#define BYTES_TO_T_UINT_2( a, b )                   \
-    BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 )
-
-#endif /* bits in mbedtls_mpi_uint */
+#define ECP_MPI_INIT_ARRAY(x)   \
+    ECP_MPI_INIT(1, sizeof(x) / sizeof(mbedtls_mpi_uint), x)
 
 /*
  * Note: the constants are in little-endian order
@@ -89,29 +58,29 @@
  */
 #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
 static const mbedtls_mpi_uint secp192r1_p[] = {
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    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( 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[] = {
-    BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ),
-    BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ),
-    BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ),
-    BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ),
-    BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ),
-    BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ),
-    BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ),
-    BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    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 ),
 };
 #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
 
@@ -120,34 +89,34 @@
  */
 #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
 static const mbedtls_mpi_uint secp224r1_p[] = {
-    BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
-    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ),
-    BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ),
-    BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ),
-    BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ),
-    BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ),
-    BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ),
-    BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ),
-    BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ),
-    BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ),
-    BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ),
-    BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ),
+    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 ),
 };
 #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
 
@@ -156,34 +125,34 @@
  */
 #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
 static const mbedtls_mpi_uint secp256r1_p[] = {
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
-    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
-    BYTES_TO_T_UINT_8( 0x01, 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 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ),
-    BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ),
-    BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ),
-    BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ),
-    BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ),
-    BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ),
-    BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ),
-    BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ),
-    BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ),
-    BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ),
-    BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
+    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 ),
 };
 #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
 
@@ -192,44 +161,44 @@
  */
 #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
 static const mbedtls_mpi_uint secp384r1_p[] = {
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
-    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    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, 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[] = {
-    BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ),
-    BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ),
-    BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ),
-    BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ),
-    BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ),
-    BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ),
-    BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ),
-    BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ),
-    BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ),
-    BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ),
-    BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ),
-    BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ),
-    BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ),
-    BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ),
-    BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ),
-    BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ),
-    BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ),
-    BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    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 ),
 };
 #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
 
@@ -238,154 +207,154 @@
  */
 #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
 static const mbedtls_mpi_uint secp521r1_p[] = {
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_2( 0xFF, 0x01 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ),
-    BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ),
-    BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ),
-    BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ),
-    BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ),
-    BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ),
-    BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ),
-    BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ),
-    BYTES_TO_T_UINT_2( 0x51, 0x00 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ),
-    BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ),
-    BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ),
-    BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ),
-    BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ),
-    BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ),
-    BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ),
-    BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ),
-    BYTES_TO_T_UINT_2( 0xC6, 0x00 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ),
-    BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ),
-    BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ),
-    BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ),
-    BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ),
-    BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ),
-    BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ),
-    BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ),
-    BYTES_TO_T_UINT_2( 0x18, 0x01 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ),
-    BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ),
-    BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ),
-    BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ),
-    BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_2( 0xFF, 0x01 ),
+    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 ),
 };
 #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
 static const mbedtls_mpi_uint secp192k1_p[] = {
-    BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    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[] = {
-    BYTES_TO_T_UINT_2( 0x00, 0x00 ),
+    MBEDTLS_BYTES_TO_T_UINT_2( 0x00, 0x00 ),
 };
 static const mbedtls_mpi_uint secp192k1_b[] = {
-    BYTES_TO_T_UINT_2( 0x03, 0x00 ),
+    MBEDTLS_BYTES_TO_T_UINT_2( 0x03, 0x00 ),
 };
 static const mbedtls_mpi_uint secp192k1_gx[] = {
-    BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ),
-    BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ),
-    BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ),
-    BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ),
-    BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ),
-    BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    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 ),
 };
 #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
 static const mbedtls_mpi_uint secp224k1_p[] = {
-    BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ),
+    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[] = {
-    BYTES_TO_T_UINT_2( 0x00, 0x00 ),
+    MBEDTLS_BYTES_TO_T_UINT_2( 0x00, 0x00 ),
 };
 static const mbedtls_mpi_uint secp224k1_b[] = {
-    BYTES_TO_T_UINT_2( 0x05, 0x00 ),
+    MBEDTLS_BYTES_TO_T_UINT_2( 0x05, 0x00 ),
 };
 static const mbedtls_mpi_uint secp224k1_gx[] = {
-    BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ),
-    BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ),
-    BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ),
-    BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ),
-    BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ),
-    BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ),
-    BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ),
-    BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ),
-    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
-    BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ),
+    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 ),
 };
 #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
 static const mbedtls_mpi_uint secp256k1_p[] = {
-    BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    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[] = {
-    BYTES_TO_T_UINT_2( 0x00, 0x00 ),
+    MBEDTLS_BYTES_TO_T_UINT_2( 0x00, 0x00 ),
 };
 static const mbedtls_mpi_uint secp256k1_b[] = {
-    BYTES_TO_T_UINT_2( 0x07, 0x00 ),
+    MBEDTLS_BYTES_TO_T_UINT_2( 0x07, 0x00 ),
 };
 static const mbedtls_mpi_uint secp256k1_gx[] = {
-    BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ),
-    BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ),
-    BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ),
-    BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ),
-    BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ),
-    BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ),
-    BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ),
-    BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ),
-    BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
+    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 ),
 };
 #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
 
@@ -394,40 +363,40 @@
  */
 #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
 static const mbedtls_mpi_uint brainpoolP256r1_p[] = {
-    BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ),
-    BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ),
-    BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ),
-    BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ),
-    BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ),
-    BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ),
-    BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ),
-    BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ),
-    BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ),
-    BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ),
-    BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ),
-    BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ),
-    BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ),
-    BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ),
-    BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ),
-    BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ),
-    BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ),
-    BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ),
-    BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ),
+    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 ),
 };
 #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */
 
@@ -436,52 +405,52 @@
  */
 #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
 static const mbedtls_mpi_uint brainpoolP384r1_p[] = {
-    BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ),
-    BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ),
-    BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ),
-    BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ),
-    BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ),
-    BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ),
-    BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ),
-    BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ),
-    BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ),
-    BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ),
-    BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ),
-    BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ),
-    BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ),
-    BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ),
-    BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ),
-    BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ),
-    BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ),
-    BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ),
-    BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ),
-    BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ),
-    BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ),
-    BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ),
-    BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ),
-    BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ),
-    BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ),
-    BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ),
-    BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ),
-    BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ),
-    BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ),
-    BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ),
-    BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ),
+    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 ),
 };
 #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */
 
@@ -490,64 +459,64 @@
  */
 #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
 static const mbedtls_mpi_uint brainpoolP512r1_p[] = {
-    BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ),
-    BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ),
-    BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ),
-    BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ),
-    BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ),
-    BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ),
-    BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ),
-    BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ),
-    BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ),
-    BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ),
-    BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ),
-    BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ),
-    BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ),
-    BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ),
-    BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ),
-    BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ),
-    BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ),
-    BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ),
-    BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ),
-    BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ),
-    BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ),
-    BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ),
-    BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ),
-    BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ),
-    BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ),
-    BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ),
-    BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ),
-    BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ),
-    BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ),
-    BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ),
-    BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ),
-    BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ),
-    BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ),
-    BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ),
-    BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ),
-    BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ),
+    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[] = {
-    BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ),
-    BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ),
-    BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ),
-    BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ),
-    BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ),
-    BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ),
-    BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ),
-    BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ),
+    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 ),
 };
 #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
 
@@ -678,6 +647,13 @@
 #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;
+static const unsigned char curve25519_part_of_n[] = {
+    0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, 0x9C, 0xD6,
+    0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED,
+};
+
 /*
  * Specialized function for creating the Curve25519 group
  */
@@ -686,7 +662,7 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     /* Actually ( A + 2 ) / 4 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "01DB42" ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->A, curve25519_a24 ) );
 
     /* P = 2^255 - 19 */
     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) );
@@ -695,8 +671,8 @@
     grp->pbits = mbedtls_mpi_bitlen( &grp->P );
 
     /* N = 2^252 + 27742317777372353535851937790883648493 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->N, 16,
-                                              "14DEF9DEA2F79CD65812631A5CF5D3ED" ) );
+    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.
@@ -717,6 +693,15 @@
 #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;
+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,
+};
+
 /*
  * Specialized function for creating the Curve448 group
  */
@@ -728,7 +713,7 @@
     mbedtls_mpi_init( &Ns );
 
     /* Actually ( A + 2 ) / 4 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "98AA" ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->A, curve448_a24 ) );
 
     /* P = 2^448 - 2^224 - 1 */
     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) );
@@ -746,8 +731,8 @@
 
     /* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */
     MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 446, 1 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &Ns, 16,
-                                              "8335DC163BB124B65129C96FDE933D8D723A70AADC873D6D54A7BB0D" ) );
+    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 */
@@ -1000,25 +985,20 @@
 #define ADD( j )    add32( &cur, A( j ), &c );
 #define SUB( j )    sub32( &cur, A( j ), &c );
 
+#define ciL    (sizeof(mbedtls_mpi_uint))         /* chars in limb  */
+#define biL    (ciL << 3)                         /* bits  in limb  */
+
 /*
  * Helpers for the main 'loop'
- * (see fix_negative for the motivation of C)
  */
 #define INIT( b )                                                       \
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;                                                            \
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;                    \
     signed char c = 0, cc;                                              \
     uint32_t cur;                                                       \
     size_t i = 0, bits = (b);                                           \
-    mbedtls_mpi C;                                                      \
-    mbedtls_mpi_uint Cp[ (b) / 8 / sizeof( mbedtls_mpi_uint) + 1 ];     \
-                                                                        \
-    C.s = 1;                                                            \
-    C.n = (b) / 8 / sizeof( mbedtls_mpi_uint) + 1;                      \
-    C.p = Cp;                                                           \
-    memset( Cp, 0, C.n * sizeof( mbedtls_mpi_uint ) );                  \
-                                                                        \
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, (b) * 2 / 8 /                 \
-                                       sizeof( mbedtls_mpi_uint ) ) );  \
+    /* N is the size of the product of two b-bit numbers, plus one */   \
+    /* limb for fix_negative */                                         \
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, ( b ) * 2 / biL + 1 ) );      \
     LOAD32;
 
 #define NEXT                    \
@@ -1033,33 +1013,41 @@
     STORE32; i++;                               \
     cur = c > 0 ? c : 0; STORE32;               \
     cur = 0; while( ++i < MAX32 ) { STORE32; }  \
-    if( c < 0 ) MBEDTLS_MPI_CHK( fix_negative( N, c, &C, bits ) );
+    if( c < 0 ) mbedtls_ecp_fix_negative( N, c, bits );
 
 /*
  * If the result is negative, we get it in the form
- * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits'
+ * c * 2^bits + N, with c negative and N positive shorter than 'bits'
  */
-static inline int fix_negative( mbedtls_mpi *N, signed char c, mbedtls_mpi *C, size_t bits )
+MBEDTLS_STATIC_TESTABLE
+void mbedtls_ecp_fix_negative( mbedtls_mpi *N, signed char c, size_t bits )
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t i;
 
-    /* C = - c * 2^(bits + 32) */
-#if !defined(MBEDTLS_HAVE_INT64)
-    ((void) bits);
-#else
-    if( bits == 224 )
-        C->p[ C->n - 1 ] = ((mbedtls_mpi_uint) -c) << 32;
-    else
-#endif
-        C->p[ C->n - 1 ] = (mbedtls_mpi_uint) -c;
-
-    /* N = - ( C - N ) */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, C, N ) );
+    /* Set N := 2^bits - 1 - N. We know that 0 <= N < 2^bits, so
+     * set the absolute value to 0xfff...fff - N. There is no carry
+     * since we're subtracting from all-bits-one.  */
+    for( i = 0; i <= bits / 8 / sizeof( mbedtls_mpi_uint ); i++ )
+    {
+        N->p[i] = ~(mbedtls_mpi_uint)0 - N->p[i];
+    }
+    /* Add 1, taking care of the carry. */
+    i = 0;
+    do
+        ++N->p[i];
+    while( N->p[i++] == 0 && i <= bits / 8 / sizeof( mbedtls_mpi_uint ) );
+    /* Invert the sign.
+     * Now N = N0 - 2^bits where N0 is the initial value of N. */
     N->s = -1;
 
-cleanup:
-
-    return( ret );
+    /* Add |c| * 2^bits to the absolute value. Since c and N are
+    * negative, this adds c * 2^bits. */
+    mbedtls_mpi_uint msw = (mbedtls_mpi_uint) -c;
+#if defined(MBEDTLS_HAVE_INT64)
+    if( bits == 224 )
+        msw <<= 32;
+#endif
+    N->p[bits / 8 / sizeof( mbedtls_mpi_uint)] += msw;
 }
 
 #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
@@ -1441,9 +1429,11 @@
 static int ecp_mod_p192k1( mbedtls_mpi *N )
 {
     static mbedtls_mpi_uint Rp[] = {
-        BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) };
+        MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00,
+                                   0x00 ) };
 
-    return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) );
+    return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0,
+                             0 ) );
 }
 #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
 
@@ -1455,12 +1445,14 @@
 static int ecp_mod_p224k1( mbedtls_mpi *N )
 {
     static mbedtls_mpi_uint Rp[] = {
-        BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) };
+        MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00,
+                                   0x00 ) };
 
 #if defined(MBEDTLS_HAVE_INT64)
     return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) );
 #else
-    return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) );
+    return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0,
+                             0 ) );
 #endif
 }
 
@@ -1474,8 +1466,10 @@
 static int ecp_mod_p256k1( mbedtls_mpi *N )
 {
     static mbedtls_mpi_uint Rp[] = {
-        BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) };
-    return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) );
+        MBEDTLS_BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00,
+                                   0x00 ) };
+    return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0,
+                             0 ) );
 }
 #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
 
diff --git a/third_party/mbedtls/repo/library/ecp_invasive.h b/third_party/mbedtls/repo/library/ecp_invasive.h
new file mode 100644
index 0000000..71c7702
--- /dev/null
+++ b/third_party/mbedtls/repo/library/ecp_invasive.h
@@ -0,0 +1,81 @@
+/**
+ * \file ecp_invasive.h
+ *
+ * \brief ECP 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_ECP_INVASIVE_H
+#define MBEDTLS_ECP_INVASIVE_H
+
+#include "common.h"
+#include "mbedtls/bignum.h"
+#include "mbedtls/ecp.h"
+
+#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_C)
+
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \
+    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \
+    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
+ *
+ * Behavior:
+ * Set N to c * 2^bits + old_value_of_N.
+ */
+void mbedtls_ecp_fix_negative( mbedtls_mpi *N, signed char c, size_t bits );
+#endif
+
+#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
+/** Generate a private key on a Montgomery curve (Curve25519 or Curve448).
+ *
+ * This function implements key generation for the set of secret keys
+ * specified in [Curve25519] p. 5 and in [Curve448]. The resulting value
+ * has the lower bits masked but is not necessarily canonical.
+ *
+ * \note            - [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf
+ *                  - [RFC7748] https://tools.ietf.org/html/rfc7748
+ *
+ * \p high_bit      The position of the high-order bit of the key to generate.
+ *                  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
+ *                  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.
+ *
+ * \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,
+                                mbedtls_mpi *d,
+                                int (*f_rng)(void *, unsigned char *, size_t),
+                                void *p_rng );
+
+#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
+
+#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_ECP_C */
+
+#endif /* MBEDTLS_ECP_INVASIVE_H */
diff --git a/third_party/mbedtls/repo/library/entropy.c b/third_party/mbedtls/repo/library/entropy.c
index db61f16..12fd3b9 100644
--- a/third_party/mbedtls/repo/library/entropy.c
+++ b/third_party/mbedtls/repo/library/entropy.c
@@ -116,6 +116,11 @@
 
 void mbedtls_entropy_free( mbedtls_entropy_context *ctx )
 {
+    /* 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 )
+        return;
+
 #if defined(MBEDTLS_HAVEGE_C)
     mbedtls_havege_free( &ctx->havege_data );
 #endif
@@ -132,7 +137,7 @@
 #endif
     ctx->source_count = 0;
     mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) );
-    ctx->accumulator_started = 0;
+    ctx->accumulator_started = -1;
 }
 
 int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx,
@@ -466,15 +471,21 @@
 #if defined(MBEDTLS_FS_IO)
 int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path )
 {
-    int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
-    FILE *f;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    FILE *f = NULL;
     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
 
-    if( ( f = fopen( path, "wb" ) ) == NULL )
-        return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
-
     if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
+    {
+        ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
         goto exit;
+    }
+
+    if( ( f = fopen( path, "wb" ) ) == NULL )
+    {
+        ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
+        goto exit;
+    }
 
     if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE )
     {
@@ -487,7 +498,9 @@
 exit:
     mbedtls_platform_zeroize( buf, sizeof( buf ) );
 
-    fclose( f );
+    if( f != NULL )
+        fclose( f );
+
     return( ret );
 }
 
diff --git a/third_party/mbedtls/repo/library/entropy_poll.c b/third_party/mbedtls/repo/library/entropy_poll.c
index 5250a7b..2c1e093 100644
--- a/third_party/mbedtls/repo/library/entropy_poll.c
+++ b/third_party/mbedtls/repo/library/entropy_poll.c
@@ -109,6 +109,21 @@
 #endif /* SYS_getrandom */
 #endif /* __linux__ || __midipix__ */
 
+#if defined(__FreeBSD__) || defined(__DragonFly__)
+#include <sys/param.h>
+#if (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || \
+    (defined(__DragonFly__) && __DragonFly_version >= 500700)
+#include <errno.h>
+#include <sys/random.h>
+#define HAVE_GETRANDOM
+static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
+{
+    return getrandom( buf, buflen, flags );
+}
+#endif /* (__FreeBSD__ && __FreeBSD_version >= 1200000) ||
+          (__DragonFly__ && __DragonFly_version >= 500700) */
+#endif /* __FreeBSD__ || __DragonFly__ */
+
 /*
  * Some BSD systems provide KERN_ARND.
  * This is equivalent to reading from /dev/urandom, only it doesn't require an
@@ -205,13 +220,13 @@
 {
     ((void) data);
     ((void) output);
-    *olen = 0;
 
+    *olen = 0;
     if( len < sizeof(unsigned char) )
         return( 0 );
 
+    output[0] = 0;
     *olen = sizeof(unsigned char);
-
     return( 0 );
 }
 #endif
diff --git a/third_party/mbedtls/repo/library/error.c b/third_party/mbedtls/repo/library/error.c
index 901a369..afad389 100644
--- a/third_party/mbedtls/repo/library/error.c
+++ b/third_party/mbedtls/repo/library/error.c
@@ -973,4 +973,8 @@
 
 #endif /* MBEDTLS_ERROR_C */
 
+#if defined(MBEDTLS_TEST_HOOKS)
+void (*mbedtls_test_hook_error_add)( int, int, const char *, int );
+#endif
+
 #endif /* MBEDTLS_ERROR_C || MBEDTLS_ERROR_STRERROR_DUMMY */
diff --git a/third_party/mbedtls/repo/library/gcm.c b/third_party/mbedtls/repo/library/gcm.c
index 2363e58..43a5e1b 100644
--- a/third_party/mbedtls/repo/library/gcm.c
+++ b/third_party/mbedtls/repo/library/gcm.c
@@ -59,29 +59,6 @@
     MBEDTLS_INTERNAL_VALIDATE( cond )
 
 /*
- * 32-bit integer manipulation macros (big endian)
- */
-#ifndef GET_UINT32_BE
-#define GET_UINT32_BE(n,b,i)                            \
-{                                                       \
-    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
-        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
-        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
-        | ( (uint32_t) (b)[(i) + 3]       );            \
-}
-#endif
-
-#ifndef PUT_UINT32_BE
-#define PUT_UINT32_BE(n,b,i)                            \
-{                                                       \
-    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
-    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
-    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
-    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
-}
-#endif
-
-/*
  * Initialize a context
  */
 void mbedtls_gcm_init( mbedtls_gcm_context *ctx )
@@ -111,12 +88,12 @@
         return( ret );
 
     /* pack h as two 64-bits ints, big-endian */
-    GET_UINT32_BE( hi, h,  0  );
-    GET_UINT32_BE( lo, h,  4  );
+    hi = MBEDTLS_GET_UINT32_BE( h,  0  );
+    lo = MBEDTLS_GET_UINT32_BE( h,  4  );
     vh = (uint64_t) hi << 32 | lo;
 
-    GET_UINT32_BE( hi, h,  8  );
-    GET_UINT32_BE( lo, h,  12 );
+    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) */
@@ -223,10 +200,10 @@
     if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) {
         unsigned char h[16];
 
-        PUT_UINT32_BE( ctx->HH[8] >> 32, h,  0 );
-        PUT_UINT32_BE( ctx->HH[8],       h,  4 );
-        PUT_UINT32_BE( ctx->HL[8] >> 32, h,  8 );
-        PUT_UINT32_BE( ctx->HL[8],       h, 12 );
+        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 );
 
         mbedtls_aesni_gcm_mult( output, x, h );
         return;
@@ -262,10 +239,10 @@
         zl ^= ctx->HL[hi];
     }
 
-    PUT_UINT32_BE( zh >> 32, output, 0 );
-    PUT_UINT32_BE( zh, output, 4 );
-    PUT_UINT32_BE( zl >> 32, output, 8 );
-    PUT_UINT32_BE( zl, output, 12 );
+    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 );
 }
 
 int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
@@ -280,6 +257,7 @@
     size_t i;
     const unsigned char *p;
     size_t use_len, olen = 0;
+    uint64_t iv_bits;
 
     GCM_VALIDATE_RET( ctx != NULL );
     GCM_VALIDATE_RET( iv != NULL );
@@ -309,7 +287,8 @@
     else
     {
         memset( work_buf, 0x00, 16 );
-        PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
+        iv_bits = (uint64_t)iv_len * 8;
+        MBEDTLS_PUT_UINT64_BE( iv_bits, work_buf, 8 );
 
         p = iv;
         while( iv_len > 0 )
@@ -442,10 +421,10 @@
     {
         memset( work_buf, 0x00, 16 );
 
-        PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0  );
-        PUT_UINT32_BE( ( orig_add_len       ), work_buf, 4  );
-        PUT_UINT32_BE( ( orig_len     >> 32 ), work_buf, 8  );
-        PUT_UINT32_BE( ( orig_len           ), work_buf, 12 );
+        MBEDTLS_PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0  );
+        MBEDTLS_PUT_UINT32_BE( ( orig_add_len       ), work_buf, 4  );
+        MBEDTLS_PUT_UINT32_BE( ( orig_len     >> 32 ), work_buf, 8  );
+        MBEDTLS_PUT_UINT32_BE( ( orig_len           ), work_buf, 12 );
 
         for( i = 0; i < 16; i++ )
             ctx->buf[i] ^= work_buf[i];
@@ -819,6 +798,15 @@
                                 add_len_test_data[i],
                                 pt_test_data[pt_index_test_data[i]],
                                 buf, 16, tag_buf );
+#if defined(MBEDTLS_GCM_ALT)
+            /* Allow alternative implementations to only support 12-byte nonces. */
+            if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
+                iv_len_test_data[i] != 12 )
+            {
+                mbedtls_printf( "skipped\n" );
+                break;
+            }
+#endif /* defined(MBEDTLS_GCM_ALT) */
             if( ret != 0 )
                 goto exit;
 
diff --git a/third_party/mbedtls/repo/library/hmac_drbg.c b/third_party/mbedtls/repo/library/hmac_drbg.c
index 25a0225..de97068 100644
--- a/third_party/mbedtls/repo/library/hmac_drbg.c
+++ b/third_party/mbedtls/repo/library/hmac_drbg.c
@@ -54,10 +54,6 @@
     memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
 
     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
-
-#if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_init( &ctx->mutex );
-#endif
 }
 
 /*
@@ -129,6 +125,10 @@
     if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
         return( ret );
 
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_init( &ctx->mutex );
+#endif
+
     /*
      * Set initial working state.
      * Use the V memory location, which is currently all 0, to initialize the
@@ -254,6 +254,11 @@
     if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
         return( ret );
 
+    /* The mutex is initialized iff the md context is set up. */
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_init( &ctx->mutex );
+#endif
+
     md_size = mbedtls_md_get_size( md_info );
 
     /*
@@ -421,14 +426,13 @@
         return;
 
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_free( &ctx->mutex );
+    /* The mutex is initialized iff the md context is set up. */
+    if( ctx->md_ctx.md_info != NULL )
+        mbedtls_mutex_free( &ctx->mutex );
 #endif
     mbedtls_md_free( &ctx->md_ctx );
     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
-#if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_init( &ctx->mutex );
-#endif
 }
 
 #if defined(MBEDTLS_FS_IO)
diff --git a/third_party/mbedtls/repo/library/md.c b/third_party/mbedtls/repo/library/md.c
index de77b16..a10a835 100644
--- a/third_party/mbedtls/repo/library/md.c
+++ b/third_party/mbedtls/repo/library/md.c
@@ -1,5 +1,5 @@
 /**
- * \file mbedtls_md.c
+ * \file md.c
  *
  * \brief Generic message digest wrapper for mbed TLS
  *
diff --git a/third_party/mbedtls/repo/library/md4.c b/third_party/mbedtls/repo/library/md4.c
index 4fd6bc3..eaa679a 100644
--- a/third_party/mbedtls/repo/library/md4.c
+++ b/third_party/mbedtls/repo/library/md4.c
@@ -44,29 +44,6 @@
 
 #if !defined(MBEDTLS_MD4_ALT)
 
-/*
- * 32-bit integer manipulation macros (little endian)
- */
-#ifndef GET_UINT32_LE
-#define GET_UINT32_LE(n,b,i)                            \
-{                                                       \
-    (n) = ( (uint32_t) (b)[(i)    ]       )             \
-        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \
-        | ( (uint32_t) (b)[(i) + 2] << 16 )             \
-        | ( (uint32_t) (b)[(i) + 3] << 24 );            \
-}
-#endif
-
-#ifndef PUT_UINT32_LE
-#define PUT_UINT32_LE(n,b,i)                                    \
-{                                                               \
-    (b)[(i)    ] = (unsigned char) ( ( (n)       ) & 0xFF );    \
-    (b)[(i) + 1] = (unsigned char) ( ( (n) >>  8 ) & 0xFF );    \
-    (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF );    \
-    (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF );    \
-}
-#endif
-
 void mbedtls_md4_init( mbedtls_md4_context *ctx )
 {
     memset( ctx, 0, sizeof( mbedtls_md4_context ) );
@@ -118,22 +95,22 @@
         uint32_t X[16], A, B, C, D;
     } local;
 
-    GET_UINT32_LE( local.X[ 0], data,  0 );
-    GET_UINT32_LE( local.X[ 1], data,  4 );
-    GET_UINT32_LE( local.X[ 2], data,  8 );
-    GET_UINT32_LE( local.X[ 3], data, 12 );
-    GET_UINT32_LE( local.X[ 4], data, 16 );
-    GET_UINT32_LE( local.X[ 5], data, 20 );
-    GET_UINT32_LE( local.X[ 6], data, 24 );
-    GET_UINT32_LE( local.X[ 7], data, 28 );
-    GET_UINT32_LE( local.X[ 8], data, 32 );
-    GET_UINT32_LE( local.X[ 9], data, 36 );
-    GET_UINT32_LE( local.X[10], data, 40 );
-    GET_UINT32_LE( local.X[11], data, 44 );
-    GET_UINT32_LE( local.X[12], data, 48 );
-    GET_UINT32_LE( local.X[13], data, 52 );
-    GET_UINT32_LE( local.X[14], data, 56 );
-    GET_UINT32_LE( local.X[15], data, 60 );
+    local.X[ 0] = MBEDTLS_GET_UINT32_LE( data,  0 );
+    local.X[ 1] = MBEDTLS_GET_UINT32_LE( data,  4 );
+    local.X[ 2] = MBEDTLS_GET_UINT32_LE( data,  8 );
+    local.X[ 3] = MBEDTLS_GET_UINT32_LE( data, 12 );
+    local.X[ 4] = MBEDTLS_GET_UINT32_LE( data, 16 );
+    local.X[ 5] = MBEDTLS_GET_UINT32_LE( data, 20 );
+    local.X[ 6] = MBEDTLS_GET_UINT32_LE( data, 24 );
+    local.X[ 7] = MBEDTLS_GET_UINT32_LE( data, 28 );
+    local.X[ 8] = MBEDTLS_GET_UINT32_LE( data, 32 );
+    local.X[ 9] = MBEDTLS_GET_UINT32_LE( data, 36 );
+    local.X[10] = MBEDTLS_GET_UINT32_LE( data, 40 );
+    local.X[11] = MBEDTLS_GET_UINT32_LE( data, 44 );
+    local.X[12] = MBEDTLS_GET_UINT32_LE( data, 48 );
+    local.X[13] = MBEDTLS_GET_UINT32_LE( data, 52 );
+    local.X[14] = MBEDTLS_GET_UINT32_LE( data, 56 );
+    local.X[15] = MBEDTLS_GET_UINT32_LE( data, 60 );
 
 #define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
 
@@ -333,8 +310,8 @@
          | ( ctx->total[1] <<  3 );
     low  = ( ctx->total[0] <<  3 );
 
-    PUT_UINT32_LE( low,  msglen, 0 );
-    PUT_UINT32_LE( high, msglen, 4 );
+    MBEDTLS_PUT_UINT32_LE( low,  msglen, 0 );
+    MBEDTLS_PUT_UINT32_LE( high, msglen, 4 );
 
     last = ctx->total[0] & 0x3F;
     padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
@@ -347,10 +324,10 @@
         return( ret );
 
 
-    PUT_UINT32_LE( ctx->state[0], output,  0 );
-    PUT_UINT32_LE( ctx->state[1], output,  4 );
-    PUT_UINT32_LE( ctx->state[2], output,  8 );
-    PUT_UINT32_LE( ctx->state[3], output, 12 );
+    MBEDTLS_PUT_UINT32_LE( ctx->state[0], output,  0 );
+    MBEDTLS_PUT_UINT32_LE( ctx->state[1], output,  4 );
+    MBEDTLS_PUT_UINT32_LE( ctx->state[2], output,  8 );
+    MBEDTLS_PUT_UINT32_LE( ctx->state[3], output, 12 );
 
     return( 0 );
 }
diff --git a/third_party/mbedtls/repo/library/md5.c b/third_party/mbedtls/repo/library/md5.c
index c4f2dbf..4b53fcf 100644
--- a/third_party/mbedtls/repo/library/md5.c
+++ b/third_party/mbedtls/repo/library/md5.c
@@ -43,29 +43,6 @@
 
 #if !defined(MBEDTLS_MD5_ALT)
 
-/*
- * 32-bit integer manipulation macros (little endian)
- */
-#ifndef GET_UINT32_LE
-#define GET_UINT32_LE(n,b,i)                            \
-{                                                       \
-    (n) = ( (uint32_t) (b)[(i)    ]       )             \
-        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \
-        | ( (uint32_t) (b)[(i) + 2] << 16 )             \
-        | ( (uint32_t) (b)[(i) + 3] << 24 );            \
-}
-#endif
-
-#ifndef PUT_UINT32_LE
-#define PUT_UINT32_LE(n,b,i)                                    \
-{                                                               \
-    (b)[(i)    ] = (unsigned char) ( ( (n)       ) & 0xFF );    \
-    (b)[(i) + 1] = (unsigned char) ( ( (n) >>  8 ) & 0xFF );    \
-    (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF );    \
-    (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF );    \
-}
-#endif
-
 void mbedtls_md5_init( mbedtls_md5_context *ctx )
 {
     memset( ctx, 0, sizeof( mbedtls_md5_context ) );
@@ -117,22 +94,22 @@
         uint32_t X[16], A, B, C, D;
     } local;
 
-    GET_UINT32_LE( local.X[ 0], data,  0 );
-    GET_UINT32_LE( local.X[ 1], data,  4 );
-    GET_UINT32_LE( local.X[ 2], data,  8 );
-    GET_UINT32_LE( local.X[ 3], data, 12 );
-    GET_UINT32_LE( local.X[ 4], data, 16 );
-    GET_UINT32_LE( local.X[ 5], data, 20 );
-    GET_UINT32_LE( local.X[ 6], data, 24 );
-    GET_UINT32_LE( local.X[ 7], data, 28 );
-    GET_UINT32_LE( local.X[ 8], data, 32 );
-    GET_UINT32_LE( local.X[ 9], data, 36 );
-    GET_UINT32_LE( local.X[10], data, 40 );
-    GET_UINT32_LE( local.X[11], data, 44 );
-    GET_UINT32_LE( local.X[12], data, 48 );
-    GET_UINT32_LE( local.X[13], data, 52 );
-    GET_UINT32_LE( local.X[14], data, 56 );
-    GET_UINT32_LE( local.X[15], data, 60 );
+    local.X[ 0] = MBEDTLS_GET_UINT32_LE( data,  0 );
+    local.X[ 1] = MBEDTLS_GET_UINT32_LE( data,  4 );
+    local.X[ 2] = MBEDTLS_GET_UINT32_LE( data,  8 );
+    local.X[ 3] = MBEDTLS_GET_UINT32_LE( data, 12 );
+    local.X[ 4] = MBEDTLS_GET_UINT32_LE( data, 16 );
+    local.X[ 5] = MBEDTLS_GET_UINT32_LE( data, 20 );
+    local.X[ 6] = MBEDTLS_GET_UINT32_LE( data, 24 );
+    local.X[ 7] = MBEDTLS_GET_UINT32_LE( data, 28 );
+    local.X[ 8] = MBEDTLS_GET_UINT32_LE( data, 32 );
+    local.X[ 9] = MBEDTLS_GET_UINT32_LE( data, 36 );
+    local.X[10] = MBEDTLS_GET_UINT32_LE( data, 40 );
+    local.X[11] = MBEDTLS_GET_UINT32_LE( data, 44 );
+    local.X[12] = MBEDTLS_GET_UINT32_LE( data, 48 );
+    local.X[13] = MBEDTLS_GET_UINT32_LE( data, 52 );
+    local.X[14] = MBEDTLS_GET_UINT32_LE( data, 56 );
+    local.X[15] = MBEDTLS_GET_UINT32_LE( data, 60 );
 
 #define S(x,n)                                                          \
     ( ( (x) << (n) ) | ( ( (x) & 0xFFFFFFFF) >> ( 32 - (n) ) ) )
@@ -353,8 +330,8 @@
          | ( ctx->total[1] <<  3 );
     low  = ( ctx->total[0] <<  3 );
 
-    PUT_UINT32_LE( low,  ctx->buffer, 56 );
-    PUT_UINT32_LE( high, ctx->buffer, 60 );
+    MBEDTLS_PUT_UINT32_LE( low,  ctx->buffer, 56 );
+    MBEDTLS_PUT_UINT32_LE( high, ctx->buffer, 60 );
 
     if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
         return( ret );
@@ -362,10 +339,10 @@
     /*
      * Output final state
      */
-    PUT_UINT32_LE( ctx->state[0], output,  0 );
-    PUT_UINT32_LE( ctx->state[1], output,  4 );
-    PUT_UINT32_LE( ctx->state[2], output,  8 );
-    PUT_UINT32_LE( ctx->state[3], output, 12 );
+    MBEDTLS_PUT_UINT32_LE( ctx->state[0], output,  0 );
+    MBEDTLS_PUT_UINT32_LE( ctx->state[1], output,  4 );
+    MBEDTLS_PUT_UINT32_LE( ctx->state[2], output,  8 );
+    MBEDTLS_PUT_UINT32_LE( ctx->state[3], output, 12 );
 
     return( 0 );
 }
diff --git a/third_party/mbedtls/repo/library/mps_common.h b/third_party/mbedtls/repo/library/mps_common.h
new file mode 100644
index 0000000..d20776f
--- /dev/null
+++ b/third_party/mbedtls/repo/library/mps_common.h
@@ -0,0 +1,195 @@
+/*
+ *  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)
+ */
+
+/**
+ * \file mps_common.h
+ *
+ * \brief Common functions and macros used by MPS
+ */
+
+#ifndef MBEDTLS_MPS_COMMON_H
+#define MBEDTLS_MPS_COMMON_H
+
+#include "mps_error.h"
+
+#include <stdio.h>
+
+/**
+ * \name SECTION:       MPS Configuration
+ *
+ * \{
+ */
+
+/*! This flag controls whether the MPS-internal components
+ *  (reader, writer, Layer 1-3) perform validation of the
+ *  expected abstract state at the entry of API calls.
+ *
+ *  Context: All MPS API functions impose assumptions/preconditions on the
+ *  context on which they operate. For example, every structure has a notion of
+ *  state integrity which is established by `xxx_init()` and preserved by any
+ *  calls to the MPS API which satisfy their preconditions and either succeed,
+ *  or fail with an error code which is explicitly documented to not corrupt
+ *  structure integrity (such as WANT_READ and WANT_WRITE);
+ *  apart from `xxx_init()` any function assumes state integrity as a
+ *  precondition (but usually more). If any of the preconditions is violated,
+ *  the function's behavior is entirely undefined.
+ *  In addition to state integrity, all MPS structures have a more refined
+ *  notion of abstract state that the API operates on. For example, all layers
+ *  have a notion of 'abtract read state' which indicates if incoming data has
+ *  been passed to the user, e.g. through mps_l2_read_start() for Layer 2
+ *  or mps_l3_read() in Layer 3. After such a call, it doesn't make sense to
+ *  call these reading functions again until the incoming data has been
+ *  explicitly 'consumed', e.g. through mps_l2_read_consume() for Layer 2 or
+ *  mps_l3_read_consume() on Layer 3. However, even if it doesn't make sense,
+ *  it's a design choice whether the API should fail gracefully on such
+ *  non-sensical calls or not, and that's what this option is about:
+ *
+ *  This option determines whether the expected abstract state
+ *  is part of the API preconditions or not: If the option is set,
+ *  then the abstract state is not part of the precondition and is
+ *  thus required to be validated by the implementation. If an unexpected
+ *  abstract state is encountered, the implementation must fail gracefully
+ *  with error #MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED.
+ *  Conversely, if this option is not set, then the expected abstract state
+ *  is included in the preconditions of the respective API calls, and
+ *  an implementation's behaviour is undefined if the abstract state is
+ *  not as expected.
+ *
+ *  For example: Enabling this makes mps_l2_read_done() fail if
+ *  no incoming record is currently open; disabling this would
+ *  lead to undefined behavior in this case.
+ *
+ *  Comment this to remove state validation.
+ */
+#define MBEDTLS_MPS_STATE_VALIDATION
+
+/*! This flag enables/disables assertions on the internal state of MPS.
+ *
+ *  Assertions are sanity checks that should never trigger when MPS
+ *  is used within the bounds of its API and preconditions.
+ *
+ *  Enabling this increases security by limiting the scope of
+ *  potential bugs, but comes at the cost of increased code size.
+ *
+ *  Note: So far, there is no guiding principle as to what
+ *  expected conditions merit an assertion, and which don't.
+ *
+ *  Comment this to disable assertions.
+ */
+#define MBEDTLS_MPS_ENABLE_ASSERTIONS
+
+/*! This flag controls whether tracing for MPS should be enabled. */
+//#define MBEDTLS_MPS_ENABLE_TRACE
+
+#if defined(MBEDTLS_MPS_STATE_VALIDATION)
+
+#define MBEDTLS_MPS_STATE_VALIDATE_RAW( cond, string )                         \
+    do                                                                         \
+    {                                                                          \
+        if( !(cond) )                                                          \
+        {                                                                      \
+            MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_ERROR, string );         \
+            MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED );  \
+        }                                                                      \
+    } while( 0 )
+
+#else /* MBEDTLS_MPS_STATE_VALIDATION */
+
+#define MBEDTLS_MPS_STATE_VALIDATE_RAW( cond, string )           \
+    do                                                           \
+    {                                                            \
+        ( cond );                                                \
+    } while( 0 )
+
+#endif /* MBEDTLS_MPS_STATE_VALIDATION */
+
+#if defined(MBEDTLS_MPS_ENABLE_ASSERTIONS)
+
+#define MBEDTLS_MPS_ASSERT_RAW( cond, string )                          \
+    do                                                                  \
+    {                                                                   \
+        if( !(cond) )                                                   \
+        {                                                               \
+            MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_ERROR, string );  \
+            MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_INTERNAL_ERROR ); \
+        }                                                               \
+    } while( 0 )
+
+#else /* MBEDTLS_MPS_ENABLE_ASSERTIONS */
+
+#define MBEDTLS_MPS_ASSERT_RAW( cond, string ) do {} while( 0 )
+
+#endif /* MBEDTLS_MPS_ENABLE_ASSERTIONS */
+
+
+/* \} name SECTION: MPS Configuration */
+
+/**
+ * \name SECTION:       Common types
+ *
+ * Various common types used throughout MPS.
+ * \{
+ */
+
+/** \brief   The type of buffer sizes and offsets used in MPS structures.
+ *
+ *           This is an unsigned integer type that should be large enough to
+ *           hold the length of any buffer or message processed by MPS.
+ *
+ *           The reason to pick a value as small as possible here is
+ *           to reduce the size of MPS structures.
+ *
+ * \warning  Care has to be taken when using a narrower type
+ *           than ::mbedtls_mps_size_t here because of
+ *           potential truncation during conversion.
+ *
+ * \warning  Handshake messages in TLS may be up to 2^24 ~ 16Mb in size.
+ *           If mbedtls_mps_[opt_]stored_size_t is smaller than that, the
+ *           maximum handshake message is restricted accordingly.
+ *
+ * For now, we use the default type of size_t throughout, and the use of
+ * smaller types or different types for ::mbedtls_mps_size_t and
+ * ::mbedtls_mps_stored_size_t is not yet supported.
+ *
+ */
+typedef size_t mbedtls_mps_stored_size_t;
+#define MBEDTLS_MPS_STORED_SIZE_MAX  ( (mbedtls_mps_stored_size_t) -1 )
+
+/** \brief The type of buffer sizes and offsets used in the MPS API
+ *         and implementation.
+ *
+ *         This must be at least as wide as ::mbedtls_stored_size_t but
+ *         may be chosen to be strictly larger if more suitable for the
+ *         target architecture.
+ *
+ *         For example, in a test build for ARM Thumb, using uint_fast16_t
+ *         instead of uint16_t reduced the code size from 1060 Byte to 962 Byte,
+ *         so almost 10%.
+ */
+typedef size_t mbedtls_mps_size_t;
+#define MBEDTLS_MPS_SIZE_MAX  ( (mbedtls_mps_size_t) -1 )
+
+#if MBEDTLS_MPS_STORED_SIZE_MAX > MBEDTLS_MPS_SIZE_MAX
+#error "Misconfiguration of mbedtls_mps_size_t and mbedtls_mps_stored_size_t."
+#endif
+
+/* \} SECTION: Common types */
+
+
+#endif /* MBEDTLS_MPS_COMMON_H */
diff --git a/third_party/mbedtls/repo/library/mps_error.h b/third_party/mbedtls/repo/library/mps_error.h
new file mode 100644
index 0000000..f78d9a0
--- /dev/null
+++ b/third_party/mbedtls/repo/library/mps_error.h
@@ -0,0 +1,103 @@
+/*
+ *  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)
+ */
+
+/**
+ * \file mps_error.h
+ *
+ * \brief Error codes used by MPS
+ */
+
+#ifndef MBEDTLS_MPS_ERROR_H
+#define MBEDTLS_MPS_ERROR_H
+
+
+/* TODO: The error code allocation needs to be revisited:
+ *
+ * - Should we make (some of) the MPS Reader error codes public?
+ *   If so, we need to adjust MBEDTLS_MPS_READER_MAKE_ERROR() to hit
+ *   a gap in the Mbed TLS public error space.
+ *   If not, we have to make sure we don't forward those errors
+ *   at the level of the public API -- no risk at the moment as
+ *   long as MPS is an experimental component not accessible from
+ *   public API.
+ */
+
+/**
+ * \name SECTION:       MPS general error codes
+ *
+ * \{
+ */
+
+#ifndef MBEDTLS_MPS_ERR_BASE
+#define MBEDTLS_MPS_ERR_BASE ( 0 )
+#endif
+
+#define MBEDTLS_MPS_MAKE_ERROR(code) \
+    ( -( MBEDTLS_MPS_ERR_BASE | (code) ) )
+
+#define MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED  MBEDTLS_MPS_MAKE_ERROR( 0x1 )
+#define MBEDTLS_ERR_MPS_INTERNAL_ERROR        MBEDTLS_MPS_MAKE_ERROR( 0x2 )
+
+/* \} name SECTION: MPS general error codes */
+
+/**
+ * \name SECTION:       MPS Reader error codes
+ *
+ * \{
+ */
+
+#ifndef MBEDTLS_MPS_READER_ERR_BASE
+#define MBEDTLS_MPS_READER_ERR_BASE ( 1 << 8 )
+#endif
+
+#define MBEDTLS_MPS_READER_MAKE_ERROR(code) \
+    ( -( MBEDTLS_MPS_READER_ERR_BASE | (code) ) )
+
+/*! An attempt to reclaim the data buffer from a reader failed because
+ *  the user hasn't yet read and committed all of it. */
+#define MBEDTLS_ERR_MPS_READER_DATA_LEFT             MBEDTLS_MPS_READER_MAKE_ERROR( 0x1 )
+
+/*! An invalid argument was passed to the reader. */
+#define MBEDTLS_ERR_MPS_READER_INVALID_ARG           MBEDTLS_MPS_READER_MAKE_ERROR( 0x2 )
+
+/*! An attempt to move a reader to consuming mode through mbedtls_mps_reader_feed()
+ *  after pausing failed because the provided data is not sufficient to serve the
+ *  read requests that led to the pausing. */
+#define MBEDTLS_ERR_MPS_READER_NEED_MORE             MBEDTLS_MPS_READER_MAKE_ERROR( 0x3 )
+
+/*! A get request failed because not enough data is available in the reader. */
+#define MBEDTLS_ERR_MPS_READER_OUT_OF_DATA           MBEDTLS_MPS_READER_MAKE_ERROR( 0x4 )
+
+/*!< A get request after pausing and reactivating the reader failed because
+ *   the request is not in line with the request made prior to pausing. The user
+ *   must not change it's 'strategy' after pausing and reactivating a reader. */
+#define MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS MBEDTLS_MPS_READER_MAKE_ERROR( 0x5 )
+
+/*! An attempt to reclaim the data buffer from a reader failed because the reader
+ *  has no accumulator it can use to backup the data that hasn't been processed. */
+#define MBEDTLS_ERR_MPS_READER_NEED_ACCUMULATOR      MBEDTLS_MPS_READER_MAKE_ERROR( 0x6 )
+
+/*! An attempt to reclaim the data buffer from a reader failed because the
+ *  accumulator passed to the reader is not large enough to hold both the
+ *  data that hasn't been processed and the excess of the last read-request. */
+#define MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL MBEDTLS_MPS_READER_MAKE_ERROR( 0x7 )
+
+/* \} name SECTION: MPS Reader error codes */
+
+#endif /* MBEDTLS_MPS_ERROR_H */
diff --git a/third_party/mbedtls/repo/library/mps_reader.c b/third_party/mbedtls/repo/library/mps_reader.c
new file mode 100644
index 0000000..9af5073
--- /dev/null
+++ b/third_party/mbedtls/repo/library/mps_reader.c
@@ -0,0 +1,564 @@
+/*
+ *  Message Processing Stack, Reader 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.
+ *
+ *  This file is part of Mbed TLS (https://tls.mbed.org)
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
+
+#include "mps_reader.h"
+#include "mps_common.h"
+#include "mps_trace.h"
+
+#include <string.h>
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#if defined(MBEDTLS_MPS_ENABLE_TRACE)
+static int mbedtls_mps_trace_id = MBEDTLS_MPS_TRACE_BIT_READER;
+#endif /* MBEDTLS_MPS_ENABLE_TRACE */
+
+/*
+ * GENERAL NOTE ON CODING STYLE
+ *
+ * The following code intentionally separates memory loads
+ * and stores from other operations (arithmetic or branches).
+ * This leads to the introduction of many local variables
+ * and significantly increases the C-code line count, but
+ * should not increase the size of generated assembly.
+ *
+ * The reason for this is twofold:
+ * (1) It will ease verification efforts using the VST
+ *     (Verified Software Toolchain)
+ *     whose program logic cannot directly reason
+ *     about instructions containing a load or store in
+ *     addition to other operations (e.g. *p = *q or
+ *     tmp = *p + 42).
+ * (2) Operating on local variables and writing the results
+ *     back to the target contexts on success only
+ *     allows to maintain structure invariants even
+ *     on failure - this in turn has two benefits:
+ *     (2.a) If for some reason an error code is not caught
+ *           and operation continues, functions are nonetheless
+ *           called with sane contexts, reducing the risk
+ *           of dangerous behavior.
+ *     (2.b) Randomized testing is easier if structures
+ *           remain intact even in the face of failing
+ *           and/or non-sensical calls.
+ *     Moreover, it might even reduce code-size because
+ *     the compiler need not write back temporary results
+ *     to memory in case of failure.
+ *
+ */
+
+static inline int mps_reader_is_accumulating(
+    mbedtls_mps_reader const *rd )
+{
+    mbedtls_mps_size_t acc_remaining;
+    if( rd->acc == NULL )
+        return( 0 );
+
+    acc_remaining = rd->acc_share.acc_remaining;
+    return( acc_remaining > 0 );
+}
+
+static inline int mps_reader_is_producing(
+    mbedtls_mps_reader const *rd )
+{
+    unsigned char *frag = rd->frag;
+    return( frag == NULL );
+}
+
+static inline int mps_reader_is_consuming(
+    mbedtls_mps_reader const *rd )
+{
+    return( !mps_reader_is_producing( rd ) );
+}
+
+static inline mbedtls_mps_size_t mps_reader_get_fragment_offset(
+    mbedtls_mps_reader const *rd )
+{
+    unsigned char *acc = rd->acc;
+    mbedtls_mps_size_t frag_offset;
+
+    if( acc == NULL )
+        return( 0 );
+
+    frag_offset = rd->acc_share.frag_offset;
+    return( frag_offset );
+}
+
+static inline mbedtls_mps_size_t mps_reader_serving_from_accumulator(
+    mbedtls_mps_reader const *rd )
+{
+    mbedtls_mps_size_t frag_offset, end;
+
+    frag_offset = mps_reader_get_fragment_offset( rd );
+    end = rd->end;
+
+    return( end < frag_offset );
+}
+
+static inline void mps_reader_zero( mbedtls_mps_reader *rd )
+{
+    /* A plain memset() would likely be more efficient,
+     * but the current way of zeroing makes it harder
+     * to overlook fields which should not be zero-initialized.
+     * It's also more suitable for FV efforts since it
+     * doesn't require reasoning about structs being
+     * interpreted as unstructured binary blobs. */
+    static mbedtls_mps_reader const zero =
+        { .frag          = NULL,
+          .frag_len      = 0,
+          .commit        = 0,
+          .end           = 0,
+          .pending       = 0,
+          .acc           = NULL,
+          .acc_len       = 0,
+          .acc_available = 0,
+          .acc_share     = { .acc_remaining = 0 }
+        };
+    *rd = zero;
+}
+
+int mbedtls_mps_reader_init( mbedtls_mps_reader *rd,
+                             unsigned char *acc,
+                             mbedtls_mps_size_t acc_len )
+{
+    MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_init" );
+    MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+                       "* Accumulator size: %u bytes", (unsigned) acc_len );
+    mps_reader_zero( rd );
+    rd->acc = acc;
+    rd->acc_len = acc_len;
+    MBEDTLS_MPS_TRACE_RETURN( 0 );
+}
+
+int mbedtls_mps_reader_free( mbedtls_mps_reader *rd )
+{
+    MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_free" );
+    mps_reader_zero( rd );
+    MBEDTLS_MPS_TRACE_RETURN( 0 );
+}
+
+int mbedtls_mps_reader_feed( mbedtls_mps_reader *rd,
+                             unsigned char *new_frag,
+                             mbedtls_mps_size_t new_frag_len )
+{
+    mbedtls_mps_size_t copy_to_acc;
+    MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_feed" );
+    MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+                       "* Fragment length: %u bytes", (unsigned) new_frag_len );
+
+    if( new_frag == NULL )
+        MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_READER_INVALID_ARG );
+
+    MBEDTLS_MPS_STATE_VALIDATE_RAW( mps_reader_is_producing( rd ),
+        "mbedtls_mps_reader_feed() requires reader to be in producing mode" );
+
+    if( mps_reader_is_accumulating( rd ) )
+    {
+        unsigned char *acc    = rd->acc;
+        mbedtls_mps_size_t acc_remaining = rd->acc_share.acc_remaining;
+        mbedtls_mps_size_t acc_available = rd->acc_available;
+
+        /* Skip over parts of the accumulator that have already been filled. */
+        acc += acc_available;
+
+        copy_to_acc = acc_remaining;
+        if( copy_to_acc > new_frag_len )
+            copy_to_acc = new_frag_len;
+
+        /* Copy new contents to accumulator. */
+        memcpy( acc, new_frag, copy_to_acc );
+
+        MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+                "Copy new data of size %u of %u into accumulator at offset %u",
+                (unsigned) copy_to_acc, (unsigned) new_frag_len, (unsigned) acc_available );
+
+        /* Check if, with the new fragment, we have enough data. */
+        acc_remaining -= copy_to_acc;
+        if( acc_remaining > 0 )
+        {
+            /* We need to accumulate more data. Stay in producing mode. */
+            acc_available += copy_to_acc;
+            rd->acc_share.acc_remaining = acc_remaining;
+            rd->acc_available = acc_available;
+            MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_READER_NEED_MORE );
+        }
+
+        /* We have filled the accumulator: Move to consuming mode. */
+
+        MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+                           "Enough data available to serve user request" );
+
+        /* Remember overlap of accumulator and fragment. */
+        rd->acc_share.frag_offset = acc_available;
+        acc_available += copy_to_acc;
+        rd->acc_available = acc_available;
+    }
+    else /* Not accumulating */
+    {
+        rd->acc_share.frag_offset = 0;
+    }
+
+    rd->frag = new_frag;
+    rd->frag_len = new_frag_len;
+    rd->commit = 0;
+    rd->end = 0;
+    MBEDTLS_MPS_TRACE_RETURN( 0 );
+}
+
+
+int mbedtls_mps_reader_get( mbedtls_mps_reader *rd,
+                            mbedtls_mps_size_t desired,
+                            unsigned char **buffer,
+                            mbedtls_mps_size_t *buflen )
+{
+    unsigned char *frag;
+    mbedtls_mps_size_t frag_len, frag_offset, end, frag_fetched, frag_remaining;
+    MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_get" );
+    MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+                       "* Bytes requested: %u", (unsigned) desired );
+
+    MBEDTLS_MPS_STATE_VALIDATE_RAW( mps_reader_is_consuming( rd ),
+          "mbedtls_mps_reader_get() requires reader to be in consuming mode" );
+
+    end = rd->end;
+    frag_offset = mps_reader_get_fragment_offset( rd );
+
+    /* Check if we're still serving from the accumulator. */
+    if( mps_reader_serving_from_accumulator( rd ) )
+    {
+        /* Illustration of supported and unsupported cases:
+         *
+         * - Allowed #1
+         *
+         *                          +-----------------------------------+
+         *                          |               frag                |
+         *                          +-----------------------------------+
+         *
+         *             end end+desired
+         *              |       |
+         *        +-----v-------v-------------+
+         *        |          acc              |
+         *        +---------------------------+
+         *                          |         |
+         *                     frag_offset  acc_available
+         *
+         * - Allowed #2
+         *
+         *                          +-----------------------------------+
+         *                          |               frag                |
+         *                          +-----------------------------------+
+         *
+         *                  end          end+desired
+         *                   |                |
+         *        +----------v----------------v
+         *        |          acc              |
+         *        +---------------------------+
+         *                          |         |
+         *                   frag_offset acc_available
+         *
+         * - Not allowed #1 (could be served, but we don't actually use it):
+         *
+         *                      +-----------------------------------+
+         *                      |               frag                |
+         *                      +-----------------------------------+
+         *
+         *              end        end+desired
+         *               |             |
+         *        +------v-------------v------+
+         *        |          acc              |
+         *        +---------------------------+
+         *                      |             |
+         *                frag_offset   acc_available
+         *
+         *
+         * - Not allowed #2 (can't be served with a contiguous buffer):
+         *
+         *                      +-----------------------------------+
+         *                      |               frag                |
+         *                      +-----------------------------------+
+         *
+         *              end                 end + desired
+         *               |                        |
+         *        +------v--------------------+   v
+         *        |            acc            |
+         *        +---------------------------+
+         *                      |             |
+         *                frag_offset   acc_available
+         *
+         * In case of Allowed #2 we're switching to serve from
+         * `frag` starting from the next call to mbedtls_mps_reader_get().
+         */
+
+        unsigned char *acc;
+
+        MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+                           "Serve the request from the accumulator" );
+        if( frag_offset - end < desired )
+        {
+            mbedtls_mps_size_t acc_available;
+            acc_available = rd->acc_available;
+            if( acc_available - end != desired )
+            {
+                /* It might be possible to serve some of these situations by
+                 * making additional space in the accumulator, removing those
+                 * parts that have already been committed.
+                 * On the other hand, this brings additional complexity and
+                 * enlarges the code size, while there doesn't seem to be a use
+                 * case where we don't attempt exactly the same `get` calls when
+                 * resuming on a reader than what we tried before pausing it.
+                 * If we believe we adhere to this restricted usage throughout
+                 * the library, this check is a good opportunity to
+                 * validate this. */
+                MBEDTLS_MPS_TRACE_RETURN(
+                    MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS );
+            }
+        }
+
+        acc = rd->acc;
+        acc += end;
+
+        *buffer = acc;
+        if( buflen != NULL )
+            *buflen = desired;
+
+        end += desired;
+        rd->end = end;
+        rd->pending = 0;
+
+        MBEDTLS_MPS_TRACE_RETURN( 0 );
+    }
+
+    /* Attempt to serve the request from the current fragment */
+    MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+                       "Serve the request from the current fragment." );
+
+    frag_len = rd->frag_len;
+    frag_fetched = end - frag_offset; /* The amount of data from the current
+                                       * fragment that has already been passed
+                                       * to the user. */
+    frag_remaining = frag_len - frag_fetched; /* Remaining data in fragment */
+
+    /* Check if we can serve the read request from the fragment. */
+    if( frag_remaining < desired )
+    {
+        MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+                           "There's not enough data in the current fragment "
+                           "to serve the request." );
+        /* There's not enough data in the current fragment,
+         * so either just RETURN what we have or fail. */
+        if( buflen == NULL )
+        {
+            if( frag_remaining > 0 )
+            {
+                rd->pending = desired - frag_remaining;
+                MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+                       "Remember to collect %u bytes before re-opening",
+                       (unsigned) rd->pending );
+            }
+            MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_READER_OUT_OF_DATA );
+        }
+
+        desired = frag_remaining;
+    }
+
+    /* There's enough data in the current fragment to serve the
+     * (potentially modified) read request. */
+
+    frag = rd->frag;
+    frag += frag_fetched;
+
+    *buffer = frag;
+    if( buflen != NULL )
+        *buflen = desired;
+
+    end += desired;
+    rd->end = end;
+    rd->pending = 0;
+    MBEDTLS_MPS_TRACE_RETURN( 0 );
+}
+
+int mbedtls_mps_reader_commit( mbedtls_mps_reader *rd )
+{
+    mbedtls_mps_size_t end;
+    MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_commit" );
+    MBEDTLS_MPS_STATE_VALIDATE_RAW( mps_reader_is_consuming( rd ),
+       "mbedtls_mps_reader_commit() requires reader to be in consuming mode" );
+
+    end = rd->end;
+    rd->commit = end;
+
+    MBEDTLS_MPS_TRACE_RETURN( 0 );
+}
+
+int mbedtls_mps_reader_reclaim( mbedtls_mps_reader *rd,
+                                int *paused )
+{
+    unsigned char *frag, *acc;
+    mbedtls_mps_size_t pending, commit;
+    mbedtls_mps_size_t acc_len, frag_offset, frag_len;
+    MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_reclaim" );
+
+    if( paused != NULL )
+        *paused = 0;
+
+    MBEDTLS_MPS_STATE_VALIDATE_RAW( mps_reader_is_consuming( rd ),
+       "mbedtls_mps_reader_reclaim() requires reader to be in consuming mode" );
+
+    frag     = rd->frag;
+    acc      = rd->acc;
+    pending  = rd->pending;
+    commit   = rd->commit;
+    frag_len = rd->frag_len;
+
+    frag_offset = mps_reader_get_fragment_offset( rd );
+
+    if( pending == 0 )
+    {
+        MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+                           "No unsatisfied read-request has been logged." );
+
+        /* Check if there's data left to be consumed. */
+        if( commit < frag_offset || commit - frag_offset < frag_len )
+        {
+            MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+                               "There is data left to be consumed." );
+            rd->end = commit;
+            MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_READER_DATA_LEFT );
+        }
+
+        rd->acc_available = 0;
+        rd->acc_share.acc_remaining = 0;
+
+        MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+                           "Fragment has been fully processed and committed." );
+    }
+    else
+    {
+        int overflow;
+
+        mbedtls_mps_size_t acc_backup_offset;
+        mbedtls_mps_size_t acc_backup_len;
+        mbedtls_mps_size_t frag_backup_offset;
+        mbedtls_mps_size_t frag_backup_len;
+
+        mbedtls_mps_size_t backup_len;
+        mbedtls_mps_size_t acc_len_needed;
+
+        MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+               "There has been an unsatisfied read with %u bytes overhead.",
+               (unsigned) pending );
+
+        if( acc == NULL )
+        {
+            MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+                               "No accumulator present" );
+            MBEDTLS_MPS_TRACE_RETURN(
+                MBEDTLS_ERR_MPS_READER_NEED_ACCUMULATOR );
+        }
+        acc_len = rd->acc_len;
+
+        /* Check if the upper layer has already fetched
+         * and committed the contents of the accumulator. */
+        if( commit < frag_offset )
+        {
+            /* No, accumulator is still being processed. */
+            frag_backup_offset = 0;
+            frag_backup_len = frag_len;
+            acc_backup_offset = commit;
+            acc_backup_len = frag_offset - commit;
+        }
+        else
+        {
+            /* Yes, the accumulator is already processed. */
+            frag_backup_offset = commit - frag_offset;
+            frag_backup_len = frag_len - frag_backup_offset;
+            acc_backup_offset = 0;
+            acc_backup_len = 0;
+        }
+
+        backup_len = acc_backup_len + frag_backup_len;
+        acc_len_needed = backup_len + pending;
+
+        overflow  = 0;
+        overflow |= ( backup_len     < acc_backup_len );
+        overflow |= ( acc_len_needed < backup_len );
+
+        if( overflow || acc_len < acc_len_needed )
+        {
+            /* Except for the different return code, we behave as if
+             * there hadn't been a call to mbedtls_mps_reader_get()
+             * since the last commit. */
+            rd->end = commit;
+            rd->pending = 0;
+            MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_ERROR,
+                               "The accumulator is too small to handle the backup." );
+            MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_ERROR,
+                               "* Size: %u", (unsigned) acc_len );
+            MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_ERROR,
+                               "* Needed: %u (%u + %u)",
+                               (unsigned) acc_len_needed,
+                               (unsigned) backup_len, (unsigned) pending );
+            MBEDTLS_MPS_TRACE_RETURN(
+                MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL );
+        }
+
+        MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+                         "Fragment backup: %u", (unsigned) frag_backup_len );
+        MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+                         "Accumulator backup: %u", (unsigned) acc_backup_len );
+
+        /* Move uncommitted parts from the accumulator to the front
+         * of the accumulator. */
+        memmove( acc, acc + acc_backup_offset, acc_backup_len );
+
+        /* Copy uncmmitted parts of the current fragment to the
+         * accumulator. */
+        memcpy( acc + acc_backup_len,
+                frag + frag_backup_offset, frag_backup_len );
+
+        rd->acc_available = backup_len;
+        rd->acc_share.acc_remaining = pending;
+
+        if( paused != NULL )
+            *paused = 1;
+    }
+
+    rd->frag     = NULL;
+    rd->frag_len = 0;
+
+    rd->commit  = 0;
+    rd->end     = 0;
+    rd->pending = 0;
+
+    MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+                       "Final state: aa %u, al %u, ar %u",
+                       (unsigned) rd->acc_available, (unsigned) rd->acc_len,
+                       (unsigned) rd->acc_share.acc_remaining );
+    MBEDTLS_MPS_TRACE_RETURN( 0 );
+}
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
diff --git a/third_party/mbedtls/repo/library/mps_reader.h b/third_party/mbedtls/repo/library/mps_reader.h
new file mode 100644
index 0000000..427c1bd
--- /dev/null
+++ b/third_party/mbedtls/repo/library/mps_reader.h
@@ -0,0 +1,382 @@
+/*
+ *  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)
+ */
+
+/**
+ * \file mps_reader.h
+ *
+ * \brief This file defines reader objects, which together with their
+ *        sibling writer objects form the basis for the communication
+ *        between the various layers of the Mbed TLS messaging stack,
+ *        as well as the communication between the messaging stack and
+ *        the (D)TLS handshake protocol implementation.
+ *
+ * Readers provide a means of transferring incoming data from
+ * a 'producer' providing it in chunks of arbitrary size, to
+ * a 'consumer' which fetches and processes it in chunks of
+ * again arbitrary, and potentially different, size.
+ *
+ * Readers can thus be seen as datagram-to-stream converters,
+ * and they abstract away the following two tasks from the user:
+ * 1. The pointer arithmetic of stepping through a producer-
+ *    provided chunk in smaller chunks.
+ * 2. The merging of incoming data chunks in case the
+ *    consumer requests data in larger chunks than what the
+ *    producer provides.
+ *
+ * The basic abstract flow of operation is the following:
+ * - Initially, the reader is in 'producing mode'.
+ * - The producer hands an incoming data buffer to the reader,
+ *   moving it from 'producing' to 'consuming' mode.
+ * - The consumer subsequently fetches and processes the buffer
+ *   content. Once that's done -- or partially done and a consumer's
+ *   request can't be fulfilled -- the producer revokes the reader's
+ *   access to the incoming data buffer, putting the reader back to
+ *   producing mode.
+ * - The producer subsequently gathers more incoming data and hands
+ *   it to the reader until it switches back to consuming mode
+ *   if enough data is available for the last consumer request to
+ *   be satisfiable.
+ * - Repeat the above.
+ *
+ * The abstract states of the reader from the producer's and
+ * consumer's perspective are as follows:
+ *
+ * - From the perspective of the consumer, the state of the
+ *   reader consists of the following:
+ *   - A byte stream representing (concatenation of) the data
+ *     received through calls to mbedtls_mps_reader_get(),
+ *   - A marker within that byte stream indicating which data
+ *     can be considered processed, and hence need not be retained,
+ *     when the reader is passed back to the producer via
+ *     mbedtls_mps_reader_reclaim().
+ *     The marker is set via mbedtls_mps_reader_commit()
+ *     which places it at the end of the current byte stream.
+ *   The consumer need not be aware of the distinction between consumer
+ *   and producer mode, because it only interfaces with the reader
+ *   when the latter is in consuming mode.
+ *
+ * - From the perspective of the producer, the reader's state is one of:
+ *   - Attached: The reader is in consuming mode.
+ *   - Unset: No incoming data buffer is currently managed by the reader,
+ *            and all previously handed incoming data buffers have been
+ *            fully processed. More data needs to be fed into the reader
+ *            via mbedtls_mps_reader_feed().
+ *
+ *   - Accumulating: No incoming data buffer is currently managed by the
+ *                   reader, but some data from the previous incoming data
+ *                   buffer hasn't been processed yet and is internally
+ *                   held back.
+ *   The Attached state belongs to consuming mode, while the Unset and
+ *   Accumulating states belong to producing mode.
+ *
+ * Transitioning from the Unset or Accumulating state to Attached is
+ * done via successful calls to mbedtls_mps_reader_feed(), while
+ * transitioning from Attached to either Unset or Accumulating (depending
+ * on what has been processed) is done via mbedtls_mps_reader_reclaim().
+ *
+ * The following diagram depicts the producer-state progression:
+ *
+ *        +------------------+             reclaim
+ *        |      Unset       +<-------------------------------------+       get
+ *        +--------|---------+                                      |   +------+
+ *                 |                                                |   |      |
+ *                 |                                                |   |      |
+ *                 |                feed                  +---------+---+--+   |
+ *                 +-------------------------------------->                <---+
+ *                                                        |    Attached    |
+ *                 +-------------------------------------->                <---+
+ *                 |     feed, enough data available      +---------+---+--+   |
+ *                 |     to serve previous consumer request         |   |      |
+ *                 |                                                |   |      |
+ *        +--------+---------+                                      |   +------+
+ *   +---->   Accumulating   |<-------------------------------------+    commit
+ *   |    +---+--------------+      reclaim, previous read request
+ *   |        |                        couldn't be fulfilled
+ *   |        |
+ *   +--------+
+ *     feed, need more data to serve
+ *     previous consumer request
+ *                                         |
+ *                                         |
+ *               producing mode            |           consuming mode
+ *                                         |
+ *
+ */
+
+#ifndef MBEDTLS_READER_H
+#define MBEDTLS_READER_H
+
+#include <stdio.h>
+
+#include "mps_common.h"
+#include "mps_error.h"
+
+struct mbedtls_mps_reader;
+typedef struct mbedtls_mps_reader mbedtls_mps_reader;
+
+/*
+ * Structure definitions
+ */
+
+struct mbedtls_mps_reader
+{
+    unsigned char *frag;  /*!< The fragment of incoming data managed by
+                           *   the reader; it is provided to the reader
+                           *   through mbedtls_mps_reader_feed(). The reader
+                           *   does not own the fragment and does not
+                           *   perform any allocation operations on it,
+                           *   but does have read and write access to it.
+                           *
+                           *   The reader is in consuming mode if
+                           *   and only if \c frag is not \c NULL.          */
+    mbedtls_mps_stored_size_t frag_len;
+                          /*!< The length of the current fragment.
+                           *   Must be 0 if \c frag == \c NULL.             */
+    mbedtls_mps_stored_size_t commit;
+                          /*!< The offset of the last commit, relative
+                           *   to the first byte in the fragment, if
+                           *   no accumulator is present. If an accumulator
+                           *   is present, it is viewed as a prefix to the
+                           *   current fragment, and this variable contains
+                           *   an offset from the beginning of the accumulator.
+                           *
+                           *   This is only used when the reader is in
+                           *   consuming mode, i.e. \c frag != \c NULL;
+                           *   otherwise, its value is \c 0.                */
+    mbedtls_mps_stored_size_t end;
+                          /*!< The offset of the end of the last chunk
+                           *   passed to the user through a call to
+                           *   mbedtls_mps_reader_get(), relative to the first
+                           *   byte in the fragment, if no accumulator is
+                           *   present. If an accumulator is present, it is
+                           *   viewed as a prefix to the current fragment, and
+                           *   this variable contains an offset from the
+                           *   beginning of the accumulator.
+                           *
+                           *   This is only used when the reader is in
+                           *   consuming mode, i.e. \c frag != \c NULL;
+                           *   otherwise, its value is \c 0.                */
+    mbedtls_mps_stored_size_t pending;
+                          /*!< The amount of incoming data missing on the
+                           *   last call to mbedtls_mps_reader_get().
+                           *   In particular, it is \c 0 if the last call
+                           *   was successful.
+                           *   If a reader is reclaimed after an
+                           *   unsuccessful call to mbedtls_mps_reader_get(),
+                           *   this variable is used to have the reader
+                           *   remember how much data should be accumulated
+                           *   so that the call to mbedtls_mps_reader_get()
+                           *   succeeds next time.
+                           *   This is only used when the reader is in
+                           *   consuming mode, i.e. \c frag != \c NULL;
+                           *   otherwise, its value is \c 0.                */
+
+    /* The accumulator is only needed if we need to be able to pause
+     * the reader. A few bytes could be saved by moving this to a
+     * separate struct and using a pointer here. */
+
+    unsigned char *acc;   /*!< The accumulator is used to gather incoming
+                           *   data if a read-request via mbedtls_mps_reader_get()
+                           *   cannot be served from the current fragment.   */
+    mbedtls_mps_stored_size_t acc_len;
+                           /*!< The total size of the accumulator.           */
+    mbedtls_mps_stored_size_t acc_available;
+                          /*!< The number of bytes currently gathered in
+                           *   the accumulator. This is both used in
+                           *   producing and in consuming mode:
+                           *   While producing, it is increased until
+                           *   it reaches the value of \c acc_remaining below.
+                           *   While consuming, it is used to judge if a
+                           *   get request can be served from the
+                           *   accumulator or not.
+                           *   Must not be larger than \c acc_len.           */
+    union
+    {
+        mbedtls_mps_stored_size_t acc_remaining;
+                              /*!< This indicates the amount of data still
+                               *   to be gathered in the accumulator. It is
+                               *   only used in producing mode.
+                               *   Must be at most acc_len - acc_available.  */
+        mbedtls_mps_stored_size_t frag_offset;
+                              /*!< If an accumulator is present and in use, this
+                               *   field indicates the offset of the current
+                               *   fragment from the beginning of the
+                               *   accumulator. If no accumulator is present
+                               *   or the accumulator is not in use, this is \c 0.
+                               *   It is only used in consuming mode.
+                               *   Must not be larger than \c acc_available. */
+    } acc_share;
+};
+
+/*
+ * API organization:
+ * A reader object is usually prepared and maintained
+ * by some lower layer and passed for usage to an upper
+ * layer, and the API naturally splits according to which
+ * layer is supposed to use the respective functions.
+ */
+
+/*
+ * Maintenance API (Lower layer)
+ */
+
+/**
+ * \brief           Initialize a reader object
+ *
+ * \param reader    The reader to be initialized.
+ * \param acc       The buffer to be used as a temporary accumulator
+ *                  in case get requests through mbedtls_mps_reader_get()
+ *                  exceed the buffer provided by mbedtls_mps_reader_feed().
+ *                  This buffer is owned by the caller and exclusive use
+ *                  for reading and writing is given to the reader for the
+ *                  duration of the reader's lifetime. It is thus the caller's
+ *                  responsibility to maintain (and not touch) the buffer for
+ *                  the lifetime of the reader, and to properly zeroize and
+ *                  free the memory after the reader has been destroyed.
+ * \param acc_len   The size in Bytes of \p acc.
+ *
+ * \return          \c 0 on success.
+ * \return          A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
+ */
+int mbedtls_mps_reader_init( mbedtls_mps_reader *reader,
+                             unsigned char *acc,
+                             mbedtls_mps_size_t acc_len );
+
+/**
+ * \brief           Free a reader object
+ *
+ * \param reader    The reader to be freed.
+ *
+ * \return          \c 0 on success.
+ * \return          A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
+ */
+int mbedtls_mps_reader_free( mbedtls_mps_reader *reader );
+
+/**
+ * \brief           Pass chunk of data for the reader to manage.
+ *
+ * \param reader    The reader context to use. The reader must be
+ *                  in producing mode.
+ * \param buf       The buffer to be managed by the reader.
+ * \param buflen    The size in Bytes of \p buffer.
+ *
+ * \return          \c 0 on success. In this case, the reader will be
+ *                  moved to consuming mode and obtains read access
+ *                  of \p buf until mbedtls_mps_reader_reclaim()
+ *                  is called. It is the responsibility of the caller
+ *                  to ensure that the \p buf persists and is not changed
+ *                  between successful calls to mbedtls_mps_reader_feed()
+ *                  and mbedtls_mps_reader_reclaim().
+ * \return          \c MBEDTLS_ERR_MPS_READER_NEED_MORE if more input data is
+ *                  required to fulfill a previous request to mbedtls_mps_reader_get().
+ *                  In this case, the reader remains in producing mode and
+ *                  takes no ownership of the provided buffer (an internal copy
+ *                  is made instead).
+ * \return          Another negative \c MBEDTLS_ERR_READER_XXX error code on
+ *                  different kinds of failures.
+ */
+int mbedtls_mps_reader_feed( mbedtls_mps_reader *reader,
+                             unsigned char *buf,
+                             mbedtls_mps_size_t buflen );
+
+/**
+ * \brief           Reclaim reader's access to the current input buffer.
+ *
+ * \param reader    The reader context to use. The reader must be
+ *                  in consuming mode.
+ * \param paused    If not \c NULL, the integer at address \p paused will be
+ *                  modified to indicate whether the reader has been paused
+ *                  (value \c 1) or not (value \c 0). Pausing happens if there
+ *                  is uncommitted data and a previous request to
+ *                  mbedtls_mps_reader_get() has exceeded the bounds of the
+ *                  input buffer.
+ *
+ * \return          \c 0 on success.
+ * \return          A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
+ */
+int mbedtls_mps_reader_reclaim( mbedtls_mps_reader *reader,
+                                int *paused );
+
+/*
+ * Usage API (Upper layer)
+ */
+
+/**
+ * \brief           Request data from the reader.
+ *
+ * \param reader    The reader context to use. The reader must
+ *                  be in consuming mode.
+ * \param desired   The desired amount of data to be read, in Bytes.
+ * \param buffer    The address to store the buffer pointer in.
+ *                  This must not be \c NULL.
+ * \param buflen    The address to store the actual buffer
+ *                  length in, or \c NULL.
+ *
+ * \return          \c 0 on success. In this case, \c *buf holds the
+ *                  address of a buffer of size \c *buflen
+ *                  (if \c buflen != \c NULL) or \c desired
+ *                  (if \c buflen == \c NULL). The user has read access
+ *                  to the buffer and guarantee of stability of the data
+ *                  until the next call to mbedtls_mps_reader_reclaim().
+ * \return          #MBEDTLS_ERR_MPS_READER_OUT_OF_DATA if there is not enough
+ *                  data available to serve the get request. In this case, the
+ *                  reader remains intact and in consuming mode, and the consumer
+ *                  should retry the call after a successful cycle of
+ *                  mbedtls_mps_reader_reclaim() and mbedtls_mps_reader_feed().
+ *                  If, after such a cycle, the consumer requests a different
+ *                  amount of data, the result is implementation-defined;
+ *                  progress is guaranteed only if the same amount of data
+ *                  is requested after a mbedtls_mps_reader_reclaim() and
+ *                  mbedtls_mps_reader_feed() cycle.
+ * \return          Another negative \c MBEDTLS_ERR_READER_XXX error
+ *                  code for different kinds of failure.
+ *
+ * \note            Passing \c NULL as \p buflen is a convenient way to
+ *                  indicate that fragmentation is not tolerated.
+ *                  It's functionally equivalent to passing a valid
+ *                  address as buflen and checking \c *buflen == \c desired
+ *                  afterwards.
+ */
+int mbedtls_mps_reader_get( mbedtls_mps_reader *reader,
+                            mbedtls_mps_size_t desired,
+                            unsigned char **buffer,
+                            mbedtls_mps_size_t *buflen );
+
+/**
+ * \brief         Mark data obtained from mbedtls_mps_reader_get() as processed.
+ *
+ *                This call indicates that all data received from prior calls to
+ *                mbedtls_mps_reader_get() has been or will have been
+ *                processed when mbedtls_mps_reader_reclaim() is called,
+ *                and thus need not be backed up.
+ *
+ *                This function has no user observable effect until
+ *                mbedtls_mps_reader_reclaim() is called. In particular,
+ *                buffers received from mbedtls_mps_reader_get() remain
+ *                valid until mbedtls_mps_reader_reclaim() is called.
+ *
+ * \param reader  The reader context to use.
+ *
+ * \return        \c 0 on success.
+ * \return        A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
+ *
+ */
+int mbedtls_mps_reader_commit( mbedtls_mps_reader *reader );
+
+#endif /* MBEDTLS_READER_H */
diff --git a/third_party/mbedtls/repo/library/mps_trace.c b/third_party/mbedtls/repo/library/mps_trace.c
new file mode 100644
index 0000000..6026a07
--- /dev/null
+++ b/third_party/mbedtls/repo/library/mps_trace.c
@@ -0,0 +1,127 @@
+/*
+ *  Message Processing Stack, Trace 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.
+ *
+ *  This file is part of Mbed TLS (https://tls.mbed.org)
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
+
+#include "mps_common.h"
+
+#if defined(MBEDTLS_MPS_ENABLE_TRACE)
+
+#include "mps_trace.h"
+#include <stdarg.h>
+
+static int trace_depth = 0;
+
+#define color_default  "\x1B[0m"
+#define color_red      "\x1B[1;31m"
+#define color_green    "\x1B[1;32m"
+#define color_yellow   "\x1B[1;33m"
+#define color_blue     "\x1B[1;34m"
+#define color_magenta  "\x1B[1;35m"
+#define color_cyan     "\x1B[1;36m"
+#define color_white    "\x1B[1;37m"
+
+static char const * colors[] =
+{
+    color_default,
+    color_green,
+    color_yellow,
+    color_magenta,
+    color_cyan,
+    color_blue,
+    color_white
+};
+
+#define MPS_TRACE_BUF_SIZE 100
+
+void mbedtls_mps_trace_print_msg( int id, int line, const char *format, ... )
+{
+    int ret;
+    char str[MPS_TRACE_BUF_SIZE];
+    va_list argp;
+    va_start( argp, format );
+    ret = mbedtls_vsnprintf( str, MPS_TRACE_BUF_SIZE, format, argp );
+    va_end( argp );
+
+    if( ret >= 0 && ret < MPS_TRACE_BUF_SIZE )
+    {
+        str[ret] = '\0';
+        mbedtls_printf( "[%d|L%d]: %s\n", id, line, str );
+    }
+}
+
+int mbedtls_mps_trace_get_depth()
+{
+    return trace_depth;
+}
+void mbedtls_mps_trace_dec_depth()
+{
+    trace_depth--;
+}
+void mbedtls_mps_trace_inc_depth()
+{
+    trace_depth++;
+}
+
+void mbedtls_mps_trace_color( int id )
+{
+    if( id > (int) ( sizeof( colors ) / sizeof( *colors ) ) )
+        return;
+    printf( "%s", colors[ id ] );
+}
+
+void mbedtls_mps_trace_indent( int level, mbedtls_mps_trace_type ty )
+{
+    if( level > 0 )
+    {
+        while( --level )
+            printf( "|  " );
+
+        printf( "|  " );
+    }
+
+    switch( ty )
+    {
+        case MBEDTLS_MPS_TRACE_TYPE_COMMENT:
+            mbedtls_printf( "@ " );
+            break;
+
+        case MBEDTLS_MPS_TRACE_TYPE_CALL:
+            mbedtls_printf( "+--> " );
+            break;
+
+        case MBEDTLS_MPS_TRACE_TYPE_ERROR:
+            mbedtls_printf( "E " );
+            break;
+
+        case MBEDTLS_MPS_TRACE_TYPE_RETURN:
+            mbedtls_printf( "< " );
+            break;
+
+        default:
+            break;
+    }
+}
+
+#endif /* MBEDTLS_MPS_ENABLE_TRACE */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
diff --git a/third_party/mbedtls/repo/library/mps_trace.h b/third_party/mbedtls/repo/library/mps_trace.h
new file mode 100644
index 0000000..7c23601
--- /dev/null
+++ b/third_party/mbedtls/repo/library/mps_trace.h
@@ -0,0 +1,175 @@
+/*
+ *  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)
+ */
+
+/**
+ * \file mps_trace.h
+ *
+ * \brief Tracing module for MPS
+ */
+
+#ifndef MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H
+#define MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H
+
+#include "common.h"
+#include "mps_common.h"
+#include "mps_trace.h"
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#define mbedtls_printf    printf
+#define mbedtls_vsnprintf vsnprintf
+#endif /* MBEDTLS_PLATFORM_C */
+
+#if defined(MBEDTLS_MPS_ENABLE_TRACE)
+
+/*
+ * Adapt this to enable/disable tracing output
+ * from the various layers of the MPS.
+ */
+
+#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_1
+#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_2
+#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_3
+#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_4
+#define MBEDTLS_MPS_TRACE_ENABLE_READER
+#define MBEDTLS_MPS_TRACE_ENABLE_WRITER
+
+/*
+ * To use the existing trace module, only change
+ * MBEDTLS_MPS_TRACE_ENABLE_XXX above, but don't modify the
+ * rest of this file.
+ */
+
+typedef enum
+{
+    MBEDTLS_MPS_TRACE_TYPE_COMMENT,
+    MBEDTLS_MPS_TRACE_TYPE_CALL,
+    MBEDTLS_MPS_TRACE_TYPE_ERROR,
+    MBEDTLS_MPS_TRACE_TYPE_RETURN
+} mbedtls_mps_trace_type;
+
+#define MBEDTLS_MPS_TRACE_BIT_LAYER_1 1
+#define MBEDTLS_MPS_TRACE_BIT_LAYER_2 2
+#define MBEDTLS_MPS_TRACE_BIT_LAYER_3 3
+#define MBEDTLS_MPS_TRACE_BIT_LAYER_4 4
+#define MBEDTLS_MPS_TRACE_BIT_WRITER  5
+#define MBEDTLS_MPS_TRACE_BIT_READER  6
+
+#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_1)
+#define MBEDTLS_MPS_TRACE_MASK_LAYER_1 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_1 )
+#else
+#define MBEDTLS_MPS_TRACE_MASK_LAYER_1 0
+#endif
+
+#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_2)
+#define MBEDTLS_MPS_TRACE_MASK_LAYER_2 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_2 )
+#else
+#define MBEDTLS_MPS_TRACE_MASK_LAYER_2 0
+#endif
+
+#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_3)
+#define MBEDTLS_MPS_TRACE_MASK_LAYER_3 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_3 )
+#else
+#define MBEDTLS_MPS_TRACE_MASK_LAYER_3 0
+#endif
+
+#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_4)
+#define MBEDTLS_MPS_TRACE_MASK_LAYER_4 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_4 )
+#else
+#define MBEDTLS_MPS_TRACE_MASK_LAYER_4 0
+#endif
+
+#if defined(MBEDTLS_MPS_TRACE_ENABLE_READER)
+#define MBEDTLS_MPS_TRACE_MASK_READER (1u << MBEDTLS_MPS_TRACE_BIT_READER )
+#else
+#define MBEDTLS_MPS_TRACE_MASK_READER 0
+#endif
+
+#if defined(MBEDTLS_MPS_TRACE_ENABLE_WRITER)
+#define MBEDTLS_MPS_TRACE_MASK_WRITER (1u << MBEDTLS_MPS_TRACE_BIT_WRITER )
+#else
+#define MBEDTLS_MPS_TRACE_MASK_WRITER 0
+#endif
+
+#define MBEDTLS_MPS_TRACE_MASK ( MBEDTLS_MPS_TRACE_MASK_LAYER_1 |       \
+                                 MBEDTLS_MPS_TRACE_MASK_LAYER_2 |       \
+                                 MBEDTLS_MPS_TRACE_MASK_LAYER_3 |       \
+                                 MBEDTLS_MPS_TRACE_MASK_LAYER_4 |       \
+                                 MBEDTLS_MPS_TRACE_MASK_READER  |       \
+                                 MBEDTLS_MPS_TRACE_MASK_WRITER )
+
+/* We have to avoid globals because E-ACSL chokes on them...
+ * Wrap everything in stub functions. */
+int  mbedtls_mps_trace_get_depth( void );
+void mbedtls_mps_trace_inc_depth( void );
+void mbedtls_mps_trace_dec_depth( void );
+
+void mbedtls_mps_trace_color( int id );
+void mbedtls_mps_trace_indent( int level, mbedtls_mps_trace_type ty );
+
+void mbedtls_mps_trace_print_msg( int id, int line, const char *format, ... );
+
+#define MBEDTLS_MPS_TRACE( type, ... )                                              \
+    do {                                                                            \
+        if( ! ( MBEDTLS_MPS_TRACE_MASK & ( 1u << mbedtls_mps_trace_id ) ) )         \
+            break;                                                                  \
+        mbedtls_mps_trace_indent( mbedtls_mps_trace_get_depth(), type );            \
+        mbedtls_mps_trace_color( mbedtls_mps_trace_id );                            \
+        mbedtls_mps_trace_print_msg( mbedtls_mps_trace_id, __LINE__, __VA_ARGS__ ); \
+        mbedtls_mps_trace_color( 0 );                                               \
+    } while( 0 )
+
+#define MBEDTLS_MPS_TRACE_INIT( ... )                                         \
+    do {                                                                      \
+        if( ! ( MBEDTLS_MPS_TRACE_MASK & ( 1u << mbedtls_mps_trace_id ) ) )   \
+            break;                                                            \
+        MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_CALL, __VA_ARGS__ );        \
+        mbedtls_mps_trace_inc_depth();                                        \
+    } while( 0 )
+
+#define MBEDTLS_MPS_TRACE_END( val )                                        \
+    do {                                                                    \
+        if( ! ( MBEDTLS_MPS_TRACE_MASK & ( 1u << mbedtls_mps_trace_id ) ) ) \
+            break;                                                          \
+        MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_RETURN, "%d (-%#04x)",    \
+               (int) (val), -((unsigned)(val)) );                           \
+        mbedtls_mps_trace_dec_depth();                                      \
+    } while( 0 )
+
+#define MBEDTLS_MPS_TRACE_RETURN( val )         \
+    do {                                        \
+        /* Breaks tail recursion. */            \
+        int ret__ = val;                        \
+        MBEDTLS_MPS_TRACE_END( ret__ );         \
+        return( ret__ );                        \
+    } while( 0 )
+
+#else /* MBEDTLS_MPS_TRACE */
+
+#define MBEDTLS_MPS_TRACE( type, ... ) do { } while( 0 )
+#define MBEDTLS_MPS_TRACE_INIT( ... )  do { } while( 0 )
+#define MBEDTLS_MPS_TRACE_END          do { } while( 0 )
+
+#define MBEDTLS_MPS_TRACE_RETURN( val ) return( val );
+
+#endif /* MBEDTLS_MPS_TRACE */
+
+#endif /* MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H */
diff --git a/third_party/mbedtls/repo/library/net_sockets.c b/third_party/mbedtls/repo/library/net_sockets.c
index 54c2b47..5fbe1f7 100644
--- a/third_party/mbedtls/repo/library/net_sockets.c
+++ b/third_party/mbedtls/repo/library/net_sockets.c
@@ -20,8 +20,12 @@
 /* Enable definition of getaddrinfo() even when compiling with -std=c99. Must
  * be set before config.h, which pulls in glibc's features.h indirectly.
  * Harmless on other platforms. */
+#ifndef _POSIX_C_SOURCE
 #define _POSIX_C_SOURCE 200112L
+#endif
+#ifndef _XOPEN_SOURCE
 #define _XOPEN_SOURCE 600 /* sockaddr_storage */
+#endif
 
 #include "common.h"
 
@@ -132,6 +136,31 @@
 }
 
 /*
+ * Return 0 if the file descriptor is valid, an error otherwise.
+ * If for_select != 0, check whether the file descriptor is within the range
+ * allowed for fd_set used for the FD_xxx macros and the select() function.
+ */
+static int check_fd( int fd, int for_select )
+{
+    if( fd < 0 )
+        return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+
+#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
+    !defined(EFI32)
+    (void) for_select;
+#else
+    /* A limitation of select() is that it only works with file descriptors
+     * that are strictly less than FD_SETSIZE. This is a limitation of the
+     * fd_set type. Error out early, because attempting to call FD_SET on a
+     * large file descriptor is a buffer overflow on typical platforms. */
+    if( for_select && fd >= FD_SETSIZE )
+        return( MBEDTLS_ERR_NET_POLL_FAILED );
+#endif
+
+    return( 0 );
+}
+
+/*
  * Initialize a context
  */
 void mbedtls_net_init( mbedtls_net_context *ctx )
@@ -462,8 +491,9 @@
 
     int fd = ctx->fd;
 
-    if( fd < 0 )
-        return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+    ret = check_fd( fd, 1 );
+    if( ret != 0 )
+        return( ret );
 
 #if defined(__has_feature)
 #if __has_feature(memory_sanitizer)
@@ -542,8 +572,9 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     int fd = ((mbedtls_net_context *) ctx)->fd;
 
-    if( fd < 0 )
-        return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+    ret = check_fd( fd, 0 );
+    if( ret != 0 )
+        return( ret );
 
     ret = (int) read( fd, buf, len );
 
@@ -581,8 +612,9 @@
     fd_set read_fds;
     int fd = ((mbedtls_net_context *) ctx)->fd;
 
-    if( fd < 0 )
-        return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+    ret = check_fd( fd, 1 );
+    if( ret != 0 )
+        return( ret );
 
     FD_ZERO( &read_fds );
     FD_SET( fd, &read_fds );
@@ -622,8 +654,9 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     int fd = ((mbedtls_net_context *) ctx)->fd;
 
-    if( fd < 0 )
-        return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+    ret = check_fd( fd, 0 );
+    if( ret != 0 )
+        return( ret );
 
     ret = (int) write( fd, buf, len );
 
diff --git a/third_party/mbedtls/repo/library/nist_kw.c b/third_party/mbedtls/repo/library/nist_kw.c
index 04829a0..1aea0b6 100644
--- a/third_party/mbedtls/repo/library/nist_kw.c
+++ b/third_party/mbedtls/repo/library/nist_kw.c
@@ -34,6 +34,7 @@
 #include "mbedtls/nist_kw.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
+#include "mbedtls/constant_time.h"
 
 #include <stdint.h>
 #include <string.h>
@@ -52,51 +53,11 @@
 #define KW_SEMIBLOCK_LENGTH    8
 #define MIN_SEMIBLOCKS_COUNT   3
 
-/* constant-time buffer comparison */
-static inline unsigned char mbedtls_nist_kw_safer_memcmp( const void *a, const void *b, size_t n )
-{
-    size_t i;
-    volatile const unsigned char *A = (volatile const unsigned char *) a;
-    volatile const unsigned char *B = (volatile const unsigned char *) b;
-    volatile unsigned char diff = 0;
-
-    for( i = 0; i < n; i++ )
-    {
-        /* Read volatile data in order before computing diff.
-         * This avoids IAR compiler warning:
-         * 'the order of volatile accesses is undefined ..' */
-        unsigned char x = A[i], y = B[i];
-        diff |= x ^ y;
-    }
-
-    return( diff );
-}
-
 /*! The 64-bit default integrity check value (ICV) for KW mode. */
 static const unsigned char NIST_KW_ICV1[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6};
 /*! The 32-bit default integrity check value (ICV) for KWP mode. */
 static const  unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6};
 
-#ifndef GET_UINT32_BE
-#define GET_UINT32_BE(n,b,i)                            \
-do {                                                    \
-    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
-        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
-        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
-        | ( (uint32_t) (b)[(i) + 3]       );            \
-} while( 0 )
-#endif
-
-#ifndef PUT_UINT32_BE
-#define PUT_UINT32_BE(n,b,i)                            \
-do {                                                    \
-    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
-    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
-    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
-    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
-} while( 0 )
-#endif
-
 /*
  * Initialize context
  */
@@ -189,8 +150,6 @@
     uint64_t t = 0;
     unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
     unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
-    unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
-    unsigned char *A = output;
 
     *out_len = 0;
     /*
@@ -245,7 +204,7 @@
         }
 
         memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 );
-        PUT_UINT32_BE( ( in_len & 0xffffffff ), output,
+        MBEDTLS_PUT_UINT32_BE( ( in_len & 0xffffffff ), output,
                        KW_SEMIBLOCK_LENGTH / 2 );
 
         memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len );
@@ -266,6 +225,9 @@
     }
     else
     {
+        unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
+        unsigned char *A = output;
+
         /*
          * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
          */
@@ -329,7 +291,7 @@
     uint64_t t = 0;
     unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
     unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
-    unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
+    unsigned char *R = NULL;
     *out_len = 0;
 
     if( semiblocks < MIN_SEMIBLOCKS_COUNT )
@@ -339,6 +301,7 @@
 
     memcpy( A, input, KW_SEMIBLOCK_LENGTH );
     memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
+    R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
 
     /* Calculate intermediate values */
     for( t = s; t >= 1; t-- )
@@ -416,7 +379,7 @@
             goto cleanup;
 
         /* Check ICV in "constant-time" */
-        diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH );
+        diff = mbedtls_ct_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH );
 
         if( diff != 0 )
         {
@@ -465,14 +428,14 @@
         }
 
         /* Check ICV in "constant-time" */
-        diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 );
+        diff = mbedtls_ct_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 );
 
         if( diff != 0 )
         {
             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
         }
 
-        GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 );
+        Plen = MBEDTLS_GET_UINT32_BE( A, KW_SEMIBLOCK_LENGTH / 2 );
 
         /*
          * Plen is the length of the plaintext, when the input is valid.
diff --git a/third_party/mbedtls/repo/library/pem.c b/third_party/mbedtls/repo/library/pem.c
index 969d492..fcfde94 100644
--- a/third_party/mbedtls/repo/library/pem.c
+++ b/third_party/mbedtls/repo/library/pem.c
@@ -343,7 +343,7 @@
     ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 );
 
     if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER )
-        return( MBEDTLS_ERR_PEM_INVALID_DATA + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PEM_INVALID_DATA, ret ) );
 
     if( ( buf = mbedtls_calloc( 1, len ) ) == NULL )
         return( MBEDTLS_ERR_PEM_ALLOC_FAILED );
@@ -352,7 +352,7 @@
     {
         mbedtls_platform_zeroize( buf, len );
         mbedtls_free( buf );
-        return( MBEDTLS_ERR_PEM_INVALID_DATA + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PEM_INVALID_DATA, ret ) );
     }
 
     if( enc != 0 )
diff --git a/third_party/mbedtls/repo/library/pk.c b/third_party/mbedtls/repo/library/pk.c
index ecf002d..05cc213 100644
--- a/third_party/mbedtls/repo/library/pk.c
+++ b/third_party/mbedtls/repo/library/pk.c
@@ -235,12 +235,15 @@
 {
     const mbedtls_md_info_t *md_info;
 
-    if( *hash_len != 0 )
+    if( *hash_len != 0 && md_alg == MBEDTLS_MD_NONE )
         return( 0 );
 
     if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
         return( -1 );
 
+    if ( *hash_len != 0 && *hash_len != mbedtls_md_get_size( md_info ) )
+        return ( -1 );
+
     *hash_len = mbedtls_md_get_size( md_info );
     return( 0 );
 }
diff --git a/third_party/mbedtls/repo/library/pkcs12.c b/third_party/mbedtls/repo/library/pkcs12.c
index 4bdeb68..cacf7db 100644
--- a/third_party/mbedtls/repo/library/pkcs12.c
+++ b/third_party/mbedtls/repo/library/pkcs12.c
@@ -60,21 +60,21 @@
      *
      */
     if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
-        return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT,
+                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
 
     if( ( ret = mbedtls_asn1_get_tag( p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-        return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret ) );
 
     salt->p = *p;
     *p += salt->len;
 
     if( ( ret = mbedtls_asn1_get_int( p, end, iterations ) ) != 0 )
-        return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret ) );
 
     if( *p != end )
-        return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     return( 0 );
 }
@@ -179,6 +179,9 @@
     mbedtls_cipher_context_t cipher_ctx;
     size_t olen = 0;
 
+    if( pwd == NULL && pwdlen != 0 )
+        return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
+
     cipher_info = mbedtls_cipher_info_from_type( cipher_type );
     if( cipher_info == NULL )
         return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
@@ -231,12 +234,23 @@
     unsigned char *p = data;
     size_t use_len;
 
-    while( data_len > 0 )
+    if( filler != NULL && fill_len != 0 )
     {
-        use_len = ( data_len > fill_len ) ? fill_len : data_len;
-        memcpy( p, filler, use_len );
-        p += use_len;
-        data_len -= use_len;
+        while( data_len > 0 )
+        {
+            use_len = ( data_len > fill_len ) ? fill_len : data_len;
+            memcpy( p, filler, use_len );
+            p += use_len;
+            data_len -= use_len;
+        }
+    }
+    else
+    {
+        /* If either of the above are not true then clearly there is nothing
+         * that this function can do. The function should *not* be called
+         * under either of those circumstances, as you could end up with an
+         * incorrect output but for safety's sake, leaving the check in as
+         * otherwise we could end up with memory corruption.*/
     }
 }
 
@@ -253,6 +267,8 @@
     unsigned char hash_output[MBEDTLS_MD_MAX_SIZE];
     unsigned char *p;
     unsigned char c;
+    int           use_password = 0;
+    int           use_salt = 0;
 
     size_t hlen, use_len, v, i;
 
@@ -263,6 +279,15 @@
     if( datalen > 128 || pwdlen > 64 || saltlen > 64 )
         return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
 
+    if( pwd == NULL && pwdlen != 0 )
+        return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
+
+    if( salt == NULL && saltlen != 0 )
+        return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
+
+    use_password = ( pwd && pwdlen != 0 );
+    use_salt = ( salt && saltlen != 0 );
+
     md_info = mbedtls_md_info_from_type( md_type );
     if( md_info == NULL )
         return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
@@ -280,8 +305,15 @@
 
     memset( diversifier, (unsigned char) id, v );
 
-    pkcs12_fill_buffer( salt_block, v, salt, saltlen );
-    pkcs12_fill_buffer( pwd_block,  v, pwd,  pwdlen  );
+    if( use_salt != 0 )
+    {
+        pkcs12_fill_buffer( salt_block, v, salt, saltlen );
+    }
+
+    if( use_password != 0 )
+    {
+        pkcs12_fill_buffer( pwd_block,  v, pwd,  pwdlen  );
+    }
 
     p = data;
     while( datalen > 0 )
@@ -293,11 +325,17 @@
         if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 )
             goto exit;
 
-        if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v ) ) != 0 )
-            goto exit;
+        if( use_salt != 0 )
+        {
+            if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v )) != 0 )
+                goto exit;
+        }
 
-        if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v ) ) != 0 )
-            goto exit;
+        if( use_password != 0)
+        {
+            if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v )) != 0 )
+                goto exit;
+        }
 
         if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 )
             goto exit;
@@ -325,22 +363,28 @@
             if( ++hash_block[i - 1] != 0 )
                 break;
 
-        // salt_block += B
-        c = 0;
-        for( i = v; i > 0; i-- )
+        if( use_salt != 0 )
         {
-            j = salt_block[i - 1] + hash_block[i - 1] + c;
-            c = (unsigned char) (j >> 8);
-            salt_block[i - 1] = j & 0xFF;
+            // salt_block += B
+            c = 0;
+            for( i = v; i > 0; i-- )
+            {
+                j = salt_block[i - 1] + hash_block[i - 1] + c;
+                c = MBEDTLS_BYTE_1( j );
+                salt_block[i - 1] = MBEDTLS_BYTE_0( j );
+            }
         }
 
-        // pwd_block  += B
-        c = 0;
-        for( i = v; i > 0; i-- )
+        if( use_password != 0 )
         {
-            j = pwd_block[i - 1] + hash_block[i - 1] + c;
-            c = (unsigned char) (j >> 8);
-            pwd_block[i - 1] = j & 0xFF;
+            // pwd_block  += B
+            c = 0;
+            for( i = v; i > 0; i-- )
+            {
+                j = pwd_block[i - 1] + hash_block[i - 1] + c;
+                c = MBEDTLS_BYTE_1( j );
+                pwd_block[i - 1] = MBEDTLS_BYTE_0( j );
+            }
         }
     }
 
diff --git a/third_party/mbedtls/repo/library/pkcs5.c b/third_party/mbedtls/repo/library/pkcs5.c
index e9e743f..2b014d9 100644
--- a/third_party/mbedtls/repo/library/pkcs5.c
+++ b/third_party/mbedtls/repo/library/pkcs5.c
@@ -60,8 +60,8 @@
     const unsigned char *end = params->p + params->len;
 
     if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
-        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
+                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
     /*
      *  PBKDF2-params ::= SEQUENCE {
      *    salt              OCTET STRING,
@@ -73,13 +73,13 @@
      */
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len,
                                       MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
 
     salt->p = p;
     p += salt->len;
 
     if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 )
-        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
 
     if( p == end )
         return( 0 );
@@ -87,21 +87,21 @@
     if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 )
     {
         if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-            return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
     }
 
     if( p == end )
         return( 0 );
 
     if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 )
-        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
 
     if( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 )
         return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
 
     if( p != end )
-        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     return( 0 );
 }
@@ -134,12 +134,12 @@
      *  }
      */
     if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
-        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
+                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
 
     if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid,
                                       &kdf_alg_params ) ) != 0 )
-        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
 
     // Only PBKDF2 supported at the moment
     //
@@ -160,7 +160,7 @@
     if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid,
                               &enc_scheme_params ) ) != 0 )
     {
-        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
     }
 
     if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 )
diff --git a/third_party/mbedtls/repo/library/pkparse.c b/third_party/mbedtls/repo/library/pkparse.c
index 0590f2b..535ed70 100644
--- a/third_party/mbedtls/repo/library/pkparse.c
+++ b/third_party/mbedtls/repo/library/pkparse.c
@@ -186,8 +186,8 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if ( end - *p < 1 )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+        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;
@@ -197,21 +197,21 @@
 #endif
             )
     {
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_UNEXPECTED_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_ERR_PK_KEY_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
     }
 
     params->p = *p;
     *p += params->len;
 
     if( *p != end )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     return( 0 );
 }
@@ -247,7 +247,7 @@
 
     /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */
     if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
 
     if( ver < 1 || ver > 3 )
         return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
@@ -285,13 +285,13 @@
 
     /* Prime-p ::= INTEGER -- Field of size p. */
     if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
 
     grp->pbits = mbedtls_mpi_bitlen( &grp->P );
 
     if( p != end_field )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     /*
      * Curve ::= SEQUENCE {
@@ -315,7 +315,7 @@
     if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ||
         ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 )
     {
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
     }
 
     p += len;
@@ -323,7 +323,7 @@
     if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ||
         ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 )
     {
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
     }
 
     p += len;
@@ -333,14 +333,14 @@
         p += len;
 
     if( p != end_curve )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     /*
      * ECPoint ::= OCTET STRING
      */
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
 
     if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G,
                                       ( const unsigned char *) p, len ) ) != 0 )
@@ -366,7 +366,7 @@
      * order INTEGER
      */
     if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
 
     grp->nbits = mbedtls_mpi_bitlen( &grp->N );
 
@@ -528,15 +528,15 @@
 
     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) );
 
     if( *p + len != end )
-        return( MBEDTLS_ERR_PK_INVALID_PUBKEY +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        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_ERR_PK_INVALID_PUBKEY + ret );
+        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 )
@@ -546,7 +546,7 @@
 
     /* Import E */
     if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
-        return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) );
 
     if( ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
                                         NULL, 0, *p, len ) ) != 0 )
@@ -561,8 +561,8 @@
     }
 
     if( *p != end )
-        return( MBEDTLS_ERR_PK_INVALID_PUBKEY +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     return( 0 );
 }
@@ -584,7 +584,7 @@
     memset( params, 0, sizeof(mbedtls_asn1_buf) );
 
     if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 )
-        return( MBEDTLS_ERR_PK_INVALID_ALG + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_ALG, ret ) );
 
     if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 )
         return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
@@ -624,7 +624,7 @@
     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
     {
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
     }
 
     end = *p + len;
@@ -633,11 +633,11 @@
         return( ret );
 
     if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 )
-        return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) );
 
     if( *p + len != end )
-        return( MBEDTLS_ERR_PK_INVALID_PUBKEY +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL )
         return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
@@ -662,8 +662,8 @@
         ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
 
     if( ret == 0 && *p != end )
-        ret = MBEDTLS_ERR_PK_INVALID_PUBKEY +
-              MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY,
+              MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
 
     if( ret != 0 )
         mbedtls_pk_free( pk );
@@ -734,14 +734,14 @@
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
     {
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        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_ERR_PK_KEY_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
     }
 
     if( version != 0 )
@@ -831,8 +831,8 @@
 
     if( p != end )
     {
-        ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
-              MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ;
+        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+              MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
     }
 
 cleanup:
@@ -843,7 +843,7 @@
     {
         /* Wrap error code if it's coming from a lower level */
         if( ( ret & 0xff80 ) == 0 )
-            ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret;
+            ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret );
         else
             ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
 
@@ -883,24 +883,24 @@
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
     {
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        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_ERR_PK_KEY_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
 
     if( version != 1 )
         return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION );
 
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        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_ERR_PK_KEY_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
     }
 
     p += len;
@@ -924,7 +924,7 @@
         else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
         {
             mbedtls_ecp_keypair_free( eck );
-            return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
         }
     }
 
@@ -940,11 +940,11 @@
             end2 = p + len;
 
             if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 )
-                return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+                return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
 
             if( p + len != end2 )
-                return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
-                        MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+                return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+                        MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
             if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 )
                 pubkey_done = 1;
@@ -961,7 +961,7 @@
         else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
         {
             mbedtls_ecp_keypair_free( eck );
-            return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
         }
     }
 
@@ -970,7 +970,7 @@
                                                       NULL, NULL ) ) != 0 )
     {
         mbedtls_ecp_keypair_free( eck );
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
     }
 
     if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 )
@@ -1028,26 +1028,28 @@
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
     {
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        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_ERR_PK_KEY_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
 
     if( version != 0 )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret ) );
 
     if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, &params ) ) != 0 )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+    {
+        return( ret );
+    }
 
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
 
     if( len < 1 )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+                MBEDTLS_ERR_ASN1_OUT_OF_DATA ) );
 
     if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL )
         return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
@@ -1130,16 +1132,16 @@
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
     {
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
     }
 
     end = p + len;
 
     if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
 
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
 
     buf = p;
 
@@ -1378,8 +1380,11 @@
     }
 #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
 
-    if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 )
+    ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen );
+    if( ret == 0 )
+    {
         return( 0 );
+    }
 
     mbedtls_pk_free( pk );
     mbedtls_pk_init( pk );
@@ -1518,7 +1523,8 @@
         return( ret );
     }
     mbedtls_pk_free( ctx );
-    if( ret != ( MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
+    if( ret != ( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY,
+                                    MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) )
     {
         return( ret );
     }
diff --git a/third_party/mbedtls/repo/library/pkwrite.c b/third_party/mbedtls/repo/library/pkwrite.c
index 0da3698..566153d 100644
--- a/third_party/mbedtls/repo/library/pkwrite.c
+++ b/third_party/mbedtls/repo/library/pkwrite.c
@@ -487,7 +487,7 @@
  *      publicExponent    INTEGER   -- e            1 + 3 + MPI_MAX + 1
  *  }
  */
-#define RSA_PUB_DER_MAX_BYTES   38 + 2 * MBEDTLS_MPI_MAX_SIZE
+#define RSA_PUB_DER_MAX_BYTES   ( 38 + 2 * MBEDTLS_MPI_MAX_SIZE )
 
 /*
  * RSA private keys:
@@ -504,10 +504,10 @@
  *      otherPrimeInfos   OtherPrimeInfos OPTIONAL  0 (not supported)
  *  }
  */
-#define MPI_MAX_SIZE_2          MBEDTLS_MPI_MAX_SIZE / 2 + \
-                                MBEDTLS_MPI_MAX_SIZE % 2
-#define RSA_PRV_DER_MAX_BYTES   47 + 3 * MBEDTLS_MPI_MAX_SIZE \
-                                   + 5 * MPI_MAX_SIZE_2
+#define MPI_MAX_SIZE_2          ( MBEDTLS_MPI_MAX_SIZE / 2 + \
+                                  MBEDTLS_MPI_MAX_SIZE % 2 )
+#define RSA_PRV_DER_MAX_BYTES   ( 47 + 3 * MBEDTLS_MPI_MAX_SIZE \
+                                   + 5 * MPI_MAX_SIZE_2 )
 
 #else /* MBEDTLS_RSA_C */
 
@@ -528,7 +528,7 @@
  *                                            + 2 * ECP_MAX (coords)    [1]
  *  }
  */
-#define ECP_PUB_DER_MAX_BYTES   30 + 2 * MBEDTLS_ECP_MAX_BYTES
+#define ECP_PUB_DER_MAX_BYTES   ( 30 + 2 * MBEDTLS_ECP_MAX_BYTES )
 
 /*
  * EC private keys:
@@ -539,7 +539,7 @@
  *      publicKey  [1] BIT STRING OPTIONAL      1 + 2 + [1] above
  *    }
  */
-#define ECP_PRV_DER_MAX_BYTES   29 + 3 * MBEDTLS_ECP_MAX_BYTES
+#define ECP_PRV_DER_MAX_BYTES   ( 29 + 3 * MBEDTLS_ECP_MAX_BYTES )
 
 #else /* MBEDTLS_ECP_C */
 
@@ -548,10 +548,10 @@
 
 #endif /* MBEDTLS_ECP_C */
 
-#define PUB_DER_MAX_BYTES   RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
-                            RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES
-#define PRV_DER_MAX_BYTES   RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \
-                            RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES
+#define PUB_DER_MAX_BYTES   ( RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
+                              RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES )
+#define PRV_DER_MAX_BYTES   ( RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \
+                              RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES )
 
 int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
 {
diff --git a/third_party/mbedtls/repo/library/poly1305.c b/third_party/mbedtls/repo/library/poly1305.c
index 492d145..7375a0c 100644
--- a/third_party/mbedtls/repo/library/poly1305.c
+++ b/third_party/mbedtls/repo/library/poly1305.c
@@ -52,13 +52,6 @@
 
 #define POLY1305_BLOCK_SIZE_BYTES ( 16U )
 
-#define BYTES_TO_U32_LE( data, offset )                           \
-    ( (uint32_t) (data)[offset]                                     \
-          | (uint32_t) ( (uint32_t) (data)[( offset ) + 1] << 8 )   \
-          | (uint32_t) ( (uint32_t) (data)[( offset ) + 2] << 16 )  \
-          | (uint32_t) ( (uint32_t) (data)[( offset ) + 3] << 24 )  \
-    )
-
 /*
  * Our implementation is tuned for 32-bit platforms with a 64-bit multiplier.
  * However we provided an alternative for platforms without such a multiplier.
@@ -129,10 +122,10 @@
     for( i = 0U; i < nblocks; i++ )
     {
         /* The input block is treated as a 128-bit little-endian integer */
-        d0   = BYTES_TO_U32_LE( input, offset + 0  );
-        d1   = BYTES_TO_U32_LE( input, offset + 4  );
-        d2   = BYTES_TO_U32_LE( input, offset + 8  );
-        d3   = BYTES_TO_U32_LE( input, offset + 12 );
+        d0   = MBEDTLS_GET_UINT32_LE( input, offset + 0  );
+        d1   = MBEDTLS_GET_UINT32_LE( input, offset + 4  );
+        d2   = MBEDTLS_GET_UINT32_LE( input, offset + 8  );
+        d3   = MBEDTLS_GET_UINT32_LE( input, offset + 12 );
 
         /* Compute: acc += (padded) block as a 130-bit integer */
         d0  += (uint64_t) acc0;
@@ -257,22 +250,10 @@
     acc3 += ctx->s[3] + (uint32_t) ( d >> 32U );
 
     /* Compute MAC (128 least significant bits of the accumulator) */
-    mac[ 0] = (unsigned char)( acc0       );
-    mac[ 1] = (unsigned char)( acc0 >>  8 );
-    mac[ 2] = (unsigned char)( acc0 >> 16 );
-    mac[ 3] = (unsigned char)( acc0 >> 24 );
-    mac[ 4] = (unsigned char)( acc1       );
-    mac[ 5] = (unsigned char)( acc1 >>  8 );
-    mac[ 6] = (unsigned char)( acc1 >> 16 );
-    mac[ 7] = (unsigned char)( acc1 >> 24 );
-    mac[ 8] = (unsigned char)( acc2       );
-    mac[ 9] = (unsigned char)( acc2 >>  8 );
-    mac[10] = (unsigned char)( acc2 >> 16 );
-    mac[11] = (unsigned char)( acc2 >> 24 );
-    mac[12] = (unsigned char)( acc3       );
-    mac[13] = (unsigned char)( acc3 >>  8 );
-    mac[14] = (unsigned char)( acc3 >> 16 );
-    mac[15] = (unsigned char)( acc3 >> 24 );
+    MBEDTLS_PUT_UINT32_LE( acc0, mac,  0 );
+    MBEDTLS_PUT_UINT32_LE( acc1, mac,  4 );
+    MBEDTLS_PUT_UINT32_LE( acc2, mac,  8 );
+    MBEDTLS_PUT_UINT32_LE( acc3, mac, 12 );
 }
 
 void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx )
@@ -297,15 +278,15 @@
     POLY1305_VALIDATE_RET( key != NULL );
 
     /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */
-    ctx->r[0] = BYTES_TO_U32_LE( key, 0 )  & 0x0FFFFFFFU;
-    ctx->r[1] = BYTES_TO_U32_LE( key, 4 )  & 0x0FFFFFFCU;
-    ctx->r[2] = BYTES_TO_U32_LE( key, 8 )  & 0x0FFFFFFCU;
-    ctx->r[3] = BYTES_TO_U32_LE( key, 12 ) & 0x0FFFFFFCU;
+    ctx->r[0] = MBEDTLS_GET_UINT32_LE( key, 0 )  & 0x0FFFFFFFU;
+    ctx->r[1] = MBEDTLS_GET_UINT32_LE( key, 4 )  & 0x0FFFFFFCU;
+    ctx->r[2] = MBEDTLS_GET_UINT32_LE( key, 8 )  & 0x0FFFFFFCU;
+    ctx->r[3] = MBEDTLS_GET_UINT32_LE( key, 12 ) & 0x0FFFFFFCU;
 
-    ctx->s[0] = BYTES_TO_U32_LE( key, 16 );
-    ctx->s[1] = BYTES_TO_U32_LE( key, 20 );
-    ctx->s[2] = BYTES_TO_U32_LE( key, 24 );
-    ctx->s[3] = BYTES_TO_U32_LE( key, 28 );
+    ctx->s[0] = MBEDTLS_GET_UINT32_LE( key, 16 );
+    ctx->s[1] = MBEDTLS_GET_UINT32_LE( key, 20 );
+    ctx->s[2] = MBEDTLS_GET_UINT32_LE( key, 24 );
+    ctx->s[3] = MBEDTLS_GET_UINT32_LE( key, 28 );
 
     /* Initial accumulator state */
     ctx->acc[0] = 0U;
diff --git a/third_party/mbedtls/repo/library/psa_crypto.c b/third_party/mbedtls/repo/library/psa_crypto.c
index 82b95dc..e6dab33 100644
--- a/third_party/mbedtls/repo/library/psa_crypto.c
+++ b/third_party/mbedtls/repo/library/psa_crypto.c
@@ -26,12 +26,17 @@
 #include "check_crypto_config.h"
 #endif
 
-#include "psa_crypto_service_integration.h"
 #include "psa/crypto.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_ecp.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
@@ -40,6 +45,8 @@
  * stored keys. */
 #include "psa_crypto_storage.h"
 
+#include "psa_crypto_random_impl.h"
+
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
@@ -49,6 +56,7 @@
 #define mbedtls_free   free
 #endif
 
+#include "mbedtls/aes.h"
 #include "mbedtls/arc4.h"
 #include "mbedtls/asn1.h"
 #include "mbedtls/asn1write.h"
@@ -60,7 +68,6 @@
 #include "mbedtls/cipher.h"
 #include "mbedtls/ccm.h"
 #include "mbedtls/cmac.h"
-#include "mbedtls/ctr_drbg.h"
 #include "mbedtls/des.h"
 #include "mbedtls/ecdh.h"
 #include "mbedtls/ecp.h"
@@ -85,20 +92,6 @@
 
 #define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) )
 
-/* constant-time buffer comparison */
-static inline int safer_memcmp( const uint8_t *a, const uint8_t *b, size_t n )
-{
-    size_t i;
-    unsigned char diff = 0;
-
-    for( i = 0; i < n; i++ )
-        diff |= a[i] ^ b[i];
-
-    return( diff );
-}
-
-
-
 /****************************************************************/
 /* Global data, support functions and library management */
 /****************************************************************/
@@ -115,25 +108,29 @@
 
 typedef struct
 {
-    void (* entropy_init )( mbedtls_entropy_context *ctx );
-    void (* entropy_free )( mbedtls_entropy_context *ctx );
-    mbedtls_entropy_context entropy;
-    mbedtls_ctr_drbg_context ctr_drbg;
     unsigned initialized : 1;
     unsigned rng_state : 2;
+    mbedtls_psa_random_context_t rng;
 } psa_global_data_t;
 
 static psa_global_data_t global_data;
 
+#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state =
+    &global_data.rng.drbg;
+#endif
+
 #define GUARD_MODULE_INITIALIZED        \
     if( global_data.initialized == 0 )  \
         return( PSA_ERROR_BAD_STATE );
 
 psa_status_t mbedtls_to_psa_error( int ret )
 {
-    /* If there's both a high-level code and low-level code, dispatch on
-     * the high-level code. */
-    switch( ret < -0x7f ? - ( -ret & 0x7f80 ) : 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 );
@@ -214,6 +211,10 @@
         case MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED:
             return( PSA_ERROR_HARDWARE_FAILURE );
 
+#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:
@@ -221,6 +222,7 @@
             return( PSA_ERROR_NOT_SUPPORTED );
         case MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR:
             return( PSA_ERROR_INSUFFICIENT_ENTROPY );
+#endif
 
         case MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH:
             return( PSA_ERROR_NOT_SUPPORTED );
@@ -239,6 +241,19 @@
         case MBEDTLS_ERR_GCM_HW_ACCEL_FAILED:
             return( PSA_ERROR_HARDWARE_FAILURE );
 
+#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
+
         case MBEDTLS_ERR_MD2_HW_ACCEL_FAILED:
         case MBEDTLS_ERR_MD4_HW_ACCEL_FAILED:
         case MBEDTLS_ERR_MD5_HW_ACCEL_FAILED:
@@ -322,7 +337,7 @@
         case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE:
             return( PSA_ERROR_BUFFER_TOO_SMALL );
         case MBEDTLS_ERR_RSA_RNG_FAILED:
-            return( PSA_ERROR_INSUFFICIENT_MEMORY );
+            return( PSA_ERROR_INSUFFICIENT_ENTROPY );
         case MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION:
             return( PSA_ERROR_NOT_SUPPORTED );
         case MBEDTLS_ERR_RSA_HW_ACCEL_FAILED:
@@ -350,8 +365,11 @@
             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 );
         case MBEDTLS_ERR_ECP_HW_ACCEL_FAILED:
             return( PSA_ERROR_HARDWARE_FAILURE );
+
         case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED:
             return( PSA_ERROR_CORRUPTION_DETECTED );
 
@@ -367,93 +385,110 @@
 /* Key management */
 /****************************************************************/
 
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-static inline int psa_key_slot_is_external( const psa_key_slot_t *slot )
-{
-    return( psa_key_lifetime_is_external( slot->attr.lifetime ) );
-}
-#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
-
-/* For now the MBEDTLS_PSA_ACCEL_ guards are also used here since the
- * current test driver in key_management.c is using this function
- * when accelerators are used for ECC key pair and public key.
- * Once that dependency is resolved these guards can be removed.
- */
 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
     defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \
-    defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \
-    defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
+    defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
 mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_family_t curve,
-                                               size_t byte_length )
+                                               size_t bits,
+                                               int bits_is_sloppy )
 {
     switch( curve )
     {
         case PSA_ECC_FAMILY_SECP_R1:
-            switch( byte_length )
+            switch( bits )
             {
-                case PSA_BITS_TO_BYTES( 192 ):
+#if defined(PSA_WANT_ECC_SECP_R1_192)
+                case 192:
                     return( MBEDTLS_ECP_DP_SECP192R1 );
-                case PSA_BITS_TO_BYTES( 224 ):
+#endif
+#if defined(PSA_WANT_ECC_SECP_R1_224)
+                case 224:
                     return( MBEDTLS_ECP_DP_SECP224R1 );
-                case PSA_BITS_TO_BYTES( 256 ):
+#endif
+#if defined(PSA_WANT_ECC_SECP_R1_256)
+                case 256:
                     return( MBEDTLS_ECP_DP_SECP256R1 );
-                case PSA_BITS_TO_BYTES( 384 ):
+#endif
+#if defined(PSA_WANT_ECC_SECP_R1_384)
+                case 384:
                     return( MBEDTLS_ECP_DP_SECP384R1 );
-                case PSA_BITS_TO_BYTES( 521 ):
+#endif
+#if defined(PSA_WANT_ECC_SECP_R1_521)
+                case 521:
                     return( MBEDTLS_ECP_DP_SECP521R1 );
-                default:
-                    return( MBEDTLS_ECP_DP_NONE );
+                case 528:
+                    if( bits_is_sloppy )
+                        return( MBEDTLS_ECP_DP_SECP521R1 );
+                    break;
+#endif
             }
             break;
 
         case PSA_ECC_FAMILY_BRAINPOOL_P_R1:
-            switch( byte_length )
+            switch( bits )
             {
-                case PSA_BITS_TO_BYTES( 256 ):
+#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
+                case 256:
                     return( MBEDTLS_ECP_DP_BP256R1 );
-                case PSA_BITS_TO_BYTES( 384 ):
+#endif
+#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
+                case 384:
                     return( MBEDTLS_ECP_DP_BP384R1 );
-                case PSA_BITS_TO_BYTES( 512 ):
+#endif
+#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
+                case 512:
                     return( MBEDTLS_ECP_DP_BP512R1 );
-                default:
-                    return( MBEDTLS_ECP_DP_NONE );
+#endif
             }
             break;
 
         case PSA_ECC_FAMILY_MONTGOMERY:
-            switch( byte_length )
+            switch( bits )
             {
-                case PSA_BITS_TO_BYTES( 255 ):
+#if defined(PSA_WANT_ECC_MONTGOMERY_255)
+                case 255:
                     return( MBEDTLS_ECP_DP_CURVE25519 );
-                case PSA_BITS_TO_BYTES( 448 ):
+                case 256:
+                    if( bits_is_sloppy )
+                        return( MBEDTLS_ECP_DP_CURVE25519 );
+                    break;
+#endif
+#if defined(PSA_WANT_ECC_MONTGOMERY_448)
+                case 448:
                     return( MBEDTLS_ECP_DP_CURVE448 );
-                default:
-                    return( MBEDTLS_ECP_DP_NONE );
+#endif
             }
             break;
 
         case PSA_ECC_FAMILY_SECP_K1:
-            switch( byte_length )
+            switch( bits )
             {
-                case PSA_BITS_TO_BYTES( 192 ):
+#if defined(PSA_WANT_ECC_SECP_K1_192)
+                case 192:
                     return( MBEDTLS_ECP_DP_SECP192K1 );
-                case PSA_BITS_TO_BYTES( 224 ):
+#endif
+#if defined(PSA_WANT_ECC_SECP_K1_224)
+                case 224:
                     return( MBEDTLS_ECP_DP_SECP224K1 );
-                case PSA_BITS_TO_BYTES( 256 ):
+#endif
+#if defined(PSA_WANT_ECC_SECP_K1_256)
+                case 256:
                     return( MBEDTLS_ECP_DP_SECP256K1 );
-                default:
-                    return( MBEDTLS_ECP_DP_NONE );
+#endif
             }
             break;
-
-        default:
-            return( MBEDTLS_ECP_DP_NONE );
     }
+
+    (void) bits_is_sloppy;
+    return( MBEDTLS_ECP_DP_NONE );
 }
 #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
-        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) ||
-        * defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) ||
-        * defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) */
+          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) */
 
 static psa_status_t validate_unstructured_key_bit_size( psa_key_type_t type,
                                                         size_t bits )
@@ -465,31 +500,37 @@
         case PSA_KEY_TYPE_HMAC:
         case PSA_KEY_TYPE_DERIVE:
             break;
-#if defined(MBEDTLS_AES_C)
+#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(MBEDTLS_CAMELLIA_C)
+#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(MBEDTLS_DES_C)
+#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(MBEDTLS_ARC4_C)
+#if defined(PSA_WANT_KEY_TYPE_ARC4)
         case PSA_KEY_TYPE_ARC4:
             if( bits < 8 || bits > 2048 )
                 return( PSA_ERROR_INVALID_ARGUMENT );
             break;
 #endif
-#if defined(MBEDTLS_CHACHA20_C)
+#if defined(PSA_WANT_KEY_TYPE_CHACHA20)
         case PSA_KEY_TYPE_CHACHA20:
             if( bits != 256 )
                 return( PSA_ERROR_INVALID_ARGUMENT );
@@ -504,500 +545,58 @@
     return( PSA_SUCCESS );
 }
 
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \
-    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
-    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 );
-}
-
-/** Load the contents of a key buffer into an internal RSA representation
+/** Check whether a given key type is valid for use with a given MAC algorithm
  *
- * \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.
- */
-static psa_status_t psa_load_rsa_representation( psa_key_type_t type,
-                                                 const uint8_t *data,
-                                                 size_t data_length,
-                                                 mbedtls_rsa_context **p_rsa )
-{
-    psa_status_t status;
-    mbedtls_pk_context ctx;
-    size_t bits;
-    mbedtls_pk_init( &ctx );
-
-    /* Parse the data. */
-    if( PSA_KEY_TYPE_IS_KEY_PAIR( type ) )
-        status = mbedtls_to_psa_error(
-            mbedtls_pk_parse_key( &ctx, data, data_length, NULL, 0 ) );
-    else
-        status = mbedtls_to_psa_error(
-            mbedtls_pk_parse_public_key( &ctx, data, data_length ) );
-    if( status != PSA_SUCCESS )
-        goto exit;
-
-    /* We have something that the pkparse module recognizes. If it is a
-     * valid RSA key, store it. */
-    if( mbedtls_pk_get_type( &ctx ) != MBEDTLS_PK_RSA )
-    {
-        status = PSA_ERROR_INVALID_ARGUMENT;
-        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( mbedtls_pk_rsa( ctx ) ) );
-    if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS )
-    {
-        status = PSA_ERROR_NOT_SUPPORTED;
-        goto exit;
-    }
-    status = psa_check_rsa_key_byte_aligned( mbedtls_pk_rsa( ctx ) );
-    if( status != PSA_SUCCESS )
-        goto exit;
-
-    /* Copy out the pointer to the RSA context, and reset the PK context
-     * such that pk_free doesn't free the RSA context we just grabbed. */
-    *p_rsa = mbedtls_pk_rsa( ctx );
-    ctx.pk_info = NULL;
-
-exit:
-    mbedtls_pk_free( &ctx );
-    return( status );
-}
-
-#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
-        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
-        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) ||
-        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) ||
-        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) ||
-        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
-
-#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
-    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
-
-/** Export an RSA key to export representation
+ * 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] 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
- */
-static psa_status_t psa_export_rsa_key( psa_key_type_t type,
-                                        mbedtls_rsa_context *rsa,
-                                        uint8_t *data,
-                                        size_t data_size,
-                                        size_t *data_length )
-{
-#if defined(MBEDTLS_PK_WRITE_C)
-    int ret;
-    mbedtls_pk_context pk;
-    uint8_t *pos = data + data_size;
-
-    mbedtls_pk_init( &pk );
-    pk.pk_info = &mbedtls_rsa_info;
-    pk.pk_ctx = rsa;
-
-    /* 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_pk_write_key_der( &pk, data, data_size );
-    else
-        ret = mbedtls_pk_write_pubkey( &pos, data, &pk );
-
-    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 );
-#else
-    (void) type;
-    (void) rsa;
-    (void) data;
-    (void) data_size;
-    (void) data_length;
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* MBEDTLS_PK_WRITE_C */
-}
-
-/** Import an RSA key from import representation to a slot
- *
- * \param[in,out] slot      The slot where to store the export representation to
- * \param[in] data          The buffer containing the import representation
- * \param[in] data_length   The amount of bytes in \p data
- */
-static psa_status_t psa_import_rsa_key( psa_key_slot_t *slot,
-                                        const uint8_t *data,
-                                        size_t data_length )
-{
-    psa_status_t status;
-    uint8_t* output = NULL;
-    mbedtls_rsa_context *rsa = NULL;
-
-    /* Parse input */
-    status = psa_load_rsa_representation( slot->attr.type,
-                                          data,
-                                          data_length,
-                                          &rsa );
-    if( status != PSA_SUCCESS )
-        goto exit;
-
-    slot->attr.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. */
-    output = mbedtls_calloc( 1, data_length );
-    if( output == NULL )
-    {
-        status = PSA_ERROR_INSUFFICIENT_MEMORY;
-        goto exit;
-    }
-
-    status = psa_export_rsa_key( slot->attr.type,
-                                 rsa,
-                                 output,
-                                 data_length,
-                                 &data_length);
-exit:
-    /* Always free the RSA object */
-    mbedtls_rsa_free( rsa );
-    mbedtls_free( rsa );
-
-    /* Free the allocated buffer only on error. */
-    if( status != PSA_SUCCESS )
-    {
-        mbedtls_free( output );
-        return( status );
-    }
-
-    /* On success, store the allocated export-formatted key. */
-    slot->data.key.data = output;
-    slot->data.key.bytes = data_length;
-
-    return( PSA_SUCCESS );
-}
-
-#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) ||
-        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
-
-#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
-    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
-/** 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] 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.
- */
-static psa_status_t psa_load_ecp_representation( psa_key_type_t type,
-                                                 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_size = data_length;
-
-    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_size = data_length / 2;
-
-        /* Montgomery public keys are represented in compressed format, meaning
-         * their curve_size is equal to the amount of input. */
-
-        /* Private keys are represented in uncompressed private random integer
-         * format, meaning their curve_size is equal to the amount of input. */
-    }
-
-    /* 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 );
-
-    /* Load the group. */
-    grp_id = mbedtls_ecc_group_of_psa( PSA_KEY_TYPE_ECC_GET_FAMILY( type ),
-                                       curve_size );
-    if( grp_id == MBEDTLS_ECP_DP_NONE )
-    {
-        status = PSA_ERROR_INVALID_ARGUMENT;
-        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) ||
-        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) ||
-        * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
-        * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) ||
-        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
-
-#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
-    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
-/** 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
- */
-static psa_status_t psa_export_ecp_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_ctr_drbg_random, &global_data.ctr_drbg ) );
-            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
-    {
-        if( data_size < PSA_BITS_TO_BYTES( ecp->grp.nbits ) )
-            return( PSA_ERROR_BUFFER_TOO_SMALL );
-
-        status = mbedtls_to_psa_error(
-                    mbedtls_ecp_write_key( ecp,
-                                           data,
-                                           PSA_BITS_TO_BYTES( ecp->grp.nbits ) ) );
-        if( status == PSA_SUCCESS )
-            *data_length = PSA_BITS_TO_BYTES( ecp->grp.nbits );
-        else
-            memset( data, 0, data_size );
-
-        return( status );
-    }
-}
-
-/** Import an ECP key from import representation to a slot
- *
- * \param[in,out] slot      The slot where to store the export representation to
- * \param[in] data          The buffer containing the import representation
- * \param[in] data_length   The amount of bytes in \p data
- */
-static psa_status_t psa_import_ecp_key( psa_key_slot_t *slot,
-                                        const uint8_t *data,
-                                        size_t data_length )
-{
-    psa_status_t status;
-    uint8_t* output = NULL;
-    mbedtls_ecp_keypair *ecp = NULL;
-
-    /* Parse input */
-    status = psa_load_ecp_representation( slot->attr.type,
-                                          data,
-                                          data_length,
-                                          &ecp );
-    if( status != PSA_SUCCESS )
-        goto exit;
-
-    if( PSA_KEY_TYPE_ECC_GET_FAMILY( slot->attr.type ) == PSA_ECC_FAMILY_MONTGOMERY)
-        slot->attr.bits = (psa_key_bits_t) ecp->grp.nbits + 1;
-    else
-        slot->attr.bits = (psa_key_bits_t) 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. */
-    output = mbedtls_calloc( 1, data_length );
-    if( output == NULL )
-    {
-        status = PSA_ERROR_INSUFFICIENT_MEMORY;
-        goto exit;
-    }
-
-    status = psa_export_ecp_key( slot->attr.type,
-                                 ecp,
-                                 output,
-                                 data_length,
-                                 &data_length);
-exit:
-    /* Always free the PK object (will also free contained ECP context) */
-    mbedtls_ecp_keypair_free( ecp );
-    mbedtls_free( ecp );
-
-    /* Free the allocated buffer only on error. */
-    if( status != PSA_SUCCESS )
-    {
-        mbedtls_free( output );
-        return( status );
-    }
-
-    /* On success, store the allocated export-formatted key. */
-    slot->data.key.data = output;
-    slot->data.key.bytes = data_length;
-
-    return( PSA_SUCCESS );
-}
-#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
-        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
-
-/** Return the size of the key in the given slot, in bits.
- *
- * \param[in] slot      A key slot.
- *
- * \return The key size in bits, read from the metadata in the slot.
- */
-static inline size_t psa_get_key_slot_bits( const psa_key_slot_t *slot )
-{
-    return( slot->attr.bits );
-}
-
-/** 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.
+ * \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 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.
+ *         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
  */
-static psa_status_t psa_allocate_buffer_to_slot( psa_key_slot_t *slot,
-                                                 size_t buffer_length )
+MBEDTLS_STATIC_TESTABLE psa_status_t psa_mac_key_can_do(
+    psa_algorithm_t algorithm,
+    psa_key_type_t key_type )
 {
-    if( slot->data.key.data != NULL )
+    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->data.key.data = mbedtls_calloc( 1, buffer_length );
-    if( slot->data.key.data == NULL )
+    slot->key.data = mbedtls_calloc( 1, buffer_length );
+    if( slot->key.data == NULL )
         return( PSA_ERROR_INSUFFICIENT_MEMORY );
 
-    slot->data.key.bytes = buffer_length;
+    slot->key.bytes = buffer_length;
     return( PSA_SUCCESS );
 }
 
@@ -1010,44 +609,26 @@
     if( status != PSA_SUCCESS )
         return( status );
 
-    memcpy( slot->data.key.data, data, data_length );
+    memcpy( slot->key.data, data, data_length );
     return( PSA_SUCCESS );
 }
 
-/** Import key data into a slot.
- *
- * `slot->type` must have been set previously.
- * This function assumes that the slot does not contain any key material yet.
- * On failure, the slot content is unchanged.
- *
- * Persistent storage is not affected.
- *
- * \param[in,out] slot  The key slot to import data into.
- *                      Its `type` field must have previously been set to
- *                      the desired key type.
- *                      It must not contain any key material yet.
- * \param[in] data      Buffer containing the key material to parse and import.
- * \param data_length   Size of \p data in bytes.
- *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_ARGUMENT
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- */
-static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
-                                              const uint8_t *data,
-                                              size_t data_length )
+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_SUCCESS;
-    size_t bit_size;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_type_t type = attributes->core.type;
 
     /* zero-length keys are never supported. */
     if( data_length == 0 )
         return( PSA_ERROR_NOT_SUPPORTED );
 
-    if( key_type_is_raw_bytes( slot->attr.type ) )
+    if( key_type_is_raw_bytes( type ) )
     {
-        bit_size = PSA_BYTES_TO_BITS( data_length );
+        *bits = PSA_BYTES_TO_BITS( data_length );
 
         /* Ensure that the bytes-to-bits conversion hasn't overflown. */
         if( data_length > SIZE_MAX / 8 )
@@ -1055,77 +636,49 @@
 
         /* Enforce a size limit, and in particular ensure that the bit
          * size fits in its representation type. */
-        if( bit_size > PSA_MAX_KEY_BITS )
+        if( ( *bits ) > PSA_MAX_KEY_BITS )
             return( PSA_ERROR_NOT_SUPPORTED );
 
-        status = validate_unstructured_key_bit_size( slot->attr.type, bit_size );
+        status = validate_unstructured_key_bit_size( type, *bits );
         if( status != PSA_SUCCESS )
             return( status );
 
-        /* Allocate memory for the key */
-        status = psa_copy_key_material_into_slot( slot, data, data_length );
-        if( status != PSA_SUCCESS )
-            return( status );
-
-        /* Write the actual key size to the slot.
-         * psa_start_key_creation() wrote the size declared by the
-         * caller, which may be 0 (meaning unspecified) or wrong. */
-        slot->attr.bits = (psa_key_bits_t) bit_size;
+        /* 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( slot->attr.type ) )
+    else if( PSA_KEY_TYPE_IS_ASYMMETRIC( type ) )
     {
-        /* Try validation through accelerators first. */
-        bit_size = slot->attr.bits;
-        psa_key_attributes_t attributes = {
-          .core = slot->attr
-        };
-        status = psa_driver_wrapper_validate_key( &attributes,
-                                                  data,
-                                                  data_length,
-                                                  &bit_size );
-        if( status == PSA_SUCCESS )
-        {
-            /* Key has been validated successfully by an accelerator.
-             * Copy key material into slot. */
-            status = psa_copy_key_material_into_slot( slot, data, data_length );
-            if( status != PSA_SUCCESS )
-                return( status );
-
-            slot->attr.bits = (psa_key_bits_t) bit_size;
-            return( PSA_SUCCESS );
-        }
-        else if( status != PSA_ERROR_NOT_SUPPORTED )
-            return( status );
-
-        /* Key format is not supported by any accelerator, try software fallback
-         * if present. */
 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
     defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
-        if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) )
+        if( PSA_KEY_TYPE_IS_ECC( type ) )
         {
-            return( psa_import_ecp_key( slot, data, data_length ) );
+            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) ||
         * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
     defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
-        if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
+        if( PSA_KEY_TYPE_IS_RSA( type ) )
         {
-            return( psa_import_rsa_key( slot, data, data_length ) );
+            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) ||
         * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
+    }
 
-        /* Fell through the fallback as well, so have nothing else to try. */
-        return( PSA_ERROR_NOT_SUPPORTED );
-    }
-    else
-    {
-        /* Unknown key type */
-        return( PSA_ERROR_NOT_SUPPORTED );
-    }
+    return( PSA_ERROR_NOT_SUPPORTED );
 }
 
 /** Calculate the intersection of two algorithm usage policies.
@@ -1133,6 +686,7 @@
  * 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 )
 {
@@ -1141,8 +695,8 @@
         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_HASH_AND_SIGN( alg1 ) &&
-        PSA_ALG_IS_HASH_AND_SIGN( alg2 ) &&
+    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 )
@@ -1150,11 +704,92 @@
         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_algorithm_t policy_alg,
+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. */
@@ -1163,12 +798,69 @@
     /* 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_HASH_AND_SIGN( requested_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. */
@@ -1178,23 +870,52 @@
         return( PSA_ALG_KEY_AGREEMENT_GET_BASE( requested_alg ) ==
                 policy_alg );
     }
-    /* If it isn't permitted, it's forbidden. */
+    /* 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 int psa_key_policy_permits( const psa_key_policy_t *policy,
-                                   psa_algorithm_t alg )
+static psa_status_t psa_key_policy_permits( const psa_key_policy_t *policy,
+                                            psa_key_type_t key_type,
+                                            psa_algorithm_t alg )
 {
-    return( psa_key_algorithm_permits( policy->alg, alg ) ||
-            psa_key_algorithm_permits( policy->alg2, 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.
  *
@@ -1202,17 +923,20 @@
  *         \c *policy contains the intersection of the original value of
  *         \c *policy and \c *constraint.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         \c *policy and \c *constraint are incompatible.
+ *         \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( policy->alg, constraint->alg );
+        psa_key_policy_algorithm_intersection( key_type, policy->alg,
+                                               constraint->alg );
     psa_algorithm_t intersection_alg2 =
-        psa_key_policy_algorithm_intersection( policy->alg2, constraint->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 )
@@ -1227,7 +951,8 @@
  *  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.
+ * 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.
@@ -1256,13 +981,21 @@
     if( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) )
         usage &= ~PSA_KEY_USAGE_EXPORT;
 
-    status = PSA_ERROR_NOT_PERMITTED;
     if( ( slot->attr.policy.usage & usage ) != usage )
+    {
+        status = PSA_ERROR_NOT_PERMITTED;
         goto error;
+    }
 
     /* Enforce that the usage policy permits the requested algortihm. */
-    if( alg != 0 && ! psa_key_policy_permits( &slot->attr.policy, alg ) )
-        goto error;
+    if( alg != 0 )
+    {
+        status = psa_key_policy_permits( &slot->attr.policy,
+                                         slot->attr.type,
+                                         alg );
+        if( status != PSA_SUCCESS )
+            goto error;
+    }
 
     return( PSA_SUCCESS );
 
@@ -1276,16 +1009,16 @@
 /** 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.
+ * available, as opposed to a key in a secure element and/or to be used
+ * by a secure element.
  *
- * This is a temporary function to use instead of
- * psa_get_and_lock_key_slot_with_policy() until secure element support is
- * fully implemented.
+ * 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 is locked. It is the responsibility of the
  * caller to unlock the key slot when it does not access it anymore.
  */
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
 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,
@@ -1297,7 +1030,7 @@
     if( status != PSA_SUCCESS )
         return( status );
 
-    if( psa_key_slot_is_external( *p_slot ) )
+    if( psa_key_lifetime_is_external( (*p_slot)->attr.lifetime ) )
     {
         psa_unlock_key_slot( *p_slot );
         *p_slot = NULL;
@@ -1306,31 +1039,17 @@
 
     return( PSA_SUCCESS );
 }
-#else /* MBEDTLS_PSA_CRYPTO_SE_C */
-/* With no secure element support, all keys are transparent. */
-#define psa_get_and_lock_transparent_key_slot_with_policy( key, p_slot, usage, alg )   \
-    psa_get_and_lock_key_slot_with_policy( key, p_slot, usage, alg )
-#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
-/** Wipe key data from a slot. Preserve metadata such as the policy. */
-static psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot )
+psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot )
 {
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    if( psa_key_slot_is_external( slot ) )
-    {
-        /* No key material to clean. */
-    }
-    else
-#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
-    {
-        /* Data pointer will always be either a valid pointer or NULL in an
-         * initialized slot, so we can just free it. */
-        if( slot->data.key.data != NULL )
-            mbedtls_platform_zeroize( slot->data.key.data, slot->data.key.bytes);
-        mbedtls_free( slot->data.key.data );
-        slot->data.key.data = NULL;
-        slot->data.key.bytes = 0;
-    }
+    /* Data pointer will always be either a valid pointer or NULL in an
+     * initialized slot, so we can just free it. */
+    if( slot->key.data != NULL )
+        mbedtls_platform_zeroize( slot->key.data, slot->key.bytes);
+
+    mbedtls_free( slot->key.data );
+    slot->key.data = NULL;
+    slot->key.bytes = 0;
 
     return( PSA_SUCCESS );
 }
@@ -1404,6 +1123,17 @@
        return( PSA_ERROR_GENERIC_ERROR );
     }
 
+    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 )
@@ -1415,7 +1145,7 @@
          * three actions. */
         psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_DESTROY_KEY );
         psa_crypto_transaction.key.lifetime = slot->attr.lifetime;
-        psa_crypto_transaction.key.slot = slot->data.se.slot_number;
+        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 )
@@ -1432,7 +1162,8 @@
             goto exit;
         }
 
-        status = psa_destroy_se_key( driver, slot->data.se.slot_number );
+        status = psa_destroy_se_key( driver,
+                                     psa_key_slot_get_slot_number( slot ) );
         if( overall_status == PSA_SUCCESS )
             overall_status = status;
     }
@@ -1464,65 +1195,14 @@
     }
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
 exit:
-#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
     status = psa_wipe_key_slot( slot );
     /* Prioritize CORRUPTION_DETECTED from wiping over a storage error */
-    if( overall_status == PSA_SUCCESS )
+    if( status != PSA_SUCCESS )
         overall_status = status;
     return( overall_status );
 }
 
-void psa_reset_key_attributes( psa_key_attributes_t *attributes )
-{
-    mbedtls_free( attributes->domain_parameters );
-    memset( attributes, 0, sizeof( *attributes ) );
-}
-
-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 )
-{
-    uint8_t *copy = NULL;
-
-    if( data_length != 0 )
-    {
-        copy = mbedtls_calloc( 1, data_length );
-        if( copy == NULL )
-            return( PSA_ERROR_INSUFFICIENT_MEMORY );
-        memcpy( copy, data, data_length );
-    }
-    /* After this point, this function is guaranteed to succeed, so it
-     * can start modifying `*attributes`. */
-
-    if( attributes->domain_parameters != NULL )
-    {
-        mbedtls_free( attributes->domain_parameters );
-        attributes->domain_parameters = NULL;
-        attributes->domain_parameters_size = 0;
-    }
-
-    attributes->domain_parameters = copy;
-    attributes->domain_parameters_size = data_length;
-    attributes->core.type = type;
-    return( PSA_SUCCESS );
-}
-
-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 )
-{
-    if( attributes->domain_parameters_size > data_size )
-        return( PSA_ERROR_BUFFER_TOO_SMALL );
-    *data_length = attributes->domain_parameters_size;
-    if( attributes->domain_parameters_size != 0 )
-        memcpy( data, attributes->domain_parameters,
-                attributes->domain_parameters_size );
-    return( PSA_SUCCESS );
-}
-
 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
     defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
 static psa_status_t psa_get_rsa_public_exponent(
@@ -1587,8 +1267,9 @@
                                 MBEDTLS_PSA_KA_MASK_DUAL_USE );
 
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    if( psa_key_slot_is_external( slot ) )
-        psa_set_key_slot_number( attributes, slot->data.se.slot_number );
+    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 */
 
     switch( slot->attr.type )
@@ -1597,21 +1278,19 @@
     defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
         case PSA_KEY_TYPE_RSA_KEY_PAIR:
         case PSA_KEY_TYPE_RSA_PUBLIC_KEY:
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
             /* TODO: reporting the public exponent for opaque keys
              * is not yet implemented.
              * https://github.com/ARMmbed/mbed-crypto/issues/216
              */
-            if( psa_key_slot_is_external( slot ) )
-                break;
-#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+            if( ! psa_key_lifetime_is_external( slot->attr.lifetime ) )
             {
                 mbedtls_rsa_context *rsa = NULL;
 
-                status = psa_load_rsa_representation( slot->attr.type,
-                                                      slot->data.key.data,
-                                                      slot->data.key.bytes,
-                                                      &rsa );
+                status = mbedtls_psa_rsa_load_representation(
+                             slot->attr.type,
+                             slot->key.data,
+                             slot->key.bytes,
+                             &rsa );
                 if( status != PSA_SUCCESS )
                     break;
 
@@ -1651,147 +1330,35 @@
 }
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
-static psa_status_t psa_internal_export_key_buffer( const psa_key_slot_t *slot,
+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( slot->data.key.bytes > data_size )
+    if( key_buffer_size > data_size )
         return( PSA_ERROR_BUFFER_TOO_SMALL );
-    memcpy( data, slot->data.key.data, slot->data.key.bytes );
-    memset( data + slot->data.key.bytes, 0,
-            data_size - slot->data.key.bytes );
-    *data_length = slot->data.key.bytes;
+    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 );
 }
 
-static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot,
-                                             uint8_t *data,
-                                             size_t data_size,
-                                             size_t *data_length,
-                                             int export_public_key )
+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 )
 {
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    const psa_drv_se_t *drv;
-    psa_drv_se_context_t *drv_context;
-#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+    psa_key_type_t type = attributes->core.type;
 
-    *data_length = 0;
-
-    if( export_public_key && ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) )
-        return( PSA_ERROR_INVALID_ARGUMENT );
-
-    /* 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 );
-
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) )
+    if( key_type_is_raw_bytes( type ) ||
+        PSA_KEY_TYPE_IS_RSA( type )   ||
+        PSA_KEY_TYPE_IS_ECC( type )      )
     {
-        psa_drv_se_export_key_t method;
-        if( drv->key_management == NULL )
-            return( PSA_ERROR_NOT_SUPPORTED );
-        method = ( export_public_key ?
-                   drv->key_management->p_export_public :
-                   drv->key_management->p_export );
-        if( method == NULL )
-            return( PSA_ERROR_NOT_SUPPORTED );
-        return( method( drv_context,
-                        slot->data.se.slot_number,
-                        data, data_size, data_length ) );
-    }
-#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
-
-    if( key_type_is_raw_bytes( slot->attr.type ) )
-    {
-        return( psa_internal_export_key_buffer( slot, data, data_size, data_length ) );
-    }
-    else if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ||
-             PSA_KEY_TYPE_IS_ECC( slot->attr.type ) )
-    {
-        if( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) )
-        {
-            /* Exporting public -> public */
-            return( psa_internal_export_key_buffer( slot, data, data_size, data_length ) );
-        }
-        else if( !export_public_key )
-        {
-            /* Exporting private -> private */
-            return( psa_internal_export_key_buffer( slot, data, data_size, data_length ) );
-        }
-
-        /* Need to export the public part of a private key,
-         * so conversion is needed. Try the accelerators first. */
-        psa_status_t status = psa_driver_wrapper_export_public_key( slot,
-                                                                    data,
-                                                                    data_size,
-                                                                    data_length );
-
-        if( status != PSA_ERROR_NOT_SUPPORTED ||
-            psa_key_lifetime_is_external( slot->attr.lifetime ) )
-            return( status );
-
-        if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
-        {
-#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
-    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
-            mbedtls_rsa_context *rsa = NULL;
-            status = psa_load_rsa_representation(
-                                    slot->attr.type,
-                                    slot->data.key.data,
-                                    slot->data.key.bytes,
-                                    &rsa );
-            if( status != PSA_SUCCESS )
-                return( status );
-
-            status = psa_export_rsa_key( PSA_KEY_TYPE_RSA_PUBLIC_KEY,
-                                         rsa,
-                                         data,
-                                         data_size,
-                                         data_length );
-
-            mbedtls_rsa_free( rsa );
-            mbedtls_free( rsa );
-
-            return( status );
-#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) ||
-        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
-        }
-        else
-        {
-#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
-    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
-            mbedtls_ecp_keypair *ecp = NULL;
-            status = psa_load_ecp_representation(
-                                    slot->attr.type,
-                                    slot->data.key.data,
-                                    slot->data.key.bytes,
-                                    &ecp );
-            if( status != PSA_SUCCESS )
-                return( status );
-
-            status = psa_export_ecp_key( PSA_KEY_TYPE_ECC_PUBLIC_KEY(
-                                            PSA_KEY_TYPE_ECC_GET_FAMILY(
-                                                slot->attr.type ) ),
-                                         ecp,
-                                         data,
-                                         data_size,
-                                         data_length );
-
-            mbedtls_ecp_keypair_free( ecp );
-            mbedtls_free( ecp );
-            return( status );
-#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) ||
-        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
-        }
+        return( psa_export_key_buffer_internal(
+                    key_buffer, key_buffer_size,
+                    data, data_size, data_length ) );
     }
     else
     {
@@ -1811,6 +1378,12 @@
     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
 
+    /* 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
@@ -1826,12 +1399,80 @@
     if( status != PSA_SUCCESS )
         return( status );
 
-    status = psa_internal_export_key( slot, data, data_size, data_length, 0 );
+    psa_key_attributes_t attributes = {
+        .core = slot->attr
+    };
+    status = psa_driver_wrapper_export_key( &attributes,
+                 slot->key.data, slot->key.bytes,
+                 data, data_size, data_length );
+
     unlock_status = psa_unlock_key_slot( slot );
 
     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->core.type;
+
+    if( PSA_KEY_TYPE_IS_RSA( type ) || PSA_KEY_TYPE_IS_ECC( type ) )
+    {
+        if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) )
+        {
+            /* Exporting public -> public */
+            return( psa_export_key_buffer_internal(
+                        key_buffer, key_buffer_size,
+                        data, data_size, data_length ) );
+        }
+
+        if( PSA_KEY_TYPE_IS_RSA( type ) )
+        {
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
+    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) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
+        }
+        else
+        {
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
+    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) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
+        }
+    }
+    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_public_key( mbedtls_svc_key_id_t key,
                                     uint8_t *data,
                                     size_t data_size,
@@ -1841,6 +1482,12 @@
     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
 
+    /* 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
@@ -1852,7 +1499,20 @@
     if( status != PSA_SUCCESS )
         return( status );
 
-    status = psa_internal_export_key( slot, data, data_size, data_length, 1 );
+    if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) )
+    {
+         status = PSA_ERROR_INVALID_ARGUMENT;
+         goto exit;
+    }
+
+    psa_key_attributes_t attributes = {
+        .core = slot->attr
+    };
+    status = psa_driver_wrapper_export_public_key(
+        &attributes, slot->key.data, slot->key.bytes,
+        data, data_size, data_length );
+
+exit:
     unlock_status = psa_unlock_key_slot( slot );
 
     return( ( status == PSA_SUCCESS ) ? unlock_status : status );
@@ -1879,6 +1539,8 @@
                              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_DERIVE ) ) != 0 )
@@ -1923,9 +1585,8 @@
     }
     else
     {
-        status = psa_validate_key_id( psa_get_key_id( attributes ), 0 );
-        if( status != PSA_SUCCESS )
-            return( status );
+        if( !psa_is_valid_key_id( psa_get_key_id( attributes ), 0 ) )
+            return( PSA_ERROR_INVALID_ARGUMENT );
     }
 
     status = psa_validate_key_policy( &attributes->core.policy );
@@ -2043,8 +1704,9 @@
      * 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->data.se.slot_number );
+                                           &slot_number );
         if( status != PSA_SUCCESS )
             return( status );
 
@@ -2052,7 +1714,7 @@
         {
             psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_CREATE_KEY );
             psa_crypto_transaction.key.lifetime = slot->attr.lifetime;
-            psa_crypto_transaction.key.slot = slot->data.se.slot_number;
+            psa_crypto_transaction.key.slot = slot_number;
             psa_crypto_transaction.key.id = slot->attr.id;
             status = psa_crypto_save_transaction( );
             if( status != PSA_SUCCESS )
@@ -2061,6 +1723,9 @@
                 return( status );
             }
         }
+
+        status = psa_copy_key_material_into_slot(
+            slot, (uint8_t *)( &slot_number ), sizeof( slot_number ) );
     }
 
     if( *p_drv == NULL && method == PSA_KEY_CREATION_REGISTER )
@@ -2093,6 +1758,13 @@
  *
  * \retval #PSA_SUCCESS
  *         The key was successfully created.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
+ * \retval #PSA_ERROR_ALREADY_EXISTS
+ * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_DATA_CORRUPT
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ *
  * \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.
  */
@@ -2112,13 +1784,15 @@
         if( driver != NULL )
         {
             psa_se_key_data_storage_t data;
+            psa_key_slot_number_t slot_number =
+                psa_key_slot_get_slot_number( slot ) ;
+
 #if defined(static_assert)
-            static_assert( sizeof( slot->data.se.slot_number ) ==
+            static_assert( sizeof( slot_number ) ==
                            sizeof( data.slot_number ),
                            "Slot number size does not match psa_se_key_data_storage_t" );
 #endif
-            memcpy( &data.slot_number, &slot->data.se.slot_number,
-                    sizeof( slot->data.se.slot_number ) );
+            memcpy( &data.slot_number, &slot_number, sizeof( slot_number ) );
             status = psa_save_persistent_key( &slot->attr,
                                               (uint8_t*) &data,
                                               sizeof( data ) );
@@ -2129,8 +1803,8 @@
             /* 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->data.key.data,
-                                              slot->data.key.bytes );
+                                              slot->key.data,
+                                              slot->key.bytes );
         }
     }
 #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
@@ -2234,11 +1908,11 @@
             mbedtls_mpi actual, required;
             int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-            psa_status_t status = psa_load_rsa_representation(
-                                    slot->attr.type,
-                                    slot->data.key.data,
-                                    slot->data.key.bytes,
-                                    &rsa );
+            psa_status_t status = mbedtls_psa_rsa_load_representation(
+                                      slot->attr.type,
+                                      slot->key.data,
+                                      slot->key.bytes,
+                                      &rsa );
             if( status != PSA_SUCCESS )
                 return( status );
 
@@ -2288,6 +1962,7 @@
     psa_status_t status;
     psa_key_slot_t *slot = NULL;
     psa_se_drv_table_entry_t *driver = NULL;
+    size_t bits;
 
     *key = MBEDTLS_SVC_KEY_ID_INIT;
 
@@ -2302,39 +1977,34 @@
     if( status != PSA_SUCCESS )
         goto exit;
 
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    if( driver != NULL )
+    /* 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
+     * or cryptoprocessor with storage), we have to allocate a buffer to
+     * hold the generated key material. */
+    if( slot->key.data == NULL )
     {
-        const psa_drv_se_t *drv = psa_get_se_driver_methods( driver );
-        /* The driver should set the number of key bits, however in
-         * case it doesn't, we initialize bits to an invalid value. */
-        size_t bits = PSA_MAX_KEY_BITS + 1;
-        if( drv->key_management == NULL ||
-            drv->key_management->p_import == NULL )
-        {
-            status = PSA_ERROR_NOT_SUPPORTED;
-            goto exit;
-        }
-        status = drv->key_management->p_import(
-            psa_get_se_driver_context( driver ),
-            slot->data.se.slot_number, attributes, data, data_length,
-            &bits );
+        status = psa_allocate_buffer_to_slot( slot, data_length );
         if( status != PSA_SUCCESS )
             goto exit;
-        if( bits > PSA_MAX_KEY_BITS )
-        {
-            status = PSA_ERROR_NOT_SUPPORTED;
-            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
-#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+    else if( bits != slot->attr.bits )
     {
-        status = psa_import_key_into_slot( slot, data, data_length );
-        if( status != PSA_SUCCESS )
-            goto exit;
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
     }
+
     status = psa_validate_optional_attributes( slot, attributes );
     if( status != PSA_SUCCESS )
         goto exit;
@@ -2386,8 +2056,8 @@
                                            psa_key_slot_t *target )
 {
     psa_status_t status = psa_copy_key_material_into_slot( target,
-                                                           source->data.key.data,
-                                                           source->data.key.bytes );
+                                                           source->key.data,
+                                                           source->key.bytes );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -2420,7 +2090,8 @@
     if( status != PSA_SUCCESS )
         goto exit;
 
-    status = psa_restrict_key_policy( &actual_attributes.core.policy,
+    status = psa_restrict_key_policy( source_slot->attr.type,
+                                      &actual_attributes.core.policy,
                                       &source_slot->attr.policy );
     if( status != PSA_SUCCESS )
         goto exit;
@@ -2439,6 +2110,17 @@
     }
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
+    if( psa_key_lifetime_is_external( actual_attributes.core.lifetime ) )
+    {
+        /*
+         * Copying through an opaque driver is not implemented yet, consider
+         * a lifetime with an external location as an invalid parameter for
+         * now.
+         */
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
     status = psa_copy_key_material( source_slot, target_slot );
     if( status != PSA_SUCCESS )
         goto exit;
@@ -2459,274 +2141,73 @@
 /* Message digests */
 /****************************************************************/
 
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
-static const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg )
-{
-    switch( alg )
-    {
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2)
-        case PSA_ALG_MD2:
-            return( &mbedtls_md2_info );
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4)
-        case PSA_ALG_MD4:
-            return( &mbedtls_md4_info );
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
-        case PSA_ALG_MD5:
-            return( &mbedtls_md5_info );
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)
-        case PSA_ALG_RIPEMD160:
-            return( &mbedtls_ripemd160_info );
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)
-        case PSA_ALG_SHA_1:
-            return( &mbedtls_sha1_info );
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)
-        case PSA_ALG_SHA_224:
-            return( &mbedtls_sha224_info );
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)
-        case PSA_ALG_SHA_256:
-            return( &mbedtls_sha256_info );
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)
-        case PSA_ALG_SHA_384:
-            return( &mbedtls_sha384_info );
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)
-        case PSA_ALG_SHA_512:
-            return( &mbedtls_sha512_info );
-#endif
-        default:
-            return( NULL );
-    }
-}
-#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
-        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) ||
-        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) ||
-        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
-
 psa_status_t psa_hash_abort( 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_MD2)
-        case PSA_ALG_MD2:
-            mbedtls_md2_free( &operation->ctx.md2 );
-            break;
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4)
-        case PSA_ALG_MD4:
-            mbedtls_md4_free( &operation->ctx.md4 );
-            break;
-#endif
-#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
-        default:
-            return( PSA_ERROR_BAD_STATE );
-    }
-    operation->alg = 0;
-    return( PSA_SUCCESS );
+    /* 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 )
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 
     /* A context must be freshly initialized before it can be set up. */
-    if( operation->alg != 0 )
+    if( operation->id != 0 )
     {
-        return( PSA_ERROR_BAD_STATE );
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
     }
 
-    switch( alg )
+    if( !PSA_ALG_IS_HASH( alg ) )
     {
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2)
-        case PSA_ALG_MD2:
-            mbedtls_md2_init( &operation->ctx.md2 );
-            ret = mbedtls_md2_starts_ret( &operation->ctx.md2 );
-            break;
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4)
-        case PSA_ALG_MD4:
-            mbedtls_md4_init( &operation->ctx.md4 );
-            ret = mbedtls_md4_starts_ret( &operation->ctx.md4 );
-            break;
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
-        case PSA_ALG_MD5:
-            mbedtls_md5_init( &operation->ctx.md5 );
-            ret = mbedtls_md5_starts_ret( &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_ret( &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_ret( &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_ret( &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_ret( &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_ret( &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_ret( &operation->ctx.sha512, 0 );
-            break;
-#endif
-        default:
-            return( PSA_ALG_IS_HASH( alg ) ?
-                    PSA_ERROR_NOT_SUPPORTED :
-                    PSA_ERROR_INVALID_ARGUMENT );
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
     }
-    if( ret == 0 )
-        operation->alg = alg;
-    else
+
+    /* 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( mbedtls_to_psa_error( ret ) );
+
+    return status;
 }
 
 psa_status_t psa_hash_update( psa_hash_operation_t *operation,
                               const uint8_t *input,
                               size_t input_length )
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    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 );
 
-    switch( operation->alg )
-    {
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2)
-        case PSA_ALG_MD2:
-            ret = mbedtls_md2_update_ret( &operation->ctx.md2,
-                                          input, input_length );
-            break;
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4)
-        case PSA_ALG_MD4:
-            ret = mbedtls_md4_update_ret( &operation->ctx.md4,
-                                          input, input_length );
-            break;
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
-        case PSA_ALG_MD5:
-            ret = mbedtls_md5_update_ret( &operation->ctx.md5,
-                                          input, input_length );
-            break;
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)
-        case PSA_ALG_RIPEMD160:
-            ret = mbedtls_ripemd160_update_ret( &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_ret( &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_ret( &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_ret( &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_ret( &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_ret( &operation->ctx.sha512,
-                                             input, input_length );
-            break;
-#endif
-        default:
-            (void)input;
-            return( PSA_ERROR_BAD_STATE );
-    }
+    status = psa_driver_wrapper_hash_update( operation, input, input_length );
 
-    if( ret != 0 )
+exit:
+    if( status != PSA_SUCCESS )
         psa_hash_abort( operation );
-    return( mbedtls_to_psa_error( ret ) );
+
+    return( status );
 }
 
 psa_status_t psa_hash_finish( psa_hash_operation_t *operation,
@@ -2734,106 +2215,45 @@
                               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_SIZE( operation->alg );
+    *hash_length = 0;
+    if( operation->id == 0 )
+        return( PSA_ERROR_BAD_STATE );
 
-    /* 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_MD2)
-        case PSA_ALG_MD2:
-            ret = mbedtls_md2_finish_ret( &operation->ctx.md2, hash );
-            break;
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4)
-        case PSA_ALG_MD4:
-            ret = mbedtls_md4_finish_ret( &operation->ctx.md4, hash );
-            break;
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
-        case PSA_ALG_MD5:
-            ret = mbedtls_md5_finish_ret( &operation->ctx.md5, hash );
-            break;
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)
-        case PSA_ALG_RIPEMD160:
-            ret = mbedtls_ripemd160_finish_ret( &operation->ctx.ripemd160, hash );
-            break;
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)
-        case PSA_ALG_SHA_1:
-            ret = mbedtls_sha1_finish_ret( &operation->ctx.sha1, hash );
-            break;
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)
-        case PSA_ALG_SHA_224:
-            ret = mbedtls_sha256_finish_ret( &operation->ctx.sha256, hash );
-            break;
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)
-        case PSA_ALG_SHA_256:
-            ret = mbedtls_sha256_finish_ret( &operation->ctx.sha256, hash );
-            break;
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)
-        case PSA_ALG_SHA_384:
-            ret = mbedtls_sha512_finish_ret( &operation->ctx.sha512, hash );
-            break;
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)
-        case PSA_ALG_SHA_512:
-            ret = mbedtls_sha512_finish_ret( &operation->ctx.sha512, hash );
-            break;
-#endif
-        default:
-            return( PSA_ERROR_BAD_STATE );
-    }
-    status = mbedtls_to_psa_error( ret );
-
-exit:
-    if( status == PSA_SUCCESS )
-    {
-        *hash_length = actual_hash_length;
-        return( psa_hash_abort( operation ) );
-    }
-    else
-    {
-        psa_hash_abort( operation );
-        return( status );
-    }
+    psa_status_t status = psa_driver_wrapper_hash_finish(
+                            operation, hash, hash_size, hash_length );
+    psa_hash_abort( operation );
+    return( status );
 }
 
 psa_status_t psa_hash_verify( psa_hash_operation_t *operation,
                               const uint8_t *hash,
                               size_t hash_length )
 {
-    uint8_t actual_hash[MBEDTLS_MD_MAX_SIZE];
+    uint8_t actual_hash[PSA_HASH_MAX_SIZE];
     size_t actual_hash_length;
-    psa_status_t status = psa_hash_finish( operation,
-                                           actual_hash, sizeof( actual_hash ),
-                                           &actual_hash_length );
+    psa_status_t status = psa_hash_finish(
+                            operation,
+                            actual_hash, sizeof( actual_hash ),
+                            &actual_hash_length );
+
     if( status != PSA_SUCCESS )
-        return( status );
+        goto exit;
+
     if( actual_hash_length != hash_length )
-        return( PSA_ERROR_INVALID_SIGNATURE );
-    if( safer_memcmp( hash, actual_hash, actual_hash_length ) != 0 )
-        return( PSA_ERROR_INVALID_SIGNATURE );
-    return( PSA_SUCCESS );
+    {
+        status = PSA_ERROR_INVALID_SIGNATURE;
+        goto exit;
+    }
+
+    if( mbedtls_psa_safer_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);
+
+    return( status );
 }
 
 psa_status_t psa_hash_compute( psa_algorithm_t alg,
@@ -2841,123 +2261,58 @@
                                uint8_t *hash, size_t hash_size,
                                size_t *hash_length )
 {
-    psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
-    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    *hash_length = 0;
+    if( !PSA_ALG_IS_HASH( alg ) )
+        return( PSA_ERROR_INVALID_ARGUMENT );
 
-    *hash_length = hash_size;
-    status = psa_hash_setup( &operation, alg );
-    if( status != PSA_SUCCESS )
-        goto exit;
-    status = psa_hash_update( &operation, input, input_length );
-    if( status != PSA_SUCCESS )
-        goto exit;
-    status = psa_hash_finish( &operation, hash, hash_size, hash_length );
-    if( status != PSA_SUCCESS )
-        goto exit;
-
-exit:
-    if( status == PSA_SUCCESS )
-        status = psa_hash_abort( &operation );
-    else
-        psa_hash_abort( &operation );
-    return( status );
+    return( psa_driver_wrapper_hash_compute( alg, input, input_length,
+                                             hash, hash_size, hash_length ) );
 }
 
 psa_status_t psa_hash_compare( psa_algorithm_t alg,
                                const uint8_t *input, size_t input_length,
                                const uint8_t *hash, size_t hash_length )
 {
-    psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
-    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    uint8_t actual_hash[PSA_HASH_MAX_SIZE];
+    size_t actual_hash_length;
 
-    status = psa_hash_setup( &operation, alg );
+    if( !PSA_ALG_IS_HASH( alg ) )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
+    psa_status_t status = psa_driver_wrapper_hash_compute(
+                            alg, input, input_length,
+                            actual_hash, sizeof(actual_hash),
+                            &actual_hash_length );
     if( status != PSA_SUCCESS )
         goto exit;
-    status = psa_hash_update( &operation, input, input_length );
-    if( status != PSA_SUCCESS )
+    if( actual_hash_length != hash_length )
+    {
+        status = PSA_ERROR_INVALID_SIGNATURE;
         goto exit;
-    status = psa_hash_verify( &operation, hash, hash_length );
-    if( status != PSA_SUCCESS )
-        goto exit;
+    }
+    if( mbedtls_psa_safer_memcmp( hash, actual_hash, actual_hash_length ) != 0 )
+        status = PSA_ERROR_INVALID_SIGNATURE;
 
 exit:
-    if( status == PSA_SUCCESS )
-        status = psa_hash_abort( &operation );
-    else
-        psa_hash_abort( &operation );
+    mbedtls_platform_zeroize( actual_hash, sizeof( actual_hash ) );
     return( status );
 }
 
 psa_status_t psa_hash_clone( const psa_hash_operation_t *source_operation,
                              psa_hash_operation_t *target_operation )
 {
-    if( target_operation->alg != 0 )
-        return( PSA_ERROR_BAD_STATE );
-
-    switch( source_operation->alg )
+    if( source_operation->id == 0 ||
+        target_operation->id != 0 )
     {
-        case 0:
-            return( PSA_ERROR_BAD_STATE );
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD2)
-        case PSA_ALG_MD2:
-            mbedtls_md2_clone( &target_operation->ctx.md2,
-                               &source_operation->ctx.md2 );
-            break;
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4)
-        case PSA_ALG_MD4:
-            mbedtls_md4_clone( &target_operation->ctx.md4,
-                               &source_operation->ctx.md4 );
-            break;
-#endif
-#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
-        default:
-            return( PSA_ERROR_NOT_SUPPORTED );
+        return( PSA_ERROR_BAD_STATE );
     }
 
-    target_operation->alg = source_operation->alg;
-    return( PSA_SUCCESS );
+    psa_status_t status = psa_driver_wrapper_hash_clone( source_operation,
+                                                         target_operation );
+    if( status != PSA_SUCCESS )
+        psa_hash_abort( target_operation );
+
+    return( status );
 }
 
 
@@ -2965,309 +2320,59 @@
 /* MAC */
 /****************************************************************/
 
-static 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;
-    mbedtls_cipher_id_t cipher_id_tmp;
-
-    if( PSA_ALG_IS_AEAD( alg ) )
-        alg = PSA_ALG_AEAD_WITH_TAG_LENGTH( alg, 0 );
-
-    if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) )
-    {
-        switch( alg )
-        {
-            case PSA_ALG_STREAM_CIPHER:
-                mode = MBEDTLS_MODE_STREAM;
-                break;
-            case PSA_ALG_CTR:
-                mode = MBEDTLS_MODE_CTR;
-                break;
-            case PSA_ALG_CFB:
-                mode = MBEDTLS_MODE_CFB;
-                break;
-            case PSA_ALG_OFB:
-                mode = MBEDTLS_MODE_OFB;
-                break;
-            case PSA_ALG_ECB_NO_PADDING:
-                mode = MBEDTLS_MODE_ECB;
-                break;
-            case PSA_ALG_CBC_NO_PADDING:
-                mode = MBEDTLS_MODE_CBC;
-                break;
-            case PSA_ALG_CBC_PKCS7:
-                mode = MBEDTLS_MODE_CBC;
-                break;
-            case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 0 ):
-                mode = MBEDTLS_MODE_CCM;
-                break;
-            case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 0 ):
-                mode = MBEDTLS_MODE_GCM;
-                break;
-            case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CHACHA20_POLY1305, 0 ):
-                mode = MBEDTLS_MODE_CHACHAPOLY;
-                break;
-            default:
-                return( NULL );
-        }
-    }
-    else if( alg == PSA_ALG_CMAC )
-        mode = MBEDTLS_MODE_ECB;
-    else
-        return( NULL );
-
-    switch( key_type )
-    {
-        case PSA_KEY_TYPE_AES:
-            cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
-            break;
-        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;
-        case PSA_KEY_TYPE_CAMELLIA:
-            cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;
-            break;
-        case PSA_KEY_TYPE_ARC4:
-            cipher_id_tmp = MBEDTLS_CIPHER_ID_ARC4;
-            break;
-        case PSA_KEY_TYPE_CHACHA20:
-            cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
-            break;
-        default:
-            return( NULL );
-    }
-    if( cipher_id != NULL )
-        *cipher_id = cipher_id_tmp;
-
-    return( mbedtls_cipher_info_from_values( cipher_id_tmp,
-                                             (int) key_bits, mode ) );
-}
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
-static size_t psa_get_hash_block_size( psa_algorithm_t alg )
-{
-    switch( alg )
-    {
-        case PSA_ALG_MD2:
-            return( 16 );
-        case PSA_ALG_MD4:
-            return( 64 );
-        case PSA_ALG_MD5:
-            return( 64 );
-        case PSA_ALG_RIPEMD160:
-            return( 64 );
-        case PSA_ALG_SHA_1:
-            return( 64 );
-        case PSA_ALG_SHA_224:
-            return( 64 );
-        case PSA_ALG_SHA_256:
-            return( 64 );
-        case PSA_ALG_SHA_384:
-            return( 128 );
-        case PSA_ALG_SHA_512:
-            return( 128 );
-        default:
-            return( 0 );
-    }
-}
-#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) */
-
-/* Initialize the MAC operation structure. Once this function has been
- * called, psa_mac_abort can run and will do the right thing. */
-static psa_status_t psa_mac_init( psa_mac_operation_t *operation,
-                                  psa_algorithm_t alg )
-{
-    psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
-
-    operation->alg = alg;
-    operation->key_set = 0;
-    operation->iv_set = 0;
-    operation->iv_required = 0;
-    operation->has_input = 0;
-    operation->is_sign = 0;
-
-#if defined(MBEDTLS_CMAC_C)
-    if( alg == PSA_ALG_CMAC )
-    {
-        operation->iv_required = 0;
-        mbedtls_cipher_init( &operation->ctx.cmac );
-        status = PSA_SUCCESS;
-    }
-    else
-#endif /* MBEDTLS_CMAC_C */
-#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.hash_ctx.alg = 0;
-        status = PSA_SUCCESS;
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
-    {
-        if( ! PSA_ALG_IS_MAC( alg ) )
-            status = PSA_ERROR_INVALID_ARGUMENT;
-    }
-
-    if( status != PSA_SUCCESS )
-        memset( operation, 0, sizeof( *operation ) );
-    return( status );
-}
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
-static psa_status_t psa_hmac_abort_internal( psa_hmac_internal_data *hmac )
-{
-    mbedtls_platform_zeroize( hmac->opad, sizeof( hmac->opad ) );
-    return( psa_hash_abort( &hmac->hash_ctx ) );
-}
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
-
 psa_status_t psa_mac_abort( 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. */
+    /* Aborting a non-active operation is allowed */
+    if( operation->id == 0 )
         return( PSA_SUCCESS );
-    }
-    else
-#if defined(MBEDTLS_CMAC_C)
-    if( operation->alg == PSA_ALG_CMAC )
-    {
-        mbedtls_cipher_free( &operation->ctx.cmac );
-    }
-    else
-#endif /* MBEDTLS_CMAC_C */
-#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;
-    operation->key_set = 0;
-    operation->iv_set = 0;
-    operation->iv_required = 0;
-    operation->has_input = 0;
+    psa_status_t status = psa_driver_wrapper_mac_abort( operation );
+    operation->mac_size = 0;
     operation->is_sign = 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 );
-}
-
-#if defined(MBEDTLS_CMAC_C)
-static int psa_cmac_setup( psa_mac_operation_t *operation,
-                           size_t key_bits,
-                           psa_key_slot_t *slot,
-                           const mbedtls_cipher_info_t *cipher_info )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    operation->mac_size = cipher_info->block_size;
-
-    ret = mbedtls_cipher_setup( &operation->ctx.cmac, cipher_info );
-    if( ret != 0 )
-        return( ret );
-
-    ret = mbedtls_cipher_cmac_starts( &operation->ctx.cmac,
-                                      slot->data.key.data,
-                                      key_bits );
-    return( ret );
-}
-#endif /* MBEDTLS_CMAC_C */
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
-static psa_status_t psa_hmac_setup_internal( psa_hmac_internal_data *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_SIZE( hash_alg );
-    size_t block_size = psa_get_hash_block_size( hash_alg );
-    psa_status_t status;
-
-    /* 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 ) );
+    operation->id = 0;
 
     return( status );
 }
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
+
+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 );
+    }
+
+    return( PSA_SUCCESS );
+}
 
 static psa_status_t psa_mac_setup( psa_mac_operation_t *operation,
                                    mbedtls_svc_key_id_t key,
@@ -3276,115 +2381,54 @@
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
-    psa_key_slot_t *slot;
-    size_t key_bits;
-    psa_key_usage_t usage =
-        is_sign ? PSA_KEY_USAGE_SIGN_HASH : PSA_KEY_USAGE_VERIFY_HASH;
-    uint8_t truncated = PSA_MAC_TRUNCATED_LENGTH( alg );
-    psa_algorithm_t full_length_alg = PSA_ALG_FULL_LENGTH_MAC( alg );
+    psa_key_slot_t *slot = NULL;
 
     /* A context must be freshly initialized before it can be set up. */
-    if( operation->alg != 0 )
+    if( operation->id != 0 )
     {
-        return( PSA_ERROR_BAD_STATE );
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
     }
 
-    status = psa_mac_init( operation, full_length_alg );
-    if( status != PSA_SUCCESS )
-        return( status );
-    if( is_sign )
-        operation->is_sign = 1;
-
-    status = psa_get_and_lock_transparent_key_slot_with_policy(
-                 key, &slot, usage, alg );
+    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;
-    key_bits = psa_get_key_slot_bits( slot );
 
-#if defined(MBEDTLS_CMAC_C)
-    if( full_length_alg == PSA_ALG_CMAC )
+    psa_key_attributes_t attributes = {
+        .core = slot->attr
+    };
+
+    status = psa_mac_finalize_alg_and_key_validation( alg, &attributes,
+                                                      &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 )
     {
-        const mbedtls_cipher_info_t *cipher_info =
-            mbedtls_cipher_info_from_psa( full_length_alg,
-                                          slot->attr.type, key_bits, NULL );
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        if( cipher_info == NULL )
-        {
-            status = PSA_ERROR_NOT_SUPPORTED;
-            goto exit;
-        }
-        operation->mac_size = cipher_info->block_size;
-        ret = psa_cmac_setup( operation, key_bits, slot, cipher_info );
-        status = mbedtls_to_psa_error( ret );
+        status = psa_driver_wrapper_mac_sign_setup( operation,
+                                                    &attributes,
+                                                    slot->key.data,
+                                                    slot->key.bytes,
+                                                    alg );
     }
     else
-#endif /* MBEDTLS_CMAC_C */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
-    if( PSA_ALG_IS_HMAC( full_length_alg ) )
     {
-        psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH( alg );
-        if( hash_alg == 0 )
-        {
-            status = PSA_ERROR_NOT_SUPPORTED;
-            goto exit;
-        }
-
-        operation->mac_size = PSA_HASH_SIZE( hash_alg );
-        /* Sanity check. This shouldn't fail on a valid configuration. */
-        if( operation->mac_size == 0 ||
-            operation->mac_size > sizeof( operation->ctx.hmac.opad ) )
-        {
-            status = PSA_ERROR_NOT_SUPPORTED;
-            goto exit;
-        }
-
-        if( slot->attr.type != PSA_KEY_TYPE_HMAC )
-        {
-            status = PSA_ERROR_INVALID_ARGUMENT;
-            goto exit;
-        }
-
-        status = psa_hmac_setup_internal( &operation->ctx.hmac,
-                                          slot->data.key.data,
-                                          slot->data.key.bytes,
-                                          hash_alg );
+        status = psa_driver_wrapper_mac_verify_setup( operation,
+                                                      &attributes,
+                                                      slot->key.data,
+                                                      slot->key.bytes,
+                                                      alg );
     }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
-    {
-        (void) key_bits;
-        status = PSA_ERROR_NOT_SUPPORTED;
-    }
-
-    if( truncated == 0 )
-    {
-        /* The "normal" case: untruncated algorithm. Nothing to do. */
-    }
-    else if( truncated < 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. */
-        status = PSA_ERROR_NOT_SUPPORTED;
-    }
-    else if( truncated > operation->mac_size )
-    {
-        /* It's impossible to "truncate" to a larger length. */
-        status = PSA_ERROR_INVALID_ARGUMENT;
-    }
-    else
-        operation->mac_size = truncated;
 
 exit:
     if( status != PSA_SUCCESS )
-    {
         psa_mac_abort( operation );
-    }
-    else
-    {
-        operation->key_set = 1;
-    }
 
     unlock_status = psa_unlock_key_slot( slot );
 
@@ -3409,590 +2453,321 @@
                              const uint8_t *input,
                              size_t input_length )
 {
-    psa_status_t status = PSA_ERROR_BAD_STATE;
-    if( ! operation->key_set )
+    if( operation->id == 0 )
         return( PSA_ERROR_BAD_STATE );
-    if( operation->iv_required && ! operation->iv_set )
-        return( PSA_ERROR_BAD_STATE );
-    operation->has_input = 1;
 
-#if defined(MBEDTLS_CMAC_C)
-    if( operation->alg == PSA_ALG_CMAC )
-    {
-        int ret = mbedtls_cipher_cmac_update( &operation->ctx.cmac,
-                                              input, input_length );
-        status = mbedtls_to_psa_error( ret );
-    }
-    else
-#endif /* MBEDTLS_CMAC_C */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
-    if( PSA_ALG_IS_HMAC( operation->alg ) )
-    {
-        status = psa_hash_update( &operation->ctx.hmac.hash_ctx, input,
-                                  input_length );
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
-    {
-        /* This shouldn't happen if `operation` was initialized by
-         * a setup function. */
-        return( PSA_ERROR_BAD_STATE );
-    }
+    /* 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 );
 
+    psa_status_t status = psa_driver_wrapper_mac_update( operation,
+                                                         input, input_length );
     if( status != PSA_SUCCESS )
         psa_mac_abort( operation );
+
     return( status );
 }
 
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
-static psa_status_t psa_hmac_finish_internal( psa_hmac_internal_data *hmac,
-                                              uint8_t *mac,
-                                              size_t mac_size )
-{
-    uint8_t tmp[MBEDTLS_MD_MAX_SIZE];
-    psa_algorithm_t hash_alg = hmac->hash_ctx.alg;
-    size_t hash_size = 0;
-    size_t block_size = psa_get_hash_block_size( 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 */
-
-static psa_status_t psa_mac_finish_internal( psa_mac_operation_t *operation,
-                                             uint8_t *mac,
-                                             size_t mac_size )
-{
-    if( ! operation->key_set )
-        return( PSA_ERROR_BAD_STATE );
-    if( operation->iv_required && ! operation->iv_set )
-        return( PSA_ERROR_BAD_STATE );
-
-    if( mac_size < operation->mac_size )
-        return( PSA_ERROR_BUFFER_TOO_SMALL );
-
-#if defined(MBEDTLS_CMAC_C)
-    if( operation->alg == PSA_ALG_CMAC )
-    {
-        uint8_t tmp[PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE];
-        int ret = mbedtls_cipher_cmac_finish( &operation->ctx.cmac, tmp );
-        if( ret == 0 )
-            memcpy( mac, tmp, operation->mac_size );
-        mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
-        return( mbedtls_to_psa_error( ret ) );
-    }
-    else
-#endif /* MBEDTLS_CMAC_C */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
-    if( PSA_ALG_IS_HMAC( operation->alg ) )
-    {
-        return( psa_hmac_finish_internal( &operation->ctx.hmac,
-                                          mac, operation->mac_size ) );
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
-    {
-        /* This shouldn't happen if `operation` was initialized by
-         * a setup function. */
-        return( PSA_ERROR_BAD_STATE );
-    }
-}
-
 psa_status_t psa_mac_sign_finish( psa_mac_operation_t *operation,
                                   uint8_t *mac,
                                   size_t mac_size,
                                   size_t *mac_length )
 {
-    psa_status_t status;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
 
-    if( operation->alg == 0 )
+    if( operation->id == 0 )
     {
-        return( PSA_ERROR_BAD_STATE );
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
     }
 
-    /* Fill the output buffer with something that isn't a valid mac
-     * (barring an attack on the mac and deliberately-crafted input),
-     * in case the caller doesn't check the return status properly. */
-    *mac_length = mac_size;
-    /* If mac_size is 0 then mac may be NULL and then the
-     * call to memset would have undefined behavior. */
-    if( mac_size != 0 )
-        memset( mac, '!', mac_size );
-
     if( ! operation->is_sign )
     {
-        return( PSA_ERROR_BAD_STATE );
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
     }
 
-    status = psa_mac_finish_internal( operation, mac, mac_size );
-
-    if( status == PSA_SUCCESS )
+    /* 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_mac_abort( operation );
-        if( status == PSA_SUCCESS )
-            *mac_length = operation->mac_size;
-        else
-            memset( mac, '!', mac_size );
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
     }
-    else
-        psa_mac_abort( operation );
-    return( status );
+
+    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_size > operation->mac_size )
+        memset( &mac[operation->mac_size], '!',
+                mac_size - operation->mac_size );
+
+    abort_status = psa_mac_abort( operation );
+
+    return( status == PSA_SUCCESS ? abort_status : status );
 }
 
 psa_status_t psa_mac_verify_finish( 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_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
 
-    if( operation->alg == 0 )
+    if( operation->id == 0 )
     {
-        return( PSA_ERROR_BAD_STATE );
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
     }
 
     if( operation->is_sign )
     {
-        return( PSA_ERROR_BAD_STATE );
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
     }
+
     if( operation->mac_size != mac_length )
     {
         status = PSA_ERROR_INVALID_SIGNATURE;
-        goto cleanup;
+        goto exit;
     }
 
-    status = psa_mac_finish_internal( operation,
-                                      actual_mac, sizeof( actual_mac ) );
-    if( status != PSA_SUCCESS )
-        goto cleanup;
+    status = psa_driver_wrapper_mac_verify_finish( operation,
+                                                   mac, mac_length );
 
-    if( safer_memcmp( mac, actual_mac, mac_length ) != 0 )
-        status = PSA_ERROR_INVALID_SIGNATURE;
+exit:
+    abort_status = psa_mac_abort( operation );
 
-cleanup:
-    if( status == PSA_SUCCESS )
-        status = psa_mac_abort( operation );
-    else
-        psa_mac_abort( operation );
-
-    mbedtls_platform_zeroize( actual_mac, sizeof( actual_mac ) );
-
-    return( status );
+    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;
+
+    psa_key_attributes_t attributes = {
+        .core = slot->attr
+    };
+
+    status = psa_mac_finalize_alg_and_key_validation( alg, &attributes,
+                                                      &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(
+                 &attributes,
+                 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;
+    }
+    if( mac_size > operation_mac_size )
+        memset( &mac[operation_mac_size], '!', mac_size - operation_mac_size );
+
+    unlock_status = psa_unlock_key_slot( 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,
+                              size_t input_length,
+                              uint8_t *mac,
+                              size_t mac_size,
+                              size_t *mac_length)
+{
+    return( psa_mac_compute_internal( key, alg,
+                                      input, input_length,
+                                      mac, mac_size, mac_length, 1 ) );
+}
+
+psa_status_t psa_mac_verify( mbedtls_svc_key_id_t key,
+                             psa_algorithm_t alg,
+                             const uint8_t *input,
+                             size_t input_length,
+                             const uint8_t *mac,
+                             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;
+
+    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;
+    }
+    if( mbedtls_psa_safer_memcmp( mac, actual_mac, actual_mac_length ) != 0 )
+    {
+        status = PSA_ERROR_INVALID_SIGNATURE;
+        goto exit;
+    }
+
+exit:
+    mbedtls_platform_zeroize( actual_mac, sizeof( actual_mac ) );
+
+    return ( status );
+}
 
 /****************************************************************/
 /* Asymmetric cryptography */
 /****************************************************************/
 
-#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 )
+static psa_status_t psa_sign_verify_check_alg( int input_is_message,
+                                               psa_algorithm_t alg )
 {
-    psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
-    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg );
-    *md_alg = mbedtls_md_get_type( md_info );
-
-    /* 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
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
-    /* For PKCS#1 v1.5 signature, if using a hash, the hash length
-     * must be correct. */
-    if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) &&
-        alg != PSA_ALG_RSA_PKCS1V15_SIGN_RAW )
+    if( input_is_message )
     {
-        if( md_info == NULL )
-            return( PSA_ERROR_NOT_SUPPORTED );
-        if( mbedtls_md_get_size( md_info ) != hash_length )
+        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 );
     }
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
-    /* PSS requires a hash internally. */
-    if( PSA_ALG_IS_RSA_PSS( alg ) )
-    {
-        if( md_info == NULL )
-            return( PSA_ERROR_NOT_SUPPORTED );
-    }
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
 
     return( PSA_SUCCESS );
 }
 
-static psa_status_t psa_rsa_sign( mbedtls_rsa_context *rsa,
-                                  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;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_md_type_t md_alg;
-
-    status = psa_rsa_decode_md_type( alg, hash_length, &md_alg );
-    if( status != PSA_SUCCESS )
-        return( status );
-
-    if( signature_size < mbedtls_rsa_get_len( rsa ) )
-        return( PSA_ERROR_BUFFER_TOO_SMALL );
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
-    if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) )
-    {
-        mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15,
-                                 MBEDTLS_MD_NONE );
-        ret = mbedtls_rsa_pkcs1_sign( rsa,
-                                      mbedtls_ctr_drbg_random,
-                                      &global_data.ctr_drbg,
-                                      MBEDTLS_RSA_PRIVATE,
-                                      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 ) )
-    {
-        mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg );
-        ret = mbedtls_rsa_rsassa_pss_sign( rsa,
-                                           mbedtls_ctr_drbg_random,
-                                           &global_data.ctr_drbg,
-                                           MBEDTLS_RSA_PRIVATE,
-                                           MBEDTLS_MD_NONE,
-                                           (unsigned int) hash_length,
-                                           hash,
-                                           signature );
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
-    {
-        return( PSA_ERROR_INVALID_ARGUMENT );
-    }
-
-    if( ret == 0 )
-        *signature_length = mbedtls_rsa_get_len( rsa );
-    return( mbedtls_to_psa_error( ret ) );
-}
-
-static psa_status_t psa_rsa_verify( mbedtls_rsa_context *rsa,
-                                    psa_algorithm_t alg,
-                                    const uint8_t *hash,
-                                    size_t hash_length,
-                                    const uint8_t *signature,
-                                    size_t signature_length )
-{
-    psa_status_t status;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_md_type_t md_alg;
-
-    status = psa_rsa_decode_md_type( alg, hash_length, &md_alg );
-    if( status != PSA_SUCCESS )
-        return( status );
-
-    if( signature_length != mbedtls_rsa_get_len( rsa ) )
-        return( PSA_ERROR_INVALID_SIGNATURE );
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
-    if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) )
-    {
-        mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15,
-                                 MBEDTLS_MD_NONE );
-        ret = mbedtls_rsa_pkcs1_verify( rsa,
-                                        mbedtls_ctr_drbg_random,
-                                        &global_data.ctr_drbg,
-                                        MBEDTLS_RSA_PUBLIC,
-                                        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 ) )
-    {
-        mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg );
-        ret = mbedtls_rsa_rsassa_pss_verify( rsa,
-                                             mbedtls_ctr_drbg_random,
-                                             &global_data.ctr_drbg,
-                                             MBEDTLS_RSA_PUBLIC,
-                                             MBEDTLS_MD_NONE,
-                                             (unsigned int) hash_length,
-                                             hash,
-                                             signature );
-    }
-    else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
-    {
-        return( PSA_ERROR_INVALID_ARGUMENT );
-    }
-
-    /* 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. */
-    if( ret == MBEDTLS_ERR_RSA_INVALID_PADDING )
-        return( PSA_ERROR_INVALID_SIGNATURE );
-    return( mbedtls_to_psa_error( ret ) );
-}
-#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
-        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
-/* `ecp` cannot be const because `ecp->grp` needs to be non-const
- * for mbedtls_ecdsa_sign() and mbedtls_ecdsa_sign_det()
- * (even though these functions don't modify it). */
-static psa_status_t psa_ecdsa_sign( mbedtls_ecp_keypair *ecp,
-                                    psa_algorithm_t alg,
-                                    const uint8_t *hash,
-                                    size_t hash_length,
-                                    uint8_t *signature,
-                                    size_t signature_size,
-                                    size_t *signature_length )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_mpi r, s;
-    size_t 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 defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
-    if( PSA_ALG_DSA_IS_DETERMINISTIC( alg ) )
-    {
-        psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
-        const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg );
-        mbedtls_md_type_t md_alg = mbedtls_md_get_type( md_info );
-        MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det_ext( &ecp->grp, &r, &s,
-                                                     &ecp->d, hash,
-                                                     hash_length, md_alg,
-                                                     mbedtls_ctr_drbg_random,
-                                                     &global_data.ctr_drbg ) );
-    }
-    else
-#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
-    {
-        (void) alg;
-        MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ecp->grp, &r, &s, &ecp->d,
-                                             hash, hash_length,
-                                             mbedtls_ctr_drbg_random,
-                                             &global_data.ctr_drbg ) );
-    }
-
-    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;
-    return( mbedtls_to_psa_error( ret ) );
-}
-
-static psa_status_t psa_ecdsa_verify( mbedtls_ecp_keypair *ecp,
-                                      const uint8_t *hash,
-                                      size_t hash_length,
-                                      const uint8_t *signature,
-                                      size_t signature_length )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_mpi r, s;
-    size_t curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits );
-    mbedtls_mpi_init( &r );
-    mbedtls_mpi_init( &s );
-
-    if( signature_length != 2 * curve_bytes )
-        return( PSA_ERROR_INVALID_SIGNATURE );
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r,
-                                              signature,
-                                              curve_bytes ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &s,
-                                              signature + curve_bytes,
-                                              curve_bytes ) );
-
-    /* Check whether the public part is loaded. If not, load it. */
-    if( mbedtls_ecp_is_zero( &ecp->Q ) )
-    {
-        MBEDTLS_MPI_CHK(
-            mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
-                             mbedtls_ctr_drbg_random, &global_data.ctr_drbg ) );
-    }
-
-    ret = mbedtls_ecdsa_verify( &ecp->grp, hash, hash_length,
-                                &ecp->Q, &r, &s );
-
-cleanup:
-    mbedtls_mpi_free( &r );
-    mbedtls_mpi_free( &s );
-    return( mbedtls_to_psa_error( ret ) );
-}
-#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
-        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
-
-psa_status_t psa_sign_hash( mbedtls_svc_key_id_t key,
-                            psa_algorithm_t alg,
-                            const uint8_t *hash,
-                            size_t hash_length,
-                            uint8_t *signature,
-                            size_t signature_size,
-                            size_t *signature_length )
+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 = signature_size;
+    *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 hash
+     * 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,
-                                                    PSA_KEY_USAGE_SIGN_HASH,
-                                                    alg );
+    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;
     }
 
-    /* Try any of the available accelerators first */
-    status = psa_driver_wrapper_sign_hash( slot,
-                                           alg,
-                                           hash,
-                                           hash_length,
-                                           signature,
-                                           signature_size,
-                                           signature_length );
-    if( status != PSA_ERROR_NOT_SUPPORTED ||
-        psa_key_lifetime_is_external( slot->attr.lifetime ) )
-        goto exit;
+    psa_key_attributes_t attributes = {
+      .core = slot->attr
+    };
 
-    /* If the operation was not supported by any accelerator, try fallback. */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
-    if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR )
+    if( input_is_message )
     {
-        mbedtls_rsa_context *rsa = NULL;
-
-        status = psa_load_rsa_representation( slot->attr.type,
-                                              slot->data.key.data,
-                                              slot->data.key.bytes,
-                                              &rsa );
-        if( status != PSA_SUCCESS )
-            goto exit;
-
-        status = psa_rsa_sign( rsa,
-                               alg,
-                               hash, hash_length,
-                               signature, signature_size,
-                               signature_length );
-
-        mbedtls_rsa_free( rsa );
-        mbedtls_free( rsa );
-    }
-    else
-#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
-        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */
-    if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) )
-    {
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
-        if(
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
-            PSA_ALG_IS_ECDSA( alg )
-#else
-            PSA_ALG_IS_RANDOMIZED_ECDSA( alg )
-#endif
-            )
-        {
-            mbedtls_ecp_keypair *ecp = NULL;
-            status = psa_load_ecp_representation( slot->attr.type,
-                                                  slot->data.key.data,
-                                                  slot->data.key.bytes,
-                                                  &ecp );
-            if( status != PSA_SUCCESS )
-                goto exit;
-            status = psa_ecdsa_sign( ecp,
-                                     alg,
-                                     hash, hash_length,
-                                     signature, signature_size,
-                                     signature_length );
-            mbedtls_ecp_keypair_free( ecp );
-            mbedtls_free( ecp );
-        }
-        else
-#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
-        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
-        {
-            status = PSA_ERROR_INVALID_ARGUMENT;
-        }
+        status = psa_driver_wrapper_sign_message(
+            &attributes, slot->key.data, slot->key.bytes,
+            alg, input, input_length,
+            signature, signature_size, signature_length );
     }
     else
     {
-        status = PSA_ERROR_NOT_SUPPORTED;
+
+        status = psa_driver_wrapper_sign_hash(
+            &attributes, slot->key.data, slot->key.bytes,
+            alg, input, input_length,
+            signature, signature_size, signature_length );
     }
 
+
 exit:
     /* 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 mac
-     * (barring an attack on the mac and deliberately-crafted input),
+     * the trailing part on success) with something that isn't a valid signature
+     * (barring an attack on the signature and deliberately-crafted input),
      * in case the caller doesn't check the return status properly. */
     if( status == PSA_SUCCESS )
         memset( signature + *signature_length, '!',
@@ -4007,6 +2782,276 @@
     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 );
+
+    psa_key_attributes_t attributes = {
+      .core = slot->attr
+    };
+
+    if( input_is_message )
+    {
+        status = psa_driver_wrapper_verify_message(
+            &attributes, slot->key.data, slot->key.bytes,
+            alg, input, input_length,
+            signature, signature_length );
+    }
+    else
+    {
+        status = psa_driver_wrapper_verify_hash(
+            &attributes, slot->key.data, slot->key.bytes,
+            alg, input, input_length,
+            signature, signature_length );
+    }
+
+    unlock_status = psa_unlock_key_slot( 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,
+                               size_t input_length,
+                               uint8_t * signature,
+                               size_t signature_size,
+                               size_t * signature_length )
+{
+    return psa_sign_internal(
+        key, 1, alg, input, input_length,
+        signature, signature_size, signature_length );
+}
+
+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,
+                                 size_t input_length,
+                                 const uint8_t * signature,
+                                 size_t signature_length )
+{
+    return psa_verify_internal(
+        key, 1, alg, input, input_length,
+        signature, signature_length );
+}
+
+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->core.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->core.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,
+                            size_t hash_length,
+                            uint8_t *signature,
+                            size_t signature_size,
+                            size_t *signature_length )
+{
+    return psa_sign_internal(
+        key, 0, alg, hash, hash_length,
+        signature, signature_size, signature_length );
+}
+
+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->core.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->core.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,
@@ -4014,88 +3059,9 @@
                               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_get_and_lock_key_slot_with_policy( key, &slot,
-                                                    PSA_KEY_USAGE_VERIFY_HASH,
-                                                    alg );
-    if( status != PSA_SUCCESS )
-        return( status );
-
-    /* Try any of the available accelerators first */
-    status = psa_driver_wrapper_verify_hash( slot,
-                                             alg,
-                                             hash,
-                                             hash_length,
-                                             signature,
-                                             signature_length );
-    if( status != PSA_ERROR_NOT_SUPPORTED ||
-        psa_key_lifetime_is_external( slot->attr.lifetime ) )
-        goto exit;
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
-    if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
-    {
-        mbedtls_rsa_context *rsa = NULL;
-
-        status = psa_load_rsa_representation( slot->attr.type,
-                                              slot->data.key.data,
-                                              slot->data.key.bytes,
-                                              &rsa );
-        if( status != PSA_SUCCESS )
-            goto exit;
-
-        status = psa_rsa_verify( rsa,
-                                 alg,
-                                 hash, hash_length,
-                                 signature, signature_length );
-        mbedtls_rsa_free( rsa );
-        mbedtls_free( rsa );
-        goto exit;
-    }
-    else
-#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
-        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */
-    if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) )
-    {
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
-        if( PSA_ALG_IS_ECDSA( alg ) )
-        {
-            mbedtls_ecp_keypair *ecp = NULL;
-            status = psa_load_ecp_representation( slot->attr.type,
-                                                  slot->data.key.data,
-                                                  slot->data.key.bytes,
-                                                  &ecp );
-            if( status != PSA_SUCCESS )
-                goto exit;
-            status = psa_ecdsa_verify( ecp,
-                                       hash, hash_length,
-                                       signature, signature_length );
-            mbedtls_ecp_keypair_free( ecp );
-            mbedtls_free( ecp );
-            goto exit;
-        }
-        else
-#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
-        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
-        {
-            status =  PSA_ERROR_INVALID_ARGUMENT;
-            goto exit;
-        }
-    }
-    else
-    {
-        status = PSA_ERROR_NOT_SUPPORTED;
-    }
-
-exit:
-    unlock_status = psa_unlock_key_slot( slot );
-
-    return( ( status == PSA_SUCCESS ) ? unlock_status : status );
+    return psa_verify_internal(
+        key, 0, alg, hash, hash_length,
+        signature, signature_length );
 }
 
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
@@ -4145,15 +3111,15 @@
         goto exit;
     }
 
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
     if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
     {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
         mbedtls_rsa_context *rsa = NULL;
-        status = psa_load_rsa_representation( slot->attr.type,
-                                              slot->data.key.data,
-                                              slot->data.key.bytes,
-                                              &rsa );
+        status = mbedtls_psa_rsa_load_representation( slot->attr.type,
+                                                      slot->key.data,
+                                                      slot->key.bytes,
+                                                      &rsa );
         if( status != PSA_SUCCESS )
             goto rsa_exit;
 
@@ -4162,50 +3128,57 @@
             status = PSA_ERROR_BUFFER_TOO_SMALL;
             goto rsa_exit;
         }
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT)
+#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_ctr_drbg_random,
-                                               &global_data.ctr_drbg,
+                                               mbedtls_psa_get_random,
+                                               MBEDTLS_PSA_RANDOM_STATE,
                                                MBEDTLS_RSA_PUBLIC,
                                                input_length,
                                                input,
                                                output ) );
+#else
+            status = PSA_ERROR_NOT_SUPPORTED;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */
         }
         else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
         if( PSA_ALG_IS_RSA_OAEP( alg ) )
         {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
             psa_rsa_oaep_set_padding_mode( alg, rsa );
             status = mbedtls_to_psa_error(
                 mbedtls_rsa_rsaes_oaep_encrypt( rsa,
-                                                mbedtls_ctr_drbg_random,
-                                                &global_data.ctr_drbg,
+                                                mbedtls_psa_get_random,
+                                                MBEDTLS_PSA_RANDOM_STATE,
                                                 MBEDTLS_RSA_PUBLIC,
                                                 salt, salt_length,
                                                 input_length,
                                                 input,
                                                 output ) );
+#else
+            status = PSA_ERROR_NOT_SUPPORTED;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */
         }
         else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */
         {
             status = PSA_ERROR_INVALID_ARGUMENT;
-            goto rsa_exit;
         }
+#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 );
-    }
-    else
 #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
         * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
+    }
+    else
     {
         status = PSA_ERROR_NOT_SUPPORTED;
     }
@@ -4251,15 +3224,15 @@
         goto exit;
     }
 
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
     if( slot->attr.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 = psa_load_rsa_representation( slot->attr.type,
-                                              slot->data.key.data,
-                                              slot->data.key.bytes,
-                                              &rsa );
+        status = mbedtls_psa_rsa_load_representation( slot->attr.type,
+                                                      slot->key.data,
+                                                      slot->key.bytes,
+                                                      &rsa );
         if( status != PSA_SUCCESS )
             goto exit;
 
@@ -4268,50 +3241,58 @@
             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 defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT)
         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_ctr_drbg_random,
-                                           &global_data.ctr_drbg,
+                                           mbedtls_psa_get_random,
+                                           MBEDTLS_PSA_RANDOM_STATE,
                                            MBEDTLS_RSA_PRIVATE,
                                            output_length,
                                            input,
                                            output,
                                            output_size ) );
+#else
+            status = PSA_ERROR_NOT_SUPPORTED;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */
         }
         else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
         if( PSA_ALG_IS_RSA_OAEP( alg ) )
         {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
             psa_rsa_oaep_set_padding_mode( alg, rsa );
             status = mbedtls_to_psa_error(
                 mbedtls_rsa_rsaes_oaep_decrypt( rsa,
-                                                mbedtls_ctr_drbg_random,
-                                                &global_data.ctr_drbg,
+                                                mbedtls_psa_get_random,
+                                                MBEDTLS_PSA_RANDOM_STATE,
                                                 MBEDTLS_RSA_PRIVATE,
                                                 salt, salt_length,
                                                 output_length,
                                                 input,
                                                 output,
                                                 output_size ) );
+#else
+            status = PSA_ERROR_NOT_SUPPORTED;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */
         }
         else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */
         {
             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 );
-    }
-    else
 #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
         * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
+    }
+    else
     {
         status = PSA_ERROR_NOT_SUPPORTED;
     }
@@ -4335,149 +3316,59 @@
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
-    int ret = 0;
-    psa_key_slot_t *slot;
-    size_t key_bits;
-    const mbedtls_cipher_info_t *cipher_info = NULL;
+    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->alg != 0 )
-        return( PSA_ERROR_BAD_STATE );
+    if( operation->id != 0 )
+    {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
 
-    /* The requested algorithm must be one that can be processed by cipher. */
     if( ! PSA_ALG_IS_CIPHER( alg ) )
-        return( PSA_ERROR_INVALID_ARGUMENT );
+    {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
 
-    /* Fetch key material from key storage. */
     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 alg. The alg member
+    /* 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 after resources have been allocated/initialized. */
-    operation->key_set = 0;
+     * so we only set it (in the driver wrapper) after resources have been
+     * allocated/initialized. */
     operation->iv_set = 0;
-    operation->mbedtls_in_use = 0;
-    operation->iv_size = 0;
-    operation->block_size = 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 );
+
+    psa_key_attributes_t attributes = {
+      .core = slot->attr
+    };
 
     /* Try doing the operation through a driver before using software fallback. */
     if( cipher_operation == MBEDTLS_ENCRYPT )
-        status = psa_driver_wrapper_cipher_encrypt_setup( &operation->ctx.driver,
-                                                          slot,
+        status = psa_driver_wrapper_cipher_encrypt_setup( operation,
+                                                          &attributes,
+                                                          slot->key.data,
+                                                          slot->key.bytes,
                                                           alg );
     else
-        status = psa_driver_wrapper_cipher_decrypt_setup( &operation->ctx.driver,
-                                                          slot,
+        status = psa_driver_wrapper_cipher_decrypt_setup( operation,
+                                                          &attributes,
+                                                          slot->key.data,
+                                                          slot->key.bytes,
                                                           alg );
 
-    if( status == PSA_SUCCESS )
-    {
-        /* Once the driver context is initialised, it needs to be freed using
-        * psa_cipher_abort. Indicate this through setting alg. */
-        operation->alg = alg;
-    }
-
-    if( status != PSA_ERROR_NOT_SUPPORTED ||
-        psa_key_lifetime_is_external( slot->attr.lifetime ) )
-        goto exit;
-
-    /* Proceed with initializing an mbed TLS cipher context if no driver is
-     * available for the given algorithm & key. */
-    mbedtls_cipher_init( &operation->ctx.cipher );
-
-    /* Once the cipher context is initialised, it needs to be freed using
-     * psa_cipher_abort. Indicate there is something to be freed through setting
-     * alg, and indicate the operation is being done using mbedtls crypto through
-     * setting mbedtls_in_use. */
-    operation->alg = alg;
-    operation->mbedtls_in_use = 1;
-
-    key_bits = psa_get_key_slot_bits( slot );
-    cipher_info = mbedtls_cipher_info_from_psa( alg, slot->attr.type, key_bits, NULL );
-    if( cipher_info == NULL )
-    {
-        status = PSA_ERROR_NOT_SUPPORTED;
-        goto exit;
-    }
-
-    ret = mbedtls_cipher_setup( &operation->ctx.cipher, cipher_info );
-    if( ret != 0 )
-        goto exit;
-
-#if defined(MBEDTLS_DES_C)
-    if( slot->attr.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, slot->data.key.data, 16 );
-        memcpy( keys + 16, slot->data.key.data, 8 );
-        ret = mbedtls_cipher_setkey( &operation->ctx.cipher,
-                                     keys,
-                                     192, cipher_operation );
-    }
-    else
-#endif
-    {
-        ret = mbedtls_cipher_setkey( &operation->ctx.cipher,
-                                     slot->data.key.data,
-                                     (int) key_bits, cipher_operation );
-    }
-    if( ret != 0 )
-        goto exit;
-
-#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
-    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_CIPHER_MODE_WITH_PADDING
-
-    operation->block_size = ( PSA_ALG_IS_STREAM_CIPHER( alg ) ? 1 :
-                              PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->attr.type ) );
-    if( ( alg & PSA_ALG_CIPHER_FROM_BLOCK_FLAG ) != 0 &&
-        alg != PSA_ALG_ECB_NO_PADDING )
-    {
-        operation->iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->attr.type );
-    }
-#if defined(MBEDTLS_CHACHA20_C)
-    else
-    if( alg == PSA_ALG_STREAM_CIPHER && slot->attr.type == PSA_KEY_TYPE_CHACHA20 )
-        operation->iv_size = 12;
-#endif
-
-    status = PSA_SUCCESS;
-
 exit:
-    if( ret != 0 )
-        status = mbedtls_to_psa_error( ret );
-    if( status == PSA_SUCCESS )
-    {
-        /* Update operation flags for both driver and software implementations */
-        operation->key_set = 1;
-    }
-    else
+    if( status != PSA_SUCCESS )
         psa_cipher_abort( operation );
 
     unlock_status = psa_unlock_key_slot( slot );
@@ -4504,43 +3395,55 @@
                                      size_t iv_size,
                                      size_t *iv_length )
 {
-    psa_status_t status;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    if( operation->iv_set || ! operation->iv_required )
-    {
-        return( PSA_ERROR_BAD_STATE );
-    }
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE];
+    size_t default_iv_length;
 
-    if( operation->mbedtls_in_use == 0 )
+    if( operation->id == 0 )
     {
-        status = psa_driver_wrapper_cipher_generate_iv( &operation->ctx.driver,
-                                                        iv,
-                                                        iv_size,
-                                                        iv_length );
+        status = PSA_ERROR_BAD_STATE;
         goto exit;
     }
 
-    if( iv_size < operation->iv_size )
+    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;
     }
-    ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg,
-                                   iv, operation->iv_size );
-    if( ret != 0 )
+
+    if( default_iv_length > PSA_CIPHER_IV_MAX_SIZE )
     {
-        status = mbedtls_to_psa_error( ret );
+        status = PSA_ERROR_GENERIC_ERROR;
         goto exit;
     }
 
-    *iv_length = operation->iv_size;
-    status = psa_cipher_set_iv( operation, iv, *iv_length );
+    status = psa_generate_random( local_iv, default_iv_length );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    status = psa_driver_wrapper_cipher_set_iv( operation,
+                                               local_iv, default_iv_length );
 
 exit:
     if( status == PSA_SUCCESS )
+    {
+        memcpy( iv, local_iv, default_iv_length );
+        *iv_length = default_iv_length;
         operation->iv_set = 1;
+    }
     else
+    {
+        *iv_length = 0;
         psa_cipher_abort( operation );
+    }
+
     return( status );
 }
 
@@ -4548,28 +3451,30 @@
                                 const uint8_t *iv,
                                 size_t iv_length )
 {
-    psa_status_t status;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    if( operation->iv_set || ! operation->iv_required )
-    {
-        return( PSA_ERROR_BAD_STATE );
-    }
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 
-    if( operation->mbedtls_in_use == 0 )
+    if( operation->id == 0 )
     {
-        status = psa_driver_wrapper_cipher_set_iv( &operation->ctx.driver,
-                                                   iv,
-                                                   iv_length );
+        status = PSA_ERROR_BAD_STATE;
         goto exit;
     }
 
-    if( iv_length != operation->iv_size )
+    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;
     }
-    ret = mbedtls_cipher_set_iv( &operation->ctx.cipher, iv, iv_length );
-    status = mbedtls_to_psa_error( ret );
+
+    status = psa_driver_wrapper_cipher_set_iv( operation,
+                                               iv,
+                                               iv_length );
+
 exit:
     if( status == PSA_SUCCESS )
         operation->iv_set = 1;
@@ -4578,94 +3483,6 @@
     return( status );
 }
 
-/* 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. */
-static psa_status_t psa_cipher_update_ecb_internal(
-    mbedtls_cipher_context_t *ctx,
-    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 block_size = ctx->cipher_info->block_size;
-    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_size -= 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_size -= 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 );
-}
-
 psa_status_t psa_cipher_update( psa_cipher_operation_t *operation,
                                 const uint8_t *input,
                                 size_t input_length,
@@ -4674,69 +3491,30 @@
                                 size_t *output_length )
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    size_t expected_output_size;
-    if( operation->alg == 0 )
+
+    if( operation->id == 0 )
     {
-        return( PSA_ERROR_BAD_STATE );
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
     }
+
     if( operation->iv_required && ! operation->iv_set )
     {
-        return( PSA_ERROR_BAD_STATE );
-    }
-
-    if( operation->mbedtls_in_use == 0 )
-    {
-        status = psa_driver_wrapper_cipher_update( &operation->ctx.driver,
-                                                   input,
-                                                   input_length,
-                                                   output,
-                                                   output_size,
-                                                   output_length );
+        status = PSA_ERROR_BAD_STATE;
         goto exit;
     }
 
-    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_size * operation->block_size;
-    }
-    else
-    {
-        expected_output_size = input_length;
-    }
+    status = psa_driver_wrapper_cipher_update( operation,
+                                               input,
+                                               input_length,
+                                               output,
+                                               output_size,
+                                               output_length );
 
-    if( output_size < expected_output_size )
-    {
-        status = PSA_ERROR_BUFFER_TOO_SMALL;
-        goto exit;
-    }
-
-    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_internal( &operation->ctx.cipher,
-                                                 input,
-                                                 input_length,
-                                                 output,
-                                                 output_size,
-                                                 output_length );
-    }
-    else
-    {
-        status = mbedtls_to_psa_error(
-            mbedtls_cipher_update( &operation->ctx.cipher, input,
-                                   input_length, output, output_length ) );
-    }
 exit:
     if( status != PSA_SUCCESS )
         psa_cipher_abort( operation );
+
     return( status );
 }
 
@@ -4746,53 +3524,25 @@
                                 size_t *output_length )
 {
     psa_status_t status = PSA_ERROR_GENERIC_ERROR;
-    uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
-    if( operation->alg == 0 )
+
+    if( operation->id == 0 )
     {
-        return( PSA_ERROR_BAD_STATE );
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
     }
+
     if( operation->iv_required && ! operation->iv_set )
     {
-        return( PSA_ERROR_BAD_STATE );
-    }
-
-    if( operation->mbedtls_in_use == 0 )
-    {
-        status = psa_driver_wrapper_cipher_finish( &operation->ctx.driver,
-                                                   output,
-                                                   output_size,
-                                                   output_length );
+        status = PSA_ERROR_BAD_STATE;
         goto exit;
     }
 
-    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;
+    status = psa_driver_wrapper_cipher_finish( operation,
+                                               output,
+                                               output_size,
+                                               output_length );
 
 exit:
-    if( operation->mbedtls_in_use == 1 )
-        mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) );
-
     if( status == PSA_SUCCESS )
         return( psa_cipher_abort( operation ) );
     else
@@ -4806,7 +3556,7 @@
 
 psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation )
 {
-    if( operation->alg == 0 )
+    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
@@ -4814,186 +3564,143 @@
         return( PSA_SUCCESS );
     }
 
-    /* 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 );
+    psa_driver_wrapper_cipher_abort( operation );
 
-    if( operation->mbedtls_in_use == 0 )
-        psa_driver_wrapper_cipher_abort( &operation->ctx.driver );
-    else
-        mbedtls_cipher_free( &operation->ctx.cipher );
-
-    operation->alg = 0;
-    operation->key_set = 0;
+    operation->id = 0;
     operation->iv_set = 0;
-    operation->mbedtls_in_use = 0;
-    operation->iv_size = 0;
-    operation->block_size = 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,
+                                 size_t input_length,
+                                 uint8_t *output,
+                                 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;
 
+    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;
+
+    psa_key_attributes_t attributes = {
+      .core = slot->attr
+    };
+
+    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( local_iv, default_iv_length );
+        if( status != PSA_SUCCESS )
+            goto exit;
+    }
+
+    status = psa_driver_wrapper_cipher_encrypt(
+        &attributes, slot->key.data, slot->key.bytes,
+        alg, local_iv, default_iv_length, input, input_length,
+        output + default_iv_length, output_size - default_iv_length,
+        output_length );
+
+exit:
+    unlock_status = psa_unlock_key_slot( 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;
+
+    return( status );
+}
+
+psa_status_t psa_cipher_decrypt( mbedtls_svc_key_id_t key,
+                                 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_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot = NULL;
+
+    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;
+
+    psa_key_attributes_t attributes = {
+      .core = slot->attr
+    };
+
+    if( input_length < PSA_CIPHER_IV_LENGTH( slot->attr.type, alg ) )
+    {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_cipher_decrypt(
+        &attributes, slot->key.data, slot->key.bytes,
+        alg, input, input_length,
+        output, output_size, output_length );
+
+exit:
+    unlock_status = psa_unlock_key_slot( slot );
+    if( status == PSA_SUCCESS )
+        status = unlock_status;
+
+    if( status != PSA_SUCCESS )
+        *output_length = 0;
+
+    return( status );
+}
 
 
 /****************************************************************/
 /* AEAD */
 /****************************************************************/
 
-typedef struct
-{
-    psa_key_slot_t *slot;
-    const mbedtls_cipher_info_t *cipher_info;
-    union
-    {
-        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
-#if defined(MBEDTLS_CCM_C)
-        mbedtls_ccm_context ccm;
-#endif /* MBEDTLS_CCM_C */
-#if defined(MBEDTLS_GCM_C)
-        mbedtls_gcm_context gcm;
-#endif /* MBEDTLS_GCM_C */
-#if defined(MBEDTLS_CHACHAPOLY_C)
-        mbedtls_chachapoly_context chachapoly;
-#endif /* MBEDTLS_CHACHAPOLY_C */
-    } ctx;
-    psa_algorithm_t core_alg;
-    uint8_t full_tag_length;
-    uint8_t tag_length;
-} aead_operation_t;
-
-#define AEAD_OPERATION_INIT {0, 0, {0}, 0, 0, 0}
-
-static void psa_aead_abort_internal( aead_operation_t *operation )
-{
-    switch( operation->core_alg )
-    {
-#if defined(MBEDTLS_CCM_C)
-        case PSA_ALG_CCM:
-            mbedtls_ccm_free( &operation->ctx.ccm );
-            break;
-#endif /* MBEDTLS_CCM_C */
-#if defined(MBEDTLS_GCM_C)
-        case PSA_ALG_GCM:
-            mbedtls_gcm_free( &operation->ctx.gcm );
-            break;
-#endif /* MBEDTLS_GCM_C */
-    }
-
-    psa_unlock_key_slot( operation->slot );
-}
-
-static psa_status_t psa_aead_setup( aead_operation_t *operation,
-                                    mbedtls_svc_key_id_t key,
-                                    psa_key_usage_t usage,
-                                    psa_algorithm_t alg )
-{
-    psa_status_t status;
-    size_t key_bits;
-    mbedtls_cipher_id_t cipher_id;
-
-    status = psa_get_and_lock_transparent_key_slot_with_policy(
-                 key, &operation->slot, usage, alg );
-    if( status != PSA_SUCCESS )
-        return( status );
-
-    key_bits = psa_get_key_slot_bits( operation->slot );
-
-    operation->cipher_info =
-        mbedtls_cipher_info_from_psa( alg, operation->slot->attr.type, key_bits,
-                                      &cipher_id );
-    if( operation->cipher_info == NULL )
-    {
-        status = PSA_ERROR_NOT_SUPPORTED;
-        goto cleanup;
-    }
-
-    switch( PSA_ALG_AEAD_WITH_TAG_LENGTH( alg, 0 ) )
-    {
-#if defined(MBEDTLS_CCM_C)
-        case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 0 ):
-            operation->core_alg = PSA_ALG_CCM;
-            operation->full_tag_length = 16;
-            /* 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_SIZE( operation->slot->attr.type ) != 16 )
-            {
-                status = PSA_ERROR_INVALID_ARGUMENT;
-                goto cleanup;
-            }
-            mbedtls_ccm_init( &operation->ctx.ccm );
-            status = mbedtls_to_psa_error(
-                mbedtls_ccm_setkey( &operation->ctx.ccm, cipher_id,
-                                    operation->slot->data.key.data,
-                                    (unsigned int) key_bits ) );
-            if( status != 0 )
-                goto cleanup;
-            break;
-#endif /* MBEDTLS_CCM_C */
-
-#if defined(MBEDTLS_GCM_C)
-        case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 0 ):
-            operation->core_alg = PSA_ALG_GCM;
-            operation->full_tag_length = 16;
-            /* 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_SIZE( operation->slot->attr.type ) != 16 )
-            {
-                status = PSA_ERROR_INVALID_ARGUMENT;
-                goto cleanup;
-            }
-            mbedtls_gcm_init( &operation->ctx.gcm );
-            status = mbedtls_to_psa_error(
-                mbedtls_gcm_setkey( &operation->ctx.gcm, cipher_id,
-                                    operation->slot->data.key.data,
-                                    (unsigned int) key_bits ) );
-            if( status != 0 )
-                goto cleanup;
-            break;
-#endif /* MBEDTLS_GCM_C */
-
-#if defined(MBEDTLS_CHACHAPOLY_C)
-        case PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CHACHA20_POLY1305, 0 ):
-            operation->core_alg = PSA_ALG_CHACHA20_POLY1305;
-            operation->full_tag_length = 16;
-            /* We only support the default tag length. */
-            if( alg != PSA_ALG_CHACHA20_POLY1305 )
-            {
-                status = PSA_ERROR_NOT_SUPPORTED;
-                goto cleanup;
-            }
-            mbedtls_chachapoly_init( &operation->ctx.chachapoly );
-            status = mbedtls_to_psa_error(
-                mbedtls_chachapoly_setkey( &operation->ctx.chachapoly,
-                                           operation->slot->data.key.data ) );
-            if( status != 0 )
-                goto cleanup;
-            break;
-#endif /* MBEDTLS_CHACHAPOLY_C */
-
-        default:
-            status = PSA_ERROR_NOT_SUPPORTED;
-            goto cleanup;
-    }
-
-    if( PSA_AEAD_TAG_LENGTH( alg ) > operation->full_tag_length )
-    {
-        status = PSA_ERROR_INVALID_ARGUMENT;
-        goto cleanup;
-    }
-    operation->tag_length = PSA_AEAD_TAG_LENGTH( alg );
-
-    return( PSA_SUCCESS );
-
-cleanup:
-    psa_aead_abort_internal( operation );
-    return( status );
-}
-
 psa_status_t psa_aead_encrypt( mbedtls_svc_key_id_t key,
                                psa_algorithm_t alg,
                                const uint8_t *nonce,
@@ -5006,106 +3713,37 @@
                                size_t ciphertext_size,
                                size_t *ciphertext_length )
 {
-    psa_status_t status;
-    aead_operation_t operation = AEAD_OPERATION_INIT;
-    uint8_t *tag;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
 
     *ciphertext_length = 0;
 
-    status = psa_aead_setup( &operation, key, PSA_KEY_USAGE_ENCRYPT, alg );
+    if( !PSA_ALG_IS_AEAD( alg ) || PSA_ALG_IS_WILDCARD( alg ) )
+        return( PSA_ERROR_NOT_SUPPORTED );
+
+    status = psa_get_and_lock_key_slot_with_policy(
+                 key, &slot, PSA_KEY_USAGE_ENCRYPT, alg );
     if( status != PSA_SUCCESS )
         return( status );
 
-    /* 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;
+    psa_key_attributes_t attributes = {
+      .core = slot->attr
+    };
 
-#if defined(MBEDTLS_GCM_C)
-    if( operation.core_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_GCM_C */
-#if defined(MBEDTLS_CCM_C)
-    if( operation.core_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_CCM_C */
-#if defined(MBEDTLS_CHACHAPOLY_C)
-    if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 )
-    {
-        if( nonce_length != 12 || 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_CHACHAPOLY_C */
-    {
-        return( PSA_ERROR_NOT_SUPPORTED );
-    }
+    status = psa_driver_wrapper_aead_encrypt(
+        &attributes, 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:
-    psa_aead_abort_internal( &operation );
-    if( status == PSA_SUCCESS )
-        *ciphertext_length = plaintext_length + operation.tag_length;
-    return( status );
-}
+    psa_unlock_key_slot( slot );
 
-/* 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 );
+    return( status );
 }
 
 psa_status_t psa_aead_decrypt( mbedtls_svc_key_id_t key,
@@ -5120,86 +3758,39 @@
                                size_t plaintext_size,
                                size_t *plaintext_length )
 {
-    psa_status_t status;
-    aead_operation_t operation = AEAD_OPERATION_INIT;
-    const uint8_t *tag = NULL;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
 
     *plaintext_length = 0;
 
-    status = psa_aead_setup( &operation, key, PSA_KEY_USAGE_DECRYPT, alg );
+    if( !PSA_ALG_IS_AEAD( alg ) || PSA_ALG_IS_WILDCARD( alg ) )
+        return( PSA_ERROR_NOT_SUPPORTED );
+
+    status = psa_get_and_lock_key_slot_with_policy(
+                 key, &slot, PSA_KEY_USAGE_DECRYPT, alg );
     if( status != PSA_SUCCESS )
         return( status );
 
-    status = psa_aead_unpadded_locate_tag( operation.tag_length,
-                                           ciphertext, ciphertext_length,
-                                           plaintext_size, &tag );
-    if( status != PSA_SUCCESS )
-        goto exit;
+    psa_key_attributes_t attributes = {
+      .core = slot->attr
+    };
 
-#if defined(MBEDTLS_GCM_C)
-    if( operation.core_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_GCM_C */
-#if defined(MBEDTLS_CCM_C)
-    if( operation.core_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_CCM_C */
-#if defined(MBEDTLS_CHACHAPOLY_C)
-    if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 )
-    {
-        if( nonce_length != 12 || 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_CHACHAPOLY_C */
-    {
-        return( PSA_ERROR_NOT_SUPPORTED );
-    }
+    status = psa_driver_wrapper_aead_decrypt(
+        &attributes, 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:
-    psa_aead_abort_internal( &operation );
-    if( status == PSA_SUCCESS )
-        *plaintext_length = ciphertext_length - operation.tag_length;
+    psa_unlock_key_slot( slot );
+
     return( status );
 }
 
-
-
 /****************************************************************/
 /* Generators */
 /****************************************************************/
@@ -5208,7 +3799,35 @@
     defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
     defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
 #define AT_LEAST_ONE_BUILTIN_KDF
-#endif
+#endif /* At least one builtin KDF */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_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 */
@@ -5239,7 +3858,7 @@
     if( PSA_ALG_IS_HKDF( kdf_alg ) )
     {
         mbedtls_free( operation->ctx.hkdf.info );
-        status = psa_hmac_abort_internal( &operation->ctx.hkdf.hmac );
+        status = psa_mac_abort( &operation->ctx.hkdf.hmac );
     }
     else
 #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF */
@@ -5249,6 +3868,13 @@
              /* 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_platform_zeroize( operation->ctx.tls12_prf.secret,
+                                      operation->ctx.tls12_prf.secret_length );
+            mbedtls_free( operation->ctx.tls12_prf.secret );
+        }
+
         if( operation->ctx.tls12_prf.seed != NULL )
         {
             mbedtls_platform_zeroize( operation->ctx.tls12_prf.seed,
@@ -5263,7 +3889,7 @@
             mbedtls_free( operation->ctx.tls12_prf.label );
         }
 
-        status = psa_hmac_abort_internal( &operation->ctx.tls12_prf.hmac );
+        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. */
@@ -5306,11 +3932,12 @@
 /* Read some bytes from an HKDF-based operation. This performs a chunk
  * of the expand phase of the HKDF algorithm. */
 static psa_status_t psa_key_derivation_hkdf_read( psa_hkdf_key_derivation_t *hkdf,
-                                             psa_algorithm_t hash_alg,
-                                             uint8_t *output,
-                                             size_t output_length )
+                                                  psa_algorithm_t hash_alg,
+                                                  uint8_t *output,
+                                                  size_t output_length )
 {
-    uint8_t hash_length = PSA_HASH_SIZE( hash_alg );
+    uint8_t hash_length = PSA_HASH_LENGTH( hash_alg );
+    size_t hmac_output_length;
     psa_status_t status;
 
     if( hkdf->state < HKDF_STATE_KEYED || ! hkdf->info_set )
@@ -5340,31 +3967,35 @@
         /* We need a new block */
         ++hkdf->block_number;
         hkdf->offset_in_block = 0;
-        status = psa_hmac_setup_internal( &hkdf->hmac,
-                                          hkdf->prk, hash_length,
-                                          hash_alg );
+
+        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_hash_update( &hkdf->hmac.hash_ctx,
-                                      hkdf->output_block,
-                                      hash_length );
+            status = psa_mac_update( &hkdf->hmac,
+                                     hkdf->output_block,
+                                     hash_length );
             if( status != PSA_SUCCESS )
                 return( status );
         }
-        status = psa_hash_update( &hkdf->hmac.hash_ctx,
-                                  hkdf->info,
-                                  hkdf->info_length );
+        status = psa_mac_update( &hkdf->hmac,
+                                 hkdf->info,
+                                 hkdf->info_length );
         if( status != PSA_SUCCESS )
             return( status );
-        status = psa_hash_update( &hkdf->hmac.hash_ctx,
-                                  &hkdf->block_number, 1 );
+        status = psa_mac_update( &hkdf->hmac,
+                                 &hkdf->block_number, 1 );
         if( status != PSA_SUCCESS )
             return( status );
-        status = psa_hmac_finish_internal( &hkdf->hmac,
-                                           hkdf->output_block,
-                                           sizeof( hkdf->output_block ) );
+        status = psa_mac_sign_finish( &hkdf->hmac,
+                                      hkdf->output_block,
+                                      sizeof( hkdf->output_block ),
+                                      &hmac_output_length );
         if( status != PSA_SUCCESS )
             return( status );
     }
@@ -5380,8 +4011,9 @@
     psa_algorithm_t alg )
 {
     psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( alg );
-    uint8_t hash_length = PSA_HASH_SIZE( hash_alg );
-    psa_hash_operation_t backup = PSA_HASH_OPERATION_INIT;
+    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
@@ -5413,10 +4045,10 @@
      * `block_number`.
      */
 
-    /* Save the hash context before using it, to preserve the hash state with
-     * only the inner padding in it. We need this, because inner padding depends
-     * on the key (secret in the RFC's terminology). */
-    status = psa_hash_clone( &tls12_prf->hmac.hash_ctx, &backup );
+    status = psa_key_derivation_start_hmac( &hmac,
+                                            hash_alg,
+                                            tls12_prf->secret,
+                                            tls12_prf->secret_length );
     if( status != PSA_SUCCESS )
         goto cleanup;
 
@@ -5426,57 +4058,58 @@
         /* 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_hash_update( &tls12_prf->hmac.hash_ctx,
-                                  tls12_prf->label, tls12_prf->label_length );
+        status = psa_mac_update( &hmac,
+                                 tls12_prf->label,
+                                 tls12_prf->label_length );
         if( status != PSA_SUCCESS )
             goto cleanup;
-        status = psa_hash_update( &tls12_prf->hmac.hash_ctx,
-                                  tls12_prf->seed, tls12_prf->seed_length );
+        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_hash_update( &tls12_prf->hmac.hash_ctx,
-                                  tls12_prf->Ai, hash_length );
+        status = psa_mac_update( &hmac, tls12_prf->Ai, hash_length );
         if( status != PSA_SUCCESS )
             goto cleanup;
     }
 
-    status = psa_hmac_finish_internal( &tls12_prf->hmac,
-                                       tls12_prf->Ai, hash_length );
-    if( status != PSA_SUCCESS )
-        goto cleanup;
-    status = psa_hash_clone( &backup, &tls12_prf->hmac.hash_ctx );
+    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_hash_update( &tls12_prf->hmac.hash_ctx,
-                              tls12_prf->Ai, hash_length );
+    status = psa_key_derivation_start_hmac( &hmac,
+                                            hash_alg,
+                                            tls12_prf->secret,
+                                            tls12_prf->secret_length );
     if( status != PSA_SUCCESS )
         goto cleanup;
-    status = psa_hash_update( &tls12_prf->hmac.hash_ctx,
-                              tls12_prf->label, tls12_prf->label_length );
+    status = psa_mac_update( &hmac, tls12_prf->Ai, hash_length );
     if( status != PSA_SUCCESS )
         goto cleanup;
-    status = psa_hash_update( &tls12_prf->hmac.hash_ctx,
-                              tls12_prf->seed, tls12_prf->seed_length );
+    status = psa_mac_update( &hmac, tls12_prf->label, tls12_prf->label_length );
     if( status != PSA_SUCCESS )
         goto cleanup;
-    status = psa_hmac_finish_internal( &tls12_prf->hmac,
-                                       tls12_prf->output_block, hash_length );
+    status = psa_mac_update( &hmac, tls12_prf->seed, tls12_prf->seed_length );
     if( status != PSA_SUCCESS )
         goto cleanup;
-    status = psa_hash_clone( &backup, &tls12_prf->hmac.hash_ctx );
+    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_hash_abort( &backup );
+    cleanup_status = psa_mac_abort( &hmac );
     if( status == PSA_SUCCESS && cleanup_status != PSA_SUCCESS )
         status = cleanup_status;
 
@@ -5490,10 +4123,21 @@
     size_t output_length )
 {
     psa_algorithm_t hash_alg = PSA_ALG_TLS12_PRF_GET_HASH( alg );
-    uint8_t hash_length = PSA_HASH_SIZE( 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. */
@@ -5573,13 +4217,14 @@
         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 );
+                                                    kdf_alg, output,
+                                                    output_length );
     }
     else
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF ||
         * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
     {
+        (void) kdf_alg;
         return( PSA_ERROR_BAD_STATE );
     }
 
@@ -5598,7 +4243,7 @@
     return( status );
 }
 
-#if defined(MBEDTLS_DES_C)
+#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 )
@@ -5608,7 +4253,7 @@
     if( data_size >= 24 )
         mbedtls_des_key_set_parity( data + 16 );
 }
-#endif /* MBEDTLS_DES_C */
+#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */
 
 static psa_status_t psa_generate_derived_key_internal(
     psa_key_slot_t *slot,
@@ -5630,11 +4275,27 @@
     status = psa_key_derivation_output_bytes( operation, data, bytes );
     if( status != PSA_SUCCESS )
         goto exit;
-#if defined(MBEDTLS_DES_C)
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
     if( slot->attr.type == PSA_KEY_TYPE_DES )
         psa_des_set_key_parity( data, bytes );
-#endif /* MBEDTLS_DES_C */
-    status = psa_import_key_into_slot( slot, data, bytes );
+#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */
+
+    status = psa_allocate_buffer_to_slot( slot, bytes );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    slot->attr.bits = (psa_key_bits_t) bits;
+    psa_key_attributes_t attributes = {
+      .core = slot->attr
+    };
+
+    status = psa_driver_wrapper_import_key( &attributes,
+                                            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 );
@@ -5656,6 +4317,9 @@
     if( psa_get_key_bits( attributes ) == 0 )
         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 );
 
@@ -5688,7 +4352,7 @@
 /* Key derivation */
 /****************************************************************/
 
-#ifdef AT_LEAST_ONE_BUILTIN_KDF
+#if defined(AT_LEAST_ONE_BUILTIN_KDF)
 static psa_status_t psa_key_derivation_setup_kdf(
     psa_key_derivation_operation_t *operation,
     psa_algorithm_t kdf_alg )
@@ -5720,7 +4384,7 @@
     if( is_kdf_alg_supported )
     {
         psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( kdf_alg );
-        size_t hash_size = PSA_HASH_SIZE( hash_alg );
+        size_t hash_size = PSA_HASH_LENGTH( hash_alg );
         if( hash_size == 0 )
             return( PSA_ERROR_NOT_SUPPORTED );
         if( ( PSA_ALG_IS_TLS12_PRF( kdf_alg ) ||
@@ -5747,17 +4411,23 @@
 
     if( PSA_ALG_IS_RAW_KEY_AGREEMENT( alg ) )
         return( PSA_ERROR_INVALID_ARGUMENT );
-#ifdef AT_LEAST_ONE_BUILTIN_KDF
     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 );
         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 */
     }
-#endif
     else
         return( PSA_ERROR_INVALID_ARGUMENT );
 
@@ -5779,36 +4449,40 @@
         case PSA_KEY_DERIVATION_INPUT_SALT:
             if( hkdf->state != HKDF_STATE_INIT )
                 return( PSA_ERROR_BAD_STATE );
-            status = psa_hmac_setup_internal( &hkdf->hmac,
-                                              data, data_length,
-                                              hash_alg );
-            if( status != PSA_SUCCESS )
-                return( status );
-            hkdf->state = HKDF_STATE_STARTED;
-            return( PSA_SUCCESS );
+            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 no salt was provided, use an empty salt. */
             if( hkdf->state == HKDF_STATE_INIT )
             {
-                status = psa_hmac_setup_internal( &hkdf->hmac,
-                                                  NULL, 0,
-                                                  hash_alg );
+                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_hash_update( &hkdf->hmac.hash_ctx,
-                                      data, data_length );
+            status = psa_mac_update( &hkdf->hmac,
+                                     data, data_length );
             if( status != PSA_SUCCESS )
                 return( status );
-            status = psa_hmac_finish_internal( &hkdf->hmac,
-                                               hkdf->prk,
-                                               sizeof( hkdf->prk ) );
+            status = psa_mac_sign_finish( &hkdf->hmac,
+                                          hkdf->prk,
+                                          sizeof( hkdf->prk ),
+                                          &data_length );
             if( status != PSA_SUCCESS )
                 return( status );
-            hkdf->offset_in_block = PSA_HASH_SIZE( hash_alg );
+            hkdf->offset_in_block = PSA_HASH_LENGTH( hash_alg );
             hkdf->block_number = 0;
             hkdf->state = HKDF_STATE_KEYED;
             return( PSA_SUCCESS );
@@ -5839,7 +4513,7 @@
                                             const uint8_t *data,
                                             size_t data_length )
 {
-    if( prf->state != TLS12_PRF_STATE_INIT )
+    if( prf->state != PSA_TLS12_PRF_STATE_INIT )
         return( PSA_ERROR_BAD_STATE );
 
     if( data_length != 0 )
@@ -5852,25 +4526,29 @@
         prf->seed_length = data_length;
     }
 
-    prf->state = TLS12_PRF_STATE_SEED_SET;
+    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,
-                                           psa_algorithm_t hash_alg,
                                            const uint8_t *data,
                                            size_t data_length )
 {
-    psa_status_t status;
-    if( prf->state != TLS12_PRF_STATE_SEED_SET )
+    if( prf->state != PSA_TLS12_PRF_STATE_SEED_SET )
         return( PSA_ERROR_BAD_STATE );
 
-    status = psa_hmac_setup_internal( &prf->hmac, data, data_length, hash_alg );
-    if( status != PSA_SUCCESS )
-        return( status );
+    if( data_length != 0 )
+    {
+        prf->secret = mbedtls_calloc( 1, data_length );
+        if( prf->secret == NULL )
+            return( PSA_ERROR_INSUFFICIENT_MEMORY );
 
-    prf->state = TLS12_PRF_STATE_KEY_SET;
+        memcpy( prf->secret, data, data_length );
+        prf->secret_length = data_length;
+    }
+
+    prf->state = PSA_TLS12_PRF_STATE_KEY_SET;
 
     return( PSA_SUCCESS );
 }
@@ -5879,7 +4557,7 @@
                                              const uint8_t *data,
                                              size_t data_length )
 {
-    if( prf->state != TLS12_PRF_STATE_KEY_SET )
+    if( prf->state != PSA_TLS12_PRF_STATE_KEY_SET )
         return( PSA_ERROR_BAD_STATE );
 
     if( data_length != 0 )
@@ -5892,13 +4570,12 @@
         prf->label_length = data_length;
     }
 
-    prf->state = TLS12_PRF_STATE_LABEL_SET;
+    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_algorithm_t hash_alg,
                                          psa_key_derivation_step_t step,
                                          const uint8_t *data,
                                          size_t data_length )
@@ -5908,7 +4585,7 @@
         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, hash_alg, data, data_length ) );
+            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:
@@ -5921,15 +4598,14 @@
 #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,
-    psa_algorithm_t hash_alg,
     const uint8_t *data,
     size_t data_length )
 {
     psa_status_t status;
-    uint8_t pms[ 4 + 2 * PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN ];
+    uint8_t pms[ 4 + 2 * PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE ];
     uint8_t *cur = pms;
 
-    if( data_length > PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN )
+    if( data_length > PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
     /* Quoting RFC 4279, Section 2:
@@ -5939,8 +4615,8 @@
      * uint16 with the value N, and the PSK itself.
      */
 
-    *cur++ = ( data_length >> 8 ) & 0xff;
-    *cur++ = ( data_length >> 0 ) & 0xff;
+    *cur++ = MBEDTLS_BYTE_1( data_length );
+    *cur++ = MBEDTLS_BYTE_0( data_length );
     memset( cur, 0, data_length );
     cur += data_length;
     *cur++ = pms[0];
@@ -5948,7 +4624,7 @@
     memcpy( cur, data, data_length );
     cur += data_length;
 
-    status = psa_tls12_prf_set_key( prf, hash_alg, pms, cur - pms );
+    status = psa_tls12_prf_set_key( prf, pms, cur - pms );
 
     mbedtls_platform_zeroize( pms, sizeof( pms ) );
     return( status );
@@ -5956,18 +4632,17 @@
 
 static psa_status_t psa_tls12_prf_psk_to_ms_input(
     psa_tls12_prf_key_derivation_t *prf,
-    psa_algorithm_t hash_alg,
     psa_key_derivation_step_t step,
     const uint8_t *data,
     size_t data_length )
 {
     if( step == PSA_KEY_DERIVATION_INPUT_SECRET )
     {
-        return( psa_tls12_prf_psk_to_ms_set_key( prf, hash_alg,
+        return( psa_tls12_prf_psk_to_ms_set_key( prf,
                                                  data, data_length ) );
     }
 
-    return( psa_tls12_prf_input( prf, hash_alg, step, data, data_length ) );
+    return( psa_tls12_prf_input( prf, step, data, data_length ) );
 }
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
 
@@ -6032,7 +4707,6 @@
     if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) )
     {
         status = psa_tls12_prf_input( &operation->ctx.tls12_prf,
-                                      PSA_ALG_HKDF_GET_HASH( kdf_alg ),
                                       step, data, data_length );
     }
     else
@@ -6041,13 +4715,15 @@
     if( PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) )
     {
         status = psa_tls12_prf_psk_to_ms_input( &operation->ctx.tls12_prf,
-                                                PSA_ALG_HKDF_GET_HASH( kdf_alg ),
                                                 step, data, data_length );
     }
     else
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
     {
         /* This can't happen unless the operation object was not initialized */
+        (void) data;
+        (void) data_length;
+        (void) kdf_alg;
         return( PSA_ERROR_BAD_STATE );
     }
 
@@ -6092,8 +4768,8 @@
 
     status = psa_key_derivation_input_internal( operation,
                                                 step, slot->attr.type,
-                                                slot->data.key.data,
-                                                slot->data.key.bytes );
+                                                slot->key.data,
+                                                slot->key.bytes );
 
     unlock_status = psa_unlock_key_slot( slot );
 
@@ -6121,10 +4797,12 @@
     psa_ecc_family_t curve = mbedtls_ecc_group_to_psa( our_key->grp.id, &bits );
     mbedtls_ecdh_init( &ecdh );
 
-    status = psa_load_ecp_representation( PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve),
-                                          peer_key,
-                                          peer_key_length,
-                                          &their_key );
+    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;
 
@@ -6141,8 +4819,8 @@
         mbedtls_ecdh_calc_secret( &ecdh,
                                   shared_secret_length,
                                   shared_secret, shared_secret_size,
-                                  mbedtls_ctr_drbg_random,
-                                  &global_data.ctr_drbg ) );
+                                  mbedtls_psa_get_random,
+                                  MBEDTLS_PSA_RANDOM_STATE ) );
     if( status != PSA_SUCCESS )
         goto exit;
     if( PSA_BITS_TO_BYTES( bits ) != *shared_secret_length )
@@ -6176,11 +4854,12 @@
             if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( private_key->attr.type ) )
                 return( PSA_ERROR_INVALID_ARGUMENT );
             mbedtls_ecp_keypair *ecp = NULL;
-            psa_status_t status = psa_load_ecp_representation(
-                                    private_key->attr.type,
-                                    private_key->data.key.data,
-                                    private_key->data.key.bytes,
-                                    &ecp );
+            psa_status_t status = mbedtls_psa_ecp_load_representation(
+                                      private_key->attr.type,
+                                      private_key->attr.bits,
+                                      private_key->key.data,
+                                      private_key->key.bytes,
+                                      &ecp );
             if( status != PSA_SUCCESS )
                 return( status );
             status = psa_key_agreement_ecdh( peer_key, peer_key_length,
@@ -6320,31 +4999,139 @@
 }
 
 
+
 /****************************************************************/
 /* Random generation */
 /****************************************************************/
 
+/** Initialize the PSA random generator.
+ */
+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( MBEDTLS_PSA_RANDOM_STATE );
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+}
+
+/** Deinitialize the PSA random generator.
+ */
+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( MBEDTLS_PSA_RANDOM_STATE );
+    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->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,
                                   size_t output_size )
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     GUARD_MODULE_INITIALIZED;
 
-    while( output_size > MBEDTLS_CTR_DRBG_MAX_REQUEST )
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+
+    size_t output_length = 0;
+    psa_status_t 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 extrernal 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 )
     {
-        ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg,
-                                       output,
-                                       MBEDTLS_CTR_DRBG_MAX_REQUEST );
+        size_t request_size =
+            ( output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ?
+              MBEDTLS_PSA_RANDOM_MAX_REQUEST :
+              output_size );
+        int ret = mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
+                                          output, request_size );
         if( ret != 0 )
             return( mbedtls_to_psa_error( ret ) );
-        output += MBEDTLS_CTR_DRBG_MAX_REQUEST;
-        output_size -= MBEDTLS_CTR_DRBG_MAX_REQUEST;
+        output_size -= request_size;
+        output += request_size;
     }
-
-    ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg, output, output_size );
-    return( mbedtls_to_psa_error( ret ) );
+    return( PSA_SUCCESS );
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
 }
 
+/* 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.
+ *
+ * In the non-external case, psa_generate_random() calls an
+ * `mbedtls_xxx_drbg_random` function which has exactly the same signature
+ * and semantics as mbedtls_psa_get_random(). As an optimization,
+ * instead of doing this back-and-forth between the PSA API and the
+ * classic API, psa_crypto_random_impl.h defines `mbedtls_psa_get_random`
+ * as a constant function pointer to `mbedtls_xxx_drbg_random`.
+ */
+#if defined (MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+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_EXTERNAL_RNG */
+
 #if defined(MBEDTLS_PSA_INJECT_ENTROPY)
 #include "mbedtls/entropy_poll.h"
 
@@ -6363,167 +5150,109 @@
 }
 #endif /* MBEDTLS_PSA_INJECT_ENTROPY */
 
-#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR)
-static psa_status_t psa_read_rsa_exponent( const uint8_t *domain_parameters,
-                                           size_t domain_parameters_size,
-                                           int *exponent )
+/** 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 )
 {
-    size_t i;
-    uint32_t acc = 0;
-
-    if( domain_parameters_size == 0 )
-    {
-        *exponent = 65537;
-        return( PSA_SUCCESS );
-    }
-
-    /* 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( domain_parameters_size > sizeof( acc ) )
-        return( PSA_ERROR_NOT_SUPPORTED );
-    for( i = 0; i < domain_parameters_size; i++ )
-        acc = ( acc << 8 ) | domain_parameters[i];
-    if( acc > INT_MAX )
-        return( PSA_ERROR_NOT_SUPPORTED );
-    *exponent = acc;
-    return( PSA_SUCCESS );
-}
-#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) */
-
-static psa_status_t psa_generate_key_internal(
-    psa_key_slot_t *slot, size_t bits,
-    const uint8_t *domain_parameters, size_t domain_parameters_size )
-{
-    psa_key_type_t type = slot->attr.type;
-
-    if( domain_parameters == NULL && domain_parameters_size != 0 )
-        return( PSA_ERROR_INVALID_ARGUMENT );
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 
     if( key_type_is_raw_bytes( type ) )
     {
-        psa_status_t status;
-
-        status = validate_unstructured_key_bit_size( slot->attr.type, bits );
+        status = validate_unstructured_key_bit_size( type, bits );
         if( status != PSA_SUCCESS )
             return( status );
-
-        /* Allocate memory for the key */
-        status = psa_allocate_buffer_to_slot( slot, PSA_BITS_TO_BYTES( bits ) );
-        if( status != PSA_SUCCESS )
-            return( status );
-
-        status = psa_generate_random( slot->data.key.data,
-                                      slot->data.key.bytes );
-        if( status != PSA_SUCCESS )
-            return( status );
-
-        slot->attr.bits = (psa_key_bits_t) bits;
-#if defined(MBEDTLS_DES_C)
-        if( type == PSA_KEY_TYPE_DES )
-            psa_des_set_key_parity( slot->data.key.data,
-                                    slot->data.key.bytes );
-#endif /* MBEDTLS_DES_C */
     }
     else
-
-#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR)
-    if ( type == PSA_KEY_TYPE_RSA_KEY_PAIR )
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
+    if( PSA_KEY_TYPE_IS_RSA( type ) && PSA_KEY_TYPE_IS_KEY_PAIR( type ) )
     {
-        mbedtls_rsa_context rsa;
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        int exponent;
-        psa_status_t status;
         if( bits > PSA_VENDOR_RSA_MAX_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 );
-        status = psa_read_rsa_exponent( domain_parameters,
-                                        domain_parameters_size,
-                                        &exponent );
-        if( status != PSA_SUCCESS )
-            return( status );
-        mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE );
-        ret = mbedtls_rsa_gen_key( &rsa,
-                                   mbedtls_ctr_drbg_random,
-                                   &global_data.ctr_drbg,
-                                   (unsigned int) bits,
-                                   exponent );
-        if( ret != 0 )
-            return( mbedtls_to_psa_error( ret ) );
-
-        /* Make sure to always have an export representation available */
-        size_t bytes = PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE( bits );
-
-        status = psa_allocate_buffer_to_slot( slot, bytes );
-        if( status != PSA_SUCCESS )
-        {
-            mbedtls_rsa_free( &rsa );
-            return( status );
-        }
-
-        status = psa_export_rsa_key( type,
-                                     &rsa,
-                                     slot->data.key.data,
-                                     bytes,
-                                     &slot->data.key.bytes );
-        mbedtls_rsa_free( &rsa );
-        if( status != PSA_SUCCESS )
-            psa_remove_key_data_from_memory( slot );
-        return( status );
     }
     else
-#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) */
+#endif /* defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) */
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR)
+    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) */
+    {
+        return( PSA_ERROR_NOT_SUPPORTED );
+    }
+
+    return( PSA_SUCCESS );
+}
+
+psa_status_t psa_generate_key_internal(
+    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;
+    psa_key_type_t type = attributes->core.type;
+
+    if( ( attributes->domain_parameters == NULL ) &&
+        ( attributes->domain_parameters_size != 0 ) )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
+    if( key_type_is_raw_bytes( type ) )
+    {
+        status = psa_generate_random( 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) && \
+    defined(MBEDTLS_GENPRIME)
+    if ( type == PSA_KEY_TYPE_RSA_KEY_PAIR )
+    {
+        return( mbedtls_psa_rsa_generate_key( attributes,
+                                              key_buffer,
+                                              key_buffer_size,
+                                              key_buffer_length ) );
+    }
+    else
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR)
+        * defined(MBEDTLS_GENPRIME) */
 
 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR)
     if ( PSA_KEY_TYPE_IS_ECC( type ) && PSA_KEY_TYPE_IS_KEY_PAIR( type ) )
     {
-        psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( type );
-        mbedtls_ecp_group_id grp_id =
-            mbedtls_ecc_group_of_psa( curve, PSA_BITS_TO_BYTES( bits ) );
-        const mbedtls_ecp_curve_info *curve_info =
-            mbedtls_ecp_curve_info_from_grp_id( grp_id );
-        mbedtls_ecp_keypair ecp;
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        if( domain_parameters_size != 0 )
-            return( PSA_ERROR_NOT_SUPPORTED );
-        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_ctr_drbg_random,
-                                   &global_data.ctr_drbg );
-        if( ret != 0 )
-        {
-            mbedtls_ecp_keypair_free( &ecp );
-            return( mbedtls_to_psa_error( ret ) );
-        }
-
-
-        /* Make sure to always have an export representation available */
-        size_t bytes = PSA_BITS_TO_BYTES( bits );
-        psa_status_t status = psa_allocate_buffer_to_slot( slot, bytes );
-        if( status != PSA_SUCCESS )
-        {
-            mbedtls_ecp_keypair_free( &ecp );
-            return( status );
-        }
-
-        status = mbedtls_to_psa_error(
-            mbedtls_ecp_write_key( &ecp, slot->data.key.data, bytes ) );
-
-        mbedtls_ecp_keypair_free( &ecp );
-        if( status != PSA_SUCCESS ) {
-            memset( slot->data.key.data, 0, bytes );
-            psa_remove_key_data_from_memory( slot );
-        }
-        return( status );
+        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) */
     {
+        (void)key_buffer_length;
         return( PSA_ERROR_NOT_SUPPORTED );
     }
 
@@ -6536,6 +5265,7 @@
     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;
 
@@ -6544,20 +5274,51 @@
     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->core.type) )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
     status = psa_start_key_creation( PSA_KEY_CREATION_GENERATE, attributes,
                                      &slot, &driver );
     if( status != PSA_SUCCESS )
         goto exit;
 
-    status = psa_driver_wrapper_generate_key( attributes,
-                                              slot );
-    if( status != PSA_ERROR_NOT_SUPPORTED ||
-        psa_key_lifetime_is_external( attributes->core.lifetime ) )
-        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
+     * or cryptoprocessor with storage), we have to allocate a buffer to
+     * hold the generated key material. */
+    if( slot->key.data == NULL )
+    {
+        if ( PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ) ==
+             PSA_KEY_LOCATION_LOCAL_STORAGE )
+        {
+            status = psa_validate_key_type_and_size_for_key_generation(
+                attributes->core.type, attributes->core.bits );
+            if( status != PSA_SUCCESS )
+                goto exit;
 
-    status = psa_generate_key_internal(
-        slot, attributes->core.bits,
-        attributes->domain_parameters, attributes->domain_parameters_size );
+            key_buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
+                                  attributes->core.type,
+                                  attributes->core.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,
+        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 )
@@ -6568,40 +5329,37 @@
     return( status );
 }
 
-
-
 /****************************************************************/
 /* 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 ) )
 {
     if( global_data.rng_state != RNG_NOT_INITIALIZED )
         return( PSA_ERROR_BAD_STATE );
-    global_data.entropy_init = entropy_init;
-    global_data.entropy_free = entropy_free;
+    global_data.rng.entropy_init = entropy_init;
+    global_data.rng.entropy_free = entropy_free;
     return( PSA_SUCCESS );
 }
+#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
 
 void mbedtls_psa_crypto_free( void )
 {
     psa_wipe_all_key_slots( );
     if( global_data.rng_state != RNG_NOT_INITIALIZED )
     {
-        mbedtls_ctr_drbg_free( &global_data.ctr_drbg );
-        global_data.entropy_free( &global_data.entropy );
+        mbedtls_psa_random_free( &global_data.rng );
     }
     /* Wipe all remaining data, including configuration.
      * In particular, this sets all state indicator to the value
      * indicating "uninitialized". */
     mbedtls_platform_zeroize( &global_data, sizeof( global_data ) );
-#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 */
+
+    /* Terminate drivers */
+    psa_driver_wrapper_free( );
 }
 
 #if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
@@ -6625,7 +5383,7 @@
         default:
             /* We found an unsupported transaction in the storage.
              * We don't know what state the storage is in. Give up. */
-            return( PSA_ERROR_STORAGE_FAILURE );
+            return( PSA_ERROR_DATA_INVALID );
     }
 }
 #endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
@@ -6633,37 +5391,15 @@
 psa_status_t psa_crypto_init( void )
 {
     psa_status_t status;
-    const unsigned char drbg_seed[] = "PSA";
 
     /* Double initialization is explicitly allowed. */
     if( global_data.initialized != 0 )
         return( PSA_SUCCESS );
 
-    /* Set default configuration if
-     * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */
-    if( global_data.entropy_init == NULL )
-        global_data.entropy_init = mbedtls_entropy_init;
-    if( global_data.entropy_free == NULL )
-        global_data.entropy_free = mbedtls_entropy_free;
-
-    /* Initialize the random generator. */
-    global_data.entropy_init( &global_data.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( &global_data.entropy,
-                                mbedtls_nv_seed_poll, NULL,
-                                MBEDTLS_ENTROPY_BLOCK_SIZE,
-                                MBEDTLS_ENTROPY_SOURCE_STRONG );
-#endif
-    mbedtls_ctr_drbg_init( &global_data.ctr_drbg );
+    /* Initialize and seed the random generator. */
+    mbedtls_psa_random_init( &global_data.rng );
     global_data.rng_state = RNG_INITIALIZED;
-    status = mbedtls_to_psa_error(
-        mbedtls_ctr_drbg_seed( &global_data.ctr_drbg,
-                               mbedtls_entropy_func,
-                               &global_data.entropy,
-                               drbg_seed, sizeof( drbg_seed ) - 1 ) );
+    status = mbedtls_psa_random_seed( &global_data.rng );
     if( status != PSA_SUCCESS )
         goto exit;
     global_data.rng_state = RNG_SEEDED;
@@ -6672,11 +5408,10 @@
     if( status != PSA_SUCCESS )
         goto exit;
 
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    status = psa_init_all_se_drivers( );
+    /* Init drivers */
+    status = psa_driver_wrapper_init( );
     if( status != PSA_SUCCESS )
         goto exit;
-#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
 #if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
     status = psa_crypto_load_transaction( );
diff --git a/third_party/mbedtls/repo/library/psa_crypto_aead.c b/third_party/mbedtls/repo/library/psa_crypto_aead.c
new file mode 100644
index 0000000..16a3711
--- /dev/null
+++ b/third_party/mbedtls/repo/library/psa_crypto_aead.c
@@ -0,0 +1,397 @@
+/*
+ *  PSA AEAD entry points
+ */
+/*
+ *  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 "common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include "psa_crypto_aead.h"
+#include "psa_crypto_core.h"
+
+#include "mbedtls/ccm.h"
+#include "mbedtls/chachapoly.h"
+#include "mbedtls/cipher.h"
+#include "mbedtls/gcm.h"
+
+typedef struct
+{
+    psa_algorithm_t core_alg;
+    uint8_t tag_length;
+    union
+    {
+        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+        mbedtls_ccm_context ccm;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+        mbedtls_gcm_context gcm;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+        mbedtls_chachapoly_context chachapoly;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+    } ctx;
+} aead_operation_t;
+
+#define AEAD_OPERATION_INIT {0, 0, {0}}
+
+static void psa_aead_abort_internal( aead_operation_t *operation )
+{
+    switch( operation->core_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 */
+    }
+}
+
+static psa_status_t psa_aead_setup(
+    aead_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t key_bits;
+    const mbedtls_cipher_info_t *cipher_info;
+    mbedtls_cipher_id_t cipher_id;
+    size_t full_tag_length = 0;
+
+    key_bits = attributes->core.bits;
+
+    cipher_info = mbedtls_cipher_info_from_psa( alg,
+                                                attributes->core.type, key_bits,
+                                                &cipher_id );
+    if( cipher_info == NULL )
+        return( PSA_ERROR_NOT_SUPPORTED );
+
+    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->core_alg = PSA_ALG_CCM;
+            full_tag_length = 16;
+            /* 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->core.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->core_alg = PSA_ALG_GCM;
+            full_tag_length = 16;
+            /* 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->core.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->core_alg = PSA_ALG_CHACHA20_POLY1305;
+            full_tag_length = 16;
+            /* 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 );
+    }
+
+    if( PSA_AEAD_TAG_LENGTH( attributes->core.type,
+                             key_bits, alg )
+        > full_tag_length )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
+    operation->tag_length = PSA_AEAD_TAG_LENGTH( attributes->core.type,
+                                                 key_bits,
+                                                 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;
+    aead_operation_t operation = AEAD_OPERATION_INIT;
+    uint8_t *tag;
+    (void) key_buffer_size;
+
+    status = psa_aead_setup( &operation, attributes, key_buffer, 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.core_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.core_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.core_alg == PSA_ALG_CHACHA20_POLY1305 )
+    {
+        if( nonce_length != 12 )
+        {
+            if( nonce_length == 8 )
+                status = PSA_ERROR_NOT_SUPPORTED;
+            else
+                status = PSA_ERROR_INVALID_ARGUMENT;
+            goto exit;
+        }
+
+        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:
+    psa_aead_abort_internal( &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;
+    aead_operation_t operation = AEAD_OPERATION_INIT;
+    const uint8_t *tag = NULL;
+    (void) key_buffer_size;
+
+    status = psa_aead_setup( &operation, attributes, key_buffer, 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.core_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.core_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.core_alg == PSA_ALG_CHACHA20_POLY1305 )
+    {
+        if( nonce_length != 12 )
+        {
+            if( nonce_length == 8 )
+                status = PSA_ERROR_NOT_SUPPORTED;
+            else
+                status = PSA_ERROR_INVALID_ARGUMENT;
+            goto exit;
+        }
+
+        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:
+    psa_aead_abort_internal( &operation );
+
+    if( status == PSA_SUCCESS )
+        *plaintext_length = ciphertext_length - operation.tag_length;
+    return( status );
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
diff --git a/third_party/mbedtls/repo/library/psa_crypto_aead.h b/third_party/mbedtls/repo/library/psa_crypto_aead.h
new file mode 100644
index 0000000..aab0f83
--- /dev/null
+++ b/third_party/mbedtls/repo/library/psa_crypto_aead.h
@@ -0,0 +1,151 @@
+/*
+ *  PSA AEAD driver entry points
+ */
+/*
+ *  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 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
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         ciphertext_size is too small.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+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
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         plaintext_size is too small.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+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 );
+
+#endif /* PSA_CRYPTO_AEAD */
diff --git a/third_party/mbedtls/repo/library/psa_crypto_cipher.c b/third_party/mbedtls/repo/library/psa_crypto_cipher.c
new file mode 100644
index 0000000..1fb9172
--- /dev/null
+++ b/third_party/mbedtls/repo/library/psa_crypto_cipher.c
@@ -0,0 +1,553 @@
+/*
+ *  PSA cipher driver entry points
+ */
+/*
+ *  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 "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>
+
+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;
+    mbedtls_cipher_id_t cipher_id_tmp;
+
+    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 )
+        {
+            case PSA_ALG_STREAM_CIPHER:
+                mode = MBEDTLS_MODE_STREAM;
+                break;
+            case PSA_ALG_CTR:
+                mode = MBEDTLS_MODE_CTR;
+                break;
+            case PSA_ALG_CFB:
+                mode = MBEDTLS_MODE_CFB;
+                break;
+            case PSA_ALG_OFB:
+                mode = MBEDTLS_MODE_OFB;
+                break;
+            case PSA_ALG_ECB_NO_PADDING:
+                mode = MBEDTLS_MODE_ECB;
+                break;
+            case PSA_ALG_CBC_NO_PADDING:
+                mode = MBEDTLS_MODE_CBC;
+                break;
+            case PSA_ALG_CBC_PKCS7:
+                mode = MBEDTLS_MODE_CBC;
+                break;
+            case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ):
+                mode = MBEDTLS_MODE_CCM;
+                break;
+            case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ):
+                mode = MBEDTLS_MODE_GCM;
+                break;
+            case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CHACHA20_POLY1305, 0 ):
+                mode = MBEDTLS_MODE_CHACHAPOLY;
+                break;
+            default:
+                return( NULL );
+        }
+    }
+    else if( alg == PSA_ALG_CMAC )
+        mode = MBEDTLS_MODE_ECB;
+    else
+        return( NULL );
+
+    switch( key_type )
+    {
+        case PSA_KEY_TYPE_AES:
+            cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
+            break;
+        case PSA_KEY_TYPE_ARIA:
+            cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA;
+            break;
+        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;
+        case PSA_KEY_TYPE_CAMELLIA:
+            cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;
+            break;
+        case PSA_KEY_TYPE_ARC4:
+            cipher_id_tmp = MBEDTLS_CIPHER_ID_ARC4;
+            break;
+        case PSA_KEY_TYPE_CHACHA20:
+            cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
+            break;
+        default:
+            return( NULL );
+    }
+    if( cipher_id != NULL )
+        *cipher_id = cipher_id_tmp;
+
+    return( mbedtls_cipher_info_from_values( cipher_id_tmp,
+                                             (int) key_bits, mode ) );
+}
+
+#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->core.type;
+
+    (void)key_buffer_size;
+
+    mbedtls_cipher_init( &operation->ctx.cipher );
+
+    operation->alg = alg;
+    key_bits = attributes->core.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 ) ) );
+}
+
+/** 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 = ctx->cipher_info->block_size;
+    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 );
+}
+
+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( 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
+    {
+        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, 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, 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, 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/third_party/mbedtls/repo/library/psa_crypto_cipher.h b/third_party/mbedtls/repo/library/psa_crypto_cipher.h
new file mode 100644
index 0000000..fae9847
--- /dev/null
+++ b/third_party/mbedtls/repo/library/psa_crypto_cipher.h
@@ -0,0 +1,305 @@
+/*
+ *  PSA cipher driver entry points
+ */
+/*
+ *  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 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       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 );
+
+/**
+ * \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
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+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
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+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
+ * \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
+ */
+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
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ */
+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
+ * \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
+ */
+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
+ */
+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
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \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
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \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/third_party/mbedtls/repo/library/psa_crypto_client.c b/third_party/mbedtls/repo/library/psa_crypto_client.c
new file mode 100644
index 0000000..629feb7
--- /dev/null
+++ b/third_party/mbedtls/repo/library/psa_crypto_client.c
@@ -0,0 +1,82 @@
+/*
+ *  PSA crypto client code
+ */
+/*
+ *  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 "common.h"
+#include "psa/crypto.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+
+#include <string.h>
+#include "mbedtls/platform.h"
+#if !defined(MBEDTLS_PLATFORM_C)
+#define mbedtls_calloc calloc
+#define mbedtls_free   free
+#endif
+
+void psa_reset_key_attributes( psa_key_attributes_t *attributes )
+{
+    mbedtls_free( attributes->domain_parameters );
+    memset( attributes, 0, sizeof( *attributes ) );
+}
+
+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 )
+{
+    uint8_t *copy = NULL;
+
+    if( data_length != 0 )
+    {
+        copy = mbedtls_calloc( 1, data_length );
+        if( copy == NULL )
+            return( PSA_ERROR_INSUFFICIENT_MEMORY );
+        memcpy( copy, data, data_length );
+    }
+    /* After this point, this function is guaranteed to succeed, so it
+     * can start modifying `*attributes`. */
+
+    if( attributes->domain_parameters != NULL )
+    {
+        mbedtls_free( attributes->domain_parameters );
+        attributes->domain_parameters = NULL;
+        attributes->domain_parameters_size = 0;
+    }
+
+    attributes->domain_parameters = copy;
+    attributes->domain_parameters_size = data_length;
+    attributes->core.type = type;
+    return( PSA_SUCCESS );
+}
+
+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 )
+{
+    if( attributes->domain_parameters_size > data_size )
+        return( PSA_ERROR_BUFFER_TOO_SMALL );
+    *data_length = attributes->domain_parameters_size;
+    if( attributes->domain_parameters_size != 0 )
+        memcpy( data, attributes->domain_parameters,
+                attributes->domain_parameters_size );
+    return( PSA_SUCCESS );
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
diff --git a/third_party/mbedtls/repo/library/psa_crypto_core.h b/third_party/mbedtls/repo/library/psa_crypto_core.h
index f61ef95..4420ec2 100644
--- a/third_party/mbedtls/repo/library/psa_crypto_core.h
+++ b/third_party/mbedtls/repo/library/psa_crypto_core.h
@@ -30,6 +30,26 @@
 #include "psa/crypto.h"
 #include "psa/crypto_se_driver.h"
 
+/** Constant-time buffer comparison
+ *
+ * \param[in]  a    Left-hand buffer for comparison.
+ * \param[in]  b    Right-hand buffer for comparison.
+ * \param n         Amount of bytes to compare.
+ *
+ * \return 0 if the buffer contents are equal, non-zero otherwise
+ */
+static inline int mbedtls_psa_safer_memcmp(
+    const uint8_t *a, const uint8_t *b, size_t n )
+{
+    size_t i;
+    unsigned char diff = 0;
+
+    for( i = 0; i < n; i++ )
+        diff |= a[i] ^ b[i];
+
+    return( diff );
+}
+
 /** The data structure representing a key slot, containing key material
  * and metadata for one key.
  */
@@ -62,23 +82,13 @@
      */
     size_t lock_count;
 
-    union
+    /* Dynamically allocated key data buffer.
+     * Format as specified in psa_export_key(). */
+    struct key_data
     {
-        /* Dynamically allocated key data buffer.
-         * Format as specified in psa_export_key(). */
-        struct key_data
-        {
-            uint8_t *data;
-            size_t bytes;
-        } key;
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-        /* Any key type in a secure element */
-        struct se
-        {
-            psa_key_slot_number_t slot_number;
-        } se;
-#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
-    } data;
+        uint8_t *data;
+        size_t bytes;
+    } key;
 } psa_key_slot_t;
 
 /* A mask of key attribute flags used only internally.
@@ -163,6 +173,20 @@
     slot->attr.flags &= ~mask;
 }
 
+#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.
@@ -176,6 +200,24 @@
  */
 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
@@ -208,4 +250,286 @@
  */
 psa_status_t mbedtls_to_psa_error( int ret );
 
+/** 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 );
+
+/** 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
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+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
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ */
+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
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ */
+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 );
+
+/**
+ * \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[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
+ * \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,
+                                        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
+ * \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
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ */
+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
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ */
+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
+ * \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
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ */
+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
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ */
+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 );
+
 #endif /* PSA_CRYPTO_CORE_H */
diff --git a/third_party/mbedtls/repo/library/psa_crypto_driver_wrappers.c b/third_party/mbedtls/repo/library/psa_crypto_driver_wrappers.c
index c3ea6f1..16166fc 100644
--- a/third_party/mbedtls/repo/library/psa_crypto_driver_wrappers.c
+++ b/third_party/mbedtls/repo/library/psa_crypto_driver_wrappers.c
@@ -19,10 +19,17 @@
  *  limitations under the License.
  */
 
+#include "psa_crypto_aead.h"
+#include "psa_crypto_cipher.h"
 #include "psa_crypto_core.h"
 #include "psa_crypto_driver_wrappers.h"
+#include "psa_crypto_hash.h"
+#include "psa_crypto_mac.h"
+
 #include "mbedtls/platform.h"
 
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
 #if defined(MBEDTLS_PSA_CRYPTO_DRIVERS)
 
 /* Include test driver definition when running tests */
@@ -37,15 +44,18 @@
 #endif /* PSA_CRYPTO_DRIVER_TEST */
 
 /* Repeat above block for each JSON-declared driver during autogeneration */
-
-/* Auto-generated values depending on which drivers are registered. ID 0 is
- * reserved for unallocated operations. */
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-#define PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID (1)
-#define PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID (2)
-#endif /* PSA_CRYPTO_DRIVER_TEST */
 #endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */
 
+/* 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. */
+#define PSA_CRYPTO_MBED_TLS_DRIVER_ID (1)
+
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+#define PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID (2)
+#define PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID (3)
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+
 /* 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
@@ -56,22 +66,203 @@
 #include "psa_crypto_se.h"
 #endif
 
-/* Start delegation functions */
-psa_status_t psa_driver_wrapper_sign_hash( psa_key_slot_t *slot,
-                                           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 psa_driver_wrapper_init( void )
 {
-#if defined(PSA_CRYPTO_DRIVER_PRESENT)
+    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 );
+}
+
+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 */
+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( attributes->core.lifetime );
+
+    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 ) );
+}
+
+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( attributes->core.lifetime );
+
+    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 ) );
+}
+
+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( slot->attr.lifetime, &drv, &drv_context ) )
+    if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) )
     {
         if( drv->asymmetric == NULL ||
             drv->asymmetric->p_sign == NULL )
@@ -79,32 +270,27 @@
             /* 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,
-                                         slot->data.se.slot_number,
-                                         alg,
-                                         hash, hash_length,
-                                         signature, signature_size,
-                                         signature_length ) );
+        return( drv->asymmetric->p_sign(
+                    drv_context, *( (psa_key_slot_number_t *)key_buffer ),
+                    alg, hash, hash_length,
+                    signature, signature_size, signature_length ) );
     }
 #endif /* PSA_CRYPTO_SE_C */
 
-    /* Then try accelerator API */
-#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
-    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
-    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime);
-    psa_key_attributes_t attributes = {
-      .core = slot->attr
-    };
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
 
     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 = test_transparent_signature_sign_hash( &attributes,
-                                                           slot->data.key.data,
-                                                           slot->data.key.bytes,
+            status = mbedtls_test_transparent_signature_sign_hash( attributes,
+                                                           key_buffer,
+                                                           key_buffer_size,
                                                            alg,
                                                            hash,
                                                            hash_length,
@@ -115,55 +301,52 @@
             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( PSA_ERROR_NOT_SUPPORTED );
+            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_LIFETIME:
-            return( test_opaque_signature_sign_hash( &attributes,
-                                                     slot->data.key.data,
-                                                     slot->data.key.bytes,
-                                                     alg,
-                                                     hash,
-                                                     hash_length,
-                                                     signature,
-                                                     signature_size,
-                                                     signature_length ) );
+        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 */
-            return( status );
+            (void)status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
     }
-#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
-#else /* PSA_CRYPTO_DRIVER_PRESENT */
-    (void)slot;
-    (void)alg;
-    (void)hash;
-    (void)hash_length;
-    (void)signature;
-    (void)signature_size;
-    (void)signature_length;
-
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_DRIVER_PRESENT */
 }
 
-psa_status_t psa_driver_wrapper_verify_hash( psa_key_slot_t *slot,
-                                             psa_algorithm_t alg,
-                                             const uint8_t *hash,
-                                             size_t hash_length,
-                                             const uint8_t *signature,
-                                             size_t signature_length )
+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 )
 {
-#if defined(PSA_CRYPTO_DRIVER_PRESENT)
     /* 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( slot->attr.lifetime, &drv, &drv_context ) )
+    if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) )
     {
         if( drv->asymmetric == NULL ||
             drv->asymmetric->p_verify == NULL )
@@ -171,156 +354,133 @@
             /* 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,
-                                           slot->data.se.slot_number,
-                                           alg,
-                                           hash, hash_length,
-                                           signature, signature_length ) );
+        return( drv->asymmetric->p_verify(
+                    drv_context, *( (psa_key_slot_number_t *)key_buffer ),
+                    alg, hash, hash_length,
+                    signature, signature_length ) );
     }
 #endif /* PSA_CRYPTO_SE_C */
 
-    /* Then try accelerator API */
-#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
-    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
-    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime);
-    psa_key_attributes_t attributes = {
-      .core = slot->attr
-    };
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
 
     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 = test_transparent_signature_verify_hash( &attributes,
-                                                             slot->data.key.data,
-                                                             slot->data.key.bytes,
-                                                             alg,
-                                                             hash,
-                                                             hash_length,
-                                                             signature,
-                                                             signature_length );
+            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 */
-            /* Fell through, meaning no accelerator supports this operation */
-            return( PSA_ERROR_NOT_SUPPORTED );
+#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_LIFETIME:
-            return( test_opaque_signature_verify_hash( &attributes,
-                                                       slot->data.key.data,
-                                                       slot->data.key.bytes,
-                                                       alg,
-                                                       hash,
-                                                       hash_length,
-                                                       signature,
-                                                       signature_length ) );
+        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 */
-            return( status );
+            (void)status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
     }
-#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
-#else /* PSA_CRYPTO_DRIVER_PRESENT */
-    (void)slot;
-    (void)alg;
-    (void)hash;
-    (void)hash_length;
-    (void)signature;
-    (void)signature_length;
-
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_DRIVER_PRESENT */
 }
 
-#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
-/** Calculate the size to allocate for buffering a key with given attributes.
+/** Get the key buffer size required to store the key material of a key
+ *  associated with an opaque driver without storage.
  *
- * This function provides a way to get the expected size for storing a key with
- * the given attributes. This will be the size of the export representation for
- * cleartext keys, and a driver-defined size for keys stored by opaque drivers.
- *
- * \param[in] attributes        The key attribute structure of the key to store.
- * \param[out] expected_size    On success, a byte size large enough to contain
- *                              the declared key.
+ * \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_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 get_expected_key_size( const psa_key_attributes_t *attributes,
-                                           size_t *expected_size )
+psa_status_t psa_driver_wrapper_get_key_buffer_size(
+    const psa_key_attributes_t *attributes,
+    size_t *key_buffer_size )
 {
-    size_t buffer_size = 0;
     psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
     psa_key_type_t key_type = attributes->core.type;
     size_t key_bits = attributes->core.bits;
 
+    *key_buffer_size = 0;
     switch( location )
     {
-        case PSA_KEY_LOCATION_LOCAL_STORAGE:
-            buffer_size = PSA_KEY_EXPORT_MAX_SIZE( key_type, key_bits );
-
-            if( buffer_size == 0 )
-                return( PSA_ERROR_NOT_SUPPORTED );
-
-            *expected_size = buffer_size;
-            return( PSA_SUCCESS );
-
 #if defined(PSA_CRYPTO_DRIVER_TEST)
-        case PSA_CRYPTO_TEST_DRIVER_LIFETIME:
-#ifdef TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION
-            *expected_size = test_size_function( key_type, key_bits );
-            return( PSA_SUCCESS );
-#else /* TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION */
-            if( PSA_KEY_TYPE_IS_KEY_PAIR( key_type ) )
+        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 ) ) ) )
             {
-                int public_key_overhead = ( ( TEST_DRIVER_KEY_CONTEXT_STORE_PUBLIC_KEY == 1 ) ?
-                                           PSA_KEY_EXPORT_MAX_SIZE( key_type, key_bits ) : 0 );
-                *expected_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE
-                                 + TEST_DRIVER_KEY_CONTEXT_PUBLIC_KEY_SIZE
-                                 + public_key_overhead;
+                *key_buffer_size = sizeof( psa_drv_slot_number_t );
+                return( PSA_SUCCESS );
             }
-            else if( PSA_KEY_TYPE_IS_PUBLIC_KEY( attributes->core.type ) )
-            {
-                *expected_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE
-                                 + TEST_DRIVER_KEY_CONTEXT_PUBLIC_KEY_SIZE;
-            }
-            else if ( !PSA_KEY_TYPE_IS_KEY_PAIR( key_type ) &&
-                      !PSA_KEY_TYPE_IS_PUBLIC_KEY ( attributes->core.type ) )
-            {
-                *expected_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE
-                                 + TEST_DRIVER_KEY_CONTEXT_SYMMETRIC_FACTOR
-                                 * ( ( key_bits + 7 ) / 8 );
-            }
-            else
-            {
-                return( PSA_ERROR_NOT_SUPPORTED );
-            }
-            return( PSA_SUCCESS );
-#endif /* TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION */
+#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
+            *key_buffer_size = mbedtls_test_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_NOT_SUPPORTED );
     }
 }
-#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
 
-psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes,
-                                              psa_key_slot_t *slot )
+psa_status_t psa_driver_wrapper_generate_key(
+    const psa_key_attributes_t *attributes,
+    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
 {
-#if defined(PSA_CRYPTO_DRIVER_PRESENT)
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime);
+
     /* 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( slot->attr.lifetime, &drv, &drv_context ) )
+    if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) )
     {
         size_t pubkey_length = 0; /* We don't support this feature yet */
         if( drv->key_management == NULL ||
@@ -331,238 +491,382 @@
         }
         return( drv->key_management->p_generate(
             drv_context,
-            slot->data.se.slot_number, attributes,
-            NULL, 0, &pubkey_length ) );
+            *( (psa_key_slot_number_t *)key_buffer ),
+            attributes, NULL, 0, &pubkey_length ) );
     }
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
-    /* Then try accelerator API */
-#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
-    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
-    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime);
-    size_t export_size = 0;
-
-    status = get_expected_key_size( attributes, &export_size );
-    if( status != PSA_SUCCESS )
-        return( status );
-
-    slot->data.key.data = mbedtls_calloc(1, export_size);
-    if( slot->data.key.data == NULL )
-        return( PSA_ERROR_INSUFFICIENT_MEMORY );
-    slot->data.key.bytes = export_size;
-
     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)
             /* Transparent drivers are limited to generating asymmetric keys */
-            if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) )
+            if( PSA_KEY_TYPE_IS_ASYMMETRIC( attributes->core.type ) )
             {
-                status = PSA_ERROR_NOT_SUPPORTED;
-                break;
+            /* 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(PSA_CRYPTO_DRIVER_TEST)
-            status = test_transparent_generate_key( attributes,
-                                                    slot->data.key.data,
-                                                    slot->data.key.bytes,
-                                                    &slot->data.key.bytes );
-            /* Declared with fallback == true */
-            if( status != PSA_ERROR_NOT_SUPPORTED )
-                break;
-#endif /* PSA_CRYPTO_DRIVER_TEST */
-            /* Fell through, meaning no accelerator supports this operation */
-            status = PSA_ERROR_NOT_SUPPORTED;
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            /* Software fallback */
+            status = psa_generate_key_internal(
+                attributes, 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_LIFETIME:
-            status = test_opaque_generate_key( attributes,
-                                               slot->data.key.data,
-                                               slot->data.key.bytes,
-                                               &slot->data.key.bytes );
+        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;
     }
 
-    if( status != PSA_SUCCESS )
-    {
-        /* free allocated buffer */
-        mbedtls_free( slot->data.key.data );
-        slot->data.key.data = NULL;
-        slot->data.key.bytes = 0;
-    }
-
     return( status );
-#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
-#else /* PSA_CRYPTO_DRIVER_PRESENT */
-    (void) attributes;
-    (void) slot;
-
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_DRIVER_PRESENT */
 }
 
-psa_status_t psa_driver_wrapper_validate_key( const psa_key_attributes_t *attributes,
-                                              const uint8_t *data,
-                                              size_t data_length,
-                                              size_t *bits )
+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 )
 {
-#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    /* Try accelerators in turn */
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-    status = test_transparent_validate_key( attributes,
-                                            data,
-                                            data_length,
-                                            bits );
-    /* Declared with fallback == true */
-    if( status != PSA_ERROR_NOT_SUPPORTED )
-        return( status );
-#endif /* PSA_CRYPTO_DRIVER_TEST */
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(
+                                      psa_get_key_lifetime( attributes ) );
 
-    return( PSA_ERROR_NOT_SUPPORTED );
-#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
-    (void) attributes;
-    (void) data;
-    (void) data_length;
-    (void) bits;
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_DRIVER_PRESENT */
-}
+    /* 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;
 
-psa_status_t psa_driver_wrapper_export_public_key( const psa_key_slot_t *slot,
-                                                   uint8_t *data,
-                                                   size_t data_size,
-                                                   size_t *data_length )
-{
-#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
-    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
-    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime);
-    psa_key_attributes_t attributes = {
-      .core = slot->attr
-    };
+    if( psa_get_se_driver( attributes->core.lifetime, &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 /* 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 = test_transparent_export_public_key( &attributes,
-                                                         slot->data.key.data,
-                                                         slot->data.key.bytes,
-                                                         data,
-                                                         data_size,
-                                                         data_length );
+            status = mbedtls_test_transparent_import_key(
+                         attributes,
+                         data, data_length,
+                         key_buffer, key_buffer_size,
+                         key_buffer_length, bits );
             /* 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( psa_import_key_into_slot( attributes,
+                                              data, data_length,
+                                              key_buffer, key_buffer_size,
+                                              key_buffer_length, bits ) );
+
+        default:
+            /* Importing a key with external storage in not yet supported.
+             * Return in error indicating that the lifetime is not valid. */
+            (void)status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+
+}
+
+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( attributes->core.lifetime, &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 /* 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 PSA_CRYPTO_TEST_DRIVER_LIFETIME:
-            return( test_opaque_export_public_key( &attributes,
-                                                   slot->data.key.data,
-                                                   slot->data.key.bytes,
-                                                   data,
-                                                   data_size,
-                                                   data_length ) );
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            return( mbedtls_test_opaque_export_key( attributes,
+                                                    key_buffer,
+                                                    key_buffer_size,
+                                                    data,
+                                                    data_size,
+                                                    data_length ) );
 #endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
         default:
             /* Key is declared with a lifetime not known to us */
             return( status );
     }
-#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
-    (void) slot;
-    (void) data;
-    (void) data_size;
-    (void) data_length;
-    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+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( attributes->core.lifetime, &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 );
+            /* 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( 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 PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            return( mbedtls_test_opaque_export_public_key( attributes,
+                                                           key_buffer,
+                                                           key_buffer_size,
+                                                           data,
+                                                           data_size,
+                                                           data_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#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( attributes->core.lifetime );
+    switch( location )
+    {
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            return( mbedtls_test_opaque_get_builtin_key(
+                        slot_number,
+                        attributes,
+                        key_buffer, key_buffer_size, key_buffer_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+        default:
+            (void) slot_number;
+            (void) key_buffer;
+            (void) key_buffer_size;
+            (void) key_buffer_length;
+            return( PSA_ERROR_DOES_NOT_EXIST );
+    }
 }
 
 /*
  * Cipher functions
  */
 psa_status_t psa_driver_wrapper_cipher_encrypt(
-    psa_key_slot_t *slot,
+    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 )
 {
-#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
-    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
-    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime);
-    psa_key_attributes_t attributes = {
-      .core = slot->attr
-    };
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
 
     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 = test_transparent_cipher_encrypt( &attributes,
-                                                      slot->data.key.data,
-                                                      slot->data.key.bytes,
-                                                      alg,
-                                                      input,
-                                                      input_length,
-                                                      output,
-                                                      output_size,
-                                                      output_length );
+            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 */
-            /* Fell through, meaning no accelerator supports this operation */
-            return( PSA_ERROR_NOT_SUPPORTED );
-        /* Add cases for opaque driver here */
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-        case PSA_CRYPTO_TEST_DRIVER_LIFETIME:
-            return( test_opaque_cipher_encrypt( &attributes,
-                                                slot->data.key.data,
-                                                slot->data.key.bytes,
+#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 */
-            return( status );
+            (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 );
     }
-#else /* PSA_CRYPTO_DRIVER_PRESENT */
-    (void) slot;
-    (void) alg;
-    (void) input;
-    (void) input_length;
-    (void) output;
-    (void) output_size;
-    (void) output_length;
-
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_DRIVER_PRESENT */
 }
 
 psa_status_t psa_driver_wrapper_cipher_decrypt(
-    psa_key_slot_t *slot,
+    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,
@@ -570,424 +874,990 @@
     size_t output_size,
     size_t *output_length )
 {
-#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
-    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
-    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime);
-    psa_key_attributes_t attributes = {
-      .core = slot->attr
-    };
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
 
     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 = test_transparent_cipher_decrypt( &attributes,
-                                                      slot->data.key.data,
-                                                      slot->data.key.bytes,
-                                                      alg,
-                                                      input,
-                                                      input_length,
-                                                      output,
-                                                      output_size,
-                                                      output_length );
+            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 */
-            /* Fell through, meaning no accelerator supports this operation */
-            return( PSA_ERROR_NOT_SUPPORTED );
-        /* Add cases for opaque driver here */
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-        case PSA_CRYPTO_TEST_DRIVER_LIFETIME:
-            return( test_opaque_cipher_decrypt( &attributes,
-                                                slot->data.key.data,
-                                                slot->data.key.bytes,
+#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 */
-            return( status );
+            (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 );
     }
-#else /* PSA_CRYPTO_DRIVER_PRESENT */
-    (void) slot;
-    (void) alg;
-    (void) input;
-    (void) input_length;
-    (void) output;
-    (void) output_size;
-    (void) output_length;
-
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_DRIVER_PRESENT */
 }
 
 psa_status_t psa_driver_wrapper_cipher_encrypt_setup(
-    psa_operation_driver_context_t *operation,
-    psa_key_slot_t *slot,
+    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 )
 {
-#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
-    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
-    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime);
-    psa_key_attributes_t attributes = {
-      .core = slot->attr
-    };
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
 
     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->ctx = mbedtls_calloc( 1, sizeof(test_transparent_cipher_operation_t) );
-            if( operation->ctx == NULL )
-                return PSA_ERROR_INSUFFICIENT_MEMORY;
-
-            status = test_transparent_cipher_encrypt_setup( operation->ctx,
-                                                            &attributes,
-                                                            slot->data.key.data,
-                                                            slot->data.key.bytes,
-                                                            alg );
+            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 = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID;
-            else
-            {
-                mbedtls_platform_zeroize(
-                    operation->ctx,
-                    sizeof( test_transparent_cipher_operation_t ) );
-                mbedtls_free( operation->ctx );
-                operation->ctx = NULL;
-            }
 
-            return( status );
+            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 */
-            return( PSA_ERROR_NOT_SUPPORTED );
-        /* Add cases for opaque driver here */
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-        case PSA_CRYPTO_TEST_DRIVER_LIFETIME:
-            operation->ctx = mbedtls_calloc( 1, sizeof(test_opaque_cipher_operation_t) );
-            if( operation->ctx == NULL )
-                return( PSA_ERROR_INSUFFICIENT_MEMORY );
-
-            status = test_opaque_cipher_encrypt_setup( operation->ctx,
-                                                       &attributes,
-                                                       slot->data.key.data,
-                                                       slot->data.key.bytes,
+            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 = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID;
-            else
-            {
-                mbedtls_platform_zeroize(
-                    operation->ctx,
-                    sizeof( test_opaque_cipher_operation_t ) );
-                mbedtls_free( operation->ctx );
-                operation->ctx = NULL;
-            }
 
             return( status );
 #endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
         default:
             /* Key is declared with a lifetime not known to us */
-            return( PSA_ERROR_NOT_SUPPORTED );
+            (void)status;
+            (void)operation;
+            (void)key_buffer;
+            (void)key_buffer_size;
+            (void)alg;
+            return( PSA_ERROR_INVALID_ARGUMENT );
     }
-#else /* PSA_CRYPTO_DRIVER_PRESENT */
-    (void)slot;
-    (void)alg;
-    (void)operation;
-
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_DRIVER_PRESENT */
 }
 
 psa_status_t psa_driver_wrapper_cipher_decrypt_setup(
-    psa_operation_driver_context_t *operation,
-    psa_key_slot_t *slot,
+    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 )
 {
-#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
     psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
-    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime);
-    psa_key_attributes_t attributes = {
-      .core = slot->attr
-    };
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
 
     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->ctx = mbedtls_calloc( 1, sizeof(test_transparent_cipher_operation_t) );
-            if( operation->ctx == NULL )
-                return( PSA_ERROR_INSUFFICIENT_MEMORY );
-
-            status = test_transparent_cipher_decrypt_setup( operation->ctx,
-                                                            &attributes,
-                                                            slot->data.key.data,
-                                                            slot->data.key.bytes,
-                                                            alg );
+            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 = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID;
-            else
-            {
-                mbedtls_platform_zeroize(
-                    operation->ctx,
-                    sizeof( test_transparent_cipher_operation_t ) );
-                mbedtls_free( operation->ctx );
-                operation->ctx = NULL;
-            }
 
-            return( status );
+            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 */
-            return( PSA_ERROR_NOT_SUPPORTED );
-        /* Add cases for opaque driver here */
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-        case PSA_CRYPTO_TEST_DRIVER_LIFETIME:
-            operation->ctx = mbedtls_calloc( 1, sizeof(test_opaque_cipher_operation_t) );
-            if( operation->ctx == NULL )
-                return PSA_ERROR_INSUFFICIENT_MEMORY;
-
-            status = test_opaque_cipher_decrypt_setup( operation->ctx,
-                                                       &attributes,
-                                                       slot->data.key.data,
-                                                       slot->data.key.bytes,
+            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 );
+#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_decrypt_setup(
+                         &operation->ctx.opaque_test_driver_ctx,
+                         attributes,
+                         key_buffer, key_buffer_size,
+                         alg );
+
+            if( status == PSA_SUCCESS )
                 operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID;
-            else
-            {
-                mbedtls_platform_zeroize(
-                    operation->ctx,
-                    sizeof( test_opaque_cipher_operation_t ) );
-                mbedtls_free( operation->ctx );
-                operation->ctx = NULL;
-            }
 
             return( status );
 #endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
         default:
             /* Key is declared with a lifetime not known to us */
-            return( PSA_ERROR_NOT_SUPPORTED );
+            (void)status;
+            (void)operation;
+            (void)key_buffer;
+            (void)key_buffer_size;
+            (void)alg;
+            return( PSA_ERROR_INVALID_ARGUMENT );
     }
-#else /* PSA_CRYPTO_DRIVER_PRESENT */
-    (void)slot;
-    (void)alg;
-    (void)operation;
-
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_DRIVER_PRESENT */
-}
-
-psa_status_t psa_driver_wrapper_cipher_generate_iv(
-    psa_operation_driver_context_t *operation,
-    uint8_t *iv,
-    size_t iv_size,
-    size_t *iv_length )
-{
-#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
-    switch( operation->id )
-    {
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
-            return( test_transparent_cipher_generate_iv( operation->ctx,
-                                                         iv,
-                                                         iv_size,
-                                                         iv_length ) );
-#endif /* PSA_CRYPTO_DRIVER_TEST */
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-        case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID:
-            return( test_opaque_cipher_generate_iv( operation->ctx,
-                                                    iv,
-                                                    iv_size,
-                                                    iv_length ) );
-#endif /* PSA_CRYPTO_DRIVER_TEST */
-        default:
-            /* Key is attached to a driver not known to us */
-            return( PSA_ERROR_BAD_STATE );
-    }
-#else /* PSA_CRYPTO_DRIVER_PRESENT */
-    (void) operation;
-    (void) iv;
-    (void) iv_size;
-    (void) iv_length;
-
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_DRIVER_PRESENT */
 }
 
 psa_status_t psa_driver_wrapper_cipher_set_iv(
-    psa_operation_driver_context_t *operation,
+    psa_cipher_operation_t *operation,
     const uint8_t *iv,
     size_t iv_length )
 {
-#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
     switch( operation->id )
     {
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
-            return( test_transparent_cipher_set_iv( operation->ctx,
-                                                    iv,
-                                                    iv_length ) );
-#endif /* PSA_CRYPTO_DRIVER_TEST */
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-        case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID:
-            return( test_opaque_cipher_set_iv( operation->ctx,
+#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 /* PSA_CRYPTO_DRIVER_TEST */
-        default:
-            /* Key is attached to a driver not known to us */
-            return( PSA_ERROR_BAD_STATE );
-    }
-#else /* PSA_CRYPTO_DRIVER_PRESENT */
-    (void) operation;
-    (void) iv;
-    (void) iv_length;
+#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
 
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_cipher_set_iv(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        iv, iv_length ) );
+
+        case PSA_CRYPTO_OPAQUE_TEST_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 );
 }
 
 psa_status_t psa_driver_wrapper_cipher_update(
-    psa_operation_driver_context_t *operation,
+    psa_cipher_operation_t *operation,
     const uint8_t *input,
     size_t input_length,
     uint8_t *output,
     size_t output_size,
     size_t *output_length )
 {
-#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
     switch( operation->id )
     {
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
-            return( test_transparent_cipher_update( operation->ctx,
-                                                    input,
-                                                    input_length,
-                                                    output,
-                                                    output_size,
-                                                    output_length ) );
-#endif /* PSA_CRYPTO_DRIVER_TEST */
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-        case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID:
-            return( test_opaque_cipher_update( operation->ctx,
+#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 /* PSA_CRYPTO_DRIVER_TEST */
-        default:
-            /* Key is attached to a driver not known to us */
-            return( PSA_ERROR_BAD_STATE );
-    }
-#else /* PSA_CRYPTO_DRIVER_PRESENT */
-    (void) operation;
-    (void) input;
-    (void) input_length;
-    (void) output;
-    (void) output_length;
-    (void) output_size;
+#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
 
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_cipher_update(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        input, input_length,
+                        output, output_size, output_length ) );
+
+        case PSA_CRYPTO_OPAQUE_TEST_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 );
 }
 
 psa_status_t psa_driver_wrapper_cipher_finish(
-    psa_operation_driver_context_t *operation,
+    psa_cipher_operation_t *operation,
     uint8_t *output,
     size_t output_size,
     size_t *output_length )
 {
-#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
     switch( operation->id )
     {
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
-            return( test_transparent_cipher_finish( operation->ctx,
-                                                    output,
-                                                    output_size,
-                                                    output_length ) );
-#endif /* PSA_CRYPTO_DRIVER_TEST */
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-        case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID:
-            return( test_opaque_cipher_finish( operation->ctx,
+#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 /* PSA_CRYPTO_DRIVER_TEST */
-        default:
-            /* Key is attached to a driver not known to us */
-            return( PSA_ERROR_BAD_STATE );
-    }
-#else /* PSA_CRYPTO_DRIVER_PRESENT */
-    (void) operation;
-    (void) output;
-    (void) output_size;
-    (void) output_length;
+#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
 
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_cipher_finish(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        output, output_size, output_length ) );
+
+        case PSA_CRYPTO_OPAQUE_TEST_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 );
 }
 
 psa_status_t psa_driver_wrapper_cipher_abort(
-    psa_operation_driver_context_t *operation )
+    psa_cipher_operation_t *operation )
 {
-#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
-    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
-
-    /* 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. */
-    if( operation->ctx == NULL && operation->id == 0 )
-        return( PSA_SUCCESS );
+    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 PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
-            status = test_transparent_cipher_abort( operation->ctx );
+            status = mbedtls_test_transparent_cipher_abort(
+                         &operation->ctx.transparent_test_driver_ctx );
             mbedtls_platform_zeroize(
-                operation->ctx,
-                sizeof( test_transparent_cipher_operation_t ) );
-            mbedtls_free( operation->ctx );
-            operation->ctx = NULL;
-            operation->id = 0;
-
+                &operation->ctx.transparent_test_driver_ctx,
+                sizeof( operation->ctx.transparent_test_driver_ctx ) );
             return( status );
-#endif /* PSA_CRYPTO_DRIVER_TEST */
-#if defined(PSA_CRYPTO_DRIVER_TEST)
+
         case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID:
-            status = test_opaque_cipher_abort( operation->ctx );
+            status = mbedtls_test_opaque_cipher_abort(
+                         &operation->ctx.opaque_test_driver_ctx );
             mbedtls_platform_zeroize(
-                operation->ctx,
-                sizeof( test_opaque_cipher_operation_t ) );
-            mbedtls_free( operation->ctx );
-            operation->ctx = NULL;
-            operation->id = 0;
-
+                &operation->ctx.opaque_test_driver_ctx,
+                sizeof( operation->ctx.opaque_test_driver_ctx ) );
             return( status );
 #endif /* PSA_CRYPTO_DRIVER_TEST */
-        default:
-            /* Operation is attached to a driver not known to us */
-            return( PSA_ERROR_BAD_STATE );
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
     }
-#else /* PSA_CRYPTO_DRIVER_PRESENT */
-    (void)operation;
 
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+    (void)status;
+    return( PSA_ERROR_INVALID_ARGUMENT );
 }
 
-/* End of automatically generated file. */
+/*
+ * Hashing functions
+ */
+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 );
+}
+
+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 = PSA_CRYPTO_TRANSPARENT_TEST_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 );
+}
+
+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 PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            target_operation->id = PSA_CRYPTO_TRANSPARENT_TEST_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 );
+    }
+}
+
+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 PSA_CRYPTO_TRANSPARENT_TEST_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 );
+    }
+}
+
+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 PSA_CRYPTO_TRANSPARENT_TEST_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 );
+    }
+}
+
+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 PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_hash_abort(
+                        &operation->ctx.test_driver_ctx ) );
+#endif
+        default:
+            return( PSA_ERROR_BAD_STATE );
+    }
+}
+
+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( attributes->core.lifetime );
+
+    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 );
+    }
+}
+
+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( attributes->core.lifetime );
+
+    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 );
+    }
+}
+
+
+/*
+ * MAC functions
+ */
+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( attributes->core.lifetime );
+
+    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 );
+    }
+}
+
+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( attributes->core.lifetime );
+
+    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 = PSA_CRYPTO_TRANSPARENT_TEST_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 = PSA_CRYPTO_OPAQUE_TEST_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 );
+    }
+}
+
+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( attributes->core.lifetime );
+
+    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 = PSA_CRYPTO_TRANSPARENT_TEST_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 = PSA_CRYPTO_OPAQUE_TEST_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 );
+    }
+}
+
+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 PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_mac_update(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        input, input_length ) );
+
+        case PSA_CRYPTO_OPAQUE_TEST_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 );
+    }
+}
+
+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 PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_mac_sign_finish(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        mac, mac_size, mac_length ) );
+
+        case PSA_CRYPTO_OPAQUE_TEST_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 );
+    }
+}
+
+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 PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_mac_verify_finish(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        mac, mac_length ) );
+
+        case PSA_CRYPTO_OPAQUE_TEST_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 );
+    }
+}
+
+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 PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_mac_abort(
+                        &operation->ctx.transparent_test_driver_ctx ) );
+        case PSA_CRYPTO_OPAQUE_TEST_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 );
+    }
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/third_party/mbedtls/repo/library/psa_crypto_driver_wrappers.h b/third_party/mbedtls/repo/library/psa_crypto_driver_wrappers.h
index 6b51437..7cb88a0 100644
--- a/third_party/mbedtls/repo/library/psa_crypto_driver_wrappers.h
+++ b/third_party/mbedtls/repo/library/psa_crypto_driver_wrappers.h
@@ -26,46 +26,90 @@
 #include "psa/crypto_driver_common.h"
 
 /*
+ * Initialization and termination functions
+ */
+psa_status_t psa_driver_wrapper_init( void );
+void psa_driver_wrapper_free( void );
+
+/*
  * Signature functions
  */
-psa_status_t psa_driver_wrapper_sign_hash( psa_key_slot_t *slot,
-                                           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 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 psa_driver_wrapper_verify_hash( psa_key_slot_t *slot,
-                                             psa_algorithm_t alg,
-                                             const uint8_t *hash,
-                                             size_t hash_length,
-                                             const uint8_t *signature,
-                                             size_t signature_length );
+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 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 );
+
+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 );
 
 /*
  * Key handling functions
  */
 
-psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes,
-                                              psa_key_slot_t *slot );
+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 psa_driver_wrapper_validate_key( const psa_key_attributes_t *attributes,
-                                              const uint8_t *data,
-                                              size_t data_length,
-                                              size_t *bits );
+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 psa_driver_wrapper_export_public_key( const psa_key_slot_t *slot,
-                                                   uint8_t *data,
-                                                   size_t data_size,
-                                                   size_t *data_length );
+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_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 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 );
 
 /*
  * Cipher functions
  */
 psa_status_t psa_driver_wrapper_cipher_encrypt(
-    psa_key_slot_t *slot,
+    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,
@@ -73,7 +117,9 @@
     size_t *output_length );
 
 psa_status_t psa_driver_wrapper_cipher_decrypt(
-    psa_key_slot_t *slot,
+    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,
@@ -82,28 +128,24 @@
     size_t *output_length );
 
 psa_status_t psa_driver_wrapper_cipher_encrypt_setup(
-    psa_operation_driver_context_t *operation,
-    psa_key_slot_t *slot,
+    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 psa_driver_wrapper_cipher_decrypt_setup(
-    psa_operation_driver_context_t *operation,
-    psa_key_slot_t *slot,
+    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 psa_driver_wrapper_cipher_generate_iv(
-    psa_operation_driver_context_t *operation,
-    uint8_t *iv,
-    size_t iv_size,
-    size_t *iv_length );
-
 psa_status_t psa_driver_wrapper_cipher_set_iv(
-    psa_operation_driver_context_t *operation,
+    psa_cipher_operation_t *operation,
     const uint8_t *iv,
     size_t iv_length );
 
 psa_status_t psa_driver_wrapper_cipher_update(
-    psa_operation_driver_context_t *operation,
+    psa_cipher_operation_t *operation,
     const uint8_t *input,
     size_t input_length,
     uint8_t *output,
@@ -111,13 +153,115 @@
     size_t *output_length );
 
 psa_status_t psa_driver_wrapper_cipher_finish(
-    psa_operation_driver_context_t *operation,
+    psa_cipher_operation_t *operation,
     uint8_t *output,
     size_t output_size,
     size_t *output_length );
 
 psa_status_t psa_driver_wrapper_cipher_abort(
-    psa_operation_driver_context_t *operation );
+    psa_cipher_operation_t *operation );
+
+/*
+ * Hashing functions
+ */
+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 psa_driver_wrapper_hash_setup(
+    psa_hash_operation_t *operation,
+    psa_algorithm_t alg );
+
+psa_status_t psa_driver_wrapper_hash_clone(
+    const psa_hash_operation_t *source_operation,
+    psa_hash_operation_t *target_operation );
+
+psa_status_t psa_driver_wrapper_hash_update(
+    psa_hash_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length );
+
+psa_status_t psa_driver_wrapper_hash_finish(
+    psa_hash_operation_t *operation,
+    uint8_t *hash,
+    size_t hash_size,
+    size_t *hash_length );
+
+psa_status_t psa_driver_wrapper_hash_abort(
+    psa_hash_operation_t *operation );
+
+/*
+ * AEAD functions
+ */
+
+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 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 );
+
+/*
+ * MAC functions
+ */
+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 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 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 psa_driver_wrapper_mac_update(
+    psa_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length );
+
+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 );
+
+psa_status_t psa_driver_wrapper_mac_verify_finish(
+    psa_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length );
+
+psa_status_t psa_driver_wrapper_mac_abort(
+    psa_mac_operation_t *operation );
 
 #endif /* PSA_CRYPTO_DRIVER_WRAPPERS_H */
 
diff --git a/third_party/mbedtls/repo/library/psa_crypto_ecp.c b/third_party/mbedtls/repo/library/psa_crypto_ecp.c
new file mode 100644
index 0000000..db6682c
--- /dev/null
+++ b/third_party/mbedtls/repo/library/psa_crypto_ecp.c
@@ -0,0 +1,472 @@
+/*
+ *  PSA ECP layer on top of Mbed TLS crypto
+ */
+/*
+ *  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 "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 "psa_crypto_hash.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include "mbedtls/platform.h"
+#if !defined(MBEDTLS_PLATFORM_C)
+#define mbedtls_calloc calloc
+#define mbedtls_free   free
+#endif
+
+#include <mbedtls/ecdsa.h>
+#include <mbedtls/ecp.h>
+#include <mbedtls/error.h>
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
+    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)
+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 );
+
+    /* Load the group. */
+    grp_id = mbedtls_ecc_group_of_psa( PSA_KEY_TYPE_ECC_GET_FAMILY( type ),
+                                       curve_bits, !explicit_bits );
+    if( grp_id == MBEDTLS_ECP_DP_NONE )
+    {
+        /* We can't distinguish between a nonsensical family/size combination
+         * (which would warrant PSA_ERROR_INVALID_ARGUMENT) and a
+         * well-regarded curve that Mbed TLS just doesn't know about (which
+         * would warrant PSA_ERROR_NOT_SUPPORTED). For uniformity with how
+         * curves that Mbed TLS knows about but for which support is disabled
+         * at build time, return NOT_SUPPORTED. */
+        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) ||
+        * 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) || \
+    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->core.type,
+                                                  attributes->core.bits,
+                                                  data,
+                                                  data_length,
+                                                  &ecp );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    if( PSA_KEY_TYPE_ECC_GET_FAMILY( attributes->core.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->core.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
+    {
+        if( data_size < PSA_BITS_TO_BYTES( ecp->grp.nbits ) )
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+        status = mbedtls_to_psa_error(
+                    mbedtls_ecp_write_key( ecp,
+                                           data,
+                                           PSA_BITS_TO_BYTES( ecp->grp.nbits ) ) );
+        if( status == PSA_SUCCESS )
+            *data_length = PSA_BITS_TO_BYTES( ecp->grp.nbits );
+        else
+            memset( data, 0, 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->core.type, attributes->core.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->core.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) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR)
+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->core.type );
+    mbedtls_ecp_group_id grp_id =
+         mbedtls_ecc_group_of_psa( curve, attributes->core.bits, 0 );
+
+    const mbedtls_ecp_curve_info *curve_info =
+        mbedtls_ecp_curve_info_from_grp_id( grp_id );
+    mbedtls_ecp_keypair ecp;
+
+    if( attributes->domain_parameters_size != 0 )
+        return( PSA_ERROR_NOT_SUPPORTED );
+
+    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( &ecp, key_buffer, key_buffer_size ) );
+
+    mbedtls_ecp_keypair_free( &ecp );
+
+    if( status == PSA_SUCCESS )
+        *key_buffer_length = key_buffer_size;
+
+    return( status );
+}
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */
+
+/****************************************************************/
+/* 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->core.type,
+                                                  attributes->core.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 );
+        const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg );
+        mbedtls_md_type_t md_alg = mbedtls_md_get_type( md_info );
+        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_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;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t curve_bytes;
+    mbedtls_mpi r, s;
+
+    (void)alg;
+
+    status = mbedtls_psa_ecp_load_representation( attributes->core.type,
+                                                  attributes->core.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 )
+    {
+        ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
+        goto cleanup;
+    }
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r,
+                                              signature,
+                                              curve_bytes ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &s,
+                                              signature + curve_bytes,
+                                              curve_bytes ) );
+
+    /* Check whether the public part is loaded. If not, load it. */
+    if( mbedtls_ecp_is_zero( &ecp->Q ) )
+    {
+        MBEDTLS_MPI_CHK(
+            mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
+                             mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE ) );
+    }
+
+    ret = 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( mbedtls_to_psa_error( ret ) );
+}
+
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/third_party/mbedtls/repo/library/psa_crypto_ecp.h b/third_party/mbedtls/repo/library/psa_crypto_ecp.h
new file mode 100644
index 0000000..feddd8a
--- /dev/null
+++ b/third_party/mbedtls/repo/library/psa_crypto_ecp.h
@@ -0,0 +1,222 @@
+/*
+ *  PSA ECP layer on top of Mbed TLS crypto
+ */
+/*
+ *  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 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 );
+
+/** 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
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+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
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ */
+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
+ * \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
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ */
+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
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ */
+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 );
+
+#endif /* PSA_CRYPTO_ECP_H */
diff --git a/third_party/mbedtls/repo/library/psa_crypto_hash.c b/third_party/mbedtls/repo/library/psa_crypto_hash.c
new file mode 100644
index 0000000..337e557
--- /dev/null
+++ b/third_party/mbedtls/repo/library/psa_crypto_hash.c
@@ -0,0 +1,489 @@
+/*
+ *  PSA hashing layer on top of Mbed TLS software crypto
+ */
+/*
+ *  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 "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_ALG_RSA_PKCS1V15_SIGN) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
+const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg )
+{
+    switch( alg )
+    {
+#if defined(MBEDTLS_MD2_C)
+        case PSA_ALG_MD2:
+            return( &mbedtls_md2_info );
+#endif
+#if defined(MBEDTLS_MD4_C)
+        case PSA_ALG_MD4:
+            return( &mbedtls_md4_info );
+#endif
+#if defined(MBEDTLS_MD5_C)
+        case PSA_ALG_MD5:
+            return( &mbedtls_md5_info );
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+        case PSA_ALG_RIPEMD160:
+            return( &mbedtls_ripemd160_info );
+#endif
+#if defined(MBEDTLS_SHA1_C)
+        case PSA_ALG_SHA_1:
+            return( &mbedtls_sha1_info );
+#endif
+#if defined(MBEDTLS_SHA256_C)
+        case PSA_ALG_SHA_224:
+            return( &mbedtls_sha224_info );
+#endif
+#if defined(MBEDTLS_SHA256_C)
+        case PSA_ALG_SHA_256:
+            return( &mbedtls_sha256_info );
+#endif
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
+        case PSA_ALG_SHA_384:
+            return( &mbedtls_sha384_info );
+#endif
+#if defined(MBEDTLS_SHA512_C)
+        case PSA_ALG_SHA_512:
+            return( &mbedtls_sha512_info );
+#endif
+        default:
+            return( NULL );
+    }
+}
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
+
+#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_MD2)
+        case PSA_ALG_MD2:
+            mbedtls_md2_free( &operation->ctx.md2 );
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4)
+        case PSA_ALG_MD4:
+            mbedtls_md4_free( &operation->ctx.md4 );
+            break;
+#endif
+#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
+        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_MD2)
+        case PSA_ALG_MD2:
+            mbedtls_md2_init( &operation->ctx.md2 );
+            ret = mbedtls_md2_starts_ret( &operation->ctx.md2 );
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4)
+        case PSA_ALG_MD4:
+            mbedtls_md4_init( &operation->ctx.md4 );
+            ret = mbedtls_md4_starts_ret( &operation->ctx.md4 );
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
+        case PSA_ALG_MD5:
+            mbedtls_md5_init( &operation->ctx.md5 );
+            ret = mbedtls_md5_starts_ret( &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_ret( &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_ret( &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_ret( &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_ret( &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_ret( &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_ret( &operation->ctx.sha512, 0 );
+            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_MD2)
+        case PSA_ALG_MD2:
+            mbedtls_md2_clone( &target_operation->ctx.md2,
+                               &source_operation->ctx.md2 );
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4)
+        case PSA_ALG_MD4:
+            mbedtls_md4_clone( &target_operation->ctx.md4,
+                               &source_operation->ctx.md4 );
+            break;
+#endif
+#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
+        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_MD2)
+        case PSA_ALG_MD2:
+            ret = mbedtls_md2_update_ret( &operation->ctx.md2,
+                                          input, input_length );
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4)
+        case PSA_ALG_MD4:
+            ret = mbedtls_md4_update_ret( &operation->ctx.md4,
+                                          input, input_length );
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
+        case PSA_ALG_MD5:
+            ret = mbedtls_md5_update_ret( &operation->ctx.md5,
+                                          input, input_length );
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)
+        case PSA_ALG_RIPEMD160:
+            ret = mbedtls_ripemd160_update_ret( &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_ret( &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_ret( &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_ret( &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_ret( &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_ret( &operation->ctx.sha512,
+                                             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_MD2)
+        case PSA_ALG_MD2:
+            ret = mbedtls_md2_finish_ret( &operation->ctx.md2, hash );
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD4)
+        case PSA_ALG_MD4:
+            ret = mbedtls_md4_finish_ret( &operation->ctx.md4, hash );
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
+        case PSA_ALG_MD5:
+            ret = mbedtls_md5_finish_ret( &operation->ctx.md5, hash );
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)
+        case PSA_ALG_RIPEMD160:
+            ret = mbedtls_ripemd160_finish_ret( &operation->ctx.ripemd160, hash );
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)
+        case PSA_ALG_SHA_1:
+            ret = mbedtls_sha1_finish_ret( &operation->ctx.sha1, hash );
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)
+        case PSA_ALG_SHA_224:
+            ret = mbedtls_sha256_finish_ret( &operation->ctx.sha256, hash );
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)
+        case PSA_ALG_SHA_256:
+            ret = mbedtls_sha256_finish_ret( &operation->ctx.sha256, hash );
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)
+        case PSA_ALG_SHA_384:
+            ret = mbedtls_sha512_finish_ret( &operation->ctx.sha512, hash );
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)
+        case PSA_ALG_SHA_512:
+            ret = mbedtls_sha512_finish_ret( &operation->ctx.sha512, hash );
+            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/third_party/mbedtls/repo/library/psa_crypto_hash.h b/third_party/mbedtls/repo/library/psa_crypto_hash.h
new file mode 100644
index 0000000..6b27c9b
--- /dev/null
+++ b/third_party/mbedtls/repo/library/psa_crypto_hash.h
@@ -0,0 +1,234 @@
+/*
+ *  PSA hashing layer on top of Mbed TLS software crypto
+ */
+/*
+ *  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 PSA_CRYPTO_HASH_H
+#define PSA_CRYPTO_HASH_H
+
+#include <psa/crypto.h>
+
+#include <mbedtls/md_internal.h>
+
+/** Get Mbed TLS MD information of a hash algorithm given its PSA identifier
+ *
+ * \param[in] alg  PSA hash algorithm identifier
+ *
+ * \return  The Mbed TLS MD information of the hash algorithm. \c NULL if the
+ *          PSA hash algorithm is not supported.
+ */
+const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg );
+
+/** 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
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+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
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+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
+ * \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
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ */
+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
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+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 successfuly, 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
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+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
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+psa_status_t mbedtls_psa_hash_abort(
+    mbedtls_psa_hash_operation_t *operation );
+
+#endif /* PSA_CRYPTO_HASH_H */
diff --git a/third_party/mbedtls/repo/library/psa_crypto_invasive.h b/third_party/mbedtls/repo/library/psa_crypto_invasive.h
index 2b4ee1f..1e5a407 100644
--- a/third_party/mbedtls/repo/library/psa_crypto_invasive.h
+++ b/third_party/mbedtls/repo/library/psa_crypto_invasive.h
@@ -35,9 +35,11 @@
 #endif
 
 #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(),
@@ -73,5 +75,12 @@
 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 );
+#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_PSA_CRYPTO_C */
 
 #endif /* PSA_CRYPTO_INVASIVE_H */
diff --git a/third_party/mbedtls/repo/library/psa_crypto_its.h b/third_party/mbedtls/repo/library/psa_crypto_its.h
index 11703a0..3a3f49a 100644
--- a/third_party/mbedtls/repo/library/psa_crypto_its.h
+++ b/third_party/mbedtls/repo/library/psa_crypto_its.h
@@ -72,12 +72,12 @@
  *
  * \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_WRITE_ONCE_FLAG
- * \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`)
+ * \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_WRITE_ONCE_FLAG
+ * \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,
@@ -97,11 +97,11 @@
  *
  * \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_INVALID_SIZE       The operation failed because the data associated with provided uid is larger than `data_size`
- * \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`, `p_data_length`)
+ * \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.
  */
@@ -119,10 +119,10 @@
  *
  * \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_INVALID_ARGUMENT   The operation failed because one of the provided pointers(`p_info`)
+ * \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,
@@ -135,10 +135,10 @@
  *
  * \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_WRITE_ONCE_FLAG
- * \retval     #PSA_ERROR_STORAGE_FAILURE    The operation failed because the physical storage has failed (Fatal error)
+ * \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_WRITE_ONCE_FLAG
+ * \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);
 
diff --git a/third_party/mbedtls/repo/library/psa_crypto_mac.c b/third_party/mbedtls/repo/library/psa_crypto_mac.c
new file mode 100644
index 0000000..dcf065a
--- /dev/null
+++ b/third_party/mbedtls/repo/library/psa_crypto_mac.c
@@ -0,0 +1,499 @@
+/*
+ *  PSA MAC layer on top of Mbed TLS software crypto
+ */
+/*
+ *  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 "common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include <psa/crypto.h>
+#include "psa_crypto_core.h"
+#include "psa_crypto_mac.h"
+#include <mbedtls/md.h>
+
+#include <mbedtls/error.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_psa_safer_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/third_party/mbedtls/repo/library/psa_crypto_mac.h b/third_party/mbedtls/repo/library/psa_crypto_mac.h
new file mode 100644
index 0000000..a821e74
--- /dev/null
+++ b/third_party/mbedtls/repo/library/psa_crypto_mac.h
@@ -0,0 +1,276 @@
+/*
+ *  PSA MAC layer on top of Mbed TLS software crypto
+ */
+/*
+ *  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 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
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+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
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \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
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \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
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+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
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+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
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+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
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+psa_status_t mbedtls_psa_mac_abort(
+    mbedtls_psa_mac_operation_t *operation );
+
+#endif /* PSA_CRYPTO_MAC_H */
diff --git a/third_party/mbedtls/repo/library/psa_crypto_random_impl.h b/third_party/mbedtls/repo/library/psa_crypto_random_impl.h
new file mode 100644
index 0000000..3c4c09a
--- /dev/null
+++ b/third_party/mbedtls/repo/library/psa_crypto_random_impl.h
@@ -0,0 +1,205 @@
+/** \file psa_crypto_random_impl.h
+ *
+ * \brief PSA crypto random generator implementation abstraction.
+ *
+ * The definitions here need to be consistent with the declarations
+ * in include/mbedtls/psa_util.h. This file contains some redundant
+ * declarations to increase the chance that a compiler will detect
+ * inconsistencies if one file is changed without updating the other,
+ * but not all potential inconsistencies can be enforced, so make sure
+ * to check the public declarations and contracts in
+ * include/mbedtls/psa_util.h if you modify this file.
+ */
+/*
+ *  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 PSA_CRYPTO_RANDOM_IMPL_H
+#define PSA_CRYPTO_RANDOM_IMPL_H
+
+#include <mbedtls/psa_util.h>
+
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+
+#include <string.h>
+#include <mbedtls/entropy.h> // only for error codes
+#include <psa/crypto.h>
+
+typedef mbedtls_psa_external_random_context_t mbedtls_psa_random_context_t;
+
+/* Trivial wrapper around psa_generate_random(). */
+int mbedtls_psa_get_random( void *p_rng,
+                            unsigned char *output,
+                            size_t output_size );
+
+/* The PSA RNG API doesn't need any externally maintained state. */
+#define MBEDTLS_PSA_RANDOM_STATE NULL
+
+#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
+/* Choose a DRBG based on configuration and availability */
+#if defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE)
+
+#include "mbedtls/hmac_drbg.h"
+
+#elif defined(MBEDTLS_CTR_DRBG_C)
+
+#include "mbedtls/ctr_drbg.h"
+
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+
+#include "mbedtls/hmac_drbg.h"
+#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_SHA256_C)
+#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_SHA512_C)
+#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA512
+#elif defined(MBEDTLS_SHA256_C)
+#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256
+#else
+#error "No hash algorithm available for HMAC_DBRG."
+#endif
+
+#else
+#error "No DRBG module available for the psa_crypto module."
+#endif
+
+#include "mbedtls/entropy.h"
+
+/** 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
+}
+
+/** The type of the PSA random generator context.
+ *
+ * The random generator context is composed of an entropy context and
+ * a DRBG context.
+ */
+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;
+
+/* Defined in include/mbedtls/psa_util.h so that it's visible to
+ * application code. The declaration here is redundant, but included
+ * as a safety net to make it more likely that a future change that
+ * accidentally causes the implementation to diverge from the interface
+ * will be noticed. */
+/* Do not include the declaration under MSVC because it doesn't accept it
+ * ("error C2370: 'mbedtls_psa_get_random' : redefinition; different storage class").
+ * Observed with Visual Studio 2013. A known bug apparently:
+ * https://stackoverflow.com/questions/8146541/duplicate-external-static-declarations-not-allowed-in-visual-studio
+ */
+#if !defined(_MSC_VER)
+static mbedtls_f_rng_t *const mbedtls_psa_get_random;
+#endif
+
+/** 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
+
+/** A pointer to the PSA DRBG state.
+ *
+ * This variable is only intended to be used through the macro
+ * #MBEDTLS_PSA_RANDOM_STATE.
+ */
+/* psa_crypto.c sets this variable to a pointer to the DRBG state in the
+ * global PSA crypto state. */
+/* The type `mbedtls_psa_drbg_context_t` is defined in
+ * include/mbedtls/psa_util.h so that `mbedtls_psa_random_state` can be
+ * declared there and be visible to application code. */
+extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state;
+
+/** A pointer to the PSA DRBG state.
+ *
+ * This macro expands to an expression that is suitable as the \c p_rng
+ * parameter to pass to mbedtls_psa_get_random().
+ *
+ * This macro exists in all configurations where the psa_crypto module is
+ * enabled. Its expansion depends on the configuration.
+ */
+#define MBEDTLS_PSA_RANDOM_STATE mbedtls_psa_random_state
+
+/** 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_entropy_context *entropy,
+    const unsigned char *custom, size_t len )
+{
+#if defined(MBEDTLS_CTR_DRBG_C)
+    return( mbedtls_ctr_drbg_seed( MBEDTLS_PSA_RANDOM_STATE,
+                                   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( MBEDTLS_PSA_RANDOM_STATE,
+                                    md_info,
+                                    mbedtls_entropy_func,
+                                    entropy,
+                                    custom, len ) );
+#endif
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
+#endif /* PSA_CRYPTO_RANDOM_IMPL_H */
diff --git a/third_party/mbedtls/repo/library/psa_crypto_rsa.c b/third_party/mbedtls/repo/library/psa_crypto_rsa.c
new file mode 100644
index 0000000..bafb55c
--- /dev/null
+++ b/third_party/mbedtls/repo/library/psa_crypto_rsa.c
@@ -0,0 +1,530 @@
+/*
+ *  PSA RSA layer on top of Mbed TLS crypto
+ */
+/*
+ *  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 "common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include <psa/crypto.h>
+#include "psa_crypto_core.h"
+#include "psa_crypto_random_impl.h"
+#include "psa_crypto_rsa.h"
+#include "psa_crypto_hash.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include "mbedtls/platform.h"
+#if !defined(MBEDTLS_PLATFORM_C)
+#define mbedtls_calloc calloc
+#define mbedtls_free   free
+#endif
+
+#include <mbedtls/rsa.h>
+#include <mbedtls/error.h>
+#include <mbedtls/pk.h>
+#include <mbedtls/pk_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) || \
+    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;
+    mbedtls_pk_context ctx;
+    size_t bits;
+    mbedtls_pk_init( &ctx );
+
+    /* Parse the data. */
+    if( PSA_KEY_TYPE_IS_KEY_PAIR( type ) )
+        status = mbedtls_to_psa_error(
+            mbedtls_pk_parse_key( &ctx, data, data_length, NULL, 0 ) );
+    else
+        status = mbedtls_to_psa_error(
+            mbedtls_pk_parse_public_key( &ctx, data, data_length ) );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    /* We have something that the pkparse module recognizes. If it is a
+     * valid RSA key, store it. */
+    if( mbedtls_pk_get_type( &ctx ) != MBEDTLS_PK_RSA )
+    {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        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( mbedtls_pk_rsa( ctx ) ) );
+    if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS )
+    {
+        status = PSA_ERROR_NOT_SUPPORTED;
+        goto exit;
+    }
+    status = psa_check_rsa_key_byte_aligned( mbedtls_pk_rsa( ctx ) );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    /* Copy out the pointer to the RSA context, and reset the PK context
+     * such that pk_free doesn't free the RSA context we just grabbed. */
+    *p_rsa = mbedtls_pk_rsa( ctx );
+    ctx.pk_info = NULL;
+
+exit:
+    mbedtls_pk_free( &ctx );
+    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) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
+    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->core.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->core.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 );
+}
+
+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 )
+{
+#if defined(MBEDTLS_PK_WRITE_C)
+    int ret;
+    mbedtls_pk_context pk;
+    uint8_t *pos = data + data_size;
+
+    mbedtls_pk_init( &pk );
+    pk.pk_info = &mbedtls_rsa_info;
+    pk.pk_ctx = rsa;
+
+    /* 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_pk_write_key_der( &pk, data, data_size );
+    else
+        ret = mbedtls_pk_write_pubkey( &pos, data, &pk );
+
+    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 );
+#else
+    (void) type;
+    (void) rsa;
+    (void) data;
+    (void) data_size;
+    (void) data_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* MBEDTLS_PK_WRITE_C */
+}
+
+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->core.type, key_buffer, key_buffer_size, &rsa );
+    if( status != PSA_SUCCESS )
+        return( status );
+
+    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) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) && \
+    defined(MBEDTLS_GENPRIME)
+static psa_status_t psa_rsa_read_exponent( const uint8_t *domain_parameters,
+                                           size_t domain_parameters_size,
+                                           int *exponent )
+{
+    size_t i;
+    uint32_t acc = 0;
+
+    if( domain_parameters_size == 0 )
+    {
+        *exponent = 65537;
+        return( PSA_SUCCESS );
+    }
+
+    /* 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( domain_parameters_size > sizeof( acc ) )
+        return( PSA_ERROR_NOT_SUPPORTED );
+    for( i = 0; i < domain_parameters_size; i++ )
+        acc = ( acc << 8 ) | domain_parameters[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,
+    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;
+
+    status = psa_rsa_read_exponent( attributes->domain_parameters,
+                                    attributes->domain_parameters_size,
+                                    &exponent );
+    if( status != PSA_SUCCESS )
+        return( status );
+
+    mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE );
+    ret = mbedtls_rsa_gen_key( &rsa,
+                               mbedtls_psa_get_random,
+                               MBEDTLS_PSA_RANDOM_STATE,
+                               (unsigned int)attributes->core.bits,
+                               exponent );
+    if( ret != 0 )
+        return( mbedtls_to_psa_error( ret ) );
+
+    status = mbedtls_psa_rsa_export_key( attributes->core.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)
+        * defined(MBEDTLS_GENPRIME) */
+
+/****************************************************************/
+/* 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 );
+    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg );
+    *md_alg = mbedtls_md_get_type( md_info );
+
+    /* 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_info == NULL )
+            return( PSA_ERROR_NOT_SUPPORTED );
+        if( mbedtls_md_get_size( md_info ) != 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->core.type,
+                                                  key_buffer,
+                                                  key_buffer_size,
+                                                  &rsa );
+    if( status != PSA_SUCCESS )
+        return( status );
+
+    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 ) )
+    {
+        mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15,
+                                 MBEDTLS_MD_NONE );
+        ret = mbedtls_rsa_pkcs1_sign( rsa,
+                                      mbedtls_psa_get_random,
+                                      MBEDTLS_PSA_RANDOM_STATE,
+                                      MBEDTLS_RSA_PRIVATE,
+                                      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 ) )
+    {
+        mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg );
+        ret = mbedtls_rsa_rsassa_pss_sign( rsa,
+                                           mbedtls_psa_get_random,
+                                           MBEDTLS_PSA_RANDOM_STATE,
+                                           MBEDTLS_RSA_PRIVATE,
+                                           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->core.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 ) )
+    {
+        mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15,
+                                 MBEDTLS_MD_NONE );
+        ret = mbedtls_rsa_pkcs1_verify( rsa,
+                                        mbedtls_psa_get_random,
+                                        MBEDTLS_PSA_RANDOM_STATE,
+                                        MBEDTLS_RSA_PUBLIC,
+                                        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 ) )
+    {
+        int slen = rsa_pss_expected_salt_len( alg, rsa, hash_length );
+        mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg );
+        ret = mbedtls_rsa_rsassa_pss_verify_ext( rsa,
+                                                 mbedtls_psa_get_random,
+                                                 MBEDTLS_PSA_RANDOM_STATE,
+                                                 MBEDTLS_RSA_PUBLIC,
+                                                 md_alg,
+                                                 (unsigned int) 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) */
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/third_party/mbedtls/repo/library/psa_crypto_rsa.h b/third_party/mbedtls/repo/library/psa_crypto_rsa.h
new file mode 100644
index 0000000..b76613e
--- /dev/null
+++ b/third_party/mbedtls/repo/library/psa_crypto_rsa.h
@@ -0,0 +1,215 @@
+/*
+ *  PSA RSA layer on top of Mbed TLS crypto
+ */
+/*
+ *  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 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
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+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
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ */
+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.
+ *
+ * \note The signature of the function is that of a PSA driver generate_key
+ *       entry point.
+ *
+ * \param[in]  attributes         The attributes for the RSA 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_rsa_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 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
+ * \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
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
+ */
+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
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ */
+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 );
+
+#endif /* PSA_CRYPTO_RSA_H */
diff --git a/third_party/mbedtls/repo/library/psa_crypto_se.h b/third_party/mbedtls/repo/library/psa_crypto_se.h
index 67fadf8..7104261 100644
--- a/third_party/mbedtls/repo/library/psa_crypto_se.h
+++ b/third_party/mbedtls/repo/library/psa_crypto_se.h
@@ -155,6 +155,13 @@
  *
  * \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 );
@@ -163,6 +170,14 @@
  *
  * \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 );
diff --git a/third_party/mbedtls/repo/library/psa_crypto_service_integration.h b/third_party/mbedtls/repo/library/psa_crypto_service_integration.h
deleted file mode 100644
index 87889af..0000000
--- a/third_party/mbedtls/repo/library/psa_crypto_service_integration.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  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 PSA_CRYPTO_SERVICE_INTEGRATION_H
-#define PSA_CRYPTO_SERVICE_INTEGRATION_H
-
-/*
- * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is being built for SPM
- * (Secure Partition Manager) integration which separates the code into two
- * parts: NSPE (Non-Secure Processing Environment) and SPE (Secure Processing
- * Environment). When building for the SPE, an additional header file should be
- * included.
- */
-#if defined(MBEDTLS_PSA_CRYPTO_SPM)
-/*
- * PSA_CRYPTO_SECURE means that the file which included this file is being
- * compiled for SPE. The files crypto_structs.h and crypto_types.h have
- * different implementations for NSPE and SPE and are compiled according to this
- * flag.
- */
-#define PSA_CRYPTO_SECURE 1
-#include "crypto_spe.h"
-#endif // MBEDTLS_PSA_CRYPTO_SPM
-
-#endif // PSA_CRYPTO_SERVICE_INTEGRATION_H
diff --git a/third_party/mbedtls/repo/library/psa_crypto_slot_management.c b/third_party/mbedtls/repo/library/psa_crypto_slot_management.c
index 4c4ad03..6f69fc8 100644
--- a/third_party/mbedtls/repo/library/psa_crypto_slot_management.c
+++ b/third_party/mbedtls/repo/library/psa_crypto_slot_management.c
@@ -22,10 +22,10 @@
 
 #if defined(MBEDTLS_PSA_CRYPTO_C)
 
-#include "psa_crypto_service_integration.h"
 #include "psa/crypto.h"
 
 #include "psa_crypto_core.h"
+#include "psa_crypto_driver_wrappers.h"
 #include "psa_crypto_slot_management.h"
 #include "psa_crypto_storage.h"
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
@@ -45,27 +45,26 @@
 
 typedef struct
 {
-    psa_key_slot_t key_slots[PSA_KEY_SLOT_COUNT];
+    psa_key_slot_t key_slots[MBEDTLS_PSA_KEY_SLOT_COUNT];
     unsigned key_slots_initialized : 1;
 } psa_global_data_t;
 
 static psa_global_data_t global_data;
 
-psa_status_t psa_validate_key_id(
-    mbedtls_svc_key_id_t key, int vendor_ok )
+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( PSA_SUCCESS );
+        return( 1 );
 
     if( vendor_ok &&
         ( PSA_KEY_ID_VENDOR_MIN <= key_id ) &&
         ( key_id <= PSA_KEY_ID_VENDOR_MAX ) )
-        return( PSA_SUCCESS );
+        return( 1 );
 
-    return( PSA_ERROR_INVALID_HANDLE );
+    return( 0 );
 }
 
 /** Get the description in memory of a key given its identifier and lock it.
@@ -124,17 +123,16 @@
     }
     else
     {
-        status = psa_validate_key_id( key, 1 );
-        if( status != PSA_SUCCESS )
-            return( status );
+        if ( !psa_is_valid_key_id( key, 1 ) )
+            return( PSA_ERROR_INVALID_HANDLE );
 
-        for( slot_idx = 0; slot_idx < PSA_KEY_SLOT_COUNT; slot_idx++ )
+        for( slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++ )
         {
             slot = &global_data.key_slots[ slot_idx ];
             if( mbedtls_svc_key_id_equal( key, slot->attr.id ) )
                 break;
         }
-        status = ( slot_idx < PSA_KEY_SLOT_COUNT ) ?
+        status = ( slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT ) ?
                  PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST;
     }
 
@@ -161,7 +159,7 @@
 {
     size_t slot_idx;
 
-    for( slot_idx = 0; slot_idx < PSA_KEY_SLOT_COUNT; slot_idx++ )
+    for( slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++ )
     {
         psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ];
         slot->lock_count = 1;
@@ -184,7 +182,7 @@
     }
 
     selected_slot = unlocked_persistent_key_slot = NULL;
-    for( slot_idx = 0; slot_idx < PSA_KEY_SLOT_COUNT; slot_idx++ )
+    for( slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++ )
     {
         psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ];
         if( ! psa_is_key_slot_occupied( slot ) )
@@ -248,25 +246,27 @@
         goto exit;
 
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    if( psa_key_lifetime_is_external( slot->attr.lifetime ) )
+    /* 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_STORAGE_FAILURE;
+            status = PSA_ERROR_DATA_INVALID;
             goto exit;
         }
         data = (psa_se_key_data_storage_t *) key_data;
-        memcpy( &slot->data.se.slot_number, &data->slot_number,
-                sizeof( slot->data.se.slot_number ) );
+        status = psa_copy_key_material_into_slot(
+                     slot, data->slot_number, sizeof( data->slot_number ) );
+        goto exit;
     }
-    else
 #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;
-    }
+
+    status = psa_copy_key_material_into_slot( slot, key_data, key_data_length );
 
 exit:
     psa_free_persistent_key_data( key_data, key_data_length );
@@ -274,6 +274,77 @@
 }
 #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.core;
+
+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 )
 {
@@ -291,25 +362,43 @@
     if( status != PSA_ERROR_DOES_NOT_EXIST )
         return( status );
 
-#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+    /* Loading keys from storage requires support for such a mechanism */
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \
+    defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
     psa_key_id_t volatile_key_id;
 
     status = psa_get_empty_key_slot( &volatile_key_id, p_slot );
     if( status != PSA_SUCCESS )
         return( status );
 
-    (*p_slot)->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT;
     (*p_slot)->attr.id = key;
+    (*p_slot)->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT;
 
-    status = psa_load_persistent_key_into_slot( *p_slot );
-    if( status != PSA_SUCCESS )
-        psa_wipe_key_slot( *p_slot );
+    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 */
 
-    return( status );
-#else
-    return( PSA_ERROR_DOES_NOT_EXIST );
+#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( 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 );
+
+    return( status );
+#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
+    return( PSA_ERROR_INVALID_HANDLE );
+#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
 }
 
 psa_status_t psa_unlock_key_slot( psa_key_slot_t *slot )
@@ -343,19 +432,26 @@
     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 )
-            return( PSA_ERROR_INVALID_ARGUMENT );
-        else
+        if( driver != NULL )
         {
             if (p_drv != NULL)
                 *p_drv = driver;
             return( PSA_SUCCESS );
         }
-#else
+#else /* MBEDTLS_PSA_CRYPTO_SE_C */
         (void) p_drv;
-        return( PSA_ERROR_INVALID_ARGUMENT );
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS)
+        /* Key location for external keys gets checked by the wrapper */
+        return( PSA_SUCCESS );
+#else /* MBEDTLS_PSA_CRYPTO_DRIVERS */
+        /* No support for external lifetimes at all, or dynamic interface
+         * did not find driver for requested lifetime. */
+        return( PSA_ERROR_INVALID_ARGUMENT );
+#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */
     }
     else
         /* Local/internal keys are always valid */
@@ -373,7 +469,10 @@
     {
         /* Persistent keys require storage support */
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-        return( PSA_SUCCESS );
+        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 */
@@ -382,7 +481,8 @@
 
 psa_status_t psa_open_key( mbedtls_svc_key_id_t key, psa_key_handle_t *handle )
 {
-#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \
+    defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
     psa_status_t status;
     psa_key_slot_t *slot;
 
@@ -390,6 +490,9 @@
     if( status != PSA_SUCCESS )
     {
         *handle = PSA_KEY_HANDLE_INIT;
+        if( status == PSA_ERROR_INVALID_HANDLE )
+            status = PSA_ERROR_DOES_NOT_EXIST;
+
         return( status );
     }
 
@@ -397,11 +500,11 @@
 
     return( psa_unlock_key_slot( slot ) );
 
-#else /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
+#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
     (void) key;
     *handle = PSA_KEY_HANDLE_INIT;
     return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* !defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
+#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
 }
 
 psa_status_t psa_close_key( psa_key_handle_t handle )
@@ -414,8 +517,12 @@
 
     status = psa_get_and_lock_key_slot_in_memory( handle, &slot );
     if( status != PSA_SUCCESS )
-        return( status );
+    {
+        if( status == PSA_ERROR_DOES_NOT_EXIST )
+            status = PSA_ERROR_INVALID_HANDLE;
 
+        return( status );
+    }
     if( slot->lock_count <= 1 )
         return( psa_wipe_key_slot( slot ) );
     else
@@ -444,7 +551,7 @@
 
     memset( stats, 0, sizeof( *stats ) );
 
-    for( slot_idx = 0; slot_idx < PSA_KEY_SLOT_COUNT; slot_idx++ )
+    for( slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++ )
     {
         const psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ];
         if( psa_is_key_slot_locked( slot ) )
@@ -456,16 +563,17 @@
             ++stats->empty_slots;
             continue;
         }
-        if( slot->attr.lifetime == PSA_KEY_LIFETIME_VOLATILE )
+        if( PSA_KEY_LIFETIME_IS_VOLATILE( slot->attr.lifetime ) )
             ++stats->volatile_slots;
-        else if( slot->attr.lifetime == PSA_KEY_LIFETIME_PERSISTENT )
+        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;
         }
-        else
+        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;
diff --git a/third_party/mbedtls/repo/library/psa_crypto_slot_management.h b/third_party/mbedtls/repo/library/psa_crypto_slot_management.h
index ef0814a..d539bdd 100644
--- a/third_party/mbedtls/repo/library/psa_crypto_slot_management.h
+++ b/third_party/mbedtls/repo/library/psa_crypto_slot_management.h
@@ -25,14 +25,10 @@
 #include "psa_crypto_core.h"
 #include "psa_crypto_se.h"
 
-/* Number of key slots (plus one because 0 is not used).
- * The value is a compile-time constant for now, for simplicity. */
-#define PSA_KEY_SLOT_COUNT 32
-
 /** Range of volatile key identifiers.
  *
- *  The last PSA_KEY_SLOT_COUNT identifiers of the implementation range
- *  of key identifiers are reserved for volatile key identifiers.
+ *  The last #MBEDTLS_PSA_KEY_SLOT_COUNT identifiers of the implementation
+ *  range of key identifiers are reserved for volatile key identifiers.
  *  A volatile key identifier is equal to #PSA_KEY_ID_VOLATILE_MIN plus the
  *  index of the key slot containing the volatile key definition.
  */
@@ -40,7 +36,7 @@
 /** The minimum value for a volatile key identifier.
  */
 #define PSA_KEY_ID_VOLATILE_MIN  ( PSA_KEY_ID_VENDOR_MAX - \
-                                   PSA_KEY_SLOT_COUNT + 1 )
+                                   MBEDTLS_PSA_KEY_SLOT_COUNT + 1 )
 
 /** The maximum value for a volatile key identifier.
  */
@@ -209,8 +205,8 @@
  * \param[in] lifetime  The key lifetime attribute.
  *
  * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_ARGUMENT The key is persistent but persistent
- *         keys are not supported.
+ * \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 );
 
@@ -221,9 +217,8 @@
  *                          vendor range are allowed, volatile key identifiers
  *                          excepted \c 0 otherwise.
  *
- * \retval #PSA_SUCCESS The identifier is valid.
- * \retval #PSA_ERROR_INVALID_ARGUMENT The key identifier is not valid.
+ * \retval <> 0 if the key identifier is valid, 0 otherwise.
  */
-psa_status_t psa_validate_key_id( mbedtls_svc_key_id_t key, int vendor_ok );
+int psa_is_valid_key_id( mbedtls_svc_key_id_t key, int vendor_ok );
 
 #endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */
diff --git a/third_party/mbedtls/repo/library/psa_crypto_storage.c b/third_party/mbedtls/repo/library/psa_crypto_storage.c
index 1ebd20e..b485c50 100644
--- a/third_party/mbedtls/repo/library/psa_crypto_storage.c
+++ b/third_party/mbedtls/repo/library/psa_crypto_storage.c
@@ -18,18 +18,13 @@
  *  limitations under the License.
  */
 
-#if defined(MBEDTLS_CONFIG_FILE)
-#include MBEDTLS_CONFIG_FILE
-#else
-#include "mbedtls/config.h"
-#endif
+#include "common.h"
 
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
 
 #include <stdlib.h>
 #include <string.h>
 
-#include "psa_crypto_service_integration.h"
 #include "psa/crypto.h"
 #include "psa_crypto_storage.h"
 #include "mbedtls/platform_util.h"
@@ -49,8 +44,6 @@
 #define mbedtls_free     free
 #endif
 
-
-
 /****************************************************************/
 /* Key storage */
 /****************************************************************/
@@ -91,6 +84,8 @@
  * \param data_size         Size of the \c data buffer in bytes.
  *
  * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_DATA_CORRUPT
  * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_DOES_NOT_EXIST
  */
@@ -108,7 +103,7 @@
 
     status = psa_its_get( data_identifier, 0, (uint32_t) data_size, data, &data_length );
     if( data_size  != data_length )
-        return( PSA_ERROR_STORAGE_FAILURE );
+        return( PSA_ERROR_DATA_INVALID );
 
     return( status );
 }
@@ -139,8 +134,9 @@
  *
  * \retval #PSA_SUCCESS
  * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
- * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_ALREADY_EXISTS
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_DATA_INVALID
  */
 static psa_status_t psa_crypto_storage_store( const mbedtls_svc_key_id_t key,
                                               const uint8_t *data,
@@ -156,7 +152,7 @@
     status = psa_its_set( data_identifier, (uint32_t) data_length, data, 0 );
     if( status != PSA_SUCCESS )
     {
-        return( PSA_ERROR_STORAGE_FAILURE );
+        return( PSA_ERROR_DATA_INVALID );
     }
 
     status = psa_its_get_info( data_identifier, &data_identifier_info );
@@ -167,7 +163,7 @@
 
     if( data_identifier_info.size != data_length )
     {
-        status = PSA_ERROR_STORAGE_FAILURE;
+        status = PSA_ERROR_DATA_INVALID;
         goto exit;
     }
 
@@ -194,11 +190,11 @@
         return( PSA_SUCCESS );
 
     if( psa_its_remove( data_identifier ) != PSA_SUCCESS )
-        return( PSA_ERROR_STORAGE_FAILURE );
+        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_STORAGE_FAILURE );
+        return( PSA_ERROR_DATA_INVALID );
 
     return( PSA_SUCCESS );
 }
@@ -212,6 +208,8 @@
  *
  * \retval #PSA_SUCCESS
  * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_DOES_NOT_EXIST
+ * \retval #PSA_ERROR_DATA_CORRUPT
  */
 static psa_status_t psa_crypto_storage_get_data_length(
     const mbedtls_svc_key_id_t key,
@@ -230,48 +228,6 @@
     return( PSA_SUCCESS );
 }
 
-/*
- * 32-bit integer manipulation macros (little endian)
- */
-#ifndef GET_UINT32_LE
-#define GET_UINT32_LE( n, b, i )                        \
-{                                                       \
-    (n) = ( (uint32_t) (b)[(i)    ]       )             \
-        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \
-        | ( (uint32_t) (b)[(i) + 2] << 16 )             \
-        | ( (uint32_t) (b)[(i) + 3] << 24 );            \
-}
-#endif
-
-#ifndef PUT_UINT32_LE
-#define PUT_UINT32_LE( n, b, i )                                \
-{                                                               \
-    (b)[(i)    ] = (unsigned char) ( ( (n)       ) & 0xFF );    \
-    (b)[(i) + 1] = (unsigned char) ( ( (n) >>  8 ) & 0xFF );    \
-    (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF );    \
-    (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF );    \
-}
-#endif
-
-/*
- * 16-bit integer manipulation macros (little endian)
- */
-#ifndef GET_UINT16_LE
-#define GET_UINT16_LE( n, b, i )                        \
-{                                                       \
-    (n) = ( (uint16_t) (b)[(i)    ]       )             \
-        | ( (uint16_t) (b)[(i) + 1] <<  8 );            \
-}
-#endif
-
-#ifndef PUT_UINT16_LE
-#define PUT_UINT16_LE( n, b, i )                                \
-{                                                               \
-    (b)[(i)    ] = (unsigned char) ( ( (n)       ) & 0xFF );    \
-    (b)[(i) + 1] = (unsigned char) ( ( (n) >>  8 ) & 0xFF );    \
-}
-#endif
-
 /**
  * Persistent key storage magic header.
  */
@@ -298,14 +254,14 @@
         (psa_persistent_key_storage_format *) storage_data;
 
     memcpy( storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH );
-    PUT_UINT32_LE( 0, storage_format->version, 0 );
-    PUT_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 );
-    PUT_UINT16_LE( (uint16_t) attr->type, storage_format->type, 0 );
-    PUT_UINT16_LE( (uint16_t) attr->bits, storage_format->bits, 0 );
-    PUT_UINT32_LE( attr->policy.usage, storage_format->policy, 0 );
-    PUT_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) );
-    PUT_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) );
-    PUT_UINT32_LE( data_length, storage_format->data_len, 0 );
+    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 );
 }
 
@@ -313,7 +269,7 @@
 {
     if( memcmp( data, PSA_KEY_STORAGE_MAGIC_HEADER,
                 PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ) != 0 )
-        return( PSA_ERROR_STORAGE_FAILURE );
+        return( PSA_ERROR_DATA_INVALID );
     return( PSA_SUCCESS );
 }
 
@@ -329,20 +285,20 @@
     uint32_t version;
 
     if( storage_data_length < sizeof(*storage_format) )
-        return( PSA_ERROR_STORAGE_FAILURE );
+        return( PSA_ERROR_DATA_INVALID );
 
     status = check_magic_header( storage_data );
     if( status != PSA_SUCCESS )
         return( status );
 
-    GET_UINT32_LE( version, storage_format->version, 0 );
+    version = MBEDTLS_GET_UINT32_LE( storage_format->version, 0 );
     if( version != 0 )
-        return( PSA_ERROR_STORAGE_FAILURE );
+        return( PSA_ERROR_DATA_INVALID );
 
-    GET_UINT32_LE( *key_data_length, storage_format->data_len, 0 );
+    *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_STORAGE_FAILURE );
+        return( PSA_ERROR_DATA_INVALID );
 
     if( *key_data_length == 0 )
     {
@@ -356,12 +312,12 @@
         memcpy( *key_data, storage_format->key_data, *key_data_length );
     }
 
-    GET_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 );
-    GET_UINT16_LE( attr->type, storage_format->type, 0 );
-    GET_UINT16_LE( attr->bits, storage_format->bits, 0 );
-    GET_UINT32_LE( attr->policy.usage, storage_format->policy, 0 );
-    GET_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) );
-    GET_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) );
+    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 );
 }
@@ -374,8 +330,12 @@
     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;
+        return( PSA_ERROR_INSUFFICIENT_STORAGE );
     storage_data_length = data_length + sizeof( psa_persistent_key_storage_format );
 
     storage_data = mbedtls_calloc( 1, storage_data_length );
@@ -426,6 +386,11 @@
     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_free( loaded_data );
     return( status );
@@ -470,7 +435,7 @@
     if( status != PSA_SUCCESS )
         return( status );
     if( length != sizeof( psa_crypto_transaction ) )
-        return( PSA_ERROR_STORAGE_FAILURE );
+        return( PSA_ERROR_DATA_INVALID );
     return( PSA_SUCCESS );
 }
 
diff --git a/third_party/mbedtls/repo/library/psa_crypto_storage.h b/third_party/mbedtls/repo/library/psa_crypto_storage.h
index fbc94fc..970e108 100644
--- a/third_party/mbedtls/repo/library/psa_crypto_storage.h
+++ b/third_party/mbedtls/repo/library/psa_crypto_storage.h
@@ -49,7 +49,7 @@
  * - 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 #PSA_KEY_SLOT_COUNT are actually used.
+ * - 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.
@@ -86,6 +86,9 @@
  * 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
@@ -94,10 +97,13 @@
  * \param data_length       The number of bytes that make up the key data.
  *
  * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
  * \retval #PSA_ERROR_STORAGE_FAILURE
  * \retval #PSA_ERROR_ALREADY_EXISTS
+ * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_DATA_CORRUPT
  */
 psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr,
                                       const uint8_t *data,
@@ -111,9 +117,10 @@
  * 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. psa_free_persistent_key_data() must be called after
- * this function to zeroize and free this buffer, regardless of whether this
- * function succeeds or fails.
+ * 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.
@@ -124,7 +131,8 @@
  *
  * \retval #PSA_SUCCESS
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_DATA_CORRUPT
  * \retval #PSA_ERROR_DOES_NOT_EXIST
  */
 psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr,
@@ -140,7 +148,7 @@
  * \retval #PSA_SUCCESS
  *         The key was successfully removed,
  *         or the key did not exist.
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_DATA_INVALID
  */
 psa_status_t psa_destroy_persistent_key( const mbedtls_svc_key_id_t key );
 
@@ -183,9 +191,8 @@
  *                             with the loaded key metadata.
  *
  * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_DATA_INVALID
  */
 psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
                                               size_t storage_data_length,
@@ -319,6 +326,7 @@
  * atomically update the transaction state.
  *
  * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_DATA_CORRUPT
  * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
  * \retval #PSA_ERROR_STORAGE_FAILURE
  */
@@ -335,6 +343,8 @@
  * \retval #PSA_ERROR_DOES_NOT_EXIST
  *         There is no ongoing transaction.
  * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_DATA_INVALID
+ * \retval #PSA_ERROR_DATA_CORRUPT
  */
 psa_status_t psa_crypto_load_transaction( void );
 
diff --git a/third_party/mbedtls/repo/library/psa_its_file.c b/third_party/mbedtls/repo/library/psa_its_file.c
index 2fbff20..c4782cd 100644
--- a/third_party/mbedtls/repo/library/psa_its_file.c
+++ b/third_party/mbedtls/repo/library/psa_its_file.c
@@ -18,11 +18,7 @@
  *  limitations under the License.
  */
 
-#if defined(MBEDTLS_CONFIG_FILE)
-#include MBEDTLS_CONFIG_FILE
-#else
-#include "mbedtls/config.h"
-#endif
+#include "common.h"
 
 #if defined(MBEDTLS_PSA_ITS_FILE_C)
 
@@ -47,7 +43,7 @@
 #define PSA_ITS_STORAGE_PREFIX ""
 #endif
 
-#define PSA_ITS_STORAGE_FILENAME_PATTERN "%08lx%08lx"
+#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*/ \
@@ -87,8 +83,8 @@
     mbedtls_snprintf( filename, PSA_ITS_STORAGE_FILENAME_LENGTH,
                       "%s" PSA_ITS_STORAGE_FILENAME_PATTERN "%s",
                       PSA_ITS_STORAGE_PREFIX,
-                      (unsigned long) ( uid >> 32 ),
-                      (unsigned long) ( uid & 0xffffffff ),
+                      (unsigned) ( uid >> 32 ),
+                      (unsigned) ( uid & 0xffffffff ),
                       PSA_ITS_STORAGE_SUFFIX );
 }
 
@@ -195,14 +191,8 @@
     size_t n;
 
     memcpy( header.magic, PSA_ITS_MAGIC_STRING, PSA_ITS_MAGIC_LENGTH );
-    header.size[0] = data_length & 0xff;
-    header.size[1] = ( data_length >> 8 ) & 0xff;
-    header.size[2] = ( data_length >> 16 ) & 0xff;
-    header.size[3] = ( data_length >> 24 ) & 0xff;
-    header.flags[0] = create_flags & 0xff;
-    header.flags[1] = ( create_flags >> 8 ) & 0xff;
-    header.flags[2] = ( create_flags >> 16 ) & 0xff;
-    header.flags[3] = ( create_flags >> 24 ) & 0xff;
+    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" );
diff --git a/third_party/mbedtls/repo/library/ripemd160.c b/third_party/mbedtls/repo/library/ripemd160.c
index ae4dee4..aed7322 100644
--- a/third_party/mbedtls/repo/library/ripemd160.c
+++ b/third_party/mbedtls/repo/library/ripemd160.c
@@ -44,29 +44,6 @@
 
 #if !defined(MBEDTLS_RIPEMD160_ALT)
 
-/*
- * 32-bit integer manipulation macros (little endian)
- */
-#ifndef GET_UINT32_LE
-#define GET_UINT32_LE(n,b,i)                            \
-{                                                       \
-    (n) = ( (uint32_t) (b)[(i)    ]       )             \
-        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \
-        | ( (uint32_t) (b)[(i) + 2] << 16 )             \
-        | ( (uint32_t) (b)[(i) + 3] << 24 );            \
-}
-#endif
-
-#ifndef PUT_UINT32_LE
-#define PUT_UINT32_LE(n,b,i)                                    \
-{                                                               \
-    (b)[(i)    ] = (unsigned char) ( ( (n)       ) & 0xFF );    \
-    (b)[(i) + 1] = (unsigned char) ( ( (n) >>  8 ) & 0xFF );    \
-    (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF );    \
-    (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF );    \
-}
-#endif
-
 void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx )
 {
     memset( ctx, 0, sizeof( mbedtls_ripemd160_context ) );
@@ -122,22 +99,22 @@
         uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16];
     } local;
 
-    GET_UINT32_LE( local.X[ 0], data,  0 );
-    GET_UINT32_LE( local.X[ 1], data,  4 );
-    GET_UINT32_LE( local.X[ 2], data,  8 );
-    GET_UINT32_LE( local.X[ 3], data, 12 );
-    GET_UINT32_LE( local.X[ 4], data, 16 );
-    GET_UINT32_LE( local.X[ 5], data, 20 );
-    GET_UINT32_LE( local.X[ 6], data, 24 );
-    GET_UINT32_LE( local.X[ 7], data, 28 );
-    GET_UINT32_LE( local.X[ 8], data, 32 );
-    GET_UINT32_LE( local.X[ 9], data, 36 );
-    GET_UINT32_LE( local.X[10], data, 40 );
-    GET_UINT32_LE( local.X[11], data, 44 );
-    GET_UINT32_LE( local.X[12], data, 48 );
-    GET_UINT32_LE( local.X[13], data, 52 );
-    GET_UINT32_LE( local.X[14], data, 56 );
-    GET_UINT32_LE( local.X[15], data, 60 );
+    local.X[ 0] = MBEDTLS_GET_UINT32_LE( data,  0 );
+    local.X[ 1] = MBEDTLS_GET_UINT32_LE( data,  4 );
+    local.X[ 2] = MBEDTLS_GET_UINT32_LE( data,  8 );
+    local.X[ 3] = MBEDTLS_GET_UINT32_LE( data, 12 );
+    local.X[ 4] = MBEDTLS_GET_UINT32_LE( data, 16 );
+    local.X[ 5] = MBEDTLS_GET_UINT32_LE( data, 20 );
+    local.X[ 6] = MBEDTLS_GET_UINT32_LE( data, 24 );
+    local.X[ 7] = MBEDTLS_GET_UINT32_LE( data, 28 );
+    local.X[ 8] = MBEDTLS_GET_UINT32_LE( data, 32 );
+    local.X[ 9] = MBEDTLS_GET_UINT32_LE( data, 36 );
+    local.X[10] = MBEDTLS_GET_UINT32_LE( data, 40 );
+    local.X[11] = MBEDTLS_GET_UINT32_LE( data, 44 );
+    local.X[12] = MBEDTLS_GET_UINT32_LE( data, 48 );
+    local.X[13] = MBEDTLS_GET_UINT32_LE( data, 52 );
+    local.X[14] = MBEDTLS_GET_UINT32_LE( data, 56 );
+    local.X[15] = MBEDTLS_GET_UINT32_LE( data, 60 );
 
     local.A = local.Ap = ctx->state[0];
     local.B = local.Bp = ctx->state[1];
@@ -400,8 +377,8 @@
          | ( ctx->total[1] <<  3 );
     low  = ( ctx->total[0] <<  3 );
 
-    PUT_UINT32_LE( low,  msglen, 0 );
-    PUT_UINT32_LE( high, msglen, 4 );
+    MBEDTLS_PUT_UINT32_LE( low,  msglen, 0 );
+    MBEDTLS_PUT_UINT32_LE( high, msglen, 4 );
 
     last = ctx->total[0] & 0x3F;
     padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
@@ -414,11 +391,11 @@
     if( ret != 0 )
         return( ret );
 
-    PUT_UINT32_LE( ctx->state[0], output,  0 );
-    PUT_UINT32_LE( ctx->state[1], output,  4 );
-    PUT_UINT32_LE( ctx->state[2], output,  8 );
-    PUT_UINT32_LE( ctx->state[3], output, 12 );
-    PUT_UINT32_LE( ctx->state[4], output, 16 );
+    MBEDTLS_PUT_UINT32_LE( ctx->state[0], output,  0 );
+    MBEDTLS_PUT_UINT32_LE( ctx->state[1], output,  4 );
+    MBEDTLS_PUT_UINT32_LE( ctx->state[2], output,  8 );
+    MBEDTLS_PUT_UINT32_LE( ctx->state[3], output, 12 );
+    MBEDTLS_PUT_UINT32_LE( ctx->state[4], output, 16 );
 
     return( 0 );
 }
diff --git a/third_party/mbedtls/repo/library/rsa.c b/third_party/mbedtls/repo/library/rsa.c
index d6abd65..8a5d40f 100644
--- a/third_party/mbedtls/repo/library/rsa.c
+++ b/third_party/mbedtls/repo/library/rsa.c
@@ -44,6 +44,8 @@
 #include "mbedtls/oid.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
+#include "constant_time_internal.h"
+#include "mbedtls/constant_time.h"
 
 #include <string.h>
 
@@ -72,22 +74,6 @@
 #define RSA_VALIDATE( cond )                                           \
     MBEDTLS_INTERNAL_VALIDATE( cond )
 
-#if defined(MBEDTLS_PKCS1_V15)
-/* constant-time buffer comparison */
-static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n )
-{
-    size_t i;
-    const unsigned char *A = (const unsigned char *) a;
-    const unsigned char *B = (const unsigned char *) b;
-    unsigned char diff = 0;
-
-    for( i = 0; i < n; i++ )
-        diff |= A[i] ^ B[i];
-
-    return( diff );
-}
-#endif /* MBEDTLS_PKCS1_V15 */
-
 int mbedtls_rsa_import( mbedtls_rsa_context *ctx,
                         const mbedtls_mpi *N,
                         const mbedtls_mpi *P, const mbedtls_mpi *Q,
@@ -102,7 +88,7 @@
         ( D != NULL && ( ret = mbedtls_mpi_copy( &ctx->D, D ) ) != 0 ) ||
         ( E != NULL && ( ret = mbedtls_mpi_copy( &ctx->E, E ) ) != 0 ) )
     {
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) );
     }
 
     if( N != NULL )
@@ -142,7 +128,7 @@
 cleanup:
 
     if( ret != 0 )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) );
 
     return( 0 );
 }
@@ -293,7 +279,7 @@
         if( ( ret = mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P,
                                          &ctx->Q ) ) != 0 )
         {
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) );
         }
 
         ctx->len = mbedtls_mpi_size( &ctx->N );
@@ -308,7 +294,7 @@
         ret = mbedtls_rsa_deduce_primes( &ctx->N, &ctx->E, &ctx->D,
                                          &ctx->P, &ctx->Q );
         if( ret != 0 )
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) );
 
     }
     else if( d_missing )
@@ -318,7 +304,7 @@
                                                          &ctx->E,
                                                          &ctx->D ) ) != 0 )
         {
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) );
         }
     }
 
@@ -333,7 +319,7 @@
         ret = mbedtls_rsa_deduce_crt( &ctx->P,  &ctx->Q,  &ctx->D,
                                       &ctx->DP, &ctx->DQ, &ctx->QP );
         if( ret != 0 )
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) );
     }
 #endif /* MBEDTLS_RSA_NO_CRT */
 
@@ -461,13 +447,13 @@
         ( DQ != NULL && ( ret = mbedtls_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) ||
         ( QP != NULL && ( ret = mbedtls_mpi_copy( QP, &ctx->QP ) ) != 0 ) )
     {
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) );
     }
 #else
     if( ( ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
                                         DP, DQ, QP ) ) != 0 )
     {
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) );
     }
 #endif
 
@@ -490,6 +476,9 @@
     mbedtls_rsa_set_padding( ctx, padding, hash_id );
 
 #if defined(MBEDTLS_THREADING_C)
+    /* Set ctx->ver to nonzero to indicate that the mutex has been
+     * initialized and will need to be freed. */
+    ctx->ver = 1;
     mbedtls_mutex_init( &ctx->mutex );
 #endif
 }
@@ -537,9 +526,6 @@
     RSA_VALIDATE_RET( ctx != NULL );
     RSA_VALIDATE_RET( f_rng != NULL );
 
-    if( nbits < 128 || exponent < 3 || nbits % 2 != 0 )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
     /*
      * If the modulus is 1024 bit long or shorter, then the security strength of
      * the RSA algorithm is less than or equal to 80 bits and therefore an error
@@ -552,6 +538,12 @@
     mbedtls_mpi_init( &G );
     mbedtls_mpi_init( &L );
 
+    if( nbits < 128 || exponent < 3 || nbits % 2 != 0 )
+    {
+        ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+        goto cleanup;
+    }
+
     /*
      * find primes P and Q with Q < P so that:
      * 1.  |P-Q| > 2^( nbits / 2 - 100 )
@@ -629,7 +621,10 @@
     if( ret != 0 )
     {
         mbedtls_rsa_free( ctx );
-        return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret );
+
+        if( ( -ret & ~0x7f ) == 0 )
+            ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_KEY_GEN_FAILED, ret );
+        return( ret );
     }
 
     return( 0 );
@@ -761,7 +756,7 @@
     mbedtls_mpi_free( &T );
 
     if( ret != 0 )
-        return( MBEDTLS_ERR_RSA_PUBLIC_FAILED + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_PUBLIC_FAILED, ret ) );
 
     return( 0 );
 }
@@ -1076,10 +1071,10 @@
     mbedtls_mpi_free( &C );
     mbedtls_mpi_free( &I );
 
-    if( ret != 0 )
-        return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret );
+    if( ret != 0 && ret >= -0x007f )
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_PRIVATE_FAILED, ret ) );
 
-    return( 0 );
+    return( ret );
 }
 
 #if defined(MBEDTLS_PKCS1_V21)
@@ -1190,7 +1185,7 @@
 
     /* Generate a random octet string seed */
     if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 )
-        return( MBEDTLS_ERR_RSA_RNG_FAILED + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_RNG_FAILED, ret ) );
 
     p += hlen;
 
@@ -1279,7 +1274,7 @@
 
             /* Check if RNG failed to generate data */
             if( rng_dl == 0 || ret != 0 )
-                return( MBEDTLS_ERR_RSA_RNG_FAILED + ret );
+                return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_RNG_FAILED, ret ) );
 
             p++;
         }
@@ -1485,126 +1480,21 @@
 #endif /* MBEDTLS_PKCS1_V21 */
 
 #if defined(MBEDTLS_PKCS1_V15)
-/** Turn zero-or-nonzero into zero-or-all-bits-one, without branches.
- *
- * \param value     The value to analyze.
- * \return          Zero if \p value is zero, otherwise all-bits-one.
- */
-static unsigned all_or_nothing_int( 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
-}
-
-/** Check whether a size is out of bounds, without branches.
- *
- * This is equivalent to `size > max`, but is likely to be compiled to
- * to code using bitwise operation rather than a branch.
- *
- * \param size      Size to check.
- * \param max       Maximum desired value for \p size.
- * \return          \c 0 if `size <= max`.
- * \return          \c 1 if `size > max`.
- */
-static unsigned size_greater_than( size_t size, size_t max )
-{
-    /* Return the sign bit (1 for negative) of (max - size). */
-    return( ( max - size ) >> ( sizeof( size_t ) * 8 - 1 ) );
-}
-
-/** Choose between two integer values, without branches.
- *
- * This is equivalent to `cond ? if1 : if0`, but is likely to be compiled
- * to code using bitwise operation rather than a branch.
- *
- * \param cond      Condition to test.
- * \param if1       Value to use if \p cond is nonzero.
- * \param if0       Value to use if \p cond is zero.
- * \return          \c if1 if \p cond is nonzero, otherwise \c if0.
- */
-static unsigned if_int( unsigned cond, unsigned if1, unsigned if0 )
-{
-    unsigned mask = all_or_nothing_int( cond );
-    return( ( mask & if1 ) | (~mask & if0 ) );
-}
-
-/** Shift some data towards the left inside a buffer without leaking
- * the length of the data through side channels.
- *
- * `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 mem_move_to_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 = size_greater_than( 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++ )
-        {
-            unsigned char current = buf[n];
-            unsigned char next = buf[n+1];
-            buf[n] = if_int( no_op, current, next );
-        }
-        buf[total-1] = if_int( no_op, buf[total-1], 0 );
-    }
-}
-
 /*
  * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function
  */
 int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
                                  int (*f_rng)(void *, unsigned char *, size_t),
                                  void *p_rng,
-                                 int mode, size_t *olen,
+                                 int mode,
+                                 size_t *olen,
                                  const unsigned char *input,
                                  unsigned char *output,
                                  size_t output_max_len )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t ilen, i, plaintext_max_size;
+    size_t ilen;
     unsigned char buf[MBEDTLS_MPI_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;
 
     RSA_VALIDATE_RET( ctx != NULL );
     RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
@@ -1614,9 +1504,6 @@
     RSA_VALIDATE_RET( olen != NULL );
 
     ilen = ctx->len;
-    plaintext_max_size = ( output_max_len > ilen - 11 ?
-                           ilen - 11 :
-                           output_max_len );
 
     if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@@ -1631,115 +1518,8 @@
     if( ret != 0 )
         goto cleanup;
 
-    /* Check and get padding length in constant time and constant
-     * memory trace. The first byte must be 0. */
-    bad |= buf[0];
-
-    if( mode == MBEDTLS_RSA_PRIVATE )
-    {
-        /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00
-         * where PS must be at least 8 nonzero bytes. */
-        bad |= buf[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  |= ((buf[i] | (unsigned char)-buf[i]) >> 7) ^ 1;
-            pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1;
-        }
-    }
-    else
-    {
-        /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00
-         * where PS must be at least 8 bytes with the value 0xFF. */
-        bad |= buf[1] ^ MBEDTLS_RSA_SIGN;
-
-        /* Read the whole buffer. Set pad_done to nonzero if we find
-         * the 0x00 byte and remember the padding length in pad_count.
-         * If there's a non-0xff byte in the padding, the padding is bad. */
-        for( i = 2; i < ilen; i++ )
-        {
-            pad_done |= if_int( buf[i], 0, 1 );
-            pad_count += if_int( pad_done, 0, 1 );
-            bad |= if_int( pad_done, 0, buf[i] ^ 0xFF );
-        }
-    }
-
-    /* If pad_done is still zero, there's no data, only unfinished padding. */
-    bad |= if_int( pad_done, 0, 1 );
-
-    /* There must be at least 8 bytes of padding. */
-    bad |= size_greater_than( 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 = if_int( 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 = size_greater_than( 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) if_int( bad, - MBEDTLS_ERR_RSA_INVALID_PADDING,
-                  if_int( 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 = all_or_nothing_int( bad | output_too_large );
-    for( i = 11; i < ilen; i++ )
-        buf[i] &= ~bad;
-
-    /* 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 = if_int( 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. */
-    mem_move_to_left( buf + 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, buf + 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;
+    ret = mbedtls_ct_rsaes_pkcs1_v15_unpadding( mode, buf, ilen,
+                                                output, output_max_len, olen );
 
 cleanup:
     mbedtls_platform_zeroize( buf, sizeof( buf ) );
@@ -1787,21 +1567,19 @@
 }
 
 #if defined(MBEDTLS_PKCS1_V21)
-/*
- * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function
- */
-int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
+static int rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
                          int (*f_rng)(void *, unsigned char *, size_t),
                          void *p_rng,
                          int mode,
                          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;
-    unsigned char salt[MBEDTLS_MD_MAX_SIZE];
+    unsigned char *salt = NULL;
     size_t slen, min_slen, hlen, offset = 0;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t msb;
@@ -1839,31 +1617,44 @@
 
     hlen = mbedtls_md_get_size( md_info );
 
-    /* Calculate the largest possible salt length. Normally this is the hash
-     * length, which is the maximum length the salt can have. If there is not
-     * enough room, use the maximum salt length that fits. The constraint is
-     * that the hash length plus the salt length plus 2 bytes must be at most
-     * the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017
-     * (PKCS#1 v2.2) §9.1.1 step 3. */
-    min_slen = hlen - 2;
-    if( olen < hlen + min_slen + 2 )
+    if (saltlen == MBEDTLS_RSA_SALT_LEN_ANY)
+    {
+       /* Calculate the largest possible salt length, up to the hash size.
+        * Normally this is the hash length, which is the maximum salt length
+        * according to FIPS 185-4 §5.5 (e) and common practice. If there is not
+        * enough room, use the maximum salt length that fits. The constraint is
+        * that the hash length plus the salt length plus 2 bytes must be at most
+        * the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017
+        * (PKCS#1 v2.2) §9.1.1 step 3. */
+        min_slen = hlen - 2;
+        if( olen < hlen + min_slen + 2 )
+            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+        else if( olen >= hlen + hlen + 2 )
+            slen = hlen;
+        else
+            slen = olen - hlen - 2;
+    }
+    else if ( (saltlen < 0) || (saltlen + hlen + 2 > olen) )
+    {
         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-    else if( olen >= hlen + hlen + 2 )
-        slen = hlen;
+    }
     else
-        slen = olen - hlen - 2;
+    {
+        slen = (size_t) saltlen;
+    }
 
     memset( sig, 0, olen );
 
-    /* Generate salt of length slen */
-    if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 )
-        return( MBEDTLS_ERR_RSA_RNG_FAILED + ret );
-
     /* Note: EMSA-PSS encoding is over the length of N - 1 bits */
     msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
     p += olen - hlen - slen - 2;
     *p++ = 0x01;
-    memcpy( p, salt, slen );
+
+    /* Generate salt of length slen in place in the encoded message */
+    salt = p;
+    if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 )
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_RNG_FAILED, ret ) );
+
     p += slen;
 
     mbedtls_md_init( &md_ctx );
@@ -1897,8 +1688,6 @@
     p += hlen;
     *p++ = 0xBC;
 
-    mbedtls_platform_zeroize( salt, sizeof( salt ) );
-
 exit:
     mbedtls_md_free( &md_ctx );
 
@@ -1909,6 +1698,40 @@
             ? mbedtls_rsa_public(  ctx, sig, sig )
             : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) );
 }
+
+/*
+ * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function with
+ * the option to pass in the salt length.
+ */
+int mbedtls_rsa_rsassa_pss_sign_ext( 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 )
+{
+    return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, md_alg,
+                                hashlen, hash, saltlen, sig );
+}
+
+
+/*
+ * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function
+ */
+int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng,
+                         int mode,
+                         mbedtls_md_type_t md_alg,
+                         unsigned int hashlen,
+                         const unsigned char *hash,
+                         unsigned char *sig )
+{
+    return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg,
+                                hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig );
+}
 #endif /* MBEDTLS_PKCS1_V21 */
 
 #if defined(MBEDTLS_PKCS1_V15)
@@ -2110,7 +1933,7 @@
     MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) );
     MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) );
 
-    if( mbedtls_safer_memcmp( verif, sig, ctx->len ) != 0 )
+    if( mbedtls_ct_memcmp( verif, sig, ctx->len ) != 0 )
     {
         ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED;
         goto cleanup;
@@ -2119,9 +1942,13 @@
     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 );
 
+    if( ret != 0 )
+        memset( sig, '!', ctx->len );
     return( ret );
 }
 #endif /* MBEDTLS_PKCS1_V15 */
@@ -2408,8 +2235,8 @@
      * Compare
      */
 
-    if( ( ret = mbedtls_safer_memcmp( encoded, encoded_expected,
-                                      sig_len ) ) != 0 )
+    if( ( ret = mbedtls_ct_memcmp( encoded, encoded_expected,
+                                              sig_len ) ) != 0 )
     {
         ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;
         goto cleanup;
@@ -2481,7 +2308,6 @@
     RSA_VALIDATE_RET( dst != NULL );
     RSA_VALIDATE_RET( src != NULL );
 
-    dst->ver = src->ver;
     dst->len = src->len;
 
     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) );
@@ -2540,7 +2366,12 @@
 #endif /* MBEDTLS_RSA_NO_CRT */
 
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_free( &ctx->mutex );
+    /* Free the mutex, but only if it hasn't been freed already. */
+    if( ctx->ver != 0 )
+    {
+        mbedtls_mutex_free( &ctx->mutex );
+        ctx->ver = 0;
+    }
 #endif
 }
 
diff --git a/third_party/mbedtls/repo/library/sha1.c b/third_party/mbedtls/repo/library/sha1.c
index 6b0f58e..0a5edaf 100644
--- a/third_party/mbedtls/repo/library/sha1.c
+++ b/third_party/mbedtls/repo/library/sha1.c
@@ -48,29 +48,6 @@
 
 #if !defined(MBEDTLS_SHA1_ALT)
 
-/*
- * 32-bit integer manipulation macros (big endian)
- */
-#ifndef GET_UINT32_BE
-#define GET_UINT32_BE(n,b,i)                            \
-{                                                       \
-    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
-        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
-        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
-        | ( (uint32_t) (b)[(i) + 3]       );            \
-}
-#endif
-
-#ifndef PUT_UINT32_BE
-#define PUT_UINT32_BE(n,b,i)                            \
-{                                                       \
-    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
-    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
-    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
-    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
-}
-#endif
-
 void mbedtls_sha1_init( mbedtls_sha1_context *ctx )
 {
     SHA1_VALIDATE( ctx != NULL );
@@ -133,22 +110,22 @@
     SHA1_VALIDATE_RET( ctx != NULL );
     SHA1_VALIDATE_RET( (const unsigned char *)data != NULL );
 
-    GET_UINT32_BE( local.W[ 0], data,  0 );
-    GET_UINT32_BE( local.W[ 1], data,  4 );
-    GET_UINT32_BE( local.W[ 2], data,  8 );
-    GET_UINT32_BE( local.W[ 3], data, 12 );
-    GET_UINT32_BE( local.W[ 4], data, 16 );
-    GET_UINT32_BE( local.W[ 5], data, 20 );
-    GET_UINT32_BE( local.W[ 6], data, 24 );
-    GET_UINT32_BE( local.W[ 7], data, 28 );
-    GET_UINT32_BE( local.W[ 8], data, 32 );
-    GET_UINT32_BE( local.W[ 9], data, 36 );
-    GET_UINT32_BE( local.W[10], data, 40 );
-    GET_UINT32_BE( local.W[11], data, 44 );
-    GET_UINT32_BE( local.W[12], data, 48 );
-    GET_UINT32_BE( local.W[13], data, 52 );
-    GET_UINT32_BE( local.W[14], data, 56 );
-    GET_UINT32_BE( local.W[15], data, 60 );
+    local.W[ 0] = MBEDTLS_GET_UINT32_BE( data,  0 );
+    local.W[ 1] = MBEDTLS_GET_UINT32_BE( data,  4 );
+    local.W[ 2] = MBEDTLS_GET_UINT32_BE( data,  8 );
+    local.W[ 3] = MBEDTLS_GET_UINT32_BE( data, 12 );
+    local.W[ 4] = MBEDTLS_GET_UINT32_BE( data, 16 );
+    local.W[ 5] = MBEDTLS_GET_UINT32_BE( data, 20 );
+    local.W[ 6] = MBEDTLS_GET_UINT32_BE( data, 24 );
+    local.W[ 7] = MBEDTLS_GET_UINT32_BE( data, 28 );
+    local.W[ 8] = MBEDTLS_GET_UINT32_BE( data, 32 );
+    local.W[ 9] = MBEDTLS_GET_UINT32_BE( data, 36 );
+    local.W[10] = MBEDTLS_GET_UINT32_BE( data, 40 );
+    local.W[11] = MBEDTLS_GET_UINT32_BE( data, 44 );
+    local.W[12] = MBEDTLS_GET_UINT32_BE( data, 48 );
+    local.W[13] = MBEDTLS_GET_UINT32_BE( data, 52 );
+    local.W[14] = MBEDTLS_GET_UINT32_BE( data, 56 );
+    local.W[15] = MBEDTLS_GET_UINT32_BE( data, 60 );
 
 #define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
 
@@ -408,8 +385,8 @@
          | ( ctx->total[1] <<  3 );
     low  = ( ctx->total[0] <<  3 );
 
-    PUT_UINT32_BE( high, ctx->buffer, 56 );
-    PUT_UINT32_BE( low,  ctx->buffer, 60 );
+    MBEDTLS_PUT_UINT32_BE( high, ctx->buffer, 56 );
+    MBEDTLS_PUT_UINT32_BE( low,  ctx->buffer, 60 );
 
     if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 )
         return( ret );
@@ -417,11 +394,11 @@
     /*
      * Output final state
      */
-    PUT_UINT32_BE( ctx->state[0], output,  0 );
-    PUT_UINT32_BE( ctx->state[1], output,  4 );
-    PUT_UINT32_BE( ctx->state[2], output,  8 );
-    PUT_UINT32_BE( ctx->state[3], output, 12 );
-    PUT_UINT32_BE( ctx->state[4], output, 16 );
+    MBEDTLS_PUT_UINT32_BE( ctx->state[0], output,  0 );
+    MBEDTLS_PUT_UINT32_BE( ctx->state[1], output,  4 );
+    MBEDTLS_PUT_UINT32_BE( ctx->state[2], output,  8 );
+    MBEDTLS_PUT_UINT32_BE( ctx->state[3], output, 12 );
+    MBEDTLS_PUT_UINT32_BE( ctx->state[4], output, 16 );
 
     return( 0 );
 }
diff --git a/third_party/mbedtls/repo/library/sha256.c b/third_party/mbedtls/repo/library/sha256.c
index be373d9..db675ef 100644
--- a/third_party/mbedtls/repo/library/sha256.c
+++ b/third_party/mbedtls/repo/library/sha256.c
@@ -50,29 +50,6 @@
 
 #if !defined(MBEDTLS_SHA256_ALT)
 
-/*
- * 32-bit integer manipulation macros (big endian)
- */
-#ifndef GET_UINT32_BE
-#define GET_UINT32_BE(n,b,i)                            \
-do {                                                    \
-    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
-        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
-        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
-        | ( (uint32_t) (b)[(i) + 3]       );            \
-} while( 0 )
-#endif
-
-#ifndef PUT_UINT32_BE
-#define PUT_UINT32_BE(n,b,i)                            \
-do {                                                    \
-    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
-    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
-    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
-    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
-} while( 0 )
-#endif
-
 void mbedtls_sha256_init( mbedtls_sha256_context *ctx )
 {
     SHA256_VALIDATE( ctx != NULL );
@@ -214,7 +191,7 @@
     for( i = 0; i < 64; i++ )
     {
         if( i < 16 )
-            GET_UINT32_BE( local.W[i], data, 4 * i );
+            local.W[i] = MBEDTLS_GET_UINT32_BE( data, 4 * i );
         else
             R( i );
 
@@ -229,7 +206,7 @@
     }
 #else /* MBEDTLS_SHA256_SMALLER */
     for( i = 0; i < 16; i++ )
-        GET_UINT32_BE( local.W[i], data, 4 * i );
+        local.W[i] = MBEDTLS_GET_UINT32_BE( data, 4 * i );
 
     for( i = 0; i < 16; i += 8 )
     {
@@ -395,8 +372,8 @@
          | ( ctx->total[1] <<  3 );
     low  = ( ctx->total[0] <<  3 );
 
-    PUT_UINT32_BE( high, ctx->buffer, 56 );
-    PUT_UINT32_BE( low,  ctx->buffer, 60 );
+    MBEDTLS_PUT_UINT32_BE( high, ctx->buffer, 56 );
+    MBEDTLS_PUT_UINT32_BE( low,  ctx->buffer, 60 );
 
     if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 )
         return( ret );
@@ -404,16 +381,16 @@
     /*
      * Output final state
      */
-    PUT_UINT32_BE( ctx->state[0], output,  0 );
-    PUT_UINT32_BE( ctx->state[1], output,  4 );
-    PUT_UINT32_BE( ctx->state[2], output,  8 );
-    PUT_UINT32_BE( ctx->state[3], output, 12 );
-    PUT_UINT32_BE( ctx->state[4], output, 16 );
-    PUT_UINT32_BE( ctx->state[5], output, 20 );
-    PUT_UINT32_BE( ctx->state[6], output, 24 );
+    MBEDTLS_PUT_UINT32_BE( ctx->state[0], output,  0 );
+    MBEDTLS_PUT_UINT32_BE( ctx->state[1], output,  4 );
+    MBEDTLS_PUT_UINT32_BE( ctx->state[2], output,  8 );
+    MBEDTLS_PUT_UINT32_BE( ctx->state[3], output, 12 );
+    MBEDTLS_PUT_UINT32_BE( ctx->state[4], output, 16 );
+    MBEDTLS_PUT_UINT32_BE( ctx->state[5], output, 20 );
+    MBEDTLS_PUT_UINT32_BE( ctx->state[6], output, 24 );
 
     if( ctx->is224 == 0 )
-        PUT_UINT32_BE( ctx->state[7], output, 28 );
+        MBEDTLS_PUT_UINT32_BE( ctx->state[7], output, 28 );
 
     return( 0 );
 }
diff --git a/third_party/mbedtls/repo/library/sha512.c b/third_party/mbedtls/repo/library/sha512.c
index 06a628a..02a135c 100644
--- a/third_party/mbedtls/repo/library/sha512.c
+++ b/third_party/mbedtls/repo/library/sha512.c
@@ -56,44 +56,13 @@
 
 #if !defined(MBEDTLS_SHA512_ALT)
 
-/*
- * 64-bit integer manipulation macros (big endian)
- */
-#ifndef GET_UINT64_BE
-#define GET_UINT64_BE(n,b,i)                            \
-{                                                       \
-    (n) = ( (uint64_t) (b)[(i)    ] << 56 )       \
-        | ( (uint64_t) (b)[(i) + 1] << 48 )       \
-        | ( (uint64_t) (b)[(i) + 2] << 40 )       \
-        | ( (uint64_t) (b)[(i) + 3] << 32 )       \
-        | ( (uint64_t) (b)[(i) + 4] << 24 )       \
-        | ( (uint64_t) (b)[(i) + 5] << 16 )       \
-        | ( (uint64_t) (b)[(i) + 6] <<  8 )       \
-        | ( (uint64_t) (b)[(i) + 7]       );      \
-}
-#endif /* GET_UINT64_BE */
-
-#ifndef PUT_UINT64_BE
-#define PUT_UINT64_BE(n,b,i)                            \
-{                                                       \
-    (b)[(i)    ] = (unsigned char) ( (n) >> 56 );       \
-    (b)[(i) + 1] = (unsigned char) ( (n) >> 48 );       \
-    (b)[(i) + 2] = (unsigned char) ( (n) >> 40 );       \
-    (b)[(i) + 3] = (unsigned char) ( (n) >> 32 );       \
-    (b)[(i) + 4] = (unsigned char) ( (n) >> 24 );       \
-    (b)[(i) + 5] = (unsigned char) ( (n) >> 16 );       \
-    (b)[(i) + 6] = (unsigned char) ( (n) >>  8 );       \
-    (b)[(i) + 7] = (unsigned char) ( (n)       );       \
-}
-#endif /* PUT_UINT64_BE */
-
 #if defined(MBEDTLS_SHA512_SMALLER)
 static void sha512_put_uint64_be( uint64_t n, unsigned char *b, uint8_t i )
 {
-    PUT_UINT64_BE(n, b, i);
+    MBEDTLS_PUT_UINT64_BE(n, b, i);
 }
 #else
-#define sha512_put_uint64_be    PUT_UINT64_BE
+#define sha512_put_uint64_be    MBEDTLS_PUT_UINT64_BE
 #endif /* MBEDTLS_SHA512_SMALLER */
 
 void mbedtls_sha512_init( mbedtls_sha512_context *ctx )
@@ -269,7 +238,7 @@
     {
         if( i < 16 )
         {
-            GET_UINT64_BE( local.W[i], data, i << 3 );
+            local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 );
         }
         else
         {
@@ -289,7 +258,7 @@
 #else /* MBEDTLS_SHA512_SMALLER */
     for( i = 0; i < 16; i++ )
     {
-        GET_UINT64_BE( local.W[i], data, i << 3 );
+        local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 );
     }
 
     for( ; i < 80; i++ )
diff --git a/third_party/mbedtls/repo/library/ssl_cache.c b/third_party/mbedtls/repo/library/ssl_cache.c
index 7e9d4da..32188cf 100644
--- a/third_party/mbedtls/repo/library/ssl_cache.c
+++ b/third_party/mbedtls/repo/library/ssl_cache.c
@@ -78,14 +78,12 @@
             continue;
 #endif
 
-        if( session->ciphersuite != entry->session.ciphersuite ||
-            session->compression != entry->session.compression ||
-            session->id_len != entry->session.id_len )
-            continue;
-
-        if( memcmp( session->id, entry->session.id,
+        if( session->id_len != entry->session.id_len ||
+            memcmp( session->id, entry->session.id,
                     entry->session.id_len ) != 0 )
+        {
             continue;
+        }
 
         ret = mbedtls_ssl_session_copy( session, &entry->session );
         if( ret != 0 )
diff --git a/third_party/mbedtls/repo/library/ssl_ciphersuites.c b/third_party/mbedtls/repo/library/ssl_ciphersuites.c
index 6985fe5..3826ad2 100644
--- a/third_party/mbedtls/repo/library/ssl_ciphersuites.c
+++ b/third_party/mbedtls/repo/library/ssl_ciphersuites.c
@@ -34,6 +34,11 @@
 
 #include <string.h>
 
+#undef HAVE_SHA384
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
+#define HAVE_SHA384
+#endif
+
 /*
  * Ordered from most preferred to least preferred in terms of security.
  *
@@ -411,7 +416,7 @@
       0 },
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_SHA384)
 #if defined(MBEDTLS_CIPHER_MODE_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,
@@ -426,7 +431,7 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #if defined(MBEDTLS_CCM_C)
     { 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,
@@ -460,13 +465,13 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_GCM_C)
@@ -477,13 +482,13 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
@@ -552,7 +557,7 @@
       0 },
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_SHA384)
 #if defined(MBEDTLS_CIPHER_MODE_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,
@@ -567,7 +572,7 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_CAMELLIA_C)
@@ -579,13 +584,13 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_GCM_C)
@@ -596,13 +601,13 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
@@ -641,13 +646,13 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
 #if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C)
+#if defined(HAVE_SHA384) && defined(MBEDTLS_GCM_C)
     { 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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */
+#endif /* HAVE_SHA384 && MBEDTLS_GCM_C */
 
 #if defined(MBEDTLS_SHA256_C)
 #if defined(MBEDTLS_GCM_C)
@@ -751,13 +756,13 @@
       0 },
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
@@ -776,13 +781,13 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
 #if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C)
+#if defined(HAVE_SHA384) && defined(MBEDTLS_GCM_C)
     { 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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */
+#endif /* HAVE_SHA384 && MBEDTLS_GCM_C */
 
 #if defined(MBEDTLS_SHA256_C)
 #if defined(MBEDTLS_GCM_C)
@@ -887,13 +892,13 @@
       0 },
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA1_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA1_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
@@ -960,7 +965,7 @@
       0 },
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_SHA384)
 #if defined(MBEDTLS_CIPHER_MODE_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,
@@ -975,7 +980,7 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_CAMELLIA_C)
@@ -987,13 +992,13 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_GCM_C)
@@ -1004,13 +1009,13 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
@@ -1079,7 +1084,7 @@
       0 },
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_SHA384)
 #if defined(MBEDTLS_CIPHER_MODE_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,
@@ -1094,7 +1099,7 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_CAMELLIA_C)
@@ -1106,13 +1111,13 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_GCM_C)
@@ -1123,13 +1128,13 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
@@ -1177,13 +1182,13 @@
       0 },
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_GCM_C */
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
@@ -1195,13 +1200,13 @@
       0 },
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 
 #if defined(MBEDTLS_SHA1_C)
     { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA",
@@ -1251,13 +1256,13 @@
       0 },
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_GCM_C)
@@ -1269,13 +1274,13 @@
       0 },
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
@@ -1313,13 +1318,13 @@
       0 },
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_GCM_C */
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
@@ -1331,13 +1336,13 @@
       0 },
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 
 #if defined(MBEDTLS_SHA1_C)
     { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA",
@@ -1387,13 +1392,13 @@
       0 },
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_GCM_C)
@@ -1405,13 +1410,13 @@
       0 },
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
@@ -1450,13 +1455,13 @@
       0 },
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 
 #if defined(MBEDTLS_SHA1_C)
     { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA",
@@ -1484,13 +1489,13 @@
       0 },
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #endif /* MBEDTLS_CAMELLIA_C */
 
@@ -1528,13 +1533,13 @@
       0 },
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_GCM_C */
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
@@ -1546,13 +1551,13 @@
       0 },
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 
 #if defined(MBEDTLS_SHA1_C)
     { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA",
@@ -1580,13 +1585,13 @@
       0 },
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_GCM_C)
@@ -1598,13 +1603,13 @@
       0 },
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* HAVE_SHA384 */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
@@ -1688,7 +1693,7 @@
       MBEDTLS_CIPHERSUITE_WEAK },
 #endif
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_SHA384)
     { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
@@ -1714,7 +1719,7 @@
       MBEDTLS_CIPHERSUITE_WEAK },
 #endif
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
@@ -1740,7 +1745,7 @@
       MBEDTLS_CIPHERSUITE_WEAK },
 #endif
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
@@ -1766,7 +1771,7 @@
       MBEDTLS_CIPHERSUITE_WEAK },
 #endif
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(HAVE_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_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
@@ -1805,7 +1810,7 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_GCM_C) && defined(HAVE_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,
@@ -1813,7 +1818,7 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_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,
@@ -1842,7 +1847,7 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_GCM_C) && defined(HAVE_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,
@@ -1850,7 +1855,7 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_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,
@@ -1879,7 +1884,7 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_GCM_C) && defined(HAVE_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,
@@ -1887,7 +1892,7 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_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,
@@ -1916,7 +1921,7 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_GCM_C) && defined(HAVE_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,
@@ -1924,7 +1929,7 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_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,
@@ -1953,7 +1958,7 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_GCM_C) && defined(HAVE_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,
@@ -1961,7 +1966,7 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_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,
@@ -1990,7 +1995,7 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
 
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_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,
@@ -2011,7 +2016,7 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_GCM_C) && defined(HAVE_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,
@@ -2019,7 +2024,7 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_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,
@@ -2048,7 +2053,7 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_GCM_C) && defined(HAVE_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,
@@ -2056,7 +2061,7 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_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,
@@ -2085,7 +2090,7 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_GCM_C) && defined(HAVE_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,
@@ -2093,7 +2098,7 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_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,
@@ -2122,7 +2127,7 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_GCM_C) && defined(HAVE_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,
@@ -2130,7 +2135,7 @@
       MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
       0 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_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,
diff --git a/third_party/mbedtls/repo/library/ssl_cli.c b/third_party/mbedtls/repo/library/ssl_cli.c
index a8331d9..b87879c 100644
--- a/third_party/mbedtls/repo/library/ssl_cli.c
+++ b/third_party/mbedtls/repo/library/ssl_cli.c
@@ -33,9 +33,11 @@
 #include "mbedtls/ssl_internal.h"
 #include "mbedtls/debug.h"
 #include "mbedtls/error.h"
+#include "mbedtls/constant_time.h"
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 #include "mbedtls/psa_util.h"
+#include "psa/crypto.h"
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #include <string.h>
@@ -136,18 +138,19 @@
      * } ServerNameList;
      *
      */
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SERVERNAME, p, 0 );
+    p += 2;
 
-    *p++ = (unsigned char)( ( (hostname_len + 5) >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( (hostname_len + 5)      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( hostname_len + 5, p, 0 );
+    p += 2;
 
-    *p++ = (unsigned char)( ( (hostname_len + 3) >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( (hostname_len + 3)      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( hostname_len + 3, p, 0 );
+    p += 2;
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF );
-    *p++ = (unsigned char)( ( hostname_len >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( hostname_len      ) & 0xFF );
+    *p++ = MBEDTLS_BYTE_0( MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME );
+
+    MBEDTLS_PUT_UINT16_BE( hostname_len, p, 0 );
+    p += 2;
 
     memcpy( p, ssl->hostname, hostname_len );
 
@@ -181,14 +184,12 @@
     /*
      * Secure renegotiation
      */
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 )
-                            & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO      )
-                            & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO, p, 0 );
+    p += 2;
 
     *p++ = 0x00;
-    *p++ = ( ssl->verify_data_len + 1 ) & 0xFF;
-    *p++ = ssl->verify_data_len & 0xFF;
+    *p++ = MBEDTLS_BYTE_0( ssl->verify_data_len + 1 );
+    *p++ = MBEDTLS_BYTE_0( ssl->verify_data_len );
 
     memcpy( p, ssl->own_verify_data, ssl->verify_data_len );
 
@@ -283,14 +284,14 @@
      * SignatureAndHashAlgorithm
      *   supported_signature_algorithms<2..2^16-2>;
      */
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SIG_ALG, p, 0 );
+    p += 2;
 
-    *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( ( sig_alg_len + 2 )      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( sig_alg_len + 2, p, 0 );
+    p += 2;
 
-    *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( sig_alg_len      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( sig_alg_len, p, 0 );
+    p += 2;
 
     *olen = 6 + sig_alg_len;
 
@@ -354,20 +355,18 @@
          grp_id++ )
     {
         info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
-        elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8;
-        elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF;
+        elliptic_curve_list[elliptic_curve_len++] = MBEDTLS_BYTE_1( info->tls_id );
+        elliptic_curve_list[elliptic_curve_len++] = MBEDTLS_BYTE_0( info->tls_id );
     }
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 )
-                            & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES      )
-                            & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES, p, 0 );
+    p += 2;
 
-    *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 )      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( elliptic_curve_len + 2, p, 0 );
+    p += 2;
 
-    *p++ = (unsigned char)( ( ( elliptic_curve_len     ) >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( ( elliptic_curve_len     )      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( elliptic_curve_len, p, 0 );
+    p += 2;
 
     *olen = 6 + elliptic_curve_len;
 
@@ -388,10 +387,8 @@
         ( "client hello, adding supported_point_formats extension" ) );
     MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 )
-                            & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS      )
-                            & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, p, 0 );
+    p += 2;
 
     *p++ = 0x00;
     *p++ = 2;
@@ -427,8 +424,8 @@
 
     MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0 );
+    p += 2;
 
     /*
      * We may need to send ClientHello multiple times for Hello verification.
@@ -470,8 +467,8 @@
         memcpy( p + 2, ssl->handshake->ecjpake_cache, kkpp_len );
     }
 
-    *p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( kkpp_len      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( kkpp_len, p, 0 );
+    p += 2;
 
     *olen = kkpp_len + 4;
 
@@ -510,11 +507,11 @@
     MBEDTLS_SSL_CHK_BUF_PTR( p, end, (unsigned)( ssl->own_cid_len + 5 ) );
 
     /* Add extension ID + size */
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_CID >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_CID      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_CID, p, 0 );
+    p += 2;
     ext_len = (size_t) ssl->own_cid_len + 1;
-    *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( ext_len      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 );
+    p += 2;
 
     *p++ = (uint8_t) ssl->own_cid_len;
     memcpy( p, ssl->own_cid, ssl->own_cid_len );
@@ -543,10 +540,8 @@
 
     MBEDTLS_SSL_CHK_BUF_PTR( p, end, 5 );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 )
-                            & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH      )
-                            & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, p, 0 );
+    p += 2;
 
     *p++ = 0x00;
     *p++ = 1;
@@ -577,8 +572,8 @@
 
     MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_TRUNCATED_HMAC, p, 0 );
+    p += 2;
 
     *p++ = 0x00;
     *p++ = 0x00;
@@ -608,8 +603,8 @@
 
     MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, p, 0 );
+    p += 2;
 
     *p++ = 0x00;
     *p++ = 0x00;
@@ -639,10 +634,8 @@
 
     MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 )
-                            & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET      )
-                            & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, p, 0 );
+    p += 2;
 
     *p++ = 0x00;
     *p++ = 0x00;
@@ -673,11 +666,11 @@
     /* The addition is safe here since the ticket length is 16 bit. */
     MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 + tlen );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SESSION_TICKET, p, 0 );
+    p += 2;
 
-    *p++ = (unsigned char)( ( tlen >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( tlen      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( tlen, p, 0 );
+    p += 2;
 
     *olen = 4;
 
@@ -685,7 +678,7 @@
         return( 0 );
 
     MBEDTLS_SSL_DEBUG_MSG( 3,
-        ( "sending session ticket of length %d", tlen ) );
+        ( "sending session ticket of length %" MBEDTLS_PRINTF_SIZET, tlen ) );
 
     memcpy( p, ssl->session_negotiate->ticket, tlen );
 
@@ -717,8 +710,8 @@
 
     MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 + alpnlen );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ALPN, p, 0 );
+    p += 2;
 
     /*
      * opaque ProtocolName<1..2^8-1>;
@@ -745,12 +738,10 @@
     *olen = p - buf;
 
     /* List length = olen - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */
-    buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF );
-    buf[5] = (unsigned char)( ( ( *olen - 6 )      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( *olen - 6, buf, 4 );
 
     /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */
-    buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF );
-    buf[3] = (unsigned char)( ( ( *olen - 4 )      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( *olen - 4, buf, 2 );
 
     return( 0 );
 }
@@ -802,12 +793,11 @@
      */
     MBEDTLS_SSL_CHK_BUF_PTR( p, end, ext_len + 4 );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_USE_SRTP >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_USE_SRTP      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_USE_SRTP, p, 0 );
+    p += 2;
 
-
-    *p++ = (unsigned char)( ( ( ext_len & 0xFF00 ) >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ext_len & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 );
+    p += 2;
 
     /* protection profile length: 2*(ssl->conf->dtls_srtp_profile_list_len) */
     /* micro-optimization:
@@ -818,8 +808,7 @@
      *                        >> 8 ) & 0xFF );
      */
     *p++ = 0;
-    *p++ = (unsigned char)( ( 2 * ssl->conf->dtls_srtp_profile_list_len )
-                            & 0xFF );
+    *p++ = MBEDTLS_BYTE_0( 2 * ssl->conf->dtls_srtp_profile_list_len );
 
     for( protection_profiles_index=0;
          protection_profiles_index < ssl->conf->dtls_srtp_profile_list_len;
@@ -831,8 +820,8 @@
         {
             MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_write_use_srtp_ext, add profile: %04x",
                                         profile_value ) );
-            *p++ = ( ( profile_value >> 8 ) & 0xFF );
-            *p++ = ( profile_value & 0xFF );
+            MBEDTLS_PUT_UINT16_BE( profile_value, p, 0 );
+            p += 2;
         }
         else
         {
@@ -900,12 +889,11 @@
 
 #if defined(MBEDTLS_HAVE_TIME)
     t = mbedtls_time( NULL );
-    *p++ = (unsigned char)( t >> 24 );
-    *p++ = (unsigned char)( t >> 16 );
-    *p++ = (unsigned char)( t >>  8 );
-    *p++ = (unsigned char)( t       );
+    MBEDTLS_PUT_UINT32_BE( t, p, 0 );
+    p += 4;
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %" MBEDTLS_PRINTF_LONGLONG,
+                                (long long) t ) );
 #else
     if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 )
         return( ret );
@@ -1114,7 +1102,7 @@
     for( i = 0; i < n; i++ )
         *p++ = ssl->session_negotiate->id[i];
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n ) );
     MBEDTLS_SSL_DEBUG_BUF( 3,   "client hello, session id", buf + 39, n );
 
     /*
@@ -1182,7 +1170,7 @@
             continue;
 
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %#04x (%s)",
-                                    ciphersuites[i], ciphersuite_info->name ) );
+                                    (unsigned int)ciphersuites[i], ciphersuite_info->name ) );
 
 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
@@ -1192,12 +1180,12 @@
         MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
 
         n++;
-        *p++ = (unsigned char)( ciphersuites[i] >> 8 );
-        *p++ = (unsigned char)( ciphersuites[i]      );
+        MBEDTLS_PUT_UINT16_BE( ciphersuites[i], p, 0 );
+        p += 2;
     }
 
     MBEDTLS_SSL_DEBUG_MSG( 3,
-        ( "client hello, got %d ciphersuites (excluding SCSVs)", n ) );
+        ( "client hello, got %" MBEDTLS_PRINTF_SIZET " ciphersuites (excluding SCSVs)", n ) );
 
     /*
      * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV
@@ -1208,8 +1196,8 @@
     {
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding EMPTY_RENEGOTIATION_INFO_SCSV" ) );
         MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
-        *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO >> 8 );
-        *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO      );
+        MBEDTLS_PUT_UINT16_BE( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO, p, 0 );
+        p += 2;
         n++;
     }
 
@@ -1220,8 +1208,8 @@
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding FALLBACK_SCSV" ) );
 
         MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
-        *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 );
-        *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE      );
+        MBEDTLS_PUT_UINT16_BE( MBEDTLS_SSL_FALLBACK_SCSV_VALUE, p, 0 );
+        p += 2;
         n++;
     }
 #endif
@@ -1420,16 +1408,15 @@
     /* olen unused if all extensions are disabled */
     ((void) olen);
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d",
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %" MBEDTLS_PRINTF_SIZET,
                                 ext_len ) );
 
     if( ext_len > 0 )
     {
         /* No need to check for space here, because the extension
          * writing functions already took care of that. */
-        *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
-        *p++ = (unsigned char)( ( ext_len      ) & 0xFF );
-        p += ext_len;
+        MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 );
+        p += 2 + ext_len;
     }
 
     ssl->out_msglen  = p - buf;
@@ -1473,9 +1460,9 @@
         /* Check verify-data in constant-time. The length OTOH is no secret */
         if( len    != 1 + ssl->verify_data_len * 2 ||
             buf[0] !=     ssl->verify_data_len * 2 ||
-            mbedtls_ssl_safer_memcmp( buf + 1,
+            mbedtls_ct_memcmp( buf + 1,
                           ssl->own_verify_data, ssl->verify_data_len ) != 0 ||
-            mbedtls_ssl_safer_memcmp( buf + 1 + ssl->verify_data_len,
+            mbedtls_ct_memcmp( buf + 1 + ssl->verify_data_len,
                           ssl->peer_verify_data, ssl->verify_data_len ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) );
@@ -1524,7 +1511,7 @@
         mbedtls_ssl_send_alert_message(
             ssl,
             MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
 
@@ -1571,7 +1558,7 @@
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension unexpected" ) );
         mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                     MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+                                     MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
 
@@ -1627,7 +1614,7 @@
         mbedtls_ssl_send_alert_message(
             ssl,
             MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
 
@@ -1653,7 +1640,7 @@
         mbedtls_ssl_send_alert_message(
             ssl,
             MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
 
@@ -1678,7 +1665,7 @@
         mbedtls_ssl_send_alert_message(
             ssl,
             MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
 
@@ -1784,7 +1771,7 @@
         mbedtls_ssl_send_alert_message(
             ssl,
             MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
     }
 
@@ -2167,10 +2154,10 @@
     }
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu",
-                           ( (uint32_t) buf[2] << 24 ) |
-                           ( (uint32_t) buf[3] << 16 ) |
-                           ( (uint32_t) buf[4] <<  8 ) |
-                           ( (uint32_t) buf[5]       ) ) );
+                                     ( (unsigned long) buf[2] << 24 ) |
+                                     ( (unsigned long) buf[3] << 16 ) |
+                                     ( (unsigned long) buf[4] <<  8 ) |
+                                     ( (unsigned long) buf[5]       ) ) );
 
     memcpy( ssl->handshake->randbytes + 32, buf + 2, 32 );
 
@@ -2253,7 +2240,7 @@
     if( ssl->handshake->ciphersuite_info == NULL )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "ciphersuite info for %04x not found", i ) );
+            ( "ciphersuite info for %04x not found", (unsigned int)i ) );
         mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
                                         MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
@@ -2261,7 +2248,7 @@
 
     mbedtls_ssl_optimize_checksum( ssl, ssl->handshake->ciphersuite_info );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n ) );
     MBEDTLS_SSL_DEBUG_BUF( 3,   "server hello, session id", buf + 35, n );
 
     /*
@@ -2304,7 +2291,7 @@
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
                    ssl->handshake->resume ? "a" : "no" ) );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", (unsigned) i ) );
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d",
                                 buf[37 + n] ) );
 
@@ -2373,7 +2360,7 @@
     ext = buf + 40 + n;
 
     MBEDTLS_SSL_DEBUG_MSG( 2,
-        ( "server hello, total extension length: %d", ext_len ) );
+        ( "server hello, total extension length: %" MBEDTLS_PRINTF_SIZET, ext_len ) );
 
     while( ext_len )
     {
@@ -2537,7 +2524,7 @@
 
         default:
             MBEDTLS_SSL_DEBUG_MSG( 3,
-                ( "unknown extension found: %d (ignoring)", ext_id ) );
+                ( "unknown extension found: %u (ignoring)", ext_id ) );
         }
 
         ext_len -= 4 + ext_size;
@@ -2609,6 +2596,7 @@
                                        unsigned char *end )
 {
     int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    size_t dhm_actual_bitlen;
 
     /*
      * Ephemeral DH parameters:
@@ -2626,10 +2614,11 @@
         return( ret );
     }
 
-    if( ssl->handshake->dhm_ctx.len * 8 < ssl->conf->dhm_min_bitlen )
+    dhm_actual_bitlen = mbedtls_mpi_bitlen( &ssl->handshake->dhm_ctx.P );
+    if( dhm_actual_bitlen < ssl->conf->dhm_min_bitlen )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %d < %d",
-                                    ssl->handshake->dhm_ctx.len * 8,
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %" MBEDTLS_PRINTF_SIZET " < %u",
+                                    dhm_actual_bitlen,
                                     ssl->conf->dhm_min_bitlen ) );
         return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
     }
@@ -2905,8 +2894,7 @@
     defined(MBEDTLS_SSL_PROTO_TLS1_2)
     if( len_bytes == 2 )
     {
-        ssl->out_msg[offset+0] = (unsigned char)( *olen >> 8 );
-        ssl->out_msg[offset+1] = (unsigned char)( *olen      );
+        MBEDTLS_PUT_UINT16_BE( *olen, ssl->out_msg, offset );
         *olen += 2;
     }
 #endif
@@ -3255,7 +3243,11 @@
     if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) )
     {
         size_t sig_len, hashlen;
-        unsigned char hash[64];
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        unsigned char hash[PSA_HASH_MAX_SIZE];
+#else
+        unsigned char hash[MBEDTLS_MD_MAX_SIZE];
+#endif
         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 );
@@ -3690,8 +3682,7 @@
          */
         content_len = ssl->handshake->dhm_ctx.len;
 
-        ssl->out_msg[4] = (unsigned char)( content_len >> 8 );
-        ssl->out_msg[5] = (unsigned char)( content_len      );
+        MBEDTLS_PUT_UINT16_BE( content_len, ssl->out_msg, 4 );
         header_len = 6;
 
         ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx,
@@ -3906,8 +3897,8 @@
             return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
         }
 
-        ssl->out_msg[header_len++] = (unsigned char)( content_len >> 8 );
-        ssl->out_msg[header_len++] = (unsigned char)( content_len      );
+        ssl->out_msg[header_len++] = MBEDTLS_BYTE_1( content_len );
+        ssl->out_msg[header_len++] = MBEDTLS_BYTE_0( content_len );
 
         memcpy( ssl->out_msg + header_len,
                 ssl->conf->psk_identity,
@@ -3958,8 +3949,8 @@
                 return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
             }
 
-            ssl->out_msg[header_len++] = (unsigned char)( content_len >> 8 );
-            ssl->out_msg[header_len++] = (unsigned char)( content_len      );
+            ssl->out_msg[header_len++] = MBEDTLS_BYTE_1( content_len );
+            ssl->out_msg[header_len++] = MBEDTLS_BYTE_0( content_len );
 
             ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx,
                     (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
@@ -4265,8 +4256,7 @@
         return( ret );
     }
 
-    ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 );
-    ssl->out_msg[5 + offset] = (unsigned char)( n      );
+    MBEDTLS_PUT_UINT16_BE( n, ssl->out_msg, offset + 4 );
 
     ssl->out_msglen  = 6 + n + offset;
     ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
@@ -4347,7 +4337,7 @@
         return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET );
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", ticket_len ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %" MBEDTLS_PRINTF_SIZET, ticket_len ) );
 
     /* We're not waiting for a NewSessionTicket message any more */
     ssl->handshake->new_session_ticket = 0;
diff --git a/third_party/mbedtls/repo/library/ssl_cookie.c b/third_party/mbedtls/repo/library/ssl_cookie.c
index c8bd1bd..abf29ae 100644
--- a/third_party/mbedtls/repo/library/ssl_cookie.c
+++ b/third_party/mbedtls/repo/library/ssl_cookie.c
@@ -36,6 +36,7 @@
 #include "mbedtls/ssl_internal.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
+#include "mbedtls/constant_time.h"
 
 #include <string.h>
 
@@ -166,15 +167,12 @@
     t = ctx->serial++;
 #endif
 
-    (*p)[0] = (unsigned char)( t >> 24 );
-    (*p)[1] = (unsigned char)( t >> 16 );
-    (*p)[2] = (unsigned char)( t >>  8 );
-    (*p)[3] = (unsigned char)( t       );
+    MBEDTLS_PUT_UINT32_BE(t, *p, 0);
     *p += 4;
 
 #if defined(MBEDTLS_THREADING_C)
     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret ) );
 #endif
 
     ret = ssl_cookie_hmac( &ctx->hmac_ctx, *p - 4,
@@ -182,8 +180,8 @@
 
 #if defined(MBEDTLS_THREADING_C)
     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR +
-                MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR,
+                MBEDTLS_ERR_THREADING_MUTEX_ERROR ) );
 #endif
 
     return( ret );
@@ -210,7 +208,7 @@
 
 #if defined(MBEDTLS_THREADING_C)
     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret ) );
 #endif
 
     if( ssl_cookie_hmac( &ctx->hmac_ctx, cookie,
@@ -220,15 +218,20 @@
 
 #if defined(MBEDTLS_THREADING_C)
     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR +
-                MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+    {
+        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR,
+                                 MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+    }
 #endif
 
     if( ret != 0 )
-        return( ret );
+        goto exit;
 
-    if( mbedtls_ssl_safer_memcmp( cookie + 4, ref_hmac, sizeof( ref_hmac ) ) != 0 )
-        return( -1 );
+    if( mbedtls_ct_memcmp( cookie + 4, ref_hmac, sizeof( ref_hmac ) ) != 0 )
+    {
+        ret = -1;
+        goto exit;
+    }
 
 #if defined(MBEDTLS_HAVE_TIME)
     cur_time = (unsigned long) mbedtls_time( NULL );
@@ -242,8 +245,13 @@
                   ( (unsigned long) cookie[3]       );
 
     if( ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout )
-        return( -1 );
+    {
+        ret = -1;
+        goto exit;
+    }
 
-    return( 0 );
+exit:
+    mbedtls_platform_zeroize( ref_hmac, sizeof( ref_hmac ) );
+    return( ret );
 }
 #endif /* MBEDTLS_SSL_COOKIE_C */
diff --git a/third_party/mbedtls/repo/library/ssl_invasive.h b/third_party/mbedtls/repo/library/ssl_invasive.h
deleted file mode 100644
index babbc27..0000000
--- a/third_party/mbedtls/repo/library/ssl_invasive.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- * \file ssl_invasive.h
- *
- * \brief SSL 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_SSL_INVASIVE_H
-#define MBEDTLS_SSL_INVASIVE_H
-
-#include "common.h"
-#include "mbedtls/md.h"
-
-#if defined(MBEDTLS_TEST_HOOKS) &&              \
-    defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
-/** \brief 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 additional data prepended to \p data. 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 data appended to \p add_data. 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 \p data in bytes.
- * \param max_data_len      The maximal length of \p data in bytes.
- * \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
- *         Success.
- * \retval MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED
- *         The hardware accelerator failed.
- */
-int mbedtls_ssl_cf_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 );
-
-/** \brief Copy data from a secret position with constant flow.
- *
- * 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.
- *
- * \param dst           The destination buffer. This must point to a writable
- *                      buffer of at least \p len bytes.
- * \param src_base      The base of the source buffer. This must point to a
- *                      readable buffer of at least \p offset_max + \p len
- *                      bytes.
- * \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_secret.
- * \param offset_max    The maximal value of \p offset_secret.
- * \param len           The number of bytes to copy.
- */
-void mbedtls_ssl_cf_memcpy_offset( unsigned char *dst,
-                                   const unsigned char *src_base,
-                                   size_t offset_secret,
-                                   size_t offset_min, size_t offset_max,
-                                   size_t len );
-#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
-
-#endif /* MBEDTLS_SSL_INVASIVE_H */
diff --git a/third_party/mbedtls/repo/library/ssl_msg.c b/third_party/mbedtls/repo/library/ssl_msg.c
index 72f09bb..0b696dd 100644
--- a/third_party/mbedtls/repo/library/ssl_msg.c
+++ b/third_party/mbedtls/repo/library/ssl_msg.c
@@ -44,8 +44,8 @@
 #include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/version.h"
-
-#include "ssl_invasive.h"
+#include "constant_time_internal.h"
+#include "mbedtls/constant_time.h"
 
 #include <string.h>
 
@@ -283,8 +283,8 @@
     }
 
     ssl->handshake->retransmit_timeout = new_timeout;
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs",
-                        ssl->handshake->retransmit_timeout ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %lu millisecs",
+                        (unsigned long) ssl->handshake->retransmit_timeout ) );
 
     return( 0 );
 }
@@ -292,8 +292,8 @@
 static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl )
 {
     ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min;
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs",
-                        ssl->handshake->retransmit_timeout ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %lu millisecs",
+                        (unsigned long) ssl->handshake->retransmit_timeout ) );
 }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
@@ -454,15 +454,13 @@
         *cur = rec->cid_len;
         cur++;
 
-        cur[0] = ( rec->data_len >> 8 ) & 0xFF;
-        cur[1] = ( rec->data_len >> 0 ) & 0xFF;
+        MBEDTLS_PUT_UINT16_BE( rec->data_len, cur, 0 );
         cur += 2;
     }
     else
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
     {
-        cur[0] = ( rec->data_len >> 8 ) & 0xFF;
-        cur[1] = ( rec->data_len >> 0 ) & 0xFF;
+        MBEDTLS_PUT_UINT16_BE( rec->data_len, cur, 0 );
         cur += 2;
     }
 
@@ -476,17 +474,18 @@
 /*
  * SSLv3.0 MAC functions
  */
-static void ssl_mac( mbedtls_md_context_t *md_ctx,
-                     const unsigned char *secret,
-                     const unsigned char *buf, size_t len,
-                     const unsigned char *ctr, int type,
-                     unsigned char out[SSL3_MAC_MAX_BYTES] )
+static int ssl_mac( mbedtls_md_context_t *md_ctx,
+                    const unsigned char *secret,
+                    const unsigned char *buf, size_t len,
+                    const unsigned char *ctr, int type,
+                    unsigned char out[SSL3_MAC_MAX_BYTES] )
 {
     unsigned char header[11];
     unsigned char padding[48];
     int padlen;
     int md_size = mbedtls_md_get_size( md_ctx->md_info );
     int md_type = mbedtls_md_get_type( md_ctx->md_info );
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     /* Only MD5 and SHA-1 supported */
     if( md_type == MBEDTLS_MD_MD5 )
@@ -495,24 +494,47 @@
         padlen = 40;
 
     memcpy( header, ctr, 8 );
-    header[ 8] = (unsigned char)  type;
-    header[ 9] = (unsigned char)( len >> 8 );
-    header[10] = (unsigned char)( len      );
+    header[8] = (unsigned char)  type;
+    MBEDTLS_PUT_UINT16_BE( len, header, 9);
 
     memset( padding, 0x36, padlen );
-    mbedtls_md_starts( md_ctx );
-    mbedtls_md_update( md_ctx, secret,  md_size );
-    mbedtls_md_update( md_ctx, padding, padlen  );
-    mbedtls_md_update( md_ctx, header,  11      );
-    mbedtls_md_update( md_ctx, buf,     len     );
-    mbedtls_md_finish( md_ctx, out              );
+    ret = mbedtls_md_starts( md_ctx );
+    if( ret != 0 )
+        return( ret );
+    ret = mbedtls_md_update( md_ctx, secret,  md_size );
+    if( ret != 0 )
+        return( ret );
+    ret = mbedtls_md_update( md_ctx, padding, padlen  );
+    if( ret != 0 )
+        return( ret );
+    ret = mbedtls_md_update( md_ctx, header,  11      );
+    if( ret != 0 )
+        return( ret );
+    ret = mbedtls_md_update( md_ctx, buf,     len     );
+    if( ret != 0 )
+        return( ret );
+    ret = mbedtls_md_finish( md_ctx, out              );
+    if( ret != 0 )
+        return( ret );
 
     memset( padding, 0x5C, padlen );
-    mbedtls_md_starts( md_ctx );
-    mbedtls_md_update( md_ctx, secret,    md_size );
-    mbedtls_md_update( md_ctx, padding,   padlen  );
-    mbedtls_md_update( md_ctx, out,       md_size );
-    mbedtls_md_finish( md_ctx, out                );
+    ret = mbedtls_md_starts( md_ctx );
+    if( ret != 0 )
+        return( ret );
+    ret = mbedtls_md_update( md_ctx, secret,    md_size );
+    if( ret != 0 )
+        return( ret );
+    ret = mbedtls_md_update( md_ctx, padding,   padlen  );
+    if( ret != 0 )
+        return( ret );
+    ret = mbedtls_md_update( md_ctx, out,       md_size );
+    if( ret != 0 )
+        return( ret );
+    ret = mbedtls_md_finish( md_ctx, out                );
+    if( ret != 0 )
+        return( ret );
+
+    return( 0 );
 }
 #endif /* MBEDTLS_SSL_PROTO_SSL3 */
 
@@ -623,9 +645,10 @@
 
     if( rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d",
-                                    (unsigned) rec->data_len,
-                                    MBEDTLS_SSL_OUT_CONTENT_LEN ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %" MBEDTLS_PRINTF_SIZET
+                                    " too large, maximum %" MBEDTLS_PRINTF_SIZET,
+                                    rec->data_len,
+                                    (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
     }
 
@@ -716,9 +739,17 @@
         if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
         {
             unsigned char mac[SSL3_MAC_MAX_BYTES];
-            ssl_mac( &transform->md_ctx_enc, transform->mac_enc,
-                     data, rec->data_len, rec->ctr, rec->type, mac );
-            memcpy( data + rec->data_len, mac, transform->maclen );
+            int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+            ret = ssl_mac( &transform->md_ctx_enc, transform->mac_enc,
+                           data, rec->data_len, rec->ctr, rec->type, mac );
+            if( ret == 0 )
+                memcpy( data + rec->data_len, mac, transform->maclen );
+            mbedtls_platform_zeroize( mac, transform->maclen );
+            if( ret != 0 )
+            {
+                MBEDTLS_SSL_DEBUG_RET( 1, "ssl_mac", ret );
+                return( ret );
+            }
         }
         else
 #endif
@@ -727,18 +758,35 @@
         if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 )
         {
             unsigned char mac[MBEDTLS_SSL_MAC_ADD];
+            int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
             ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
                                               transform->minor_ver );
 
-            mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data,
-                                    add_data_len );
-            mbedtls_md_hmac_update( &transform->md_ctx_enc,
-                                    data, rec->data_len );
-            mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac );
-            mbedtls_md_hmac_reset( &transform->md_ctx_enc );
+            ret = mbedtls_md_hmac_update( &transform->md_ctx_enc,
+                                          add_data, add_data_len );
+            if( ret != 0 )
+                goto hmac_failed_etm_disabled;
+            ret = mbedtls_md_hmac_update( &transform->md_ctx_enc,
+                                          data, rec->data_len );
+            if( ret != 0 )
+                goto hmac_failed_etm_disabled;
+            ret = mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac );
+            if( ret != 0 )
+                goto hmac_failed_etm_disabled;
+            ret = mbedtls_md_hmac_reset( &transform->md_ctx_enc );
+            if( ret != 0 )
+                goto hmac_failed_etm_disabled;
 
             memcpy( data + rec->data_len, mac, transform->maclen );
+
+        hmac_failed_etm_disabled:
+            mbedtls_platform_zeroize( mac, transform->maclen );
+            if( ret != 0 )
+            {
+                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_hmac_xxx", ret );
+                return( ret );
+            }
         }
         else
 #endif
@@ -764,7 +812,7 @@
     {
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         size_t olen;
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
                                     "including %d bytes of padding",
                                     rec->data_len, 0 ) );
 
@@ -842,7 +890,7 @@
                                dynamic_iv_is_explicit ? dynamic_iv_len : 0 );
         MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
                                add_data, add_data_len );
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
                                     "including 0 bytes of padding",
                                     rec->data_len ) );
 
@@ -945,8 +993,9 @@
         }
 #endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
 
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
-                            "including %d bytes of IV and %d bytes of padding",
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
+                            "including %" MBEDTLS_PRINTF_SIZET
+                            " bytes of IV and %" MBEDTLS_PRINTF_SIZET " bytes of padding",
                             rec->data_len, transform->ivlen,
                             padlen + 1 ) );
 
@@ -1010,18 +1059,34 @@
             MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data,
                                    add_data_len );
 
-            mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data,
-                                    add_data_len );
-            mbedtls_md_hmac_update( &transform->md_ctx_enc,
-                                    data, rec->data_len );
-            mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac );
-            mbedtls_md_hmac_reset( &transform->md_ctx_enc );
+            ret = mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data,
+                                          add_data_len );
+            if( ret != 0 )
+                goto hmac_failed_etm_enabled;
+            ret = mbedtls_md_hmac_update( &transform->md_ctx_enc,
+                                          data, rec->data_len );
+            if( ret != 0 )
+                goto hmac_failed_etm_enabled;
+            ret = mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac );
+            if( ret != 0 )
+                goto hmac_failed_etm_enabled;
+            ret = mbedtls_md_hmac_reset( &transform->md_ctx_enc );
+            if( ret != 0 )
+                goto hmac_failed_etm_enabled;
 
             memcpy( data + rec->data_len, mac, transform->maclen );
 
             rec->data_len += transform->maclen;
             post_avail -= transform->maclen;
             auth_done++;
+
+        hmac_failed_etm_enabled:
+            mbedtls_platform_zeroize( mac, transform->maclen );
+            if( ret != 0 )
+            {
+                MBEDTLS_SSL_DEBUG_RET( 1, "HMAC calculation failed", ret );
+                return( ret );
+            }
         }
 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
     }
@@ -1044,239 +1109,6 @@
     return( 0 );
 }
 
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
-/*
- * Turn a bit into a mask:
- * - if bit == 1, return the all-bits 1 mask, aka (size_t) -1
- * - if bit == 0, return the all-bits 0 mask, aka 0
- *
- * This function can be used to write constant-time code by replacing branches
- * with bit operations using masks.
- *
- * This function is implemented without using comparison operators, as those
- * might be translated to branches by some compilers on some platforms.
- */
-static size_t mbedtls_ssl_cf_mask_from_bit( size_t bit )
-{
-    /* 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 -bit;
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-}
-
-/*
- * Constant-flow mask generation for "less than" comparison:
- * - if x < 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.
- *
- * This function is implemented without using comparison operators, as those
- * might be translated to branches by some compilers on some platforms.
- */
-static size_t mbedtls_ssl_cf_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_ssl_cf_mask_from_bit( sub1 );
-
-    return( mask );
-}
-
-/*
- * Constant-flow mask generation for "greater or equal" comparison:
- * - if x >= 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.
- *
- * This function is implemented without using comparison operators, as those
- * might be translated to branches by some compilers on some platforms.
- */
-static size_t mbedtls_ssl_cf_mask_ge( size_t x, size_t y )
-{
-    return( ~mbedtls_ssl_cf_mask_lt( x, y ) );
-}
-
-/*
- * Constant-flow boolean "equal" comparison:
- * return x == y
- *
- * This function can be used to write constant-time code by replacing branches
- * with bit operations - it can be used in conjunction with
- * mbedtls_ssl_cf_mask_from_bit().
- *
- * This function is implemented without using comparison operators, as those
- * might be translated to branches by some compilers on some platforms.
- */
-static size_t mbedtls_ssl_cf_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 | -diff );
-
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-
-    /* diff1 = (x != y) ? 1 : 0 */
-    const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 );
-
-    return( 1 ^ diff1 );
-}
-
-/*
- * Constant-flow conditional memcpy:
- *  - if c1 == c2, equivalent to memcpy(dst, src, len),
- *  - otherwise, a no-op,
- * but with execution flow independent of the values of c1 and c2.
- *
- * This function is implemented without using comparison operators, as those
- * might be translated to branches by some compilers on some platforms.
- */
-static void mbedtls_ssl_cf_memcpy_if_eq( unsigned char *dst,
-                                         const unsigned char *src,
-                                         size_t len,
-                                         size_t c1, size_t c2 )
-{
-    /* mask = c1 == c2 ? 0xff : 0x00 */
-    const size_t equal = mbedtls_ssl_cf_bool_eq( c1, c2 );
-    const unsigned char mask = (unsigned char) mbedtls_ssl_cf_mask_from_bit( equal );
-
-    /* dst[i] = c1 == c2 ? src[i] : dst[i] */
-    for( size_t i = 0; i < len; i++ )
-        dst[i] = ( src[i] & mask ) | ( dst[i] & ~mask );
-}
-
-/*
- * Compute HMAC of variable-length data with constant flow.
- *
- * Only works with MD-5, SHA-1, SHA-256 and SHA-384.
- * (Otherwise, computation of block_size needs to be adapted.)
- */
-MBEDTLS_STATIC_TESTABLE int mbedtls_ssl_cf_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.0-1.2 only support 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 ) );
-
-    /* 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_ssl_cf_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 ) );
-    }
-
-    /* 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 );
-}
-
-/*
- * Constant-flow memcpy from variable position in buffer.
- * - functionally equivalent to memcpy(dst, src + offset_secret, len)
- * - but with execution flow independent from the value of offset_secret.
- */
-MBEDTLS_STATIC_TESTABLE void mbedtls_ssl_cf_memcpy_offset(
-                                   unsigned char *dst,
-                                   const unsigned char *src_base,
-                                   size_t offset_secret,
-                                   size_t offset_min, size_t offset_max,
-                                   size_t len )
-{
-    size_t offset;
-
-    for( offset = offset_min; offset <= offset_max; offset++ )
-    {
-        mbedtls_ssl_cf_memcpy_if_eq( dst, src_base + offset, len,
-                                     offset, offset_secret );
-    }
-}
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
-
 int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
                              mbedtls_ssl_transform *transform,
                              mbedtls_record *rec )
@@ -1366,7 +1198,8 @@
         {
             if( rec->data_len < dynamic_iv_len )
             {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) ",
+                MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
+                                            " ) < explicit_iv_len (%" MBEDTLS_PRINTF_SIZET ") ",
                                             rec->data_len,
                                             dynamic_iv_len ) );
                 return( MBEDTLS_ERR_SSL_INVALID_MAC );
@@ -1385,7 +1218,8 @@
         /* Check that there's space for the authentication tag. */
         if( rec->data_len < transform->taglen )
         {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < taglen (%d) ",
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
+                                        ") < taglen (%" MBEDTLS_PRINTF_SIZET ") ",
                                         rec->data_len,
                                         transform->taglen ) );
             return( MBEDTLS_ERR_SSL_INVALID_MAC );
@@ -1488,7 +1322,9 @@
         if( rec->data_len < minlen + transform->ivlen ||
             rec->data_len < minlen + transform->maclen + 1 )
         {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) "
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
+                                        ") < max( ivlen(%" MBEDTLS_PRINTF_SIZET
+                                        "), maclen (%" MBEDTLS_PRINTF_SIZET ") "
                                 "+ 1 ) ( + expl IV )", rec->data_len,
                                 transform->ivlen,
                                 transform->maclen ) );
@@ -1512,7 +1348,7 @@
              *
              * Afterwards, we know that data + data_len is followed by at
              * least maclen Bytes, which justifies the call to
-             * mbedtls_ssl_safer_memcmp() below.
+             * mbedtls_ct_memcmp() below.
              *
              * Further, we still know that data_len > minlen */
             rec->data_len -= transform->maclen;
@@ -1522,12 +1358,20 @@
             /* Calculate expected MAC. */
             MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data,
                                    add_data_len );
-            mbedtls_md_hmac_update( &transform->md_ctx_dec, add_data,
-                                    add_data_len );
-            mbedtls_md_hmac_update( &transform->md_ctx_dec,
+            ret = mbedtls_md_hmac_update( &transform->md_ctx_dec, add_data,
+                                          add_data_len );
+            if( ret != 0 )
+                goto hmac_failed_etm_enabled;
+            ret = mbedtls_md_hmac_update( &transform->md_ctx_dec,
                                     data, rec->data_len );
-            mbedtls_md_hmac_finish( &transform->md_ctx_dec, mac_expect );
-            mbedtls_md_hmac_reset( &transform->md_ctx_dec );
+            if( ret != 0 )
+                goto hmac_failed_etm_enabled;
+            ret = mbedtls_md_hmac_finish( &transform->md_ctx_dec, mac_expect );
+            if( ret != 0 )
+                goto hmac_failed_etm_enabled;
+            ret = mbedtls_md_hmac_reset( &transform->md_ctx_dec );
+            if( ret != 0 )
+                goto hmac_failed_etm_enabled;
 
             MBEDTLS_SSL_DEBUG_BUF( 4, "message  mac", data + rec->data_len,
                                    transform->maclen );
@@ -1535,13 +1379,23 @@
                                    transform->maclen );
 
             /* Compare expected MAC with MAC at the end of the record. */
-            if( mbedtls_ssl_safer_memcmp( data + rec->data_len, mac_expect,
-                                          transform->maclen ) != 0 )
+            if( mbedtls_ct_memcmp( data + rec->data_len, mac_expect,
+                                              transform->maclen ) != 0 )
             {
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
-                return( MBEDTLS_ERR_SSL_INVALID_MAC );
+                ret = MBEDTLS_ERR_SSL_INVALID_MAC;
+                goto hmac_failed_etm_enabled;
             }
             auth_done++;
+
+        hmac_failed_etm_enabled:
+            mbedtls_platform_zeroize( mac_expect, transform->maclen );
+            if( ret != 0 )
+            {
+                if( ret != MBEDTLS_ERR_SSL_INVALID_MAC )
+                    MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_hmac_xxx", ret );
+                return( ret );
+            }
         }
 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
 
@@ -1554,7 +1408,8 @@
          * data_len >= minlen + ivlen ( = minlen or 2 * minlen ). */
         if( rec->data_len % transform->ivlen != 0 )
         {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0",
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
+                                        ") %% ivlen (%" MBEDTLS_PRINTF_SIZET ") != 0",
                                         rec->data_len, transform->ivlen ) );
             return( MBEDTLS_ERR_SSL_INVALID_MAC );
         }
@@ -1613,7 +1468,7 @@
 
         if( auth_done == 1 )
         {
-            const size_t mask = mbedtls_ssl_cf_mask_ge(
+            const size_t mask = mbedtls_ct_size_mask_ge(
                                 rec->data_len,
                                 padlen + 1 );
             correct &= mask;
@@ -1624,14 +1479,16 @@
 #if defined(MBEDTLS_SSL_DEBUG_ALL)
             if( rec->data_len < transform->maclen + padlen + 1 )
             {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)",
+                MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
+                                            ") < maclen (%" MBEDTLS_PRINTF_SIZET
+                                            ") + padlen (%" MBEDTLS_PRINTF_SIZET ")",
                                             rec->data_len,
                                             transform->maclen,
                                             padlen + 1 ) );
             }
 #endif
 
-            const size_t mask = mbedtls_ssl_cf_mask_ge(
+            const size_t mask = mbedtls_ct_size_mask_ge(
                                 rec->data_len,
                                 transform->maclen + padlen + 1 );
             correct &= mask;
@@ -1653,8 +1510,8 @@
             if( padlen > transform->ivlen )
             {
 #if defined(MBEDTLS_SSL_DEBUG_ALL)
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, "
-                                            "should be no more than %d",
+                MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %" MBEDTLS_PRINTF_SIZET ", "
+                                            "should be no more than %" MBEDTLS_PRINTF_SIZET,
                                             padlen, transform->ivlen ) );
 #endif
                 correct = 0;
@@ -1687,18 +1544,18 @@
                 /* pad_count += (idx >= padding_idx) &&
                  *              (check[idx] == padlen - 1);
                  */
-                const size_t mask = mbedtls_ssl_cf_mask_ge( idx, padding_idx );
-                const size_t equal = mbedtls_ssl_cf_bool_eq( 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;
             }
-            correct &= mbedtls_ssl_cf_bool_eq( pad_count, padlen );
+            correct &= mbedtls_ct_size_bool_eq( pad_count, padlen );
 
 #if defined(MBEDTLS_SSL_DEBUG_ALL)
             if( padlen > 0 && correct == 0 )
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) );
 #endif
-            padlen &= mbedtls_ssl_cf_mask_from_bit( correct );
+            padlen &= mbedtls_ct_size_mask( correct );
         }
         else
 #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
@@ -1756,11 +1613,16 @@
 #if defined(MBEDTLS_SSL_PROTO_SSL3)
         if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
         {
-            ssl_mac( &transform->md_ctx_dec,
-                     transform->mac_dec,
-                     data, rec->data_len,
-                     rec->ctr, rec->type,
-                     mac_expect );
+            ret = ssl_mac( &transform->md_ctx_dec,
+                           transform->mac_dec,
+                           data, rec->data_len,
+                           rec->ctr, rec->type,
+                           mac_expect );
+            if( ret != 0 )
+            {
+                MBEDTLS_SSL_DEBUG_RET( 1, "ssl_mac", ret );
+                goto hmac_failed_etm_disabled;
+            }
             memcpy( mac_peer, data + rec->data_len, transform->maclen );
         }
         else
@@ -1782,20 +1644,20 @@
             const size_t max_len = rec->data_len + padlen;
             const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0;
 
-            ret = mbedtls_ssl_cf_hmac( &transform->md_ctx_dec,
-                                       add_data, add_data_len,
-                                       data, rec->data_len, min_len, max_len,
-                                       mac_expect );
+            ret = mbedtls_ct_hmac( &transform->md_ctx_dec,
+                                   add_data, add_data_len,
+                                   data, rec->data_len, min_len, max_len,
+                                   mac_expect );
             if( ret != 0 )
             {
-                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_cf_hmac", ret );
-                return( ret );
+                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ct_hmac", ret );
+                goto hmac_failed_etm_disabled;
             }
 
-            mbedtls_ssl_cf_memcpy_offset( mac_peer, data,
-                                          rec->data_len,
-                                          min_len, max_len,
-                                          transform->maclen );
+            mbedtls_ct_memcpy_offset( mac_peer, data,
+                                      rec->data_len,
+                                      min_len, max_len,
+                                      transform->maclen );
         }
         else
 #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
@@ -1810,8 +1672,8 @@
         MBEDTLS_SSL_DEBUG_BUF( 4, "message  mac", mac_peer, transform->maclen );
 #endif
 
-        if( mbedtls_ssl_safer_memcmp( mac_peer, mac_expect,
-                                      transform->maclen ) != 0 )
+        if( mbedtls_ct_memcmp( mac_peer, mac_expect,
+                                          transform->maclen ) != 0 )
         {
 #if defined(MBEDTLS_SSL_DEBUG_ALL)
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
@@ -1819,6 +1681,12 @@
             correct = 0;
         }
         auth_done++;
+
+    hmac_failed_etm_disabled:
+        mbedtls_platform_zeroize( mac_peer, transform->maclen );
+        mbedtls_platform_zeroize( mac_expect, transform->maclen );
+        if( ret != 0 )
+            return( ret );
     }
 
     /*
@@ -1890,7 +1758,7 @@
 
     memcpy( msg_pre, ssl->out_msg, len_pre );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %d, ",
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %" MBEDTLS_PRINTF_SIZET ", ",
                    ssl->out_msglen ) );
 
     MBEDTLS_SSL_DEBUG_BUF( 4, "before compression: output payload",
@@ -1911,7 +1779,7 @@
     ssl->out_msglen = out_buf_len -
                       ssl->transform_out->ctx_deflate.avail_out - bytes_written;
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ",
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %" MBEDTLS_PRINTF_SIZET ", ",
                    ssl->out_msglen ) );
 
     MBEDTLS_SSL_DEBUG_BUF( 4, "after compression: output payload",
@@ -1942,7 +1810,7 @@
 
     memcpy( msg_pre, ssl->in_msg, len_pre );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ",
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %" MBEDTLS_PRINTF_SIZET ", ",
                    ssl->in_msglen ) );
 
     MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload",
@@ -1963,7 +1831,7 @@
     ssl->in_msglen = in_buf_len -
                      ssl->transform_in->ctx_inflate.avail_out - header_bytes;
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ",
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %" MBEDTLS_PRINTF_SIZET ", ",
                    ssl->in_msglen ) );
 
     MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload",
@@ -2042,7 +1910,8 @@
 
             if( ssl->in_left != 0 )
             {
-                MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %d",
+                MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %"
+                                            MBEDTLS_PRINTF_SIZET,
                                     ssl->next_record_offset ) );
                 memmove( ssl->in_hdr,
                          ssl->in_hdr + ssl->next_record_offset,
@@ -2052,7 +1921,8 @@
             ssl->next_record_offset = 0;
         }
 
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d",
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
+                                    ", nb_want: %" MBEDTLS_PRINTF_SIZET,
                        ssl->in_left, nb_want ) );
 
         /*
@@ -2094,7 +1964,7 @@
             else
                 timeout = ssl->conf->read_timeout;
 
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %u ms", timeout ) );
+            MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %lu ms", (unsigned long) timeout ) );
 
             if( ssl->f_recv_timeout != NULL )
                 ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len,
@@ -2153,7 +2023,8 @@
     else
 #endif
     {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d",
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
+                                    ", nb_want: %" MBEDTLS_PRINTF_SIZET,
                        ssl->in_left, nb_want ) );
 
         while( ssl->in_left < nb_want )
@@ -2177,7 +2048,8 @@
                 }
             }
 
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d",
+            MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
+                                        ", nb_want: %" MBEDTLS_PRINTF_SIZET,
                                         ssl->in_left, nb_want ) );
             MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret );
 
@@ -2190,8 +2062,8 @@
             if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) )
             {
                 MBEDTLS_SSL_DEBUG_MSG( 1,
-                    ( "f_recv returned %d bytes but only %lu were requested",
-                    ret, (unsigned long)len ) );
+                    ( "f_recv returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " were requested",
+                    ret, len ) );
                 return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
             }
 
@@ -2230,7 +2102,8 @@
 
     while( ssl->out_left > 0 )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d",
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %" MBEDTLS_PRINTF_SIZET
+                                    ", out_left: %" MBEDTLS_PRINTF_SIZET,
                        mbedtls_ssl_out_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) );
 
         buf = ssl->out_hdr - ssl->out_left;
@@ -2244,8 +2117,8 @@
         if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1,
-                ( "f_send returned %d bytes but only %lu bytes were sent",
-                ret, (unsigned long)ssl->out_left ) );
+                ( "f_send returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " bytes were sent",
+                ret, ssl->out_left ) );
             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
         }
 
@@ -2286,14 +2159,15 @@
     /* Allocate space for current message */
     if( ( msg = mbedtls_calloc( 1, sizeof(  mbedtls_ssl_flight_item ) ) ) == NULL )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed",
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %" MBEDTLS_PRINTF_SIZET " bytes failed",
                             sizeof( mbedtls_ssl_flight_item ) ) );
         return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
     }
 
     if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", ssl->out_msglen ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %" MBEDTLS_PRINTF_SIZET " bytes failed",
+                                    ssl->out_msglen ) );
         mbedtls_free( msg );
         return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
     }
@@ -2508,13 +2382,13 @@
              * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */
             memcpy( ssl->out_msg, cur->p, 6 );
 
-            ssl->out_msg[6] = ( ( frag_off >> 16 ) & 0xff );
-            ssl->out_msg[7] = ( ( frag_off >>  8 ) & 0xff );
-            ssl->out_msg[8] = ( ( frag_off       ) & 0xff );
+            ssl->out_msg[6] = MBEDTLS_BYTE_2( frag_off );
+            ssl->out_msg[7] = MBEDTLS_BYTE_1( frag_off );
+            ssl->out_msg[8] = MBEDTLS_BYTE_0( frag_off );
 
-            ssl->out_msg[ 9] = ( ( cur_hs_frag_len >> 16 ) & 0xff );
-            ssl->out_msg[10] = ( ( cur_hs_frag_len >>  8 ) & 0xff );
-            ssl->out_msg[11] = ( ( cur_hs_frag_len       ) & 0xff );
+            ssl->out_msg[ 9] = MBEDTLS_BYTE_2( cur_hs_frag_len );
+            ssl->out_msg[10] = MBEDTLS_BYTE_1( cur_hs_frag_len );
+            ssl->out_msg[11] = MBEDTLS_BYTE_0( cur_hs_frag_len );
 
             MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 );
 
@@ -2699,9 +2573,10 @@
     if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: "
-                                    "size %u, maximum %u",
-                                    (unsigned) ssl->out_msglen,
-                                    (unsigned) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
+                                    "size %" MBEDTLS_PRINTF_SIZET
+                                    ", maximum %" MBEDTLS_PRINTF_SIZET,
+                                    ssl->out_msglen,
+                                    (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
     }
 
@@ -2710,9 +2585,9 @@
      */
     if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
     {
-        ssl->out_msg[1] = (unsigned char)( hs_len >> 16 );
-        ssl->out_msg[2] = (unsigned char)( hs_len >>  8 );
-        ssl->out_msg[3] = (unsigned char)( hs_len       );
+        ssl->out_msg[1] = MBEDTLS_BYTE_2( hs_len );
+        ssl->out_msg[2] = MBEDTLS_BYTE_1( hs_len );
+        ssl->out_msg[3] = MBEDTLS_BYTE_0( hs_len );
 
         /*
          * DTLS has additional fields in the Handshake layer,
@@ -2728,9 +2603,9 @@
             if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 )
             {
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: "
-                              "size %u, maximum %u",
-                               (unsigned) ( hs_len ),
-                               (unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) );
+                              "size %" MBEDTLS_PRINTF_SIZET ", maximum %" MBEDTLS_PRINTF_SIZET,
+                               hs_len,
+                               (size_t) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) );
                 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
             }
 
@@ -2740,8 +2615,7 @@
             /* Write message_seq and update it, except for HelloRequest */
             if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
             {
-                ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF;
-                ssl->out_msg[5] = ( ssl->handshake->out_msg_seq      ) & 0xFF;
+                MBEDTLS_PUT_UINT16_BE( ssl->handshake->out_msg_seq, ssl->out_msg, 4 );
                 ++( ssl->handshake->out_msg_seq );
             }
             else
@@ -2855,8 +2729,7 @@
                            ssl->conf->transport, ssl->out_hdr + 1 );
 
         memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 );
-        ssl->out_len[0] = (unsigned char)( len >> 8 );
-        ssl->out_len[1] = (unsigned char)( len      );
+        MBEDTLS_PUT_UINT16_BE( len, ssl->out_len, 0);
 
         if( ssl->transform_out != NULL )
         {
@@ -2896,8 +2769,7 @@
             memcpy( ssl->out_cid, rec.cid, rec.cid_len );
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
             ssl->out_msglen = len = rec.data_len;
-            ssl->out_len[0] = (unsigned char)( rec.data_len >> 8 );
-            ssl->out_len[1] = (unsigned char)( rec.data_len      );
+            MBEDTLS_PUT_UINT16_BE( rec.data_len, ssl->out_len, 0 );
         }
 
         protected_record_size = len + mbedtls_ssl_out_hdr_len( ssl );
@@ -2922,8 +2794,8 @@
         /* Now write the potentially updated record content type. */
         ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
 
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, "
-                                    "version = [%d:%d], msglen = %d",
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %u, "
+                                    "version = [%u:%u], msglen = %" MBEDTLS_PRINTF_SIZET,
                                     ssl->out_hdr[0], ssl->out_hdr[1],
                                     ssl->out_hdr[2], len ) );
 
@@ -3119,7 +2991,7 @@
 {
     if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %d",
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %" MBEDTLS_PRINTF_SIZET,
                             ssl->in_msglen ) );
         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
     }
@@ -3127,7 +2999,7 @@
     ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl );
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
-                        " %d, type = %d, hslen = %d",
+                        " %" MBEDTLS_PRINTF_SIZET ", type = %u, hslen = %" MBEDTLS_PRINTF_SIZET,
                         ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) );
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
@@ -3163,7 +3035,7 @@
                 ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST )
             {
                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, "
-                                    "message_seq = %d, start_of_flight = %d",
+                                    "message_seq = %u, start_of_flight = %u",
                                     recv_msg_seq,
                                     ssl->handshake->in_flight_start_seq ) );
 
@@ -3176,7 +3048,7 @@
             else
             {
                 MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: "
-                                    "message_seq = %d, expected = %d",
+                                    "message_seq = %u, expected = %u",
                                     recv_msg_seq,
                                     ssl->handshake->in_msg_seq ) );
             }
@@ -3469,12 +3341,11 @@
     /* Go back and fill length fields */
     obuf[27] = (unsigned char)( *olen - 28 );
 
-    obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 );
-    obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >>  8 );
-    obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 )       );
+    obuf[14] = obuf[22] = MBEDTLS_BYTE_2( *olen - 25 );
+    obuf[15] = obuf[23] = MBEDTLS_BYTE_1( *olen - 25 );
+    obuf[16] = obuf[24] = MBEDTLS_BYTE_0( *olen - 25 );
 
-    obuf[11] = (unsigned char)( ( *olen - 13 ) >>  8 );
-    obuf[12] = (unsigned char)( ( *olen - 13 )       );
+    MBEDTLS_PUT_UINT16_BE( *olen - 13, obuf, 11 );
 
     return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED );
 }
@@ -3746,8 +3617,8 @@
                        ( (size_t) buf[ rec_hdr_len_offset + 1 ] << 0 );
     MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", buf, rec->data_offset );
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, "
-                                "version = [%d:%d], msglen = %d",
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %u, "
+                                "version = [%d:%d], msglen = %" MBEDTLS_PRINTF_SIZET,
                                 rec->type,
                                 major_ver, minor_ver, rec->data_len ) );
 
@@ -3790,8 +3661,8 @@
         if( rec_epoch != ssl->in_epoch )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: "
-                                        "expected %d, received %d",
-                                        ssl->in_epoch, rec_epoch ) );
+                                        "expected %u, received %lu",
+                                        ssl->in_epoch, (unsigned long) rec_epoch ) );
 
             /* Records from the next epoch are considered for buffering
              * (concretely: early Finished messages). */
@@ -4325,31 +4196,41 @@
                     {
                         /* If we can't buffer a future message because
                          * of space limitations -- ignore. */
-                        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n",
-                             (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
-                             (unsigned) hs->buffering.total_bytes_buffered ) );
+                        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %" MBEDTLS_PRINTF_SIZET
+                                                    " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET
+                                                    " (already %" MBEDTLS_PRINTF_SIZET
+                                                    " bytes buffered) -- ignore\n",
+                             msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+                             hs->buffering.total_bytes_buffered ) );
                         goto exit;
                     }
                     else
                     {
-                        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- attempt to make space by freeing buffered future messages\n",
-                             (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
-                             (unsigned) hs->buffering.total_bytes_buffered ) );
+                        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %" MBEDTLS_PRINTF_SIZET
+                                                    " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET
+                                                    " (already %" MBEDTLS_PRINTF_SIZET
+                                                    " bytes buffered) -- attempt to make space by freeing buffered future messages\n",
+                             msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+                             hs->buffering.total_bytes_buffered ) );
                     }
 
                     if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 )
                     {
-                        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %u (%u with bitmap) would exceed the compile-time limit %u (already %u bytes buffered) -- fail\n",
-                             (unsigned) msg_len,
-                             (unsigned) reassembly_buf_sz,
-                             MBEDTLS_SSL_DTLS_MAX_BUFFERING,
-                             (unsigned) hs->buffering.total_bytes_buffered ) );
+                        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %" MBEDTLS_PRINTF_SIZET
+                                                    " (%" MBEDTLS_PRINTF_SIZET " with bitmap) would exceed"
+                                                    " the compile-time limit %" MBEDTLS_PRINTF_SIZET
+                                                    " (already %" MBEDTLS_PRINTF_SIZET
+                                                    " bytes buffered) -- fail\n",
+                             msg_len,
+                             reassembly_buf_sz,
+                             (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+                             hs->buffering.total_bytes_buffered ) );
                         ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
                         goto exit;
                     }
                 }
 
-                MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d",
+                MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %" MBEDTLS_PRINTF_SIZET,
                                             msg_len ) );
 
                 hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz );
@@ -4395,7 +4276,8 @@
                 frag_off = ssl_get_hs_frag_off( ssl );
                 frag_len = ssl_get_hs_frag_len( ssl );
 
-                MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d",
+                MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %" MBEDTLS_PRINTF_SIZET
+                                            ", length = %" MBEDTLS_PRINTF_SIZET,
                                             frag_off, frag_len ) );
                 memcpy( msg + frag_off, ssl->in_msg + 12, frag_len );
 
@@ -4622,15 +4504,18 @@
     if( rec->buf_len > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
                          hs->buffering.total_bytes_buffered ) )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n",
-                        (unsigned) rec->buf_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
-                        (unsigned) hs->buffering.total_bytes_buffered ) );
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %" MBEDTLS_PRINTF_SIZET
+                                    " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET
+                                    " (already %" MBEDTLS_PRINTF_SIZET
+                                    " bytes buffered) -- ignore\n",
+                        rec->buf_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+                        hs->buffering.total_bytes_buffered ) );
         return( 0 );
     }
 
     /* Buffer record */
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u",
-                                ssl->in_epoch + 1 ) );
+                                ssl->in_epoch + 1U ) );
     MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", rec->buf, rec->buf_len );
 
     /* ssl_parse_record_header() only considers records
@@ -4858,8 +4743,7 @@
     ssl->in_hdr[0] = rec.type;
     ssl->in_msg    = rec.buf + rec.data_offset;
     ssl->in_msglen = rec.data_len;
-    ssl->in_len[0] = (unsigned char)( rec.data_len >> 8 );
-    ssl->in_len[1] = (unsigned char)( rec.data_len      );
+    MBEDTLS_PUT_UINT16_BE( rec.data_len, ssl->in_len, 0 );
 
 #if defined(MBEDTLS_ZLIB_SUPPORT)
     if( ssl->transform_in != NULL &&
@@ -4903,7 +4787,7 @@
     {
         if( ssl->in_msglen != 1 )
         {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %d",
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %" MBEDTLS_PRINTF_SIZET,
                            ssl->in_msglen ) );
             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
         }
@@ -4939,12 +4823,12 @@
             /* Note: Standard allows for more than one 2 byte alert
                to be packed in a single message, but Mbed TLS doesn't
                currently support this. */
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %d",
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %" MBEDTLS_PRINTF_SIZET,
                            ssl->in_msglen ) );
             return( MBEDTLS_ERR_SSL_INVALID_RECORD );
         }
 
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]",
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%u:%u]",
                        ssl->in_msg[0], ssl->in_msg[1] ) );
 
         /*
@@ -5771,7 +5655,8 @@
         if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) "
-                                "maximum fragment length: %d > %d",
+                                "maximum fragment length: %" MBEDTLS_PRINTF_SIZET
+                                " > %" MBEDTLS_PRINTF_SIZET,
                                 len, max_len ) );
             return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
         }
diff --git a/third_party/mbedtls/repo/library/ssl_srv.c b/third_party/mbedtls/repo/library/ssl_srv.c
index e33b828..1a63173 100644
--- a/third_party/mbedtls/repo/library/ssl_srv.c
+++ b/third_party/mbedtls/repo/library/ssl_srv.c
@@ -34,6 +34,8 @@
 #include "mbedtls/debug.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
+#include "constant_time_internal.h"
+#include "mbedtls/constant_time.h"
 
 #include <string.h>
 
@@ -196,7 +198,7 @@
         /* Check verify-data in constant-time. The length OTOH is no secret */
         if( len    != 1 + ssl->verify_data_len ||
             buf[0] !=     ssl->verify_data_len ||
-            mbedtls_ssl_safer_memcmp( buf + 1, ssl->peer_verify_data,
+            mbedtls_ct_memcmp( buf + 1, ssl->peer_verify_data,
                           ssl->verify_data_len ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) );
@@ -298,13 +300,13 @@
         {
             mbedtls_ssl_sig_hash_set_add( &ssl->handshake->hash_algs, sig_cur, md_cur );
             MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:"
-                                        " match sig %d and hash %d",
-                                        sig_cur, md_cur ) );
+                                        " match sig %u and hash %u",
+                                        (unsigned) sig_cur, (unsigned) md_cur ) );
         }
         else
         {
             MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: "
-                                        "hash alg %d not supported", md_cur ) );
+                                        "hash alg %u not supported", (unsigned) md_cur ) );
         }
     }
 
@@ -633,7 +635,7 @@
     /* Remember the client asked us to send a new ticket */
     ssl->handshake->new_session_ticket = 1;
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", len ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %" MBEDTLS_PRINTF_SIZET, len ) );
 
     if( len == 0 )
         return( 0 );
@@ -1048,7 +1050,7 @@
     }
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "trying ciphersuite: %#04x (%s)",
-                                suite_id, suite_info->name ) );
+                                (unsigned int) suite_id, suite_info->name ) );
 
     if( suite_info->min_minor_ver > ssl->minor_ver ||
         suite_info->max_minor_ver < ssl->minor_ver )
@@ -1116,7 +1118,7 @@
             mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, sig_type ) == MBEDTLS_MD_NONE )
         {
             MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no suitable hash algorithm "
-                                        "for signature algorithm %d", sig_type ) );
+                                        "for signature algorithm %u", (unsigned) sig_type ) );
             return( 0 );
         }
     }
@@ -1247,7 +1249,7 @@
     sess_len = ( buf[2] << 8 ) | buf[3];
     chal_len = ( buf[4] << 8 ) | buf[5];
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d",
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciph_len: %u, sess_len: %u, chal_len: %u",
                    ciph_len, sess_len, chal_len ) );
 
     /*
@@ -1322,8 +1324,7 @@
     for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 )
     {
         if( p[0] == 0 &&
-            p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) &&
-            p[2] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE      ) & 0xff ) )
+            MBEDTLS_GET_UINT16_BE(p, 1) != MBEDTLS_SSL_FALLBACK_SCSV_VALUE )
         {
             MBEDTLS_SSL_DEBUG_MSG( 3, ( "received FALLBACK_SCSV" ) );
 
@@ -1354,8 +1355,7 @@
 #endif
         {
             if( p[0] != 0 ||
-                p[1] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) ||
-                p[2] != ( ( ciphersuites[i]      ) & 0xFF ) )
+                MBEDTLS_GET_UINT16_BE(p, 1) != ciphersuites[i] )
                 continue;
 
             got_common_suite = 1;
@@ -1629,7 +1629,7 @@
             if( cli_msg_seq != ssl->handshake->in_msg_seq )
             {
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message_seq: "
-                                    "%d (expected %d)", cli_msg_seq,
+                                    "%u (expected %u)", cli_msg_seq,
                                     ssl->handshake->in_msg_seq ) );
                 return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
             }
@@ -1887,8 +1887,7 @@
             ext_len = ( buf[ext_offset + 0] << 8 )
                     | ( buf[ext_offset + 1]      );
 
-            if( ( ext_len > 0 && ext_len < 4 ) ||
-                msg_len != ext_offset + 2 + ext_len )
+            if( msg_len != ext_offset + 2 + ext_len )
             {
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
                 mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
@@ -2073,20 +2072,12 @@
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
 
             default:
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
+                MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %u (ignoring)",
                                ext_id ) );
             }
 
             ext_len -= 4 + ext_size;
             ext += 4 + ext_size;
-
-            if( ext_len > 0 && ext_len < 4 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-                return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-            }
         }
 #if defined(MBEDTLS_SSL_PROTO_SSL3)
     }
@@ -2095,8 +2086,7 @@
 #if defined(MBEDTLS_SSL_FALLBACK_SCSV)
     for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 )
     {
-        if( p[0] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) &&
-            p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE      ) & 0xff ) )
+        if( MBEDTLS_GET_UINT16_BE( p, 0 ) == MBEDTLS_SSL_FALLBACK_SCSV_VALUE )
         {
             MBEDTLS_SSL_DEBUG_MSG( 2, ( "received FALLBACK_SCSV" ) );
 
@@ -2214,8 +2204,7 @@
         for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 )
 #endif
         {
-            if( p[0] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) ||
-                p[1] != ( ( ciphersuites[i]      ) & 0xFF ) )
+            if( MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i] )
                 continue;
 
             got_common_suite = 1;
@@ -2274,7 +2263,7 @@
         else
         {
             MBEDTLS_SSL_DEBUG_MSG( 3, ( "no hash algorithm for signature algorithm "
-                                        "%d - should not happen", sig_alg ) );
+                                        "%u - should not happen", (unsigned) sig_alg ) );
         }
     }
 #endif
@@ -2299,8 +2288,8 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding truncated hmac extension" ) );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_TRUNCATED_HMAC, p, 0 );
+    p += 2;
 
     *p++ = 0x00;
     *p++ = 0x00;
@@ -2343,12 +2332,11 @@
      *      opaque cid<0..2^8-1>;
      *   } ConnectionId;
     */
-
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_CID >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_CID      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_CID, p, 0 );
+    p += 2;
     ext_len = (size_t) ssl->own_cid_len + 1;
-    *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( ext_len      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 );
+    p += 2;
 
     *p++ = (uint8_t) ssl->own_cid_len;
     memcpy( p, ssl->own_cid, ssl->own_cid_len );
@@ -2390,8 +2378,8 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding encrypt then mac extension" ) );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, p, 0 );
+    p += 2;
 
     *p++ = 0x00;
     *p++ = 0x00;
@@ -2417,8 +2405,8 @@
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding extended master secret "
                         "extension" ) );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, p, 0 );
+    p += 2;
 
     *p++ = 0x00;
     *p++ = 0x00;
@@ -2442,8 +2430,8 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding session ticket extension" ) );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SESSION_TICKET, p, 0 );
+    p += 2;
 
     *p++ = 0x00;
     *p++ = 0x00;
@@ -2466,8 +2454,8 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO, p, 0 );
+    p += 2;
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
     if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
@@ -2507,8 +2495,8 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, p, 0 );
+    p += 2;
 
     *p++ = 0x00;
     *p++ = 1;
@@ -2537,8 +2525,8 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, supported_point_formats extension" ) );
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, p, 0 );
+    p += 2;
 
     *p++ = 0x00;
     *p++ = 2;
@@ -2575,8 +2563,8 @@
         return;
     }
 
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0 );
+    p += 2;
 
     ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx,
                                         p + 2, end - p - 2, &kkpp_len,
@@ -2587,8 +2575,8 @@
         return;
     }
 
-    *p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF );
-    *p++ = (unsigned char)( ( kkpp_len      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( kkpp_len, p, 0 );
+    p += 2;
 
     *olen = kkpp_len + 4;
 }
@@ -2613,18 +2601,15 @@
      * 6 . 6    protocol name length
      * 7 . 7+n  protocol name
      */
-    buf[0] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF );
-    buf[1] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ALPN, buf, 0);
 
     *olen = 7 + strlen( ssl->alpn_chosen );
 
-    buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF );
-    buf[3] = (unsigned char)( ( ( *olen - 4 )      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( *olen - 4, buf, 2 );
 
-    buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF );
-    buf[5] = (unsigned char)( ( ( *olen - 6 )      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( *olen - 6, buf, 4 );
 
-    buf[6] = (unsigned char)( ( ( *olen - 7 )      ) & 0xFF );
+    buf[6] = MBEDTLS_BYTE_0( *olen - 7 );
 
     memcpy( buf + 7, ssl->alpn_chosen, *olen - 7 );
 }
@@ -2669,15 +2654,13 @@
     }
 
     /* extension */
-    buf[0] = (unsigned char)( ( MBEDTLS_TLS_EXT_USE_SRTP >> 8 ) & 0xFF );
-    buf[1] = (unsigned char)( ( MBEDTLS_TLS_EXT_USE_SRTP      ) & 0xFF );
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_USE_SRTP, buf, 0 );
     /*
      * total length 5 and mki value: only one profile(2 bytes)
      *              and length(2 bytes) and srtp_mki  )
      */
     ext_len = 5 + mki_len;
-    buf[2] = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
-    buf[3] = (unsigned char)( ext_len & 0xFF );
+    MBEDTLS_PUT_UINT16_BE( ext_len, buf, 2 );
 
     /* protection profile length: 2 */
     buf[4] = 0x00;
@@ -2686,8 +2669,7 @@
                                 ssl->dtls_srtp_info.chosen_dtls_srtp_profile );
     if( profile_value != MBEDTLS_TLS_SRTP_UNSET )
     {
-        buf[6] = (unsigned char)( ( profile_value >> 8 ) & 0xFF );
-        buf[7] = (unsigned char)( profile_value & 0xFF );
+        MBEDTLS_PUT_UINT16_BE( profile_value, buf, 6 );
     }
     else
     {
@@ -2774,6 +2756,55 @@
 }
 #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
 
+static void ssl_handle_id_based_session_resumption( mbedtls_ssl_context *ssl )
+{
+    int ret;
+    mbedtls_ssl_session session_tmp;
+    mbedtls_ssl_session * const session = ssl->session_negotiate;
+
+    /* Resume is 0  by default, see ssl_handshake_init().
+     * It may be already set to 1 by ssl_parse_session_ticket_ext(). */
+    if( ssl->handshake->resume == 1 )
+        return;
+    if( session->id_len == 0 )
+        return;
+    if( ssl->conf->f_get_cache == NULL )
+        return;
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
+        return;
+#endif
+
+    mbedtls_ssl_session_init( &session_tmp );
+
+    session_tmp.id_len = session->id_len;
+    memcpy( session_tmp.id, session->id, session->id_len );
+
+    ret = ssl->conf->f_get_cache( ssl->conf->p_cache,
+                                  &session_tmp );
+    if( ret != 0 )
+        goto exit;
+
+    if( session->ciphersuite != session_tmp.ciphersuite ||
+        session->compression != session_tmp.compression )
+    {
+        /* Mismatch between cached and negotiated session */
+        goto exit;
+    }
+
+    /* Move semantics */
+    mbedtls_ssl_session_free( session );
+    *session = session_tmp;
+    memset( &session_tmp, 0, sizeof( session_tmp ) );
+
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) );
+    ssl->handshake->resume = 1;
+
+exit:
+
+    mbedtls_ssl_session_free( &session_tmp );
+}
+
 static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
 {
 #if defined(MBEDTLS_HAVE_TIME)
@@ -2821,12 +2852,11 @@
 
 #if defined(MBEDTLS_HAVE_TIME)
     t = mbedtls_time( NULL );
-    *p++ = (unsigned char)( t >> 24 );
-    *p++ = (unsigned char)( t >> 16 );
-    *p++ = (unsigned char)( t >>  8 );
-    *p++ = (unsigned char)( t       );
+    MBEDTLS_PUT_UINT32_BE( t, p, 0 );
+    p += 4;
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %" MBEDTLS_PRINTF_LONGLONG,
+                                (long long) t ) );
 #else
     if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 )
         return( ret );
@@ -2843,22 +2873,7 @@
 
     MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 );
 
-    /*
-     * Resume is 0  by default, see ssl_handshake_init().
-     * It may be already set to 1 by ssl_parse_session_ticket_ext().
-     * If not, try looking up session ID in our cache.
-     */
-    if( ssl->handshake->resume == 0 &&
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-        ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE &&
-#endif
-        ssl->session_negotiate->id_len != 0 &&
-        ssl->conf->f_get_cache != NULL &&
-        ssl->conf->f_get_cache( ssl->conf->p_cache, ssl->session_negotiate ) == 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) );
-        ssl->handshake->resume = 1;
-    }
+    ssl_handle_id_based_session_resumption( ssl );
 
     if( ssl->handshake->resume == 0 )
     {
@@ -2914,19 +2929,19 @@
     memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len );
     p += ssl->session_negotiate->id_len;
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n ) );
     MBEDTLS_SSL_DEBUG_BUF( 3,   "server hello, session id", buf + 39, n );
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
                    ssl->handshake->resume ? "a" : "no" ) );
 
-    *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite >> 8 );
-    *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite      );
-    *p++ = (unsigned char)( ssl->session_negotiate->compression      );
+    MBEDTLS_PUT_UINT16_BE( ssl->session_negotiate->ciphersuite, p, 0 );
+    p += 2;
+    *p++ = MBEDTLS_BYTE_0( ssl->session_negotiate->compression );
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s",
            mbedtls_ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite ) ) );
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X",
-                   ssl->session_negotiate->compression ) );
+                   (unsigned int) ssl->session_negotiate->compression ) );
 
     /* Do not write the extensions if the protocol is SSLv3 */
 #if defined(MBEDTLS_SSL_PROTO_SSL3)
@@ -2995,13 +3010,13 @@
     ext_len += olen;
 #endif
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %" MBEDTLS_PRINTF_SIZET,
+                                ext_len ) );
 
     if( ext_len > 0 )
     {
-        *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
-        *p++ = (unsigned char)( ( ext_len      ) & 0xFF );
-        p += ext_len;
+        MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 );
+        p += 2 + ext_len;
     }
 
 #if defined(MBEDTLS_SSL_PROTO_SSL3)
@@ -3140,8 +3155,7 @@
 #endif
         }
 
-        p[0] = (unsigned char)( sa_len >> 8 );
-        p[1] = (unsigned char)( sa_len      );
+        MBEDTLS_PUT_UINT16_BE( sa_len, p, 0 );
         sa_len += 2;
         p += sa_len;
     }
@@ -3181,8 +3195,8 @@
                 break;
             }
 
-            *p++ = (unsigned char)( dn_size >> 8 );
-            *p++ = (unsigned char)( dn_size      );
+            MBEDTLS_PUT_UINT16_BE( dn_size, p, 0 );
+            p += 2;
             memcpy( p, crt->subject_raw.p, dn_size );
             p += dn_size;
 
@@ -3196,8 +3210,7 @@
     ssl->out_msglen  = p - buf;
     ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
     ssl->out_msg[0]  = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST;
-    ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size  >> 8 );
-    ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size       );
+    MBEDTLS_PUT_UINT16_BE( total_dn_size, ssl->out_msg, 4 + ct_len + sa_len );
 
     ret = mbedtls_ssl_write_handshake_msg( ssl );
 
@@ -3454,7 +3467,11 @@
     {
         size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed;
         size_t hashlen = 0;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        unsigned char hash[PSA_HASH_MAX_SIZE];
+#else
         unsigned char hash[MBEDTLS_MD_MAX_SIZE];
+#endif
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
         /*
@@ -3502,7 +3519,7 @@
             md_alg = MBEDTLS_MD_NONE;
         }
 
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %d for signing", md_alg ) );
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %u for signing", (unsigned) md_alg ) );
 
         /*
          * 2.2: Compute the hash to be signed
@@ -3695,8 +3712,8 @@
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
     if( signature_len != 0 )
     {
-        ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len >> 8 );
-        ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len      );
+        ssl->out_msg[ssl->out_msglen++] = MBEDTLS_BYTE_1( signature_len );
+        ssl->out_msg[ssl->out_msglen++] = MBEDTLS_BYTE_0( signature_len );
 
         MBEDTLS_SSL_DEBUG_BUF( 3, "my signature",
                                ssl->out_msg + ssl->out_msglen,
@@ -3852,12 +3869,13 @@
     defined(MBEDTLS_SSL_PROTO_TLS1_2)
     if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 )
     {
-        if ( p + 2 > end ) {
+        if ( p + 2 > end )
+        {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
             return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
         }
-        if( *p++ != ( ( len >> 8 ) & 0xFF ) ||
-            *p++ != ( ( len      ) & 0xFF ) )
+        if( *p++ != MBEDTLS_BYTE_1( len ) ||
+            *p++ != MBEDTLS_BYTE_0( len ) )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
             return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
@@ -3959,16 +3977,7 @@
     diff |= peer_pms[1] ^ ver[1];
 
     /* mask = diff ? 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 = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) );
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
+    mask = mbedtls_ct_uint_mask( diff );
 
     /*
      * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding
@@ -4051,7 +4060,7 @@
         /* Identity is not a big secret since clients send it in the clear,
          * but treat it carefully anyway, just in case */
         if( n != ssl->conf->psk_identity_len ||
-            mbedtls_ssl_safer_memcmp( ssl->conf->psk_identity, *p, n ) != 0 )
+            mbedtls_ct_memcmp( ssl->conf->psk_identity, *p, n ) != 0 )
         {
             ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;
         }
@@ -4620,14 +4629,8 @@
         tlen = 0;
     }
 
-    ssl->out_msg[4] = ( lifetime >> 24 ) & 0xFF;
-    ssl->out_msg[5] = ( lifetime >> 16 ) & 0xFF;
-    ssl->out_msg[6] = ( lifetime >>  8 ) & 0xFF;
-    ssl->out_msg[7] = ( lifetime       ) & 0xFF;
-
-    ssl->out_msg[8] = (unsigned char)( ( tlen >> 8 ) & 0xFF );
-    ssl->out_msg[9] = (unsigned char)( ( tlen      ) & 0xFF );
-
+    MBEDTLS_PUT_UINT32_BE( lifetime, ssl->out_msg, 4 );
+    MBEDTLS_PUT_UINT16_BE( tlen, ssl->out_msg, 8 );
     ssl->out_msglen = 10 + tlen;
 
     /*
diff --git a/third_party/mbedtls/repo/library/ssl_ticket.c b/third_party/mbedtls/repo/library/ssl_ticket.c
index 626d137..046ed1b 100644
--- a/third_party/mbedtls/repo/library/ssl_ticket.c
+++ b/third_party/mbedtls/repo/library/ssl_ticket.c
@@ -245,8 +245,7 @@
     {
          goto cleanup;
     }
-    state_len_bytes[0] = ( clear_len >> 8 ) & 0xff;
-    state_len_bytes[1] = ( clear_len      ) & 0xff;
+    MBEDTLS_PUT_UINT16_BE( clear_len, state_len_bytes, 0 );
 
     /* Encrypt and authenticate */
     if( ( ret = mbedtls_cipher_auth_encrypt_ext( &key->ctx,
diff --git a/third_party/mbedtls/repo/library/ssl_tls.c b/third_party/mbedtls/repo/library/ssl_tls.c
index a1a5859..2e6469d 100644
--- a/third_party/mbedtls/repo/library/ssl_tls.c
+++ b/third_party/mbedtls/repo/library/ssl_tls.c
@@ -43,6 +43,7 @@
 #include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/version.h"
+#include "mbedtls/constant_time.h"
 
 #include <string.h>
 
@@ -187,6 +188,10 @@
     mbedtls_ssl_session_free( dst );
     memcpy( dst, src, sizeof( mbedtls_ssl_session ) );
 
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+    dst->ticket = NULL;
+#endif
+
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 
 #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
@@ -260,6 +265,72 @@
 
     return 0;
 }
+
+static void handle_buffer_resizing( mbedtls_ssl_context *ssl, int downsizing,
+                                    size_t in_buf_new_len,
+                                    size_t out_buf_new_len )
+{
+    int modified = 0;
+    size_t written_in = 0, iv_offset_in = 0, len_offset_in = 0;
+    size_t written_out = 0, iv_offset_out = 0, len_offset_out = 0;
+    if( ssl->in_buf != NULL )
+    {
+        written_in = ssl->in_msg - ssl->in_buf;
+        iv_offset_in = ssl->in_iv - ssl->in_buf;
+        len_offset_in = ssl->in_len - ssl->in_buf;
+        if( downsizing ?
+            ssl->in_buf_len > in_buf_new_len && ssl->in_left < in_buf_new_len :
+            ssl->in_buf_len < in_buf_new_len )
+        {
+            if( resize_buffer( &ssl->in_buf, in_buf_new_len, &ssl->in_buf_len ) != 0 )
+            {
+                MBEDTLS_SSL_DEBUG_MSG( 1, ( "input buffer resizing failed - out of memory" ) );
+            }
+            else
+            {
+                MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating in_buf to %" MBEDTLS_PRINTF_SIZET,
+                                            in_buf_new_len ) );
+                modified = 1;
+            }
+        }
+    }
+
+    if( ssl->out_buf != NULL )
+    {
+        written_out = ssl->out_msg - ssl->out_buf;
+        iv_offset_out = ssl->out_iv - ssl->out_buf;
+        len_offset_out = ssl->out_len - ssl->out_buf;
+        if( downsizing ?
+            ssl->out_buf_len > out_buf_new_len && ssl->out_left < out_buf_new_len :
+            ssl->out_buf_len < out_buf_new_len )
+        {
+            if( resize_buffer( &ssl->out_buf, out_buf_new_len, &ssl->out_buf_len ) != 0 )
+            {
+                MBEDTLS_SSL_DEBUG_MSG( 1, ( "output buffer resizing failed - out of memory" ) );
+            }
+            else
+            {
+                MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating out_buf to %" MBEDTLS_PRINTF_SIZET,
+                                            out_buf_new_len ) );
+                modified = 1;
+            }
+        }
+    }
+    if( modified )
+    {
+        /* Update pointers here to avoid doing it twice. */
+        mbedtls_ssl_reset_in_out_pointers( ssl );
+        /* Fields below might not be properly updated with record
+         * splitting or with CID, so they are manually updated here. */
+        ssl->out_msg = ssl->out_buf + written_out;
+        ssl->out_len = ssl->out_buf + len_offset_out;
+        ssl->out_iv = ssl->out_buf + iv_offset_out;
+
+        ssl->in_msg = ssl->in_buf + written_in;
+        ssl->in_len = ssl->in_buf + len_offset_in;
+        ssl->in_iv = ssl->in_buf + iv_offset_in;
+    }
+}
 #endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */
 
 /*
@@ -375,19 +446,37 @@
         goto exit;
     }
 
-    mbedtls_md_hmac_starts( &md_ctx, S1, hs );
-    mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb );
-    mbedtls_md_hmac_finish( &md_ctx, 4 + tmp );
+    ret = mbedtls_md_hmac_starts( &md_ctx, S1, hs );
+    if( ret != 0 )
+        goto exit;
+    ret = mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb );
+    if( ret != 0 )
+        goto exit;
+    ret = mbedtls_md_hmac_finish( &md_ctx, 4 + tmp );
+    if( ret != 0 )
+        goto exit;
 
     for( i = 0; i < dlen; i += 16 )
     {
-        mbedtls_md_hmac_reset ( &md_ctx );
-        mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 + nb );
-        mbedtls_md_hmac_finish( &md_ctx, h_i );
+        ret = mbedtls_md_hmac_reset ( &md_ctx );
+        if( ret != 0 )
+            goto exit;
+        ret = mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 + nb );
+        if( ret != 0 )
+            goto exit;
+        ret = mbedtls_md_hmac_finish( &md_ctx, h_i );
+        if( ret != 0 )
+            goto exit;
 
-        mbedtls_md_hmac_reset ( &md_ctx );
-        mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 );
-        mbedtls_md_hmac_finish( &md_ctx, 4 + tmp );
+        ret = mbedtls_md_hmac_reset ( &md_ctx );
+        if( ret != 0 )
+            goto exit;
+        ret = mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 );
+        if( ret != 0 )
+            goto exit;
+        ret = mbedtls_md_hmac_finish( &md_ctx, 4 + tmp );
+        if( ret != 0 )
+            goto exit;
 
         k = ( i + 16 > dlen ) ? dlen % 16 : 16;
 
@@ -411,19 +500,37 @@
         goto exit;
     }
 
-    mbedtls_md_hmac_starts( &md_ctx, S2, hs );
-    mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb );
-    mbedtls_md_hmac_finish( &md_ctx, tmp );
+    ret = mbedtls_md_hmac_starts( &md_ctx, S2, hs );
+    if( ret != 0 )
+        goto exit;
+    ret = mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb );
+    if( ret != 0 )
+        goto exit;
+    ret = mbedtls_md_hmac_finish( &md_ctx, tmp );
+    if( ret != 0 )
+        goto exit;
 
     for( i = 0; i < dlen; i += 20 )
     {
-        mbedtls_md_hmac_reset ( &md_ctx );
-        mbedtls_md_hmac_update( &md_ctx, tmp, 20 + nb );
-        mbedtls_md_hmac_finish( &md_ctx, h_i );
+        ret = mbedtls_md_hmac_reset ( &md_ctx );
+        if( ret != 0 )
+            goto exit;
+        ret = mbedtls_md_hmac_update( &md_ctx, tmp, 20 + nb );
+        if( ret != 0 )
+            goto exit;
+        ret = mbedtls_md_hmac_finish( &md_ctx, h_i );
+        if( ret != 0 )
+            goto exit;
 
-        mbedtls_md_hmac_reset ( &md_ctx );
-        mbedtls_md_hmac_update( &md_ctx, tmp, 20 );
-        mbedtls_md_hmac_finish( &md_ctx, tmp );
+        ret = mbedtls_md_hmac_reset ( &md_ctx );
+        if( ret != 0 )
+            goto exit;
+        ret = mbedtls_md_hmac_update( &md_ctx, tmp, 20 );
+        if( ret != 0 )
+            goto exit;
+        ret = mbedtls_md_hmac_finish( &md_ctx, tmp );
+        if( ret != 0 )
+            goto exit;
 
         k = ( i + 20 > dlen ) ? dlen % 20 : 20;
 
@@ -613,19 +720,37 @@
     if ( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
         goto exit;
 
-    mbedtls_md_hmac_starts( &md_ctx, secret, slen );
-    mbedtls_md_hmac_update( &md_ctx, tmp + md_len, nb );
-    mbedtls_md_hmac_finish( &md_ctx, tmp );
+    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;
 
     for( i = 0; i < dlen; i += md_len )
     {
-        mbedtls_md_hmac_reset ( &md_ctx );
-        mbedtls_md_hmac_update( &md_ctx, tmp, md_len + nb );
-        mbedtls_md_hmac_finish( &md_ctx, h_i );
+        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_md_hmac_reset ( &md_ctx );
-        mbedtls_md_hmac_update( &md_ctx, tmp, md_len );
-        mbedtls_md_hmac_finish( &md_ctx, tmp );
+        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;
 
         k = ( i + md_len > dlen ) ? dlen % md_len : md_len;
 
@@ -655,7 +780,7 @@
 }
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
 static int tls_prf_sha384( const unsigned char *secret, size_t slen,
                            const char *label,
                            const unsigned char *random, size_t rlen,
@@ -664,7 +789,7 @@
     return( tls_prf_generic( MBEDTLS_MD_SHA384, secret, slen,
                              label, random, rlen, dstbuf, dlen ) );
 }
-#endif /* MBEDTLS_SHA512_C */
+#endif /* MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384 */
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
 static void ssl_update_checksum_start( mbedtls_ssl_context *, const unsigned char *, size_t );
@@ -691,7 +816,7 @@
 static void ssl_calc_finished_tls_sha256( mbedtls_ssl_context *,unsigned char *, int );
 #endif
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
 static void ssl_update_checksum_sha384( mbedtls_ssl_context *, const unsigned char *, size_t );
 static void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *, unsigned char*, size_t * );
 static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *, int );
@@ -738,7 +863,7 @@
     else
 #endif
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
     if( tls_prf == tls_prf_sha384 )
     {
         return( MBEDTLS_SSL_TLS_PRF_SHA384 );
@@ -779,11 +904,11 @@
 #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
         case MBEDTLS_SSL_TLS_PRF_SHA384:
             tls_prf = tls_prf_sha384;
         break;
-#endif /* MBEDTLS_SHA512_C */
+#endif /* MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384 */
 #if defined(MBEDTLS_SHA256_C)
         case MBEDTLS_SSL_TLS_PRF_SHA256:
             tls_prf = tls_prf_sha256;
@@ -897,7 +1022,7 @@
     cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher );
     if( cipher_info == NULL )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %d not found",
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %u not found",
                                     ciphersuite_info->cipher ) );
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
     }
@@ -905,8 +1030,8 @@
     md_info = mbedtls_md_info_from_type( ciphersuite_info->mac );
     if( md_info == NULL )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "mbedtls_md info for %d not found",
-                            ciphersuite_info->mac ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "mbedtls_md info for %u not found",
+                            (unsigned) ciphersuite_info->mac ) );
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
     }
 
@@ -1165,8 +1290,14 @@
            For AEAD-based ciphersuites, there is nothing to do here. */
         if( mac_key_len != 0 )
         {
-            mbedtls_md_hmac_starts( &transform->md_ctx_enc, mac_enc, mac_key_len );
-            mbedtls_md_hmac_starts( &transform->md_ctx_dec, mac_dec, mac_key_len );
+            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;
         }
     }
     else
@@ -1384,7 +1515,8 @@
                                    int minor_ver,
                                    mbedtls_md_type_t hash )
 {
-#if !defined(MBEDTLS_SSL_PROTO_TLS1_2) || !defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SSL_PROTO_TLS1_2) ||       \
+    !( defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) )
     (void) hash;
 #endif
 
@@ -1407,7 +1539,7 @@
     else
 #endif
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
     if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 &&
         hash == MBEDTLS_MD_SHA384 )
     {
@@ -1799,7 +1931,7 @@
 }
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
 void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *ssl,
                                  unsigned char *hash,
                                  size_t *hlen )
@@ -1846,7 +1978,7 @@
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
     return;
 }
-#endif /* MBEDTLS_SHA512_C */
+#endif /* MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384 */
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
@@ -1881,8 +2013,8 @@
         if( end - p < 2 )
             return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
 
-        *(p++) = (unsigned char)( psk_len >> 8 );
-        *(p++) = (unsigned char)( psk_len      );
+        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 );
@@ -1922,9 +2054,8 @@
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret );
             return( ret );
         }
-        *(p++) = (unsigned char)( len >> 8 );
-        *(p++) = (unsigned char)( len );
-        p += len;
+        MBEDTLS_PUT_UINT16_BE( len, p, 0 );
+        p += 2 + len;
 
         MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K  );
     }
@@ -1944,9 +2075,8 @@
             return( ret );
         }
 
-        *(p++) = (unsigned char)( zlen >> 8 );
-        *(p++) = (unsigned char)( zlen      );
-        p += zlen;
+        MBEDTLS_PUT_UINT16_BE( zlen, p, 0 );
+        p += 2 + zlen;
 
         MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
                                 MBEDTLS_DEBUG_ECDH_Z );
@@ -1962,8 +2092,8 @@
     if( end - p < 2 )
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
 
-    *(p++) = (unsigned char)( psk_len >> 8 );
-    *(p++) = (unsigned char)( psk_len      );
+    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 );
@@ -2151,22 +2281,23 @@
         n = crt->raw.len;
         if( n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i )
         {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d",
-                           i + 3 + n, MBEDTLS_SSL_OUT_CONTENT_LEN ) );
+            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_CERTIFICATE_TOO_LARGE );
         }
 
-        ssl->out_msg[i    ] = (unsigned char)( n >> 16 );
-        ssl->out_msg[i + 1] = (unsigned char)( n >>  8 );
-        ssl->out_msg[i + 2] = (unsigned char)( n       );
+        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 );
 
         i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n );
         i += n; crt = crt->next;
     }
 
-    ssl->out_msg[4]  = (unsigned char)( ( i - 7 ) >> 16 );
-    ssl->out_msg[5]  = (unsigned char)( ( i - 7 ) >>  8 );
-    ssl->out_msg[6]  = (unsigned char)( ( i - 7 )       );
+    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 );
 
     ssl->out_msglen  = i;
     ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
@@ -2643,8 +2774,8 @@
 #if defined(MBEDTLS_DEBUG_C)
     if( ssl->session_negotiate->verify_result != 0 )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %x",
-                                    ssl->session_negotiate->verify_result ) );
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %08x",
+                                    (unsigned int) ssl->session_negotiate->verify_result ) );
     }
     else
     {
@@ -2767,7 +2898,7 @@
     chain = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
     if( chain == NULL )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
+        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,
@@ -2869,7 +3000,7 @@
     else
 #endif
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
     if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 )
         ssl->handshake->update_checksum = ssl_update_checksum_sha384;
     else
@@ -2902,7 +3033,7 @@
     mbedtls_sha256_starts_ret( &ssl->handshake->fin_sha256, 0 );
 #endif
 #endif
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_hash_abort( &ssl->handshake->fin_sha384_psa );
     psa_hash_setup( &ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384 );
@@ -2929,7 +3060,7 @@
     mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len );
 #endif
 #endif
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_hash_update( &ssl->handshake->fin_sha384_psa, buf, len );
 #else
@@ -2962,7 +3093,7 @@
 }
 #endif
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
 static void ssl_update_checksum_sha384( mbedtls_ssl_context *ssl,
                                         const unsigned char *buf, size_t len )
 {
@@ -3196,9 +3327,7 @@
 }
 #endif /* MBEDTLS_SHA256_C */
 
-#if defined(MBEDTLS_SHA512_C)
-
-typedef int (*finish_sha384_t)(mbedtls_sha512_context*, unsigned char*);
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
 
 static void ssl_calc_finished_tls_sha384(
                 mbedtls_ssl_context *ssl, unsigned char *buf, int from )
@@ -3258,13 +3387,19 @@
     MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha512 state", (unsigned char *)
                    sha512.state, sizeof( sha512.state ) );
 #endif
-    /*
-     * For SHA-384, we can save 16 bytes by keeping padbuf 48 bytes long.
-     * However, to avoid stringop-overflow warning in gcc, we have to cast
-     * mbedtls_sha512_finish_ret().
+    /* mbedtls_sha512_finish_ret's output parameter is declared as a
+     * 64-byte buffer, but sice we're using SHA-384, we know that the
+     * output fits in 48 bytes. This is correct C, but GCC 11.1 warns
+     * about it.
      */
-    finish_sha384_t finish = (finish_sha384_t)mbedtls_sha512_finish_ret;
-    finish( &sha512, padbuf );
+#if defined(__GNUC__) && __GNUC__ >= 11
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
+    mbedtls_sha512_finish_ret( &sha512, padbuf );
+#if defined(__GNUC__) && __GNUC__ >= 11
+#pragma GCC diagnostic pop
+#endif
 
     mbedtls_sha512_free( &sha512 );
 #endif
@@ -3278,7 +3413,7 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
 }
-#endif /* MBEDTLS_SHA512_C */
+#endif /* MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384 */
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
 void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl )
@@ -3500,22 +3635,6 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse finished" ) );
 
-    ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 );
-
-    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
-        return( ret );
-    }
-
-    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 );
-        return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
-    }
-
     /* There is currently no ciphersuite using another length with TLS 1.2 */
 #if defined(MBEDTLS_SSL_PROTO_SSL3)
     if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
@@ -3524,22 +3643,41 @@
 #endif
         hash_len = 12;
 
+    ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 );
+
+    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
+    {
+        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;
+        goto exit;
+    }
+
     if( ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED ||
         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 );
-        return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED );
+        ret = MBEDTLS_ERR_SSL_BAD_HS_FINISHED;
+        goto exit;
     }
 
-    if( mbedtls_ssl_safer_memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ),
+    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_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED );
+                                        MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
+        ret = MBEDTLS_ERR_SSL_BAD_HS_FINISHED;
+        goto exit;
     }
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
@@ -3568,7 +3706,9 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse finished" ) );
 
-    return( 0 );
+exit:
+    mbedtls_platform_zeroize( buf, hash_len );
+    return( ret );
 }
 
 static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake )
@@ -3592,7 +3732,7 @@
     mbedtls_sha256_starts_ret( &handshake->fin_sha256, 0 );
 #endif
 #endif
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     handshake->fin_sha384_psa = psa_hash_operation_init();
     psa_hash_setup( &handshake->fin_sha384_psa, PSA_ALG_SHA_384 );
@@ -3686,64 +3826,9 @@
     }
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
     /* If the buffers are too small - reallocate */
-    {
-        int modified = 0;
-        size_t written_in = 0, iv_offset_in = 0, len_offset_in = 0;
-        size_t written_out = 0, iv_offset_out = 0, len_offset_out = 0;
-        if( ssl->in_buf != NULL )
-        {
-            written_in = ssl->in_msg - ssl->in_buf;
-            iv_offset_in = ssl->in_iv - ssl->in_buf;
-            len_offset_in = ssl->in_len - ssl->in_buf;
-            if( ssl->in_buf_len < MBEDTLS_SSL_IN_BUFFER_LEN )
-            {
-                if( resize_buffer( &ssl->in_buf, MBEDTLS_SSL_IN_BUFFER_LEN,
-                                   &ssl->in_buf_len ) != 0 )
-                {
-                    MBEDTLS_SSL_DEBUG_MSG( 1, ( "input buffer resizing failed - out of memory" ) );
-                }
-                else
-                {
-                    MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating in_buf to %d", MBEDTLS_SSL_IN_BUFFER_LEN ) );
-                    modified = 1;
-                }
-            }
-        }
 
-        if( ssl->out_buf != NULL )
-        {
-            written_out = ssl->out_msg - ssl->out_buf;
-            iv_offset_out = ssl->out_iv - ssl->out_buf;
-            len_offset_out = ssl->out_len - ssl->out_buf;
-            if( ssl->out_buf_len < MBEDTLS_SSL_OUT_BUFFER_LEN )
-            {
-                if( resize_buffer( &ssl->out_buf, MBEDTLS_SSL_OUT_BUFFER_LEN,
-                                   &ssl->out_buf_len ) != 0 )
-                {
-                    MBEDTLS_SSL_DEBUG_MSG( 1, ( "output buffer resizing failed - out of memory" ) );
-                }
-                else
-                {
-                    MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating out_buf to %d", MBEDTLS_SSL_OUT_BUFFER_LEN ) );
-                    modified = 1;
-                }
-            }
-        }
-        if( modified )
-        {
-            /* Update pointers here to avoid doing it twice. */
-            mbedtls_ssl_reset_in_out_pointers( ssl );
-            /* Fields below might not be properly updated with record
-             * splitting or with CID, so they are manually updated here. */
-            ssl->out_msg = ssl->out_buf + written_out;
-            ssl->out_len = ssl->out_buf + len_offset_out;
-            ssl->out_iv = ssl->out_buf + iv_offset_out;
-
-            ssl->in_msg = ssl->in_buf + written_in;
-            ssl->in_len = ssl->in_buf + len_offset_in;
-            ssl->in_iv = ssl->in_buf + iv_offset_in;
-        }
-    }
+    handle_buffer_resizing( ssl, 0, MBEDTLS_SSL_IN_BUFFER_LEN,
+                                    MBEDTLS_SSL_OUT_BUFFER_LEN );
 #endif
 
     /* All pointers should exist and can be directly freed without issue */
@@ -3849,7 +3934,7 @@
     ssl->in_buf = mbedtls_calloc( 1, in_buf_len );
     if( ssl->in_buf == NULL )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", in_buf_len ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", in_buf_len ) );
         ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
         goto error;
     }
@@ -3860,7 +3945,7 @@
     ssl->out_buf = mbedtls_calloc( 1, out_buf_len );
     if( ssl->out_buf == NULL )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", out_buf_len ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", out_buf_len ) );
         ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
         goto error;
     }
@@ -5261,8 +5346,8 @@
     MBEDTLS_VERSION_MAJOR,
     MBEDTLS_VERSION_MINOR,
     MBEDTLS_VERSION_PATCH,
-    ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 8 ) & 0xFF,
-    ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 0 ) & 0xFF,
+    MBEDTLS_BYTE_1( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG ),
+    MBEDTLS_BYTE_0( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG ),
 };
 
 /*
@@ -5343,14 +5428,8 @@
     {
         start = (uint64_t) session->start;
 
-        *p++ = (unsigned char)( ( start >> 56 ) & 0xFF );
-        *p++ = (unsigned char)( ( start >> 48 ) & 0xFF );
-        *p++ = (unsigned char)( ( start >> 40 ) & 0xFF );
-        *p++ = (unsigned char)( ( start >> 32 ) & 0xFF );
-        *p++ = (unsigned char)( ( start >> 24 ) & 0xFF );
-        *p++ = (unsigned char)( ( start >> 16 ) & 0xFF );
-        *p++ = (unsigned char)( ( start >>  8 ) & 0xFF );
-        *p++ = (unsigned char)( ( start       ) & 0xFF );
+        MBEDTLS_PUT_UINT64_BE( start, p, 0 );
+        p += 8;
     }
 #endif /* MBEDTLS_HAVE_TIME */
 
@@ -5366,22 +5445,20 @@
 
     if( used <= buf_len )
     {
-        *p++ = (unsigned char)( ( session->ciphersuite >> 8 ) & 0xFF );
-        *p++ = (unsigned char)( ( session->ciphersuite      ) & 0xFF );
+        MBEDTLS_PUT_UINT16_BE( session->ciphersuite, p, 0 );
+        p += 2;
 
-        *p++ = (unsigned char)( session->compression & 0xFF );
+        *p++ = MBEDTLS_BYTE_0( session->compression );
 
-        *p++ = (unsigned char)( session->id_len & 0xFF );
+        *p++ = MBEDTLS_BYTE_0( session->id_len );
         memcpy( p, session->id, 32 );
         p += 32;
 
         memcpy( p, session->master, 48 );
         p += 48;
 
-        *p++ = (unsigned char)( ( session->verify_result >> 24 ) & 0xFF );
-        *p++ = (unsigned char)( ( session->verify_result >> 16 ) & 0xFF );
-        *p++ = (unsigned char)( ( session->verify_result >>  8 ) & 0xFF );
-        *p++ = (unsigned char)( ( session->verify_result       ) & 0xFF );
+        MBEDTLS_PUT_UINT32_BE( session->verify_result, p, 0 );
+        p += 4;
     }
 
     /*
@@ -5398,9 +5475,9 @@
 
     if( used <= buf_len )
     {
-        *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF );
-        *p++ = (unsigned char)( ( cert_len >>  8 ) & 0xFF );
-        *p++ = (unsigned char)( ( cert_len       ) & 0xFF );
+        *p++ = MBEDTLS_BYTE_2( cert_len );
+        *p++ = MBEDTLS_BYTE_1( cert_len );
+        *p++ = MBEDTLS_BYTE_0( cert_len );
 
         if( session->peer_cert != NULL )
         {
@@ -5441,9 +5518,9 @@
 
     if( used <= buf_len )
     {
-        *p++ = (unsigned char)( ( session->ticket_len >> 16 ) & 0xFF );
-        *p++ = (unsigned char)( ( session->ticket_len >>  8 ) & 0xFF );
-        *p++ = (unsigned char)( ( session->ticket_len       ) & 0xFF );
+        *p++ = MBEDTLS_BYTE_2( session->ticket_len );
+        *p++ = MBEDTLS_BYTE_1( session->ticket_len );
+        *p++ = MBEDTLS_BYTE_0( session->ticket_len );
 
         if( session->ticket != NULL )
         {
@@ -5451,10 +5528,8 @@
             p += session->ticket_len;
         }
 
-        *p++ = (unsigned char)( ( session->ticket_lifetime >> 24 ) & 0xFF );
-        *p++ = (unsigned char)( ( session->ticket_lifetime >> 16 ) & 0xFF );
-        *p++ = (unsigned char)( ( session->ticket_lifetime >>  8 ) & 0xFF );
-        *p++ = (unsigned char)( ( session->ticket_lifetime       ) & 0xFF );
+        MBEDTLS_PUT_UINT32_BE( session->ticket_lifetime, p, 0 );
+        p += 4;
     }
 #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
 
@@ -5479,7 +5554,7 @@
     used += 1;
 
     if( used <= buf_len )
-        *p++ = (unsigned char)( ( session->encrypt_then_mac ) & 0xFF );
+        *p++ = MBEDTLS_BYTE_0( session->encrypt_then_mac );
 #endif
 
     /* Done */
@@ -5978,7 +6053,7 @@
     mbedtls_sha256_free(   &handshake->fin_sha256    );
 #endif
 #endif
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_hash_abort( &handshake->fin_sha384_psa );
 #else
@@ -6068,66 +6143,8 @@
      * 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 */
-    {
-        int modified = 0;
-        uint32_t buf_len = mbedtls_ssl_get_input_buflen( ssl );
-        size_t written_in = 0, iv_offset_in = 0, len_offset_in = 0;
-        size_t written_out = 0, iv_offset_out = 0, len_offset_out = 0;
-        if( ssl->in_buf != NULL )
-        {
-            written_in = ssl->in_msg - ssl->in_buf;
-            iv_offset_in = ssl->in_iv - ssl->in_buf;
-            len_offset_in = ssl->in_len - ssl->in_buf;
-            if( ssl->in_buf_len > buf_len && ssl->in_left < buf_len )
-            {
-                if( resize_buffer( &ssl->in_buf, buf_len, &ssl->in_buf_len ) != 0 )
-                {
-                    MBEDTLS_SSL_DEBUG_MSG( 1, ( "input buffer resizing failed - out of memory" ) );
-                }
-                else
-                {
-                    MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating in_buf to %d", buf_len ) );
-                    modified = 1;
-                }
-            }
-        }
-
-
-        buf_len = mbedtls_ssl_get_output_buflen( ssl );
-        if(ssl->out_buf != NULL )
-        {
-            written_out = ssl->out_msg - ssl->out_buf;
-            iv_offset_out = ssl->out_iv - ssl->out_buf;
-            len_offset_out = ssl->out_len - ssl->out_buf;
-            if( ssl->out_buf_len > mbedtls_ssl_get_output_buflen( ssl ) &&
-                ssl->out_left < buf_len )
-            {
-                if( resize_buffer( &ssl->out_buf, buf_len, &ssl->out_buf_len ) != 0 )
-                {
-                    MBEDTLS_SSL_DEBUG_MSG( 1, ( "output buffer resizing failed - out of memory" ) );
-                }
-                else
-                {
-                    MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating out_buf to %d", buf_len ) );
-                    modified = 1;
-                }
-            }
-        }
-        if( modified )
-        {
-            /* Update pointers here to avoid doing it twice. */
-            mbedtls_ssl_reset_in_out_pointers( ssl );
-            /* Fields below might not be properly updated with record
-             * splitting or with CID, so they are manually updated here. */
-            ssl->out_msg = ssl->out_buf + written_out;
-            ssl->out_len = ssl->out_buf + len_offset_out;
-            ssl->out_iv = ssl->out_buf + iv_offset_out;
-
-            ssl->in_msg = ssl->in_buf + written_in;
-            ssl->in_len = ssl->in_buf + len_offset_in;
-            ssl->in_iv = ssl->in_buf + iv_offset_in;
-        }
-    }
+    handle_buffer_resizing( ssl, 1, mbedtls_ssl_get_input_buflen( ssl ),
+                                    mbedtls_ssl_get_output_buflen( ssl ) );
 #endif
 }
 
@@ -6190,11 +6207,11 @@
     MBEDTLS_VERSION_MAJOR,
     MBEDTLS_VERSION_MINOR,
     MBEDTLS_VERSION_PATCH,
-    ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 8 ) & 0xFF,
-    ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 0 ) & 0xFF,
-    ( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG >> 16 ) & 0xFF,
-    ( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG >>  8 ) & 0xFF,
-    ( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG >>  0 ) & 0xFF,
+    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 ),
 };
 
 /*
@@ -6335,10 +6352,8 @@
     used += 4 + session_len;
     if( used <= buf_len )
     {
-        *p++ = (unsigned char)( ( session_len >> 24 ) & 0xFF );
-        *p++ = (unsigned char)( ( session_len >> 16 ) & 0xFF );
-        *p++ = (unsigned char)( ( session_len >>  8 ) & 0xFF );
-        *p++ = (unsigned char)( ( session_len       ) & 0xFF );
+        MBEDTLS_PUT_UINT32_BE( session_len, p, 0 );
+        p += 4;
 
         ret = ssl_session_save( ssl->session, 1,
                                 p, session_len, &session_len );
@@ -6380,10 +6395,8 @@
     used += 4;
     if( used <= buf_len )
     {
-        *p++ = (unsigned char)( ( ssl->badmac_seen >> 24 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->badmac_seen >> 16 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->badmac_seen >>  8 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->badmac_seen       ) & 0xFF );
+        MBEDTLS_PUT_UINT32_BE( ssl->badmac_seen, p, 0 );
+        p += 4;
     }
 #endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
 
@@ -6391,23 +6404,11 @@
     used += 16;
     if( used <= buf_len )
     {
-        *p++ = (unsigned char)( ( ssl->in_window_top >> 56 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->in_window_top >> 48 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->in_window_top >> 40 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->in_window_top >> 32 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->in_window_top >> 24 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->in_window_top >> 16 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->in_window_top >>  8 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->in_window_top       ) & 0xFF );
+        MBEDTLS_PUT_UINT64_BE( ssl->in_window_top, p, 0 );
+        p += 8;
 
-        *p++ = (unsigned char)( ( ssl->in_window >> 56 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->in_window >> 48 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->in_window >> 40 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->in_window >> 32 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->in_window >> 24 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->in_window >> 16 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->in_window >>  8 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->in_window       ) & 0xFF );
+        MBEDTLS_PUT_UINT64_BE( ssl->in_window, p, 0 );
+        p += 8;
     }
 #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
 
@@ -6430,8 +6431,8 @@
     used += 2;
     if( used <= buf_len )
     {
-        *p++ = (unsigned char)( ( ssl->mtu >>  8 ) & 0xFF );
-        *p++ = (unsigned char)( ( ssl->mtu       ) & 0xFF );
+        MBEDTLS_PUT_UINT16_BE( ssl->mtu, p, 0 );
+        p += 2;
     }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
@@ -6478,7 +6479,7 @@
                            unsigned char *dstbuf, size_t dlen );
 static tls_prf_fn ssl_tls12prf_from_cs( int ciphersuite_id )
 {
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
     const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
          mbedtls_ssl_ciphersuite_from_id( ciphersuite_id );
 
@@ -6893,6 +6894,8 @@
 static int ssl_preset_default_hashes[] = {
 #if defined(MBEDTLS_SHA512_C)
     MBEDTLS_MD_SHA512,
+#endif
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
     MBEDTLS_MD_SHA384,
 #endif
 #if defined(MBEDTLS_SHA256_C)
@@ -7252,9 +7255,11 @@
         case MBEDTLS_SSL_HASH_SHA256:
             return( MBEDTLS_MD_SHA256 );
 #endif
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
         case MBEDTLS_SSL_HASH_SHA384:
             return( MBEDTLS_MD_SHA384 );
+#endif
+#if defined(MBEDTLS_SHA512_C)
         case MBEDTLS_SSL_HASH_SHA512:
             return( MBEDTLS_MD_SHA512 );
 #endif
@@ -7284,9 +7289,11 @@
         case MBEDTLS_MD_SHA256:
             return( MBEDTLS_SSL_HASH_SHA256 );
 #endif
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
         case MBEDTLS_MD_SHA384:
             return( MBEDTLS_SSL_HASH_SHA384 );
+#endif
+#if defined(MBEDTLS_SHA512_C)
         case MBEDTLS_MD_SHA512:
             return( MBEDTLS_SSL_HASH_SHA512 );
 #endif
@@ -7446,7 +7453,7 @@
             break;
 #endif
 #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
         case MBEDTLS_SSL_HASH_SHA384:
             ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384;
             break;
@@ -7591,7 +7598,7 @@
         goto exit;
     }
 
-    if( ( status = psa_hash_finish( &hash_operation, hash, MBEDTLS_MD_MAX_SIZE,
+    if( ( status = psa_hash_finish( &hash_operation, hash, PSA_HASH_MAX_SIZE,
                                     hashlen ) ) != PSA_SUCCESS )
     {
          MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_finish", status );
diff --git a/third_party/mbedtls/repo/library/ssl_tls13_keys.c b/third_party/mbedtls/repo/library/ssl_tls13_keys.c
index c39e032..3de6f03 100644
--- a/third_party/mbedtls/repo/library/ssl_tls13_keys.c
+++ b/third_party/mbedtls/repo/library/ssl_tls13_keys.c
@@ -112,17 +112,17 @@
 #endif
 
     *p++ = 0;
-    *p++ = (unsigned char)( ( desired_length >> 0 ) & 0xFF );
+    *p++ = MBEDTLS_BYTE_0( desired_length );
 
     /* Add label incl. prefix */
-    *p++ = (unsigned char)( total_label_len & 0xFF );
+    *p++ = MBEDTLS_BYTE_0( total_label_len );
     memcpy( p, tls1_3_label_prefix, sizeof(tls1_3_label_prefix) );
     p += sizeof(tls1_3_label_prefix);
     memcpy( p, label, llen );
     p += llen;
 
     /* Add context value */
-    *p++ = (unsigned char)( clen & 0xFF );
+    *p++ = MBEDTLS_BYTE_0( clen );
     if( clen != 0 )
         memcpy( p, ctx, clen );
 
diff --git a/third_party/mbedtls/repo/library/threading.c b/third_party/mbedtls/repo/library/threading.c
index 2bb932d..2de117f 100644
--- a/third_party/mbedtls/repo/library/threading.c
+++ b/third_party/mbedtls/repo/library/threading.c
@@ -67,6 +67,12 @@
     if( mutex == NULL )
         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;
 }
 
diff --git a/third_party/mbedtls/repo/library/version_features.c b/third_party/mbedtls/repo/library/version_features.c
index 42ccaf9..40c9520 100644
--- a/third_party/mbedtls/repo/library/version_features.c
+++ b/third_party/mbedtls/repo/library/version_features.c
@@ -225,6 +225,9 @@
 #if defined(MBEDTLS_ECP_INTERNAL_ALT)
     "MBEDTLS_ECP_INTERNAL_ALT",
 #endif /* MBEDTLS_ECP_INTERNAL_ALT */
+#if defined(MBEDTLS_ECP_NO_FALLBACK)
+    "MBEDTLS_ECP_NO_FALLBACK",
+#endif /* MBEDTLS_ECP_NO_FALLBACK */
 #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
     "MBEDTLS_ECP_RANDOMIZE_JAC_ALT",
 #endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
@@ -264,6 +267,9 @@
 #if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY)
     "MBEDTLS_CAMELLIA_SMALL_MEMORY",
 #endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */
+#if defined(MBEDTLS_CHECK_RETURN_WARNING)
+    "MBEDTLS_CHECK_RETURN_WARNING",
+#endif /* MBEDTLS_CHECK_RETURN_WARNING */
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     "MBEDTLS_CIPHER_MODE_CBC",
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
@@ -435,9 +441,18 @@
 #if defined(MBEDTLS_PKCS1_V21)
     "MBEDTLS_PKCS1_V21",
 #endif /* MBEDTLS_PKCS1_V21 */
+#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
+    "MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS",
+#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+    "MBEDTLS_PSA_CRYPTO_CLIENT",
+#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",
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
 #if defined(MBEDTLS_PSA_CRYPTO_SPM)
     "MBEDTLS_PSA_CRYPTO_SPM",
 #endif /* MBEDTLS_PSA_CRYPTO_SPM */
diff --git a/third_party/mbedtls/repo/library/x509.c b/third_party/mbedtls/repo/library/x509.c
index 2a7be32..f21e9e6 100644
--- a/third_party/mbedtls/repo/library/x509.c
+++ b/third_party/mbedtls/repo/library/x509.c
@@ -81,18 +81,18 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ( end - *p ) < 1 )
-        return( MBEDTLS_ERR_X509_INVALID_SERIAL +
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SERIAL,
+                MBEDTLS_ERR_ASN1_OUT_OF_DATA ) );
 
     if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) &&
         **p !=   MBEDTLS_ASN1_INTEGER )
-        return( MBEDTLS_ERR_X509_INVALID_SERIAL +
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SERIAL,
+                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
 
     serial->tag = *(*p)++;
 
     if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SERIAL, ret ) );
 
     serial->p = *p;
     *p += serial->len;
@@ -112,7 +112,7 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
 
     return( 0 );
 }
@@ -126,7 +126,7 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
 
     return( 0 );
 }
@@ -151,39 +151,39 @@
 
     /* Make sure we got a SEQUENCE and setup bounds */
     if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
-        return( MBEDTLS_ERR_X509_INVALID_ALG +
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
+                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
 
     p = alg->p;
     end = p + alg->len;
 
     if( p >= end )
-        return( MBEDTLS_ERR_X509_INVALID_ALG +
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
+                MBEDTLS_ERR_ASN1_OUT_OF_DATA ) );
 
     /* Parse md_oid */
     md_oid.tag = *p;
 
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
 
     md_oid.p = p;
     p += md_oid.len;
 
     /* Get md_alg from md_oid */
     if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
 
     /* Make sure params is absent of NULL */
     if( p == end )
         return( 0 );
 
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
 
     if( p != end )
-        return( MBEDTLS_ERR_X509_INVALID_ALG +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     return( 0 );
 }
@@ -217,8 +217,8 @@
 
     /* Make sure params is a SEQUENCE and setup bounds */
     if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
-        return( MBEDTLS_ERR_X509_INVALID_ALG +
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
+                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
 
     p = (unsigned char *) params->p;
     end = p + params->len;
@@ -239,14 +239,14 @@
             return( ret );
 
         if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
 
         if( p != end2 )
-            return( MBEDTLS_ERR_X509_INVALID_ALG +
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
+                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
     }
     else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-        return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
 
     if( p == end )
         return( 0 );
@@ -265,19 +265,19 @@
 
         /* Only MFG1 is recognised for now */
         if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 )
-            return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE +
-                    MBEDTLS_ERR_OID_NOT_FOUND );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE,
+                    MBEDTLS_ERR_OID_NOT_FOUND ) );
 
         /* Parse HashAlgorithm */
         if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 )
             return( ret );
 
         if( p != end2 )
-            return( MBEDTLS_ERR_X509_INVALID_ALG +
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
+                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
     }
     else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-        return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
 
     if( p == end )
         return( 0 );
@@ -291,14 +291,14 @@
         end2 = p + len;
 
         if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
 
         if( p != end2 )
-            return( MBEDTLS_ERR_X509_INVALID_ALG +
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
+                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
     }
     else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-        return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
 
     if( p == end )
         return( 0 );
@@ -314,21 +314,21 @@
         end2 = p + len;
 
         if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
 
         if( p != end2 )
-            return( MBEDTLS_ERR_X509_INVALID_ALG +
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
+                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
         if( trailer_field != 1 )
             return( MBEDTLS_ERR_X509_INVALID_ALG );
     }
     else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-        return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
 
     if( p != end )
-        return( MBEDTLS_ERR_X509_INVALID_ALG +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     return( 0 );
 }
@@ -354,47 +354,47 @@
 
     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) );
 
     end = *p + len;
 
     if( ( end - *p ) < 1 )
-        return( MBEDTLS_ERR_X509_INVALID_NAME +
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME,
+                MBEDTLS_ERR_ASN1_OUT_OF_DATA ) );
 
     oid = &cur->oid;
     oid->tag = **p;
 
     if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) );
 
     oid->p = *p;
     *p += oid->len;
 
     if( ( end - *p ) < 1 )
-        return( MBEDTLS_ERR_X509_INVALID_NAME +
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME,
+                MBEDTLS_ERR_ASN1_OUT_OF_DATA ) );
 
     if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING      &&
         **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING &&
         **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING &&
         **p != MBEDTLS_ASN1_BIT_STRING )
-        return( MBEDTLS_ERR_X509_INVALID_NAME +
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME,
+                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
 
     val = &cur->val;
     val->tag = *(*p)++;
 
     if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) );
 
     val->p = *p;
     *p += val->len;
 
     if( *p != end )
     {
-        return( MBEDTLS_ERR_X509_INVALID_NAME +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
     }
 
     cur->next = NULL;
@@ -440,7 +440,7 @@
          */
         if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len,
                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) );
 
         end_set  = *p + set_len;
 
@@ -604,8 +604,8 @@
     unsigned char tag;
 
     if( ( end - *p ) < 1 )
-        return( MBEDTLS_ERR_X509_INVALID_DATE +
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE,
+                MBEDTLS_ERR_ASN1_OUT_OF_DATA ) );
 
     tag = **p;
 
@@ -614,14 +614,14 @@
     else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME )
         year_len = 4;
     else
-        return( MBEDTLS_ERR_X509_INVALID_DATE +
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE,
+                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
 
     (*p)++;
     ret = mbedtls_asn1_get_len( p, end, &len );
 
     if( ret != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, ret ) );
 
     return x509_parse_time( p, len, year_len, tm );
 }
@@ -633,13 +633,13 @@
     int tag_type;
 
     if( ( end - *p ) < 1 )
-        return( MBEDTLS_ERR_X509_INVALID_SIGNATURE +
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SIGNATURE,
+                MBEDTLS_ERR_ASN1_OUT_OF_DATA ) );
 
     tag_type = **p;
 
     if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SIGNATURE, ret ) );
 
     sig->tag = tag_type;
     sig->len = len;
@@ -663,7 +663,7 @@
         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
 
     if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 )
-        return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG, ret ) );
 
 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
     if( *pk_alg == MBEDTLS_PK_RSASSA_PSS )
@@ -714,7 +714,7 @@
     ret = mbedtls_asn1_get_tag( p, end, &ext->len,
               MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag );
     if( ret != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
     ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag;
     ext->p   = *p;
@@ -725,11 +725,11 @@
      */
     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
     if( end != *p + len )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     return( 0 );
 }
diff --git a/third_party/mbedtls/repo/library/x509_crl.c b/third_party/mbedtls/repo/library/x509_crl.c
index edeb39b..ac4fc75 100644
--- a/third_party/mbedtls/repo/library/x509_crl.c
+++ b/third_party/mbedtls/repo/library/x509_crl.c
@@ -79,7 +79,7 @@
             return( 0 );
         }
 
-        return( MBEDTLS_ERR_X509_INVALID_VERSION + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_VERSION, ret ) );
     }
 
     return( 0 );
@@ -125,7 +125,7 @@
         /* Get enclosing sequence tag */
         if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
         end_ext_data = *p + len;
 
@@ -133,7 +133,7 @@
         if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len,
                                           MBEDTLS_ASN1_OID ) ) != 0 )
         {
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
         }
         *p += len;
 
@@ -142,29 +142,29 @@
                                            &is_critical ) ) != 0 &&
             ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
         {
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+            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_ERR_X509_INVALID_EXTENSIONS + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
         /* Ignore data so far and just check its length */
         *p += len;
         if( *p != end_ext_data )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
         /* Abort on (unsupported) critical extensions */
         if( is_critical )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                    MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                    MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
     }
 
     if( *p != end )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     return( 0 );
 }
@@ -198,27 +198,27 @@
             ext->p = NULL;
             return( 0 );
         }
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
     }
 
     end = *p + ext->len;
 
     if( end != *p + ext->len )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     while( *p < end )
     {
         if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
         *p += len;
     }
 
     if( *p != end )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     return( 0 );
 }
@@ -364,8 +364,8 @@
     if( len != (size_t) ( end - p ) )
     {
         mbedtls_x509_crl_free( crl );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
     }
 
     /*
@@ -377,7 +377,7 @@
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
     {
         mbedtls_x509_crl_free( crl );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
     }
 
     end = p + len;
@@ -421,7 +421,7 @@
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
     {
         mbedtls_x509_crl_free( crl );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
     }
 
     if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 )
@@ -444,10 +444,10 @@
 
     if( ( ret = mbedtls_x509_get_time( &p, end, &crl->next_update ) ) != 0 )
     {
-        if( ret != ( MBEDTLS_ERR_X509_INVALID_DATE +
-                        MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) &&
-            ret != ( MBEDTLS_ERR_X509_INVALID_DATE +
-                        MBEDTLS_ERR_ASN1_OUT_OF_DATA ) )
+        if( ret != ( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE,
+                        MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) &&
+            ret != ( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE,
+                        MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ) )
         {
             mbedtls_x509_crl_free( crl );
             return( ret );
@@ -486,8 +486,8 @@
     if( p != end )
     {
         mbedtls_x509_crl_free( crl );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
     }
 
     end = crl->raw.p + crl->raw.len;
@@ -521,8 +521,8 @@
     if( p != end )
     {
         mbedtls_x509_crl_free( crl );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
     }
 
     return( 0 );
diff --git a/third_party/mbedtls/repo/library/x509_crt.c b/third_party/mbedtls/repo/library/x509_crt.c
index a623c57..a6cccf8 100644
--- a/third_party/mbedtls/repo/library/x509_crt.c
+++ b/third_party/mbedtls/repo/library/x509_crt.c
@@ -91,15 +91,10 @@
  */
 #define X509_MAX_VERIFY_CHAIN_SIZE    ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 )
 
-/*
- * Default profile
- */
+/* Default profile. Do not remove items unless there are serious security
+ * concerns. */
 const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =
 {
-#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES)
-    /* Allow SHA-1 (weak, but still safe in controlled environments) */
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
-#endif
     /* Only SHA-2 hashes */
     MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
     MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
@@ -397,17 +392,17 @@
             return( 0 );
         }
 
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
     }
 
     end = *p + len;
 
     if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_VERSION + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_VERSION, ret ) );
 
     if( *p != end )
-        return( MBEDTLS_ERR_X509_INVALID_VERSION +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_VERSION,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     return( 0 );
 }
@@ -427,7 +422,7 @@
 
     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, ret ) );
 
     end = *p + len;
 
@@ -438,8 +433,8 @@
         return( ret );
 
     if( *p != end )
-        return( MBEDTLS_ERR_X509_INVALID_DATE +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     return( 0 );
 }
@@ -464,7 +459,7 @@
         if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
             return( 0 );
 
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
     }
 
     uid->p = *p;
@@ -491,7 +486,7 @@
 
     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
     if( *p == end )
         return( 0 );
@@ -502,7 +497,7 @@
             ret = mbedtls_asn1_get_int( p, end, ca_istrue );
 
         if( ret != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
         if( *ca_istrue != 0 )
             *ca_istrue = 1;
@@ -512,17 +507,17 @@
         return( 0 );
 
     if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
     if( *p != end )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     /* Do not accept max_pathlen equal to INT_MAX to avoid a signed integer
      * overflow, which is an undefined behavior. */
     if( *max_pathlen == INT_MAX )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_INVALID_LENGTH ) );
 
     (*max_pathlen)++;
 
@@ -537,11 +532,11 @@
     mbedtls_x509_bitstring bs = { 0, 0, NULL };
 
     if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
     if( bs.len != 1 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_INVALID_LENGTH ) );
 
     /* Get actual bitstring */
     *ns_cert_type = *bs.p;
@@ -557,11 +552,11 @@
     mbedtls_x509_bitstring bs = { 0, 0, NULL };
 
     if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
     if( bs.len < 1 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_INVALID_LENGTH ) );
 
     /* Get actual bitstring */
     *key_usage = 0;
@@ -585,12 +580,12 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
     /* Sequence length must be >= 1 */
     if( ext_key_usage->buf.p == NULL )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_INVALID_LENGTH ) );
 
     return( 0 );
 }
@@ -635,11 +630,11 @@
     /* Get main sequence tag */
     if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
     if( *p + len != end )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     while( *p < end )
     {
@@ -649,13 +644,13 @@
         tag = **p;
         (*p)++;
         if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
         if( ( tag & MBEDTLS_ASN1_TAG_CLASS_MASK ) !=
                 MBEDTLS_ASN1_CONTEXT_SPECIFIC )
         {
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                    MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                    MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
         }
 
         /*
@@ -691,8 +686,8 @@
             cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
 
             if( cur->next == NULL )
-                return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                        MBEDTLS_ERR_ASN1_ALLOC_FAILED );
+                return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                        MBEDTLS_ERR_ASN1_ALLOC_FAILED ) );
 
             cur = cur->next;
         }
@@ -708,8 +703,8 @@
     cur->next = NULL;
 
     if( *p != end )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     return( 0 );
 }
@@ -776,18 +771,18 @@
     ret = mbedtls_asn1_get_tag( p, end, &len,
                              MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
     if( ret != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
     if( *p + len != end )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     /*
      * Cannot be an empty sequence.
      */
     if( len == 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     while( *p < end )
     {
@@ -799,13 +794,13 @@
          */
         if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
         policy_end = *p + len;
 
         if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len,
                                           MBEDTLS_ASN1_OID ) ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
         policy_oid.tag = MBEDTLS_ASN1_OID;
         policy_oid.len = len;
@@ -833,8 +828,8 @@
             cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
 
             if( cur->next == NULL )
-                return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                        MBEDTLS_ERR_ASN1_ALLOC_FAILED );
+                return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                        MBEDTLS_ERR_ASN1_ALLOC_FAILED ) );
 
             cur = cur->next;
         }
@@ -854,7 +849,7 @@
         {
             if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len,
                      MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-                return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+                return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
             /*
              * Skip the optional policy qualifiers.
              */
@@ -862,16 +857,16 @@
         }
 
         if( *p != policy_end )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
     }
 
     /* Set final sequence entry's next pointer to NULL */
     cur->next = NULL;
 
     if( *p != end )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     return( parse_ret );
 }
@@ -911,14 +906,14 @@
 
         if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
         end_ext_data = *p + len;
 
         /* Get extension ID */
         if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len,
                                           MBEDTLS_ASN1_OID ) ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
         extn_oid.tag = MBEDTLS_ASN1_OID;
         extn_oid.p = *p;
@@ -927,19 +922,19 @@
         /* Get optional critical */
         if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
             ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+            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_ERR_X509_INVALID_EXTENSIONS + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
         start_ext_octet = *p;
         end_ext_octet = *p + len;
 
         if( end_ext_octet != end_ext_data )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
         /*
          * Detect supported extensions
@@ -965,8 +960,8 @@
             if( is_critical )
             {
                 /* Data is marked as critical: fail */
-                return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                        MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+                return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                        MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
             }
 #endif
             continue;
@@ -1059,8 +1054,8 @@
     }
 
     if( *p != end )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
     return( 0 );
 }
@@ -1138,7 +1133,7 @@
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
     {
         mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
     }
 
     end = p + len;
@@ -1185,7 +1180,7 @@
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
     {
         mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
     }
 
     if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
@@ -1218,7 +1213,7 @@
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
     {
         mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
     }
 
     if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
@@ -1283,8 +1278,8 @@
     if( p != end )
     {
         mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
     }
 
     end = crt_end;
@@ -1322,8 +1317,8 @@
     if( p != end )
     {
         mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
     }
 
     return( 0 );
@@ -1629,6 +1624,8 @@
     }
 #endif /* MBEDTLS_THREADING_C */
 
+    memset( &sb, 0, sizeof( sb ) );
+
     while( ( entry = readdir( dir ) ) != NULL )
     {
         snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name,
@@ -1704,7 +1701,7 @@
 
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
                                       MBEDTLS_ASN1_OID ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
     cur_oid.tag = MBEDTLS_ASN1_OID;
     cur_oid.p = p;
@@ -1721,20 +1718,20 @@
     if( p + len >= end )
     {
         mbedtls_platform_zeroize( other_name, sizeof( *other_name ) );
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
     }
     p += len;
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
                      MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-       return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+       return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OID ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
     other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID;
     other_name->value.hardware_module_name.oid.p = p;
@@ -1743,13 +1740,13 @@
     if( p + len >= end )
     {
         mbedtls_platform_zeroize( other_name, sizeof( *other_name ) );
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
     }
     p += len;
     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
                                       MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
     other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;
     other_name->value.hardware_module_name.val.p = p;
@@ -1759,8 +1756,8 @@
     {
         mbedtls_platform_zeroize( other_name,
                                   sizeof( *other_name ) );
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
     }
     return( 0 );
 }
diff --git a/third_party/mbedtls/repo/library/x509_csr.c b/third_party/mbedtls/repo/library/x509_csr.c
index 5463f8a..e259410 100644
--- a/third_party/mbedtls/repo/library/x509_csr.c
+++ b/third_party/mbedtls/repo/library/x509_csr.c
@@ -73,7 +73,7 @@
             return( 0 );
         }
 
-        return( MBEDTLS_ERR_X509_INVALID_VERSION + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_VERSION, ret ) );
     }
 
     return( 0 );
@@ -131,8 +131,8 @@
     if( len != (size_t) ( end - p ) )
     {
         mbedtls_x509_csr_free( csr );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
     }
 
     /*
@@ -144,7 +144,7 @@
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
     {
         mbedtls_x509_csr_free( csr );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
     }
 
     end = p + len;
@@ -176,7 +176,7 @@
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
     {
         mbedtls_x509_csr_free( csr );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
     }
 
     if( ( ret = mbedtls_x509_get_name( &p, p + len, &csr->subject ) ) != 0 )
@@ -210,7 +210,7 @@
             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
     {
         mbedtls_x509_csr_free( csr );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
     }
 
     p += len;
@@ -244,8 +244,8 @@
     if( p != end )
     {
         mbedtls_x509_csr_free( csr );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT +
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT,
+                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
     }
 
     return( 0 );
diff --git a/third_party/mbedtls/repo/library/x509write_crt.c b/third_party/mbedtls/repo/library/x509write_crt.c
index 32c6550..184c90c 100644
--- a/third_party/mbedtls/repo/library/x509write_crt.c
+++ b/third_party/mbedtls/repo/library/x509write_crt.c
@@ -163,7 +163,7 @@
     return(
         mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,
                              MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ),
-                             0, buf + sizeof(buf) - len, len ) );
+                             is_ca, buf + sizeof(buf) - len, len ) );
 }
 
 #if defined(MBEDTLS_SHA1_C)
@@ -233,7 +233,7 @@
 int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx,
                                          unsigned int key_usage )
 {
-    unsigned char buf[5], ku[2];
+    unsigned char buf[5] = {0}, ku[2] = {0};
     unsigned char *c;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
@@ -251,8 +251,7 @@
         return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
 
     c = buf + 5;
-    ku[0] = (unsigned char)( key_usage      );
-    ku[1] = (unsigned char)( key_usage >> 8 );
+    MBEDTLS_PUT_UINT16_LE( key_usage, ku, 0 );
     ret = mbedtls_asn1_write_named_bitstring( &c, buf, ku, 9 );
 
     if( ret < 0 )
@@ -272,7 +271,7 @@
 int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
                                     unsigned char ns_cert_type )
 {
-    unsigned char buf[4];
+    unsigned char buf[4] = {0};
     unsigned char *c;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
diff --git a/third_party/mbedtls/repo/library/x509write_csr.c b/third_party/mbedtls/repo/library/x509write_csr.c
index c7c8032..afda950 100644
--- a/third_party/mbedtls/repo/library/x509write_csr.c
+++ b/third_party/mbedtls/repo/library/x509write_csr.c
@@ -91,7 +91,7 @@
 
 int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage )
 {
-    unsigned char buf[4];
+    unsigned char buf[4] = {0};
     unsigned char *c;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
@@ -113,7 +113,7 @@
 int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx,
                                     unsigned char ns_cert_type )
 {
-    unsigned char buf[4];
+    unsigned char buf[4] = {0};
     unsigned char *c;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
diff --git a/third_party/mbedtls/repo/library/xtea.c b/third_party/mbedtls/repo/library/xtea.c
index 4b8c9c0..77f6cb6 100644
--- a/third_party/mbedtls/repo/library/xtea.c
+++ b/third_party/mbedtls/repo/library/xtea.c
@@ -37,29 +37,6 @@
 
 #if !defined(MBEDTLS_XTEA_ALT)
 
-/*
- * 32-bit integer manipulation macros (big endian)
- */
-#ifndef GET_UINT32_BE
-#define GET_UINT32_BE(n,b,i)                            \
-{                                                       \
-    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
-        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
-        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
-        | ( (uint32_t) (b)[(i) + 3]       );            \
-}
-#endif
-
-#ifndef PUT_UINT32_BE
-#define PUT_UINT32_BE(n,b,i)                            \
-{                                                       \
-    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
-    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
-    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
-    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
-}
-#endif
-
 void mbedtls_xtea_init( mbedtls_xtea_context *ctx )
 {
     memset( ctx, 0, sizeof( mbedtls_xtea_context ) );
@@ -84,7 +61,7 @@
 
     for( i = 0; i < 4; i++ )
     {
-        GET_UINT32_BE( ctx->k[i], key, i << 2 );
+        ctx->k[i] = MBEDTLS_GET_UINT32_BE( key, i << 2 );
     }
 }
 
@@ -98,8 +75,8 @@
 
     k = ctx->k;
 
-    GET_UINT32_BE( v0, input, 0 );
-    GET_UINT32_BE( v1, input, 4 );
+    v0 = MBEDTLS_GET_UINT32_BE( input, 0 );
+    v1 = MBEDTLS_GET_UINT32_BE( input, 4 );
 
     if( mode == MBEDTLS_XTEA_ENCRYPT )
     {
@@ -124,8 +101,8 @@
         }
     }
 
-    PUT_UINT32_BE( v0, output, 0 );
-    PUT_UINT32_BE( v1, output, 4 );
+    MBEDTLS_PUT_UINT32_BE( v0, output, 0 );
+    MBEDTLS_PUT_UINT32_BE( v1, output, 4 );
 
     return( 0 );
 }
diff --git a/third_party/mbedtls/repo/programs/.gitignore b/third_party/mbedtls/repo/programs/.gitignore
index 88fb9d5..d402607 100644
--- a/third_party/mbedtls/repo/programs/.gitignore
+++ b/third_party/mbedtls/repo/programs/.gitignore
@@ -1,8 +1,13 @@
+# Ignore makefiles generated by CMake, but not the makefile that's checked in.
 */Makefile
+!fuzz/Makefile
+
 *.sln
 *.vcxproj
 
-aes/aescrypt2
+*.o
+*.exe
+
 aes/crypt_and_hash
 hash/generic_sum
 hash/hello
@@ -48,6 +53,8 @@
 ssl/ssl_server2
 test/benchmark
 test/cpp_dummy_build
+test/cpp_dummy_build.cpp
+test/dlopen
 test/ecp-bench
 test/query_compile_time_config
 test/selftest
@@ -60,6 +67,7 @@
 x509/cert_req
 x509/cert_write
 x509/crl_app
+x509/load_roots
 x509/req_app
 
 # generated files
diff --git a/third_party/mbedtls/repo/programs/Makefile b/third_party/mbedtls/repo/programs/Makefile
index 9cbc471..2d0f705 100644
--- a/third_party/mbedtls/repo/programs/Makefile
+++ b/third_party/mbedtls/repo/programs/Makefile
@@ -3,8 +3,8 @@
 # To compile with PKCS11: add "-lpkcs11-helper" to LDFLAGS
 
 CFLAGS	?= -O2
-WARNING_CFLAGS ?= -Wall -Wextra
-WARNING_CXXFLAGS ?= -Wall -Wextra
+WARNING_CFLAGS ?= -Wall -Wextra -Wformat=2 -Wno-format-nonliteral
+WARNING_CXXFLAGS ?= -Wall -Wextra -Wformat=2 -Wno-format-nonliteral
 LDFLAGS ?=
 
 MBEDTLS_TEST_PATH:=../tests/src
@@ -18,6 +18,12 @@
 		-lmbedx509$(SHARED_SUFFIX)	\
 		-lmbedcrypto$(SHARED_SUFFIX)
 
+ifeq ($(shell uname -s),Linux)
+DLOPEN_LDFLAGS ?= -ldl
+else
+DLOPEN_LDFLAGS ?=
+endif
+
 include ../3rdparty/Makefile.inc
 LOCAL_CFLAGS+=$(THIRDPARTY_INCLUDES)
 
@@ -55,8 +61,19 @@
 LOCAL_LDFLAGS += -lz
 endif
 
+# Only build the dlopen test in shared library builds, and not when building
+# for Windows.
+ifdef BUILD_DLOPEN
+# Don't override the value
+else ifdef WINDOWS_BUILD
+BUILD_DLOPEN =
+else ifdef SHARED
+BUILD_DLOPEN = y
+else
+BUILD_DLOPEN =
+endif
+
 APPS = \
-	aes/aescrypt2$(EXEXT) \
 	aes/crypt_and_hash$(EXEXT) \
 	hash/generic_sum$(EXEXT) \
 	hash/hello$(EXEXT) \
@@ -107,6 +124,7 @@
 	x509/cert_req$(EXEXT) \
 	x509/cert_write$(EXEXT) \
 	x509/crl_app$(EXEXT) \
+	x509/load_roots$(EXEXT) \
 	x509/req_app$(EXEXT) \
 # End of APPS
 
@@ -114,6 +132,10 @@
 APPS +=	ssl/ssl_pthread_server$(EXEXT)
 endif
 
+ifdef BUILD_DLOPEN
+APPS +=	test/dlopen
+endif
+
 ifdef TEST_CPP
 APPS += test/cpp_dummy_build$(EXEXT)
 endif
@@ -139,10 +161,6 @@
 ${MBEDTLS_TEST_OBJS}:
 	$(MAKE) -C ../tests mbedtls_test
 
-aes/aescrypt2$(EXEXT): aes/aescrypt2.c $(DEP)
-	echo "  CC    aes/aescrypt2.c"
-	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) aes/aescrypt2.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
-
 aes/crypt_and_hash$(EXEXT): aes/crypt_and_hash.c $(DEP)
 	echo "  CC    aes/crypt_and_hash.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) aes/crypt_and_hash.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
@@ -239,7 +257,7 @@
 	echo "  CC    psa/key_ladder_demo.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) psa/key_ladder_demo.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
-psa/psa_constant_names$(EXEXT): psa/psa_constant_names.c $(DEP)
+psa/psa_constant_names$(EXEXT): psa/psa_constant_names.c psa/psa_constant_names_generated.c $(DEP)
 	echo "  CC    psa/psa_constant_names.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) psa/psa_constant_names.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
@@ -267,21 +285,32 @@
 	echo "  CC    ssl/ssl_client1.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_client1.c  $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
-ssl/ssl_client2$(EXEXT): ssl/ssl_client2.c test/query_config.c $(DEP)
+SSL_TEST_OBJECTS = test/query_config.o ssl/ssl_test_lib.o
+SSL_TEST_DEPS = $(SSL_TEST_OBJECTS) \
+		test/query_config.h \
+		ssl/ssl_test_lib.h \
+		ssl/ssl_test_common_source.c \
+		$(DEP)
+
+ssl/ssl_test_lib.o: ssl/ssl_test_lib.c ssl/ssl_test_lib.h $(DEP)
+	echo "  CC    ssl/ssl_test_lib.c"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) -c ssl/ssl_test_lib.c -o $@
+
+ssl/ssl_client2$(EXEXT): ssl/ssl_client2.c $(SSL_TEST_DEPS)
 	echo "  CC    ssl/ssl_client2.c"
-	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_client2.c test/query_config.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_client2.c $(SSL_TEST_OBJECTS) $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
 ssl/ssl_server$(EXEXT): ssl/ssl_server.c $(DEP)
 	echo "  CC    ssl/ssl_server.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_server.c   $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
-ssl/ssl_server2$(EXEXT): ssl/ssl_server2.c test/query_config.c $(DEP)
+ssl/ssl_server2$(EXEXT): ssl/ssl_server2.c $(SSL_TEST_DEPS)
 	echo "  CC    ssl/ssl_server2.c"
-	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_server2.c test/query_config.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_server2.c $(SSL_TEST_OBJECTS) $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
-ssl/ssl_context_info$(EXEXT): ssl/ssl_context_info.c test/query_config.c $(DEP)
+ssl/ssl_context_info$(EXEXT): ssl/ssl_context_info.c test/query_config.o test/query_config.h $(DEP)
 	echo "  CC    ssl/ssl_context_info.c"
-	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_context_info.c test/query_config.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_context_info.c test/query_config.o $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
 ssl/ssl_fork_server$(EXEXT): ssl/ssl_fork_server.c $(DEP)
 	echo "  CC    ssl/ssl_fork_server.c"
@@ -303,10 +332,27 @@
 	echo "  CC    test/benchmark.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/benchmark.c   $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
+test/cpp_dummy_build.cpp: test/generate_cpp_dummy_build.sh
+	echo "  Gen   test/cpp_dummy_build.cpp"
+	test/generate_cpp_dummy_build.sh
+
 test/cpp_dummy_build$(EXEXT): test/cpp_dummy_build.cpp $(DEP)
 	echo "  CXX   test/cpp_dummy_build.cpp"
 	$(CXX) $(LOCAL_CXXFLAGS) $(CXXFLAGS) test/cpp_dummy_build.cpp   $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
+ifdef BUILD_DLOPEN
+test/dlopen$(EXEXT): test/dlopen.c $(DEP)
+	echo "  CC    test/dlopen.c"
+# Do not link any test objects (that would bring in a static dependency on
+# libmbedcrypto at least). Do not link with libmbed* (that would defeat the
+# purpose of testing dynamic loading).
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/dlopen.c $(LDFLAGS) $(DLOPEN_LDFLAGS) -o $@
+endif
+
+test/query_config.o: test/query_config.c test/query_config.h $(DEP)
+	echo "  CC    test/query_config.c"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) -c test/query_config.c -o $@
+
 test/selftest$(EXEXT): test/selftest.c $(DEP)
 	echo "  CC    test/selftest.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/selftest.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
@@ -319,9 +365,9 @@
 	echo "  CC    test/zeroize.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/zeroize.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
-test/query_compile_time_config$(EXEXT): test/query_compile_time_config.c test/query_config.c $(DEP)
+test/query_compile_time_config$(EXEXT): test/query_compile_time_config.c test/query_config.o test/query_config.h $(DEP)
 	echo "  CC    test/query_compile_time_config.c"
-	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/query_compile_time_config.c test/query_config.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/query_compile_time_config.c test/query_config.o $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
 util/pem2der$(EXEXT): util/pem2der.c $(DEP)
 	echo "  CC    util/pem2der.c"
@@ -347,6 +393,10 @@
 	echo "  CC    x509/cert_req.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/cert_req.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
+x509/load_roots$(EXEXT): x509/load_roots.c $(DEP)
+	echo "  CC    x509/load_roots.c"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/load_roots.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
 x509/req_app$(EXEXT): x509/req_app.c $(DEP)
 	echo "  CC    x509/req_app.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/req_app.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
@@ -359,10 +409,12 @@
 ifndef WINDOWS
 	rm -f $(APPS)
 	-rm -f ssl/ssl_pthread_server$(EXEXT)
-	-rm -f test/cpp_dummy_build$(EXEXT)
+	-rm -f test/cpp_dummy_build.cpp test/cpp_dummy_build$(EXEXT)
+	-rm -f test/dlopen$(EXEXT)
 else
 	if exist *.o del /Q /F *.o
 	if exist *.exe del /Q /F *.exe
+	if exist test\cpp_dummy_build.cpp del /Q /F test\cpp_dummy_build.cpp
 endif
 	$(MAKE) -C fuzz clean
 
diff --git a/third_party/mbedtls/repo/programs/README.md b/third_party/mbedtls/repo/programs/README.md
index d26349d..e9e9f57 100644
--- a/third_party/mbedtls/repo/programs/README.md
+++ b/third_party/mbedtls/repo/programs/README.md
@@ -5,9 +5,6 @@
 
 ## Symmetric cryptography (AES) examples
 
-* [`aes/aescrypt2.c`](aes/aescrypt2.c): file encryption and authentication with a key derived from a low-entropy secret, demonstrating the low-level AES interface, the digest interface and HMAC.  
-  Warning: this program illustrates how to use low-level functions in the library. It should not be taken as an example of how to build a secure encryption mechanism. To derive a key from a low-entropy secret such as a password, use a standard key stretching mechanism such as PBKDF2 (provided by the `pkcs5` module). To encrypt and authenticate data, use a standard mode such as GCM or CCM (both available as library module).
-
 * [`aes/crypt_and_hash.c`](aes/crypt_and_hash.c): file encryption and authentication, demonstrating the generic cipher interface and the generic hash interface.
 
 ## Hash (digest) examples
diff --git a/third_party/mbedtls/repo/programs/aes/CMakeLists.txt b/third_party/mbedtls/repo/programs/aes/CMakeLists.txt
index 6b8ce2a..62a54c7 100644
--- a/third_party/mbedtls/repo/programs/aes/CMakeLists.txt
+++ b/third_party/mbedtls/repo/programs/aes/CMakeLists.txt
@@ -1,5 +1,4 @@
 set(executables
-    aescrypt2
     crypt_and_hash
 )
 
diff --git a/third_party/mbedtls/repo/programs/aes/aescrypt2.c b/third_party/mbedtls/repo/programs/aes/aescrypt2.c
deleted file mode 100644
index 95d64d9..0000000
--- a/third_party/mbedtls/repo/programs/aes/aescrypt2.c
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
- *  AES-256 file encryption program
- *
- *  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.
- */
-
-/* Enable definition of fileno() even when compiling with -std=c99. Must be
- * set before config.h, which pulls in glibc's features.h indirectly.
- * Harmless on other platforms. */
-#define _POSIX_C_SOURCE 200112L
-
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
-
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#define mbedtls_fprintf         fprintf
-#define mbedtls_printf          printf
-#define mbedtls_exit            exit
-#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
-#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
-#endif /* MBEDTLS_PLATFORM_C */
-
-#include "mbedtls/aes.h"
-#include "mbedtls/md.h"
-#include "mbedtls/platform_util.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if defined(_WIN32)
-#include <windows.h>
-#if !defined(_WIN32_WCE)
-#include <io.h>
-#endif
-#else
-#include <sys/types.h>
-#include <unistd.h>
-#endif
-
-#define MODE_ENCRYPT    0
-#define MODE_DECRYPT    1
-
-#define USAGE   \
-    "\n  aescrypt2 <mode> <input filename> <output filename> <key>\n" \
-    "\n   <mode>: 0 = encrypt, 1 = decrypt\n" \
-    "\n  example: aescrypt2 0 file file.aes hex:E76B2413958B00E193\n" \
-    "\n"
-
-#if !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_SHA256_C) || \
-    !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_MD_C)
-int main( void )
-{
-    mbedtls_printf("MBEDTLS_AES_C and/or MBEDTLS_SHA256_C "
-                    "and/or MBEDTLS_FS_IO and/or MBEDTLS_MD_C "
-                    "not defined.\n");
-    mbedtls_exit( 0 );
-}
-#else
-
-
-int main( int argc, char *argv[] )
-{
-    int ret = 0;
-    int exit_code = MBEDTLS_EXIT_FAILURE;
-
-    unsigned int i, n;
-    int mode, lastn;
-    size_t keylen;
-    FILE *fkey, *fin = NULL, *fout = NULL;
-
-    char *p;
-
-    unsigned char IV[16];
-    unsigned char tmp[16];
-    unsigned char key[512];
-    unsigned char digest[64];
-    unsigned char buffer[1024];
-    unsigned char diff;
-
-    mbedtls_aes_context aes_ctx;
-    mbedtls_md_context_t sha_ctx;
-
-#if defined(_WIN32_WCE)
-    long filesize, offset;
-#elif defined(_WIN32)
-       LARGE_INTEGER li_size;
-    __int64 filesize, offset;
-#else
-      off_t filesize, offset;
-#endif
-
-    mbedtls_aes_init( &aes_ctx );
-    mbedtls_md_init( &sha_ctx );
-
-    ret = mbedtls_md_setup( &sha_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 1 );
-    if( ret != 0 )
-    {
-        mbedtls_printf( "  ! mbedtls_md_setup() returned -0x%04x\n", (unsigned int) -ret );
-        goto exit;
-    }
-
-    /*
-     * Parse the command-line arguments.
-     */
-    if( argc != 5 )
-    {
-        mbedtls_printf( USAGE );
-
-#if defined(_WIN32)
-        mbedtls_printf( "\n  Press Enter to exit this program.\n" );
-        fflush( stdout ); getchar();
-#endif
-
-        goto exit;
-    }
-
-    mode = atoi( argv[1] );
-    memset( IV,     0, sizeof( IV ) );
-    memset( key,    0, sizeof( key ) );
-    memset( digest, 0, sizeof( digest ) );
-    memset( buffer, 0, sizeof( buffer ) );
-
-    if( mode != MODE_ENCRYPT && mode != MODE_DECRYPT )
-    {
-        mbedtls_fprintf( stderr, "invalide operation mode\n" );
-        goto exit;
-    }
-
-    if( strcmp( argv[2], argv[3] ) == 0 )
-    {
-        mbedtls_fprintf( stderr, "input and output filenames must differ\n" );
-        goto exit;
-    }
-
-    if( ( fin = fopen( argv[2], "rb" ) ) == NULL )
-    {
-        mbedtls_fprintf( stderr, "fopen(%s,rb) failed\n", argv[2] );
-        goto exit;
-    }
-
-    if( ( fout = fopen( argv[3], "wb+" ) ) == NULL )
-    {
-        mbedtls_fprintf( stderr, "fopen(%s,wb+) failed\n", argv[3] );
-        goto exit;
-    }
-
-    /*
-     * Read the secret key from file or command line
-     */
-    if( ( fkey = fopen( argv[4], "rb" ) ) != NULL )
-    {
-        keylen = fread( key, 1, sizeof( key ), fkey );
-        fclose( fkey );
-    }
-    else
-    {
-        if( memcmp( argv[4], "hex:", 4 ) == 0 )
-        {
-            p = &argv[4][4];
-            keylen = 0;
-
-            while( sscanf( p, "%02X", &n ) > 0 &&
-                   keylen < (int) sizeof( key ) )
-            {
-                key[keylen++] = (unsigned char) n;
-                p += 2;
-            }
-        }
-        else
-        {
-            keylen = strlen( argv[4] );
-
-            if( keylen > (int) sizeof( key ) )
-                keylen = (int) sizeof( key );
-
-            memcpy( key, argv[4], keylen );
-        }
-    }
-
-#if defined(_WIN32_WCE)
-    filesize = fseek( fin, 0L, SEEK_END );
-#else
-#if defined(_WIN32)
-    /*
-     * Support large files (> 2Gb) on Win32
-     */
-    li_size.QuadPart = 0;
-    li_size.LowPart  =
-        SetFilePointer( (HANDLE) _get_osfhandle( _fileno( fin ) ),
-                        li_size.LowPart, &li_size.HighPart, FILE_END );
-
-    if( li_size.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR )
-    {
-        mbedtls_fprintf( stderr, "SetFilePointer(0,FILE_END) failed\n" );
-        goto exit;
-    }
-
-    filesize = li_size.QuadPart;
-#else
-    if( ( filesize = lseek( fileno( fin ), 0, SEEK_END ) ) < 0 )
-    {
-        perror( "lseek" );
-        goto exit;
-    }
-#endif
-#endif
-
-    if( fseek( fin, 0, SEEK_SET ) < 0 )
-    {
-        mbedtls_fprintf( stderr, "fseek(0,SEEK_SET) failed\n" );
-        goto exit;
-    }
-
-    if( mode == MODE_ENCRYPT )
-    {
-        /*
-         * Generate the initialization vector as:
-         * IV = SHA-256( filesize || filename )[0..15]
-         */
-        for( i = 0; i < 8; i++ )
-            buffer[i] = (unsigned char)( filesize >> ( i << 3 ) );
-
-        p = argv[2];
-
-        mbedtls_md_starts( &sha_ctx );
-        mbedtls_md_update( &sha_ctx, buffer, 8 );
-        mbedtls_md_update( &sha_ctx, (unsigned char *) p, strlen( p ) );
-        mbedtls_md_finish( &sha_ctx, digest );
-
-        memcpy( IV, digest, 16 );
-
-        /*
-         * The last four bits in the IV are actually used
-         * to store the file size modulo the AES block size.
-         */
-        lastn = (int)( filesize & 0x0F );
-
-        IV[15] = (unsigned char)
-            ( ( IV[15] & 0xF0 ) | lastn );
-
-        /*
-         * Append the IV at the beginning of the output.
-         */
-        if( fwrite( IV, 1, 16, fout ) != 16 )
-        {
-            mbedtls_fprintf( stderr, "fwrite(%d bytes) failed\n", 16 );
-            goto exit;
-        }
-
-        /*
-         * Hash the IV and the secret key together 8192 times
-         * using the result to setup the AES context and HMAC.
-         */
-        memset( digest, 0,  32 );
-        memcpy( digest, IV, 16 );
-
-        for( i = 0; i < 8192; i++ )
-        {
-            mbedtls_md_starts( &sha_ctx );
-            mbedtls_md_update( &sha_ctx, digest, 32 );
-            mbedtls_md_update( &sha_ctx, key, keylen );
-            mbedtls_md_finish( &sha_ctx, digest );
-        }
-
-        mbedtls_aes_setkey_enc( &aes_ctx, digest, 256 );
-        mbedtls_md_hmac_starts( &sha_ctx, digest, 32 );
-
-        /*
-         * Encrypt and write the ciphertext.
-         */
-        for( offset = 0; offset < filesize; offset += 16 )
-        {
-            n = ( filesize - offset > 16 ) ? 16 : (int)
-                ( filesize - offset );
-
-            if( fread( buffer, 1, n, fin ) != (size_t) n )
-            {
-                mbedtls_fprintf( stderr, "fread(%u bytes) failed\n", n );
-                goto exit;
-            }
-
-            for( i = 0; i < 16; i++ )
-                buffer[i] = (unsigned char)( buffer[i] ^ IV[i] );
-
-            mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, buffer, buffer );
-            mbedtls_md_hmac_update( &sha_ctx, buffer, 16 );
-
-            if( fwrite( buffer, 1, 16, fout ) != 16 )
-            {
-                mbedtls_fprintf( stderr, "fwrite(%d bytes) failed\n", 16 );
-                goto exit;
-            }
-
-            memcpy( IV, buffer, 16 );
-        }
-
-        /*
-         * Finally write the HMAC.
-         */
-        mbedtls_md_hmac_finish( &sha_ctx, digest );
-
-        if( fwrite( digest, 1, 32, fout ) != 32 )
-        {
-            mbedtls_fprintf( stderr, "fwrite(%d bytes) failed\n", 16 );
-            goto exit;
-        }
-    }
-
-    if( mode == MODE_DECRYPT )
-    {
-        /*
-         *  The encrypted file must be structured as follows:
-         *
-         *        00 .. 15              Initialization Vector
-         *        16 .. 31              AES Encrypted Block #1
-         *           ..
-         *      N*16 .. (N+1)*16 - 1    AES Encrypted Block #N
-         *  (N+1)*16 .. (N+1)*16 + 32   HMAC-SHA-256(ciphertext)
-         */
-        if( filesize < 48 )
-        {
-            mbedtls_fprintf( stderr, "File too short to be encrypted.\n" );
-            goto exit;
-        }
-
-        if( ( filesize & 0x0F ) != 0 )
-        {
-            mbedtls_fprintf( stderr, "File size not a multiple of 16.\n" );
-            goto exit;
-        }
-
-        /*
-         * Subtract the IV + HMAC length.
-         */
-        filesize -= ( 16 + 32 );
-
-        /*
-         * Read the IV and original filesize modulo 16.
-         */
-        if( fread( buffer, 1, 16, fin ) != 16 )
-        {
-            mbedtls_fprintf( stderr, "fread(%d bytes) failed\n", 16 );
-            goto exit;
-        }
-
-        memcpy( IV, buffer, 16 );
-        lastn = IV[15] & 0x0F;
-
-        /*
-         * Hash the IV and the secret key together 8192 times
-         * using the result to setup the AES context and HMAC.
-         */
-        memset( digest, 0,  32 );
-        memcpy( digest, IV, 16 );
-
-        for( i = 0; i < 8192; i++ )
-        {
-            mbedtls_md_starts( &sha_ctx );
-            mbedtls_md_update( &sha_ctx, digest, 32 );
-            mbedtls_md_update( &sha_ctx, key, keylen );
-            mbedtls_md_finish( &sha_ctx, digest );
-        }
-
-        mbedtls_aes_setkey_dec( &aes_ctx, digest, 256 );
-        mbedtls_md_hmac_starts( &sha_ctx, digest, 32 );
-
-        /*
-         * Decrypt and write the plaintext.
-         */
-        for( offset = 0; offset < filesize; offset += 16 )
-        {
-            if( fread( buffer, 1, 16, fin ) != 16 )
-            {
-                mbedtls_fprintf( stderr, "fread(%d bytes) failed\n", 16 );
-                goto exit;
-            }
-
-            memcpy( tmp, buffer, 16 );
-
-            mbedtls_md_hmac_update( &sha_ctx, buffer, 16 );
-            mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_DECRYPT, buffer, buffer );
-
-            for( i = 0; i < 16; i++ )
-                buffer[i] = (unsigned char)( buffer[i] ^ IV[i] );
-
-            memcpy( IV, tmp, 16 );
-
-            n = ( lastn > 0 && offset == filesize - 16 )
-                ? lastn : 16;
-
-            if( fwrite( buffer, 1, n, fout ) != (size_t) n )
-            {
-                mbedtls_fprintf( stderr, "fwrite(%u bytes) failed\n", n );
-                goto exit;
-            }
-        }
-
-        /*
-         * Verify the message authentication code.
-         */
-        mbedtls_md_hmac_finish( &sha_ctx, digest );
-
-        if( fread( buffer, 1, 32, fin ) != 32 )
-        {
-            mbedtls_fprintf( stderr, "fread(%d bytes) failed\n", 32 );
-            goto exit;
-        }
-
-        /* Use constant-time buffer comparison */
-        diff = 0;
-        for( i = 0; i < 32; i++ )
-            diff |= digest[i] ^ buffer[i];
-
-        if( diff != 0 )
-        {
-            mbedtls_fprintf( stderr, "HMAC check failed: wrong key, "
-                             "or file corrupted.\n" );
-            goto exit;
-        }
-    }
-
-    exit_code = MBEDTLS_EXIT_SUCCESS;
-
-exit:
-    if( fin )
-        fclose( fin );
-    if( fout )
-        fclose( fout );
-
-    /* Zeroize all command line arguments to also cover
-       the case when the user has missed or reordered some,
-       in which case the key might not be in argv[4]. */
-    for( i = 0; i < (unsigned int) argc; i++ )
-        mbedtls_platform_zeroize( argv[i], strlen( argv[i] ) );
-
-    mbedtls_platform_zeroize( IV,     sizeof( IV ) );
-    mbedtls_platform_zeroize( key,    sizeof( key ) );
-    mbedtls_platform_zeroize( tmp,    sizeof( tmp ) );
-    mbedtls_platform_zeroize( buffer, sizeof( buffer ) );
-    mbedtls_platform_zeroize( digest, sizeof( digest ) );
-
-    mbedtls_aes_free( &aes_ctx );
-    mbedtls_md_free( &sha_ctx );
-
-    mbedtls_exit( exit_code );
-}
-#endif /* MBEDTLS_AES_C && MBEDTLS_SHA256_C && MBEDTLS_FS_IO */
diff --git a/third_party/mbedtls/repo/programs/aes/crypt_and_hash.c b/third_party/mbedtls/repo/programs/aes/crypt_and_hash.c
index 63a1248..18bdf6c 100644
--- a/third_party/mbedtls/repo/programs/aes/crypt_and_hash.c
+++ b/third_party/mbedtls/repo/programs/aes/crypt_and_hash.c
@@ -281,10 +281,27 @@
 
         p = argv[2];
 
-        mbedtls_md_starts( &md_ctx );
-        mbedtls_md_update( &md_ctx, buffer, 8 );
-        mbedtls_md_update( &md_ctx, (unsigned char *) p, strlen( p ) );
-        mbedtls_md_finish( &md_ctx, digest );
+        if( mbedtls_md_starts( &md_ctx ) != 0 )
+        {
+            mbedtls_fprintf( stderr, "mbedtls_md_starts() returned error\n" );
+            goto exit;
+        }
+        if( mbedtls_md_update( &md_ctx, buffer, 8 ) != 0 )
+        {
+            mbedtls_fprintf( stderr, "mbedtls_md_update() returned error\n" );
+            goto exit;
+        }
+        if( mbedtls_md_update( &md_ctx, ( unsigned char * ) p, strlen( p ) )
+            != 0 )
+        {
+            mbedtls_fprintf( stderr, "mbedtls_md_update() returned error\n" );
+            goto exit;
+        }
+        if( mbedtls_md_finish( &md_ctx, digest ) != 0 )
+        {
+            mbedtls_fprintf( stderr, "mbedtls_md_finish() returned error\n" );
+            goto exit;
+        }
 
         memcpy( IV, digest, 16 );
 
@@ -306,10 +323,30 @@
 
         for( i = 0; i < 8192; i++ )
         {
-            mbedtls_md_starts( &md_ctx );
-            mbedtls_md_update( &md_ctx, digest, 32 );
-            mbedtls_md_update( &md_ctx, key, keylen );
-            mbedtls_md_finish( &md_ctx, digest );
+            if( mbedtls_md_starts( &md_ctx ) != 0 )
+            {
+                mbedtls_fprintf( stderr,
+                                 "mbedtls_md_starts() returned error\n" );
+                goto exit;
+            }
+            if( mbedtls_md_update( &md_ctx, digest, 32 ) != 0 )
+            {
+                mbedtls_fprintf( stderr,
+                                 "mbedtls_md_update() returned error\n" );
+                goto exit;
+            }
+            if( mbedtls_md_update( &md_ctx, key, keylen ) != 0 )
+            {
+                mbedtls_fprintf( stderr,
+                                 "mbedtls_md_update() returned error\n" );
+                goto exit;
+            }
+            if( mbedtls_md_finish( &md_ctx, digest ) != 0 )
+            {
+                mbedtls_fprintf( stderr,
+                                 "mbedtls_md_finish() returned error\n" );
+                goto exit;
+            }
 
         }
 
@@ -330,7 +367,11 @@
             goto exit;
         }
 
-        mbedtls_md_hmac_starts( &md_ctx, digest, 32 );
+        if( mbedtls_md_hmac_starts( &md_ctx, digest, 32 ) != 0 )
+        {
+            mbedtls_fprintf( stderr, "mbedtls_md_hmac_starts() returned error\n" );
+            goto exit;
+        }
 
         /*
          * Encrypt and write the ciphertext.
@@ -352,7 +393,11 @@
                 goto exit;
             }
 
-            mbedtls_md_hmac_update( &md_ctx, output, olen );
+            if( mbedtls_md_hmac_update( &md_ctx, output, olen ) != 0 )
+            {
+                mbedtls_fprintf( stderr, "mbedtls_md_hmac_update() returned error\n" );
+                goto exit;
+            }
 
             if( fwrite( output, 1, olen, fout ) != olen )
             {
@@ -366,7 +411,11 @@
             mbedtls_fprintf( stderr, "mbedtls_cipher_finish() returned error\n" );
             goto exit;
         }
-        mbedtls_md_hmac_update( &md_ctx, output, olen );
+        if( mbedtls_md_hmac_update( &md_ctx, output, olen ) != 0 )
+        {
+            mbedtls_fprintf( stderr, "mbedtls_md_hmac_update() returned error\n" );
+            goto exit;
+        }
 
         if( fwrite( output, 1, olen, fout ) != olen )
         {
@@ -377,7 +426,11 @@
         /*
          * Finally write the HMAC.
          */
-        mbedtls_md_hmac_finish( &md_ctx, digest );
+        if( mbedtls_md_hmac_finish( &md_ctx, digest ) != 0 )
+        {
+            mbedtls_fprintf( stderr, "mbedtls_md_hmac_finish() returned error\n" );
+            goto exit;
+        }
 
         if( fwrite( digest, 1, mbedtls_md_get_size( md_info ), fout ) != mbedtls_md_get_size( md_info ) )
         {
@@ -446,10 +499,26 @@
 
         for( i = 0; i < 8192; i++ )
         {
-            mbedtls_md_starts( &md_ctx );
-            mbedtls_md_update( &md_ctx, digest, 32 );
-            mbedtls_md_update( &md_ctx, key, keylen );
-            mbedtls_md_finish( &md_ctx, digest );
+            if( mbedtls_md_starts( &md_ctx ) != 0 )
+            {
+                mbedtls_fprintf( stderr, "mbedtls_md_starts() returned error\n" );
+                goto exit;
+            }
+            if( mbedtls_md_update( &md_ctx, digest, 32 ) != 0 )
+            {
+                mbedtls_fprintf( stderr, "mbedtls_md_update() returned error\n" );
+                goto exit;
+            }
+            if( mbedtls_md_update( &md_ctx, key, keylen ) != 0 )
+            {
+                mbedtls_fprintf( stderr, "mbedtls_md_update() returned error\n" );
+                goto exit;
+            }
+            if( mbedtls_md_finish( &md_ctx, digest ) != 0 )
+            {
+                mbedtls_fprintf( stderr, "mbedtls_md_finish() returned error\n" );
+                goto exit;
+            }
         }
 
         if( mbedtls_cipher_setkey( &cipher_ctx, digest, cipher_info->key_bitlen,
@@ -471,7 +540,11 @@
             goto exit;
         }
 
-        mbedtls_md_hmac_starts( &md_ctx, digest, 32 );
+        if( mbedtls_md_hmac_starts( &md_ctx, digest, 32 ) != 0 )
+        {
+            mbedtls_fprintf( stderr, "mbedtls_md_hmac_starts() returned error\n" );
+            goto exit;
+        }
 
         /*
          * Decrypt and write the plaintext.
@@ -488,7 +561,11 @@
                 goto exit;
             }
 
-            mbedtls_md_hmac_update( &md_ctx, buffer, ilen );
+            if( mbedtls_md_hmac_update( &md_ctx, buffer, ilen ) != 0 )
+            {
+                mbedtls_fprintf( stderr, "mbedtls_md_hmac_update() returned error\n" );
+                goto exit;
+            }
             if( mbedtls_cipher_update( &cipher_ctx, buffer, ilen, output,
                                        &olen ) != 0 )
             {
@@ -506,7 +583,11 @@
         /*
          * Verify the message authentication code.
          */
-        mbedtls_md_hmac_finish( &md_ctx, digest );
+        if( mbedtls_md_hmac_finish( &md_ctx, digest ) != 0 )
+        {
+            mbedtls_fprintf( stderr, "mbedtls_md_hmac_finish() returned error\n" );
+            goto exit;
+        }
 
         if( fread( buffer, 1, mbedtls_md_get_size( md_info ), fin ) != mbedtls_md_get_size( md_info ) )
         {
@@ -529,7 +610,11 @@
         /*
          * Write the final block of data
          */
-        mbedtls_cipher_finish( &cipher_ctx, output, &olen );
+        if( mbedtls_cipher_finish( &cipher_ctx, output, &olen ) != 0 )
+        {
+            mbedtls_fprintf( stderr, "mbedtls_cipher_finish() returned error\n" );
+            goto exit;
+        }
 
         if( fwrite( output, 1, olen, fout ) != olen )
         {
diff --git a/third_party/mbedtls/repo/programs/fuzz/.gitignore b/third_party/mbedtls/repo/programs/fuzz/.gitignore
index 6fcc004..5dc0960 100644
--- a/third_party/mbedtls/repo/programs/fuzz/.gitignore
+++ b/third_party/mbedtls/repo/programs/fuzz/.gitignore
@@ -1,4 +1,3 @@
-*.o
 fuzz_client
 fuzz_dtlsclient
 fuzz_dtlsserver
diff --git a/third_party/mbedtls/repo/programs/fuzz/CMakeLists.txt b/third_party/mbedtls/repo/programs/fuzz/CMakeLists.txt
index f0e5705..fd55e31 100644
--- a/third_party/mbedtls/repo/programs/fuzz/CMakeLists.txt
+++ b/third_party/mbedtls/repo/programs/fuzz/CMakeLists.txt
@@ -32,20 +32,24 @@
 
 foreach(exe IN LISTS executables_no_common_c executables_with_common_c)
 
-    add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
-
-    if (NOT FUZZINGENGINE_LIB)
-        target_link_libraries(${exe} ${libs})
-        set_property(TARGET ${exe} APPEND PROPERTY SOURCES onefile.c)
-    else()
-        target_link_libraries(${exe} ${libs} FuzzingEngine)
-        SET_TARGET_PROPERTIES(${exe} PROPERTIES LINKER_LANGUAGE CXX)
+    set(exe_sources ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
+    if(NOT FUZZINGENGINE_LIB)
+        list(APPEND exe_sources onefile.c)
     endif()
 
     # This emulates "if ( ... IN_LIST ... )" which becomes available in CMake 3.3
     list(FIND executables_with_common_c ${exe} exe_index)
-    if (${exe_index} GREATER -1)
-        set_property(TARGET ${exe} APPEND PROPERTY SOURCES common.c)
+    if(${exe_index} GREATER -1)
+        list(APPEND exe_sources common.c)
+    endif()
+
+    add_executable(${exe} ${exe_sources})
+
+    if (NOT FUZZINGENGINE_LIB)
+        target_link_libraries(${exe} ${libs})
+    else()
+        target_link_libraries(${exe} ${libs} FuzzingEngine)
+        SET_TARGET_PROPERTIES(${exe} PROPERTIES LINKER_LANGUAGE CXX)
     endif()
 
 endforeach()
diff --git a/third_party/mbedtls/repo/programs/fuzz/Makefile b/third_party/mbedtls/repo/programs/fuzz/Makefile
index fa17918..084fc24 100644
--- a/third_party/mbedtls/repo/programs/fuzz/Makefile
+++ b/third_party/mbedtls/repo/programs/fuzz/Makefile
@@ -20,8 +20,6 @@
 DLEXT ?= so
 EXEXT=
 SHARED_SUFFIX=
-# python2 for POSIX since FreeBSD has only python2 as default.
-PYTHON ?= python2
 
 # Zlib shared library extensions:
 ifdef ZLIB
diff --git a/third_party/mbedtls/repo/programs/fuzz/common.c b/third_party/mbedtls/repo/programs/fuzz/common.c
index ac39ee2..e12ee3b 100644
--- a/third_party/mbedtls/repo/programs/fuzz/common.c
+++ b/third_party/mbedtls/repo/programs/fuzz/common.c
@@ -1,4 +1,5 @@
 #include "common.h"
+#include <limits.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
diff --git a/third_party/mbedtls/repo/programs/pkey/dh_client.c b/third_party/mbedtls/repo/programs/pkey/dh_client.c
index d6e4990..f6c6226 100644
--- a/third_party/mbedtls/repo/programs/pkey/dh_client.c
+++ b/third_party/mbedtls/repo/programs/pkey/dh_client.c
@@ -274,7 +274,9 @@
     mbedtls_printf( "...\n  . Receiving and decrypting the ciphertext" );
     fflush( stdout );
 
-    mbedtls_aes_setkey_dec( &aes, buf, 256 );
+    ret = mbedtls_aes_setkey_dec( &aes, buf, 256 );
+    if( ret != 0 )
+        goto exit;
 
     memset( buf, 0, sizeof( buf ) );
 
@@ -284,7 +286,9 @@
         goto exit;
     }
 
-    mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_DECRYPT, buf, buf );
+    ret = mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_DECRYPT, buf, buf );
+    if( ret != 0 )
+        goto exit;
     buf[16] = '\0';
     mbedtls_printf( "\n  . Plaintext is \"%s\"\n\n", (char *) buf );
 
diff --git a/third_party/mbedtls/repo/programs/pkey/dh_server.c b/third_party/mbedtls/repo/programs/pkey/dh_server.c
index dccf095..8f032a3 100644
--- a/third_party/mbedtls/repo/programs/pkey/dh_server.c
+++ b/third_party/mbedtls/repo/programs/pkey/dh_server.c
@@ -295,9 +295,13 @@
     mbedtls_printf( "...\n  . Encrypting and sending the ciphertext" );
     fflush( stdout );
 
-    mbedtls_aes_setkey_enc( &aes, buf, 256 );
+    ret = mbedtls_aes_setkey_enc( &aes, buf, 256 );
+    if( ret != 0 )
+        goto exit;
     memcpy( buf, PLAINTEXT, 16 );
-    mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_ENCRYPT, buf, buf );
+    ret = mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_ENCRYPT, buf, buf );
+    if( ret != 0 )
+        goto exit;
 
     if( ( ret = mbedtls_net_send( &client_fd, buf, 16 ) ) != 16 )
     {
diff --git a/third_party/mbedtls/repo/programs/pkey/key_app_writer.c b/third_party/mbedtls/repo/programs/pkey/key_app_writer.c
index 6a4d0e4..0d531ea 100644
--- a/third_party/mbedtls/repo/programs/pkey/key_app_writer.c
+++ b/third_party/mbedtls/repo/programs/pkey/key_app_writer.c
@@ -197,7 +197,9 @@
 {
     int ret = 1;
     int exit_code = MBEDTLS_EXIT_FAILURE;
-    char buf[1024];
+#if defined(MBEDTLS_ERROR_C)
+    char buf[200];
+#endif
     int i;
     char *p, *q;
 
@@ -208,7 +210,9 @@
      * Set to sane values
      */
     mbedtls_pk_init( &key );
+#if defined(MBEDTLS_ERROR_C)
     memset( buf, 0, sizeof( buf ) );
+#endif
 
     mbedtls_mpi_init( &N ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q );
     mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &DP );
@@ -296,8 +300,7 @@
 
         if( ret != 0 )
         {
-            mbedtls_strerror( ret, (char *) buf, sizeof(buf) );
-            mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
+            mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile returned -0x%04x", (unsigned int) -ret );
             goto exit;
         }
 
@@ -357,8 +360,7 @@
 
         if( ret != 0 )
         {
-            mbedtls_strerror( ret, (char *) buf, sizeof(buf) );
-            mbedtls_printf( " failed\n  !  mbedtls_pk_parse_public_key returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
+            mbedtls_printf( " failed\n  !  mbedtls_pk_parse_public_key returned -0x%04x", (unsigned int) -ret );
             goto exit;
         }
 
diff --git a/third_party/mbedtls/repo/programs/psa/crypto_examples.c b/third_party/mbedtls/repo/programs/psa/crypto_examples.c
index d165d2e..935d657 100644
--- a/third_party/mbedtls/repo/programs/psa/crypto_examples.c
+++ b/third_party/mbedtls/repo/programs/psa/crypto_examples.c
@@ -159,7 +159,7 @@
 cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block( void )
 {
     enum {
-        block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( PSA_KEY_TYPE_AES ),
+        block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH( PSA_KEY_TYPE_AES ),
         key_bits = 256,
         part_size = block_size,
     };
@@ -207,7 +207,7 @@
 static psa_status_t cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi( void )
 {
     enum {
-        block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( PSA_KEY_TYPE_AES ),
+        block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH( PSA_KEY_TYPE_AES ),
         key_bits = 256,
         input_size = 100,
         part_size = 10,
@@ -255,7 +255,7 @@
 static psa_status_t cipher_example_encrypt_decrypt_aes_ctr_multi( void )
 {
     enum {
-        block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( PSA_KEY_TYPE_AES ),
+        block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH( PSA_KEY_TYPE_AES ),
         key_bits = 256,
         input_size = 100,
         part_size = 10,
diff --git a/third_party/mbedtls/repo/programs/psa/key_ladder_demo.c b/third_party/mbedtls/repo/programs/psa/key_ladder_demo.c
index 47d5de6..5d64349 100644
--- a/third_party/mbedtls/repo/programs/psa/key_ladder_demo.c
+++ b/third_party/mbedtls/repo/programs/psa/key_ladder_demo.c
@@ -365,6 +365,8 @@
     psa_status_t status;
     FILE *input_file = NULL;
     FILE *output_file = NULL;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_type_t key_type;
     long input_position;
     size_t input_size;
     size_t buffer_size = 0;
@@ -385,7 +387,10 @@
     }
 #endif
     input_size = input_position;
-    buffer_size = PSA_AEAD_ENCRYPT_OUTPUT_SIZE( WRAPPING_ALG, input_size );
+    PSA_CHECK( psa_get_key_attributes( wrapping_key, &attributes ) );
+    key_type = psa_get_key_type( &attributes );
+    buffer_size =
+        PSA_AEAD_ENCRYPT_OUTPUT_SIZE( key_type, WRAPPING_ALG, input_size );
     /* Check for integer overflow. */
     if( buffer_size < input_size )
     {
@@ -442,6 +447,8 @@
     psa_status_t status;
     FILE *input_file = NULL;
     FILE *output_file = NULL;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_type_t key_type;
     unsigned char *buffer = NULL;
     size_t ciphertext_size = 0;
     size_t plaintext_size;
@@ -465,8 +472,10 @@
         status = DEMO_ERROR;
         goto exit;
     }
+    PSA_CHECK( psa_get_key_attributes( wrapping_key, &attributes) );
+    key_type = psa_get_key_type( &attributes);
     ciphertext_size =
-        PSA_AEAD_ENCRYPT_OUTPUT_SIZE( WRAPPING_ALG, header.payload_size );
+        PSA_AEAD_ENCRYPT_OUTPUT_SIZE( key_type, WRAPPING_ALG, header.payload_size );
     /* Check for integer overflow. */
     if( ciphertext_size < header.payload_size )
     {
diff --git a/third_party/mbedtls/repo/programs/psa/psa_constant_names_generated.c b/third_party/mbedtls/repo/programs/psa/psa_constant_names_generated.c
index a6eee21..de29716 100644
--- a/third_party/mbedtls/repo/programs/psa/psa_constant_names_generated.c
+++ b/third_party/mbedtls/repo/programs/psa/psa_constant_names_generated.c
@@ -8,6 +8,8 @@
     case PSA_ERROR_BUFFER_TOO_SMALL: return "PSA_ERROR_BUFFER_TOO_SMALL";
     case PSA_ERROR_COMMUNICATION_FAILURE: return "PSA_ERROR_COMMUNICATION_FAILURE";
     case PSA_ERROR_CORRUPTION_DETECTED: return "PSA_ERROR_CORRUPTION_DETECTED";
+    case PSA_ERROR_DATA_CORRUPT: return "PSA_ERROR_DATA_CORRUPT";
+    case PSA_ERROR_DATA_INVALID: return "PSA_ERROR_DATA_INVALID";
     case PSA_ERROR_DOES_NOT_EXIST: return "PSA_ERROR_DOES_NOT_EXIST";
     case PSA_ERROR_GENERIC_ERROR: return "PSA_ERROR_GENERIC_ERROR";
     case PSA_ERROR_HARDWARE_FAILURE: return "PSA_ERROR_HARDWARE_FAILURE";
@@ -38,6 +40,7 @@
     case PSA_ECC_FAMILY_SECT_K1: return "PSA_ECC_FAMILY_SECT_K1";
     case PSA_ECC_FAMILY_SECT_R1: return "PSA_ECC_FAMILY_SECT_R1";
     case PSA_ECC_FAMILY_SECT_R2: return "PSA_ECC_FAMILY_SECT_R2";
+    case PSA_ECC_FAMILY_TWISTED_EDWARDS: return "PSA_ECC_FAMILY_TWISTED_EDWARDS";
     default: return NULL;
     }
 }
@@ -64,6 +67,7 @@
     case PSA_ALG_SHA3_256: return "PSA_ALG_SHA3_256";
     case PSA_ALG_SHA3_384: return "PSA_ALG_SHA3_384";
     case PSA_ALG_SHA3_512: return "PSA_ALG_SHA3_512";
+    case PSA_ALG_SHAKE256_512: return "PSA_ALG_SHAKE256_512";
     case PSA_ALG_SHA_1: return "PSA_ALG_SHA_1";
     case PSA_ALG_SHA_224: return "PSA_ALG_SHA_224";
     case PSA_ALG_SHA_256: return "PSA_ALG_SHA_256";
@@ -92,6 +96,7 @@
     switch (type) {
     case PSA_KEY_TYPE_AES: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_AES", 16); break;
     case PSA_KEY_TYPE_ARC4: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_ARC4", 17); break;
+    case PSA_KEY_TYPE_ARIA: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_ARIA", 17); break;
     case PSA_KEY_TYPE_CAMELLIA: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_CAMELLIA", 21); break;
     case PSA_KEY_TYPE_CATEGORY_FLAG_PAIR: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_CATEGORY_FLAG_PAIR", 31); break;
     case PSA_KEY_TYPE_CATEGORY_KEY_PAIR: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_CATEGORY_KEY_PAIR", 30); break;
@@ -148,20 +153,28 @@
     unsigned long length_modifier = NO_LENGTH_MODIFIER;
     if (PSA_ALG_IS_MAC(alg)) {
         core_alg = PSA_ALG_TRUNCATED_MAC(alg, 0);
-        if (core_alg != alg) {
+        if (alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(", 33);
+            length_modifier = PSA_MAC_TRUNCATED_LENGTH(alg);
+        } else if (core_alg != alg) {
             append(&buffer, buffer_size, &required_size,
                    "PSA_ALG_TRUNCATED_MAC(", 22);
             length_modifier = PSA_MAC_TRUNCATED_LENGTH(alg);
         }
     } else if (PSA_ALG_IS_AEAD(alg)) {
-        core_alg = PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(alg);
+        core_alg = PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg);
         if (core_alg == 0) {
             /* For unknown AEAD algorithms, there is no "default tag length". */
             core_alg = alg;
+        } else if (alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(", 43);
+            length_modifier = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);
         } else if (core_alg != alg) {
             append(&buffer, buffer_size, &required_size,
-                   "PSA_ALG_AEAD_WITH_TAG_LENGTH(", 29);
-            length_modifier = PSA_AEAD_TAG_LENGTH(alg);
+                   "PSA_ALG_AEAD_WITH_SHORTENED_TAG(", 32);
+            length_modifier = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);
         }
     } else if (PSA_ALG_IS_KEY_AGREEMENT(alg) &&
                !PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) {
@@ -198,23 +211,30 @@
     case PSA_ALG_ECB_NO_PADDING: append(&buffer, buffer_size, &required_size, "PSA_ALG_ECB_NO_PADDING", 22); break;
     case PSA_ALG_ECDH: append(&buffer, buffer_size, &required_size, "PSA_ALG_ECDH", 12); break;
     case PSA_ALG_ECDSA_ANY: append(&buffer, buffer_size, &required_size, "PSA_ALG_ECDSA_ANY", 17); break;
+    case PSA_ALG_ED25519PH: append(&buffer, buffer_size, &required_size, "PSA_ALG_ED25519PH", 17); break;
+    case PSA_ALG_ED448PH: append(&buffer, buffer_size, &required_size, "PSA_ALG_ED448PH", 15); break;
     case PSA_ALG_FFDH: append(&buffer, buffer_size, &required_size, "PSA_ALG_FFDH", 12); break;
     case PSA_ALG_GCM: append(&buffer, buffer_size, &required_size, "PSA_ALG_GCM", 11); break;
+    case PSA_ALG_HASH_EDDSA_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_HASH_EDDSA_BASE", 23); break;
     case PSA_ALG_HKDF_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_HKDF_BASE", 17); break;
     case PSA_ALG_HMAC_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_HMAC_BASE", 17); break;
     case PSA_ALG_MD2: append(&buffer, buffer_size, &required_size, "PSA_ALG_MD2", 11); break;
     case PSA_ALG_MD4: append(&buffer, buffer_size, &required_size, "PSA_ALG_MD4", 11); break;
     case PSA_ALG_MD5: append(&buffer, buffer_size, &required_size, "PSA_ALG_MD5", 11); break;
+    case PSA_ALG_NONE: append(&buffer, buffer_size, &required_size, "PSA_ALG_NONE", 12); break;
     case PSA_ALG_OFB: append(&buffer, buffer_size, &required_size, "PSA_ALG_OFB", 11); break;
+    case PSA_ALG_PURE_EDDSA: append(&buffer, buffer_size, &required_size, "PSA_ALG_PURE_EDDSA", 18); break;
     case PSA_ALG_RIPEMD160: append(&buffer, buffer_size, &required_size, "PSA_ALG_RIPEMD160", 17); break;
     case PSA_ALG_RSA_OAEP_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_RSA_OAEP_BASE", 21); break;
     case PSA_ALG_RSA_PKCS1V15_CRYPT: append(&buffer, buffer_size, &required_size, "PSA_ALG_RSA_PKCS1V15_CRYPT", 26); break;
     case PSA_ALG_RSA_PKCS1V15_SIGN_RAW: append(&buffer, buffer_size, &required_size, "PSA_ALG_RSA_PKCS1V15_SIGN_RAW", 29); break;
+    case PSA_ALG_RSA_PSS_ANY_SALT_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_RSA_PSS_ANY_SALT_BASE", 29); break;
     case PSA_ALG_RSA_PSS_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_RSA_PSS_BASE", 20); break;
     case PSA_ALG_SHA3_224: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA3_224", 16); break;
     case PSA_ALG_SHA3_256: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA3_256", 16); break;
     case PSA_ALG_SHA3_384: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA3_384", 16); break;
     case PSA_ALG_SHA3_512: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA3_512", 16); break;
+    case PSA_ALG_SHAKE256_512: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHAKE256_512", 20); break;
     case PSA_ALG_SHA_1: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA_1", 13); break;
     case PSA_ALG_SHA_224: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA_224", 15); break;
     case PSA_ALG_SHA_256: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA_256", 15); break;
@@ -283,13 +303,20 @@
                             psa_hash_algorithm_name,
                             PSA_ALG_GET_HASH(core_alg));
             append(&buffer, buffer_size, &required_size, ")", 1);
-        } else if (PSA_ALG_IS_RSA_PSS(core_alg)) {
+        } else if (PSA_ALG_IS_RSA_PSS_STANDARD_SALT(core_alg)) {
             append(&buffer, buffer_size, &required_size,
                    "PSA_ALG_RSA_PSS(", 15 + 1);
             append_with_alg(&buffer, buffer_size, &required_size,
                             psa_hash_algorithm_name,
                             PSA_ALG_GET_HASH(core_alg));
             append(&buffer, buffer_size, &required_size, ")", 1);
+        } else if (PSA_ALG_IS_RSA_PSS_ANY_SALT(core_alg)) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_RSA_PSS_ANY_SALT(", 24 + 1);
+            append_with_alg(&buffer, buffer_size, &required_size,
+                            psa_hash_algorithm_name,
+                            PSA_ALG_GET_HASH(core_alg));
+            append(&buffer, buffer_size, &required_size, ")", 1);
         } else if (PSA_ALG_IS_TLS12_PRF(core_alg)) {
             append(&buffer, buffer_size, &required_size,
                    "PSA_ALG_TLS12_PRF(", 17 + 1);
@@ -377,6 +404,13 @@
         append(&buffer, buffer_size, &required_size, "PSA_KEY_USAGE_SIGN_HASH", 23);
         usage ^= PSA_KEY_USAGE_SIGN_HASH;
     }
+    if (usage & PSA_KEY_USAGE_SIGN_MESSAGE) {
+        if (required_size != 0) {
+            append(&buffer, buffer_size, &required_size, " | ", 3);
+        }
+        append(&buffer, buffer_size, &required_size, "PSA_KEY_USAGE_SIGN_MESSAGE", 26);
+        usage ^= PSA_KEY_USAGE_SIGN_MESSAGE;
+    }
     if (usage & PSA_KEY_USAGE_VERIFY_HASH) {
         if (required_size != 0) {
             append(&buffer, buffer_size, &required_size, " | ", 3);
@@ -384,6 +418,13 @@
         append(&buffer, buffer_size, &required_size, "PSA_KEY_USAGE_VERIFY_HASH", 25);
         usage ^= PSA_KEY_USAGE_VERIFY_HASH;
     }
+    if (usage & PSA_KEY_USAGE_VERIFY_MESSAGE) {
+        if (required_size != 0) {
+            append(&buffer, buffer_size, &required_size, " | ", 3);
+        }
+        append(&buffer, buffer_size, &required_size, "PSA_KEY_USAGE_VERIFY_MESSAGE", 28);
+        usage ^= PSA_KEY_USAGE_VERIFY_MESSAGE;
+    }
     if (usage != 0) {
         if (required_size != 0) {
             append(&buffer, buffer_size, &required_size, " | ", 3);
diff --git a/third_party/mbedtls/repo/programs/random/gen_random_havege.c b/third_party/mbedtls/repo/programs/random/gen_random_havege.c
index ccca7f3..e82e627 100644
--- a/third_party/mbedtls/repo/programs/random/gen_random_havege.c
+++ b/third_party/mbedtls/repo/programs/random/gen_random_havege.c
@@ -81,7 +81,7 @@
         if( ( ret = mbedtls_havege_random( &hs, buf, sizeof( buf ) ) ) != 0 )
         {
             mbedtls_printf( " failed\n  !  mbedtls_havege_random returned -0x%04X",
-                            -ret );
+                            ( unsigned int ) -ret );
             goto exit;
         }
 
diff --git a/third_party/mbedtls/repo/programs/ssl/CMakeLists.txt b/third_party/mbedtls/repo/programs/ssl/CMakeLists.txt
index 149aa30..dfc16a5 100644
--- a/third_party/mbedtls/repo/programs/ssl/CMakeLists.txt
+++ b/third_party/mbedtls/repo/programs/ssl/CMakeLists.txt
@@ -27,13 +27,21 @@
 )
 
 foreach(exe IN LISTS executables)
-    add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
+    set(extra_sources "")
+    if(exe STREQUAL "ssl_client2" OR exe STREQUAL "ssl_server2")
+        list(APPEND extra_sources
+            ${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.c)
+    endif()
+    add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>
+        ${extra_sources})
     target_link_libraries(${exe} ${libs})
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
 endforeach()
 
-set_property(TARGET ssl_client2 APPEND PROPERTY SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.c)
-set_property(TARGET ssl_server2 APPEND PROPERTY SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.c)
+set_property(TARGET ssl_client2 APPEND PROPERTY SOURCES
+    ssl_test_lib.c ${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.c)
+set_property(TARGET ssl_server2 APPEND PROPERTY SOURCES
+    ssl_test_lib.c ${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.c)
 
 if(THREADS_FOUND)
     add_executable(ssl_pthread_server ssl_pthread_server.c $<TARGET_OBJECTS:mbedtls_test>)
diff --git a/third_party/mbedtls/repo/programs/ssl/dtls_client.c b/third_party/mbedtls/repo/programs/ssl/dtls_client.c
index 03a06ff..8c302a0 100644
--- a/third_party/mbedtls/repo/programs/ssl/dtls_client.c
+++ b/third_party/mbedtls/repo/programs/ssl/dtls_client.c
@@ -191,6 +191,7 @@
     mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );
     mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
     mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
+    mbedtls_ssl_conf_read_timeout( &conf, READ_TIMEOUT_MS );
 
     if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
     {
diff --git a/third_party/mbedtls/repo/programs/ssl/dtls_server.c b/third_party/mbedtls/repo/programs/ssl/dtls_server.c
index 22e3fc5..5f71ec9 100644
--- a/third_party/mbedtls/repo/programs/ssl/dtls_server.c
+++ b/third_party/mbedtls/repo/programs/ssl/dtls_server.c
@@ -87,7 +87,7 @@
 #include "mbedtls/ssl_cache.h"
 #endif
 
-#define READ_TIMEOUT_MS 10000   /* 5 seconds */
+#define READ_TIMEOUT_MS 10000   /* 10 seconds */
 #define DEBUG_LEVEL 0
 
 
@@ -223,6 +223,7 @@
 
     mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
     mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
+    mbedtls_ssl_conf_read_timeout( &conf, READ_TIMEOUT_MS );
 
 #if defined(MBEDTLS_SSL_CACHE_C)
     mbedtls_ssl_conf_session_cache( &conf, &cache,
diff --git a/third_party/mbedtls/repo/programs/ssl/ssl_client2.c b/third_party/mbedtls/repo/programs/ssl/ssl_client2.c
index fc69061..8e62dbe 100644
--- a/third_party/mbedtls/repo/programs/ssl/ssl_client2.c
+++ b/third_party/mbedtls/repo/programs/ssl/ssl_client2.c
@@ -17,68 +17,25 @@
  *  limitations under the License.
  */
 
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
-
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#define mbedtls_time       time
-#define mbedtls_time_t     time_t
-#define mbedtls_printf     printf
-#define mbedtls_fprintf    fprintf
-#define mbedtls_snprintf   snprintf
-#define mbedtls_calloc     calloc
-#define mbedtls_free       free
-#define mbedtls_exit            exit
-#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
-#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
-#endif
-
-#if !defined(MBEDTLS_ENTROPY_C) || \
-    !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \
-    !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_CTR_DRBG_C) || \
-    defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
-int main( void )
-{
-    mbedtls_printf( "MBEDTLS_ENTROPY_C and/or "
-           "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or "
-           "MBEDTLS_NET_C and/or MBEDTLS_CTR_DRBG_C and/or not defined "
-           " and/or MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined.\n" );
-    mbedtls_exit( 0 );
-}
-#else
-
-#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-#include "mbedtls/memory_buffer_alloc.h"
-#endif
-
-#include "mbedtls/net_sockets.h"
-#include "mbedtls/ssl.h"
-#include "mbedtls/entropy.h"
-#include "mbedtls/ctr_drbg.h"
-#include "mbedtls/certs.h"
-#include "mbedtls/x509.h"
-#include "mbedtls/error.h"
-#include "mbedtls/debug.h"
-#include "mbedtls/timing.h"
-#include "mbedtls/base64.h"
+#include "ssl_test_lib.h"
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-#include "psa/crypto.h"
-#include "mbedtls/psa_util.h"
+#include "test/psa_crypto_helpers.h"
 #endif
 
-#include <test/helpers.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#if defined(MBEDTLS_SSL_TEST_IMPOSSIBLE)
+int main( void )
+{
+    mbedtls_printf( MBEDTLS_SSL_TEST_IMPOSSIBLE );
+    mbedtls_exit( 0 );
+}
+#elif !defined(MBEDTLS_SSL_CLI_C)
+int main( void )
+{
+    mbedtls_printf( "MBEDTLS_SSL_CLI_C not defined.\n" );
+    mbedtls_exit( 0 );
+}
+#else /* !MBEDTLS_SSL_TEST_IMPOSSIBLE && MBEDTLS_SSL_CLI_C */
 
 /* Size of memory to be allocated for the heap, when using the library's memory
  * management and MBEDTLS_MEMORY_BUFFER_ALLOC_C is enabled. */
@@ -469,9 +426,9 @@
     "    arc4=%%d             default: (library default: 0)\n" \
     "    allow_sha1=%%d       default: 0\n"                             \
     "    min_version=%%s      default: (library default: tls1)\n"       \
-    "    max_version=%%s      default: (library default: tls1_2)\n"     \
+    "    max_version=%%s      default: (library default: tls12)\n"      \
     "    force_version=%%s    default: \"\" (none)\n"       \
-    "                        options: ssl3, tls1, tls1_1, tls1_2, dtls1, dtls1_2\n" \
+    "                        options: ssl3, tls1, tls1_1, tls12, dtls1, dtls12\n" \
     "\n"                                                    \
     "    force_ciphersuite=<name>    default: all enabled\n"\
     "    query_config=<name>         return 0 if the specified\n"       \
@@ -568,425 +525,7 @@
     const char *mki;            /* The dtls mki value to use                */
 } opt;
 
-int query_config( const char *config );
-
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
-typedef struct eap_tls_keys
-{
-    unsigned char master_secret[48];
-    unsigned char randbytes[64];
-    mbedtls_tls_prf_types tls_prf_type;
-} eap_tls_keys;
-
-static int eap_tls_key_derivation ( void *p_expkey,
-                                    const unsigned char *ms,
-                                    const unsigned char *kb,
-                                    size_t maclen,
-                                    size_t keylen,
-                                    size_t ivlen,
-                                    const unsigned char client_random[32],
-                                    const unsigned char server_random[32],
-                                    mbedtls_tls_prf_types tls_prf_type )
-{
-    eap_tls_keys *keys = (eap_tls_keys *)p_expkey;
-
-    ( ( void ) kb );
-    memcpy( keys->master_secret, ms, sizeof( keys->master_secret ) );
-    memcpy( keys->randbytes, client_random, 32 );
-    memcpy( keys->randbytes + 32, server_random, 32 );
-    keys->tls_prf_type = tls_prf_type;
-
-    if( opt.debug_level > 2 )
-    {
-        mbedtls_printf("exported maclen is %u\n", (unsigned)maclen);
-        mbedtls_printf("exported keylen is %u\n", (unsigned)keylen);
-        mbedtls_printf("exported ivlen is %u\n", (unsigned)ivlen);
-    }
-    return( 0 );
-}
-
-static int nss_keylog_export( void *p_expkey,
-                              const unsigned char *ms,
-                              const unsigned char *kb,
-                              size_t maclen,
-                              size_t keylen,
-                              size_t ivlen,
-                              const unsigned char client_random[32],
-                              const unsigned char server_random[32],
-                              mbedtls_tls_prf_types tls_prf_type )
-{
-    char nss_keylog_line[ 200 ];
-    size_t const client_random_len = 32;
-    size_t const master_secret_len = 48;
-    size_t len = 0;
-    size_t j;
-    int ret = 0;
-
-    ((void) p_expkey);
-    ((void) kb);
-    ((void) maclen);
-    ((void) keylen);
-    ((void) ivlen);
-    ((void) server_random);
-    ((void) tls_prf_type);
-
-    len += sprintf( nss_keylog_line + len,
-                    "%s", "CLIENT_RANDOM " );
-
-    for( j = 0; j < client_random_len; j++ )
-    {
-        len += sprintf( nss_keylog_line + len,
-                        "%02x", client_random[j] );
-    }
-
-    len += sprintf( nss_keylog_line + len, " " );
-
-    for( j = 0; j < master_secret_len; j++ )
-    {
-        len += sprintf( nss_keylog_line + len,
-                        "%02x", ms[j] );
-    }
-
-    len += sprintf( nss_keylog_line + len, "\n" );
-    nss_keylog_line[ len ] = '\0';
-
-    mbedtls_printf( "\n" );
-    mbedtls_printf( "---------------- NSS KEYLOG -----------------\n" );
-    mbedtls_printf( "%s", nss_keylog_line );
-    mbedtls_printf( "---------------------------------------------\n" );
-
-    if( opt.nss_keylog_file != NULL )
-    {
-        FILE *f;
-
-        if( ( f = fopen( opt.nss_keylog_file, "a" ) ) == NULL )
-        {
-            ret = -1;
-            goto exit;
-        }
-
-        if( fwrite( nss_keylog_line, 1, len, f ) != len )
-        {
-            ret = -1;
-            fclose( f );
-            goto exit;
-        }
-
-        fclose( f );
-    }
-
-exit:
-    mbedtls_platform_zeroize( nss_keylog_line,
-                              sizeof( nss_keylog_line ) );
-    return( ret );
-}
-
-#if defined( MBEDTLS_SSL_DTLS_SRTP )
-/* Supported SRTP mode needs a maximum of :
- * - 16 bytes for key (AES-128)
- * - 14 bytes SALT
- * One for sender, one for receiver context
- */
-#define MBEDTLS_TLS_SRTP_MAX_KEY_MATERIAL_LENGTH    60
-typedef struct dtls_srtp_keys
-{
-    unsigned char master_secret[48];
-    unsigned char randbytes[64];
-    mbedtls_tls_prf_types tls_prf_type;
-} dtls_srtp_keys;
-
-static int dtls_srtp_key_derivation( void *p_expkey,
-                                     const unsigned char *ms,
-                                     const unsigned char *kb,
-                                     size_t maclen,
-                                     size_t keylen,
-                                     size_t ivlen,
-                                     const unsigned char client_random[32],
-                                     const unsigned char server_random[32],
-                                     mbedtls_tls_prf_types tls_prf_type )
-{
-    dtls_srtp_keys *keys = (dtls_srtp_keys *)p_expkey;
-
-    ( ( void ) kb );
-    memcpy( keys->master_secret, ms, sizeof( keys->master_secret ) );
-    memcpy( keys->randbytes, client_random, 32 );
-    memcpy( keys->randbytes + 32, server_random, 32 );
-    keys->tls_prf_type = tls_prf_type;
-
-    if( opt.debug_level > 2 )
-    {
-        mbedtls_printf( "exported maclen is %u\n", (unsigned) maclen );
-        mbedtls_printf( "exported keylen is %u\n", (unsigned) keylen );
-        mbedtls_printf( "exported ivlen is %u\n", (unsigned) ivlen );
-    }
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_DTLS_SRTP */
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
-
-static void my_debug( void *ctx, int level,
-                      const char *file, int line,
-                      const char *str )
-{
-    const char *p, *basename;
-
-    /* Extract basename from file */
-    for( p = basename = file; *p != '\0'; p++ )
-        if( *p == '/' || *p == '\\' )
-            basename = p + 1;
-
-    mbedtls_fprintf( (FILE *) ctx, "%s:%04d: |%d| %s",
-                     basename, line, level, str );
-    fflush(  (FILE *) ctx  );
-}
-
-
-mbedtls_time_t dummy_constant_time( mbedtls_time_t* time )
-{
-    (void) time;
-    return 0x5af2a056;
-}
-
-int dummy_entropy( void *data, unsigned char *output, size_t len )
-{
-    size_t i;
-    int ret;
-    (void) data;
-
-    ret = mbedtls_entropy_func( data, output, len );
-    for ( i = 0; i < len; i++ )
-    {
-        //replace result with pseudo random
-        output[i] = (unsigned char) rand();
-    }
-    return( ret );
-}
-
-#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
-int ca_callback( void *data, mbedtls_x509_crt const *child,
-                 mbedtls_x509_crt **candidates )
-{
-    int ret = 0;
-    mbedtls_x509_crt *ca = (mbedtls_x509_crt *) data;
-    mbedtls_x509_crt *first;
-
-    /* This is a test-only implementation of the CA callback
-     * which always returns the entire list of trusted certificates.
-     * Production implementations managing a large number of CAs
-     * should use an efficient presentation and lookup for the
-     * set of trusted certificates (such as a hashtable) and only
-     * return those trusted certificates which satisfy basic
-     * parental checks, such as the matching of child `Issuer`
-     * and parent `Subject` field or matching key identifiers. */
-    ((void) child);
-
-    first = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
-    if( first == NULL )
-    {
-        ret = -1;
-        goto exit;
-    }
-    mbedtls_x509_crt_init( first );
-
-    if( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) != 0 )
-    {
-        ret = -1;
-        goto exit;
-    }
-
-    while( ca->next != NULL )
-    {
-        ca = ca->next;
-        if( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) != 0 )
-        {
-            ret = -1;
-            goto exit;
-        }
-    }
-
-exit:
-
-    if( ret != 0 )
-    {
-        mbedtls_x509_crt_free( first );
-        mbedtls_free( first );
-        first = NULL;
-    }
-
-    *candidates = first;
-    return( ret );
-}
-#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
-
-/*
- * Test recv/send functions that make sure each try returns
- * WANT_READ/WANT_WRITE at least once before sucesseding
- */
-
-static int delayed_recv( void *ctx, unsigned char *buf, size_t len )
-{
-    static int first_try = 1;
-    int ret;
-
-    if( first_try )
-    {
-        first_try = 0;
-        return( MBEDTLS_ERR_SSL_WANT_READ );
-    }
-
-    ret = mbedtls_net_recv( ctx, buf, len );
-    if( ret != MBEDTLS_ERR_SSL_WANT_READ )
-        first_try = 1; /* Next call will be a new operation */
-    return( ret );
-}
-
-static int delayed_send( void *ctx, const unsigned char *buf, size_t len )
-{
-    static int first_try = 1;
-    int ret;
-
-    if( first_try )
-    {
-        first_try = 0;
-        return( MBEDTLS_ERR_SSL_WANT_WRITE );
-    }
-
-    ret = mbedtls_net_send( ctx, buf, len );
-    if( ret != MBEDTLS_ERR_SSL_WANT_WRITE )
-        first_try = 1; /* Next call will be a new operation */
-    return( ret );
-}
-
-typedef struct
-{
-    mbedtls_ssl_context *ssl;
-    mbedtls_net_context *net;
-} io_ctx_t;
-
-#if defined(MBEDTLS_SSL_RECORD_CHECKING)
-static int ssl_check_record( mbedtls_ssl_context const *ssl,
-                             unsigned char const *buf, size_t len )
-{
-    int ret;
-    unsigned char *tmp_buf;
-
-    tmp_buf = mbedtls_calloc( 1, len );
-    if( tmp_buf == NULL )
-        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
-    memcpy( tmp_buf, buf, len );
-
-    ret = mbedtls_ssl_check_record( ssl, tmp_buf, len );
-    if( ret != MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE )
-    {
-        int ret_repeated;
-
-        /* Test-only: Make sure that mbedtls_ssl_check_record()
-         *            doesn't alter state. */
-        memcpy( tmp_buf, buf, len ); /* Restore buffer */
-        ret_repeated = mbedtls_ssl_check_record( ssl, tmp_buf, len );
-        if( ret != ret_repeated )
-        {
-            mbedtls_printf( "mbedtls_ssl_check_record() returned inconsistent results.\n" );
-            return( -1 );
-        }
-
-        switch( ret )
-        {
-            case 0:
-                break;
-
-            case MBEDTLS_ERR_SSL_INVALID_RECORD:
-                if( opt.debug_level > 1 )
-                    mbedtls_printf( "mbedtls_ssl_check_record() detected invalid record.\n" );
-                break;
-
-            case MBEDTLS_ERR_SSL_INVALID_MAC:
-                if( opt.debug_level > 1 )
-                    mbedtls_printf( "mbedtls_ssl_check_record() detected unauthentic record.\n" );
-                break;
-
-            case MBEDTLS_ERR_SSL_UNEXPECTED_RECORD:
-                if( opt.debug_level > 1 )
-                    mbedtls_printf( "mbedtls_ssl_check_record() detected unexpected record.\n" );
-                break;
-
-            default:
-                mbedtls_printf( "mbedtls_ssl_check_record() failed fatally with -%#04x.\n", (unsigned int) -ret );
-                return( -1 );
-        }
-
-        /* Regardless of the outcome, forward the record to the stack. */
-    }
-
-    mbedtls_free( tmp_buf );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_RECORD_CHECKING */
-
-static int recv_cb( void *ctx, unsigned char *buf, size_t len )
-{
-    io_ctx_t *io_ctx = (io_ctx_t*) ctx;
-    size_t recv_len;
-    int ret;
-
-    if( opt.nbio == 2 )
-        ret = delayed_recv( io_ctx->net, buf, len );
-    else
-        ret = mbedtls_net_recv( io_ctx->net, buf, len );
-    if( ret < 0 )
-        return( ret );
-    recv_len = (size_t) ret;
-
-    if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        /* Here's the place to do any datagram/record checking
-         * in between receiving the packet from the underlying
-         * transport and passing it on to the TLS stack. */
-#if defined(MBEDTLS_SSL_RECORD_CHECKING)
-        if( ssl_check_record( io_ctx->ssl, buf, recv_len ) != 0 )
-            return( -1 );
-#endif /* MBEDTLS_SSL_RECORD_CHECKING */
-    }
-
-    return( (int) recv_len );
-}
-
-static int recv_timeout_cb( void *ctx, unsigned char *buf, size_t len,
-                            uint32_t timeout )
-{
-    io_ctx_t *io_ctx = (io_ctx_t*) ctx;
-    int ret;
-    size_t recv_len;
-
-    ret = mbedtls_net_recv_timeout( io_ctx->net, buf, len, timeout );
-    if( ret < 0 )
-        return( ret );
-    recv_len = (size_t) ret;
-
-    if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        /* Here's the place to do any datagram/record checking
-         * in between receiving the packet from the underlying
-         * transport and passing it on to the TLS stack. */
-#if defined(MBEDTLS_SSL_RECORD_CHECKING)
-        if( ssl_check_record( io_ctx->ssl, buf, recv_len ) != 0 )
-            return( -1 );
-#endif /* MBEDTLS_SSL_RECORD_CHECKING */
-    }
-
-    return( (int) recv_len );
-}
-
-static int send_cb( void *ctx, unsigned char const *buf, size_t len )
-{
-    io_ctx_t *io_ctx = (io_ctx_t*) ctx;
-
-    if( opt.nbio == 2 )
-        return( delayed_send( io_ctx->net, buf, len ) );
-
-    return( mbedtls_net_send( io_ctx->net, buf, len ) );
-}
+#include "ssl_test_common_source.c"
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 static unsigned char peer_crt_info[1024];
@@ -1020,75 +559,8 @@
 
     return( 0 );
 }
-
-static int ssl_sig_hashes_for_test[] = {
-#if defined(MBEDTLS_SHA512_C)
-    MBEDTLS_MD_SHA512,
-    MBEDTLS_MD_SHA384,
-#endif
-#if defined(MBEDTLS_SHA256_C)
-    MBEDTLS_MD_SHA256,
-    MBEDTLS_MD_SHA224,
-#endif
-#if defined(MBEDTLS_SHA1_C)
-    /* Allow SHA-1 as we use it extensively in tests. */
-    MBEDTLS_MD_SHA1,
-#endif
-    MBEDTLS_MD_NONE
-};
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
-/*
- * Wait for an event from the underlying transport or the timer
- * (Used in event-driven IO mode).
- */
-#if !defined(MBEDTLS_TIMING_C)
-int idle( mbedtls_net_context *fd,
-          int idle_reason )
-#else
-int idle( mbedtls_net_context *fd,
-          mbedtls_timing_delay_context *timer,
-          int idle_reason )
-#endif
-{
-
-    int ret;
-    int poll_type = 0;
-
-    if( idle_reason == MBEDTLS_ERR_SSL_WANT_WRITE )
-        poll_type = MBEDTLS_NET_POLL_WRITE;
-    else if( idle_reason == MBEDTLS_ERR_SSL_WANT_READ )
-        poll_type = MBEDTLS_NET_POLL_READ;
-#if !defined(MBEDTLS_TIMING_C)
-    else
-        return( 0 );
-#endif
-
-    while( 1 )
-    {
-        /* Check if timer has expired */
-#if defined(MBEDTLS_TIMING_C)
-        if( timer != NULL &&
-            mbedtls_timing_get_delay( timer ) == 2 )
-        {
-            break;
-        }
-#endif /* MBEDTLS_TIMING_C */
-
-        /* Check if underlying transport became available */
-        if( poll_type != 0 )
-        {
-            ret = mbedtls_net_poll( fd, poll_type, 0 );
-            if( ret < 0 )
-                return( ret );
-            if( ret == poll_type )
-                break;
-        }
-    }
-
-    return( 0 );
-}
-
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
 int report_cid_usage( mbedtls_ssl_context *ssl,
                       const char *additional_description )
@@ -1218,8 +690,7 @@
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
     mbedtls_x509_crt_profile crt_profile_for_test = mbedtls_x509_crt_profile_default;
 #endif
-    mbedtls_entropy_context entropy;
-    mbedtls_ctr_drbg_context ctr_drbg;
+    rng_context_t rng;
     mbedtls_ssl_context ssl;
     mbedtls_ssl_config conf;
     mbedtls_ssl_session saved_session;
@@ -1236,7 +707,7 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_key_id_t key_slot = 0; /* invalid key slot */
 #endif
-#endif
+#endif  /* MBEDTLS_X509_CRT_PARSE_C */
     char *p, *q;
     const int *list;
 #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
@@ -1267,6 +738,10 @@
     mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) );
 #endif
 
+#if defined(MBEDTLS_TEST_HOOKS)
+    test_hooks_init( );
+#endif /* MBEDTLS_TEST_HOOKS */
+
     /*
      * Make sure memory references are valid.
      */
@@ -1274,7 +749,7 @@
     mbedtls_ssl_init( &ssl );
     mbedtls_ssl_config_init( &conf );
     memset( &saved_session, 0, sizeof( mbedtls_ssl_session ) );
-    mbedtls_ctr_drbg_init( &ctr_drbg );
+    rng_init( &rng );
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
     mbedtls_x509_crt_init( &cacert );
     mbedtls_x509_crt_init( &clicert );
@@ -1293,7 +768,10 @@
         ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
         goto exit;
     }
-#endif
+#endif  /* MBEDTLS_USE_PSA_CRYPTO */
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+    mbedtls_test_enable_insecure_external_rng( );
+#endif  /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
 
     if( argc == 0 )
     {
@@ -1629,8 +1107,8 @@
             else if( strcmp( q, "tls1_1" ) == 0 ||
                      strcmp( q, "dtls1" ) == 0 )
                 opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2;
-            else if( strcmp( q, "tls1_2" ) == 0 ||
-                     strcmp( q, "dtls1_2" ) == 0 )
+            else if( strcmp( q, "tls12" ) == 0 ||
+                     strcmp( q, "dtls12" ) == 0 )
                 opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3;
             else
                 goto usage;
@@ -1644,8 +1122,8 @@
             else if( strcmp( q, "tls1_1" ) == 0 ||
                      strcmp( q, "dtls1" ) == 0 )
                 opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2;
-            else if( strcmp( q, "tls1_2" ) == 0 ||
-                     strcmp( q, "dtls1_2" ) == 0 )
+            else if( strcmp( q, "tls12" ) == 0 ||
+                     strcmp( q, "dtls12" ) == 0 )
                 opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3;
             else
                 goto usage;
@@ -1685,7 +1163,7 @@
                 opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2;
                 opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2;
             }
-            else if( strcmp( q, "tls1_2" ) == 0 )
+            else if( strcmp( q, "tls12" ) == 0 )
             {
                 opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3;
                 opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3;
@@ -1696,7 +1174,7 @@
                 opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2;
                 opt.transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM;
             }
-            else if( strcmp( q, "dtls1_2" ) == 0 )
+            else if( strcmp( q, "dtls12" ) == 0 )
             {
                 opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3;
                 opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3;
@@ -2066,31 +1544,9 @@
     mbedtls_printf( "\n  . Seeding the random number generator..." );
     fflush( stdout );
 
-    mbedtls_entropy_init( &entropy );
-    if (opt.reproducible)
-    {
-        srand( 1 );
-        if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, dummy_entropy,
-                                           &entropy, (const unsigned char *) pers,
-                                           strlen( pers ) ) ) != 0 )
-        {
-            mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned -0x%x\n",
-                            (unsigned int) -ret );
-            goto exit;
-        }
-    }
-    else
-    {
-        if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
-                                           &entropy, (const unsigned char *) pers,
-                                           strlen( pers ) ) ) != 0 )
-        {
-            mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned -0x%x\n",
-                            (unsigned int) -ret );
-            goto exit;
-        }
-    }
-
+    ret = rng_seed( &rng, opt.reproducible, pers );
+    if( ret != 0 )
+        goto exit;
     mbedtls_printf( " ok\n" );
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
@@ -2215,7 +1671,7 @@
                                                PSA_ALG_SHA_256 ) ) != 0 )
         {
             mbedtls_printf( " failed\n  !  "
-                            "mbedtls_pk_wrap_as_opaque returned -0x%x\n\n", -ret );
+                            "mbedtls_pk_wrap_as_opaque returned -0x%x\n\n", (unsigned int)  -ret );
             goto exit;
         }
     }
@@ -2339,12 +1795,12 @@
 #endif
 
 #if defined(MBEDTLS_SSL_DTLS_SRTP)
+    const mbedtls_ssl_srtp_profile forced_profile[] =
+                                { opt.force_srtp_profile, MBEDTLS_TLS_SRTP_UNSET };
     if( opt.use_srtp == 1 )
     {
         if( opt.force_srtp_profile != 0 )
         {
-            const mbedtls_ssl_srtp_profile forced_profile[] =
-                                        { opt.force_srtp_profile, MBEDTLS_TLS_SRTP_UNSET };
             ret = mbedtls_ssl_conf_dtls_srtp_protection_profiles ( &conf, forced_profile );
         }
         else
@@ -2434,9 +1890,9 @@
 #else
         fprintf( stderr, "Warning: reproducible option used without constant time\n" );
 #endif
-#endif
+#endif  /* MBEDTLS_HAVE_TIME */
     }
-    mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
+    mbedtls_ssl_conf_rng( &conf, rng_get, &rng );
     mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
 
     mbedtls_ssl_conf_read_timeout( &conf, opt.read_timeout );
@@ -2480,7 +1936,7 @@
             goto exit;
         }
     }
-#endif
+#endif  /* MBEDTLS_X509_CRT_PARSE_C */
 
 #if defined(MBEDTLS_ECP_C)
     if( opt.curves != NULL &&
@@ -3545,19 +3001,10 @@
 
     mbedtls_net_free( &server_fd );
 
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-    mbedtls_x509_crt_free( &clicert );
-    mbedtls_x509_crt_free( &cacert );
-    mbedtls_pk_free( &pkey );
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_destroy_key( key_slot );
-#endif
-#endif
-    mbedtls_ssl_session_free( &saved_session );
     mbedtls_ssl_free( &ssl );
     mbedtls_ssl_config_free( &conf );
-    mbedtls_ctr_drbg_free( &ctr_drbg );
-    mbedtls_entropy_free( &entropy );
+    mbedtls_ssl_session_free( &saved_session );
+
     if( session_data != NULL )
         mbedtls_platform_zeroize( session_data, session_data_len );
     mbedtls_free( session_data );
@@ -3567,6 +3014,15 @@
     mbedtls_free( context_buf );
 #endif
 
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    mbedtls_x509_crt_free( &clicert );
+    mbedtls_x509_crt_free( &cacert );
+    mbedtls_pk_free( &pkey );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_destroy_key( key_slot );
+#endif
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) && \
     defined(MBEDTLS_USE_PSA_CRYPTO)
     if( opt.psk_opaque != 0 )
@@ -3588,12 +3044,41 @@
 #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED &&
           MBEDTLS_USE_PSA_CRYPTO */
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    const char* message = mbedtls_test_helper_is_psa_leaking();
+    if( message )
+    {
+        if( ret == 0 )
+            ret = 1;
+        mbedtls_printf( "PSA memory leak detected: %s\n",  message);
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    /* For builds with MBEDTLS_TEST_USE_PSA_CRYPTO_RNG psa crypto
+     * resources are freed by rng_free(). */
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
+    !defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+    mbedtls_psa_crypto_free( );
+#endif
+
+    rng_free( &rng );
+
+#if defined(MBEDTLS_TEST_HOOKS)
+    if( test_hooks_failure_detected( ) )
+    {
+        if( ret == 0 )
+            ret = 1;
+        mbedtls_printf( "Test hooks detected errors.\n" );
+    }
+    test_hooks_free( );
+#endif /* MBEDTLS_TEST_HOOKS */
+
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
 #if defined(MBEDTLS_MEMORY_DEBUG)
     mbedtls_memory_buffer_alloc_status();
 #endif
     mbedtls_memory_buffer_alloc_free();
-#endif
+#endif  /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */
 
 #if defined(_WIN32)
     if( opt.query_config_mode == DFL_QUERY_CONFIG_MODE )
@@ -3612,6 +3097,4 @@
     else
         mbedtls_exit( query_config_ret );
 }
-#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
-          MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
-          MBEDTLS_CTR_DRBG_C MBEDTLS_TIMING_C */
+#endif /* !MBEDTLS_SSL_TEST_IMPOSSIBLE && MBEDTLS_SSL_CLI_C */
diff --git a/third_party/mbedtls/repo/programs/ssl/ssl_context_info.c b/third_party/mbedtls/repo/programs/ssl/ssl_context_info.c
index a204d9e..7018080 100644
--- a/third_party/mbedtls/repo/programs/ssl/ssl_context_info.c
+++ b/third_party/mbedtls/repo/programs/ssl/ssl_context_info.c
@@ -22,6 +22,7 @@
 #else
 #include MBEDTLS_CONFIG_FILE
 #endif
+#include "mbedtls/debug.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -164,6 +165,7 @@
     }
 }
 
+MBEDTLS_PRINTF_ATTRIBUTE( 1, 2 )
 void printf_err( const char *str, ... )
 {
     va_list args;
@@ -222,7 +224,13 @@
                 error_exit();
             }
 
-            if( ( b64_file = fopen( argv[i], "r" ) ) == NULL )
+            if( NULL != b64_file )
+            {
+                printf_err( "Cannot specify more than one file with -f\n" );
+                error_exit( );
+            }
+
+            if( ( b64_file = fopen( argv[i], "r" )) == NULL )
             {
                 printf_err( "Cannot find file \"%s\"\n", argv[i] );
                 error_exit();
@@ -464,7 +472,8 @@
             }
             else if( len > *max_len )
             {
-                printf_err( "The code found is too large by %u bytes.\n", len - *max_len );
+                printf_err( "The code found is too large by %" MBEDTLS_PRINTF_SIZET " bytes.\n",
+                            len - *max_len );
                 len = pad = 0;
             }
             else if( len % 4 != 0 )
diff --git a/third_party/mbedtls/repo/programs/ssl/ssl_pthread_server.c b/third_party/mbedtls/repo/programs/ssl/ssl_pthread_server.c
index c8ab215..c4c6ef1 100644
--- a/third_party/mbedtls/repo/programs/ssl/ssl_pthread_server.c
+++ b/third_party/mbedtls/repo/programs/ssl/ssl_pthread_server.c
@@ -142,7 +142,7 @@
     if( ( ret = mbedtls_ssl_setup( &ssl, thread_info->config ) ) != 0 )
     {
         mbedtls_printf( "  [ #%ld ]  failed: mbedtls_ssl_setup returned -0x%04x\n",
-                thread_id, -ret );
+                thread_id, ( unsigned int ) -ret );
         goto thread_exit;
     }
 
@@ -158,7 +158,7 @@
         if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
         {
             mbedtls_printf( "  [ #%ld ]  failed: mbedtls_ssl_handshake returned -0x%04x\n",
-                    thread_id, -ret );
+                    thread_id, ( unsigned int ) -ret );
             goto thread_exit;
         }
     }
@@ -195,7 +195,7 @@
 
                 default:
                     mbedtls_printf( "  [ #%ld ]  mbedtls_ssl_read returned -0x%04x\n",
-                            thread_id, -ret );
+                            thread_id, ( unsigned int ) -ret );
                     goto thread_exit;
             }
         }
@@ -229,7 +229,7 @@
         if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
         {
             mbedtls_printf( "  [ #%ld ]  failed: mbedtls_ssl_write returned -0x%04x\n",
-                    thread_id, ret );
+                    thread_id, ( unsigned int ) ret );
             goto thread_exit;
         }
     }
@@ -246,7 +246,7 @@
             ret != MBEDTLS_ERR_SSL_WANT_WRITE )
         {
             mbedtls_printf( "  [ #%ld ]  failed: mbedtls_ssl_close_notify returned -0x%04x\n",
-                    thread_id, ret );
+                    thread_id, ( unsigned int ) ret );
             goto thread_exit;
         }
     }
@@ -263,7 +263,7 @@
         char error_buf[100];
         mbedtls_strerror( ret, error_buf, 100 );
         mbedtls_printf("  [ #%ld ]  Last error was: -0x%04x - %s\n\n",
-               thread_id, -ret, error_buf );
+               thread_id, ( unsigned int ) -ret, error_buf );
     }
 #endif
 
@@ -408,7 +408,7 @@
                                strlen( pers ) ) ) != 0 )
     {
         mbedtls_printf( " failed: mbedtls_ctr_drbg_seed returned -0x%04x\n",
-                -ret );
+                ( unsigned int ) -ret );
         goto exit;
     }
 
@@ -425,7 +425,7 @@
                     MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
     {
         mbedtls_printf( " failed: mbedtls_ssl_config_defaults returned -0x%04x\n",
-                -ret );
+                ( unsigned int ) -ret );
         goto exit;
     }
 
@@ -470,7 +470,8 @@
     {
         char error_buf[100];
         mbedtls_strerror( ret, error_buf, 100 );
-        mbedtls_printf( "  [ main ]  Last error was: -0x%04x - %s\n", -ret, error_buf );
+        mbedtls_printf( "  [ main ]  Last error was: -0x%04x - %s\n", ( unsigned int ) -ret,
+                        error_buf );
     }
 #endif
 
@@ -482,7 +483,8 @@
     if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd,
                                     NULL, 0, NULL ) ) != 0 )
     {
-        mbedtls_printf( "  [ main ] failed: mbedtls_net_accept returned -0x%04x\n", ret );
+        mbedtls_printf( "  [ main ] failed: mbedtls_net_accept returned -0x%04x\n",
+                        ( unsigned int ) ret );
         goto exit;
     }
 
diff --git a/third_party/mbedtls/repo/programs/ssl/ssl_server2.c b/third_party/mbedtls/repo/programs/ssl/ssl_server2.c
index ceeb224..ee45312 100644
--- a/third_party/mbedtls/repo/programs/ssl/ssl_server2.c
+++ b/third_party/mbedtls/repo/programs/ssl/ssl_server2.c
@@ -17,64 +17,22 @@
  *  limitations under the License.
  */
 
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
+#include "ssl_test_lib.h"
 
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#define mbedtls_calloc     calloc
-#define mbedtls_free       free
-#define mbedtls_time       time
-#define mbedtls_time_t     time_t
-#define mbedtls_calloc    calloc
-#define mbedtls_fprintf    fprintf
-#define mbedtls_printf     printf
-#define mbedtls_exit            exit
-#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
-#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
-#endif
-
-#if !defined(MBEDTLS_ENTROPY_C) || \
-    !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_SRV_C) || \
-    !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_CTR_DRBG_C) || \
-    defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
+#if defined(MBEDTLS_SSL_TEST_IMPOSSIBLE)
 int main( void )
 {
-    mbedtls_printf( "MBEDTLS_ENTROPY_C and/or "
-           "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_SRV_C and/or "
-           "MBEDTLS_NET_C and/or MBEDTLS_CTR_DRBG_C and/or not defined "
-           " and/or MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined.\n" );
+    mbedtls_printf( MBEDTLS_SSL_TEST_IMPOSSIBLE );
     mbedtls_exit( 0 );
 }
-#else
+#elif !defined(MBEDTLS_SSL_SRV_C)
+int main( void )
+{
+    mbedtls_printf( "MBEDTLS_SSL_SRV_C not defined.\n" );
+    mbedtls_exit( 0 );
+}
+#else /* !MBEDTLS_SSL_TEST_IMPOSSIBLE && MBEDTLS_SSL_SRV_C */
 
-#include "mbedtls/net_sockets.h"
-#include "mbedtls/ssl.h"
-#include "mbedtls/entropy.h"
-#include "mbedtls/ctr_drbg.h"
-#include "mbedtls/certs.h"
-#include "mbedtls/x509.h"
-#include "mbedtls/error.h"
-#include "mbedtls/debug.h"
-#include "mbedtls/timing.h"
-#include "mbedtls/base64.h"
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-#include "psa/crypto.h"
-#include "mbedtls/psa_util.h"
-#endif
-
-#include <test/helpers.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 #include <stdint.h>
 
 #if !defined(_MSC_VER)
@@ -97,10 +55,6 @@
 #include "mbedtls/ssl_cookie.h"
 #endif
 
-#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-#include "mbedtls/memory_buffer_alloc.h"
-#endif
-
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && defined(MBEDTLS_FS_IO)
 #define SNI_OPTION
 #endif
@@ -109,6 +63,10 @@
 #include <windows.h>
 #endif
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "test/psa_crypto_helpers.h"
+#endif
+
 /* Size of memory to be allocated for the heap, when using the library's memory
  * management and MBEDTLS_MEMORY_BUFFER_ALLOC_C is enabled. */
 #define MEMORY_HEAP_SIZE        120000
@@ -549,12 +507,12 @@
     "    arc4=%%d             default: (library default: 0)\n" \
     "    allow_sha1=%%d       default: 0\n"                             \
     "    min_version=%%s      default: (library default: tls1)\n"       \
-    "    max_version=%%s      default: (library default: tls1_2)\n"     \
+    "    max_version=%%s      default: (library default: tls12)\n"      \
     "    force_version=%%s    default: \"\" (none)\n"       \
-    "                        options: ssl3, tls1, tls1_1, tls1_2, dtls1, dtls1_2\n" \
+    "                        options: ssl3, tls1, tls1_1, tls12, dtls1, dtls12\n" \
     "\n"                                                                \
     "    version_suites=a,b,c,d      per-version ciphersuites\n"        \
-    "                                in order from ssl3 to tls1_2\n"    \
+    "                                in order from ssl3 to tls12\n"     \
     "                                default: all enabled\n"            \
     "    force_ciphersuite=<name>    default: all enabled\n"            \
     "    query_config=<name>         return 0 if the specified\n"       \
@@ -670,424 +628,7 @@
     int support_mki;            /* The dtls mki mki support                 */
 } opt;
 
-int query_config( const char *config );
-
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
-typedef struct eap_tls_keys
-{
-    unsigned char master_secret[48];
-    unsigned char randbytes[64];
-    mbedtls_tls_prf_types tls_prf_type;
-} eap_tls_keys;
-
-static int eap_tls_key_derivation ( void *p_expkey,
-                                    const unsigned char *ms,
-                                    const unsigned char *kb,
-                                    size_t maclen,
-                                    size_t keylen,
-                                    size_t ivlen,
-                                    const unsigned char client_random[32],
-                                    const unsigned char server_random[32],
-                                    mbedtls_tls_prf_types tls_prf_type )
-{
-    eap_tls_keys *keys = (eap_tls_keys *)p_expkey;
-
-    ( ( void ) kb );
-    memcpy( keys->master_secret, ms, sizeof( keys->master_secret ) );
-    memcpy( keys->randbytes, client_random, 32 );
-    memcpy( keys->randbytes + 32, server_random, 32 );
-    keys->tls_prf_type = tls_prf_type;
-
-    if( opt.debug_level > 2 )
-    {
-        mbedtls_printf("exported maclen is %u\n", (unsigned)maclen);
-        mbedtls_printf("exported keylen is %u\n", (unsigned)keylen);
-        mbedtls_printf("exported ivlen is %u\n", (unsigned)ivlen);
-    }
-    return( 0 );
-}
-
-static int nss_keylog_export( void *p_expkey,
-                              const unsigned char *ms,
-                              const unsigned char *kb,
-                              size_t maclen,
-                              size_t keylen,
-                              size_t ivlen,
-                              const unsigned char client_random[32],
-                              const unsigned char server_random[32],
-                              mbedtls_tls_prf_types tls_prf_type )
-{
-    char nss_keylog_line[ 200 ];
-    size_t const client_random_len = 32;
-    size_t const master_secret_len = 48;
-    size_t len = 0;
-    size_t j;
-    int ret = 0;
-
-    ((void) p_expkey);
-    ((void) kb);
-    ((void) maclen);
-    ((void) keylen);
-    ((void) ivlen);
-    ((void) server_random);
-    ((void) tls_prf_type);
-
-    len += sprintf( nss_keylog_line + len,
-                    "%s", "CLIENT_RANDOM " );
-
-    for( j = 0; j < client_random_len; j++ )
-    {
-        len += sprintf( nss_keylog_line + len,
-                        "%02x", client_random[j] );
-    }
-
-    len += sprintf( nss_keylog_line + len, " " );
-
-    for( j = 0; j < master_secret_len; j++ )
-    {
-        len += sprintf( nss_keylog_line + len,
-                        "%02x", ms[j] );
-    }
-
-    len += sprintf( nss_keylog_line + len, "\n" );
-    nss_keylog_line[ len ] = '\0';
-
-    mbedtls_printf( "\n" );
-    mbedtls_printf( "---------------- NSS KEYLOG -----------------\n" );
-    mbedtls_printf( "%s", nss_keylog_line );
-    mbedtls_printf( "---------------------------------------------\n" );
-
-    if( opt.nss_keylog_file != NULL )
-    {
-        FILE *f;
-
-        if( ( f = fopen( opt.nss_keylog_file, "a" ) ) == NULL )
-        {
-            ret = -1;
-            goto exit;
-        }
-
-        if( fwrite( nss_keylog_line, 1, len, f ) != len )
-        {
-            ret = -1;
-            fclose( f );
-            goto exit;
-        }
-
-        fclose( f );
-    }
-
-exit:
-    mbedtls_platform_zeroize( nss_keylog_line,
-                              sizeof( nss_keylog_line ) );
-    return( ret );
-}
-
-#if defined( MBEDTLS_SSL_DTLS_SRTP )
-/* Supported SRTP mode needs a maximum of :
- * - 16 bytes for key (AES-128)
- * - 14 bytes SALT
- * One for sender, one for receiver context
- */
-#define MBEDTLS_TLS_SRTP_MAX_KEY_MATERIAL_LENGTH    60
-typedef struct dtls_srtp_keys
-{
-    unsigned char master_secret[48];
-    unsigned char randbytes[64];
-    mbedtls_tls_prf_types tls_prf_type;
-} dtls_srtp_keys;
-
-static int dtls_srtp_key_derivation( void *p_expkey,
-                                     const unsigned char *ms,
-                                     const unsigned char *kb,
-                                     size_t maclen,
-                                     size_t keylen,
-                                     size_t ivlen,
-                                     const unsigned char client_random[32],
-                                     const unsigned char server_random[32],
-                                     mbedtls_tls_prf_types tls_prf_type )
-{
-    dtls_srtp_keys *keys = (dtls_srtp_keys *)p_expkey;
-
-    ( ( void ) kb );
-    memcpy( keys->master_secret, ms, sizeof( keys->master_secret ) );
-    memcpy( keys->randbytes, client_random, 32 );
-    memcpy( keys->randbytes + 32, server_random, 32 );
-    keys->tls_prf_type = tls_prf_type;
-
-    if( opt.debug_level > 2 )
-    {
-        mbedtls_printf( "exported maclen is %u\n", (unsigned) maclen );
-        mbedtls_printf( "exported keylen is %u\n", (unsigned) keylen );
-        mbedtls_printf( "exported ivlen is %u\n", (unsigned) ivlen );
-    }
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_DTLS_SRTP */
-
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
-
-static void my_debug( void *ctx, int level,
-                      const char *file, int line,
-                      const char *str )
-{
-    const char *p, *basename;
-
-    /* Extract basename from file */
-    for( p = basename = file; *p != '\0'; p++ )
-        if( *p == '/' || *p == '\\' )
-            basename = p + 1;
-
-    mbedtls_fprintf( (FILE *) ctx, "%s:%04d: |%d| %s", basename, line, level, str );
-    fflush(  (FILE *) ctx  );
-}
-
-mbedtls_time_t dummy_constant_time( mbedtls_time_t* time )
-{
-    (void) time;
-    return 0x5af2a056;
-}
-
-int dummy_entropy( void *data, unsigned char *output, size_t len )
-{
-    size_t i;
-    int ret;
-    (void) data;
-
-    ret = mbedtls_entropy_func( data, output, len );
-    for (i = 0; i < len; i++ ) {
-        //replace result with pseudo random
-        output[i] = (unsigned char) rand();
-    }
-    return( ret );
-}
-
-#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
-int ca_callback( void *data, mbedtls_x509_crt const *child,
-                 mbedtls_x509_crt **candidates)
-{
-    int ret = 0;
-    mbedtls_x509_crt *ca = (mbedtls_x509_crt *) data;
-    mbedtls_x509_crt *first;
-
-    /* This is a test-only implementation of the CA callback
-     * which always returns the entire list of trusted certificates.
-     * Production implementations managing a large number of CAs
-     * should use an efficient presentation and lookup for the
-     * set of trusted certificates (such as a hashtable) and only
-     * return those trusted certificates which satisfy basic
-     * parental checks, such as the matching of child `Issuer`
-     * and parent `Subject` field. */
-    ((void) child);
-
-    first = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
-    if( first == NULL )
-    {
-        ret = -1;
-        goto exit;
-    }
-    mbedtls_x509_crt_init( first );
-
-    if( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) != 0 )
-    {
-        ret = -1;
-        goto exit;
-    }
-
-    while( ca->next != NULL )
-    {
-        ca = ca->next;
-        if( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) != 0 )
-        {
-            ret = -1;
-            goto exit;
-        }
-    }
-
-exit:
-
-    if( ret != 0 )
-    {
-        mbedtls_x509_crt_free( first );
-        mbedtls_free( first );
-        first = NULL;
-    }
-
-    *candidates = first;
-    return( ret );
-}
-#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
-
-/*
- * Test recv/send functions that make sure each try returns
- * WANT_READ/WANT_WRITE at least once before sucesseding
- */
-static int delayed_recv( void *ctx, unsigned char *buf, size_t len )
-{
-    static int first_try = 1;
-    int ret;
-
-    if( first_try )
-    {
-        first_try = 0;
-        return( MBEDTLS_ERR_SSL_WANT_READ );
-    }
-
-    ret = mbedtls_net_recv( ctx, buf, len );
-    if( ret != MBEDTLS_ERR_SSL_WANT_READ )
-        first_try = 1; /* Next call will be a new operation */
-    return( ret );
-}
-
-static int delayed_send( void *ctx, const unsigned char *buf, size_t len )
-{
-    static int first_try = 1;
-    int ret;
-
-    if( first_try )
-    {
-        first_try = 0;
-        return( MBEDTLS_ERR_SSL_WANT_WRITE );
-    }
-
-    ret = mbedtls_net_send( ctx, buf, len );
-    if( ret != MBEDTLS_ERR_SSL_WANT_WRITE )
-        first_try = 1; /* Next call will be a new operation */
-    return( ret );
-}
-
-typedef struct
-{
-    mbedtls_ssl_context *ssl;
-    mbedtls_net_context *net;
-} io_ctx_t;
-
-#if defined(MBEDTLS_SSL_RECORD_CHECKING)
-static int ssl_check_record( mbedtls_ssl_context const *ssl,
-                             unsigned char const *buf, size_t len )
-{
-    int ret;
-    unsigned char *tmp_buf;
-
-    /* Record checking may modify the input buffer,
-     * so make a copy. */
-    tmp_buf = mbedtls_calloc( 1, len );
-    if( tmp_buf == NULL )
-        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
-    memcpy( tmp_buf, buf, len );
-
-    ret = mbedtls_ssl_check_record( ssl, tmp_buf, len );
-    if( ret != MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE )
-    {
-        int ret_repeated;
-
-        /* Test-only: Make sure that mbedtls_ssl_check_record()
-         *            doesn't alter state. */
-        memcpy( tmp_buf, buf, len ); /* Restore buffer */
-        ret_repeated = mbedtls_ssl_check_record( ssl, tmp_buf, len );
-        if( ret != ret_repeated )
-        {
-            mbedtls_printf( "mbedtls_ssl_check_record() returned inconsistent results.\n" );
-            return( -1 );
-        }
-
-        switch( ret )
-        {
-            case 0:
-                break;
-
-            case MBEDTLS_ERR_SSL_INVALID_RECORD:
-                if( opt.debug_level > 1 )
-                    mbedtls_printf( "mbedtls_ssl_check_record() detected invalid record.\n" );
-                break;
-
-            case MBEDTLS_ERR_SSL_INVALID_MAC:
-                if( opt.debug_level > 1 )
-                    mbedtls_printf( "mbedtls_ssl_check_record() detected unauthentic record.\n" );
-                break;
-
-            case MBEDTLS_ERR_SSL_UNEXPECTED_RECORD:
-                if( opt.debug_level > 1 )
-                    mbedtls_printf( "mbedtls_ssl_check_record() detected unexpected record.\n" );
-                break;
-
-            default:
-                mbedtls_printf( "mbedtls_ssl_check_record() failed fatally with -%#04x.\n", (unsigned int) -ret );
-                return( -1 );
-        }
-
-        /* Regardless of the outcome, forward the record to the stack. */
-    }
-
-    mbedtls_free( tmp_buf );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_RECORD_CHECKING */
-
-static int recv_cb( void *ctx, unsigned char *buf, size_t len )
-{
-    io_ctx_t *io_ctx = (io_ctx_t*) ctx;
-    size_t recv_len;
-    int ret;
-
-    if( opt.nbio == 2 )
-        ret = delayed_recv( io_ctx->net, buf, len );
-    else
-        ret = mbedtls_net_recv( io_ctx->net, buf, len );
-    if( ret < 0 )
-        return( ret );
-    recv_len = (size_t) ret;
-
-    if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        /* Here's the place to do any datagram/record checking
-         * in between receiving the packet from the underlying
-         * transport and passing it on to the TLS stack. */
-#if defined(MBEDTLS_SSL_RECORD_CHECKING)
-        if( ssl_check_record( io_ctx->ssl, buf, recv_len ) != 0 )
-            return( -1 );
-#endif /* MBEDTLS_SSL_RECORD_CHECKING */
-    }
-
-    return( (int) recv_len );
-}
-
-static int recv_timeout_cb( void *ctx, unsigned char *buf, size_t len,
-                            uint32_t timeout )
-{
-    io_ctx_t *io_ctx = (io_ctx_t*) ctx;
-    int ret;
-    size_t recv_len;
-
-    ret = mbedtls_net_recv_timeout( io_ctx->net, buf, len, timeout );
-    if( ret < 0 )
-        return( ret );
-    recv_len = (size_t) ret;
-
-    if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        /* Here's the place to do any datagram/record checking
-         * in between receiving the packet from the underlying
-         * transport and passing it on to the TLS stack. */
-#if defined(MBEDTLS_SSL_RECORD_CHECKING)
-        if( ssl_check_record( io_ctx->ssl, buf, recv_len ) != 0 )
-            return( -1 );
-#endif /* MBEDTLS_SSL_RECORD_CHECKING */
-    }
-
-    return( (int) recv_len );
-}
-
-static int send_cb( void *ctx, unsigned char const *buf, size_t len )
-{
-    io_ctx_t *io_ctx = (io_ctx_t*) ctx;
-
-    if( opt.nbio == 2 )
-        return( delayed_send( io_ctx->net, buf, len ) );
-
-    return( mbedtls_net_send( io_ctx->net, buf, len ) );
-}
+#include "ssl_test_common_source.c"
 
 /*
  * Return authmode from string, or -1 on error
@@ -1406,24 +947,6 @@
 }
 #endif
 
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-static int ssl_sig_hashes_for_test[] = {
-#if defined(MBEDTLS_SHA512_C)
-    MBEDTLS_MD_SHA512,
-    MBEDTLS_MD_SHA384,
-#endif
-#if defined(MBEDTLS_SHA256_C)
-    MBEDTLS_MD_SHA256,
-    MBEDTLS_MD_SHA224,
-#endif
-#if defined(MBEDTLS_SHA1_C)
-    /* Allow SHA-1 as we use it extensively in tests. */
-    MBEDTLS_MD_SHA1,
-#endif
-    MBEDTLS_MD_NONE
-};
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
-
 /** Return true if \p ret is a status code indicating that there is an
  * operation in progress on an SSL connection, and false if it indicates
  * success or a fatal error.
@@ -1662,56 +1185,6 @@
 }
 #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
 
-/*
- * Wait for an event from the underlying transport or the timer
- * (Used in event-driven IO mode).
- */
-#if !defined(MBEDTLS_TIMING_C)
-int idle( mbedtls_net_context *fd,
-          int idle_reason )
-#else
-int idle( mbedtls_net_context *fd,
-          mbedtls_timing_delay_context *timer,
-          int idle_reason )
-#endif
-{
-    int ret;
-    int poll_type = 0;
-
-    if( idle_reason == MBEDTLS_ERR_SSL_WANT_WRITE )
-        poll_type = MBEDTLS_NET_POLL_WRITE;
-    else if( idle_reason == MBEDTLS_ERR_SSL_WANT_READ )
-        poll_type = MBEDTLS_NET_POLL_READ;
-#if !defined(MBEDTLS_TIMING_C)
-    else
-        return( 0 );
-#endif
-
-    while( 1 )
-    {
-        /* Check if timer has expired */
-#if defined(MBEDTLS_TIMING_C)
-        if( timer != NULL &&
-            mbedtls_timing_get_delay( timer ) == 2 )
-        {
-            break;
-        }
-#endif /* MBEDTLS_TIMING_C */
-
-        /* Check if underlying transport became available */
-        if( poll_type != 0 )
-        {
-            ret = mbedtls_net_poll( fd, poll_type, 0 );
-            if( ret < 0 )
-                return( ret );
-            if( ret == poll_type )
-                break;
-        }
-    }
-
-    return( 0 );
-}
-
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 static psa_status_t psa_setup_psk_key_slot( psa_key_id_t *slot,
                                             psa_algorithm_t alg,
@@ -1813,8 +1286,7 @@
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
     mbedtls_x509_crt_profile crt_profile_for_test = mbedtls_x509_crt_profile_default;
 #endif
-    mbedtls_entropy_context entropy;
-    mbedtls_ctr_drbg_context ctr_drbg;
+    rng_context_t rng;
     mbedtls_ssl_context ssl;
     mbedtls_ssl_config conf;
 #if defined(MBEDTLS_TIMING_C)
@@ -1901,6 +1373,10 @@
 #endif  /* MBEDTLS_MEMORY_DEBUG */
 #endif  /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */
 
+#if defined(MBEDTLS_TEST_HOOKS)
+    test_hooks_init( );
+#endif /* MBEDTLS_TEST_HOOKS */
+
     /*
      * Make sure memory references are valid in case we exit early.
      */
@@ -1908,7 +1384,7 @@
     mbedtls_net_init( &listen_fd );
     mbedtls_ssl_init( &ssl );
     mbedtls_ssl_config_init( &conf );
-    mbedtls_ctr_drbg_init( &ctr_drbg );
+    rng_init( &rng );
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
     mbedtls_x509_crt_init( &cacert );
     mbedtls_x509_crt_init( &srvcert );
@@ -1944,7 +1420,10 @@
         ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
         goto exit;
     }
-#endif
+#endif  /* MBEDTLS_USE_PSA_CRYPTO */
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+    mbedtls_test_enable_insecure_external_rng( );
+#endif  /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
 
 #if !defined(_WIN32)
     /* Abort cleanly on SIGTERM and SIGINT */
@@ -2262,8 +1741,8 @@
             else if( strcmp( q, "tls1_1" ) == 0 ||
                      strcmp( q, "dtls1" ) == 0 )
                 opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2;
-            else if( strcmp( q, "tls1_2" ) == 0 ||
-                     strcmp( q, "dtls1_2" ) == 0 )
+            else if( strcmp( q, "tls12" ) == 0 ||
+                     strcmp( q, "dtls12" ) == 0 )
                 opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3;
             else
                 goto usage;
@@ -2277,8 +1756,8 @@
             else if( strcmp( q, "tls1_1" ) == 0 ||
                      strcmp( q, "dtls1" ) == 0 )
                 opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2;
-            else if( strcmp( q, "tls1_2" ) == 0 ||
-                     strcmp( q, "dtls1_2" ) == 0 )
+            else if( strcmp( q, "tls12" ) == 0 ||
+                     strcmp( q, "dtls12" ) == 0 )
                 opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3;
             else
                 goto usage;
@@ -2318,7 +1797,7 @@
                 opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2;
                 opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2;
             }
-            else if( strcmp( q, "tls1_2" ) == 0 )
+            else if( strcmp( q, "tls12" ) == 0 )
             {
                 opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3;
                 opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3;
@@ -2329,7 +1808,7 @@
                 opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2;
                 opt.transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM;
             }
-            else if( strcmp( q, "dtls1_2" ) == 0 )
+            else if( strcmp( q, "dtls12" ) == 0 )
             {
                 opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3;
                 opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3;
@@ -2824,31 +2303,9 @@
     mbedtls_printf( "\n  . Seeding the random number generator..." );
     fflush( stdout );
 
-    mbedtls_entropy_init( &entropy );
-    if (opt.reproducible)
-    {
-        srand( 1 );
-        if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, dummy_entropy,
-                                           &entropy, (const unsigned char *) pers,
-                                           strlen( pers ) ) ) != 0 )
-        {
-            mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned -0x%x\n",
-                            (unsigned int) -ret );
-            goto exit;
-        }
-    }
-    else
-    {
-        if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
-                                           &entropy, (const unsigned char *) pers,
-                                           strlen( pers ) ) ) != 0 )
-        {
-            mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned -0x%x\n",
-                            (unsigned int) -ret );
-            goto exit;
-        }
-    }
-
+    ret = rng_seed( &rng, opt.reproducible, pers );
+    if( ret != 0 )
+        goto exit;
     mbedtls_printf( " ok\n" );
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
@@ -3151,11 +2608,11 @@
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
 #if defined(MBEDTLS_SSL_DTLS_SRTP)
+    const mbedtls_ssl_srtp_profile forced_profile[] = { opt.force_srtp_profile, MBEDTLS_TLS_SRTP_UNSET };
     if( opt.use_srtp == 1 )
     {
         if( opt.force_srtp_profile != 0 )
         {
-            const mbedtls_ssl_srtp_profile forced_profile[] = { opt.force_srtp_profile, MBEDTLS_TLS_SRTP_UNSET };
             ret = mbedtls_ssl_conf_dtls_srtp_protection_profiles( &conf, forced_profile );
         }
         else
@@ -3235,9 +2692,9 @@
 #else
         fprintf( stderr, "Warning: reproducible option used without constant time\n" );
 #endif
-#endif
+#endif  /* MBEDTLS_HAVE_TIME */
     }
-    mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
+    mbedtls_ssl_conf_rng( &conf, rng_get, &rng );
     mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
 
 #if defined(MBEDTLS_SSL_CACHE_C)
@@ -3256,7 +2713,7 @@
     if( opt.tickets == MBEDTLS_SSL_SESSION_TICKETS_ENABLED )
     {
         if( ( ret = mbedtls_ssl_ticket_setup( &ticket_ctx,
-                        mbedtls_ctr_drbg_random, &ctr_drbg,
+                        rng_get, &rng,
                         MBEDTLS_CIPHER_AES_256_GCM,
                         opt.ticket_timeout ) ) != 0 )
         {
@@ -3278,7 +2735,7 @@
         if( opt.cookies > 0 )
         {
             if( ( ret = mbedtls_ssl_cookie_setup( &cookie_ctx,
-                                          mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
+                                                  rng_get, &rng ) ) != 0 )
             {
                 mbedtls_printf( " failed\n  ! mbedtls_ssl_cookie_setup returned %d\n\n", ret );
                 goto exit;
@@ -3430,8 +2887,8 @@
         ssl_async_keys.inject_error = ( opt.async_private_error < 0 ?
                                         - opt.async_private_error :
                                         opt.async_private_error );
-        ssl_async_keys.f_rng = mbedtls_ctr_drbg_random;
-        ssl_async_keys.p_rng = &ctr_drbg;
+        ssl_async_keys.f_rng = rng_get;
+        ssl_async_keys.p_rng = &rng;
         mbedtls_ssl_conf_async_private_cb( &conf,
                                            sign,
                                            decrypt,
@@ -4475,9 +3932,35 @@
     mbedtls_net_free( &client_fd );
     mbedtls_net_free( &listen_fd );
 
-#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO)
-    mbedtls_dhm_free( &dhm );
+    mbedtls_ssl_free( &ssl );
+    mbedtls_ssl_config_free( &conf );
+
+#if defined(MBEDTLS_SSL_CACHE_C)
+    mbedtls_ssl_cache_free( &cache );
 #endif
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    mbedtls_ssl_ticket_free( &ticket_ctx );
+#endif
+#if defined(MBEDTLS_SSL_COOKIE_C)
+    mbedtls_ssl_cookie_free( &cookie_ctx );
+#endif
+
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+    if( context_buf != NULL )
+        mbedtls_platform_zeroize( context_buf, context_buf_len );
+    mbedtls_free( context_buf );
+#endif
+
+#if defined(SNI_OPTION)
+    sni_free( sni_info );
+#endif
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+    ret = psk_free( psk_info );
+    if( ( ret != 0 ) && ( opt.query_config_mode == DFL_QUERY_CONFIG_MODE ) )
+        mbedtls_printf( "Failed to list of opaque PSKs - error was %d\n", ret );
+#endif
+
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
     mbedtls_x509_crt_free( &cacert );
     mbedtls_x509_crt_free( &srvcert );
@@ -4485,6 +3968,11 @@
     mbedtls_x509_crt_free( &srvcert2 );
     mbedtls_pk_free( &pkey2 );
 #endif
+
+#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO)
+    mbedtls_dhm_free( &dhm );
+#endif
+
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
     for( i = 0; (size_t) i < ssl_async_keys.slots_used; i++ )
     {
@@ -4496,17 +3984,6 @@
         }
     }
 #endif
-#if defined(SNI_OPTION)
-    sni_free( sni_info );
-#endif
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
-    ret = psk_free( psk_info );
-    if( ( ret != 0 ) && ( opt.query_config_mode == DFL_QUERY_CONFIG_MODE ) )
-        mbedtls_printf( "Failed to list of opaque PSKs - error was %d\n", ret );
-#endif
-#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO)
-    mbedtls_dhm_free( &dhm );
-#endif
 
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) && \
     defined(MBEDTLS_USE_PSA_CRYPTO)
@@ -4527,35 +4004,49 @@
 #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED &&
           MBEDTLS_USE_PSA_CRYPTO */
 
-    mbedtls_ssl_free( &ssl );
-    mbedtls_ssl_config_free( &conf );
-    mbedtls_ctr_drbg_free( &ctr_drbg );
-    mbedtls_entropy_free( &entropy );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    const char* message = mbedtls_test_helper_is_psa_leaking();
+    if( message )
+    {
+        if( ret == 0 )
+            ret = 1;
+        mbedtls_printf( "PSA memory leak detected: %s\n",  message);
+    }
+#endif
 
-#if defined(MBEDTLS_SSL_CACHE_C)
-    mbedtls_ssl_cache_free( &cache );
+    /* For builds with MBEDTLS_TEST_USE_PSA_CRYPTO_RNG psa crypto
+     * resources are freed by rng_free(). */
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
+    !defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+    mbedtls_psa_crypto_free( );
 #endif
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    mbedtls_ssl_ticket_free( &ticket_ctx );
-#endif
-#if defined(MBEDTLS_SSL_COOKIE_C)
-    mbedtls_ssl_cookie_free( &cookie_ctx );
-#endif
+
+    rng_free( &rng );
 
     mbedtls_free( buf );
 
-#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
-    if( context_buf != NULL )
-        mbedtls_platform_zeroize( context_buf, context_buf_len );
-    mbedtls_free( context_buf );
-#endif
+#if defined(MBEDTLS_TEST_HOOKS)
+    /* Let test hooks detect errors such as resource leaks.
+     * Don't do it in query_config mode, because some test code prints
+     * information to stdout and this gets mixed with the regular output. */
+    if( opt.query_config_mode == DFL_QUERY_CONFIG_MODE )
+    {
+        if( test_hooks_failure_detected( ) )
+        {
+            if( ret == 0 )
+                ret = 1;
+            mbedtls_printf( "Test hooks detected errors.\n" );
+        }
+    }
+    test_hooks_free( );
+#endif /* MBEDTLS_TEST_HOOKS */
 
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
 #if defined(MBEDTLS_MEMORY_DEBUG)
     mbedtls_memory_buffer_alloc_status();
 #endif
     mbedtls_memory_buffer_alloc_free();
-#endif
+#endif  /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */
 
     if( opt.query_config_mode == DFL_QUERY_CONFIG_MODE )
     {
@@ -4576,6 +4067,4 @@
     else
         mbedtls_exit( query_config_ret );
 }
-#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
-          MBEDTLS_SSL_SRV_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
-          MBEDTLS_CTR_DRBG_C */
+#endif /* !MBEDTLS_SSL_TEST_IMPOSSIBLE && MBEDTLS_SSL_SRV_C */
diff --git a/third_party/mbedtls/repo/programs/ssl/ssl_test_common_source.c b/third_party/mbedtls/repo/programs/ssl/ssl_test_common_source.c
new file mode 100644
index 0000000..f5d8680
--- /dev/null
+++ b/third_party/mbedtls/repo/programs/ssl/ssl_test_common_source.c
@@ -0,0 +1,306 @@
+/*
+ *  Common source code for SSL test programs. This file is included by
+ *  both ssl_client2.c and ssl_server2.c and is intended for source
+ *  code that is textually identical in both programs, but that cannot be
+ *  compiled separately because it refers to types or macros that are
+ *  different in the two programs, or because it would have an incomplete
+ *  type.
+ *
+ *  This file is meant to be #include'd and cannot be compiled separately.
+ *
+ *  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.
+ */
+
+#if defined(MBEDTLS_SSL_EXPORT_KEYS)
+int eap_tls_key_derivation( void *p_expkey,
+                            const unsigned char *ms,
+                            const unsigned char *kb,
+                            size_t maclen,
+                            size_t keylen,
+                            size_t ivlen,
+                            const unsigned char client_random[32],
+                            const unsigned char server_random[32],
+                            mbedtls_tls_prf_types tls_prf_type )
+{
+    eap_tls_keys *keys = (eap_tls_keys *)p_expkey;
+
+    ( ( void ) kb );
+    memcpy( keys->master_secret, ms, sizeof( keys->master_secret ) );
+    memcpy( keys->randbytes, client_random, 32 );
+    memcpy( keys->randbytes + 32, server_random, 32 );
+    keys->tls_prf_type = tls_prf_type;
+
+    if( opt.debug_level > 2 )
+    {
+        mbedtls_printf("exported maclen is %u\n", (unsigned)maclen);
+        mbedtls_printf("exported keylen is %u\n", (unsigned)keylen);
+        mbedtls_printf("exported ivlen is %u\n", (unsigned)ivlen);
+    }
+    return( 0 );
+}
+
+int nss_keylog_export( void *p_expkey,
+                       const unsigned char *ms,
+                       const unsigned char *kb,
+                       size_t maclen,
+                       size_t keylen,
+                       size_t ivlen,
+                       const unsigned char client_random[32],
+                       const unsigned char server_random[32],
+                       mbedtls_tls_prf_types tls_prf_type )
+{
+    char nss_keylog_line[ 200 ];
+    size_t const client_random_len = 32;
+    size_t const master_secret_len = 48;
+    size_t len = 0;
+    size_t j;
+    int ret = 0;
+
+    ((void) p_expkey);
+    ((void) kb);
+    ((void) maclen);
+    ((void) keylen);
+    ((void) ivlen);
+    ((void) server_random);
+    ((void) tls_prf_type);
+
+    len += sprintf( nss_keylog_line + len,
+                    "%s", "CLIENT_RANDOM " );
+
+    for( j = 0; j < client_random_len; j++ )
+    {
+        len += sprintf( nss_keylog_line + len,
+                        "%02x", client_random[j] );
+    }
+
+    len += sprintf( nss_keylog_line + len, " " );
+
+    for( j = 0; j < master_secret_len; j++ )
+    {
+        len += sprintf( nss_keylog_line + len,
+                        "%02x", ms[j] );
+    }
+
+    len += sprintf( nss_keylog_line + len, "\n" );
+    nss_keylog_line[ len ] = '\0';
+
+    mbedtls_printf( "\n" );
+    mbedtls_printf( "---------------- NSS KEYLOG -----------------\n" );
+    mbedtls_printf( "%s", nss_keylog_line );
+    mbedtls_printf( "---------------------------------------------\n" );
+
+    if( opt.nss_keylog_file != NULL )
+    {
+        FILE *f;
+
+        if( ( f = fopen( opt.nss_keylog_file, "a" ) ) == NULL )
+        {
+            ret = -1;
+            goto exit;
+        }
+
+        if( fwrite( nss_keylog_line, 1, len, f ) != len )
+        {
+            ret = -1;
+            fclose( f );
+            goto exit;
+        }
+
+        fclose( f );
+    }
+
+exit:
+    mbedtls_platform_zeroize( nss_keylog_line,
+                              sizeof( nss_keylog_line ) );
+    return( ret );
+}
+
+#if defined( MBEDTLS_SSL_DTLS_SRTP )
+int dtls_srtp_key_derivation( void *p_expkey,
+                              const unsigned char *ms,
+                              const unsigned char *kb,
+                              size_t maclen,
+                              size_t keylen,
+                              size_t ivlen,
+                              const unsigned char client_random[32],
+                              const unsigned char server_random[32],
+                              mbedtls_tls_prf_types tls_prf_type )
+{
+    dtls_srtp_keys *keys = (dtls_srtp_keys *)p_expkey;
+
+    ( ( void ) kb );
+    memcpy( keys->master_secret, ms, sizeof( keys->master_secret ) );
+    memcpy( keys->randbytes, client_random, 32 );
+    memcpy( keys->randbytes + 32, server_random, 32 );
+    keys->tls_prf_type = tls_prf_type;
+
+    if( opt.debug_level > 2 )
+    {
+        mbedtls_printf( "exported maclen is %u\n", (unsigned) maclen );
+        mbedtls_printf( "exported keylen is %u\n", (unsigned) keylen );
+        mbedtls_printf( "exported ivlen is %u\n", (unsigned) ivlen );
+    }
+    return( 0 );
+}
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
+#endif /* MBEDTLS_SSL_EXPORT_KEYS */
+
+#if defined(MBEDTLS_SSL_RECORD_CHECKING)
+int ssl_check_record( mbedtls_ssl_context const *ssl,
+                      unsigned char const *buf, size_t len )
+{
+    int my_ret = 0, ret_cr1, ret_cr2;
+    unsigned char *tmp_buf;
+
+    /* Record checking may modify the input buffer,
+     * so make a copy. */
+    tmp_buf = mbedtls_calloc( 1, len );
+    if( tmp_buf == NULL )
+        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+    memcpy( tmp_buf, buf, len );
+
+    ret_cr1 = mbedtls_ssl_check_record( ssl, tmp_buf, len );
+    if( ret_cr1 != MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE )
+    {
+        /* Test-only: Make sure that mbedtls_ssl_check_record()
+         *            doesn't alter state. */
+        memcpy( tmp_buf, buf, len ); /* Restore buffer */
+        ret_cr2 = mbedtls_ssl_check_record( ssl, tmp_buf, len );
+        if( ret_cr2 != ret_cr1 )
+        {
+            mbedtls_printf( "mbedtls_ssl_check_record() returned inconsistent results.\n" );
+            my_ret = -1;
+            goto cleanup;
+        }
+
+        switch( ret_cr1 )
+        {
+            case 0:
+                break;
+
+            case MBEDTLS_ERR_SSL_INVALID_RECORD:
+                if( opt.debug_level > 1 )
+                    mbedtls_printf( "mbedtls_ssl_check_record() detected invalid record.\n" );
+                break;
+
+            case MBEDTLS_ERR_SSL_INVALID_MAC:
+                if( opt.debug_level > 1 )
+                    mbedtls_printf( "mbedtls_ssl_check_record() detected unauthentic record.\n" );
+                break;
+
+            case MBEDTLS_ERR_SSL_UNEXPECTED_RECORD:
+                if( opt.debug_level > 1 )
+                    mbedtls_printf( "mbedtls_ssl_check_record() detected unexpected record.\n" );
+                break;
+
+            default:
+                mbedtls_printf( "mbedtls_ssl_check_record() failed fatally with -%#04x.\n", (unsigned int) -ret_cr1 );
+                my_ret = -1;
+                goto cleanup;
+        }
+
+        /* Regardless of the outcome, forward the record to the stack. */
+    }
+
+cleanup:
+    mbedtls_free( tmp_buf );
+
+    return( my_ret );
+}
+#endif /* MBEDTLS_SSL_RECORD_CHECKING */
+
+int recv_cb( void *ctx, unsigned char *buf, size_t len )
+{
+    io_ctx_t *io_ctx = (io_ctx_t*) ctx;
+    size_t recv_len;
+    int ret;
+
+    if( opt.nbio == 2 )
+        ret = delayed_recv( io_ctx->net, buf, len );
+    else
+        ret = mbedtls_net_recv( io_ctx->net, buf, len );
+    if( ret < 0 )
+        return( ret );
+    recv_len = (size_t) ret;
+
+    if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+    {
+        /* Here's the place to do any datagram/record checking
+         * in between receiving the packet from the underlying
+         * transport and passing it on to the TLS stack. */
+#if defined(MBEDTLS_SSL_RECORD_CHECKING)
+        if( ssl_check_record( io_ctx->ssl, buf, recv_len ) != 0 )
+            return( -1 );
+#endif /* MBEDTLS_SSL_RECORD_CHECKING */
+    }
+
+    return( (int) recv_len );
+}
+
+int recv_timeout_cb( void *ctx, unsigned char *buf, size_t len,
+                     uint32_t timeout )
+{
+    io_ctx_t *io_ctx = (io_ctx_t*) ctx;
+    int ret;
+    size_t recv_len;
+
+    ret = mbedtls_net_recv_timeout( io_ctx->net, buf, len, timeout );
+    if( ret < 0 )
+        return( ret );
+    recv_len = (size_t) ret;
+
+    if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+    {
+        /* Here's the place to do any datagram/record checking
+         * in between receiving the packet from the underlying
+         * transport and passing it on to the TLS stack. */
+#if defined(MBEDTLS_SSL_RECORD_CHECKING)
+        if( ssl_check_record( io_ctx->ssl, buf, recv_len ) != 0 )
+            return( -1 );
+#endif /* MBEDTLS_SSL_RECORD_CHECKING */
+    }
+
+    return( (int) recv_len );
+}
+
+int send_cb( void *ctx, unsigned char const *buf, size_t len )
+{
+    io_ctx_t *io_ctx = (io_ctx_t*) ctx;
+
+    if( opt.nbio == 2 )
+        return( delayed_send( io_ctx->net, buf, len ) );
+
+    return( mbedtls_net_send( io_ctx->net, buf, len ) );
+}
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+int ssl_sig_hashes_for_test[] = {
+#if defined(MBEDTLS_SHA512_C)
+    MBEDTLS_MD_SHA512,
+    MBEDTLS_MD_SHA384,
+#endif
+#if defined(MBEDTLS_SHA256_C)
+    MBEDTLS_MD_SHA256,
+    MBEDTLS_MD_SHA224,
+#endif
+#if defined(MBEDTLS_SHA1_C)
+    /* Allow SHA-1 as we use it extensively in tests. */
+    MBEDTLS_MD_SHA1,
+#endif
+    MBEDTLS_MD_NONE
+};
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
diff --git a/third_party/mbedtls/repo/programs/ssl/ssl_test_lib.c b/third_party/mbedtls/repo/programs/ssl/ssl_test_lib.c
new file mode 100644
index 0000000..1bb9d61
--- /dev/null
+++ b/third_party/mbedtls/repo/programs/ssl/ssl_test_lib.c
@@ -0,0 +1,357 @@
+/*
+ *  Common code library for SSL test programs.
+ *
+ *  In addition to the functions in this file, there is shared source code
+ *  that cannot be compiled separately in "ssl_test_common_source.c".
+ *
+ *  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 "ssl_test_lib.h"
+
+#if defined(MBEDTLS_TEST_HOOKS)
+#include "test/helpers.h"
+#endif
+
+#if !defined(MBEDTLS_SSL_TEST_IMPOSSIBLE)
+
+void my_debug( void *ctx, int level,
+               const char *file, int line,
+               const char *str )
+{
+    const char *p, *basename;
+
+    /* Extract basename from file */
+    for( p = basename = file; *p != '\0'; p++ )
+        if( *p == '/' || *p == '\\' )
+            basename = p + 1;
+
+    mbedtls_fprintf( (FILE *) ctx, "%s:%04d: |%d| %s",
+                     basename, line, level, str );
+    fflush( (FILE *) ctx  );
+}
+
+mbedtls_time_t dummy_constant_time( mbedtls_time_t* time )
+{
+    (void) time;
+    return 0x5af2a056;
+}
+
+#if !defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+static int dummy_entropy( void *data, unsigned char *output, size_t len )
+{
+    size_t i;
+    int ret;
+    (void) data;
+
+    ret = mbedtls_entropy_func( data, output, len );
+    for( i = 0; i < len; i++ )
+    {
+        //replace result with pseudo random
+        output[i] = (unsigned char) rand();
+    }
+    return( ret );
+}
+#endif
+
+void rng_init( rng_context_t *rng )
+{
+#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+    (void) rng;
+    psa_crypto_init( );
+#else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
+
+#if defined(MBEDTLS_CTR_DRBG_C)
+    mbedtls_ctr_drbg_init( &rng->drbg );
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+    mbedtls_hmac_drbg_init( &rng->drbg );
+#else
+#error "No DRBG available"
+#endif
+
+    mbedtls_entropy_init( &rng->entropy );
+#endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
+}
+
+int rng_seed( rng_context_t *rng, int reproducible, const char *pers )
+{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if( reproducible )
+    {
+        mbedtls_fprintf( stderr,
+                         "MBEDTLS_USE_PSA_CRYPTO does not support reproducible mode.\n" );
+        return( -1 );
+    }
+#endif
+#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+    /* The PSA crypto RNG does its own seeding. */
+    (void) rng;
+    (void) pers;
+    if( reproducible )
+    {
+        mbedtls_fprintf( stderr,
+                         "The PSA RNG does not support reproducible mode.\n" );
+        return( -1 );
+    }
+    return( 0 );
+#else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
+    int ( *f_entropy )( void *, unsigned char *, size_t ) =
+        ( reproducible ? dummy_entropy : mbedtls_entropy_func );
+
+    if ( reproducible )
+        srand( 1 );
+
+#if defined(MBEDTLS_CTR_DRBG_C)
+    int ret = mbedtls_ctr_drbg_seed( &rng->drbg,
+                                     f_entropy, &rng->entropy,
+                                     (const unsigned char *) pers,
+                                     strlen( pers ) );
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+#if defined(MBEDTLS_SHA256_C)
+    const mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
+#elif defined(MBEDTLS_SHA512_C)
+    const mbedtls_md_type_t md_type = MBEDTLS_MD_SHA512;
+#else
+#error "No message digest available for HMAC_DRBG"
+#endif
+    int ret = mbedtls_hmac_drbg_seed( &rng->drbg,
+                                      mbedtls_md_info_from_type( md_type ),
+                                      f_entropy, &rng->entropy,
+                                      (const unsigned char *) pers,
+                                      strlen( pers ) );
+#else /* !defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_HMAC_DRBG_C) */
+#error "No DRBG available"
+#endif /* !defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_HMAC_DRBG_C) */
+
+    if( ret != 0 )
+    {
+        mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned -0x%x\n",
+                        (unsigned int) -ret );
+        return( ret );
+    }
+#endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
+
+    return( 0 );
+}
+
+void rng_free( rng_context_t *rng )
+{
+#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+    (void) rng;
+    /* Deinitialize the PSA crypto subsystem. This deactivates all PSA APIs.
+     * This is ok because none of our applications try to do any crypto after
+     * deinitializing the RNG. */
+    mbedtls_psa_crypto_free( );
+#else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
+
+#if defined(MBEDTLS_CTR_DRBG_C)
+    mbedtls_ctr_drbg_free( &rng->drbg );
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+    mbedtls_hmac_drbg_free( &rng->drbg );
+#else
+#error "No DRBG available"
+#endif
+
+    mbedtls_entropy_free( &rng->entropy );
+#endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
+}
+
+int rng_get( void *p_rng, unsigned char *output, size_t output_len )
+{
+#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+    (void) p_rng;
+    return( mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
+                                    output, output_len ) );
+#else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
+    rng_context_t *rng = p_rng;
+
+#if defined(MBEDTLS_CTR_DRBG_C)
+    return( mbedtls_ctr_drbg_random( &rng->drbg, output, output_len ) );
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+    return( mbedtls_hmac_drbg_random( &rng->drbg, output, output_len ) );
+#else
+#error "No DRBG available"
+#endif
+
+#endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
+}
+
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+int ca_callback( void *data, mbedtls_x509_crt const *child,
+                 mbedtls_x509_crt **candidates )
+{
+    int ret = 0;
+    mbedtls_x509_crt *ca = (mbedtls_x509_crt *) data;
+    mbedtls_x509_crt *first;
+
+    /* This is a test-only implementation of the CA callback
+     * which always returns the entire list of trusted certificates.
+     * Production implementations managing a large number of CAs
+     * should use an efficient presentation and lookup for the
+     * set of trusted certificates (such as a hashtable) and only
+     * return those trusted certificates which satisfy basic
+     * parental checks, such as the matching of child `Issuer`
+     * and parent `Subject` field or matching key identifiers. */
+    ((void) child);
+
+    first = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
+    if( first == NULL )
+    {
+        ret = -1;
+        goto exit;
+    }
+    mbedtls_x509_crt_init( first );
+
+    if( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) != 0 )
+    {
+        ret = -1;
+        goto exit;
+    }
+
+    while( ca->next != NULL )
+    {
+        ca = ca->next;
+        if( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) != 0 )
+        {
+            ret = -1;
+            goto exit;
+        }
+    }
+
+exit:
+
+    if( ret != 0 )
+    {
+        mbedtls_x509_crt_free( first );
+        mbedtls_free( first );
+        first = NULL;
+    }
+
+    *candidates = first;
+    return( ret );
+}
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
+
+int delayed_recv( void *ctx, unsigned char *buf, size_t len )
+{
+    static int first_try = 1;
+    int ret;
+
+    if( first_try )
+    {
+        first_try = 0;
+        return( MBEDTLS_ERR_SSL_WANT_READ );
+    }
+
+    ret = mbedtls_net_recv( ctx, buf, len );
+    if( ret != MBEDTLS_ERR_SSL_WANT_READ )
+        first_try = 1; /* Next call will be a new operation */
+    return( ret );
+}
+
+int delayed_send( void *ctx, const unsigned char *buf, size_t len )
+{
+    static int first_try = 1;
+    int ret;
+
+    if( first_try )
+    {
+        first_try = 0;
+        return( MBEDTLS_ERR_SSL_WANT_WRITE );
+    }
+
+    ret = mbedtls_net_send( ctx, buf, len );
+    if( ret != MBEDTLS_ERR_SSL_WANT_WRITE )
+        first_try = 1; /* Next call will be a new operation */
+    return( ret );
+}
+
+#if !defined(MBEDTLS_TIMING_C)
+int idle( mbedtls_net_context *fd,
+          int idle_reason )
+#else
+int idle( mbedtls_net_context *fd,
+          mbedtls_timing_delay_context *timer,
+          int idle_reason )
+#endif
+{
+    int ret;
+    int poll_type = 0;
+
+    if( idle_reason == MBEDTLS_ERR_SSL_WANT_WRITE )
+        poll_type = MBEDTLS_NET_POLL_WRITE;
+    else if( idle_reason == MBEDTLS_ERR_SSL_WANT_READ )
+        poll_type = MBEDTLS_NET_POLL_READ;
+#if !defined(MBEDTLS_TIMING_C)
+    else
+        return( 0 );
+#endif
+
+    while( 1 )
+    {
+        /* Check if timer has expired */
+#if defined(MBEDTLS_TIMING_C)
+        if( timer != NULL &&
+            mbedtls_timing_get_delay( timer ) == 2 )
+        {
+            break;
+        }
+#endif /* MBEDTLS_TIMING_C */
+
+        /* Check if underlying transport became available */
+        if( poll_type != 0 )
+        {
+            ret = mbedtls_net_poll( fd, poll_type, 0 );
+            if( ret < 0 )
+                return( ret );
+            if( ret == poll_type )
+                break;
+        }
+    }
+
+    return( 0 );
+}
+
+#if defined(MBEDTLS_TEST_HOOKS)
+
+void test_hooks_init( void )
+{
+    mbedtls_test_info_reset( );
+
+#if defined(MBEDTLS_TEST_MUTEX_USAGE)
+    mbedtls_test_mutex_usage_init( );
+#endif
+}
+
+int test_hooks_failure_detected( void )
+{
+#if defined(MBEDTLS_TEST_MUTEX_USAGE)
+    /* Errors are reported via mbedtls_test_info. */
+    mbedtls_test_mutex_usage_check( );
+#endif
+
+    if( mbedtls_test_info.result != MBEDTLS_TEST_RESULT_SUCCESS )
+        return( 1 );
+    return( 0 );
+}
+
+void test_hooks_free( void )
+{
+}
+
+#endif /* MBEDTLS_TEST_HOOKS */
+
+#endif /* !defined(MBEDTLS_SSL_TEST_IMPOSSIBLE) */
diff --git a/third_party/mbedtls/repo/programs/ssl/ssl_test_lib.h b/third_party/mbedtls/repo/programs/ssl/ssl_test_lib.h
new file mode 100644
index 0000000..98751a0
--- /dev/null
+++ b/third_party/mbedtls/repo/programs/ssl/ssl_test_lib.h
@@ -0,0 +1,294 @@
+/*
+ *  Common code for SSL test programs
+ *
+ *  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_PROGRAMS_SSL_SSL_TEST_LIB_H
+#define MBEDTLS_PROGRAMS_SSL_SSL_TEST_LIB_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#define mbedtls_calloc     calloc
+#define mbedtls_free       free
+#define mbedtls_time       time
+#define mbedtls_time_t     time_t
+#define mbedtls_printf     printf
+#define mbedtls_fprintf    fprintf
+#define mbedtls_snprintf   snprintf
+#define mbedtls_exit            exit
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif
+
+#undef HAVE_RNG
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) &&         \
+    ( defined(MBEDTLS_USE_PSA_CRYPTO) ||                \
+      defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG) )
+#define HAVE_RNG
+#elif defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_CTR_DRBG_C)
+#define HAVE_RNG
+#elif defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_HMAC_DRBG_C) &&     \
+    ( defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C) )
+#define HAVE_RNG
+#endif
+
+#if !defined(MBEDTLS_NET_C) ||                              \
+    !defined(MBEDTLS_SSL_TLS_C) ||                          \
+    defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
+#define MBEDTLS_SSL_TEST_IMPOSSIBLE                             \
+    "MBEDTLS_NET_C and/or "                                     \
+    "MBEDTLS_SSL_TLS_C not defined, "                           \
+    "and/or MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined.\n"
+#elif !defined(HAVE_RNG)
+#define MBEDTLS_SSL_TEST_IMPOSSIBLE             \
+    "No random generator is available.\n"
+#else
+#undef MBEDTLS_SSL_TEST_IMPOSSIBLE
+
+#undef HAVE_RNG
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mbedtls/net_sockets.h"
+#include "mbedtls/ssl.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/hmac_drbg.h"
+#include "mbedtls/certs.h"
+#include "mbedtls/x509.h"
+#include "mbedtls/error.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/timing.h"
+#include "mbedtls/base64.h"
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
+#endif
+
+#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
+#include "mbedtls/memory_buffer_alloc.h"
+#endif
+
+#include <test/helpers.h>
+
+#include "../test/query_config.h"
+
+#if defined(MBEDTLS_SSL_EXPORT_KEYS)
+
+typedef struct eap_tls_keys
+{
+    unsigned char master_secret[48];
+    unsigned char randbytes[64];
+    mbedtls_tls_prf_types tls_prf_type;
+} eap_tls_keys;
+
+#if defined( MBEDTLS_SSL_DTLS_SRTP )
+
+/* Supported SRTP mode needs a maximum of :
+ * - 16 bytes for key (AES-128)
+ * - 14 bytes SALT
+ * One for sender, one for receiver context
+ */
+#define MBEDTLS_TLS_SRTP_MAX_KEY_MATERIAL_LENGTH    60
+
+typedef struct dtls_srtp_keys
+{
+    unsigned char master_secret[48];
+    unsigned char randbytes[64];
+    mbedtls_tls_prf_types tls_prf_type;
+} dtls_srtp_keys;
+
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
+#endif /* MBEDTLS_SSL_EXPORT_KEYS */
+
+typedef struct
+{
+    mbedtls_ssl_context *ssl;
+    mbedtls_net_context *net;
+} io_ctx_t;
+
+void my_debug( void *ctx, int level,
+               const char *file, int line,
+               const char *str );
+
+mbedtls_time_t dummy_constant_time( mbedtls_time_t* time );
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+/* If MBEDTLS_TEST_USE_PSA_CRYPTO_RNG is defined, the SSL test programs will use
+ * mbedtls_psa_get_random() rather than entropy+DRBG as a random generator.
+ *
+ * The constraints are:
+ * - Without the entropy module, the PSA RNG is the only option.
+ * - Without at least one of the DRBG modules, the PSA RNG is the only option.
+ * - The PSA RNG does not support explicit seeding, so it is incompatible with
+ *   the reproducible mode used by test programs.
+ * - For good overall test coverage, there should be at least one configuration
+ *   where the test programs use the PSA RNG while the PSA RNG is itself based
+ *   on entropy+DRBG, and at least one configuration where the test programs
+ *   do not use the PSA RNG even though it's there.
+ *
+ * A simple choice that meets the constraints is to use the PSA RNG whenever
+ * MBEDTLS_USE_PSA_CRYPTO is enabled. There's no real technical reason the
+ * choice to use the PSA RNG in the test programs and the choice to use
+ * PSA crypto when TLS code needs crypto have to be tied together, but it
+ * happens to be a good match. It's also a good match from an application
+ * perspective: either PSA is preferred for TLS (both for crypto and for
+ * random generation) or it isn't.
+ */
+#define MBEDTLS_TEST_USE_PSA_CRYPTO_RNG
+#endif
+
+/** A context for random number generation (RNG).
+ */
+typedef struct
+{
+#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+    unsigned char dummy;
+#else /* MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
+    mbedtls_entropy_context entropy;
+#if defined(MBEDTLS_CTR_DRBG_C)
+    mbedtls_ctr_drbg_context drbg;
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+    mbedtls_hmac_drbg_context drbg;
+#else
+#error "No DRBG available"
+#endif
+#endif /* MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
+} rng_context_t;
+
+/** Initialize the RNG.
+ *
+ * This function only initializes the memory used by the RNG context.
+ * Before using the RNG, it must be seeded with rng_seed().
+ */
+void rng_init( rng_context_t *rng );
+
+/* Seed the random number generator.
+ *
+ * \param rng           The RNG context to use. It must have been initialized
+ *                      with rng_init().
+ * \param reproducible  If zero, seed the RNG from entropy.
+ *                      If nonzero, use a fixed seed, so that the program
+ *                      will produce the same sequence of random numbers
+ *                      each time it is invoked.
+ * \param pers          A null-terminated string. Different values for this
+ *                      string cause the RNG to emit different output for
+ *                      the same seed.
+ *
+ * return 0 on success, a negative value on error.
+ */
+int rng_seed( rng_context_t *rng, int reproducible, const char *pers );
+
+/** Deinitialize the RNG. Free any embedded resource.
+ *
+ * \param rng           The RNG context to deinitialize. It must have been
+ *                      initialized with rng_init().
+ */
+void rng_free( rng_context_t *rng );
+
+/** Generate random data.
+ *
+ * This function is suitable for use as the \c f_rng argument to Mbed TLS
+ * library functions.
+ *
+ * \param p_rng         The random generator context. This must be a pointer to
+ *                      a #rng_context_t structure.
+ * \param output        The buffer to fill.
+ * \param output_len    The length of the buffer in bytes.
+ *
+ * \return              \c 0 on success.
+ * \return              An Mbed TLS error code on error.
+ */
+int rng_get( void *p_rng, unsigned char *output, size_t output_len );
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+/* The test implementation of the PSA external RNG is insecure. When
+ * MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG is enabled, before using any PSA crypto
+ * function that makes use of an RNG, you must call
+ * mbedtls_test_enable_insecure_external_rng(). */
+#include <test/fake_external_rng_for_test.h>
+#endif
+
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+int ca_callback( void *data, mbedtls_x509_crt const *child,
+                 mbedtls_x509_crt **candidates );
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
+
+/*
+ * Test recv/send functions that make sure each try returns
+ * WANT_READ/WANT_WRITE at least once before sucesseding
+ */
+int delayed_recv( void *ctx, unsigned char *buf, size_t len );
+int delayed_send( void *ctx, const unsigned char *buf, size_t len );
+
+/*
+ * Wait for an event from the underlying transport or the timer
+ * (Used in event-driven IO mode).
+ */
+int idle( mbedtls_net_context *fd,
+#if defined(MBEDTLS_TIMING_C)
+          mbedtls_timing_delay_context *timer,
+#endif
+          int idle_reason );
+
+#if defined(MBEDTLS_TEST_HOOKS)
+/** Initialize whatever test hooks are enabled by the compile-time
+ * configuration and make sense for the TLS test programs. */
+void test_hooks_init( void );
+
+/** Check if any test hooks detected a problem.
+ *
+ * If a problem was detected, it's ok for the calling program to keep going,
+ * but it should ultimately exit with an error status.
+ *
+ * \note When implementing a test hook that detects errors on its own
+ *       (as opposed to e.g. leaving the error for a memory sanitizer to
+ *       report), make sure to print a message to standard error either at
+ *       the time the problem is detected or during the execution of this
+ *       function. This function does not indicate what problem was detected,
+ *       so printing a message is the only way to provide feedback in the
+ *       logs of the calling program.
+ *
+ * \return Nonzero if a problem was detected.
+ *         \c 0 if no problem was detected.
+ */
+int test_hooks_failure_detected( void );
+
+/** Free any resources allocated for the sake of test hooks.
+ *
+ * Call this at the end of the program so that resource leak analyzers
+ * don't complain.
+ */
+void test_hooks_free( void );
+
+#endif /* !MBEDTLS_TEST_HOOKS */
+
+#endif /* MBEDTLS_SSL_TEST_IMPOSSIBLE conditions: else */
+#endif /* MBEDTLS_PROGRAMS_SSL_SSL_TEST_LIB_H */
diff --git a/third_party/mbedtls/repo/programs/test/CMakeLists.txt b/third_party/mbedtls/repo/programs/test/CMakeLists.txt
index 49b44e7..403797c 100644
--- a/third_party/mbedtls/repo/programs/test/CMakeLists.txt
+++ b/third_party/mbedtls/repo/programs/test/CMakeLists.txt
@@ -22,11 +22,34 @@
 )
 
 if(TEST_CPP)
-    list(APPEND executables_mbedcrypto cpp_dummy_build)
+    set(cpp_dummy_build_cpp "${CMAKE_CURRENT_BINARY_DIR}/cpp_dummy_build.cpp")
+    set(generate_cpp_dummy_build "${CMAKE_CURRENT_SOURCE_DIR}/generate_cpp_dummy_build.sh")
+    add_custom_command(
+        OUTPUT "${cpp_dummy_build_cpp}"
+        COMMAND "${generate_cpp_dummy_build}" "${cpp_dummy_build_cpp}"
+        DEPENDS "${generate_cpp_dummy_build}"
+        WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+    )
+    add_executable(cpp_dummy_build "${cpp_dummy_build_cpp}")
+    target_include_directories(cpp_dummy_build PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../include)
+    target_link_libraries(cpp_dummy_build ${mbedcrypto_target})
+endif()
+
+if(USE_SHARED_MBEDTLS_LIBRARY AND
+   NOT ${CMAKE_SYSTEM_NAME} MATCHES "[Ww][Ii][Nn]")
+    add_executable(dlopen "dlopen.c")
+    target_include_directories(dlopen PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../include)
+    target_link_libraries(dlopen ${CMAKE_DL_LIBS})
 endif()
 
 foreach(exe IN LISTS executables_libs executables_mbedcrypto)
-    add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
+    set(extra_sources "")
+    if(exe STREQUAL "query_compile_time_config")
+        list(APPEND extra_sources
+            ${CMAKE_CURRENT_SOURCE_DIR}/query_config.c)
+    endif()
+    add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>
+        ${extra_sources})
 
     # This emulates "if ( ... IN_LIST ... )" which becomes available in CMake 3.3
     list(FIND executables_libs ${exe} exe_index)
@@ -37,9 +60,6 @@
     endif()
 endforeach()
 
-set_property(TARGET query_compile_time_config APPEND PROPERTY SOURCES
-             ${CMAKE_CURRENT_SOURCE_DIR}/query_config.c)
-
 install(TARGETS ${executables_libs} ${executables_mbedcrypto}
         DESTINATION "bin"
         PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
diff --git a/third_party/mbedtls/repo/programs/test/benchmark.c b/third_party/mbedtls/repo/programs/test/benchmark.c
index 251cbb6..88c9e65 100644
--- a/third_party/mbedtls/repo/programs/test/benchmark.c
+++ b/third_party/mbedtls/repo/programs/test/benchmark.c
@@ -266,6 +266,21 @@
 #define ecp_clear_precomputed( g )
 #endif
 
+#if defined(MBEDTLS_ECP_C)
+static int set_ecp_curve( const char *string, mbedtls_ecp_curve_info *curve )
+{
+    const mbedtls_ecp_curve_info *found =
+        mbedtls_ecp_curve_info_from_name( string );
+    if( found != NULL )
+    {
+        *curve = *found;
+        return( 1 );
+    }
+    else
+        return( 0 );
+}
+#endif
+
 unsigned char buf[BUFSIZE];
 
 typedef struct {
@@ -289,6 +304,17 @@
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
     unsigned char alloc_buf[HEAP_SIZE] = { 0 };
 #endif
+#if defined(MBEDTLS_ECP_C)
+    mbedtls_ecp_curve_info single_curve[2] = {
+        { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
+        { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
+    };
+    const mbedtls_ecp_curve_info *curve_list = mbedtls_ecp_curve_list( );
+#endif
+
+#if defined(MBEDTLS_ECP_C)
+    (void) curve_list; /* Unused in some configurations where no benchmark uses ECC */
+#endif
 
     if( argc <= 1 )
     {
@@ -356,6 +382,10 @@
                 todo.ecdsa = 1;
             else if( strcmp( argv[i], "ecdh" ) == 0 )
                 todo.ecdh = 1;
+#if defined(MBEDTLS_ECP_C)
+            else if( set_ecp_curve( argv[i], single_curve ) )
+                curve_list = single_curve;
+#endif
             else
             {
                 mbedtls_printf( "Unrecognized option: %s\n", argv[i] );
@@ -419,7 +449,8 @@
     {
         mbedtls_des3_context des3;
         mbedtls_des3_init( &des3 );
-        mbedtls_des3_set3key_enc( &des3, tmp );
+        if( mbedtls_des3_set3key_enc( &des3, tmp ) != 0 )
+            mbedtls_exit( 1 );
         TIME_AND_TSC( "3DES",
                 mbedtls_des3_crypt_cbc( &des3, MBEDTLS_DES_ENCRYPT, BUFSIZE, tmp, buf, buf ) );
         mbedtls_des3_free( &des3 );
@@ -429,7 +460,8 @@
     {
         mbedtls_des_context des;
         mbedtls_des_init( &des );
-        mbedtls_des_setkey_enc( &des, tmp );
+        if( mbedtls_des_setkey_enc( &des, tmp ) != 0 )
+            mbedtls_exit( 1 );
         TIME_AND_TSC( "DES",
                 mbedtls_des_crypt_cbc( &des, MBEDTLS_DES_ENCRYPT, BUFSIZE, tmp, buf, buf ) );
         mbedtls_des_free( &des );
@@ -467,7 +499,7 @@
 
             memset( buf, 0, sizeof( buf ) );
             memset( tmp, 0, sizeof( tmp ) );
-            mbedtls_aes_setkey_enc( &aes, tmp, keysize );
+            CHECK_AND_CONTINUE( mbedtls_aes_setkey_enc( &aes, tmp, keysize ) );
 
             TIME_AND_TSC( title,
                 mbedtls_aes_crypt_cbc( &aes, MBEDTLS_AES_ENCRYPT, BUFSIZE, tmp, buf, buf ) );
@@ -488,7 +520,7 @@
 
             memset( buf, 0, sizeof( buf ) );
             memset( tmp, 0, sizeof( tmp ) );
-            mbedtls_aes_xts_setkey_enc( &ctx, tmp, keysize * 2 );
+            CHECK_AND_CONTINUE( mbedtls_aes_xts_setkey_enc( &ctx, tmp, keysize * 2 ) );
 
             TIME_AND_TSC( title,
                     mbedtls_aes_crypt_xts( &ctx, MBEDTLS_AES_ENCRYPT, BUFSIZE,
@@ -845,7 +877,7 @@
 
         memset( buf, 0x2A, sizeof( buf ) );
 
-        for( curve_info = mbedtls_ecp_curve_list();
+        for( curve_info = curve_list;
              curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
              curve_info++ )
         {
@@ -867,7 +899,7 @@
             mbedtls_ecdsa_free( &ecdsa );
         }
 
-        for( curve_info = mbedtls_ecp_curve_list();
+        for( curve_info = curve_list;
              curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
              curve_info++ )
         {
@@ -911,8 +943,23 @@
         };
         const mbedtls_ecp_curve_info *curve_info;
         size_t olen;
+        const mbedtls_ecp_curve_info *selected_montgomery_curve_list =
+            montgomery_curve_list;
 
-        for( curve_info = mbedtls_ecp_curve_list();
+        if( curve_list == (const mbedtls_ecp_curve_info*) &single_curve )
+        {
+            mbedtls_ecp_group grp;
+            mbedtls_ecp_group_init( &grp );
+            if( mbedtls_ecp_group_load( &grp, curve_list->grp_id ) != 0 )
+                mbedtls_exit( 1 );
+            if( mbedtls_ecp_get_type( &grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
+                selected_montgomery_curve_list = single_curve;
+            else /* empty list */
+                selected_montgomery_curve_list = single_curve + 1;
+            mbedtls_ecp_group_free( &grp );
+        }
+
+        for( curve_info = curve_list;
              curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
              curve_info++ )
         {
@@ -938,7 +985,7 @@
         }
 
         /* Montgomery curves need to be handled separately */
-        for ( curve_info = montgomery_curve_list;
+        for ( curve_info = selected_montgomery_curve_list;
               curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
               curve_info++ )
         {
@@ -960,7 +1007,7 @@
             mbedtls_mpi_free( &z );
         }
 
-        for( curve_info = mbedtls_ecp_curve_list();
+        for( curve_info = curve_list;
              curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
              curve_info++ )
         {
@@ -986,7 +1033,7 @@
         }
 
         /* Montgomery curves need to be handled separately */
-        for ( curve_info = montgomery_curve_list;
+        for ( curve_info = selected_montgomery_curve_list;
               curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
               curve_info++)
         {
@@ -1015,7 +1062,6 @@
     {
         mbedtls_ecdh_context ecdh_srv, ecdh_cli;
         unsigned char buf_srv[BUFSIZE], buf_cli[BUFSIZE];
-        const mbedtls_ecp_curve_info * curve_list = mbedtls_ecp_curve_list();
         const mbedtls_ecp_curve_info *curve_info;
         size_t olen;
 
diff --git a/third_party/mbedtls/repo/programs/test/cpp_dummy_build.cpp b/third_party/mbedtls/repo/programs/test/cpp_dummy_build.cpp
deleted file mode 100644
index c69cd2b..0000000
--- a/third_party/mbedtls/repo/programs/test/cpp_dummy_build.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- *  This program is a dummy C++ program to ensure Mbed TLS library header files
- *  can be included and built with a C++ compiler.
- *
- *  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.
- */
-
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
-
-#include "mbedtls/aes.h"
-#include "mbedtls/aesni.h"
-#include "mbedtls/arc4.h"
-#include "mbedtls/aria.h"
-#include "mbedtls/asn1.h"
-#include "mbedtls/asn1write.h"
-#include "mbedtls/base64.h"
-#include "mbedtls/bignum.h"
-#include "mbedtls/blowfish.h"
-#include "mbedtls/bn_mul.h"
-#include "mbedtls/camellia.h"
-#include "mbedtls/ccm.h"
-#include "mbedtls/certs.h"
-#include "mbedtls/chacha20.h"
-#include "mbedtls/chachapoly.h"
-#include "mbedtls/check_config.h"
-#include "mbedtls/cipher.h"
-#include "mbedtls/cipher_internal.h"
-#include "mbedtls/cmac.h"
-#include "mbedtls/compat-1.3.h"
-#include "mbedtls/ctr_drbg.h"
-#include "mbedtls/debug.h"
-#include "mbedtls/des.h"
-#include "mbedtls/dhm.h"
-#include "mbedtls/ecdh.h"
-#include "mbedtls/ecdsa.h"
-#include "mbedtls/ecjpake.h"
-#include "mbedtls/ecp.h"
-#include "mbedtls/ecp_internal.h"
-#include "mbedtls/entropy.h"
-#include "mbedtls/entropy_poll.h"
-#include "mbedtls/error.h"
-#include "mbedtls/gcm.h"
-#include "mbedtls/havege.h"
-#include "mbedtls/hkdf.h"
-#include "mbedtls/hmac_drbg.h"
-#include "mbedtls/md.h"
-#include "mbedtls/md2.h"
-#include "mbedtls/md4.h"
-#include "mbedtls/md5.h"
-#include "mbedtls/md_internal.h"
-#include "mbedtls/net.h"
-#include "mbedtls/net_sockets.h"
-#include "mbedtls/nist_kw.h"
-#include "mbedtls/oid.h"
-#include "mbedtls/padlock.h"
-#include "mbedtls/pem.h"
-#include "mbedtls/pk.h"
-#include "mbedtls/pk_internal.h"
-#include "mbedtls/pkcs11.h"
-#include "mbedtls/pkcs12.h"
-#include "mbedtls/pkcs5.h"
-#include "mbedtls/platform_time.h"
-#include "mbedtls/platform_util.h"
-#include "mbedtls/poly1305.h"
-#include "mbedtls/psa_util.h"
-#include "mbedtls/ripemd160.h"
-#include "mbedtls/rsa.h"
-#include "mbedtls/rsa_internal.h"
-#include "mbedtls/sha1.h"
-#include "mbedtls/sha256.h"
-#include "mbedtls/sha512.h"
-#include "mbedtls/ssl.h"
-#include "mbedtls/ssl_cache.h"
-#include "mbedtls/ssl_ciphersuites.h"
-#include "mbedtls/ssl_cookie.h"
-#include "mbedtls/ssl_internal.h"
-#include "mbedtls/ssl_ticket.h"
-#include "mbedtls/threading.h"
-#include "mbedtls/timing.h"
-#include "mbedtls/version.h"
-#include "mbedtls/x509.h"
-#include "mbedtls/x509_crl.h"
-#include "mbedtls/x509_crt.h"
-#include "mbedtls/x509_csr.h"
-#include "mbedtls/xtea.h"
-
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#endif
-
-#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-#include "mbedtls/memory_buffer_alloc.h"
-#endif
-
-#include "psa/crypto.h"
-#include "psa/crypto_se_driver.h"
-#include "psa/crypto_entropy_driver.h"
-#include "psa/crypto_accel_driver.h"
-#include "../library/psa_crypto_its.h"
-
-int main()
-{
-    mbedtls_platform_context *ctx = NULL;
-    mbedtls_platform_setup(ctx);
-    mbedtls_printf("CPP Build test\n");
-    mbedtls_platform_teardown(ctx);
-}
diff --git a/third_party/mbedtls/repo/programs/test/dlopen.c b/third_party/mbedtls/repo/programs/test/dlopen.c
new file mode 100644
index 0000000..2ee5316
--- /dev/null
+++ b/third_party/mbedtls/repo/programs/test/dlopen.c
@@ -0,0 +1,116 @@
+/*
+ *  Test dynamic loading of libmbed*
+ *
+ *  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.
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include "mbedtls/platform.h"
+#if !defined(MBEDTLS_PLATFORM_C)
+#include <stdio.h>
+#include <stdlib.h>
+#define mbedtls_fprintf    fprintf
+#define mbedtls_printf     printf
+#define mbedtls_exit       exit
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#include "mbedtls/x509_crt.h"
+#endif
+
+#if defined(__APPLE__)
+#define SO_SUFFIX ".dylib"
+#else
+#define SO_SUFFIX ".so"
+#endif
+
+#define CRYPTO_SO_FILENAME "libmbedcrypto" SO_SUFFIX
+#define X509_SO_FILENAME "libmbedx509" SO_SUFFIX
+#define TLS_SO_FILENAME "libmbedtls" SO_SUFFIX
+
+#include <dlfcn.h>
+
+#define CHECK_DLERROR( function, argument )                             \
+    do                                                                  \
+    {                                                                   \
+        char *CHECK_DLERROR_error = dlerror ( );                        \
+        if( CHECK_DLERROR_error != NULL )                               \
+        {                                                               \
+            fprintf( stderr, "Dynamic loading error for %s(%s): %s\n",  \
+                     function, argument, CHECK_DLERROR_error );         \
+            mbedtls_exit( MBEDTLS_EXIT_FAILURE );                       \
+        }                                                               \
+    }                                                                   \
+    while( 0 )
+
+int main( void )
+{
+#if defined(MBEDTLS_MD_C) || defined(MBEDTLS_SSL_TLS_C)
+    unsigned n;
+#endif
+
+#if defined(MBEDTLS_SSL_TLS_C)
+    void *tls_so = dlopen( TLS_SO_FILENAME, RTLD_NOW );
+    CHECK_DLERROR( "dlopen", TLS_SO_FILENAME );
+    const int *( *ssl_list_ciphersuites )( void ) =
+        dlsym( tls_so, "mbedtls_ssl_list_ciphersuites" );
+    CHECK_DLERROR( "dlsym", "mbedtls_ssl_list_ciphersuites" );
+    const int *ciphersuites = ssl_list_ciphersuites( );
+    for( n = 0; ciphersuites[n] != 0; n++ )
+        /* nothing to do, we're just counting */;
+    mbedtls_printf( "dlopen(%s): %u ciphersuites\n",
+                    TLS_SO_FILENAME, n );
+    dlclose( tls_so );
+    CHECK_DLERROR( "dlclose", TLS_SO_FILENAME );
+#endif  /* MBEDTLS_SSL_TLS_C */
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    void *x509_so = dlopen( X509_SO_FILENAME, RTLD_NOW );
+    CHECK_DLERROR( "dlopen", X509_SO_FILENAME );
+    const mbedtls_x509_crt_profile *profile =
+        dlsym( x509_so, "mbedtls_x509_crt_profile_default" );
+    CHECK_DLERROR( "dlsym", "mbedtls_x509_crt_profile_default" );
+    mbedtls_printf( "dlopen(%s): Allowed md mask: %08x\n",
+                    X509_SO_FILENAME, (unsigned) profile->allowed_mds );
+    dlclose( x509_so );
+    CHECK_DLERROR( "dlclose", X509_SO_FILENAME );
+#endif  /* MBEDTLS_X509_CRT_PARSE_C */
+
+#if defined(MBEDTLS_MD_C)
+    void *crypto_so = dlopen( CRYPTO_SO_FILENAME, RTLD_NOW );
+    CHECK_DLERROR( "dlopen", CRYPTO_SO_FILENAME );
+    const int *( *md_list )( void ) =
+        dlsym( crypto_so, "mbedtls_md_list" );
+    CHECK_DLERROR( "dlsym", "mbedtls_md_list" );
+    const int *mds = md_list( );
+    for( n = 0; mds[n] != 0; n++ )
+        /* nothing to do, we're just counting */;
+    mbedtls_printf( "dlopen(%s): %u hashes\n",
+                    CRYPTO_SO_FILENAME, n );
+    dlclose( crypto_so );
+    CHECK_DLERROR( "dlclose", CRYPTO_SO_FILENAME );
+#endif  /* MBEDTLS_MD_C */
+
+    return( 0 );
+}
+
diff --git a/third_party/mbedtls/repo/programs/test/dlopen_demo.sh b/third_party/mbedtls/repo/programs/test/dlopen_demo.sh
new file mode 100755
index 0000000..2dde3eb
--- /dev/null
+++ b/third_party/mbedtls/repo/programs/test/dlopen_demo.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+# Run the shared library dynamic loading demo program.
+# This is only expected to work when Mbed TLS is built as a shared 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.
+
+set -e -u
+
+program_dir="${0%/*}"
+program="$program_dir/dlopen"
+top_dir="$program_dir/../.."
+library_dir="$top_dir/library"
+
+# ELF-based Unix-like (Linux, *BSD, Solaris, ...)
+if [ -n "${LD_LIBRARY_PATH-}" ]; then
+    LD_LIBRARY_PATH="$library_dir:$LD_LIBRARY_PATH"
+else
+    LD_LIBRARY_PATH="$library_dir"
+fi
+export LD_LIBRARY_PATH
+
+# OSX/macOS
+if [ -n "${DYLD_LIBRARY_PATH-}" ]; then
+    DYLD_LIBRARY_PATH="$library_dir:$DYLD_LIBRARY_PATH"
+else
+    DYLD_LIBRARY_PATH="$library_dir"
+fi
+export DYLD_LIBRARY_PATH
+
+echo "Running dynamic loading test program: $program"
+echo "Loading libraries from: $library_dir"
+"$program"
diff --git a/third_party/mbedtls/repo/programs/test/generate_cpp_dummy_build.sh b/third_party/mbedtls/repo/programs/test/generate_cpp_dummy_build.sh
new file mode 100755
index 0000000..90a181d
--- /dev/null
+++ b/third_party/mbedtls/repo/programs/test/generate_cpp_dummy_build.sh
@@ -0,0 +1,97 @@
+#!/bin/sh
+
+DEFAULT_OUTPUT_FILE=programs/test/cpp_dummy_build.cpp
+
+if [ "$1" = "--help" ]; then
+    cat <<EOF
+Usage: $0 [OUTPUT]
+Generate a C++ dummy build program that includes all the headers.
+OUTPUT defaults to "programs/test/cpp_dummy_build.cpp".
+Run this program from the root of an Mbed TLS directory tree or from
+its "programs" or "programs/test" subdirectory.
+EOF
+    exit
+fi
+
+# 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.
+
+set -e
+
+# Ensure a reproducible order for *.h
+export LC_ALL=C
+
+print_cpp () {
+    cat <<'EOF'
+/* Automatically generated file. Do not edit.
+ *
+ *  This program is a dummy C++ program to ensure Mbed TLS library header files
+ *  can be included and built with a C++ compiler.
+ *
+ *  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 "mbedtls/config.h"
+
+EOF
+
+  for header in include/mbedtls/*.h include/psa/*.h; do
+    case ${header#include/} in
+      psa/crypto_config.h) :;; # not meant for direct inclusion
+      # Some of the psa/crypto_*.h headers are not meant to be included directly.
+      # They do have include guards that make them no-ops if psa/crypto.h
+      # has been included before. Since psa/crypto.h comes before psa/crypto_*.h
+      # in the wildcard enumeration, we don't need to skip those headers.
+      *) echo "#include \"${header#include/}\"";;
+    esac
+  done
+
+    cat <<'EOF'
+
+int main()
+{
+    mbedtls_platform_context *ctx = NULL;
+    mbedtls_platform_setup(ctx);
+    mbedtls_printf("CPP Build test passed\n");
+    mbedtls_platform_teardown(ctx);
+}
+EOF
+}
+
+if [ -d include/mbedtls ]; then
+    :
+elif [ -d ../include/mbedtls ]; then
+    cd ..
+elif [ -d ../../include/mbedtls ]; then
+    cd ../..
+else
+    echo >&2 "This script must be run from an Mbed TLS source tree."
+    exit 3
+fi
+
+print_cpp >"${1:-$DEFAULT_OUTPUT_FILE}"
diff --git a/third_party/mbedtls/repo/programs/test/query_compile_time_config.c b/third_party/mbedtls/repo/programs/test/query_compile_time_config.c
index abe8f76..0e356c8 100644
--- a/third_party/mbedtls/repo/programs/test/query_compile_time_config.c
+++ b/third_party/mbedtls/repo/programs/test/query_compile_time_config.c
@@ -40,7 +40,7 @@
     "Mbed TLS build and the macro expansion of that configuration will be\n" \
     "printed (if any). Otherwise, 1 will be returned.\n"
 
-int query_config( const char *config );
+#include "query_config.h"
 
 int main( int argc, char *argv[] )
 {
diff --git a/third_party/mbedtls/repo/programs/test/query_config.c b/third_party/mbedtls/repo/programs/test/query_config.c
index 1345b11..5dfe383 100644
--- a/third_party/mbedtls/repo/programs/test/query_config.c
+++ b/third_party/mbedtls/repo/programs/test/query_config.c
@@ -23,6 +23,8 @@
 #include MBEDTLS_CONFIG_FILE
 #endif
 
+#include "query_config.h"
+
 #if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
 #else
@@ -656,6 +658,14 @@
     }
 #endif /* MBEDTLS_ECP_INTERNAL_ALT */
 
+#if defined(MBEDTLS_ECP_NO_FALLBACK)
+    if( strcmp( "MBEDTLS_ECP_NO_FALLBACK", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_NO_FALLBACK );
+        return( 0 );
+    }
+#endif /* MBEDTLS_ECP_NO_FALLBACK */
+
 #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
     if( strcmp( "MBEDTLS_ECP_RANDOMIZE_JAC_ALT", config ) == 0 )
     {
@@ -760,6 +770,14 @@
     }
 #endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */
 
+#if defined(MBEDTLS_CHECK_RETURN_WARNING)
+    if( strcmp( "MBEDTLS_CHECK_RETURN_WARNING", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_CHECK_RETURN_WARNING );
+        return( 0 );
+    }
+#endif /* MBEDTLS_CHECK_RETURN_WARNING */
+
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     if( strcmp( "MBEDTLS_CIPHER_MODE_CBC", config ) == 0 )
     {
@@ -1216,6 +1234,22 @@
     }
 #endif /* MBEDTLS_PKCS1_V21 */
 
+#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
+    if( strcmp( "MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS );
+        return( 0 );
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
+
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+    if( strcmp( "MBEDTLS_PSA_CRYPTO_CLIENT", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_CRYPTO_CLIENT );
+        return( 0 );
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
+
 #if defined(MBEDTLS_PSA_CRYPTO_DRIVERS)
     if( strcmp( "MBEDTLS_PSA_CRYPTO_DRIVERS", config ) == 0 )
     {
@@ -1224,6 +1258,14 @@
     }
 #endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */
 
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+    if( strcmp( "MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG );
+        return( 0 );
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
 #if defined(MBEDTLS_PSA_CRYPTO_SPM)
     if( strcmp( "MBEDTLS_PSA_CRYPTO_SPM", config ) == 0 )
     {
@@ -2608,6 +2650,38 @@
     }
 #endif /* MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO */
 
+#if defined(MBEDTLS_CHECK_RETURN)
+    if( strcmp( "MBEDTLS_CHECK_RETURN", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_CHECK_RETURN );
+        return( 0 );
+    }
+#endif /* MBEDTLS_CHECK_RETURN */
+
+#if defined(MBEDTLS_IGNORE_RETURN)
+    if( strcmp( "MBEDTLS_IGNORE_RETURN", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_IGNORE_RETURN );
+        return( 0 );
+    }
+#endif /* MBEDTLS_IGNORE_RETURN */
+
+#if defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE)
+    if( strcmp( "MBEDTLS_PSA_HMAC_DRBG_MD_TYPE", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_HMAC_DRBG_MD_TYPE );
+        return( 0 );
+    }
+#endif /* MBEDTLS_PSA_HMAC_DRBG_MD_TYPE */
+
+#if defined(MBEDTLS_PSA_KEY_SLOT_COUNT)
+    if( strcmp( "MBEDTLS_PSA_KEY_SLOT_COUNT", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_KEY_SLOT_COUNT );
+        return( 0 );
+    }
+#endif /* MBEDTLS_PSA_KEY_SLOT_COUNT */
+
 #if defined(MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT)
     if( strcmp( "MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT", config ) == 0 )
     {
@@ -2712,6 +2786,14 @@
     }
 #endif /* MBEDTLS_SSL_COOKIE_TIMEOUT */
 
+#if defined(MBEDTLS_TLS_EXT_CID)
+    if( strcmp( "MBEDTLS_TLS_EXT_CID", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_TLS_EXT_CID );
+        return( 0 );
+    }
+#endif /* MBEDTLS_TLS_EXT_CID */
+
 #if defined(MBEDTLS_X509_MAX_INTERMEDIATE_CA)
     if( strcmp( "MBEDTLS_X509_MAX_INTERMEDIATE_CA", config ) == 0 )
     {
@@ -2728,14 +2810,6 @@
     }
 #endif /* MBEDTLS_X509_MAX_FILE_PATH_LEN */
 
-#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES)
-    if( strcmp( "MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES", config ) == 0 )
-    {
-        MACRO_EXPANSION_TO_STR( MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES );
-        return( 0 );
-    }
-#endif /* MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES */
-
 #if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE)
     if( strcmp( "MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE", config ) == 0 )
     {
diff --git a/third_party/mbedtls/repo/programs/test/query_config.h b/third_party/mbedtls/repo/programs/test/query_config.h
new file mode 100644
index 0000000..23009c4
--- /dev/null
+++ b/third_party/mbedtls/repo/programs/test/query_config.h
@@ -0,0 +1,42 @@
+/*
+ *  Query Mbed TLS compile time configurations from config.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.
+ */
+
+#ifndef MBEDTLS_PROGRAMS_TEST_QUERY_CONFIG_H
+#define MBEDTLS_PROGRAMS_TEST_QUERY_CONFIG_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+/** Check whether a given configuration symbol is enabled.
+ *
+ * \param config    The symbol to query (e.g. "MBEDTLS_RSA_C").
+ * \return          \c 0 if the symbol was defined at compile time
+ *                  (in MBEDTLS_CONFIG_FILE or config.h),
+ *                  \c 1 otherwise.
+ *
+ * \note            This function is defined in `programs/test/query_config.c`
+ *                  which is automatically generated by
+ *                  `scripts/generate_query_config.pl`.
+ */
+int query_config( const char *config );
+
+#endif /* MBEDTLS_PROGRAMS_TEST_QUERY_CONFIG_H */
diff --git a/third_party/mbedtls/repo/programs/test/udp_proxy.c b/third_party/mbedtls/repo/programs/test/udp_proxy.c
index 0b1bfd7..11fe9bf 100644
--- a/third_party/mbedtls/repo/programs/test/udp_proxy.c
+++ b/third_party/mbedtls/repo/programs/test/udp_proxy.c
@@ -683,26 +683,21 @@
 }
 
 /*
- * Avoid dropping or delaying a packet that was already dropped twice: this
- * only results in uninteresting timeouts. We can't rely on type to identify
- * packets, since during renegotiation they're all encrypted.  So, rely on
- * size mod 2048 (which is usually just size).
- */
-static unsigned char dropped[2048] = { 0 };
-#define DROP_MAX 2
-
-/* We only drop packets at the level of entire datagrams, not at the level
+ * Avoid dropping or delaying a packet that was already dropped or delayed
+ * ("held") twice: this only results in uninteresting timeouts. We can't rely
+ * on type to identify packets, since during renegotiation they're all
+ * encrypted. So, rely on size mod 2048 (which is usually just size).
+ *
+ * We only hold packets at the level of entire datagrams, not at the level
  * of records. In particular, if the peer changes the way it packs multiple
  * records into a single datagram, we don't necessarily count the number of
- * times a record has been dropped correctly. However, the only known reason
+ * times a record has been held correctly. However, the only known reason
  * why a peer would change datagram packing is disabling the latter on
- * retransmission, in which case we'd drop involved records at most
- * DROP_MAX + 1 times. */
-void update_dropped( const packet *p )
-{
-    size_t id = p->len % sizeof( dropped );
-    ++dropped[id];
-}
+ * retransmission, in which case we'd hold involved records at most
+ * HOLD_MAX + 1 times.
+ */
+static unsigned char held[2048] = { 0 };
+#define HOLD_MAX 2
 
 int handle_message( const char *way,
                     mbedtls_net_context *dst,
@@ -729,7 +724,7 @@
     cur.dst  = dst;
     print_packet( &cur, NULL );
 
-    id = cur.len % sizeof( dropped );
+    id = cur.len % sizeof( held );
 
     if( strcmp( way, "S <- C" ) == 0 )
     {
@@ -771,10 +766,10 @@
           ! ( opt.protect_hvr &&
               strcmp( cur.type, "HelloVerifyRequest" ) == 0 ) &&
           cur.len != (size_t) opt.protect_len &&
-          dropped[id] < DROP_MAX &&
+          held[id] < HOLD_MAX &&
           rand() % opt.drop == 0 ) )
     {
-        update_dropped( &cur );
+        ++held[id];
     }
     else if( ( opt.delay_ccs == 1 &&
                strcmp( cur.type, "ChangeCipherSpec" ) == 0 ) ||
@@ -784,9 +779,10 @@
                ! ( opt.protect_hvr &&
                    strcmp( cur.type, "HelloVerifyRequest" ) == 0 ) &&
                cur.len != (size_t) opt.protect_len &&
-               dropped[id] < DROP_MAX &&
+               held[id] < HOLD_MAX &&
                rand() % opt.delay == 0 ) )
     {
+        ++held[id];
         delay_packet( &cur );
     }
     else
@@ -897,7 +893,7 @@
      * 3. Forward packets forever (kill the process to terminate it)
      */
     clear_pending();
-    memset( dropped, 0, sizeof( dropped ) );
+    memset( held, 0, sizeof( held ) );
 
     nb_fds = client_fd.fd;
     if( nb_fds < server_fd.fd )
@@ -1005,8 +1001,8 @@
 
     for( delay_idx = 0; delay_idx < MAX_DELAYED_HS; delay_idx++ )
     {
-        mbedtls_free( opt.delay_cli + delay_idx );
-        mbedtls_free( opt.delay_srv + delay_idx );
+        mbedtls_free( opt.delay_cli[delay_idx] );
+        mbedtls_free( opt.delay_srv[delay_idx] );
     }
 
     mbedtls_net_free( &client_fd );
diff --git a/third_party/mbedtls/repo/programs/x509/CMakeLists.txt b/third_party/mbedtls/repo/programs/x509/CMakeLists.txt
index 29cbeb8..5b1c319 100644
--- a/third_party/mbedtls/repo/programs/x509/CMakeLists.txt
+++ b/third_party/mbedtls/repo/programs/x509/CMakeLists.txt
@@ -15,6 +15,7 @@
     cert_req
     cert_write
     crl_app
+    load_roots
     req_app
 )
 
diff --git a/third_party/mbedtls/repo/programs/x509/load_roots.c b/third_party/mbedtls/repo/programs/x509/load_roots.c
new file mode 100644
index 0000000..6a40949
--- /dev/null
+++ b/third_party/mbedtls/repo/programs/x509/load_roots.c
@@ -0,0 +1,217 @@
+/*
+ *  Root CA reading application
+ *
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ *
+ *  This file is provided under the Apache License 2.0, or the
+ *  GNU General Public License v2.0 or later.
+ *
+ *  **********
+ *  Apache License 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.
+ *
+ *  **********
+ *
+ *  **********
+ *  GNU General Public License v2.0 or later:
+ *
+ *  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.
+ *
+ *  **********
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#define mbedtls_time            time
+#define mbedtls_time_t          time_t
+#define mbedtls_fprintf         fprintf
+#define mbedtls_printf          printf
+#define mbedtls_exit            exit
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
+
+#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) ||  \
+    !defined(MBEDTLS_TIMING_C)
+int main( void )
+{
+    mbedtls_printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_FS_IO and/or "
+           "MBEDTLS_TIMING_C not defined.\n");
+    mbedtls_exit( 0 );
+}
+#else
+
+#include "mbedtls/error.h"
+#include "mbedtls/timing.h"
+#include "mbedtls/x509_crt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define DFL_ITERATIONS          1
+#define DFL_PRIME_CACHE         1
+
+#define USAGE \
+    "\n usage: load_roots param=<>... [--] FILE...\n"   \
+    "\n acceptable parameters:\n"                       \
+    "    iterations=%%d        Iteration count (not including cache priming); default: 1\n"  \
+    "    prime=%%d             Prime the disk read cache? Default: 1 (yes)\n"  \
+    "\n"
+
+
+/*
+ * global options
+ */
+struct options
+{
+    const char **filenames;     /* NULL-terminated list of file names */
+    unsigned iterations;        /* Number of iterations to time */
+    int prime_cache;            /* Prime the disk read cache? */
+} opt;
+
+
+int read_certificates( const char *const *filenames )
+{
+    mbedtls_x509_crt cas;
+    int ret = 0;
+    const char *const *cur;
+
+    mbedtls_x509_crt_init( &cas );
+
+    for( cur = filenames; *cur != NULL; cur++ )
+    {
+        ret = mbedtls_x509_crt_parse_file( &cas, *cur );
+        if( ret != 0 )
+        {
+#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
+            char error_message[200];
+            mbedtls_strerror( ret, error_message, sizeof( error_message ) );
+            printf( "\n%s: -0x%04x (%s)\n",
+                    *cur, (unsigned) -ret, error_message );
+#else
+            printf( "\n%s: -0x%04x\n",
+                    *cur, (unsigned) -ret );
+#endif
+            goto exit;
+        }
+    }
+
+exit:
+    mbedtls_x509_crt_free( &cas );
+    return( ret == 0 );
+}
+
+int main( int argc, char *argv[] )
+{
+    int exit_code = MBEDTLS_EXIT_FAILURE;
+    unsigned i, j;
+    struct mbedtls_timing_hr_time timer;
+    unsigned long ms;
+
+    if( argc <= 1 )
+    {
+        mbedtls_printf( USAGE );
+        goto exit;
+    }
+
+    opt.filenames = NULL;
+    opt.iterations = DFL_ITERATIONS;
+    opt.prime_cache = DFL_PRIME_CACHE;
+
+    for( i = 1; i < (unsigned) argc; i++ )
+    {
+        char *p = argv[i];
+        char *q = NULL;
+
+        if( strcmp( p, "--" ) == 0 )
+            break;
+        if( ( q = strchr( p, '=' ) ) == NULL )
+            break;
+        *q++ = '\0';
+
+        for( j = 0; p + j < q; j++ )
+        {
+            if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' )
+                argv[i][j] |= 0x20;
+        }
+
+        if( strcmp( p, "iterations" ) == 0 )
+        {
+            opt.iterations = atoi( q );
+        }
+        else if( strcmp( p, "prime" ) == 0 )
+        {
+            opt.iterations = atoi( q ) != 0;
+        }
+        else
+        {
+            mbedtls_printf( "Unknown option: %s\n", p );
+            mbedtls_printf( USAGE );
+            goto exit;
+        }
+    }
+
+    opt.filenames = (const char**) argv + i;
+    if( *opt.filenames == 0 )
+    {
+        mbedtls_printf( "Missing list of certificate files to parse\n" );
+        goto exit;
+    }
+
+    mbedtls_printf( "Parsing %u certificates", argc - i );
+    if( opt.prime_cache )
+    {
+        if( ! read_certificates( opt.filenames ) )
+            goto exit;
+        mbedtls_printf( " " );
+    }
+
+    (void) mbedtls_timing_get_timer( &timer, 1 );
+    for( i = 1; i <= opt.iterations; i++ )
+    {
+        if( ! read_certificates( opt.filenames ) )
+            goto exit;
+        mbedtls_printf( "." );
+    }
+    ms = mbedtls_timing_get_timer( &timer, 0 );
+    mbedtls_printf( "\n%u iterations -> %lu ms\n", opt.iterations, ms );
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
+exit:
+    mbedtls_exit( exit_code );
+}
+#endif /* necessary configuration */
diff --git a/third_party/mbedtls/repo/scripts/assemble_changelog.py b/third_party/mbedtls/repo/scripts/assemble_changelog.py
index 8f7d1fd..56d6c37 100755
--- a/third_party/mbedtls/repo/scripts/assemble_changelog.py
+++ b/third_party/mbedtls/repo/scripts/assemble_changelog.py
@@ -74,6 +74,9 @@
     b'Changes',
 )
 
+# The maximum line length for an entry
+MAX_LINE_LENGTH = 80
+
 CategoryContent = namedtuple('CategoryContent', [
     'name', 'title_line', # Title text and line number of the title
     'body', 'body_line', # Body text and starting line number of the body
@@ -198,6 +201,8 @@
     # a version that is not yet released. Something like "3.1a" is accepted.
     _version_number_re = re.compile(br'[0-9]+\.[0-9A-Za-z.]+')
     _incomplete_version_number_re = re.compile(br'.*\.[A-Za-z]')
+    _only_url_re = re.compile(br'^\s*\w+://\S+\s*$')
+    _has_url_re = re.compile(br'.*://.*')
 
     def add_categories_from_text(self, filename, line_offset,
                                  text, allow_unknown_category):
@@ -214,6 +219,21 @@
                                        line_offset + category.title_line,
                                        'Unknown category: "{}"',
                                        category.name.decode('utf8'))
+
+            body_split = category.body.splitlines()
+
+            for line_number, line in enumerate(body_split, 1):
+                if not self._only_url_re.match(line) and \
+                   len(line) > MAX_LINE_LENGTH:
+                    long_url_msg = '. URL exceeding length limit must be alone in its line.' \
+                        if self._has_url_re.match(line) else ""
+                    raise InputFormatError(filename,
+                                           category.body_line + line_number,
+                                           'Line is longer than allowed: '
+                                           'Length {} (Max {}){}',
+                                           len(line), MAX_LINE_LENGTH,
+                                           long_url_msg)
+
             self.categories[category.name] += category.body
 
     def __init__(self, input_stream, changelog_format):
diff --git a/third_party/mbedtls/repo/scripts/ci.requirements.txt b/third_party/mbedtls/repo/scripts/ci.requirements.txt
new file mode 100644
index 0000000..18b40ec
--- /dev/null
+++ b/third_party/mbedtls/repo/scripts/ci.requirements.txt
@@ -0,0 +1,10 @@
+# Python package requirements for Mbed TLS testing.
+
+# Use a known version of Pylint, because new versions tend to add warnings
+# that could start rejecting our code.
+# 2.4.4 is the version in Ubuntu 20.04. It supports Python >=3.5.
+pylint == 2.4.4
+
+# Use the earliest version of mypy that works with our code base.
+# See https://github.com/ARMmbed/mbedtls/pull/3953 .
+mypy >= 0.780
diff --git a/third_party/mbedtls/repo/scripts/config.py b/third_party/mbedtls/repo/scripts/config.py
index ae0614a..01f570e 100755
--- a/third_party/mbedtls/repo/scripts/config.py
+++ b/third_party/mbedtls/repo/scripts/config.py
@@ -171,6 +171,7 @@
     'MBEDTLS_DEPRECATED_REMOVED', # conflicts with deprecated options
     'MBEDTLS_DEPRECATED_WARNING', # conflicts with deprecated options
     'MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED', # influences the use of ECDH in TLS
+    'MBEDTLS_ECP_NO_FALLBACK', # removes internal ECP implementation
     'MBEDTLS_ECP_NO_INTERNAL_RNG', # removes a feature
     'MBEDTLS_ECP_RESTARTABLE', # incompatible with USE_PSA_CRYPTO
     'MBEDTLS_ENTROPY_FORCE_SHA256', # interacts with CTR_DRBG_128_BIT_KEY
@@ -185,6 +186,7 @@
     'MBEDTLS_PKCS11_C', # build dependency (libpkcs11-helper)
     'MBEDTLS_PLATFORM_NO_STD_FUNCTIONS', # removes a feature
     'MBEDTLS_PSA_CRYPTO_CONFIG', # toggles old/new style PSA config
+    'MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG', # behavior change + build dependency
     'MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER', # incompatible with USE_PSA_CRYPTO
     'MBEDTLS_PSA_CRYPTO_SPM', # platform dependency (PSA SPM)
     'MBEDTLS_PSA_INJECT_ENTROPY', # build dependency (hook functions)
diff --git a/third_party/mbedtls/repo/scripts/data_files/error.fmt b/third_party/mbedtls/repo/scripts/data_files/error.fmt
index 9e479bb..3be94bd 100644
--- a/third_party/mbedtls/repo/scripts/data_files/error.fmt
+++ b/third_party/mbedtls/repo/scripts/data_files/error.fmt
@@ -162,4 +162,8 @@
 
 #endif /* MBEDTLS_ERROR_C */
 
+#if defined(MBEDTLS_TEST_HOOKS)
+void (*mbedtls_test_hook_error_add)( int, int, const char *, int );
+#endif
+
 #endif /* MBEDTLS_ERROR_C || MBEDTLS_ERROR_STRERROR_DUMMY */
diff --git a/third_party/mbedtls/repo/scripts/data_files/query_config.fmt b/third_party/mbedtls/repo/scripts/data_files/query_config.fmt
index be1faef..be541cb 100644
--- a/third_party/mbedtls/repo/scripts/data_files/query_config.fmt
+++ b/third_party/mbedtls/repo/scripts/data_files/query_config.fmt
@@ -23,6 +23,8 @@
 #include MBEDTLS_CONFIG_FILE
 #endif
 
+#include "query_config.h"
+
 #if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
 #else
diff --git a/third_party/mbedtls/repo/scripts/data_files/vs2010-app-template.vcxproj b/third_party/mbedtls/repo/scripts/data_files/vs2010-app-template.vcxproj
index 1771960..039fd09 100644
--- a/third_party/mbedtls/repo/scripts/data_files/vs2010-app-template.vcxproj
+++ b/third_party/mbedtls/repo/scripts/data_files/vs2010-app-template.vcxproj
@@ -1,171 +1,171 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <SOURCES>
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid><GUID></ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace><APPNAME></RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-INCLUDE_DIRECTORIES
-      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-INCLUDE_DIRECTORIES
-      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-INCLUDE_DIRECTORIES
-      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-INCLUDE_DIRECTORIES
-      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <SOURCES>

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid><GUID></ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace><APPNAME></RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+INCLUDE_DIRECTORIES

+      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+INCLUDE_DIRECTORIES

+      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+INCLUDE_DIRECTORIES

+      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+INCLUDE_DIRECTORIES

+      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/scripts/data_files/vs2010-main-template.vcxproj b/third_party/mbedtls/repo/scripts/data_files/vs2010-main-template.vcxproj
index 8f1d060..c0f3a3c 100644
--- a/third_party/mbedtls/repo/scripts/data_files/vs2010-main-template.vcxproj
+++ b/third_party/mbedtls/repo/scripts/data_files/vs2010-main-template.vcxproj
@@ -1,156 +1,156 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{46CF2D25-6A36-4189-B59C-E4815388E554}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>mbedTLS</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>_USRDLL;MBEDTLS_EXPORTS;KRML_VERIFIED_UINT128;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-INCLUDE_DIRECTORIES
-      </AdditionalIncludeDirectories>
-      <CompileAs>CompileAsC</CompileAs>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>_USRDLL;MBEDTLS_EXPORTS;KRML_VERIFIED_UINT128;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-INCLUDE_DIRECTORIES
-      </AdditionalIncludeDirectories>
-      <CompileAs>CompileAsC</CompileAs>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;_USRDLL;MBEDTLS_EXPORTS;KRML_VERIFIED_UINT128;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-INCLUDE_DIRECTORIES
-      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;MBEDTLS_EXPORTS;KRML_VERIFIED_UINT128;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-INCLUDE_DIRECTORIES
-      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-HEADER_ENTRIES
-  </ItemGroup>
-  <ItemGroup>
-SOURCE_ENTRIES
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{46CF2D25-6A36-4189-B59C-E4815388E554}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>mbedTLS</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>_USRDLL;MBEDTLS_EXPORTS;KRML_VERIFIED_UINT128;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+INCLUDE_DIRECTORIES

+      </AdditionalIncludeDirectories>

+      <CompileAs>CompileAsC</CompileAs>

+    </ClCompile>

+    <Link>

+      <SubSystem>Windows</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>_USRDLL;MBEDTLS_EXPORTS;KRML_VERIFIED_UINT128;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+INCLUDE_DIRECTORIES

+      </AdditionalIncludeDirectories>

+      <CompileAs>CompileAsC</CompileAs>

+    </ClCompile>

+    <Link>

+      <SubSystem>Windows</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;_USRDLL;MBEDTLS_EXPORTS;KRML_VERIFIED_UINT128;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+INCLUDE_DIRECTORIES

+      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Windows</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;MBEDTLS_EXPORTS;KRML_VERIFIED_UINT128;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+INCLUDE_DIRECTORIES

+      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Windows</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+HEADER_ENTRIES

+  </ItemGroup>

+  <ItemGroup>

+SOURCE_ENTRIES

+  </ItemGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/scripts/data_files/vs2010-sln-template.sln b/third_party/mbedtls/repo/scripts/data_files/vs2010-sln-template.sln
index 1c7ad2b..fc65a0b 100644
--- a/third_party/mbedtls/repo/scripts/data_files/vs2010-sln-template.sln
+++ b/third_party/mbedtls/repo/scripts/data_files/vs2010-sln-template.sln
@@ -1,28 +1,28 @@
-
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual C++ Express 2010
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mbedTLS", "mbedTLS.vcxproj", "{46CF2D25-6A36-4189-B59C-E4815388E554}"
-EndProject
-APP_ENTRIES
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Win32 = Debug|Win32
-		Debug|x64 = Debug|x64
-		Release|Win32 = Release|Win32
-		Release|x64 = Release|x64
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|Win32.ActiveCfg = Debug|Win32
-		{46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|Win32.Build.0 = Debug|Win32
-		{46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|x64.ActiveCfg = Debug|x64
-		{46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|x64.Build.0 = Debug|x64
-		{46CF2D25-6A36-4189-B59C-E4815388E554}.Release|Win32.ActiveCfg = Release|Win32
-		{46CF2D25-6A36-4189-B59C-E4815388E554}.Release|Win32.Build.0 = Release|Win32
-		{46CF2D25-6A36-4189-B59C-E4815388E554}.Release|x64.ActiveCfg = Release|x64
-		{46CF2D25-6A36-4189-B59C-E4815388E554}.Release|x64.Build.0 = Release|x64
-CONF_ENTRIES
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-EndGlobal
+

+Microsoft Visual Studio Solution File, Format Version 11.00

+# Visual C++ Express 2010

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mbedTLS", "mbedTLS.vcxproj", "{46CF2D25-6A36-4189-B59C-E4815388E554}"

+EndProject

+APP_ENTRIES

+Global

+	GlobalSection(SolutionConfigurationPlatforms) = preSolution

+		Debug|Win32 = Debug|Win32

+		Debug|x64 = Debug|x64

+		Release|Win32 = Release|Win32

+		Release|x64 = Release|x64

+	EndGlobalSection

+	GlobalSection(ProjectConfigurationPlatforms) = postSolution

+		{46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|Win32.ActiveCfg = Debug|Win32

+		{46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|Win32.Build.0 = Debug|Win32

+		{46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|x64.ActiveCfg = Debug|x64

+		{46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|x64.Build.0 = Debug|x64

+		{46CF2D25-6A36-4189-B59C-E4815388E554}.Release|Win32.ActiveCfg = Release|Win32

+		{46CF2D25-6A36-4189-B59C-E4815388E554}.Release|Win32.Build.0 = Release|Win32

+		{46CF2D25-6A36-4189-B59C-E4815388E554}.Release|x64.ActiveCfg = Release|x64

+		{46CF2D25-6A36-4189-B59C-E4815388E554}.Release|x64.Build.0 = Release|x64

+CONF_ENTRIES

+	EndGlobalSection

+	GlobalSection(SolutionProperties) = preSolution

+		HideSolutionNode = FALSE

+	EndGlobalSection

+EndGlobal

diff --git a/third_party/mbedtls/repo/scripts/generate_errors.pl b/third_party/mbedtls/repo/scripts/generate_errors.pl
index ed17a0d..65383fa 100755
--- a/third_party/mbedtls/repo/scripts/generate_errors.pl
+++ b/third_party/mbedtls/repo/scripts/generate_errors.pl
@@ -21,6 +21,7 @@
 # limitations under the License.
 
 use strict;
+use warnings;
 
 my ($include_dir, $data_dir, $error_file);
 
@@ -53,26 +54,54 @@
                              PEM PK PKCS12 PKCS5
                              RSA SSL X509 );
 
-my $line_separator = $/;
 undef $/;
 
 open(FORMAT_FILE, "$error_format_file") or die "Opening error format file '$error_format_file': $!";
 my $error_format = <FORMAT_FILE>;
 close(FORMAT_FILE);
 
-$/ = $line_separator;
-
 my @files = <$include_dir/*.h>;
 my @necessary_include_files;
 my @matches;
 foreach my $file (@files) {
     open(FILE, "$file");
-    my @grep_res = grep(/^\s*#define\s+MBEDTLS_ERR_\w+\s+\-0x[0-9A-Fa-f]+/, <FILE>);
-    push(@matches, @grep_res);
+    my $content = <FILE>;
     close FILE;
-    my $include_name = $file;
-    $include_name =~ s!.*/!!;
-    push @necessary_include_files, $include_name if @grep_res;
+    my $found = 0;
+    while ($content =~ m[
+            # Both the before-comment and the after-comment are optional.
+            # Only the comment content is a regex capture group. The comment
+            # start and end parts are outside the capture group.
+            (?:/\*[*!](?!<)             # Doxygen before-comment start
+                ((?:[^*]|\*+[^*/])*)    # $1: Comment content (no */ inside)
+                \*/)?                   # Comment end
+            \s*\#\s*define\s+(MBEDTLS_ERR_\w+)  # $2: name
+            \s+\-(0[Xx][0-9A-Fa-f]+)\s*         # $3: value (without the sign)
+            (?:/\*[*!]<                 # Doxygen after-comment start
+                ((?:[^*]|\*+[^*/])*)    # $4: Comment content (no */ inside)
+                \*/)?                   # Comment end
+    ]gsx) {
+        my ($before, $name, $value, $after) = ($1, $2, $3, $4);
+        # Discard Doxygen comments that are coincidentally present before
+        # an error definition but not attached to it. This is ad hoc, based
+        # on what actually matters (or mattered at some point).
+        undef $before if defined($before) && $before =~ /\s*\\name\s/s;
+        die "Description neither before nor after $name in $file\n"
+          if !defined($before) && !defined($after);
+        die "Description both before and after $name in $file\n"
+          if defined($before) && defined($after);
+        my $description = (defined($before) ? $before : $after);
+        $description =~ s/^\s+//;
+        $description =~ s/\n( *\*)? */ /g;
+        $description =~ s/\.?\s+$//;
+        push @matches, [$name, $value, $description];
+        ++$found;
+    }
+    if ($found) {
+        my $include_name = $file;
+        $include_name =~ s!.*/!!;
+        push @necessary_include_files, $include_name;
+    }
 }
 
 my $ll_old_define = "";
@@ -86,20 +115,14 @@
 
 my %error_codes_seen;
 
-foreach my $line (@matches)
+foreach my $match (@matches)
 {
-    next if ($line =~ /compat-1.2.h/);
-    my ($error_name, $error_code) = $line =~ /(MBEDTLS_ERR_\w+)\s+\-(0x\w+)/;
-    my ($description) = $line =~ /\/\*\*< (.*?)\.? \*\//;
+    my ($error_name, $error_code, $description) = @$match;
 
     die "Duplicated error code: $error_code ($error_name)\n"
         if( $error_codes_seen{$error_code}++ );
 
     $description =~ s/\\/\\\\/g;
-    if ($description eq "") {
-        $description = "DESCRIPTION MISSING";
-        warn "Missing description for $error_name\n";
-    }
 
     my ($module_name) = $error_name =~ /^MBEDTLS_ERR_([^_]+)/;
 
diff --git a/third_party/mbedtls/repo/scripts/generate_psa_constants.py b/third_party/mbedtls/repo/scripts/generate_psa_constants.py
index 01d3e3a..71afd02 100755
--- a/third_party/mbedtls/repo/scripts/generate_psa_constants.py
+++ b/third_party/mbedtls/repo/scripts/generate_psa_constants.py
@@ -27,9 +27,10 @@
 # limitations under the License.
 
 import os
-import re
 import sys
 
+from mbedtls_dev import macro_collector
+
 OUTPUT_TEMPLATE = '''\
 /* Automatically generated by generate_psa_constant.py. DO NOT EDIT. */
 
@@ -99,20 +100,28 @@
     unsigned long length_modifier = NO_LENGTH_MODIFIER;
     if (PSA_ALG_IS_MAC(alg)) {
         core_alg = PSA_ALG_TRUNCATED_MAC(alg, 0);
-        if (core_alg != alg) {
+        if (alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(", 33);
+            length_modifier = PSA_MAC_TRUNCATED_LENGTH(alg);
+        } else if (core_alg != alg) {
             append(&buffer, buffer_size, &required_size,
                    "PSA_ALG_TRUNCATED_MAC(", 22);
             length_modifier = PSA_MAC_TRUNCATED_LENGTH(alg);
         }
     } else if (PSA_ALG_IS_AEAD(alg)) {
-        core_alg = PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(alg);
+        core_alg = PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg);
         if (core_alg == 0) {
             /* For unknown AEAD algorithms, there is no "default tag length". */
             core_alg = alg;
+        } else if (alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(", 43);
+            length_modifier = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);
         } else if (core_alg != alg) {
             append(&buffer, buffer_size, &required_size,
-                   "PSA_ALG_AEAD_WITH_TAG_LENGTH(", 29);
-            length_modifier = PSA_AEAD_TAG_LENGTH(alg);
+                   "PSA_ALG_AEAD_WITH_SHORTENED_TAG(", 32);
+            length_modifier = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);
         }
     } else if (PSA_ALG_IS_KEY_AGREEMENT(alg) &&
                !PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) {
@@ -205,103 +214,15 @@
     }\
 '''
 
-class MacroCollector:
-    """Collect PSA crypto macro definitions from C header files.
+class CaseBuilder(macro_collector.PSAMacroCollector):
+    """Collect PSA crypto macro definitions and write value recognition functions.
 
     1. Call `read_file` on the input header file(s).
     2. Call `write_file` to write ``psa_constant_names_generated.c``.
     """
 
     def __init__(self):
-        self.statuses = set()
-        self.key_types = set()
-        self.key_types_from_curve = {}
-        self.key_types_from_group = {}
-        self.ecc_curves = set()
-        self.dh_groups = set()
-        self.algorithms = set()
-        self.hash_algorithms = set()
-        self.ka_algorithms = set()
-        self.algorithms_from_hash = {}
-        self.key_usages = set()
-
-    # "#define" followed by a macro name with either no parameters
-    # or a single parameter and a non-empty expansion.
-    # Grab the macro name in group 1, the parameter name if any in group 2
-    # and the expansion in group 3.
-    _define_directive_re = re.compile(r'\s*#\s*define\s+(\w+)' +
-                                      r'(?:\s+|\((\w+)\)\s*)' +
-                                      r'(.+)')
-    _deprecated_definition_re = re.compile(r'\s*MBEDTLS_DEPRECATED')
-
-    def read_line(self, line):
-        """Parse a C header line and record the PSA identifier it defines if any.
-        This function analyzes lines that start with "#define PSA_"
-        (up to non-significant whitespace) and skips all non-matching lines.
-        """
-        # pylint: disable=too-many-branches
-        m = re.match(self._define_directive_re, line)
-        if not m:
-            return
-        name, parameter, expansion = m.groups()
-        expansion = re.sub(r'/\*.*?\*/|//.*', r' ', expansion)
-        if re.match(self._deprecated_definition_re, expansion):
-            # Skip deprecated values, which are assumed to be
-            # backward compatibility aliases that share
-            # numerical values with non-deprecated values.
-            return
-        if name.endswith('_FLAG') or name.endswith('MASK'):
-            # Macro only to build actual values
-            return
-        elif (name.startswith('PSA_ERROR_') or name == 'PSA_SUCCESS') \
-           and not parameter:
-            self.statuses.add(name)
-        elif name.startswith('PSA_KEY_TYPE_') and not parameter:
-            self.key_types.add(name)
-        elif name.startswith('PSA_KEY_TYPE_') and parameter == 'curve':
-            self.key_types_from_curve[name] = name[:13] + 'IS_' + name[13:]
-        elif name.startswith('PSA_KEY_TYPE_') and parameter == 'group':
-            self.key_types_from_group[name] = name[:13] + 'IS_' + name[13:]
-        elif name.startswith('PSA_ECC_FAMILY_') and not parameter:
-            self.ecc_curves.add(name)
-        elif name.startswith('PSA_DH_FAMILY_') and not parameter:
-            self.dh_groups.add(name)
-        elif name.startswith('PSA_ALG_') and not parameter:
-            if name in ['PSA_ALG_ECDSA_BASE',
-                        'PSA_ALG_RSA_PKCS1V15_SIGN_BASE']:
-                # Ad hoc skipping of duplicate names for some numerical values
-                return
-            self.algorithms.add(name)
-            # Ad hoc detection of hash algorithms
-            if re.search(r'0x020000[0-9A-Fa-f]{2}', expansion):
-                self.hash_algorithms.add(name)
-            # Ad hoc detection of key agreement algorithms
-            if re.search(r'0x09[0-9A-Fa-f]{2}0000', expansion):
-                self.ka_algorithms.add(name)
-        elif name.startswith('PSA_ALG_') and parameter == 'hash_alg':
-            if name in ['PSA_ALG_DSA', 'PSA_ALG_ECDSA']:
-                # A naming irregularity
-                tester = name[:8] + 'IS_RANDOMIZED_' + name[8:]
-            else:
-                tester = name[:8] + 'IS_' + name[8:]
-            self.algorithms_from_hash[name] = tester
-        elif name.startswith('PSA_KEY_USAGE_') and not parameter:
-            self.key_usages.add(name)
-        else:
-            # Other macro without parameter
-            return
-
-    _nonascii_re = re.compile(rb'[^\x00-\x7f]+')
-    _continued_line_re = re.compile(rb'\\\r?\n\Z')
-    def read_file(self, header_file):
-        for line in header_file:
-            m = re.search(self._continued_line_re, line)
-            while m:
-                cont = next(header_file)
-                line = line[:m.start(0)] + cont
-                m = re.search(self._continued_line_re, line)
-            line = re.sub(self._nonascii_re, rb'', line).decode('ascii')
-            self.read_line(line)
+        super().__init__(include_intermediate=True)
 
     @staticmethod
     def _make_return_case(name):
@@ -383,7 +304,7 @@
 
     def _make_key_usage_code(self):
         return '\n'.join([self._make_bit_test('usage', bit)
-                          for bit in sorted(self.key_usages)])
+                          for bit in sorted(self.key_usage_flags)])
 
     def write_file(self, output_file):
         """Generate the pretty-printer function code from the gathered
@@ -404,7 +325,7 @@
         output_file.write(OUTPUT_TEMPLATE % data)
 
 def generate_psa_constants(header_file_names, output_file_name):
-    collector = MacroCollector()
+    collector = CaseBuilder()
     for header_file_name in header_file_names:
         with open(header_file_name, 'rb') as header_file:
             collector.read_file(header_file)
diff --git a/third_party/mbedtls/repo/scripts/generate_visualc_files.pl b/third_party/mbedtls/repo/scripts/generate_visualc_files.pl
index 6c2b5e4..d11041c 100755
--- a/third_party/mbedtls/repo/scripts/generate_visualc_files.pl
+++ b/third_party/mbedtls/repo/scripts/generate_visualc_files.pl
@@ -40,6 +40,7 @@
 my $test_source_dir = 'tests/src';
 my $test_header_dir = 'tests/include/test';
 my $test_drivers_header_dir = 'tests/include/test/drivers';
+my $test_drivers_source_dir = 'tests/src/drivers';
 
 my @thirdparty_header_dirs = qw(
     3rdparty/everest/include/everest
@@ -116,6 +117,7 @@
         && -d $psa_header_dir
         && -d $source_dir
         && -d $test_source_dir
+        && -d $test_drivers_source_dir
         && -d $test_header_dir
         && -d $test_drivers_header_dir
         && -d $programs_dir;
@@ -161,6 +163,9 @@
         $appname eq "query_compile_time_config" ) {
         $srcs .= "\r\n    <ClCompile Include=\"..\\..\\programs\\test\\query_config.c\" \/>";
     }
+    if( $appname eq "ssl_client2" or $appname eq "ssl_server2" ) {
+        $srcs .= "\r\n    <ClCompile Include=\"..\\..\\programs\\ssl\\ssl_test_lib.c\" \/>";
+    }
 
     my $content = $template;
     $content =~ s/<SOURCES>/$srcs/g;
@@ -272,6 +277,7 @@
     my @source_dirs = (
                        $source_dir,
                        $test_source_dir,
+                       $test_drivers_source_dir,
                        @thirdparty_source_dirs,
                       );
     my @sources = (map { <$_/*.c> } @source_dirs);
diff --git a/third_party/mbedtls/repo/scripts/maintainer.requirements.txt b/third_party/mbedtls/repo/scripts/maintainer.requirements.txt
new file mode 100644
index 0000000..b149921
--- /dev/null
+++ b/third_party/mbedtls/repo/scripts/maintainer.requirements.txt
@@ -0,0 +1,10 @@
+# Python packages that are only useful to Mbed TLS maintainers.
+
+-r ci.requirements.txt
+
+# For source code analyses
+clang
+
+# For building some test vectors
+pycryptodomex
+pycryptodome-test-vectors
diff --git a/third_party/mbedtls/repo/scripts/mbedtls_dev/asymmetric_key_data.py b/third_party/mbedtls/repo/scripts/mbedtls_dev/asymmetric_key_data.py
new file mode 100644
index 0000000..6fd6223
--- /dev/null
+++ b/third_party/mbedtls/repo/scripts/mbedtls_dev/asymmetric_key_data.py
@@ -0,0 +1,166 @@
+"""Sample key material for asymmetric key types.
+
+Meant for use in crypto_knowledge.py.
+"""
+
+# 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.
+
+import binascii
+import re
+from typing import Dict
+
+STR_TRANS_REMOVE_BLANKS = str.maketrans('', '', ' \t\n\r')
+
+def unhexlify(text: str) -> bytes:
+    return binascii.unhexlify(text.translate(STR_TRANS_REMOVE_BLANKS))
+
+def construct_asymmetric_key_data(src) -> Dict[str, Dict[int, bytes]]:
+    """Split key pairs into separate table entries and convert hex to bytes.
+
+    Input format: src[abbreviated_type][size] = (private_key_hex, public_key_hex)
+    Output format: dst['PSA_KEY_TYPE_xxx'][size] = key_bytes
+    """
+    dst = {} #type: Dict[str, Dict[int, bytes]]
+    for typ in src:
+        private = 'PSA_KEY_TYPE_' + re.sub(r'(\(|\Z)', r'_KEY_PAIR\1', typ, 1)
+        public = 'PSA_KEY_TYPE_' + re.sub(r'(\(|\Z)', r'_PUBLIC_KEY\1', typ, 1)
+        dst[private] = {}
+        dst[public] = {}
+        for size in src[typ]:
+            dst[private][size] = unhexlify(src[typ][size][0])
+            dst[public][size] = unhexlify(src[typ][size][1])
+    return dst
+
+## These are valid keys that don't try to exercise any edge cases. They're
+## either test vectors from some specification, or randomly generated. All
+## pairs consist of a private key and its public key.
+#pylint: disable=line-too-long
+ASYMMETRIC_KEY_DATA = construct_asymmetric_key_data({
+    'ECC(PSA_ECC_FAMILY_SECP_K1)': {
+        192: ("297ac1722ccac7589ecb240dc719842538ca974beb79f228",
+              "0426b7bb38da649ac2138fc050c6548b32553dab68afebc36105d325b75538c12323cb0764789ecb992671beb2b6bef2f5"),
+        224: ("0024122bf020fa113f6c0ac978dfbd41f749257a9468febdbe0dc9f7e8",
+              "042cc7335f4b76042bed44ef45959a62aa215f7a5ff0c8111b8c44ed654ee71c1918326ad485b2d599fe2a6eab096ee26d977334d2bac6d61d"),
+        256: ("7fa06fa02d0e911b9a47fdc17d2d962ca01e2f31d60c6212d0ed7e3bba23a7b9",
+              "045c39154579efd667adc73a81015a797d2c8682cdfbd3c3553c4a185d481cdc50e42a0e1cbc3ca29a32a645e927f54beaed14c9dbbf8279d725f5495ca924b24d"),
+    },
+    'ECC(PSA_ECC_FAMILY_SECP_R1)': {
+        225: ("872f203b3ad35b7f2ecc803c3a0e1e0b1ed61cc1afe71b189cd4c995",
+              "046f00eadaa949fee3e9e1c7fa1247eecec86a0dce46418b9bd3117b981d4bd0ae7a990de912f9d060d6cb531a42d22e394ac29e81804bf160"),
+        256: ("49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee",
+              "047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45"),
+        384: ("3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a",
+              "04d9c662b50ba29ca47990450e043aeaf4f0c69b15676d112f622a71c93059af999691c5680d2b44d111579db12f4a413a2ed5c45fcfb67b5b63e00b91ebe59d09a6b1ac2c0c4282aa12317ed5914f999bc488bb132e8342cc36f2ca5e3379c747"),
+        521: ("01b1b6ad07bb79e7320da59860ea28e055284f6058f279de666e06d435d2af7bda28d99fa47b7dd0963e16b0073078ee8b8a38d966a582f46d19ff95df3ad9685aae",
+              "04001de142d54f69eb038ee4b7af9d3ca07736fd9cf719eb354d69879ee7f3c136fb0fbf9f08f86be5fa128ec1a051d3e6c643e85ada8ffacf3663c260bd2c844b6f5600cee8e48a9e65d09cadd89f235dee05f3b8a646be715f1f67d5b434e0ff23a1fc07ef7740193e40eeff6f3bcdfd765aa9155033524fe4f205f5444e292c4c2f6ac1"),
+    },
+    'ECC(PSA_ECC_FAMILY_SECP_R2)': {
+        160: ("00bf539a1cdda0d7f71a50a3f98aec0a2e8e4ced1e",
+              "049570d541398665adb5cfa16f5af73b3196926bbd4b876bdb80f8eab20d0f540c22f4de9c140f6d7b"),
+    },
+    'ECC(PSA_ECC_FAMILY_SECT_K1)': {
+        163: ("03ebc8fcded2d6ab72ec0f75bdb4fd080481273e71",
+              "0406f88f90b4b65950f06ce433afdb097e320f433dc2062b8a65db8fafd3c110f46bc45663fbf021ee7eb9"),
+        233: ("41f08485ce587b06061c087e76e247c359de2ba9927ee013b2f1ed9ca8",
+              "0401e9d7189189f773bd8f71be2c10774ba18842434dfa9312595ea545104400f45a9d5675647513ba75b079fe66a29daac2ec86a6a5d4e75c5f290c1f"),
+        239: ("1a8069ce2c2c8bdd7087f2a6ab49588797e6294e979495602ab9650b9c61",
+              "04068d76b9f4508762c2379db9ee8b87ad8d86d9535132ffba3b5680440cfa28eb133d4232faf1c9aba96af11aefe634a551440800d5f8185105d3072d"),
+        283: ("006d627885dd48b9ec6facb5b3865377d755b75a5d51440e45211c1f600e15eff8a881a0",
+              "0405f48374debceaadb46ba385fd92048fcc5b9af1a1c90408bf94a68b9378df1cbfdfb6fb026a96bea06d8f181bf10c020adbcc88b6ecff96bdc564a9649c247cede601c4be63afc3"),
+        409: ("3ff5e74d932fa77db139b7c948c81e4069c72c24845574064beea8976b70267f1c6f9a503e3892ea1dcbb71fcea423faa370a8",
+              "04012c587f69f68b308ba6dcb238797f4e22290ca939ae806604e2b5ab4d9caef5a74a98fd87c4f88d292dd39d92e556e16c6ecc3c019a105826eef507cd9a04119f54d5d850b3720b3792d5d03410e9105610f7e4b420166ed45604a7a1f229d80975ba6be2060e8b"),
+        571: ("005008c97b4a161c0db1bac6452c72846d57337aa92d8ecb4a66eb01d2f29555ffb61a5317225dcc8ca6917d91789e227efc0bfe9eeda7ee21998cd11c3c9885056b0e55b4f75d51",
+              "04050172a7fd7adf98e4e2ed2742faa5cd12731a15fb0dbbdf75b1c3cc771a4369af6f2fa00e802735650881735759ea9c79961ded18e0daa0ac59afb1d513b5bbda9962e435f454fc020b4afe1445c2302ada07d295ec2580f8849b2dfa7f956b09b4cbe4c88d3b1c217049f75d3900d36df0fa12689256b58dd2ef784ebbeb0564600cf47a841485f8cf897a68accd5a"),
+    },
+    'ECC(PSA_ECC_FAMILY_SECT_R1)': {
+        163: ("009b05dc82d46d64a04a22e6e5ca70ca1231e68c50",
+              "0400465eeb9e7258b11e33c02266bfe834b20bcb118700772796ee4704ec67651bd447e3011959a79a04cb"),
+        233: ("00e5e42834e3c78758088b905deea975f28dc20ef6173e481f96e88afe7f",
+              "0400cd68c8af4430c92ec7a7048becfdf00a6bae8d1b4c37286f2d336f2a0e017eca3748f4ad6d435c85867aa014eea1bd6d9d005bbd8319cab629001d"),
+        283: ("004cecad915f6f3c9bbbd92d1eb101eda23f16c7dad60a57c87c7e1fd2b29b22f6d666ad",
+              "04052f9ff887254c2d1440ba9e30f13e2185ba53c373b2c410dae21cf8c167f796c08134f601cbc4c570bffbc2433082cf4d9eb5ba173ecb8caec15d66a02673f60807b2daa729b765"),
+        409: ("00c22422d265721a3ae2b3b2baeb77bee50416e19877af97b5fc1c700a0a88916ecb9050135883accb5e64edc77a3703f4f67a64",
+              "0401aa25466b1d291846db365957b25431591e50d9c109fe2106e93bb369775896925b15a7bfec397406ab4fe6f6b1a13bf8fdcb9300fa5500a813228676b0a6c572ed96b0f4aec7e87832e7e20f17ca98ecdfd36f59c82bddb8665f1f357a73900e827885ec9e1f22"),
+        571: ("026ac1cdf92a13a1b8d282da9725847908745138f5c6706b52d164e3675fcfbf86fc3e6ab2de732193267db029dd35a0599a94a118f480231cfc6ccca2ebfc1d8f54176e0f5656a1",
+              "040708f3403ee9948114855c17572152a08f8054d486defef5f29cbffcfb7cfd9280746a1ac5f751a6ad902ec1e0525120e9be56f03437af196fbe60ee7856e3542ab2cf87880632d80290e39b1a2bd03c6bbf6225511c567bd2ff41d2325dc58346f2b60b1feee4dc8b2af2296c2dc52b153e0556b5d24152b07f690c3fa24e4d1d19efbdeb1037833a733654d2366c74"),
+    },
+    'ECC(PSA_ECC_FAMILY_SECT_R2)': {
+        163: ("0210b482a458b4822d0cb21daa96819a67c8062d34",
+              "0403692601144c32a6cfa369ae20ae5d43c1c764678c037bafe80c6fd2e42b7ced96171d9c5367fd3dca6f"),
+    },
+    'ECC(PSA_ECC_FAMILY_BRAINPOOL_P_R1)': {
+        160: ("69502c4fdaf48d4fa617bdd24498b0406d0eeaac",
+              "04d4b9186816358e2f9c59cf70748cb70641b22fbab65473db4b4e22a361ed7e3de7e8a8ddc4130c5c"),
+        192: ("1688a2c5fbf4a3c851d76a98c3ec88f445a97996283db59f",
+              "043fdd168c179ff5363dd71dcd58de9617caad791ae0c37328be9ca0bfc79cebabf6a95d1c52df5b5f3c8b1a2441cf6c88"),
+        224: ("a69835dafeb5da5ab89c59860dddebcfd80b529a99f59b880882923c",
+              "045fbea378fc8583b3837e3f21a457c31eaf20a54e18eb11d104b3adc47f9d1c97eb9ea4ac21740d70d88514b98bf0bc31addac1d19c4ab3cc"),
+        256: ("2161d6f2db76526fa62c16f356a80f01f32f776784b36aa99799a8b7662080ff",
+              "04768c8cae4abca6306db0ed81b0c4a6215c378066ec6d616c146e13f1c7df809b96ab6911c27d8a02339f0926840e55236d3d1efbe2669d090e4c4c660fada91d"),
+        320: ("61b8daa7a6e5aa9fccf1ef504220b2e5a5b8c6dc7475d16d3172d7db0b2778414e4f6e8fa2032ead",
+              "049caed8fb4742956cc2ad12a9a1c995e21759ef26a07bc2054136d3d2f28bb331a70e26c4c687275ab1f434be7871e115d2350c0c5f61d4d06d2bcdb67f5cb63fdb794e5947c87dc6849a58694e37e6cd"),
+        384: ("3dd92e750d90d7d39fc1885cd8ad12ea9441f22b9334b4d965202adb1448ce24c5808a85dd9afc229af0a3124f755bcb",
+              "04719f9d093a627e0d350385c661cebf00c61923566fe9006a3107af1d871bc6bb68985fd722ea32be316f8e783b7cd1957785f66cfc0cb195dd5c99a8e7abaa848553a584dfd2b48e76d445fe00dd8be59096d877d4696d23b4bc8db14724e66a"),
+        512: ("372c9778f69f726cbca3f4a268f16b4d617d10280d79a6a029cd51879fe1012934dfe5395455337df6906dc7d6d2eea4dbb2065c0228f73b3ed716480e7d71d2",
+              "0438b7ec92b61c5c6c7fbc28a4ec759d48fcd4e2e374defd5c4968a54dbef7510e517886fbfc38ea39aa529359d70a7156c35d3cbac7ce776bdb251dd64bce71234424ee7049eed072f0dbc4d79996e175d557e263763ae97095c081e73e7db2e38adc3d4c9a0487b1ede876dc1fca61c902e9a1d8722b8612928f18a24845591a"),
+    },
+    'ECC(PSA_ECC_FAMILY_MONTGOMERY)': {
+        255: ("70076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c6a",
+              "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"),
+        448: ("e4e49f52686f9ee3b638528f721f1596196ffd0a1cddb64c3f216f06541805cfeb1a286dc78018095cdfec050e8007b5f4908962ba20d6c1",
+              "c0d3a5a2b416a573dc9909f92f134ac01323ab8f8e36804e578588ba2d09fe7c3e737f771ca112825b548a0ffded6d6a2fd09a3e77dec30e"),
+    },
+    'ECC(PSA_ECC_FAMILY_TWISTED_EDWARDS)': {
+        255: ("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
+              "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"),
+        448: ("6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b",
+              "5fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180"),
+    },
+    'RSA': {
+        1024: ("""
+3082025e
+ 020100
+ 02818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3
+ 0203010001
+ 02818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1
+ 024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113
+ 024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091
+ 024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d
+ 024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1
+ 024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24
+""", """
+ 308189
+  02818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3
+ 0203010001
+"""),
+        1536: ("""
+3082037b
+ 020100
+ 0281c100c870feb6ca6b1d2bd9f2dd99e20f1fe2d7e5192de662229dbe162bd1ba66336a7182903ca0b72796cd441c83d24bcdc3e9a2f5e4399c8a043f1c3ddf04754a66d4cfe7b3671a37dd31a9b4c13bfe06ee90f9d94ddaa06de67a52ac863e68f756736ceb014405a6160579640f831dddccc34ad0b05070e3f9954a58d1815813e1b83bcadba814789c87f1ef2ba5d738b793ec456a67360eea1b5faf1c7cc7bf24f3b2a9d0f8958b1096e0f0c335f8888d0c63a51c3c0337214fa3f5efdf6dcc35
+ 0203010001
+ 0281c06d2d670047973a87752a9d5bc14f3dae00acb01f593aa0e24cf4a49f932931de4bbfb332e2d38083da80bc0b6d538edba479f7f77d0deffb4a28e6e67ff6273585bb4cd862535c946605ab0809d65f0e38f76e4ec2c3d9b8cd6e14bcf667943892cd4b34cc6420a439abbf3d7d35ef73976dd6f9cbde35a51fa5213f0107f83e3425835d16d3c9146fc9e36ce75a09bb66cdff21dd5a776899f1cb07e282cca27be46510e9c799f0d8db275a6be085d9f3f803218ee3384265bfb1a3640e8ca1
+ 026100e6848c31d466fffefc547e3a3b0d3785de6f78b0dd12610843512e495611a0675509b1650b27415009838dd8e68eec6e7530553b637d602424643b33e8bc5b762e1799bc79d56b13251d36d4f201da2182416ce13574e88278ff04467ad602d9
+ 026100de994fdf181f02be2bf9e5f5e4e517a94993b827d1eaf609033e3a6a6f2396ae7c44e9eb594cf1044cb3ad32ea258f0c82963b27bb650ed200cde82cb993374be34be5b1c7ead5446a2b82a4486e8c1810a0b01551609fb0841d474bada802bd
+ 026076ddae751b73a959d0bfb8ff49e7fcd378e9be30652ecefe35c82cb8003bc29cc60ae3809909baf20c95db9516fe680865417111d8b193dbcf30281f1249de57c858bf1ba32f5bb1599800e8398a9ef25c7a642c95261da6f9c17670e97265b1
+ 0260732482b837d5f2a9443e23c1aa0106d83e82f6c3424673b5fdc3769c0f992d1c5c93991c7038e882fcda04414df4d7a5f4f698ead87851ce37344b60b72d7b70f9c60cae8566e7a257f8e1bef0e89df6e4c2f9d24d21d9f8889e4c7eccf91751
+ 026009050d94493da8f00a4ddbe9c800afe3d44b43f78a48941a79b2814a1f0b81a18a8b2347642a03b27998f5a18de9abc9ae0e54ab8294feac66dc87e854cce6f7278ac2710cb5878b592ffeb1f4f0a1853e4e8d1d0561b6efcc831a296cf7eeaf
+""", """
+3081c9
+ 0281c100c870feb6ca6b1d2bd9f2dd99e20f1fe2d7e5192de662229dbe162bd1ba66336a7182903ca0b72796cd441c83d24bcdc3e9a2f5e4399c8a043f1c3ddf04754a66d4cfe7b3671a37dd31a9b4c13bfe06ee90f9d94ddaa06de67a52ac863e68f756736ceb014405a6160579640f831dddccc34ad0b05070e3f9954a58d1815813e1b83bcadba814789c87f1ef2ba5d738b793ec456a67360eea1b5faf1c7cc7bf24f3b2a9d0f8958b1096e0f0c335f8888d0c63a51c3c0337214fa3f5efdf6dcc35
+ 0203010001
+"""),
+    },
+})
diff --git a/third_party/mbedtls/repo/scripts/mbedtls_dev/c_build_helper.py b/third_party/mbedtls/repo/scripts/mbedtls_dev/c_build_helper.py
new file mode 100644
index 0000000..5c587a1
--- /dev/null
+++ b/third_party/mbedtls/repo/scripts/mbedtls_dev/c_build_helper.py
@@ -0,0 +1,138 @@
+"""Generate and run C code.
+"""
+
+# 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.
+
+import os
+import platform
+import subprocess
+import sys
+import tempfile
+
+def remove_file_if_exists(filename):
+    """Remove the specified file, ignoring errors."""
+    if not filename:
+        return
+    try:
+        os.remove(filename)
+    except OSError:
+        pass
+
+def create_c_file(file_label):
+    """Create a temporary C file.
+
+    * ``file_label``: a string that will be included in the file name.
+
+    Return ```(c_file, c_name, exe_name)``` where ``c_file`` is a Python
+    stream open for writing to the file, ``c_name`` is the name of the file
+    and ``exe_name`` is the name of the executable that will be produced
+    by compiling the file.
+    """
+    c_fd, c_name = tempfile.mkstemp(prefix='tmp-{}-'.format(file_label),
+                                    suffix='.c')
+    exe_suffix = '.exe' if platform.system() == 'Windows' else ''
+    exe_name = c_name[:-2] + exe_suffix
+    remove_file_if_exists(exe_name)
+    c_file = os.fdopen(c_fd, 'w', encoding='ascii')
+    return c_file, c_name, exe_name
+
+def generate_c_printf_expressions(c_file, cast_to, printf_format, expressions):
+    """Generate C instructions to print the value of ``expressions``.
+
+    Write the code with ``c_file``'s ``write`` method.
+
+    Each expression is cast to the type ``cast_to`` and printed with the
+    printf format ``printf_format``.
+    """
+    for expr in expressions:
+        c_file.write('    printf("{}\\n", ({}) {});\n'
+                     .format(printf_format, cast_to, expr))
+
+def generate_c_file(c_file,
+                    caller, header,
+                    main_generator):
+    """Generate a temporary C source file.
+
+    * ``c_file`` is an open stream on the C source file.
+    * ``caller``: an informational string written in a comment at the top
+      of the file.
+    * ``header``: extra code to insert before any function in the generated
+      C file.
+    * ``main_generator``: a function called with ``c_file`` as its sole argument
+      to generate the body of the ``main()`` function.
+    """
+    c_file.write('/* Generated by {} */'
+                 .format(caller))
+    c_file.write('''
+#include <stdio.h>
+''')
+    c_file.write(header)
+    c_file.write('''
+int main(void)
+{
+''')
+    main_generator(c_file)
+    c_file.write('''    return 0;
+}
+''')
+
+def get_c_expression_values(
+        cast_to, printf_format,
+        expressions,
+        caller=__name__, file_label='',
+        header='', include_path=None,
+        keep_c=False,
+): # pylint: disable=too-many-arguments
+    """Generate and run a program to print out numerical values for expressions.
+
+    * ``cast_to``: a C type.
+    * ``printf_format``: a printf format suitable for the type ``cast_to``.
+    * ``header``: extra code to insert before any function in the generated
+      C file.
+    * ``expressions``: a list of C language expressions that have the type
+      ``cast_to``.
+    * ``include_path``: a list of directories containing header files.
+    * ``keep_c``: if true, keep the temporary C file (presumably for debugging
+      purposes).
+
+    Return the list of values of the ``expressions``.
+    """
+    if include_path is None:
+        include_path = []
+    c_name = None
+    exe_name = None
+    try:
+        c_file, c_name, exe_name = create_c_file(file_label)
+        generate_c_file(
+            c_file, caller, header,
+            lambda c_file: generate_c_printf_expressions(c_file,
+                                                         cast_to, printf_format,
+                                                         expressions)
+        )
+        c_file.close()
+        cc = os.getenv('CC', 'cc')
+        subprocess.check_call([cc] +
+                              ['-I' + dir for dir in include_path] +
+                              ['-o', exe_name, c_name])
+        if keep_c:
+            sys.stderr.write('List of {} tests kept at {}\n'
+                             .format(caller, c_name))
+        else:
+            os.remove(c_name)
+        output = subprocess.check_output([exe_name])
+        return output.decode('ascii').strip().split('\n')
+    finally:
+        remove_file_if_exists(exe_name)
diff --git a/third_party/mbedtls/repo/scripts/mbedtls_dev/crypto_knowledge.py b/third_party/mbedtls/repo/scripts/mbedtls_dev/crypto_knowledge.py
new file mode 100644
index 0000000..7214adb
--- /dev/null
+++ b/third_party/mbedtls/repo/scripts/mbedtls_dev/crypto_knowledge.py
@@ -0,0 +1,153 @@
+"""Knowledge about cryptographic mechanisms implemented in Mbed TLS.
+
+This module is entirely based on the PSA API.
+"""
+
+# 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.
+
+import re
+from typing import Dict, Iterable, Optional, Pattern, Tuple
+
+from mbedtls_dev.asymmetric_key_data import ASYMMETRIC_KEY_DATA
+
+class KeyType:
+    """Knowledge about a PSA key type."""
+
+    def __init__(self, name: str, params: Optional[Iterable[str]] = None):
+        """Analyze a key type.
+
+        The key type must be specified in PSA syntax. In its simplest form,
+        `name` is a string 'PSA_KEY_TYPE_xxx' which is the name of a PSA key
+        type macro. For key types that take arguments, the arguments can
+        be passed either through the optional argument `params` or by
+        passing an expression of the form 'PSA_KEY_TYPE_xxx(param1, ...)'
+        in `name` as a string.
+        """
+
+        self.name = name.strip()
+        """The key type macro name (``PSA_KEY_TYPE_xxx``).
+
+        For key types constructed from a macro with arguments, this is the
+        name of the macro, and the arguments are in `self.params`.
+        """
+        if params is None:
+            if '(' in self.name:
+                m = re.match(r'(\w+)\s*\((.*)\)\Z', self.name)
+                assert m is not None
+                self.name = m.group(1)
+                params = m.group(2).split(',')
+        self.params = (None if params is None else
+                       [param.strip() for param in params])
+        """The parameters of the key type, if there are any.
+
+        None if the key type is a macro without arguments.
+        """
+        assert re.match(r'PSA_KEY_TYPE_\w+\Z', self.name)
+
+        self.expression = self.name
+        """A C expression whose value is the key type encoding."""
+        if self.params is not None:
+            self.expression += '(' + ', '.join(self.params) + ')'
+
+        self.private_type = re.sub(r'_PUBLIC_KEY\Z', r'_KEY_PAIR', self.name)
+        """The key type macro name for the corresponding key pair type.
+
+        For everything other than a public key type, this is the same as
+        `self.name`.
+        """
+
+    ECC_KEY_SIZES = {
+        'PSA_ECC_FAMILY_SECP_K1': (192, 224, 256),
+        'PSA_ECC_FAMILY_SECP_R1': (225, 256, 384, 521),
+        'PSA_ECC_FAMILY_SECP_R2': (160,),
+        'PSA_ECC_FAMILY_SECT_K1': (163, 233, 239, 283, 409, 571),
+        'PSA_ECC_FAMILY_SECT_R1': (163, 233, 283, 409, 571),
+        'PSA_ECC_FAMILY_SECT_R2': (163,),
+        'PSA_ECC_FAMILY_BRAINPOOL_P_R1': (160, 192, 224, 256, 320, 384, 512),
+        'PSA_ECC_FAMILY_MONTGOMERY': (255, 448),
+        'PSA_ECC_FAMILY_TWISTED_EDWARDS': (255, 448),
+    }
+    KEY_TYPE_SIZES = {
+        'PSA_KEY_TYPE_AES': (128, 192, 256), # exhaustive
+        'PSA_KEY_TYPE_ARC4': (8, 128, 2048), # extremes + sensible
+        'PSA_KEY_TYPE_ARIA': (128, 192, 256), # exhaustive
+        'PSA_KEY_TYPE_CAMELLIA': (128, 192, 256), # exhaustive
+        'PSA_KEY_TYPE_CHACHA20': (256,), # exhaustive
+        'PSA_KEY_TYPE_DERIVE': (120, 128), # sample
+        'PSA_KEY_TYPE_DES': (64, 128, 192), # exhaustive
+        'PSA_KEY_TYPE_HMAC': (128, 160, 224, 256, 384, 512), # standard size for each supported hash
+        'PSA_KEY_TYPE_RAW_DATA': (8, 40, 128), # sample
+        'PSA_KEY_TYPE_RSA_KEY_PAIR': (1024, 1536), # small sample
+    }
+    def sizes_to_test(self) -> Tuple[int, ...]:
+        """Return a tuple of key sizes to test.
+
+        For key types that only allow a single size, or only a small set of
+        sizes, these are all the possible sizes. For key types that allow a
+        wide range of sizes, these are a representative sample of sizes,
+        excluding large sizes for which a typical resource-constrained platform
+        may run out of memory.
+        """
+        if self.private_type == 'PSA_KEY_TYPE_ECC_KEY_PAIR':
+            assert self.params is not None
+            return self.ECC_KEY_SIZES[self.params[0]]
+        return self.KEY_TYPE_SIZES[self.private_type]
+
+    # "48657265006973206b6579a064617461"
+    DATA_BLOCK = b'Here\000is key\240data'
+    def key_material(self, bits: int) -> bytes:
+        """Return a byte string containing suitable key material with the given bit length.
+
+        Use the PSA export representation. The resulting byte string is one that
+        can be obtained with the following code:
+        ```
+        psa_set_key_type(&attributes, `self.expression`);
+        psa_set_key_bits(&attributes, `bits`);
+        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT);
+        psa_generate_key(&attributes, &id);
+        psa_export_key(id, `material`, ...);
+        ```
+        """
+        if self.expression in ASYMMETRIC_KEY_DATA:
+            if bits not in ASYMMETRIC_KEY_DATA[self.expression]:
+                raise ValueError('No key data for {}-bit {}'
+                                 .format(bits, self.expression))
+            return ASYMMETRIC_KEY_DATA[self.expression][bits]
+        if bits % 8 != 0:
+            raise ValueError('Non-integer number of bytes: {} bits for {}'
+                             .format(bits, self.expression))
+        length = bits // 8
+        if self.name == 'PSA_KEY_TYPE_DES':
+            # "644573206b457901644573206b457902644573206b457904"
+            des3 = b'dEs kEy\001dEs kEy\002dEs kEy\004'
+            return des3[:length]
+        return b''.join([self.DATA_BLOCK] * (length // len(self.DATA_BLOCK)) +
+                        [self.DATA_BLOCK[:length % len(self.DATA_BLOCK)]])
+
+    KEY_TYPE_FOR_SIGNATURE = {
+        'PSA_KEY_USAGE_SIGN_HASH': re.compile('.*KEY_PAIR'),
+        'PSA_KEY_USAGE_VERIFY_HASH': re.compile('.*KEY.*')
+    } #type: Dict[str, Pattern]
+    """Use a regexp to determine key types for which signature is possible
+       when using the actual usage flag.
+    """
+    def is_valid_for_signature(self, usage: str) -> bool:
+        """Determine if the key type is compatible with the specified
+           signitute type.
+
+        """
+        # This is just temporaly solution for the implicit usage flags.
+        return re.match(self.KEY_TYPE_FOR_SIGNATURE[usage], self.name) is not None
diff --git a/third_party/mbedtls/repo/scripts/mbedtls_dev/macro_collector.py b/third_party/mbedtls/repo/scripts/mbedtls_dev/macro_collector.py
new file mode 100644
index 0000000..3440ba7
--- /dev/null
+++ b/third_party/mbedtls/repo/scripts/mbedtls_dev/macro_collector.py
@@ -0,0 +1,528 @@
+"""Collect macro definitions from header files.
+"""
+
+# 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.
+
+import itertools
+import re
+from typing import Dict, Iterable, Iterator, List, Optional, Pattern, Set, Tuple, Union
+
+
+class ReadFileLineException(Exception):
+    def __init__(self, filename: str, line_number: Union[int, str]) -> None:
+        message = 'in {} at {}'.format(filename, line_number)
+        super(ReadFileLineException, self).__init__(message)
+        self.filename = filename
+        self.line_number = line_number
+
+
+class read_file_lines:
+    # Dear Pylint, conventionally, a context manager class name is lowercase.
+    # pylint: disable=invalid-name,too-few-public-methods
+    """Context manager to read a text file line by line.
+
+    ```
+    with read_file_lines(filename) as lines:
+        for line in lines:
+            process(line)
+    ```
+    is equivalent to
+    ```
+    with open(filename, 'r') as input_file:
+        for line in input_file:
+            process(line)
+    ```
+    except that if process(line) raises an exception, then the read_file_lines
+    snippet annotates the exception with the file name and line number.
+    """
+    def __init__(self, filename: str, binary: bool = False) -> None:
+        self.filename = filename
+        self.line_number = 'entry' #type: Union[int, str]
+        self.generator = None #type: Optional[Iterable[Tuple[int, str]]]
+        self.binary = binary
+    def __enter__(self) -> 'read_file_lines':
+        self.generator = enumerate(open(self.filename,
+                                        'rb' if self.binary else 'r'))
+        return self
+    def __iter__(self) -> Iterator[str]:
+        assert self.generator is not None
+        for line_number, content in self.generator:
+            self.line_number = line_number
+            yield content
+        self.line_number = 'exit'
+    def __exit__(self, exc_type, exc_value, exc_traceback) -> None:
+        if exc_type is not None:
+            raise ReadFileLineException(self.filename, self.line_number) \
+                from exc_value
+
+
+class PSAMacroEnumerator:
+    """Information about constructors of various PSA Crypto types.
+
+    This includes macro names as well as information about their arguments
+    when applicable.
+
+    This class only provides ways to enumerate expressions that evaluate to
+    values of the covered types. Derived classes are expected to populate
+    the set of known constructors of each kind, as well as populate
+    `self.arguments_for` for arguments that are not of a kind that is
+    enumerated here.
+    """
+    #pylint: disable=too-many-instance-attributes
+
+    def __init__(self) -> None:
+        """Set up an empty set of known constructor macros.
+        """
+        self.statuses = set() #type: Set[str]
+        self.lifetimes = set() #type: Set[str]
+        self.locations = set() #type: Set[str]
+        self.persistence_levels = set() #type: Set[str]
+        self.algorithms = set() #type: Set[str]
+        self.ecc_curves = set() #type: Set[str]
+        self.dh_groups = set() #type: Set[str]
+        self.key_types = set() #type: Set[str]
+        self.key_usage_flags = set() #type: Set[str]
+        self.hash_algorithms = set() #type: Set[str]
+        self.mac_algorithms = set() #type: Set[str]
+        self.ka_algorithms = set() #type: Set[str]
+        self.kdf_algorithms = set() #type: Set[str]
+        self.aead_algorithms = set() #type: Set[str]
+        self.sign_algorithms = set() #type: Set[str]
+        # macro name -> list of argument names
+        self.argspecs = {} #type: Dict[str, List[str]]
+        # argument name -> list of values
+        self.arguments_for = {
+            'mac_length': [],
+            'min_mac_length': [],
+            'tag_length': [],
+            'min_tag_length': [],
+        } #type: Dict[str, List[str]]
+        # Whether to include intermediate macros in enumerations. Intermediate
+        # macros serve as category headers and are not valid values of their
+        # type. See `is_internal_name`.
+        # Always false in this class, may be set to true in derived classes.
+        self.include_intermediate = False
+
+    def is_internal_name(self, name: str) -> bool:
+        """Whether this is an internal macro. Internal macros will be skipped."""
+        if not self.include_intermediate:
+            if name.endswith('_BASE') or name.endswith('_NONE'):
+                return True
+            if '_CATEGORY_' in name:
+                return True
+        return name.endswith('_FLAG') or name.endswith('_MASK')
+
+    def gather_arguments(self) -> None:
+        """Populate the list of values for macro arguments.
+
+        Call this after parsing all the inputs.
+        """
+        self.arguments_for['hash_alg'] = sorted(self.hash_algorithms)
+        self.arguments_for['mac_alg'] = sorted(self.mac_algorithms)
+        self.arguments_for['ka_alg'] = sorted(self.ka_algorithms)
+        self.arguments_for['kdf_alg'] = sorted(self.kdf_algorithms)
+        self.arguments_for['aead_alg'] = sorted(self.aead_algorithms)
+        self.arguments_for['sign_alg'] = sorted(self.sign_algorithms)
+        self.arguments_for['curve'] = sorted(self.ecc_curves)
+        self.arguments_for['group'] = sorted(self.dh_groups)
+        self.arguments_for['persistence'] = sorted(self.persistence_levels)
+        self.arguments_for['location'] = sorted(self.locations)
+        self.arguments_for['lifetime'] = sorted(self.lifetimes)
+
+    @staticmethod
+    def _format_arguments(name: str, arguments: Iterable[str]) -> str:
+        """Format a macro call with arguments.
+
+        The resulting format is consistent with
+        `InputsForTest.normalize_argument`.
+        """
+        return name + '(' + ', '.join(arguments) + ')'
+
+    _argument_split_re = re.compile(r' *, *')
+    @classmethod
+    def _argument_split(cls, arguments: str) -> List[str]:
+        return re.split(cls._argument_split_re, arguments)
+
+    def distribute_arguments(self, name: str) -> Iterator[str]:
+        """Generate macro calls with each tested argument set.
+
+        If name is a macro without arguments, just yield "name".
+        If name is a macro with arguments, yield a series of
+        "name(arg1,...,argN)" where each argument takes each possible
+        value at least once.
+        """
+        try:
+            if name not in self.argspecs:
+                yield name
+                return
+            argspec = self.argspecs[name]
+            if argspec == []:
+                yield name + '()'
+                return
+            argument_lists = [self.arguments_for[arg] for arg in argspec]
+            arguments = [values[0] for values in argument_lists]
+            yield self._format_arguments(name, arguments)
+            # Dear Pylint, enumerate won't work here since we're modifying
+            # the array.
+            # pylint: disable=consider-using-enumerate
+            for i in range(len(arguments)):
+                for value in argument_lists[i][1:]:
+                    arguments[i] = value
+                    yield self._format_arguments(name, arguments)
+                arguments[i] = argument_lists[0][0]
+        except BaseException as e:
+            raise Exception('distribute_arguments({})'.format(name)) from e
+
+    def distribute_arguments_without_duplicates(
+            self, seen: Set[str], name: str
+    ) -> Iterator[str]:
+        """Same as `distribute_arguments`, but don't repeat seen results."""
+        for result in self.distribute_arguments(name):
+            if result not in seen:
+                seen.add(result)
+                yield result
+
+    def generate_expressions(self, names: Iterable[str]) -> Iterator[str]:
+        """Generate expressions covering values constructed from the given names.
+
+        `names` can be any iterable collection of macro names.
+
+        For example:
+        * ``generate_expressions(['PSA_ALG_CMAC', 'PSA_ALG_HMAC'])``
+          generates ``'PSA_ALG_CMAC'`` as well as ``'PSA_ALG_HMAC(h)'`` for
+          every known hash algorithm ``h``.
+        * ``macros.generate_expressions(macros.key_types)`` generates all
+          key types.
+        """
+        seen = set() #type: Set[str]
+        return itertools.chain(*(
+            self.distribute_arguments_without_duplicates(seen, name)
+            for name in names
+        ))
+
+
+class PSAMacroCollector(PSAMacroEnumerator):
+    """Collect PSA crypto macro definitions from C header files.
+    """
+
+    def __init__(self, include_intermediate: bool = False) -> None:
+        """Set up an object to collect PSA macro definitions.
+
+        Call the read_file method of the constructed object on each header file.
+
+        * include_intermediate: if true, include intermediate macros such as
+          PSA_XXX_BASE that do not designate semantic values.
+        """
+        super().__init__()
+        self.include_intermediate = include_intermediate
+        self.key_types_from_curve = {} #type: Dict[str, str]
+        self.key_types_from_group = {} #type: Dict[str, str]
+        self.algorithms_from_hash = {} #type: Dict[str, str]
+
+    @staticmethod
+    def algorithm_tester(name: str) -> str:
+        """The predicate for whether an algorithm is built from the given constructor.
+
+        The given name must be the name of an algorithm constructor of the
+        form ``PSA_ALG_xxx`` which is used as ``PSA_ALG_xxx(yyy)`` to build
+        an algorithm value. Return the corresponding predicate macro which
+        is used as ``predicate(alg)`` to test whether ``alg`` can be built
+        as ``PSA_ALG_xxx(yyy)``. The predicate is usually called
+        ``PSA_ALG_IS_xxx``.
+        """
+        prefix = 'PSA_ALG_'
+        assert name.startswith(prefix)
+        midfix = 'IS_'
+        suffix = name[len(prefix):]
+        if suffix in ['DSA', 'ECDSA']:
+            midfix += 'RANDOMIZED_'
+        elif suffix == 'RSA_PSS':
+            suffix += '_STANDARD_SALT'
+        return prefix + midfix + suffix
+
+    def record_algorithm_subtype(self, name: str, expansion: str) -> None:
+        """Record the subtype of an algorithm constructor.
+
+        Given a ``PSA_ALG_xxx`` macro name and its expansion, if the algorithm
+        is of a subtype that is tracked in its own set, add it to the relevant
+        set.
+        """
+        # This code is very ad hoc and fragile. It should be replaced by
+        # something more robust.
+        if re.match(r'MAC(?:_|\Z)', name):
+            self.mac_algorithms.add(name)
+        elif re.match(r'KDF(?:_|\Z)', name):
+            self.kdf_algorithms.add(name)
+        elif re.search(r'0x020000[0-9A-Fa-f]{2}', expansion):
+            self.hash_algorithms.add(name)
+        elif re.search(r'0x03[0-9A-Fa-f]{6}', expansion):
+            self.mac_algorithms.add(name)
+        elif re.search(r'0x05[0-9A-Fa-f]{6}', expansion):
+            self.aead_algorithms.add(name)
+        elif re.search(r'0x09[0-9A-Fa-f]{2}0000', expansion):
+            self.ka_algorithms.add(name)
+        elif re.search(r'0x08[0-9A-Fa-f]{6}', expansion):
+            self.kdf_algorithms.add(name)
+
+    # "#define" followed by a macro name with either no parameters
+    # or a single parameter and a non-empty expansion.
+    # Grab the macro name in group 1, the parameter name if any in group 2
+    # and the expansion in group 3.
+    _define_directive_re = re.compile(r'\s*#\s*define\s+(\w+)' +
+                                      r'(?:\s+|\((\w+)\)\s*)' +
+                                      r'(.+)')
+    _deprecated_definition_re = re.compile(r'\s*MBEDTLS_DEPRECATED')
+
+    def read_line(self, line):
+        """Parse a C header line and record the PSA identifier it defines if any.
+        This function analyzes lines that start with "#define PSA_"
+        (up to non-significant whitespace) and skips all non-matching lines.
+        """
+        # pylint: disable=too-many-branches
+        m = re.match(self._define_directive_re, line)
+        if not m:
+            return
+        name, parameter, expansion = m.groups()
+        expansion = re.sub(r'/\*.*?\*/|//.*', r' ', expansion)
+        if parameter:
+            self.argspecs[name] = [parameter]
+        if re.match(self._deprecated_definition_re, expansion):
+            # Skip deprecated values, which are assumed to be
+            # backward compatibility aliases that share
+            # numerical values with non-deprecated values.
+            return
+        if self.is_internal_name(name):
+            # Macro only to build actual values
+            return
+        elif (name.startswith('PSA_ERROR_') or name == 'PSA_SUCCESS') \
+           and not parameter:
+            self.statuses.add(name)
+        elif name.startswith('PSA_KEY_TYPE_') and not parameter:
+            self.key_types.add(name)
+        elif name.startswith('PSA_KEY_TYPE_') and parameter == 'curve':
+            self.key_types_from_curve[name] = name[:13] + 'IS_' + name[13:]
+        elif name.startswith('PSA_KEY_TYPE_') and parameter == 'group':
+            self.key_types_from_group[name] = name[:13] + 'IS_' + name[13:]
+        elif name.startswith('PSA_ECC_FAMILY_') and not parameter:
+            self.ecc_curves.add(name)
+        elif name.startswith('PSA_DH_FAMILY_') and not parameter:
+            self.dh_groups.add(name)
+        elif name.startswith('PSA_ALG_') and not parameter:
+            if name in ['PSA_ALG_ECDSA_BASE',
+                        'PSA_ALG_RSA_PKCS1V15_SIGN_BASE']:
+                # Ad hoc skipping of duplicate names for some numerical values
+                return
+            self.algorithms.add(name)
+            self.record_algorithm_subtype(name, expansion)
+        elif name.startswith('PSA_ALG_') and parameter == 'hash_alg':
+            self.algorithms_from_hash[name] = self.algorithm_tester(name)
+        elif name.startswith('PSA_KEY_USAGE_') and not parameter:
+            self.key_usage_flags.add(name)
+        else:
+            # Other macro without parameter
+            return
+
+    _nonascii_re = re.compile(rb'[^\x00-\x7f]+')
+    _continued_line_re = re.compile(rb'\\\r?\n\Z')
+    def read_file(self, header_file):
+        for line in header_file:
+            m = re.search(self._continued_line_re, line)
+            while m:
+                cont = next(header_file)
+                line = line[:m.start(0)] + cont
+                m = re.search(self._continued_line_re, line)
+            line = re.sub(self._nonascii_re, rb'', line).decode('ascii')
+            self.read_line(line)
+
+
+class InputsForTest(PSAMacroEnumerator):
+    # pylint: disable=too-many-instance-attributes
+    """Accumulate information about macros to test.
+enumerate
+    This includes macro names as well as information about their arguments
+    when applicable.
+    """
+
+    def __init__(self) -> None:
+        super().__init__()
+        self.all_declared = set() #type: Set[str]
+        # Identifier prefixes
+        self.table_by_prefix = {
+            'ERROR': self.statuses,
+            'ALG': self.algorithms,
+            'ECC_CURVE': self.ecc_curves,
+            'DH_GROUP': self.dh_groups,
+            'KEY_LIFETIME': self.lifetimes,
+            'KEY_LOCATION': self.locations,
+            'KEY_PERSISTENCE': self.persistence_levels,
+            'KEY_TYPE': self.key_types,
+            'KEY_USAGE': self.key_usage_flags,
+        } #type: Dict[str, Set[str]]
+        # Test functions
+        self.table_by_test_function = {
+            # Any function ending in _algorithm also gets added to
+            # self.algorithms.
+            'key_type': [self.key_types],
+            'block_cipher_key_type': [self.key_types],
+            'stream_cipher_key_type': [self.key_types],
+            'ecc_key_family': [self.ecc_curves],
+            'ecc_key_types': [self.ecc_curves],
+            'dh_key_family': [self.dh_groups],
+            'dh_key_types': [self.dh_groups],
+            'hash_algorithm': [self.hash_algorithms],
+            'mac_algorithm': [self.mac_algorithms],
+            'cipher_algorithm': [],
+            'hmac_algorithm': [self.mac_algorithms, self.sign_algorithms],
+            'aead_algorithm': [self.aead_algorithms],
+            'key_derivation_algorithm': [self.kdf_algorithms],
+            'key_agreement_algorithm': [self.ka_algorithms],
+            'asymmetric_signature_algorithm': [self.sign_algorithms],
+            'asymmetric_signature_wildcard': [self.algorithms],
+            'asymmetric_encryption_algorithm': [],
+            'other_algorithm': [],
+            'lifetime': [self.lifetimes],
+        } #type: Dict[str, List[Set[str]]]
+        self.arguments_for['mac_length'] += ['1', '63']
+        self.arguments_for['min_mac_length'] += ['1', '63']
+        self.arguments_for['tag_length'] += ['1', '63']
+        self.arguments_for['min_tag_length'] += ['1', '63']
+
+    def add_numerical_values(self) -> None:
+        """Add numerical values that are not supported to the known identifiers."""
+        # Sets of names per type
+        self.algorithms.add('0xffffffff')
+        self.ecc_curves.add('0xff')
+        self.dh_groups.add('0xff')
+        self.key_types.add('0xffff')
+        self.key_usage_flags.add('0x80000000')
+
+        # Hard-coded values for unknown algorithms
+        #
+        # These have to have values that are correct for their respective
+        # PSA_ALG_IS_xxx macros, but are also not currently assigned and are
+        # not likely to be assigned in the near future.
+        self.hash_algorithms.add('0x020000fe') # 0x020000ff is PSA_ALG_ANY_HASH
+        self.mac_algorithms.add('0x03007fff')
+        self.ka_algorithms.add('0x09fc0000')
+        self.kdf_algorithms.add('0x080000ff')
+        # For AEAD algorithms, the only variability is over the tag length,
+        # and this only applies to known algorithms, so don't test an
+        # unknown algorithm.
+
+    def get_names(self, type_word: str) -> Set[str]:
+        """Return the set of known names of values of the given type."""
+        return {
+            'status': self.statuses,
+            'algorithm': self.algorithms,
+            'ecc_curve': self.ecc_curves,
+            'dh_group': self.dh_groups,
+            'key_type': self.key_types,
+            'key_usage': self.key_usage_flags,
+        }[type_word]
+
+    # Regex for interesting header lines.
+    # Groups: 1=macro name, 2=type, 3=argument list (optional).
+    _header_line_re = \
+        re.compile(r'#define +' +
+                   r'(PSA_((?:(?:DH|ECC|KEY)_)?[A-Z]+)_\w+)' +
+                   r'(?:\(([^\n()]*)\))?')
+    # Regex of macro names to exclude.
+    _excluded_name_re = re.compile(r'_(?:GET|IS|OF)_|_(?:BASE|FLAG|MASK)\Z')
+    # Additional excluded macros.
+    _excluded_names = set([
+        # Macros that provide an alternative way to build the same
+        # algorithm as another macro.
+        'PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG',
+        'PSA_ALG_FULL_LENGTH_MAC',
+        # Auxiliary macro whose name doesn't fit the usual patterns for
+        # auxiliary macros.
+        'PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE',
+    ])
+    def parse_header_line(self, line: str) -> None:
+        """Parse a C header line, looking for "#define PSA_xxx"."""
+        m = re.match(self._header_line_re, line)
+        if not m:
+            return
+        name = m.group(1)
+        self.all_declared.add(name)
+        if re.search(self._excluded_name_re, name) or \
+           name in self._excluded_names or \
+           self.is_internal_name(name):
+            return
+        dest = self.table_by_prefix.get(m.group(2))
+        if dest is None:
+            return
+        dest.add(name)
+        if m.group(3):
+            self.argspecs[name] = self._argument_split(m.group(3))
+
+    _nonascii_re = re.compile(rb'[^\x00-\x7f]+') #type: Pattern
+    def parse_header(self, filename: str) -> None:
+        """Parse a C header file, looking for "#define PSA_xxx"."""
+        with read_file_lines(filename, binary=True) as lines:
+            for line in lines:
+                line = re.sub(self._nonascii_re, rb'', line).decode('ascii')
+                self.parse_header_line(line)
+
+    _macro_identifier_re = re.compile(r'[A-Z]\w+')
+    def generate_undeclared_names(self, expr: str) -> Iterable[str]:
+        for name in re.findall(self._macro_identifier_re, expr):
+            if name not in self.all_declared:
+                yield name
+
+    def accept_test_case_line(self, function: str, argument: str) -> bool:
+        #pylint: disable=unused-argument
+        undeclared = list(self.generate_undeclared_names(argument))
+        if undeclared:
+            raise Exception('Undeclared names in test case', undeclared)
+        return True
+
+    @staticmethod
+    def normalize_argument(argument: str) -> str:
+        """Normalize whitespace in the given C expression.
+
+        The result uses the same whitespace as
+        ` PSAMacroEnumerator.distribute_arguments`.
+        """
+        return re.sub(r',', r', ', re.sub(r' +', r'', argument))
+
+    def add_test_case_line(self, function: str, argument: str) -> None:
+        """Parse a test case data line, looking for algorithm metadata tests."""
+        sets = []
+        if function.endswith('_algorithm'):
+            sets.append(self.algorithms)
+            if function == 'key_agreement_algorithm' and \
+               argument.startswith('PSA_ALG_KEY_AGREEMENT('):
+                # We only want *raw* key agreement algorithms as such, so
+                # exclude ones that are already chained with a KDF.
+                # Keep the expression as one to test as an algorithm.
+                function = 'other_algorithm'
+        sets += self.table_by_test_function[function]
+        if self.accept_test_case_line(function, argument):
+            for s in sets:
+                s.add(self.normalize_argument(argument))
+
+    # Regex matching a *.data line containing a test function call and
+    # its arguments. The actual definition is partly positional, but this
+    # regex is good enough in practice.
+    _test_case_line_re = re.compile(r'(?!depends_on:)(\w+):([^\n :][^:\n]*)')
+    def parse_test_cases(self, filename: str) -> None:
+        """Parse a test case file (*.data), looking for algorithm metadata tests."""
+        with read_file_lines(filename) as lines:
+            for line in lines:
+                m = re.match(self._test_case_line_re, line)
+                if m:
+                    self.add_test_case_line(m.group(1), m.group(2))
diff --git a/third_party/mbedtls/repo/scripts/mbedtls_dev/psa_storage.py b/third_party/mbedtls/repo/scripts/mbedtls_dev/psa_storage.py
new file mode 100644
index 0000000..45f0380
--- /dev/null
+++ b/third_party/mbedtls/repo/scripts/mbedtls_dev/psa_storage.py
@@ -0,0 +1,203 @@
+"""Knowledge about the PSA key store as implemented in 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.
+
+import re
+import struct
+from typing import Dict, List, Optional, Set, Union
+import unittest
+
+from mbedtls_dev import c_build_helper
+
+
+class Expr:
+    """Representation of a C expression with a known or knowable numerical value."""
+
+    def __init__(self, content: Union[int, str]):
+        if isinstance(content, int):
+            digits = 8 if content > 0xffff else 4
+            self.string = '{0:#0{1}x}'.format(content, digits + 2)
+            self.value_if_known = content #type: Optional[int]
+        else:
+            self.string = content
+            self.unknown_values.add(self.normalize(content))
+            self.value_if_known = None
+
+    value_cache = {} #type: Dict[str, int]
+    """Cache of known values of expressions."""
+
+    unknown_values = set() #type: Set[str]
+    """Expressions whose values are not present in `value_cache` yet."""
+
+    def update_cache(self) -> None:
+        """Update `value_cache` for expressions registered in `unknown_values`."""
+        expressions = sorted(self.unknown_values)
+        values = c_build_helper.get_c_expression_values(
+            'unsigned long', '%lu',
+            expressions,
+            header="""
+            #include <psa/crypto.h>
+            """,
+            include_path=['include']) #type: List[str]
+        for e, v in zip(expressions, values):
+            self.value_cache[e] = int(v, 0)
+        self.unknown_values.clear()
+
+    @staticmethod
+    def normalize(string: str) -> str:
+        """Put the given C expression in a canonical form.
+
+        This function is only intended to give correct results for the
+        relatively simple kind of C expression typically used with this
+        module.
+        """
+        return re.sub(r'\s+', r'', string)
+
+    def value(self) -> int:
+        """Return the numerical value of the expression."""
+        if self.value_if_known is None:
+            if re.match(r'([0-9]+|0x[0-9a-f]+)\Z', self.string, re.I):
+                return int(self.string, 0)
+            normalized = self.normalize(self.string)
+            if normalized not in self.value_cache:
+                self.update_cache()
+            self.value_if_known = self.value_cache[normalized]
+        return self.value_if_known
+
+Exprable = Union[str, int, Expr]
+"""Something that can be converted to a C expression with a known numerical value."""
+
+def as_expr(thing: Exprable) -> Expr:
+    """Return an `Expr` object for `thing`.
+
+    If `thing` is already an `Expr` object, return it. Otherwise build a new
+    `Expr` object from `thing`. `thing` can be an integer or a string that
+    contains a C expression.
+    """
+    if isinstance(thing, Expr):
+        return thing
+    else:
+        return Expr(thing)
+
+
+class Key:
+    """Representation of a PSA crypto key object and its storage encoding.
+    """
+
+    LATEST_VERSION = 0
+    """The latest version of the storage format."""
+
+    def __init__(self, *,
+                 version: Optional[int] = None,
+                 id: Optional[int] = None, #pylint: disable=redefined-builtin
+                 lifetime: Exprable = 'PSA_KEY_LIFETIME_PERSISTENT',
+                 type: Exprable, #pylint: disable=redefined-builtin
+                 bits: int,
+                 usage: Exprable, alg: Exprable, alg2: Exprable,
+                 material: bytes #pylint: disable=used-before-assignment
+                ) -> None:
+        self.version = self.LATEST_VERSION if version is None else version
+        self.id = id #pylint: disable=invalid-name #type: Optional[int]
+        self.lifetime = as_expr(lifetime) #type: Expr
+        self.type = as_expr(type) #type: Expr
+        self.bits = bits #type: int
+        self.usage = as_expr(usage) #type: Expr
+        self.alg = as_expr(alg) #type: Expr
+        self.alg2 = as_expr(alg2) #type: Expr
+        self.material = material #type: bytes
+
+    MAGIC = b'PSA\000KEY\000'
+
+    @staticmethod
+    def pack(
+            fmt: str,
+            *args: Union[int, Expr]
+    ) -> bytes: #pylint: disable=used-before-assignment
+        """Pack the given arguments into a byte string according to the given format.
+
+        This function is similar to `struct.pack`, but with the following differences:
+        * All integer values are encoded with standard sizes and in
+          little-endian representation. `fmt` must not include an endianness
+          prefix.
+        * Arguments can be `Expr` objects instead of integers.
+        * Only integer-valued elements are supported.
+        """
+        return struct.pack('<' + fmt, # little-endian, standard sizes
+                           *[arg.value() if isinstance(arg, Expr) else arg
+                             for arg in args])
+
+    def bytes(self) -> bytes:
+        """Return the representation of the key in storage as a byte array.
+
+        This is the content of the PSA storage file. When PSA storage is
+        implemented over stdio files, this does not include any wrapping made
+        by the PSA-storage-over-stdio-file implementation.
+        """
+        header = self.MAGIC + self.pack('L', self.version)
+        if self.version == 0:
+            attributes = self.pack('LHHLLL',
+                                   self.lifetime, self.type, self.bits,
+                                   self.usage, self.alg, self.alg2)
+            material = self.pack('L', len(self.material)) + self.material
+        else:
+            raise NotImplementedError
+        return header + attributes + material
+
+    def hex(self) -> str:
+        """Return the representation of the key as a hexadecimal string.
+
+        This is the hexadecimal representation of `self.bytes`.
+        """
+        return self.bytes().hex()
+
+    def location_value(self) -> int:
+        """The numerical value of the location encoded in the key's lifetime."""
+        return self.lifetime.value() >> 8
+
+
+class TestKey(unittest.TestCase):
+    # pylint: disable=line-too-long
+    """A few smoke tests for the functionality of the `Key` class."""
+
+    def test_numerical(self):
+        key = Key(version=0,
+                  id=1, lifetime=0x00000001,
+                  type=0x2400, bits=128,
+                  usage=0x00000300, alg=0x05500200, alg2=0x04c01000,
+                  material=b'@ABCDEFGHIJKLMNO')
+        expected_hex = '505341004b45590000000000010000000024800000030000000250050010c00410000000404142434445464748494a4b4c4d4e4f'
+        self.assertEqual(key.bytes(), bytes.fromhex(expected_hex))
+        self.assertEqual(key.hex(), expected_hex)
+
+    def test_names(self):
+        length = 0xfff8 // 8 # PSA_MAX_KEY_BITS in bytes
+        key = Key(version=0,
+                  id=1, lifetime='PSA_KEY_LIFETIME_PERSISTENT',
+                  type='PSA_KEY_TYPE_RAW_DATA', bits=length*8,
+                  usage=0, alg=0, alg2=0,
+                  material=b'\x00' * length)
+        expected_hex = '505341004b45590000000000010000000110f8ff000000000000000000000000ff1f0000' + '00' * length
+        self.assertEqual(key.bytes(), bytes.fromhex(expected_hex))
+        self.assertEqual(key.hex(), expected_hex)
+
+    def test_defaults(self):
+        key = Key(type=0x1001, bits=8,
+                  usage=0, alg=0, alg2=0,
+                  material=b'\x2a')
+        expected_hex = '505341004b455900000000000100000001100800000000000000000000000000010000002a'
+        self.assertEqual(key.bytes(), bytes.fromhex(expected_hex))
+        self.assertEqual(key.hex(), expected_hex)
diff --git a/third_party/mbedtls/repo/scripts/mbedtls_dev/test_case.py b/third_party/mbedtls/repo/scripts/mbedtls_dev/test_case.py
new file mode 100644
index 0000000..6a46e42
--- /dev/null
+++ b/third_party/mbedtls/repo/scripts/mbedtls_dev/test_case.py
@@ -0,0 +1,100 @@
+"""Library for generating Mbed TLS test data.
+"""
+
+# 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.
+
+import binascii
+import os
+import sys
+from typing import Iterable, List, Optional
+
+from mbedtls_dev import typing_util
+
+def hex_string(data: bytes) -> str:
+    return '"' + binascii.hexlify(data).decode('ascii') + '"'
+
+
+class MissingDescription(Exception):
+    pass
+
+class MissingFunction(Exception):
+    pass
+
+class TestCase:
+    """An Mbed TLS test case."""
+
+    def __init__(self, description: Optional[str] = None):
+        self.comments = [] #type: List[str]
+        self.description = description #type: Optional[str]
+        self.dependencies = [] #type: List[str]
+        self.function = None #type: Optional[str]
+        self.arguments = [] #type: List[str]
+
+    def add_comment(self, *lines: str) -> None:
+        self.comments += lines
+
+    def set_description(self, description: str) -> None:
+        self.description = description
+
+    def set_dependencies(self, dependencies: List[str]) -> None:
+        self.dependencies = dependencies
+
+    def set_function(self, function: str) -> None:
+        self.function = function
+
+    def set_arguments(self, arguments: List[str]) -> None:
+        self.arguments = arguments
+
+    def check_completeness(self) -> None:
+        if self.description is None:
+            raise MissingDescription
+        if self.function is None:
+            raise MissingFunction
+
+    def write(self, out: typing_util.Writable) -> None:
+        """Write the .data file paragraph for this test case.
+
+        The output starts and ends with a single newline character. If the
+        surrounding code writes lines (consisting of non-newline characters
+        and a final newline), you will end up with a blank line before, but
+        not after the test case.
+        """
+        self.check_completeness()
+        assert self.description is not None # guide mypy
+        assert self.function is not None # guide mypy
+        out.write('\n')
+        for line in self.comments:
+            out.write('# ' + line + '\n')
+        out.write(self.description + '\n')
+        if self.dependencies:
+            out.write('depends_on:' + ':'.join(self.dependencies) + '\n')
+        out.write(self.function + ':' + ':'.join(self.arguments) + '\n')
+
+def write_data_file(filename: str,
+                    test_cases: Iterable[TestCase],
+                    caller: Optional[str] = None) -> None:
+    """Write the test cases to the specified file.
+
+    If the file already exists, it is overwritten.
+    """
+    if caller is None:
+        caller = os.path.basename(sys.argv[0])
+    with open(filename, 'w') as out:
+        out.write('# Automatically generated by {}. Do not edit!\n'
+                  .format(caller))
+        for tc in test_cases:
+            tc.write(out)
+        out.write('\n# End of automatically generated file.\n')
diff --git a/third_party/mbedtls/repo/scripts/mbedtls_dev/typing_util.py b/third_party/mbedtls/repo/scripts/mbedtls_dev/typing_util.py
new file mode 100644
index 0000000..4c34449
--- /dev/null
+++ b/third_party/mbedtls/repo/scripts/mbedtls_dev/typing_util.py
@@ -0,0 +1,39 @@
+"""Auxiliary definitions used in type annotations.
+"""
+
+# 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.
+
+from typing import Any
+
+# The typing_extensions module is necessary for type annotations that are
+# checked with mypy. It is only used for type annotations or to define
+# things that are themselves only used for type annotations. It is not
+# available on a default Python installation. Therefore, try loading
+# what we need from it for the sake of mypy (which depends on, or comes
+# with, typing_extensions), and if not define substitutes that lack the
+# static type information but are good enough at runtime.
+try:
+    from typing_extensions import Protocol #pylint: disable=import-error
+except ImportError:
+    class Protocol: #type: ignore
+        #pylint: disable=too-few-public-methods
+        pass
+
+class Writable(Protocol):
+    """Abstract class for typing hints."""
+    # pylint: disable=no-self-use,too-few-public-methods,unused-argument
+    def write(self, text: str) -> Any:
+        ...
diff --git a/third_party/mbedtls/repo/scripts/min_requirements.py b/third_party/mbedtls/repo/scripts/min_requirements.py
new file mode 100755
index 0000000..eecab1c
--- /dev/null
+++ b/third_party/mbedtls/repo/scripts/min_requirements.py
@@ -0,0 +1,138 @@
+#!/usr/bin/env python3
+"""Install all the required Python packages, with the minimum Python version.
+"""
+
+# 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.
+
+import argparse
+import os
+import re
+import subprocess
+import sys
+import tempfile
+import typing
+
+from typing import List, Optional
+from mbedtls_dev import typing_util
+
+def pylint_doesn_t_notice_that_certain_types_are_used_in_annotations(
+        _list: List[typing.Any],
+) -> None:
+    pass
+
+
+class Requirements:
+    """Collect and massage Python requirements."""
+
+    def __init__(self) -> None:
+        self.requirements = [] #type: List[str]
+
+    def adjust_requirement(self, req: str) -> str:
+        """Adjust a requirement to the minimum specified version."""
+        # allow inheritance #pylint: disable=no-self-use
+        # If a requirement specifies a minimum version, impose that version.
+        req = re.sub(r'>=|~=', r'==', req)
+        return req
+
+    def add_file(self, filename: str) -> None:
+        """Add requirements from the specified file.
+
+        This method supports a subset of pip's requirement file syntax:
+        * One requirement specifier per line, which is passed to
+          `adjust_requirement`.
+        * Comments (``#`` at the beginning of the line or after whitespace).
+        * ``-r FILENAME`` to include another file.
+        """
+        for line in open(filename):
+            line = line.strip()
+            line = re.sub(r'(\A|\s+)#.*', r'', line)
+            if not line:
+                continue
+            m = re.match(r'-r\s+', line)
+            if m:
+                nested_file = os.path.join(os.path.dirname(filename),
+                                           line[m.end(0):])
+                self.add_file(nested_file)
+                continue
+            self.requirements.append(self.adjust_requirement(line))
+
+    def write(self, out: typing_util.Writable) -> None:
+        """List the gathered requirements."""
+        for req in self.requirements:
+            out.write(req + '\n')
+
+    def install(
+            self,
+            pip_general_options: Optional[List[str]] = None,
+            pip_install_options: Optional[List[str]] = None,
+    ) -> None:
+        """Call pip to install the requirements."""
+        if pip_general_options is None:
+            pip_general_options = []
+        if pip_install_options is None:
+            pip_install_options = []
+        with tempfile.TemporaryDirectory() as temp_dir:
+            # This is more complicated than it needs to be for the sake
+            # of Windows. Use a temporary file rather than the command line
+            # to avoid quoting issues. Use a temporary directory rather
+            # than NamedTemporaryFile because with a NamedTemporaryFile on
+            # Windows, the subprocess can't open the file because this process
+            # has an exclusive lock on it.
+            req_file_name = os.path.join(temp_dir, 'requirements.txt')
+            with open(req_file_name, 'w') as req_file:
+                self.write(req_file)
+            subprocess.check_call([sys.executable, '-m', 'pip'] +
+                                  pip_general_options +
+                                  ['install'] + pip_install_options +
+                                  ['-r', req_file_name])
+
+DEFAULT_REQUIREMENTS_FILE = 'ci.requirements.txt'
+
+def main() -> None:
+    """Command line entry point."""
+    parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument('--no-act', '-n',
+                        action='store_true',
+                        help="Don't act, just print what will be done")
+    parser.add_argument('--pip-install-option',
+                        action='append', dest='pip_install_options',
+                        help="Pass this option to pip install")
+    parser.add_argument('--pip-option',
+                        action='append', dest='pip_general_options',
+                        help="Pass this general option to pip")
+    parser.add_argument('--user',
+                        action='append_const', dest='pip_install_options',
+                        const='--user',
+                        help="Install to the Python user install directory"
+                             " (short for --pip-install-option --user)")
+    parser.add_argument('files', nargs='*', metavar='FILE',
+                        help="Requirement files"
+                             " (default: {} in the script's directory)" \
+                             .format(DEFAULT_REQUIREMENTS_FILE))
+    options = parser.parse_args()
+    if not options.files:
+        options.files = [os.path.join(os.path.dirname(__file__),
+                                      DEFAULT_REQUIREMENTS_FILE)]
+    reqs = Requirements()
+    for filename in options.files:
+        reqs.add_file(filename)
+    reqs.write(sys.stdout)
+    if not options.no_act:
+        reqs.install(pip_general_options=options.pip_general_options,
+                     pip_install_options=options.pip_install_options)
+
+if __name__ == '__main__':
+    main()
diff --git a/third_party/mbedtls/repo/scripts/windows_msbuild.bat b/third_party/mbedtls/repo/scripts/windows_msbuild.bat
index cfb5f01..e419931 100644
--- a/third_party/mbedtls/repo/scripts/windows_msbuild.bat
+++ b/third_party/mbedtls/repo/scripts/windows_msbuild.bat
@@ -1,20 +1,20 @@
-@rem Build and test Mbed TLS with Visual Studio using msbuild.
-@rem Usage: windows_msbuild [RETARGET]
-@rem   RETARGET: version of Visual Studio to emulate
-@rem             https://docs.microsoft.com/en-us/cpp/build/how-to-modify-the-target-framework-and-platform-toolset
-
-@rem These parameters are hard-coded for now.
-set "arch=x64" & @rem "x86" or "x64"
-set "cfg=Release" & @rem "Debug" or "Release"
-set "vcvarsall=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat"
-
-if not "%~1"=="" set "retarget=,PlatformToolset=%1"
-
-@rem If the %USERPROFILE%\Source directory exists, then running
-@rem vcvarsall.bat will silently change the directory to that directory.
-@rem Setting the VSCMD_START_DIR environment variable causes it to change
-@rem to that directory instead.
-set "VSCMD_START_DIR=%~dp0\..\visualc\VS2010"
-
-"%vcvarsall%" x64 && ^
-msbuild /t:Rebuild /p:Configuration=%cfg%%retarget% /m mbedTLS.sln
+@rem Build and test Mbed TLS with Visual Studio using msbuild.

+@rem Usage: windows_msbuild [RETARGET]

+@rem   RETARGET: version of Visual Studio to emulate

+@rem             https://docs.microsoft.com/en-us/cpp/build/how-to-modify-the-target-framework-and-platform-toolset

+

+@rem These parameters are hard-coded for now.

+set "arch=x64" & @rem "x86" or "x64"

+set "cfg=Release" & @rem "Debug" or "Release"

+set "vcvarsall=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat"

+

+if not "%~1"=="" set "retarget=,PlatformToolset=%1"

+

+@rem If the %USERPROFILE%\Source directory exists, then running

+@rem vcvarsall.bat will silently change the directory to that directory.

+@rem Setting the VSCMD_START_DIR environment variable causes it to change

+@rem to that directory instead.

+set "VSCMD_START_DIR=%~dp0\..\visualc\VS2010"

+

+"%vcvarsall%" x64 && ^

+msbuild /t:Rebuild /p:Configuration=%cfg%%retarget% /m mbedTLS.sln

diff --git a/third_party/mbedtls/repo/tests/.gitignore b/third_party/mbedtls/repo/tests/.gitignore
index d9f4b51..8f7315d 100644
--- a/third_party/mbedtls/repo/tests/.gitignore
+++ b/third_party/mbedtls/repo/tests/.gitignore
@@ -13,3 +13,5 @@
 src/*.o
 src/drivers/*.o
 src/libmbed*
+
+libtestdriver1/*
diff --git a/third_party/mbedtls/repo/tests/CMakeLists.txt b/third_party/mbedtls/repo/tests/CMakeLists.txt
index f8ce925..f861272 100644
--- a/third_party/mbedtls/repo/tests/CMakeLists.txt
+++ b/third_party/mbedtls/repo/tests/CMakeLists.txt
@@ -67,6 +67,10 @@
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function")
 endif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
 
+if(CMAKE_COMPILER_IS_CLANG)
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wdocumentation -Wno-documentation-deprecated-sync -Wunreachable-code")
+endif(CMAKE_COMPILER_IS_CLANG)
+
 if(MSVC)
     # If a warning level has been defined, suppress all warnings for test code
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W0")
@@ -130,6 +134,8 @@
 add_test_suite(mdx)
 add_test_suite(memory_buffer_alloc)
 add_test_suite(mpi)
+add_test_suite(mps)
+add_test_suite(net)
 add_test_suite(nist_kw)
 add_test_suite(oid)
 add_test_suite(pem)
@@ -137,19 +143,27 @@
 add_test_suite(pkcs1_v15)
 add_test_suite(pkcs1_v21)
 add_test_suite(pkcs5)
+add_test_suite(pkcs12)
 add_test_suite(pkparse)
 add_test_suite(pkwrite)
 add_test_suite(poly1305)
 add_test_suite(psa_crypto)
+add_test_suite(psa_crypto_attributes)
 add_test_suite(psa_crypto_entropy)
 add_test_suite(psa_crypto_hash)
 add_test_suite(psa_crypto_init)
 add_test_suite(psa_crypto_metadata)
+add_test_suite(psa_crypto_not_supported psa_crypto_not_supported.generated)
+add_test_suite(psa_crypto_not_supported psa_crypto_not_supported.misc)
 add_test_suite(psa_crypto_persistent_key)
 add_test_suite(psa_crypto_se_driver_hal)
 add_test_suite(psa_crypto_se_driver_hal_mocks)
 add_test_suite(psa_crypto_slot_management)
+add_test_suite(psa_crypto_storage_format psa_crypto_storage_format.misc)
+add_test_suite(psa_crypto_storage_format psa_crypto_storage_format.current)
+add_test_suite(psa_crypto_storage_format psa_crypto_storage_format.v0)
 add_test_suite(psa_its)
+add_test_suite(random)
 add_test_suite(rsa)
 add_test_suite(shax)
 add_test_suite(ssl)
diff --git a/third_party/mbedtls/repo/tests/Makefile b/third_party/mbedtls/repo/tests/Makefile
index 511db9d..6e232c9 100644
--- a/third_party/mbedtls/repo/tests/Makefile
+++ b/third_party/mbedtls/repo/tests/Makefile
@@ -3,9 +3,12 @@
 # To compile with PKCS11: add "-lpkcs11-helper" to LDFLAGS
 
 CFLAGS	?= -O2
-WARNING_CFLAGS ?= -Wall -Wextra
+WARNING_CFLAGS ?= -Wall -Wextra -Wformat=2 -Wno-format-nonliteral
 LDFLAGS ?=
 
+# Set this to -v to see the details of failing test cases
+TEST_FLAGS ?= $(if $(filter-out 0 OFF Off off NO No no FALSE False false N n,$(CTEST_OUTPUT_ON_FAILURE)),-v,)
+
 # Include public header files from ../include, test-specific header files
 # from ./include, and private header files (used by some invasive tests)
 # from ../library.
@@ -49,13 +52,16 @@
 ifdef SHARED
 SHARED_SUFFIX=.$(DLEXT)
 endif
-PYTHON ?= python
 else
 DLEXT ?= so
 EXEXT=
 SHARED_SUFFIX=
-# python2 for POSIX since FreeBSD has only python2 as default.
-PYTHON ?= python2
+endif
+
+ifdef WINDOWS
+PYTHON ?= python
+else
+PYTHON ?= $(shell if type python3 >/dev/null 2>/dev/null; then echo python3; else echo python; fi)
 endif
 
 # Zlib shared library extensions:
@@ -84,8 +90,16 @@
 
 mbedtls_test: $(MBEDTLS_TEST_OBJS)
 
+TEST_OBJS_DEPS = $(wildcard include/test/*.h include/test/*/*.h)
+ifdef RECORD_PSA_STATUS_COVERAGE_LOG
+# Explicitly depend on this header because on a clean copy of the source tree,
+# it doesn't exist yet and must be generated as part of the build, and
+# therefore the wildcard enumeration above doesn't include it.
+TEST_OBJS_DEPS += include/test/instrument_record_status.h
+endif
+
 # Rule to compile common test C files in src folder
-src/%.o : src/%.c
+src/%.o : src/%.c $(TEST_OBJS_DEPS)
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $<
 
@@ -121,20 +135,16 @@
 		-o .
 
 
-$(BINARIES): %$(EXEXT): %.c $(MBEDLIBS) $(MBEDTLS_TEST_OBJS)
+$(BINARIES): %$(EXEXT): %.c $(MBEDLIBS) $(TEST_OBJS_DEPS) $(MBEDTLS_TEST_OBJS)
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $< $(MBEDTLS_TEST_OBJS) $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
-# Some test suites require additional header files.
-$(filter test_suite_psa_crypto%, $(BINARIES)): include/test/psa_crypto_helpers.h
-$(addprefix embedded_,$(filter test_suite_psa_crypto%, $(APPS))): embedded_%: TESTS/mbedtls/%/psa_crypto_helpers.h
-$(filter test_suite_psa_%, $(BINARIES)): include/test/psa_helpers.h
-$(addprefix embedded_,$(filter test_suite_psa_%, $(APPS))): embedded_%: TESTS/mbedtls/%/psa_helpers.h
-
 clean:
 ifndef WINDOWS
-	rm -rf $(BINARIES) *.c *.datax TESTS
+	rm -rf $(BINARIES) *.c *.datax
 	rm -f src/*.o src/drivers/*.o src/libmbed*
+	rm -f include/test/instrument_record_status.h
+	rm -rf libtestdriver1
 else
 	if exist *.c del /Q /F *.c
 	if exist *.exe del /Q /F *.exe
@@ -142,52 +152,61 @@
 	if exist src/*.o del /Q /F src/*.o
 	if exist src/drivers/*.o del /Q /F src/drivers/*.o
 	if exist src/libmbed* del /Q /F src/libmed*
-ifneq ($(wildcard TESTS/.*),)
-	rmdir /Q /S TESTS
-endif
+	if exist include/test/instrument_record_status.h del /Q /F include/test/instrument_record_status.h
 endif
 
 # Test suites caught by SKIP_TEST_SUITES are built but not executed.
 check: $(BINARIES)
-	perl scripts/run-test-suites.pl --skip=$(SKIP_TEST_SUITES)
+	perl scripts/run-test-suites.pl $(TEST_FLAGS) --skip=$(SKIP_TEST_SUITES)
 
 test: check
 
-# Create separate targets for generating embedded tests.
-EMBEDDED_TESTS := $(addprefix embedded_,$(APPS))
+# Generate test library
 
-# Generate test code for target.
-
-.SECONDEXPANSION:
-$(EMBEDDED_TESTS): embedded_%: suites/$$(firstword $$(subst ., ,$$*)).function suites/%.data scripts/generate_test_code.py suites/helpers.function suites/main_test.function suites/target_test.function
-	echo "  Gen  ./TESTS/mbedtls/$*/$*.c"
-	$(PYTHON) scripts/generate_test_code.py -f suites/$(firstword $(subst ., ,$*)).function \
-		-d suites/$*.data \
-		-t suites/main_test.function \
-		-p suites/target_test.function \
-		-s suites  \
-		--helpers-file suites/helpers.function \
-		-o ./TESTS/mbedtls/$*
-
-generate-target-tests: $(EMBEDDED_TESTS)
-
-define copy_header_to_target
-TESTS/mbedtls/$(1)/$(2): include/test/$(2)
-	echo "  Copy ./$$@"
-ifndef WINDOWS
-	mkdir -p $$(@D)
-	cp $$< $$@
-else
-	mkdir $$(@D)
-	copy $$< $$@
-endif
-
+# Perl code that is executed to transform each original line from a library
+# source file into the corresponding line in the test driver copy of the
+# library. Add a LIBTESTDRIVER1_/libtestdriver1_ to mbedtls_xxx and psa_xxx
+# symbols.
+define libtestdriver1_rewrite :=
+	s!^(\s*#\s*include\s*[\"<])(mbedtls|psa)/!$${1}libtestdriver1/include/$${2}/!; \
+	next if /^\s*#\s*include/; \
+	s/\b(?=MBEDTLS_|PSA_)/LIBTESTDRIVER1_/g; \
+	s/\b(?=mbedtls_|psa_)/libtestdriver1_/g;
 endef
-$(foreach app, $(APPS), $(foreach file, $(notdir $(wildcard include/test/*.h)), \
-	$(eval $(call copy_header_to_target,$(app),$(file)))))
+
+libtestdriver1.a:
+	# Copy the library and fake a 3rdparty Makefile include.
+	rm -Rf ./libtestdriver1
+	mkdir ./libtestdriver1
+	cp -Rf ../library ./libtestdriver1
+	cp -Rf ../include ./libtestdriver1
+	mkdir ./libtestdriver1/3rdparty
+	touch ./libtestdriver1/3rdparty/Makefile.inc
+
+	# Set the test driver base (minimal) configuration.
+	cp ./include/test/drivers/config_test_driver.h ./libtestdriver1/include/mbedtls/config.h
+
+	# Set the PSA cryptography configuration for the test library.
+	# It is set from the copied include/psa/crypto_config.h of the Mbed TLS
+        # library the test library is intended to be linked with extended by
+        # ./include/test/drivers/crypto_config_test_driver_extension.h to
+        # mirror the PSA_ACCEL_* macros.
+	mv ./libtestdriver1/include/psa/crypto_config.h ./libtestdriver1/include/psa/crypto_config.h.bak
+	head -n -1 ./libtestdriver1/include/psa/crypto_config.h.bak > ./libtestdriver1/include/psa/crypto_config.h
+	cat ./include/test/drivers/crypto_config_test_driver_extension.h >> ./libtestdriver1/include/psa/crypto_config.h
+	echo "#endif /* PSA_CRYPTO_CONFIG_H */" >> ./libtestdriver1/include/psa/crypto_config.h
+
+	# Prefix MBEDTLS_* PSA_* symbols with LIBTESTDRIVER1_ as well as
+	# mbedtls_* psa_* symbols with libtestdriver1_ to avoid symbol clash
+	# when this test driver library is linked with the Mbed TLS library.
+	perl -pi -e '$(libtestdriver1_rewrite)' ./libtestdriver1/library/*.[ch]
+	perl -pi -e '$(libtestdriver1_rewrite)' ./libtestdriver1/include/*/*.h
+
+	$(MAKE) -C ./libtestdriver1/library CFLAGS="-I../../ $(CFLAGS)" LDFLAGS="$(LDFLAGS)" libmbedcrypto.a
+	cp ./libtestdriver1/library/libmbedcrypto.a ../library/libtestdriver1.a
 
 ifdef RECORD_PSA_STATUS_COVERAGE_LOG
-$(BINARIES): include/test/instrument_record_status.h
 include/test/instrument_record_status.h: ../include/psa/crypto.h Makefile
+	echo "  Gen  $@"
 	sed <../include/psa/crypto.h >$@ -n 's/^psa_status_t \([A-Za-z0-9_]*\)(.*/#define \1(...) RECORD_STATUS("\1", \1(__VA_ARGS__))/p'
 endif
diff --git a/third_party/mbedtls/repo/tests/compat.sh b/third_party/mbedtls/repo/tests/compat.sh
index 6e0a8f9..444c80c 100755
--- a/third_party/mbedtls/repo/tests/compat.sh
+++ b/third_party/mbedtls/repo/tests/compat.sh
@@ -67,7 +67,7 @@
 fi
 
 # default values for options
-MODES="tls1 tls1_1 tls1_2 dtls1 dtls1_2"
+MODES="tls1 tls1_1 tls12 dtls1 dtls12"
 VERIFIES="NO YES"
 TYPES="ECDSA RSA PSK"
 FILTER=""
@@ -156,7 +156,7 @@
 # is_dtls <mode>
 is_dtls()
 {
-    test "$1" = "dtls1" -o "$1" = "dtls1_2"
+    test "$1" = "dtls1" -o "$1" = "dtls12"
 }
 
 # minor_ver <mode>
@@ -172,7 +172,7 @@
         tls1_1|dtls1)
             echo 2
             ;;
-        tls1_2|dtls1_2)
+        tls12|dtls12)
             echo 3
             ;;
         *)
@@ -881,14 +881,14 @@
         "tls1_1")
             G_PRIO_MODE="+VERS-TLS1.1"
             ;;
-        "tls1_2")
+        "tls12")
             G_PRIO_MODE="+VERS-TLS1.2"
             ;;
         "dtls1")
             G_PRIO_MODE="+VERS-DTLS1.0"
             G_MODE="-u"
             ;;
-        "dtls1_2")
+        "dtls12")
             G_PRIO_MODE="+VERS-DTLS1.2"
             G_MODE="-u"
             ;;
@@ -905,10 +905,23 @@
     fi
 
     M_SERVER_ARGS="server_port=$PORT server_addr=0.0.0.0 force_version=$MODE arc4=1"
-    O_SERVER_ARGS="-accept $PORT -cipher NULL,ALL -$MODE -dhparam data_files/dhparams.pem"
+    O_SERVER_ARGS="-accept $PORT -cipher NULL,ALL -$MODE"
     G_SERVER_ARGS="-p $PORT --http $G_MODE"
     G_SERVER_PRIO="NORMAL:${G_PRIO_CCM}+ARCFOUR-128:+NULL:+MD5:+PSK:+DHE-PSK:+ECDHE-PSK:+SHA256:+SHA384:+RSA-PSK:-VERS-TLS-ALL:$G_PRIO_MODE"
 
+    # The default prime for `openssl s_server` depends on the version:
+    # * OpenSSL <= 1.0.2a: 512-bit
+    # * OpenSSL 1.0.2b to 1.1.1b: 1024-bit
+    # * OpenSSL >= 1.1.1c: 2048-bit
+    # Mbed TLS wants >=1024, so force that for older versions. Don't force
+    # it for newer versions, which reject a 1024-bit prime. Indifferently
+    # force it or not for intermediate versions.
+    case $($OPENSSL_CMD version) in
+        "OpenSSL 1.0"*)
+            O_SERVER_ARGS="$O_SERVER_ARGS -dhparam data_files/dhparams.pem"
+            ;;
+    esac
+
     # with OpenSSL 1.0.1h, -www, -WWW and -HTTP break DTLS handshakes
     if is_dtls "$MODE"; then
         O_SERVER_ARGS="$O_SERVER_ARGS"
diff --git a/third_party/mbedtls/repo/tests/configs/user-config-for-test.h b/third_party/mbedtls/repo/tests/configs/user-config-for-test.h
new file mode 100644
index 0000000..6e7c154
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/configs/user-config-for-test.h
@@ -0,0 +1,59 @@
+/* MBEDTLS_USER_CONFIG_FILE for testing.
+ * Only used for a few test configurations.
+ *
+ * Typical usage (note multiple levels of quoting):
+ *     make CFLAGS="'-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/user-config-for-test.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.
+ */
+
+#if defined(PSA_CRYPTO_DRIVER_TEST_ALL)
+
+/* Enable the use of the test driver in the library, and build the generic
+ * part of the test driver. */
+#define PSA_CRYPTO_DRIVER_TEST
+
+/* Use the accelerator driver for all cryptographic mechanisms for which
+ * the test driver implemented. */
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_AES
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR
+#define MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING
+#define MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7
+#define MBEDTLS_PSA_ACCEL_ALG_CTR
+#define MBEDTLS_PSA_ACCEL_ALG_CFB
+#define MBEDTLS_PSA_ACCEL_ALG_ECDSA
+#define MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA
+#define MBEDTLS_PSA_ACCEL_ALG_MD2
+#define MBEDTLS_PSA_ACCEL_ALG_MD4
+#define MBEDTLS_PSA_ACCEL_ALG_MD5
+#define MBEDTLS_PSA_ACCEL_ALG_OFB
+#define MBEDTLS_PSA_ACCEL_ALG_RIPEMD160
+#define MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN
+#define MBEDTLS_PSA_ACCEL_ALG_RSA_PSS
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_1
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_224
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_256
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_384
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_512
+#define MBEDTLS_PSA_ACCEL_ALG_XTS
+#define MBEDTLS_PSA_ACCEL_ALG_CMAC
+#define MBEDTLS_PSA_ACCEL_ALG_HMAC
+
+#endif  /* PSA_CRYPTO_DRIVER_TEST_ALL */
diff --git a/third_party/mbedtls/repo/tests/data_files/Makefile b/third_party/mbedtls/repo/tests/data_files/Makefile
index b90ce74..f3cba5a 100644
--- a/third_party/mbedtls/repo/tests/data_files/Makefile
+++ b/third_party/mbedtls/repo/tests/data_files/Makefile
@@ -1018,6 +1018,14 @@
 	$(OPENSSL) x509 -inform PEM -in $< -outform DER -out $@
 all_final += server1.v1.crt server1.v1.der
 
+server1.ca.crt: server1.key server1.req.sha256 $(test_ca_crt) $(test_ca_key_file_rsa)
+	$(MBEDTLS_CERT_WRITE) request_file=server1.req.sha256 issuer_crt=$(test_ca_crt) issuer_key=$(test_ca_key_file_rsa) issuer_pwd=$(test_ca_pwd_rsa) version=1 not_before=20190210144406 not_after=20290210144406 md=SHA1 is_ca=1 version=3 output_file=$@
+server1.ca_noauthid.crt: server1.key server1.req.sha256 $(test_ca_crt) $(test_ca_key_file_rsa)
+	$(MBEDTLS_CERT_WRITE) request_file=server1.req.sha256 issuer_crt=$(test_ca_crt) issuer_key=$(test_ca_key_file_rsa) issuer_pwd=$(test_ca_pwd_rsa) not_before=20190210144406 not_after=20290210144406 md=SHA1 authority_identifier=0 is_ca=1 version=3 output_file=$@
+server1.ca.der: server1.ca.crt
+	$(OPENSSL) x509 -inform PEM -in $< -outform DER -out $@
+all_final += server1.ca.crt server1.ca_noauthid.crt server1.ca.der
+
 server1_ca.crt: server1.crt $(test_ca_crt)
 	cat server1.crt $(test_ca_crt) > $@
 all_final += server1_ca.crt
@@ -1124,6 +1132,16 @@
 all_final += cert_md5.crt
 
 ################################################################
+#### Diffie-Hellman parameters
+################################################################
+
+dh.998.pem:
+	$(OPENSSL) dhparam -out $@ -text 998
+
+dh.999.pem:
+	$(OPENSSL) dhparam -out $@ -text 999
+
+################################################################
 #### Meta targets
 ################################################################
 
diff --git a/third_party/mbedtls/repo/tests/data_files/dh.998.pem b/third_party/mbedtls/repo/tests/data_files/dh.998.pem
new file mode 100644
index 0000000..96d6cf2
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/data_files/dh.998.pem
@@ -0,0 +1,17 @@
+    DH Parameters: (998 bit)
+        prime:
+            39:5f:30:c0:7b:06:b7:6a:49:c6:c0:81:1f:39:77:
+            b3:35:e2:8d:66:fc:6a:6e:94:f3:df:97:f2:89:31:
+            6c:75:39:08:16:d1:a4:b8:0c:68:c5:63:21:61:eb:
+            48:2d:77:99:08:1d:67:38:37:0a:cd:cf:39:b6:3c:
+            9d:8a:e5:85:3c:71:e3:4b:3e:1e:b9:80:e3:cc:7a:
+            fd:84:05:b0:df:36:15:29:4e:3e:23:3b:c3:ae:6b:
+            c7:11:b9:64:43:40:75:c7:4a:ef:a7:2d:00:e2:62:
+            8f:93:78:96:8f:2c:25:8d:7d:1f:eb:5c:3c:bf:51:
+            de:f8:08:25:db
+        generator: 2 (0x2)
+-----BEGIN DH PARAMETERS-----
+MIGCAn05XzDAewa3aknGwIEfOXezNeKNZvxqbpTz35fyiTFsdTkIFtGkuAxoxWMh
+YetILXeZCB1nODcKzc85tjydiuWFPHHjSz4euYDjzHr9hAWw3zYVKU4+IzvDrmvH
+EblkQ0B1x0rvpy0A4mKPk3iWjywljX0f61w8v1He+Agl2wIBAg==
+-----END DH PARAMETERS-----
diff --git a/third_party/mbedtls/repo/tests/data_files/dh.999.pem b/third_party/mbedtls/repo/tests/data_files/dh.999.pem
new file mode 100644
index 0000000..6e3ceb3
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/data_files/dh.999.pem
@@ -0,0 +1,17 @@
+    DH Parameters: (999 bit)
+        prime:
+            4f:b8:d2:d8:3c:b3:02:c9:64:f5:99:fe:61:cc:b3:
+            69:1c:ba:bb:a2:33:db:38:2f:85:87:b7:12:fb:69:
+            6e:a5:32:3e:ff:24:df:c4:61:07:0c:e1:88:72:fa:
+            14:d4:22:65:18:66:09:7e:43:35:c4:5a:62:f7:0a:
+            69:be:45:71:6e:ac:c5:56:d8:22:9e:c4:9c:23:2b:
+            bd:6d:3b:b6:02:4f:5d:12:a7:ac:90:b8:9e:be:93:
+            82:bc:09:7c:cd:e1:09:21:1e:3d:69:2a:76:41:00:
+            68:6d:b7:e8:e8:df:d6:1b:82:93:d9:21:4a:ea:71:
+            f2:e6:c4:94:03
+        generator: 2 (0x2)
+-----BEGIN DH PARAMETERS-----
+MIGCAn1PuNLYPLMCyWT1mf5hzLNpHLq7ojPbOC+Fh7cS+2lupTI+/yTfxGEHDOGI
+cvoU1CJlGGYJfkM1xFpi9wppvkVxbqzFVtginsScIyu9bTu2Ak9dEqeskLievpOC
+vAl8zeEJIR49aSp2QQBobbfo6N/WG4KT2SFK6nHy5sSUAwIBAg==
+-----END DH PARAMETERS-----
diff --git a/third_party/mbedtls/repo/tests/data_files/server1.ca.crt b/third_party/mbedtls/repo/tests/data_files/server1.ca.crt
new file mode 100644
index 0000000..84691d6
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/data_files/server1.ca.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRTCCAi2gAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER
+MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
+MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIFNlcnZlciAxMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/
+uOhFkNvuiBZS0/FDUEeWEllkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFD
+d185fAkER4KwVzlw7aPsFRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVf
+CrFTxjB+FTms+Vruf5KepgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTr
+lZvc/kFeF6babFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9w
+bp7OvViJ4lNZnm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQAB
+o1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQfdNY/KcF0dEU7BRIsPai9
+Q1kCpjAfBgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0B
+AQUFAAOCAQEAgt0Fk6cLMjsZUkVpkpTw6EJuKA48H8ieUSTDzYoaDWJQsFY34OIc
+0UpfMwl1jl0qEcVboOdcJHug0EXsfm6XUlSJkPnmcdt/N4gU3/TVkdQwqbvrwjae
+S+Jb1E7fTAiauMi6++svV/sfKqE3OCTJWF+6D0LdgnxEVZM6DvnFU9Jvw+CPTIx6
++SYZLm5sOTL0sWMIxwAEjwGJ3T1m0sjPjnnl4Jn/XtD8UuRRYB/RS6e2TlKovwWP
+G3eUdEs2QJ5lnnD+d7AUYq9nAYnb42M1ZdAxRQxxu2wweiTpUubvT4W6wkG8veix
+UM45EKsxPinnK0rK9bzrPDwpntIHhEUcSQ==
+-----END CERTIFICATE-----
diff --git a/third_party/mbedtls/repo/tests/data_files/server1.ca.der b/third_party/mbedtls/repo/tests/data_files/server1.ca.der
new file mode 100644
index 0000000..a5ff059
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/data_files/server1.ca.der
Binary files differ
diff --git a/third_party/mbedtls/repo/tests/data_files/server1.ca_noauthid.crt b/third_party/mbedtls/repo/tests/data_files/server1.ca_noauthid.crt
new file mode 100644
index 0000000..e66956d
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/data_files/server1.ca_noauthid.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDJDCCAgygAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER
+MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
+MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIFNlcnZlciAxMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/
+uOhFkNvuiBZS0/FDUEeWEllkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFD
+d185fAkER4KwVzlw7aPsFRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVf
+CrFTxjB+FTms+Vruf5KepgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTr
+lZvc/kFeF6babFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9w
+bp7OvViJ4lNZnm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQAB
+ozIwMDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQfdNY/KcF0dEU7BRIsPai9
+Q1kCpjANBgkqhkiG9w0BAQUFAAOCAQEAMblPCsjj6RJ8sOm54sdlSJOTGWEo/1LF
+q1bJnKE3FXDeU8pbhEhpfsd2zcKdJxzp7Bg8Ms/xKBuOZhn/4C/n2FwZpEeAsS7J
+tZifKp+GXVs0xbcji9aB8niWXSl/CoICpvHpMAz8k2HT4LDvbC2ElXkqLT7n7k1B
+/ODI3BME34NquyBTDezQb4Gz7bx42OKLrxZkKrO3UF3TQTYBZvlH7IO7SvZhQPGk
+b8a2jKYfeQCCIvcywWQ7qzlgzTgnXJ0RrLyCqOqLFs6ztHPgclHa+XYF5yftSKIS
+zTJLT0IWBtwgB2opv7YSx7tKYhj+uHHY7C3iSXzAgPy5TYkissGXbw==
+-----END CERTIFICATE-----
diff --git a/third_party/mbedtls/repo/tests/docker/bionic/Dockerfile b/third_party/mbedtls/repo/tests/docker/bionic/Dockerfile
index 1d24aa3..3132be9 100644
--- a/third_party/mbedtls/repo/tests/docker/bionic/Dockerfile
+++ b/third_party/mbedtls/repo/tests/docker/bionic/Dockerfile
@@ -160,7 +160,3 @@
 
 ENV GNUTLS_NEXT_CLI=/usr/local/gnutls-3.6.5/bin/gnutls-cli
 ENV GNUTLS_NEXT_SERV=/usr/local/gnutls-3.6.5/bin/gnutls-serv
-
-RUN pip3 install --no-cache-dir \
-    mbed-host-tests \
-    mock
diff --git a/third_party/mbedtls/repo/tests/include/spe/crypto_spe.h b/third_party/mbedtls/repo/tests/include/spe/crypto_spe.h
new file mode 100644
index 0000000..f80fd86
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/include/spe/crypto_spe.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/**
+ * \file crypto_spe.h
+ *
+ * \brief When Mbed Crypto is built with the MBEDTLS_PSA_CRYPTO_SPM option
+ *        enabled, this header is included by all .c files in Mbed Crypto that
+ *        use PSA Crypto function names. This avoids duplication of symbols
+ *        between TF-M and Mbed Crypto.
+ *
+ * \note  This file should be included before including any PSA Crypto headers
+ *        from Mbed Crypto.
+ */
+
+#ifndef CRYPTO_SPE_H
+#define CRYPTO_SPE_H
+
+#define PSA_FUNCTION_NAME(x) mbedcrypto__ ## x
+
+#define psa_crypto_init \
+        PSA_FUNCTION_NAME(psa_crypto_init)
+#define psa_key_derivation_get_capacity \
+        PSA_FUNCTION_NAME(psa_key_derivation_get_capacity)
+#define psa_key_derivation_set_capacity \
+        PSA_FUNCTION_NAME(psa_key_derivation_set_capacity)
+#define psa_key_derivation_input_bytes \
+        PSA_FUNCTION_NAME(psa_key_derivation_input_bytes)
+#define psa_key_derivation_output_bytes \
+        PSA_FUNCTION_NAME(psa_key_derivation_output_bytes)
+#define psa_key_derivation_input_key \
+        PSA_FUNCTION_NAME(psa_key_derivation_input_key)
+#define psa_key_derivation_output_key \
+        PSA_FUNCTION_NAME(psa_key_derivation_output_key)
+#define psa_key_derivation_setup \
+        PSA_FUNCTION_NAME(psa_key_derivation_setup)
+#define psa_key_derivation_abort \
+        PSA_FUNCTION_NAME(psa_key_derivation_abort)
+#define psa_key_derivation_key_agreement \
+        PSA_FUNCTION_NAME(psa_key_derivation_key_agreement)
+#define psa_raw_key_agreement \
+        PSA_FUNCTION_NAME(psa_raw_key_agreement)
+#define psa_generate_random \
+        PSA_FUNCTION_NAME(psa_generate_random)
+#define psa_aead_encrypt \
+        PSA_FUNCTION_NAME(psa_aead_encrypt)
+#define psa_aead_decrypt \
+        PSA_FUNCTION_NAME(psa_aead_decrypt)
+#define psa_open_key \
+        PSA_FUNCTION_NAME(psa_open_key)
+#define psa_close_key \
+        PSA_FUNCTION_NAME(psa_close_key)
+#define psa_import_key \
+        PSA_FUNCTION_NAME(psa_import_key)
+#define psa_destroy_key \
+        PSA_FUNCTION_NAME(psa_destroy_key)
+#define psa_get_key_attributes \
+        PSA_FUNCTION_NAME(psa_get_key_attributes)
+#define psa_reset_key_attributes \
+        PSA_FUNCTION_NAME(psa_reset_key_attributes)
+#define psa_export_key \
+        PSA_FUNCTION_NAME(psa_export_key)
+#define psa_export_public_key \
+        PSA_FUNCTION_NAME(psa_export_public_key)
+#define psa_purge_key \
+        PSA_FUNCTION_NAME(psa_purge_key)
+#define psa_copy_key \
+        PSA_FUNCTION_NAME(psa_copy_key)
+#define psa_cipher_operation_init \
+        PSA_FUNCTION_NAME(psa_cipher_operation_init)
+#define psa_cipher_generate_iv \
+        PSA_FUNCTION_NAME(psa_cipher_generate_iv)
+#define psa_cipher_set_iv \
+        PSA_FUNCTION_NAME(psa_cipher_set_iv)
+#define psa_cipher_encrypt_setup \
+        PSA_FUNCTION_NAME(psa_cipher_encrypt_setup)
+#define psa_cipher_decrypt_setup \
+        PSA_FUNCTION_NAME(psa_cipher_decrypt_setup)
+#define psa_cipher_update \
+        PSA_FUNCTION_NAME(psa_cipher_update)
+#define psa_cipher_finish \
+        PSA_FUNCTION_NAME(psa_cipher_finish)
+#define psa_cipher_abort \
+        PSA_FUNCTION_NAME(psa_cipher_abort)
+#define psa_hash_operation_init \
+        PSA_FUNCTION_NAME(psa_hash_operation_init)
+#define psa_hash_setup \
+        PSA_FUNCTION_NAME(psa_hash_setup)
+#define psa_hash_update \
+        PSA_FUNCTION_NAME(psa_hash_update)
+#define psa_hash_finish \
+        PSA_FUNCTION_NAME(psa_hash_finish)
+#define psa_hash_verify \
+        PSA_FUNCTION_NAME(psa_hash_verify)
+#define psa_hash_abort \
+        PSA_FUNCTION_NAME(psa_hash_abort)
+#define psa_hash_clone \
+        PSA_FUNCTION_NAME(psa_hash_clone)
+#define psa_hash_compute \
+        PSA_FUNCTION_NAME(psa_hash_compute)
+#define psa_hash_compare \
+        PSA_FUNCTION_NAME(psa_hash_compare)
+#define psa_mac_operation_init \
+        PSA_FUNCTION_NAME(psa_mac_operation_init)
+#define psa_mac_sign_setup \
+        PSA_FUNCTION_NAME(psa_mac_sign_setup)
+#define psa_mac_verify_setup \
+        PSA_FUNCTION_NAME(psa_mac_verify_setup)
+#define psa_mac_update \
+        PSA_FUNCTION_NAME(psa_mac_update)
+#define psa_mac_sign_finish \
+        PSA_FUNCTION_NAME(psa_mac_sign_finish)
+#define psa_mac_verify_finish \
+        PSA_FUNCTION_NAME(psa_mac_verify_finish)
+#define psa_mac_abort \
+        PSA_FUNCTION_NAME(psa_mac_abort)
+#define psa_sign_hash \
+        PSA_FUNCTION_NAME(psa_sign_hash)
+#define psa_verify_hash \
+        PSA_FUNCTION_NAME(psa_verify_hash)
+#define psa_asymmetric_encrypt \
+        PSA_FUNCTION_NAME(psa_asymmetric_encrypt)
+#define psa_asymmetric_decrypt \
+        PSA_FUNCTION_NAME(psa_asymmetric_decrypt)
+#define psa_generate_key \
+        PSA_FUNCTION_NAME(psa_generate_key)
+
+#endif /* CRYPTO_SPE_H */
diff --git a/third_party/mbedtls/repo/tests/include/test/asn1_helpers.h b/third_party/mbedtls/repo/tests/include/test/asn1_helpers.h
new file mode 100644
index 0000000..91ae260
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/include/test/asn1_helpers.h
@@ -0,0 +1,50 @@
+/** Helper functions for tests that manipulate ASN.1 data.
+ */
+/*
+ *  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 ASN1_HELPERS_H
+#define ASN1_HELPERS_H
+
+#include "test/helpers.h"
+
+/** Skip past an INTEGER in an ASN.1 buffer.
+ *
+ * Mark the current test case as failed in any of the following conditions:
+ * - The buffer does not start with an ASN.1 INTEGER.
+ * - The integer's size or parity does not match the constraints expressed
+ *   through \p min_bits, \p max_bits and \p must_be_odd.
+ *
+ * \param p             Upon entry, `*p` points to the first byte of the
+ *                      buffer to parse.
+ *                      On successful return, `*p` points to the first byte
+ *                      after the parsed INTEGER.
+ *                      On failure, `*p` is unspecified.
+ * \param end           The end of the ASN.1 buffer.
+ * \param min_bits      Fail the test case if the integer does not have at
+ *                      least this many significant bits.
+ * \param max_bits      Fail the test case if the integer has more than
+ *                      this many significant bits.
+ * \param must_be_odd   Fail the test case if the integer is even.
+ *
+ * \return              \c 0 if the test failed, otherwise 1.
+ */
+int mbedtls_test_asn1_skip_integer( unsigned char **p, const unsigned char *end,
+                                    size_t min_bits, size_t max_bits,
+                                    int must_be_odd );
+
+#endif /* ASN1_HELPERS_H */
diff --git a/third_party/mbedtls/repo/tests/include/test/drivers/aead.h b/third_party/mbedtls/repo/tests/include/test/drivers/aead.h
new file mode 100644
index 0000000..2207cb3
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/include/test/drivers/aead.h
@@ -0,0 +1,71 @@
+/*
+ * Test driver for AEAD driver entry points.
+ */
+/*  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 PSA_CRYPTO_TEST_DRIVERS_AEAD_H
+#define PSA_CRYPTO_TEST_DRIVERS_AEAD_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+#include <psa/crypto_driver_common.h>
+
+typedef struct {
+    /* If not PSA_SUCCESS, return this error code instead of processing the
+     * function call. */
+    psa_status_t forced_status;
+    /* Count the amount of times AEAD driver functions are called. */
+    unsigned long hits;
+    /* Status returned by the last AEAD driver function call. */
+    psa_status_t driver_status;
+} mbedtls_test_driver_aead_hooks_t;
+
+#define MBEDTLS_TEST_DRIVER_AEAD_INIT { 0, 0, 0 }
+static inline mbedtls_test_driver_aead_hooks_t
+    mbedtls_test_driver_aead_hooks_init( void )
+{
+    const mbedtls_test_driver_aead_hooks_t v = MBEDTLS_TEST_DRIVER_AEAD_INIT;
+    return( v );
+}
+
+extern mbedtls_test_driver_aead_hooks_t mbedtls_test_driver_aead_hooks;
+
+psa_status_t mbedtls_test_transparent_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 mbedtls_test_transparent_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 );
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_TEST_DRIVERS_AEAD_H */
diff --git a/third_party/mbedtls/repo/tests/include/test/drivers/cipher.h b/third_party/mbedtls/repo/tests/include/test/drivers/cipher.h
index ef787f7..c1aa616 100644
--- a/third_party/mbedtls/repo/tests/include/test/drivers/cipher.h
+++ b/third_party/mbedtls/repo/tests/include/test/drivers/cipher.h
@@ -28,22 +28,9 @@
 
 #if defined(PSA_CRYPTO_DRIVER_TEST)
 #include <psa/crypto_driver_common.h>
+#include <psa/crypto.h>
 
 #include "mbedtls/cipher.h"
-typedef struct {
-    psa_algorithm_t alg;
-    unsigned int key_set : 1;
-    unsigned int iv_required : 1;
-    unsigned int iv_set : 1;
-    uint8_t iv_size;
-    uint8_t block_size;
-    mbedtls_cipher_context_t cipher;
-} test_transparent_cipher_operation_t;
-
-typedef struct{
-    unsigned int initialised : 1;
-    test_transparent_cipher_operation_t ctx;
-} test_opaque_cipher_operation_t;
 
 typedef struct {
     /* If non-null, on success, copy this to the output. */
@@ -54,127 +41,106 @@
     psa_status_t forced_status;
     /* Count the amount of times one of the cipher driver functions is called. */
     unsigned long hits;
-} test_driver_cipher_hooks_t;
+} mbedtls_test_driver_cipher_hooks_t;
 
-#define TEST_DRIVER_CIPHER_INIT { NULL, 0, PSA_SUCCESS, 0 }
-static inline test_driver_cipher_hooks_t test_driver_cipher_hooks_init( void )
+#define MBEDTLS_TEST_DRIVER_CIPHER_INIT { NULL, 0, PSA_SUCCESS, 0 }
+static inline mbedtls_test_driver_cipher_hooks_t
+     mbedtls_test_driver_cipher_hooks_init( void )
 {
-    const test_driver_cipher_hooks_t v = TEST_DRIVER_CIPHER_INIT;
+    const mbedtls_test_driver_cipher_hooks_t v = MBEDTLS_TEST_DRIVER_CIPHER_INIT;
     return( v );
 }
 
-extern test_driver_cipher_hooks_t test_driver_cipher_hooks;
+extern mbedtls_test_driver_cipher_hooks_t mbedtls_test_driver_cipher_hooks;
 
-psa_status_t test_transparent_cipher_encrypt(
+psa_status_t mbedtls_test_transparent_cipher_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    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 mbedtls_test_transparent_cipher_decrypt(
     const psa_key_attributes_t *attributes,
     const uint8_t *key, size_t key_length,
     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 test_transparent_cipher_decrypt(
+psa_status_t mbedtls_test_transparent_cipher_encrypt_setup(
+    mbedtls_transparent_test_driver_cipher_operation_t *operation,
     const psa_key_attributes_t *attributes,
     const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg,
+    psa_algorithm_t alg);
+
+psa_status_t mbedtls_test_transparent_cipher_decrypt_setup(
+    mbedtls_transparent_test_driver_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg);
+
+psa_status_t mbedtls_test_transparent_cipher_abort(
+    mbedtls_transparent_test_driver_cipher_operation_t *operation );
+
+psa_status_t mbedtls_test_transparent_cipher_set_iv(
+    mbedtls_transparent_test_driver_cipher_operation_t *operation,
+    const uint8_t *iv, size_t iv_length);
+
+psa_status_t mbedtls_test_transparent_cipher_update(
+    mbedtls_transparent_test_driver_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 test_transparent_cipher_encrypt_setup(
-    test_transparent_cipher_operation_t *operation,
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg);
-
-psa_status_t test_transparent_cipher_decrypt_setup(
-    test_transparent_cipher_operation_t *operation,
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg);
-
-psa_status_t test_transparent_cipher_abort(
-    test_transparent_cipher_operation_t *operation);
-
-psa_status_t test_transparent_cipher_generate_iv(
-    test_transparent_cipher_operation_t *operation,
-    uint8_t *iv,
-    size_t iv_size,
-    size_t *iv_length);
-
-psa_status_t test_transparent_cipher_set_iv(
-    test_transparent_cipher_operation_t *operation,
-    const uint8_t *iv,
-    size_t iv_length);
-
-psa_status_t test_transparent_cipher_update(
-    test_transparent_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 test_transparent_cipher_finish(
-    test_transparent_cipher_operation_t *operation,
-    uint8_t *output,
-    size_t output_size,
-    size_t *output_length);
+psa_status_t mbedtls_test_transparent_cipher_finish(
+    mbedtls_transparent_test_driver_cipher_operation_t *operation,
+    uint8_t *output, size_t output_size, size_t *output_length);
 
 /*
  * opaque versions
  */
-psa_status_t test_opaque_cipher_encrypt(
+psa_status_t mbedtls_test_opaque_cipher_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    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 mbedtls_test_opaque_cipher_decrypt(
     const psa_key_attributes_t *attributes,
     const uint8_t *key, size_t key_length,
     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 test_opaque_cipher_decrypt(
+psa_status_t mbedtls_test_opaque_cipher_encrypt_setup(
+    mbedtls_opaque_test_driver_cipher_operation_t *operation,
     const psa_key_attributes_t *attributes,
     const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg,
+    psa_algorithm_t alg);
+
+psa_status_t mbedtls_test_opaque_cipher_decrypt_setup(
+    mbedtls_opaque_test_driver_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg);
+
+psa_status_t mbedtls_test_opaque_cipher_abort(
+    mbedtls_opaque_test_driver_cipher_operation_t *operation);
+
+psa_status_t mbedtls_test_opaque_cipher_set_iv(
+    mbedtls_opaque_test_driver_cipher_operation_t *operation,
+    const uint8_t *iv, size_t iv_length);
+
+psa_status_t mbedtls_test_opaque_cipher_update(
+    mbedtls_opaque_test_driver_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 test_opaque_cipher_encrypt_setup(
-    test_opaque_cipher_operation_t *operation,
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg);
-
-psa_status_t test_opaque_cipher_decrypt_setup(
-    test_opaque_cipher_operation_t *operation,
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg);
-
-psa_status_t test_opaque_cipher_abort(
-    test_opaque_cipher_operation_t *operation);
-
-psa_status_t test_opaque_cipher_generate_iv(
-    test_opaque_cipher_operation_t *operation,
-    uint8_t *iv,
-    size_t iv_size,
-    size_t *iv_length);
-
-psa_status_t test_opaque_cipher_set_iv(
-    test_opaque_cipher_operation_t *operation,
-    const uint8_t *iv,
-    size_t iv_length);
-
-psa_status_t test_opaque_cipher_update(
-    test_opaque_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 test_opaque_cipher_finish(
-    test_opaque_cipher_operation_t *operation,
-    uint8_t *output,
-    size_t output_size,
-    size_t *output_length);
+psa_status_t mbedtls_test_opaque_cipher_finish(
+    mbedtls_opaque_test_driver_cipher_operation_t *operation,
+    uint8_t *output, size_t output_size, size_t *output_length);
 
 #endif /* PSA_CRYPTO_DRIVER_TEST */
 #endif /* PSA_CRYPTO_TEST_DRIVERS_CIPHER_H */
diff --git a/third_party/mbedtls/repo/tests/include/test/drivers/config_test_driver.h b/third_party/mbedtls/repo/tests/include/test/drivers/config_test_driver.h
new file mode 100644
index 0000000..97be72d
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/include/test/drivers/config_test_driver.h
@@ -0,0 +1,55 @@
+/*
+ * Mbed TLS configuration for PSA test driver libraries. It includes:
+ * . the minimum set of modules needed by the PSA core.
+ * . the Mbed TLS configuration options that may need to be additionally
+ *   enabled for the purpose of a specific test.
+ * . the PSA configuration file for the Mbed TLS library and its test drivers.
+ */
+/*
+ *  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_CONFIG_H
+#define MBEDTLS_CONFIG_H
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#define MBEDTLS_PSA_CRYPTO_C
+#define MBEDTLS_PSA_CRYPTO_CONFIG
+
+/* PSA core mandatory configuration options */
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_AES_C
+#define MBEDTLS_SHA256_C
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1
+#define MBEDTLS_CTR_DRBG_C
+#define MBEDTLS_ENTROPY_C
+
+/*
+ * Configuration options that may need to be additionally enabled for the
+ * purpose of a specific set of tests.
+ */
+//#define MBEDTLS_SHA1_C
+//#define MBEDTLS_SHA512_C
+//#define MBEDTLS_PEM_PARSE_C
+//#define MBEDTLS_BASE64_C
+
+#include "mbedtls/config_psa.h"
+#include "mbedtls/check_config.h"
+
+#endif /* MBEDTLS_CONFIG_H */
diff --git a/third_party/mbedtls/repo/tests/include/test/drivers/crypto_config_test_driver_extension.h b/third_party/mbedtls/repo/tests/include/test/drivers/crypto_config_test_driver_extension.h
new file mode 100644
index 0000000..f5be7b3
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/include/test/drivers/crypto_config_test_driver_extension.h
@@ -0,0 +1,231 @@
+/**
+ * This file is intended to be used to build PSA test driver libraries. It is
+ * intended to be appended by the test build system to the crypto_config.h file
+ * of the Mbed TLS library the test library will be linked to. It mirrors the
+ * PSA_ACCEL_* macros defining the cryptographic operations the test library
+ * supports.
+ */
+
+#if defined(PSA_WANT_ALG_CBC_NO_PADDING)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING)
+#undef MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_CBC_PKCS7)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7)
+#undef MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_CFB)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_CFB)
+#undef MBEDTLS_PSA_ACCEL_ALG_CFB
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_CFB 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_CTR)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_CTR)
+#undef MBEDTLS_PSA_ACCEL_ALG_CTR
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_CTR 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA)
+#undef MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_ECDSA)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA)
+#undef MBEDTLS_PSA_ACCEL_ALG_ECDSA
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_ECDSA 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_MD2)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_MD2)
+#undef MBEDTLS_PSA_ACCEL_ALG_MD2
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_MD2 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_MD4)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_MD4)
+#undef MBEDTLS_PSA_ACCEL_ALG_MD4
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_MD4 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_MD5)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_MD5)
+#undef MBEDTLS_PSA_ACCEL_ALG_MD5
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_MD5 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_OFB)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_OFB)
+#undef MBEDTLS_PSA_ACCEL_ALG_OFB
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_OFB 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_RIPEMD160)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160)
+#undef MBEDTLS_PSA_ACCEL_ALG_RIPEMD160
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_RIPEMD160 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN)
+#undef MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_RSA_PSS)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS)
+#undef MBEDTLS_PSA_ACCEL_ALG_RSA_PSS
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_RSA_PSS 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_SHA_1)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1)
+#undef MBEDTLS_PSA_ACCEL_ALG_SHA_1
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_1 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_SHA_224)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224)
+#undef MBEDTLS_PSA_ACCEL_ALG_SHA_224
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_224 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_SHA_256)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
+#undef MBEDTLS_PSA_ACCEL_ALG_SHA_256
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_256 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_SHA_384)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384)
+#undef MBEDTLS_PSA_ACCEL_ALG_SHA_384
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_384 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_SHA_512)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512)
+#undef MBEDTLS_PSA_ACCEL_ALG_SHA_512
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_512 1
+#endif
+#endif
+
+#if defined(PSA_WANT_ALG_XTS)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_XTS)
+#undef MBEDTLS_PSA_ACCEL_ALG_XTS
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_XTS 1
+#endif
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_AES)
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES)
+#undef MBEDTLS_PSA_ACCEL_KEY_TYPE_AES
+#else
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_AES 1
+#endif
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_CAMELLIA)
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA)
+#undef MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA
+#else
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA 1
+#endif
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR)
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR)
+#undef MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR
+#else
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR 1
+#endif
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR)
+#undef MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR
+#else
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR 1
+#endif
+#endif
+
+#define MBEDTLS_PSA_ACCEL_ALG_CBC_MAC 1
+#define MBEDTLS_PSA_ACCEL_ALG_CCM 1
+#define MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305 1
+#define MBEDTLS_PSA_ACCEL_ALG_CMAC 1
+#define MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING 1
+#define MBEDTLS_PSA_ACCEL_ALG_ECDH 1
+#define MBEDTLS_PSA_ACCEL_ALG_GCM 1
+#define MBEDTLS_PSA_ACCEL_ALG_HKDF 1
+#define MBEDTLS_PSA_ACCEL_ALG_HMAC 1
+#define MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP 1
+#define MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT 1
+#define MBEDTLS_PSA_ACCEL_ALG_STREAM_CIPHER 1
+#define MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF 1
+#define MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS 1
+
+#if defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA)
+#define MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256 1
+#define MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384 1
+#define MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512 1
+#define MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255 1
+#define MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448 1
+#define MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192 1
+#define MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224 1
+#define MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256 1
+#define MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192 1
+#define MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224 1
+#define MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256 1
+#define MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384 1
+#define MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521 1
+#endif
+
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_DERIVE 1
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_HMAC 1
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ARC4 1
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20 1
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_DES 1
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY 1
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RAW_DATA 1
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY 1
diff --git a/third_party/mbedtls/repo/tests/include/test/drivers/hash.h b/third_party/mbedtls/repo/tests/include/test/drivers/hash.h
new file mode 100644
index 0000000..865cd74
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/include/test/drivers/hash.h
@@ -0,0 +1,80 @@
+/*
+ * Test driver for hash driver entry points.
+ */
+/*  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 PSA_CRYPTO_TEST_DRIVERS_HASH_H
+#define PSA_CRYPTO_TEST_DRIVERS_HASH_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+#include <psa/crypto_driver_common.h>
+
+typedef struct {
+    /* If not PSA_SUCCESS, return this error code instead of processing the
+     * function call. */
+    psa_status_t forced_status;
+    /* Count the amount of times hash driver entry points are called. */
+    unsigned long hits;
+    /* Status returned by the last hash driver entry point call. */
+    psa_status_t driver_status;
+} mbedtls_test_driver_hash_hooks_t;
+
+#define MBEDTLS_TEST_DRIVER_HASH_INIT { 0, 0, 0 }
+static inline mbedtls_test_driver_hash_hooks_t
+    mbedtls_test_driver_hash_hooks_init( void )
+{
+    const mbedtls_test_driver_hash_hooks_t v = MBEDTLS_TEST_DRIVER_HASH_INIT;
+    return( v );
+}
+
+extern mbedtls_test_driver_hash_hooks_t mbedtls_test_driver_hash_hooks;
+
+psa_status_t mbedtls_test_transparent_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 mbedtls_test_transparent_hash_setup(
+    mbedtls_transparent_test_driver_hash_operation_t *operation,
+    psa_algorithm_t alg );
+
+psa_status_t mbedtls_test_transparent_hash_clone(
+    const mbedtls_transparent_test_driver_hash_operation_t *source_operation,
+    mbedtls_transparent_test_driver_hash_operation_t *target_operation );
+
+psa_status_t mbedtls_test_transparent_hash_update(
+    mbedtls_transparent_test_driver_hash_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length );
+
+psa_status_t mbedtls_test_transparent_hash_finish(
+    mbedtls_transparent_test_driver_hash_operation_t *operation,
+    uint8_t *hash,
+    size_t hash_size,
+    size_t *hash_length );
+
+psa_status_t mbedtls_test_transparent_hash_abort(
+    mbedtls_transparent_test_driver_hash_operation_t *operation );
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_TEST_DRIVERS_HASH_H */
diff --git a/third_party/mbedtls/repo/tests/include/test/drivers/key_management.h b/third_party/mbedtls/repo/tests/include/test/drivers/key_management.h
index 90f8c58..bb08bf6 100644
--- a/third_party/mbedtls/repo/tests/include/test/drivers/key_management.h
+++ b/third_party/mbedtls/repo/tests/include/test/drivers/key_management.h
@@ -29,6 +29,9 @@
 #if defined(PSA_CRYPTO_DRIVER_TEST)
 #include <psa/crypto_driver_common.h>
 
+#define PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT     0
+#define PSA_CRYPTO_TEST_DRIVER_BUILTIN_ECDSA_KEY_SLOT   1
+
 typedef struct {
     /* If non-null, on success, copy this to the output. */
     void *forced_output;
@@ -39,40 +42,61 @@
     /* Count the amount of times one of the key management driver functions
      * is called. */
     unsigned long hits;
-} test_driver_key_management_hooks_t;
+} mbedtls_test_driver_key_management_hooks_t;
 
-#define TEST_DRIVER_KEY_MANAGEMENT_INIT { NULL, 0, PSA_ERROR_NOT_SUPPORTED, 0 }
-static inline test_driver_key_management_hooks_t test_driver_key_management_hooks_init( void )
+#define MBEDTLS_TEST_DRIVER_KEY_MANAGEMENT_INIT { NULL, 0, PSA_SUCCESS, 0 }
+static inline mbedtls_test_driver_key_management_hooks_t
+    mbedtls_test_driver_key_management_hooks_init( void )
 {
-    const test_driver_key_management_hooks_t v = TEST_DRIVER_KEY_MANAGEMENT_INIT;
+    const mbedtls_test_driver_key_management_hooks_t
+        v = MBEDTLS_TEST_DRIVER_KEY_MANAGEMENT_INIT;
     return( v );
 }
 
-extern test_driver_key_management_hooks_t test_driver_key_management_hooks;
+extern mbedtls_test_driver_key_management_hooks_t
+    mbedtls_test_driver_key_management_hooks;
 
-psa_status_t test_transparent_generate_key(
+psa_status_t mbedtls_test_transparent_init( void );
+void mbedtls_test_transparent_free( void );
+psa_status_t mbedtls_test_opaque_init( void );
+void mbedtls_test_opaque_free( void );
+
+psa_status_t mbedtls_test_transparent_generate_key(
     const psa_key_attributes_t *attributes,
     uint8_t *key, size_t key_size, size_t *key_length );
 
-psa_status_t test_opaque_generate_key(
+psa_status_t mbedtls_test_opaque_generate_key(
     const psa_key_attributes_t *attributes,
     uint8_t *key, size_t key_size, size_t *key_length );
 
-psa_status_t test_transparent_validate_key(
+psa_status_t mbedtls_test_opaque_export_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    uint8_t *data, size_t data_size, size_t *data_length );
+
+psa_status_t mbedtls_test_transparent_export_public_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    uint8_t *data, size_t data_size, size_t *data_length );
+
+psa_status_t mbedtls_test_opaque_export_public_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    uint8_t *data, size_t data_size, size_t *data_length );
+
+psa_status_t mbedtls_test_transparent_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 test_transparent_export_public_key(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    uint8_t *data, size_t data_size, size_t *data_length );
-
-psa_status_t test_opaque_export_public_key(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    uint8_t *data, size_t data_size, size_t *data_length );
+psa_status_t mbedtls_test_opaque_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_TEST */
 #endif /* PSA_CRYPTO_TEST_DRIVERS_KEY_MANAGEMENT_H */
diff --git a/third_party/mbedtls/repo/tests/include/test/drivers/mac.h b/third_party/mbedtls/repo/tests/include/test/drivers/mac.h
new file mode 100644
index 0000000..7733dd3
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/include/test/drivers/mac.h
@@ -0,0 +1,141 @@
+/*
+ * Test driver for MAC driver entry points.
+ */
+/*  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 PSA_CRYPTO_TEST_DRIVERS_MAC_H
+#define PSA_CRYPTO_TEST_DRIVERS_MAC_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+#include <psa/crypto_driver_common.h>
+
+typedef struct {
+    /* If not PSA_SUCCESS, return this error code instead of processing the
+     * function call. */
+    psa_status_t forced_status;
+    /* Count the amount of times MAC driver functions are called. */
+    unsigned long hits;
+    /* Status returned by the last MAC driver function call. */
+    psa_status_t driver_status;
+} mbedtls_test_driver_mac_hooks_t;
+
+#define MBEDTLS_TEST_DRIVER_MAC_INIT { 0, 0, 0 }
+static inline mbedtls_test_driver_mac_hooks_t
+    mbedtls_test_driver_mac_hooks_init( void )
+{
+    const mbedtls_test_driver_mac_hooks_t v = MBEDTLS_TEST_DRIVER_MAC_INIT;
+    return( v );
+}
+
+extern mbedtls_test_driver_mac_hooks_t mbedtls_test_driver_mac_hooks;
+
+psa_status_t mbedtls_test_transparent_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 mbedtls_test_transparent_mac_sign_setup(
+    mbedtls_transparent_test_driver_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 mbedtls_test_transparent_mac_verify_setup(
+    mbedtls_transparent_test_driver_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 mbedtls_test_transparent_mac_update(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length );
+
+psa_status_t mbedtls_test_transparent_mac_sign_finish(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length );
+
+psa_status_t mbedtls_test_transparent_mac_verify_finish(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length );
+
+psa_status_t mbedtls_test_transparent_mac_abort(
+    mbedtls_transparent_test_driver_mac_operation_t *operation );
+
+psa_status_t mbedtls_test_opaque_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 mbedtls_test_opaque_mac_sign_setup(
+    mbedtls_opaque_test_driver_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 mbedtls_test_opaque_mac_verify_setup(
+    mbedtls_opaque_test_driver_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 mbedtls_test_opaque_mac_update(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length );
+
+psa_status_t mbedtls_test_opaque_mac_sign_finish(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length );
+
+psa_status_t mbedtls_test_opaque_mac_verify_finish(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length );
+
+psa_status_t mbedtls_test_opaque_mac_abort(
+    mbedtls_opaque_test_driver_mac_operation_t *operation );
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_TEST_DRIVERS_MAC_H */
diff --git a/third_party/mbedtls/repo/tests/include/test/drivers/signature.h b/third_party/mbedtls/repo/tests/include/test/drivers/signature.h
index 8abcb11..5e64edc 100644
--- a/third_party/mbedtls/repo/tests/include/test/drivers/signature.h
+++ b/third_party/mbedtls/repo/tests/include/test/drivers/signature.h
@@ -38,40 +38,86 @@
     psa_status_t forced_status;
     /* Count the amount of times one of the signature driver functions is called. */
     unsigned long hits;
-} test_driver_signature_hooks_t;
+} mbedtls_test_driver_signature_hooks_t;
 
-#define TEST_DRIVER_SIGNATURE_INIT { NULL, 0, PSA_ERROR_NOT_SUPPORTED, 0 }
-static inline test_driver_signature_hooks_t test_driver_signature_hooks_init( void )
+#define MBEDTLS_TEST_DRIVER_SIGNATURE_INIT { NULL, 0, PSA_SUCCESS, 0 }
+static inline mbedtls_test_driver_signature_hooks_t
+    mbedtls_test_driver_signature_hooks_init( void )
 {
-    const test_driver_signature_hooks_t v = TEST_DRIVER_SIGNATURE_INIT;
+    const mbedtls_test_driver_signature_hooks_t
+        v = MBEDTLS_TEST_DRIVER_SIGNATURE_INIT;
     return( v );
 }
 
-extern test_driver_signature_hooks_t test_driver_signature_sign_hooks;
-extern test_driver_signature_hooks_t test_driver_signature_verify_hooks;
+extern mbedtls_test_driver_signature_hooks_t
+    mbedtls_test_driver_signature_sign_hooks;
+extern mbedtls_test_driver_signature_hooks_t
+    mbedtls_test_driver_signature_verify_hooks;
 
-psa_status_t test_transparent_signature_sign_hash(
+psa_status_t mbedtls_test_transparent_signature_sign_message(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key,
+    size_t key_length,
+    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 mbedtls_test_opaque_signature_sign_message(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key,
+    size_t key_length,
+    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 mbedtls_test_transparent_signature_verify_message(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key,
+    size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    const uint8_t *signature,
+    size_t signature_length );
+
+psa_status_t mbedtls_test_opaque_signature_verify_message(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key,
+    size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    const uint8_t *signature,
+    size_t signature_length );
+
+psa_status_t mbedtls_test_transparent_signature_sign_hash(
     const psa_key_attributes_t *attributes,
     const uint8_t *key, size_t key_length,
     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 test_opaque_signature_sign_hash(
+psa_status_t mbedtls_test_opaque_signature_sign_hash(
     const psa_key_attributes_t *attributes,
     const uint8_t *key, size_t key_length,
     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 test_transparent_signature_verify_hash(
+psa_status_t mbedtls_test_transparent_signature_verify_hash(
     const psa_key_attributes_t *attributes,
     const uint8_t *key, size_t key_length,
     psa_algorithm_t alg,
     const uint8_t *hash, size_t hash_length,
     const uint8_t *signature, size_t signature_length );
 
-psa_status_t test_opaque_signature_verify_hash(
+psa_status_t mbedtls_test_opaque_signature_verify_hash(
     const psa_key_attributes_t *attributes,
     const uint8_t *key, size_t key_length,
     psa_algorithm_t alg,
diff --git a/third_party/mbedtls/repo/tests/include/test/drivers/size.h b/third_party/mbedtls/repo/tests/include/test/drivers/size.h
index 4bfe986..b2665bd 100644
--- a/third_party/mbedtls/repo/tests/include/test/drivers/size.h
+++ b/third_party/mbedtls/repo/tests/include/test/drivers/size.h
@@ -29,67 +29,9 @@
 #if defined(PSA_CRYPTO_DRIVER_TEST)
 #include <psa/crypto_driver_common.h>
 
-typedef struct {
-    unsigned int context;
-} test_driver_key_context_t;
-
-/** \def TEST_DRIVER_KEY_CONTEXT_BASE_SIZE
- *
- * This macro returns the base size for the key context. It is the size of the
- * driver specific information stored in each key context.
- */
-#define TEST_DRIVER_KEY_CONTEXT_BASE_SIZE          sizeof( test_driver_key_context_t )
-
-/** \def TEST_DRIVER_KEY_CONTEXT_KEY_PAIR_SIZE
- *
- * Number of bytes included in every key context for a key pair.
- *
- * This pair size is for an ECC 256-bit private/public key pair.
- * Based on this value, the size of the private key can be derived by
- * subtracting the public key size below from this one.
- */
-
-#define TEST_DRIVER_KEY_CONTEXT_KEY_PAIR_SIZE      65
-
-/** \def TEST_DRIVER_KEY_CONTEXT_PUBLIC_KEY_SIZE
- *
- * Number of bytes included in every key context for a public key.
- *
- * For ECC public keys, it needs 257 bits so 33 bytes.
- */
-#define TEST_DRIVER_KEY_CONTEXT_PUBLIC_KEY_SIZE    33
-
-/** \def TEST_DRIVER_KEY_CONTEXT_SYMMETRIC_FACTOR
- *
- * Every key context for a symmetric key includes this many times the key size.
- */
-#define TEST_DRIVER_KEY_CONTEXT_SYMMETRIC_FACTOR   0
-
-/** \def TEST_DRIVER_KEY_CONTEXT_STORE_PUBLIC_KEY
- *
- * If this is true for a key pair, the key context includes space for the public key.
- * If this is false, no additional space is added for the public key.
- *
- * For this instance, store the public key with the private one.
- */
-#define TEST_DRIVER_KEY_CONTEXT_STORE_PUBLIC_KEY   1
-
-/** \def TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION
- *
- * If TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION is defined, the test driver
- * provides a size_function entry point, otherwise, it does not.
- *
- * Some opaque drivers have the need to support a custom size for the storage
- * of key and context information. The size_function provides the ability to
- * provide that customization.
- */
-//#define TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION
-
-#ifdef TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION
-size_t test_size_function(
+size_t mbedtls_test_size_function(
     const psa_key_type_t key_type,
     const size_t key_bits );
-#endif /* TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION */
 
 #endif /* PSA_CRYPTO_DRIVER_TEST */
 #endif /* PSA_CRYPTO_TEST_DRIVERS_SIZE_H */
diff --git a/third_party/mbedtls/repo/tests/include/test/drivers/test_driver.h b/third_party/mbedtls/repo/tests/include/test/drivers/test_driver.h
index f26b795..5b60932 100644
--- a/third_party/mbedtls/repo/tests/include/test/drivers/test_driver.h
+++ b/third_party/mbedtls/repo/tests/include/test/drivers/test_driver.h
@@ -20,11 +20,14 @@
 #ifndef PSA_CRYPTO_TEST_DRIVER_H
 #define PSA_CRYPTO_TEST_DRIVER_H
 
-#define PSA_CRYPTO_TEST_DRIVER_LIFETIME 0x7fffff
+#define PSA_CRYPTO_TEST_DRIVER_LOCATION 0x7fffff
 
-#include "test/drivers/signature.h"
-#include "test/drivers/key_management.h"
+#include "test/drivers/aead.h"
 #include "test/drivers/cipher.h"
+#include "test/drivers/hash.h"
+#include "test/drivers/mac.h"
+#include "test/drivers/key_management.h"
+#include "test/drivers/signature.h"
 #include "test/drivers/size.h"
 
 #endif /* PSA_CRYPTO_TEST_DRIVER_H */
diff --git a/third_party/mbedtls/repo/tests/include/test/fake_external_rng_for_test.h b/third_party/mbedtls/repo/tests/include/test/fake_external_rng_for_test.h
new file mode 100644
index 0000000..faeef22
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/include/test/fake_external_rng_for_test.h
@@ -0,0 +1,56 @@
+/*
+ * Insecure but standalone implementation of mbedtls_psa_external_get_random().
+ * Only for use in tests!
+ */
+/*
+ *  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 FAKE_EXTERNAL_RNG_FOR_TEST_H
+#define FAKE_EXTERNAL_RNG_FOR_TEST_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+/** Enable the insecure implementation of mbedtls_psa_external_get_random().
+ *
+ * The insecure implementation of mbedtls_psa_external_get_random() is
+ * disabled by default.
+ *
+ * When MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG is enabled and the test
+ * helpers are linked into a program, you must enable this before running any
+ * code that uses the PSA subsystem to generate random data (including internal
+ * random generation for purposes such as blinding when the random generation
+ * is routed through PSA).
+ *
+ * You can enable and disable it at any time, regardless of the state
+ * of the PSA subsystem. You may disable it temporarily to simulate a
+ * depleted entropy source.
+ */
+void mbedtls_test_enable_insecure_external_rng( void );
+
+/** Disable the insecure implementation of mbedtls_psa_external_get_random().
+ *
+ * See mbedtls_test_enable_insecure_external_rng().
+ */
+void mbedtls_test_disable_insecure_external_rng( void );
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
+#endif /* FAKE_EXTERNAL_RNG_FOR_TEST_H */
diff --git a/third_party/mbedtls/repo/tests/include/test/helpers.h b/third_party/mbedtls/repo/tests/include/test/helpers.h
index 2c7b179..5d10190 100644
--- a/third_party/mbedtls/repo/tests/include/test/helpers.h
+++ b/third_party/mbedtls/repo/tests/include/test/helpers.h
@@ -31,6 +31,11 @@
 #include MBEDTLS_CONFIG_FILE
 #endif
 
+#if defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_PTHREAD) && \
+    defined(MBEDTLS_TEST_HOOKS)
+#define MBEDTLS_TEST_MUTEX_USAGE
+#endif
+
 #if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
 #else
@@ -49,10 +54,106 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#if defined(MBEDTLS_BIGNUM_C)
+#include "mbedtls/bignum.h"
+#endif
+
+typedef enum
+{
+    MBEDTLS_TEST_RESULT_SUCCESS = 0,
+    MBEDTLS_TEST_RESULT_FAILED,
+    MBEDTLS_TEST_RESULT_SKIPPED
+} mbedtls_test_result_t;
+
+typedef struct
+{
+    mbedtls_test_result_t result;
+    const char *test;
+    const char *filename;
+    int line_no;
+    unsigned long step;
+    char line1[76];
+    char line2[76];
+#if defined(MBEDTLS_TEST_MUTEX_USAGE)
+    const char *mutex_usage_error;
+#endif
+}
+mbedtls_test_info_t;
+extern mbedtls_test_info_t mbedtls_test_info;
+
 int mbedtls_test_platform_setup( void );
 void mbedtls_test_platform_teardown( void );
 
 /**
+ * \brief           Record the current test case as a failure.
+ *
+ *                  This function can be called directly however it is usually
+ *                  called via macros such as TEST_ASSERT, TEST_EQUAL,
+ *                  PSA_ASSERT, etc...
+ *
+ * \note            If the test case was already marked as failed, calling
+ *                  `mbedtls_test_fail( )` again will not overwrite any
+ *                  previous information about the failure.
+ *
+ * \param test      Description of the failure or assertion that failed. This
+ *                  MUST be a string literal.
+ * \param line_no   Line number where the failure originated.
+ * \param filename  Filename where the failure originated.
+ */
+void mbedtls_test_fail( const char *test, int line_no, const char* filename );
+
+/**
+ * \brief           Record the current test case as skipped.
+ *
+ *                  This function can be called directly however it is usually
+ *                  called via the TEST_ASSUME macro.
+ *
+ * \param test      Description of the assumption that caused the test case to
+ *                  be skipped. This MUST be a string literal.
+ * \param line_no   Line number where the test case was skipped.
+ * \param filename  Filename where the test case was skipped.
+ */
+void mbedtls_test_skip( const char *test, int line_no, const char* filename );
+
+/**
+ * \brief       Set the test step number for failure reports.
+ *
+ *              Call this function to display "step NNN" in addition to the
+ *              line number and file name if a test fails. Typically the "step
+ *              number" is the index of a for loop but it can be whatever you
+ *              want.
+ *
+ * \param step  The step number to report.
+ */
+void mbedtls_test_set_step( unsigned long step );
+
+/**
+ * \brief       Reset mbedtls_test_info to a ready/starting state.
+ */
+void mbedtls_test_info_reset( void );
+
+/**
+ * \brief           Record the current test case as a failure if two integers
+ *                  have a different value.
+ *
+ *                  This function is usually called via the macro
+ *                  #TEST_EQUAL.
+ *
+ * \param test      Description of the failure or assertion that failed. This
+ *                  MUST be a string literal. This normally has the form
+ *                  "EXPR1 == EXPR2" where EXPR1 has the value \p value1
+ *                  and EXPR2 has the value \p value2.
+ * \param line_no   Line number where the failure originated.
+ * \param filename  Filename where the failure originated.
+ * \param value1    The first value to compare.
+ * \param value2    The second value to compare.
+ *
+ * \return          \c 1 if the values are equal, otherwise \c 0.
+ */
+int mbedtls_test_equal( const char *test, int line_no, const char* filename,
+                        unsigned long long value1, unsigned long long value2 );
+
+/**
  * \brief          This function decodes the hexadecimal representation of
  *                 data.
  *
@@ -190,4 +291,55 @@
 void mbedtls_test_param_failed_reset_state( void );
 #endif /* MBEDTLS_CHECK_PARAMS */
 
+#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+#include "test/fake_external_rng_for_test.h"
+#endif
+
+#if defined(MBEDTLS_TEST_MUTEX_USAGE)
+/** Permanently activate the mutex usage verification framework. See
+ * threading_helpers.c for information. */
+void mbedtls_test_mutex_usage_init( void );
+
+/** Call this function after executing a test case to check for mutex usage
+ * errors. */
+void mbedtls_test_mutex_usage_check( void );
+#endif /* MBEDTLS_TEST_MUTEX_USAGE */
+
+#if defined(MBEDTLS_TEST_HOOKS)
+/**
+ * \brief   Check that only a pure high-level error code is being combined with
+ *          a pure low-level error code as otherwise the resultant error code
+ *          would be corrupted.
+ *
+ * \note    Both high-level and low-level error codes cannot be greater than
+ *          zero however can be zero. If one error code is zero then the
+ *          other error code is returned even if both codes are zero.
+ *
+ * \note    If the check fails, fail the test currently being run.
+ */
+void mbedtls_test_err_add_check( int high, int low,
+                                 const char *file, int line);
+#endif
+
+#if defined(MBEDTLS_BIGNUM_C)
+/** Read an MPI from a string.
+ *
+ * Like mbedtls_mpi_read_string(), but size the resulting bignum based
+ * on the number of digits in the string. In particular, construct a
+ * bignum with 0 limbs for an empty string, and a bignum with leading 0
+ * limbs if the string has sufficiently many leading 0 digits.
+ *
+ * This is important so that the "0 (null)" and "0 (1 limb)" and
+ * "leading zeros" test cases do what they claim.
+ *
+ * \param[out] X        The MPI object to populate. It must be initialized.
+ * \param radix         The radix (2 to 16).
+ * \param[in] s         The null-terminated string to read from.
+ *
+ * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
+ */
+/* Since the library has exactly the desired behavior, this is trivial. */
+int mbedtls_test_read_mpi( mbedtls_mpi *X, int radix, const char *s );
+#endif /* MBEDTLS_BIGNUM_C */
+
 #endif /* TEST_HELPERS_H */
diff --git a/third_party/mbedtls/repo/tests/include/test/macros.h b/third_party/mbedtls/repo/tests/include/test/macros.h
index f404780..7b4c2f6 100644
--- a/third_party/mbedtls/repo/tests/include/test/macros.h
+++ b/third_party/mbedtls/repo/tests/include/test/macros.h
@@ -51,6 +51,243 @@
 #include "mbedtls/memory_buffer_alloc.h"
 #endif
 
+/**
+ * \brief   This macro tests the expression passed to it as a test step or
+ *          individual test in a test case.
+ *
+ *          It allows a library function to return a value and return an error
+ *          code that can be tested.
+ *
+ *          When MBEDTLS_CHECK_PARAMS is enabled, calls to the parameter failure
+ *          callback, MBEDTLS_PARAM_FAILED(), will be assumed to be a test
+ *          failure.
+ *
+ *          This macro is not suitable for negative parameter validation tests,
+ *          as it assumes the test step will not create an error.
+ *
+ *          Failing the test means:
+ *          - Mark this test case as failed.
+ *          - Print a message identifying the failure.
+ *          - Jump to the \c exit label.
+ *
+ *          This macro expands to an instruction, not an expression.
+ *          It may jump to the \c exit label.
+ *
+ * \param   TEST    The test expression to be tested.
+ */
+#define TEST_ASSERT( TEST )                                 \
+    do {                                                    \
+       if( ! (TEST) )                                       \
+       {                                                    \
+          mbedtls_test_fail( #TEST, __LINE__, __FILE__ );   \
+          goto exit;                                        \
+       }                                                    \
+    } while( 0 )
+
+/** Evaluate two integer expressions and fail the test case if they have
+ * different values.
+ *
+ * The two expressions should have the same signedness, otherwise the
+ * comparison is not meaningful if the signed value is negative.
+ *
+ * \param expr1     An integral-typed expression to evaluate.
+ * \param expr2     Another integral-typed expression to evaluate.
+ */
+#define TEST_EQUAL( expr1, expr2 )                                      \
+    do {                                                                \
+        if( ! mbedtls_test_equal( #expr1 " == " #expr2, __LINE__, __FILE__, \
+                                  expr1, expr2 ) )                      \
+            goto exit;                                                  \
+    } while( 0 )
+
+/** Allocate memory dynamically and fail the test case if this fails.
+ * The allocated memory will be filled with zeros.
+ *
+ * You must set \p pointer to \c NULL before calling this macro and
+ * put `mbedtls_free( pointer )` in the test's cleanup code.
+ *
+ * If \p length is zero, the resulting \p pointer will be \c NULL.
+ * This is usually what we want in tests since API functions are
+ * supposed to accept null pointers when a buffer size is zero.
+ *
+ * This macro expands to an instruction, not an expression.
+ * It may jump to the \c exit label.
+ *
+ * \param pointer   An lvalue where the address of the allocated buffer
+ *                  will be stored.
+ *                  This expression may be evaluated multiple times.
+ * \param length    Number of elements to allocate.
+ *                  This expression may be evaluated multiple times.
+ *
+ */
+#define ASSERT_ALLOC( pointer, length )                           \
+    do                                                            \
+    {                                                             \
+        TEST_ASSERT( ( pointer ) == NULL );                       \
+        if( ( length ) != 0 )                                     \
+        {                                                         \
+            ( pointer ) = mbedtls_calloc( sizeof( *( pointer ) ), \
+                                          ( length ) );           \
+            TEST_ASSERT( ( pointer ) != NULL );                   \
+        }                                                         \
+    }                                                             \
+    while( 0 )
+
+/** Allocate memory dynamically. If the allocation fails, skip the test case.
+ *
+ * This macro behaves like #ASSERT_ALLOC, except that if the allocation
+ * fails, it marks the test as skipped rather than failed.
+ */
+#define ASSERT_ALLOC_WEAK( pointer, length )                      \
+    do                                                            \
+    {                                                             \
+        TEST_ASSERT( ( pointer ) == NULL );                       \
+        if( ( length ) != 0 )                                     \
+        {                                                         \
+            ( pointer ) = mbedtls_calloc( sizeof( *( pointer ) ), \
+                                          ( length ) );           \
+            TEST_ASSUME( ( pointer ) != NULL );                   \
+        }                                                         \
+    }                                                             \
+    while( 0 )
+
+/** Compare two buffers and fail the test case if they differ.
+ *
+ * This macro expands to an instruction, not an expression.
+ * It may jump to the \c exit label.
+ *
+ * \param p1        Pointer to the start of the first buffer.
+ * \param size1     Size of the first buffer in bytes.
+ *                  This expression may be evaluated multiple times.
+ * \param p2        Pointer to the start of the second buffer.
+ * \param size2     Size of the second buffer in bytes.
+ *                  This expression may be evaluated multiple times.
+ */
+#define ASSERT_COMPARE( p1, size1, p2, size2 )                          \
+    do                                                                  \
+    {                                                                   \
+        TEST_ASSERT( ( size1 ) == ( size2 ) );                          \
+        if( ( size1 ) != 0 )                                            \
+            TEST_ASSERT( memcmp( ( p1 ), ( p2 ), ( size1 ) ) == 0 );    \
+    }                                                                   \
+    while( 0 )
+
+/**
+ * \brief   This macro tests the expression passed to it and skips the
+ *          running test if it doesn't evaluate to 'true'.
+ *
+ * \param   TEST    The test expression to be tested.
+ */
+#define TEST_ASSUME( TEST )                                 \
+    do {                                                    \
+        if( ! (TEST) )                                      \
+        {                                                   \
+            mbedtls_test_skip( #TEST, __LINE__, __FILE__ ); \
+            goto exit;                                      \
+        }                                                   \
+    } while( 0 )
+
+#if defined(MBEDTLS_CHECK_PARAMS) && !defined(MBEDTLS_PARAM_FAILED_ALT)
+/**
+ * \brief   This macro tests the statement passed to it as a test step or
+ *          individual test in a test case. The macro assumes the test will fail
+ *          and will generate an error.
+ *
+ *          It allows a library function to return a value and tests the return
+ *          code on return to confirm the given error code was returned.
+ *
+ *          When MBEDTLS_CHECK_PARAMS is enabled, calls to the parameter failure
+ *          callback, MBEDTLS_PARAM_FAILED(), are assumed to indicate the
+ *          expected failure, and the test will pass.
+ *
+ *          This macro is intended for negative parameter validation tests,
+ *          where the failing function may return an error value or call
+ *          MBEDTLS_PARAM_FAILED() to indicate the error.
+ *
+ * \param   PARAM_ERROR_VALUE   The expected error code.
+ *
+ * \param   TEST                The test expression to be tested.
+ */
+#define TEST_INVALID_PARAM_RET( PARAM_ERR_VALUE, TEST )                 \
+    do {                                                                \
+        mbedtls_test_param_failed_expect_call( );                       \
+        if( ( ( TEST ) != ( PARAM_ERR_VALUE ) ) ||                      \
+            ( mbedtls_test_param_failed_check_expected_call( ) != 0 ) ) \
+        {                                                               \
+            mbedtls_test_fail( #TEST, __LINE__, __FILE__ );             \
+            goto exit;                                                  \
+        }                                                               \
+        mbedtls_test_param_failed_check_expected_call( );               \
+   } while( 0 )
+
+/**
+ * \brief   This macro tests the statement passed to it as a test step or
+ *          individual test in a test case. The macro assumes the test will fail
+ *          and will generate an error.
+ *
+ *          It assumes the library function under test cannot return a value and
+ *          assumes errors can only be indicated byt calls to
+ *          MBEDTLS_PARAM_FAILED().
+ *
+ *          When MBEDTLS_CHECK_PARAMS is enabled, calls to the parameter failure
+ *          callback, MBEDTLS_PARAM_FAILED(), are assumed to indicate the
+ *          expected failure. If MBEDTLS_CHECK_PARAMS is not enabled, no test
+ *          can be made.
+ *
+ *          This macro is intended for negative parameter validation tests,
+ *          where the failing function can only return an error by calling
+ *          MBEDTLS_PARAM_FAILED() to indicate the error.
+ *
+ * \param   TEST                The test expression to be tested.
+ */
+#define TEST_INVALID_PARAM( TEST )                                       \
+    do {                                                                 \
+        memcpy( jmp_tmp, mbedtls_test_param_failed_get_state_buf( ),     \
+                sizeof( jmp_tmp ) );                                     \
+        if( setjmp(  mbedtls_test_param_failed_get_state_buf( ) ) == 0 ) \
+        {                                                                \
+            TEST;                                                        \
+            mbedtls_test_fail( #TEST, __LINE__, __FILE__ );              \
+            goto exit;                                                   \
+        }                                                                \
+        mbedtls_test_param_failed_reset_state( );                        \
+    } while( 0 )
+#endif /* MBEDTLS_CHECK_PARAMS && !MBEDTLS_PARAM_FAILED_ALT */
+
+/**
+ * \brief   This macro tests the statement passed to it as a test step or
+ *          individual test in a test case. The macro assumes the test will not fail.
+ *
+ *          It assumes the library function under test cannot return a value and
+ *          assumes errors can only be indicated by calls to
+ *          MBEDTLS_PARAM_FAILED().
+ *
+ *          When MBEDTLS_CHECK_PARAMS is enabled, calls to the parameter failure
+ *          callback, MBEDTLS_PARAM_FAILED(), are assumed to indicate the
+ *          expected failure. If MBEDTLS_CHECK_PARAMS is not enabled, no test
+ *          can be made.
+ *
+ *          This macro is intended to test that functions returning void
+ *          accept all of the parameter values they're supposed to accept - eg
+ *          that they don't call MBEDTLS_PARAM_FAILED() when a parameter
+ *          that's allowed to be NULL happens to be NULL.
+ *
+ *          Note: for functions that return something other that void,
+ *          checking that they accept all the parameters they're supposed to
+ *          accept is best done by using TEST_ASSERT() and checking the return
+ *          value as well.
+ *
+ *          Note: this macro is available even when #MBEDTLS_CHECK_PARAMS is
+ *          disabled, as it makes sense to check that the functions accept all
+ *          legal values even if this option is disabled - only in that case,
+ *          the test is more about whether the function segfaults than about
+ *          whether it invokes MBEDTLS_PARAM_FAILED().
+ *
+ * \param   TEST                The test expression to be tested.
+ */
+#define TEST_VALID_PARAM( TEST )                                    \
+    TEST_ASSERT( ( TEST, 1 ) );
+
 #define TEST_HELPER_ASSERT(a) if( !( a ) )                          \
 {                                                                   \
     mbedtls_fprintf( stderr, "Assertion Failed at %s:%d - %s\n",    \
@@ -58,40 +295,45 @@
     mbedtls_exit( 1 );                                              \
 }
 
+/** \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] ) ) )
-#else
-/* On platforms where we don't know how to implement this check,
- * omit it. Oh well, a non-portable check is better than nothing. */
-#define IS_ARRAY_NOT_POINTER( arg ) 1
-#endif
-
 /* 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_UNSAFE( array )            \
-    ( sizeof( array ) / sizeof( *( array ) ) )
-/** 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.
- */
 #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
+
 /** Return the smaller of two values.
  *
  * \param x         An integer-valued expression without side effects.
diff --git a/third_party/mbedtls/repo/tests/include/test/psa_crypto_helpers.h b/third_party/mbedtls/repo/tests/include/test/psa_crypto_helpers.h
index 01b0547..f5622e2 100644
--- a/third_party/mbedtls/repo/tests/include/test/psa_crypto_helpers.h
+++ b/third_party/mbedtls/repo/tests/include/test/psa_crypto_helpers.h
@@ -21,84 +21,138 @@
 #ifndef PSA_CRYPTO_HELPERS_H
 #define PSA_CRYPTO_HELPERS_H
 
+#include "test/helpers.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
 #include "test/psa_helpers.h"
 
 #include <psa/crypto.h>
-#include <psa_crypto_slot_management.h>
 
-static int test_helper_is_psa_pristine( int line, const char *file )
-{
-    mbedtls_psa_stats_t stats;
-    const char *msg = NULL;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "mbedtls/psa_util.h"
+#endif
 
-    mbedtls_psa_get_stats( &stats );
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
 
-    if( stats.volatile_slots != 0 )
-        msg = "A volatile slot has not been closed properly.";
-    else if( stats.persistent_slots != 0 )
-        msg = "A persistent slot has not been closed properly.";
-    else if( stats.external_slots != 0 )
-        msg = "An external slot has not been closed properly.";
-    else if( stats.half_filled_slots != 0 )
-        msg = "A half-filled slot has not been cleared properly.";
-    else if( stats.locked_slots != 0 )
-    {
-        msg = "Some slots are still marked as locked.";
-    }
+/* Internal function for #TEST_USES_KEY_ID. Return 1 on success, 0 on failure. */
+int mbedtls_test_uses_key_id( mbedtls_svc_key_id_t key_id );
 
-    /* If the test has already failed, don't overwrite the failure
-     * information. Do keep the stats lookup above, because it can be
-     * convenient to break on it when debugging a failure. */
-    if( msg != NULL && test_info.result == TEST_RESULT_SUCCESS )
-        test_fail( msg, line, file );
+/** Destroy persistent keys recorded with #TEST_USES_KEY_ID.
+ */
+void mbedtls_test_psa_purge_key_storage( void );
 
-    return( msg == NULL );
-}
+/** Purge the in-memory cache of persistent keys recorded with
+ * #TEST_USES_KEY_ID.
+ *
+ * Call this function before calling PSA_DONE() if it's ok for
+ * persistent keys to still exist at this point.
+ */
+void mbedtls_test_psa_purge_key_cache( void );
+
+/** \def TEST_USES_KEY_ID
+ *
+ * Call this macro in a test function before potentially creating a
+ * persistent key. Test functions that use this mechanism must call
+ * mbedtls_test_psa_purge_key_storage() in their cleanup code.
+ *
+ * This macro records a persistent key identifier as potentially used in the
+ * current test case. Recorded key identifiers will be cleaned up at the end
+ * of the test case, even on failure.
+ *
+ * This macro has no effect on volatile keys. Therefore, it is safe to call
+ * this macro in a test function that creates either volatile or persistent
+ * keys depending on the test data.
+ *
+ * This macro currently has no effect on special identifiers
+ * used to store implementation-specific files.
+ *
+ * Calling this macro multiple times on the same key identifier in the same
+ * test case has no effect.
+ *
+ * This macro can fail the test case if there isn't enough memory to
+ * record the key id.
+ *
+ * \param key_id    The PSA key identifier to record.
+ */
+#define TEST_USES_KEY_ID( key_id )                      \
+    TEST_ASSERT( mbedtls_test_uses_key_id( key_id ) )
+
+#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
+
+#define TEST_USES_KEY_ID( key_id ) ( (void) ( key_id ) )
+#define mbedtls_test_psa_purge_key_storage( ) ( (void) 0 )
+#define mbedtls_test_psa_purge_key_cache( ) ( (void) 0 )
+
+#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
+
+#define PSA_INIT( ) PSA_ASSERT( psa_crypto_init( ) )
+
+/** Check for things that have not been cleaned up properly in the
+ * PSA subsystem.
+ *
+ * \return NULL if nothing has leaked.
+ * \return A string literal explaining what has not been cleaned up
+ *         if applicable.
+ */
+const char *mbedtls_test_helper_is_psa_leaking( void );
 
 /** Check that no PSA Crypto key slots are in use.
+ *
+ * If any slots are in use, mark the current test as failed and jump to
+ * the exit label. This is equivalent to
+ * `TEST_ASSERT( ! mbedtls_test_helper_is_psa_leaking( ) )`
+ * but with a more informative message.
  */
-#define ASSERT_PSA_PRISTINE( )                                    \
-    do                                                            \
-    {                                                             \
-        if( ! test_helper_is_psa_pristine( __LINE__, __FILE__ ) ) \
-            goto exit;                                            \
-    }                                                             \
+#define ASSERT_PSA_PRISTINE( )                                          \
+    do                                                                  \
+    {                                                                   \
+        if( test_fail_if_psa_leaking( __LINE__, __FILE__ ) )            \
+            goto exit;                                                  \
+    }                                                                   \
     while( 0 )
 
-static void test_helper_psa_done( int line, const char *file )
-{
-    (void) test_helper_is_psa_pristine( line, file );
-    mbedtls_psa_crypto_free( );
-}
-
-/** Shut down the PSA Crypto subsystem. Expect a clean shutdown, with no slots
- * in use.
+/** Shut down the PSA Crypto subsystem and destroy persistent keys.
+ * Expect a clean shutdown, with no slots in use.
+ *
+ * If some key slots are still in use, record the test case as failed,
+ * but continue executing. This macro is suitable (and primarily intended)
+ * for use in the cleanup section of test functions.
+ *
+ * \note Persistent keys must be recorded with #TEST_USES_KEY_ID before
+ *       creating them.
  */
-#define PSA_DONE( ) test_helper_psa_done( __LINE__, __FILE__ )
+#define PSA_DONE( )                                                     \
+    do                                                                  \
+    {                                                                   \
+        test_fail_if_psa_leaking( __LINE__, __FILE__ );                 \
+        mbedtls_test_psa_purge_key_storage( );                          \
+        mbedtls_psa_crypto_free( );                                     \
+    }                                                                   \
+    while( 0 )
+
+/** Shut down the PSA Crypto subsystem, allowing persistent keys to survive.
+ * Expect a clean shutdown, with no slots in use.
+ *
+ * If some key slots are still in use, record the test case as failed and
+ * jump to the `exit` label.
+ */
+#define PSA_SESSION_DONE( )                                             \
+    do                                                                  \
+    {                                                                   \
+        mbedtls_test_psa_purge_key_cache( );                            \
+        ASSERT_PSA_PRISTINE( );                                         \
+        mbedtls_psa_crypto_free( );                                     \
+    }                                                                   \
+    while( 0 )
 
 
 
 #if defined(RECORD_PSA_STATUS_COVERAGE_LOG)
-#include <psa/crypto.h>
-
-/** Name of the file where return statuses are logged by #RECORD_STATUS. */
-#define STATUS_LOG_FILE_NAME "statuses.log"
-
-static psa_status_t record_status( psa_status_t status,
-                                   const char *func,
-                                   const char *file, int line,
-                                   const char *expr )
-{
-    /* We open the log file on first use.
-     * We never close the log file, so the record_status feature is not
-     * compatible with resource leak detectors such as Asan.
-     */
-    static FILE *log;
-    if( log == NULL )
-        log = fopen( STATUS_LOG_FILE_NAME, "a" );
-    fprintf( log, "%d:%s:%s:%d:%s\n", (int) status, func, file, line, expr );
-    return( status );
-}
+psa_status_t mbedtls_test_record_status( psa_status_t status,
+                                         const char *func,
+                                         const char *file, int line,
+                                         const char *expr );
 
 /** Return value logging wrapper macro.
  *
@@ -125,10 +179,127 @@
  * \return          The value of \p expr.
  */
 #define RECORD_STATUS( string, expr )                                   \
-    record_status( ( expr ), string, __FILE__, __LINE__, #expr )
+    mbedtls_test_record_status( ( expr ), string, __FILE__, __LINE__, #expr )
 
 #include "instrument_record_status.h"
 
 #endif /* defined(RECORD_PSA_STATUS_COVERAGE_LOG) */
 
+/** Return extended key usage policies.
+ *
+ * Do a key policy permission extension on key usage policies always involves
+ * permissions of other usage policies
+ * (like PSA_KEY_USAGE_SIGN_HASH involves PSA_KEY_USAGE_SIGN_MESSGAE).
+ */
+psa_key_usage_t mbedtls_test_update_key_usage_flags( psa_key_usage_t usage_flags );
+
+/** Skip a test case if the given key is a 192 bits AES key and the AES
+ *  implementation is at least partially provided by an accelerator or
+ *  alternative implementation.
+ *
+ *  Call this macro in a test case when a cryptographic operation that may
+ *  involve an AES operation returns a #PSA_ERROR_NOT_SUPPORTED error code.
+ *  The macro call will skip and not fail the test case in case the operation
+ *  involves a 192 bits AES key and the AES implementation is at least
+ *  partially provided by an accelerator or alternative implementation.
+ *
+ *  Hardware AES implementations not supporting 192 bits keys commonly exist.
+ *  Consequently, PSA test cases aim at not failing when an AES operation with
+ *  a 192 bits key performed by an alternative AES implementation returns
+ *  with the #PSA_ERROR_NOT_SUPPORTED error code. The purpose of this macro
+ *  is to facilitate this and make the test case code more readable.
+ *
+ *  \param key_type  Key type
+ *  \param key_bits  Key length in number of bits.
+ */
+#if defined(MBEDTLS_AES_ALT) || \
+    defined(MBEDTLS_AES_SETKEY_ENC_ALT) || \
+    defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES)
+#define MBEDTLS_TEST_HAVE_ALT_AES 1
+#else
+#define MBEDTLS_TEST_HAVE_ALT_AES 0
+#endif
+
+#define MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192( key_type, key_bits )        \
+    do                                                                    \
+    {                                                                     \
+        if( ( MBEDTLS_TEST_HAVE_ALT_AES ) &&                              \
+            ( ( key_type ) == PSA_KEY_TYPE_AES ) &&                       \
+            ( key_bits == 192 ) )                                         \
+        {                                                                 \
+            mbedtls_test_skip( "AES-192 not supported", __LINE__, __FILE__ );     \
+            goto exit;                                                    \
+        }                                                                 \
+    }                                                                     \
+    while( 0 )
+
+/** Skip a test case if a GCM operation with a nonce length different from
+ *  12 bytes fails and was performed by an accelerator or alternative
+ *  implementation.
+ *
+ *  Call this macro in a test case when an AEAD cryptography operation that
+ *  may involve the GCM mode returns with a #PSA_ERROR_NOT_SUPPORTED error
+ *  code. The macro call will skip and not fail the test case in case the
+ *  operation involves the GCM mode, a nonce with a length different from
+ *  12 bytes and the GCM mode implementation is an alternative one.
+ *
+ *  Hardware GCM implementations not supporting nonce lengths different from
+ *  12 bytes commonly exist, as supporting a non-12-byte nonce requires
+ *  additional computations involving the GHASH function.
+ *  Consequently, PSA test cases aim at not failing when an AEAD operation in
+ *  GCM mode with a nonce length different from 12 bytes is performed by an
+ *  alternative GCM implementation and returns with a #PSA_ERROR_NOT_SUPPORTED
+ *  error code. The purpose of this macro is to facilitate this check and make
+ *  the test case code more readable.
+ *
+ *  \param  alg             The AEAD algorithm.
+ *  \param  nonce_length    The nonce length in number of bytes.
+ */
+#if defined(MBEDTLS_GCM_ALT) || \
+    defined(MBEDTLS_PSA_ACCEL_ALG_GCM)
+#define MBEDTLS_TEST_HAVE_ALT_GCM  1
+#else
+#define MBEDTLS_TEST_HAVE_ALT_GCM  0
+#endif
+
+#define MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE( alg,           \
+                                                            nonce_length ) \
+    do                                                                     \
+    {                                                                      \
+        if( ( MBEDTLS_TEST_HAVE_ALT_GCM ) &&                               \
+            ( PSA_ALG_AEAD_WITH_SHORTENED_TAG( ( alg ) , 0 ) ==            \
+              PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ) ) &&       \
+            ( ( nonce_length ) != 12 ) )                                   \
+        {                                                                  \
+            mbedtls_test_skip( "GCM with non-12-byte IV is not supported", __LINE__, __FILE__ ); \
+            goto exit;                                                     \
+        }                                                                  \
+    }                                                                      \
+    while( 0 )
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
+/** \def USE_PSA_INIT
+ *
+ * Call this macro to initialize the PSA subsystem if #MBEDTLS_USE_PSA_CRYPTO
+ * is enabled and do nothing otherwise. If the initialization fails, mark
+ * the test case as failed and jump to the \p exit label.
+ */
+/** \def USE_PSA_DONE
+ *
+ * Call this macro at the end of a test case if you called #USE_PSA_INIT.
+ * This is like #PSA_DONE, except that it does nothing if
+ * #MBEDTLS_USE_PSA_CRYPTO is disabled.
+ */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#define USE_PSA_INIT( ) PSA_INIT( )
+#define USE_PSA_DONE( ) PSA_DONE( )
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+/* Define empty macros so that we can use them in the preamble and teardown
+ * of every test function that uses PSA conditionally based on
+ * MBEDTLS_USE_PSA_CRYPTO. */
+#define USE_PSA_INIT( ) ( (void) 0 )
+#define USE_PSA_DONE( ) ( (void) 0 )
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
+
 #endif /* PSA_CRYPTO_HELPERS_H */
diff --git a/third_party/mbedtls/repo/tests/include/test/psa_exercise_key.h b/third_party/mbedtls/repo/tests/include/test/psa_exercise_key.h
new file mode 100644
index 0000000..e67f515
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/include/test/psa_exercise_key.h
@@ -0,0 +1,269 @@
+/** Code to exercise a PSA key object, i.e. validate that it seems well-formed
+ * and can do what it is supposed to do.
+ */
+/*
+ *  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 PSA_EXERCISE_KEY_H
+#define PSA_EXERCISE_KEY_H
+
+#include "test/helpers.h"
+#include "test/psa_crypto_helpers.h"
+
+#include <psa/crypto.h>
+
+/** \def KNOWN_SUPPORTED_HASH_ALG
+ *
+ * A hash algorithm that is known to be supported.
+ *
+ * This is used in some smoke tests.
+ */
+#if defined(PSA_WANT_ALG_MD2)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_MD2
+#elif defined(PSA_WANT_ALG_MD4)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_MD4
+#elif defined(PSA_WANT_ALG_MD5)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_MD5
+/* MBEDTLS_RIPEMD160_C omitted. This is necessary for the sake of
+ * exercise_signature_key() because Mbed TLS doesn't support RIPEMD160
+ * in RSA PKCS#1v1.5 signatures. A RIPEMD160-only configuration would be
+ * implausible anyway. */
+#elif defined(PSA_WANT_ALG_SHA_1)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_1
+#elif defined(PSA_WANT_ALG_SHA_256)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_256
+#elif defined(PSA_WANT_ALG_SHA_384)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_384
+#elif defined(PSA_WANT_ALG_SHA_512)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_512
+#elif defined(PSA_WANT_ALG_SHA3_256)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA3_256
+#else
+#undef KNOWN_SUPPORTED_HASH_ALG
+#endif
+
+/** \def KNOWN_MBEDTLS_SUPPORTED_HASH_ALG
+ *
+ * A hash algorithm that is known to be supported by Mbed TLS APIs.
+ *
+ * This is used in some smoke tests where the hash algorithm is used as
+ * part of another algorithm like a signature algorithm and the hashing is
+ * completed through an Mbed TLS hash API, not the PSA one.
+ */
+#if defined(MBEDTLS_MD2_C)
+#define KNOWN_MBEDTLS_SUPPORTED_HASH_ALG PSA_ALG_MD2
+#elif defined(MBEDTLS_MD4_C)
+#define KNOWN_MBEDTLS_SUPPORTED_HASH_ALG PSA_ALG_MD4
+#elif defined(MBEDTLS_MD5_C)
+#define KNOWN_MBEDTLS_SUPPORTED_HASH_ALG PSA_ALG_MD5
+/* MBEDTLS_RIPEMD160_C omitted. This is necessary for the sake of
+ * exercise_signature_key() because Mbed TLS doesn't support RIPEMD160
+ * in RSA PKCS#1v1.5 signatures. A RIPEMD160-only configuration would be
+ * implausible anyway. */
+#elif defined(MBEDTLS_SHA1_C)
+#define KNOWN_MBEDTLS_SUPPORTED_HASH_ALG PSA_ALG_SHA_1
+#elif defined(MBEDTLS_SHA256_C)
+#define KNOWN_MBEDTLS_SUPPORTED_HASH_ALG PSA_ALG_SHA_256
+#elif defined(MBEDTLS_SHA512_C)
+#define KNOWN_MBEDTLS_SUPPORTED_HASH_ALG PSA_ALG_SHA_512
+#else
+#undef KNOWN_MBEDLTS_SUPPORTED_HASH_ALG
+#endif
+
+/** \def KNOWN_SUPPORTED_BLOCK_CIPHER
+ *
+ * A block cipher that is known to be supported.
+ *
+ * For simplicity's sake, stick to block ciphers with 16-byte blocks.
+ */
+#if defined(MBEDTLS_AES_C)
+#define KNOWN_SUPPORTED_BLOCK_CIPHER PSA_KEY_TYPE_AES
+#elif defined(MBEDTLS_ARIA_C)
+#define KNOWN_SUPPORTED_BLOCK_CIPHER PSA_KEY_TYPE_ARIA
+#elif defined(MBEDTLS_CAMELLIA_C)
+#define KNOWN_SUPPORTED_BLOCK_CIPHER PSA_KEY_TYPE_CAMELLIA
+#undef KNOWN_SUPPORTED_BLOCK_CIPHER
+#endif
+
+/** \def KNOWN_SUPPORTED_MAC_ALG
+ *
+ * A MAC mode that is known to be supported.
+ *
+ * It must either be HMAC with #KNOWN_SUPPORTED_HASH_ALG or
+ * a block cipher-based MAC with #KNOWN_SUPPORTED_BLOCK_CIPHER.
+ *
+ * This is used in some smoke tests.
+ */
+#if defined(KNOWN_SUPPORTED_HASH_ALG) && defined(PSA_WANT_ALG_HMAC)
+#define KNOWN_SUPPORTED_MAC_ALG ( PSA_ALG_HMAC( KNOWN_SUPPORTED_HASH_ALG ) )
+#define KNOWN_SUPPORTED_MAC_KEY_TYPE PSA_KEY_TYPE_HMAC
+#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CMAC_C)
+#define KNOWN_SUPPORTED_MAC_ALG PSA_ALG_CMAC
+#define KNOWN_SUPPORTED_MAC_KEY_TYPE KNOWN_SUPPORTED_BLOCK_CIPHER
+#else
+#undef KNOWN_SUPPORTED_MAC_ALG
+#undef KNOWN_SUPPORTED_MAC_KEY_TYPE
+#endif
+
+/** \def KNOWN_SUPPORTED_BLOCK_CIPHER_ALG
+ *
+ * A cipher algorithm and key type that are known to be supported.
+ *
+ * This is used in some smoke tests.
+ */
+#if defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CIPHER_MODE_CTR)
+#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_CTR
+#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CIPHER_MODE_CBC)
+#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_CBC_NO_PADDING
+#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CIPHER_MODE_CFB)
+#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_CFB
+#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CIPHER_MODE_OFB)
+#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_OFB
+#else
+#undef KNOWN_SUPPORTED_BLOCK_CIPHER_ALG
+#endif
+#if defined(KNOWN_SUPPORTED_BLOCK_CIPHER_ALG)
+#define KNOWN_SUPPORTED_CIPHER_ALG KNOWN_SUPPORTED_BLOCK_CIPHER_ALG
+#define KNOWN_SUPPORTED_CIPHER_KEY_TYPE KNOWN_SUPPORTED_BLOCK_CIPHER
+#elif defined(MBEDTLS_RC4_C)
+#define KNOWN_SUPPORTED_CIPHER_ALG PSA_ALG_RC4
+#define KNOWN_SUPPORTED_CIPHER_KEY_TYPE PSA_KEY_TYPE_RC4
+#else
+#undef KNOWN_SUPPORTED_CIPHER_ALG
+#undef KNOWN_SUPPORTED_CIPHER_KEY_TYPE
+#endif
+
+/** Convenience function to set up a key derivation.
+ *
+ * In case of failure, mark the current test case as failed.
+ *
+ * The inputs \p input1 and \p input2 are, in order:
+ * - HKDF: salt, info.
+ * - TKS 1.2 PRF, TLS 1.2 PSK-to-MS: seed, label.
+ *
+ * \param operation         The operation object to use.
+ *                          It must be in the initialized state.
+ * \param key               The key to use.
+ * \param alg               The algorithm to use.
+ * \param input1            The first input to pass.
+ * \param input1_length     The length of \p input1 in bytes.
+ * \param input2            The first input to pass.
+ * \param input2_length     The length of \p input2 in bytes.
+ * \param capacity          The capacity to set.
+ *
+ * \return                  \c 1 on success, \c 0 on failure.
+ */
+int mbedtls_test_psa_setup_key_derivation_wrap(
+    psa_key_derivation_operation_t* operation,
+    mbedtls_svc_key_id_t key,
+    psa_algorithm_t alg,
+    const unsigned char* input1, size_t input1_length,
+    const unsigned char* input2, size_t input2_length,
+    size_t capacity );
+
+/** Perform a key agreement using the given key pair against its public key
+ * using psa_raw_key_agreement().
+ *
+ * The result is discarded. The purpose of this function is to smoke-test a key.
+ *
+ * In case of failure, mark the current test case as failed.
+ *
+ * \param alg               A key agreement algorithm compatible with \p key.
+ * \param key               A key that allows key agreement with \p alg.
+ *
+ * \return                  \c 1 on success, \c 0 on failure.
+ */
+psa_status_t mbedtls_test_psa_raw_key_agreement_with_self(
+    psa_algorithm_t alg,
+    mbedtls_svc_key_id_t key );
+
+/** Perform a key agreement using the given key pair against its public key
+ * using psa_key_derivation_raw_key().
+ *
+ * The result is discarded. The purpose of this function is to smoke-test a key.
+ *
+ * In case of failure, mark the current test case as failed.
+ *
+ * \param operation         An operation that has been set up for a key
+ *                          agreement algorithm that is compatible with
+ *                          \p key.
+ * \param key               A key pair object that is suitable for a key
+ *                          agreement with \p operation.
+ *
+ * \return                  \c 1 on success, \c 0 on failure.
+ */
+psa_status_t mbedtls_test_psa_key_agreement_with_self(
+    psa_key_derivation_operation_t *operation,
+    mbedtls_svc_key_id_t key );
+
+/** Perform sanity checks on the given key representation.
+ *
+ * If any of the checks fail, mark the current test case as failed.
+ *
+ * The checks depend on the key type.
+ * - All types: check the export size against maximum-size macros.
+ * - DES: parity bits.
+ * - RSA: check the ASN.1 structure and the size and parity of the integers.
+ * - ECC private or public key: exact representation length.
+ * - Montgomery public key: first byte.
+ *
+ * \param type              The key type.
+ * \param bits              The key size in bits.
+ * \param exported          A buffer containing the key representation.
+ * \param exported_length   The length of \p exported in bytes.
+ *
+ * \return                  \c 1 if all checks passed, \c 0 on failure.
+ */
+int mbedtls_test_psa_exported_key_sanity_check(
+    psa_key_type_t type, size_t bits,
+    const uint8_t *exported, size_t exported_length );
+
+/** Do smoke tests on a key.
+ *
+ * Perform one of each operation indicated by \p alg (decrypt/encrypt,
+ * sign/verify, or derivation) that is permitted according to \p usage.
+ * \p usage and \p alg should correspond to the expected policy on the
+ * key.
+ *
+ * Export the key if permitted by \p usage, and check that the output
+ * looks sensible. If \p usage forbids export, check that
+ * \p psa_export_key correctly rejects the attempt. If the key is
+ * asymmetric, also check \p psa_export_public_key.
+ *
+ * If the key fails the tests, this function calls the test framework's
+ * `mbedtls_test_fail` function and returns false. Otherwise this function
+ * returns true. Therefore it should be used as follows:
+ * ```
+ * if( ! exercise_key( ... ) ) goto exit;
+ * ```
+ *
+ * \param key       The key to exercise. It should be capable of performing
+ *                  \p alg.
+ * \param usage     The usage flags to assume.
+ * \param alg       The algorithm to exercise.
+ *
+ * \retval 0 The key failed the smoke tests.
+ * \retval 1 The key passed the smoke tests.
+ */
+int mbedtls_test_psa_exercise_key( mbedtls_svc_key_id_t key,
+                                   psa_key_usage_t usage,
+                                   psa_algorithm_t alg );
+
+psa_key_usage_t mbedtls_test_psa_usage_to_exercise( psa_key_type_t type,
+                                                    psa_algorithm_t alg );
+
+#endif /* PSA_EXERCISE_KEY_H */
diff --git a/third_party/mbedtls/repo/tests/include/test/random.h b/third_party/mbedtls/repo/tests/include/test/random.h
index 5e7e4e6..6428280 100644
--- a/third_party/mbedtls/repo/tests/include/test/random.h
+++ b/third_party/mbedtls/repo/tests/include/test/random.h
@@ -36,8 +36,11 @@
 
 typedef struct
 {
-    unsigned char *buf;
+    unsigned char *buf; /* Pointer to a buffer of length bytes. */
     size_t length;
+    /* If fallback_f_rng is NULL, fail after delivering length bytes. */
+    int ( *fallback_f_rng )( void*, unsigned char *, size_t );
+    void *fallback_p_rng;
 } mbedtls_test_rnd_buf_info;
 
 /**
@@ -67,24 +70,25 @@
                                size_t len );
 
 /**
- * This function only returns zeros
+ * This function only returns zeros.
  *
- * rng_state shall be NULL.
+ * \p rng_state shall be \c NULL.
  */
 int mbedtls_test_rnd_zero_rand( void *rng_state,
                                 unsigned char *output,
                                 size_t len );
 
 /**
- * This function returns random based on a buffer it receives.
+ * This function returns random data based on a buffer it receives.
  *
- * rng_state shall be a pointer to a rnd_buf_info structure.
+ * \p rng_state shall be a pointer to a #mbedtls_test_rnd_buf_info structure.
  *
  * The number of bytes released from the buffer on each call to
- * the random function is specified by per_call. (Can be between
- * 1 and 4)
+ * the random function is specified by \p len.
  *
- * After the buffer is empty it will return rand();
+ * After the buffer is empty, this function will call the fallback RNG in the
+ * #mbedtls_test_rnd_buf_info structure if there is one, and
+ * will return #MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise.
  */
 int mbedtls_test_rnd_buffer_rand( void *rng_state,
                                   unsigned char *output,
@@ -96,7 +100,7 @@
  * Pseudo random is based on the XTEA encryption algorithm to
  * generate pseudorandom.
  *
- * rng_state shall be a pointer to a rnd_pseudo_info structure.
+ * \p rng_state shall be a pointer to a #mbedtls_test_rnd_pseudo_info structure.
  */
 int mbedtls_test_rnd_pseudo_rand( void *rng_state,
                                   unsigned char *output,
diff --git a/third_party/mbedtls/repo/tests/scripts/all.sh b/third_party/mbedtls/repo/tests/scripts/all.sh
index af59c62..c07ef34 100755
--- a/third_party/mbedtls/repo/tests/scripts/all.sh
+++ b/third_party/mbedtls/repo/tests/scripts/all.sh
@@ -1,4 +1,4 @@
-#! /usr/bin/env sh
+#! /usr/bin/env bash
 
 # all.sh
 #
@@ -59,6 +59,15 @@
 # This script must be invoked from the toplevel directory of a git
 # working copy of Mbed TLS.
 #
+# The behavior on an error depends on whether --keep-going (alias -k)
+# is in effect.
+#  * Without --keep-going: the script stops on the first error without
+#    cleaning up. This lets you work in the configuration of the failing
+#    component.
+#  * With --keep-going: the script runs all requested components and
+#    reports failures at the end. In particular the script always cleans
+#    up on exit.
+#
 # Note that the output is not saved. You may want to run
 #   script -c tests/scripts/all.sh
 # or
@@ -81,6 +90,12 @@
 #
 # Each component must start by invoking `msg` with a short informative message.
 #
+# Warning: due to the way bash detects errors, the failure of a command
+# inside 'if' or '!' is not detected. Use the 'not' function instead of '!'.
+#
+# Each component is executed in a separate shell process. The component
+# fails if any command in it returns a non-zero status.
+#
 # The framework performs some cleanup tasks after each component. This
 # means that components can assume that the working directory is in a
 # cleaned-up state, and don't need to perform the cleanup themselves.
@@ -91,19 +106,6 @@
 #   `tests/Makefile` and `programs/fuzz/Makefile` from git.
 #   This cleans up after an in-tree use of CMake.
 #
-# Any command that is expected to fail must be protected so that the
-# script keeps running in --keep-going mode despite `set -e`. In keep-going
-# mode, if a protected command fails, this is logged as a failure and the
-# script will exit with a failure status once it has run all components.
-# Commands can be protected in any of the following ways:
-# * `make` is a function which runs the `make` command with protection.
-#   Note that you must write `make VAR=value`, not `VAR=value make`,
-#   because the `VAR=value make` syntax doesn't work with functions.
-# * Put `report_status` before the command to protect it.
-# * Put `if_build_successful` before a command. This protects it, and
-#   additionally skips it if a prior invocation of `make` in the same
-#   component failed.
-#
 # The tests are roughly in order from fastest to slowest. This doesn't
 # have to be exact, but in general you should add slower tests towards
 # the end and fast checks near the beginning.
@@ -114,8 +116,9 @@
 #### Initialization and command line parsing
 ################################################################
 
-# Abort on errors (and uninitialised variables)
-set -eu
+# Abort on errors (even on the left-hand side of a pipe).
+# Treat uninitialised variables as errors.
+set -e -o pipefail -u
 
 pre_check_environment () {
     if [ -d library -a -d include -a -d tests ]; then :; else
@@ -126,9 +129,16 @@
 
 pre_initialize_variables () {
     CONFIG_H='include/mbedtls/config.h'
-    CONFIG_BAK="$CONFIG_H.bak"
     CRYPTO_CONFIG_H='include/psa/crypto_config.h'
-    CRYPTO_CONFIG_BAK="$CRYPTO_CONFIG_H.bak"
+
+    # Files that are clobbered by some jobs will be backed up. Use a different
+    # suffix from auxiliary scripts so that all.sh and auxiliary scripts can
+    # independently decide when to remove the backup file.
+    backup_suffix='.all.bak'
+    # Files clobbered by config.py
+    files_to_back_up="$CONFIG_H $CRYPTO_CONFIG_H"
+    # Files clobbered by in-tree cmake
+    files_to_back_up="$files_to_back_up Makefile library/Makefile programs/Makefile tests/Makefile programs/fuzz/Makefile"
 
     append_outcome=0
     MEMORY=0
@@ -161,13 +171,14 @@
     : ${ARMC5_BIN_DIR:=/usr/bin}
     : ${ARMC6_BIN_DIR:=/usr/bin}
     : ${ARM_NONE_EABI_GCC_PREFIX:=arm-none-eabi-}
+    : ${ARM_LINUX_GNUEABI_GCC_PREFIX:=arm-linux-gnueabi-}
 
     # if MAKEFLAGS is not set add the -j option to speed up invocations of make
     if [ -z "${MAKEFLAGS+set}" ]; then
-        export MAKEFLAGS="-j"
+        export MAKEFLAGS="-j$(all_sh_nproc)"
     fi
 
-    # Include more verbose output for failing tests run by CMake
+    # Include more verbose output for failing tests run by CMake or make
     export CTEST_OUTPUT_ON_FAILURE=1
 
     # CFLAGS and LDFLAGS for Asan builds that don't use CMake
@@ -175,8 +186,8 @@
 
     # Gather the list of available components. These are the functions
     # defined in this script whose name starts with "component_".
-    # Parse the script with sed, because in sh there is no way to list
-    # defined functions.
+    # Parse the script with sed. This way we get the functions in the order
+    # they are defined.
     ALL_COMPONENTS=$(sed -n 's/^ *component_\([0-9A-Z_a-z]*\) *().*/\1/p' <"$0")
 
     # Exclude components that are not supported on this platform.
@@ -193,6 +204,8 @@
 # Test whether the component $1 is included in the command line patterns.
 is_component_included()
 {
+    # Temporarily disable wildcard expansion so that $COMMAND_LINE_COMPONENTS
+    # only does word splitting.
     set -f
     for pattern in $COMMAND_LINE_COMPONENTS; do
         set +f
@@ -230,7 +243,15 @@
      --arm-none-eabi-gcc-prefix=<string>
                         Prefix for a cross-compiler for arm-none-eabi
                         (default: "${ARM_NONE_EABI_GCC_PREFIX}")
+     --arm-linux-gnueabi-gcc-prefix=<string>
+                        Prefix for a cross-compiler for arm-linux-gnueabi
+                        (default: "${ARM_LINUX_GNUEABI_GCC_PREFIX}")
      --armcc            Run ARM Compiler builds (on by default).
+     --restore          First clean up the build tree, restoring backed up
+                        files. Do not run any components unless they are
+                        explicitly specified.
+     --error-test       Error test mode: run a failing function in addition
+                        to any specified component. May be repeated.
      --except           Exclude the COMPONENTs listed on the command line,
                         instead of running only those.
      --no-append-outcome    Write a new outcome file and analyze it (default).
@@ -259,13 +280,11 @@
 EOF
 }
 
-# remove built files as well as the cmake cache/config
+# Cleanup before/after running a component.
+# Remove built files as well as the cmake cache/config.
+# Does not remove generated source files.
 cleanup()
 {
-    if [ -n "${MBEDTLS_ROOT_DIR+set}" ]; then
-        cd "$MBEDTLS_ROOT_DIR"
-    fi
-
     command make clean
 
     # Remove CMake artefacts
@@ -276,21 +295,26 @@
               -iname CMakeCache.txt \) -exec rm {} \+
     # Recover files overwritten by in-tree CMake builds
     rm -f include/Makefile include/mbedtls/Makefile programs/*/Makefile
-    git update-index --no-skip-worktree Makefile library/Makefile programs/Makefile tests/Makefile programs/fuzz/Makefile
-    git checkout -- Makefile library/Makefile programs/Makefile tests/Makefile programs/fuzz/Makefile
 
     # Remove any artifacts from the component_test_cmake_as_subdirectory test.
     rm -rf programs/test/cmake_subproject/build
     rm -f programs/test/cmake_subproject/Makefile
     rm -f programs/test/cmake_subproject/cmake_subproject
 
-    if [ -f "$CONFIG_BAK" ]; then
-        mv "$CONFIG_BAK" "$CONFIG_H"
-    fi
+    # Restore files that may have been clobbered by the job
+    for x in $files_to_back_up; do
+        cp -p "$x$backup_suffix" "$x"
+    done
+}
 
-    if [ -f "$CRYPTO_CONFIG_BAK" ]; then
-        mv "$CRYPTO_CONFIG_BAK" "$CRYPTO_CONFIG_H"
-    fi
+# Final cleanup when this script exits (except when exiting on a failure
+# in non-keep-going mode).
+final_cleanup () {
+    cleanup
+
+    for x in $files_to_back_up; do
+        rm -f "$x$backup_suffix"
+    done
 }
 
 # Executed on exit. May be redefined depending on command line options.
@@ -299,7 +323,7 @@
 }
 
 fatal_signal () {
-    cleanup
+    final_cleanup
     final_report $1
     trap - $1
     kill -$1 $$
@@ -309,6 +333,18 @@
 trap 'fatal_signal INT' INT
 trap 'fatal_signal TERM' TERM
 
+# Number of processors on this machine. Used as the default setting
+# for parallel make.
+all_sh_nproc ()
+{
+    {
+        nproc || # Linux
+        sysctl -n hw.ncpuonline || # NetBSD, OpenBSD
+        sysctl -n hw.ncpu || # FreeBSD
+        echo 1
+    } 2>/dev/null
+}
+
 msg()
 {
     if [ -n "${current_component:-}" ]; then
@@ -357,17 +393,11 @@
     done
 }
 
-check_headers_in_cpp () {
-    ls include/mbedtls | grep "\.h$" >headers.txt
-    <programs/test/cpp_dummy_build.cpp sed -n 's/"$//; s!^#include "mbedtls/!!p' |
-    sort |
-    diff headers.txt -
-    rm headers.txt
-}
-
 pre_parse_command_line () {
     COMMAND_LINE_COMPONENTS=
     all_except=0
+    error_test=0
+    restore_first=0
     no_armcc=
 
     # Note that legacy options are ignored instead of being omitted from this
@@ -377,9 +407,11 @@
         case "$1" in
             --append-outcome) append_outcome=1;;
             --arm-none-eabi-gcc-prefix) shift; ARM_NONE_EABI_GCC_PREFIX="$1";;
+            --arm-linux-gnueabi-gcc-prefix) shift; ARM_LINUX_GNUEABI_GCC_PREFIX="$1";;
             --armcc) no_armcc=;;
             --armc5-bin-dir) shift; ARMC5_BIN_DIR="$1";;
             --armc6-bin-dir) shift; ARMC6_BIN_DIR="$1";;
+            --error-test) error_test=$((error_test + 1));;
             --except) all_except=1;;
             --force|-f) FORCE=1;;
             --gnutls-cli) shift; GNUTLS_CLI="$1";;
@@ -405,6 +437,7 @@
             --quiet|-q) QUIET=1;;
             --random-seed) unset SEED;;
             --release-test|-r) SEED=$RELEASE_SEED;;
+            --restore) restore_first=1;;
             --seed|-s) shift; SEED="$1";;
             -*)
                 echo >&2 "Unknown option: $1"
@@ -417,7 +450,7 @@
     done
 
     # With no list of components, run everything.
-    if [ -z "$COMMAND_LINE_COMPONENTS" ]; then
+    if [ -z "$COMMAND_LINE_COMPONENTS" ] && [ $restore_first -eq 0 ]; then
         all_except=1
     fi
 
@@ -427,6 +460,32 @@
         COMMAND_LINE_COMPONENTS="$COMMAND_LINE_COMPONENTS *_armcc*"
     fi
 
+    # Error out if an explicitly requested component doesn't exist.
+    if [ $all_except -eq 0 ]; then
+        unsupported=0
+        # Temporarily disable wildcard expansion so that $COMMAND_LINE_COMPONENTS
+        # only does word splitting.
+        set -f
+        for component in $COMMAND_LINE_COMPONENTS; do
+            set +f
+            # If the requested name includes a wildcard character, don't
+            # check it. Accept wildcard patterns that don't match anything.
+            case $component in
+                *[*?\[]*) continue;;
+            esac
+            case " $SUPPORTED_COMPONENTS " in
+                *" $component "*) :;;
+                *)
+                    echo >&2 "Component $component was explicitly requested, but is not known or not supported."
+                    unsupported=$((unsupported + 1));;
+            esac
+        done
+        set +f
+        if [ $unsupported -ne 0 ]; then
+            exit 2
+        fi
+    fi
+
     # Build the list of components to run.
     RUN_COMPONENTS=
     for component in $SUPPORTED_COMPONENTS; do
@@ -462,9 +521,36 @@
     fi
 }
 
+pre_restore_files () {
+    # If the makefiles have been generated by a framework such as cmake,
+    # restore them from git. If the makefiles look like modifications from
+    # the ones checked into git, take care not to modify them. Whatever
+    # this function leaves behind is what the script will restore before
+    # each component.
+    case "$(head -n1 Makefile)" in
+        *[Gg]enerated*)
+            git update-index --no-skip-worktree Makefile library/Makefile programs/Makefile tests/Makefile programs/fuzz/Makefile
+            git checkout -- Makefile library/Makefile programs/Makefile tests/Makefile programs/fuzz/Makefile
+            ;;
+    esac
+}
+
+pre_back_up () {
+    for x in $files_to_back_up; do
+        cp -p "$x" "$x$backup_suffix"
+    done
+}
+
 pre_setup_keep_going () {
-    failure_summary=
-    failure_count=0
+    failure_count=0 # Number of failed components
+    last_failure_status=0 # Last failure status in this component
+
+    # See err_trap
+    previous_failure_status=0
+    previous_failed_command=
+    previous_failure_funcall_depth=0
+    unset report_failed_command
+
     start_red=
     end_color=
     if [ -t 1 ]; then
@@ -475,76 +561,106 @@
                 ;;
         esac
     fi
-    record_status () {
-        if "$@"; then
-            last_status=0
-        else
-            last_status=$?
-            text="$current_section: $* -> $last_status"
-            failure_summary="$failure_summary
-$text"
-            failure_count=$((failure_count + 1))
-            echo "${start_red}^^^^$text^^^^${end_color}" >&2
-        fi
-    }
-    make () {
-        case "$*" in
-            *test|*check)
-                if [ $build_status -eq 0 ]; then
-                    record_status command make "$@"
-                else
-                    echo "(skipped because the build failed)"
-                fi
-                ;;
-            *)
-                record_status command make "$@"
-                build_status=$last_status
-                ;;
+
+    # Keep a summary of failures in a file. We'll print it out at the end.
+    failure_summary_file=$PWD/all-sh-failures-$$.log
+    : >"$failure_summary_file"
+
+    # Whether it makes sense to keep a component going after the specified
+    # command fails (test command) or not (configure or build).
+    # This function normally receives the failing simple command
+    # ($BASH_COMMAND) as an argument, but if $report_failed_command is set,
+    # this is passed instead.
+    # This doesn't have to be 100% accurate: all failures are recorded anyway.
+    # False positives result in running things that can't be expected to
+    # work. False negatives result in things not running after something else
+    # failed even though they might have given useful feedback.
+    can_keep_going_after_failure () {
+        case "$1" in
+            "msg "*) false;;
+            "cd "*) false;;
+            *make*[\ /]tests*) false;; # make tests, make CFLAGS=-I../tests, ...
+            *test*) true;; # make test, tests/stuff, env V=v tests/stuff, ...
+            *make*check*) true;;
+            "grep "*) true;;
+            "[ "*) true;;
+            "! "*) true;;
+            *) false;;
         esac
     }
+
+    # This function runs if there is any error in a component.
+    # It must either exit with a nonzero status, or set
+    # last_failure_status to a nonzero value.
+    err_trap () {
+        # Save $? (status of the failing command). This must be the very
+        # first thing, before $? is overridden.
+        last_failure_status=$?
+        failed_command=${report_failed_command-$BASH_COMMAND}
+
+        if [[ $last_failure_status -eq $previous_failure_status &&
+              "$failed_command" == "$previous_failed_command" &&
+              ${#FUNCNAME[@]} == $((previous_failure_funcall_depth - 1)) ]]
+        then
+            # The same command failed twice in a row, but this time one level
+            # less deep in the function call stack. This happens when the last
+            # command of a function returns a nonzero status, and the function
+            # returns that same status. Ignore the second failure.
+            previous_failure_funcall_depth=${#FUNCNAME[@]}
+            return
+        fi
+        previous_failure_status=$last_failure_status
+        previous_failed_command=$failed_command
+        previous_failure_funcall_depth=${#FUNCNAME[@]}
+
+        text="$current_section: $failed_command -> $last_failure_status"
+        echo "${start_red}^^^^$text^^^^${end_color}" >&2
+        echo "$text" >>"$failure_summary_file"
+
+        # If the command is fatal (configure or build command), stop this
+        # component. Otherwise (test command) keep the component running
+        # (run more tests from the same build).
+        if ! can_keep_going_after_failure "$failed_command"; then
+            exit $last_failure_status
+        fi
+    }
+
     final_report () {
         if [ $failure_count -gt 0 ]; then
             echo
             echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
-            echo "${start_red}FAILED: $failure_count${end_color}$failure_summary"
+            echo "${start_red}FAILED: $failure_count components${end_color}"
+            cat "$failure_summary_file"
             echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
-            exit 1
         elif [ -z "${1-}" ]; then
             echo "SUCCESS :)"
         fi
         if [ -n "${1-}" ]; then
             echo "Killed by SIG$1."
         fi
+        rm -f "$failure_summary_file"
+        if [ $failure_count -gt 0 ]; then
+            exit 1
+        fi
     }
 }
 
+# record_status() and if_build_succeeded() are kept temporarily for backward
+# compatibility. Don't use them in new components.
+record_status () {
+    "$@"
+}
 if_build_succeeded () {
-    if [ $build_status -eq 0 ]; then
-        record_status "$@"
-    fi
+    "$@"
 }
 
-# to be used instead of ! for commands run with
-# record_status or if_build_succeeded
-not() {
-    ! "$@"
-}
-
-pre_setup_quiet_redirect () {
-    if [ $QUIET -ne 1 ]; then
-        redirect_out () {
-            "$@"
-        }
-        redirect_err () {
-            "$@"
-        }
-    else
-        redirect_out () {
-            "$@" >/dev/null
-        }
-        redirect_err () {
-            "$@" 2>/dev/null
-        }
+# '! true' does not trigger the ERR trap. Arrange to trigger it, with
+# a reasonably informative error message (not just "$@").
+not () {
+    if "$@"; then
+        report_failed_command="! $*"
+        false
+        unset report_failed_command
     fi
 }
 
@@ -669,28 +785,28 @@
 
 component_check_recursion () {
     msg "Check: recursion.pl" # < 1s
-    record_status tests/scripts/recursion.pl library/*.c
+    tests/scripts/recursion.pl library/*.c
 }
 
 component_check_generated_files () {
     msg "Check: freshness of generated source files" # < 1s
-    record_status tests/scripts/check-generated-files.sh
+    tests/scripts/check-generated-files.sh
 }
 
 component_check_doxy_blocks () {
     msg "Check: doxygen markup outside doxygen blocks" # < 1s
-    record_status tests/scripts/check-doxy-blocks.pl
+    tests/scripts/check-doxy-blocks.pl
 }
 
 component_check_files () {
     msg "Check: file sanity checks (permissions, encodings)" # < 1s
-    record_status tests/scripts/check_files.py
+    tests/scripts/check_files.py
 }
 
 component_check_changelog () {
     msg "Check: changelog entries" # < 1s
     rm -f ChangeLog.new
-    record_status scripts/assemble_changelog.py -o ChangeLog.new
+    scripts/assemble_changelog.py -o ChangeLog.new
     if [ -e ChangeLog.new ]; then
         # Show the diff for information. It isn't an error if the diff is
         # non-empty.
@@ -701,7 +817,7 @@
 
 component_check_names () {
     msg "Check: declared and exported names (builds the library)" # < 3s
-    record_status tests/scripts/check-names.sh -v
+    tests/scripts/check_names.py -v
 }
 
 component_check_test_cases () {
@@ -711,13 +827,13 @@
     else
         opt=''
     fi
-    record_status tests/scripts/check_test_cases.py $opt
+    tests/scripts/check_test_cases.py $opt
     unset opt
 }
 
 component_check_doxygen_warnings () {
     msg "Check: doxygen warnings (builds the documentation)" # ~ 3s
-    record_status tests/scripts/doxygen.sh
+    tests/scripts/doxygen.sh
 }
 
 
@@ -737,7 +853,7 @@
     make test
 
     msg "selftest: make, default config (out-of-box)" # ~10s
-    if_build_succeeded programs/test/selftest
+    programs/test/selftest
 
     export MBEDTLS_TEST_OUTCOME_FILE="$SAVE_MBEDTLS_TEST_OUTCOME_FILE"
     unset SAVE_MBEDTLS_TEST_OUTCOME_FILE
@@ -752,16 +868,16 @@
     make test
 
     msg "test: selftest (ASan build)" # ~ 10s
-    if_build_succeeded programs/test/selftest
+    programs/test/selftest
 
     msg "test: ssl-opt.sh (ASan build)" # ~ 1 min
-    if_build_succeeded tests/ssl-opt.sh
+    tests/ssl-opt.sh
 
     msg "test: compat.sh (ASan build)" # ~ 6 min
-    if_build_succeeded tests/compat.sh
+    tests/compat.sh
 
     msg "test: context-info.sh (ASan build)" # ~ 15 sec
-    if_build_succeeded tests/context-info.sh
+    tests/context-info.sh
 }
 
 component_test_full_cmake_gcc_asan () {
@@ -774,16 +890,16 @@
     make test
 
     msg "test: selftest (ASan build)" # ~ 10s
-    if_build_succeeded programs/test/selftest
+    programs/test/selftest
 
     msg "test: ssl-opt.sh (full config, ASan build)"
-    if_build_succeeded tests/ssl-opt.sh
+    tests/ssl-opt.sh
 
     msg "test: compat.sh (full config, ASan build)"
-    if_build_succeeded tests/compat.sh
+    tests/compat.sh
 
     msg "test: context-info.sh (full config, ASan build)" # ~ 15 sec
-    if_build_succeeded tests/context-info.sh
+    tests/context-info.sh
 }
 
 component_test_psa_crypto_key_id_encodes_owner () {
@@ -798,16 +914,53 @@
     make test
 }
 
+# check_renamed_symbols HEADER LIB
+# Check that if HEADER contains '#define MACRO ...' then MACRO is not a symbol
+# name is LIB.
+check_renamed_symbols () {
+    ! nm "$2" | sed 's/.* //' |
+      grep -x -F "$(sed -n 's/^ *# *define  *\([A-Z_a-z][0-9A-Z_a-z]*\)..*/\1/p' "$1")"
+}
+
+component_build_psa_crypto_spm () {
+    msg "build: full config - USE_PSA_CRYPTO + PSA_CRYPTO_KEY_ID_ENCODES_OWNER + PSA_CRYPTO_SPM, make, gcc"
+    scripts/config.py full
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py unset MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_SPM
+    # We can only compile, not link, since our test and sample programs
+    # aren't equipped for the modified names used when MBEDTLS_PSA_CRYPTO_SPM
+    # is active.
+    make CC=gcc CFLAGS='-Werror -Wall -Wextra -I../tests/include/spe' lib
+
+    # Check that if a symbol is renamed by crypto_spe.h, the non-renamed
+    # version is not present.
+    echo "Checking for renamed symbols in the library"
+    check_renamed_symbols tests/include/spe/crypto_spe.h library/libmbedcrypto.a
+}
+
+component_test_psa_crypto_client () {
+    msg "build: default config - PSA_CRYPTO_C + PSA_CRYPTO_CLIENT, make"
+    scripts/config.py unset MBEDTLS_PSA_CRYPTO_C
+    scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CLIENT
+    make
+
+    msg "test: default config - PSA_CRYPTO_C + PSA_CRYPTO_CLIENT, make"
+    make test
+}
+
 component_test_zlib_make() {
     msg "build: zlib enabled, make"
     scripts/config.py set MBEDTLS_ZLIB_SUPPORT
-    make ZLIB=1 CFLAGS='-Werror -O1'
+    make ZLIB=1 CFLAGS='-Werror -O2'
 
     msg "test: main suites (zlib, make)"
     make test
 
     msg "test: ssl-opt.sh (zlib, make)"
-    if_build_succeeded tests/ssl-opt.sh
+    tests/ssl-opt.sh
 }
 support_test_zlib_make () {
     base=support_test_zlib_$$
@@ -824,23 +977,32 @@
 component_test_zlib_cmake() {
     msg "build: zlib enabled, cmake"
     scripts/config.py set MBEDTLS_ZLIB_SUPPORT
-    cmake -D ENABLE_ZLIB_SUPPORT=On -D CMAKE_BUILD_TYPE:String=Check .
+    cmake -D ENABLE_ZLIB_SUPPORT=On -D CMAKE_BUILD_TYPE:String=Release .
     make
 
     msg "test: main suites (zlib, cmake)"
     make test
 
     msg "test: ssl-opt.sh (zlib, cmake)"
-    if_build_succeeded tests/ssl-opt.sh
+    tests/ssl-opt.sh
 }
 support_test_zlib_cmake () {
     support_test_zlib_make "$@"
 }
 
+component_test_psa_crypto_rsa_no_genprime() {
+    msg "build: default config minus MBEDTLS_GENPRIME"
+    scripts/config.py unset MBEDTLS_GENPRIME
+    make
+
+    msg "test: default config minus MBEDTLS_GENPRIME"
+    make test
+}
+
 component_test_ref_configs () {
     msg "test/build: ref-configs (ASan build)" # ~ 6 min 20s
     CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
-    record_status tests/scripts/test-ref-configs.pl
+    tests/scripts/test-ref-configs.pl
 }
 
 component_test_sslv3 () {
@@ -853,14 +1015,14 @@
     make test
 
     msg "build: SSLv3 - compat.sh (ASan build)" # ~ 6 min
-    if_build_succeeded tests/compat.sh -m 'tls1 tls1_1 tls1_2 dtls1 dtls1_2'
-    if_build_succeeded env OPENSSL_CMD="$OPENSSL_LEGACY" tests/compat.sh -m 'ssl3'
+    tests/compat.sh -m 'tls1 tls1_1 tls12 dtls1 dtls12'
+    env OPENSSL_CMD="$OPENSSL_LEGACY" tests/compat.sh -m 'ssl3'
 
     msg "build: SSLv3 - ssl-opt.sh (ASan build)" # ~ 6 min
-    if_build_succeeded tests/ssl-opt.sh
+    tests/ssl-opt.sh
 
     msg "build: SSLv3 - context-info.sh (ASan build)" # ~ 15 sec
-    if_build_succeeded tests/context-info.sh
+    tests/context-info.sh
 }
 
 component_test_no_renegotiation () {
@@ -873,7 +1035,7 @@
     make test
 
     msg "test: !MBEDTLS_SSL_RENEGOTIATION - ssl-opt.sh (ASan build)" # ~ 6 min
-    if_build_succeeded tests/ssl-opt.sh
+    tests/ssl-opt.sh
 }
 
 component_test_no_pem_no_fs () {
@@ -889,7 +1051,7 @@
     make test
 
     msg "test: !MBEDTLS_PEM_PARSE_C !MBEDTLS_FS_IO - ssl-opt.sh (ASan build)" # ~ 6 min
-    if_build_succeeded tests/ssl-opt.sh
+    tests/ssl-opt.sh
 }
 
 component_test_rsa_no_crt () {
@@ -902,47 +1064,170 @@
     make test
 
     msg "test: RSA_NO_CRT - RSA-related part of ssl-opt.sh (ASan build)" # ~ 5s
-    if_build_succeeded tests/ssl-opt.sh -f RSA
+    tests/ssl-opt.sh -f RSA
 
     msg "test: RSA_NO_CRT - RSA-related part of compat.sh (ASan build)" # ~ 3 min
-    if_build_succeeded tests/compat.sh -t RSA
+    tests/compat.sh -t RSA
 
     msg "test: RSA_NO_CRT - RSA-related part of context-info.sh (ASan build)" # ~ 15 sec
-    if_build_succeeded tests/context-info.sh
+    tests/context-info.sh
 }
 
-component_test_no_ctr_drbg () {
-    msg "build: Full minus CTR_DRBG"
+component_test_no_ctr_drbg_classic () {
+    msg "build: Full minus CTR_DRBG, classic crypto in TLS"
     scripts/config.py full
     scripts/config.py unset MBEDTLS_CTR_DRBG_C
-    scripts/config.py unset MBEDTLS_PSA_CRYPTO_C # requires CTR_DRBG
-    scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C # requires PSA Crypto
-    scripts/config.py unset MBEDTLS_PSA_CRYPTO_SE_C # requires PSA Crypto
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO # requires PSA Crypto
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
 
     CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
     make
 
-    msg "test: no CTR_DRBG"
+    msg "test: Full minus CTR_DRBG, classic crypto - main suites"
     make test
 
-    # no ssl-opt.sh/compat.sh as they all depend on CTR_DRBG so far
+    # In this configuration, the TLS test programs use HMAC_DRBG.
+    # The SSL tests are slow, so run a small subset, just enough to get
+    # confidence that the SSL code copes with HMAC_DRBG.
+    msg "test: Full minus CTR_DRBG, classic crypto - ssl-opt.sh (subset)"
+    tests/ssl-opt.sh -f 'Default\|SSL async private.*delay=\|tickets enabled on server'
+
+    msg "test: Full minus CTR_DRBG, classic crypto - compat.sh (subset)"
+    tests/compat.sh -m tls12 -t 'ECDSA PSK' -V NO -p OpenSSL
 }
 
-component_test_no_hmac_drbg () {
-    msg "build: Full minus HMAC_DRBG"
+component_test_no_ctr_drbg_use_psa () {
+    msg "build: Full minus CTR_DRBG, PSA crypto in TLS"
+    scripts/config.py full
+    scripts/config.py unset MBEDTLS_CTR_DRBG_C
+    scripts/config.py set MBEDTLS_USE_PSA_CRYPTO
+
+    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+    make
+
+    msg "test: Full minus CTR_DRBG, USE_PSA_CRYPTO - main suites"
+    make test
+
+    # In this configuration, the TLS test programs use HMAC_DRBG.
+    # The SSL tests are slow, so run a small subset, just enough to get
+    # confidence that the SSL code copes with HMAC_DRBG.
+    msg "test: Full minus CTR_DRBG, USE_PSA_CRYPTO - ssl-opt.sh (subset)"
+    tests/ssl-opt.sh -f 'Default\|SSL async private.*delay=\|tickets enabled on server'
+
+    msg "test: Full minus CTR_DRBG, USE_PSA_CRYPTO - compat.sh (subset)"
+    tests/compat.sh -m tls12 -t 'ECDSA PSK' -V NO -p OpenSSL
+}
+
+component_test_no_hmac_drbg_classic () {
+    msg "build: Full minus HMAC_DRBG, classic crypto in TLS"
     scripts/config.py full
     scripts/config.py unset MBEDTLS_HMAC_DRBG_C
     scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
 
     CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
     make
 
-    msg "test: no HMAC_DRBG"
+    msg "test: Full minus HMAC_DRBG, classic crypto - main suites"
     make test
 
-    # No ssl-opt.sh/compat.sh as they never use HMAC_DRBG so far,
-    # so there's little value in running those lengthy tests here.
+    # Normally our ECDSA implementation uses deterministic ECDSA. But since
+    # HMAC_DRBG is disabled in this configuration, randomized ECDSA is used
+    # instead.
+    # Test SSL with non-deterministic ECDSA. Only test features that
+    # might be affected by how ECDSA signature is performed.
+    msg "test: Full minus HMAC_DRBG, classic crypto - ssl-opt.sh (subset)"
+    tests/ssl-opt.sh -f 'Default\|SSL async private: sign'
+
+    # To save time, only test one protocol version, since this part of
+    # the protocol is identical in (D)TLS up to 1.2.
+    msg "test: Full minus HMAC_DRBG, classic crypto - compat.sh (ECDSA)"
+    tests/compat.sh -m tls12 -t 'ECDSA'
+}
+
+component_test_no_hmac_drbg_use_psa () {
+    msg "build: Full minus HMAC_DRBG, PSA crypto in TLS"
+    scripts/config.py full
+    scripts/config.py unset MBEDTLS_HMAC_DRBG_C
+    scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG
+    scripts/config.py set MBEDTLS_USE_PSA_CRYPTO
+
+    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+    make
+
+    msg "test: Full minus HMAC_DRBG, USE_PSA_CRYPTO - main suites"
+    make test
+
+    # Normally our ECDSA implementation uses deterministic ECDSA. But since
+    # HMAC_DRBG is disabled in this configuration, randomized ECDSA is used
+    # instead.
+    # Test SSL with non-deterministic ECDSA. Only test features that
+    # might be affected by how ECDSA signature is performed.
+    msg "test: Full minus HMAC_DRBG, USE_PSA_CRYPTO - ssl-opt.sh (subset)"
+    tests/ssl-opt.sh -f 'Default\|SSL async private: sign'
+
+    # To save time, only test one protocol version, since this part of
+    # the protocol is identical in (D)TLS up to 1.2.
+    msg "test: Full minus HMAC_DRBG, USE_PSA_CRYPTO - compat.sh (ECDSA)"
+    tests/compat.sh -m tls12 -t 'ECDSA'
+}
+
+component_test_psa_external_rng_no_drbg_classic () {
+    msg "build: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, classic crypto in TLS"
+    scripts/config.py full
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+    scripts/config.py unset MBEDTLS_ENTROPY_C
+    scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
+    scripts/config.py unset MBEDTLS_PLATFORM_NV_SEED_ALT
+    scripts/config.py unset MBEDTLS_CTR_DRBG_C
+    scripts/config.py unset MBEDTLS_HMAC_DRBG_C
+    scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG
+    scripts/config.py set MBEDTLS_ECP_NO_INTERNAL_RNG
+    # When MBEDTLS_USE_PSA_CRYPTO is disabled and there is no DRBG,
+    # the SSL test programs don't have an RNG and can't work. Explicitly
+    # make them use the PSA RNG with -DMBEDTLS_TEST_USE_PSA_CRYPTO_RNG.
+    make CFLAGS="$ASAN_CFLAGS -O2 -DMBEDTLS_TEST_USE_PSA_CRYPTO_RNG" LDFLAGS="$ASAN_CFLAGS"
+
+    msg "test: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, classic crypto - main suites"
+    make test
+
+    msg "test: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, classic crypto - ssl-opt.sh (subset)"
+    tests/ssl-opt.sh -f 'Default'
+}
+
+component_test_psa_external_rng_no_drbg_use_psa () {
+    msg "build: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, PSA crypto in TLS"
+    scripts/config.py full
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+    scripts/config.py unset MBEDTLS_ENTROPY_C
+    scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
+    scripts/config.py unset MBEDTLS_PLATFORM_NV_SEED_ALT
+    scripts/config.py unset MBEDTLS_CTR_DRBG_C
+    scripts/config.py unset MBEDTLS_HMAC_DRBG_C
+    scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG
+    scripts/config.py set MBEDTLS_ECP_NO_INTERNAL_RNG
+    make CFLAGS="$ASAN_CFLAGS -O2" LDFLAGS="$ASAN_CFLAGS"
+
+    msg "test: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, PSA crypto - main suites"
+    make test
+
+    msg "test: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, PSA crypto - ssl-opt.sh (subset)"
+    tests/ssl-opt.sh -f 'Default\|opaque'
+}
+
+component_test_psa_external_rng_use_psa_crypto () {
+    msg "build: full + PSA_CRYPTO_EXTERNAL_RNG + USE_PSA_CRYPTO minus CTR_DRBG"
+    scripts/config.py full
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+    scripts/config.py set MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py unset MBEDTLS_CTR_DRBG_C
+    make CFLAGS="$ASAN_CFLAGS -O2" LDFLAGS="$ASAN_CFLAGS"
+
+    msg "test: full + PSA_CRYPTO_EXTERNAL_RNG + USE_PSA_CRYPTO minus CTR_DRBG"
+    make test
+
+    msg "test: full + PSA_CRYPTO_EXTERNAL_RNG + USE_PSA_CRYPTO minus CTR_DRBG"
+    tests/ssl-opt.sh -f 'Default\|opaque'
 }
 
 component_test_ecp_no_internal_rng () {
@@ -992,11 +1277,11 @@
     make test
 
     msg "test: new ECDH context - ECDH-related part of ssl-opt.sh (ASan build)" # ~ 5s
-    if_build_succeeded tests/ssl-opt.sh -f ECDH
+    tests/ssl-opt.sh -f ECDH
 
     msg "test: new ECDH context - compat.sh with some ECDH ciphersuites (ASan build)" # ~ 3 min
     # Exclude some symmetric ciphers that are redundant here to gain time.
-    if_build_succeeded tests/compat.sh -f ECDH -V NO -e 'ARCFOUR\|ARIA\|CAMELLIA\|CHACHA\|DES\|RC4'
+    tests/compat.sh -f ECDH -V NO -e 'ARCFOUR\|ARIA\|CAMELLIA\|CHACHA\|DES\|RC4'
 }
 
 component_test_everest () {
@@ -1010,11 +1295,11 @@
     make test
 
     msg "test: Everest ECDH context - ECDH-related part of ssl-opt.sh (ASan build)" # ~ 5s
-    if_build_succeeded tests/ssl-opt.sh -f ECDH
+    tests/ssl-opt.sh -f ECDH
 
     msg "test: Everest ECDH context - compat.sh with some ECDH ciphersuites (ASan build)" # ~ 3 min
     # Exclude some symmetric ciphers that are redundant here to gain time.
-    if_build_succeeded tests/compat.sh -f ECDH -V NO -e 'ARCFOUR\|ARIA\|CAMELLIA\|CHACHA\|DES\|RC4'
+    tests/compat.sh -f ECDH -V NO -e 'ARCFOUR\|ARIA\|CAMELLIA\|CHACHA\|DES\|RC4'
 }
 
 component_test_everest_curve25519_only () {
@@ -1044,7 +1329,7 @@
     make
 
     msg "test: small SSL_OUT_CONTENT_LEN - ssl-opt.sh MFL and large packet tests"
-    if_build_succeeded tests/ssl-opt.sh -f "Max fragment\|Large packet"
+    tests/ssl-opt.sh -f "Max fragment\|Large packet"
 }
 
 component_test_small_ssl_in_content_len () {
@@ -1055,7 +1340,7 @@
     make
 
     msg "test: small SSL_IN_CONTENT_LEN - ssl-opt.sh MFL tests"
-    if_build_succeeded tests/ssl-opt.sh -f "Max fragment"
+    tests/ssl-opt.sh -f "Max fragment"
 }
 
 component_test_small_ssl_dtls_max_buffering () {
@@ -1065,7 +1350,7 @@
     make
 
     msg "test: small MBEDTLS_SSL_DTLS_MAX_BUFFERING #0 - ssl-opt.sh specific reordering test"
-    if_build_succeeded tests/ssl-opt.sh -f "DTLS reordering: Buffer out-of-order hs msg before reassembling next, free buffered msg"
+    tests/ssl-opt.sh -f "DTLS reordering: Buffer out-of-order hs msg before reassembling next, free buffered msg"
 }
 
 component_test_small_mbedtls_ssl_dtls_max_buffering () {
@@ -1075,38 +1360,38 @@
     make
 
     msg "test: small MBEDTLS_SSL_DTLS_MAX_BUFFERING #1 - ssl-opt.sh specific reordering test"
-    if_build_succeeded tests/ssl-opt.sh -f "DTLS reordering: Buffer encrypted Finished message, drop for fragmented NewSessionTicket"
+    tests/ssl-opt.sh -f "DTLS reordering: Buffer encrypted Finished message, drop for fragmented NewSessionTicket"
 }
 
 component_test_psa_collect_statuses () {
   msg "build+test: psa_collect_statuses" # ~30s
   scripts/config.py full
-  record_status tests/scripts/psa_collect_statuses.py
+  tests/scripts/psa_collect_statuses.py
   # Check that psa_crypto_init() succeeded at least once
-  record_status grep -q '^0:psa_crypto_init:' tests/statuses.log
+  grep -q '^0:psa_crypto_init:' tests/statuses.log
   rm -f tests/statuses.log
 }
 
 component_test_full_cmake_clang () {
     msg "build: cmake, full config, clang" # ~ 50s
     scripts/config.py full
-    CC=clang cmake -D CMAKE_BUILD_TYPE:String=Check -D ENABLE_TESTING=On .
+    CC=clang cmake -D CMAKE_BUILD_TYPE:String=Release -D ENABLE_TESTING=On .
     make
 
     msg "test: main suites (full config, clang)" # ~ 5s
     make test
 
     msg "test: psa_constant_names (full config, clang)" # ~ 1s
-    record_status tests/scripts/test_psa_constant_names.py
+    tests/scripts/test_psa_constant_names.py
 
     msg "test: ssl-opt.sh default, ECJPAKE, SSL async (full config)" # ~ 1s
-    if_build_succeeded tests/ssl-opt.sh -f 'Default\|ECJPAKE\|SSL async private'
+    tests/ssl-opt.sh -f 'Default\|ECJPAKE\|SSL async private'
 
     msg "test: compat.sh RC4, DES, 3DES & NULL (full config)" # ~ 2 min
-    if_build_succeeded env OPENSSL_CMD="$OPENSSL_LEGACY" GNUTLS_CLI="$GNUTLS_LEGACY_CLI" GNUTLS_SERV="$GNUTLS_LEGACY_SERV" tests/compat.sh -e '^$' -f 'NULL\|DES\|RC4\|ARCFOUR'
+    env OPENSSL_CMD="$OPENSSL_LEGACY" GNUTLS_CLI="$GNUTLS_LEGACY_CLI" GNUTLS_SERV="$GNUTLS_LEGACY_SERV" tests/compat.sh -e '^$' -f 'NULL\|DES\|RC4\|ARCFOUR'
 
     msg "test: compat.sh ARIA + ChachaPoly"
-    if_build_succeeded env OPENSSL_CMD="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
+    env OPENSSL_CMD="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
 }
 
 component_test_memsan_constant_flow () {
@@ -1213,70 +1498,68 @@
   msg "build: make, crypto only"
   scripts/config.py crypto
   make CFLAGS='-O1 -Werror'
-  if_build_succeeded are_empty_libraries library/libmbedx509.* library/libmbedtls.*
+  are_empty_libraries library/libmbedx509.* library/libmbedtls.*
 }
 
 component_build_crypto_full () {
   msg "build: make, crypto only, full config"
   scripts/config.py crypto_full
   make CFLAGS='-O1 -Werror'
-  if_build_succeeded are_empty_libraries library/libmbedx509.* library/libmbedtls.*
+  are_empty_libraries library/libmbedx509.* library/libmbedtls.*
 }
 
 component_build_crypto_baremetal () {
   msg "build: make, crypto only, baremetal config"
   scripts/config.py crypto_baremetal
   make CFLAGS='-O1 -Werror'
-  if_build_succeeded are_empty_libraries library/libmbedx509.* library/libmbedtls.*
+  are_empty_libraries library/libmbedx509.* library/libmbedtls.*
 }
 
 component_test_depends_curves () {
     msg "test/build: curves.pl (gcc)" # ~ 4 min
-    record_status tests/scripts/curves.pl
+    tests/scripts/curves.pl
 }
 
 component_test_depends_curves_psa () {
     msg "test/build: curves.pl with MBEDTLS_USE_PSA_CRYPTO defined (gcc)"
     scripts/config.py set MBEDTLS_USE_PSA_CRYPTO
-    record_status tests/scripts/curves.pl
+    tests/scripts/curves.pl
 }
 
 component_test_depends_hashes () {
     msg "test/build: depends-hashes.pl (gcc)" # ~ 2 min
-    record_status tests/scripts/depends-hashes.pl
+    tests/scripts/depends-hashes.pl
 }
 
 component_test_depends_hashes_psa () {
     msg "test/build: depends-hashes.pl with MBEDTLS_USE_PSA_CRYPTO defined (gcc)"
     scripts/config.py set MBEDTLS_USE_PSA_CRYPTO
-    record_status tests/scripts/depends-hashes.pl
+    tests/scripts/depends-hashes.pl
 }
 
 component_test_depends_pkalgs () {
     msg "test/build: depends-pkalgs.pl (gcc)" # ~ 2 min
-    record_status tests/scripts/depends-pkalgs.pl
+    tests/scripts/depends-pkalgs.pl
 }
 
 component_test_depends_pkalgs_psa () {
     msg "test/build: depends-pkalgs.pl with MBEDTLS_USE_PSA_CRYPTO defined (gcc)"
     scripts/config.py set MBEDTLS_USE_PSA_CRYPTO
-    record_status tests/scripts/depends-pkalgs.pl
+    tests/scripts/depends-pkalgs.pl
 }
 
 component_build_key_exchanges () {
     msg "test/build: key-exchanges (gcc)" # ~ 1 min
-    record_status tests/scripts/key-exchanges.pl
+    tests/scripts/key-exchanges.pl
 }
 
-component_build_default_make_gcc_and_cxx () {
-    msg "build: Unix make, -Os (gcc)" # ~ 30s
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra -Os'
+component_test_make_cxx () {
+    msg "build: Unix make, full, gcc + g++"
+    scripts/config.py full
+    make TEST_CPP=1 lib programs
 
-    msg "test: verify header list in cpp_dummy_build.cpp"
-    record_status check_headers_in_cpp
-
-    msg "build: Unix make, incremental g++"
-    make TEST_CPP=1
+    msg "test: cpp_dummy_build"
+    programs/test/cpp_dummy_build
 }
 
 component_test_no_use_psa_crypto_full_cmake_asan() {
@@ -1296,29 +1579,218 @@
     make test
 
     msg "test: ssl-opt.sh (full minus MBEDTLS_USE_PSA_CRYPTO)"
-    if_build_succeeded tests/ssl-opt.sh
+    tests/ssl-opt.sh
 
     msg "test: compat.sh default (full minus MBEDTLS_USE_PSA_CRYPTO)"
-    if_build_succeeded tests/compat.sh
+    tests/compat.sh
 
     msg "test: compat.sh RC4, DES & NULL (full minus MBEDTLS_USE_PSA_CRYPTO)"
-    if_build_succeeded env OPENSSL_CMD="$OPENSSL_LEGACY" GNUTLS_CLI="$GNUTLS_LEGACY_CLI" GNUTLS_SERV="$GNUTLS_LEGACY_SERV" tests/compat.sh -e '3DES\|DES-CBC3' -f 'NULL\|DES\|RC4\|ARCFOUR'
+    env OPENSSL_CMD="$OPENSSL_LEGACY" GNUTLS_CLI="$GNUTLS_LEGACY_CLI" GNUTLS_SERV="$GNUTLS_LEGACY_SERV" tests/compat.sh -e '3DES\|DES-CBC3' -f 'NULL\|DES\|RC4\|ARCFOUR'
 
     msg "test: compat.sh ARIA + ChachaPoly (full minus MBEDTLS_USE_PSA_CRYPTO)"
-    if_build_succeeded env OPENSSL_CMD="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
+    env OPENSSL_CMD="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
 }
 
-component_test_psa_crypto_config_basic() {
-    # full plus MBEDTLS_PSA_CRYPTO_CONFIG
-    msg "build: full + MBEDTLS_PSA_CRYPTO_CONFIG"
-    scripts/config.py full
-    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
-    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
+component_test_psa_crypto_config_accel_ecdsa () {
+    msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated ECDSA"
 
-    msg "test: full + MBEDTLS_PSA_CRYPTO_CONFIG"
+    # Disable ALG_STREAM_CIPHER and ALG_ECB_NO_PADDING to avoid having
+    # partial support for cipher operations in the driver test library.
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_STREAM_CIPHER
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_ECB_NO_PADDING
+
+    # SHA384 needed for some ECDSA signature tests.
+    scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_SHA512_C
+
+    loc_accel_list="ALG_ECDSA ALG_DETERMINISTIC_ECDSA KEY_TYPE_ECC_KEY_PAIR KEY_TYPE_ECC_PUBLIC_KEY"
+    loc_accel_flags=$( echo "$loc_accel_list" | sed 's/[^ ]* */-DLIBTESTDRIVER1_MBEDTLS_PSA_ACCEL_&/g' )
+    make -C tests libtestdriver1.a CFLAGS="$ASAN_CFLAGS $loc_accel_flags" LDFLAGS="$ASAN_CFLAGS"
+
+    # Restore test driver base configuration
+    scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_SHA512_C
+
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py unset MBEDTLS_ECDSA_C
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+
+    loc_accel_flags="$loc_accel_flags $( echo "$loc_accel_list" | sed 's/[^ ]* */-DMBEDTLS_PSA_ACCEL_&/g' )"
+    make CFLAGS="$ASAN_CFLAGS -O -Werror -I../tests/include -I../tests -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_TEST_LIBTESTDRIVER1 $loc_accel_flags" LDFLAGS="-ltestdriver1 $ASAN_CFLAGS"
+
+    unset loc_accel_flags
+    unset loc_accel_list
+
+    if_build_succeeded not grep mbedtls_ecdsa_ library/ecdsa.o
+
+    msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated ECDSA"
+    make test
+}
+
+component_test_psa_crypto_config_accel_rsa_signature () {
+    msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated RSA signature"
+
+    # Disable ALG_STREAM_CIPHER and ALG_ECB_NO_PADDING to avoid having
+    # partial support for cipher operations in the driver test library.
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_STREAM_CIPHER
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_ECB_NO_PADDING
+
+    # It seems it is not possible to remove only the support for RSA signature
+    # in the library. Thus we have to remove all RSA support (signature and
+    # encryption/decryption). AS there is no driver support for asymmetric
+    # encryption/decryption so far remove RSA encryption/decryption from the
+    # application algorithm list.
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_OAEP
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
+
+    # Make sure both the library and the test library support the SHA hash
+    # algorithms and only those ones (SHA256 is included by default). That way:
+    # - the test library can compute the RSA signatures even in the case of a
+    #   composite RSA signature algorithm based on a SHA hash (no other hash
+    #   used in the unit tests).
+    # - the dependency of RSA signature tests on PSA_WANT_ALG_SHA_xyz is
+    #   fulfilled as the hash SHA algorithm is supported by the library, and
+    #   thus the tests are run, not skipped.
+    # - when testing a signature key with an algorithm wildcard built from
+    #   PSA_ALG_ANY_HASH as algorithm to test with the key, the chosen hash
+    #   algorithm based on the hashes supported by the library is also
+    #   supported by the test library.
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_MD2
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_MD4
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_MD5
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RIPEMD160_C
+
+    scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_SHA1_C
+    scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_SHA512_C
+    # We need PEM parsing in the test library as well to support the import
+    # of PEM encoded RSA keys.
+    scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_PEM_PARSE_C
+    scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_BASE64_C
+
+    loc_accel_list="ALG_RSA_PKCS1V15_SIGN ALG_RSA_PSS KEY_TYPE_RSA_KEY_PAIR KEY_TYPE_RSA_PUBLIC_KEY"
+    loc_accel_flags=$( echo "$loc_accel_list" | sed 's/[^ ]* */-DLIBTESTDRIVER1_MBEDTLS_PSA_ACCEL_&/g' )
+    make -C tests libtestdriver1.a CFLAGS="$ASAN_CFLAGS $loc_accel_flags" LDFLAGS="$ASAN_CFLAGS"
+
+    # Restore test driver base configuration
+    scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_SHA1_C
+    scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_SHA512_C
+    scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_PEM_PARSE_C
+    scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_BASE64_C
+
+
+    # Mbed TLS library build
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+
+    # Remove RSA support and its dependencies
+    scripts/config.py unset MBEDTLS_PKCS1_V15
+    scripts/config.py unset MBEDTLS_PKCS1_V21
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+    scripts/config.py unset MBEDTLS_RSA_C
+    scripts/config.py unset MBEDTLS_X509_RSASSA_PSS_SUPPORT
+
+    scripts/config.py unset MBEDTLS_MD2_C
+    scripts/config.py unset MBEDTLS_MD4_C
+    scripts/config.py unset MBEDTLS_MD5_C
+    scripts/config.py unset MBEDTLS_RIPEMD160_C
+    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1
+    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_1
+    scripts/config.py unset MBEDTLS_SSL_CBC_RECORD_SPLITTING
+
+    loc_accel_flags="$loc_accel_flags $( echo "$loc_accel_list" | sed 's/[^ ]* */-DMBEDTLS_PSA_ACCEL_&/g' )"
+    make CFLAGS="$ASAN_CFLAGS -Werror -I../tests/include -I../tests -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_TEST_LIBTESTDRIVER1 $loc_accel_flags" LDFLAGS="-ltestdriver1 $ASAN_CFLAGS"
+
+    unset loc_accel_flags
+    unset loc_accel_list
+
+    if_build_succeeded not grep mbedtls_rsa_rsassa_pkcs1_v15_sign library/rsa.o
+    if_build_succeeded not grep mbedtls_rsa_rsassa_pss_sign_ext library/rsa.o
+
+    msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated RSA signature"
+    make test
+}
+
+component_test_psa_crypto_config_accel_hash () {
+    msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated hash"
+
+    # Disable ALG_STREAM_CIPHER and ALG_ECB_NO_PADDING to avoid having
+    # partial support for cipher operations in the driver test library.
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_STREAM_CIPHER
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_ECB_NO_PADDING
+
+    loc_accel_list="ALG_MD4 ALG_MD5 ALG_RIPEMD160 ALG_SHA_1 ALG_SHA_224 ALG_SHA_256 ALG_SHA_384 ALG_SHA_512"
+    loc_accel_flags=$( echo "$loc_accel_list" | sed 's/[^ ]* */-DLIBTESTDRIVER1_MBEDTLS_PSA_ACCEL_&/g' )
+    make -C tests libtestdriver1.a CFLAGS="$ASAN_CFLAGS $loc_accel_flags" LDFLAGS="$ASAN_CFLAGS"
+
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py unset MBEDTLS_MD2_C
+    scripts/config.py unset MBEDTLS_MD4_C
+    scripts/config.py unset MBEDTLS_MD5_C
+    scripts/config.py unset MBEDTLS_RIPEMD160_C
+    scripts/config.py unset MBEDTLS_SHA1_C
+    # Don't unset MBEDTLS_SHA256_C as it is needed by PSA crypto core.
+    scripts/config.py unset MBEDTLS_SHA512_C
+    # Unset MBEDTLS_SSL_PROTO_SSL3, MBEDTLS_SSL_PROTO_TLS1 and MBEDTLS_SSL_PROTO_TLS1_1 as they depend on MBEDTLS_SHA1_C
+    scripts/config.py unset MBEDTLS_SSL_PROTO_SSL3
+    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1
+    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_1
+    # Unset MBEDTLS_SSL_CBC_RECORD_SPLITTING as it depends on MBEDTLS_SSL_PROTO_TLS1 in the default configuration.
+    scripts/config.py unset MBEDTLS_SSL_CBC_RECORD_SPLITTING
+    loc_accel_flags="$loc_accel_flags $( echo "$loc_accel_list" | sed 's/[^ ]* */-DMBEDTLS_PSA_ACCEL_&/g' )"
+    make CFLAGS="$ASAN_CFLAGS -Werror -I../tests/include -I../tests -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_TEST_LIBTESTDRIVER1 $loc_accel_flags" LDFLAGS="-ltestdriver1 $ASAN_CFLAGS"
+
+    unset loc_accel_flags
+    unset loc_accel_list
+
+    if_build_succeeded not grep mbedtls_sha512_init library/sha512.o
+    if_build_succeeded not grep mbedtls_sha1_init library/sha1.o
+
+    msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated hash"
+    make test
+}
+
+component_test_psa_crypto_config_accel_cipher () {
+    msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated cipher"
+
+    loc_accel_list="ALG_CBC_NO_PADDING ALG_CBC_PKCS7 ALG_CTR ALG_CFB ALG_OFB ALG_XTS KEY_TYPE_DES"
+    loc_accel_flags=$( echo "$loc_accel_list" | sed 's/[^ ]* */-DLIBTESTDRIVER1_MBEDTLS_PSA_ACCEL_&/g' )
+    make -C tests libtestdriver1.a CFLAGS="$ASAN_CFLAGS $loc_accel_flags" LDFLAGS="$ASAN_CFLAGS"
+
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+
+    # There is no intended accelerator support for ALG STREAM_CIPHER and
+    # ALG_ECB_NO_PADDING. Therefore, asking for them in the build implies the
+    # inclusion of the Mbed TLS cipher operations. As we want to test here with
+    # cipher operations solely supported by accelerators, disabled those
+    # PSA configuration options.
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_STREAM_CIPHER
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_ECB_NO_PADDING
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_CMAC
+
+    scripts/config.py unset MBEDTLS_CIPHER_MODE_CBC
+    scripts/config.py unset MBEDTLS_CIPHER_PADDING_PKCS7
+    scripts/config.py unset MBEDTLS_CIPHER_MODE_CTR
+    scripts/config.py unset MBEDTLS_CIPHER_MODE_CFB
+    scripts/config.py unset MBEDTLS_CIPHER_MODE_OFB
+    scripts/config.py unset MBEDTLS_CIPHER_MODE_XTS
+    scripts/config.py unset MBEDTLS_DES_C
+
+    loc_accel_flags="$loc_accel_flags $( echo "$loc_accel_list" | sed 's/[^ ]* */-DMBEDTLS_PSA_ACCEL_&/g' )"
+    make CFLAGS="$ASAN_CFLAGS -Werror -I../tests/include -I../tests -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_TEST_LIBTESTDRIVER1 $loc_accel_flags" LDFLAGS="-ltestdriver1 $ASAN_CFLAGS"
+
+    unset loc_accel_flags
+    unset loc_accel_list
+
+    if_build_succeeded not grep mbedtls_des* library/des.o
+
+    msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated hash"
     make test
 }
 
@@ -1335,6 +1807,19 @@
     make test
 }
 
+component_test_psa_crypto_config_chachapoly_disabled() {
+    # full minus MBEDTLS_CHACHAPOLY_C without PSA_WANT_ALG_GCM and PSA_WANT_ALG_CHACHA20_POLY1305
+    msg "build: full minus MBEDTLS_CHACHAPOLY_C without PSA_WANT_ALG_GCM and PSA_WANT_ALG_CHACHA20_POLY1305"
+    scripts/config.py full
+    scripts/config.py unset MBEDTLS_CHACHAPOLY_C
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_GCM
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_CHACHA20_POLY1305
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -O2" LDFLAGS="$ASAN_CFLAGS"
+
+    msg "test: full minus MBEDTLS_CHACHAPOLY_C without PSA_WANT_ALG_GCM and PSA_WANT_ALG_CHACHA20_POLY1305"
+    make test
+}
+
 # This should be renamed to test and updated once the accelerator ECDSA code is in place and ready to test.
 component_build_psa_accel_alg_ecdsa() {
     # full plus MBEDTLS_PSA_CRYPTO_CONFIG with PSA_WANT_ALG_ECDSA
@@ -1763,7 +2248,8 @@
     scripts/config.py set MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
     scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
     scripts/config.py unset MBEDTLS_PLATFORM_NV_SEED_ALT
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra -Os'
+    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Check .
+    make
 }
 
 component_build_no_ssl_srv () {
@@ -1796,7 +2282,7 @@
     scripts/config.py set MBEDTLS_PLATFORM_MEMORY
     scripts/config.py set MBEDTLS_MEMORY_BACKTRACE
     scripts/config.py set MBEDTLS_MEMORY_DEBUG
-    CC=gcc cmake .
+    CC=gcc cmake -DCMAKE_BUILD_TYPE:String=Release .
     make
 
     msg "test: MBEDTLS_MEMORY_BUFFER_ALLOC_C and MBEDTLS_MEMORY_BACKTRACE"
@@ -1807,7 +2293,7 @@
     msg "build: default config with memory buffer allocator"
     scripts/config.py set MBEDTLS_MEMORY_BUFFER_ALLOC_C
     scripts/config.py set MBEDTLS_PLATFORM_MEMORY
-    CC=gcc cmake .
+    CC=gcc cmake -DCMAKE_BUILD_TYPE:String=Release .
     make
 
     msg "test: MBEDTLS_MEMORY_BUFFER_ALLOC_C"
@@ -1815,7 +2301,7 @@
 
     msg "test: ssl-opt.sh, MBEDTLS_MEMORY_BUFFER_ALLOC_C"
     # MBEDTLS_MEMORY_BUFFER_ALLOC is slow. Skip tests that tend to time out.
-    if_build_succeeded tests/ssl-opt.sh -e '^DTLS proxy'
+    tests/ssl-opt.sh -e '^DTLS proxy'
 }
 
 component_test_no_max_fragment_length () {
@@ -1826,7 +2312,7 @@
     make
 
     msg "test: ssl-opt.sh, MFL-related tests"
-    if_build_succeeded tests/ssl-opt.sh -f "Max fragment length"
+    tests/ssl-opt.sh -f "Max fragment length"
 }
 
 component_test_asan_remove_peer_certificate () {
@@ -1839,13 +2325,13 @@
     make test
 
     msg "test: ssl-opt.sh, !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE"
-    if_build_succeeded tests/ssl-opt.sh
+    tests/ssl-opt.sh
 
     msg "test: compat.sh, !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE"
-    if_build_succeeded tests/compat.sh
+    tests/compat.sh
 
     msg "test: context-info.sh, !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE"
-    if_build_succeeded tests/context-info.sh
+    tests/context-info.sh
 }
 
 component_test_no_max_fragment_length_small_ssl_out_content_len () {
@@ -1857,10 +2343,10 @@
     make
 
     msg "test: MFL tests (disabled MFL extension case) & large packet tests"
-    if_build_succeeded tests/ssl-opt.sh -f "Max fragment length\|Large buffer"
+    tests/ssl-opt.sh -f "Max fragment length\|Large buffer"
 
     msg "test: context-info.sh (disabled MFL extension case)"
-    if_build_succeeded tests/context-info.sh
+    tests/context-info.sh
 }
 
 component_test_variable_ssl_in_out_buffer_len () {
@@ -1873,10 +2359,10 @@
     make test
 
     msg "test: ssl-opt.sh, MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH enabled"
-    if_build_succeeded tests/ssl-opt.sh
+    tests/ssl-opt.sh
 
     msg "test: compat.sh, MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH enabled"
-    if_build_succeeded tests/compat.sh
+    tests/compat.sh
 }
 
 component_test_variable_ssl_in_out_buffer_len_CID () {
@@ -1891,10 +2377,10 @@
     make test
 
     msg "test: ssl-opt.sh, MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH and MBEDTLS_SSL_DTLS_CONNECTION_ID enabled"
-    if_build_succeeded tests/ssl-opt.sh
+    tests/ssl-opt.sh
 
     msg "test: compat.sh, MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH and MBEDTLS_SSL_DTLS_CONNECTION_ID enabled"
-    if_build_succeeded tests/compat.sh
+    tests/compat.sh
 }
 
 component_test_variable_ssl_in_out_buffer_len_record_splitting () {
@@ -1909,10 +2395,10 @@
     make test
 
     msg "test: ssl-opt.sh, MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH and MBEDTLS_SSL_CBC_RECORD_SPLITTING enabled"
-    if_build_succeeded tests/ssl-opt.sh
+    tests/ssl-opt.sh
 
     msg "test: compat.sh, MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH and MBEDTLS_SSL_CBC_RECORD_SPLITTING enabled"
-    if_build_succeeded tests/compat.sh
+    tests/compat.sh
 }
 
 component_test_ssl_alloc_buffer_and_mfl () {
@@ -1922,14 +2408,14 @@
     scripts/config.py set MBEDTLS_MEMORY_DEBUG
     scripts/config.py set MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
     scripts/config.py set MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH
-    CC=gcc cmake .
+    CC=gcc cmake -DCMAKE_BUILD_TYPE:String=Release .
     make
 
     msg "test: MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH, MBEDTLS_MEMORY_BUFFER_ALLOC_C, MBEDTLS_MEMORY_DEBUG and MBEDTLS_SSL_MAX_FRAGMENT_LENGTH"
     make test
 
     msg "test: MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH, MBEDTLS_MEMORY_BUFFER_ALLOC_C, MBEDTLS_MEMORY_DEBUG and MBEDTLS_SSL_MAX_FRAGMENT_LENGTH"
-    if_build_succeeded tests/ssl-opt.sh -f "Handshake memory usage"
+    tests/ssl-opt.sh -f "Handshake memory usage"
 }
 
 component_test_when_no_ciphersuites_have_mac () {
@@ -1943,7 +2429,7 @@
     make test
 
     msg "test ssl-opt.sh: !MBEDTLS_SSL_SOME_MODES_USE_MAC"
-    if_build_succeeded tests/ssl-opt.sh -f 'Default\|EtM' -e 'without EtM'
+    tests/ssl-opt.sh -f 'Default\|EtM' -e 'without EtM'
 }
 
 component_test_null_entropy () {
@@ -1965,7 +2451,7 @@
 component_test_no_date_time () {
     msg "build: default config without MBEDTLS_HAVE_TIME_DATE"
     scripts/config.py unset MBEDTLS_HAVE_TIME_DATE
-    CC=gcc cmake
+    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Check .
     make
 
     msg "test: !MBEDTLS_HAVE_TIME_DATE - main suites"
@@ -1995,7 +2481,7 @@
     msg "selftest: malloc(0) returns NULL (ASan+UBSan build)"
     # Just the calloc selftest. "make test" ran the others as part of the
     # test suites.
-    if_build_succeeded programs/test/selftest calloc
+    programs/test/selftest calloc
 
     msg "test ssl-opt.sh: malloc(0) returns NULL (ASan+UBSan build)"
     # Run a subset of the tests. The choice is a balance between coverage
@@ -2003,7 +2489,7 @@
     # The current choice is to skip tests whose description includes
     # "proxy", which is an approximation of skipping tests that use the
     # UDP proxy, which tend to be slower and flakier.
-    if_build_succeeded tests/ssl-opt.sh -e 'proxy'
+    tests/ssl-opt.sh -e 'proxy'
 }
 
 component_test_aes_fewer_tables () {
@@ -2082,11 +2568,17 @@
 
 component_test_psa_crypto_drivers () {
     msg "build: MBEDTLS_PSA_CRYPTO_DRIVERS w/ driver hooks"
+    scripts/config.py full
     scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS
+    loc_cflags="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST_ALL"
+    loc_cflags="${loc_cflags} '-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/user-config-for-test.h\"'"
+    loc_cflags="${loc_cflags} -I../tests/include -O2"
 
-    msg "test: MBEDTLS_PSA_CRYPTO_DRIVERS, signature"
+    make CC=gcc CFLAGS="${loc_cflags}" LDFLAGS="$ASAN_CFLAGS"
+    unset loc_cflags
+
+    msg "test: full + MBEDTLS_PSA_CRYPTO_DRIVERS"
     make test
 }
 
@@ -2094,6 +2586,7 @@
     msg "build/test: make shared" # ~ 40s
     make SHARED=1 all check
     ldd programs/util/strerror | grep libmbedcrypto
+    programs/test/dlopen_demo.sh
 }
 
 component_test_cmake_shared () {
@@ -2102,6 +2595,7 @@
     make
     ldd programs/util/strerror | grep libmbedcrypto
     make test
+    programs/test/dlopen_demo.sh
 }
 
 test_build_opt () {
@@ -2140,7 +2634,8 @@
 }
 
 component_test_m32_o0 () {
-    # Build once with -O0, to compile out the i386 specific inline assembly
+    # Build without optimization, so as to use portable C code (in a 32-bit
+    # build) and not the i386-specific inline assembly.
     msg "build: i386, make, gcc -O0 (ASan build)" # ~ 30s
     scripts/config.py full
     make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O0" LDFLAGS="-m32 $ASAN_CFLAGS"
@@ -2155,19 +2650,20 @@
     esac
 }
 
-component_test_m32_o1 () {
-    # Build again with -O1, to compile in the i386 specific inline assembly
-    msg "build: i386, make, gcc -O1 (ASan build)" # ~ 30s
+component_test_m32_o2 () {
+    # Build with optimization, to use the i386 specific inline assembly
+    # and go faster for tests.
+    msg "build: i386, make, gcc -O2 (ASan build)" # ~ 30s
     scripts/config.py full
-    make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O1" LDFLAGS="-m32 $ASAN_CFLAGS"
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O2" LDFLAGS="-m32 $ASAN_CFLAGS"
 
-    msg "test: i386, make, gcc -O1 (ASan build)"
+    msg "test: i386, make, gcc -O2 (ASan build)"
     make test
 
-    msg "test ssl-opt.sh, i386, make, gcc-O1"
-    if_build_succeeded tests/ssl-opt.sh
+    msg "test ssl-opt.sh, i386, make, gcc-O2"
+    tests/ssl-opt.sh
 }
-support_test_m32_o1 () {
+support_test_m32_o2 () {
     support_test_m32_o0 "$@"
 }
 
@@ -2181,11 +2677,11 @@
     make test
 
     msg "test: i386, Everest ECDH context - ECDH-related part of ssl-opt.sh (ASan build)" # ~ 5s
-    if_build_succeeded tests/ssl-opt.sh -f ECDH
+    tests/ssl-opt.sh -f ECDH
 
     msg "test: i386, Everest ECDH context - compat.sh with some ECDH ciphersuites (ASan build)" # ~ 3 min
     # Exclude some symmetric ciphers that are redundant here to gain time.
-    if_build_succeeded tests/compat.sh -f ECDH -V NO -e 'ARCFOUR\|ARIA\|CAMELLIA\|CHACHA\|DES\|RC4'
+    tests/compat.sh -f ECDH -V NO -e 'ARCFOUR\|ARIA\|CAMELLIA\|CHACHA\|DES\|RC4'
 }
 support_test_m32_everest () {
     support_test_m32_o0 "$@"
@@ -2281,14 +2777,29 @@
     ${ARM_NONE_EABI_GCC_PREFIX}size library/*.o
 }
 
-component_build_arm_none_eabi_gcc_arm5vte () {
-    msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -march=arm5vte" # ~ 10s
+component_build_arm_linux_gnueabi_gcc_arm5vte () {
+    msg "build: ${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc -march=arm5vte" # ~ 10s
     scripts/config.py baremetal
     # Build for a target platform that's close to what Debian uses
     # for its "armel" distribution (https://wiki.debian.org/ArmEabiPort).
     # See https://github.com/ARMmbed/mbedtls/pull/2169 and comments.
-    # It would be better to build with arm-linux-gnueabi-gcc but
-    # we don't have that on our CI at this time.
+    # Build everything including programs, see for example
+    # https://github.com/ARMmbed/mbedtls/pull/3449#issuecomment-675313720
+    make CC="${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc" AR="${ARM_LINUX_GNUEABI_GCC_PREFIX}ar" CFLAGS='-Werror -Wall -Wextra -march=armv5te -O1' LDFLAGS='-march=armv5te'
+
+    msg "size: ${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc -march=armv5te -O1"
+    ${ARM_LINUX_GNUEABI_GCC_PREFIX}size library/*.o
+}
+support_build_arm_linux_gnueabi_gcc_arm5vte () {
+    type ${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc >/dev/null 2>&1
+}
+
+component_build_arm_none_eabi_gcc_arm5vte () {
+    msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -march=arm5vte" # ~ 10s
+    scripts/config.py baremetal
+    # This is an imperfect substitute for
+    # component_build_arm_linux_gnueabi_gcc_arm5vte
+    # in case the gcc-arm-linux-gnueabi toolchain is not available
     make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" CFLAGS='-std=c99 -Werror -Wall -Wextra -march=armv5te -O1' LDFLAGS='-march=armv5te' SHELL='sh -x' lib
 
     msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -march=armv5te -O1"
@@ -2310,7 +2821,7 @@
     scripts/config.py set MBEDTLS_NO_UDBL_DIVISION
     make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-std=c99 -Werror -Wall -Wextra' lib
     echo "Checking that software 64-bit division is not required"
-    if_build_succeeded not grep __aeabi_uldiv library/*.o
+    not grep __aeabi_uldiv library/*.o
 }
 
 component_build_arm_none_eabi_gcc_no_64bit_multiplication () {
@@ -2319,7 +2830,7 @@
     scripts/config.py set MBEDTLS_NO_64BIT_MULTIPLICATION
     make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-std=c99 -Werror -O1 -march=armv6-m -mthumb' lib
     echo "Checking that software 64-bit multiplication is not required"
-    if_build_succeeded not grep __aeabi_lmul library/*.o
+    not grep __aeabi_lmul library/*.o
 }
 
 component_build_armcc () {
@@ -2354,15 +2865,6 @@
     make CFLAGS='-Werror -O1'
 }
 
-component_test_allow_sha1 () {
-    msg "build: allow SHA1 in certificates by default"
-    scripts/config.py set MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES
-    make CFLAGS='-Werror -Wall -Wextra'
-    msg "test: allow SHA1 in certificates by default"
-    make test
-    if_build_succeeded tests/ssl-opt.sh -f SHA-1
-}
-
 component_test_tls13_experimental () {
     msg "build: default config with MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL enabled"
     scripts/config.pl set MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL
@@ -2402,13 +2904,13 @@
     make test
 
     msg "test: ssl-opt.sh (MSan)" # ~ 1 min
-    if_build_succeeded tests/ssl-opt.sh
+    tests/ssl-opt.sh
 
     # Optional part(s)
 
     if [ "$MEMORY" -gt 0 ]; then
         msg "test: compat.sh (MSan)" # ~ 6 min 20s
-        if_build_succeeded tests/compat.sh
+        tests/compat.sh
     fi
 }
 
@@ -2424,26 +2926,56 @@
     # seem to receive signals under valgrind on OS X).
     if [ "$MEMORY" -gt 0 ]; then
         msg "test: ssl-opt.sh --memcheck (Release)"
-        if_build_succeeded tests/ssl-opt.sh --memcheck
+        tests/ssl-opt.sh --memcheck
     fi
 
     if [ "$MEMORY" -gt 1 ]; then
         msg "test: compat.sh --memcheck (Release)"
-        if_build_succeeded tests/compat.sh --memcheck
+        tests/compat.sh --memcheck
     fi
 
     if [ "$MEMORY" -gt 0 ]; then
         msg "test: context-info.sh --memcheck (Release)"
-        if_build_succeeded tests/context-info.sh --memcheck
+        tests/context-info.sh --memcheck
     fi
 }
 
+support_test_cmake_out_of_source () {
+    distrib_id=""
+    distrib_ver=""
+    distrib_ver_minor=""
+    distrib_ver_major=""
+
+    # Attempt to parse lsb-release to find out distribution and version. If not
+    # found this should fail safe (test is supported).
+    if [[ -f /etc/lsb-release ]]; then
+
+        while read -r lsb_line; do
+            case "$lsb_line" in
+                "DISTRIB_ID"*) distrib_id=${lsb_line/#DISTRIB_ID=};;
+                "DISTRIB_RELEASE"*) distrib_ver=${lsb_line/#DISTRIB_RELEASE=};;
+            esac
+        done < /etc/lsb-release
+
+        distrib_ver_major="${distrib_ver%%.*}"
+        distrib_ver="${distrib_ver#*.}"
+        distrib_ver_minor="${distrib_ver%%.*}"
+    fi
+
+    # Running the out of source CMake test on Ubuntu 16.04 using more than one
+    # processor (as the CI does) can create a race condition whereby the build
+    # fails to see a generated file, despite that file actually having been
+    # generated. This problem appears to go away with 18.04 or newer, so make
+    # the out of source tests unsupported on Ubuntu 16.04.
+    [ "$distrib_id" != "Ubuntu" ] || [ "$distrib_ver_major" -gt 16 ]
+}
+
 component_test_cmake_out_of_source () {
     msg "build: cmake 'out-of-source' build"
     MBEDTLS_ROOT_DIR="$PWD"
     mkdir "$OUT_OF_SOURCE_DIR"
     cd "$OUT_OF_SOURCE_DIR"
-    cmake "$MBEDTLS_ROOT_DIR"
+    cmake -D CMAKE_BUILD_TYPE:String=Check "$MBEDTLS_ROOT_DIR"
     make
 
     msg "test: cmake 'out-of-source' build"
@@ -2453,15 +2985,13 @@
     # "No such file or directory", which would indicate that some required
     # file is missing (ssl-opt.sh tolerates the absence of some files so
     # may exit with status 0 but emit errors).
-    if_build_succeeded ./tests/ssl-opt.sh -f 'Fallback SCSV: beginning of list' 2>ssl-opt.err
-    if [ -s ssl-opt.err ]; then
-        cat ssl-opt.err >&2
-        record_status [ ! -s ssl-opt.err ]
-        rm ssl-opt.err
-    fi
+    ./tests/ssl-opt.sh -f 'Fallback SCSV: beginning of list' 2>ssl-opt.err
+    cat ssl-opt.err >&2
+    # If ssl-opt.err is non-empty, record an error and keep going.
+    [ ! -s ssl-opt.err ]
+    rm ssl-opt.err
     cd "$MBEDTLS_ROOT_DIR"
     rm -rf "$OUT_OF_SOURCE_DIR"
-    unset MBEDTLS_ROOT_DIR
 }
 
 component_test_cmake_as_subdirectory () {
@@ -2471,7 +3001,7 @@
     cd programs/test/cmake_subproject
     cmake .
     make
-    if_build_succeeded ./cmake_subproject
+    ./cmake_subproject
 
     cd "$MBEDTLS_ROOT_DIR"
     unset MBEDTLS_ROOT_DIR
@@ -2496,9 +3026,9 @@
         for compiler in clang gcc; do
             msg "test: $compiler $optimization_flag, mbedtls_platform_zeroize()"
             make programs CC="$compiler" DEBUG=1 CFLAGS="$optimization_flag"
-            if_build_succeeded gdb -ex "$gdb_disable_aslr" -x tests/scripts/test_zeroize.gdb -nw -batch -nx 2>&1 | tee test_zeroize.log
-            if_build_succeeded grep "The buffer was correctly zeroized" test_zeroize.log
-            if_build_succeeded not grep -i "error" test_zeroize.log
+            gdb -ex "$gdb_disable_aslr" -x tests/scripts/test_zeroize.gdb -nw -batch -nx 2>&1 | tee test_zeroize.log
+            grep "The buffer was correctly zeroized" test_zeroize.log
+            not grep -i "error" test_zeroize.log
             rm -f test_zeroize.log
             make clean
         done
@@ -2507,9 +3037,30 @@
     unset gdb_disable_aslr
 }
 
+component_test_psa_compliance () {
+    msg "build: make, default config + CMAC, libmbedcrypto.a only"
+    scripts/config.py set MBEDTLS_CMAC_C
+    make -C library libmbedcrypto.a
+
+    msg "unit test: test_psa_compliance.py"
+    ./tests/scripts/test_psa_compliance.py
+}
+
+support_test_psa_compliance () {
+    # psa-compliance-tests only supports CMake >= 3.10.0
+    ver="$(cmake --version)"
+    ver="${ver#cmake version }"
+    ver_major="${ver%%.*}"
+
+    ver="${ver#*.}"
+    ver_minor="${ver%%.*}"
+
+    [ "$ver_major" -eq 3 ] && [ "$ver_minor" -ge 10 ]
+}
+
 component_check_python_files () {
     msg "Lint: Python scripts"
-    record_status tests/scripts/check-python-files.sh
+    tests/scripts/check-python-files.sh
 }
 
 component_check_generate_test_code () {
@@ -2517,7 +3068,7 @@
     # unittest writes out mundane stuff like number or tests run on stderr.
     # Our convention is to reserve stderr for actual errors, and write
     # harmless info on stdout so it can be suppress with --quiet.
-    record_status ./tests/scripts/test_generate_test_code.py 2>&1
+    ./tests/scripts/test_generate_test_code.py 2>&1
 }
 
 ################################################################
@@ -2526,7 +3077,7 @@
 
 post_report () {
     msg "Done, cleaning up"
-    cleanup
+    final_cleanup
 
     final_report
 }
@@ -2537,26 +3088,71 @@
 #### Run all the things
 ################################################################
 
+# Function invoked by --error-test to test error reporting.
+pseudo_component_error_test () {
+    msg "Testing error reporting $error_test_i"
+    if [ $KEEP_GOING -ne 0 ]; then
+        echo "Expect three failing commands."
+    fi
+    # If the component doesn't run in a subshell, changing error_test_i to an
+    # invalid integer will cause an error in the loop that runs this function.
+    error_test_i=this_should_not_be_used_since_the_component_runs_in_a_subshell
+    # Expected error: 'grep non_existent /dev/null -> 1'
+    grep non_existent /dev/null
+    # Expected error: '! grep -q . tests/scripts/all.sh -> 1'
+    not grep -q . "$0"
+    # Expected error: 'make unknown_target -> 2'
+    make unknown_target
+    false "this should not be executed"
+}
+
 # Run one component and clean up afterwards.
 run_component () {
-    # Back up the configuration in case the component modifies it.
-    # The cleanup function will restore it.
-    cp -p "$CONFIG_H" "$CONFIG_BAK"
-    cp -p "$CRYPTO_CONFIG_H" "$CRYPTO_CONFIG_BAK"
     current_component="$1"
     export MBEDTLS_TEST_CONFIGURATION="$current_component"
 
     # Unconditionally create a seedfile that's sufficiently long.
     # Do this before each component, because a previous component may
     # have messed it up or shortened it.
-    redirect_err dd if=/dev/urandom of=./tests/seedfile bs=64 count=1
+    local dd_cmd
+    dd_cmd=(dd if=/dev/urandom of=./tests/seedfile bs=64 count=1)
+    case $OSTYPE in
+        linux*|freebsd*|openbsd*|darwin*) dd_cmd+=(status=none)
+    esac
+    "${dd_cmd[@]}"
 
-    # Run the component code.
-    if [ $QUIET -eq 1 ]; then
-        # msg() is silenced, so just print the component name here
-        echo "${current_component#component_}"
+    # Run the component in a subshell, with error trapping and output
+    # redirection set up based on the relevant options.
+    if [ $KEEP_GOING -eq 1 ]; then
+        # We want to keep running if the subshell fails, so 'set -e' must
+        # be off when the subshell runs.
+        set +e
     fi
-    redirect_out "$@"
+    (
+        if [ $QUIET -eq 1 ]; then
+            # msg() will be silenced, so just print the component name here.
+            echo "${current_component#component_}"
+            exec >/dev/null
+        fi
+        if [ $KEEP_GOING -eq 1 ]; then
+            # Keep "set -e" off, and run an ERR trap instead to record failures.
+            set -E
+            trap err_trap ERR
+        fi
+        # The next line is what runs the component
+        "$@"
+        if [ $KEEP_GOING -eq 1 ]; then
+            trap - ERR
+            exit $last_failure_status
+        fi
+    )
+    component_status=$?
+    if [ $KEEP_GOING -eq 1 ]; then
+        set -e
+        if [ $component_status -ne 0 ]; then
+            failure_count=$((failure_count + 1))
+        fi
+    fi
 
     # Restore the build tree to a clean state.
     cleanup
@@ -2569,22 +3165,23 @@
 pre_parse_command_line "$@"
 
 pre_check_git
+pre_restore_files
+pre_back_up
 
 build_status=0
 if [ $KEEP_GOING -eq 1 ]; then
     pre_setup_keep_going
-else
-    record_status () {
-        "$@"
-    }
 fi
-pre_setup_quiet_redirect
 pre_prepare_outcome_file
 pre_print_configuration
 pre_check_tools
 cleanup
 
 # Run the requested tests.
+for ((error_test_i=1; error_test_i <= error_test; error_test_i++)); do
+    run_component pseudo_component_error_test
+done
+unset error_test_i
 for component in $RUN_COMPONENTS; do
     run_component "component_$component"
 done
diff --git a/third_party/mbedtls/repo/tests/scripts/basic-build-test.sh b/third_party/mbedtls/repo/tests/scripts/basic-build-test.sh
index 64ed145..8756634 100755
--- a/third_party/mbedtls/repo/tests/scripts/basic-build-test.sh
+++ b/third_party/mbedtls/repo/tests/scripts/basic-build-test.sh
@@ -62,6 +62,11 @@
 : ${SEED:=1}
 export SEED
 
+# if MAKEFLAGS is not set add the -j option to speed up invocations of make
+if [ -z "${MAKEFLAGS+set}" ]; then
+    export MAKEFLAGS="-j"
+fi
+
 # To avoid setting OpenSSL and GnuTLS for each call to compat.sh and ssl-opt.sh
 # we just export the variables they require
 export OPENSSL_CMD="$OPENSSL"
@@ -87,7 +92,7 @@
 make clean
 cp "$CONFIG_H" "$CONFIG_BAK"
 scripts/config.py full
-make -j
+make
 
 
 # Step 2 - Execute the tests
@@ -107,6 +112,7 @@
 # Step 2b - System Tests (keep going even if some tests fail)
 echo
 echo '################ ssl-opt.sh ################'
+echo "ssl-opt.sh will use SEED=$SEED for udp_proxy"
 sh ssl-opt.sh |tee sys-test-$TEST_OUTPUT
 echo '^^^^^^^^^^^^^^^^ ssl-opt.sh ^^^^^^^^^^^^^^^^'
 echo
@@ -154,116 +160,126 @@
 echo "Test Report Summary"
 echo
 
-cd tests
+# A failure of the left-hand side of a pipe is ignored (this is a limitation
+# of sh). We'll use the presence of this file as a marker that the generation
+# of the report succeeded.
+rm -f "tests/basic-build-test-$$.ok"
 
-# Step 4a - Unit tests
-echo "Unit tests - tests/scripts/run-test-suites.pl"
+{
 
-PASSED_TESTS=$(tail -n6 unit-test-$TEST_OUTPUT|sed -n -e 's/test cases passed :[\t]*\([0-9]*\)/\1/p'| tr -d ' ')
-SKIPPED_TESTS=$(tail -n6 unit-test-$TEST_OUTPUT|sed -n -e 's/skipped :[ \t]*\([0-9]*\)/\1/p'| tr -d ' ')
-TOTAL_SUITES=$(tail -n6 unit-test-$TEST_OUTPUT|sed -n -e 's/.* (\([0-9]*\) .*, [0-9]* tests run)/\1/p'| tr -d ' ')
-FAILED_TESTS=$(tail -n6 unit-test-$TEST_OUTPUT|sed -n -e 's/failed :[\t]*\([0-9]*\)/\1/p' |tr -d ' ')
+    cd tests
 
-echo "No test suites     : $TOTAL_SUITES"
-echo "Passed             : $PASSED_TESTS"
-echo "Failed             : $FAILED_TESTS"
-echo "Skipped            : $SKIPPED_TESTS"
-echo "Total exec'd tests : $(($PASSED_TESTS + $FAILED_TESTS))"
-echo "Total avail tests  : $(($PASSED_TESTS + $FAILED_TESTS + $SKIPPED_TESTS))"
-echo
+    # Step 4a - Unit tests
+    echo "Unit tests - tests/scripts/run-test-suites.pl"
 
-TOTAL_PASS=$PASSED_TESTS
-TOTAL_FAIL=$FAILED_TESTS
-TOTAL_SKIP=$SKIPPED_TESTS
-TOTAL_AVAIL=$(($PASSED_TESTS + $FAILED_TESTS + $SKIPPED_TESTS))
-TOTAL_EXED=$(($PASSED_TESTS + $FAILED_TESTS))
+    PASSED_TESTS=$(tail -n6 unit-test-$TEST_OUTPUT|sed -n -e 's/test cases passed :[\t]*\([0-9]*\)/\1/p'| tr -d ' ')
+    SKIPPED_TESTS=$(tail -n6 unit-test-$TEST_OUTPUT|sed -n -e 's/skipped :[ \t]*\([0-9]*\)/\1/p'| tr -d ' ')
+    TOTAL_SUITES=$(tail -n6 unit-test-$TEST_OUTPUT|sed -n -e 's/.* (\([0-9]*\) .*, [0-9]* tests run)/\1/p'| tr -d ' ')
+    FAILED_TESTS=$(tail -n6 unit-test-$TEST_OUTPUT|sed -n -e 's/failed :[\t]*\([0-9]*\)/\1/p' |tr -d ' ')
 
-# Step 4b - TLS Options tests
-echo "TLS Options tests - tests/ssl-opt.sh"
+    echo "No test suites     : $TOTAL_SUITES"
+    echo "Passed             : $PASSED_TESTS"
+    echo "Failed             : $FAILED_TESTS"
+    echo "Skipped            : $SKIPPED_TESTS"
+    echo "Total exec'd tests : $(($PASSED_TESTS + $FAILED_TESTS))"
+    echo "Total avail tests  : $(($PASSED_TESTS + $FAILED_TESTS + $SKIPPED_TESTS))"
+    echo
 
-PASSED_TESTS=$(tail -n5 sys-test-$TEST_OUTPUT|sed -n -e 's/.* (\([0-9]*\) \/ [0-9]* tests ([0-9]* skipped))$/\1/p')
-SKIPPED_TESTS=$(tail -n5 sys-test-$TEST_OUTPUT|sed -n -e 's/.* ([0-9]* \/ [0-9]* tests (\([0-9]*\) skipped))$/\1/p')
-TOTAL_TESTS=$(tail -n5 sys-test-$TEST_OUTPUT|sed -n -e 's/.* ([0-9]* \/ \([0-9]*\) tests ([0-9]* skipped))$/\1/p')
-FAILED_TESTS=$(($TOTAL_TESTS - $PASSED_TESTS))
+    TOTAL_PASS=$PASSED_TESTS
+    TOTAL_FAIL=$FAILED_TESTS
+    TOTAL_SKIP=$SKIPPED_TESTS
+    TOTAL_AVAIL=$(($PASSED_TESTS + $FAILED_TESTS + $SKIPPED_TESTS))
+    TOTAL_EXED=$(($PASSED_TESTS + $FAILED_TESTS))
 
-echo "Passed             : $PASSED_TESTS"
-echo "Failed             : $FAILED_TESTS"
-echo "Skipped            : $SKIPPED_TESTS"
-echo "Total exec'd tests : $TOTAL_TESTS"
-echo "Total avail tests  : $(($TOTAL_TESTS + $SKIPPED_TESTS))"
-echo
+    # Step 4b - TLS Options tests
+    echo "TLS Options tests - tests/ssl-opt.sh"
 
-TOTAL_PASS=$(($TOTAL_PASS+$PASSED_TESTS))
-TOTAL_FAIL=$(($TOTAL_FAIL+$FAILED_TESTS))
-TOTAL_SKIP=$(($TOTAL_SKIP+$SKIPPED_TESTS))
-TOTAL_AVAIL=$(($TOTAL_AVAIL + $TOTAL_TESTS + $SKIPPED_TESTS))
-TOTAL_EXED=$(($TOTAL_EXED + $TOTAL_TESTS))
+    PASSED_TESTS=$(tail -n5 sys-test-$TEST_OUTPUT|sed -n -e 's/.* (\([0-9]*\) \/ [0-9]* tests ([0-9]* skipped))$/\1/p')
+    SKIPPED_TESTS=$(tail -n5 sys-test-$TEST_OUTPUT|sed -n -e 's/.* ([0-9]* \/ [0-9]* tests (\([0-9]*\) skipped))$/\1/p')
+    TOTAL_TESTS=$(tail -n5 sys-test-$TEST_OUTPUT|sed -n -e 's/.* ([0-9]* \/ \([0-9]*\) tests ([0-9]* skipped))$/\1/p')
+    FAILED_TESTS=$(($TOTAL_TESTS - $PASSED_TESTS))
+
+    echo "Passed             : $PASSED_TESTS"
+    echo "Failed             : $FAILED_TESTS"
+    echo "Skipped            : $SKIPPED_TESTS"
+    echo "Total exec'd tests : $TOTAL_TESTS"
+    echo "Total avail tests  : $(($TOTAL_TESTS + $SKIPPED_TESTS))"
+    echo
+
+    TOTAL_PASS=$(($TOTAL_PASS+$PASSED_TESTS))
+    TOTAL_FAIL=$(($TOTAL_FAIL+$FAILED_TESTS))
+    TOTAL_SKIP=$(($TOTAL_SKIP+$SKIPPED_TESTS))
+    TOTAL_AVAIL=$(($TOTAL_AVAIL + $TOTAL_TESTS + $SKIPPED_TESTS))
+    TOTAL_EXED=$(($TOTAL_EXED + $TOTAL_TESTS))
 
 
-# Step 4c - System Compatibility tests
-echo "System/Compatibility tests - tests/compat.sh"
+    # Step 4c - System Compatibility tests
+    echo "System/Compatibility tests - tests/compat.sh"
 
-PASSED_TESTS=$(cat compat-test-$TEST_OUTPUT | sed -n -e 's/.* (\([0-9]*\) \/ [0-9]* tests ([0-9]* skipped))$/\1/p' | awk 'BEGIN{ s = 0 } { s += $1 } END{ print s }')
-SKIPPED_TESTS=$(cat compat-test-$TEST_OUTPUT | sed -n -e 's/.* ([0-9]* \/ [0-9]* tests (\([0-9]*\) skipped))$/\1/p' | awk 'BEGIN{ s = 0 } { s += $1 } END{ print s }')
-EXED_TESTS=$(cat compat-test-$TEST_OUTPUT | sed -n -e 's/.* ([0-9]* \/ \([0-9]*\) tests ([0-9]* skipped))$/\1/p' | awk 'BEGIN{ s = 0 } { s += $1 } END{ print s }')
-FAILED_TESTS=$(($EXED_TESTS - $PASSED_TESTS))
+    PASSED_TESTS=$(cat compat-test-$TEST_OUTPUT | sed -n -e 's/.* (\([0-9]*\) \/ [0-9]* tests ([0-9]* skipped))$/\1/p' | awk 'BEGIN{ s = 0 } { s += $1 } END{ print s }')
+    SKIPPED_TESTS=$(cat compat-test-$TEST_OUTPUT | sed -n -e 's/.* ([0-9]* \/ [0-9]* tests (\([0-9]*\) skipped))$/\1/p' | awk 'BEGIN{ s = 0 } { s += $1 } END{ print s }')
+    EXED_TESTS=$(cat compat-test-$TEST_OUTPUT | sed -n -e 's/.* ([0-9]* \/ \([0-9]*\) tests ([0-9]* skipped))$/\1/p' | awk 'BEGIN{ s = 0 } { s += $1 } END{ print s }')
+    FAILED_TESTS=$(($EXED_TESTS - $PASSED_TESTS))
 
-echo "Passed             : $PASSED_TESTS"
-echo "Failed             : $FAILED_TESTS"
-echo "Skipped            : $SKIPPED_TESTS"
-echo "Total exec'd tests : $EXED_TESTS"
-echo "Total avail tests  : $(($EXED_TESTS + $SKIPPED_TESTS))"
-echo
+    echo "Passed             : $PASSED_TESTS"
+    echo "Failed             : $FAILED_TESTS"
+    echo "Skipped            : $SKIPPED_TESTS"
+    echo "Total exec'd tests : $EXED_TESTS"
+    echo "Total avail tests  : $(($EXED_TESTS + $SKIPPED_TESTS))"
+    echo
 
-TOTAL_PASS=$(($TOTAL_PASS+$PASSED_TESTS))
-TOTAL_FAIL=$(($TOTAL_FAIL+$FAILED_TESTS))
-TOTAL_SKIP=$(($TOTAL_SKIP+$SKIPPED_TESTS))
-TOTAL_AVAIL=$(($TOTAL_AVAIL + $EXED_TESTS + $SKIPPED_TESTS))
-TOTAL_EXED=$(($TOTAL_EXED + $EXED_TESTS))
+    TOTAL_PASS=$(($TOTAL_PASS+$PASSED_TESTS))
+    TOTAL_FAIL=$(($TOTAL_FAIL+$FAILED_TESTS))
+    TOTAL_SKIP=$(($TOTAL_SKIP+$SKIPPED_TESTS))
+    TOTAL_AVAIL=$(($TOTAL_AVAIL + $EXED_TESTS + $SKIPPED_TESTS))
+    TOTAL_EXED=$(($TOTAL_EXED + $EXED_TESTS))
 
 
-# Step 4d - Grand totals
-echo "-------------------------------------------------------------------------"
-echo "Total tests"
+    # Step 4d - Grand totals
+    echo "-------------------------------------------------------------------------"
+    echo "Total tests"
 
-echo "Total Passed       : $TOTAL_PASS"
-echo "Total Failed       : $TOTAL_FAIL"
-echo "Total Skipped      : $TOTAL_SKIP"
-echo "Total exec'd tests : $TOTAL_EXED"
-echo "Total avail tests  : $TOTAL_AVAIL"
-echo
+    echo "Total Passed       : $TOTAL_PASS"
+    echo "Total Failed       : $TOTAL_FAIL"
+    echo "Total Skipped      : $TOTAL_SKIP"
+    echo "Total exec'd tests : $TOTAL_EXED"
+    echo "Total avail tests  : $TOTAL_AVAIL"
+    echo
 
 
-# Step 4e - Coverage
-echo "Coverage"
+    # Step 4e - Coverage
+    echo "Coverage"
 
-LINES_TESTED=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  lines......: [0-9]*.[0-9]% (\([0-9]*\) of [0-9]* lines)/\1/p')
-LINES_TOTAL=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  lines......: [0-9]*.[0-9]% ([0-9]* of \([0-9]*\) lines)/\1/p')
-FUNCS_TESTED=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  functions..: [0-9]*.[0-9]% (\([0-9]*\) of [0-9]* functions)$/\1/p')
-FUNCS_TOTAL=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  functions..: [0-9]*.[0-9]% ([0-9]* of \([0-9]*\) functions)$/\1/p')
-BRANCHES_TESTED=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  branches...: [0-9]*.[0-9]% (\([0-9]*\) of [0-9]* branches)$/\1/p')
-BRANCHES_TOTAL=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  branches...: [0-9]*.[0-9]% ([0-9]* of \([0-9]*\) branches)$/\1/p')
+    LINES_TESTED=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  lines......: [0-9]*.[0-9]% (\([0-9]*\) of [0-9]* lines)/\1/p')
+    LINES_TOTAL=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  lines......: [0-9]*.[0-9]% ([0-9]* of \([0-9]*\) lines)/\1/p')
+    FUNCS_TESTED=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  functions..: [0-9]*.[0-9]% (\([0-9]*\) of [0-9]* functions)$/\1/p')
+    FUNCS_TOTAL=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  functions..: [0-9]*.[0-9]% ([0-9]* of \([0-9]*\) functions)$/\1/p')
+    BRANCHES_TESTED=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  branches...: [0-9]*.[0-9]% (\([0-9]*\) of [0-9]* branches)$/\1/p')
+    BRANCHES_TOTAL=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  branches...: [0-9]*.[0-9]% ([0-9]* of \([0-9]*\) branches)$/\1/p')
 
-LINES_PERCENT=$((1000*$LINES_TESTED/$LINES_TOTAL))
-LINES_PERCENT="$(($LINES_PERCENT/10)).$(($LINES_PERCENT-($LINES_PERCENT/10)*10))"
+    LINES_PERCENT=$((1000*$LINES_TESTED/$LINES_TOTAL))
+    LINES_PERCENT="$(($LINES_PERCENT/10)).$(($LINES_PERCENT-($LINES_PERCENT/10)*10))"
 
-FUNCS_PERCENT=$((1000*$FUNCS_TESTED/$FUNCS_TOTAL))
-FUNCS_PERCENT="$(($FUNCS_PERCENT/10)).$(($FUNCS_PERCENT-($FUNCS_PERCENT/10)*10))"
+    FUNCS_PERCENT=$((1000*$FUNCS_TESTED/$FUNCS_TOTAL))
+    FUNCS_PERCENT="$(($FUNCS_PERCENT/10)).$(($FUNCS_PERCENT-($FUNCS_PERCENT/10)*10))"
 
-BRANCHES_PERCENT=$((1000*$BRANCHES_TESTED/$BRANCHES_TOTAL))
-BRANCHES_PERCENT="$(($BRANCHES_PERCENT/10)).$(($BRANCHES_PERCENT-($BRANCHES_PERCENT/10)*10))"
+    BRANCHES_PERCENT=$((1000*$BRANCHES_TESTED/$BRANCHES_TOTAL))
+    BRANCHES_PERCENT="$(($BRANCHES_PERCENT/10)).$(($BRANCHES_PERCENT-($BRANCHES_PERCENT/10)*10))"
 
-echo "Lines Tested       : $LINES_TESTED of $LINES_TOTAL $LINES_PERCENT%"
-echo "Functions Tested   : $FUNCS_TESTED of $FUNCS_TOTAL $FUNCS_PERCENT%"
-echo "Branches Tested    : $BRANCHES_TESTED of $BRANCHES_TOTAL $BRANCHES_PERCENT%"
-echo
+    rm unit-test-$TEST_OUTPUT
+    rm sys-test-$TEST_OUTPUT
+    rm compat-test-$TEST_OUTPUT
+    rm cov-$TEST_OUTPUT
 
-rm unit-test-$TEST_OUTPUT
-rm sys-test-$TEST_OUTPUT
-rm compat-test-$TEST_OUTPUT
-rm cov-$TEST_OUTPUT
+    echo "Lines Tested       : $LINES_TESTED of $LINES_TOTAL $LINES_PERCENT%"
+    echo "Functions Tested   : $FUNCS_TESTED of $FUNCS_TOTAL $FUNCS_PERCENT%"
+    echo "Branches Tested    : $BRANCHES_TESTED of $BRANCHES_TOTAL $BRANCHES_PERCENT%"
+    echo
 
-cd ..
+    # Mark the report generation as having succeeded. This must be the
+    # last thing in the report generation.
+    touch "basic-build-test-$$.ok"
+} | tee coverage-summary.txt
 
 make clean
 
@@ -271,6 +287,7 @@
     mv "$CONFIG_BAK" "$CONFIG_H"
 fi
 
-if [ $TOTAL_FAIL -ne 0 ]; then
-    exit 1
-fi
+# The file must exist, otherwise it means something went wrong while generating
+# the coverage report. If something did go wrong, rm will complain so this
+# script will exit with a failure status.
+rm "tests/basic-build-test-$$.ok"
diff --git a/third_party/mbedtls/repo/tests/scripts/check-generated-files.sh b/third_party/mbedtls/repo/tests/scripts/check-generated-files.sh
index 845d1c6..5e35be8 100755
--- a/third_party/mbedtls/repo/tests/scripts/check-generated-files.sh
+++ b/third_party/mbedtls/repo/tests/scripts/check-generated-files.sh
@@ -44,56 +44,56 @@
     UPDATE='y'
 fi
 
+# check SCRIPT FILENAME[...]
+# check SCRIPT DIRECTORY
+# Run SCRIPT and check that it does not modify any of the specified files.
+# In the first form, there can be any number of FILENAMEs, which must be
+# regular files.
+# In the second form, there must be a single DIRECTORY, standing for the
+# list of files in the directory. Running SCRIPT must not modify any file
+# in the directory and must not add or remove files either.
+# If $UPDATE is empty, abort with an error status if a file is modified.
 check()
 {
     SCRIPT=$1
-    TO_CHECK=$2
-    PATTERN=""
-    FILES=""
+    shift
 
-    if [ -d $TO_CHECK ]; then
-        for FILE in $TO_CHECK/*; do
-            FILES="$FILE $FILES"
-        done
-    else
-        FILES=$TO_CHECK
+    directory=
+    if [ -d "$1" ]; then
+        directory="$1"
+        set -- "$1"/*
     fi
 
-    for FILE in $FILES; do
-        cp $FILE $FILE.bak
+    for FILE in "$@"; do
+        cp "$FILE" "$FILE.bak"
     done
 
-    $SCRIPT
+    "$SCRIPT"
 
     # Compare the script output to the old files and remove backups
-    for FILE in $FILES; do
-        if ! diff $FILE $FILE.bak >/dev/null 2>&1; then
+    for FILE in "$@"; do
+        if ! diff "$FILE" "$FILE.bak" >/dev/null 2>&1; then
             echo "'$FILE' was either modified or deleted by '$SCRIPT'"
             if [ -z "$UPDATE" ]; then
                 exit 1
             fi
         fi
         if [ -z "$UPDATE" ]; then
-            mv $FILE.bak $FILE
+            mv "$FILE.bak" "$FILE"
         else
-            rm $FILE.bak
-        fi
-
-        if [ -d $TO_CHECK ]; then
-            # Create a grep regular expression that we can check against the
-            # directory contents to test whether new files have been created
-            if [ -z $PATTERN ]; then
-                PATTERN="$(basename $FILE)"
-            else
-                PATTERN="$PATTERN\|$(basename $FILE)"
-            fi
+            rm "$FILE.bak"
         fi
     done
 
-    if [ -d $TO_CHECK ]; then
+    if [ -n "$directory" ]; then
+        old_list="$*"
+        set -- "$directory"/*
+        new_list="$*"
         # Check if there are any new files
-        if ls -1 $TO_CHECK | grep -v "$PATTERN" >/dev/null 2>&1; then
-            echo "Files were created by '$SCRIPT'"
+        if [ "$old_list" != "$new_list" ]; then
+            echo "Files were deleted or created by '$SCRIPT'"
+            echo "Before: $old_list"
+            echo "After: $new_list"
             if [ -z "$UPDATE" ]; then
                 exit 1
             fi
@@ -106,3 +106,4 @@
 check scripts/generate_features.pl library/version_features.c
 check scripts/generate_visualc_files.pl visualc/VS2010
 check scripts/generate_psa_constants.py programs/psa/psa_constant_names_generated.c
+check tests/scripts/generate_psa_tests.py $(tests/scripts/generate_psa_tests.py --list)
diff --git a/third_party/mbedtls/repo/tests/scripts/check-names.sh b/third_party/mbedtls/repo/tests/scripts/check-names.sh
deleted file mode 100755
index 55f76da..0000000
--- a/third_party/mbedtls/repo/tests/scripts/check-names.sh
+++ /dev/null
@@ -1,133 +0,0 @@
-#!/bin/sh
-#
-# 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.
-
-set -eu
-
-if [ $# -ne 0 ] && [ "$1" = "--help" ]; then
-    cat <<EOF
-$0 [-v]
-This script confirms that the naming of all symbols and identifiers in mbed
-TLS are consistent with the house style and are also self-consistent.
-
-  -v    If the script fails unexpectedly, print a command trace.
-EOF
-    exit
-fi
-
-if grep --version|head -n1|grep GNU >/dev/null; then :; else
-    echo "This script requires GNU grep.">&2
-    exit 1
-fi
-
-trace=
-if [ $# -ne 0 ] && [ "$1" = "-v" ]; then
-  shift
-  trace='-x'
-  exec 2>check-names.err
-  trap 'echo "FAILED UNEXPECTEDLY, status=$?";
-        cat check-names.err' EXIT
-  set -x
-fi
-
-printf "Analysing source code...\n"
-
-sh $trace tests/scripts/list-macros.sh
-tests/scripts/list-enum-consts.pl
-sh $trace tests/scripts/list-identifiers.sh
-sh $trace tests/scripts/list-symbols.sh
-
-FAIL=0
-
-printf "\nExported symbols declared in header: "
-UNDECLARED=$( diff exported-symbols identifiers | sed -n -e 's/^< //p' )
-if [ "x$UNDECLARED" = "x" ]; then
-    echo "PASS"
-else
-    echo "FAIL"
-    echo "$UNDECLARED"
-    FAIL=1
-fi
-
-diff macros identifiers | sed -n -e 's/< //p' > actual-macros
-
-for THING in actual-macros enum-consts; do
-    printf 'Names of %s: ' "$THING"
-    test -r $THING
-    BAD=$( grep -E -v '^(MBEDTLS|PSA)_[0-9A-Z_]*[0-9A-Z]$' $THING || true )
-    UNDERSCORES=$( grep -E '.*__.*' $THING || true )
-
-    if [ "x$BAD" = "x" ] && [ "x$UNDERSCORES" = "x" ]; then
-        echo "PASS"
-    else
-        echo "FAIL"
-        echo "$BAD"
-        echo "$UNDERSCORES"
-        FAIL=1
-    fi
-done
-
-for THING in identifiers; do
-    printf 'Names of %s: ' "$THING"
-    test -r $THING
-    BAD=$( grep -E -v '^(mbedtls|psa)_[0-9a-z_]*[0-9a-z]$' $THING || true )
-    if [ "x$BAD" = "x" ]; then
-        echo "PASS"
-    else
-        echo "FAIL"
-        echo "$BAD"
-        FAIL=1
-    fi
-done
-
-printf "Likely typos: "
-sort -u actual-macros enum-consts > _caps
-HEADERS=$( ls include/mbedtls/*.h include/psa/*.h | egrep -v 'compat-1\.3\.h' )
-HEADERS="$HEADERS library/*.h"
-HEADERS="$HEADERS 3rdparty/everest/include/everest/everest.h 3rdparty/everest/include/everest/x25519.h"
-LIBRARY="$( ls library/*.c )"
-LIBRARY="$LIBRARY 3rdparty/everest/library/everest.c 3rdparty/everest/library/x25519.c"
-NL='
-'
-sed -n 's/MBED..._[A-Z0-9_]*/\'"$NL"'&\'"$NL"/gp \
-    $HEADERS $LIBRARY \
-    | grep MBEDTLS | sort -u > _MBEDTLS_XXX
-TYPOS=$( diff _caps _MBEDTLS_XXX | sed -n 's/^> //p' \
-            | egrep -v 'XXX|__|_$|^MBEDTLS_.*CONFIG_FILE$' || true )
-rm _MBEDTLS_XXX _caps
-if [ "x$TYPOS" = "x" ]; then
-    echo "PASS"
-else
-    echo "FAIL"
-    echo "$TYPOS"
-    FAIL=1
-fi
-
-if [ -n "$trace" ]; then
-  set +x
-  trap - EXIT
-  rm check-names.err
-fi
-
-printf "\nOverall: "
-if [ "$FAIL" -eq 0 ]; then
-    rm macros actual-macros enum-consts identifiers exported-symbols
-    echo "PASSED"
-    exit 0
-else
-    echo "FAILED"
-    exit 1
-fi
diff --git a/third_party/mbedtls/repo/tests/scripts/check-python-files.sh b/third_party/mbedtls/repo/tests/scripts/check-python-files.sh
index 518c423..449803a 100755
--- a/third_party/mbedtls/repo/tests/scripts/check-python-files.sh
+++ b/third_party/mbedtls/repo/tests/scripts/check-python-files.sh
@@ -14,11 +14,13 @@
 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
-# Purpose:
-#
-# Run 'pylint' on Python files for programming errors and helps enforcing
-# PEP8 coding standards.
+
+# Purpose: check Python files for potential programming errors or maintenance
+# hurdles. Run pylint to detect some potential mistakes and enforce PEP8
+# coding standards. If available, run mypy to perform static type checking.
+
+# We'll keep going on errors and report the status at the end.
+ret=0
 
 if type python3 >/dev/null 2>/dev/null; then
     PYTHON=python3
@@ -26,4 +28,56 @@
     PYTHON=python
 fi
 
-$PYTHON -m pylint -j 2 scripts/*.py tests/scripts/*.py
+check_version () {
+    $PYTHON - "$2" <<EOF
+import packaging.version
+import sys
+import $1 as package
+actual = package.__version__
+wanted = sys.argv[1]
+if packaging.version.parse(actual) < packaging.version.parse(wanted):
+    sys.stderr.write("$1: version %s is too old (want %s)\n" % (actual, wanted))
+    exit(1)
+EOF
+}
+
+can_pylint () {
+    # Pylint 1.5.2 from Ubuntu 16.04 is too old:
+    #     E: 34, 0: Unable to import 'mbedtls_dev' (import-error)
+    # Pylint 1.8.3 from Ubuntu 18.04 passed on the first commit containing this line.
+    check_version pylint 1.8.3
+}
+
+can_mypy () {
+    # mypy 0.770 is too old:
+    #     tests/scripts/test_psa_constant_names.py:34: error: Cannot find implementation or library stub for module named 'mbedtls_dev'
+    # mypy 0.780 from pip passed on the first commit containing this line.
+    check_version mypy.version 0.780
+}
+
+# With just a --can-xxx option, check whether the tool for xxx is available
+# with an acceptable version, and exit without running any checks. The exit
+# status is true if the tool is available and acceptable and false otherwise.
+if [ "$1" = "--can-pylint" ]; then
+    can_pylint
+    exit
+elif [ "$1" = "--can-mypy" ]; then
+    can_mypy
+    exit
+fi
+
+echo 'Running pylint ...'
+$PYTHON -m pylint -j 2 scripts/mbedtls_dev/*.py scripts/*.py tests/scripts/*.py || {
+    echo >&2 "pylint reported errors"
+    ret=1
+}
+
+# Check types if mypy is available
+if can_mypy; then
+    echo
+    echo 'Running mypy ...'
+    $PYTHON -m mypy scripts/*.py tests/scripts/*.py ||
+      ret=1
+fi
+
+exit $ret
diff --git a/third_party/mbedtls/repo/tests/scripts/check_files.py b/third_party/mbedtls/repo/tests/scripts/check_files.py
index 13fee9d..8857e00 100755
--- a/third_party/mbedtls/repo/tests/scripts/check_files.py
+++ b/third_party/mbedtls/repo/tests/scripts/check_files.py
@@ -29,6 +29,10 @@
 import re
 import subprocess
 import sys
+try:
+    from typing import FrozenSet, Optional, Pattern # pylint: disable=unused-import
+except ImportError:
+    pass
 
 
 class FileIssueTracker:
@@ -48,8 +52,8 @@
     ``heading``: human-readable description of the issue
     """
 
-    suffix_exemptions = frozenset()
-    path_exemptions = None
+    suffix_exemptions = frozenset() #type: FrozenSet[str]
+    path_exemptions = None #type: Optional[Pattern[str]]
     # heading must be defined in derived classes.
     # pylint: disable=no-member
 
@@ -161,13 +165,64 @@
 
     heading = "Incorrect permissions:"
 
+    # .py files can be either full scripts or modules, so they may or may
+    # not be executable.
+    suffix_exemptions = frozenset({".py"})
+
     def check_file_for_issue(self, filepath):
         is_executable = os.access(filepath, os.X_OK)
-        should_be_executable = filepath.endswith((".sh", ".pl", ".py"))
+        should_be_executable = filepath.endswith((".sh", ".pl"))
         if is_executable != should_be_executable:
             self.files_with_issues[filepath] = None
 
 
+class ShebangIssueTracker(FileIssueTracker):
+    """Track files with a bad, missing or extraneous shebang line.
+
+    Executable scripts must start with a valid shebang (#!) line.
+    """
+
+    heading = "Invalid shebang line:"
+
+    # Allow either /bin/sh, /bin/bash, or /usr/bin/env.
+    # Allow at most one argument (this is a Linux limitation).
+    # For sh and bash, the argument if present must be options.
+    # For env, the argument must be the base name of the interpeter.
+    _shebang_re = re.compile(rb'^#! ?(?:/bin/(bash|sh)(?: -[^\n ]*)?'
+                             rb'|/usr/bin/env ([^\n /]+))$')
+    _extensions = {
+        b'bash': 'sh',
+        b'perl': 'pl',
+        b'python3': 'py',
+        b'sh': 'sh',
+    }
+
+    def is_valid_shebang(self, first_line, filepath):
+        m = re.match(self._shebang_re, first_line)
+        if not m:
+            return False
+        interpreter = m.group(1) or m.group(2)
+        if interpreter not in self._extensions:
+            return False
+        if not filepath.endswith('.' + self._extensions[interpreter]):
+            return False
+        return True
+
+    def check_file_for_issue(self, filepath):
+        is_executable = os.access(filepath, os.X_OK)
+        with open(filepath, "rb") as f:
+            first_line = f.readline()
+        if first_line.startswith(b'#!'):
+            if not is_executable:
+                # Shebang on a non-executable file
+                self.files_with_issues[filepath] = None
+            elif not self.is_valid_shebang(first_line, filepath):
+                self.files_with_issues[filepath] = [1]
+        elif is_executable:
+            # Executable without a shebang
+            self.files_with_issues[filepath] = None
+
+
 class EndOfFileNewlineIssueTracker(FileIssueTracker):
     """Track files that end with an incomplete line
     (no newline character at the end of the last line)."""
@@ -288,6 +343,7 @@
         self.setup_logger(log_file)
         self.issues_to_check = [
             PermissionIssueTracker(),
+            ShebangIssueTracker(),
             EndOfFileNewlineIssueTracker(),
             Utf8BomIssueTracker(),
             UnixLineEndingIssueTracker(),
diff --git a/third_party/mbedtls/repo/tests/scripts/check_names.py b/third_party/mbedtls/repo/tests/scripts/check_names.py
new file mode 100755
index 0000000..b0638d7
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/scripts/check_names.py
@@ -0,0 +1,910 @@
+#!/usr/bin/env python3
+#
+# 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 script confirms that the naming of all symbols and identifiers in Mbed TLS
+are consistent with the house style and are also self-consistent. It only runs
+on Linux and macOS since it depends on nm.
+
+It contains two major Python classes, CodeParser and NameChecker. They both have
+a comprehensive "run-all" function (comprehensive_parse() and perform_checks())
+but the individual functions can also be used for specific needs.
+
+CodeParser makes heavy use of regular expressions to parse the code, and is
+dependent on the current code formatting. Many Python C parser libraries require
+preprocessed C code, which means no macro parsing. Compiler tools are also not
+very helpful when we want the exact location in the original source (which
+becomes impossible when e.g. comments are stripped).
+
+NameChecker performs the following checks:
+
+- All exported and available symbols in the library object files, are explicitly
+  declared in the header files. This uses the nm command.
+- All macros, constants, and identifiers (function names, struct names, etc)
+  follow the required regex pattern.
+- Typo checking: All words that begin with MBED exist as macros or constants.
+
+The script returns 0 on success, 1 on test failure, and 2 if there is a script
+error. It must be run from Mbed TLS root.
+"""
+
+import abc
+import argparse
+import fnmatch
+import glob
+import textwrap
+import os
+import sys
+import traceback
+import re
+import enum
+import shutil
+import subprocess
+import logging
+
+# Naming patterns to check against. These are defined outside the NameCheck
+# class for ease of modification.
+MACRO_PATTERN = r"^(MBEDTLS|PSA)_[0-9A-Z_]*[0-9A-Z]$"
+CONSTANTS_PATTERN = MACRO_PATTERN
+IDENTIFIER_PATTERN = r"^(mbedtls|psa)_[0-9a-z_]*[0-9a-z]$"
+
+class Match(): # pylint: disable=too-few-public-methods
+    """
+    A class representing a match, together with its found position.
+
+    Fields:
+    * filename: the file that the match was in.
+    * line: the full line containing the match.
+    * line_no: the line number.
+    * pos: a tuple of (start, end) positions on the line where the match is.
+    * name: the match itself.
+    """
+    def __init__(self, filename, line, line_no, pos, name):
+        # pylint: disable=too-many-arguments
+        self.filename = filename
+        self.line = line
+        self.line_no = line_no
+        self.pos = pos
+        self.name = name
+
+    def __str__(self):
+        """
+        Return a formatted code listing representation of the erroneous line.
+        """
+        gutter = format(self.line_no, "4d")
+        underline = self.pos[0] * " " + (self.pos[1] - self.pos[0]) * "^"
+
+        return (
+            " {0} |\n".format(" " * len(gutter)) +
+            " {0} | {1}".format(gutter, self.line) +
+            " {0} | {1}\n".format(" " * len(gutter), underline)
+        )
+
+class Problem(abc.ABC): # pylint: disable=too-few-public-methods
+    """
+    An abstract parent class representing a form of static analysis error.
+    It extends an Abstract Base Class, which means it is not instantiable, and
+    it also mandates certain abstract methods to be implemented in subclasses.
+    """
+    # Class variable to control the quietness of all problems
+    quiet = False
+    def __init__(self):
+        self.textwrapper = textwrap.TextWrapper()
+        self.textwrapper.width = 80
+        self.textwrapper.initial_indent = "    > "
+        self.textwrapper.subsequent_indent = "      "
+
+    def __str__(self):
+        """
+        Unified string representation method for all Problems.
+        """
+        if self.__class__.quiet:
+            return self.quiet_output()
+        return self.verbose_output()
+
+    @abc.abstractmethod
+    def quiet_output(self):
+        """
+        The output when --quiet is enabled.
+        """
+        pass
+
+    @abc.abstractmethod
+    def verbose_output(self):
+        """
+        The default output with explanation and code snippet if appropriate.
+        """
+        pass
+
+class SymbolNotInHeader(Problem): # pylint: disable=too-few-public-methods
+    """
+    A problem that occurs when an exported/available symbol in the object file
+    is not explicitly declared in header files. Created with
+    NameCheck.check_symbols_declared_in_header()
+
+    Fields:
+    * symbol_name: the name of the symbol.
+    """
+    def __init__(self, symbol_name):
+        self.symbol_name = symbol_name
+        Problem.__init__(self)
+
+    def quiet_output(self):
+        return "{0}".format(self.symbol_name)
+
+    def verbose_output(self):
+        return self.textwrapper.fill(
+            "'{0}' was found as an available symbol in the output of nm, "
+            "however it was not declared in any header files."
+            .format(self.symbol_name))
+
+class PatternMismatch(Problem): # pylint: disable=too-few-public-methods
+    """
+    A problem that occurs when something doesn't match the expected pattern.
+    Created with NameCheck.check_match_pattern()
+
+    Fields:
+    * pattern: the expected regex pattern
+    * match: the Match object in question
+    """
+    def __init__(self, pattern, match):
+        self.pattern = pattern
+        self.match = match
+        Problem.__init__(self)
+
+
+    def quiet_output(self):
+        return (
+            "{0}:{1}:{2}"
+            .format(self.match.filename, self.match.line_no, self.match.name)
+        )
+
+    def verbose_output(self):
+        return self.textwrapper.fill(
+            "{0}:{1}: '{2}' does not match the required pattern '{3}'."
+            .format(
+                self.match.filename,
+                self.match.line_no,
+                self.match.name,
+                self.pattern
+            )
+        ) + "\n" + str(self.match)
+
+class Typo(Problem): # pylint: disable=too-few-public-methods
+    """
+    A problem that occurs when a word using MBED doesn't appear to be defined as
+    constants nor enum values. Created with NameCheck.check_for_typos()
+
+    Fields:
+    * match: the Match object of the MBED name in question.
+    """
+    def __init__(self, match):
+        self.match = match
+        Problem.__init__(self)
+
+    def quiet_output(self):
+        return (
+            "{0}:{1}:{2}"
+            .format(self.match.filename, self.match.line_no, self.match.name)
+        )
+
+    def verbose_output(self):
+        return self.textwrapper.fill(
+            "{0}:{1}: '{2}' looks like a typo. It was not found in any "
+            "macros or any enums. If this is not a typo, put "
+            "//no-check-names after it."
+            .format(self.match.filename, self.match.line_no, self.match.name)
+        ) + "\n" + str(self.match)
+
+class CodeParser():
+    """
+    Class for retrieving files and parsing the code. This can be used
+    independently of the checks that NameChecker performs, for example for
+    list_internal_identifiers.py.
+    """
+    def __init__(self, log):
+        self.log = log
+        self.check_repo_path()
+
+        # Memo for storing "glob expression": set(filepaths)
+        self.files = {}
+
+        # Globally excluded filenames.
+        # Note that "*" can match directory separators in exclude lists.
+        self.excluded_files = ["*/bn_mul", "*/compat-1.3.h"]
+
+    @staticmethod
+    def check_repo_path():
+        """
+        Check that the current working directory is the project root, and throw
+        an exception if not.
+        """
+        if not all(os.path.isdir(d) for d in ["include", "library", "tests"]):
+            raise Exception("This script must be run from Mbed TLS root")
+
+    def comprehensive_parse(self):
+        """
+        Comprehensive ("default") function to call each parsing function and
+        retrieve various elements of the code, together with the source location.
+
+        Returns a dict of parsed item key to the corresponding List of Matches.
+        """
+        self.log.info("Parsing source code...")
+        self.log.debug(
+            "The following files are excluded from the search: {}"
+            .format(str(self.excluded_files))
+        )
+
+        all_macros = self.parse_macros([
+            "include/mbedtls/*.h",
+            "include/psa/*.h",
+            "library/*.h",
+            "tests/include/test/drivers/*.h",
+            "3rdparty/everest/include/everest/everest.h",
+            "3rdparty/everest/include/everest/x25519.h"
+        ])
+        enum_consts = self.parse_enum_consts([
+            "include/mbedtls/*.h",
+            "library/*.h",
+            "3rdparty/everest/include/everest/everest.h",
+            "3rdparty/everest/include/everest/x25519.h"
+        ])
+        identifiers = self.parse_identifiers([
+            "include/mbedtls/*.h",
+            "include/psa/*.h",
+            "library/*.h",
+            "3rdparty/everest/include/everest/everest.h",
+            "3rdparty/everest/include/everest/x25519.h"
+        ])
+        mbed_words = self.parse_mbed_words([
+            "include/mbedtls/*.h",
+            "include/psa/*.h",
+            "library/*.h",
+            "3rdparty/everest/include/everest/everest.h",
+            "3rdparty/everest/include/everest/x25519.h",
+            "library/*.c",
+            "3rdparty/everest/library/everest.c",
+            "3rdparty/everest/library/x25519.c"
+        ])
+        symbols = self.parse_symbols()
+
+        # Remove identifier macros like mbedtls_printf or mbedtls_calloc
+        identifiers_justname = [x.name for x in identifiers]
+        actual_macros = []
+        for macro in all_macros:
+            if macro.name not in identifiers_justname:
+                actual_macros.append(macro)
+
+        self.log.debug("Found:")
+        # Aligns the counts on the assumption that none exceeds 4 digits
+        self.log.debug("  {:4} Total Macros".format(len(all_macros)))
+        self.log.debug("  {:4} Non-identifier Macros".format(len(actual_macros)))
+        self.log.debug("  {:4} Enum Constants".format(len(enum_consts)))
+        self.log.debug("  {:4} Identifiers".format(len(identifiers)))
+        self.log.debug("  {:4} Exported Symbols".format(len(symbols)))
+        return {
+            "macros": actual_macros,
+            "enum_consts": enum_consts,
+            "identifiers": identifiers,
+            "symbols": symbols,
+            "mbed_words": mbed_words
+        }
+
+    def is_file_excluded(self, path, exclude_wildcards):
+        """Whether the given file path is excluded."""
+        # exclude_wildcards may be None. Also, consider the global exclusions.
+        exclude_wildcards = (exclude_wildcards or []) + self.excluded_files
+        for pattern in exclude_wildcards:
+            if fnmatch.fnmatch(path, pattern):
+                return True
+        return False
+
+    def get_files(self, include_wildcards, exclude_wildcards):
+        """
+        Get all files that match any of the UNIX-style wildcards. While the
+        check_names script is designed only for use on UNIX/macOS (due to nm),
+        this function alone would work fine on Windows even with forward slashes
+        in the wildcard.
+
+        Args:
+        * include_wildcards: a List of shell-style wildcards to match filepaths.
+        * exclude_wildcards: a List of shell-style wildcards to exclude.
+
+        Returns a List of relative filepaths.
+        """
+        accumulator = set()
+
+        for include_wildcard in include_wildcards:
+            accumulator = accumulator.union(glob.iglob(include_wildcard))
+
+        return list(path for path in accumulator
+                    if not self.is_file_excluded(path, exclude_wildcards))
+
+    def parse_macros(self, include, exclude=None):
+        """
+        Parse all macros defined by #define preprocessor directives.
+
+        Args:
+        * include: A List of glob expressions to look for files through.
+        * exclude: A List of glob expressions for excluding files.
+
+        Returns a List of Match objects for the found macros.
+        """
+        macro_regex = re.compile(r"# *define +(?P<macro>\w+)")
+        exclusions = (
+            "asm", "inline", "EMIT", "_CRT_SECURE_NO_DEPRECATE", "MULADDC_"
+        )
+
+        files = self.get_files(include, exclude)
+        self.log.debug("Looking for macros in {} files".format(len(files)))
+
+        macros = []
+        for header_file in files:
+            with open(header_file, "r", encoding="utf-8") as header:
+                for line_no, line in enumerate(header):
+                    for macro in macro_regex.finditer(line):
+                        if macro.group("macro").startswith(exclusions):
+                            continue
+
+                        macros.append(Match(
+                            header_file,
+                            line,
+                            line_no,
+                            macro.span("macro"),
+                            macro.group("macro")))
+
+        return macros
+
+    def parse_mbed_words(self, include, exclude=None):
+        """
+        Parse all words in the file that begin with MBED, in and out of macros,
+        comments, anything.
+
+        Args:
+        * include: A List of glob expressions to look for files through.
+        * exclude: A List of glob expressions for excluding files.
+
+        Returns a List of Match objects for words beginning with MBED.
+        """
+        # Typos of TLS are common, hence the broader check below than MBEDTLS.
+        mbed_regex = re.compile(r"\bMBED.+?_[A-Z0-9_]*")
+        exclusions = re.compile(r"// *no-check-names|#error")
+
+        files = self.get_files(include, exclude)
+        self.log.debug("Looking for MBED words in {} files".format(len(files)))
+
+        mbed_words = []
+        for filename in files:
+            with open(filename, "r", encoding="utf-8") as fp:
+                for line_no, line in enumerate(fp):
+                    if exclusions.search(line):
+                        continue
+
+                    for name in mbed_regex.finditer(line):
+                        mbed_words.append(Match(
+                            filename,
+                            line,
+                            line_no,
+                            name.span(0),
+                            name.group(0)))
+
+        return mbed_words
+
+    def parse_enum_consts(self, include, exclude=None):
+        """
+        Parse all enum value constants that are declared.
+
+        Args:
+        * include: A List of glob expressions to look for files through.
+        * exclude: A List of glob expressions for excluding files.
+
+        Returns a List of Match objects for the findings.
+        """
+        files = self.get_files(include, exclude)
+        self.log.debug("Looking for enum consts in {} files".format(len(files)))
+
+        # Emulate a finite state machine to parse enum declarations.
+        # OUTSIDE_KEYWORD = outside the enum keyword
+        # IN_BRACES = inside enum opening braces
+        # IN_BETWEEN = between enum keyword and opening braces
+        states = enum.Enum("FSM", ["OUTSIDE_KEYWORD", "IN_BRACES", "IN_BETWEEN"])
+        enum_consts = []
+        for header_file in files:
+            state = states.OUTSIDE_KEYWORD
+            with open(header_file, "r", encoding="utf-8") as header:
+                for line_no, line in enumerate(header):
+                    # Match typedefs and brackets only when they are at the
+                    # beginning of the line -- if they are indented, they might
+                    # be sub-structures within structs, etc.
+                    if (state == states.OUTSIDE_KEYWORD and
+                            re.search(r"^(typedef +)?enum +{", line)):
+                        state = states.IN_BRACES
+                    elif (state == states.OUTSIDE_KEYWORD and
+                          re.search(r"^(typedef +)?enum", line)):
+                        state = states.IN_BETWEEN
+                    elif (state == states.IN_BETWEEN and
+                          re.search(r"^{", line)):
+                        state = states.IN_BRACES
+                    elif (state == states.IN_BRACES and
+                          re.search(r"^}", line)):
+                        state = states.OUTSIDE_KEYWORD
+                    elif (state == states.IN_BRACES and
+                          not re.search(r"^ *#", line)):
+                        enum_const = re.search(r"^ *(?P<enum_const>\w+)", line)
+                        if not enum_const:
+                            continue
+
+                        enum_consts.append(Match(
+                            header_file,
+                            line,
+                            line_no,
+                            enum_const.span("enum_const"),
+                            enum_const.group("enum_const")))
+
+        return enum_consts
+
+    IGNORED_CHUNK_REGEX = re.compile('|'.join([
+        r'/\*.*?\*/', # block comment entirely on one line
+        r'//.*', # line comment
+        r'(?P<string>")(?:[^\\\"]|\\.)*"', # string literal
+    ]))
+
+    def strip_comments_and_literals(self, line, in_block_comment):
+        """Strip comments and string literals from line.
+
+        Continuation lines are not supported.
+
+        If in_block_comment is true, assume that the line starts inside a
+        block comment.
+
+        Return updated values of (line, in_block_comment) where:
+        * Comments in line have been replaced by a space (or nothing at the
+          start or end of the line).
+        * String contents have been removed.
+        * in_block_comment indicates whether the line ends inside a block
+          comment that continues on the next line.
+        """
+
+        # Terminate current multiline comment?
+        if in_block_comment:
+            m = re.search(r"\*/", line)
+            if m:
+                in_block_comment = False
+                line = line[m.end(0):]
+            else:
+                return '', True
+
+        # Remove full comments and string literals.
+        # Do it all together to handle cases like "/*" correctly.
+        # Note that continuation lines are not supported.
+        line = re.sub(self.IGNORED_CHUNK_REGEX,
+                      lambda s: '""' if s.group('string') else ' ',
+                      line)
+
+        # Start an unfinished comment?
+        # (If `/*` was part of a complete comment, it's already been removed.)
+        m = re.search(r"/\*", line)
+        if m:
+            in_block_comment = True
+            line = line[:m.start(0)]
+
+        return line, in_block_comment
+
+    IDENTIFIER_REGEX = re.compile('|'.join([
+        # Match " something(a" or " *something(a". Functions.
+        # Assumptions:
+        # - function definition from return type to one of its arguments is
+        #   all on one line
+        # - function definition line only contains alphanumeric, asterisk,
+        #   underscore, and open bracket
+        r".* \**(\w+) *\( *\w",
+        # Match "(*something)(".
+        r".*\( *\* *(\w+) *\) *\(",
+        # Match names of named data structures.
+        r"(?:typedef +)?(?:struct|union|enum) +(\w+)(?: *{)?$",
+        # Match names of typedef instances, after closing bracket.
+        r"}? *(\w+)[;[].*",
+    ]))
+    # The regex below is indented for clarity.
+    EXCLUSION_LINES = re.compile("|".join([
+        r"extern +\"C\"",
+        r"(typedef +)?(struct|union|enum)( *{)?$",
+        r"} *;?$",
+        r"$",
+        r"//",
+        r"#",
+    ]))
+
+    def parse_identifiers_in_file(self, header_file, identifiers):
+        """
+        Parse all lines of a header where a function/enum/struct/union/typedef
+        identifier is declared, based on some regex and heuristics. Highly
+        dependent on formatting style.
+
+        Append found matches to the list ``identifiers``.
+        """
+
+        with open(header_file, "r", encoding="utf-8") as header:
+            in_block_comment = False
+            # The previous line variable is used for concatenating lines
+            # when identifiers are formatted and spread across multiple
+            # lines.
+            previous_line = ""
+
+            for line_no, line in enumerate(header):
+                line, in_block_comment = \
+                    self.strip_comments_and_literals(line, in_block_comment)
+
+                if self.EXCLUSION_LINES.match(line):
+                    previous_line = ""
+                    continue
+
+                # If the line contains only space-separated alphanumeric
+                # characters (or underscore, asterisk, or open parenthesis),
+                # and nothing else, high chance it's a declaration that
+                # continues on the next line
+                if re.search(r"^([\w\*\(]+\s+)+$", line):
+                    previous_line += line
+                    continue
+
+                # If previous line seemed to start an unfinished declaration
+                # (as above), concat and treat them as one.
+                if previous_line:
+                    line = previous_line.strip() + " " + line.strip() + "\n"
+                    previous_line = ""
+
+                # Skip parsing if line has a space in front = heuristic to
+                # skip function argument lines (highly subject to formatting
+                # changes)
+                if line[0] == " ":
+                    continue
+
+                identifier = self.IDENTIFIER_REGEX.search(line)
+
+                if not identifier:
+                    continue
+
+                # Find the group that matched, and append it
+                for group in identifier.groups():
+                    if not group:
+                        continue
+
+                    identifiers.append(Match(
+                        header_file,
+                        line,
+                        line_no,
+                        identifier.span(),
+                        group))
+
+    def parse_identifiers(self, include, exclude=None):
+        """
+        Parse all lines of a header where a function/enum/struct/union/typedef
+        identifier is declared, based on some regex and heuristics. Highly
+        dependent on formatting style.
+
+        Args:
+        * include: A List of glob expressions to look for files through.
+        * exclude: A List of glob expressions for excluding files.
+
+        Returns a List of Match objects with identifiers.
+        """
+
+        files = self.get_files(include, exclude)
+        self.log.debug("Looking for identifiers in {} files".format(len(files)))
+
+        identifiers = []
+        for header_file in files:
+            self.parse_identifiers_in_file(header_file, identifiers)
+
+        return identifiers
+
+    def parse_symbols(self):
+        """
+        Compile the Mbed TLS libraries, and parse the TLS, Crypto, and x509
+        object files using nm to retrieve the list of referenced symbols.
+        Exceptions thrown here are rethrown because they would be critical
+        errors that void several tests, and thus needs to halt the program. This
+        is explicitly done for clarity.
+
+        Returns a List of unique symbols defined and used in the libraries.
+        """
+        self.log.info("Compiling...")
+        symbols = []
+
+        # Back up the config and atomically compile with the full configratuion.
+        shutil.copy(
+            "include/mbedtls/config.h",
+            "include/mbedtls/config.h.bak"
+        )
+        try:
+            # Use check=True in all subprocess calls so that failures are raised
+            # as exceptions and logged.
+            subprocess.run(
+                ["python3", "scripts/config.py", "full"],
+                universal_newlines=True,
+                check=True
+            )
+            my_environment = os.environ.copy()
+            my_environment["CFLAGS"] = "-fno-asynchronous-unwind-tables"
+            # Run make clean separately to lib to prevent unwanted behavior when
+            # make is invoked with parallelism.
+            subprocess.run(
+                ["make", "clean"],
+                universal_newlines=True,
+                check=True
+            )
+            subprocess.run(
+                ["make", "lib"],
+                env=my_environment,
+                universal_newlines=True,
+                stdout=subprocess.PIPE,
+                stderr=subprocess.STDOUT,
+                check=True
+            )
+
+            # Perform object file analysis using nm
+            symbols = self.parse_symbols_from_nm([
+                "library/libmbedcrypto.a",
+                "library/libmbedtls.a",
+                "library/libmbedx509.a"
+            ])
+
+            subprocess.run(
+                ["make", "clean"],
+                universal_newlines=True,
+                check=True
+            )
+        except subprocess.CalledProcessError as error:
+            self.log.debug(error.output)
+            raise error
+        finally:
+            # Put back the original config regardless of there being errors.
+            # Works also for keyboard interrupts.
+            shutil.move(
+                "include/mbedtls/config.h.bak",
+                "include/mbedtls/config.h"
+            )
+
+        return symbols
+
+    def parse_symbols_from_nm(self, object_files):
+        """
+        Run nm to retrieve the list of referenced symbols in each object file.
+        Does not return the position data since it is of no use.
+
+        Args:
+        * object_files: a List of compiled object filepaths to search through.
+
+        Returns a List of unique symbols defined and used in any of the object
+        files.
+        """
+        nm_undefined_regex = re.compile(r"^\S+: +U |^$|^\S+:$")
+        nm_valid_regex = re.compile(r"^\S+( [0-9A-Fa-f]+)* . _*(?P<symbol>\w+)")
+        exclusions = ("FStar", "Hacl")
+
+        symbols = []
+
+        # Gather all outputs of nm
+        nm_output = ""
+        for lib in object_files:
+            nm_output += subprocess.run(
+                ["nm", "-og", lib],
+                universal_newlines=True,
+                stdout=subprocess.PIPE,
+                stderr=subprocess.STDOUT,
+                check=True
+            ).stdout
+
+        for line in nm_output.splitlines():
+            if not nm_undefined_regex.search(line):
+                symbol = nm_valid_regex.search(line)
+                if (symbol and not symbol.group("symbol").startswith(exclusions)):
+                    symbols.append(symbol.group("symbol"))
+                else:
+                    self.log.error(line)
+
+        return symbols
+
+class NameChecker():
+    """
+    Representation of the core name checking operation performed by this script.
+    """
+    def __init__(self, parse_result, log):
+        self.parse_result = parse_result
+        self.log = log
+
+    def perform_checks(self, quiet=False):
+        """
+        A comprehensive checker that performs each check in order, and outputs
+        a final verdict.
+
+        Args:
+        * quiet: whether to hide detailed problem explanation.
+        """
+        self.log.info("=============")
+        Problem.quiet = quiet
+        problems = 0
+        problems += self.check_symbols_declared_in_header()
+
+        pattern_checks = [
+            ("macros", MACRO_PATTERN),
+            ("enum_consts", CONSTANTS_PATTERN),
+            ("identifiers", IDENTIFIER_PATTERN)
+        ]
+        for group, check_pattern in pattern_checks:
+            problems += self.check_match_pattern(group, check_pattern)
+
+        problems += self.check_for_typos()
+
+        self.log.info("=============")
+        if problems > 0:
+            self.log.info("FAIL: {0} problem(s) to fix".format(str(problems)))
+            if quiet:
+                self.log.info("Remove --quiet to see explanations.")
+            else:
+                self.log.info("Use --quiet for minimal output.")
+            return 1
+        else:
+            self.log.info("PASS")
+            return 0
+
+    def check_symbols_declared_in_header(self):
+        """
+        Perform a check that all detected symbols in the library object files
+        are properly declared in headers.
+        Assumes parse_names_in_source() was called before this.
+
+        Returns the number of problems that need fixing.
+        """
+        problems = []
+
+        for symbol in self.parse_result["symbols"]:
+            found_symbol_declared = False
+            for identifier_match in self.parse_result["identifiers"]:
+                if symbol == identifier_match.name:
+                    found_symbol_declared = True
+                    break
+
+            if not found_symbol_declared:
+                problems.append(SymbolNotInHeader(symbol))
+
+        self.output_check_result("All symbols in header", problems)
+        return len(problems)
+
+    def check_match_pattern(self, group_to_check, check_pattern):
+        """
+        Perform a check that all items of a group conform to a regex pattern.
+        Assumes parse_names_in_source() was called before this.
+
+        Args:
+        * group_to_check: string key to index into self.parse_result.
+        * check_pattern: the regex to check against.
+
+        Returns the number of problems that need fixing.
+        """
+        problems = []
+
+        for item_match in self.parse_result[group_to_check]:
+            if not re.search(check_pattern, item_match.name):
+                problems.append(PatternMismatch(check_pattern, item_match))
+            # Double underscore should not be used for names
+            if re.search(r".*__.*", item_match.name):
+                problems.append(
+                    PatternMismatch("no double underscore allowed", item_match))
+
+        self.output_check_result(
+            "Naming patterns of {}".format(group_to_check),
+            problems)
+        return len(problems)
+
+    def check_for_typos(self):
+        """
+        Perform a check that all words in the soure code beginning with MBED are
+        either defined as macros, or as enum constants.
+        Assumes parse_names_in_source() was called before this.
+
+        Returns the number of problems that need fixing.
+        """
+        problems = []
+
+        # Set comprehension, equivalent to a list comprehension wrapped by set()
+        all_caps_names = {
+            match.name
+            for match
+            in self.parse_result["macros"] + self.parse_result["enum_consts"]}
+        typo_exclusion = re.compile(r"XXX|__|_$|^MBEDTLS_.*CONFIG_FILE$|"
+                                    r"MBEDTLS_TEST_LIBTESTDRIVER*")
+
+        for name_match in self.parse_result["mbed_words"]:
+            found = name_match.name in all_caps_names
+
+            # Since MBEDTLS_PSA_ACCEL_XXX defines are defined by the
+            # PSA driver, they will not exist as macros. However, they
+            # should still be checked for typos using the equivalent
+            # BUILTINs that exist.
+            if "MBEDTLS_PSA_ACCEL_" in name_match.name:
+                found = name_match.name.replace(
+                    "MBEDTLS_PSA_ACCEL_",
+                    "MBEDTLS_PSA_BUILTIN_") in all_caps_names
+
+            if not found and not typo_exclusion.search(name_match.name):
+                problems.append(Typo(name_match))
+
+        self.output_check_result("Likely typos", problems)
+        return len(problems)
+
+    def output_check_result(self, name, problems):
+        """
+        Write out the PASS/FAIL status of a performed check depending on whether
+        there were problems.
+
+        Args:
+        * name: the name of the test
+        * problems: a List of encountered Problems
+        """
+        if problems:
+            self.log.info("{}: FAIL\n".format(name))
+            for problem in problems:
+                self.log.warning(str(problem))
+        else:
+            self.log.info("{}: PASS".format(name))
+
+def main():
+    """
+    Perform argument parsing, and create an instance of CodeParser and
+    NameChecker to begin the core operation.
+    """
+    parser = argparse.ArgumentParser(
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+        description=(
+            "This script confirms that the naming of all symbols and identifiers "
+            "in Mbed TLS are consistent with the house style and are also "
+            "self-consistent.\n\n"
+            "Expected to be run from the MbedTLS root directory.")
+    )
+    parser.add_argument(
+        "-v", "--verbose",
+        action="store_true",
+        help="show parse results"
+    )
+    parser.add_argument(
+        "-q", "--quiet",
+        action="store_true",
+        help="hide unnecessary text, explanations, and highlighs"
+    )
+
+    args = parser.parse_args()
+
+    # Configure the global logger, which is then passed to the classes below
+    log = logging.getLogger()
+    log.setLevel(logging.DEBUG if args.verbose else logging.INFO)
+    log.addHandler(logging.StreamHandler())
+
+    try:
+        code_parser = CodeParser(log)
+        parse_result = code_parser.comprehensive_parse()
+    except Exception: # pylint: disable=broad-except
+        traceback.print_exc()
+        sys.exit(2)
+
+    name_checker = NameChecker(parse_result, log)
+    return_code = name_checker.perform_checks(quiet=args.quiet)
+
+    sys.exit(return_code)
+
+if __name__ == "__main__":
+    main()
diff --git a/third_party/mbedtls/repo/tests/scripts/generate_psa_tests.py b/third_party/mbedtls/repo/tests/scripts/generate_psa_tests.py
new file mode 100755
index 0000000..af25feb
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/scripts/generate_psa_tests.py
@@ -0,0 +1,767 @@
+#!/usr/bin/env python3
+"""Generate test data for PSA cryptographic mechanisms.
+
+With no arguments, generate all test data. With non-option arguments,
+generate only the specified files.
+"""
+
+# 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.
+
+import argparse
+import os
+import re
+import sys
+from typing import Callable, Dict, FrozenSet, Iterable, Iterator, List, Optional, TypeVar
+
+import scripts_path # pylint: disable=unused-import
+from mbedtls_dev import crypto_knowledge
+from mbedtls_dev import macro_collector
+from mbedtls_dev import psa_storage
+from mbedtls_dev import test_case
+
+T = TypeVar('T') #pylint: disable=invalid-name
+
+
+def psa_want_symbol(name: str) -> str:
+    """Return the PSA_WANT_xxx symbol associated with a PSA crypto feature."""
+    if name.startswith('PSA_'):
+        return name[:4] + 'WANT_' + name[4:]
+    else:
+        raise ValueError('Unable to determine the PSA_WANT_ symbol for ' + name)
+
+def finish_family_dependency(dep: str, bits: int) -> str:
+    """Finish dep if it's a family dependency symbol prefix.
+
+    A family dependency symbol prefix is a PSA_WANT_ symbol that needs to be
+    qualified by the key size. If dep is such a symbol, finish it by adjusting
+    the prefix and appending the key size. Other symbols are left unchanged.
+    """
+    return re.sub(r'_FAMILY_(.*)', r'_\1_' + str(bits), dep)
+
+def finish_family_dependencies(dependencies: List[str], bits: int) -> List[str]:
+    """Finish any family dependency symbol prefixes.
+
+    Apply `finish_family_dependency` to each element of `dependencies`.
+    """
+    return [finish_family_dependency(dep, bits) for dep in dependencies]
+
+SYMBOLS_WITHOUT_DEPENDENCY = frozenset([
+    'PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG', # modifier, only in policies
+    'PSA_ALG_AEAD_WITH_SHORTENED_TAG', # modifier
+    'PSA_ALG_ANY_HASH', # only in policies
+    'PSA_ALG_AT_LEAST_THIS_LENGTH_MAC', # modifier, only in policies
+    'PSA_ALG_KEY_AGREEMENT', # chaining
+    'PSA_ALG_TRUNCATED_MAC', # modifier
+])
+def automatic_dependencies(*expressions: str) -> List[str]:
+    """Infer dependencies of a test case by looking for PSA_xxx symbols.
+
+    The arguments are strings which should be C expressions. Do not use
+    string literals or comments as this function is not smart enough to
+    skip them.
+    """
+    used = set()
+    for expr in expressions:
+        used.update(re.findall(r'PSA_(?:ALG|ECC_FAMILY|KEY_TYPE)_\w+', expr))
+    used.difference_update(SYMBOLS_WITHOUT_DEPENDENCY)
+    return sorted(psa_want_symbol(name) for name in used)
+
+# A temporary hack: at the time of writing, not all dependency symbols
+# are implemented yet. Skip test cases for which the dependency symbols are
+# not available. Once all dependency symbols are available, this hack must
+# be removed so that a bug in the dependency symbols proprely leads to a test
+# failure.
+def read_implemented_dependencies(filename: str) -> FrozenSet[str]:
+    return frozenset(symbol
+                     for line in open(filename)
+                     for symbol in re.findall(r'\bPSA_WANT_\w+\b', line))
+_implemented_dependencies = None #type: Optional[FrozenSet[str]] #pylint: disable=invalid-name
+def hack_dependencies_not_implemented(dependencies: List[str]) -> None:
+    global _implemented_dependencies #pylint: disable=global-statement,invalid-name
+    if _implemented_dependencies is None:
+        _implemented_dependencies = \
+            read_implemented_dependencies('include/psa/crypto_config.h')
+    if not all((dep.lstrip('!') in _implemented_dependencies or 'PSA_WANT' not in dep)
+               for dep in dependencies):
+        dependencies.append('DEPENDENCY_NOT_IMPLEMENTED_YET')
+
+
+class Information:
+    """Gather information about PSA constructors."""
+
+    def __init__(self) -> None:
+        self.constructors = self.read_psa_interface()
+
+    @staticmethod
+    def remove_unwanted_macros(
+            constructors: macro_collector.PSAMacroEnumerator
+    ) -> None:
+        # Mbed TLS doesn't support finite-field DH yet and will not support
+        # finite-field DSA. Don't attempt to generate any related test case.
+        constructors.key_types.discard('PSA_KEY_TYPE_DH_KEY_PAIR')
+        constructors.key_types.discard('PSA_KEY_TYPE_DH_PUBLIC_KEY')
+        constructors.key_types.discard('PSA_KEY_TYPE_DSA_KEY_PAIR')
+        constructors.key_types.discard('PSA_KEY_TYPE_DSA_PUBLIC_KEY')
+
+    def read_psa_interface(self) -> macro_collector.PSAMacroEnumerator:
+        """Return the list of known key types, algorithms, etc."""
+        constructors = macro_collector.InputsForTest()
+        header_file_names = ['include/psa/crypto_values.h',
+                             'include/psa/crypto_extra.h']
+        test_suites = ['tests/suites/test_suite_psa_crypto_metadata.data']
+        for header_file_name in header_file_names:
+            constructors.parse_header(header_file_name)
+        for test_cases in test_suites:
+            constructors.parse_test_cases(test_cases)
+        self.remove_unwanted_macros(constructors)
+        constructors.gather_arguments()
+        return constructors
+
+
+def test_case_for_key_type_not_supported(
+        verb: str, key_type: str, bits: int,
+        dependencies: List[str],
+        *args: str,
+        param_descr: str = ''
+) -> test_case.TestCase:
+    """Return one test case exercising a key creation method
+    for an unsupported key type or size.
+    """
+    hack_dependencies_not_implemented(dependencies)
+    tc = test_case.TestCase()
+    short_key_type = re.sub(r'PSA_(KEY_TYPE|ECC_FAMILY)_', r'', key_type)
+    adverb = 'not' if dependencies else 'never'
+    if param_descr:
+        adverb = param_descr + ' ' + adverb
+    tc.set_description('PSA {} {} {}-bit {} supported'
+                       .format(verb, short_key_type, bits, adverb))
+    tc.set_dependencies(dependencies)
+    tc.set_function(verb + '_not_supported')
+    tc.set_arguments([key_type] + list(args))
+    return tc
+
+class NotSupported:
+    """Generate test cases for when something is not supported."""
+
+    def __init__(self, info: Information) -> None:
+        self.constructors = info.constructors
+
+    ALWAYS_SUPPORTED = frozenset([
+        'PSA_KEY_TYPE_DERIVE',
+        'PSA_KEY_TYPE_RAW_DATA',
+    ])
+    def test_cases_for_key_type_not_supported(
+            self,
+            kt: crypto_knowledge.KeyType,
+            param: Optional[int] = None,
+            param_descr: str = '',
+    ) -> Iterator[test_case.TestCase]:
+        """Return test cases exercising key creation when the given type is unsupported.
+
+        If param is present and not None, emit test cases conditioned on this
+        parameter not being supported. If it is absent or None, emit test cases
+        conditioned on the base type not being supported.
+        """
+        if kt.name in self.ALWAYS_SUPPORTED:
+            # Don't generate test cases for key types that are always supported.
+            # They would be skipped in all configurations, which is noise.
+            return
+        import_dependencies = [('!' if param is None else '') +
+                               psa_want_symbol(kt.name)]
+        if kt.params is not None:
+            import_dependencies += [('!' if param == i else '') +
+                                    psa_want_symbol(sym)
+                                    for i, sym in enumerate(kt.params)]
+        if kt.name.endswith('_PUBLIC_KEY'):
+            generate_dependencies = []
+        else:
+            generate_dependencies = import_dependencies
+        for bits in kt.sizes_to_test():
+            yield test_case_for_key_type_not_supported(
+                'import', kt.expression, bits,
+                finish_family_dependencies(import_dependencies, bits),
+                test_case.hex_string(kt.key_material(bits)),
+                param_descr=param_descr,
+            )
+            if not generate_dependencies and param is not None:
+                # If generation is impossible for this key type, rather than
+                # supported or not depending on implementation capabilities,
+                # only generate the test case once.
+                continue
+                # For public key we expect that key generation fails with
+                # INVALID_ARGUMENT. It is handled by KeyGenerate class.
+            if not kt.name.endswith('_PUBLIC_KEY'):
+                yield test_case_for_key_type_not_supported(
+                    'generate', kt.expression, bits,
+                    finish_family_dependencies(generate_dependencies, bits),
+                    str(bits),
+                    param_descr=param_descr,
+                )
+            # To be added: derive
+
+    ECC_KEY_TYPES = ('PSA_KEY_TYPE_ECC_KEY_PAIR',
+                     'PSA_KEY_TYPE_ECC_PUBLIC_KEY')
+
+    def test_cases_for_not_supported(self) -> Iterator[test_case.TestCase]:
+        """Generate test cases that exercise the creation of keys of unsupported types."""
+        for key_type in sorted(self.constructors.key_types):
+            if key_type in self.ECC_KEY_TYPES:
+                continue
+            kt = crypto_knowledge.KeyType(key_type)
+            yield from self.test_cases_for_key_type_not_supported(kt)
+        for curve_family in sorted(self.constructors.ecc_curves):
+            for constr in self.ECC_KEY_TYPES:
+                kt = crypto_knowledge.KeyType(constr, [curve_family])
+                yield from self.test_cases_for_key_type_not_supported(
+                    kt, param_descr='type')
+                yield from self.test_cases_for_key_type_not_supported(
+                    kt, 0, param_descr='curve')
+
+def test_case_for_key_generation(
+        key_type: str, bits: int,
+        dependencies: List[str],
+        *args: str,
+        result: str = ''
+) -> test_case.TestCase:
+    """Return one test case exercising a key generation.
+    """
+    hack_dependencies_not_implemented(dependencies)
+    tc = test_case.TestCase()
+    short_key_type = re.sub(r'PSA_(KEY_TYPE|ECC_FAMILY)_', r'', key_type)
+    tc.set_description('PSA {} {}-bit'
+                       .format(short_key_type, bits))
+    tc.set_dependencies(dependencies)
+    tc.set_function('generate_key')
+    tc.set_arguments([key_type] + list(args) + [result])
+
+    return tc
+
+class KeyGenerate:
+    """Generate positive and negative (invalid argument) test cases for key generation."""
+
+    def __init__(self, info: Information) -> None:
+        self.constructors = info.constructors
+
+    ECC_KEY_TYPES = ('PSA_KEY_TYPE_ECC_KEY_PAIR',
+                     'PSA_KEY_TYPE_ECC_PUBLIC_KEY')
+
+    @staticmethod
+    def test_cases_for_key_type_key_generation(
+            kt: crypto_knowledge.KeyType
+    ) -> Iterator[test_case.TestCase]:
+        """Return test cases exercising key generation.
+
+        All key types can be generated except for public keys. For public key
+        PSA_ERROR_INVALID_ARGUMENT status is expected.
+        """
+        result = 'PSA_SUCCESS'
+
+        import_dependencies = [psa_want_symbol(kt.name)]
+        if kt.params is not None:
+            import_dependencies += [psa_want_symbol(sym)
+                                    for i, sym in enumerate(kt.params)]
+        if kt.name.endswith('_PUBLIC_KEY'):
+            # The library checks whether the key type is a public key generically,
+            # before it reaches a point where it needs support for the specific key
+            # type, so it returns INVALID_ARGUMENT for unsupported public key types.
+            generate_dependencies = []
+            result = 'PSA_ERROR_INVALID_ARGUMENT'
+        else:
+            generate_dependencies = import_dependencies
+            if kt.name == 'PSA_KEY_TYPE_RSA_KEY_PAIR':
+                generate_dependencies.append("MBEDTLS_GENPRIME")
+        for bits in kt.sizes_to_test():
+            yield test_case_for_key_generation(
+                kt.expression, bits,
+                finish_family_dependencies(generate_dependencies, bits),
+                str(bits),
+                result
+            )
+
+    def test_cases_for_key_generation(self) -> Iterator[test_case.TestCase]:
+        """Generate test cases that exercise the generation of keys."""
+        for key_type in sorted(self.constructors.key_types):
+            if key_type in self.ECC_KEY_TYPES:
+                continue
+            kt = crypto_knowledge.KeyType(key_type)
+            yield from self.test_cases_for_key_type_key_generation(kt)
+        for curve_family in sorted(self.constructors.ecc_curves):
+            for constr in self.ECC_KEY_TYPES:
+                kt = crypto_knowledge.KeyType(constr, [curve_family])
+                yield from self.test_cases_for_key_type_key_generation(kt)
+
+class StorageKey(psa_storage.Key):
+    """Representation of a key for storage format testing."""
+
+    IMPLICIT_USAGE_FLAGS = {
+        'PSA_KEY_USAGE_SIGN_HASH': 'PSA_KEY_USAGE_SIGN_MESSAGE',
+        'PSA_KEY_USAGE_VERIFY_HASH': 'PSA_KEY_USAGE_VERIFY_MESSAGE'
+    } #type: Dict[str, str]
+    """Mapping of usage flags to the flags that they imply."""
+
+    def __init__(
+            self,
+            usage: str,
+            without_implicit_usage: Optional[bool] = False,
+            **kwargs
+    ) -> None:
+        """Prepare to generate a key.
+
+        * `usage`                 : The usage flags used for the key.
+        * `without_implicit_usage`: Flag to defide to apply the usage extension
+        """
+        super().__init__(usage=usage, **kwargs)
+
+        if not without_implicit_usage:
+            for flag, implicit in self.IMPLICIT_USAGE_FLAGS.items():
+                if self.usage.value() & psa_storage.Expr(flag).value() and \
+                   self.usage.value() & psa_storage.Expr(implicit).value() == 0:
+                    self.usage = psa_storage.Expr(self.usage.string + ' | ' + implicit)
+
+class StorageTestData(StorageKey):
+    """Representation of test case data for storage format testing."""
+
+    def __init__(
+            self,
+            description: str,
+            expected_usage: Optional[str] = None,
+            **kwargs
+    ) -> None:
+        """Prepare to generate test data
+
+        * `description`   : used for the the test case names
+        * `expected_usage`: the usage flags generated as the expected usage flags
+                            in the test cases. CAn differ from the usage flags
+                            stored in the keys because of the usage flags extension.
+        """
+        super().__init__(**kwargs)
+        self.description = description #type: str
+        self.expected_usage = expected_usage if expected_usage else self.usage.string #type: str
+
+class StorageFormat:
+    """Storage format stability test cases."""
+
+    def __init__(self, info: Information, version: int, forward: bool) -> None:
+        """Prepare to generate test cases for storage format stability.
+
+        * `info`: information about the API. See the `Information` class.
+        * `version`: the storage format version to generate test cases for.
+        * `forward`: if true, generate forward compatibility test cases which
+          save a key and check that its representation is as intended. Otherwise
+          generate backward compatibility test cases which inject a key
+          representation and check that it can be read and used.
+        """
+        self.constructors = info.constructors #type: macro_collector.PSAMacroEnumerator
+        self.version = version #type: int
+        self.forward = forward #type: bool
+
+    def make_test_case(self, key: StorageTestData) -> test_case.TestCase:
+        """Construct a storage format test case for the given key.
+
+        If ``forward`` is true, generate a forward compatibility test case:
+        create a key and validate that it has the expected representation.
+        Otherwise generate a backward compatibility test case: inject the
+        key representation into storage and validate that it can be read
+        correctly.
+        """
+        verb = 'save' if self.forward else 'read'
+        tc = test_case.TestCase()
+        tc.set_description('PSA storage {}: {}'.format(verb, key.description))
+        dependencies = automatic_dependencies(
+            key.lifetime.string, key.type.string,
+            key.expected_usage, key.alg.string, key.alg2.string,
+        )
+        dependencies = finish_family_dependencies(dependencies, key.bits)
+        tc.set_dependencies(dependencies)
+        tc.set_function('key_storage_' + verb)
+        if self.forward:
+            extra_arguments = []
+        else:
+            flags = []
+            # Some test keys have the RAW_DATA type and attributes that don't
+            # necessarily make sense. We do this to validate numerical
+            # encodings of the attributes.
+            # Raw data keys have no useful exercise anyway so there is no
+            # loss of test coverage.
+            if key.type.string != 'PSA_KEY_TYPE_RAW_DATA':
+                flags.append('TEST_FLAG_EXERCISE')
+            if 'READ_ONLY' in key.lifetime.string:
+                flags.append('TEST_FLAG_READ_ONLY')
+            extra_arguments = [' | '.join(flags) if flags else '0']
+        tc.set_arguments([key.lifetime.string,
+                          key.type.string, str(key.bits),
+                          key.expected_usage, key.alg.string, key.alg2.string,
+                          '"' + key.material.hex() + '"',
+                          '"' + key.hex() + '"',
+                          *extra_arguments])
+        return tc
+
+    def key_for_lifetime(
+            self,
+            lifetime: str,
+    ) -> StorageTestData:
+        """Construct a test key for the given lifetime."""
+        short = lifetime
+        short = re.sub(r'PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION',
+                       r'', short)
+        short = re.sub(r'PSA_KEY_[A-Z]+_', r'', short)
+        description = 'lifetime: ' + short
+        key = StorageTestData(version=self.version,
+                              id=1, lifetime=lifetime,
+                              type='PSA_KEY_TYPE_RAW_DATA', bits=8,
+                              usage='PSA_KEY_USAGE_EXPORT', alg=0, alg2=0,
+                              material=b'L',
+                              description=description)
+        return key
+
+    def all_keys_for_lifetimes(self) -> Iterator[StorageTestData]:
+        """Generate test keys covering lifetimes."""
+        lifetimes = sorted(self.constructors.lifetimes)
+        expressions = self.constructors.generate_expressions(lifetimes)
+        for lifetime in expressions:
+            # Don't attempt to create or load a volatile key in storage
+            if 'VOLATILE' in lifetime:
+                continue
+            # Don't attempt to create a read-only key in storage,
+            # but do attempt to load one.
+            if 'READ_ONLY' in lifetime and self.forward:
+                continue
+            yield self.key_for_lifetime(lifetime)
+
+    def keys_for_usage_flags(
+            self,
+            usage_flags: List[str],
+            short: Optional[str] = None,
+            test_implicit_usage: Optional[bool] = False
+    ) -> Iterator[StorageTestData]:
+        """Construct a test key for the given key usage."""
+        usage = ' | '.join(usage_flags) if usage_flags else '0'
+        if short is None:
+            short = re.sub(r'\bPSA_KEY_USAGE_', r'', usage)
+        extra_desc = ' with implication' if test_implicit_usage else ''
+        description = 'usage' + extra_desc + ': ' + short
+        key1 = StorageTestData(version=self.version,
+                               id=1, lifetime=0x00000001,
+                               type='PSA_KEY_TYPE_RAW_DATA', bits=8,
+                               expected_usage=usage,
+                               usage=usage, alg=0, alg2=0,
+                               material=b'K',
+                               description=description)
+        yield key1
+
+        if test_implicit_usage:
+            description = 'usage without implication' + ': ' + short
+            key2 = StorageTestData(version=self.version,
+                                   id=1, lifetime=0x00000001,
+                                   type='PSA_KEY_TYPE_RAW_DATA', bits=8,
+                                   without_implicit_usage=True,
+                                   usage=usage, alg=0, alg2=0,
+                                   material=b'K',
+                                   description=description)
+            yield key2
+
+    def generate_keys_for_usage_flags(self, **kwargs) -> Iterator[StorageTestData]:
+        """Generate test keys covering usage flags."""
+        known_flags = sorted(self.constructors.key_usage_flags)
+        yield from self.keys_for_usage_flags(['0'], **kwargs)
+        for usage_flag in known_flags:
+            yield from self.keys_for_usage_flags([usage_flag], **kwargs)
+        for flag1, flag2 in zip(known_flags,
+                                known_flags[1:] + [known_flags[0]]):
+            yield from self.keys_for_usage_flags([flag1, flag2], **kwargs)
+
+    def generate_key_for_all_usage_flags(self) -> Iterator[StorageTestData]:
+        known_flags = sorted(self.constructors.key_usage_flags)
+        yield from self.keys_for_usage_flags(known_flags, short='all known')
+
+    def all_keys_for_usage_flags(self) -> Iterator[StorageTestData]:
+        yield from self.generate_keys_for_usage_flags()
+        yield from self.generate_key_for_all_usage_flags()
+
+    def keys_for_type(
+            self,
+            key_type: str,
+            params: Optional[Iterable[str]] = None
+    ) -> Iterator[StorageTestData]:
+        """Generate test keys for the given key type.
+
+        For key types that depend on a parameter (e.g. elliptic curve family),
+        `param` is the parameter to pass to the constructor. Only a single
+        parameter is supported.
+        """
+        kt = crypto_knowledge.KeyType(key_type, params)
+        for bits in kt.sizes_to_test():
+            usage_flags = 'PSA_KEY_USAGE_EXPORT'
+            alg = 0
+            alg2 = 0
+            key_material = kt.key_material(bits)
+            short_expression = re.sub(r'\bPSA_(?:KEY_TYPE|ECC_FAMILY)_',
+                                      r'',
+                                      kt.expression)
+            description = 'type: {} {}-bit'.format(short_expression, bits)
+            key = StorageTestData(version=self.version,
+                                  id=1, lifetime=0x00000001,
+                                  type=kt.expression, bits=bits,
+                                  usage=usage_flags, alg=alg, alg2=alg2,
+                                  material=key_material,
+                                  description=description)
+            yield key
+
+    def all_keys_for_types(self) -> Iterator[StorageTestData]:
+        """Generate test keys covering key types and their representations."""
+        key_types = sorted(self.constructors.key_types)
+        for key_type in self.constructors.generate_expressions(key_types):
+            yield from self.keys_for_type(key_type)
+
+    def keys_for_algorithm(self, alg: str) -> Iterator[StorageTestData]:
+        """Generate test keys for the specified algorithm."""
+        # For now, we don't have information on the compatibility of key
+        # types and algorithms. So we just test the encoding of algorithms,
+        # and not that operations can be performed with them.
+        descr = re.sub(r'PSA_ALG_', r'', alg)
+        descr = re.sub(r',', r', ', re.sub(r' +', r'', descr))
+        usage = 'PSA_KEY_USAGE_EXPORT'
+        key1 = StorageTestData(version=self.version,
+                               id=1, lifetime=0x00000001,
+                               type='PSA_KEY_TYPE_RAW_DATA', bits=8,
+                               usage=usage, alg=alg, alg2=0,
+                               material=b'K',
+                               description='alg: ' + descr)
+        yield key1
+        key2 = StorageTestData(version=self.version,
+                               id=1, lifetime=0x00000001,
+                               type='PSA_KEY_TYPE_RAW_DATA', bits=8,
+                               usage=usage, alg=0, alg2=alg,
+                               material=b'L',
+                               description='alg2: ' + descr)
+        yield key2
+
+    def all_keys_for_algorithms(self) -> Iterator[StorageTestData]:
+        """Generate test keys covering algorithm encodings."""
+        algorithms = sorted(self.constructors.algorithms)
+        for alg in self.constructors.generate_expressions(algorithms):
+            yield from self.keys_for_algorithm(alg)
+
+    def generate_all_keys(self) -> Iterator[StorageTestData]:
+        """Generate all keys for the test cases."""
+        yield from self.all_keys_for_lifetimes()
+        yield from self.all_keys_for_usage_flags()
+        yield from self.all_keys_for_types()
+        yield from self.all_keys_for_algorithms()
+
+    def all_test_cases(self) -> Iterator[test_case.TestCase]:
+        """Generate all storage format test cases."""
+        # First build a list of all keys, then construct all the corresponding
+        # test cases. This allows all required information to be obtained in
+        # one go, which is a significant performance gain as the information
+        # includes numerical values obtained by compiling a C program.
+        all_keys = list(self.generate_all_keys())
+        for key in all_keys:
+            if key.location_value() != 0:
+                # Skip keys with a non-default location, because they
+                # require a driver and we currently have no mechanism to
+                # determine whether a driver is available.
+                continue
+            yield self.make_test_case(key)
+
+class StorageFormatForward(StorageFormat):
+    """Storage format stability test cases for forward compatibility."""
+
+    def __init__(self, info: Information, version: int) -> None:
+        super().__init__(info, version, True)
+
+class StorageFormatV0(StorageFormat):
+    """Storage format stability test cases for version 0 compatibility."""
+
+    def __init__(self, info: Information) -> None:
+        super().__init__(info, 0, False)
+
+    def all_keys_for_usage_flags(self) -> Iterator[StorageTestData]:
+        """Generate test keys covering usage flags."""
+        yield from self.generate_keys_for_usage_flags(test_implicit_usage=True)
+        yield from self.generate_key_for_all_usage_flags()
+
+    def keys_for_implicit_usage(
+            self,
+            implyer_usage: str,
+            alg: str,
+            key_type: crypto_knowledge.KeyType
+    ) -> StorageTestData:
+        # pylint: disable=too-many-locals
+        """Generate test keys for the specified implicit usage flag,
+           algorithm and key type combination.
+        """
+        bits = key_type.sizes_to_test()[0]
+        implicit_usage = StorageKey.IMPLICIT_USAGE_FLAGS[implyer_usage]
+        usage_flags = 'PSA_KEY_USAGE_EXPORT'
+        material_usage_flags = usage_flags + ' | ' + implyer_usage
+        expected_usage_flags = material_usage_flags + ' | ' + implicit_usage
+        alg2 = 0
+        key_material = key_type.key_material(bits)
+        usage_expression = re.sub(r'PSA_KEY_USAGE_', r'', implyer_usage)
+        alg_expression = re.sub(r'PSA_ALG_', r'', alg)
+        alg_expression = re.sub(r',', r', ', re.sub(r' +', r'', alg_expression))
+        key_type_expression = re.sub(r'\bPSA_(?:KEY_TYPE|ECC_FAMILY)_',
+                                     r'',
+                                     key_type.expression)
+        description = 'implied by {}: {} {} {}-bit'.format(
+            usage_expression, alg_expression, key_type_expression, bits)
+        key = StorageTestData(version=self.version,
+                              id=1, lifetime=0x00000001,
+                              type=key_type.expression, bits=bits,
+                              usage=material_usage_flags,
+                              expected_usage=expected_usage_flags,
+                              without_implicit_usage=True,
+                              alg=alg, alg2=alg2,
+                              material=key_material,
+                              description=description)
+        return key
+
+    def gather_key_types_for_sign_alg(self) -> Dict[str, List[str]]:
+        # pylint: disable=too-many-locals
+        """Match possible key types for sign algorithms."""
+        # To create a valid combinaton both the algorithms and key types
+        # must be filtered. Pair them with keywords created from its names.
+        incompatible_alg_keyword = frozenset(['RAW', 'ANY', 'PURE'])
+        incompatible_key_type_keywords = frozenset(['MONTGOMERY'])
+        keyword_translation = {
+            'ECDSA': 'ECC',
+            'ED[0-9]*.*' : 'EDWARDS'
+        }
+        exclusive_keywords = {
+            'EDWARDS': 'ECC'
+        }
+        key_types = set(self.constructors.generate_expressions(self.constructors.key_types))
+        algorithms = set(self.constructors.generate_expressions(self.constructors.sign_algorithms))
+        alg_with_keys = {} #type: Dict[str, List[str]]
+        translation_table = str.maketrans('(', '_', ')')
+        for alg in algorithms:
+            # Generate keywords from the name of the algorithm
+            alg_keywords = set(alg.partition('(')[0].split(sep='_')[2:])
+            # Translate keywords for better matching with the key types
+            for keyword in alg_keywords.copy():
+                for pattern, replace in keyword_translation.items():
+                    if re.match(pattern, keyword):
+                        alg_keywords.remove(keyword)
+                        alg_keywords.add(replace)
+            # Filter out incompatible algortihms
+            if not alg_keywords.isdisjoint(incompatible_alg_keyword):
+                continue
+
+            for key_type in key_types:
+                # Generate keywords from the of the key type
+                key_type_keywords = set(key_type.translate(translation_table).split(sep='_')[3:])
+
+                # Remove ambigious keywords
+                for keyword1, keyword2 in exclusive_keywords.items():
+                    if keyword1 in key_type_keywords:
+                        key_type_keywords.remove(keyword2)
+
+                if key_type_keywords.isdisjoint(incompatible_key_type_keywords) and\
+                   not key_type_keywords.isdisjoint(alg_keywords):
+                    if alg in alg_with_keys:
+                        alg_with_keys[alg].append(key_type)
+                    else:
+                        alg_with_keys[alg] = [key_type]
+        return alg_with_keys
+
+    def all_keys_for_implicit_usage(self) -> Iterator[StorageTestData]:
+        """Generate test keys for usage flag extensions."""
+        # Generate a key type and algorithm pair for each extendable usage
+        # flag to generate a valid key for exercising. The key is generated
+        # without usage extension to check the extension compatiblity.
+        alg_with_keys = self.gather_key_types_for_sign_alg()
+
+        for usage in sorted(StorageKey.IMPLICIT_USAGE_FLAGS, key=str):
+            for alg in sorted(alg_with_keys):
+                for key_type in sorted(alg_with_keys[alg]):
+                    # The key types must be filtered to fit the specific usage flag.
+                    kt = crypto_knowledge.KeyType(key_type)
+                    if kt.is_valid_for_signature(usage):
+                        yield self.keys_for_implicit_usage(usage, alg, kt)
+
+    def generate_all_keys(self) -> Iterator[StorageTestData]:
+        yield from super().generate_all_keys()
+        yield from self.all_keys_for_implicit_usage()
+
+class TestGenerator:
+    """Generate test data."""
+
+    def __init__(self, options) -> None:
+        self.test_suite_directory = self.get_option(options, 'directory',
+                                                    'tests/suites')
+        self.info = Information()
+
+    @staticmethod
+    def get_option(options, name: str, default: T) -> T:
+        value = getattr(options, name, None)
+        return default if value is None else value
+
+    def filename_for(self, basename: str) -> str:
+        """The location of the data file with the specified base name."""
+        return os.path.join(self.test_suite_directory, basename + '.data')
+
+    def write_test_data_file(self, basename: str,
+                             test_cases: Iterable[test_case.TestCase]) -> None:
+        """Write the test cases to a .data file.
+
+        The output file is ``basename + '.data'`` in the test suite directory.
+        """
+        filename = self.filename_for(basename)
+        test_case.write_data_file(filename, test_cases)
+
+    TARGETS = {
+        'test_suite_psa_crypto_generate_key.generated':
+        lambda info: KeyGenerate(info).test_cases_for_key_generation(),
+        'test_suite_psa_crypto_not_supported.generated':
+        lambda info: NotSupported(info).test_cases_for_not_supported(),
+        'test_suite_psa_crypto_storage_format.current':
+        lambda info: StorageFormatForward(info, 0).all_test_cases(),
+        'test_suite_psa_crypto_storage_format.v0':
+        lambda info: StorageFormatV0(info).all_test_cases(),
+    } #type: Dict[str, Callable[[Information], Iterable[test_case.TestCase]]]
+
+    def generate_target(self, name: str) -> None:
+        test_cases = self.TARGETS[name](self.info)
+        self.write_test_data_file(name, test_cases)
+
+def main(args):
+    """Command line entry point."""
+    parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument('--list', action='store_true',
+                        help='List available targets and exit')
+    parser.add_argument('targets', nargs='*', metavar='TARGET',
+                        help='Target file to generate (default: all; "-": none)')
+    options = parser.parse_args(args)
+    generator = TestGenerator(options)
+    if options.list:
+        for name in sorted(generator.TARGETS):
+            print(generator.filename_for(name))
+        return
+    if options.targets:
+        # Allow "-" as a special case so you can run
+        # ``generate_psa_tests.py - $targets`` and it works uniformly whether
+        # ``$targets`` is empty or not.
+        options.targets = [os.path.basename(re.sub(r'\.data\Z', r'', target))
+                           for target in options.targets
+                           if target != '-']
+    else:
+        options.targets = sorted(generator.TARGETS)
+    for target in options.targets:
+        generator.generate_target(target)
+
+if __name__ == '__main__':
+    main(sys.argv[1:])
diff --git a/third_party/mbedtls/repo/tests/scripts/generate_test_code.py b/third_party/mbedtls/repo/tests/scripts/generate_test_code.py
index 7382fb6..f5750aa 100755
--- a/third_party/mbedtls/repo/tests/scripts/generate_test_code.py
+++ b/third_party/mbedtls/repo/tests/scripts/generate_test_code.py
@@ -106,10 +106,6 @@
 Platform file contains platform specific setup code and test case
 dispatch code. For example, host_test.function reads test data
 file from host's file system and dispatches tests.
-In case of on-target target_test.function tests are not dispatched
-on target. Target code is kept minimum and only test functions are
-dispatched. Test case dispatch is done on the host using tools like
-Greentea.
 
 Template file:
 ---------
diff --git a/third_party/mbedtls/repo/tests/scripts/list-enum-consts.pl b/third_party/mbedtls/repo/tests/scripts/list-enum-consts.pl
deleted file mode 100755
index 3d8df10..0000000
--- a/third_party/mbedtls/repo/tests/scripts/list-enum-consts.pl
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/env perl
-#
-# 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.
-
-use warnings;
-use strict;
-
-use utf8;
-use open qw(:std utf8);
-
--d 'include/mbedtls' or die "$0: must be run from root\n";
-
-@ARGV = grep { ! /compat-1\.3\.h/ } <include/mbedtls/*.h>;
-push @ARGV, "3rdparty/everest/include/everest/everest.h";
-push @ARGV, "3rdparty/everest/include/everest/x25519.h";
-
-
-my @consts;
-my $state = 'out';
-while (<>)
-{
-    if( $state eq 'out' and /^(typedef )?enum \{/ ) {
-        $state = 'in';
-    } elsif( $state eq 'out' and /^(typedef )?enum/ ) {
-        $state = 'start';
-    } elsif( $state eq 'start' and /{/ ) {
-        $state = 'in';
-    } elsif( $state eq 'in' and /}/ ) {
-        $state = 'out';
-    } elsif( $state eq 'in' and not /^#/) {
-        s/=.*//; s!/\*.*!!; s/,.*//; s/\s+//g; chomp;
-        push @consts, $_ if $_;
-    }
-}
-
-open my $fh, '>', 'enum-consts' or die;
-print $fh "$_\n" for sort @consts;
-close $fh or die;
-
-printf "%8d enum-consts\n", scalar @consts;
diff --git a/third_party/mbedtls/repo/tests/scripts/list-identifiers.sh b/third_party/mbedtls/repo/tests/scripts/list-identifiers.sh
index a1c3d2d..9b93080 100755
--- a/third_party/mbedtls/repo/tests/scripts/list-identifiers.sh
+++ b/third_party/mbedtls/repo/tests/scripts/list-identifiers.sh
@@ -1,8 +1,11 @@
 #!/bin/bash
 #
 # Create a file named identifiers containing identifiers from internal header
-# files or all header files, based on --internal flag.
+# files, based on the --internal flag.
 # Outputs the line count of the file to stdout.
+# A very thin wrapper around list_internal_identifiers.py for backwards
+# compatibility.
+# Must be run from Mbed TLS root.
 #
 # Usage: list-identifiers.sh [ -i | --internal ]
 #
@@ -24,7 +27,7 @@
 set -eu
 
 if [ -d include/mbedtls ]; then :; else
-    echo "$0: must be run from root" >&2
+    echo "$0: Must be run from Mbed TLS root" >&2
     exit 1
 fi
 
@@ -47,32 +50,17 @@
 
 if [ $INTERNAL ]
 then
-    HEADERS=$( ls include/mbedtls/*_internal.h library/*.h | egrep -v 'compat-1\.3\.h|bn_mul' )
+    tests/scripts/list_internal_identifiers.py
+    wc -l identifiers
 else
-    HEADERS=$( ls include/mbedtls/*.h include/psa/*.h library/*.h | egrep -v 'compat-1\.3\.h|bn_mul' )
-    HEADERS="$HEADERS 3rdparty/everest/include/everest/everest.h 3rdparty/everest/include/everest/x25519.h"
+    cat <<EOF
+Sorry, this script has to be called with --internal.
+
+This script exists solely for backwards compatibility with the previous
+iteration of list-identifiers.sh, of which only the --internal option remains in
+use. It is a thin wrapper around list_internal_identifiers.py.
+
+check-names.sh, which used to depend on this script, has been replaced with
+check_names.py and is now self-complete.
+EOF
 fi
-
-rm -f identifiers
-
-grep '^[^ /#{]' $HEADERS | \
-    sed -e 's/^[^:]*://' | \
-    egrep -v '^(extern "C"|(typedef )?(struct|union|enum)( {)?$|};?$)' \
-    > _decls
-
-if true; then
-sed -n -e 's/.* \**\([a-zA-Z_][a-zA-Z0-9_]*\)(.*/\1/p' \
-       -e 's/.*(\*\(.*\))(.*/\1/p' _decls
-grep -v '(' _decls | sed -e 's/\([a-zA-Z0-9_]*\)[;[].*/\1/' -e 's/.* \**//'
-fi > _identifiers
-
-if [ $( wc -l < _identifiers ) -eq $( wc -l < _decls ) ]; then
-    rm _decls
-    egrep -v '^(u?int(16|32|64)_t)$' _identifiers | sort > identifiers
-    rm _identifiers
-else
-    echo "$0: oops, lost some identifiers" 2>&1
-    exit 1
-fi
-
-wc -l identifiers
diff --git a/third_party/mbedtls/repo/tests/scripts/list-macros.sh b/third_party/mbedtls/repo/tests/scripts/list-macros.sh
deleted file mode 100755
index a8617a0..0000000
--- a/third_party/mbedtls/repo/tests/scripts/list-macros.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/sh
-#
-# 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.
-
-set -eu
-
-if [ -d include/mbedtls ]; then :; else
-    echo "$0: must be run from root" >&2
-    exit 1
-fi
-
-HEADERS=$( ls include/mbedtls/*.h include/psa/*.h | egrep -v 'compat-1\.3\.h' )
-HEADERS="$HEADERS library/*.h"
-HEADERS="$HEADERS 3rdparty/everest/include/everest/everest.h 3rdparty/everest/include/everest/x25519.h"
-
-sed -n -e 's/.*#define \([a-zA-Z0-9_]*\).*/\1/p' $HEADERS \
-    | egrep -v '^(asm|inline|EMIT|_CRT_SECURE_NO_DEPRECATE)$|^MULADDC_' \
-    | sort -u > macros
-
-# For include/mbedtls/config_psa.h need to ignore the MBEDTLS_xxx define
-# in that file since they may not be defined in include/psa/crypto_config.h
-# This line renames the potentially missing defines to ones that should
-# be present.
-sed -ne 's/^MBEDTLS_PSA_BUILTIN_/MBEDTLS_PSA_ACCEL_/p' <macros >>macros
-
-wc -l macros
diff --git a/third_party/mbedtls/repo/tests/scripts/list-symbols.sh b/third_party/mbedtls/repo/tests/scripts/list-symbols.sh
deleted file mode 100755
index 8bdc55f..0000000
--- a/third_party/mbedtls/repo/tests/scripts/list-symbols.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/sh
-#
-# 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.
-
-set -eu
-
-if [ -d include/mbedtls ]; then :; else
-    echo "$0: must be run from root" >&2
-    exit 1
-fi
-
-if grep -i cmake Makefile >/dev/null; then
-    echo "$0: not compatible with cmake" >&2
-    exit 1
-fi
-
-cp include/mbedtls/config.h include/mbedtls/config.h.bak
-scripts/config.py full
-make clean
-make_ret=
-CFLAGS=-fno-asynchronous-unwind-tables make lib \
-      >list-symbols.make.log 2>&1 ||
-  {
-    make_ret=$?
-    echo "Build failure: CFLAGS=-fno-asynchronous-unwind-tables make lib"
-    cat list-symbols.make.log >&2
-  }
-rm list-symbols.make.log
-mv include/mbedtls/config.h.bak include/mbedtls/config.h
-if [ -n "$make_ret" ]; then
-    exit "$make_ret"
-fi
-
-if uname | grep -F Darwin >/dev/null; then
-    nm -gUj library/libmbed*.a 2>/dev/null | sed -n -e 's/^_//p' | grep -v -e ^FStar -e ^Hacl
-elif uname | grep -F Linux >/dev/null; then
-    nm -og library/libmbed*.a | grep -v '^[^ ]*: *U \|^$\|^[^ ]*:$' | sed 's/^[^ ]* . //' | grep -v -e ^FStar -e ^Hacl
-fi | sort > exported-symbols
-make clean
-
-wc -l exported-symbols
diff --git a/third_party/mbedtls/repo/tests/scripts/list_internal_identifiers.py b/third_party/mbedtls/repo/tests/scripts/list_internal_identifiers.py
new file mode 100755
index 0000000..779a16f
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/scripts/list_internal_identifiers.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python3
+#
+# 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 script generates a file called identifiers that contains all Mbed TLS
+identifiers found on internal headers. This is the equivalent of what was
+previously `list-identifiers.sh --internal`, and is useful for generating an
+exclusion file list for ABI/API checking, since we do not promise compatibility
+for them.
+
+It uses the CodeParser class from check_names.py to perform the parsing.
+
+The script returns 0 on success, 1 if there is a script error.
+Must be run from Mbed TLS root.
+"""
+
+import argparse
+import logging
+from check_names import CodeParser
+
+def main():
+    parser = argparse.ArgumentParser(
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+        description=(
+            "This script writes a list of parsed identifiers in internal "
+            "headers to \"identifiers\". This is useful for generating a list "
+            "of names to exclude from API/ABI compatibility checking. "))
+
+    parser.parse_args()
+
+    name_check = CodeParser(logging.getLogger())
+    result = name_check.parse_identifiers([
+        "include/mbedtls/*_internal.h",
+        "library/*.h"
+    ])
+    result.sort(key=lambda x: x.name)
+
+    identifiers = ["{}\n".format(match.name) for match in result]
+    with open("identifiers", "w", encoding="utf-8") as f:
+        f.writelines(identifiers)
+
+if __name__ == "__main__":
+    main()
diff --git a/third_party/mbedtls/repo/tests/scripts/mbedtls_test.py b/third_party/mbedtls/repo/tests/scripts/mbedtls_test.py
deleted file mode 100755
index a5d0940..0000000
--- a/third_party/mbedtls/repo/tests/scripts/mbedtls_test.py
+++ /dev/null
@@ -1,382 +0,0 @@
-#!/usr/bin/env python3
-
-# Greentea host test script for Mbed TLS on-target test suite 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.
-
-
-"""
-Mbed TLS on-target test suite tests are implemented as Greentea
-tests. Greentea tests are implemented in two parts: target test and
-host test. Target test is a C application that is built for the
-target platform and executes on the target. Host test is a Python
-class derived from mbed_host_tests.BaseHostTest. Target communicates
-with the host over serial for the test data and sends back the result.
-
-Python tool mbedgt (Greentea) is responsible for flashing the test
-binary on to the target and dynamically loading this host test module.
-
-Greentea documentation can be found here:
-https://github.com/ARMmbed/greentea
-"""
-
-
-import re
-import os
-import binascii
-
-from mbed_host_tests import BaseHostTest, event_callback # pylint: disable=import-error
-
-
-class TestDataParserError(Exception):
-    """Indicates error in test data, read from .data file."""
-    pass
-
-
-class TestDataParser:
-    """
-    Parses test name, dependencies, test function name and test parameters
-    from the data file.
-    """
-
-    def __init__(self):
-        """
-        Constructor
-        """
-        self.tests = []
-
-    def parse(self, data_file):
-        """
-        Data file parser.
-
-        :param data_file: Data file path
-        """
-        with open(data_file, 'r') as data_f:
-            self.__parse(data_f)
-
-    @staticmethod
-    def __escaped_split(inp_str, split_char):
-        """
-        Splits inp_str on split_char except when escaped.
-
-        :param inp_str: String to split
-        :param split_char: Split character
-        :return: List of splits
-        """
-        split_colon_fn = lambda x: re.sub(r'\\' + split_char, split_char, x)
-        if len(split_char) > 1:
-            raise ValueError('Expected split character. Found string!')
-        out = list(map(split_colon_fn, re.split(r'(?<!\\)' + split_char, inp_str)))
-        out = [x for x in out if x]
-        return out
-
-    def __parse(self, data_f):
-        """
-        Parses data file using supplied file object.
-
-        :param data_f: Data file object
-        :return:
-        """
-        for line in data_f:
-            line = line.strip()
-            if not line:
-                continue
-            # Read test name
-            name = line
-
-            # Check dependencies
-            dependencies = []
-            line = next(data_f).strip()
-            match = re.search('depends_on:(.*)', line)
-            if match:
-                dependencies = [int(x) for x in match.group(1).split(':')]
-                line = next(data_f).strip()
-
-            # Read test vectors
-            line = line.replace('\\n', '\n')
-            parts = self.__escaped_split(line, ':')
-            function_name = int(parts[0])
-            args = parts[1:]
-            args_count = len(args)
-            if args_count % 2 != 0:
-                err_str_fmt = "Number of test arguments({}) should be even: {}"
-                raise TestDataParserError(err_str_fmt.format(args_count, line))
-            grouped_args = [(args[i * 2], args[(i * 2) + 1])
-                            for i in range(int(len(args)/2))]
-            self.tests.append((name, function_name, dependencies,
-                               grouped_args))
-
-    def get_test_data(self):
-        """
-        Returns test data.
-        """
-        return self.tests
-
-
-class MbedTlsTest(BaseHostTest):
-    """
-    Host test for Mbed TLS unit tests. This script is loaded at
-    run time by Greentea for executing Mbed TLS test suites. Each
-    communication from the target is received in this object as
-    an event, which is then handled by the event handler method
-    decorated by the associated event. Ex: @event_callback('GO').
-
-    Target test sends requests for dispatching next test. It reads
-    tests from the intermediate data file and sends test function
-    identifier, dependency identifiers, expression identifiers and
-    the test data in binary form. Target test checks dependencies
-    , evaluate integer constant expressions and dispatches the test
-    function with received test parameters. After test function is
-    finished, target sends the result. This class handles the result
-    event and prints verdict in the form that Greentea understands.
-
-    """
-    # status/error codes from suites/helpers.function
-    DEPENDENCY_SUPPORTED = 0
-    KEY_VALUE_MAPPING_FOUND = DEPENDENCY_SUPPORTED
-    DISPATCH_TEST_SUCCESS = DEPENDENCY_SUPPORTED
-
-    KEY_VALUE_MAPPING_NOT_FOUND = -1    # Expression Id not found.
-    DEPENDENCY_NOT_SUPPORTED = -2       # Dependency not supported.
-    DISPATCH_TEST_FN_NOT_FOUND = -3     # Test function not found.
-    DISPATCH_INVALID_TEST_DATA = -4     # Invalid parameter type.
-    DISPATCH_UNSUPPORTED_SUITE = -5     # Test suite not supported/enabled.
-
-    def __init__(self):
-        """
-        Constructor initialises test index to 0.
-        """
-        super(MbedTlsTest, self).__init__()
-        self.tests = []
-        self.test_index = -1
-        self.dep_index = 0
-        self.suite_passed = True
-        self.error_str = dict()
-        self.error_str[self.DEPENDENCY_SUPPORTED] = \
-            'DEPENDENCY_SUPPORTED'
-        self.error_str[self.KEY_VALUE_MAPPING_NOT_FOUND] = \
-            'KEY_VALUE_MAPPING_NOT_FOUND'
-        self.error_str[self.DEPENDENCY_NOT_SUPPORTED] = \
-            'DEPENDENCY_NOT_SUPPORTED'
-        self.error_str[self.DISPATCH_TEST_FN_NOT_FOUND] = \
-            'DISPATCH_TEST_FN_NOT_FOUND'
-        self.error_str[self.DISPATCH_INVALID_TEST_DATA] = \
-            'DISPATCH_INVALID_TEST_DATA'
-        self.error_str[self.DISPATCH_UNSUPPORTED_SUITE] = \
-            'DISPATCH_UNSUPPORTED_SUITE'
-
-    def setup(self):
-        """
-        Setup hook implementation. Reads test suite data file and parses out
-        tests.
-        """
-        binary_path = self.get_config_item('image_path')
-        script_dir = os.path.split(os.path.abspath(__file__))[0]
-        suite_name = os.path.splitext(os.path.basename(binary_path))[0]
-        data_file = ".".join((suite_name, 'datax'))
-        data_file = os.path.join(script_dir, '..', 'mbedtls',
-                                 suite_name, data_file)
-        if os.path.exists(data_file):
-            self.log("Running tests from %s" % data_file)
-            parser = TestDataParser()
-            parser.parse(data_file)
-            self.tests = parser.get_test_data()
-            self.print_test_info()
-        else:
-            self.log("Data file not found: %s" % data_file)
-            self.notify_complete(False)
-
-    def print_test_info(self):
-        """
-        Prints test summary read by Greentea to detect test cases.
-        """
-        self.log('{{__testcase_count;%d}}' % len(self.tests))
-        for name, _, _, _ in self.tests:
-            self.log('{{__testcase_name;%s}}' % name)
-
-    @staticmethod
-    def align_32bit(data_bytes):
-        """
-        4 byte aligns input byte array.
-
-        :return:
-        """
-        data_bytes += bytearray((4 - (len(data_bytes))) % 4)
-
-    @staticmethod
-    def hex_str_bytes(hex_str):
-        """
-        Converts Hex string representation to byte array
-
-        :param hex_str: Hex in string format.
-        :return: Output Byte array
-        """
-        if hex_str[0] != '"' or hex_str[len(hex_str) - 1] != '"':
-            raise TestDataParserError("HEX test parameter missing '\"':"
-                                      " %s" % hex_str)
-        hex_str = hex_str.strip('"')
-        if len(hex_str) % 2 != 0:
-            raise TestDataParserError("HEX parameter len should be mod of "
-                                      "2: %s" % hex_str)
-
-        data_bytes = binascii.unhexlify(hex_str)
-        return data_bytes
-
-    @staticmethod
-    def int32_to_big_endian_bytes(i):
-        """
-        Coverts i to byte array in big endian format.
-
-        :param i: Input integer
-        :return: Output bytes array in big endian or network order
-        """
-        data_bytes = bytearray([((i >> x) & 0xff) for x in [24, 16, 8, 0]])
-        return data_bytes
-
-    def test_vector_to_bytes(self, function_id, dependencies, parameters):
-        """
-        Converts test vector into a byte array that can be sent to the target.
-
-        :param function_id: Test Function Identifier
-        :param dependencies: Dependency list
-        :param parameters: Test function input parameters
-        :return: Byte array and its length
-        """
-        data_bytes = bytearray([len(dependencies)])
-        if dependencies:
-            data_bytes += bytearray(dependencies)
-        data_bytes += bytearray([function_id, len(parameters)])
-        for typ, param in parameters:
-            if typ in ('int', 'exp'):
-                i = int(param, 0)
-                data_bytes += b'I' if typ == 'int' else b'E'
-                self.align_32bit(data_bytes)
-                data_bytes += self.int32_to_big_endian_bytes(i)
-            elif typ == 'char*':
-                param = param.strip('"')
-                i = len(param) + 1  # + 1 for null termination
-                data_bytes += b'S'
-                self.align_32bit(data_bytes)
-                data_bytes += self.int32_to_big_endian_bytes(i)
-                data_bytes += bytearray(param, encoding='ascii')
-                data_bytes += b'\0'   # Null terminate
-            elif typ == 'hex':
-                binary_data = self.hex_str_bytes(param)
-                data_bytes += b'H'
-                self.align_32bit(data_bytes)
-                i = len(binary_data)
-                data_bytes += self.int32_to_big_endian_bytes(i)
-                data_bytes += binary_data
-        length = self.int32_to_big_endian_bytes(len(data_bytes))
-        return data_bytes, length
-
-    def run_next_test(self):
-        """
-        Fetch next test information and execute the test.
-
-        """
-        self.test_index += 1
-        self.dep_index = 0
-        if self.test_index < len(self.tests):
-            name, function_id, dependencies, args = self.tests[self.test_index]
-            self.run_test(name, function_id, dependencies, args)
-        else:
-            self.notify_complete(self.suite_passed)
-
-    def run_test(self, name, function_id, dependencies, args):
-        """
-        Execute the test on target by sending next test information.
-
-        :param name: Test name
-        :param function_id: function identifier
-        :param dependencies: Dependencies list
-        :param args: test parameters
-        :return:
-        """
-        self.log("Running: %s" % name)
-
-        param_bytes, length = self.test_vector_to_bytes(function_id,
-                                                        dependencies, args)
-        self.send_kv(
-            ''.join('{:02x}'.format(x) for x in length),
-            ''.join('{:02x}'.format(x) for x in param_bytes)
-        )
-
-    @staticmethod
-    def get_result(value):
-        """
-        Converts result from string type to integer
-        :param value: Result code in string
-        :return: Integer result code. Value is from the test status
-                 constants defined under the MbedTlsTest class.
-        """
-        try:
-            return int(value)
-        except ValueError:
-            ValueError("Result should return error number. "
-                       "Instead received %s" % value)
-
-    @event_callback('GO')
-    def on_go(self, _key, _value, _timestamp):
-        """
-        Sent by the target to start first test.
-
-        :param _key: Event key
-        :param _value: Value. ignored
-        :param _timestamp: Timestamp ignored.
-        :return:
-        """
-        self.run_next_test()
-
-    @event_callback("R")
-    def on_result(self, _key, value, _timestamp):
-        """
-        Handle result. Prints test start, finish required by Greentea
-        to detect test execution.
-
-        :param _key: Event key
-        :param value: Value. ignored
-        :param _timestamp: Timestamp ignored.
-        :return:
-        """
-        int_val = self.get_result(value)
-        name, _, _, _ = self.tests[self.test_index]
-        self.log('{{__testcase_start;%s}}' % name)
-        self.log('{{__testcase_finish;%s;%d;%d}}' % (name, int_val == 0,
-                                                     int_val != 0))
-        if int_val != 0:
-            self.suite_passed = False
-        self.run_next_test()
-
-    @event_callback("F")
-    def on_failure(self, _key, value, _timestamp):
-        """
-        Handles test execution failure. That means dependency not supported or
-        Test function not supported. Hence marking test as skipped.
-
-        :param _key: Event key
-        :param value: Value. ignored
-        :param _timestamp: Timestamp ignored.
-        :return:
-        """
-        int_val = self.get_result(value)
-        if int_val in self.error_str:
-            err = self.error_str[int_val]
-        else:
-            err = 'Unknown error'
-        # For skip status, do not write {{__testcase_finish;...}}
-        self.log("Error: %s" % err)
-        self.run_next_test()
diff --git a/third_party/mbedtls/repo/tests/scripts/scripts_path.py b/third_party/mbedtls/repo/tests/scripts/scripts_path.py
new file mode 100644
index 0000000..10bf6f8
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/scripts/scripts_path.py
@@ -0,0 +1,28 @@
+"""Add our Python library directory to the module search path.
+
+Usage:
+
+    import scripts_path # pylint: disable=unused-import
+"""
+
+# 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.
+
+import os
+import sys
+
+sys.path.append(os.path.join(os.path.dirname(__file__),
+                             os.path.pardir, os.path.pardir,
+                             'scripts'))
diff --git a/third_party/mbedtls/repo/tests/scripts/set_psa_test_dependencies.py b/third_party/mbedtls/repo/tests/scripts/set_psa_test_dependencies.py
new file mode 100755
index 0000000..61923d8
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/scripts/set_psa_test_dependencies.py
@@ -0,0 +1,302 @@
+#!/usr/bin/env python3
+
+"""Edit test cases to use PSA dependencies instead of classic dependencies.
+"""
+
+# 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.
+
+import os
+import re
+import sys
+
+CLASSIC_DEPENDENCIES = frozenset([
+    # This list is manually filtered from config.h.
+
+    # Mbed TLS feature support.
+    # Only features that affect what can be done are listed here.
+    # Options that control optimizations or alternative implementations
+    # are omitted.
+    'MBEDTLS_CIPHER_MODE_CBC',
+    'MBEDTLS_CIPHER_MODE_CFB',
+    'MBEDTLS_CIPHER_MODE_CTR',
+    'MBEDTLS_CIPHER_MODE_OFB',
+    'MBEDTLS_CIPHER_MODE_XTS',
+    'MBEDTLS_CIPHER_NULL_CIPHER',
+    'MBEDTLS_CIPHER_PADDING_PKCS7',
+    'MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS',
+    'MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN',
+    'MBEDTLS_CIPHER_PADDING_ZEROS',
+    #curve#'MBEDTLS_ECP_DP_SECP192R1_ENABLED',
+    #curve#'MBEDTLS_ECP_DP_SECP224R1_ENABLED',
+    #curve#'MBEDTLS_ECP_DP_SECP256R1_ENABLED',
+    #curve#'MBEDTLS_ECP_DP_SECP384R1_ENABLED',
+    #curve#'MBEDTLS_ECP_DP_SECP521R1_ENABLED',
+    #curve#'MBEDTLS_ECP_DP_SECP192K1_ENABLED',
+    #curve#'MBEDTLS_ECP_DP_SECP224K1_ENABLED',
+    #curve#'MBEDTLS_ECP_DP_SECP256K1_ENABLED',
+    #curve#'MBEDTLS_ECP_DP_BP256R1_ENABLED',
+    #curve#'MBEDTLS_ECP_DP_BP384R1_ENABLED',
+    #curve#'MBEDTLS_ECP_DP_BP512R1_ENABLED',
+    #curve#'MBEDTLS_ECP_DP_CURVE25519_ENABLED',
+    #curve#'MBEDTLS_ECP_DP_CURVE448_ENABLED',
+    'MBEDTLS_ECDSA_DETERMINISTIC',
+    #'MBEDTLS_GENPRIME', #needed for RSA key generation
+    'MBEDTLS_PKCS1_V15',
+    'MBEDTLS_PKCS1_V21',
+    'MBEDTLS_SHA512_NO_SHA384',
+
+    # Mbed TLS modules.
+    # Only modules that provide cryptographic mechanisms are listed here.
+    # Platform, data formatting, X.509 or TLS modules are omitted.
+    'MBEDTLS_AES_C',
+    'MBEDTLS_ARC4_C',
+    'MBEDTLS_BIGNUM_C',
+    #cipher#'MBEDTLS_BLOWFISH_C',
+    'MBEDTLS_CAMELLIA_C',
+    'MBEDTLS_ARIA_C',
+    'MBEDTLS_CCM_C',
+    'MBEDTLS_CHACHA20_C',
+    'MBEDTLS_CHACHAPOLY_C',
+    'MBEDTLS_CMAC_C',
+    'MBEDTLS_CTR_DRBG_C',
+    'MBEDTLS_DES_C',
+    'MBEDTLS_DHM_C',
+    'MBEDTLS_ECDH_C',
+    'MBEDTLS_ECDSA_C',
+    'MBEDTLS_ECJPAKE_C',
+    'MBEDTLS_ECP_C',
+    'MBEDTLS_ENTROPY_C',
+    'MBEDTLS_GCM_C',
+    'MBEDTLS_HKDF_C',
+    'MBEDTLS_HMAC_DRBG_C',
+    'MBEDTLS_NIST_KW_C',
+    'MBEDTLS_MD2_C',
+    'MBEDTLS_MD4_C',
+    'MBEDTLS_MD5_C',
+    'MBEDTLS_PKCS5_C',
+    'MBEDTLS_PKCS12_C',
+    'MBEDTLS_POLY1305_C',
+    'MBEDTLS_RIPEMD160_C',
+    'MBEDTLS_RSA_C',
+    'MBEDTLS_SHA1_C',
+    'MBEDTLS_SHA256_C',
+    'MBEDTLS_SHA512_C',
+    'MBEDTLS_XTEA_C',
+])
+
+def is_classic_dependency(dep):
+    """Whether dep is a classic dependency that PSA test cases should not use."""
+    if dep.startswith('!'):
+        dep = dep[1:]
+    return dep in CLASSIC_DEPENDENCIES
+
+def is_systematic_dependency(dep):
+    """Whether dep is a PSA dependency which is determined systematically."""
+    if dep.startswith('PSA_WANT_ECC_'):
+        return False
+    return dep.startswith('PSA_WANT_')
+
+WITHOUT_SYSTEMATIC_DEPENDENCIES = frozenset([
+    'PSA_ALG_AEAD_WITH_SHORTENED_TAG', # only a modifier
+    'PSA_ALG_ANY_HASH', # only meaningful in policies
+    'PSA_ALG_KEY_AGREEMENT', # only a way to combine algorithms
+    'PSA_ALG_TRUNCATED_MAC', # only a modifier
+    'PSA_KEY_TYPE_NONE', # not a real key type
+    'PSA_KEY_TYPE_DERIVE', # always supported, don't list it to reduce noise
+    'PSA_KEY_TYPE_RAW_DATA', # always supported, don't list it to reduce noise
+    'PSA_ALG_AT_LEAST_THIS_LENGTH_MAC', #only a modifier
+    'PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG', #only a modifier
+])
+
+SPECIAL_SYSTEMATIC_DEPENDENCIES = {
+    'PSA_ALG_ECDSA_ANY': frozenset(['PSA_WANT_ALG_ECDSA']),
+    'PSA_ALG_RSA_PKCS1V15_SIGN_RAW': frozenset(['PSA_WANT_ALG_RSA_PKCS1V15_SIGN']),
+}
+
+def dependencies_of_symbol(symbol):
+    """Return the dependencies for a symbol that designates a cryptographic mechanism."""
+    if symbol in WITHOUT_SYSTEMATIC_DEPENDENCIES:
+        return frozenset()
+    if symbol in SPECIAL_SYSTEMATIC_DEPENDENCIES:
+        return SPECIAL_SYSTEMATIC_DEPENDENCIES[symbol]
+    if symbol.startswith('PSA_ALG_CATEGORY_') or \
+       symbol.startswith('PSA_KEY_TYPE_CATEGORY_'):
+        # Categories are used in test data when an unsupported but plausible
+        # mechanism number needed. They have no associated dependency.
+        return frozenset()
+    return {symbol.replace('_', '_WANT_', 1)}
+
+def systematic_dependencies(file_name, function_name, arguments):
+    """List the systematically determined dependency for a test case."""
+    deps = set()
+
+    # Run key policy negative tests even if the algorithm to attempt performing
+    # is not supported but in the case where the test is to check an
+    # incompatibility between a requested algorithm for a cryptographic
+    # operation and a key policy. In the latter, we want to filter out the
+    # cases # where PSA_ERROR_NOT_SUPPORTED is returned instead of
+    # PSA_ERROR_NOT_PERMITTED.
+    if function_name.endswith('_key_policy') and \
+       arguments[-1].startswith('PSA_ERROR_') and \
+       arguments[-1] != ('PSA_ERROR_NOT_PERMITTED'):
+        arguments[-2] = ''
+    if function_name == 'copy_fail' and \
+       arguments[-1].startswith('PSA_ERROR_'):
+        arguments[-2] = ''
+        arguments[-3] = ''
+
+    # Storage format tests that only look at how the file is structured and
+    # don't care about the format of the key material don't depend on any
+    # cryptographic mechanisms.
+    if os.path.basename(file_name) == 'test_suite_psa_crypto_persistent_key.data' and \
+       function_name in {'format_storage_data_check',
+                         'parse_storage_data_check'}:
+        return []
+
+    for arg in arguments:
+        for symbol in re.findall(r'PSA_(?:ALG|KEY_TYPE)_\w+', arg):
+            deps.update(dependencies_of_symbol(symbol))
+    return sorted(deps)
+
+def updated_dependencies(file_name, function_name, arguments, dependencies):
+    """Rework the list of dependencies into PSA_WANT_xxx.
+
+    Remove classic crypto dependencies such as MBEDTLS_RSA_C,
+    MBEDTLS_PKCS1_V15, etc.
+
+    Add systematic PSA_WANT_xxx dependencies based on the called function and
+    its arguments, replacing existing PSA_WANT_xxx dependencies.
+    """
+    automatic = systematic_dependencies(file_name, function_name, arguments)
+    manual = [dep for dep in dependencies
+              if not (is_systematic_dependency(dep) or
+                      is_classic_dependency(dep))]
+    return automatic + manual
+
+def keep_manual_dependencies(file_name, function_name, arguments):
+    #pylint: disable=unused-argument
+    """Declare test functions with unusual dependencies here."""
+    # If there are no arguments, we can't do any useful work. Assume that if
+    # there are dependencies, they are warranted.
+    if not arguments:
+        return True
+    # When PSA_ERROR_NOT_SUPPORTED is expected, usually, at least one of the
+    # constants mentioned in the test should not be supported. It isn't
+    # possible to determine which one in a systematic way. So let the programmer
+    # decide.
+    if arguments[-1] == 'PSA_ERROR_NOT_SUPPORTED':
+        return True
+    return False
+
+def process_data_stanza(stanza, file_name, test_case_number):
+    """Update PSA crypto dependencies in one Mbed TLS test case.
+
+    stanza is the test case text (including the description, the dependencies,
+    the line with the function and arguments, and optionally comments). Return
+    a new stanza with an updated dependency line, preserving everything else
+    (description, comments, arguments, etc.).
+    """
+    if not stanza.lstrip('\n'):
+        # Just blank lines
+        return stanza
+    # Expect 2 or 3 non-comment lines: description, optional dependencies,
+    # function-and-arguments.
+    content_matches = list(re.finditer(r'^[\t ]*([^\t #].*)$', stanza, re.M))
+    if len(content_matches) < 2:
+        raise Exception('Not enough content lines in paragraph {} in {}'
+                        .format(test_case_number, file_name))
+    if len(content_matches) > 3:
+        raise Exception('Too many content lines in paragraph {} in {}'
+                        .format(test_case_number, file_name))
+    arguments = content_matches[-1].group(0).split(':')
+    function_name = arguments.pop(0)
+    if keep_manual_dependencies(file_name, function_name, arguments):
+        return stanza
+    if len(content_matches) == 2:
+        # Insert a line for the dependencies. If it turns out that there are
+        # no dependencies, we'll remove that empty line below.
+        dependencies_location = content_matches[-1].start()
+        text_before = stanza[:dependencies_location]
+        text_after = '\n' + stanza[dependencies_location:]
+        old_dependencies = []
+        dependencies_leader = 'depends_on:'
+    else:
+        dependencies_match = content_matches[-2]
+        text_before = stanza[:dependencies_match.start()]
+        text_after = stanza[dependencies_match.end():]
+        old_dependencies = dependencies_match.group(0).split(':')
+        dependencies_leader = old_dependencies.pop(0) + ':'
+        if dependencies_leader != 'depends_on:':
+            raise Exception('Next-to-last line does not start with "depends_on:"'
+                            ' in paragraph {} in {}'
+                            .format(test_case_number, file_name))
+    new_dependencies = updated_dependencies(file_name, function_name, arguments,
+                                            old_dependencies)
+    if new_dependencies:
+        stanza = (text_before +
+                  dependencies_leader + ':'.join(new_dependencies) +
+                  text_after)
+    else:
+        # The dependencies have become empty. Remove the depends_on: line.
+        assert text_after[0] == '\n'
+        stanza = text_before + text_after[1:]
+    return stanza
+
+def process_data_file(file_name, old_content):
+    """Update PSA crypto dependencies in an Mbed TLS test suite data file.
+
+    Process old_content (the old content of the file) and return the new content.
+    """
+    old_stanzas = old_content.split('\n\n')
+    new_stanzas = [process_data_stanza(stanza, file_name, n)
+                   for n, stanza in enumerate(old_stanzas, start=1)]
+    return '\n\n'.join(new_stanzas)
+
+def update_file(file_name, old_content, new_content):
+    """Update the given file with the given new content.
+
+    Replace the existing file. The previous version is renamed to *.bak.
+    Don't modify the file if the content was unchanged.
+    """
+    if new_content == old_content:
+        return
+    backup = file_name + '.bak'
+    tmp = file_name + '.tmp'
+    with open(tmp, 'w', encoding='utf-8') as new_file:
+        new_file.write(new_content)
+    os.replace(file_name, backup)
+    os.replace(tmp, file_name)
+
+def process_file(file_name):
+    """Update PSA crypto dependencies in an Mbed TLS test suite data file.
+
+    Replace the existing file. The previous version is renamed to *.bak.
+    Don't modify the file if the content was unchanged.
+    """
+    old_content = open(file_name, encoding='utf-8').read()
+    if file_name.endswith('.data'):
+        new_content = process_data_file(file_name, old_content)
+    else:
+        raise Exception('File type not recognized: {}'
+                        .format(file_name))
+    update_file(file_name, old_content, new_content)
+
+def main(args):
+    for file_name in args:
+        process_file(file_name)
+
+if __name__ == '__main__':
+    main(sys.argv[1:])
diff --git a/third_party/mbedtls/repo/tests/scripts/test-ref-configs.pl b/third_party/mbedtls/repo/tests/scripts/test-ref-configs.pl
index cf4175a..d34bbde 100755
--- a/third_party/mbedtls/repo/tests/scripts/test-ref-configs.pl
+++ b/third_party/mbedtls/repo/tests/scripts/test-ref-configs.pl
@@ -29,17 +29,15 @@
 
 my %configs = (
     'config-ccm-psk-tls1_2.h' => {
-        'compat' => '-m tls1_2 -f \'^TLS-PSK-WITH-AES-...-CCM-8\'',
+        'compat' => '-m tls12 -f \'^TLS-PSK-WITH-AES-...-CCM-8\'',
     },
     'config-mini-tls1_1.h' => {
         'compat' => '-m tls1_1 -f \'^DES-CBC3-SHA$\|^TLS-RSA-WITH-3DES-EDE-CBC-SHA$\'', #'
     },
     'config-no-entropy.h' => {
     },
-    'config-psa-crypto.h' => {
-    },
     'config-suite-b.h' => {
-        'compat' => "-m tls1_2 -f 'ECDHE-ECDSA.*AES.*GCM' -p mbedTLS",
+        'compat' => "-m tls12 -f 'ECDHE-ECDSA.*AES.*GCM' -p mbedTLS",
     },
     'config-symmetric-only.h' => {
     },
diff --git a/third_party/mbedtls/repo/tests/scripts/test_generate_test_code.py b/third_party/mbedtls/repo/tests/scripts/test_generate_test_code.py
index 000c2a7..9bf66f1 100755
--- a/third_party/mbedtls/repo/tests/scripts/test_generate_test_code.py
+++ b/third_party/mbedtls/repo/tests/scripts/test_generate_test_code.py
@@ -20,21 +20,10 @@
 Unit tests for generate_test_code.py
 """
 
-# pylint: disable=wrong-import-order
-try:
-    # Python 2
-    from StringIO import StringIO
-except ImportError:
-    # Python 3
-    from io import StringIO
+from io import StringIO
 from unittest import TestCase, main as unittest_main
-try:
-    # Python 2
-    from mock import patch
-except ImportError:
-    # Python 3
-    from unittest.mock import patch
-# pylint: enable=wrong-import-order
+from unittest.mock import patch
+
 from generate_test_code import gen_dependencies, gen_dependencies_one_line
 from generate_test_code import gen_function_wrapper, gen_dispatch
 from generate_test_code import parse_until_pattern, GeneratorInputError
@@ -317,25 +306,16 @@
         :return: Line read from file.
         """
         parent = super(StringIOWrapper, self)
-        if getattr(parent, 'next', None):
-            # Python 2
-            line = parent.next()
-        else:
-            # Python 3
-            line = parent.__next__()
+        line = parent.__next__()
         return line
 
-    # Python 3
-    __next__ = next
-
-    def readline(self, length=0):
+    def readline(self, _length=0):
         """
         Wrap the base class readline.
 
         :param length:
         :return:
         """
-        # pylint: disable=unused-argument
         line = super(StringIOWrapper, self).readline()
         if line is not None:
             self.line_no += 1
@@ -549,38 +529,6 @@
     Test suite for testing parse_function_code()
     """
 
-    def assert_raises_regex(self, exp, regex, func, *args):
-        """
-        Python 2 & 3 portable wrapper of assertRaisesRegex(p)? function.
-
-        :param exp: Exception type expected to be raised by cb.
-        :param regex: Expected exception message
-        :param func: callable object under test
-        :param args: variable positional arguments
-        """
-        parent = super(ParseFunctionCode, self)
-
-        # Pylint does not appreciate that the super method called
-        # conditionally can be available in other Python version
-        # then that of Pylint.
-        # Workaround is to call the method via getattr.
-        # Pylint ignores that the method got via getattr is
-        # conditionally executed. Method has to be a callable.
-        # Hence, using a dummy callable for getattr default.
-        dummy = lambda *x: None
-        # First Python 3 assertRaisesRegex is checked, since Python 2
-        # assertRaisesRegexp is also available in Python 3 but is
-        # marked deprecated.
-        for name in ('assertRaisesRegex', 'assertRaisesRegexp'):
-            method = getattr(parent, name, dummy)
-            if method is not dummy:
-                method(exp, regex, func, *args)
-                break
-        else:
-            raise AttributeError(" 'ParseFunctionCode' object has no attribute"
-                                 " 'assertRaisesRegex' or 'assertRaisesRegexp'"
-                                )
-
     def test_no_function(self):
         """
         Test no test function found.
@@ -593,8 +541,8 @@
 '''
         stream = StringIOWrapper('test_suite_ut.function', data)
         err_msg = 'file: test_suite_ut.function - Test functions not found!'
-        self.assert_raises_regex(GeneratorInputError, err_msg,
-                                 parse_function_code, stream, [], [])
+        self.assertRaisesRegex(GeneratorInputError, err_msg,
+                               parse_function_code, stream, [], [])
 
     def test_no_end_case_comment(self):
         """
@@ -609,8 +557,8 @@
         stream = StringIOWrapper('test_suite_ut.function', data)
         err_msg = r'file: test_suite_ut.function - '\
                   'end case pattern .*? not found!'
-        self.assert_raises_regex(GeneratorInputError, err_msg,
-                                 parse_function_code, stream, [], [])
+        self.assertRaisesRegex(GeneratorInputError, err_msg,
+                               parse_function_code, stream, [], [])
 
     @patch("generate_test_code.parse_function_arguments")
     def test_function_called(self,
@@ -727,8 +675,8 @@
         data = 'int entropy_threshold( char * a, data_t * h, int result )'
         err_msg = 'file: test_suite_ut.function - Test functions not found!'
         stream = StringIOWrapper('test_suite_ut.function', data)
-        self.assert_raises_regex(GeneratorInputError, err_msg,
-                                 parse_function_code, stream, [], [])
+        self.assertRaisesRegex(GeneratorInputError, err_msg,
+                               parse_function_code, stream, [], [])
 
     @patch("generate_test_code.gen_dispatch")
     @patch("generate_test_code.gen_dependencies")
diff --git a/third_party/mbedtls/repo/tests/scripts/test_psa_compliance.py b/third_party/mbedtls/repo/tests/scripts/test_psa_compliance.py
new file mode 100755
index 0000000..3b5205e
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/scripts/test_psa_compliance.py
@@ -0,0 +1,146 @@
+#!/usr/bin/env python3
+"""Run the PSA Cryto API compliance test suite.
+Clone the repo and check out the commit specified by PSA_ARCH_TEST_REPO and PSA_ARCH_TEST_REF,
+then complie and run the test suite. The clone is stored at <Mbed TLS root>/psa-arch-tests.
+Known defects in either the test suite or mbedtls - identified by their test number - are ignored,
+while unexpected failures AND successes are reported as errors,
+to help keep the list of known defects as up to date as possible.
+"""
+
+# 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.
+
+import os
+import re
+import shutil
+import subprocess
+import sys
+
+# PSA Compliance tests we expect to fail due to known defects in Mbed TLS (or the test suite)
+# The test numbers correspond to the numbers used by the console output of the test suite.
+# Test number 2xx corresponds to the files in the folder
+# psa-arch-tests/api-tests/dev_apis/crypto/test_c0xx
+EXPECTED_FAILURES = {
+    # Multipart AEAD is not supported in Mbed TLS 2.x.
+    252, 253, 254, 255, 256, 257, 258, 259, 260, 261,
+
+    # psa_hash_suspend() and psa_hash_resume() are not supported.
+    # - Tracked in issue #3274
+    262, 263
+}
+
+# We currently use a fork of ARM-software/psa-arch-tests, with a couple of downstream patches
+# that allow it to build with Mbed TLS 2, and fixes a couple of issues in the compliance test suite.
+# These fixes allow the tests numbered 216, 248 and 249 to complete successfully.
+#
+# Once all the fixes are upstreamed, this fork should be replaced with an upstream commit/tag.
+# - Tracked in issue #5145
+#
+# Web URL: https://github.com/bensze01/psa-arch-tests/tree/fixes-for-mbedtls-2
+PSA_ARCH_TESTS_REPO = 'https://github.com/bensze01/psa-arch-tests.git'
+PSA_ARCH_TESTS_REF = 'fixes-for-mbedtls-2'
+
+#pylint: disable=too-many-branches,too-many-statements
+def main():
+    mbedtls_dir = os.getcwd()
+
+    if not os.path.exists('library/libmbedcrypto.a'):
+        subprocess.check_call(['make', '-C', 'library', 'libmbedcrypto.a'])
+
+    psa_arch_tests_dir = 'psa-arch-tests'
+    os.makedirs(psa_arch_tests_dir, exist_ok=True)
+    try:
+        os.chdir(psa_arch_tests_dir)
+
+        # Reuse existing local clone
+        subprocess.check_call(['git', 'init'])
+        subprocess.check_call(['git', 'fetch', PSA_ARCH_TESTS_REPO, PSA_ARCH_TESTS_REF])
+        subprocess.check_call(['git', 'checkout', 'FETCH_HEAD'])
+
+        build_dir = 'api-tests/build'
+        try:
+            shutil.rmtree(build_dir)
+        except FileNotFoundError:
+            pass
+        os.mkdir(build_dir)
+        os.chdir(build_dir)
+
+        #pylint: disable=bad-continuation
+        subprocess.check_call([
+            'cmake', '..',
+                     '-GUnix Makefiles',
+                     '-DTARGET=tgt_dev_apis_stdc',
+                     '-DTOOLCHAIN=HOST_GCC',
+                     '-DSUITE=CRYPTO',
+                     '-DMISSING_CRYPTO_1_0=1',
+                     '-DPSA_CRYPTO_LIB_FILENAME={}/library/libmbedcrypto.a'.format(mbedtls_dir),
+                     '-DPSA_INCLUDE_PATHS={}/include'.format(mbedtls_dir)
+        ])
+        subprocess.check_call(['cmake', '--build', '.'])
+
+        proc = subprocess.Popen(['./psa-arch-tests-crypto'],
+                                bufsize=1, stdout=subprocess.PIPE, universal_newlines=True)
+
+        test_re = re.compile(
+            '^TEST: (?P<test_num>[0-9]*)|'
+            '^TEST RESULT: (?P<test_result>FAILED|PASSED)'
+        )
+        test = -1
+        unexpected_successes = set(EXPECTED_FAILURES)
+        expected_failures = []
+        unexpected_failures = []
+        for line in proc.stdout:
+            print(line, end='')
+            match = test_re.match(line)
+            if match is not None:
+                groupdict = match.groupdict()
+                test_num = groupdict['test_num']
+                if test_num is not None:
+                    test = int(test_num)
+                elif groupdict['test_result'] == 'FAILED':
+                    try:
+                        unexpected_successes.remove(test)
+                        expected_failures.append(test)
+                        print('Expected failure, ignoring')
+                    except KeyError:
+                        unexpected_failures.append(test)
+                        print('ERROR: Unexpected failure')
+                elif test in unexpected_successes:
+                    print('ERROR: Unexpected success')
+        proc.wait()
+
+        print()
+        print('***** test_psa_compliance.py report ******')
+        print()
+        print('Expected failures:', ', '.join(str(i) for i in expected_failures))
+        print('Unexpected failures:', ', '.join(str(i) for i in unexpected_failures))
+        print('Unexpected successes:', ', '.join(str(i) for i in sorted(unexpected_successes)))
+        print()
+        if unexpected_successes or unexpected_failures:
+            if unexpected_successes:
+                print('Unexpected successes encountered.')
+                print('Please remove the corresponding tests from '
+                      'EXPECTED_FAILURES in tests/scripts/compliance_test.py')
+                print()
+            print('FAILED')
+            return 1
+        else:
+            print('SUCCESS')
+            return 0
+    finally:
+        os.chdir(mbedtls_dir)
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/third_party/mbedtls/repo/tests/scripts/test_psa_constant_names.py b/third_party/mbedtls/repo/tests/scripts/test_psa_constant_names.py
index c7011a7..07c8ab2 100755
--- a/third_party/mbedtls/repo/tests/scripts/test_psa_constant_names.py
+++ b/third_party/mbedtls/repo/tests/scripts/test_psa_constant_names.py
@@ -24,353 +24,63 @@
 
 import argparse
 from collections import namedtuple
-import itertools
 import os
-import platform
 import re
 import subprocess
 import sys
-import tempfile
+from typing import Iterable, List, Optional, Tuple
 
-class ReadFileLineException(Exception):
-    def __init__(self, filename, line_number):
-        message = 'in {} at {}'.format(filename, line_number)
-        super(ReadFileLineException, self).__init__(message)
-        self.filename = filename
-        self.line_number = line_number
+import scripts_path # pylint: disable=unused-import
+from mbedtls_dev import c_build_helper
+from mbedtls_dev.macro_collector import InputsForTest, PSAMacroEnumerator
+from mbedtls_dev import typing_util
 
-class read_file_lines:
-    # Dear Pylint, conventionally, a context manager class name is lowercase.
-    # pylint: disable=invalid-name,too-few-public-methods
-    """Context manager to read a text file line by line.
-
-    ```
-    with read_file_lines(filename) as lines:
-        for line in lines:
-            process(line)
-    ```
-    is equivalent to
-    ```
-    with open(filename, 'r') as input_file:
-        for line in input_file:
-            process(line)
-    ```
-    except that if process(line) raises an exception, then the read_file_lines
-    snippet annotates the exception with the file name and line number.
-    """
-    def __init__(self, filename, binary=False):
-        self.filename = filename
-        self.line_number = 'entry'
-        self.generator = None
-        self.binary = binary
-    def __enter__(self):
-        self.generator = enumerate(open(self.filename,
-                                        'rb' if self.binary else 'r'))
-        return self
-    def __iter__(self):
-        for line_number, content in self.generator:
-            self.line_number = line_number
-            yield content
-        self.line_number = 'exit'
-    def __exit__(self, exc_type, exc_value, exc_traceback):
-        if exc_type is not None:
-            raise ReadFileLineException(self.filename, self.line_number) \
-                from exc_value
-
-class Inputs:
-    # pylint: disable=too-many-instance-attributes
-    """Accumulate information about macros to test.
-
-    This includes macro names as well as information about their arguments
-    when applicable.
-    """
-
-    def __init__(self):
-        self.all_declared = set()
-        # Sets of names per type
-        self.statuses = set(['PSA_SUCCESS'])
-        self.algorithms = set(['0xffffffff'])
-        self.ecc_curves = set(['0xff'])
-        self.dh_groups = set(['0xff'])
-        self.key_types = set(['0xffff'])
-        self.key_usage_flags = set(['0x80000000'])
-        # Hard-coded value for unknown algorithms
-        self.hash_algorithms = set(['0x020000fe'])
-        self.mac_algorithms = set(['0x0300ffff'])
-        self.ka_algorithms = set(['0x09fc0000'])
-        self.kdf_algorithms = set(['0x080000ff'])
-        # For AEAD algorithms, the only variability is over the tag length,
-        # and this only applies to known algorithms, so don't test an
-        # unknown algorithm.
-        self.aead_algorithms = set()
-        # Identifier prefixes
-        self.table_by_prefix = {
-            'ERROR': self.statuses,
-            'ALG': self.algorithms,
-            'ECC_CURVE': self.ecc_curves,
-            'DH_GROUP': self.dh_groups,
-            'KEY_TYPE': self.key_types,
-            'KEY_USAGE': self.key_usage_flags,
-        }
-        # Test functions
-        self.table_by_test_function = {
-            # Any function ending in _algorithm also gets added to
-            # self.algorithms.
-            'key_type': [self.key_types],
-            'block_cipher_key_type': [self.key_types],
-            'stream_cipher_key_type': [self.key_types],
-            'ecc_key_family': [self.ecc_curves],
-            'ecc_key_types': [self.ecc_curves],
-            'dh_key_family': [self.dh_groups],
-            'dh_key_types': [self.dh_groups],
-            'hash_algorithm': [self.hash_algorithms],
-            'mac_algorithm': [self.mac_algorithms],
-            'cipher_algorithm': [],
-            'hmac_algorithm': [self.mac_algorithms],
-            'aead_algorithm': [self.aead_algorithms],
-            'key_derivation_algorithm': [self.kdf_algorithms],
-            'key_agreement_algorithm': [self.ka_algorithms],
-            'asymmetric_signature_algorithm': [],
-            'asymmetric_signature_wildcard': [self.algorithms],
-            'asymmetric_encryption_algorithm': [],
-            'other_algorithm': [],
-        }
-        # macro name -> list of argument names
-        self.argspecs = {}
-        # argument name -> list of values
-        self.arguments_for = {
-            'mac_length': ['1', '63'],
-            'tag_length': ['1', '63'],
-        }
-
-    def get_names(self, type_word):
-        """Return the set of known names of values of the given type."""
-        return {
-            'status': self.statuses,
-            'algorithm': self.algorithms,
-            'ecc_curve': self.ecc_curves,
-            'dh_group': self.dh_groups,
-            'key_type': self.key_types,
-            'key_usage': self.key_usage_flags,
-        }[type_word]
-
-    def gather_arguments(self):
-        """Populate the list of values for macro arguments.
-
-        Call this after parsing all the inputs.
-        """
-        self.arguments_for['hash_alg'] = sorted(self.hash_algorithms)
-        self.arguments_for['mac_alg'] = sorted(self.mac_algorithms)
-        self.arguments_for['ka_alg'] = sorted(self.ka_algorithms)
-        self.arguments_for['kdf_alg'] = sorted(self.kdf_algorithms)
-        self.arguments_for['aead_alg'] = sorted(self.aead_algorithms)
-        self.arguments_for['curve'] = sorted(self.ecc_curves)
-        self.arguments_for['group'] = sorted(self.dh_groups)
-
-    @staticmethod
-    def _format_arguments(name, arguments):
-        """Format a macro call with arguments.."""
-        return name + '(' + ', '.join(arguments) + ')'
-
-    def distribute_arguments(self, name):
-        """Generate macro calls with each tested argument set.
-
-        If name is a macro without arguments, just yield "name".
-        If name is a macro with arguments, yield a series of
-        "name(arg1,...,argN)" where each argument takes each possible
-        value at least once.
-        """
-        try:
-            if name not in self.argspecs:
-                yield name
-                return
-            argspec = self.argspecs[name]
-            if argspec == []:
-                yield name + '()'
-                return
-            argument_lists = [self.arguments_for[arg] for arg in argspec]
-            arguments = [values[0] for values in argument_lists]
-            yield self._format_arguments(name, arguments)
-            # Dear Pylint, enumerate won't work here since we're modifying
-            # the array.
-            # pylint: disable=consider-using-enumerate
-            for i in range(len(arguments)):
-                for value in argument_lists[i][1:]:
-                    arguments[i] = value
-                    yield self._format_arguments(name, arguments)
-                arguments[i] = argument_lists[0][0]
-        except BaseException as e:
-            raise Exception('distribute_arguments({})'.format(name)) from e
-
-    def generate_expressions(self, names):
-        return itertools.chain(*map(self.distribute_arguments, names))
-
-    _argument_split_re = re.compile(r' *, *')
-    @classmethod
-    def _argument_split(cls, arguments):
-        return re.split(cls._argument_split_re, arguments)
-
-    # Regex for interesting header lines.
-    # Groups: 1=macro name, 2=type, 3=argument list (optional).
-    _header_line_re = \
-        re.compile(r'#define +' +
-                   r'(PSA_((?:(?:DH|ECC|KEY)_)?[A-Z]+)_\w+)' +
-                   r'(?:\(([^\n()]*)\))?')
-    # Regex of macro names to exclude.
-    _excluded_name_re = re.compile(r'_(?:GET|IS|OF)_|_(?:BASE|FLAG|MASK)\Z')
-    # Additional excluded macros.
-    _excluded_names = set([
-        # Macros that provide an alternative way to build the same
-        # algorithm as another macro.
-        'PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH',
-        'PSA_ALG_FULL_LENGTH_MAC',
-        # Auxiliary macro whose name doesn't fit the usual patterns for
-        # auxiliary macros.
-        'PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE',
-    ])
-    def parse_header_line(self, line):
-        """Parse a C header line, looking for "#define PSA_xxx"."""
-        m = re.match(self._header_line_re, line)
-        if not m:
-            return
-        name = m.group(1)
-        self.all_declared.add(name)
-        if re.search(self._excluded_name_re, name) or \
-           name in self._excluded_names:
-            return
-        dest = self.table_by_prefix.get(m.group(2))
-        if dest is None:
-            return
-        dest.add(name)
-        if m.group(3):
-            self.argspecs[name] = self._argument_split(m.group(3))
-
-    _nonascii_re = re.compile(rb'[^\x00-\x7f]+')
-    def parse_header(self, filename):
-        """Parse a C header file, looking for "#define PSA_xxx"."""
-        with read_file_lines(filename, binary=True) as lines:
-            for line in lines:
-                line = re.sub(self._nonascii_re, rb'', line).decode('ascii')
-                self.parse_header_line(line)
-
-    _macro_identifier_re = re.compile(r'[A-Z]\w+')
-    def generate_undeclared_names(self, expr):
-        for name in re.findall(self._macro_identifier_re, expr):
-            if name not in self.all_declared:
-                yield name
-
-    def accept_test_case_line(self, function, argument):
-        #pylint: disable=unused-argument
-        undeclared = list(self.generate_undeclared_names(argument))
-        if undeclared:
-            raise Exception('Undeclared names in test case', undeclared)
-        return True
-
-    def add_test_case_line(self, function, argument):
-        """Parse a test case data line, looking for algorithm metadata tests."""
-        sets = []
-        if function.endswith('_algorithm'):
-            sets.append(self.algorithms)
-            if function == 'key_agreement_algorithm' and \
-               argument.startswith('PSA_ALG_KEY_AGREEMENT('):
-                # We only want *raw* key agreement algorithms as such, so
-                # exclude ones that are already chained with a KDF.
-                # Keep the expression as one to test as an algorithm.
-                function = 'other_algorithm'
-        sets += self.table_by_test_function[function]
-        if self.accept_test_case_line(function, argument):
-            for s in sets:
-                s.add(argument)
-
-    # Regex matching a *.data line containing a test function call and
-    # its arguments. The actual definition is partly positional, but this
-    # regex is good enough in practice.
-    _test_case_line_re = re.compile(r'(?!depends_on:)(\w+):([^\n :][^:\n]*)')
-    def parse_test_cases(self, filename):
-        """Parse a test case file (*.data), looking for algorithm metadata tests."""
-        with read_file_lines(filename) as lines:
-            for line in lines:
-                m = re.match(self._test_case_line_re, line)
-                if m:
-                    self.add_test_case_line(m.group(1), m.group(2))
-
-def gather_inputs(headers, test_suites, inputs_class=Inputs):
+def gather_inputs(headers: Iterable[str],
+                  test_suites: Iterable[str],
+                  inputs_class=InputsForTest) -> PSAMacroEnumerator:
     """Read the list of inputs to test psa_constant_names with."""
     inputs = inputs_class()
     for header in headers:
         inputs.parse_header(header)
     for test_cases in test_suites:
         inputs.parse_test_cases(test_cases)
+    inputs.add_numerical_values()
     inputs.gather_arguments()
     return inputs
 
-def remove_file_if_exists(filename):
-    """Remove the specified file, ignoring errors."""
-    if not filename:
-        return
-    try:
-        os.remove(filename)
-    except OSError:
-        pass
-
-def run_c(type_word, expressions, include_path=None, keep_c=False):
-    """Generate and run a program to print out numerical values for expressions."""
-    if include_path is None:
-        include_path = []
+def run_c(type_word: str,
+          expressions: Iterable[str],
+          include_path: Optional[str] = None,
+          keep_c: bool = False) -> List[str]:
+    """Generate and run a program to print out numerical values of C expressions."""
     if type_word == 'status':
         cast_to = 'long'
         printf_format = '%ld'
     else:
         cast_to = 'unsigned long'
         printf_format = '0x%08lx'
-    c_name = None
-    exe_name = None
-    try:
-        c_fd, c_name = tempfile.mkstemp(prefix='tmp-{}-'.format(type_word),
-                                        suffix='.c',
-                                        dir='programs/psa')
-        exe_suffix = '.exe' if platform.system() == 'Windows' else ''
-        exe_name = c_name[:-2] + exe_suffix
-        remove_file_if_exists(exe_name)
-        c_file = os.fdopen(c_fd, 'w', encoding='ascii')
-        c_file.write('/* Generated by test_psa_constant_names.py for {} values */'
-                     .format(type_word))
-        c_file.write('''
-#include <stdio.h>
-#include <psa/crypto.h>
-int main(void)
-{
-''')
-        for expr in expressions:
-            c_file.write('    printf("{}\\n", ({}) {});\n'
-                         .format(printf_format, cast_to, expr))
-        c_file.write('''    return 0;
-}
-''')
-        c_file.close()
-        cc = os.getenv('CC', 'cc')
-        subprocess.check_call([cc] +
-                              ['-I' + dir for dir in include_path] +
-                              ['-o', exe_name, c_name])
-        if keep_c:
-            sys.stderr.write('List of {} tests kept at {}\n'
-                             .format(type_word, c_name))
-        else:
-            os.remove(c_name)
-        output = subprocess.check_output([exe_name])
-        return output.decode('ascii').strip().split('\n')
-    finally:
-        remove_file_if_exists(exe_name)
+    return c_build_helper.get_c_expression_values(
+        cast_to, printf_format,
+        expressions,
+        caller='test_psa_constant_names.py for {} values'.format(type_word),
+        file_label=type_word,
+        header='#include <psa/crypto.h>',
+        include_path=include_path,
+        keep_c=keep_c
+    )
 
 NORMALIZE_STRIP_RE = re.compile(r'\s+')
-def normalize(expr):
+def normalize(expr: str) -> str:
     """Normalize the C expression so as not to care about trivial differences.
 
     Currently "trivial differences" means whitespace.
     """
     return re.sub(NORMALIZE_STRIP_RE, '', expr)
 
-def collect_values(inputs, type_word, include_path=None, keep_c=False):
+def collect_values(inputs: InputsForTest,
+                   type_word: str,
+                   include_path: Optional[str] = None,
+                   keep_c: bool = False) -> Tuple[List[str], List[str]]:
     """Generate expressions using known macro names and calculate their values.
 
     Return a list of pairs of (expr, value) where expr is an expression and
@@ -388,12 +98,12 @@
     Error = namedtuple('Error',
                        ['type', 'expression', 'value', 'output'])
 
-    def __init__(self, options):
+    def __init__(self, options) -> None:
         self.options = options
         self.count = 0
-        self.errors = []
+        self.errors = [] #type: List[Tests.Error]
 
-    def run_one(self, inputs, type_word):
+    def run_one(self, inputs: InputsForTest, type_word: str) -> None:
         """Test psa_constant_names for the specified type.
 
         Run the program on the names for this type.
@@ -403,9 +113,10 @@
         expressions, values = collect_values(inputs, type_word,
                                              include_path=self.options.include,
                                              keep_c=self.options.keep_c)
-        output = subprocess.check_output([self.options.program, type_word] +
-                                         values)
-        outputs = output.decode('ascii').strip().split('\n')
+        output_bytes = subprocess.check_output([self.options.program,
+                                                type_word] + values)
+        output = output_bytes.decode('ascii')
+        outputs = output.strip().split('\n')
         self.count += len(expressions)
         for expr, value, output in zip(expressions, values, outputs):
             if self.options.show:
@@ -416,13 +127,13 @@
                                               value=value,
                                               output=output))
 
-    def run_all(self, inputs):
+    def run_all(self, inputs: InputsForTest) -> None:
         """Run psa_constant_names on all the gathered inputs."""
         for type_word in ['status', 'algorithm', 'ecc_curve', 'dh_group',
                           'key_type', 'key_usage']:
             self.run_one(inputs, type_word)
 
-    def report(self, out):
+    def report(self, out: typing_util.Writable) -> None:
         """Describe each case where the output is not as expected.
 
         Write the errors to ``out``.
@@ -457,7 +168,7 @@
                         help='Program to test')
     parser.add_argument('--show',
                         action='store_true',
-                        help='Keep the intermediate C file')
+                        help='Show tested values on stdout')
     parser.add_argument('--no-show',
                         action='store_false', dest='show',
                         help='Don\'t show tested values (default)')
diff --git a/third_party/mbedtls/repo/tests/src/asn1_helpers.c b/third_party/mbedtls/repo/tests/src/asn1_helpers.c
new file mode 100644
index 0000000..79aa166
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/src/asn1_helpers.c
@@ -0,0 +1,74 @@
+/** \file asn1_helpers.c
+ *
+ * \brief Helper functions for tests that manipulate ASN.1 data.
+ */
+
+/*
+ *  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 <test/helpers.h>
+#include <test/macros.h>
+
+#if defined(MBEDTLS_ASN1_PARSE_C)
+
+#include <mbedtls/asn1.h>
+
+int mbedtls_test_asn1_skip_integer( unsigned char **p, const unsigned char *end,
+                                    size_t min_bits, size_t max_bits,
+                                    int must_be_odd )
+{
+    size_t len;
+    size_t actual_bits;
+    unsigned char msb;
+    TEST_EQUAL( mbedtls_asn1_get_tag( p, end, &len,
+                                      MBEDTLS_ASN1_INTEGER ),
+                0 );
+
+    /* Check if the retrieved length doesn't extend the actual buffer's size.
+     * It is assumed here, that end >= p, which validates casting to size_t. */
+    TEST_ASSERT( len <= (size_t)( end - *p) );
+
+    /* Tolerate a slight departure from DER encoding:
+     * - 0 may be represented by an empty string or a 1-byte string.
+     * - The sign bit may be used as a value bit. */
+    if( ( len == 1 && ( *p )[0] == 0 ) ||
+        ( len > 1 && ( *p )[0] == 0 && ( ( *p )[1] & 0x80 ) != 0 ) )
+    {
+        ++( *p );
+        --len;
+    }
+    if( min_bits == 0 && len == 0 )
+        return( 1 );
+    msb = ( *p )[0];
+    TEST_ASSERT( msb != 0 );
+    actual_bits = 8 * ( len - 1 );
+    while( msb != 0 )
+    {
+        msb >>= 1;
+        ++actual_bits;
+    }
+    TEST_ASSERT( actual_bits >= min_bits );
+    TEST_ASSERT( actual_bits <= max_bits );
+    if( must_be_odd )
+        TEST_ASSERT( ( ( *p )[len-1] & 1 ) != 0 );
+    *p += len;
+    return( 1 );
+exit:
+    return( 0 );
+}
+
+#endif /* MBEDTLS_ASN1_PARSE_C */
diff --git a/third_party/mbedtls/repo/tests/src/drivers/cipher.c b/third_party/mbedtls/repo/tests/src/drivers/cipher.c
deleted file mode 100644
index fa7c6a9..0000000
--- a/third_party/mbedtls/repo/tests/src/drivers/cipher.c
+++ /dev/null
@@ -1,611 +0,0 @@
-/*
- * Test driver for cipher functions.
- * Currently only supports multi-part operations using AES-CTR.
- */
-/*  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.
- */
-
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
-
-#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
-#include "psa/crypto.h"
-#include "psa_crypto_core.h"
-#include "mbedtls/cipher.h"
-
-#include "test/drivers/cipher.h"
-
-#include "test/random.h"
-
-#include <string.h>
-
-/* Test driver implements AES-CTR only. Its default behaviour (when its return
- * status is not overridden through the hooks) is to take care of all AES-CTR
- * operations, and return PSA_ERROR_NOT_SUPPORTED for all others.
- * Set test_driver_cipher_hooks.forced_status to PSA_ERROR_NOT_SUPPORTED to use
- * fallback even for AES-CTR. */
-test_driver_cipher_hooks_t test_driver_cipher_hooks = TEST_DRIVER_CIPHER_INIT;
-
-static psa_status_t test_transparent_cipher_oneshot(
-    mbedtls_operation_t direction,
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg,
-    const uint8_t *input, size_t input_length,
-    uint8_t *output, size_t output_size, size_t *output_length)
-{
-    test_driver_cipher_hooks.hits++;
-
-    /* Test driver supports AES-CTR only, to verify operation calls. */
-    if( alg != PSA_ALG_CTR ||
-        psa_get_key_type( attributes ) != PSA_KEY_TYPE_AES )
-        return( PSA_ERROR_NOT_SUPPORTED );
-
-    /* If test driver response code is not SUCCESS, we can return early */
-    if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
-        return( test_driver_cipher_hooks.forced_status );
-
-    /* If test driver output is overridden, we don't need to do actual crypto */
-    if( test_driver_cipher_hooks.forced_output != NULL )
-    {
-        if( output_size < test_driver_cipher_hooks.forced_output_length )
-            return( PSA_ERROR_BUFFER_TOO_SMALL );
-
-        memcpy( output,
-                test_driver_cipher_hooks.forced_output,
-                test_driver_cipher_hooks.forced_output_length );
-        *output_length = test_driver_cipher_hooks.forced_output_length;
-
-        return( test_driver_cipher_hooks.forced_status );
-    }
-
-    /* Run AES-CTR using the cipher module */
-    {
-        mbedtls_test_rnd_pseudo_info rnd_info;
-        memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
-
-        const mbedtls_cipher_info_t *cipher_info =
-            mbedtls_cipher_info_from_values( MBEDTLS_CIPHER_ID_AES,
-                                             key_length * 8,
-                                             MBEDTLS_MODE_CTR );
-        mbedtls_cipher_context_t cipher;
-        int ret = 0;
-        uint8_t temp_output_buffer[16] = {0};
-        size_t temp_output_length = 0;
-
-        if( direction == MBEDTLS_ENCRYPT )
-        {
-            /* Oneshot encrypt needs to prepend the IV to the output */
-            if( output_size < ( input_length + 16 ) )
-                return( PSA_ERROR_BUFFER_TOO_SMALL );
-        }
-        else
-        {
-            /* Oneshot decrypt has the IV prepended to the input */
-            if( output_size < ( input_length - 16 ) )
-                return( PSA_ERROR_BUFFER_TOO_SMALL );
-        }
-
-        if( cipher_info == NULL )
-            return( PSA_ERROR_NOT_SUPPORTED );
-
-        mbedtls_cipher_init( &cipher );
-        ret = mbedtls_cipher_setup( &cipher, cipher_info );
-        if( ret != 0 )
-            goto exit;
-
-        ret = mbedtls_cipher_setkey( &cipher,
-                                     key,
-                                     key_length * 8, direction );
-        if( ret != 0 )
-            goto exit;
-
-        if( direction == MBEDTLS_ENCRYPT )
-        {
-            mbedtls_test_rnd_pseudo_info rnd_info;
-            memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
-
-            ret = mbedtls_test_rnd_pseudo_rand( &rnd_info,
-                                                temp_output_buffer,
-                                                16 );
-            if( ret != 0 )
-                goto exit;
-
-            ret = mbedtls_cipher_set_iv( &cipher, temp_output_buffer, 16 );
-        }
-        else
-            ret = mbedtls_cipher_set_iv( &cipher, input, 16 );
-
-        if( ret != 0 )
-            goto exit;
-
-        if( direction == MBEDTLS_ENCRYPT )
-        {
-            ret = mbedtls_cipher_update( &cipher,
-                                         input, input_length,
-                                         &output[16], output_length );
-            if( ret == 0 )
-            {
-                memcpy( output, temp_output_buffer, 16 );
-                *output_length += 16;
-            }
-        }
-        else
-            ret = mbedtls_cipher_update( &cipher,
-                                         &input[16], input_length - 16,
-                                         output, output_length );
-
-        if( ret != 0 )
-            goto exit;
-
-        ret = mbedtls_cipher_finish( &cipher,
-                                     temp_output_buffer,
-                                     &temp_output_length );
-
-exit:
-        if( ret != 0 )
-        {
-            *output_length = 0;
-            memset(output, 0, output_size);
-        }
-
-        mbedtls_cipher_free( &cipher );
-        return( mbedtls_to_psa_error( ret ) );
-    }
-}
-
-psa_status_t test_transparent_cipher_encrypt(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg,
-    const uint8_t *input, size_t input_length,
-    uint8_t *output, size_t output_size, size_t *output_length)
-{
-    return (
-        test_transparent_cipher_oneshot(
-            MBEDTLS_ENCRYPT,
-            attributes,
-            key, key_length,
-            alg,
-            input, input_length,
-            output, output_size, output_length) );
-}
-
-psa_status_t test_transparent_cipher_decrypt(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg,
-    const uint8_t *input, size_t input_length,
-    uint8_t *output, size_t output_size, size_t *output_length)
-{
-    return (
-        test_transparent_cipher_oneshot(
-            MBEDTLS_DECRYPT,
-            attributes,
-            key, key_length,
-            alg,
-            input, input_length,
-            output, output_size, output_length) );
-}
-
-static psa_status_t test_transparent_cipher_setup(
-    mbedtls_operation_t direction,
-    test_transparent_cipher_operation_t *operation,
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg)
-{
-    const mbedtls_cipher_info_t *cipher_info = NULL;
-    int ret = 0;
-
-    test_driver_cipher_hooks.hits++;
-
-    if( operation->alg != 0 )
-        return( PSA_ERROR_BAD_STATE );
-
-    /* Wiping the entire struct here, instead of member-by-member. This is useful
-     * for the test suite, since it gives a chance of catching memory corruption
-     * errors should the core not have allocated (enough) memory for our context
-     * struct. */
-    memset( operation, 0, sizeof( *operation ) );
-
-    /* Allow overriding return value for testing purposes */
-    if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
-        return( test_driver_cipher_hooks.forced_status );
-
-    /* Test driver supports AES-CTR only, to verify operation calls. */
-    if( alg != PSA_ALG_CTR ||
-        psa_get_key_type( attributes ) != PSA_KEY_TYPE_AES )
-        return( PSA_ERROR_NOT_SUPPORTED );
-
-    operation->alg = alg;
-    operation->iv_size = 16;
-
-    cipher_info = mbedtls_cipher_info_from_values( MBEDTLS_CIPHER_ID_AES,
-                                                   key_length * 8,
-                                                   MBEDTLS_MODE_CTR );
-    if( cipher_info == NULL )
-        return( PSA_ERROR_NOT_SUPPORTED );
-
-    mbedtls_cipher_init( &operation->cipher );
-    ret = mbedtls_cipher_setup( &operation->cipher, cipher_info );
-    if( ret != 0 ) {
-        mbedtls_cipher_free( &operation->cipher );
-        return( mbedtls_to_psa_error( ret ) );
-    }
-
-    ret = mbedtls_cipher_setkey( &operation->cipher,
-                                 key,
-                                 key_length * 8, direction );
-    if( ret != 0 ) {
-        mbedtls_cipher_free( &operation->cipher );
-        return( mbedtls_to_psa_error( ret ) );
-    }
-
-    operation->iv_set = 0;
-    operation->iv_required = 1;
-    operation->key_set = 1;
-
-    return( test_driver_cipher_hooks.forced_status );
-}
-
-psa_status_t test_transparent_cipher_encrypt_setup(
-    test_transparent_cipher_operation_t *operation,
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg)
-{
-    return ( test_transparent_cipher_setup( MBEDTLS_ENCRYPT,
-                                            operation,
-                                            attributes,
-                                            key,
-                                            key_length,
-                                            alg ) );
-}
-
-psa_status_t test_transparent_cipher_decrypt_setup(
-    test_transparent_cipher_operation_t *operation,
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg)
-{
-    return ( test_transparent_cipher_setup( MBEDTLS_DECRYPT,
-                                            operation,
-                                            attributes,
-                                            key,
-                                            key_length,
-                                            alg ) );
-}
-
-psa_status_t test_transparent_cipher_abort(
-    test_transparent_cipher_operation_t *operation)
-{
-    test_driver_cipher_hooks.hits++;
-
-    if( operation->alg == 0 )
-        return( PSA_SUCCESS );
-    if( operation->alg != PSA_ALG_CTR )
-        return( PSA_ERROR_BAD_STATE );
-
-    mbedtls_cipher_free( &operation->cipher );
-
-    /* Wiping the entire struct here, instead of member-by-member. This is useful
-     * for the test suite, since it gives a chance of catching memory corruption
-     * errors should the core not have allocated (enough) memory for our context
-     * struct. */
-    memset( operation, 0, sizeof( *operation ) );
-
-    return( PSA_SUCCESS );
-}
-
-psa_status_t test_transparent_cipher_generate_iv(
-    test_transparent_cipher_operation_t *operation,
-    uint8_t *iv,
-    size_t iv_size,
-    size_t *iv_length)
-{
-    psa_status_t status;
-    mbedtls_test_rnd_pseudo_info rnd_info;
-    memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
-
-    test_driver_cipher_hooks.hits++;
-
-    if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
-        return( test_driver_cipher_hooks.forced_status );
-
-    if( operation->alg != PSA_ALG_CTR )
-        return( PSA_ERROR_BAD_STATE );
-
-    if( operation->iv_set || ! operation->iv_required )
-        return( PSA_ERROR_BAD_STATE );
-
-    if( iv_size < operation->iv_size )
-        return( PSA_ERROR_BUFFER_TOO_SMALL );
-
-    status = mbedtls_to_psa_error(
-        mbedtls_test_rnd_pseudo_rand( &rnd_info,
-                                      iv,
-                                      operation->iv_size ) );
-    if( status != PSA_SUCCESS )
-        return( status );
-
-    *iv_length = operation->iv_size;
-    status = test_transparent_cipher_set_iv( operation, iv, *iv_length );
-
-    return( status );
-}
-
-psa_status_t test_transparent_cipher_set_iv(
-    test_transparent_cipher_operation_t *operation,
-    const uint8_t *iv,
-    size_t iv_length)
-{
-    psa_status_t status;
-
-    test_driver_cipher_hooks.hits++;
-
-    if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
-        return( test_driver_cipher_hooks.forced_status );
-
-    if( operation->alg != PSA_ALG_CTR )
-        return( PSA_ERROR_BAD_STATE );
-
-    if( operation->iv_set || ! operation->iv_required )
-        return( PSA_ERROR_BAD_STATE );
-
-    if( iv_length != operation->iv_size )
-        return( PSA_ERROR_INVALID_ARGUMENT );
-
-    status = mbedtls_to_psa_error(
-        mbedtls_cipher_set_iv( &operation->cipher, iv, iv_length ) );
-
-    if( status == PSA_SUCCESS )
-        operation->iv_set = 1;
-
-    return( status );
-}
-
-psa_status_t test_transparent_cipher_update(
-    test_transparent_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;
-
-    test_driver_cipher_hooks.hits++;
-
-    if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
-        return( test_driver_cipher_hooks.forced_status );
-
-    if( operation->alg != PSA_ALG_CTR )
-        return( PSA_ERROR_BAD_STATE );
-
-    /* CTR is a stream cipher, so data in and out are always the same size */
-    if( output_size < input_length )
-        return( PSA_ERROR_BUFFER_TOO_SMALL );
-
-    status = mbedtls_to_psa_error(
-        mbedtls_cipher_update( &operation->cipher, input,
-                               input_length, output, output_length ) );
-
-    if( status != PSA_SUCCESS )
-        return status;
-
-    if( test_driver_cipher_hooks.forced_output != NULL )
-    {
-        if( output_size < test_driver_cipher_hooks.forced_output_length )
-            return PSA_ERROR_BUFFER_TOO_SMALL;
-
-        memcpy( output,
-                test_driver_cipher_hooks.forced_output,
-                test_driver_cipher_hooks.forced_output_length );
-        *output_length = test_driver_cipher_hooks.forced_output_length;
-    }
-
-    return( test_driver_cipher_hooks.forced_status );
-}
-
-psa_status_t test_transparent_cipher_finish(
-    test_transparent_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];
-
-    test_driver_cipher_hooks.hits++;
-
-    if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
-        return( test_driver_cipher_hooks.forced_status );
-
-    if( operation->alg != PSA_ALG_CTR )
-        return( PSA_ERROR_BAD_STATE );
-
-    if( ! operation->key_set )
-        return( PSA_ERROR_BAD_STATE );
-
-    if( operation->iv_required && ! operation->iv_set )
-        return( PSA_ERROR_BAD_STATE );
-
-    status = mbedtls_to_psa_error(
-        mbedtls_cipher_finish( &operation->cipher,
-                               temp_output_buffer,
-                               output_length ) );
-
-    mbedtls_cipher_free( &operation->cipher );
-
-    if( status != PSA_SUCCESS )
-        return( status );
-
-    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
-        return( PSA_ERROR_BUFFER_TOO_SMALL );
-
-
-    if( test_driver_cipher_hooks.forced_output != NULL )
-    {
-        if( output_size < test_driver_cipher_hooks.forced_output_length )
-            return PSA_ERROR_BUFFER_TOO_SMALL;
-
-        memcpy( output,
-                test_driver_cipher_hooks.forced_output,
-                test_driver_cipher_hooks.forced_output_length );
-        *output_length = test_driver_cipher_hooks.forced_output_length;
-    }
-
-    return( test_driver_cipher_hooks.forced_status );
-}
-
-/*
- * opaque versions, to do
- */
-psa_status_t test_opaque_cipher_encrypt(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg,
-    const uint8_t *input, size_t input_length,
-    uint8_t *output, size_t output_size, size_t *output_length)
-{
-    (void) attributes;
-    (void) key;
-    (void) key_length;
-    (void) alg;
-    (void) input;
-    (void) input_length;
-    (void) output;
-    (void) output_size;
-    (void) output_length;
-    return( PSA_ERROR_NOT_SUPPORTED );
-}
-
-psa_status_t test_opaque_cipher_decrypt(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg,
-    const uint8_t *input, size_t input_length,
-    uint8_t *output, size_t output_size, size_t *output_length)
-{
-    (void) attributes;
-    (void) key;
-    (void) key_length;
-    (void) alg;
-    (void) input;
-    (void) input_length;
-    (void) output;
-    (void) output_size;
-    (void) output_length;
-    return( PSA_ERROR_NOT_SUPPORTED );
-}
-
-psa_status_t test_opaque_cipher_encrypt_setup(
-    test_opaque_cipher_operation_t *operation,
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg)
-{
-    (void) operation;
-    (void) attributes;
-    (void) key;
-    (void) key_length;
-    (void) alg;
-    return( PSA_ERROR_NOT_SUPPORTED );
-}
-
-psa_status_t test_opaque_cipher_decrypt_setup(
-    test_opaque_cipher_operation_t *operation,
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg)
-{
-    (void) operation;
-    (void) attributes;
-    (void) key;
-    (void) key_length;
-    (void) alg;
-    return( PSA_ERROR_NOT_SUPPORTED );
-}
-
-psa_status_t test_opaque_cipher_abort(
-    test_opaque_cipher_operation_t *operation)
-{
-    (void) operation;
-    return( PSA_ERROR_NOT_SUPPORTED );
-}
-
-psa_status_t test_opaque_cipher_generate_iv(
-    test_opaque_cipher_operation_t *operation,
-    uint8_t *iv,
-    size_t iv_size,
-    size_t *iv_length)
-{
-    (void) operation;
-    (void) iv;
-    (void) iv_size;
-    (void) iv_length;
-    return( PSA_ERROR_NOT_SUPPORTED );
-}
-
-psa_status_t test_opaque_cipher_set_iv(
-    test_opaque_cipher_operation_t *operation,
-    const uint8_t *iv,
-    size_t iv_length)
-{
-    (void) operation;
-    (void) iv;
-    (void) iv_length;
-    return( PSA_ERROR_NOT_SUPPORTED );
-}
-
-psa_status_t test_opaque_cipher_update(
-    test_opaque_cipher_operation_t *operation,
-    const uint8_t *input,
-    size_t input_length,
-    uint8_t *output,
-    size_t output_size,
-    size_t *output_length)
-{
-    (void) operation;
-    (void) input;
-    (void) input_length;
-    (void) output;
-    (void) output_size;
-    (void) output_length;
-    return( PSA_ERROR_NOT_SUPPORTED );
-}
-
-psa_status_t test_opaque_cipher_finish(
-    test_opaque_cipher_operation_t *operation,
-    uint8_t *output,
-    size_t output_size,
-    size_t *output_length)
-{
-    (void) operation;
-    (void) output;
-    (void) output_size;
-    (void) output_length;
-    return( PSA_ERROR_NOT_SUPPORTED );
-}
-#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/third_party/mbedtls/repo/tests/src/drivers/hash.c b/third_party/mbedtls/repo/tests/src/drivers/hash.c
new file mode 100644
index 0000000..0d59bee
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/src/drivers/hash.c
@@ -0,0 +1,233 @@
+/*
+ * Test driver for hash entry points.
+ */
+/*  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.
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
+#include "psa_crypto_hash.h"
+
+#include "test/drivers/hash.h"
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+#include "libtestdriver1/library/psa_crypto_hash.h"
+#endif
+
+mbedtls_test_driver_hash_hooks_t
+    mbedtls_test_driver_hash_hooks = MBEDTLS_TEST_DRIVER_HASH_INIT;
+
+psa_status_t mbedtls_test_transparent_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_test_driver_hash_hooks.hits++;
+
+    if( mbedtls_test_driver_hash_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_hash_hooks.driver_status =
+             mbedtls_test_driver_hash_hooks.forced_status;
+    }
+    else
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)
+        mbedtls_test_driver_hash_hooks.driver_status =
+            libtestdriver1_mbedtls_psa_hash_compute(
+                alg, input, input_length,
+                hash, hash_size, hash_length );
+#elif defined(MBEDTLS_PSA_BUILTIN_HASH)
+        mbedtls_test_driver_hash_hooks.driver_status =
+            mbedtls_psa_hash_compute(
+                alg, input, input_length,
+                hash, hash_size, hash_length );
+#else
+        (void) alg;
+        (void) input;
+        (void) input_length;
+        (void) hash;
+        (void) hash_size;
+        (void) hash_length;
+        mbedtls_test_driver_hash_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+#endif
+    }
+
+    return( mbedtls_test_driver_hash_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_hash_setup(
+    mbedtls_transparent_test_driver_hash_operation_t *operation,
+    psa_algorithm_t alg )
+{
+    mbedtls_test_driver_hash_hooks.hits++;
+
+    if( mbedtls_test_driver_hash_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_hash_hooks.driver_status =
+             mbedtls_test_driver_hash_hooks.forced_status;
+    }
+    else
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)
+        mbedtls_test_driver_hash_hooks.driver_status =
+            libtestdriver1_mbedtls_psa_hash_setup( operation, alg );
+#elif defined(MBEDTLS_PSA_BUILTIN_HASH)
+        mbedtls_test_driver_hash_hooks.driver_status =
+            mbedtls_psa_hash_setup( operation, alg );
+#else
+        (void) operation;
+        (void) alg;
+        mbedtls_test_driver_hash_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+#endif
+    }
+
+    return( mbedtls_test_driver_hash_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_hash_clone(
+    const mbedtls_transparent_test_driver_hash_operation_t *source_operation,
+    mbedtls_transparent_test_driver_hash_operation_t *target_operation )
+{
+    mbedtls_test_driver_hash_hooks.hits++;
+
+    if( mbedtls_test_driver_hash_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_hash_hooks.driver_status =
+             mbedtls_test_driver_hash_hooks.forced_status;
+    }
+    else
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)
+        mbedtls_test_driver_hash_hooks.driver_status =
+            libtestdriver1_mbedtls_psa_hash_clone( source_operation,
+                                                   target_operation );
+#elif defined(MBEDTLS_PSA_BUILTIN_HASH)
+        mbedtls_test_driver_hash_hooks.driver_status =
+            mbedtls_psa_hash_clone( source_operation, target_operation );
+#else
+        (void) source_operation;
+        (void) target_operation;
+        mbedtls_test_driver_hash_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+#endif
+    }
+
+    return( mbedtls_test_driver_hash_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_hash_update(
+    mbedtls_transparent_test_driver_hash_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length )
+{
+    mbedtls_test_driver_hash_hooks.hits++;
+
+    if( mbedtls_test_driver_hash_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_hash_hooks.driver_status =
+             mbedtls_test_driver_hash_hooks.forced_status;
+    }
+    else
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)
+        mbedtls_test_driver_hash_hooks.driver_status =
+            libtestdriver1_mbedtls_psa_hash_update(
+                operation, input, input_length );
+#elif defined(MBEDTLS_PSA_BUILTIN_HASH)
+        mbedtls_test_driver_hash_hooks.driver_status =
+            mbedtls_psa_hash_update( operation, input, input_length );
+#else
+        (void) operation;
+        (void) input;
+        (void) input_length;
+        mbedtls_test_driver_hash_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+#endif
+    }
+
+    return( mbedtls_test_driver_hash_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_hash_finish(
+    mbedtls_transparent_test_driver_hash_operation_t *operation,
+    uint8_t *hash,
+    size_t hash_size,
+    size_t *hash_length )
+{
+    mbedtls_test_driver_hash_hooks.hits++;
+
+    if( mbedtls_test_driver_hash_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_hash_hooks.driver_status =
+             mbedtls_test_driver_hash_hooks.forced_status;
+    }
+    else
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)
+        mbedtls_test_driver_hash_hooks.driver_status =
+            libtestdriver1_mbedtls_psa_hash_finish(
+                operation, hash, hash_size, hash_length );
+#elif defined(MBEDTLS_PSA_BUILTIN_HASH)
+        mbedtls_test_driver_hash_hooks.driver_status =
+            mbedtls_psa_hash_finish( operation, hash, hash_size, hash_length );
+#else
+        (void) operation;
+        (void) hash;
+        (void) hash_size;
+        (void) hash_length;
+        mbedtls_test_driver_hash_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+#endif
+    }
+
+    return( mbedtls_test_driver_hash_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_hash_abort(
+    mbedtls_transparent_test_driver_hash_operation_t *operation )
+{
+    mbedtls_test_driver_hash_hooks.hits++;
+
+    if( mbedtls_test_driver_hash_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_hash_hooks.driver_status =
+             mbedtls_test_driver_hash_hooks.forced_status;
+    }
+    else
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)
+        mbedtls_test_driver_hash_hooks.driver_status =
+            libtestdriver1_mbedtls_psa_hash_abort( operation );
+#elif defined(MBEDTLS_PSA_BUILTIN_HASH)
+        mbedtls_test_driver_hash_hooks.driver_status =
+            mbedtls_psa_hash_abort( operation );
+#else
+        (void) operation;
+        mbedtls_test_driver_hash_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+#endif
+    }
+
+    return( mbedtls_test_driver_hash_hooks.driver_status );
+}
+#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/third_party/mbedtls/repo/tests/src/drivers/key_management.c b/third_party/mbedtls/repo/tests/src/drivers/key_management.c
deleted file mode 100644
index 00d2b45..0000000
--- a/third_party/mbedtls/repo/tests/src/drivers/key_management.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Test driver for generating and verifying keys.
- * Currently only supports generating and verifying ECC keys.
- */
-/*  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.
- */
-
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
-
-#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
-#include "psa/crypto.h"
-#include "psa_crypto_core.h"
-#include "mbedtls/ecp.h"
-#include "mbedtls/error.h"
-
-#include "test/drivers/key_management.h"
-
-#include "test/random.h"
-
-#include <string.h>
-
-test_driver_key_management_hooks_t test_driver_key_management_hooks =
-    TEST_DRIVER_KEY_MANAGEMENT_INIT;
-
-psa_status_t test_transparent_generate_key(
-    const psa_key_attributes_t *attributes,
-    uint8_t *key, size_t key_size, size_t *key_length )
-{
-#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) && \
-    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
-    (void)attributes;
-#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR &&
-        * !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */
-    ++test_driver_key_management_hooks.hits;
-
-    if( test_driver_key_management_hooks.forced_status != PSA_SUCCESS )
-        return( test_driver_key_management_hooks.forced_status );
-
-    if( test_driver_key_management_hooks.forced_output != NULL )
-    {
-        if( test_driver_key_management_hooks.forced_output_length > key_size )
-            return( PSA_ERROR_BUFFER_TOO_SMALL );
-        memcpy( key, test_driver_key_management_hooks.forced_output,
-                test_driver_key_management_hooks.forced_output_length );
-        *key_length = test_driver_key_management_hooks.forced_output_length;
-        return( PSA_SUCCESS );
-    }
-
-    /* Copied from psa_crypto.c */
-#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \
-    defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
-    if ( PSA_KEY_TYPE_IS_ECC( psa_get_key_type( attributes ) )
-         && PSA_KEY_TYPE_IS_KEY_PAIR( psa_get_key_type( attributes ) ) )
-    {
-        psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
-            psa_get_key_type( attributes ) );
-        mbedtls_ecp_group_id grp_id =
-            mbedtls_ecc_group_of_psa(
-                curve,
-                PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) ) );
-        const mbedtls_ecp_curve_info *curve_info =
-            mbedtls_ecp_curve_info_from_grp_id( grp_id );
-        mbedtls_ecp_keypair ecp;
-        mbedtls_test_rnd_pseudo_info rnd_info;
-        memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
-
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        if( attributes->domain_parameters_size != 0 )
-            return( PSA_ERROR_NOT_SUPPORTED );
-        if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL )
-            return( PSA_ERROR_NOT_SUPPORTED );
-        if( curve_info->bit_size != psa_get_key_bits( attributes ) )
-            return( PSA_ERROR_INVALID_ARGUMENT );
-        mbedtls_ecp_keypair_init( &ecp );
-        ret = mbedtls_ecp_gen_key( grp_id, &ecp,
-                                   &mbedtls_test_rnd_pseudo_rand,
-                                   &rnd_info );
-        if( ret != 0 )
-        {
-            mbedtls_ecp_keypair_free( &ecp );
-            return( mbedtls_to_psa_error( ret ) );
-        }
-
-        /* Make sure to use export representation */
-        size_t bytes = PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) );
-        if( key_size < bytes )
-        {
-            mbedtls_ecp_keypair_free( &ecp );
-            return( PSA_ERROR_BUFFER_TOO_SMALL );
-        }
-        psa_status_t status = mbedtls_to_psa_error(
-            mbedtls_mpi_write_binary( &ecp.d, key, bytes ) );
-
-        if( status == PSA_SUCCESS )
-        {
-            *key_length = bytes;
-        }
-        else
-        {
-            memset( key, 0, bytes );
-        }
-
-        mbedtls_ecp_keypair_free( &ecp );
-        return( status );
-    }
-    else
-#endif /* MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR ||
-        * MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */
-    return( PSA_ERROR_NOT_SUPPORTED );
-}
-
-psa_status_t test_opaque_generate_key(
-    const psa_key_attributes_t *attributes,
-    uint8_t *key, size_t key_size, size_t *key_length )
-{
-    (void) attributes;
-    (void) key;
-    (void) key_size;
-    (void) key_length;
-    return( PSA_ERROR_NOT_SUPPORTED );
-}
-
-psa_status_t test_transparent_validate_key(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *data,
-    size_t data_length,
-    size_t *bits )
-{
-    ++test_driver_key_management_hooks.hits;
-
-    if( test_driver_key_management_hooks.forced_status != PSA_SUCCESS )
-        return( test_driver_key_management_hooks.forced_status );
-
-#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \
-    defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
-    psa_key_type_t type = psa_get_key_type( attributes );
-    if ( PSA_KEY_TYPE_IS_ECC( type ) )
-    {
-        // Code mostly copied from psa_load_ecp_representation
-        psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( type );
-        mbedtls_ecp_group_id grp_id;
-        mbedtls_ecp_keypair ecp;
-        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-
-        if( psa_get_key_bits( attributes ) == 0 )
-        {
-            // Attempt auto-detect of curve bit size
-            size_t curve_size = data_length;
-
-            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_size = data_length / 2;
-
-                /* Montgomery public keys are represented in compressed format, meaning
-                 * their curve_size is equal to the amount of input. */
-
-                /* Private keys are represented in uncompressed private random integer
-                 * format, meaning their curve_size is equal to the amount of input. */
-            }
-
-            grp_id = mbedtls_ecc_group_of_psa( curve, curve_size );
-        }
-        else
-        {
-            grp_id = mbedtls_ecc_group_of_psa( curve,
-                PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) ) );
-        }
-
-        const mbedtls_ecp_curve_info *curve_info =
-            mbedtls_ecp_curve_info_from_grp_id( grp_id );
-
-        if( attributes->domain_parameters_size != 0 )
-            return( PSA_ERROR_NOT_SUPPORTED );
-        if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL )
-            return( PSA_ERROR_NOT_SUPPORTED );
-
-        *bits = curve_info->bit_size;
-
-        mbedtls_ecp_keypair_init( &ecp );
-
-        status = mbedtls_to_psa_error(
-                    mbedtls_ecp_group_load( &ecp.grp, grp_id ) );
-        if( status != PSA_SUCCESS )
-            goto ecp_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 ecp_exit;
-
-            /* Check that the point is on the curve. */
-            status = mbedtls_to_psa_error(
-                mbedtls_ecp_check_pubkey( &ecp.grp, &ecp.Q ) );
-        }
-        else
-        {
-            /* Load and validate the secret value. */
-            status = mbedtls_to_psa_error(
-                mbedtls_ecp_read_key( ecp.grp.id,
-                                      &ecp,
-                                      data,
-                                      data_length ) );
-        }
-
-ecp_exit:
-        mbedtls_ecp_keypair_free( &ecp );
-        return( status );
-    }
-    return( PSA_ERROR_NOT_SUPPORTED );
-#else
-    (void) attributes;
-    (void) data;
-    (void) data_length;
-    (void) bits;
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR ||
-        * MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */
-}
-
-psa_status_t test_transparent_export_public_key(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    uint8_t *data, size_t data_size, size_t *data_length )
-{
-    ++test_driver_key_management_hooks.hits;
-
-    if( test_driver_key_management_hooks.forced_status != PSA_SUCCESS )
-        return( test_driver_key_management_hooks.forced_status );
-
-    if( test_driver_key_management_hooks.forced_output != NULL )
-    {
-        if( test_driver_key_management_hooks.forced_output_length > data_size )
-            return( PSA_ERROR_BUFFER_TOO_SMALL );
-        memcpy( data, test_driver_key_management_hooks.forced_output,
-                test_driver_key_management_hooks.forced_output_length );
-        *data_length = test_driver_key_management_hooks.forced_output_length;
-        return( PSA_SUCCESS );
-    }
-
-    if( key == NULL || key_length == 0 )
-        return( PSA_ERROR_INVALID_ARGUMENT );
-
-    psa_key_type_t keytype = psa_get_key_type( attributes );
-    (void) keytype;
-
-#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \
-    defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
-    if( PSA_KEY_TYPE_IS_ECC( keytype ) )
-    {
-        if( !PSA_KEY_TYPE_IS_KEY_PAIR( keytype ) )
-            return( PSA_ERROR_INVALID_ARGUMENT );
-
-        /* Mostly copied from psa_crypto.c */
-        mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
-        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-        mbedtls_ecp_keypair ecp;
-        mbedtls_test_rnd_pseudo_info rnd_info;
-        memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
-
-        if( attributes->domain_parameters_size != 0 )
-            return( PSA_ERROR_NOT_SUPPORTED );
-
-        grp_id = mbedtls_ecc_group_of_psa( PSA_KEY_TYPE_ECC_GET_FAMILY( keytype ),
-                                           PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) ) );
-        if( grp_id == MBEDTLS_ECP_DP_NONE )
-            return( PSA_ERROR_NOT_SUPPORTED );
-
-        mbedtls_ecp_keypair_init( &ecp );
-
-        status = mbedtls_to_psa_error(
-                    mbedtls_ecp_group_load( &ecp.grp, grp_id ) );
-        if( status != PSA_SUCCESS )
-            goto ecp_exit;
-
-        status = mbedtls_to_psa_error(
-            mbedtls_ecp_read_key( ecp.grp.id,
-                                  &ecp,
-                                  key,
-                                  key_length ) );
-        if( status != PSA_SUCCESS )
-            goto ecp_exit;
-
-        /* Calculate the public key */
-        status = mbedtls_to_psa_error(
-            mbedtls_ecp_mul( &ecp.grp, &ecp.Q, &ecp.d, &ecp.grp.G,
-                             &mbedtls_test_rnd_pseudo_rand,
-                             &rnd_info ) );
-        if( status != PSA_SUCCESS )
-            goto ecp_exit;
-
-        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 );
-ecp_exit:
-        mbedtls_ecp_keypair_free( &ecp );
-        return( status );
-    }
-#endif /* MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR ||
-        * MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */
-
-    return( PSA_ERROR_NOT_SUPPORTED );
-}
-
-psa_status_t test_opaque_export_public_key(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    uint8_t *data, size_t data_size, size_t *data_length )
-{
-    (void) attributes;
-    (void) key;
-    (void) key_length;
-    (void) data;
-    (void) data_size;
-    (void) data_length;
-    return( PSA_ERROR_NOT_SUPPORTED );
-}
-
-#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/third_party/mbedtls/repo/tests/src/drivers/platform_builtin_keys.c b/third_party/mbedtls/repo/tests/src/drivers/platform_builtin_keys.c
new file mode 100644
index 0000000..759fa78
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/src/drivers/platform_builtin_keys.c
@@ -0,0 +1,91 @@
+/** \file platform_builtin_keys.c
+ *
+ * \brief Test driver implementation of the builtin key support
+ */
+
+/*
+ *  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 <psa/crypto.h>
+#include <psa/crypto_extra.h>
+
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+#include <test/drivers/test_driver.h>
+#endif
+
+typedef struct
+{
+    psa_key_id_t builtin_key_id;
+    psa_key_lifetime_t lifetime;
+    psa_drv_slot_number_t slot_number;
+} mbedtls_psa_builtin_key_description_t;
+
+static const mbedtls_psa_builtin_key_description_t builtin_keys[] = {
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+    /* For testing, assign the AES builtin key slot to the boundary values.
+     * ECDSA can be exercised on key ID MBEDTLS_PSA_KEY_ID_BUILTIN_MIN + 1. */
+    { MBEDTLS_PSA_KEY_ID_BUILTIN_MIN - 1,
+      PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
+        PSA_KEY_PERSISTENCE_READ_ONLY, PSA_CRYPTO_TEST_DRIVER_LOCATION ),
+      PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT },
+    { MBEDTLS_PSA_KEY_ID_BUILTIN_MIN,
+      PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
+        PSA_KEY_PERSISTENCE_READ_ONLY, PSA_CRYPTO_TEST_DRIVER_LOCATION ),
+      PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT },
+    { MBEDTLS_PSA_KEY_ID_BUILTIN_MIN + 1,
+      PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
+        PSA_KEY_PERSISTENCE_READ_ONLY, PSA_CRYPTO_TEST_DRIVER_LOCATION ),
+      PSA_CRYPTO_TEST_DRIVER_BUILTIN_ECDSA_KEY_SLOT},
+    { MBEDTLS_PSA_KEY_ID_BUILTIN_MAX - 1,
+      PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
+        PSA_KEY_PERSISTENCE_READ_ONLY, PSA_CRYPTO_TEST_DRIVER_LOCATION ),
+      PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT},
+    { MBEDTLS_PSA_KEY_ID_BUILTIN_MAX,
+      PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
+        PSA_KEY_PERSISTENCE_READ_ONLY, PSA_CRYPTO_TEST_DRIVER_LOCATION ),
+      PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT},
+    { MBEDTLS_PSA_KEY_ID_BUILTIN_MAX + 1,
+      PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
+        PSA_KEY_PERSISTENCE_READ_ONLY, PSA_CRYPTO_TEST_DRIVER_LOCATION ),
+      PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT},
+#else
+    {0, 0, 0}
+#endif
+};
+
+psa_status_t mbedtls_psa_platform_get_builtin_key(
+    mbedtls_svc_key_id_t key_id,
+    psa_key_lifetime_t *lifetime,
+    psa_drv_slot_number_t *slot_number )
+{
+    psa_key_id_t app_key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key_id );
+    const mbedtls_psa_builtin_key_description_t *builtin_key;
+
+    for( size_t i = 0;
+         i < ( sizeof( builtin_keys ) / sizeof( builtin_keys[0] ) ); i++ )
+    {
+        builtin_key = &builtin_keys[i];
+        if( builtin_key->builtin_key_id == app_key_id )
+        {
+            *lifetime = builtin_key->lifetime;
+            *slot_number = builtin_key->slot_number;
+            return( PSA_SUCCESS );
+        }
+    }
+
+    return( PSA_ERROR_DOES_NOT_EXIST );
+}
diff --git a/third_party/mbedtls/repo/tests/src/drivers/signature.c b/third_party/mbedtls/repo/tests/src/drivers/signature.c
deleted file mode 100644
index cea0351..0000000
--- a/third_party/mbedtls/repo/tests/src/drivers/signature.c
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Test driver for signature functions.
- * Currently supports signing and verifying precalculated hashes, using
- * only deterministic ECDSA on curves secp256r1, secp384r1 and secp521r1.
- */
-/*  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.
- */
-
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
-
-#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
-#include "psa/crypto.h"
-#include "psa_crypto_core.h"
-#include "mbedtls/ecp.h"
-
-#include "test/drivers/signature.h"
-
-#include "mbedtls/md.h"
-#include "mbedtls/ecdsa.h"
-
-#include "test/random.h"
-
-#include <string.h>
-
-test_driver_signature_hooks_t test_driver_signature_sign_hooks = TEST_DRIVER_SIGNATURE_INIT;
-test_driver_signature_hooks_t test_driver_signature_verify_hooks = TEST_DRIVER_SIGNATURE_INIT;
-
-psa_status_t test_transparent_signature_sign_hash(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg,
-    const uint8_t *hash, size_t hash_length,
-    uint8_t *signature, size_t signature_size, size_t *signature_length )
-{
-    ++test_driver_signature_sign_hooks.hits;
-
-    if( test_driver_signature_sign_hooks.forced_status != PSA_SUCCESS )
-        return( test_driver_signature_sign_hooks.forced_status );
-
-    if( test_driver_signature_sign_hooks.forced_output != NULL )
-    {
-        if( test_driver_signature_sign_hooks.forced_output_length > signature_size )
-            return( PSA_ERROR_BUFFER_TOO_SMALL );
-        memcpy( signature, test_driver_signature_sign_hooks.forced_output,
-                test_driver_signature_sign_hooks.forced_output_length );
-        *signature_length = test_driver_signature_sign_hooks.forced_output_length;
-        return( PSA_SUCCESS );
-    }
-
-    psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
-
-#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
-    defined(MBEDTLS_SHA256_C)
-    if( alg != PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ) )
-        return( PSA_ERROR_NOT_SUPPORTED );
-    mbedtls_ecp_group_id grp_id;
-    switch( psa_get_key_type( attributes ) )
-    {
-        case PSA_ECC_CURVE_SECP_R1:
-            switch( psa_get_key_bits( attributes ) )
-            {
-                case 256:
-                    grp_id = MBEDTLS_ECP_DP_SECP256R1;
-                    break;
-                case 384:
-                    grp_id = MBEDTLS_ECP_DP_SECP384R1;
-                    break;
-                case 521:
-                    grp_id = MBEDTLS_ECP_DP_SECP521R1;
-                    break;
-                default:
-                    return( PSA_ERROR_NOT_SUPPORTED );
-            }
-            break;
-        default:
-            return( PSA_ERROR_NOT_SUPPORTED );
-    }
-
-    /* Beyond this point, the driver is actually doing the work of
-     * calculating the signature. */
-
-    status = PSA_ERROR_GENERIC_ERROR;
-    int ret = 0;
-    mbedtls_mpi r, s;
-    mbedtls_mpi_init( &r );
-    mbedtls_mpi_init( &s );
-    mbedtls_ecp_keypair ecp;
-    mbedtls_ecp_keypair_init( &ecp );
-    size_t curve_bytes = PSA_BITS_TO_BYTES( ecp.grp.pbits );
-
-    MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ecp.grp, grp_id ) );
-    MBEDTLS_MPI_CHK( mbedtls_ecp_point_read_binary( &ecp.grp, &ecp.Q,
-                                                    key, key_length ) );
-
-    /* Code adapted from psa_ecdsa_sign() in psa_crypto.c. */
-    mbedtls_md_type_t md_alg = MBEDTLS_MD_SHA256;
-    if( signature_size < 2 * curve_bytes )
-    {
-        status = PSA_ERROR_BUFFER_TOO_SMALL;
-        goto cleanup;
-    }
-    MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ecp.grp, &r, &s, &ecp.d,
-                                  hash, hash_length, md_alg ) );
-    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:
-    status = mbedtls_to_psa_error( ret );
-    mbedtls_mpi_free( &r );
-    mbedtls_mpi_free( &s );
-    mbedtls_ecp_keypair_free( &ecp );
-    if( status == PSA_SUCCESS )
-        *signature_length = 2 * curve_bytes;
-#else /* defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
-         defined(MBEDTLS_SHA256_C) */
-    (void) attributes;
-    (void) key;
-    (void) key_length;
-    (void) alg;
-    (void) hash;
-    (void) hash_length;
-#endif /* defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
-          defined(MBEDTLS_SHA256_C) */
-
-    return( status );
-}
-
-psa_status_t test_opaque_signature_sign_hash(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg,
-    const uint8_t *hash, size_t hash_length,
-    uint8_t *signature, size_t signature_size, size_t *signature_length )
-{
-    (void) attributes;
-    (void) key;
-    (void) key_length;
-    (void) alg;
-    (void) hash;
-    (void) hash_length;
-    (void) signature;
-    (void) signature_size;
-    (void) signature_length;
-    return( PSA_ERROR_NOT_SUPPORTED );
-}
-
-psa_status_t test_transparent_signature_verify_hash(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg,
-    const uint8_t *hash, size_t hash_length,
-    const uint8_t *signature, size_t signature_length )
-{
-    ++test_driver_signature_verify_hooks.hits;
-
-    if( test_driver_signature_verify_hooks.forced_status != PSA_SUCCESS )
-        return( test_driver_signature_verify_hooks.forced_status );
-
-    psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
-
-#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
-    defined(MBEDTLS_SHA256_C)
-    if( alg != PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ) )
-        return( PSA_ERROR_NOT_SUPPORTED );
-    mbedtls_ecp_group_id grp_id;
-    switch( psa_get_key_type( attributes ) )
-    {
-        case PSA_ECC_CURVE_SECP_R1:
-            switch( psa_get_key_bits( attributes ) )
-            {
-                case 256:
-                    grp_id = MBEDTLS_ECP_DP_SECP256R1;
-                    break;
-                case 384:
-                    grp_id = MBEDTLS_ECP_DP_SECP384R1;
-                    break;
-                case 521:
-                    grp_id = MBEDTLS_ECP_DP_SECP521R1;
-                    break;
-                default:
-                    return( PSA_ERROR_NOT_SUPPORTED );
-            }
-            break;
-        default:
-            return( PSA_ERROR_NOT_SUPPORTED );
-    }
-
-    /* Beyond this point, the driver is actually doing the work of
-     * calculating the signature. */
-
-    status = PSA_ERROR_GENERIC_ERROR;
-    int ret = 0;
-    mbedtls_mpi r, s;
-    mbedtls_mpi_init( &r );
-    mbedtls_mpi_init( &s );
-    mbedtls_ecp_keypair ecp;
-    mbedtls_ecp_keypair_init( &ecp );
-    mbedtls_test_rnd_pseudo_info rnd_info;
-    memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
-    size_t curve_bytes = PSA_BITS_TO_BYTES( ecp.grp.pbits );
-
-    MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ecp.grp, grp_id ) );
-
-    /* Code adapted from psa_ecdsa_verify() in psa_crypto.c. */
-    if( signature_length < 2 * curve_bytes )
-    {
-        status = PSA_ERROR_BUFFER_TOO_SMALL;
-        goto cleanup;
-    }
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r,
-                                              signature,
-                                              curve_bytes ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &s,
-                                              signature + curve_bytes,
-                                              curve_bytes ) );
-
-    if( PSA_KEY_TYPE_IS_PUBLIC_KEY( psa_get_key_type( attributes ) ) )
-        MBEDTLS_MPI_CHK( mbedtls_ecp_point_read_binary( &ecp.grp, &ecp.Q,
-                                                    key, key_length ) );
-    else
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ecp.d, key, key_length ) );
-        MBEDTLS_MPI_CHK(
-            mbedtls_ecp_mul( &ecp.grp, &ecp.Q, &ecp.d, &ecp.grp.G,
-                             &mbedtls_test_rnd_pseudo_rand,
-                             &rnd_info ) );
-    }
-
-    MBEDTLS_MPI_CHK( mbedtls_ecdsa_verify( &ecp.grp, hash, hash_length,
-                                &ecp.Q, &r, &s ) );
-cleanup:
-    status = mbedtls_to_psa_error( ret );
-    mbedtls_mpi_free( &r );
-    mbedtls_mpi_free( &s );
-    mbedtls_ecp_keypair_free( &ecp );
-#else /* defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
-         defined(MBEDTLS_SHA256_C) */
-    (void) attributes;
-    (void) key;
-    (void) key_length;
-    (void) alg;
-    (void) hash;
-    (void) hash_length;
-    (void) signature;
-    (void) signature_length;
-#endif /* defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
-          defined(MBEDTLS_SHA256_C) */
-
-    return( status );
-}
-
-psa_status_t test_opaque_signature_verify_hash(
-    const psa_key_attributes_t *attributes,
-    const uint8_t *key, size_t key_length,
-    psa_algorithm_t alg,
-    const uint8_t *hash, size_t hash_length,
-    const uint8_t *signature, size_t signature_length )
-{
-    (void) attributes;
-    (void) key;
-    (void) key_length;
-    (void) alg;
-    (void) hash;
-    (void) hash_length;
-    (void) signature;
-    (void) signature_length;
-    return( PSA_ERROR_NOT_SUPPORTED );
-}
-
-#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/third_party/mbedtls/repo/tests/src/drivers/size.c b/third_party/mbedtls/repo/tests/src/drivers/size.c
deleted file mode 100644
index 16a8692..0000000
--- a/third_party/mbedtls/repo/tests/src/drivers/size.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Test driver for retrieving key context size.
- * Only used by opaque drivers.
- */
-/*  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.
- */
-
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
-
-#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
-
-#include "test/drivers/size.h"
-
-#ifdef TEST_KEY_CONTEXT_SIZE_FUNCTION
-size_t test_size_function(
-    const psa_key_type_t key_type,
-    const size_t key_bits )
-{
-    (void) key_type;
-    (void) key_bits;
-    return 0;
-}
-#endif /*TEST_KEY_CONTEXT_SIZE_FUNCTION */
-
-#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/third_party/mbedtls/repo/tests/src/drivers/test_driver_aead.c b/third_party/mbedtls/repo/tests/src/drivers/test_driver_aead.c
new file mode 100644
index 0000000..25396c9
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/src/drivers/test_driver_aead.c
@@ -0,0 +1,96 @@
+/*
+ * Test driver for AEAD entry points.
+ */
+/*  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.
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
+#include "psa_crypto_aead.h"
+
+#include "test/drivers/aead.h"
+
+mbedtls_test_driver_aead_hooks_t
+    mbedtls_test_driver_aead_hooks = MBEDTLS_TEST_DRIVER_AEAD_INIT;
+
+psa_status_t mbedtls_test_transparent_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 )
+{
+    mbedtls_test_driver_aead_hooks.hits++;
+
+    if( mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_aead_hooks.driver_status =
+             mbedtls_test_driver_aead_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_aead_hooks.driver_status =
+            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 );
+    }
+
+    return( mbedtls_test_driver_aead_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_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 )
+{
+    mbedtls_test_driver_aead_hooks.hits++;
+
+    if( mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_aead_hooks.driver_status =
+             mbedtls_test_driver_aead_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_aead_hooks.driver_status =
+            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 );
+    }
+
+    return( mbedtls_test_driver_aead_hooks.driver_status );
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/third_party/mbedtls/repo/tests/src/drivers/test_driver_cipher.c b/third_party/mbedtls/repo/tests/src/drivers/test_driver_cipher.c
new file mode 100644
index 0000000..30a8119
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/src/drivers/test_driver_cipher.c
@@ -0,0 +1,436 @@
+/*
+ * Test driver for cipher functions.
+ * Currently only supports multi-part operations using AES-CTR.
+ */
+/*  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.
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
+#include "psa/crypto.h"
+#include "psa_crypto_cipher.h"
+#include "psa_crypto_core.h"
+#include "mbedtls/cipher.h"
+
+#include "test/drivers/cipher.h"
+
+#include "test/random.h"
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+#include "libtestdriver1/library/psa_crypto_cipher.h"
+#endif
+
+#include <string.h>
+
+mbedtls_test_driver_cipher_hooks_t mbedtls_test_driver_cipher_hooks =
+    MBEDTLS_TEST_DRIVER_CIPHER_INIT;
+
+psa_status_t mbedtls_test_transparent_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 )
+{
+    mbedtls_test_driver_cipher_hooks.hits++;
+
+    if( mbedtls_test_driver_cipher_hooks.forced_output != NULL )
+    {
+        if( output_size < mbedtls_test_driver_cipher_hooks.forced_output_length )
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+        memcpy( output,
+                mbedtls_test_driver_cipher_hooks.forced_output,
+                mbedtls_test_driver_cipher_hooks.forced_output_length );
+        *output_length = mbedtls_test_driver_cipher_hooks.forced_output_length;
+
+        return( mbedtls_test_driver_cipher_hooks.forced_status );
+    }
+
+    if( mbedtls_test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
+        return( mbedtls_test_driver_cipher_hooks.forced_status );
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)
+    return( libtestdriver1_mbedtls_psa_cipher_encrypt(
+                (const libtestdriver1_psa_key_attributes_t *)attributes,
+                key_buffer, key_buffer_size,
+                alg, iv, iv_length, input, input_length,
+                output, output_size, output_length ) );
+#elif 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 ) );
+#endif
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_transparent_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 )
+{
+   mbedtls_test_driver_cipher_hooks.hits++;
+
+    if( mbedtls_test_driver_cipher_hooks.forced_output != NULL )
+    {
+        if( output_size < mbedtls_test_driver_cipher_hooks.forced_output_length )
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+        memcpy( output,
+                mbedtls_test_driver_cipher_hooks.forced_output,
+                mbedtls_test_driver_cipher_hooks.forced_output_length );
+        *output_length = mbedtls_test_driver_cipher_hooks.forced_output_length;
+
+        return( mbedtls_test_driver_cipher_hooks.forced_status );
+    }
+
+    if( mbedtls_test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
+        return( mbedtls_test_driver_cipher_hooks.forced_status );
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)
+    return( libtestdriver1_mbedtls_psa_cipher_decrypt(
+                (const libtestdriver1_psa_key_attributes_t *)attributes,
+                key_buffer, key_buffer_size,
+                alg, input, input_length,
+                output, output_size, output_length ) );
+#elif 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 ) );
+#endif
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_transparent_cipher_encrypt_setup(
+    mbedtls_transparent_test_driver_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg)
+{
+    mbedtls_test_driver_cipher_hooks.hits++;
+
+    /* Wiping the entire struct here, instead of member-by-member. This is
+     * useful for the test suite, since it gives a chance of catching memory
+     * corruption errors should the core not have allocated (enough) memory for
+     * our context struct. */
+    memset( operation, 0, sizeof( *operation ) );
+
+    if( mbedtls_test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
+        return( mbedtls_test_driver_cipher_hooks.forced_status );
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)
+    return( libtestdriver1_mbedtls_psa_cipher_encrypt_setup(
+                operation,
+                (const libtestdriver1_psa_key_attributes_t *)attributes,
+                key, key_length, alg ) );
+#elif defined(MBEDTLS_PSA_BUILTIN_CIPHER)
+    return( mbedtls_psa_cipher_encrypt_setup(
+                operation, attributes, key, key_length, alg ) );
+#endif
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_transparent_cipher_decrypt_setup(
+    mbedtls_transparent_test_driver_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg)
+{
+    mbedtls_test_driver_cipher_hooks.hits++;
+
+    if( mbedtls_test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
+        return( mbedtls_test_driver_cipher_hooks.forced_status );
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)
+    return( libtestdriver1_mbedtls_psa_cipher_decrypt_setup(
+                operation,
+                (const libtestdriver1_psa_key_attributes_t *)attributes,
+                key, key_length, alg ) );
+#elif defined(MBEDTLS_PSA_BUILTIN_CIPHER)
+    return( mbedtls_psa_cipher_decrypt_setup(
+                operation, attributes, key, key_length, alg ) );
+#endif
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_transparent_cipher_abort(
+    mbedtls_transparent_test_driver_cipher_operation_t *operation)
+{
+    mbedtls_test_driver_cipher_hooks.hits++;
+
+    if( operation->alg == 0 )
+        return( PSA_SUCCESS );
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)
+    libtestdriver1_mbedtls_psa_cipher_abort( operation );
+#elif defined(MBEDTLS_PSA_BUILTIN_CIPHER)
+    mbedtls_psa_cipher_abort( operation );
+#endif
+
+    /* Wiping the entire struct here, instead of member-by-member. This is
+     * useful for the test suite, since it gives a chance of catching memory
+     * corruption errors should the core not have allocated (enough) memory for
+     * our context struct. */
+    memset( operation, 0, sizeof( *operation ) );
+
+    return( mbedtls_test_driver_cipher_hooks.forced_status );
+}
+
+psa_status_t mbedtls_test_transparent_cipher_set_iv(
+    mbedtls_transparent_test_driver_cipher_operation_t *operation,
+    const uint8_t *iv,
+    size_t iv_length)
+{
+    mbedtls_test_driver_cipher_hooks.hits++;
+
+    if( mbedtls_test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
+        return( mbedtls_test_driver_cipher_hooks.forced_status );
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)
+    return( libtestdriver1_mbedtls_psa_cipher_set_iv(
+                operation, iv, iv_length ) );
+#elif defined(MBEDTLS_PSA_BUILTIN_CIPHER)
+    return( mbedtls_psa_cipher_set_iv( operation, iv, iv_length ) );
+#endif
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_transparent_cipher_update(
+    mbedtls_transparent_test_driver_cipher_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length)
+{
+    mbedtls_test_driver_cipher_hooks.hits++;
+
+    if( mbedtls_test_driver_cipher_hooks.forced_output != NULL )
+    {
+        if( output_size < mbedtls_test_driver_cipher_hooks.forced_output_length )
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+
+        memcpy( output,
+                mbedtls_test_driver_cipher_hooks.forced_output,
+                mbedtls_test_driver_cipher_hooks.forced_output_length );
+        *output_length = mbedtls_test_driver_cipher_hooks.forced_output_length;
+
+        return( mbedtls_test_driver_cipher_hooks.forced_status );
+    }
+
+    if( mbedtls_test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
+        return( mbedtls_test_driver_cipher_hooks.forced_status );
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)
+    return( libtestdriver1_mbedtls_psa_cipher_update(
+                operation, input, input_length,
+                output, output_size, output_length ) );
+#elif defined(MBEDTLS_PSA_BUILTIN_CIPHER)
+    return( mbedtls_psa_cipher_update(
+                operation, input, input_length,
+                output, output_size, output_length ) );
+#endif
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_transparent_cipher_finish(
+    mbedtls_transparent_test_driver_cipher_operation_t *operation,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length)
+{
+    mbedtls_test_driver_cipher_hooks.hits++;
+
+    if( mbedtls_test_driver_cipher_hooks.forced_output != NULL )
+    {
+        if( output_size < mbedtls_test_driver_cipher_hooks.forced_output_length )
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+
+        memcpy( output,
+                mbedtls_test_driver_cipher_hooks.forced_output,
+                mbedtls_test_driver_cipher_hooks.forced_output_length );
+        *output_length = mbedtls_test_driver_cipher_hooks.forced_output_length;
+
+        return( mbedtls_test_driver_cipher_hooks.forced_status );
+    }
+
+    if( mbedtls_test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
+        return( mbedtls_test_driver_cipher_hooks.forced_status );
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)
+    return( libtestdriver1_mbedtls_psa_cipher_finish(
+                operation, output, output_size, output_length ) );
+#elif defined(MBEDTLS_PSA_BUILTIN_CIPHER)
+    return( mbedtls_psa_cipher_finish(
+                operation, output, output_size, output_length ) );
+#endif
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+/*
+ * opaque versions, to do
+ */
+psa_status_t mbedtls_test_opaque_cipher_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    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)
+{
+    (void) attributes;
+    (void) key;
+    (void) key_length;
+    (void) alg;
+    (void) iv;
+    (void) iv_length;
+    (void) input;
+    (void) input_length;
+    (void) output;
+    (void) output_size;
+    (void) output_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_opaque_cipher_decrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t input_length,
+    uint8_t *output, size_t output_size, size_t *output_length)
+{
+    (void) attributes;
+    (void) key;
+    (void) key_length;
+    (void) alg;
+    (void) input;
+    (void) input_length;
+    (void) output;
+    (void) output_size;
+    (void) output_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_opaque_cipher_encrypt_setup(
+    mbedtls_opaque_test_driver_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg)
+{
+    (void) operation;
+    (void) attributes;
+    (void) key;
+    (void) key_length;
+    (void) alg;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_opaque_cipher_decrypt_setup(
+    mbedtls_opaque_test_driver_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg)
+{
+    (void) operation;
+    (void) attributes;
+    (void) key;
+    (void) key_length;
+    (void) alg;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_opaque_cipher_abort(
+    mbedtls_opaque_test_driver_cipher_operation_t *operation )
+{
+    (void) operation;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_opaque_cipher_set_iv(
+    mbedtls_opaque_test_driver_cipher_operation_t *operation,
+    const uint8_t *iv,
+    size_t iv_length)
+{
+    (void) operation;
+    (void) iv;
+    (void) iv_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_opaque_cipher_update(
+    mbedtls_opaque_test_driver_cipher_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length)
+{
+    (void) operation;
+    (void) input;
+    (void) input_length;
+    (void) output;
+    (void) output_size;
+    (void) output_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_opaque_cipher_finish(
+    mbedtls_opaque_test_driver_cipher_operation_t *operation,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length)
+{
+    (void) operation;
+    (void) output;
+    (void) output_size;
+    (void) output_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/third_party/mbedtls/repo/tests/src/drivers/test_driver_key_management.c b/third_party/mbedtls/repo/tests/src/drivers/test_driver_key_management.c
new file mode 100644
index 0000000..029fcdd
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/src/drivers/test_driver_key_management.c
@@ -0,0 +1,456 @@
+/*
+ * Test driver for generating and verifying keys.
+ * Currently only supports generating and verifying ECC keys.
+ */
+/*  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.
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
+#include "psa/crypto.h"
+#include "psa_crypto_core.h"
+#include "psa_crypto_ecp.h"
+#include "psa_crypto_rsa.h"
+#include "mbedtls/ecp.h"
+#include "mbedtls/error.h"
+
+#include "test/drivers/key_management.h"
+#include "test/random.h"
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+#include "libtestdriver1/library/psa_crypto_ecp.h"
+#include "libtestdriver1/library/psa_crypto_rsa.h"
+#endif
+
+#include <string.h>
+
+mbedtls_test_driver_key_management_hooks_t
+    mbedtls_test_driver_key_management_hooks = MBEDTLS_TEST_DRIVER_KEY_MANAGEMENT_INIT;
+
+const uint8_t mbedtls_test_driver_aes_key[16] =
+    { 0x36, 0x77, 0x39, 0x7A, 0x24, 0x43, 0x26, 0x46,
+      0x29, 0x4A, 0x40, 0x4E, 0x63, 0x52, 0x66, 0x55 };
+const uint8_t mbedtls_test_driver_ecdsa_key[32] =
+    { 0xdc, 0x7d, 0x9d, 0x26, 0xd6, 0x7a, 0x4f, 0x63,
+      0x2c, 0x34, 0xc2, 0xdc, 0x0b, 0x69, 0x86, 0x18,
+      0x38, 0x82, 0xc2, 0x06, 0xdf, 0x04, 0xcd, 0xb7,
+      0xd6, 0x9a, 0xab, 0xe2, 0x8b, 0xe4, 0xf8, 0x1a };
+const uint8_t mbedtls_test_driver_ecdsa_pubkey[65] =
+    { 0x04,
+      0x85, 0xf6, 0x4d, 0x89, 0xf0, 0x0b, 0xe6, 0x6c,
+      0x88, 0xdd, 0x93, 0x7e, 0xfd, 0x6d, 0x7c, 0x44,
+      0x56, 0x48, 0xdc, 0xb7, 0x01, 0x15, 0x0b, 0x8a,
+      0x95, 0x09, 0x29, 0x58, 0x50, 0xf4, 0x1c, 0x19,
+      0x31, 0xe5, 0x71, 0xfb, 0x8f, 0x8c, 0x78, 0x31,
+      0x7a, 0x20, 0xb3, 0x80, 0xe8, 0x66, 0x58, 0x4b,
+      0xbc, 0x25, 0x16, 0xc3, 0xd2, 0x70, 0x2d, 0x79,
+      0x2f, 0x13, 0x1a, 0x92, 0x20, 0x95, 0xfd, 0x6c };
+
+psa_status_t mbedtls_test_transparent_init( void )
+{
+psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+    status = libtestdriver1_psa_crypto_init( );
+    if( status != PSA_SUCCESS )
+        return( status );
+#endif
+
+    (void)status;
+    return( PSA_SUCCESS );
+}
+
+void mbedtls_test_transparent_free( void )
+{
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+    libtestdriver1_mbedtls_psa_crypto_free( );
+#endif
+
+    return;
+}
+
+psa_status_t mbedtls_test_opaque_init( void )
+{
+    return( PSA_SUCCESS );
+}
+
+void mbedtls_test_opaque_free( void )
+{
+    return;
+}
+
+psa_status_t mbedtls_test_transparent_generate_key(
+    const psa_key_attributes_t *attributes,
+    uint8_t *key, size_t key_size, size_t *key_length )
+{
+    ++mbedtls_test_driver_key_management_hooks.hits;
+
+    if( mbedtls_test_driver_key_management_hooks.forced_status != PSA_SUCCESS )
+        return( mbedtls_test_driver_key_management_hooks.forced_status );
+
+    if( mbedtls_test_driver_key_management_hooks.forced_output != NULL )
+    {
+        if( mbedtls_test_driver_key_management_hooks.forced_output_length >
+            key_size )
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
+        memcpy( key, mbedtls_test_driver_key_management_hooks.forced_output,
+                mbedtls_test_driver_key_management_hooks.forced_output_length );
+        *key_length = mbedtls_test_driver_key_management_hooks.forced_output_length;
+        return( PSA_SUCCESS );
+    }
+
+    if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type( attributes ) )
+        && PSA_KEY_TYPE_IS_KEY_PAIR( psa_get_key_type( attributes ) ) )
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR)
+        return( libtestdriver1_mbedtls_psa_ecp_generate_key(
+                    (const libtestdriver1_psa_key_attributes_t *)attributes,
+                    key, key_size, key_length ) );
+#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR)
+        return( mbedtls_psa_ecp_generate_key(
+                    attributes, key, key_size, key_length ) );
+#endif
+    }
+    else if( psa_get_key_type( attributes ) == PSA_KEY_TYPE_RSA_KEY_PAIR )
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR)
+        return( libtestdriver1_mbedtls_psa_rsa_generate_key(
+                    (const libtestdriver1_psa_key_attributes_t *)attributes,
+                    key, key_size, key_length ) );
+#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR)
+        return( mbedtls_psa_rsa_generate_key(
+                    attributes, key, key_size, key_length ) );
+#endif
+    }
+
+    (void)attributes;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_opaque_generate_key(
+    const psa_key_attributes_t *attributes,
+    uint8_t *key, size_t key_size, size_t *key_length )
+{
+    (void) attributes;
+    (void) key;
+    (void) key_size;
+    (void) key_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_transparent_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)
+{
+    ++mbedtls_test_driver_key_management_hooks.hits;
+
+    if( mbedtls_test_driver_key_management_hooks.forced_status != PSA_SUCCESS )
+        return( mbedtls_test_driver_key_management_hooks.forced_status );
+
+    psa_key_type_t type = psa_get_key_type( attributes );
+
+    if( PSA_KEY_TYPE_IS_ECC( type ) )
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    ( defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
+      defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) )
+        return( libtestdriver1_mbedtls_psa_ecp_import_key(
+                    (const libtestdriver1_psa_key_attributes_t *)attributes,
+                    data, data_length,
+                    key_buffer, key_buffer_size,
+                    key_buffer_length, bits ) );
+#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
+      defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
+        return( mbedtls_psa_ecp_import_key(
+                    attributes,
+                    data, data_length,
+                    key_buffer, key_buffer_size,
+                    key_buffer_length, bits ) );
+#endif
+    }
+    else if( PSA_KEY_TYPE_IS_RSA( type ) )
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    ( defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
+      defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) )
+        return( libtestdriver1_mbedtls_psa_rsa_import_key(
+                    (const libtestdriver1_psa_key_attributes_t *)attributes,
+                    data, data_length,
+                    key_buffer, key_buffer_size,
+                    key_buffer_length, bits ) );
+#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
+      defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
+        return( mbedtls_psa_rsa_import_key(
+                    attributes,
+                    data, data_length,
+                    key_buffer, key_buffer_size,
+                    key_buffer_length, bits ) );
+#endif
+    }
+
+    (void)data;
+    (void)data_length;
+    (void)key_buffer;
+    (void)key_buffer_size;
+    (void)key_buffer_length;
+    (void)bits;
+    (void)type;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_opaque_export_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    uint8_t *data, size_t data_size, size_t *data_length )
+{
+    if( key_length != sizeof( psa_drv_slot_number_t ) )
+    {
+        /* Test driver does not support generic opaque key handling yet. */
+        return( PSA_ERROR_NOT_SUPPORTED );
+    }
+
+    /* Assume this is a builtin key based on the key material length. */
+    psa_drv_slot_number_t slot_number = *( ( psa_drv_slot_number_t* ) key );
+
+    switch( slot_number )
+    {
+        case PSA_CRYPTO_TEST_DRIVER_BUILTIN_ECDSA_KEY_SLOT:
+            /* This is the ECDSA slot. Verify the key's attributes before
+             * returning the private key. */
+            if( psa_get_key_type( attributes ) !=
+                PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ) )
+                return( PSA_ERROR_CORRUPTION_DETECTED );
+            if( psa_get_key_bits( attributes ) != 256 )
+                return( PSA_ERROR_CORRUPTION_DETECTED );
+            if( psa_get_key_algorithm( attributes ) !=
+                PSA_ALG_ECDSA( PSA_ALG_ANY_HASH ) )
+                return( PSA_ERROR_CORRUPTION_DETECTED );
+            if( ( psa_get_key_usage_flags( attributes ) &
+                  PSA_KEY_USAGE_EXPORT ) == 0 )
+                return( PSA_ERROR_CORRUPTION_DETECTED );
+
+            if( data_size < sizeof( mbedtls_test_driver_ecdsa_key ) )
+                return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+            memcpy( data, mbedtls_test_driver_ecdsa_key,
+                    sizeof( mbedtls_test_driver_ecdsa_key ) );
+            *data_length = sizeof( mbedtls_test_driver_ecdsa_key );
+            return( PSA_SUCCESS );
+
+        case PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT:
+            /* This is the AES slot. Verify the key's attributes before
+             * returning the key. */
+            if( psa_get_key_type( attributes ) != PSA_KEY_TYPE_AES )
+                return( PSA_ERROR_CORRUPTION_DETECTED );
+            if( psa_get_key_bits( attributes ) != 128 )
+                return( PSA_ERROR_CORRUPTION_DETECTED );
+            if( psa_get_key_algorithm( attributes ) != PSA_ALG_CTR )
+                return( PSA_ERROR_CORRUPTION_DETECTED );
+            if( ( psa_get_key_usage_flags( attributes ) &
+                  PSA_KEY_USAGE_EXPORT ) == 0 )
+                return( PSA_ERROR_CORRUPTION_DETECTED );
+
+            if( data_size < sizeof( mbedtls_test_driver_aes_key ) )
+                return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+            memcpy( data, mbedtls_test_driver_aes_key,
+                    sizeof( mbedtls_test_driver_aes_key ) );
+            *data_length = sizeof( mbedtls_test_driver_aes_key );
+            return( PSA_SUCCESS );
+
+        default:
+            return( PSA_ERROR_DOES_NOT_EXIST );
+    }
+}
+
+psa_status_t mbedtls_test_transparent_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 )
+{
+    ++mbedtls_test_driver_key_management_hooks.hits;
+
+    if( mbedtls_test_driver_key_management_hooks.forced_status != PSA_SUCCESS )
+        return( mbedtls_test_driver_key_management_hooks.forced_status );
+
+    if( mbedtls_test_driver_key_management_hooks.forced_output != NULL )
+    {
+        if( mbedtls_test_driver_key_management_hooks.forced_output_length >
+            data_size )
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
+        memcpy( data, mbedtls_test_driver_key_management_hooks.forced_output,
+                mbedtls_test_driver_key_management_hooks.forced_output_length );
+        *data_length = mbedtls_test_driver_key_management_hooks.forced_output_length;
+        return( PSA_SUCCESS );
+    }
+
+    psa_key_type_t key_type = psa_get_key_type( attributes );
+
+    if( PSA_KEY_TYPE_IS_ECC( key_type ) )
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    ( defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
+      defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) )
+        return( libtestdriver1_mbedtls_psa_ecp_export_public_key(
+                    (const libtestdriver1_psa_key_attributes_t *)attributes,
+                    key_buffer, key_buffer_size,
+                    data, data_size, data_length ) );
+#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
+      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 ) );
+#endif
+    }
+    else if( PSA_KEY_TYPE_IS_RSA( key_type ) )
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    ( defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
+      defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) )
+        return( libtestdriver1_mbedtls_psa_rsa_export_public_key(
+                    (const libtestdriver1_psa_key_attributes_t *)attributes,
+                    key_buffer, key_buffer_size,
+                    data, data_size, data_length ) );
+#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
+      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 ) );
+#endif
+    }
+
+    (void)key_buffer;
+    (void)key_buffer_size;
+    (void)key_type;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_opaque_export_public_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    uint8_t *data, size_t data_size, size_t *data_length )
+{
+    if( key_length != sizeof( psa_drv_slot_number_t ) )
+    {
+        /* Test driver does not support generic opaque key handling yet. */
+        return( PSA_ERROR_NOT_SUPPORTED );
+    }
+
+    /* Assume this is a builtin key based on the key material length. */
+    psa_drv_slot_number_t slot_number = *( ( psa_drv_slot_number_t* ) key );
+    switch( slot_number )
+    {
+        case PSA_CRYPTO_TEST_DRIVER_BUILTIN_ECDSA_KEY_SLOT:
+            /* This is the ECDSA slot. Verify the key's attributes before
+             * returning the public key. */
+            if( psa_get_key_type( attributes ) !=
+                PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ) )
+                return( PSA_ERROR_CORRUPTION_DETECTED );
+            if( psa_get_key_bits( attributes ) != 256 )
+                return( PSA_ERROR_CORRUPTION_DETECTED );
+            if( psa_get_key_algorithm( attributes ) !=
+                PSA_ALG_ECDSA( PSA_ALG_ANY_HASH ) )
+                return( PSA_ERROR_CORRUPTION_DETECTED );
+
+            if( data_size < sizeof( mbedtls_test_driver_ecdsa_pubkey ) )
+                return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+            memcpy( data, mbedtls_test_driver_ecdsa_pubkey,
+                    sizeof( mbedtls_test_driver_ecdsa_pubkey ) );
+            *data_length = sizeof( mbedtls_test_driver_ecdsa_pubkey );
+            return( PSA_SUCCESS );
+
+        default:
+            return( PSA_ERROR_DOES_NOT_EXIST );
+    }
+}
+
+/* The opaque test driver exposes two built-in keys when builtin key support is
+ * compiled in.
+ * The key in slot #PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT is an AES-128
+ * key which allows CTR mode.
+ * The key in slot #PSA_CRYPTO_TEST_DRIVER_BUILTIN_ECDSA_KEY_SLOT is a secp256r1
+ * private key which allows ECDSA sign & verify.
+ * The key buffer format for these is the raw format of psa_drv_slot_number_t
+ * (i.e. for an actual driver this would mean 'builtin_key_size' =
+ * sizeof(psa_drv_slot_number_t)).
+ */
+psa_status_t mbedtls_test_opaque_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 )
+{
+    switch( slot_number )
+    {
+        case PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT:
+            psa_set_key_type( attributes, PSA_KEY_TYPE_AES );
+            psa_set_key_bits( attributes, 128 );
+            psa_set_key_usage_flags(
+                attributes,
+                PSA_KEY_USAGE_ENCRYPT |
+                PSA_KEY_USAGE_DECRYPT |
+                PSA_KEY_USAGE_EXPORT );
+            psa_set_key_algorithm( attributes, PSA_ALG_CTR );
+
+            if( key_buffer_size < sizeof( psa_drv_slot_number_t ) )
+                return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+            *( (psa_drv_slot_number_t*) key_buffer ) =
+                PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT;
+            *key_buffer_length = sizeof( psa_drv_slot_number_t );
+            return( PSA_SUCCESS );
+        case PSA_CRYPTO_TEST_DRIVER_BUILTIN_ECDSA_KEY_SLOT:
+            psa_set_key_type(
+                attributes,
+                PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ) );
+            psa_set_key_bits( attributes, 256 );
+            psa_set_key_usage_flags(
+                attributes,
+                PSA_KEY_USAGE_SIGN_HASH |
+                PSA_KEY_USAGE_VERIFY_HASH |
+                PSA_KEY_USAGE_EXPORT );
+            psa_set_key_algorithm(
+                attributes, PSA_ALG_ECDSA( PSA_ALG_ANY_HASH ) );
+
+            if( key_buffer_size < sizeof( psa_drv_slot_number_t ) )
+                return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+            *( (psa_drv_slot_number_t*) key_buffer ) =
+                PSA_CRYPTO_TEST_DRIVER_BUILTIN_ECDSA_KEY_SLOT;
+            *key_buffer_length = sizeof( psa_drv_slot_number_t );
+            return( PSA_SUCCESS );
+        default:
+            return( PSA_ERROR_DOES_NOT_EXIST );
+    }
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/third_party/mbedtls/repo/tests/src/drivers/test_driver_mac.c b/third_party/mbedtls/repo/tests/src/drivers/test_driver_mac.c
new file mode 100644
index 0000000..06b6eb7
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/src/drivers/test_driver_mac.c
@@ -0,0 +1,480 @@
+/*
+ * Test driver for MAC entry points.
+ */
+/*  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.
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
+#include "psa_crypto_mac.h"
+
+#include "test/drivers/mac.h"
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+#include "libtestdriver1/library/psa_crypto_mac.h"
+#endif
+
+mbedtls_test_driver_mac_hooks_t mbedtls_test_driver_mac_hooks =
+    MBEDTLS_TEST_DRIVER_MAC_INIT;
+
+psa_status_t mbedtls_test_transparent_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 )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC)
+        mbedtls_test_driver_mac_hooks.driver_status =
+            libtestdriver1_mbedtls_psa_mac_compute(
+                (const libtestdriver1_psa_key_attributes_t *)attributes,
+                key_buffer, key_buffer_size, alg,
+                input, input_length,
+                mac, mac_size, mac_length );
+#elif defined(MBEDTLS_PSA_BUILTIN_MAC)
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_psa_mac_compute(
+                attributes, key_buffer, key_buffer_size, alg,
+                input, input_length,
+                mac, mac_size, mac_length );
+#else
+        (void) attributes;
+        (void) key_buffer;
+        (void) key_buffer_size;
+        (void) alg;
+        (void) input;
+        (void) input_length;
+        (void) mac;
+        (void) mac_size;
+        (void) mac_length;
+        mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+#endif
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_mac_sign_setup(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC)
+        mbedtls_test_driver_mac_hooks.driver_status =
+            libtestdriver1_mbedtls_psa_mac_sign_setup(
+                operation,
+                (const libtestdriver1_psa_key_attributes_t *)attributes,
+                key_buffer, key_buffer_size, alg );
+#elif defined(MBEDTLS_PSA_BUILTIN_MAC)
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_psa_mac_sign_setup(
+                operation, attributes, key_buffer, key_buffer_size, alg );
+#else
+        (void) operation;
+        (void) attributes;
+        (void) key_buffer;
+        (void) key_buffer_size;
+        (void) alg;
+        mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+#endif
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_mac_verify_setup(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC)
+        mbedtls_test_driver_mac_hooks.driver_status =
+            libtestdriver1_mbedtls_psa_mac_verify_setup(
+                operation,
+                (const libtestdriver1_psa_key_attributes_t *)attributes,
+                key_buffer, key_buffer_size, alg );
+#elif defined(MBEDTLS_PSA_BUILTIN_MAC)
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_psa_mac_verify_setup(
+                operation, attributes, key_buffer, key_buffer_size, alg );
+#else
+        (void) operation;
+        (void) attributes;
+        (void) key_buffer;
+        (void) key_buffer_size;
+        (void) alg;
+        mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+#endif
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_mac_update(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC)
+        mbedtls_test_driver_mac_hooks.driver_status =
+            libtestdriver1_mbedtls_psa_mac_update(
+                operation, input, input_length );
+#elif defined(MBEDTLS_PSA_BUILTIN_MAC)
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_psa_mac_update(
+                operation, input, input_length );
+#else
+        (void) operation;
+        (void) input;
+        (void) input_length;
+        mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+#endif
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_mac_sign_finish(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC)
+        mbedtls_test_driver_mac_hooks.driver_status =
+            libtestdriver1_mbedtls_psa_mac_sign_finish(
+                operation, mac, mac_size, mac_length );
+#elif defined(MBEDTLS_PSA_BUILTIN_MAC)
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_psa_mac_sign_finish(
+                operation, mac, mac_size, mac_length );
+#else
+        (void) operation;
+        (void) mac;
+        (void) mac_size;
+        (void) mac_length;
+        mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+#endif
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_mac_verify_finish(
+    mbedtls_transparent_test_driver_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC)
+        mbedtls_test_driver_mac_hooks.driver_status =
+            libtestdriver1_mbedtls_psa_mac_verify_finish(
+                operation, mac, mac_length );
+#elif defined(MBEDTLS_PSA_BUILTIN_MAC)
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_psa_mac_verify_finish(
+                operation, mac, mac_length );
+#else
+        (void) operation;
+        (void) mac;
+        (void) mac_length;
+        mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+#endif
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_mac_abort(
+    mbedtls_transparent_test_driver_mac_operation_t *operation )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC)
+        mbedtls_test_driver_mac_hooks.driver_status =
+            libtestdriver1_mbedtls_psa_mac_abort( operation );
+#elif defined(MBEDTLS_PSA_BUILTIN_MAC)
+        mbedtls_test_driver_mac_hooks.driver_status =
+            mbedtls_psa_mac_abort( operation );
+#else
+        (void) operation;
+        mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+#endif
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_opaque_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 )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        (void) attributes;
+        (void) key_buffer;
+        (void) key_buffer_size;
+        (void) alg;
+        (void) input;
+        (void) input_length;
+        (void) mac;
+        (void) mac_size;
+        (void) mac_length;
+        mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_opaque_mac_sign_setup(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        (void) operation;
+        (void) attributes;
+        (void) key_buffer;
+        (void) key_buffer_size;
+        (void) alg;
+        mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_opaque_mac_verify_setup(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        (void) operation;
+        (void) attributes;
+        (void) key_buffer;
+        (void) key_buffer_size;
+        (void) alg;
+        mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_opaque_mac_update(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        (void) operation;
+        (void) input;
+        (void) input_length;
+        mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_opaque_mac_sign_finish(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        (void) operation;
+        (void) mac;
+        (void) mac_size;
+        (void) mac_length;
+        mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_opaque_mac_verify_finish(
+    mbedtls_opaque_test_driver_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        (void) operation;
+        (void) mac;
+        (void) mac_length;
+        mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_opaque_mac_abort(
+    mbedtls_opaque_test_driver_mac_operation_t *operation )
+{
+    mbedtls_test_driver_mac_hooks.hits++;
+
+    if( mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_mac_hooks.driver_status =
+             mbedtls_test_driver_mac_hooks.forced_status;
+    }
+    else
+    {
+        (void) operation;
+        mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return( mbedtls_test_driver_mac_hooks.driver_status );
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/third_party/mbedtls/repo/tests/src/drivers/test_driver_signature.c b/third_party/mbedtls/repo/tests/src/drivers/test_driver_signature.c
new file mode 100644
index 0000000..3de43a8
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/src/drivers/test_driver_signature.c
@@ -0,0 +1,433 @@
+/*
+ * Test driver for signature functions.
+ * Currently supports signing and verifying precalculated hashes, using
+ * only deterministic ECDSA on curves secp256r1, secp384r1 and secp521r1.
+ */
+/*  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.
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
+#include "psa/crypto.h"
+#include "psa_crypto_core.h"
+#include "psa_crypto_ecp.h"
+#include "psa_crypto_hash.h"
+#include "psa_crypto_rsa.h"
+#include "mbedtls/ecp.h"
+
+#include "test/drivers/hash.h"
+#include "test/drivers/signature.h"
+#include "test/drivers/hash.h"
+
+#include "mbedtls/md.h"
+#include "mbedtls/ecdsa.h"
+
+#include "test/random.h"
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+#include "libtestdriver1/library/psa_crypto_ecp.h"
+#include "libtestdriver1/library/psa_crypto_hash.h"
+#include "libtestdriver1/library/psa_crypto_rsa.h"
+#endif
+
+#include <string.h>
+
+mbedtls_test_driver_signature_hooks_t
+    mbedtls_test_driver_signature_sign_hooks = MBEDTLS_TEST_DRIVER_SIGNATURE_INIT;
+mbedtls_test_driver_signature_hooks_t
+    mbedtls_test_driver_signature_verify_hooks = MBEDTLS_TEST_DRIVER_SIGNATURE_INIT;
+
+psa_status_t 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 )
+{
+    if( attributes->core.type == PSA_KEY_TYPE_RSA_KEY_PAIR )
+    {
+        if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) ||
+            PSA_ALG_IS_RSA_PSS( alg) )
+        {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    ( defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
+      defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) )
+            return( libtestdriver1_mbedtls_psa_rsa_sign_hash(
+                        (const libtestdriver1_psa_key_attributes_t *) attributes,
+                        key_buffer, key_buffer_size,
+                        alg, hash, hash_length,
+                        signature, signature_size, signature_length ) );
+#elif 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
+        }
+        else
+        {
+            return( PSA_ERROR_INVALID_ARGUMENT );
+        }
+    }
+    else if( PSA_KEY_TYPE_IS_ECC( attributes->core.type ) )
+    {
+        if( PSA_ALG_IS_ECDSA( alg ) )
+        {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    ( defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+      defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) )
+            return( libtestdriver1_mbedtls_psa_ecdsa_sign_hash(
+                        (const libtestdriver1_psa_key_attributes_t *) attributes,
+                        key_buffer, key_buffer_size,
+                        alg, hash, hash_length,
+                        signature, signature_size, signature_length ) );
+#elif 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
+        }
+        else
+        {
+            return( PSA_ERROR_INVALID_ARGUMENT );
+        }
+    }
+
+    (void)attributes;
+    (void)key_buffer;
+    (void)key_buffer_size;
+    (void)alg;
+    (void)hash;
+    (void)hash_length;
+    (void)signature;
+    (void)signature_size;
+    (void)signature_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t 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 )
+{
+    if( PSA_KEY_TYPE_IS_RSA( attributes->core.type ) )
+    {
+        if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) ||
+            PSA_ALG_IS_RSA_PSS( alg) )
+        {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    ( defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
+      defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) )
+            return( libtestdriver1_mbedtls_psa_rsa_verify_hash(
+                        (const libtestdriver1_psa_key_attributes_t *) attributes,
+                        key_buffer, key_buffer_size,
+                        alg, hash, hash_length,
+                        signature, signature_length ) );
+#elif 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
+        }
+        else
+        {
+            return( PSA_ERROR_INVALID_ARGUMENT );
+        }
+    }
+    else if( PSA_KEY_TYPE_IS_ECC( attributes->core.type ) )
+    {
+        if( PSA_ALG_IS_ECDSA( alg ) )
+        {
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    ( defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+      defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) )
+            return( libtestdriver1_mbedtls_psa_ecdsa_verify_hash(
+                        (const libtestdriver1_psa_key_attributes_t *) attributes,
+                        key_buffer, key_buffer_size,
+                        alg, hash, hash_length,
+                        signature, signature_length ) );
+#elif 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
+        }
+        else
+        {
+            return( PSA_ERROR_INVALID_ARGUMENT );
+        }
+    }
+
+    (void)attributes;
+    (void)key_buffer;
+    (void)key_buffer_size;
+    (void)alg;
+    (void)hash;
+    (void)hash_length;
+    (void)signature;
+    (void)signature_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_transparent_signature_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;
+    size_t hash_length;
+    uint8_t hash[PSA_HASH_MAX_SIZE];
+
+    ++mbedtls_test_driver_signature_sign_hooks.hits;
+
+    if( mbedtls_test_driver_signature_sign_hooks.forced_status != PSA_SUCCESS )
+        return( mbedtls_test_driver_signature_sign_hooks.forced_status );
+
+    if( mbedtls_test_driver_signature_sign_hooks.forced_output != NULL )
+    {
+        if( mbedtls_test_driver_signature_sign_hooks.forced_output_length > signature_size )
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+        memcpy( signature, mbedtls_test_driver_signature_sign_hooks.forced_output,
+                mbedtls_test_driver_signature_sign_hooks.forced_output_length );
+        *signature_length = mbedtls_test_driver_signature_sign_hooks.forced_output_length;
+
+        return( PSA_SUCCESS );
+    }
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)
+    status = libtestdriver1_mbedtls_psa_hash_compute(
+                PSA_ALG_SIGN_GET_HASH( alg ), input, input_length,
+                hash, sizeof( hash ), &hash_length );
+#elif defined(MBEDTLS_PSA_BUILTIN_HASH)
+    status = mbedtls_psa_hash_compute(
+                PSA_ALG_SIGN_GET_HASH( alg ), input, input_length,
+                hash, sizeof( hash ), &hash_length );
+#else
+    (void) input;
+    (void) input_length;
+    status = PSA_ERROR_NOT_SUPPORTED;
+#endif
+    if( status != PSA_SUCCESS )
+        return status;
+
+    return( sign_hash( attributes, key_buffer, key_buffer_size,
+                       alg, hash, hash_length,
+                       signature, signature_size, signature_length ) );
+}
+
+psa_status_t mbedtls_test_opaque_signature_sign_message(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key,
+    size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *signature,
+    size_t signature_size,
+    size_t *signature_length )
+{
+    (void) attributes;
+    (void) key;
+    (void) key_length;
+    (void) alg;
+    (void) input;
+    (void) input_length;
+    (void) signature;
+    (void) signature_size;
+    (void) signature_length;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_transparent_signature_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;
+    size_t hash_length;
+    uint8_t hash[PSA_HASH_MAX_SIZE];
+
+    ++mbedtls_test_driver_signature_verify_hooks.hits;
+
+    if( mbedtls_test_driver_signature_verify_hooks.forced_status != PSA_SUCCESS )
+        return( mbedtls_test_driver_signature_verify_hooks.forced_status );
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)
+    status = libtestdriver1_mbedtls_psa_hash_compute(
+                PSA_ALG_SIGN_GET_HASH( alg ), input, input_length,
+                hash, sizeof( hash ), &hash_length );
+#elif defined(MBEDTLS_PSA_BUILTIN_HASH)
+    status = mbedtls_psa_hash_compute(
+                PSA_ALG_SIGN_GET_HASH( alg ), input, input_length,
+                hash, sizeof( hash ), &hash_length );
+#else
+    (void) input;
+    (void) input_length;
+    status = PSA_ERROR_NOT_SUPPORTED;
+#endif
+    if( status != PSA_SUCCESS )
+        return status;
+
+    return( verify_hash( attributes, key_buffer, key_buffer_size,
+                         alg, hash, hash_length,
+                         signature, signature_length ) );
+}
+
+psa_status_t mbedtls_test_opaque_signature_verify_message(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key,
+    size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    const uint8_t *signature,
+    size_t signature_length )
+{
+    (void) attributes;
+    (void) key;
+    (void) key_length;
+    (void) alg;
+    (void) input;
+    (void) input_length;
+    (void) signature;
+    (void) signature_length;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_transparent_signature_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 )
+{
+    ++mbedtls_test_driver_signature_sign_hooks.hits;
+
+    if( mbedtls_test_driver_signature_sign_hooks.forced_status != PSA_SUCCESS )
+        return( mbedtls_test_driver_signature_sign_hooks.forced_status );
+
+    if( mbedtls_test_driver_signature_sign_hooks.forced_output != NULL )
+    {
+        if( mbedtls_test_driver_signature_sign_hooks.forced_output_length > signature_size )
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
+        memcpy( signature, mbedtls_test_driver_signature_sign_hooks.forced_output,
+                mbedtls_test_driver_signature_sign_hooks.forced_output_length );
+        *signature_length = mbedtls_test_driver_signature_sign_hooks.forced_output_length;
+        return( PSA_SUCCESS );
+    }
+
+    return( sign_hash( attributes, key_buffer, key_buffer_size,
+                      alg, hash, hash_length,
+                      signature, signature_size, signature_length ) );
+}
+
+psa_status_t mbedtls_test_opaque_signature_sign_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length,
+    uint8_t *signature, size_t signature_size, size_t *signature_length )
+{
+    (void) attributes;
+    (void) key;
+    (void) key_length;
+    (void) alg;
+    (void) hash;
+    (void) hash_length;
+    (void) signature;
+    (void) signature_size;
+    (void) signature_length;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t mbedtls_test_transparent_signature_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 )
+{
+    ++mbedtls_test_driver_signature_verify_hooks.hits;
+
+    if( mbedtls_test_driver_signature_verify_hooks.forced_status != PSA_SUCCESS )
+        return( mbedtls_test_driver_signature_verify_hooks.forced_status );
+
+    return verify_hash( attributes, key_buffer, key_buffer_size,
+                        alg, hash, hash_length,
+                        signature, signature_length );
+}
+
+psa_status_t mbedtls_test_opaque_signature_verify_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length )
+{
+    (void) attributes;
+    (void) key;
+    (void) key_length;
+    (void) alg;
+    (void) hash;
+    (void) hash_length;
+    (void) signature;
+    (void) signature_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/third_party/mbedtls/repo/tests/src/drivers/test_driver_size.c b/third_party/mbedtls/repo/tests/src/drivers/test_driver_size.c
new file mode 100644
index 0000000..d8bcaee
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/src/drivers/test_driver_size.c
@@ -0,0 +1,101 @@
+/*
+ * Test driver for retrieving key context size.
+ * Only used by opaque drivers.
+ */
+/*  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.
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
+
+#include "test/drivers/size.h"
+#include "psa/crypto.h"
+
+typedef struct {
+    unsigned int context;
+} test_driver_key_context_t;
+
+/*
+ * This macro returns the base size for the key context. It is the size of the
+ * driver specific information stored in each key context.
+ */
+#define TEST_DRIVER_KEY_CONTEXT_BASE_SIZE sizeof( test_driver_key_context_t )
+
+/*
+ * Number of bytes included in every key context for a key pair.
+ *
+ * This pair size is for an ECC 256-bit private/public key pair.
+ * Based on this value, the size of the private key can be derived by
+ * subtracting the public key size below from this one.
+ */
+#define TEST_DRIVER_KEY_CONTEXT_KEY_PAIR_SIZE      65
+
+/*
+ * Number of bytes included in every key context for a public key.
+ *
+ * For ECC public keys, it needs 257 bits so 33 bytes.
+ */
+#define TEST_DRIVER_KEY_CONTEXT_PUBLIC_KEY_SIZE    33
+
+/*
+ * Every key context for a symmetric key includes this many times the key size.
+ */
+#define TEST_DRIVER_KEY_CONTEXT_SYMMETRIC_FACTOR   0
+
+/*
+ * If this is true for a key pair, the key context includes space for the public key.
+ * If this is false, no additional space is added for the public key.
+ *
+ * For this instance, store the public key with the private one.
+ */
+#define TEST_DRIVER_KEY_CONTEXT_STORE_PUBLIC_KEY   1
+
+size_t mbedtls_test_size_function(
+    const psa_key_type_t key_type,
+    const size_t key_bits )
+{
+    size_t key_buffer_size = 0;
+
+    if( PSA_KEY_TYPE_IS_KEY_PAIR( key_type ) )
+    {
+        int public_key_overhead =
+            ( ( TEST_DRIVER_KEY_CONTEXT_STORE_PUBLIC_KEY == 1 )
+              ? PSA_EXPORT_KEY_OUTPUT_SIZE( key_type, key_bits ) : 0 );
+        key_buffer_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE +
+                          TEST_DRIVER_KEY_CONTEXT_PUBLIC_KEY_SIZE +
+                          public_key_overhead;
+    }
+    else if( PSA_KEY_TYPE_IS_PUBLIC_KEY( key_type ) )
+    {
+        key_buffer_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE +
+                          TEST_DRIVER_KEY_CONTEXT_PUBLIC_KEY_SIZE;
+    }
+    else if ( !PSA_KEY_TYPE_IS_KEY_PAIR( key_type ) &&
+              !PSA_KEY_TYPE_IS_PUBLIC_KEY ( key_type ) )
+    {
+        key_buffer_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE +
+                          ( TEST_DRIVER_KEY_CONTEXT_SYMMETRIC_FACTOR *
+                            ( ( key_bits + 7 ) / 8 ) );
+    }
+
+    return( key_buffer_size );
+}
+#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/third_party/mbedtls/repo/tests/src/fake_external_rng_for_test.c b/third_party/mbedtls/repo/tests/src/fake_external_rng_for_test.c
new file mode 100644
index 0000000..9c2195b
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/src/fake_external_rng_for_test.c
@@ -0,0 +1,56 @@
+/** \file fake_external_rng_for_test.c
+ *
+ * \brief Helper functions to test PSA crypto 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.
+ */
+
+#include <test/fake_external_rng_for_test.h>
+
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+#include <test/random.h>
+#include <psa/crypto.h>
+
+static int test_insecure_external_rng_enabled = 0;
+
+void mbedtls_test_enable_insecure_external_rng( void )
+{
+    test_insecure_external_rng_enabled = 1;
+}
+
+void mbedtls_test_disable_insecure_external_rng( void )
+{
+    test_insecure_external_rng_enabled = 0;
+}
+
+psa_status_t mbedtls_psa_external_get_random(
+    mbedtls_psa_external_random_context_t *context,
+    uint8_t *output, size_t output_size, size_t *output_length )
+{
+    (void) context;
+
+    if( !test_insecure_external_rng_enabled )
+        return( PSA_ERROR_INSUFFICIENT_ENTROPY );
+
+    /* This implementation is for test purposes only!
+     * Use the libc non-cryptographic random generator. */
+    mbedtls_test_rnd_std_rand( NULL, output, output_size );
+    *output_length = output_size;
+    return( PSA_SUCCESS );
+}
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
diff --git a/third_party/mbedtls/repo/tests/src/helpers.c b/third_party/mbedtls/repo/tests/src/helpers.c
index a18f1d4..c53e4fc 100644
--- a/third_party/mbedtls/repo/tests/src/helpers.c
+++ b/third_party/mbedtls/repo/tests/src/helpers.c
@@ -44,6 +44,8 @@
 static mbedtls_platform_context platform_ctx;
 #endif
 
+mbedtls_test_info_t mbedtls_test_info;
+
 /*----------------------------------------------------------------------------*/
 /* Helper Functions */
 
@@ -77,6 +79,67 @@
     return( 0 );
 }
 
+void mbedtls_test_fail( const char *test, int line_no, const char* filename )
+{
+    if( mbedtls_test_info.result == MBEDTLS_TEST_RESULT_FAILED )
+    {
+        /* We've already recorded the test as having failed. Don't
+         * overwrite any previous information about the failure. */
+        return;
+    }
+    mbedtls_test_info.result = MBEDTLS_TEST_RESULT_FAILED;
+    mbedtls_test_info.test = test;
+    mbedtls_test_info.line_no = line_no;
+    mbedtls_test_info.filename = filename;
+}
+
+void mbedtls_test_skip( const char *test, int line_no, const char* filename )
+{
+    mbedtls_test_info.result = MBEDTLS_TEST_RESULT_SKIPPED;
+    mbedtls_test_info.test = test;
+    mbedtls_test_info.line_no = line_no;
+    mbedtls_test_info.filename = filename;
+}
+
+void mbedtls_test_set_step( unsigned long step )
+{
+    mbedtls_test_info.step = step;
+}
+
+void mbedtls_test_info_reset( void )
+{
+    mbedtls_test_info.result = MBEDTLS_TEST_RESULT_SUCCESS;
+    mbedtls_test_info.step = (unsigned long)( -1 );
+    mbedtls_test_info.test = 0;
+    mbedtls_test_info.line_no = 0;
+    mbedtls_test_info.filename = 0;
+    memset( mbedtls_test_info.line1, 0, sizeof( mbedtls_test_info.line1 ) );
+    memset( mbedtls_test_info.line2, 0, sizeof( mbedtls_test_info.line2 ) );
+}
+
+int mbedtls_test_equal( const char *test, int line_no, const char* filename,
+                        unsigned long long value1, unsigned long long value2 )
+{
+    if( value1 == value2 )
+        return( 1 );
+    if( mbedtls_test_info.result == MBEDTLS_TEST_RESULT_FAILED )
+    {
+        /* We've already recorded the test as having failed. Don't
+         * overwrite any previous information about the failure. */
+        return( 0 );
+    }
+    mbedtls_test_fail( test, line_no, filename );
+    (void) mbedtls_snprintf( mbedtls_test_info.line1,
+                             sizeof( mbedtls_test_info.line1 ),
+                             "lhs = 0x%016llx = %lld",
+                             value1, (long long) value1 );
+    (void) mbedtls_snprintf( mbedtls_test_info.line2,
+                             sizeof( mbedtls_test_info.line2 ),
+                             "rhs = 0x%016llx = %lld",
+                             value2, (long long) value2 );
+    return( 0 );
+}
+
 int mbedtls_test_unhexify( unsigned char *obuf,
                            size_t obufmax,
                            const char *ibuf,
@@ -244,3 +307,74 @@
     }
 }
 #endif /* MBEDTLS_CHECK_PARAMS */
+
+#if defined(MBEDTLS_TEST_HOOKS)
+void mbedtls_test_err_add_check( int high, int low,
+                                 const char *file, int line )
+{
+    /* Error codes are always negative (a value of zero is a success) however
+     * their positive opposites can be easier to understand. The following
+     * examples given in comments have been made positive for ease of
+     * understanding. The structure of an error code is such:
+     *
+     *                                                shhhhhhhhlllllll
+     *
+     * s = sign bit.
+     * h = high level error code (includes high level module ID (bits 12..14)
+     *     and module-dependent error code (bits 7..11)).
+     * l = low level error code.
+     */
+    if ( high > -0x1000 && high != 0 )
+    /* high < 0001000000000000
+     * No high level module ID bits are set.
+     */
+    {
+        mbedtls_test_fail( "'high' is not a high-level error code",
+                            line, file );
+    }
+    else if ( high < -0x7F80 )
+    /* high > 0111111110000000
+     * Error code is greater than the largest allowed high level module ID.
+     */
+    {
+        mbedtls_test_fail( "'high' error code is greater than 15 bits",
+                            line, file );
+    }
+    else if ( ( high & 0x7F ) != 0 )
+    /* high & 0000000001111111
+     * Error code contains low level error code bits.
+     */
+    {
+        mbedtls_test_fail( "'high' contains a low-level error code",
+                            line, file );
+    }
+    else if ( low < -0x007F )
+    /* low >  0000000001111111
+     * Error code contains high or module level error code bits.
+     */
+    {
+        mbedtls_test_fail( "'low' error code is greater than 7 bits",
+                            line, file );
+    }
+    else if ( low > 0 )
+    {
+        mbedtls_test_fail( "'low' error code is greater than zero",
+                            line, file );
+    }
+}
+#endif /* MBEDTLS_TEST_HOOKS */
+
+#if defined(MBEDTLS_BIGNUM_C)
+int mbedtls_test_read_mpi( mbedtls_mpi *X, int radix, const char *s )
+{
+    /* mbedtls_mpi_read_string() currently retains leading zeros.
+     * It always allocates at least one limb for the value 0. */
+    if( s[0] == 0 )
+    {
+        mbedtls_mpi_free( X );
+        return( 0 );
+    }
+    else
+        return( mbedtls_mpi_read_string( X, radix, s ) );
+}
+#endif
diff --git a/third_party/mbedtls/repo/tests/src/psa_crypto_helpers.c b/third_party/mbedtls/repo/tests/src/psa_crypto_helpers.c
new file mode 100644
index 0000000..299b6d1
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/src/psa_crypto_helpers.c
@@ -0,0 +1,131 @@
+/** \file psa_crypto_helpers.c
+ *
+ * \brief Helper functions to test PSA crypto 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.
+ */
+
+#include <test/helpers.h>
+#include <test/macros.h>
+#include <psa_crypto_slot_management.h>
+#include <test/psa_crypto_helpers.h>
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include <psa/crypto.h>
+
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+
+#include <psa_crypto_storage.h>
+
+static mbedtls_svc_key_id_t key_ids_used_in_test[9];
+static size_t num_key_ids_used;
+
+int mbedtls_test_uses_key_id( mbedtls_svc_key_id_t key_id )
+{
+    size_t i;
+    if( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key_id ) >
+        PSA_MAX_PERSISTENT_KEY_IDENTIFIER )
+    {
+        /* Don't touch key id values that designate non-key files. */
+        return( 1 );
+    }
+    for( i = 0; i < num_key_ids_used ; i++ )
+    {
+        if( mbedtls_svc_key_id_equal( key_id, key_ids_used_in_test[i] ) )
+            return( 1 );
+    }
+    if( num_key_ids_used == ARRAY_LENGTH( key_ids_used_in_test ) )
+        return( 0 );
+    key_ids_used_in_test[num_key_ids_used] = key_id;
+    ++num_key_ids_used;
+    return( 1 );
+}
+
+void mbedtls_test_psa_purge_key_storage( void )
+{
+    size_t i;
+    for( i = 0; i < num_key_ids_used; i++ )
+        psa_destroy_persistent_key( key_ids_used_in_test[i] );
+    num_key_ids_used = 0;
+}
+
+void mbedtls_test_psa_purge_key_cache( void )
+{
+    size_t i;
+    for( i = 0; i < num_key_ids_used; i++ )
+        psa_purge_key( key_ids_used_in_test[i] );
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
+
+const char *mbedtls_test_helper_is_psa_leaking( void )
+{
+    mbedtls_psa_stats_t stats;
+
+    mbedtls_psa_get_stats( &stats );
+
+    if( stats.volatile_slots != 0 )
+        return( "A volatile slot has not been closed properly." );
+    if( stats.persistent_slots != 0 )
+        return( "A persistent slot has not been closed properly." );
+    if( stats.external_slots != 0 )
+        return( "An external slot has not been closed properly." );
+     if( stats.half_filled_slots != 0 )
+        return( "A half-filled slot has not been cleared properly." );
+    if( stats.locked_slots != 0 )
+        return( "Some slots are still marked as locked." );
+
+    return( NULL );
+}
+
+#if defined(RECORD_PSA_STATUS_COVERAGE_LOG)
+/** Name of the file where return statuses are logged by #RECORD_STATUS. */
+#define STATUS_LOG_FILE_NAME "statuses.log"
+
+psa_status_t mbedtls_test_record_status( psa_status_t status,
+                                         const char *func,
+                                         const char *file, int line,
+                                         const char *expr )
+{
+    /* We open the log file on first use.
+     * We never close the log file, so the record_status feature is not
+     * compatible with resource leak detectors such as Asan.
+     */
+    static FILE *log;
+    if( log == NULL )
+        log = fopen( STATUS_LOG_FILE_NAME, "a" );
+    fprintf( log, "%d:%s:%s:%d:%s\n", (int) status, func, file, line, expr );
+    return( status );
+}
+#endif /* defined(RECORD_PSA_STATUS_COVERAGE_LOG) */
+
+psa_key_usage_t mbedtls_test_update_key_usage_flags( psa_key_usage_t usage_flags )
+{
+    psa_key_usage_t updated_usage = usage_flags;
+
+    if( usage_flags & PSA_KEY_USAGE_SIGN_HASH )
+        updated_usage |= PSA_KEY_USAGE_SIGN_MESSAGE;
+
+    if( usage_flags & PSA_KEY_USAGE_VERIFY_HASH )
+        updated_usage |= PSA_KEY_USAGE_VERIFY_MESSAGE;
+
+    return( updated_usage );
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/third_party/mbedtls/repo/tests/src/psa_exercise_key.c b/third_party/mbedtls/repo/tests/src/psa_exercise_key.c
new file mode 100644
index 0000000..c1e76c8
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/src/psa_exercise_key.c
@@ -0,0 +1,965 @@
+/** Code to exercise a PSA key object, i.e. validate that it seems well-formed
+ * and can do what it is supposed to do.
+ */
+
+/*
+ *  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 <test/helpers.h>
+#include <test/macros.h>
+#include <test/psa_exercise_key.h>
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include <mbedtls/asn1.h>
+#include <psa/crypto.h>
+
+#include <test/asn1_helpers.h>
+#include <psa_crypto_slot_management.h>
+#include <test/psa_crypto_helpers.h>
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+static int lifetime_is_dynamic_secure_element( psa_key_lifetime_t lifetime )
+{
+    return( PSA_KEY_LIFETIME_GET_LOCATION( lifetime ) !=
+            PSA_KEY_LOCATION_LOCAL_STORAGE );
+}
+#endif
+
+static int check_key_attributes_sanity( mbedtls_svc_key_id_t key )
+{
+    int ok = 0;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_lifetime_t lifetime;
+    mbedtls_svc_key_id_t id;
+    psa_key_type_t type;
+    size_t bits;
+
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+    lifetime = psa_get_key_lifetime( &attributes );
+    id = psa_get_key_id( &attributes );
+    type = psa_get_key_type( &attributes );
+    bits = psa_get_key_bits( &attributes );
+
+    /* Persistence */
+    if( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) )
+    {
+        TEST_ASSERT(
+            ( PSA_KEY_ID_VOLATILE_MIN <=
+              MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ) &&
+            ( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) <=
+              PSA_KEY_ID_VOLATILE_MAX ) );
+    }
+    else
+    {
+        TEST_ASSERT(
+            ( PSA_KEY_ID_USER_MIN <= MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ) &&
+            ( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) <= PSA_KEY_ID_USER_MAX ) );
+    }
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    /* randomly-generated 64-bit constant, should never appear in test data */
+    psa_key_slot_number_t slot_number = 0xec94d4a5058a1a21;
+    psa_status_t status = psa_get_key_slot_number( &attributes, &slot_number );
+    if( lifetime_is_dynamic_secure_element( lifetime ) )
+    {
+        /* Mbed Crypto currently always exposes the slot number to
+         * applications. This is not mandated by the PSA specification
+         * and may change in future versions. */
+        TEST_EQUAL( status, 0 );
+        TEST_ASSERT( slot_number != 0xec94d4a5058a1a21 );
+    }
+    else
+    {
+        TEST_EQUAL( status, PSA_ERROR_INVALID_ARGUMENT );
+    }
+#endif
+
+    /* Type and size */
+    TEST_ASSERT( type != 0 );
+    TEST_ASSERT( bits != 0 );
+    TEST_ASSERT( bits <= PSA_MAX_KEY_BITS );
+    if( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) )
+        TEST_ASSERT( bits % 8 == 0 );
+
+    /* MAX macros concerning specific key types */
+    if( PSA_KEY_TYPE_IS_ECC( type ) )
+        TEST_ASSERT( bits <= PSA_VENDOR_ECC_MAX_CURVE_BITS );
+    else if( PSA_KEY_TYPE_IS_RSA( type ) )
+        TEST_ASSERT( bits <= PSA_VENDOR_RSA_MAX_KEY_BITS );
+    TEST_ASSERT( PSA_BLOCK_CIPHER_BLOCK_LENGTH( type ) <= PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE );
+
+    ok = 1;
+
+exit:
+    /*
+     * Key attributes may have been returned by psa_get_key_attributes()
+     * thus reset them as required.
+     */
+    psa_reset_key_attributes( &attributes );
+
+    return( ok );
+}
+
+static int exercise_mac_key( mbedtls_svc_key_id_t key,
+                             psa_key_usage_t usage,
+                             psa_algorithm_t alg )
+{
+    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+    const unsigned char input[] = "foo";
+    unsigned char mac[PSA_MAC_MAX_SIZE] = {0};
+    size_t mac_length = sizeof( mac );
+
+    /* Convert wildcard algorithm to exercisable algorithm */
+    if( alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG )
+    {
+        alg = PSA_ALG_TRUNCATED_MAC( alg, PSA_MAC_TRUNCATED_LENGTH( alg ) );
+    }
+
+    if( usage & PSA_KEY_USAGE_SIGN_HASH )
+    {
+        PSA_ASSERT( psa_mac_sign_setup( &operation, key, alg ) );
+        PSA_ASSERT( psa_mac_update( &operation,
+                                    input, sizeof( input ) ) );
+        PSA_ASSERT( psa_mac_sign_finish( &operation,
+                                         mac, sizeof( mac ),
+                                         &mac_length ) );
+    }
+
+    if( usage & PSA_KEY_USAGE_VERIFY_HASH )
+    {
+        psa_status_t verify_status =
+            ( usage & PSA_KEY_USAGE_SIGN_HASH ?
+              PSA_SUCCESS :
+              PSA_ERROR_INVALID_SIGNATURE );
+        PSA_ASSERT( psa_mac_verify_setup( &operation, key, alg ) );
+        PSA_ASSERT( psa_mac_update( &operation,
+                                    input, sizeof( input ) ) );
+        TEST_EQUAL( psa_mac_verify_finish( &operation, mac, mac_length ),
+                    verify_status );
+    }
+
+    return( 1 );
+
+exit:
+    psa_mac_abort( &operation );
+    return( 0 );
+}
+
+static int exercise_cipher_key( mbedtls_svc_key_id_t key,
+                                psa_key_usage_t usage,
+                                psa_algorithm_t alg )
+{
+    psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
+    unsigned char iv[16] = {0};
+    size_t iv_length = sizeof( iv );
+    const unsigned char plaintext[16] = "Hello, world...";
+    unsigned char ciphertext[32] = "(wabblewebblewibblewobblewubble)";
+    size_t ciphertext_length = sizeof( ciphertext );
+    unsigned char decrypted[sizeof( ciphertext )];
+    size_t part_length;
+
+    if( usage & PSA_KEY_USAGE_ENCRYPT )
+    {
+        PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
+        PSA_ASSERT( psa_cipher_generate_iv( &operation,
+                                            iv, sizeof( iv ),
+                                            &iv_length ) );
+        PSA_ASSERT( psa_cipher_update( &operation,
+                                       plaintext, sizeof( plaintext ),
+                                       ciphertext, sizeof( ciphertext ),
+                                       &ciphertext_length ) );
+        PSA_ASSERT( psa_cipher_finish( &operation,
+                                       ciphertext + ciphertext_length,
+                                       sizeof( ciphertext ) - ciphertext_length,
+                                       &part_length ) );
+        ciphertext_length += part_length;
+    }
+
+    if( usage & PSA_KEY_USAGE_DECRYPT )
+    {
+        psa_status_t status;
+        int maybe_invalid_padding = 0;
+        if( ! ( usage & PSA_KEY_USAGE_ENCRYPT ) )
+        {
+            psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+            PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+            /* This should be PSA_CIPHER_GET_IV_SIZE but the API doesn't
+             * have this macro yet. */
+            iv_length = PSA_BLOCK_CIPHER_BLOCK_LENGTH(
+                psa_get_key_type( &attributes ) );
+            maybe_invalid_padding = ! PSA_ALG_IS_STREAM_CIPHER( alg );
+            psa_reset_key_attributes( &attributes );
+        }
+        PSA_ASSERT( psa_cipher_decrypt_setup( &operation, key, alg ) );
+        PSA_ASSERT( psa_cipher_set_iv( &operation,
+                                       iv, iv_length ) );
+        PSA_ASSERT( psa_cipher_update( &operation,
+                                       ciphertext, ciphertext_length,
+                                       decrypted, sizeof( decrypted ),
+                                       &part_length ) );
+        status = psa_cipher_finish( &operation,
+                                    decrypted + part_length,
+                                    sizeof( decrypted ) - part_length,
+                                    &part_length );
+        /* For a stream cipher, all inputs are valid. For a block cipher,
+         * if the input is some aribtrary data rather than an actual
+         ciphertext, a padding error is likely.  */
+        if( maybe_invalid_padding )
+            TEST_ASSERT( status == PSA_SUCCESS ||
+                         status == PSA_ERROR_INVALID_PADDING );
+        else
+            PSA_ASSERT( status );
+    }
+
+    return( 1 );
+
+exit:
+    psa_cipher_abort( &operation );
+    return( 0 );
+}
+
+static int exercise_aead_key( mbedtls_svc_key_id_t key,
+                              psa_key_usage_t usage,
+                              psa_algorithm_t alg )
+{
+    unsigned char nonce[16] = {0};
+    size_t nonce_length = sizeof( nonce );
+    unsigned char plaintext[16] = "Hello, world...";
+    unsigned char ciphertext[48] = "(wabblewebblewibblewobblewubble)";
+    size_t ciphertext_length = sizeof( ciphertext );
+    size_t plaintext_length = sizeof( ciphertext );
+
+    /* Convert wildcard algorithm to exercisable algorithm */
+    if( alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG )
+    {
+        alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, PSA_ALG_AEAD_GET_TAG_LENGTH( alg ) );
+    }
+
+    /* Default IV length for AES-GCM is 12 bytes */
+    if( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) ==
+        PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ) )
+    {
+        nonce_length = 12;
+    }
+
+    /* IV length for CCM needs to be between 7 and 13 bytes */
+    if( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) ==
+        PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ) )
+    {
+        nonce_length = 12;
+    }
+
+    if( usage & PSA_KEY_USAGE_ENCRYPT )
+    {
+        PSA_ASSERT( psa_aead_encrypt( key, alg,
+                                      nonce, nonce_length,
+                                      NULL, 0,
+                                      plaintext, sizeof( plaintext ),
+                                      ciphertext, sizeof( ciphertext ),
+                                      &ciphertext_length ) );
+    }
+
+    if( usage & PSA_KEY_USAGE_DECRYPT )
+    {
+        psa_status_t verify_status =
+            ( usage & PSA_KEY_USAGE_ENCRYPT ?
+              PSA_SUCCESS :
+              PSA_ERROR_INVALID_SIGNATURE );
+        TEST_EQUAL( psa_aead_decrypt( key, alg,
+                                      nonce, nonce_length,
+                                      NULL, 0,
+                                      ciphertext, ciphertext_length,
+                                      plaintext, sizeof( plaintext ),
+                                      &plaintext_length ),
+                    verify_status );
+    }
+
+    return( 1 );
+
+exit:
+    return( 0 );
+}
+
+static int exercise_signature_key( mbedtls_svc_key_id_t key,
+                                   psa_key_usage_t usage,
+                                   psa_algorithm_t alg )
+{
+    if( usage & ( PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH ) )
+    {
+        unsigned char payload[PSA_HASH_MAX_SIZE] = {1};
+        size_t payload_length = 16;
+        unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = {0};
+        size_t signature_length = sizeof( signature );
+        psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
+
+        /* If the policy allows signing with any hash, just pick one. */
+        if( PSA_ALG_IS_SIGN_HASH( alg ) && hash_alg == PSA_ALG_ANY_HASH )
+        {
+    #if defined(KNOWN_MBEDTLS_SUPPORTED_HASH_ALG)
+            hash_alg = KNOWN_MBEDTLS_SUPPORTED_HASH_ALG;
+            alg ^= PSA_ALG_ANY_HASH ^ hash_alg;
+    #else
+            TEST_ASSERT( ! "No hash algorithm for hash-and-sign testing" );
+    #endif
+        }
+
+        /* Some algorithms require the payload to have the size of
+         * the hash encoded in the algorithm. Use this input size
+         * even for algorithms that allow other input sizes. */
+        if( hash_alg != 0 )
+            payload_length = PSA_HASH_LENGTH( hash_alg );
+
+        if( usage & PSA_KEY_USAGE_SIGN_HASH )
+        {
+            PSA_ASSERT( psa_sign_hash( key, alg,
+                                       payload, payload_length,
+                                       signature, sizeof( signature ),
+                                       &signature_length ) );
+        }
+
+        if( usage & PSA_KEY_USAGE_VERIFY_HASH )
+        {
+            psa_status_t verify_status =
+                ( usage & PSA_KEY_USAGE_SIGN_HASH ?
+                  PSA_SUCCESS :
+                  PSA_ERROR_INVALID_SIGNATURE );
+            TEST_EQUAL( psa_verify_hash( key, alg,
+                                         payload, payload_length,
+                                         signature, signature_length ),
+                        verify_status );
+        }
+    }
+
+    if( usage & ( PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE ) )
+    {
+        unsigned char message[256] = "Hello, world...";
+        unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = {0};
+        size_t message_length = 16;
+        size_t signature_length = sizeof( signature );
+
+        if( usage & PSA_KEY_USAGE_SIGN_MESSAGE )
+        {
+            PSA_ASSERT( psa_sign_message( key, alg,
+                                          message, message_length,
+                                          signature, sizeof( signature ),
+                                          &signature_length ) );
+        }
+
+        if( usage & PSA_KEY_USAGE_VERIFY_MESSAGE )
+        {
+            psa_status_t verify_status =
+                ( usage & PSA_KEY_USAGE_SIGN_MESSAGE ?
+                  PSA_SUCCESS :
+                  PSA_ERROR_INVALID_SIGNATURE );
+            TEST_EQUAL( psa_verify_message( key, alg,
+                                            message, message_length,
+                                            signature, signature_length ),
+                        verify_status );
+        }
+    }
+
+    return( 1 );
+
+exit:
+    return( 0 );
+}
+
+static int exercise_asymmetric_encryption_key( mbedtls_svc_key_id_t key,
+                                               psa_key_usage_t usage,
+                                               psa_algorithm_t alg )
+{
+    unsigned char plaintext[256] = "Hello, world...";
+    unsigned char ciphertext[256] = "(wabblewebblewibblewobblewubble)";
+    size_t ciphertext_length = sizeof( ciphertext );
+    size_t plaintext_length = 16;
+
+    if( usage & PSA_KEY_USAGE_ENCRYPT )
+    {
+        PSA_ASSERT( psa_asymmetric_encrypt( key, alg,
+                                            plaintext, plaintext_length,
+                                            NULL, 0,
+                                            ciphertext, sizeof( ciphertext ),
+                                            &ciphertext_length ) );
+    }
+
+    if( usage & PSA_KEY_USAGE_DECRYPT )
+    {
+        psa_status_t status =
+            psa_asymmetric_decrypt( key, alg,
+                                    ciphertext, ciphertext_length,
+                                    NULL, 0,
+                                    plaintext, sizeof( plaintext ),
+                                    &plaintext_length );
+        TEST_ASSERT( status == PSA_SUCCESS ||
+                     ( ( usage & PSA_KEY_USAGE_ENCRYPT ) == 0 &&
+                       ( status == PSA_ERROR_INVALID_ARGUMENT ||
+                         status == PSA_ERROR_INVALID_PADDING ) ) );
+    }
+
+    return( 1 );
+
+exit:
+    return( 0 );
+}
+
+int mbedtls_test_psa_setup_key_derivation_wrap(
+    psa_key_derivation_operation_t* operation,
+    mbedtls_svc_key_id_t key,
+    psa_algorithm_t alg,
+    const unsigned char* input1, size_t input1_length,
+    const unsigned char* input2, size_t input2_length,
+    size_t capacity )
+{
+    PSA_ASSERT( psa_key_derivation_setup( operation, alg ) );
+    if( PSA_ALG_IS_HKDF( alg ) )
+    {
+        PSA_ASSERT( psa_key_derivation_input_bytes( operation,
+                                                    PSA_KEY_DERIVATION_INPUT_SALT,
+                                                    input1, input1_length ) );
+        PSA_ASSERT( psa_key_derivation_input_key( operation,
+                                                  PSA_KEY_DERIVATION_INPUT_SECRET,
+                                                  key ) );
+        PSA_ASSERT( psa_key_derivation_input_bytes( operation,
+                                                    PSA_KEY_DERIVATION_INPUT_INFO,
+                                                    input2,
+                                                    input2_length ) );
+    }
+    else if( PSA_ALG_IS_TLS12_PRF( alg ) ||
+             PSA_ALG_IS_TLS12_PSK_TO_MS( alg ) )
+    {
+        PSA_ASSERT( psa_key_derivation_input_bytes( operation,
+                                                    PSA_KEY_DERIVATION_INPUT_SEED,
+                                                    input1, input1_length ) );
+        PSA_ASSERT( psa_key_derivation_input_key( operation,
+                                                  PSA_KEY_DERIVATION_INPUT_SECRET,
+                                                  key ) );
+        PSA_ASSERT( psa_key_derivation_input_bytes( operation,
+                                                    PSA_KEY_DERIVATION_INPUT_LABEL,
+                                                    input2, input2_length ) );
+    }
+    else
+    {
+        TEST_ASSERT( ! "Key derivation algorithm not supported" );
+    }
+
+    if( capacity != SIZE_MAX )
+        PSA_ASSERT( psa_key_derivation_set_capacity( operation, capacity ) );
+
+    return( 1 );
+
+exit:
+    return( 0 );
+}
+
+
+static int exercise_key_derivation_key( mbedtls_svc_key_id_t key,
+                                        psa_key_usage_t usage,
+                                        psa_algorithm_t alg )
+{
+    psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
+    unsigned char input1[] = "Input 1";
+    size_t input1_length = sizeof( input1 );
+    unsigned char input2[] = "Input 2";
+    size_t input2_length = sizeof( input2 );
+    unsigned char output[1];
+    size_t capacity = sizeof( output );
+
+    if( usage & PSA_KEY_USAGE_DERIVE )
+    {
+        if( !mbedtls_test_psa_setup_key_derivation_wrap( &operation, key, alg,
+                                                         input1, input1_length,
+                                                         input2, input2_length,
+                                                         capacity ) )
+            goto exit;
+
+        PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
+                                                     output,
+                                                     capacity ) );
+        PSA_ASSERT( psa_key_derivation_abort( &operation ) );
+    }
+
+    return( 1 );
+
+exit:
+    return( 0 );
+}
+
+/* We need two keys to exercise key agreement. Exercise the
+ * private key against its own public key. */
+psa_status_t mbedtls_test_psa_key_agreement_with_self(
+    psa_key_derivation_operation_t *operation,
+    mbedtls_svc_key_id_t key )
+{
+    psa_key_type_t private_key_type;
+    psa_key_type_t public_key_type;
+    size_t key_bits;
+    uint8_t *public_key = NULL;
+    size_t public_key_length;
+    /* Return GENERIC_ERROR if something other than the final call to
+     * psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
+     * but it's good enough: callers will report it as a failed test anyway. */
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+    private_key_type = psa_get_key_type( &attributes );
+    key_bits = psa_get_key_bits( &attributes );
+    public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( private_key_type );
+    public_key_length = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( public_key_type, key_bits );
+    ASSERT_ALLOC( public_key, public_key_length );
+    PSA_ASSERT( psa_export_public_key( key, public_key, public_key_length,
+                                       &public_key_length ) );
+
+    status = psa_key_derivation_key_agreement(
+        operation, PSA_KEY_DERIVATION_INPUT_SECRET, key,
+        public_key, public_key_length );
+exit:
+    /*
+     * Key attributes may have been returned by psa_get_key_attributes()
+     * thus reset them as required.
+     */
+    psa_reset_key_attributes( &attributes );
+
+    mbedtls_free( public_key );
+    return( status );
+}
+
+/* We need two keys to exercise key agreement. Exercise the
+ * private key against its own public key. */
+psa_status_t mbedtls_test_psa_raw_key_agreement_with_self(
+    psa_algorithm_t alg,
+    mbedtls_svc_key_id_t key )
+{
+    psa_key_type_t private_key_type;
+    psa_key_type_t public_key_type;
+    size_t key_bits;
+    uint8_t *public_key = NULL;
+    size_t public_key_length;
+    uint8_t output[1024];
+    size_t output_length;
+    /* Return GENERIC_ERROR if something other than the final call to
+     * psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
+     * but it's good enough: callers will report it as a failed test anyway. */
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+    private_key_type = psa_get_key_type( &attributes );
+    key_bits = psa_get_key_bits( &attributes );
+    public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( private_key_type );
+    public_key_length = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( public_key_type, key_bits );
+    ASSERT_ALLOC( public_key, public_key_length );
+    PSA_ASSERT( psa_export_public_key( key,
+                                       public_key, public_key_length,
+                                       &public_key_length ) );
+
+    status = psa_raw_key_agreement( alg, key,
+                                    public_key, public_key_length,
+                                    output, sizeof( output ), &output_length );
+    if ( status == PSA_SUCCESS )
+    {
+        TEST_ASSERT( output_length <=
+                     PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE( private_key_type,
+                                                        key_bits ) );
+        TEST_ASSERT( output_length <=
+                     PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE );
+    }
+
+exit:
+    /*
+     * Key attributes may have been returned by psa_get_key_attributes()
+     * thus reset them as required.
+     */
+    psa_reset_key_attributes( &attributes );
+
+    mbedtls_free( public_key );
+    return( status );
+}
+
+static int exercise_raw_key_agreement_key( mbedtls_svc_key_id_t key,
+                                           psa_key_usage_t usage,
+                                           psa_algorithm_t alg )
+{
+    int ok = 0;
+
+    if( usage & PSA_KEY_USAGE_DERIVE )
+    {
+        /* We need two keys to exercise key agreement. Exercise the
+         * private key against its own public key. */
+        PSA_ASSERT( mbedtls_test_psa_raw_key_agreement_with_self( alg, key ) );
+    }
+    ok = 1;
+
+exit:
+    return( ok );
+}
+
+static int exercise_key_agreement_key( mbedtls_svc_key_id_t key,
+                                       psa_key_usage_t usage,
+                                       psa_algorithm_t alg )
+{
+    psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
+    unsigned char output[1];
+    int ok = 0;
+
+    if( usage & PSA_KEY_USAGE_DERIVE )
+    {
+        /* We need two keys to exercise key agreement. Exercise the
+         * private key against its own public key. */
+        PSA_ASSERT( psa_key_derivation_setup( &operation, alg ) );
+        PSA_ASSERT( mbedtls_test_psa_key_agreement_with_self( &operation, key ) );
+        PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
+                                                     output,
+                                                     sizeof( output ) ) );
+        PSA_ASSERT( psa_key_derivation_abort( &operation ) );
+    }
+    ok = 1;
+
+exit:
+    return( ok );
+}
+
+int mbedtls_test_psa_exported_key_sanity_check(
+    psa_key_type_t type, size_t bits,
+    const uint8_t *exported, size_t exported_length )
+{
+    TEST_ASSERT( exported_length <= PSA_EXPORT_KEY_OUTPUT_SIZE( type, bits ) );
+
+    if( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) )
+        TEST_EQUAL( exported_length, PSA_BITS_TO_BYTES( bits ) );
+    else
+
+#if defined(MBEDTLS_ASN1_PARSE_C)
+    if( type == PSA_KEY_TYPE_RSA_KEY_PAIR )
+    {
+        uint8_t *p = (uint8_t*) exported;
+        const uint8_t *end = exported + exported_length;
+        size_t len;
+        /*   RSAPrivateKey ::= SEQUENCE {
+         *       version             INTEGER,  -- must be 0
+         *       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
+         *   }
+         */
+        TEST_EQUAL( mbedtls_asn1_get_tag( &p, end, &len,
+                                          MBEDTLS_ASN1_SEQUENCE |
+                                          MBEDTLS_ASN1_CONSTRUCTED ), 0 );
+        TEST_EQUAL( len, end - p );
+        if( ! mbedtls_test_asn1_skip_integer( &p, end, 0, 0, 0 ) )
+            goto exit;
+        if( ! mbedtls_test_asn1_skip_integer( &p, end, bits, bits, 1 ) )
+            goto exit;
+        if( ! mbedtls_test_asn1_skip_integer( &p, end, 2, bits, 1 ) )
+            goto exit;
+        /* Require d to be at least half the size of n. */
+        if( ! mbedtls_test_asn1_skip_integer( &p, end, bits / 2, bits, 1 ) )
+            goto exit;
+        /* Require p and q to be at most half the size of n, rounded up. */
+        if( ! mbedtls_test_asn1_skip_integer( &p, end, bits / 2, bits / 2 + 1, 1 ) )
+            goto exit;
+        if( ! mbedtls_test_asn1_skip_integer( &p, end, bits / 2, bits / 2 + 1, 1 ) )
+            goto exit;
+        if( ! mbedtls_test_asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
+            goto exit;
+        if( ! mbedtls_test_asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
+            goto exit;
+        if( ! mbedtls_test_asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
+            goto exit;
+        TEST_EQUAL( p - end, 0 );
+
+        TEST_ASSERT( exported_length <= PSA_EXPORT_KEY_PAIR_MAX_SIZE );
+    }
+    else
+#endif /* MBEDTLS_ASN1_PARSE_C */
+
+#if defined(MBEDTLS_ECP_C)
+    if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( type ) )
+    {
+        /* Just the secret value */
+        TEST_EQUAL( exported_length, PSA_BITS_TO_BYTES( bits ) );
+
+        TEST_ASSERT( exported_length <= PSA_EXPORT_KEY_PAIR_MAX_SIZE );
+    }
+    else
+#endif /* MBEDTLS_ECP_C */
+
+#if defined(MBEDTLS_ASN1_PARSE_C)
+    if( type == PSA_KEY_TYPE_RSA_PUBLIC_KEY )
+    {
+        uint8_t *p = (uint8_t*) exported;
+        const uint8_t *end = exported + exported_length;
+        size_t len;
+        /*   RSAPublicKey ::= SEQUENCE {
+         *      modulus            INTEGER,    -- n
+         *      publicExponent     INTEGER  }  -- e
+         */
+        TEST_EQUAL( mbedtls_asn1_get_tag( &p, end, &len,
+                                          MBEDTLS_ASN1_SEQUENCE |
+                                          MBEDTLS_ASN1_CONSTRUCTED ),
+                    0 );
+        TEST_EQUAL( len, end - p );
+        if( ! mbedtls_test_asn1_skip_integer( &p, end, bits, bits, 1 ) )
+            goto exit;
+        if( ! mbedtls_test_asn1_skip_integer( &p, end, 2, bits, 1 ) )
+            goto exit;
+        TEST_EQUAL( p - end, 0 );
+
+
+        TEST_ASSERT( exported_length <=
+                     PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( type, bits ) );
+        TEST_ASSERT( exported_length <=
+                     PSA_EXPORT_PUBLIC_KEY_MAX_SIZE );
+    }
+    else
+#endif /* MBEDTLS_ASN1_PARSE_C */
+
+#if defined(MBEDTLS_ECP_C)
+    if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( type ) )
+    {
+
+        TEST_ASSERT( exported_length <=
+                     PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( type, bits ) );
+        TEST_ASSERT( exported_length <=
+                     PSA_EXPORT_PUBLIC_KEY_MAX_SIZE );
+
+        if( PSA_KEY_TYPE_ECC_GET_FAMILY( type ) == PSA_ECC_FAMILY_MONTGOMERY )
+        {
+            /* The representation of an ECC Montgomery public key is
+             * the raw compressed point */
+             TEST_EQUAL( PSA_BITS_TO_BYTES( bits ), exported_length );
+        }
+        else
+        {
+            /* The representation of an ECC Weierstrass public key is:
+             *      - 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;
+             *      - where m is the bit size associated with the curve.
+             */
+            TEST_EQUAL( 1 + 2 * PSA_BITS_TO_BYTES( bits ), exported_length );
+            TEST_EQUAL( exported[0], 4 );
+        }
+    }
+    else
+#endif /* MBEDTLS_ECP_C */
+
+    {
+        TEST_ASSERT( ! "Sanity check not implemented for this key type" );
+    }
+
+#if defined(MBEDTLS_DES_C)
+    if( type == PSA_KEY_TYPE_DES )
+    {
+        /* Check the parity bits. */
+        unsigned i;
+        for( i = 0; i < bits / 8; i++ )
+        {
+            unsigned bit_count = 0;
+            unsigned m;
+            for( m = 1; m <= 0x100; m <<= 1 )
+            {
+                if( exported[i] & m )
+                    ++bit_count;
+            }
+            TEST_ASSERT( bit_count % 2 != 0 );
+        }
+    }
+#endif
+
+    return( 1 );
+
+exit:
+    return( 0 );
+}
+
+static int exercise_export_key( mbedtls_svc_key_id_t key,
+                                psa_key_usage_t usage )
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    uint8_t *exported = NULL;
+    size_t exported_size = 0;
+    size_t exported_length = 0;
+    int ok = 0;
+
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+
+    exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
+                        psa_get_key_type( &attributes ),
+                        psa_get_key_bits( &attributes ) );
+    ASSERT_ALLOC( exported, exported_size );
+
+    if( ( usage & PSA_KEY_USAGE_EXPORT ) == 0 &&
+        ! PSA_KEY_TYPE_IS_PUBLIC_KEY( psa_get_key_type( &attributes ) ) )
+    {
+        TEST_EQUAL( psa_export_key( key, exported,
+                                    exported_size, &exported_length ),
+                    PSA_ERROR_NOT_PERMITTED );
+        ok = 1;
+        goto exit;
+    }
+
+    PSA_ASSERT( psa_export_key( key,
+                                exported, exported_size,
+                                &exported_length ) );
+    ok = mbedtls_test_psa_exported_key_sanity_check(
+        psa_get_key_type( &attributes ), psa_get_key_bits( &attributes ),
+        exported, exported_length );
+
+exit:
+    /*
+     * Key attributes may have been returned by psa_get_key_attributes()
+     * thus reset them as required.
+     */
+    psa_reset_key_attributes( &attributes );
+
+    mbedtls_free( exported );
+    return( ok );
+}
+
+static int exercise_export_public_key( mbedtls_svc_key_id_t key )
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_type_t public_type;
+    uint8_t *exported = NULL;
+    size_t exported_size = 0;
+    size_t exported_length = 0;
+    int ok = 0;
+
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+    if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( psa_get_key_type( &attributes ) ) )
+    {
+        exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
+                            psa_get_key_type( &attributes ),
+                            psa_get_key_bits( &attributes ) );
+        ASSERT_ALLOC( exported, exported_size );
+
+        TEST_EQUAL( psa_export_public_key( key, exported,
+                                           exported_size, &exported_length ),
+                    PSA_ERROR_INVALID_ARGUMENT );
+        ok = 1;
+        goto exit;
+    }
+
+    public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(
+        psa_get_key_type( &attributes ) );
+    exported_size = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( public_type,
+                                                       psa_get_key_bits( &attributes ) );
+    ASSERT_ALLOC( exported, exported_size );
+
+    PSA_ASSERT( psa_export_public_key( key,
+                                       exported, exported_size,
+                                       &exported_length ) );
+    ok = mbedtls_test_psa_exported_key_sanity_check(
+        public_type, psa_get_key_bits( &attributes ),
+        exported, exported_length );
+
+exit:
+    /*
+     * Key attributes may have been returned by psa_get_key_attributes()
+     * thus reset them as required.
+     */
+    psa_reset_key_attributes( &attributes );
+
+    mbedtls_free( exported );
+    return( ok );
+}
+
+int mbedtls_test_psa_exercise_key( mbedtls_svc_key_id_t key,
+                                   psa_key_usage_t usage,
+                                   psa_algorithm_t alg )
+{
+    int ok = 0;
+
+    if( ! check_key_attributes_sanity( key ) )
+        return( 0 );
+
+    if( alg == 0 )
+        ok = 1; /* If no algorihm, do nothing (used for raw data "keys"). */
+    else if( PSA_ALG_IS_MAC( alg ) )
+        ok = exercise_mac_key( key, usage, alg );
+    else if( PSA_ALG_IS_CIPHER( alg ) )
+        ok = exercise_cipher_key( key, usage, alg );
+    else if( PSA_ALG_IS_AEAD( alg ) )
+        ok = exercise_aead_key( key, usage, alg );
+    else if( PSA_ALG_IS_SIGN( alg ) )
+        ok = exercise_signature_key( key, usage, alg );
+    else if( PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) )
+        ok = exercise_asymmetric_encryption_key( key, usage, alg );
+    else if( PSA_ALG_IS_KEY_DERIVATION( alg ) )
+        ok = exercise_key_derivation_key( key, usage, alg );
+    else if( PSA_ALG_IS_RAW_KEY_AGREEMENT( alg ) )
+        ok = exercise_raw_key_agreement_key( key, usage, alg );
+    else if( PSA_ALG_IS_KEY_AGREEMENT( alg ) )
+        ok = exercise_key_agreement_key( key, usage, alg );
+    else
+        TEST_ASSERT( ! "No code to exercise this category of algorithm" );
+
+    ok = ok && exercise_export_key( key, usage );
+    ok = ok && exercise_export_public_key( key );
+
+exit:
+    return( ok );
+}
+
+psa_key_usage_t mbedtls_test_psa_usage_to_exercise( psa_key_type_t type,
+                                                    psa_algorithm_t alg )
+{
+    if( PSA_ALG_IS_MAC( alg ) || PSA_ALG_IS_SIGN( alg ) )
+    {
+        if( PSA_ALG_IS_SIGN_HASH( alg ) )
+        {
+            if( PSA_ALG_SIGN_GET_HASH( alg ) )
+                return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
+                        PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:
+                        PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH |
+                        PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE );
+        }
+        else if( PSA_ALG_IS_SIGN_MESSAGE( alg) )
+            return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
+                    PSA_KEY_USAGE_VERIFY_MESSAGE :
+                    PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE );
+
+        return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
+                PSA_KEY_USAGE_VERIFY_HASH :
+                PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH );
+    }
+    else if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) ||
+             PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) )
+    {
+        return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
+                PSA_KEY_USAGE_ENCRYPT :
+                PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
+    }
+    else if( PSA_ALG_IS_KEY_DERIVATION( alg ) ||
+             PSA_ALG_IS_KEY_AGREEMENT( alg ) )
+    {
+        return( PSA_KEY_USAGE_DERIVE );
+    }
+    else
+    {
+        return( 0 );
+    }
+
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/third_party/mbedtls/repo/tests/src/random.c b/third_party/mbedtls/repo/tests/src/random.c
index e01bd4d..7f3f401 100644
--- a/third_party/mbedtls/repo/tests/src/random.c
+++ b/third_party/mbedtls/repo/tests/src/random.c
@@ -35,6 +35,8 @@
 #include <test/random.h>
 #include <string.h>
 
+#include <mbedtls/entropy.h>
+
 int mbedtls_test_rnd_std_rand( void *rng_state,
                                unsigned char *output,
                                size_t len )
@@ -91,8 +93,16 @@
     }
 
     if( len - use_len > 0 )
-        return( mbedtls_test_rnd_std_rand( NULL, output + use_len,
-                                           len - use_len ) );
+    {
+        if( info->fallback_f_rng != NULL )
+        {
+            return( info->fallback_f_rng( info->fallback_p_rng,
+                                          output + use_len,
+                                          len - use_len ) );
+        }
+        else
+            return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
+    }
 
     return( 0 );
 }
diff --git a/third_party/mbedtls/repo/tests/src/threading_helpers.c b/third_party/mbedtls/repo/tests/src/threading_helpers.c
new file mode 100644
index 0000000..ca91b79
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/src/threading_helpers.c
@@ -0,0 +1,223 @@
+/** Mutex usage verification framework. */
+
+/*
+ *  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 <test/helpers.h>
+#include <test/macros.h>
+
+#if defined(MBEDTLS_TEST_MUTEX_USAGE)
+
+#include "mbedtls/threading.h"
+
+/** Mutex usage verification framework.
+ *
+ * The mutex usage verification code below aims to detect bad usage of
+ * Mbed TLS's mutex abstraction layer at runtime. Note that this is solely
+ * about the use of the mutex itself, not about checking whether the mutex
+ * correctly protects whatever it is supposed to protect.
+ *
+ * The normal usage of a mutex is:
+ * ```
+ * digraph mutex_states {
+ *   "UNINITIALIZED"; // the initial state
+ *   "IDLE";
+ *   "FREED";
+ *   "LOCKED";
+ *   "UNINITIALIZED" -> "IDLE" [label="init"];
+ *   "FREED" -> "IDLE" [label="init"];
+ *   "IDLE" -> "LOCKED" [label="lock"];
+ *   "LOCKED" -> "IDLE" [label="unlock"];
+ *   "IDLE" -> "FREED" [label="free"];
+ * }
+ * ```
+ *
+ * All bad transitions that can be unambiguously detected are reported.
+ * An attempt to use an uninitialized mutex cannot be detected in general
+ * since the memory content may happen to denote a valid state. For the same
+ * reason, a double init cannot be detected.
+ * All-bits-zero is the state of a freed mutex, which is distinct from an
+ * initialized mutex, so attempting to use zero-initialized memory as a mutex
+ * without calling the init function is detected.
+ *
+ * The framework attempts to detect missing calls to init and free by counting
+ * calls to init and free. If there are more calls to init than free, this
+ * means that a mutex is not being freed somewhere, which is a memory leak
+ * on platforms where a mutex consumes resources other than the
+ * mbedtls_threading_mutex_t object itself. If there are more calls to free
+ * than init, this indicates a missing init, which is likely to be detected
+ * by an attempt to lock the mutex as well. A limitation of this framework is
+ * that it cannot detect scenarios where there is exactly the same number of
+ * calls to init and free but the calls don't match. A bug like this is
+ * unlikely to happen uniformly throughout the whole test suite though.
+ *
+ * If an error is detected, this framework will report what happened and the
+ * test case will be marked as failed. Unfortunately, the error report cannot
+ * indicate the exact location of the problematic call. To locate the error,
+ * use a debugger and set a breakpoint on mbedtls_test_mutex_usage_error().
+ */
+enum value_of_mutex_is_valid_field
+{
+    /* Potential values for the is_valid field of mbedtls_threading_mutex_t.
+     * Note that MUTEX_FREED must be 0 and MUTEX_IDLE must be 1 for
+     * compatibility with threading_mutex_init_pthread() and
+     * threading_mutex_free_pthread(). MUTEX_LOCKED could be any nonzero
+     * value. */
+    MUTEX_FREED = 0, //!< Set by threading_mutex_free_pthread
+    MUTEX_IDLE = 1, //!< Set by threading_mutex_init_pthread and by our unlock
+    MUTEX_LOCKED = 2, //!< Set by our lock
+};
+
+typedef struct
+{
+    void (*init)( mbedtls_threading_mutex_t * );
+    void (*free)( mbedtls_threading_mutex_t * );
+    int (*lock)( mbedtls_threading_mutex_t * );
+    int (*unlock)( mbedtls_threading_mutex_t * );
+} mutex_functions_t;
+static mutex_functions_t mutex_functions;
+
+/** The total number of calls to mbedtls_mutex_init(), minus the total number
+ * of calls to mbedtls_mutex_free().
+ *
+ * Reset to 0 after each test case.
+ */
+static int live_mutexes;
+
+static void mbedtls_test_mutex_usage_error( mbedtls_threading_mutex_t *mutex,
+                                            const char *msg )
+{
+    (void) mutex;
+    if( mbedtls_test_info.mutex_usage_error == NULL )
+        mbedtls_test_info.mutex_usage_error = msg;
+    mbedtls_fprintf( stdout, "[mutex: %s] ", msg );
+    /* Don't mark the test as failed yet. This way, if the test fails later
+     * for a functional reason, the test framework will report the message
+     * and location for this functional reason. If the test passes,
+     * mbedtls_test_mutex_usage_check() will mark it as failed. */
+}
+
+static void mbedtls_test_wrap_mutex_init( mbedtls_threading_mutex_t *mutex )
+{
+    mutex_functions.init( mutex );
+    if( mutex->is_valid )
+        ++live_mutexes;
+}
+
+static void mbedtls_test_wrap_mutex_free( mbedtls_threading_mutex_t *mutex )
+{
+    switch( mutex->is_valid )
+    {
+        case MUTEX_FREED:
+            mbedtls_test_mutex_usage_error( mutex, "free without init or double free" );
+            break;
+        case MUTEX_IDLE:
+            /* Do nothing. The underlying free function will reset is_valid
+             * to 0. */
+            break;
+        case MUTEX_LOCKED:
+            mbedtls_test_mutex_usage_error( mutex, "free without unlock" );
+            break;
+        default:
+            mbedtls_test_mutex_usage_error( mutex, "corrupted state" );
+            break;
+    }
+    if( mutex->is_valid )
+        --live_mutexes;
+    mutex_functions.free( mutex );
+}
+
+static int mbedtls_test_wrap_mutex_lock( mbedtls_threading_mutex_t *mutex )
+{
+    int ret = mutex_functions.lock( mutex );
+    switch( mutex->is_valid )
+    {
+        case MUTEX_FREED:
+            mbedtls_test_mutex_usage_error( mutex, "lock without init" );
+            break;
+        case MUTEX_IDLE:
+            if( ret == 0 )
+                mutex->is_valid = 2;
+            break;
+        case MUTEX_LOCKED:
+            mbedtls_test_mutex_usage_error( mutex, "double lock" );
+            break;
+        default:
+            mbedtls_test_mutex_usage_error( mutex, "corrupted state" );
+            break;
+    }
+    return( ret );
+}
+
+static int mbedtls_test_wrap_mutex_unlock( mbedtls_threading_mutex_t *mutex )
+{
+    int ret = mutex_functions.unlock( mutex );
+    switch( mutex->is_valid )
+    {
+        case MUTEX_FREED:
+            mbedtls_test_mutex_usage_error( mutex, "unlock without init" );
+            break;
+        case MUTEX_IDLE:
+            mbedtls_test_mutex_usage_error( mutex, "unlock without lock" );
+            break;
+        case MUTEX_LOCKED:
+            if( ret == 0 )
+                mutex->is_valid = MUTEX_IDLE;
+            break;
+        default:
+            mbedtls_test_mutex_usage_error( mutex, "corrupted state" );
+            break;
+    }
+    return( ret );
+}
+
+void mbedtls_test_mutex_usage_init( void )
+{
+    mutex_functions.init = mbedtls_mutex_init;
+    mutex_functions.free = mbedtls_mutex_free;
+    mutex_functions.lock = mbedtls_mutex_lock;
+    mutex_functions.unlock = mbedtls_mutex_unlock;
+    mbedtls_mutex_init = &mbedtls_test_wrap_mutex_init;
+    mbedtls_mutex_free = &mbedtls_test_wrap_mutex_free;
+    mbedtls_mutex_lock = &mbedtls_test_wrap_mutex_lock;
+    mbedtls_mutex_unlock = &mbedtls_test_wrap_mutex_unlock;
+}
+
+void mbedtls_test_mutex_usage_check( void )
+{
+    if( live_mutexes != 0 )
+    {
+        /* A positive number (more init than free) means that a mutex resource
+         * is leaking (on platforms where a mutex consumes more than the
+         * mbedtls_threading_mutex_t object itself). The rare case of a
+         * negative number means a missing init somewhere. */
+        mbedtls_fprintf( stdout, "[mutex: %d leaked] ", live_mutexes );
+        live_mutexes = 0;
+        if( mbedtls_test_info.mutex_usage_error == NULL )
+            mbedtls_test_info.mutex_usage_error = "missing free";
+    }
+    if( mbedtls_test_info.mutex_usage_error != NULL &&
+        mbedtls_test_info.result != MBEDTLS_TEST_RESULT_FAILED )
+    {
+        /* Functionally, the test passed. But there was a mutex usage error,
+         * so mark the test as failed after all. */
+        mbedtls_test_fail( "Mutex usage error", __LINE__, __FILE__ );
+    }
+    mbedtls_test_info.mutex_usage_error = NULL;
+}
+
+#endif /* MBEDTLS_TEST_MUTEX_USAGE */
diff --git a/third_party/mbedtls/repo/tests/ssl-opt.sh b/third_party/mbedtls/repo/tests/ssl-opt.sh
index fcd73f2..43b6d04 100755
--- a/third_party/mbedtls/repo/tests/ssl-opt.sh
+++ b/third_party/mbedtls/repo/tests/ssl-opt.sh
@@ -77,6 +77,14 @@
     O_LEGACY_CLI=false
 fi
 
+if [ -n "${OPENSSL_NEXT:-}" ]; then
+    O_NEXT_SRV="$OPENSSL_NEXT s_server -www -cert data_files/server5.crt -key data_files/server5.key"
+    O_NEXT_CLI="echo 'GET / HTTP/1.0' | $OPENSSL_NEXT s_client"
+else
+    O_NEXT_SRV=false
+    O_NEXT_CLI=false
+fi
+
 if [ -n "${GNUTLS_NEXT_SERV:-}" ]; then
     G_NEXT_SRV="$GNUTLS_NEXT_SERV --x509certfile data_files/server5.crt --x509keyfile data_files/server5.key"
 else
@@ -114,8 +122,8 @@
     echo "Usage: $0 [options]"
     printf "  -h|--help\tPrint this help.\n"
     printf "  -m|--memcheck\tCheck memory leaks and errors.\n"
-    printf "  -f|--filter\tOnly matching tests are executed (BRE)\n"
-    printf "  -e|--exclude\tMatching tests are excluded (BRE)\n"
+    printf "  -f|--filter\tOnly matching tests are executed (substring or BRE)\n"
+    printf "  -e|--exclude\tMatching tests are excluded (substring or BRE)\n"
     printf "  -n|--number\tExecute only numbered test (comma-separated, e.g. '245,256')\n"
     printf "  -s|--show-numbers\tShow test numbers in front of test names\n"
     printf "  -p|--preserve-logs\tPreserve logs of successful tests as well\n"
@@ -178,6 +186,14 @@
         ;;
 esac
 
+# Read boolean configuration options from config.h for easy and quick
+# testing. Skip non-boolean options (with something other than spaces
+# and a comment after "#define SYMBOL"). The variable contains a
+# space-separated list of symbols.
+CONFIGS_ENABLED=" $(<"$CONFIG_H" \
+                    sed -n 's!^ *#define  *\([A-Za-z][0-9A-Z_a-z]*\) *\(/*\)*!\1!p' |
+                    tr '\n' ' ')"
+
 # Skip next test; use this macro to skip tests which are legitimate
 # in theory and expected to be re-introduced at some point, but
 # aren't expected to succeed at the moment due to problems outside
@@ -188,16 +204,17 @@
 
 # skip next test if the flag is not enabled in config.h
 requires_config_enabled() {
-    if grep "^#define $1" $CONFIG_H > /dev/null; then :; else
-        SKIP_NEXT="YES"
-    fi
+    case $CONFIGS_ENABLED in
+        *" $1 "*) :;;
+        *) SKIP_NEXT="YES";;
+    esac
 }
 
 # skip next test if the flag is enabled in config.h
 requires_config_disabled() {
-    if grep "^#define $1" $CONFIG_H > /dev/null; then
-        SKIP_NEXT="YES"
-    fi
+    case $CONFIGS_ENABLED in
+        *" $1 "*) SKIP_NEXT="YES";;
+    esac
 }
 
 get_config_value_or_default() {
@@ -233,12 +250,29 @@
     fi
 }
 
-requires_ciphersuite_enabled() {
-    if [ -z "$($P_CLI --help 2>/dev/null | grep $1)" ]; then
-        SKIP_NEXT="YES"
+requires_config_value_equals() {
+    VAL=$( get_config_value_or_default "$1" )
+    if [ -z "$VAL" ]; then
+        # Should never happen
+        echo "Mbed TLS configuration $1 is not defined"
+        exit 1
+    elif [ "$VAL" -ne "$2" ]; then
+       SKIP_NEXT="YES"
     fi
 }
 
+# Space-separated list of ciphersuites supported by this build of
+# Mbed TLS.
+P_CIPHERSUITES=" $($P_CLI --help 2>/dev/null |
+                   grep TLS- |
+                   tr -s ' \n' ' ')"
+requires_ciphersuite_enabled() {
+    case $P_CIPHERSUITES in
+        *" $1 "*) :;;
+        *) SKIP_NEXT="YES";;
+    esac
+}
+
 # maybe_requires_ciphersuite_enabled CMD [RUN_TEST_OPTION...]
 # If CMD (call to a TLS client or server program) requires a specific
 # ciphersuite, arrange to only run the test case if this ciphersuite is
@@ -281,6 +315,12 @@
     fi
 }
 
+# skip next test if either IN_CONTENT_LEN or MAX_CONTENT_LEN are below a value
+requires_max_content_len() {
+    requires_config_value_at_least "MBEDTLS_SSL_IN_CONTENT_LEN" $1
+    requires_config_value_at_least "MBEDTLS_SSL_OUT_CONTENT_LEN" $1
+}
+
 # skip next test if GnuTLS isn't available
 requires_gnutls() {
     if [ -z "${GNUTLS_AVAILABLE:-}" ]; then
@@ -323,6 +363,19 @@
     fi
 }
 
+requires_openssl_next() {
+    if [ -z "${OPENSSL_NEXT_AVAILABLE:-}" ]; then
+        if which "${OPENSSL_NEXT:-}" >/dev/null 2>&1; then
+            OPENSSL_NEXT_AVAILABLE="YES"
+        else
+            OPENSSL_NEXT_AVAILABLE="NO"
+        fi
+    fi
+    if [ "$OPENSSL_NEXT_AVAILABLE" = "NO" ]; then
+        SKIP_NEXT="YES"
+    fi
+}
+
 # skip next test if IPv6 isn't available on this host
 requires_ipv6() {
     if [ -z "${HAS_IPV6:-}" ]; then
@@ -359,10 +412,11 @@
 }
 
 # Calculate the input & output maximum content lengths set in the config
-MAX_CONTENT_LEN=$( ../scripts/config.py get MBEDTLS_SSL_MAX_CONTENT_LEN || echo "16384")
-MAX_IN_LEN=$( ../scripts/config.py get MBEDTLS_SSL_IN_CONTENT_LEN || echo "$MAX_CONTENT_LEN")
-MAX_OUT_LEN=$( ../scripts/config.py get MBEDTLS_SSL_OUT_CONTENT_LEN || echo "$MAX_CONTENT_LEN")
+MAX_CONTENT_LEN=$( get_config_value_or_default "MBEDTLS_SSL_MAX_CONTENT_LEN" )
+MAX_IN_LEN=$( get_config_value_or_default "MBEDTLS_SSL_IN_CONTENT_LEN" )
+MAX_OUT_LEN=$( get_config_value_or_default "MBEDTLS_SSL_OUT_CONTENT_LEN" )
 
+# Calculate the maximum content length that fits both
 if [ "$MAX_IN_LEN" -lt "$MAX_CONTENT_LEN" ]; then
     MAX_CONTENT_LEN="$MAX_IN_LEN"
 fi
@@ -431,6 +485,32 @@
     fi
 }
 
+# True if the presence of the given pattern in a log definitely indicates
+# that the test has failed. False if the presence is inconclusive.
+#
+# Inputs:
+# * $1: pattern found in the logs
+# * $TIMES_LEFT: >0 if retrying is an option
+#
+# Outputs:
+# * $outcome: set to a retry reason if the pattern is inconclusive,
+#             unchanged otherwise.
+# * Return value: 1 if the pattern is inconclusive,
+#                 0 if the failure is definitive.
+log_pattern_presence_is_conclusive() {
+    # If we've run out of attempts, then don't retry no matter what.
+    if [ $TIMES_LEFT -eq 0 ]; then
+        return 0
+    fi
+    case $1 in
+        "resend")
+            # An undesired resend may have been caused by the OS dropping or
+            # delaying a packet at an inopportune time.
+            outcome="RETRY(resend)"
+            return 1;;
+    esac
+}
+
 # fail <message>
 fail() {
     record_outcome "FAIL" "$1"
@@ -462,17 +542,21 @@
 
 # is_polar <cmd_line>
 is_polar() {
-    echo "$1" | grep 'ssl_server2\|ssl_client2' > /dev/null
+    case "$1" in
+        *ssl_client2*) true;;
+        *ssl_server2*) true;;
+        *) false;;
+    esac
 }
 
 # openssl s_server doesn't have -www with DTLS
 check_osrv_dtls() {
-    if echo "$SRV_CMD" | grep 's_server.*-dtls' >/dev/null; then
-        NEEDS_INPUT=1
-        SRV_CMD="$( echo $SRV_CMD | sed s/-www// )"
-    else
-        NEEDS_INPUT=0
-    fi
+    case "$SRV_CMD" in
+        *s_server*-dtls*)
+            NEEDS_INPUT=1
+            SRV_CMD="$( echo $SRV_CMD | sed s/-www// )";;
+        *) NEEDS_INPUT=0;;
+    esac
 }
 
 # provide input to commands that need it
@@ -501,6 +585,8 @@
 # Wait for process $2 named $3 to be listening on port $1. Print error to $4.
 if type lsof >/dev/null 2>/dev/null; then
     wait_app_start() {
+        newline='
+'
         START_TIME=$(date +%s)
         if [ "$DTLS" -eq 1 ]; then
             proto=UDP
@@ -508,7 +594,15 @@
             proto=TCP
         fi
         # Make a tight loop, server normally takes less than 1s to start.
-        while ! lsof -a -n -b -i "$proto:$1" -p "$2" >/dev/null 2>/dev/null; do
+        while true; do
+              SERVER_PIDS=$(lsof -a -n -b -i "$proto:$1" -F p)
+              # When we use a proxy, it will be listening on the same port we
+              # are checking for as well as the server and lsof will list both.
+              # If multiple PIDs are returned, each one will be on a separate
+              # line, each prepended with 'p'.
+             case ${newline}${SERVER_PIDS}${newline} in
+                  *${newline}p${2}${newline}*) break;;
+              esac
               if [ $(( $(date +%s) - $START_TIME )) -gt $DOG_DELAY ]; then
                   echo "$3 START TIMEOUT"
                   echo "$3 START TIMEOUT" >> $4
@@ -627,11 +721,25 @@
 
 # check if the given command uses dtls and sets global variable DTLS
 detect_dtls() {
-    if echo "$1" | grep 'dtls=1\|-dtls1\|-u' >/dev/null; then
-        DTLS=1
-    else
-        DTLS=0
-    fi
+    case "$1" in
+        *dtls=1*|*-dtls*|*-u*) DTLS=1;;
+        *) DTLS=0;;
+    esac
+}
+
+# check if the given command uses gnutls and sets global variable CMD_IS_GNUTLS
+is_gnutls() {
+    case "$1" in
+    *gnutls-cli*)
+        CMD_IS_GNUTLS=1
+        ;;
+    *gnutls-serv*)
+        CMD_IS_GNUTLS=1
+        ;;
+    *)
+        CMD_IS_GNUTLS=0
+        ;;
+    esac
 }
 
 # Compare file content
@@ -651,68 +759,12 @@
         fi
 }
 
-# Usage: run_test name [-p proxy_cmd] srv_cmd cli_cmd cli_exit [option [...]]
-# Options:  -s pattern  pattern that must be present in server output
-#           -c pattern  pattern that must be present in client output
-#           -u pattern  lines after pattern must be unique in client output
-#           -f call shell function on client output
-#           -S pattern  pattern that must be absent in server output
-#           -C pattern  pattern that must be absent in client output
-#           -U pattern  lines after pattern must be unique in server output
-#           -F call shell function on server output
-#           -g call shell function on server and client output
-run_test() {
-    NAME="$1"
-    shift 1
-
-    if echo "$NAME" | grep "$FILTER" | grep -v "$EXCLUDE" >/dev/null; then :
-    else
-        SKIP_NEXT="NO"
-        # There was no request to run the test, so don't record its outcome.
-        return
-    fi
-
-    print_name "$NAME"
-
-    # Do we only run numbered tests?
-    if [ "X$RUN_TEST_NUMBER" = "X" ]; then :
-    elif echo ",$RUN_TEST_NUMBER," | grep ",$TESTS," >/dev/null; then :
-    else
-        SKIP_NEXT="YES"
-    fi
-
-    # does this test use a proxy?
-    if [ "X$1" = "X-p" ]; then
-        PXY_CMD="$2"
-        shift 2
-    else
-        PXY_CMD=""
-    fi
-
-    # get commands and client output
-    SRV_CMD="$1"
-    CLI_CMD="$2"
-    CLI_EXPECT="$3"
-    shift 3
-
-    # Check if test uses files
-    TEST_USES_FILES=$(echo "$SRV_CMD $CLI_CMD" | grep "\.\(key\|crt\|pem\)" )
-    if [ ! -z "$TEST_USES_FILES" ]; then
-       requires_config_enabled MBEDTLS_FS_IO
-    fi
-
-    # If the client or serve requires a ciphersuite, check that it's enabled.
-    maybe_requires_ciphersuite_enabled "$SRV_CMD" "$@"
-    maybe_requires_ciphersuite_enabled "$CLI_CMD" "$@"
-
-    # should we skip?
-    if [ "X$SKIP_NEXT" = "XYES" ]; then
-        SKIP_NEXT="NO"
-        record_outcome "SKIP"
-        SKIPS=$(( $SKIPS + 1 ))
-        return
-    fi
-
+# Analyze the commands that will be used in a test.
+#
+# Analyze and possibly instrument $PXY_CMD, $CLI_CMD, $SRV_CMD to pass
+# extra arguments or go through wrappers.
+# Set $DTLS (0=TLS, 1=DTLS).
+analyze_test_commands() {
     # update DTLS variable
     detect_dtls "$SRV_CMD"
 
@@ -726,6 +778,30 @@
         esac
     fi
 
+    # update CMD_IS_GNUTLS variable
+    is_gnutls "$SRV_CMD"
+
+    # if the server uses gnutls but doesn't set priority, explicitly
+    # set the default priority
+    if [ "$CMD_IS_GNUTLS" -eq 1 ]; then
+        case "$SRV_CMD" in
+              *--priority*) :;;
+              *) SRV_CMD="$SRV_CMD --priority=NORMAL";;
+        esac
+    fi
+
+    # update CMD_IS_GNUTLS variable
+    is_gnutls "$CLI_CMD"
+
+    # if the client uses gnutls but doesn't set priority, explicitly
+    # set the default priority
+    if [ "$CMD_IS_GNUTLS" -eq 1 ]; then
+        case "$CLI_CMD" in
+              *--priority*) :;;
+              *) CLI_CMD="$CLI_CMD --priority=NORMAL";;
+        esac
+    fi
+
     # fix client port
     if [ -n "$PXY_CMD" ]; then
         CLI_CMD=$( echo "$CLI_CMD" | sed s/+SRV_PORT/$PXY_PORT/g )
@@ -742,47 +818,29 @@
             CLI_CMD="valgrind --leak-check=full $CLI_CMD"
         fi
     fi
+}
 
-    TIMES_LEFT=2
-    while [ $TIMES_LEFT -gt 0 ]; do
-        TIMES_LEFT=$(( $TIMES_LEFT - 1 ))
+# Check for failure conditions after a test case.
+#
+# Inputs from run_test:
+# * positional parameters: test options (see run_test documentation)
+# * $CLI_EXIT: client return code
+# * $CLI_EXPECT: expected client return code
+# * $SRV_RET: server return code
+# * $CLI_OUT, $SRV_OUT, $PXY_OUT: files containing client/server/proxy logs
+# * $TIMES_LEFT: if nonzero, a RETRY outcome is allowed
+#
+# Outputs:
+# * $outcome: one of PASS/RETRY*/FAIL
+check_test_failure() {
+    outcome=FAIL
 
-        # run the commands
-        if [ -n "$PXY_CMD" ]; then
-            printf "# %s\n%s\n" "$NAME" "$PXY_CMD" > $PXY_OUT
-            $PXY_CMD >> $PXY_OUT 2>&1 &
-            PXY_PID=$!
-            wait_proxy_start "$PXY_PORT" "$PXY_PID"
-        fi
-
-        check_osrv_dtls
-        printf '# %s\n%s\n' "$NAME" "$SRV_CMD" > $SRV_OUT
-        provide_input | $SRV_CMD >> $SRV_OUT 2>&1 &
-        SRV_PID=$!
-        wait_server_start "$SRV_PORT" "$SRV_PID"
-
-        printf '# %s\n%s\n' "$NAME" "$CLI_CMD" > $CLI_OUT
-        eval "$CLI_CMD" >> $CLI_OUT 2>&1 &
-        wait_client_done
-
-        sleep 0.05
-
-        # terminate the server (and the proxy)
-        kill $SRV_PID
-        wait $SRV_PID
-
-        if [ -n "$PXY_CMD" ]; then
-            kill $PXY_PID >/dev/null 2>&1
-            wait $PXY_PID
-        fi
-
-        # retry only on timeouts
-        if grep '===CLIENT_TIMEOUT===' $CLI_OUT >/dev/null; then
-            printf "RETRY "
-        else
-            TIMES_LEFT=0
-        fi
-    done
+    if [ $TIMES_LEFT -gt 0 ] &&
+       grep '===CLIENT_TIMEOUT===' $CLI_OUT >/dev/null
+    then
+        outcome="RETRY(client-timeout)"
+        return
+    fi
 
     # check if the client and server went at least to the handshake stage
     # (useful to avoid tests with only negative assertions and non-zero
@@ -803,9 +861,11 @@
         fi
     fi
 
-    # check server exit code
-    if [ $? != 0 ]; then
-        fail "server fail"
+    # Check server exit code (only for Mbed TLS: GnuTLS and OpenSSL don't
+    # exit with status 0 when interrupted by a signal, and we don't really
+    # care anyway), in case e.g. the server reports a memory leak.
+    if [ $SRV_RET != 0 ] && is_polar "$SRV_CMD"; then
+        fail "Server exited with status $SRV_RET"
         return
     fi
 
@@ -839,14 +899,18 @@
 
             "-S")
                 if grep -v '^==' $SRV_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then
-                    fail "pattern '$2' MUST NOT be present in the Server output"
+                    if log_pattern_presence_is_conclusive "$2"; then
+                        fail "pattern '$2' MUST NOT be present in the Server output"
+                    fi
                     return
                 fi
                 ;;
 
             "-C")
                 if grep -v '^==' $CLI_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then
-                    fail "pattern '$2' MUST NOT be present in the Client output"
+                    if log_pattern_presence_is_conclusive "$2"; then
+                        fail "pattern '$2' MUST NOT be present in the Client output"
+                    fi
                     return
                 fi
                 ;;
@@ -910,6 +974,131 @@
     fi
 
     # if we're here, everything is ok
+    outcome=PASS
+}
+
+# Run the current test case: start the server and if applicable the proxy, run
+# the client, wait for all processes to finish or time out.
+#
+# Inputs:
+# * $NAME: test case name
+# * $CLI_CMD, $SRV_CMD, $PXY_CMD: commands to run
+# * $CLI_OUT, $SRV_OUT, $PXY_OUT: files to contain client/server/proxy logs
+#
+# Outputs:
+# * $CLI_EXIT: client return code
+# * $SRV_RET: server return code
+do_run_test_once() {
+    # run the commands
+    if [ -n "$PXY_CMD" ]; then
+        printf "# %s\n%s\n" "$NAME" "$PXY_CMD" > $PXY_OUT
+        $PXY_CMD >> $PXY_OUT 2>&1 &
+        PXY_PID=$!
+        wait_proxy_start "$PXY_PORT" "$PXY_PID"
+    fi
+
+    check_osrv_dtls
+    printf '# %s\n%s\n' "$NAME" "$SRV_CMD" > $SRV_OUT
+    provide_input | $SRV_CMD >> $SRV_OUT 2>&1 &
+    SRV_PID=$!
+    wait_server_start "$SRV_PORT" "$SRV_PID"
+
+    printf '# %s\n%s\n' "$NAME" "$CLI_CMD" > $CLI_OUT
+    eval "$CLI_CMD" >> $CLI_OUT 2>&1 &
+    wait_client_done
+
+    sleep 0.05
+
+    # terminate the server (and the proxy)
+    kill $SRV_PID
+    wait $SRV_PID
+    SRV_RET=$?
+
+    if [ -n "$PXY_CMD" ]; then
+        kill $PXY_PID >/dev/null 2>&1
+        wait $PXY_PID
+    fi
+}
+
+# Usage: run_test name [-p proxy_cmd] srv_cmd cli_cmd cli_exit [option [...]]
+# Options:  -s pattern  pattern that must be present in server output
+#           -c pattern  pattern that must be present in client output
+#           -u pattern  lines after pattern must be unique in client output
+#           -f call shell function on client output
+#           -S pattern  pattern that must be absent in server output
+#           -C pattern  pattern that must be absent in client output
+#           -U pattern  lines after pattern must be unique in server output
+#           -F call shell function on server output
+#           -g call shell function on server and client output
+run_test() {
+    NAME="$1"
+    shift 1
+
+    if is_excluded "$NAME"; then
+        SKIP_NEXT="NO"
+        # There was no request to run the test, so don't record its outcome.
+        return
+    fi
+
+    print_name "$NAME"
+
+    # Do we only run numbered tests?
+    if [ -n "$RUN_TEST_NUMBER" ]; then
+        case ",$RUN_TEST_NUMBER," in
+            *",$TESTS,"*) :;;
+            *) SKIP_NEXT="YES";;
+        esac
+    fi
+
+    # does this test use a proxy?
+    if [ "X$1" = "X-p" ]; then
+        PXY_CMD="$2"
+        shift 2
+    else
+        PXY_CMD=""
+    fi
+
+    # get commands and client output
+    SRV_CMD="$1"
+    CLI_CMD="$2"
+    CLI_EXPECT="$3"
+    shift 3
+
+    # Check if test uses files
+    case "$SRV_CMD $CLI_CMD" in
+        *data_files/*)
+            requires_config_enabled MBEDTLS_FS_IO;;
+    esac
+
+    # If the client or serve requires a ciphersuite, check that it's enabled.
+    maybe_requires_ciphersuite_enabled "$SRV_CMD" "$@"
+    maybe_requires_ciphersuite_enabled "$CLI_CMD" "$@"
+
+    # should we skip?
+    if [ "X$SKIP_NEXT" = "XYES" ]; then
+        SKIP_NEXT="NO"
+        record_outcome "SKIP"
+        SKIPS=$(( $SKIPS + 1 ))
+        return
+    fi
+
+    analyze_test_commands "$@"
+
+    TIMES_LEFT=2
+    while [ $TIMES_LEFT -gt 0 ]; do
+        TIMES_LEFT=$(( $TIMES_LEFT - 1 ))
+
+        do_run_test_once
+
+        check_test_failure "$@"
+        case $outcome in
+            PASS) break;;
+            RETRY*) printf "$outcome ";;
+            FAIL) return;;
+        esac
+    done
+
+    # If we get this far, the test case passed.
     record_outcome "PASS"
     if [ "$PRESERVE_LOGS" -gt 0 ]; then
         mv $SRV_OUT o-srv-${TESTS}.log
@@ -925,8 +1114,8 @@
 run_test_psa() {
     requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
     run_test    "PSA-supported ciphersuite: $1" \
-                "$P_SRV debug_level=3 force_version=tls1_2" \
-                "$P_CLI debug_level=3 force_version=tls1_2 force_ciphersuite=$1" \
+                "$P_SRV debug_level=3 force_version=tls12" \
+                "$P_CLI debug_level=3 force_version=tls12 force_ciphersuite=$1" \
                 0 \
                 -c "Successfully setup PSA-based decryption cipher context" \
                 -c "Successfully setup PSA-based encryption cipher context" \
@@ -948,8 +1137,8 @@
 run_test_psa_force_curve() {
     requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
     run_test    "PSA - ECDH with $1" \
-                "$P_SRV debug_level=4 force_version=tls1_2" \
-                "$P_CLI debug_level=4 force_version=tls1_2 force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256 curves=$1" \
+                "$P_SRV debug_level=4 force_version=tls12" \
+                "$P_CLI debug_level=4 force_version=tls12 force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256 curves=$1" \
                 0 \
                 -c "Successfully setup PSA-based decryption cipher context" \
                 -c "Successfully setup PSA-based encryption cipher context" \
@@ -975,14 +1164,14 @@
 run_test_memory_after_hanshake_with_mfl()
 {
     # The test passes if the difference is around 2*(16k-MFL)
-    local MEMORY_USAGE_LIMIT="$(( $2 - ( 2 * ( 16384 - $1 )) ))"
+    MEMORY_USAGE_LIMIT="$(( $2 - ( 2 * ( 16384 - $1 )) ))"
 
     # Leave some margin for robustness
     MEMORY_USAGE_LIMIT="$(( ( MEMORY_USAGE_LIMIT * 110 ) / 100 ))"
 
     run_test    "Handshake memory usage (MFL $1)" \
-                "$P_SRV debug_level=3 auth_mode=required force_version=tls1_2" \
-                "$P_CLI debug_level=3 force_version=tls1_2 \
+                "$P_SRV debug_level=3 auth_mode=required force_version=tls12" \
+                "$P_CLI debug_level=3 force_version=tls12 \
                     crt_file=data_files/server5.crt key_file=data_files/server5.key \
                     force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-CCM max_frag_len=$1" \
                 0 \
@@ -1000,8 +1189,8 @@
     # first test with default MFU is to get reference memory usage
     MEMORY_USAGE_MFL_16K=0
     run_test    "Handshake memory usage initial (MFL 16384 - default)" \
-                "$P_SRV debug_level=3 auth_mode=required force_version=tls1_2" \
-                "$P_CLI debug_level=3 force_version=tls1_2 \
+                "$P_SRV debug_level=3 auth_mode=required force_version=tls12" \
+                "$P_CLI debug_level=3 force_version=tls12 \
                     crt_file=data_files/server5.crt key_file=data_files/server5.key \
                     force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-CCM" \
                 0 \
@@ -1037,6 +1226,46 @@
 
 get_options "$@"
 
+# Optimize filters: if $FILTER and $EXCLUDE can be expressed as shell
+# patterns rather than regular expressions, use a case statement instead
+# of calling grep. To keep the optimizer simple, it is incomplete and only
+# detects simple cases: plain substring, everything, nothing.
+#
+# As an exception, the character '.' is treated as an ordinary character
+# if it is the only special character in the string. This is because it's
+# rare to need "any one character", but needing a literal '.' is common
+# (e.g. '-f "DTLS 1.2"').
+need_grep=
+case "$FILTER" in
+    '^$') simple_filter=;;
+    '.*') simple_filter='*';;
+    *[][$+*?\\^{\|}]*) # Regexp special characters (other than .), we need grep
+        need_grep=1;;
+    *) # No regexp or shell-pattern special character
+        simple_filter="*$FILTER*";;
+esac
+case "$EXCLUDE" in
+    '^$') simple_exclude=;;
+    '.*') simple_exclude='*';;
+    *[][$+*?\\^{\|}]*) # Regexp special characters (other than .), we need grep
+        need_grep=1;;
+    *) # No regexp or shell-pattern special character
+        simple_exclude="*$EXCLUDE*";;
+esac
+if [ -n "$need_grep" ]; then
+    is_excluded () {
+        ! echo "$1" | grep "$FILTER" | grep -q -v "$EXCLUDE"
+    }
+else
+    is_excluded () {
+        case "$1" in
+            $simple_exclude) true;;
+            $simple_filter) false;;
+            *) true;;
+        esac
+    }
+fi
+
 # sanity checks, avoid an avalanche of errors
 P_SRV_BIN="${P_SRV%%[  ]*}"
 P_CLI_BIN="${P_CLI%%[  ]*}"
@@ -1094,17 +1323,24 @@
 
 # fix commands to use this port, force IPv4 while at it
 # +SRV_PORT will be replaced by either $SRV_PORT or $PXY_PORT later
+# Note: Using 'localhost' rather than 127.0.0.1 here is unwise, as on many
+# machines that will resolve to ::1, and we don't want ipv6 here.
 P_SRV="$P_SRV server_addr=127.0.0.1 server_port=$SRV_PORT"
 P_CLI="$P_CLI server_addr=127.0.0.1 server_port=+SRV_PORT"
 P_PXY="$P_PXY server_addr=127.0.0.1 server_port=$SRV_PORT listen_addr=127.0.0.1 listen_port=$PXY_PORT ${SEED:+"seed=$SEED"}"
-O_SRV="$O_SRV -accept $SRV_PORT -dhparam data_files/dhparams.pem"
-O_CLI="$O_CLI -connect localhost:+SRV_PORT"
+O_SRV="$O_SRV -accept $SRV_PORT"
+O_CLI="$O_CLI -connect 127.0.0.1:+SRV_PORT"
 G_SRV="$G_SRV -p $SRV_PORT"
 G_CLI="$G_CLI -p +SRV_PORT"
 
 if [ -n "${OPENSSL_LEGACY:-}" ]; then
     O_LEGACY_SRV="$O_LEGACY_SRV -accept $SRV_PORT -dhparam data_files/dhparams.pem"
-    O_LEGACY_CLI="$O_LEGACY_CLI -connect localhost:+SRV_PORT"
+    O_LEGACY_CLI="$O_LEGACY_CLI -connect 127.0.0.1:+SRV_PORT"
+fi
+
+if [ -n "${OPENSSL_NEXT:-}" ]; then
+    O_NEXT_SRV="$O_NEXT_SRV -accept $SRV_PORT"
+    O_NEXT_CLI="$O_NEXT_CLI -connect 127.0.0.1:+SRV_PORT"
 fi
 
 if [ -n "${GNUTLS_NEXT_SERV:-}" ]; then
@@ -1264,8 +1500,13 @@
 run_test_psa_force_curve "brainpoolP256r1"
 requires_config_enabled MBEDTLS_ECP_DP_SECP224R1_ENABLED
 run_test_psa_force_curve "secp224r1"
-requires_config_enabled MBEDTLS_ECP_DP_SECP224K1_ENABLED
-run_test_psa_force_curve "secp224k1"
+## SECP224K1 is buggy via the PSA API
+## (https://github.com/ARMmbed/mbedtls/issues/3541),
+## so it is disabled in PSA even when it's enabled in Mbed TLS.
+## The proper dependency would be on PSA_WANT_ECC_SECP_K1_224 but
+## dependencies on PSA symbols in ssl-opt.sh are not implemented yet.
+#requires_config_enabled MBEDTLS_ECP_DP_SECP224K1_ENABLED
+#run_test_psa_force_curve "secp224k1"
 requires_config_enabled MBEDTLS_ECP_DP_SECP192R1_ENABLED
 run_test_psa_force_curve "secp192r1"
 requires_config_enabled MBEDTLS_ECP_DP_SECP192K1_ENABLED
@@ -1356,19 +1597,12 @@
 
 # Tests for SHA-1 support
 
-requires_config_disabled MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES
 run_test    "SHA-1 forbidden by default in server certificate" \
             "$P_SRV key_file=data_files/server2.key crt_file=data_files/server2.crt" \
             "$P_CLI debug_level=2 allow_sha1=0" \
             1 \
             -c "The certificate is signed with an unacceptable hash"
 
-requires_config_enabled MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES
-run_test    "SHA-1 allowed by default in server certificate" \
-            "$P_SRV key_file=data_files/server2.key crt_file=data_files/server2.crt" \
-            "$P_CLI debug_level=2 allow_sha1=0" \
-            0
-
 run_test    "SHA-1 explicitly allowed in server certificate" \
             "$P_SRV key_file=data_files/server2.key crt_file=data_files/server2.crt" \
             "$P_CLI allow_sha1=1" \
@@ -1379,19 +1613,12 @@
             "$P_CLI allow_sha1=0" \
             0
 
-requires_config_disabled MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES
 run_test    "SHA-1 forbidden by default in client certificate" \
             "$P_SRV auth_mode=required allow_sha1=0" \
             "$P_CLI key_file=data_files/cli-rsa.key crt_file=data_files/cli-rsa-sha1.crt" \
             1 \
             -s "The certificate is signed with an unacceptable hash"
 
-requires_config_enabled MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES
-run_test    "SHA-1 allowed by default in client certificate" \
-            "$P_SRV auth_mode=required allow_sha1=0" \
-            "$P_CLI key_file=data_files/cli-rsa.key crt_file=data_files/cli-rsa-sha1.crt" \
-            0
-
 run_test    "SHA-1 explicitly allowed in client certificate" \
             "$P_SRV auth_mode=required allow_sha1=1" \
             "$P_CLI key_file=data_files/cli-rsa.key crt_file=data_files/cli-rsa-sha1.crt" \
@@ -2298,8 +2525,12 @@
             -c "ignoring unexpected CID" \
             -s "ignoring unexpected CID"
 
+# This and the test below it require MAX_CONTENT_LEN to be at least MFL+1, because the
+# tests check that the buffer contents are reallocated when the message is
+# larger than the buffer.
 requires_config_enabled MBEDTLS_SSL_DTLS_CONNECTION_ID
 requires_config_enabled MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH
+requires_max_content_len 513
 run_test    "Connection ID: Cli+Srv enabled, variable buffer lengths, MFL=512" \
             "$P_SRV dtls=1 cid=1 cid_val=dead debug_level=2" \
             "$P_CLI force_ciphersuite="TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8" max_frag_len=512 dtls=1 cid=1 cid_val=beef" \
@@ -2313,6 +2544,7 @@
 
 requires_config_enabled MBEDTLS_SSL_DTLS_CONNECTION_ID
 requires_config_enabled MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH
+requires_max_content_len 1025
 run_test    "Connection ID: Cli+Srv enabled, variable buffer lengths, MFL=1024" \
             "$P_SRV dtls=1 cid=1 cid_val=dead debug_level=2" \
             "$P_CLI force_ciphersuite="TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8" max_frag_len=1024 dtls=1 cid=1 cid_val=beef" \
@@ -2617,7 +2849,7 @@
 run_test    "CBC Record splitting: TLS 1.2, no splitting" \
             "$P_SRV" \
             "$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA \
-             request_size=123 force_version=tls1_2" \
+             request_size=123 force_version=tls12" \
             0 \
             -s "Read from client: 123 bytes read" \
             -S "Read from client: 1 bytes read" \
@@ -2824,10 +3056,13 @@
             -c "parse new session ticket" \
             -c "a session has been resumed"
 
+# For reasons that aren't fully understood, this test randomly fails with high
+# probability with OpenSSL 1.0.2g on the CI, see #5012.
+requires_openssl_next
 run_test    "Session resume using tickets, DTLS: openssl client" \
             "$P_SRV dtls=1 debug_level=3 tickets=1" \
-            "( $O_CLI -dtls1 -sess_out $SESSION; \
-               $O_CLI -dtls1 -sess_in $SESSION; \
+            "( $O_NEXT_CLI -dtls1 -sess_out $SESSION; \
+               $O_NEXT_CLI -dtls1 -sess_in $SESSION; \
                rm -f $SESSION )" \
             0 \
             -s "found session ticket extension" \
@@ -3024,10 +3259,13 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+# For reasons that aren't fully understood, this test randomly fails with high
+# probability with OpenSSL 1.0.2g on the CI, see #5012.
+requires_openssl_next
 run_test    "Session resume using cache, DTLS: openssl client" \
             "$P_SRV dtls=1 debug_level=3 tickets=0" \
-            "( $O_CLI -dtls1 -sess_out $SESSION; \
-               $O_CLI -dtls1 -sess_in $SESSION; \
+            "( $O_NEXT_CLI -dtls1 -sess_out $SESSION; \
+               $O_NEXT_CLI -dtls1 -sess_in $SESSION; \
                rm -f $SESSION )" \
             0 \
             -s "found session ticket extension" \
@@ -3046,15 +3284,6 @@
 
 # Tests for Max Fragment Length extension
 
-if [ "$MAX_CONTENT_LEN" -lt "4096" ]; then
-    printf '%s defines MBEDTLS_SSL_MAX_CONTENT_LEN to be less than 4096. Fragment length tests will fail.\n' "${CONFIG_H}"
-    exit 1
-fi
-
-if [ $MAX_CONTENT_LEN -ne 16384 ]; then
-    echo "Using non-default maximum content length $MAX_CONTENT_LEN"
-fi
-
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: enabled, default" \
             "$P_SRV debug_level=3" \
@@ -3119,7 +3348,7 @@
             -s "1 bytes read"
 
 requires_config_disabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
-run_test    "Max fragment length DTLS: disabled, larger message" \
+run_test    "Max fragment length, DTLS: disabled, larger message" \
             "$P_SRV debug_level=3 dtls=1" \
             "$P_CLI debug_level=3 dtls=1 request_size=$(( $MAX_CONTENT_LEN + 1))" \
             1 \
@@ -3129,6 +3358,7 @@
             -S "Maximum output fragment length is 16384" \
             -c "fragment larger than.*maximum "
 
+requires_max_content_len 4096
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: used by client" \
             "$P_SRV debug_level=3" \
@@ -3143,6 +3373,7 @@
             -s "server hello, max_fragment_length extension" \
             -c "found max_fragment_length extension"
 
+requires_max_content_len 1024
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: client 512, server 1024" \
             "$P_SRV debug_level=3 max_frag_len=1024" \
@@ -3157,6 +3388,7 @@
             -s "server hello, max_fragment_length extension" \
             -c "found max_fragment_length extension"
 
+requires_max_content_len 2048
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: client 512, server 2048" \
             "$P_SRV debug_level=3 max_frag_len=2048" \
@@ -3171,6 +3403,7 @@
             -s "server hello, max_fragment_length extension" \
             -c "found max_fragment_length extension"
 
+requires_max_content_len 4096
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: client 512, server 4096" \
             "$P_SRV debug_level=3 max_frag_len=4096" \
@@ -3185,6 +3418,7 @@
             -s "server hello, max_fragment_length extension" \
             -c "found max_fragment_length extension"
 
+requires_max_content_len 1024
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: client 1024, server 512" \
             "$P_SRV debug_level=3 max_frag_len=512" \
@@ -3199,6 +3433,7 @@
             -s "server hello, max_fragment_length extension" \
             -c "found max_fragment_length extension"
 
+requires_max_content_len 2048
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: client 1024, server 2048" \
             "$P_SRV debug_level=3 max_frag_len=2048" \
@@ -3213,6 +3448,7 @@
             -s "server hello, max_fragment_length extension" \
             -c "found max_fragment_length extension"
 
+requires_max_content_len 4096
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: client 1024, server 4096" \
             "$P_SRV debug_level=3 max_frag_len=4096" \
@@ -3227,6 +3463,7 @@
             -s "server hello, max_fragment_length extension" \
             -c "found max_fragment_length extension"
 
+requires_max_content_len 2048
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: client 2048, server 512" \
             "$P_SRV debug_level=3 max_frag_len=512" \
@@ -3241,6 +3478,7 @@
             -s "server hello, max_fragment_length extension" \
             -c "found max_fragment_length extension"
 
+requires_max_content_len 2048
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: client 2048, server 1024" \
             "$P_SRV debug_level=3 max_frag_len=1024" \
@@ -3255,6 +3493,7 @@
             -s "server hello, max_fragment_length extension" \
             -c "found max_fragment_length extension"
 
+requires_max_content_len 4096
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: client 2048, server 4096" \
             "$P_SRV debug_level=3 max_frag_len=4096" \
@@ -3269,6 +3508,7 @@
             -s "server hello, max_fragment_length extension" \
             -c "found max_fragment_length extension"
 
+requires_max_content_len 4096
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: client 4096, server 512" \
             "$P_SRV debug_level=3 max_frag_len=512" \
@@ -3283,6 +3523,7 @@
             -s "server hello, max_fragment_length extension" \
             -c "found max_fragment_length extension"
 
+requires_max_content_len 4096
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: client 4096, server 1024" \
             "$P_SRV debug_level=3 max_frag_len=1024" \
@@ -3297,6 +3538,7 @@
             -s "server hello, max_fragment_length extension" \
             -c "found max_fragment_length extension"
 
+requires_max_content_len 4096
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: client 4096, server 2048" \
             "$P_SRV debug_level=3 max_frag_len=2048" \
@@ -3311,6 +3553,7 @@
             -s "server hello, max_fragment_length extension" \
             -c "found max_fragment_length extension"
 
+requires_max_content_len 4096
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: used by server" \
             "$P_SRV debug_level=3 max_frag_len=4096" \
@@ -3325,6 +3568,7 @@
             -S "server hello, max_fragment_length extension" \
             -C "found max_fragment_length extension"
 
+requires_max_content_len 4096
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 requires_gnutls
 run_test    "Max fragment length: gnutls server" \
@@ -3336,6 +3580,7 @@
             -c "client hello, adding max_fragment_length extension" \
             -c "found max_fragment_length extension"
 
+requires_max_content_len 2048
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: client, message just fits" \
             "$P_SRV debug_level=3" \
@@ -3352,6 +3597,7 @@
             -c "2048 bytes written in 1 fragments" \
             -s "2048 bytes read"
 
+requires_max_content_len 2048
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: client, larger message" \
             "$P_SRV debug_level=3" \
@@ -3369,6 +3615,7 @@
             -s "2048 bytes read" \
             -s "297 bytes read"
 
+requires_max_content_len 2048
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
 run_test    "Max fragment length: DTLS client, larger message" \
             "$P_SRV debug_level=3 dtls=1" \
@@ -3480,6 +3727,7 @@
 
 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+requires_max_content_len 2048
 run_test    "Renegotiation with max fragment length: client 2048, server 512" \
             "$P_SRV debug_level=3 exchanges=2 renegotiation=1 auth_mode=optional renegotiate=1 max_frag_len=512" \
             "$P_CLI debug_level=3 exchanges=2 renegotiation=1 renegotiate=1 max_frag_len=2048 force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8" \
@@ -4199,24 +4447,17 @@
             -C "! mbedtls_ssl_handshake returned" \
             -S "X509 - Certificate verification failed"
 
-# The "max_int chain" tests assume that MAX_INTERMEDIATE_CA is set to its
-# default value (8)
+# This script assumes that MBEDTLS_X509_MAX_INTERMEDIATE_CA has its default
+# value, defined here as MAX_IM_CA. Some test cases will be skipped if the
+# library is configured with a different value.
 
 MAX_IM_CA='8'
-MAX_IM_CA_CONFIG=$( ../scripts/config.py get MBEDTLS_X509_MAX_INTERMEDIATE_CA)
 
-if [ -n "$MAX_IM_CA_CONFIG" ] && [ "$MAX_IM_CA_CONFIG" -ne "$MAX_IM_CA" ]; then
-    cat <<EOF
-${CONFIG_H} contains a value for the configuration of
-MBEDTLS_X509_MAX_INTERMEDIATE_CA that is different from the script's
-test value of ${MAX_IM_CA}.
-
-The tests assume this value and if it changes, the tests in this
-script should also be adjusted.
-EOF
-    exit 1
-fi
-
+# The tests for the max_int tests can pass with any number higher than MAX_IM_CA
+# because only a chain of MAX_IM_CA length is tested. Equally, the max_int+1
+# tests can pass with any number less than MAX_IM_CA. However, stricter preconditions
+# are in place so that the semantics are consistent with the test description.
+requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
 run_test    "Authentication: server max_int chain, client default" \
             "$P_SRV crt_file=data_files/dir-maxpath/c09.pem \
@@ -4225,6 +4466,7 @@
             0 \
             -C "X509 - A fatal error occurred"
 
+requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
 run_test    "Authentication: server max_int+1 chain, client default" \
             "$P_SRV crt_file=data_files/dir-maxpath/c10.pem \
@@ -4233,6 +4475,7 @@
             1 \
             -c "X509 - A fatal error occurred"
 
+requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
 run_test    "Authentication: server max_int+1 chain, client optional" \
             "$P_SRV crt_file=data_files/dir-maxpath/c10.pem \
@@ -4242,6 +4485,7 @@
             1 \
             -c "X509 - A fatal error occurred"
 
+requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
 run_test    "Authentication: server max_int+1 chain, client none" \
             "$P_SRV crt_file=data_files/dir-maxpath/c10.pem \
@@ -4251,6 +4495,7 @@
             0 \
             -C "X509 - A fatal error occurred"
 
+requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
 run_test    "Authentication: client max_int+1 chain, server default" \
             "$P_SRV ca_file=data_files/dir-maxpath/00.crt" \
@@ -4259,6 +4504,7 @@
             0 \
             -S "X509 - A fatal error occurred"
 
+requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
 run_test    "Authentication: client max_int+1 chain, server optional" \
             "$P_SRV ca_file=data_files/dir-maxpath/00.crt auth_mode=optional" \
@@ -4267,6 +4513,7 @@
             1 \
             -s "X509 - A fatal error occurred"
 
+requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
 run_test    "Authentication: client max_int+1 chain, server required" \
             "$P_SRV ca_file=data_files/dir-maxpath/00.crt auth_mode=required" \
@@ -4275,6 +4522,7 @@
             1 \
             -s "X509 - A fatal error occurred"
 
+requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
 run_test    "Authentication: client max_int chain, server required" \
             "$P_SRV ca_file=data_files/dir-maxpath/00.crt auth_mode=required" \
@@ -4452,6 +4700,7 @@
             -C "! mbedtls_ssl_handshake returned" \
             -S "X509 - Certificate verification failed"
 
+requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
 requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
 run_test    "Authentication, CA callback: server max_int chain, client default" \
@@ -4462,6 +4711,7 @@
             -c "use CA callback for X.509 CRT verification" \
             -C "X509 - A fatal error occurred"
 
+requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
 requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
 run_test    "Authentication, CA callback: server max_int+1 chain, client default" \
@@ -4472,6 +4722,7 @@
             -c "use CA callback for X.509 CRT verification" \
             -c "X509 - A fatal error occurred"
 
+requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
 requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
 run_test    "Authentication, CA callback: server max_int+1 chain, client optional" \
@@ -4483,6 +4734,7 @@
             -c "use CA callback for X.509 CRT verification" \
             -c "X509 - A fatal error occurred"
 
+requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
 requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
 run_test    "Authentication, CA callback: client max_int+1 chain, server optional" \
@@ -4493,6 +4745,7 @@
             -s "use CA callback for X.509 CRT verification" \
             -s "X509 - A fatal error occurred"
 
+requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
 requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
 run_test    "Authentication, CA callback: client max_int+1 chain, server required" \
@@ -4503,6 +4756,7 @@
             -s "use CA callback for X.509 CRT verification" \
             -s "X509 - A fatal error occurred"
 
+requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
 requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
 run_test    "Authentication, CA callback: client max_int chain, server required" \
@@ -4520,7 +4774,7 @@
                     key_file=data_files/server5.key \
                     crt_file2=data_files/server5-sha1.crt \
                     key_file2=data_files/server5.key" \
-            "$P_CLI force_version=tls1_2" \
+            "$P_CLI force_version=tls12" \
             0 \
             -c "signed using.*ECDSA with SHA256" \
             -C "signed using.*ECDSA with SHA1"
@@ -5067,14 +5321,14 @@
 
 run_test    "Version check: cli min 1.2, srv max 1.1 -> fail" \
             "$P_SRV max_version=tls1_1" \
-            "$P_CLI min_version=tls1_2" \
+            "$P_CLI min_version=tls12" \
             1 \
             -s "mbedtls_ssl_handshake returned" \
             -c "mbedtls_ssl_handshake returned" \
             -c "SSL - Handshake protocol not within min/max boundaries"
 
 run_test    "Version check: srv min 1.2, cli max 1.1 -> fail" \
-            "$P_SRV min_version=tls1_2" \
+            "$P_SRV min_version=tls12" \
             "$P_CLI max_version=tls1_1" \
             1 \
             -s "mbedtls_ssl_handshake returned" \
@@ -5490,6 +5744,20 @@
             0 \
             -C "DHM prime too short:"
 
+run_test    "DHM size: server 999, client 999, OK" \
+            "$P_SRV dhm_file=data_files/dh.999.pem" \
+            "$P_CLI force_ciphersuite=TLS-DHE-RSA-WITH-AES-128-CBC-SHA \
+                    debug_level=1 dhmlen=999" \
+            0 \
+            -C "DHM prime too short:"
+
+run_test    "DHM size: server 1000, client 1000, OK" \
+            "$P_SRV dhm_file=data_files/dh.1000.pem" \
+            "$P_CLI force_ciphersuite=TLS-DHE-RSA-WITH-AES-128-CBC-SHA \
+                    debug_level=1 dhmlen=1000" \
+            0 \
+            -C "DHM prime too short:"
+
 run_test    "DHM size: server 1000, client default, rejected" \
             "$P_SRV dhm_file=data_files/dh.1000.pem" \
             "$P_CLI force_ciphersuite=TLS-DHE-RSA-WITH-AES-128-CBC-SHA \
@@ -5497,6 +5765,27 @@
             1 \
             -c "DHM prime too short:"
 
+run_test    "DHM size: server 1000, client 1001, rejected" \
+            "$P_SRV dhm_file=data_files/dh.1000.pem" \
+            "$P_CLI force_ciphersuite=TLS-DHE-RSA-WITH-AES-128-CBC-SHA \
+                    debug_level=1 dhmlen=1001" \
+            1 \
+            -c "DHM prime too short:"
+
+run_test    "DHM size: server 999, client 1000, rejected" \
+            "$P_SRV dhm_file=data_files/dh.999.pem" \
+            "$P_CLI force_ciphersuite=TLS-DHE-RSA-WITH-AES-128-CBC-SHA \
+                    debug_level=1 dhmlen=1000" \
+            1 \
+            -c "DHM prime too short:"
+
+run_test    "DHM size: server 998, client 999, rejected" \
+            "$P_SRV dhm_file=data_files/dh.998.pem" \
+            "$P_CLI force_ciphersuite=TLS-DHE-RSA-WITH-AES-128-CBC-SHA \
+                    debug_level=1 dhmlen=999" \
+            1 \
+            -c "DHM prime too short:"
+
 run_test    "DHM size: server default, client 2049, rejected" \
             "$P_SRV" \
             "$P_CLI force_ciphersuite=TLS-DHE-RSA-WITH-AES-128-CBC-SHA \
@@ -5518,7 +5807,7 @@
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque psk on client, no callback" \
             "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo" \
-            "$P_CLI extended_ms=0 debug_level=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+            "$P_CLI extended_ms=0 debug_level=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
             psk_identity=foo psk=abc123 psk_opaque=1" \
             0 \
             -c "skip PMS generation for opaque PSK"\
@@ -5532,7 +5821,7 @@
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque psk on client, no callback, SHA-384" \
             "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo" \
-            "$P_CLI extended_ms=0 debug_level=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \
+            "$P_CLI extended_ms=0 debug_level=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \
             psk_identity=foo psk=abc123 psk_opaque=1" \
             0 \
             -c "skip PMS generation for opaque PSK"\
@@ -5546,7 +5835,7 @@
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque psk on client, no callback, EMS" \
             "$P_SRV extended_ms=1 debug_level=3 psk=abc123 psk_identity=foo" \
-            "$P_CLI extended_ms=1 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+            "$P_CLI extended_ms=1 debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
             psk_identity=foo psk=abc123 psk_opaque=1" \
             0 \
             -c "skip PMS generation for opaque PSK"\
@@ -5560,7 +5849,7 @@
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque psk on client, no callback, SHA-384, EMS" \
             "$P_SRV extended_ms=1 debug_level=3 psk=abc123 psk_identity=foo" \
-            "$P_CLI extended_ms=1 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \
+            "$P_CLI extended_ms=1 debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \
             psk_identity=foo psk=abc123 psk_opaque=1" \
             0 \
             -c "skip PMS generation for opaque PSK"\
@@ -5573,8 +5862,8 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, static opaque on server, no callback" \
-            "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
-            "$P_CLI extended_ms=0 debug_level=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+            "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
+            "$P_CLI extended_ms=0 debug_level=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
             psk_identity=foo psk=abc123" \
             0 \
             -C "skip PMS generation for opaque PSK"\
@@ -5587,8 +5876,8 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, static opaque on server, no callback, SHA-384" \
-            "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384" \
-            "$P_CLI extended_ms=0 debug_level=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \
+            "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384" \
+            "$P_CLI extended_ms=0 debug_level=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \
             psk_identity=foo psk=abc123" \
             0 \
             -C "skip PMS generation for opaque PSK"\
@@ -5601,9 +5890,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, static opaque on server, no callback, EMS" \
-            "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls1_2 \
+            "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 \
             force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA extended_ms=1" \
-            "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+            "$P_CLI debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
             psk_identity=foo psk=abc123 extended_ms=1" \
             0 \
             -c "session hash for extended master secret"\
@@ -5616,9 +5905,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, static opaque on server, no callback, EMS, SHA384" \
-            "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls1_2 \
+            "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 \
             force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 extended_ms=1" \
-            "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \
+            "$P_CLI debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \
             psk_identity=foo psk=abc123 extended_ms=1" \
             0 \
             -c "session hash for extended master secret"\
@@ -5631,8 +5920,8 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, no static PSK on server, opaque PSK from callback" \
-            "$P_SRV extended_ms=0 debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
-            "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+            "$P_SRV extended_ms=0 debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
+            "$P_CLI extended_ms=0 debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
             psk_identity=def psk=beef" \
             0 \
             -C "skip PMS generation for opaque PSK"\
@@ -5645,8 +5934,8 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, no static PSK on server, opaque PSK from callback, SHA-384" \
-            "$P_SRV extended_ms=0 debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384" \
-            "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \
+            "$P_SRV extended_ms=0 debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384" \
+            "$P_CLI extended_ms=0 debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \
             psk_identity=def psk=beef" \
             0 \
             -C "skip PMS generation for opaque PSK"\
@@ -5659,9 +5948,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, no static PSK on server, opaque PSK from callback, EMS" \
-            "$P_SRV debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls1_2 \
+            "$P_SRV debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls12 \
             force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA extended_ms=1" \
-            "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+            "$P_CLI debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
             psk_identity=abc psk=dead extended_ms=1" \
             0 \
             -c "session hash for extended master secret"\
@@ -5674,9 +5963,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, no static PSK on server, opaque PSK from callback, EMS, SHA384" \
-            "$P_SRV debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls1_2 \
+            "$P_SRV debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls12 \
             force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 extended_ms=1" \
-            "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \
+            "$P_CLI debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \
             psk_identity=abc psk=dead extended_ms=1" \
             0 \
             -c "session hash for extended master secret"\
@@ -5689,8 +5978,8 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, mismatching static raw PSK on server, opaque PSK from callback" \
-            "$P_SRV extended_ms=0 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
-            "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+            "$P_SRV extended_ms=0 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
+            "$P_CLI extended_ms=0 debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
             psk_identity=def psk=beef" \
             0 \
             -C "skip PMS generation for opaque PSK"\
@@ -5703,8 +5992,8 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, mismatching static opaque PSK on server, opaque PSK from callback" \
-            "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
-            "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+            "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
+            "$P_CLI extended_ms=0 debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
             psk_identity=def psk=beef" \
             0 \
             -C "skip PMS generation for opaque PSK"\
@@ -5717,8 +6006,8 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, mismatching static opaque PSK on server, raw PSK from callback" \
-            "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
-            "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+            "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
+            "$P_CLI extended_ms=0 debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
             psk_identity=def psk=beef" \
             0 \
             -C "skip PMS generation for opaque PSK"\
@@ -5730,8 +6019,8 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, id-matching but wrong raw PSK on server, opaque PSK from callback" \
-            "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=def psk=abc123 debug_level=3 psk_list=abc,dead,def,beef min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
-            "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+            "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=def psk=abc123 debug_level=3 psk_list=abc,dead,def,beef min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
+            "$P_CLI extended_ms=0 debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
             psk_identity=def psk=beef" \
             0 \
             -C "skip PMS generation for opaque PSK"\
@@ -5743,8 +6032,8 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, matching opaque PSK on server, wrong opaque PSK from callback" \
-            "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=def psk=beef debug_level=3 psk_list=abc,dead,def,abc123 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
-            "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
+            "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=def psk=beef debug_level=3 psk_list=abc,dead,def,abc123 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
+            "$P_CLI extended_ms=0 debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
             psk_identity=def psk=beef" \
             1 \
             -s "SSL - Verification of the message MAC failed"
@@ -5852,7 +6141,7 @@
             -S "SSL - Verification of the message MAC failed"
 
 server_needs_more_time 1
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
 run_test    "ECJPAKE: password mismatch, TLS" \
             "$P_SRV debug_level=3 ecjpake_pw=bla" \
             "$P_CLI debug_level=3 ecjpake_pw=bad \
@@ -5861,7 +6150,7 @@
             -C "re-using cached ecjpake parameters" \
             -s "SSL - Verification of the message MAC failed"
 
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
 run_test    "ECJPAKE: working, DTLS" \
             "$P_SRV debug_level=3 dtls=1 ecjpake_pw=bla" \
             "$P_CLI debug_level=3 dtls=1 ecjpake_pw=bla \
@@ -5870,7 +6159,7 @@
             -c "re-using cached ecjpake parameters" \
             -S "SSL - Verification of the message MAC failed"
 
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
 run_test    "ECJPAKE: working, DTLS, no cookie" \
             "$P_SRV debug_level=3 dtls=1 ecjpake_pw=bla cookies=0" \
             "$P_CLI debug_level=3 dtls=1 ecjpake_pw=bla \
@@ -5880,7 +6169,7 @@
             -S "SSL - Verification of the message MAC failed"
 
 server_needs_more_time 1
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
 run_test    "ECJPAKE: password mismatch, DTLS" \
             "$P_SRV debug_level=3 dtls=1 ecjpake_pw=bla" \
             "$P_CLI debug_level=3 dtls=1 ecjpake_pw=bad \
@@ -5890,7 +6179,7 @@
             -s "SSL - Verification of the message MAC failed"
 
 # for tests with configs/config-thread.h
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
 run_test    "ECJPAKE: working, DTLS, nolog" \
             "$P_SRV dtls=1 ecjpake_pw=bla" \
             "$P_CLI dtls=1 ecjpake_pw=bla \
@@ -5931,7 +6220,7 @@
 requires_config_enabled MBEDTLS_AES_C
 run_test    "Per-version suites: TLS 1.2" \
             "$P_SRV version_suites=TLS-RSA-WITH-CAMELLIA-128-CBC-SHA,TLS-RSA-WITH-AES-256-CBC-SHA,TLS-RSA-WITH-AES-128-CBC-SHA,TLS-RSA-WITH-AES-128-GCM-SHA256" \
-            "$P_CLI force_version=tls1_2" \
+            "$P_CLI force_version=tls12" \
             0 \
             -c "Ciphersuite is TLS-RSA-WITH-AES-128-GCM-SHA256"
 
@@ -6098,21 +6387,21 @@
 
 run_test    "Small client packet TLS 1.2 BlockCipher" \
             "$P_SRV" \
-            "$P_CLI request_size=1 force_version=tls1_2 \
+            "$P_CLI request_size=1 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
             -s "Read from client: 1 bytes read"
 
 run_test    "Small client packet TLS 1.2 BlockCipher, without EtM" \
             "$P_SRV" \
-            "$P_CLI request_size=1 force_version=tls1_2 \
+            "$P_CLI request_size=1 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA etm=0" \
             0 \
             -s "Read from client: 1 bytes read"
 
 run_test    "Small client packet TLS 1.2 BlockCipher larger MAC" \
             "$P_SRV" \
-            "$P_CLI request_size=1 force_version=tls1_2 \
+            "$P_CLI request_size=1 force_version=tls12 \
              force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384" \
             0 \
             -s "Read from client: 1 bytes read"
@@ -6120,7 +6409,7 @@
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Small client packet TLS 1.2 BlockCipher, truncated MAC" \
             "$P_SRV trunc_hmac=1" \
-            "$P_CLI request_size=1 force_version=tls1_2 \
+            "$P_CLI request_size=1 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
             0 \
             -s "Read from client: 1 bytes read"
@@ -6128,21 +6417,21 @@
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Small client packet TLS 1.2 BlockCipher, without EtM, truncated MAC" \
             "$P_SRV trunc_hmac=1" \
-            "$P_CLI request_size=1 force_version=tls1_2 \
+            "$P_CLI request_size=1 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1 etm=0" \
             0 \
             -s "Read from client: 1 bytes read"
 
 run_test    "Small client packet TLS 1.2 StreamCipher" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
-            "$P_CLI request_size=1 force_version=tls1_2 \
+            "$P_CLI request_size=1 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             0 \
             -s "Read from client: 1 bytes read"
 
 run_test    "Small client packet TLS 1.2 StreamCipher, without EtM" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
-            "$P_CLI request_size=1 force_version=tls1_2 \
+            "$P_CLI request_size=1 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
             0 \
             -s "Read from client: 1 bytes read"
@@ -6150,7 +6439,7 @@
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Small client packet TLS 1.2 StreamCipher, truncated MAC" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
-            "$P_CLI request_size=1 force_version=tls1_2 \
+            "$P_CLI request_size=1 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             0 \
             -s "Read from client: 1 bytes read"
@@ -6158,21 +6447,21 @@
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Small client packet TLS 1.2 StreamCipher, without EtM, truncated MAC" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
-            "$P_CLI request_size=1 force_version=tls1_2 \
+            "$P_CLI request_size=1 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1 etm=0" \
             0 \
             -s "Read from client: 1 bytes read"
 
 run_test    "Small client packet TLS 1.2 AEAD" \
             "$P_SRV" \
-            "$P_CLI request_size=1 force_version=tls1_2 \
+            "$P_CLI request_size=1 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CCM" \
             0 \
             -s "Read from client: 1 bytes read"
 
 run_test    "Small client packet TLS 1.2 AEAD shorter tag" \
             "$P_SRV" \
-            "$P_CLI request_size=1 force_version=tls1_2 \
+            "$P_CLI request_size=1 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CCM-8" \
             0 \
             -s "Read from client: 1 bytes read"
@@ -6215,7 +6504,7 @@
 
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 run_test    "Small client packet DTLS 1.2" \
-            "$P_SRV dtls=1 force_version=dtls1_2" \
+            "$P_SRV dtls=1 force_version=dtls12" \
             "$P_CLI dtls=1 request_size=1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
@@ -6223,7 +6512,7 @@
 
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 run_test    "Small client packet DTLS 1.2, without EtM" \
-            "$P_SRV dtls=1 force_version=dtls1_2 etm=0" \
+            "$P_SRV dtls=1 force_version=dtls12 etm=0" \
             "$P_CLI dtls=1 request_size=1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
@@ -6232,7 +6521,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Small client packet DTLS 1.2, truncated hmac" \
-            "$P_SRV dtls=1 force_version=dtls1_2 trunc_hmac=1" \
+            "$P_SRV dtls=1 force_version=dtls12 trunc_hmac=1" \
             "$P_CLI dtls=1 request_size=1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
             0 \
@@ -6241,7 +6530,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Small client packet DTLS 1.2, without EtM, truncated MAC" \
-            "$P_SRV dtls=1 force_version=dtls1_2 trunc_hmac=1 etm=0" \
+            "$P_SRV dtls=1 force_version=dtls12 trunc_hmac=1 etm=0" \
             "$P_CLI dtls=1 request_size=1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1"\
             0 \
@@ -6387,21 +6676,21 @@
 
 run_test    "Small server packet TLS 1.2 BlockCipher" \
             "$P_SRV response_size=1" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
             -c "Read from server: 1 bytes read"
 
 run_test    "Small server packet TLS 1.2 BlockCipher, without EtM" \
             "$P_SRV response_size=1" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA etm=0" \
             0 \
             -c "Read from server: 1 bytes read"
 
 run_test    "Small server packet TLS 1.2 BlockCipher larger MAC" \
             "$P_SRV response_size=1" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384" \
             0 \
             -c "Read from server: 1 bytes read"
@@ -6409,7 +6698,7 @@
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Small server packet TLS 1.2 BlockCipher, truncated MAC" \
             "$P_SRV response_size=1 trunc_hmac=1" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
             0 \
             -c "Read from server: 1 bytes read"
@@ -6417,21 +6706,21 @@
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Small server packet TLS 1.2 BlockCipher, without EtM, truncated MAC" \
             "$P_SRV response_size=1 trunc_hmac=1" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1 etm=0" \
             0 \
             -c "Read from server: 1 bytes read"
 
 run_test    "Small server packet TLS 1.2 StreamCipher" \
             "$P_SRV response_size=1 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             0 \
             -c "Read from server: 1 bytes read"
 
 run_test    "Small server packet TLS 1.2 StreamCipher, without EtM" \
             "$P_SRV response_size=1 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
             0 \
             -c "Read from server: 1 bytes read"
@@ -6439,7 +6728,7 @@
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Small server packet TLS 1.2 StreamCipher, truncated MAC" \
             "$P_SRV response_size=1 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             0 \
             -c "Read from server: 1 bytes read"
@@ -6447,21 +6736,21 @@
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Small server packet TLS 1.2 StreamCipher, without EtM, truncated MAC" \
             "$P_SRV response_size=1 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1 etm=0" \
             0 \
             -c "Read from server: 1 bytes read"
 
 run_test    "Small server packet TLS 1.2 AEAD" \
             "$P_SRV response_size=1" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CCM" \
             0 \
             -c "Read from server: 1 bytes read"
 
 run_test    "Small server packet TLS 1.2 AEAD shorter tag" \
             "$P_SRV response_size=1" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CCM-8" \
             0 \
             -c "Read from server: 1 bytes read"
@@ -6504,7 +6793,7 @@
 
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 run_test    "Small server packet DTLS 1.2" \
-            "$P_SRV dtls=1 response_size=1 force_version=dtls1_2" \
+            "$P_SRV dtls=1 response_size=1 force_version=dtls12" \
             "$P_CLI dtls=1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
@@ -6512,7 +6801,7 @@
 
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 run_test    "Small server packet DTLS 1.2, without EtM" \
-            "$P_SRV dtls=1 response_size=1 force_version=dtls1_2 etm=0" \
+            "$P_SRV dtls=1 response_size=1 force_version=dtls12 etm=0" \
             "$P_CLI dtls=1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
@@ -6521,7 +6810,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Small server packet DTLS 1.2, truncated hmac" \
-            "$P_SRV dtls=1 response_size=1 force_version=dtls1_2 trunc_hmac=1" \
+            "$P_SRV dtls=1 response_size=1 force_version=dtls12 trunc_hmac=1" \
             "$P_CLI dtls=1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
             0 \
@@ -6530,15 +6819,15 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Small server packet DTLS 1.2, without EtM, truncated MAC" \
-            "$P_SRV dtls=1 response_size=1 force_version=dtls1_2 trunc_hmac=1 etm=0" \
+            "$P_SRV dtls=1 response_size=1 force_version=dtls12 trunc_hmac=1 etm=0" \
             "$P_CLI dtls=1 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1"\
             0 \
             -c "Read from server: 1 bytes read"
 
 # A test for extensions in SSLv3
-
 requires_config_enabled MBEDTLS_SSL_PROTO_SSL3
+requires_max_content_len 4096
 run_test    "SSLv3 with extensions, server side" \
             "$P_SRV min_version=ssl3 debug_level=3" \
             "$P_CLI force_version=ssl3 tickets=1 max_frag_len=4096 alpn=abc,1234" \
@@ -6700,7 +6989,7 @@
 
 run_test    "Large client packet TLS 1.2 BlockCipher" \
             "$P_SRV" \
-            "$P_CLI request_size=16384 force_version=tls1_2 \
+            "$P_CLI request_size=16384 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
@@ -6708,14 +6997,14 @@
 
 run_test    "Large client packet TLS 1.2 BlockCipher, without EtM" \
             "$P_SRV" \
-            "$P_CLI request_size=16384 force_version=tls1_2 etm=0 \
+            "$P_CLI request_size=16384 force_version=tls12 etm=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 run_test    "Large client packet TLS 1.2 BlockCipher larger MAC" \
             "$P_SRV" \
-            "$P_CLI request_size=16384 force_version=tls1_2 \
+            "$P_CLI request_size=16384 force_version=tls12 \
              force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384" \
             0 \
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
@@ -6724,7 +7013,7 @@
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large client packet TLS 1.2 BlockCipher, truncated MAC" \
             "$P_SRV trunc_hmac=1" \
-            "$P_CLI request_size=16384 force_version=tls1_2 \
+            "$P_CLI request_size=16384 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1" \
             0 \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
@@ -6732,7 +7021,7 @@
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large client packet TLS 1.2 BlockCipher, without EtM, truncated MAC" \
             "$P_SRV trunc_hmac=1" \
-            "$P_CLI request_size=16384 force_version=tls1_2 \
+            "$P_CLI request_size=16384 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1 etm=0" \
             0 \
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
@@ -6740,7 +7029,7 @@
 
 run_test    "Large client packet TLS 1.2 StreamCipher" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
-            "$P_CLI request_size=16384 force_version=tls1_2 \
+            "$P_CLI request_size=16384 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             0 \
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
@@ -6748,7 +7037,7 @@
 
 run_test    "Large client packet TLS 1.2 StreamCipher, without EtM" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
-            "$P_CLI request_size=16384 force_version=tls1_2 \
+            "$P_CLI request_size=16384 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
             0 \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
@@ -6756,7 +7045,7 @@
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large client packet TLS 1.2 StreamCipher, truncated MAC" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
-            "$P_CLI request_size=16384 force_version=tls1_2 \
+            "$P_CLI request_size=16384 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
             0 \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
@@ -6764,7 +7053,7 @@
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large client packet TLS 1.2 StreamCipher, without EtM, truncated MAC" \
             "$P_SRV arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
-            "$P_CLI request_size=16384 force_version=tls1_2 \
+            "$P_CLI request_size=16384 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1 etm=0" \
             0 \
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
@@ -6772,7 +7061,7 @@
 
 run_test    "Large client packet TLS 1.2 AEAD" \
             "$P_SRV" \
-            "$P_CLI request_size=16384 force_version=tls1_2 \
+            "$P_CLI request_size=16384 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CCM" \
             0 \
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
@@ -6780,13 +7069,14 @@
 
 run_test    "Large client packet TLS 1.2 AEAD shorter tag" \
             "$P_SRV" \
-            "$P_CLI request_size=16384 force_version=tls1_2 \
+            "$P_CLI request_size=16384 force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CCM-8" \
             0 \
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
 # Test for large server packets
+# The tests below fail when the server's OUT_CONTENT_LEN is less than 16384.
 requires_config_enabled MBEDTLS_SSL_PROTO_SSL3
 run_test    "Large server packet SSLv3 StreamCipher" \
             "$P_SRV response_size=16384 min_version=ssl3 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
@@ -6946,14 +7236,14 @@
 
 run_test    "Large server packet TLS 1.2 BlockCipher" \
             "$P_SRV response_size=16384" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
             -c "Read from server: 16384 bytes read"
 
 run_test    "Large server packet TLS 1.2 BlockCipher, without EtM" \
             "$P_SRV response_size=16384" \
-            "$P_CLI force_version=tls1_2 etm=0 \
+            "$P_CLI force_version=tls12 etm=0 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA" \
             0 \
             -s "16384 bytes written in 1 fragments" \
@@ -6961,7 +7251,7 @@
 
 run_test    "Large server packet TLS 1.2 BlockCipher larger MAC" \
             "$P_SRV response_size=16384" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384" \
             0 \
             -c "Read from server: 16384 bytes read"
@@ -6969,7 +7259,7 @@
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large server packet TLS 1.2 BlockCipher truncated MAC" \
             "$P_SRV response_size=16384" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA \
              trunc_hmac=1" \
             0 \
@@ -6977,7 +7267,7 @@
 
 run_test    "Large server packet TLS 1.2 BlockCipher, without EtM, truncated MAC" \
             "$P_SRV response_size=16384 trunc_hmac=1" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CBC-SHA trunc_hmac=1 etm=0" \
             0 \
             -s "16384 bytes written in 1 fragments" \
@@ -6985,7 +7275,7 @@
 
 run_test    "Large server packet TLS 1.2 StreamCipher" \
             "$P_SRV response_size=16384 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
             0 \
             -s "16384 bytes written in 1 fragments" \
@@ -6993,7 +7283,7 @@
 
 run_test    "Large server packet TLS 1.2 StreamCipher, without EtM" \
             "$P_SRV response_size=16384 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA etm=0" \
             0 \
             -s "16384 bytes written in 1 fragments" \
@@ -7002,7 +7292,7 @@
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large server packet TLS 1.2 StreamCipher truncated MAC" \
             "$P_SRV response_size=16384 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA \
              trunc_hmac=1" \
             0 \
@@ -7011,7 +7301,7 @@
 requires_config_enabled MBEDTLS_SSL_TRUNCATED_HMAC
 run_test    "Large server packet TLS 1.2 StreamCipher, without EtM, truncated MAC" \
             "$P_SRV response_size=16384 arc4=1 force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-RC4-128-SHA trunc_hmac=1 etm=0" \
             0 \
             -s "16384 bytes written in 1 fragments" \
@@ -7019,14 +7309,14 @@
 
 run_test    "Large server packet TLS 1.2 AEAD" \
             "$P_SRV response_size=16384" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CCM" \
             0 \
             -c "Read from server: 16384 bytes read"
 
 run_test    "Large server packet TLS 1.2 AEAD shorter tag" \
             "$P_SRV response_size=16384" \
-            "$P_CLI force_version=tls1_2 \
+            "$P_CLI force_version=tls12 \
              force_ciphersuite=TLS-RSA-WITH-AES-256-CCM-8" \
             0 \
             -c "Read from server: 16384 bytes read"
@@ -7808,6 +8098,7 @@
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+requires_max_content_len 4096
 run_test    "DTLS fragmenting: none (for reference)" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
              crt_file=data_files/server7_int-ca.crt \
@@ -7828,6 +8119,7 @@
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: server only (max_frag_len)" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
              crt_file=data_files/server7_int-ca.crt \
@@ -7852,6 +8144,7 @@
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+requires_max_content_len 4096
 run_test    "DTLS fragmenting: server only (more) (max_frag_len)" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
              crt_file=data_files/server7_int-ca.crt \
@@ -7872,6 +8165,7 @@
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: client-initiated, server only (max_frag_len)" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=none \
              crt_file=data_files/server7_int-ca.crt \
@@ -7899,6 +8193,7 @@
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: client-initiated, server only (max_frag_len), proxy MTU" \
             -p "$P_PXY mtu=1110" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=none \
@@ -7920,6 +8215,7 @@
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: client-initiated, both (max_frag_len)" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
              crt_file=data_files/server7_int-ca.crt \
@@ -7947,6 +8243,7 @@
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: client-initiated, both (max_frag_len), proxy MTU" \
             -p "$P_PXY mtu=1110" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
@@ -7967,6 +8264,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
+requires_max_content_len 4096
 run_test    "DTLS fragmenting: none (for reference) (MTU)" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
              crt_file=data_files/server7_int-ca.crt \
@@ -7986,6 +8284,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
+requires_max_content_len 4096
 run_test    "DTLS fragmenting: client (MTU)" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
              crt_file=data_files/server7_int-ca.crt \
@@ -8005,6 +8304,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: server (MTU)" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
              crt_file=data_files/server7_int-ca.crt \
@@ -8024,6 +8324,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: both (MTU=1024)" \
             -p "$P_PXY mtu=1024" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
@@ -8046,9 +8347,10 @@
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SHA256_C
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 requires_config_enabled MBEDTLS_AES_C
 requires_config_enabled MBEDTLS_GCM_C
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: both (MTU=512)" \
             -p "$P_PXY mtu=512" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
@@ -8077,9 +8379,10 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 requires_config_enabled MBEDTLS_AES_C
 requires_config_enabled MBEDTLS_GCM_C
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: proxy MTU: auto-reduction (not valgrind)" \
             -p "$P_PXY mtu=508" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
@@ -8101,9 +8404,10 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 requires_config_enabled MBEDTLS_AES_C
 requires_config_enabled MBEDTLS_GCM_C
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: proxy MTU: auto-reduction (with valgrind)" \
             -p "$P_PXY mtu=508" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
@@ -8127,6 +8431,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: proxy MTU, simple handshake (MTU=1024)" \
             -p "$P_PXY mtu=1024" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
@@ -8153,9 +8458,10 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 requires_config_enabled MBEDTLS_AES_C
 requires_config_enabled MBEDTLS_GCM_C
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: proxy MTU, simple handshake (MTU=512)" \
             -p "$P_PXY mtu=512" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
@@ -8179,6 +8485,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: proxy MTU, simple handshake, nbio (MTU=1024)" \
             -p "$P_PXY mtu=1024" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
@@ -8202,9 +8509,10 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 requires_config_enabled MBEDTLS_AES_C
 requires_config_enabled MBEDTLS_GCM_C
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: proxy MTU, simple handshake, nbio (MTU=512)" \
             -p "$P_PXY mtu=512" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
@@ -8238,9 +8546,10 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 requires_config_enabled MBEDTLS_AES_C
 requires_config_enabled MBEDTLS_GCM_C
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: proxy MTU, resumed handshake" \
             -p "$P_PXY mtu=1450" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
@@ -8267,9 +8576,10 @@
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SHA256_C
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
 requires_config_enabled MBEDTLS_CHACHAPOLY_C
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: proxy MTU, ChachaPoly renego" \
             -p "$P_PXY mtu=512" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
@@ -8298,10 +8608,11 @@
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SHA256_C
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
 requires_config_enabled MBEDTLS_AES_C
 requires_config_enabled MBEDTLS_GCM_C
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: proxy MTU, AES-GCM renego" \
             -p "$P_PXY mtu=512" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
@@ -8330,10 +8641,11 @@
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SHA256_C
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
 requires_config_enabled MBEDTLS_AES_C
 requires_config_enabled MBEDTLS_CCM_C
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: proxy MTU, AES-CCM renego" \
             -p "$P_PXY mtu=1024" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
@@ -8362,11 +8674,12 @@
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SHA256_C
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
 requires_config_enabled MBEDTLS_AES_C
 requires_config_enabled MBEDTLS_CIPHER_MODE_CBC
 requires_config_enabled MBEDTLS_SSL_ENCRYPT_THEN_MAC
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: proxy MTU, AES-CBC EtM renego" \
             -p "$P_PXY mtu=1024" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
@@ -8395,10 +8708,11 @@
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SHA256_C
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
 requires_config_enabled MBEDTLS_AES_C
 requires_config_enabled MBEDTLS_CIPHER_MODE_CBC
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: proxy MTU, AES-CBC non-EtM renego" \
             -p "$P_PXY mtu=1024" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
@@ -8424,10 +8738,11 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 requires_config_enabled MBEDTLS_AES_C
 requires_config_enabled MBEDTLS_GCM_C
 client_needs_more_time 2
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: proxy MTU + 3d" \
             -p "$P_PXY mtu=512 drop=8 delay=8 duplicate=8" \
             "$P_SRV dgram_packing=0 dtls=1 debug_level=2 auth_mode=required \
@@ -8448,10 +8763,11 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 requires_config_enabled MBEDTLS_AES_C
 requires_config_enabled MBEDTLS_GCM_C
 client_needs_more_time 2
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: proxy MTU + 3d, nbio" \
             -p "$P_PXY mtu=512 drop=8 delay=8 duplicate=8" \
             "$P_SRV dtls=1 debug_level=2 auth_mode=required \
@@ -8477,12 +8793,13 @@
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 requires_gnutls
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: gnutls server, DTLS 1.2" \
             "$G_SRV -u" \
             "$P_CLI dtls=1 debug_level=2 \
              crt_file=data_files/server8_int-ca2.crt \
              key_file=data_files/server8.key \
-             mtu=512 force_version=dtls1_2" \
+             mtu=512 force_version=dtls12" \
             0 \
             -c "fragmenting handshake message" \
             -C "error"
@@ -8492,6 +8809,7 @@
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
 requires_gnutls
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: gnutls server, DTLS 1.0" \
             "$G_SRV -u" \
             "$P_CLI dtls=1 debug_level=2 \
@@ -8515,11 +8833,12 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 requires_gnutls
 requires_not_i686
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: gnutls client, DTLS 1.2" \
             "$P_SRV dtls=1 debug_level=2 \
              crt_file=data_files/server7_int-ca.crt \
              key_file=data_files/server7.key \
-             mtu=512 force_version=dtls1_2" \
+             mtu=512 force_version=dtls12" \
             "$G_CLI -u --insecure 127.0.0.1" \
             0 \
             -s "fragmenting handshake message"
@@ -8531,6 +8850,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
 requires_gnutls
 requires_not_i686
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: gnutls client, DTLS 1.0" \
             "$P_SRV dtls=1 debug_level=2 \
              crt_file=data_files/server7_int-ca.crt \
@@ -8544,12 +8864,13 @@
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: openssl server, DTLS 1.2" \
             "$O_SRV -dtls1_2 -verify 10" \
             "$P_CLI dtls=1 debug_level=2 \
              crt_file=data_files/server8_int-ca2.crt \
              key_file=data_files/server8.key \
-             mtu=512 force_version=dtls1_2" \
+             mtu=512 force_version=dtls12" \
             0 \
             -c "fragmenting handshake message" \
             -C "error"
@@ -8558,6 +8879,7 @@
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: openssl server, DTLS 1.0" \
             "$O_SRV -dtls1 -verify 10" \
             "$P_CLI dtls=1 debug_level=2 \
@@ -8572,11 +8894,12 @@
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: openssl client, DTLS 1.2" \
             "$P_SRV dtls=1 debug_level=2 \
              crt_file=data_files/server7_int-ca.crt \
              key_file=data_files/server7.key \
-             mtu=512 force_version=dtls1_2" \
+             mtu=512 force_version=dtls12" \
             "$O_CLI -dtls1_2" \
             0 \
             -s "fragmenting handshake message"
@@ -8585,6 +8908,7 @@
 requires_config_enabled MBEDTLS_RSA_C
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: openssl client, DTLS 1.0" \
             "$P_SRV dtls=1 debug_level=2 \
              crt_file=data_files/server7_int-ca.crt \
@@ -8604,13 +8928,14 @@
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 client_needs_more_time 4
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: 3d, gnutls server, DTLS 1.2" \
             -p "$P_PXY drop=8 delay=8 duplicate=8" \
             "$G_NEXT_SRV -u" \
             "$P_CLI dgram_packing=0 dtls=1 debug_level=2 \
              crt_file=data_files/server8_int-ca2.crt \
              key_file=data_files/server8.key \
-             hs_timeout=250-60000 mtu=512 force_version=dtls1_2" \
+             hs_timeout=250-60000 mtu=512 force_version=dtls12" \
             0 \
             -c "fragmenting handshake message" \
             -C "error"
@@ -8621,6 +8946,7 @@
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
 client_needs_more_time 4
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: 3d, gnutls server, DTLS 1.0" \
             -p "$P_PXY drop=8 delay=8 duplicate=8" \
             "$G_NEXT_SRV -u" \
@@ -8638,12 +8964,13 @@
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 client_needs_more_time 4
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: 3d, gnutls client, DTLS 1.2" \
             -p "$P_PXY drop=8 delay=8 duplicate=8" \
             "$P_SRV dtls=1 debug_level=2 \
              crt_file=data_files/server7_int-ca.crt \
              key_file=data_files/server7.key \
-             hs_timeout=250-60000 mtu=512 force_version=dtls1_2" \
+             hs_timeout=250-60000 mtu=512 force_version=dtls12" \
            "$G_NEXT_CLI -u --insecure 127.0.0.1" \
             0 \
             -s "fragmenting handshake message"
@@ -8654,6 +8981,7 @@
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
 client_needs_more_time 4
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: 3d, gnutls client, DTLS 1.0" \
             -p "$P_PXY drop=8 delay=8 duplicate=8" \
             "$P_SRV dtls=1 debug_level=2 \
@@ -8675,13 +9003,14 @@
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 client_needs_more_time 4
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: 3d, openssl server, DTLS 1.2" \
             -p "$P_PXY drop=8 delay=8 duplicate=8" \
             "$O_SRV -dtls1_2 -verify 10" \
             "$P_CLI dtls=1 debug_level=2 \
              crt_file=data_files/server8_int-ca2.crt \
              key_file=data_files/server8.key \
-             hs_timeout=250-60000 mtu=512 force_version=dtls1_2" \
+             hs_timeout=250-60000 mtu=512 force_version=dtls12" \
             0 \
             -c "fragmenting handshake message" \
             -C "error"
@@ -8692,6 +9021,7 @@
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
 client_needs_more_time 4
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: 3d, openssl server, DTLS 1.0" \
             -p "$P_PXY drop=8 delay=8 duplicate=8" \
             "$O_SRV -dtls1 -verify 10" \
@@ -8709,12 +9039,13 @@
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 client_needs_more_time 4
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: 3d, openssl client, DTLS 1.2" \
             -p "$P_PXY drop=8 delay=8 duplicate=8" \
             "$P_SRV dtls=1 debug_level=2 \
              crt_file=data_files/server7_int-ca.crt \
              key_file=data_files/server7.key \
-             hs_timeout=250-60000 mtu=512 force_version=dtls1_2" \
+             hs_timeout=250-60000 mtu=512 force_version=dtls12" \
             "$O_CLI -dtls1_2" \
             0 \
             -s "fragmenting handshake message"
@@ -8727,6 +9058,7 @@
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
 client_needs_more_time 4
+requires_max_content_len 2048
 run_test    "DTLS fragmenting: 3d, openssl client, DTLS 1.0" \
             -p "$P_PXY drop=8 delay=8 duplicate=8" \
             "$P_SRV dgram_packing=0 dtls=1 debug_level=2 \
@@ -9807,6 +10139,7 @@
 requires_config_enabled MBEDTLS_MEMORY_DEBUG
 requires_config_enabled MBEDTLS_MEMORY_BUFFER_ALLOC_C
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+requires_max_content_len 16384
 run_tests_memory_after_hanshake
 
 # Final report
diff --git a/third_party/mbedtls/repo/tests/suites/helpers.function b/third_party/mbedtls/repo/tests/suites/helpers.function
index aafcf5c..91ad925 100644
--- a/third_party/mbedtls/repo/tests/suites/helpers.function
+++ b/third_party/mbedtls/repo/tests/suites/helpers.function
@@ -5,6 +5,7 @@
 #include <test/macros.h>
 #include <test/helpers.h>
 #include <test/random.h>
+#include <test/psa_crypto_helpers.h>
 
 #include <stdlib.h>
 
@@ -75,292 +76,8 @@
                                                build */
 
 /*----------------------------------------------------------------------------*/
-/* Macros */
-
-/**
- * \brief   This macro tests the expression passed to it as a test step or
- *          individual test in a test case.
- *
- *          It allows a library function to return a value and return an error
- *          code that can be tested.
- *
- *          When MBEDTLS_CHECK_PARAMS is enabled, calls to the parameter failure
- *          callback, MBEDTLS_PARAM_FAILED(), will be assumed to be a test
- *          failure.
- *
- *          This macro is not suitable for negative parameter validation tests,
- *          as it assumes the test step will not create an error.
- *
- *          Failing the test means:
- *          - Mark this test case as failed.
- *          - Print a message identifying the failure.
- *          - Jump to the \c exit label.
- *
- *          This macro expands to an instruction, not an expression.
- *          It may jump to the \c exit label.
- *
- * \param   TEST    The test expression to be tested.
- */
-#define TEST_ASSERT( TEST )                                 \
-    do {                                                    \
-       if( ! (TEST) )                                       \
-       {                                                    \
-          test_fail( #TEST, __LINE__, __FILE__ );           \
-          goto exit;                                        \
-       }                                                    \
-    } while( 0 )
-
-/** Evaluate two expressions and fail the test case if they have different
- * values.
- *
- * \param expr1     An expression to evaluate.
- * \param expr2     The expected value of \p expr1. This can be any
- *                  expression, but it is typically a constant.
- */
-#define TEST_EQUAL( expr1, expr2 )              \
-    TEST_ASSERT( ( expr1 ) == ( expr2 ) )
-
-/** Allocate memory dynamically and fail the test case if this fails.
- * The allocated memory will be filled with zeros.
- *
- * You must set \p pointer to \c NULL before calling this macro and
- * put `mbedtls_free( pointer )` in the test's cleanup code.
- *
- * If \p length is zero, the resulting \p pointer will be \c NULL.
- * This is usually what we want in tests since API functions are
- * supposed to accept null pointers when a buffer size is zero.
- *
- * This macro expands to an instruction, not an expression.
- * It may jump to the \c exit label.
- *
- * \param pointer   An lvalue where the address of the allocated buffer
- *                  will be stored.
- *                  This expression may be evaluated multiple times.
- * \param length    Number of elements to allocate.
- *                  This expression may be evaluated multiple times.
- *
- */
-#define ASSERT_ALLOC( pointer, length )                           \
-    do                                                            \
-    {                                                             \
-        TEST_ASSERT( ( pointer ) == NULL );                       \
-        if( ( length ) != 0 )                                     \
-        {                                                         \
-            ( pointer ) = mbedtls_calloc( sizeof( *( pointer ) ), \
-                                          ( length ) );           \
-            TEST_ASSERT( ( pointer ) != NULL );                   \
-        }                                                         \
-    }                                                             \
-    while( 0 )
-
-/** Allocate memory dynamically. If the allocation fails, skip the test case.
- *
- * This macro behaves like #ASSERT_ALLOC, except that if the allocation
- * fails, it marks the test as skipped rather than failed.
- */
-#define ASSERT_ALLOC_WEAK( pointer, length )                      \
-    do                                                            \
-    {                                                             \
-        TEST_ASSERT( ( pointer ) == NULL );                       \
-        if( ( length ) != 0 )                                     \
-        {                                                         \
-            ( pointer ) = mbedtls_calloc( sizeof( *( pointer ) ), \
-                                          ( length ) );           \
-            TEST_ASSUME( ( pointer ) != NULL );                   \
-        }                                                         \
-    }                                                             \
-    while( 0 )
-
-/** Compare two buffers and fail the test case if they differ.
- *
- * This macro expands to an instruction, not an expression.
- * It may jump to the \c exit label.
- *
- * \param p1        Pointer to the start of the first buffer.
- * \param size1     Size of the first buffer in bytes.
- *                  This expression may be evaluated multiple times.
- * \param p2        Pointer to the start of the second buffer.
- * \param size2     Size of the second buffer in bytes.
- *                  This expression may be evaluated multiple times.
- */
-#define ASSERT_COMPARE( p1, size1, p2, size2 )                          \
-    do                                                                  \
-    {                                                                   \
-        TEST_ASSERT( ( size1 ) == ( size2 ) );                          \
-        if( ( size1 ) != 0 )                                            \
-            TEST_ASSERT( memcmp( ( p1 ), ( p2 ), ( size1 ) ) == 0 );    \
-    }                                                                   \
-    while( 0 )
-
-/**
- * \brief   This macro tests the expression passed to it and skips the
- *          running test if it doesn't evaluate to 'true'.
- *
- * \param   TEST    The test expression to be tested.
- */
-#define TEST_ASSUME( TEST )                         \
-    do {                                            \
-        if( ! (TEST) )                              \
-        {                                           \
-            test_skip( #TEST, __LINE__, __FILE__ ); \
-            goto exit;                              \
-        }                                           \
-    } while( 0 )
-
-#if defined(MBEDTLS_CHECK_PARAMS) && !defined(MBEDTLS_PARAM_FAILED_ALT)
-/**
- * \brief   This macro tests the statement passed to it as a test step or
- *          individual test in a test case. The macro assumes the test will fail
- *          and will generate an error.
- *
- *          It allows a library function to return a value and tests the return
- *          code on return to confirm the given error code was returned.
- *
- *          When MBEDTLS_CHECK_PARAMS is enabled, calls to the parameter failure
- *          callback, MBEDTLS_PARAM_FAILED(), are assumed to indicate the
- *          expected failure, and the test will pass.
- *
- *          This macro is intended for negative parameter validation tests,
- *          where the failing function may return an error value or call
- *          MBEDTLS_PARAM_FAILED() to indicate the error.
- *
- * \param   PARAM_ERROR_VALUE   The expected error code.
- *
- * \param   TEST                The test expression to be tested.
- */
-#define TEST_INVALID_PARAM_RET( PARAM_ERR_VALUE, TEST )                 \
-    do {                                                                \
-        mbedtls_test_param_failed_expect_call( );                       \
-        if( ( ( TEST ) != ( PARAM_ERR_VALUE ) ) ||                      \
-            ( mbedtls_test_param_failed_check_expected_call( ) != 0 ) ) \
-        {                                                               \
-            test_fail( #TEST, __LINE__, __FILE__ );                     \
-            goto exit;                                                  \
-        }                                                               \
-        mbedtls_test_param_failed_check_expected_call( );               \
-   } while( 0 )
-
-/**
- * \brief   This macro tests the statement passed to it as a test step or
- *          individual test in a test case. The macro assumes the test will fail
- *          and will generate an error.
- *
- *          It assumes the library function under test cannot return a value and
- *          assumes errors can only be indicated byt calls to
- *          MBEDTLS_PARAM_FAILED().
- *
- *          When MBEDTLS_CHECK_PARAMS is enabled, calls to the parameter failure
- *          callback, MBEDTLS_PARAM_FAILED(), are assumed to indicate the
- *          expected failure. If MBEDTLS_CHECK_PARAMS is not enabled, no test
- *          can be made.
- *
- *          This macro is intended for negative parameter validation tests,
- *          where the failing function can only return an error by calling
- *          MBEDTLS_PARAM_FAILED() to indicate the error.
- *
- * \param   TEST                The test expression to be tested.
- */
-#define TEST_INVALID_PARAM( TEST )                                       \
-    do {                                                                 \
-        memcpy( jmp_tmp, mbedtls_test_param_failed_get_state_buf( ),     \
-                sizeof( jmp_tmp ) );                                     \
-        if( setjmp(  mbedtls_test_param_failed_get_state_buf( ) ) == 0 ) \
-        {                                                                \
-            TEST;                                                        \
-            test_fail( #TEST, __LINE__, __FILE__ );                      \
-            goto exit;                                                   \
-        }                                                                \
-        mbedtls_test_param_failed_reset_state( );                        \
-    } while( 0 )
-#endif /* MBEDTLS_CHECK_PARAMS && !MBEDTLS_PARAM_FAILED_ALT */
-
-/**
- * \brief   This macro tests the statement passed to it as a test step or
- *          individual test in a test case. The macro assumes the test will not fail.
- *
- *          It assumes the library function under test cannot return a value and
- *          assumes errors can only be indicated by calls to
- *          MBEDTLS_PARAM_FAILED().
- *
- *          When MBEDTLS_CHECK_PARAMS is enabled, calls to the parameter failure
- *          callback, MBEDTLS_PARAM_FAILED(), are assumed to indicate the
- *          expected failure. If MBEDTLS_CHECK_PARAMS is not enabled, no test
- *          can be made.
- *
- *          This macro is intended to test that functions returning void
- *          accept all of the parameter values they're supposed to accept - eg
- *          that they don't call MBEDTLS_PARAM_FAILED() when a parameter
- *          that's allowed to be NULL happens to be NULL.
- *
- *          Note: for functions that return something other that void,
- *          checking that they accept all the parameters they're supposed to
- *          accept is best done by using TEST_ASSERT() and checking the return
- *          value as well.
- *
- *          Note: this macro is available even when #MBEDTLS_CHECK_PARAMS is
- *          disabled, as it makes sense to check that the functions accept all
- *          legal values even if this option is disabled - only in that case,
- *          the test is more about whether the function segfaults than about
- *          whether it invokes MBEDTLS_PARAM_FAILED().
- *
- * \param   TEST                The test expression to be tested.
- */
-#define TEST_VALID_PARAM( TEST )                                    \
-    TEST_ASSERT( ( TEST, 1 ) );
-
-/** Allocate memory dynamically and fail the test case if this fails.
- *
- * You must set \p pointer to \c NULL before calling this macro and
- * put `mbedtls_free( pointer )` in the test's cleanup code.
- *
- * If \p length is zero, the resulting \p pointer will be \c NULL.
- * This is usually what we want in tests since API functions are
- * supposed to accept null pointers when a buffer size is zero.
- *
- * This macro expands to an instruction, not an expression.
- * It may jump to the \c exit label.
- *
- * \param pointer   An lvalue where the address of the allocated buffer
- *                  will be stored.
- *                  This expression may be evaluated multiple times.
- * \param length    Number of elements to allocate.
- *                  This expression may be evaluated multiple times.
- *
- */
-#define ASSERT_ALLOC( pointer, length )                           \
-    do                                                            \
-    {                                                             \
-        TEST_ASSERT( ( pointer ) == NULL );                       \
-        if( ( length ) != 0 )                                     \
-        {                                                         \
-            ( pointer ) = mbedtls_calloc( sizeof( *( pointer ) ), \
-                                          ( length ) );           \
-            TEST_ASSERT( ( pointer ) != NULL );                   \
-        }                                                         \
-    }                                                             \
-    while( 0 )
-
-/*----------------------------------------------------------------------------*/
 /* Global variables */
 
-typedef enum
-{
-    TEST_RESULT_SUCCESS = 0,
-    TEST_RESULT_FAILED,
-    TEST_RESULT_SKIPPED
-} test_result_t;
-
-typedef struct
-{
-    test_result_t result;
-    const char *test;
-    const char *filename;
-    int line_no;
-    unsigned long step;
-}
-test_info_t;
-static test_info_t test_info;
-
 #if defined(MBEDTLS_CHECK_PARAMS)
 jmp_buf jmp_tmp;
 #endif
@@ -383,40 +100,25 @@
 /*----------------------------------------------------------------------------*/
 /* Helper Functions */
 
-/** Set the test step number for failure reports.
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+/** Check that no PSA Crypto key slots are in use.
  *
- * Call this function to display "step NNN" in addition to the line number
- * and file name if a test fails. Typically the "step number" is the index
- * of a for loop but it can be whatever you want.
+ * If any slots are in use, mark the current test as failed.
  *
- * \param step  The step number to report.
+ * \return 0 if the key store is empty, 1 otherwise.
  */
-void test_set_step( unsigned long step )
+int test_fail_if_psa_leaking( int line_no, const char *filename )
 {
-    test_info.step = step;
-}
-
-void test_fail( const char *test, int line_no, const char* filename )
-{
-    if( test_info.result == TEST_RESULT_FAILED )
+    const char *msg = mbedtls_test_helper_is_psa_leaking( );
+    if( msg == NULL )
+        return 0;
+    else
     {
-        /* We've already recorded the test as having failed. Don't
-         * overwrite any previous information about the failure. */
-        return;
+        mbedtls_test_fail( msg, line_no, filename );
+        return 1;
     }
-    test_info.result = TEST_RESULT_FAILED;
-    test_info.test = test;
-    test_info.line_no = line_no;
-    test_info.filename = filename;
 }
-
-void test_skip( const char *test, int line_no, const char* filename )
-{
-    test_info.result = TEST_RESULT_SKIPPED;
-    test_info.test = test;
-    test_info.line_no = line_no;
-    test_info.filename = filename;
-}
+#endif /* defined(MBEDTLS_PSA_CRYPTO_C) */
 
 #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
 static int redirect_output( FILE* out_stream, const char* path )
diff --git a/third_party/mbedtls/repo/tests/suites/host_test.function b/third_party/mbedtls/repo/tests/suites/host_test.function
index 872a3a4..17926eb 100644
--- a/third_party/mbedtls/repo/tests/suites/host_test.function
+++ b/third_party/mbedtls/repo/tests/suites/host_test.function
@@ -33,7 +33,7 @@
  *
  * \return      0 if success else 1
  */
-int verify_int( char *str, int *value )
+int verify_int( char *str, int32_t *value )
 {
     size_t i;
     int minus = 0;
@@ -238,7 +238,7 @@
  *
  * \return      0 for success else 1
  */
-static int convert_params( size_t cnt , char ** params , int * int_params_store )
+static int convert_params( size_t cnt , char ** params , int32_t * int_params_store )
 {
     char ** cur = params;
     char ** out = params;
@@ -360,8 +360,6 @@
 /**
  * \brief       Tests snprintf implementation.
  *
- * \param none
- *
  * \return      0 for success else 1
  */
 static int run_test_snprintf( void )
@@ -428,15 +426,15 @@
  * \param unmet_dependencies         The array of unmet dependencies.
  * \param missing_unmet_dependencies Non-zero if there was a problem tracking
  *                                   all unmet dependencies, 0 otherwise.
- * \param ret           The test dispatch status (DISPATCH_xxx).
- * \param test_info     A pointer to the test info structure.
+ * \param ret                        The test dispatch status (DISPATCH_xxx).
+ * \param info                       A pointer to the test info structure.
  */
 static void write_outcome_result( FILE *outcome_file,
                                   size_t unmet_dep_count,
                                   int unmet_dependencies[],
                                   int missing_unmet_dependencies,
                                   int ret,
-                                  const test_info_t *info )
+                                  const mbedtls_test_info_t *info )
 {
     if( outcome_file == NULL )
         return;
@@ -462,10 +460,10 @@
             }
             switch( info->result )
             {
-                case TEST_RESULT_SUCCESS:
+                case MBEDTLS_TEST_RESULT_SUCCESS:
                     mbedtls_fprintf( outcome_file, "PASS;" );
                     break;
-                case TEST_RESULT_SKIPPED:
+                case MBEDTLS_TEST_RESULT_SKIPPED:
                     mbedtls_fprintf( outcome_file, "SKIP;Runtime skip" );
                     break;
                 default:
@@ -522,7 +520,7 @@
     char buf[5000];
     char *params[50];
     /* Store for proccessed integer params. */
-    int int_params[50];
+    int32_t int_params[50];
     void *pointer;
 #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
     int stdout_fd = -1;
@@ -536,6 +534,10 @@
     mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof( alloc_buf ) );
 #endif
 
+#if defined(MBEDTLS_TEST_MUTEX_USAGE)
+    mbedtls_test_mutex_usage_init( );
+#endif
+
     /*
      * The C standard doesn't guarantee that all-bits-0 is the representation
      * of a NULL pointer. We do however use that in our code for initializing
@@ -601,7 +603,7 @@
     }
 
     /* Initialize the struct that holds information about the last test */
-    memset( &test_info, 0, sizeof( test_info ) );
+    mbedtls_test_info_reset( );
 
     /* Now begin to execute the tests in the testfiles */
     for ( testfile_index = 0;
@@ -638,7 +640,8 @@
             if( ( ret = get_line( file, buf, sizeof(buf) ) ) != 0 )
                 break;
             mbedtls_fprintf( stdout, "%s%.66s",
-                    test_info.result == TEST_RESULT_FAILED ? "\n" : "", buf );
+                    mbedtls_test_info.result == MBEDTLS_TEST_RESULT_FAILED ?
+                    "\n" : "", buf );
             mbedtls_fprintf( stdout, " " );
             for( i = strlen( buf ) + 1; i < 67; i++ )
                 mbedtls_fprintf( stdout, "." );
@@ -682,8 +685,7 @@
             // If there are no unmet dependencies execute the test
             if( unmet_dep_count == 0 )
             {
-                test_info.result = TEST_RESULT_SUCCESS;
-                test_info.step = (unsigned long)( -1 );
+                mbedtls_test_info_reset( );
 
 #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
                 /* Suppress all output from the library unless we're verbose
@@ -723,7 +725,7 @@
             write_outcome_result( outcome_file,
                                   unmet_dep_count, unmet_dependencies,
                                   missing_unmet_dependencies,
-                                  ret, &test_info );
+                                  ret, &mbedtls_test_info );
             if( unmet_dep_count > 0 || ret == DISPATCH_UNSUPPORTED_SUITE )
             {
                 total_skipped++;
@@ -753,11 +755,11 @@
             }
             else if( ret == DISPATCH_TEST_SUCCESS )
             {
-                if( test_info.result == TEST_RESULT_SUCCESS )
+                if( mbedtls_test_info.result == MBEDTLS_TEST_RESULT_SUCCESS )
                 {
                     mbedtls_fprintf( stdout, "PASS\n" );
                 }
-                else if( test_info.result == TEST_RESULT_SKIPPED )
+                else if( mbedtls_test_info.result == MBEDTLS_TEST_RESULT_SKIPPED )
                 {
                     mbedtls_fprintf( stdout, "----\n" );
                     total_skipped++;
@@ -767,14 +769,21 @@
                     total_errors++;
                     mbedtls_fprintf( stdout, "FAILED\n" );
                     mbedtls_fprintf( stdout, "  %s\n  at ",
-                                     test_info.test );
-                    if( test_info.step != (unsigned long)( -1 ) )
+                                     mbedtls_test_info.test );
+                    if( mbedtls_test_info.step != (unsigned long)( -1 ) )
                     {
                         mbedtls_fprintf( stdout, "step %lu, ",
-                                         test_info.step );
+                                         mbedtls_test_info.step );
                     }
                     mbedtls_fprintf( stdout, "line %d, %s",
-                                     test_info.line_no, test_info.filename );
+                                     mbedtls_test_info.line_no,
+                                     mbedtls_test_info.filename );
+                    if( mbedtls_test_info.line1[0] != 0 )
+                        mbedtls_fprintf( stdout, "\n  %s",
+                                         mbedtls_test_info.line1 );
+                    if( mbedtls_test_info.line2[0] != 0 )
+                        mbedtls_fprintf( stdout, "\n  %s",
+                                         mbedtls_test_info.line2 );
                 }
                 fflush( stdout );
             }
diff --git a/third_party/mbedtls/repo/tests/suites/main_test.function b/third_party/mbedtls/repo/tests/suites/main_test.function
index 256224e..ac00f45 100644
--- a/third_party/mbedtls/repo/tests/suites/main_test.function
+++ b/third_party/mbedtls/repo/tests/suites/main_test.function
@@ -33,6 +33,10 @@
 #include "psa/crypto.h"
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
+#if defined(MBEDTLS_TEST_HOOKS)
+#include "mbedtls/error.h"
+#endif
+
 /* Test code may use deprecated identifiers only if the preprocessor symbol
  * MBEDTLS_TEST_DEPRECATED is defined. When building tests, set
  * MBEDTLS_TEST_DEPRECATED explicitly if MBEDTLS_DEPRECATED_WARNING is
@@ -105,7 +109,7 @@
  *              Identifiers and check code is generated by script:
  *              $generator_script
  *
- * \param exp_id    Dependency identifier.
+ * \param dep_id    Dependency identifier.
  *
  * \return       DEPENDENCY_SUPPORTED if set else DEPENDENCY_NOT_SUPPORTED
  */
@@ -129,13 +133,17 @@
 /**
  * \brief       Function pointer type for test function wrappers.
  *
+ * A test function wrapper decodes the parameters and passes them to the
+ * underlying test function. Both the wrapper and the underlying function
+ * return void. Test wrappers assume that they are passed a suitable
+ * parameter array and do not perform any error detection.
  *
- * \param void **   Pointer to void pointers. Represents an array of test
- *                  function parameters.
- *
- * \return       void
+ * \param param_array   The array of parameters. Each element is a `void *`
+ *                      which the wrapper casts to the correct type and
+ *                      dereferences. Each wrapper function hard-codes the
+ *                      number and types of the parameters.
  */
-typedef void (*TestWrapper_t)( void ** );
+typedef void (*TestWrapper_t)( void **param_array );
 
 
 /**
@@ -158,12 +166,16 @@
  *               parameter failure callback, to be used. Calls to setjmp()
  *               can invalidate the state of any local auto variables.
  *
- * \param fp     Function pointer to the test function
- * \param params Parameters to pass
+ * \param fp     Function pointer to the test function.
+ * \param params Parameters to pass to the #TestWrapper_t wrapper function.
  *
  */
 void execute_function_ptr(TestWrapper_t fp, void **params)
 {
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+    mbedtls_test_enable_insecure_external_rng( );
+#endif
+
 #if defined(MBEDTLS_CHECK_PARAMS)
     mbedtls_test_param_failed_location_record_t location_record;
 
@@ -175,22 +187,27 @@
     {
         /* Unexpected parameter validation error */
         mbedtls_test_param_failed_get_location_record( &location_record );
-        test_fail( location_record.failure_condition,
-                   location_record.line,
-                   location_record.file );
-        test_info.result = TEST_RESULT_FAILED;
+        mbedtls_test_fail( location_record.failure_condition,
+                           location_record.line,
+                           location_record.file );
     }
 
     mbedtls_test_param_failed_reset_state( );
 #else
     fp( params );
 #endif
+
+#if defined(MBEDTLS_TEST_MUTEX_USAGE)
+    mbedtls_test_mutex_usage_check( );
+#endif /* MBEDTLS_TEST_MUTEX_USAGE */
 }
 
 /**
  * \brief        Dispatches test functions based on function index.
  *
- * \param exp_id    Test function index.
+ * \param func_idx    Test function index.
+ * \param params      The array of parameters to pass to the test function.
+ *                    It will be decoded by the #TestWrapper_t wrapper function.
  *
  * \return       DISPATCH_TEST_SUCCESS if found
  *               DISPATCH_TEST_FN_NOT_FOUND if not found
@@ -219,9 +236,10 @@
 
 
 /**
- * \brief       Checks if test function is supported
+ * \brief       Checks if test function is supported in this build-time
+ *              configuration.
  *
- * \param exp_id    Test function index.
+ * \param func_idx    Test function index.
  *
  * \return       DISPATCH_TEST_SUCCESS if found
  *               DISPATCH_TEST_FN_NOT_FOUND if not found
@@ -265,6 +283,10 @@
  */
 int main( int argc, const char *argv[] )
 {
+#if defined(MBEDTLS_TEST_HOOKS) && defined (MBEDTLS_ERROR_C)
+    mbedtls_test_hook_error_add = &mbedtls_test_err_add_check;
+#endif
+
     int ret = mbedtls_test_platform_setup();
     if( ret != 0 )
     {
diff --git a/third_party/mbedtls/repo/tests/suites/target_test.function b/third_party/mbedtls/repo/tests/suites/target_test.function
deleted file mode 100644
index 8354b96..0000000
--- a/third_party/mbedtls/repo/tests/suites/target_test.function
+++ /dev/null
@@ -1,450 +0,0 @@
-#line 2 "suites/target_test.function"
-
-#include "greentea-client/test_env.h"
-
-/**
- * \brief       Increments pointer and asserts that it does not overflow.
- *
- * \param p     Pointer to byte array
- * \param start Pointer to start of byte array
- * \param len   Length of byte array
- * \param step  Increment size
- *
- */
-#define INCR_ASSERT(p, start, len, step) do                     \
-{                                                               \
-    TEST_HELPER_ASSERT( ( p ) >= ( start ) );                               \
-    TEST_HELPER_ASSERT( sizeof( *( p ) ) == sizeof( *( start ) ) );         \
-    /* <= is checked to support use inside a loop where         \
-       pointer is incremented after reading data.       */      \
-    TEST_HELPER_ASSERT( (uint32_t)( ( ( p ) - ( start ) ) + ( step ) ) <= ( len ) );\
-    ( p ) += ( step );                                          \
-}                                                               \
-while( 0 )
-
-
-/**
- * \brief       4 byte align unsigned char pointer
- *
- * \param p     Pointer to byte array
- * \param start Pointer to start of byte array
- * \param len   Length of byte array
- *
- */
-#define ALIGN_32BIT(p, start, len) do               \
-{                                                   \
-    uint32_t align = ( - (uintptr_t)( p ) ) % 4;    \
-    INCR_ASSERT( ( p ), ( start ), ( len ), align );\
-}                                                   \
-while( 0 )
-
-
-/**
- * \brief       Verify dependencies. Dependency identifiers are
- *              encoded in the buffer as 8 bit unsigned integers.
- *
- * \param count     Number of dependencies.
- * \param dep_p     Pointer to buffer.
- *
- * \return          DEPENDENCY_SUPPORTED if success else DEPENDENCY_NOT_SUPPORTED.
- */
-int verify_dependencies( uint8_t count, uint8_t * dep_p )
-{
-    uint8_t i;
-    for ( i = 0; i < count; i++ )
-    {
-        if ( dep_check( (int)(dep_p[i]) ) != DEPENDENCY_SUPPORTED )
-            return( DEPENDENCY_NOT_SUPPORTED );
-    }
-    return( DEPENDENCY_SUPPORTED );
-}
-
-/**
- * \brief       Receives hex string on serial interface, and converts to a byte.
- *
- * \param none
- *
- * \return      unsigned int8
- */
-uint8_t receive_byte()
-{
-    uint8_t byte;
-    uint8_t c[3];
-    size_t len;
-
-    c[0] = greentea_getc();
-    c[1] = greentea_getc();
-    c[2] = '\0';
-
-    TEST_HELPER_ASSERT( mbedtls_test_unhexify( &byte, sizeof( byte ),
-                                               c, &len ) == 0 );
-    TEST_HELPER_ASSERT( len != 2 );
-
-    return( byte );
-}
-
-/**
- * \brief       Receives unsigned integer on serial interface.
- *              Integers are encoded in network order, and sent as hex ascii string.
- *
- * \param none
- *
- * \return      unsigned int
- */
-uint32_t receive_uint32()
-{
-    uint32_t value;
-    size_t len;
-    const uint8_t c_be[8] = { greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc()
-                             };
-    const uint8_t c[9] = { c_be[6], c_be[7], c_be[4], c_be[5], c_be[2],
-                           c_be[3], c_be[0], c_be[1], '\0' };
-
-    TEST_HELPER_ASSERT( mbedtls_test_unhexify( (uint8_t*)&value, sizeof( value ),
-                                               c, &len ) == 0 );
-    TEST_HELPER_ASSERT( len != 8 );
-
-    return( value );
-}
-
-/**
- * \brief       Parses out an unsigned 32 int value from the byte array.
- *              Integers are encoded in network order.
- *
- * \param p     Pointer to byte array
- *
- * \return      unsigned int
- */
-uint32_t parse_uint32( uint8_t * p )
-{
-    uint32_t value;
-    value =  *p++ << 24;
-    value |= *p++ << 16;
-    value |= *p++ << 8;
-    value |= *p;
-    return( value );
-}
-
-
-/**
- * \brief       Receives test data on serial as greentea key,value pair:
- *              {{<length>;<byte array>}}
- *
- * \param data_len  Out pointer to hold received data length.
- *
- * \return      Byte array.
- */
-uint8_t * receive_data( uint32_t * data_len )
-{
-    uint32_t i = 0, errors = 0;
-    char c;
-    uint8_t * data = NULL;
-
-    /* Read opening braces */
-    i = 0;
-    while ( i < 2 )
-    {
-        c = greentea_getc();
-        /* Ignore any prevous CR LF characters */
-        if ( c == '\n' || c == '\r' )
-            continue;
-        i++;
-        if ( c != '{' )
-            return( NULL );
-    }
-
-    /* Read data length */
-    *data_len = receive_uint32();
-    data = (uint8_t *)malloc( *data_len );
-    TEST_HELPER_ASSERT( data != NULL );
-
-    greentea_getc(); // read ';' received after key i.e. *data_len
-
-    for( i = 0; i < *data_len; i++ )
-        data[i] = receive_byte();
-
-    /* Read closing braces */
-    for( i = 0; i < 2; i++ )
-    {
-        c = greentea_getc();
-        if ( c != '}' )
-        {
-            errors++;
-            break;
-        }
-    }
-
-    if ( errors )
-    {
-        free( data );
-        data = NULL;
-        *data_len = 0;
-    }
-
-    return( data );
-}
-
-/**
- * \brief       Parse the received byte array and count the number of arguments
- *              to the test function passed as type hex.
- *
- * \param count     Parameter count
- * \param data      Received Byte array
- * \param data_len  Byte array length
- *
- * \return      count of hex params
- */
-uint32_t find_hex_count( uint8_t count, uint8_t * data, uint32_t data_len )
-{
-    uint32_t i = 0, sz = 0;
-    char c;
-    uint8_t * p = NULL;
-    uint32_t hex_count = 0;
-
-    p = data;
-
-    for( i = 0; i < count; i++ )
-    {
-        c = (char)*p;
-        INCR_ASSERT( p, data, data_len, 1 );
-
-        /* Align p to 4 bytes for int, expression, string len or hex length */
-        ALIGN_32BIT( p, data, data_len );
-
-        /* Network to host conversion */
-        sz = (int32_t)parse_uint32( p );
-
-        INCR_ASSERT( p, data, data_len, sizeof( int32_t ) );
-
-        if ( c == 'H' || c == 'S' )
-        {
-            INCR_ASSERT( p, data, data_len, sz );
-            hex_count += ( c == 'H' )?1:0;
-        }
-    }
-
-    return( hex_count );
-}
-
-/**
- * \brief       Parses received byte array for test parameters.
- *
- * \param count     Parameter count
- * \param data      Received Byte array
- * \param data_len  Byte array length
- * \param error     Parsing error out variable.
- *
- * \return      Array of parsed parameters allocated on heap.
- *              Note: Caller has the responsibility to delete
- *                    the memory after use.
- */
-void ** parse_parameters( uint8_t count, uint8_t * data, uint32_t data_len,
-                          int * error )
-{
-    uint32_t i = 0, hex_count = 0;
-    char c;
-    void ** params = NULL;
-    void ** cur = NULL;
-    uint8_t * p = NULL;
-
-    hex_count = find_hex_count(count, data, data_len);
-
-    params = (void **)malloc( sizeof( void *) * ( count + hex_count ) );
-    TEST_HELPER_ASSERT( params != NULL );
-    cur = params;
-
-    p = data;
-
-    /* Parameters */
-    for( i = 0; i < count; i++ )
-    {
-        c = (char)*p;
-        INCR_ASSERT( p, data, data_len, 1 );
-
-        /* Align p to 4 bytes for int, expression, string len or hex length */
-        ALIGN_32BIT( p, data, data_len );
-
-        /* Network to host conversion */
-        *( (int32_t *)p ) = (int32_t)parse_uint32( p );
-
-        switch( c )
-        {
-            case 'E':
-                {
-                    if ( get_expression( *( (int32_t *)p ), (int32_t *)p ) )
-                    {
-                        *error = KEY_VALUE_MAPPING_NOT_FOUND;
-                        goto exit;
-                    }
-                } /* Intentional fall through */
-            case 'I':
-                {
-                    *cur++ = (void *)p;
-                    INCR_ASSERT( p, data, data_len, sizeof( int32_t ) );
-                }
-                break;
-            case 'H': /* Intentional fall through */
-            case 'S':
-                {
-                    uint32_t * sz = (uint32_t *)p;
-                    INCR_ASSERT( p, data, data_len, sizeof( int32_t ) );
-                    *cur++ = (void *)p;
-                    if ( c == 'H' )
-                        *cur++ = (void *)sz;
-                    INCR_ASSERT( p, data, data_len, ( *sz ) );
-                }
-                break;
-            default:
-                    {
-                        *error = DISPATCH_INVALID_TEST_DATA;
-                        goto exit;
-                    }
-                break;
-        }
-    }
-
-exit:
-    if ( *error )
-    {
-        free( params );
-        params = NULL;
-    }
-
-    return( params );
-}
-
-/**
- * \brief       Sends greentea key and int value pair to host.
- *
- * \param key   key string
- * \param value integer value
- *
- * \return      void
- */
-void send_key_integer( char * key, int value )
-{
-    char str[50];
-    snprintf( str, sizeof( str ), "%d", value );
-    greentea_send_kv( key, str );
-}
-
-/**
- * \brief       Sends test setup failure to the host.
- *
- * \param failure   Test set failure
- *
- * \return      void
- */
-void send_failure( int failure )
-{
-    send_key_integer( "F", failure );
-}
-
-/**
- * \brief       Sends test status to the host.
- *
- * \param status    Test status (PASS=0/FAIL=!0)
- *
- * \return      void
- */
-void send_status( int status )
-{
-    send_key_integer( "R", status );
-}
-
-
-/**
- * \brief       Embedded implementation of execute_tests().
- *              Ignores command line and received test data
- *              on serial.
- *
- * \param argc  not used
- * \param argv  not used
- *
- * \return      Program exit status.
- */
-int execute_tests( int args, const char ** argv )
-{
-    int ret = 0;
-    uint32_t data_len = 0;
-    uint8_t count = 0, function_id;
-    void ** params = NULL;
-    uint8_t * data = NULL, * p = NULL;
-
-    GREENTEA_SETUP( 800, "mbedtls_test" );
-    greentea_send_kv( "GO", " " );
-
-    while ( 1 )
-    {
-        ret = 0;
-        test_info.result = TEST_RESULT_SUCCESS;
-        test_info.step = (unsigned long)( -1 );
-        data_len = 0;
-
-        data = receive_data( &data_len );
-        if ( data == NULL )
-            continue;
-        p = data;
-
-        do
-        {
-            /* Read dependency count */
-            count = *p;
-            TEST_HELPER_ASSERT( count < data_len );
-            INCR_ASSERT( p, data, data_len, sizeof( uint8_t ) );
-            ret = verify_dependencies( count, p );
-            if ( ret != DEPENDENCY_SUPPORTED )
-                break;
-
-            if ( count )
-                INCR_ASSERT( p, data, data_len, count );
-
-            /* Read function id */
-            function_id = *p;
-            INCR_ASSERT( p, data, data_len, sizeof( uint8_t ) );
-            if ( ( ret = check_test( function_id ) ) != DISPATCH_TEST_SUCCESS )
-                break;
-
-            /* Read number of parameters */
-            count = *p;
-            INCR_ASSERT( p, data, data_len, sizeof( uint8_t ) );
-
-            /* Parse parameters if present */
-            if ( count )
-            {
-                params = parse_parameters( count, p, data_len - ( p - data ), &ret );
-                if ( ret )
-                    break;
-            }
-
-            ret = dispatch_test( function_id, params );
-        }
-        while ( 0 );
-
-        if ( data )
-        {
-            free( data );
-            data = NULL;
-        }
-
-        if ( params )
-        {
-            free( params );
-            params = NULL;
-        }
-
-        if ( ret )
-            send_failure( ret );
-        else
-            send_status( test_info.result );
-    }
-    return( 0 );
-}
-
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_aes.function b/third_party/mbedtls/repo/tests/suites/test_suite_aes.function
index 754a167..5a64099 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_aes.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_aes.function
@@ -67,7 +67,7 @@
 
     mbedtls_aes_init( &ctx );
 
-    mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cbc( &ctx, MBEDTLS_AES_ENCRYPT, src_str->len, iv_str->x, src_str->x, output ) == cbc_result );
     if( cbc_result == 0 )
     {
@@ -92,7 +92,7 @@
     memset(output, 0x00, 100);
     mbedtls_aes_init( &ctx );
 
-    mbedtls_aes_setkey_dec( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_dec( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cbc( &ctx, MBEDTLS_AES_DECRYPT, src_str->len, iv_str->x, src_str->x, output ) == cbc_result );
     if( cbc_result == 0)
     {
@@ -210,6 +210,8 @@
     /* Valid pointers are passed for builds with MBEDTLS_CHECK_PARAMS, as
      * otherwise we wouldn't get to the size check we're interested in. */
     TEST_ASSERT( mbedtls_aes_crypt_xts( &ctx, MBEDTLS_AES_ENCRYPT, length, data_unit, src, output ) == retval );
+exit:
+    mbedtls_aes_xts_free( &ctx );
 }
 /* END_CASE */
 
@@ -242,7 +244,7 @@
     mbedtls_aes_init( &ctx );
 
 
-    mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cfb128( &ctx, MBEDTLS_AES_ENCRYPT, 16, &iv_offset, iv_str->x, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x, 16, dst->len ) == 0 );
@@ -264,7 +266,7 @@
     mbedtls_aes_init( &ctx );
 
 
-    mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cfb128( &ctx, MBEDTLS_AES_DECRYPT, 16, &iv_offset, iv_str->x, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x, 16, dst->len ) == 0 );
@@ -285,7 +287,7 @@
     mbedtls_aes_init( &ctx );
 
 
-    mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cfb8( &ctx, MBEDTLS_AES_ENCRYPT, src_str->len, iv_str->x, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x,
@@ -307,7 +309,7 @@
     mbedtls_aes_init( &ctx );
 
 
-    mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cfb8( &ctx, MBEDTLS_AES_DECRYPT, src_str->len, iv_str->x, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x,
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_asn1parse.function b/third_party/mbedtls/repo/tests/suites/test_suite_asn1parse.function
index 990f343..414278f 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_asn1parse.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_asn1parse.function
@@ -130,7 +130,7 @@
     size_t parsed_length;
     int ret;
 
-    test_set_step( buffer_size );
+    mbedtls_test_set_step( buffer_size );
     /* Allocate a new buffer of exactly the length to parse each time.
      * This gives memory sanitizers a chance to catch buffer overreads. */
     if( buffer_size == 0 )
@@ -198,7 +198,7 @@
 
     TEST_ASSERT( content > state->input_start );
     offset = content - state->input_start;
-    test_set_step( offset );
+    mbedtls_test_set_step( offset );
 
     if( *rest == 0 )
         return( RET_TRAVERSE_STOP );
@@ -252,7 +252,7 @@
      */
     for( buffer_size = 1; buffer_size <= input->len + 1; buffer_size++ )
     {
-        test_set_step( buffer_size );
+        mbedtls_test_set_step( buffer_size );
         /* Allocate a new buffer of exactly the length to parse each time.
          * This gives memory sanitizers a chance to catch buffer overreads. */
         ASSERT_ALLOC( buf, buffer_size );
@@ -417,7 +417,7 @@
     }
 
 #if defined(MBEDTLS_BIGNUM_C)
-    ret = mbedtls_mpi_read_string( &expected_mpi, 16, expected_hex );
+    ret = mbedtls_test_read_mpi( &expected_mpi, 16, expected_hex );
     TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
     if( ret == MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
     {
@@ -594,6 +594,7 @@
     unsigned char *p = input->x;
     const char *rest = description;
     unsigned long n;
+    unsigned int step = 0;
 
     TEST_EQUAL( mbedtls_asn1_get_sequence_of( &p, input->x + input->len,
                                               &head, tag ),
@@ -614,7 +615,7 @@
             cur = &head;
             while( *rest )
             {
-                ++test_info.step;
+                mbedtls_test_set_step( step );
                 TEST_ASSERT( cur != NULL );
                 TEST_EQUAL( cur->buf.tag, tag );
                 n = strtoul( rest, (char **) &rest, 0 );
@@ -625,6 +626,7 @@
                 if( *rest )
                     ++rest;
                 cur = cur->next;
+                ++step;
             }
             TEST_ASSERT( cur == NULL );
         }
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_asn1write.function b/third_party/mbedtls/repo/tests/suites/test_suite_asn1write.function
index 21465c7..8824739 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_asn1write.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_asn1write.function
@@ -15,7 +15,7 @@
 
 int generic_write_start_step( generic_write_data_t *data )
 {
-    test_set_step( data->size );
+    mbedtls_test_set_step( data->size );
     ASSERT_ALLOC( data->output, data->size == 0 ? 1 : data->size );
     data->end = data->output + data->size;
     data->p = data->end;
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_base64.data b/third_party/mbedtls/repo/tests/suites/test_suite_base64.data
index da99ffa..5556668 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_base64.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_base64.data
@@ -1,3 +1,33 @@
+mask_of_range empty (1..0)
+mask_of_range:1:0
+
+mask_of_range empty (255..0)
+mask_of_range:255:0
+
+mask_of_range empty (42..7)
+mask_of_range:42:7
+
+mask_of_range 0..0
+mask_of_range:0:0
+
+mask_of_range 42..42
+mask_of_range:42:42
+
+mask_of_range 255..255
+mask_of_range:255:255
+
+mask_of_range 0..255
+mask_of_range:0:255
+
+mask_of_range 'A'..'Z'
+mask_of_range:65:90
+
+enc_char (all digits)
+enc_chars:
+
+dec_value (all characters)
+dec_chars:
+
 Test case mbedtls_base64_encode #1 buffer just right
 mbedtls_base64_encode:"":"":0:0
 
@@ -151,6 +181,20 @@
 Base64 encode hex #4
 base64_encode_hex:"01020304050607":"AQIDBAUGBw==":13:0
 
+# Rotate the bytes around so that they end up at each offset modulo 3 in
+# successive test cases.
+Base64 encode hex all valid input bytes #0
+base64_encode_hex:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==":345:0
+
+Base64 encode hex all valid input bytes #1
+base64_encode_hex:"0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff00":"AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+f4CBgoOEhYaHiImKi4yNjo+QkZKTlJWWl5iZmpucnZ6foKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vr/AwcLDxMXGx8jJysvMzc7P0NHS09TV1tfY2drb3N3e3+Dh4uPk5ebn6Onq6+zt7u/w8fLz9PX29/j5+vv8/f7/AA==":345:0
+
+Base64 encode hex all valid input bytes #2
+base64_encode_hex:"02030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff0001":"AgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVpbXF1eX2BhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gIGCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnp+goaKjpKWmp6ipqqusra6vsLGys7S1tre4ubq7vL2+v8DBwsPExcbHyMnKy8zNzs/Q0dLT1NXW19jZ2tvc3d7f4OHi4+Tl5ufo6err7O3u7/Dx8vP09fb3+Pn6+/z9/v8AAQ==":345:0
+
+Base64 encode all valid output characters at all offsets
+base64_encode_hex:"00108310518720928b30d38f41149351559761969b71d79f8218a39259a7a29aabb2dbafc31cb3d35db7e39ebbf3dfbff800420c41461c824a2cc34e3d04524d45565d865a6dc75e7e08628e49669e8a6aaecb6ebf0c72cf4d76df8e7aefcf7effe00108310518720928b30d38f41149351559761969b71d79f8218a39259a7a29aabb2dbafc31cb3d35db7e39ebbf3dfbff800420c41461c824a2cc34e3d04524d45565d865a6dc75e7e08628e49669e8a6aaecb6ebf0c72cf4d76df8e7aefcf7efd0":"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/Q":261:0
+
 Base64 decode hex #1
 base64_decode_hex:"AQIDBAUGBwgJ":"010203040506070809":9:0
 
@@ -166,6 +210,9 @@
 Base64 decode hex #5 (buffer too small)
 base64_decode_hex:"AQIDBAUGBw==":"01020304050607":6:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
 
+Base64 decode all valid input characters at all offsets
+base64_decode_hex:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/Q":"00108310518720928b30d38f41149351559761969b71d79f8218a39259a7a29aabb2dbafc31cb3d35db7e39ebbf3dfbff800420c41461c824a2cc34e3d04524d45565d865a6dc75e7e08628e49669e8a6aaecb6ebf0c72cf4d76df8e7aefcf7effe00108310518720928b30d38f41149351559761969b71d79f8218a39259a7a29aabb2dbafc31cb3d35db7e39ebbf3dfbff800420c41461c824a2cc34e3d04524d45565d865a6dc75e7e08628e49669e8a6aaecb6ebf0c72cf4d76df8e7aefcf7efd0":195:0
+
 Base64 Selftest
 depends_on:MBEDTLS_SELF_TEST
 base64_selftest:
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_base64.function b/third_party/mbedtls/repo/tests/suites/test_suite_base64.function
index dc6ec15..7baa3d5 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_base64.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_base64.function
@@ -1,5 +1,14 @@
 /* BEGIN_HEADER */
 #include "mbedtls/base64.h"
+#include "constant_time_internal.h"
+#include "constant_time_invasive.h"
+#include <test/constant_flow.h>
+
+#if defined(MBEDTLS_TEST_HOOKS)
+static const char base64_digits[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+#endif /* MBEDTLS_TEST_HOOKS */
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -7,19 +16,87 @@
  * END_DEPENDENCIES
  */
 
+/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
+void mask_of_range( int low_arg, int high_arg )
+{
+    unsigned char low = low_arg, high = high_arg;
+    unsigned c;
+    for( c = 0; c <= 0xff; c++ )
+    {
+        mbedtls_test_set_step( c );
+        TEST_CF_SECRET( &c, sizeof( c ) );
+        unsigned char m = mbedtls_ct_uchar_mask_of_range( low, high, c );
+        TEST_CF_PUBLIC( &c, sizeof( c ) );
+        TEST_CF_PUBLIC( &m, sizeof( m ) );
+        if( low <= c && c <= high )
+            TEST_EQUAL( m, 0xff );
+        else
+            TEST_EQUAL( m, 0 );
+    }
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
+void enc_chars( )
+{
+    for( unsigned value = 0; value < 64; value++ )
+    {
+        mbedtls_test_set_step( value );
+        TEST_CF_SECRET( &value, sizeof( value ) );
+        unsigned char digit = mbedtls_ct_base64_enc_char( value );
+        TEST_CF_PUBLIC( &value, sizeof( value ) );
+        TEST_CF_PUBLIC( &digit, sizeof( digit ) );
+        TEST_EQUAL( digit, base64_digits[value] );
+    }
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
+void dec_chars( )
+{
+    char *p;
+    signed char expected;
+
+    for( unsigned c = 0; c <= 0xff; c++ )
+    {
+        mbedtls_test_set_step( c );
+        /* base64_digits is 0-terminated. sizeof()-1 excludes the trailing 0. */
+        p = memchr( base64_digits, c, sizeof( base64_digits ) - 1 );
+        if( p == NULL )
+            expected = -1;
+        else
+            expected = p - base64_digits;
+        TEST_CF_SECRET( &c, sizeof( c ) );
+        signed char actual = mbedtls_ct_base64_dec_value( c );
+        TEST_CF_PUBLIC( &c, sizeof( c ) );
+        TEST_CF_PUBLIC( &actual, sizeof( actual ) );
+        TEST_EQUAL( actual, expected );
+    }
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void mbedtls_base64_encode( char * src_string, char * dst_string,
                             int dst_buf_size, int result )
 {
     unsigned char src_str[1000];
     unsigned char dst_str[1000];
-    size_t len;
+    size_t len, src_len;
 
     memset(src_str, 0x00, 1000);
     memset(dst_str, 0x00, 1000);
 
     strncpy( (char *) src_str, src_string, sizeof(src_str) - 1 );
-    TEST_ASSERT( mbedtls_base64_encode( dst_str, dst_buf_size, &len, src_str, strlen( (char *) src_str ) ) == result );
+    src_len = strlen( (char *) src_str );
+
+    TEST_CF_SECRET( src_str, sizeof( src_str ) );
+    TEST_ASSERT( mbedtls_base64_encode( dst_str, dst_buf_size, &len, src_str, src_len) == result );
+    TEST_CF_PUBLIC( src_str, sizeof( src_str ) );
+
+    /* dest_str will have had tainted data copied to it, prevent the TEST_ASSERT below from triggering
+       CF failures by unmarking it. */
+    TEST_CF_PUBLIC( dst_str, len );
+
     if( result == 0 )
     {
         TEST_ASSERT( strcmp( (char *) dst_str, dst_string ) == 0 );
@@ -57,7 +134,14 @@
 
     res = mbedtls_test_zero_alloc( dst_buf_size );
 
+    TEST_CF_SECRET( src->x, src->len );
     TEST_ASSERT( mbedtls_base64_encode( res, dst_buf_size, &len, src->x, src->len ) == result );
+    TEST_CF_PUBLIC( src->x, src->len );
+
+    /* res will have had tainted data copied to it, prevent the TEST_ASSERT below from triggering
+       CF failures by unmarking it. */
+    TEST_CF_PUBLIC( res, len );
+
     if( result == 0 )
     {
         TEST_ASSERT( len == strlen( dst ) );
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_ccm.function b/third_party/mbedtls/repo/tests/suites/test_suite_ccm.function
index faa7e13..5a3726e 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_ccm.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_ccm.function
@@ -201,12 +201,11 @@
     unsigned char iv[13];
     unsigned char result[50];
     mbedtls_ccm_context ctx;
-    size_t i, iv_len, tag_len;
+    size_t iv_len, tag_len;
     int ret;
 
     mbedtls_ccm_init( &ctx );
 
-    memset( iv, 0x00, sizeof( iv ) );
     memset( result, 0x00, sizeof( result ) );
 
     if( sec_level % 4 == 0)
@@ -214,12 +213,10 @@
     else
         tag_len = 1 << ( sec_level % 4 + 1);
 
-    for( i = 0; i < source_address->len; i++ )
-        iv[i] = source_address->x[i];
-
-    for( i = 0; i < frame_counter->len; i++ )
-        iv[source_address->len + i] = frame_counter->x[i];
-
+    TEST_ASSERT( source_address->len == 8 );
+    TEST_ASSERT( frame_counter->len == 4 );
+    memcpy( iv, source_address->x, source_address->len );
+    memcpy( iv + source_address->len, frame_counter->x, frame_counter->len );
     iv[source_address->len + frame_counter->len] = sec_level;
     iv_len = sizeof( iv );
 
@@ -254,7 +251,7 @@
     unsigned char iv[13];
     unsigned char result[50];
     mbedtls_ccm_context ctx;
-    size_t i, iv_len, tag_len;
+    size_t iv_len, tag_len;
     int ret;
 
     mbedtls_ccm_init( &ctx );
@@ -267,12 +264,10 @@
     else
         tag_len = 1 << ( sec_level % 4 + 1);
 
-    for( i = 0; i < source_address->len; i++ )
-        iv[i] = source_address->x[i];
-
-    for( i = 0; i < frame_counter->len; i++ )
-        iv[source_address->len + i] = frame_counter->x[i];
-
+    TEST_ASSERT( source_address->len == 8 );
+    TEST_ASSERT( frame_counter->len == 4 );
+    memcpy( iv, source_address->x, source_address->len );
+    memcpy( iv + source_address->len, frame_counter->x, frame_counter->len );
     iv[source_address->len + frame_counter->len] = sec_level;
     iv_len = sizeof( iv );
 
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_cipher.aes.data b/third_party/mbedtls/repo/tests/suites/test_suite_cipher.aes.data
index 4dbdd52..c8fbca2 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_cipher.aes.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_cipher.aes.data
@@ -1798,6 +1798,102 @@
 depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
 test_vec_crypt:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_DECRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"5c9d844ed46f9885085e5d6a4f94c7d7":"014730f80ac625fe84f026c60bfd547d":0:1
 
+AES-128-ECB crypt Encrypt NIST KAT #1 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_ENCRYPT:"00000000000000000000000000000000":"":"80000000000000000000000000000000":"3ad78e726c1ec02b7ebfe92b23d9ec34":0:1
+
+AES-128-ECB crypt Encrypt NIST KAT #2 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_ENCRYPT:"ffffffffffffffffffffffffffffe000":"":"00000000000000000000000000000000":"323994cfb9da285a5d9642e1759b224a":0:1
+
+AES-128-ECB crypt Encrypt NIST KAT #3 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_ENCRYPT:"10a58869d74be5a374cf867cfb473859":"":"00000000000000000000000000000000":"6d251e6944b051e04eaa6fb4dbf78465":0:1
+
+AES-128-ECB crypt Encrypt NIST KAT #4 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_ENCRYPT:"00000000000000000000000000000000":"":"f34481ec3cc627bacd5dc3fb08f273e6":"0336763e966d92595a567cc9ce537f5e":0:1
+
+AES-128-ECB crypt Decrypt NIST KAT #1 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_DECRYPT:"00000000000000000000000000000000":"":"3ad78e726c1ec02b7ebfe92b23d9ec34":"80000000000000000000000000000000":0:1
+
+AES-128-ECB crypt Decrypt NIST KAT #2 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_DECRYPT:"ffffc000000000000000000000000000":"":"df556a33438db87bc41b1752c55e5e49":"00000000000000000000000000000000":0:1
+
+AES-128-ECB crypt Decrypt NIST KAT #3 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_DECRYPT:"10a58869d74be5a374cf867cfb473859":"":"6d251e6944b051e04eaa6fb4dbf78465":"00000000000000000000000000000000":0:1
+
+AES-128-ECB crypt Decrypt NIST KAT #4 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_DECRYPT:"00000000000000000000000000000000":"":"0336763e966d92595a567cc9ce537f5e":"f34481ec3cc627bacd5dc3fb08f273e6":0:1
+
+AES-192-ECB crypt Encrypt NIST KAT #1 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_ENCRYPT:"000000000000000000000000000000000000000000000000":"":"80000000000000000000000000000000":"6cd02513e8d4dc986b4afe087a60bd0c":0:1
+
+AES-192-ECB crypt Encrypt NIST KAT #2 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_ENCRYPT:"ff0000000000000000000000000000000000000000000000":"":"00000000000000000000000000000000":"833f71258d53036b02952c76c744f5a1":0:1
+
+AES-192-ECB crypt Encrypt NIST KAT #3 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_ENCRYPT:"e9f065d7c13573587f7875357dfbb16c53489f6a4bd0f7cd":"":"00000000000000000000000000000000":"0956259c9cd5cfd0181cca53380cde06":0:1
+
+AES-192-ECB crypt Encrypt NIST KAT #4 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_ENCRYPT:"000000000000000000000000000000000000000000000000":"":"1b077a6af4b7f98229de786d7516b639":"275cfc0413d8ccb70513c3859b1d0f72":0:1
+
+AES-192-ECB crypt Decrypt NIST KAT #1 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_DECRYPT:"000000000000000000000000000000000000000000000000":"":"6cd02513e8d4dc986b4afe087a60bd0c":"80000000000000000000000000000000":0:1
+
+AES-192-ECB crypt Decrypt NIST KAT #2 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_DECRYPT:"ffe000000000000000000000000000000000000000000000":"":"7ababc4b3f516c9aafb35f4140b548f9":"00000000000000000000000000000000":0:1
+
+AES-192-ECB crypt Decrypt NIST KAT #3 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_DECRYPT:"e9f065d7c13573587f7875357dfbb16c53489f6a4bd0f7cd":"":"0956259c9cd5cfd0181cca53380cde06":"00000000000000000000000000000000":0:1
+
+AES-192-ECB crypt Decrypt NIST KAT #4 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_DECRYPT:"000000000000000000000000000000000000000000000000":"":"275cfc0413d8ccb70513c3859b1d0f72":"1b077a6af4b7f98229de786d7516b639":0:1
+
+AES-256-ECB crypt Encrypt NIST KAT #1 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_ENCRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"":"80000000000000000000000000000000":"ddc6bf790c15760d8d9aeb6f9a75fd4e":0:1
+
+AES-256-ECB crypt Encrypt NIST KAT #2 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_ENCRYPT:"ff00000000000000000000000000000000000000000000000000000000000000":"":"00000000000000000000000000000000":"ec52a212f80a09df6317021bc2a9819e":0:1
+
+AES-256-ECB crypt Encrypt NIST KAT #3 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_ENCRYPT:"c47b0294dbbbee0fec4757f22ffeee3587ca4730c3d33b691df38bab076bc558":"":"00000000000000000000000000000000":"46f2fb342d6f0ab477476fc501242c5f":0:1
+
+AES-256-ECB crypt Encrypt NIST KAT #4 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_ENCRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"":"014730f80ac625fe84f026c60bfd547d":"5c9d844ed46f9885085e5d6a4f94c7d7":0:1
+
+AES-256-ECB crypt Decrypt NIST KAT #1 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_DECRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"":"ddc6bf790c15760d8d9aeb6f9a75fd4e":"80000000000000000000000000000000":0:1
+
+AES-256-ECB crypt Decrypt NIST KAT #2 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_DECRYPT:"ffe0000000000000000000000000000000000000000000000000000000000000":"":"d1ccb9b1337002cbac42c520b5d67722":"00000000000000000000000000000000":0:1
+
+AES-256-ECB crypt Decrypt NIST KAT #3 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_DECRYPT:"c47b0294dbbbee0fec4757f22ffeee3587ca4730c3d33b691df38bab076bc558":"":"46f2fb342d6f0ab477476fc501242c5f":"00000000000000000000000000000000":0:1
+
+AES-256-ECB crypt Decrypt NIST KAT #4 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_DECRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"":"5c9d844ed46f9885085e5d6a4f94c7d7":"014730f80ac625fe84f026c60bfd547d":0:1
+
 Cipher Corner Case behaviours
 depends_on:MBEDTLS_AES_C
 cipher_special_behaviours:
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_cipher.function b/third_party/mbedtls/repo/tests/suites/test_suite_cipher.function
index 1d98f3d..b0b1629 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_cipher.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_cipher.function
@@ -9,10 +9,6 @@
 #include "mbedtls/gcm.h"
 #endif
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-#include "test/psa_crypto_helpers.h"
-#endif
-
 #if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C)
 #define MBEDTLS_CIPHER_AUTH_CRYPT
 #endif
@@ -106,9 +102,10 @@
     (void)valid_mode; /* In some configurations this is unused */
 
     mbedtls_cipher_init( &valid_ctx );
-    mbedtls_cipher_setup( &valid_ctx, valid_info );
     mbedtls_cipher_init( &invalid_ctx );
 
+    TEST_ASSERT( mbedtls_cipher_setup( &valid_ctx, valid_info ) == 0 );
+
     /* mbedtls_cipher_setup() */
     TEST_ASSERT( mbedtls_cipher_setup( &valid_ctx, NULL ) ==
                  MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_debug.data b/third_party/mbedtls/repo/tests/suites/test_suite_debug.data
index eb99b79..6d57442 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_debug.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_debug.data
@@ -37,6 +37,27 @@
 Debug print buffer #5
 mbedtls_debug_print_buf:"MyFile":999:"Test return value":"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30":"MyFile(0999)\: dumping 'Test return value' (49 bytes)\nMyFile(0999)\: 0000\:  00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f  ................\nMyFile(0999)\: 0010\:  10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f  ................\nMyFile(0999)\: 0020\:  20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f   !"#$%&'()*+,-./\nMyFile(0999)\: 0030\:  30                                               0\n"
 
+Debug print mbedtls_mpi: 0 (empty representation)
+mbedtls_debug_print_mpi:16:"":"MyFile":999:"VALUE":"MyFile(0999)\: value of 'VALUE' (0 bits) is\:\nMyFile(0999)\:  00\n"
+
+Debug print mbedtls_mpi: 0 (non-empty representation)
+mbedtls_debug_print_mpi:16:"00000000000000":"MyFile":999:"VALUE":"MyFile(0999)\: value of 'VALUE' (0 bits) is\:\nMyFile(0999)\:  00\n"
+
+Debug print mbedtls_mpi #2: 3 bits
+mbedtls_debug_print_mpi:16:"00000000000007":"MyFile":999:"VALUE":"MyFile(0999)\: value of 'VALUE' (3 bits) is\:\nMyFile(0999)\:  07\n"
+
+Debug print mbedtls_mpi: 49 bits
+mbedtls_debug_print_mpi:16:"01020304050607":"MyFile":999:"VALUE":"MyFile(0999)\: value of 'VALUE' (49 bits) is\:\nMyFile(0999)\:  01 02 03 04 05 06 07\n"
+
+Debug print mbedtls_mpi: 759 bits
+mbedtls_debug_print_mpi:16:"0000000000000000000000000000000000000000000000000000000041379d00fed1491fe15df284dfde4a142f68aa8d412023195cee66883e6290ffe703f4ea5963bf212713cee46b107c09182b5edcd955adac418bf4918e2889af48e1099d513830cec85c26ac1e158b52620e33ba8692f893efbb2f958b4424":"MyFile":999:"VALUE":"MyFile(0999)\: value of 'VALUE' (759 bits) is\:\nMyFile(0999)\:  41 37 9d 00 fe d1 49 1f e1 5d f2 84 df de 4a 14\nMyFile(0999)\:  2f 68 aa 8d 41 20 23 19 5c ee 66 88 3e 62 90 ff\nMyFile(0999)\:  e7 03 f4 ea 59 63 bf 21 27 13 ce e4 6b 10 7c 09\nMyFile(0999)\:  18 2b 5e dc d9 55 ad ac 41 8b f4 91 8e 28 89 af\nMyFile(0999)\:  48 e1 09 9d 51 38 30 ce c8 5c 26 ac 1e 15 8b 52\nMyFile(0999)\:  62 0e 33 ba 86 92 f8 93 ef bb 2f 95 8b 44 24\n"
+
+Debug print mbedtls_mpi: 764 bits #1
+mbedtls_debug_print_mpi:16:"0941379d00fed1491fe15df284dfde4a142f68aa8d412023195cee66883e6290ffe703f4ea5963bf212713cee46b107c09182b5edcd955adac418bf4918e2889af48e1099d513830cec85c26ac1e158b52620e33ba8692f893efbb2f958b4424":"MyFile":999:"VALUE":"MyFile(0999)\: value of 'VALUE' (764 bits) is\:\nMyFile(0999)\:  09 41 37 9d 00 fe d1 49 1f e1 5d f2 84 df de 4a\nMyFile(0999)\:  14 2f 68 aa 8d 41 20 23 19 5c ee 66 88 3e 62 90\nMyFile(0999)\:  ff e7 03 f4 ea 59 63 bf 21 27 13 ce e4 6b 10 7c\nMyFile(0999)\:  09 18 2b 5e dc d9 55 ad ac 41 8b f4 91 8e 28 89\nMyFile(0999)\:  af 48 e1 09 9d 51 38 30 ce c8 5c 26 ac 1e 15 8b\nMyFile(0999)\:  52 62 0e 33 ba 86 92 f8 93 ef bb 2f 95 8b 44 24\n"
+
+Debug print mbedtls_mpi: 764 bits #2
+mbedtls_debug_print_mpi:16:"0000000000000000000000000000000000000000000000000000000941379d00fed1491fe15df284dfde4a142f68aa8d412023195cee66883e6290ffe703f4ea5963bf212713cee46b107c09182b5edcd955adac418bf4918e2889af48e1099d513830cec85c26ac1e158b52620e33ba8692f893efbb2f958b4424":"MyFile":999:"VALUE":"MyFile(0999)\: value of 'VALUE' (764 bits) is\:\nMyFile(0999)\:  09 41 37 9d 00 fe d1 49 1f e1 5d f2 84 df de 4a\nMyFile(0999)\:  14 2f 68 aa 8d 41 20 23 19 5c ee 66 88 3e 62 90\nMyFile(0999)\:  ff e7 03 f4 ea 59 63 bf 21 27 13 ce e4 6b 10 7c\nMyFile(0999)\:  09 18 2b 5e dc d9 55 ad ac 41 8b f4 91 8e 28 89\nMyFile(0999)\:  af 48 e1 09 9d 51 38 30 ce c8 5c 26 ac 1e 15 8b\nMyFile(0999)\:  52 62 0e 33 ba 86 92 f8 93 ef bb 2f 95 8b 44 24\n"
+
 Debug print certificate #1 (RSA)
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_BASE64_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
 mbedtls_debug_print_crt:"data_files/server1.crt":"MyFile":999:"PREFIX_":"MyFile(0999)\: PREFIX_ #1\:\nMyFile(0999)\: cert. version     \: 3\nMyFile(0999)\: serial number     \: 01\nMyFile(0999)\: issuer name       \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nMyFile(0999)\: subject name      \: C=NL, O=PolarSSL, CN=PolarSSL Server 1\nMyFile(0999)\: issued  on        \: 2019-02-10 14\:44\:06\nMyFile(0999)\: expires on        \: 2029-02-10 14\:44\:06\nMyFile(0999)\: signed using      \: RSA with SHA1\nMyFile(0999)\: RSA key size      \: 2048 bits\nMyFile(0999)\: basic constraints \: CA=false\nMyFile(0999)\: value of 'crt->rsa.N' (2048 bits) is\:\nMyFile(0999)\:  a9 02 1f 3d 40 6a d5 55 53 8b fd 36 ee 82 65 2e\nMyFile(0999)\:  15 61 5e 89 bf b8 e8 45 90 db ee 88 16 52 d3 f1\nMyFile(0999)\:  43 50 47 96 12 59 64 87 6b fd 2b e0 46 f9 73 be\nMyFile(0999)\:  dd cf 92 e1 91 5b ed 66 a0 6f 89 29 79 45 80 d0\nMyFile(0999)\:  83 6a d5 41 43 77 5f 39 7c 09 04 47 82 b0 57 39\nMyFile(0999)\:  70 ed a3 ec 15 19 1e a8 33 08 47 c1 05 42 a9 fd\nMyFile(0999)\:  4c c3 b4 df dd 06 1f 4d 10 51 40 67 73 13 0f 40\nMyFile(0999)\:  f8 6d 81 25 5f 0a b1 53 c6 30 7e 15 39 ac f9 5a\nMyFile(0999)\:  ee 7f 92 9e a6 05 5b e7 13 97 85 b5 23 92 d9 d4\nMyFile(0999)\:  24 06 d5 09 25 89 75 07 dd a6 1a 8f 3f 09 19 be\nMyFile(0999)\:  ad 65 2c 64 eb 95 9b dc fe 41 5e 17 a6 da 6c 5b\nMyFile(0999)\:  69 cc 02 ba 14 2c 16 24 9c 4a dc cd d0 f7 52 67\nMyFile(0999)\:  73 f1 2d a0 23 fd 7e f4 31 ca 2d 70 ca 89 0b 04\nMyFile(0999)\:  db 2e a6 4f 70 6e 9e ce bd 58 89 e2 53 59 9e 6e\nMyFile(0999)\:  5a 92 65 e2 88 3f 0c 94 19 a3 dd e5 e8 9d 95 13\nMyFile(0999)\:  ed 29 db ab 70 12 dc 5a ca 6b 17 ab 52 82 54 b1\nMyFile(0999)\: value of 'crt->rsa.E' (17 bits) is\:\nMyFile(0999)\:  01 00 01\n"
@@ -44,21 +65,3 @@
 Debug print certificate #2 (EC)
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_BASE64_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA256_C
 mbedtls_debug_print_crt:"data_files/test-ca2.crt":"MyFile":999:"PREFIX_":"MyFile(0999)\: PREFIX_ #1\:\nMyFile(0999)\: cert. version     \: 3\nMyFile(0999)\: serial number     \: C1\:43\:E2\:7E\:62\:43\:CC\:E8\nMyFile(0999)\: issuer name       \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nMyFile(0999)\: subject name      \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nMyFile(0999)\: issued  on        \: 2019-02-10 14\:44\:00\nMyFile(0999)\: expires on        \: 2029-02-10 14\:44\:00\nMyFile(0999)\: signed using      \: ECDSA with SHA256\nMyFile(0999)\: EC key size       \: 384 bits\nMyFile(0999)\: basic constraints \: CA=true\nMyFile(0999)\: value of 'crt->eckey.Q(X)' (384 bits) is\:\nMyFile(0999)\:  c3 da 2b 34 41 37 58 2f 87 56 fe fc 89 ba 29 43\nMyFile(0999)\:  4b 4e e0 6e c3 0e 57 53 33 39 58 d4 52 b4 91 95\nMyFile(0999)\:  39 0b 23 df 5f 17 24 62 48 fc 1a 95 29 ce 2c 2d\nMyFile(0999)\: value of 'crt->eckey.Q(Y)' (384 bits) is\:\nMyFile(0999)\:  87 c2 88 52 80 af d6 6a ab 21 dd b8 d3 1c 6e 58\nMyFile(0999)\:  b8 ca e8 b2 69 8e f3 41 ad 29 c3 b4 5f 75 a7 47\nMyFile(0999)\:  6f d5 19 29 55 69 9a 53 3b 20 b4 66 16 60 33 1e\n"
-
-Debug print mbedtls_mpi #1
-mbedtls_debug_print_mpi:16:"01020304050607":"MyFile":999:"VALUE":"MyFile(0999)\: value of 'VALUE' (49 bits) is\:\nMyFile(0999)\:  01 02 03 04 05 06 07\n"
-
-Debug print mbedtls_mpi #2
-mbedtls_debug_print_mpi:16:"00000000000007":"MyFile":999:"VALUE":"MyFile(0999)\: value of 'VALUE' (3 bits) is\:\nMyFile(0999)\:  07\n"
-
-Debug print mbedtls_mpi #3
-mbedtls_debug_print_mpi:16:"00000000000000":"MyFile":999:"VALUE":"MyFile(0999)\: value of 'VALUE' (0 bits) is\:\nMyFile(0999)\:  00\n"
-
-Debug print mbedtls_mpi #4
-mbedtls_debug_print_mpi:16:"0941379d00fed1491fe15df284dfde4a142f68aa8d412023195cee66883e6290ffe703f4ea5963bf212713cee46b107c09182b5edcd955adac418bf4918e2889af48e1099d513830cec85c26ac1e158b52620e33ba8692f893efbb2f958b4424":"MyFile":999:"VALUE":"MyFile(0999)\: value of 'VALUE' (764 bits) is\:\nMyFile(0999)\:  09 41 37 9d 00 fe d1 49 1f e1 5d f2 84 df de 4a\nMyFile(0999)\:  14 2f 68 aa 8d 41 20 23 19 5c ee 66 88 3e 62 90\nMyFile(0999)\:  ff e7 03 f4 ea 59 63 bf 21 27 13 ce e4 6b 10 7c\nMyFile(0999)\:  09 18 2b 5e dc d9 55 ad ac 41 8b f4 91 8e 28 89\nMyFile(0999)\:  af 48 e1 09 9d 51 38 30 ce c8 5c 26 ac 1e 15 8b\nMyFile(0999)\:  52 62 0e 33 ba 86 92 f8 93 ef bb 2f 95 8b 44 24\n"
-
-Debug print mbedtls_mpi #5
-mbedtls_debug_print_mpi:16:"0000000000000000000000000000000000000000000000000000000941379d00fed1491fe15df284dfde4a142f68aa8d412023195cee66883e6290ffe703f4ea5963bf212713cee46b107c09182b5edcd955adac418bf4918e2889af48e1099d513830cec85c26ac1e158b52620e33ba8692f893efbb2f958b4424":"MyFile":999:"VALUE":"MyFile(0999)\: value of 'VALUE' (764 bits) is\:\nMyFile(0999)\:  09 41 37 9d 00 fe d1 49 1f e1 5d f2 84 df de 4a\nMyFile(0999)\:  14 2f 68 aa 8d 41 20 23 19 5c ee 66 88 3e 62 90\nMyFile(0999)\:  ff e7 03 f4 ea 59 63 bf 21 27 13 ce e4 6b 10 7c\nMyFile(0999)\:  09 18 2b 5e dc d9 55 ad ac 41 8b f4 91 8e 28 89\nMyFile(0999)\:  af 48 e1 09 9d 51 38 30 ce c8 5c 26 ac 1e 15 8b\nMyFile(0999)\:  52 62 0e 33 ba 86 92 f8 93 ef bb 2f 95 8b 44 24\n"
-
-Debug print mbedtls_mpi #6
-mbedtls_debug_print_mpi:16:"0000000000000000000000000000000000000000000000000000000041379d00fed1491fe15df284dfde4a142f68aa8d412023195cee66883e6290ffe703f4ea5963bf212713cee46b107c09182b5edcd955adac418bf4918e2889af48e1099d513830cec85c26ac1e158b52620e33ba8692f893efbb2f958b4424":"MyFile":999:"VALUE":"MyFile(0999)\: value of 'VALUE' (759 bits) is\:\nMyFile(0999)\:  41 37 9d 00 fe d1 49 1f e1 5d f2 84 df de 4a 14\nMyFile(0999)\:  2f 68 aa 8d 41 20 23 19 5c ee 66 88 3e 62 90 ff\nMyFile(0999)\:  e7 03 f4 ea 59 63 bf 21 27 13 ce e4 6b 10 7c 09\nMyFile(0999)\:  18 2b 5e dc d9 55 ad ac 41 8b f4 91 8e 28 89 af\nMyFile(0999)\:  48 e1 09 9d 51 38 30 ce c8 5c 26 ac 1e 15 8b 52\nMyFile(0999)\:  62 0e 33 ba 86 92 f8 93 ef bb 2f 95 8b 44 24\n"
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_debug.function b/third_party/mbedtls/repo/tests/suites/test_suite_debug.function
index 377d630..fe5549a 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_debug.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_debug.function
@@ -179,7 +179,7 @@
 
     TEST_ASSERT( mbedtls_ssl_setup( &ssl, &conf ) == 0 );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &val, radix, value ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &val, radix, value ) == 0 );
 
     mbedtls_ssl_conf_dbg( &conf, string_debug, &buffer);
 
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_des.function b/third_party/mbedtls/repo/tests/suites/test_suite_des.function
index 5b24935..7256fb5 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_des.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_des.function
@@ -24,7 +24,7 @@
     mbedtls_des_init( &ctx );
 
 
-    mbedtls_des_setkey_enc( &ctx, key_str->x );
+    TEST_ASSERT( mbedtls_des_setkey_enc( &ctx, key_str->x ) == 0 );
     TEST_ASSERT( mbedtls_des_crypt_ecb( &ctx, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x, 8, dst->len ) == 0 );
@@ -44,7 +44,7 @@
     mbedtls_des_init( &ctx );
 
 
-    mbedtls_des_setkey_dec( &ctx, key_str->x );
+    TEST_ASSERT( mbedtls_des_setkey_dec( &ctx, key_str->x ) == 0 );
     TEST_ASSERT( mbedtls_des_crypt_ecb( &ctx, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x, 8, dst->len ) == 0 );
@@ -65,7 +65,7 @@
     mbedtls_des_init( &ctx );
 
 
-    mbedtls_des_setkey_enc( &ctx, key_str->x );
+    TEST_ASSERT( mbedtls_des_setkey_enc( &ctx, key_str->x ) == 0 );
     TEST_ASSERT( mbedtls_des_crypt_cbc( &ctx, MBEDTLS_DES_ENCRYPT, src_str->len, iv_str->x, src_str->x, output ) == cbc_result );
     if( cbc_result == 0 )
     {
@@ -91,7 +91,7 @@
     mbedtls_des_init( &ctx );
 
 
-    mbedtls_des_setkey_dec( &ctx, key_str->x );
+    TEST_ASSERT( mbedtls_des_setkey_dec( &ctx, key_str->x ) == 0 );
     TEST_ASSERT( mbedtls_des_crypt_cbc( &ctx, MBEDTLS_DES_DECRYPT, src_str->len, iv_str->x, src_str->x, output ) == cbc_result );
     if( cbc_result == 0 )
     {
@@ -117,9 +117,9 @@
 
 
     if( key_count == 2 )
-        mbedtls_des3_set2key_enc( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set2key_enc( &ctx, key_str->x ) == 0 );
     else if( key_count == 3 )
-        mbedtls_des3_set3key_enc( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set3key_enc( &ctx, key_str->x ) == 0 );
     else
         TEST_ASSERT( 0 );
 
@@ -144,9 +144,9 @@
 
 
     if( key_count == 2 )
-        mbedtls_des3_set2key_dec( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set2key_dec( &ctx, key_str->x ) == 0 );
     else if( key_count == 3 )
-        mbedtls_des3_set3key_dec( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set3key_dec( &ctx, key_str->x ) == 0 );
     else
         TEST_ASSERT( 0 );
 
@@ -172,9 +172,9 @@
 
 
     if( key_count == 2 )
-        mbedtls_des3_set2key_enc( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set2key_enc( &ctx, key_str->x ) == 0 );
     else if( key_count == 3 )
-        mbedtls_des3_set3key_enc( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set3key_enc( &ctx, key_str->x ) == 0 );
     else
         TEST_ASSERT( 0 );
 
@@ -205,9 +205,9 @@
 
 
     if( key_count == 2 )
-        mbedtls_des3_set2key_dec( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set2key_dec( &ctx, key_str->x ) == 0 );
     else if( key_count == 3 )
-        mbedtls_des3_set3key_dec( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set3key_dec( &ctx, key_str->x ) == 0 );
     else
         TEST_ASSERT( 0 );
 
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_dhm.data b/third_party/mbedtls/repo/tests/suites/test_suite_dhm.data
index c4795b6..4e13e48 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_dhm.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_dhm.data
@@ -1,26 +1,110 @@
+Diffie-Hellman full exchange: tiny x_size
+dhm_do_dhm:10:"93450983094850938450983409623":1:10:"9345098304850938450983409622":0
+
 Diffie-Hellman parameter validation
 dhm_invalid_params:
 
-Diffie-Hellman full exchange #1
-dhm_do_dhm:10:"23":10:"5":0
+Diffie-Hellman full exchange: 5-bit, x_size=3
+dhm_do_dhm:10:"23":3:10:"5":0
 
-Diffie-Hellman full exchange #2
-dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622":0
+Diffie-Hellman full exchange: 5-bit, x_size=2
+dhm_do_dhm:10:"23":2:10:"5":0
 
-Diffie-Hellman full exchange #3
-dhm_do_dhm:10:"93450983094850938450983409623982317398171298719873918739182739712938719287391879381271":10:"9345098309485093845098340962223981329819812792137312973297123912791271":0
+## Repeat this test case and a few similar ones several times. The RNG state
+## changes, so we get to exercise the code with a few different values.
+Diffie-Hellman full exchange: 5-bit #1
+dhm_do_dhm:10:"23":1:10:"5":0
 
-Diffie-Hellman trivial subgroup #1
-dhm_do_dhm:10:"23":10:"1":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
+Diffie-Hellman full exchange: 5-bit #2
+dhm_do_dhm:10:"23":1:10:"5":0
 
-Diffie-Hellman trivial subgroup #2
-dhm_do_dhm:10:"23":10:"-1":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
+Diffie-Hellman full exchange: 5-bit #3
+dhm_do_dhm:10:"23":1:10:"5":0
+
+Diffie-Hellman full exchange: 5-bit #4
+dhm_do_dhm:10:"23":1:10:"5":0
+
+Diffie-Hellman full exchange: 5-bit #5
+dhm_do_dhm:10:"23":1:10:"5":0
+
+## This is x_size = P_size + 1. Arguably x_size > P_size makes no sense,
+## but it's the current undocumented behavior to treat it the same as when
+## x_size = P_size. If this behavior changes in the future, change the expected
+## return status from 0 to MBEDTLS_ERR_DHM_BAD_INPUT_DATA.
+Diffie-Hellman full exchange: 97-bit, x_size=14
+dhm_do_dhm:10:"93450983094850938450983409623":14:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit #1
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit #2
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit #3
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit #4
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit #5
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit, x_size=12
+dhm_do_dhm:10:"93450983094850938450983409623":12:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit, x_size=11
+dhm_do_dhm:10:"93450983094850938450983409623":11:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit, x_size=1 #1
+dhm_do_dhm:10:"93450983094850938450983409623":1:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit, x_size=1 #2
+dhm_do_dhm:10:"93450983094850938450983409623":1:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit, x_size=1 #3
+dhm_do_dhm:10:"93450983094850938450983409623":1:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit, x_size=1 #4
+dhm_do_dhm:10:"93450983094850938450983409623":1:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 97-bit, x_size=1 #5
+dhm_do_dhm:10:"93450983094850938450983409623":1:10:"9345098304850938450983409622":0
+
+Diffie-Hellman full exchange: 286-bit
+dhm_do_dhm:10:"93450983094850938450983409623982317398171298719873918739182739712938719287391879381271":36:10:"9345098309485093845098340962223981329819812792137312973297123912791271":0
 
 Diffie-Hellman small modulus
-dhm_do_dhm:10:"3":10:"5":MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED
+dhm_do_dhm:10:"3":1:10:"5":MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED+MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
 Diffie-Hellman zero modulus
-dhm_do_dhm:10:"0":10:"5":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
+dhm_do_dhm:10:"0":1:10:"5":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
+
+Diffie-Hellman with G=0
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"0":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
+
+Diffie-Hellman with G=1
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"1":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
+
+Diffie-Hellman with G=-1
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"-1":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
+
+Diffie-Hellman with G=P-1
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"93450983094850938450983409622":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
+
+Diffie-Hellman with G=P-2
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"93450983094850938450983409621":0
+
+Diffie-Hellman with G=P
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"93450983094850938450983409623":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
+
+Diffie-Hellman with G=P+1
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"93450983094850938450983409624":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
+
+Diffie-Hellman with G=P+2
+dhm_do_dhm:10:"93450983094850938450983409623":13:10:"93450983094850938450983409625":0
+
+Diffie-Hellman: x_size < 0
+dhm_do_dhm:10:"93450983094850938450983409623":-1:10:"9345098304850938450983409622":MBEDTLS_ERR_DHM_BAD_INPUT_DATA
 
 Diffie-Hellman MPI_MAX_SIZE modulus
 dhm_make_public:MBEDTLS_MPI_MAX_SIZE:10:"5":0
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_dhm.function b/third_party/mbedtls/repo/tests/suites/test_suite_dhm.function
index 1726b9e..96ff2ac 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_dhm.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_dhm.function
@@ -1,5 +1,68 @@
 /* BEGIN_HEADER */
 #include "mbedtls/dhm.h"
+
+/* Sanity checks on a Diffie-Hellman parameter: check the length-value
+ * syntax and check that the value is the expected one (taken from the
+ * DHM context by the caller). */
+static int check_dhm_param_output( const mbedtls_mpi *expected,
+                                   const unsigned char *buffer,
+                                   size_t size,
+                                   size_t *offset )
+{
+    size_t n;
+    mbedtls_mpi actual;
+    int ok = 0;
+    mbedtls_mpi_init( &actual );
+
+    ++mbedtls_test_info.step;
+
+    TEST_ASSERT( size >= *offset + 2 );
+    n = ( buffer[*offset] << 8 ) | buffer[*offset + 1];
+    *offset += 2;
+    /* The DHM param output from Mbed TLS has leading zeros stripped, as
+     * permitted but not required by RFC 5246 \S4.4. */
+    TEST_EQUAL( n, mbedtls_mpi_size( expected ) );
+    TEST_ASSERT( size >= *offset + n );
+    TEST_EQUAL( 0, mbedtls_mpi_read_binary( &actual, buffer + *offset, n ) );
+    TEST_EQUAL( 0, mbedtls_mpi_cmp_mpi( expected, &actual ) );
+    *offset += n;
+
+    ok = 1;
+exit:
+    mbedtls_mpi_free( &actual );
+    return( ok );
+}
+
+/* Sanity checks on Diffie-Hellman parameters: syntax, range, and comparison
+ * against the context. */
+static int check_dhm_params( const mbedtls_dhm_context *ctx,
+                             size_t x_size,
+                             const unsigned char *ske, size_t ske_len )
+{
+    size_t offset = 0;
+
+    /* Check that ctx->X and ctx->GX are within range. */
+    TEST_ASSERT( mbedtls_mpi_cmp_int( &ctx->X, 1 ) > 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) < 0 );
+    TEST_ASSERT( mbedtls_mpi_size( &ctx->X ) <= x_size );
+    TEST_ASSERT( mbedtls_mpi_cmp_int( &ctx->GX, 1 ) > 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &ctx->GX, &ctx->P ) < 0 );
+
+    /* Check ske: it must contain P, G and G^X, each prefixed with a
+     * 2-byte size. */
+    if( !check_dhm_param_output( &ctx->P, ske, ske_len, &offset ) )
+        goto exit;
+    if( !check_dhm_param_output( &ctx->G, ske, ske_len, &offset ) )
+        goto exit;
+    if( !check_dhm_param_output( &ctx->GX, ske, ske_len, &offset ) )
+        goto exit;
+    TEST_EQUAL( offset, ske_len );
+
+    return( 1 );
+exit:
+    return( 0 );
+}
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -115,7 +178,7 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void dhm_do_dhm( int radix_P, char *input_P,
+void dhm_do_dhm( int radix_P, char *input_P, int x_size,
                  int radix_G, char *input_G, int result )
 {
     mbedtls_dhm_context ctx_srv;
@@ -129,7 +192,7 @@
     size_t pub_cli_len = 0;
     size_t sec_srv_len;
     size_t sec_cli_len;
-    int x_size, i;
+    int i;
     mbedtls_test_rnd_pseudo_info rnd_info;
 
     mbedtls_dhm_init( &ctx_srv );
@@ -143,19 +206,21 @@
     /*
      * Set params
      */
-    TEST_ASSERT( mbedtls_mpi_read_string( &ctx_srv.P, radix_P, input_P ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &ctx_srv.G, radix_G, input_G ) == 0 );
-    x_size = mbedtls_mpi_size( &ctx_srv.P );
-    pub_cli_len = x_size;
+    TEST_ASSERT( mbedtls_test_read_mpi( &ctx_srv.P, radix_P, input_P ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &ctx_srv.G, radix_G, input_G ) == 0 );
+    pub_cli_len = mbedtls_mpi_size( &ctx_srv.P );
 
     /*
      * First key exchange
      */
+    mbedtls_test_set_step( 10 );
     TEST_ASSERT( mbedtls_dhm_make_params( &ctx_srv, x_size, ske, &ske_len,
                                           &mbedtls_test_rnd_pseudo_rand,
                                           &rnd_info ) == result );
     if ( result != 0 )
         goto exit;
+    if( !check_dhm_params( &ctx_srv, x_size, ske, ske_len ) )
+        goto exit;
 
     ske[ske_len++] = 0;
     ske[ske_len++] = 0;
@@ -179,6 +244,7 @@
     /* Re-do calc_secret on server a few times to test update of blinding values */
     for( i = 0; i < 3; i++ )
     {
+        mbedtls_test_set_step( 20 + i );
         sec_srv_len = 1000;
         TEST_ASSERT( mbedtls_dhm_calc_secret( &ctx_srv, sec_srv,
                                               sizeof( sec_srv ), &sec_srv_len,
@@ -195,9 +261,12 @@
      */
     p = ske;
 
+    mbedtls_test_set_step( 30 );
     TEST_ASSERT( mbedtls_dhm_make_params( &ctx_srv, x_size, ske, &ske_len,
                                           &mbedtls_test_rnd_pseudo_rand,
                                           &rnd_info ) == 0 );
+    if( !check_dhm_params( &ctx_srv, x_size, ske, ske_len ) )
+        goto exit;
     ske[ske_len++] = 0;
     ske[ske_len++] = 0;
     TEST_ASSERT( mbedtls_dhm_read_params( &ctx_cli, &p, ske + ske_len ) == 0 );
@@ -238,7 +307,7 @@
     TEST_ASSERT( mbedtls_mpi_shift_l( &P, ( P_bytes * 8 ) - 1 ) == 0 );
     TEST_ASSERT( mbedtls_mpi_set_bit( &P, 0, 1 ) == 0 );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &G, radix_G, input_G ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &G, radix_G, input_G ) == 0 );
 
     TEST_ASSERT( mbedtls_dhm_set_group( &ctx, &P, &G ) == 0 );
     TEST_ASSERT( mbedtls_dhm_make_public( &ctx, (int) mbedtls_mpi_size( &P ),
@@ -262,8 +331,8 @@
     mbedtls_dhm_init( &ctx );
     mbedtls_mpi_init( &P ); mbedtls_mpi_init( &G );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &P, 16, p ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &G, 16, g ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &P, 16, p ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &G, 16, g ) == 0 );
 
     TEST_ASSERT( mbedtls_dhm_parse_dhmfile( &ctx, filename ) == 0 );
 
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_ecdh.function b/third_party/mbedtls/repo/tests/suites/test_suite_ecdh.function
index 3ab96fa..69197e6 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_ecdh.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_ecdh.function
@@ -240,6 +240,8 @@
 
     rnd_info_A.buf = rnd_buf_A->x;
     rnd_info_A.length = rnd_buf_A->len;
+    rnd_info_A.fallback_f_rng = mbedtls_test_rnd_std_rand;
+    rnd_info_A.fallback_p_rng = NULL;
 
     /* Fix rnd_buf_A->x by shifting it left if necessary */
     if( grp.nbits % 8 != 0 )
@@ -256,6 +258,8 @@
 
     rnd_info_B.buf = rnd_buf_B->x;
     rnd_info_B.length = rnd_buf_B->len;
+    rnd_info_B.fallback_f_rng = mbedtls_test_rnd_std_rand;
+    rnd_info_B.fallback_p_rng = NULL;
 
     /* Fix rnd_buf_B->x by shifting it left if necessary */
     if( grp.nbits % 8 != 0 )
@@ -274,21 +278,21 @@
                                           mbedtls_test_rnd_buffer_rand,
                                           &rnd_info_A ) == 0 );
     TEST_ASSERT( ! mbedtls_ecp_is_zero( &qA ) );
-    TEST_ASSERT( mbedtls_mpi_read_string( &check, 16, xA_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &check, 16, xA_str ) == 0 );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &qA.X, &check ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &check, 16, yA_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &check, 16, yA_str ) == 0 );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &qA.Y, &check ) == 0 );
 
     TEST_ASSERT( mbedtls_ecdh_gen_public( &grp, &dB, &qB,
                                           mbedtls_test_rnd_buffer_rand,
                                           &rnd_info_B ) == 0 );
     TEST_ASSERT( ! mbedtls_ecp_is_zero( &qB ) );
-    TEST_ASSERT( mbedtls_mpi_read_string( &check, 16, xB_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &check, 16, xB_str ) == 0 );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &qB.X, &check ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &check, 16, yB_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &check, 16, yB_str ) == 0 );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &qB.Y, &check ) == 0 );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &check, 16, z_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &check, 16, z_str ) == 0 );
     TEST_ASSERT( mbedtls_ecdh_compute_shared( &grp, &zA, &qB, &dA, NULL, NULL ) == 0 );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &zA, &check ) == 0 );
     TEST_ASSERT( mbedtls_ecdh_compute_shared( &grp, &zB, &qA, &dB, NULL, NULL ) == 0 );
@@ -362,9 +366,13 @@
     mbedtls_ecdh_init( &srv );
     mbedtls_ecdh_init( &cli );
 
+    rnd_info_A.fallback_f_rng = mbedtls_test_rnd_std_rand;
+    rnd_info_A.fallback_p_rng = NULL;
     rnd_info_A.buf = dA->x;
     rnd_info_A.length = dA->len;
 
+    rnd_info_B.fallback_f_rng = mbedtls_test_rnd_std_rand;
+    rnd_info_B.fallback_p_rng = NULL;
     rnd_info_B.buf = dB->x;
     rnd_info_B.length = dB->len;
 
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_ecdsa.data b/third_party/mbedtls/repo/tests/suites/test_suite_ecdsa.data
index 889f684..755a43c 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_ecdsa.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_ecdsa.data
@@ -1,6 +1,26 @@
 ECDSA Parameter validation
 ecdsa_invalid_param:
 
+ECDSA primitive hash zero #1
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecdsa_prim_zero:MBEDTLS_ECP_DP_SECP192R1
+
+ECDSA primitive hash zero #2
+depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED
+ecdsa_prim_zero:MBEDTLS_ECP_DP_SECP224R1
+
+ECDSA primitive hash zero #3
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdsa_prim_zero:MBEDTLS_ECP_DP_SECP256R1
+
+ECDSA primitive hash zero #4
+depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+ecdsa_prim_zero:MBEDTLS_ECP_DP_SECP384R1
+
+ECDSA primitive hash zero #5
+depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED
+ecdsa_prim_zero:MBEDTLS_ECP_DP_SECP521R1
+
 ECDSA primitive random #1
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 ecdsa_prim_random:MBEDTLS_ECP_DP_SECP192R1
@@ -33,6 +53,26 @@
 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED
 ecdsa_prim_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0065FDA3409451DCAB0A0EAD45495112A3D813C17BFD34BDF8C1209D7DF5849120597779060A7FF9D704ADF78B570FFAD6F062E95C7E0C5D5481C5B153B48B375FA1":"0151518F1AF0F563517EDD5485190DF95A4BF57B5CBA4CF2A9A3F6474725A35F7AFE0A6DDEB8BEDBCD6A197E592D40188901CECD650699C9B5E456AEA5ADD19052A8":"006F3B142EA1BFFF7E2837AD44C9E4FF6D2D34C73184BBAD90026DD5E6E85317D9DF45CAD7803C6C20035B2F3FF63AFF4E1BA64D1C077577DA3F4286C58F0AEAE643":"00C1C2B305419F5A41344D7E4359933D734096F556197A9B244342B8B62F46F9373778F9DE6B6497B1EF825FF24F42F9B4A4BD7382CFC3378A540B1B7F0C1B956C2F":"DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA20A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F":"0154FD3836AF92D0DCA57DD5341D3053988534FDE8318FC6AAAAB68E2E6F4339B19F2F281A7E0B22C269D93CF8794A9278880ED7DBB8D9362CAEACEE544320552251":"017705A7030290D1CEB605A9A1BB03FF9CDD521E87A696EC926C8C10C8362DF4975367101F67D1CF9BCCBF2F3D239534FA509E70AAC851AE01AAC68D62F866472660":0
 
+ECDSA write-read hash zero #1
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecdsa_write_read_zero:MBEDTLS_ECP_DP_SECP192R1
+
+ECDSA write-read hash zero #2
+depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED
+ecdsa_write_read_zero:MBEDTLS_ECP_DP_SECP224R1
+
+ECDSA write-read hash zero #3
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecdsa_write_read_zero:MBEDTLS_ECP_DP_SECP256R1
+
+ECDSA write-read hash zero #4
+depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+ecdsa_write_read_zero:MBEDTLS_ECP_DP_SECP384R1
+
+ECDSA write-read hash zero #5
+depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED
+ecdsa_write_read_zero:MBEDTLS_ECP_DP_SECP521R1
+
 ECDSA write-read random #1
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 ecdsa_write_read_random:MBEDTLS_ECP_DP_SECP192R1
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_ecdsa.function b/third_party/mbedtls/repo/tests/suites/test_suite_ecdsa.function
index e6da884..d47bb4e 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_ecdsa.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_ecdsa.function
@@ -205,6 +205,38 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void ecdsa_prim_zero( int id )
+{
+    mbedtls_ecp_group grp;
+    mbedtls_ecp_point Q;
+    mbedtls_mpi d, r, s;
+    mbedtls_test_rnd_pseudo_info rnd_info;
+    unsigned char buf[MBEDTLS_MD_MAX_SIZE];
+
+    mbedtls_ecp_group_init( &grp );
+    mbedtls_ecp_point_init( &Q );
+    mbedtls_mpi_init( &d ); mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s );
+    memset( &rnd_info, 0x00, sizeof( mbedtls_test_rnd_pseudo_info ) );
+    memset( buf, 0, sizeof( buf ) );
+
+    TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
+    TEST_ASSERT( mbedtls_ecp_gen_keypair( &grp, &d, &Q,
+                                          &mbedtls_test_rnd_pseudo_rand,
+                                          &rnd_info ) == 0 );
+
+    TEST_ASSERT( mbedtls_ecdsa_sign( &grp, &r, &s, &d, buf, sizeof( buf ),
+                                     &mbedtls_test_rnd_pseudo_rand,
+                                     &rnd_info ) == 0 );
+    TEST_ASSERT( mbedtls_ecdsa_verify( &grp, buf, sizeof( buf ), &Q, &r, &s ) == 0 );
+
+exit:
+    mbedtls_ecp_group_free( &grp );
+    mbedtls_ecp_point_free( &Q );
+    mbedtls_mpi_free( &d ); mbedtls_mpi_free( &r ); mbedtls_mpi_free( &s );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void ecdsa_prim_random( int id )
 {
     mbedtls_ecp_group grp;
@@ -257,9 +289,11 @@
 
     TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
     TEST_ASSERT( mbedtls_ecp_point_read_string( &Q, 16, xQ_str, yQ_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &d, 16, d_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &r_check, 16, r_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &s_check, 16, s_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &d, 16, d_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &r_check, 16, r_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &s_check, 16, s_str ) == 0 );
+    rnd_info.fallback_f_rng = mbedtls_test_rnd_std_rand;
+    rnd_info.fallback_p_rng = NULL;
     rnd_info.buf = rnd_buf->x;
     rnd_info.length = rnd_buf->len;
 
@@ -320,9 +354,9 @@
     memset( hash, 0, sizeof( hash ) );
 
     TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &d, 16, d_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &r_check, 16, r_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &s_check, 16, s_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &d, 16, d_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &r_check, 16, r_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &s_check, 16, s_str ) == 0 );
 
     md_info = mbedtls_md_info_from_type( md_alg );
     TEST_ASSERT( md_info != NULL );
@@ -347,6 +381,66 @@
 /* END_CASE */
 
 /* BEGIN_CASE depends_on:MBEDTLS_SHA256_C */
+void ecdsa_write_read_zero( int id )
+{
+    mbedtls_ecdsa_context ctx;
+    mbedtls_test_rnd_pseudo_info rnd_info;
+    unsigned char hash[32];
+    unsigned char sig[200];
+    size_t sig_len, i;
+
+    mbedtls_ecdsa_init( &ctx );
+    memset( &rnd_info, 0x00, sizeof( mbedtls_test_rnd_pseudo_info ) );
+    memset( hash, 0, sizeof( hash ) );
+    memset( sig, 0x2a, sizeof( sig ) );
+
+    /* generate signing key */
+    TEST_ASSERT( mbedtls_ecdsa_genkey( &ctx, id,
+                                       &mbedtls_test_rnd_pseudo_rand,
+                                       &rnd_info ) == 0 );
+
+    /* generate and write signature, then read and verify it */
+    TEST_ASSERT( mbedtls_ecdsa_write_signature( &ctx, MBEDTLS_MD_SHA256,
+                 hash, sizeof( hash ),
+                 sig, &sig_len, &mbedtls_test_rnd_pseudo_rand,
+                 &rnd_info ) == 0 );
+    TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ),
+                 sig, sig_len ) == 0 );
+
+    /* check we didn't write past the announced length */
+    for( i = sig_len; i < sizeof( sig ); i++ )
+        TEST_ASSERT( sig[i] == 0x2a );
+
+    /* try verification with invalid length */
+    TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ),
+                 sig, sig_len - 1 ) != 0 );
+    TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ),
+                 sig, sig_len + 1 ) != 0 );
+
+    /* try invalid sequence tag */
+    sig[0]++;
+    TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ),
+                 sig, sig_len ) != 0 );
+    sig[0]--;
+
+    /* try modifying r */
+    sig[10]++;
+    TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ),
+                 sig, sig_len ) == MBEDTLS_ERR_ECP_VERIFY_FAILED );
+    sig[10]--;
+
+    /* try modifying s */
+    sig[sig_len - 1]++;
+    TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ),
+                 sig, sig_len ) == MBEDTLS_ERR_ECP_VERIFY_FAILED );
+    sig[sig_len - 1]--;
+
+exit:
+    mbedtls_ecdsa_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SHA256_C */
 void ecdsa_write_read_random( int id )
 {
     mbedtls_ecdsa_context ctx;
@@ -491,7 +585,7 @@
     memset( sig, 0, sizeof( sig ) );
 
     TEST_ASSERT( mbedtls_ecp_group_load( &ctx.grp, id ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &ctx.d, 16, d_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &ctx.d, 16, d_str ) == 0 );
 
     md_info = mbedtls_md_info_from_type( md_alg );
     TEST_ASSERT( md_info != NULL );
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_ecjpake.data b/third_party/mbedtls/repo/tests/suites/test_suite_ecjpake.data
index ffa59e5..fe14f88 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_ecjpake.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_ecjpake.data
@@ -56,7 +56,7 @@
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round one: KKP1: zero-length r
-read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb51600":MBEDTLS_ERR_ECP_INVALID_KEY
+read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb51600":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round one: KKP1: no data for r
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb51601":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -104,7 +104,7 @@
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round one: KKP2: zero-length r
-read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb51600":MBEDTLS_ERR_ECP_INVALID_KEY
+read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb51600":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round one: KKP2: no data for r
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb51601":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -170,7 +170,7 @@
 read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a641045516ea3e54a0d5d8b2ce786b38d383370029a5dbe4459c9dd601b408a24ae6465c8ac905b9eb03b5d3691c139ef83f1cd4200f6c9cd4ec392218a59ed243d3c8":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round two client: zero-length r
-read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a641045516ea3e54a0d5d8b2ce786b38d383370029a5dbe4459c9dd601b408a24ae6465c8ac905b9eb03b5d3691c139ef83f1cd4200f6c9cd4ec392218a59ed243d3c800":MBEDTLS_ERR_ECP_INVALID_KEY
+read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a641045516ea3e54a0d5d8b2ce786b38d383370029a5dbe4459c9dd601b408a24ae6465c8ac905b9eb03b5d3691c139ef83f1cd4200f6c9cd4ec392218a59ed243d3c800":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round two client: no data for r
 read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a641045516ea3e54a0d5d8b2ce786b38d383370029a5dbe4459c9dd601b408a24ae6465c8ac905b9eb03b5d3691c139ef83f1cd4200f6c9cd4ec392218a59ed243d3c801":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -224,7 +224,7 @@
 read_round_two_srv:"410469d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee4104077e8c31e20e6bedb760c13593e69f15be85c27d68cd09ccb8c4183608917c5c3d409fac39fefee82f7292d36f0d23e055913f45a52b85dd8a2052e9e129bb4d":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round two server: zero-length r
-read_round_two_srv:"410469d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee4104077e8c31e20e6bedb760c13593e69f15be85c27d68cd09ccb8c4183608917c5c3d409fac39fefee82f7292d36f0d23e055913f45a52b85dd8a2052e9e129bb4d00":MBEDTLS_ERR_ECP_INVALID_KEY
+read_round_two_srv:"410469d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee4104077e8c31e20e6bedb760c13593e69f15be85c27d68cd09ccb8c4183608917c5c3d409fac39fefee82f7292d36f0d23e055913f45a52b85dd8a2052e9e129bb4d00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round two server: no data for r
 read_round_two_srv:"410469d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee4104077e8c31e20e6bedb760c13593e69f15be85c27d68cd09ccb8c4183608917c5c3d409fac39fefee82f7292d36f0d23e055913f45a52b85dd8a2052e9e129bb4d20":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_ecp.data b/third_party/mbedtls/repo/tests/suites/test_suite_ecp.data
index 408a9b7..79912eb 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_ecp.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_ecp.data
@@ -36,13 +36,133 @@
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 mbedtls_ecp_curve_info:MBEDTLS_ECP_DP_SECP192R1:19:192:"secp192r1"
 
-ECP check pubkey Montgomery #1 (too big)
+ECP check pubkey Curve25519 #1 (biggest)
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF":"0":"1":0
+
+ECP check pubkey Curve25519 #2 (too big)
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
 ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"010000000000000000000000000000000000000000000000000000000000000000":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
 
-ECP check pubkey Montgomery #2 (biggest)
+ECP check pubkey Curve25519 #3 (DoS big)
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
-ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF":"0":"1":0
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"0100000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+ECP check pubkey Curve25519 y ignored
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"2":"-1":"1":0
+
+ECP check pubkey Curve25519 z is not 1
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"2":"0":"2":MBEDTLS_ERR_ECP_INVALID_KEY
+
+ECP check pubkey Curve25519 x negative
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"-2":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+# see https://cr.yp.to/ecdh.html#validate
+ECP check pubkey Curve25519 low-order point #1
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"0":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+# see https://cr.yp.to/ecdh.html#validate
+ECP check pubkey Curve25519 low-order point #2
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"1":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+# see https://cr.yp.to/ecdh.html#validate
+ECP check pubkey Curve25519 low-order point #3 (let's call this u)
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"b8495f16056286fdb1329ceb8d09da6ac49ff1fae35616aeb8413b7c7aebe0":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+# see https://cr.yp.to/ecdh.html#validate
+ECP check pubkey Curve25519 low-order point #4 (let's call this v)
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"57119fd0dd4e22d8868e1c58c45c44045bef839c55b1d0b1248c50a3bc959c5f":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+# see https://cr.yp.to/ecdh.html#validate
+ECP check pubkey Curve25519 low-order point #5 p-1
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+# see https://cr.yp.to/ecdh.html#validate
+ECP check pubkey Curve25519 low-order point #6 p
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+# see https://cr.yp.to/ecdh.html#validate
+ECP check pubkey Curve25519 low-order point #7 p+1
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+# see https://cr.yp.to/ecdh.html#validate
+ECP check pubkey Curve25519 low-order point #8 p+u
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"80b8495f16056286fdb1329ceb8d09da6ac49ff1fae35616aeb8413b7c7aebcd":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+# see https://cr.yp.to/ecdh.html#validate
+ECP check pubkey Curve25519 low-order point #9 p+v
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"d7119fd0dd4e22d8868e1c58c45c44045bef839c55b1d0b1248c50a3bc959c4c":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+# see https://cr.yp.to/ecdh.html#validate
+ECP check pubkey Curve25519 low-order point #10 2p-1
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd9":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+# see https://cr.yp.to/ecdh.html#validate
+ECP check pubkey Curve25519 low-order point #11 2p
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffda":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+# see https://cr.yp.to/ecdh.html#validate
+ECP check pubkey Curve25519 low-order point #12 2p+1
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE25519:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdb":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+ECP check pubkey Curve448 #1 (biggest)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE448:"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF":"0":"1":0
+
+ECP check pubkey Curve448 #2 (too big)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE448:"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+ECP check pubkey Curve448 #3 (DoS big)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE448:"0100000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+ECP check pubkey Curve448 y ignored
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE448:"2":"-1":"1":0
+
+ECP check pubkey Curve448 z is not 1
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE448:"2":"0":"2":MBEDTLS_ERR_ECP_INVALID_KEY
+
+ECP check pubkey Curve448 x negative
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE448:"-2":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+ECP check pubkey Curve448 low-order point #1
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE448:"0":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+ECP check pubkey Curve448 low-order point #2
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE448:"1":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+ECP check pubkey Curve448 low-order point #3 p-1
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE448:"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+ECP check pubkey Curve448 low-order point #4 p
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE448:"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
+
+ECP check pubkey Curve448 low-order point #5 p+1
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_check_pub:MBEDTLS_ECP_DP_CURVE448:"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000000000000":"0":"1":MBEDTLS_ERR_ECP_INVALID_KEY
 
 ECP check pubkey Koblitz #1 (point not on curve)
 depends_on:MBEDTLS_ECP_DP_SECP224K1_ENABLED
@@ -276,6 +396,42 @@
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 mbedtls_ecp_gen_key:MBEDTLS_ECP_DP_SECP192R1
 
+ECP generate Montgomery key: Curve25519, random in range
+genkey_mx_known_answer:254:"9e020406080a0c0e10121416181a1c1e20222426282a2c2e30323436383a3df0":"4f0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1ef8"
+
+ECP generate Montgomery key: Curve25519, clear higher bit
+genkey_mx_known_answer:254:"ff0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1ef8":"7f808101820283038404850586068707880889098a0a8b0b8c0c8d0d8e0e8f78"
+
+ECP generate Montgomery key: Curve25519, clear low bits
+genkey_mx_known_answer:254:"9e020406080a0c0e10121416181a1c1e20222426282a2c2e30323436383a3dff":"4f0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1ef8"
+
+ECP generate Montgomery key: Curve25519, random = all-bits-zero
+genkey_mx_known_answer:254:"0000000000000000000000000000000000000000000000000000000000000000":"4000000000000000000000000000000000000000000000000000000000000000"
+
+ECP generate Montgomery key: Curve25519, random = all-bits-one
+genkey_mx_known_answer:254:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":"7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8"
+
+ECP generate Montgomery key: Curve25519, not enough entropy
+genkey_mx_known_answer:254:"4f0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e":""
+
+ECP generate Montgomery key: Curve448, random in range
+genkey_mx_known_answer:447:"cf0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536fc":"cf0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536fc"
+
+ECP generate Montgomery key: Curve448, set high bit
+genkey_mx_known_answer:447:"0f0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536fc":"8f0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536fc"
+
+ECP generate Montgomery key: Curve448, clear low bits
+genkey_mx_known_answer:447:"cf0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536ff":"cf0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536fc"
+
+ECP generate Montgomery key: Curve448, random = all-bits-zero
+genkey_mx_known_answer:447:"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+
+ECP generate Montgomery key: Curve448, random = all-bits-one
+genkey_mx_known_answer:447:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"
+
+ECP generate Montgomery key: Curve448, not enough entropy
+genkey_mx_known_answer:447:"4f0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536":""
+
 ECP read key #1 (short weierstrass, too small)
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 mbedtls_ecp_read_key:MBEDTLS_ECP_DP_SECP192R1:"00":MBEDTLS_ERR_ECP_INVALID_KEY:0
@@ -440,15 +596,15 @@
 
 ECP point multiplication Curve25519 (element of order 2: origin) #3
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
-ecp_test_mul:MBEDTLS_ECP_DP_CURVE25519:"5AC99F33632E5A768DE7E81BF854C27C46E3FBF2ABBACD29EC4AFF517369C660":"00":"00":"01":"00":"01":"00":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+ecp_test_mul:MBEDTLS_ECP_DP_CURVE25519:"5AC99F33632E5A768DE7E81BF854C27C46E3FBF2ABBACD29EC4AFF517369C660":"00":"00":"01":"00":"01":"00":MBEDTLS_ERR_ECP_INVALID_KEY
 
 ECP point multiplication Curve25519 (element of order 4: 1) #4
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
-ecp_test_mul:MBEDTLS_ECP_DP_CURVE25519:"5AC99F33632E5A768DE7E81BF854C27C46E3FBF2ABBACD29EC4AFF517369C660":"01":"00":"01":"00":"01":"00":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+ecp_test_mul:MBEDTLS_ECP_DP_CURVE25519:"5AC99F33632E5A768DE7E81BF854C27C46E3FBF2ABBACD29EC4AFF517369C660":"01":"00":"01":"00":"01":"00":MBEDTLS_ERR_ECP_INVALID_KEY
 
 ECP point multiplication Curve25519 (element of order 8) #5
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
-ecp_test_mul:MBEDTLS_ECP_DP_CURVE25519:"5AC99F33632E5A768DE7E81BF854C27C46E3FBF2ABBACD29EC4AFF517369C660":"B8495F16056286FDB1329CEB8D09DA6AC49FF1FAE35616AEB8413B7C7AEBE0":"00":"01":"00":"01":"00":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+ecp_test_mul:MBEDTLS_ECP_DP_CURVE25519:"5AC99F33632E5A768DE7E81BF854C27C46E3FBF2ABBACD29EC4AFF517369C660":"B8495F16056286FDB1329CEB8D09DA6AC49FF1FAE35616AEB8413B7C7AEBE0":"00":"01":"00":"01":"00":MBEDTLS_ERR_ECP_INVALID_KEY
 
 ECP point multiplication rng fail secp256r1
 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
@@ -458,6 +614,14 @@
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
 ecp_test_mul_rng:MBEDTLS_ECP_DP_CURVE25519:"5AC99F33632E5A768DE7E81BF854C27C46E3FBF2ABBACD29EC4AFF517369C660"
 
+ECP point muladd secp256r1 #1
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_muladd:MBEDTLS_ECP_DP_SECP256R1:"01":"04e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e0e1ff20e1ffe120e1e1e173287170a761308491683e345cacaebb500c96e1a7bbd37772968b2c951f0579":"01":"04e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1ffffffff20e120e1e1e1e13a4e135157317b79d4ecf329fed4f9eb00dc67dbddae33faca8b6d8a0255b5ce":"04fab65e09aa5dd948320f86246be1d3fc571e7f799d9005170ed5cc868b67598431a668f96aa9fd0b0eb15f0edf4c7fe1be2885eadcb57e3db4fdd093585d3fa6"
+
+ECP point muladd secp256r1 #2
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_muladd:MBEDTLS_ECP_DP_SECP256R1:"01":"04e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1ffffffff20e120e1e1e1e13a4e135157317b79d4ecf329fed4f9eb00dc67dbddae33faca8b6d8a0255b5ce":"01":"04e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e0e1ff20e1ffe120e1e1e173287170a761308491683e345cacaebb500c96e1a7bbd37772968b2c951f0579":"04fab65e09aa5dd948320f86246be1d3fc571e7f799d9005170ed5cc868b67598431a668f96aa9fd0b0eb15f0edf4c7fe1be2885eadcb57e3db4fdd093585d3fa6"
+
 ECP test vectors Curve448 (RFC 7748 6.2, after decodeUCoordinate)
 depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
 ecp_test_vec_x:MBEDTLS_ECP_DP_CURVE448:"eb7298a5c0d8c29a1dab27f1a6826300917389449741a974f5bac9d98dc298d46555bce8bae89eeed400584bb046cf75579f51d125498f98":"a01fc432e5807f17530d1288da125b0cd453d941726436c8bbd9c5222c3da7fa639ce03db8d23b274a0721a1aed5227de6e3b731ccf7089b":"ad997351b6106f36b0d1091b929c4c37213e0d2b97e85ebb20c127691d0dad8f1d8175b0723745e639a3cb7044290b99e0e2a0c27a6a301c":"0936f37bc6c1bd07ae3dec7ab5dc06a73ca13242fb343efc72b9d82730b445f3d4b0bd077162a46dcfec6f9b590bfcbcf520cdb029a8b73e":"9d874a5137509a449ad5853040241c5236395435c36424fd560b0cb62b281d285275a740ce32a22dd1740f4aa9161cec95ccc61a18f4ff07"
@@ -508,3 +672,127 @@
 ECP restartable muladd secp256r1 max_ops=250
 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
 ecp_muladd_restart:MBEDTLS_ECP_DP_SECP256R1:"CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C":"2B57C0235FB7489768D058FF4911C20FDBE71E3699D91339AFBB903EE17255DC":"C3875E57C85038A0D60370A87505200DC8317C8C534948BEA6559C7C18E6D4CE":"3B4E49C4FDBFC006FF993C81A50EAE221149076D6EC09DDD9FB3B787F85B6483":"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D":250:4:64
+
+ECP fix_negative: 0, -1, 224
+fix_negative:"00":-1:224
+
+ECP fix_negative: 1, -1, 224
+fix_negative:"01":-1:224
+
+ECP fix_negative: 2^32-1, -1, 224
+fix_negative:"ffffffff":-1:224
+
+ECP fix_negative: 2^32, -1, 224
+fix_negative:"0100000000":-1:224
+
+ECP fix_negative: 2^64-1, -1, 224
+fix_negative:"ffffffffffffffff":-1:224
+
+ECP fix_negative: 2^64, -1, 224
+fix_negative:"010000000000000000":-1:224
+
+ECP fix_negative: 2^128-1, -1, 224
+fix_negative:"ffffffffffffffffffffffffffffffff":-1:224
+
+ECP fix_negative: 2^128, -1, 224
+fix_negative:"0100000000000000000000000000000000":-1:224
+
+ECP fix_negative: 2^128+1, -1, 224
+fix_negative:"0100000000000000000000000000000001":-1:224
+
+ECP fix_negative: 2^224-1, -1, 224
+fix_negative:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffff":-1:224
+
+ECP fix_negative: 0, -2, 224
+fix_negative:"00":-2:224
+
+ECP fix_negative: 1, -2, 224
+fix_negative:"01":-2:224
+
+ECP fix_negative: 2^32-1, -2, 224
+fix_negative:"ffffffff":-2:224
+
+ECP fix_negative: 2^32, -2, 224
+fix_negative:"0100000000":-2:224
+
+ECP fix_negative: 2^64-1, -2, 224
+fix_negative:"ffffffffffffffff":-2:224
+
+ECP fix_negative: 2^64, -2, 224
+fix_negative:"010000000000000000":-2:224
+
+ECP fix_negative: 2^128-1, -2, 224
+fix_negative:"ffffffffffffffffffffffffffffffff":-2:224
+
+ECP fix_negative: 2^128, -2, 224
+fix_negative:"0100000000000000000000000000000000":-2:224
+
+ECP fix_negative: 2^128+1, -2, 224
+fix_negative:"0100000000000000000000000000000001":-2:224
+
+ECP fix_negative: 2^224-1, -2, 224
+fix_negative:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffff":-2:224
+
+ECP fix_negative: 0, -1, 256
+fix_negative:"00":-1:256
+
+ECP fix_negative: 1, -1, 256
+fix_negative:"01":-1:256
+
+ECP fix_negative: 2^32-1, -1, 256
+fix_negative:"ffffffff":-1:256
+
+ECP fix_negative: 2^32, -1, 256
+fix_negative:"0100000000":-1:256
+
+ECP fix_negative: 2^64-1, -1, 256
+fix_negative:"ffffffffffffffff":-1:256
+
+ECP fix_negative: 2^64, -1, 256
+fix_negative:"010000000000000000":-1:256
+
+ECP fix_negative: 2^128-1, -1, 256
+fix_negative:"ffffffffffffffffffffffffffffffff":-1:256
+
+ECP fix_negative: 2^128, -1, 256
+fix_negative:"0100000000000000000000000000000000":-1:256
+
+ECP fix_negative: 2^128+1, -1, 256
+fix_negative:"0100000000000000000000000000000001":-1:256
+
+ECP fix_negative: 2^256-1, -1, 256
+fix_negative:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":-1:256
+
+ECP fix_negative: 0, -2, 256
+fix_negative:"00":-2:256
+
+ECP fix_negative: 1, -2, 256
+fix_negative:"01":-2:256
+
+ECP fix_negative: 2^32-1, -2, 256
+fix_negative:"ffffffff":-2:256
+
+ECP fix_negative: 2^32, -2, 256
+fix_negative:"0100000000":-2:256
+
+ECP fix_negative: 2^64-1, -2, 256
+fix_negative:"ffffffffffffffff":-2:256
+
+ECP fix_negative: 2^64, -2, 256
+fix_negative:"010000000000000000":-2:256
+
+ECP fix_negative: 2^128-1, -2, 256
+fix_negative:"ffffffffffffffffffffffffffffffff":-2:256
+
+ECP fix_negative: 2^128, -2, 256
+fix_negative:"0100000000000000000000000000000000":-2:256
+
+ECP fix_negative: 2^128+1, -2, 256
+fix_negative:"0100000000000000000000000000000001":-2:256
+
+ECP fix_negative: 2^256-1, -2, 256
+fix_negative:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":-2:256
+
+# The first call to fix_negative in the test case of issue #4296.
+ECP fix_negative: #4296.1
+fix_negative:"8A4DD4C8B42C5EAED15FE4F4579F4CE513EC90A94010BF000000000000000000":-1:256
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_ecp.function b/third_party/mbedtls/repo/tests/suites/test_suite_ecp.function
index 4ee75a6..538c648 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_ecp.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_ecp.function
@@ -1,11 +1,21 @@
 /* BEGIN_HEADER */
 #include "mbedtls/ecp.h"
 
+#include "ecp_invasive.h"
+
+#if defined(MBEDTLS_TEST_HOOKS) &&                  \
+    ( defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||  \
+      defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||  \
+      defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) )
+#define HAVE_FIX_NEGATIVE
+#endif
+
 #define ECP_PF_UNKNOWN     -1
 
 #define ECP_PT_RESET( x )           \
     mbedtls_ecp_point_free( x );    \
     mbedtls_ecp_point_init( x );
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -376,6 +386,8 @@
     TEST_ASSERT( by_id == by_name );
 
     TEST_ASSERT( by_id->bit_size == size );
+    TEST_ASSERT( size <= MBEDTLS_ECP_MAX_BITS );
+    TEST_ASSERT( size <= MBEDTLS_ECP_MAX_BYTES * 8 );
 }
 /* END_CASE */
 
@@ -391,9 +403,9 @@
 
     TEST_ASSERT( mbedtls_ecp_group_load( &grp, grp_id ) == 0 );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &P.X, 16, x_hex ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &P.Y, 16, y_hex ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &P.Z, 16, z_hex ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &P.X, 16, x_hex ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &P.Y, 16, y_hex ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &P.Z, 16, z_hex ) == 0 );
 
     TEST_ASSERT( mbedtls_ecp_check_pubkey( &grp, &P ) == ret );
 
@@ -442,13 +454,13 @@
 
     TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &dA, 16, dA_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &xA, 16, xA_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &yA, 16, yA_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &dA, 16, dA_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &xA, 16, xA_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &yA, 16, yA_str ) == 0 );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &dB, 16, dB_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &xZ, 16, xZ_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &yZ, 16, yZ_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &dB, 16, dB_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &xZ, 16, xZ_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &yZ, 16, yZ_str ) == 0 );
 
     mbedtls_ecp_set_max_ops( (unsigned) max_ops );
 
@@ -526,13 +538,13 @@
 
     TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &u1, 16, u1_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &u2, 16, u2_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &xR, 16, xR_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &yR, 16, yR_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &u1, 16, u1_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &u2, 16, u2_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &xR, 16, xR_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &yR, 16, yR_str ) == 0 );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &Q.X, 16, xQ_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Q.Y, 16, yQ_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Q.X, 16, xQ_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Q.Y, 16, yQ_str ) == 0 );
     TEST_ASSERT( mbedtls_mpi_lset( &Q.Z, 1 ) == 0 );
 
     mbedtls_ecp_set_max_ops( (unsigned) max_ops );
@@ -589,14 +601,14 @@
 
     TEST_ASSERT( mbedtls_ecp_check_pubkey( &grp, &grp.G ) == 0 );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &dA, 16, dA_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &xA, 16, xA_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &yA, 16, yA_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &dB, 16, dB_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &xB, 16, xB_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &yB, 16, yB_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &xZ, 16, xZ_str ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &yZ, 16, yZ_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &dA, 16, dA_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &xA, 16, xA_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &yA, 16, yA_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &dB, 16, dB_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &xB, 16, xB_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &yB, 16, yB_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &xZ, 16, xZ_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &yZ, 16, yZ_str ) == 0 );
 
     TEST_ASSERT( mbedtls_ecp_mul( &grp, &R, &dA, &grp.G,
                           &mbedtls_test_rnd_pseudo_rand, &rnd_info ) == 0 );
@@ -644,11 +656,11 @@
 
     TEST_ASSERT( mbedtls_ecp_check_pubkey( &grp, &grp.G ) == 0 );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &dA, 16, dA_hex ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &dB, 16, dB_hex ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &xA, 16, xA_hex ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &xB, 16, xB_hex ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &xS, 16, xS_hex ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &dA, 16, dA_hex ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &dB, 16, dB_hex ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &xA, 16, xA_hex ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &xB, 16, xB_hex ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &xS, 16, xS_hex ) == 0 );
 
     TEST_ASSERT( mbedtls_ecp_mul( &grp, &R, &dA, &grp.G,
                           &mbedtls_test_rnd_pseudo_rand, &rnd_info ) == 0 );
@@ -752,6 +764,53 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
+void ecp_muladd( int id,
+                 data_t *u1_bin, data_t *P1_bin,
+                 data_t *u2_bin, data_t *P2_bin,
+                 data_t *expected_result )
+{
+    /* Compute R = u1 * P1 + u2 * P2 */
+    mbedtls_ecp_group grp;
+    mbedtls_ecp_point P1, P2, R;
+    mbedtls_mpi u1, u2;
+    uint8_t actual_result[MBEDTLS_ECP_MAX_PT_LEN];
+    size_t len;
+
+    mbedtls_ecp_group_init( &grp );
+    mbedtls_ecp_point_init( &P1 );
+    mbedtls_ecp_point_init( &P2 );
+    mbedtls_ecp_point_init( &R );
+    mbedtls_mpi_init( &u1 );
+    mbedtls_mpi_init( &u2 );
+
+    TEST_EQUAL( 0, mbedtls_ecp_group_load( &grp, id ) );
+    TEST_EQUAL( 0, mbedtls_mpi_read_binary( &u1, u1_bin->x, u1_bin->len ) );
+    TEST_EQUAL( 0, mbedtls_mpi_read_binary( &u2, u2_bin->x, u2_bin->len ) );
+    TEST_EQUAL( 0, mbedtls_ecp_point_read_binary( &grp, &P1,
+                                                  P1_bin->x, P1_bin->len ) );
+    TEST_EQUAL( 0, mbedtls_ecp_point_read_binary( &grp, &P2,
+                                                  P2_bin->x, P2_bin->len ) );
+
+    TEST_EQUAL( 0, mbedtls_ecp_muladd( &grp, &R, &u1, &P1, &u2, &P2 ) );
+    TEST_EQUAL( 0, mbedtls_ecp_point_write_binary(
+                    &grp, &R, MBEDTLS_ECP_PF_UNCOMPRESSED,
+                    &len, actual_result, sizeof( actual_result ) ) );
+    TEST_ASSERT( len <= MBEDTLS_ECP_MAX_PT_LEN );
+
+    ASSERT_COMPARE( expected_result->x, expected_result->len,
+                    actual_result, len );
+
+exit:
+    mbedtls_ecp_group_free( &grp );
+    mbedtls_ecp_point_free( &P1 );
+    mbedtls_ecp_point_free( &P2 );
+    mbedtls_ecp_point_free( &R );
+    mbedtls_mpi_free( &u1 );
+    mbedtls_mpi_free( &u2 );
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void ecp_fast_mod( int id, char * N_str )
 {
@@ -761,7 +820,7 @@
     mbedtls_mpi_init( &N ); mbedtls_mpi_init( &R );
     mbedtls_ecp_group_init( &grp );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, 16, N_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &N, 16, N_str ) == 0 );
     TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
     TEST_ASSERT( grp.modp != NULL );
 
@@ -800,15 +859,16 @@
 
     TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &P.X, 16, x ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &P.Y, 16, y ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &P.Z, 16, z ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &P.X, 16, x ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &P.Y, 16, y ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &P.Z, 16, z ) == 0 );
 
     TEST_ASSERT( mbedtls_ecp_point_write_binary( &grp, &P, format,
                                    &olen, buf, blen ) == ret );
 
     if( ret == 0 )
     {
+        TEST_ASSERT( olen <= MBEDTLS_ECP_MAX_PT_LEN );
         TEST_ASSERT( mbedtls_test_hexcmp( buf, out->x, olen, out->len ) == 0 );
     }
 
@@ -831,9 +891,9 @@
 
     TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, 16, x ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Y, 16, y ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Z, 16, z ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, 16, x ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y, 16, y ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Z, 16, z ) == 0 );
 
     TEST_ASSERT( mbedtls_ecp_point_read_binary( &grp, &P, buf->x, buf->len ) == ret );
 
@@ -875,9 +935,9 @@
 
     TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, 16, x ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Y, 16, y ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Z, 16, z ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, 16, x ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y, 16, y ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Z, 16, z ) == 0 );
 
     TEST_ASSERT( mbedtls_ecp_tls_read_point( &grp, &P, &vbuf, buf->len ) == ret );
 
@@ -1012,7 +1072,7 @@
     mbedtls_mpi_init( &d );
 
     TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &d, 16, key_hex ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &d, 16, key_hex ) == 0 );
 
     TEST_ASSERT( mbedtls_ecp_check_privkey( &grp, &d ) == ret );
 
@@ -1039,7 +1099,7 @@
     if( id != MBEDTLS_ECP_DP_NONE )
         TEST_ASSERT( mbedtls_ecp_group_load( &prv.grp, id ) == 0 );
     TEST_ASSERT( mbedtls_ecp_point_read_string( &prv.Q, 16, Qx, Qy ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &prv.d, 16, d ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &prv.d, 16, d ) == 0 );
 
     TEST_ASSERT( mbedtls_ecp_check_pub_priv( &pub, &prv ) == ret );
 
@@ -1152,6 +1212,85 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:HAVE_FIX_NEGATIVE */
+void fix_negative( data_t *N_bin, int c, int bits )
+{
+    mbedtls_mpi C, M, N;
+
+    mbedtls_mpi_init( &C );
+    mbedtls_mpi_init( &M );
+    mbedtls_mpi_init( &N );
+
+    /* C = - c * 2^bits (positive since c is negative) */
+    TEST_EQUAL( 0, mbedtls_mpi_lset( &C, -c ) );
+    TEST_EQUAL( 0, mbedtls_mpi_shift_l( &C, bits ) );
+
+    TEST_EQUAL( 0, mbedtls_mpi_read_binary( &N, N_bin->x, N_bin->len ) );
+    TEST_EQUAL( 0, mbedtls_mpi_grow( &N, C.n ) );
+
+    /* M = N - C = - ( C - N ) (expected result of fix_negative) */
+    TEST_EQUAL( 0, mbedtls_mpi_sub_mpi( &M, &N, &C ) );
+
+    mbedtls_ecp_fix_negative( &N, c, bits );
+
+    TEST_EQUAL( 0, mbedtls_mpi_cmp_mpi( &N, &M ) );
+
+exit:
+    mbedtls_mpi_free( &C );
+    mbedtls_mpi_free( &M );
+    mbedtls_mpi_free( &N );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS:MBEDTLS_ECP_MONTGOMERY_ENABLED */
+void genkey_mx_known_answer( int bits, data_t *seed, data_t *expected )
+{
+    mbedtls_test_rnd_buf_info rnd_info;
+    mbedtls_mpi d;
+    int ret;
+    uint8_t *actual = NULL;
+
+    mbedtls_mpi_init( &d );
+    rnd_info.buf = seed->x;
+    rnd_info.length = seed->len;
+    rnd_info.fallback_f_rng = NULL;
+    rnd_info.fallback_p_rng = NULL;
+
+    ASSERT_ALLOC( actual, expected->len );
+
+    ret = mbedtls_ecp_gen_privkey_mx( bits, &d,
+                                      mbedtls_test_rnd_buffer_rand, &rnd_info );
+
+    if( expected->len == 0 )
+    {
+        /* Expecting an error (happens if there isn't enough randomness) */
+        TEST_ASSERT( ret != 0 );
+    }
+    else
+    {
+        TEST_EQUAL( ret, 0 );
+        TEST_EQUAL( (size_t) bits + 1, mbedtls_mpi_bitlen( &d ) );
+        TEST_EQUAL( 0, mbedtls_mpi_write_binary( &d, actual, expected->len ) );
+        /* Test the exact result. This assumes that the output of the
+         * RNG is used in a specific way, which is overly constraining.
+         * The advantage is that it's easier to test the expected properties
+         * of the generated key:
+         * - The most significant bit must be at a specific positions
+         *   (can be enforced by checking the bit-length).
+         * - The least significant bits must have specific values
+         *   (can be enforced by checking these bits).
+         * - Other bits must be random (by testing with different RNG outputs,
+         *   we validate that those bits are indeed influenced by the RNG). */
+        ASSERT_COMPARE( expected->x, expected->len,
+                        actual, expected->len );
+    }
+
+exit:
+    mbedtls_free( actual );
+    mbedtls_mpi_free( &d );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
 void ecp_selftest(  )
 {
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_entropy.data b/third_party/mbedtls/repo/tests/suites/test_suite_entropy.data
index b2d20b4..95bfe66 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_entropy.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_entropy.data
@@ -1,3 +1,9 @@
+Entropy init-free-free
+entropy_init_free:0
+
+Entropy init-free-init-free
+entropy_init_free:1
+
 Create NV seed_file
 nv_seed_file_create:
 
@@ -7,6 +13,9 @@
 Entropy write/update seed file: nonexistent
 entropy_seed_file:"no_such_dir/file":MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR
 
+Entropy write/update seed file: base NV seed file
+entropy_write_base_seed_file:0
+
 Entropy no sources
 entropy_no_sources:
 
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_entropy.function b/third_party/mbedtls/repo/tests/suites/test_suite_entropy.function
index d9ea441..e5e88bb 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_entropy.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_entropy.function
@@ -134,6 +134,28 @@
  * END_DEPENDENCIES
  */
 
+/* BEGIN_CASE */
+void entropy_init_free( int reinit )
+{
+    mbedtls_entropy_context ctx;
+
+    /* Double free is not explicitly documented to work, but it is convenient
+     * to call mbedtls_entropy_free() unconditionally on an error path without
+     * checking whether it has already been called in the success path. */
+
+    mbedtls_entropy_init( &ctx );
+    mbedtls_entropy_free( &ctx );
+
+    if( reinit )
+        mbedtls_entropy_init( &ctx );
+    mbedtls_entropy_free( &ctx );
+
+    /* This test case always succeeds, functionally speaking. A plausible
+     * bug might trigger an invalid pointer dereference or a memory leak. */
+    goto exit;
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
 void entropy_seed_file( char * path, int ret )
 {
@@ -149,6 +171,21 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
+void entropy_write_base_seed_file( int ret )
+{
+    mbedtls_entropy_context ctx;
+
+    mbedtls_entropy_init( &ctx );
+
+    TEST_ASSERT( mbedtls_entropy_write_seed_file( &ctx, MBEDTLS_PLATFORM_STD_NV_SEED_FILE ) == ret );
+    TEST_ASSERT( mbedtls_entropy_update_seed_file( &ctx, MBEDTLS_PLATFORM_STD_NV_SEED_FILE ) == ret );
+
+exit:
+    mbedtls_entropy_free( &ctx );
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void entropy_no_sources( )
 {
@@ -217,6 +254,9 @@
 
     for( j = len; j < sizeof( buf ); j++ )
         TEST_ASSERT( acc[j] == 0 );
+
+exit:
+    mbedtls_entropy_free( &ctx );
 }
 /* END_CASE */
 
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_mpi.data b/third_party/mbedtls/repo/tests/suites/test_suite_mpi.data
index 0966393..2addd23 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_mpi.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_mpi.data
@@ -10,21 +10,39 @@
 Base test mpi_read_write_string #1
 mpi_read_write_string:10:"128":10:"128":100:0:0
 
+Base test mpi_read_write_string #1 (Leading 0)
+mpi_read_write_string:10:"0128":10:"128":100:0:0
+
 Base test mpi_read_write_string #2
 mpi_read_write_string:10:"128":16:"80":100:0:0
 
-Base test mpi_read_write_string #3 (Read zero)
+Base test mpi_read_write_string #3 (Read zero decimal)
 mpi_read_write_string:10:"0":10:"0":100:0:0
 
-Base test mpi_read_write_string #3 (Negative decimal) [#1]
+Base test mpi_read_write_string #3 (Read zero hex)
+mpi_read_write_string:16:"0":16:"00":100:0:0
+
+Base test mpi_read_write_string #3 (Read minus zero decimal)
+mpi_read_write_string:10:"-0":10:"0":100:0:0
+
+Base test mpi_read_write_string #3 (Read minus zero hex)
+mpi_read_write_string:16:"-0":16:"00":100:0:0
+
+Base test mpi_read_write_string #3 (Negative decimal)
 mpi_read_write_string:10:"-23":10:"-23":100:0:0
 
-Base test mpi_read_write_string #3 (Negative hex)
+Base test mpi_read_write_string #3 (Negative decimal, leading 0)
+mpi_read_write_string:10:"-023":10:"-23":100:0:0
+
+Base test mpi_read_write_string #3 (Negative hex -> decimal)
 mpi_read_write_string:16:"-20":10:"-32":100:0:0
 
-Base test mpi_read_write_string #3 (Negative decimal) [#2]
+Base test mpi_read_write_string #3 (Negative hex)
 mpi_read_write_string:16:"-23":16:"-23":100:0:0
 
+Base test mpi_read_write_string #3 (Negative hex, leading 0)
+mpi_read_write_string:16:"-023":16:"-23":100:0:0
+
 Base test mpi_read_write_string #4 (Buffer just fits)
 mpi_read_write_string:16:"-4":4:"-10":4:0:0
 
@@ -49,12 +67,18 @@
 Test mpi_read_write_string #7
 mpi_read_write_string:10:"56125680981752282334141896320372489490613963693556392520816017892111350604111697682705498319512049040516698827829292076808006940873974979584527073481012636016353913462376755556720019831187364993587901952757307830896531678727717924":16:"0941379d00fed1491fe15df284dfde4a142f68aa8d412023195cee66883e6290ffe703f4ea5963bf212713cee46b107c09182b5edcd955adac418bf4918e2889af48e1099d513830cec85c26ac1e158b52620e33ba8692f893efbb2f958b4424":200:0:0
 
-Test mpi_read_write_string #8 (Empty MPI -> hex)
-mpi_read_write_string:16:"":16:"00":4:0:0
+Test mpi_read_write_string #8 (Empty MPI hex -> hex)
+mpi_read_write_string:16:"":16:"":4:0:0
 
-Test mpi_read_write_string #9 (Empty MPI -> dec)
+Test mpi_read_write_string #9 (Empty MPI hex -> dec)
 mpi_read_write_string:16:"":10:"0":4:0:0
 
+Test mpi_read_write_string #8 (Empty MPI dec -> hex)
+mpi_read_write_string:10:"":16:"":4:0:0
+
+Test mpi_read_write_string #9 (Empty MPI dec -> dec)
+mpi_read_write_string:10:"":10:"0":4:0:0
+
 Test mpi_write_string #10 (Negative hex with odd number of digits)
 mpi_read_write_string:16:"-1":16:"":3:0:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
 
@@ -97,6 +121,12 @@
 Base test mbedtls_mpi_write_file #1
 mbedtls_mpi_write_file:10:"56125680981752282334141896320372489490613963693556392520816017892111350604111697682705498319512049040516698827829292076808006940873974979584527073481012636016353913462376755556720019831187364993587901952757307830896531678727717924":16:"data_files/mpi_write"
 
+Test mbedtls_mpi_lsb: 0 (null)
+mbedtls_mpi_lsb:16:"":0
+
+Test mbedtls_mpi_lsb: 0 (1 limb)
+mbedtls_mpi_lsb:16:"0":0
+
 Base test mbedtls_mpi_lsb #1
 mbedtls_mpi_lsb:10:"56125680981752282334141896320372489490613963693556392520816017892111350604111697682705498319512049040516698827829292076808006940873974979584527073481012636016353913462376755556720019831187364993587901952757307830896531678727717924":2
 
@@ -127,7 +157,10 @@
 Base test mbedtls_mpi_bitlen #6
 mbedtls_mpi_bitlen:10:"10":4
 
-Base test mbedtls_mpi_bitlen #7
+Base test mbedtls_mpi_bitlen: 0 (null)
+mbedtls_mpi_bitlen:10:"":0
+
+Base test mbedtls_mpi_bitlen: 0 (1 limb)
 mbedtls_mpi_bitlen:10:"0":0
 
 Base test mbedtls_mpi_cmp_int #1
@@ -175,6 +208,90 @@
 Base test mbedtls_mpi_cmp_mpi (Mixed values) #6
 mbedtls_mpi_cmp_mpi:10:"-2":10:"31231231289798":-1
 
+Test mbedtls_mpi_cmp_mpi: 0 (null) = 0 (null)
+mbedtls_mpi_cmp_mpi:10:"":10:"":0
+
+Test mbedtls_mpi_cmp_mpi: 0 (null) = 0 (1 limb)
+mbedtls_mpi_cmp_mpi:10:"":10:"0":0
+
+Test mbedtls_mpi_cmp_mpi: 0 (1 limb) = 0 (null)
+mbedtls_mpi_cmp_mpi:10:"0":10:"":0
+
+Test mbedtls_mpi_cmp_mpi: 0 (1 limb) = 0 (1 limb)
+mbedtls_mpi_cmp_mpi:10:"0":10:"0":0
+
+Test mbedtls_mpi_cmp_mpi: 0 (null) < positive
+mbedtls_mpi_cmp_mpi:10:"":10:"123":-1
+
+Test mbedtls_mpi_cmp_mpi: 0 (1 limb) < positive
+mbedtls_mpi_cmp_mpi:10:"0":10:"123":-1
+
+Test mbedtls_mpi_cmp_mpi: 0 (null) > negative
+mbedtls_mpi_cmp_mpi:10:"":10:"-123":1
+
+Test mbedtls_mpi_cmp_mpi: 0 (1 limb) > negative
+mbedtls_mpi_cmp_mpi:10:"0":10:"-123":1
+
+Test mbedtls_mpi_cmp_mpi: positive > 0 (null)
+mbedtls_mpi_cmp_mpi:10:"123":10:"":1
+
+Test mbedtls_mpi_cmp_mpi: positive > 0 (1 limb)
+mbedtls_mpi_cmp_mpi:10:"123":10:"0":1
+
+Test mbedtls_mpi_cmp_mpi: negative < 0 (null)
+mbedtls_mpi_cmp_mpi:10:"-123":10:"":-1
+
+Test mbedtls_mpi_cmp_mpi: negative < 0 (1 limb)
+mbedtls_mpi_cmp_mpi:10:"-123":10:"0":-1
+
+Test mbedtls_mpi_cmp_mpi: 0 (null) < positive with leading zero limb
+mbedtls_mpi_cmp_mpi:16:"":16:"0000000000000000123":-1
+
+Test mbedtls_mpi_cmp_mpi: 0 (1 limb) < positive with leading zero limb
+mbedtls_mpi_cmp_mpi:16:"0":16:"0000000000000000123":-1
+
+Test mbedtls_mpi_cmp_mpi: 0 (null) > negative with leading zero limb
+mbedtls_mpi_cmp_mpi:16:"":16:"-0000000000000000123":1
+
+Test mbedtls_mpi_cmp_mpi: 0 (1 limb) > negative with leading zero limb
+mbedtls_mpi_cmp_mpi:16:"0":16:"-0000000000000000123":1
+
+Test mbedtls_mpi_cmp_mpi: positive with leading zero limb > 0 (null)
+mbedtls_mpi_cmp_mpi:16:"0000000000000000123":16:"":1
+
+Test mbedtls_mpi_cmp_mpi: positive with leading zero limb > 0 (1 limb)
+mbedtls_mpi_cmp_mpi:16:"0000000000000000123":16:"0":1
+
+Test mbedtls_mpi_cmp_mpi: negative with leading zero limb < 0 (null)
+mbedtls_mpi_cmp_mpi:16:"-0000000000000000123":16:"":-1
+
+Test mbedtls_mpi_cmp_mpi: negative with leading zero limb < 0 (1 limb)
+mbedtls_mpi_cmp_mpi:16:"-0000000000000000123":16:"0":-1
+
+Test mbedtls_mpi_cmp_mpi: 0 (null) < large positive
+mbedtls_mpi_cmp_mpi:16:"":16:"1230000000000000000":-1
+
+Test mbedtls_mpi_cmp_mpi: 0 (1 limb) < large positive
+mbedtls_mpi_cmp_mpi:16:"0":16:"1230000000000000000":-1
+
+Test mbedtls_mpi_cmp_mpi: 0 (null) > large negative
+mbedtls_mpi_cmp_mpi:16:"":16:"-1230000000000000000":1
+
+Test mbedtls_mpi_cmp_mpi: 0 (1 limb) > large negative
+mbedtls_mpi_cmp_mpi:16:"0":16:"-1230000000000000000":1
+
+Test mbedtls_mpi_cmp_mpi: large positive > 0 (null)
+mbedtls_mpi_cmp_mpi:16:"1230000000000000000":16:"":1
+
+Test mbedtls_mpi_cmp_mpi: large positive > 0 (1 limb)
+mbedtls_mpi_cmp_mpi:16:"1230000000000000000":16:"0":1
+
+Test mbedtls_mpi_cmp_mpi: large negative < 0 (null)
+mbedtls_mpi_cmp_mpi:16:"-1230000000000000000":16:"":-1
+
+Test mbedtls_mpi_cmp_mpi: large negative < 0 (1 limb)
+mbedtls_mpi_cmp_mpi:16:"-1230000000000000000":16:"0":-1
+
 Base test mbedtls_mpi_lt_mpi_ct #1
 mbedtls_mpi_lt_mpi_ct:1:"2B5":1:"2B5":0:0
 
@@ -208,6 +325,9 @@
 Base test mbedtls_mpi_lt_mpi_ct (Y is longer in storage)
 mbedtls_mpi_lt_mpi_ct:3:"2B5":4:"2B5":0:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
+Base test mbedtls_mpi_lt_mpi_ct (length=0)
+mbedtls_mpi_lt_mpi_ct:0:"":0:"":0:0
+
 Base test mbedtls_mpi_lt_mpi_ct (corner case - 64 bit) #1
 mbedtls_mpi_lt_mpi_ct:2:"7FFFFFFFFFFFFFFF":2:"FF":0:0
 
@@ -280,7 +400,16 @@
 Base test mbedtls_mpi_cmp_abs (Negative values) #3
 mbedtls_mpi_cmp_abs:10:"-2":10:"-1":1
 
-Base test mbedtls_mpi_cmp_abs (Zero and Zero) #4
+Test mbedtls_mpi_cmp_abs: 0 (null) = 0 (null)
+mbedtls_mpi_cmp_abs:10:"":10:"":0
+
+Test mbedtls_mpi_cmp_abs: 0 (null) = 0 (1 limb)
+mbedtls_mpi_cmp_abs:10:"":10:"0":0
+
+Test mbedtls_mpi_cmp_abs: 0 (1 limb) = 0 (null)
+mbedtls_mpi_cmp_abs:10:"0":10:"":0
+
+Test mbedtls_mpi_cmp_abs: 0 (1 limb) = 0 (1 limb)
 mbedtls_mpi_cmp_abs:10:"0":10:"0":0
 
 Base test mbedtls_mpi_cmp_abs (Mix values) #1
@@ -292,84 +421,261 @@
 Base test mbedtls_mpi_cmp_abs (Mix values) #3
 mbedtls_mpi_cmp_abs:10:"-2":10:"1":1
 
-Copy zero (1 limb) to positive (1 limb)
-mbedtls_mpi_copy_sint:0:1500
+Copy large negative to large negative
+mbedtls_mpi_copy:"-ca5cadedb01dfaceacc01ade":"-face1e55ca11ab1ecab005e5"
 
-Copy zero (1 limb) to negative (1 limb)
-mbedtls_mpi_copy_sint:0:-1500
+Copy large negative to large positive
+mbedtls_mpi_copy:"-ca5cadedb01dfaceacc01ade":"face1e55ca11ab1ecab005e5"
 
-Copy positive (1 limb) to zero (1 limb)
-mbedtls_mpi_copy_sint:1500:0
+Copy large negative to small negative
+mbedtls_mpi_copy:"-ca5cadedb01dfaceacc01ade":"-beef"
 
-Copy negative (1 limb) to zero (1 limb)
-mbedtls_mpi_copy_sint:-1500:0
+Copy large negative to small positive
+mbedtls_mpi_copy:"-ca5cadedb01dfaceacc01ade":"beef"
 
-Copy positive (1 limb) to negative (1 limb)
-mbedtls_mpi_copy_sint:1500:-42
+Copy large negative to zero (1 limb)
+mbedtls_mpi_copy:"-ca5cadedb01dfaceacc01ade":"0"
 
-Copy negative (1 limb) to positive (1 limb)
-mbedtls_mpi_copy_sint:-42:1500
+Copy large negative to zero (null)
+mbedtls_mpi_copy:"-ca5cadedb01dfaceacc01ade":""
+
+Copy large positive to large negative
+mbedtls_mpi_copy:"ca5cadedb01dfaceacc01ade":"-face1e55ca11ab1ecab005e5"
+
+Copy large positive to large positive
+mbedtls_mpi_copy:"ca5cadedb01dfaceacc01ade":"face1e55ca11ab1ecab005e5"
+
+Copy large positive to small negative
+mbedtls_mpi_copy:"ca5cadedb01dfaceacc01ade":"-beef"
+
+Copy large positive to small positive
+mbedtls_mpi_copy:"ca5cadedb01dfaceacc01ade":"beef"
+
+Copy large positive to zero (1 limb)
+mbedtls_mpi_copy:"ca5cadedb01dfaceacc01ade":"0"
+
+Copy large positive to zero (null)
+mbedtls_mpi_copy:"ca5cadedb01dfaceacc01ade":""
+
+Copy small negative to large negative
+mbedtls_mpi_copy:"-bead":"-face1e55ca11ab1ecab005e5"
+
+Copy small negative to large positive
+mbedtls_mpi_copy:"-bead":"face1e55ca11ab1ecab005e5"
+
+Copy small negative to small negative
+mbedtls_mpi_copy:"-bead":"-beef"
+
+Copy small negative to small positive
+mbedtls_mpi_copy:"-bead":"beef"
+
+Copy small negative to zero (1 limb)
+mbedtls_mpi_copy:"-bead":"0"
+
+Copy small negative to zero (null)
+mbedtls_mpi_copy:"-bead":""
+
+Copy small positive to large negative
+mbedtls_mpi_copy:"bead":"-face1e55ca11ab1ecab005e5"
+
+Copy small positive to large positive
+mbedtls_mpi_copy:"bead":"face1e55ca11ab1ecab005e5"
+
+Copy small positive to small negative
+mbedtls_mpi_copy:"bead":"-beef"
+
+Copy small positive to small positive
+mbedtls_mpi_copy:"bead":"beef"
+
+Copy small positive to zero (1 limb)
+mbedtls_mpi_copy:"bead":"0"
+
+Copy small positive to zero (null)
+mbedtls_mpi_copy:"bead":""
+
+Copy zero (1 limb) to large negative
+mbedtls_mpi_copy:"0":"-face1e55ca11ab1ecab005e5"
+
+Copy zero (1 limb) to large positive
+mbedtls_mpi_copy:"0":"face1e55ca11ab1ecab005e5"
+
+Copy zero (1 limb) to small negative
+mbedtls_mpi_copy:"0":"-beef"
+
+Copy zero (1 limb) to small positive
+mbedtls_mpi_copy:"0":"beef"
+
+Copy zero (1 limb) to zero (1 limb)
+mbedtls_mpi_copy:"0":"0"
+
+Copy zero (1 limb) to zero (null)
+mbedtls_mpi_copy:"0":""
+
+Copy zero (null) to large negative
+mbedtls_mpi_copy:"":"-face1e55ca11ab1ecab005e5"
+
+Copy zero (null) to large positive
+mbedtls_mpi_copy:"":"face1e55ca11ab1ecab005e5"
+
+Copy zero (null) to small negative
+mbedtls_mpi_copy:"":"-beef"
+
+Copy zero (null) to small positive
+mbedtls_mpi_copy:"":"beef"
+
+Copy zero (null) to zero (1 limb)
+mbedtls_mpi_copy:"":"0"
 
 Copy zero (null) to zero (null)
-mbedtls_mpi_copy_binary:"":""
+mbedtls_mpi_copy:"":""
 
-Copy zero (null) to positive (1 limb)
-mbedtls_mpi_copy_binary:"":"1234"
+Copy self: large negative
+mpi_copy_self:"-ca5cadedb01dfaceacc01ade"
 
-Copy positive (1 limb) to zero (null)
-mbedtls_mpi_copy_binary:"1234":""
+Copy self: large positive
+mpi_copy_self:"ca5cadedb01dfaceacc01ade"
 
-Copy positive to larger
-mbedtls_mpi_copy_binary:"bead":"ca5cadedb01dfaceacc01ade"
+Copy self: small negative
+mpi_copy_self:"-bead"
 
-Copy positive to smaller
-mbedtls_mpi_copy_binary:"ca5cadedb01dfaceacc01ade":"bead"
-
-Copy self: positive (1 limb)
-mpi_copy_self:14
+Copy self: small positive
+mpi_copy_self:"bead"
 
 Copy self: zero (1 limb)
-mpi_copy_self:0
+mpi_copy_self:"0"
 
-Swap zero (1 limb) with positive (1 limb)
-mbedtls_mpi_swap_sint:0:1500
+Copy self: zero (null)
+mpi_copy_self:""
 
-Swap zero (1 limb) with negative (1 limb)
-mbedtls_mpi_swap_sint:0:-1500
+Swap large negative with large negative
+mbedtls_mpi_swap:"-ca5cadedb01dfaceacc01ade":"-face1e55ca11ab1ecab005e5"
 
-Swap positive (1 limb) with zero (1 limb)
-mbedtls_mpi_swap_sint:1500:0
+Swap large negative with large positive
+mbedtls_mpi_swap:"-ca5cadedb01dfaceacc01ade":"face1e55ca11ab1ecab005e5"
 
-Swap negative (1 limb) with zero (1 limb)
-mbedtls_mpi_swap_sint:-1500:0
+Swap large negative with small negative
+mbedtls_mpi_swap:"-ca5cadedb01dfaceacc01ade":"-beef"
 
-Swap positive (1 limb) with negative (1 limb)
-mbedtls_mpi_swap_sint:1500:-42
+Swap large negative with small positive
+mbedtls_mpi_swap:"-ca5cadedb01dfaceacc01ade":"beef"
 
-Swap negative (1 limb) with positive (1 limb)
-mbedtls_mpi_swap_sint:-42:1500
+Swap large negative with zero (1 limb)
+mbedtls_mpi_swap:"-ca5cadedb01dfaceacc01ade":"0"
+
+Swap large negative with zero (null)
+mbedtls_mpi_swap:"-ca5cadedb01dfaceacc01ade":""
+
+Swap large positive with large negative
+mbedtls_mpi_swap:"ca5cadedb01dfaceacc01ade":"-face1e55ca11ab1ecab005e5"
+
+Swap large positive with large positive
+mbedtls_mpi_swap:"ca5cadedb01dfaceacc01ade":"face1e55ca11ab1ecab005e5"
+
+Swap large positive with small negative
+mbedtls_mpi_swap:"ca5cadedb01dfaceacc01ade":"-beef"
+
+Swap large positive with small positive
+mbedtls_mpi_swap:"ca5cadedb01dfaceacc01ade":"beef"
+
+Swap large positive with zero (1 limb)
+mbedtls_mpi_swap:"ca5cadedb01dfaceacc01ade":"0"
+
+Swap large positive with zero (null)
+mbedtls_mpi_swap:"ca5cadedb01dfaceacc01ade":""
+
+Swap small negative with large negative
+mbedtls_mpi_swap:"-bead":"-face1e55ca11ab1ecab005e5"
+
+Swap small negative with large positive
+mbedtls_mpi_swap:"-bead":"face1e55ca11ab1ecab005e5"
+
+Swap small negative with small negative
+mbedtls_mpi_swap:"-bead":"-beef"
+
+Swap small negative with small positive
+mbedtls_mpi_swap:"-bead":"beef"
+
+Swap small negative with zero (1 limb)
+mbedtls_mpi_swap:"-bead":"0"
+
+Swap small negative with zero (null)
+mbedtls_mpi_swap:"-bead":""
+
+Swap small positive with large negative
+mbedtls_mpi_swap:"bead":"-face1e55ca11ab1ecab005e5"
+
+Swap small positive with large positive
+mbedtls_mpi_swap:"bead":"face1e55ca11ab1ecab005e5"
+
+Swap small positive with small negative
+mbedtls_mpi_swap:"bead":"-beef"
+
+Swap small positive with small positive
+mbedtls_mpi_swap:"bead":"beef"
+
+Swap small positive with zero (1 limb)
+mbedtls_mpi_swap:"bead":"0"
+
+Swap small positive with zero (null)
+mbedtls_mpi_swap:"bead":""
+
+Swap zero (1 limb) with large negative
+mbedtls_mpi_swap:"0":"-face1e55ca11ab1ecab005e5"
+
+Swap zero (1 limb) with large positive
+mbedtls_mpi_swap:"0":"face1e55ca11ab1ecab005e5"
+
+Swap zero (1 limb) with small negative
+mbedtls_mpi_swap:"0":"-beef"
+
+Swap zero (1 limb) with small positive
+mbedtls_mpi_swap:"0":"beef"
+
+Swap zero (1 limb) with zero (1 limb)
+mbedtls_mpi_swap:"0":"0"
+
+Swap zero (1 limb) with zero (null)
+mbedtls_mpi_swap:"0":""
+
+Swap zero (null) with large negative
+mbedtls_mpi_swap:"":"-face1e55ca11ab1ecab005e5"
+
+Swap zero (null) with large positive
+mbedtls_mpi_swap:"":"face1e55ca11ab1ecab005e5"
+
+Swap zero (null) with small negative
+mbedtls_mpi_swap:"":"-beef"
+
+Swap zero (null) with small positive
+mbedtls_mpi_swap:"":"beef"
+
+Swap zero (null) with zero (1 limb)
+mbedtls_mpi_swap:"":"0"
 
 Swap zero (null) with zero (null)
-mbedtls_mpi_swap_binary:"":""
+mbedtls_mpi_swap:"":""
 
-Swap zero (null) with positive (1 limb)
-mbedtls_mpi_swap_binary:"":"1234"
+Swap self: large negative
+mpi_swap_self:"-ca5cadedb01dfaceacc01ade"
 
-Swap positive (1 limb) with zero (null)
-mbedtls_mpi_swap_binary:"1234":""
+Swap self: large positive
+mpi_swap_self:"ca5cadedb01dfaceacc01ade"
 
-Swap positive with larger
-mbedtls_mpi_swap_binary:"bead":"ca5cadedb01dfaceacc01ade"
+Swap self: small negative
+mpi_swap_self:"-bead"
 
-Swap positive with smaller
-mbedtls_mpi_swap_binary:"ca5cadedb01dfaceacc01ade":"bead"
+Swap self: small positive
+mpi_swap_self:"bead"
 
-Swap self: 1 limb
-mpi_swap_self:"face"
+Swap self: zero (1 limb)
+mpi_swap_self:"0"
 
-Swap self: null
+Swap self: zero (null)
 mpi_swap_self:""
 
+Shrink 0 limbs in a buffer of size 0 to 0
+mbedtls_mpi_shrink:0:0:0:0
+
 Shrink 2 limbs in a buffer of size 2 to 4
 mbedtls_mpi_shrink:2:2:4:4
 
@@ -394,42 +700,6 @@
 Shrink 0 limbs in a buffer of size 4 to 0 yielding 1
 mbedtls_mpi_shrink:4:0:0:1
 
-Test mbedtls_mpi_safe_cond_assign #1
-mbedtls_mpi_safe_cond_assign:+1:"01":+1:"02"
-
-Test mbedtls_mpi_safe_cond_assign #2
-mbedtls_mpi_safe_cond_assign:+1:"FF000000000000000001":+1:"02"
-
-Test mbedtls_mpi_safe_cond_assign #3
-mbedtls_mpi_safe_cond_assign:+1:"01":+1:"FF000000000000000002"
-
-Test mbedtls_mpi_safe_cond_assign #4
-mbedtls_mpi_safe_cond_assign:+1:"01":-1:"02"
-
-Test mbedtls_mpi_safe_cond_assign #5
-mbedtls_mpi_safe_cond_assign:-1:"01":+1:"02"
-
-Test mbedtls_mpi_safe_cond_assign #6
-mbedtls_mpi_safe_cond_assign:-1:"01":-1:"02"
-
-Test mbedtls_mpi_safe_cond_swap #1
-mbedtls_mpi_safe_cond_swap:+1:"01":+1:"02"
-
-Test mbedtls_mpi_safe_cond_swap #2
-mbedtls_mpi_safe_cond_swap:+1:"FF000000000000000001":+1:"02"
-
-Test mbedtls_mpi_safe_cond_swap #3
-mbedtls_mpi_safe_cond_swap:+1:"01":+1:"FF000000000000000002"
-
-Test mbedtls_mpi_safe_cond_swap #4
-mbedtls_mpi_safe_cond_swap:+1:"01":-1:"02"
-
-Test mbedtls_mpi_safe_cond_swap #5
-mbedtls_mpi_safe_cond_swap:-1:"01":+1:"02"
-
-Test mbedtls_mpi_safe_cond_swap #6
-mbedtls_mpi_safe_cond_swap:-1:"01":-1:"02"
-
 Base test mbedtls_mpi_add_abs #1
 mbedtls_mpi_add_abs:10:"12345678":10:"642531":10:"12988209"
 
@@ -442,6 +712,15 @@
 Base test mbedtls_mpi_add_abs #4
 mbedtls_mpi_add_abs:10:"-12345678":10:"-642531":10:"12988209"
 
+Test mbedtls_mpi_add_abs: 0 (null) + 0 (null)
+mbedtls_mpi_add_abs:16:"":16:"":16:"0"
+
+Test mbedtls_mpi_add_abs: 0 (null) + 1
+mbedtls_mpi_add_abs:16:"":16:"01":16:"01"
+
+Test mbedtls_mpi_add_abs: 1 + 0 (null)
+mbedtls_mpi_add_abs:16:"01":16:"":16:"01"
+
 Test mbedtls_mpi_add_abs #1
 mbedtls_mpi_add_abs:10:"-643808006803554439230129854961492699151386107534013432918073439524138264842370630061369715394739134090922937332590384720397133335969549256322620979036686633213903952966175107096769180017646161851573147596390153":10:"56125680981752282333498088313568935051383833838594899821664631784577337171193624243181360054669678410455329112434552942717084003541384594864129940145043086760031292483340068923506115878221189886491132772739661669044958531131327771":10:"56125680981752282334141896320372489490613963693556392520816017892111350604111697682705498319512049040516698827829292076808006940873974979584527073481012636016353913462376755556720019831187364993587901952757307830896531678727717924"
 
@@ -463,6 +742,21 @@
 Base test mbedtls_mpi_add_mpi #4
 mbedtls_mpi_add_mpi:10:"-12345678":10:"-642531":10:"-12988209"
 
+Test mbedtls_mpi_add_mpi: 0 (null) + 0 (null)
+mbedtls_mpi_add_mpi:16:"":16:"":16:"0"
+
+Test mbedtls_mpi_add_mpi: 0 (null) + 1
+mbedtls_mpi_add_mpi:16:"":16:"01":16:"01"
+
+Test mbedtls_mpi_add_mpi: 1 + 0 (null)
+mbedtls_mpi_add_mpi:16:"01":16:"":16:"01"
+
+Test mbedtls_mpi_add_mpi: 0 (null) + -1
+mbedtls_mpi_add_mpi:16:"":16:"-01":16:"-01"
+
+Test mbedtls_mpi_add_mpi: -1 + 0 (null)
+mbedtls_mpi_add_mpi:16:"-01":16:"":16:"-01"
+
 Test mbedtls_mpi_add_mpi #1
 mbedtls_mpi_add_mpi:10:"203956878356401977405765866929034577280193993314348263094772646453283062722701277632936616063144088173312372882677123879538709400158306567338328279154499698366071906766440037074217117805690872792848149112022286332144876183376326512083574821647933992961249917319836219304274280243803104015000563790123":10:"531872289054204184185084734375133399408303613982130856645299464930952178606045848877129147820387996428175564228204785846141207532462936339834139412401975338705794646595487324365194792822189473092273993580587964571659678084484152603881094176995594813302284232006001752128168901293560051833646881436219":10:"735829167410606161590850601304167976688497607296479119740072111384235241328747126510065763883532084601487937110881909725679916932621242907172467691556475037071866553361927361439411910627880345885122142692610250903804554267860479115964668998643528806263534149325837971432443181537363155848647445226342"
 
@@ -484,18 +778,36 @@
 Test mbedtls_mpi_add_int #2
 mbedtls_mpi_add_int:10:"2039568783564019774057658669290345772801939933143482630947726464532830627227012776329":-9871232:10:"2039568783564019774057658669290345772801939933143482630947726464532830627227002905097"
 
-Base test mbedtls_mpi_sub_abs #1 (Test with larger second input)
+Test mbedtls_mpi_add_int: 0 (null) + 0
+mbedtls_mpi_add_int:16:"":0:16:"0"
+
+Test mbedtls_mpi_add_int: 0 (null) + 1
+mbedtls_mpi_add_int:16:"":1:16:"1"
+
+Base test mbedtls_mpi_sub_abs #1 (|B| > |A|)
 mbedtls_mpi_sub_abs:10:"5":10:"7":10:"0":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
 
-Base test mbedtls_mpi_sub_abs #2 (Test with larger second input)
+Base test mbedtls_mpi_sub_abs #2 (|B| > |A|)
 mbedtls_mpi_sub_abs:10:"-5":10:"-7":10:"0":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
 
-Base test mbedtls_mpi_sub_abs #3 (Test with larger second input)
+Base test mbedtls_mpi_sub_abs #3 (|B| > |A|)
 mbedtls_mpi_sub_abs:10:"-5":10:"7":10:"0":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
 
-Base test mbedtls_mpi_sub_abs #4 (Test with larger second input)
+Base test mbedtls_mpi_sub_abs #4 (|B| > |A|)
 mbedtls_mpi_sub_abs:10:"5":10:"-7":10:"0":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
 
+Base test mbedtls_mpi_sub_abs #1 (|B| >> |A| with more limbs)
+mbedtls_mpi_sub_abs:10:"5":16:"123456789abcdef01":10:"0":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
+
+Base test mbedtls_mpi_sub_abs #2 (|B| >> |A| with more limbs)
+mbedtls_mpi_sub_abs:10:"-5":16:"-123456789abcdef01":10:"0":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
+
+Base test mbedtls_mpi_sub_abs #3 (|B| >> |A| with more limbs)
+mbedtls_mpi_sub_abs:10:"-5":16:"123456789abcdef01":10:"0":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
+
+Base test mbedtls_mpi_sub_abs #4 (|B| >> |A| with more limbs)
+mbedtls_mpi_sub_abs:10:"5":16:"-123456789abcdef01":10:"0":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
+
 Base test mbedtls_mpi_sub_abs #1
 mbedtls_mpi_sub_abs:10:"7":10:"5":10:"2":0
 
@@ -508,6 +820,24 @@
 Base test mbedtls_mpi_sub_abs #4
 mbedtls_mpi_sub_abs:10:"7":10:"-5":10:"2":0
 
+Test mbedtls_mpi_sub_abs: 0 (null) - 0 (null)
+mbedtls_mpi_sub_abs:16:"":16:"":16:"":0
+
+Test mbedtls_mpi_sub_abs: 0 (null) - 0 (1 limb)
+mbedtls_mpi_sub_abs:16:"":16:"00":16:"":0
+
+Test mbedtls_mpi_sub_abs: 0 (1 limb) - 0 (null)
+mbedtls_mpi_sub_abs:16:"00":16:"":16:"":0
+
+Test mbedtls_mpi_sub_abs: 0 (1 limb) - 0 (1 limb)
+mbedtls_mpi_sub_abs:16:"00":16:"00":16:"":0
+
+Test mbedtls_mpi_sub_abs: 1 - 0 (null)
+mbedtls_mpi_sub_abs:16:"01":16:"":16:"01":0
+
+Test mbedtls_mpi_sub_abs: 0 (null) - 1
+mbedtls_mpi_sub_abs:16:"":16:"01":16:"":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
+
 Test mbedtls_mpi_sub_abs #1
 mbedtls_mpi_sub_abs:16:"FFFFFFFFFF":16:"01":16:"FFFFFFFFFE":0
 
@@ -532,6 +862,27 @@
 Base test mbedtls_mpi_sub_mpi #4 (Test with negative subtraction)
 mbedtls_mpi_sub_mpi:10:"5":10:"-7":10:"12"
 
+Test mbedtls_mpi_sub_mpi: 0 (null) - 0 (null)
+mbedtls_mpi_sub_mpi:16:"":16:"":16:"0"
+
+Test mbedtls_mpi_sub_mpi: 0 (null) - 0 (1 limb)
+mbedtls_mpi_sub_mpi:16:"":16:"00":16:"0"
+
+Test mbedtls_mpi_sub_mpi: 0 (null) - 1
+mbedtls_mpi_sub_mpi:16:"":16:"1":16:"-1"
+
+Test mbedtls_mpi_sub_mpi: 0 (null) - -1
+mbedtls_mpi_sub_mpi:16:"":16:"-1":16:"1"
+
+Test mbedtls_mpi_sub_mpi: 0 (1 limb) - 0 (null)
+mbedtls_mpi_sub_mpi:16:"00":16:"":16:"0"
+
+Test mbedtls_mpi_sub_mpi: 1 - 0 (null)
+mbedtls_mpi_sub_mpi:16:"1":16:"":16:"1"
+
+Test mbedtls_mpi_sub_mpi: -1 - 0 (null)
+mbedtls_mpi_sub_mpi:16:"-1":16:"":16:"-1"
+
 Test mbedtls_mpi_sub_mpi #1
 mbedtls_mpi_sub_mpi:10:"531872289054204184185084734375133399408303613982130856645299464930952178606045848877129147820387996428175564228204785846141207532462936339834139412401975338705794646595487324365194792822189473092273993580587964571659678084484152603881094176995594813302284232006001752128168901293560051833646881436219":10:"203956878356401977405765866929034577280193993314348263094772646453283062722701277632936616063144088173312372882677123879538709400158306567338328279154499698366071906766440037074217117805690872792848149112022286332144876183376326512083574821647933992961249917319836219304274280243803104015000563790123":10:"327915410697802206779318867446098822128109620667782593550526818477669115883344571244192531757243908254863191345527661966602498132304629772495811133247475640339722739829047287290977675016498600299425844468565678239514801901107826091797519355347660820341034314686165532823894621049756947818646317646096"
 
@@ -544,12 +895,30 @@
 Test mbedtls_mpi_sub_int #2
 mbedtls_mpi_sub_int:10:"2039568783564019774057658669290345772801939933143482630947726464532830627227012776329":9871232:10:"2039568783564019774057658669290345772801939933143482630947726464532830627227002905097"
 
+Test mbedtls_mpi_sub_int: 0 (null) - 0
+mbedtls_mpi_sub_int:16:"":0:16:"0"
+
+Test mbedtls_mpi_sub_int: 0 (null) - 1
+mbedtls_mpi_sub_int:16:"":1:16:"-1"
+
+Test mbedtls_mpi_sub_int: 0 (null) - -1
+mbedtls_mpi_sub_int:16:"":-1:16:"1"
+
 Test mbedtls_mpi_shift_l #1
 mbedtls_mpi_shift_l:10:"64":1:10:"128"
 
 Test mbedtls_mpi_shift_l #2
 mbedtls_mpi_shift_l:10:"658385546911733550164516088405238961461880256029834598831972039469421755117818013653494814438931957316403111689187691446941406788869098983929874080332195117465344344350008880118042764943201875870917468833709791733282363323948005998269792207":37:10:"90487820548639020691922304619723076305400961610119884872723190678642804168382367856686134531865643066983017249846286450251272364365605022750900439437595355052945035915579216557330505438734955340526145476988250171181404966718289259743378883640981192704"
 
+Test mbedtls_mpi_shift_l: 0 (null) <<= 0
+mbedtls_mpi_shift_l:16:"":0:16:"0"
+
+Test mbedtls_mpi_shift_l: 0 (null) <<= 1
+mbedtls_mpi_shift_l:16:"":1:16:"0"
+
+Test mbedtls_mpi_shift_l: 0 (null) <<= 64
+mbedtls_mpi_shift_l:16:"":64:16:"0"
+
 Test mbedtls_mpi_shift_r #1
 mbedtls_mpi_shift_r:10:"128":1:10:"64"
 
@@ -568,6 +937,15 @@
 Test mbedtls_mpi_shift_r #7
 mbedtls_mpi_shift_r:16:"FFFFFFFFFFFFFFFF":128:16:"00"
 
+Test mbedtls_mpi_shift_r: 0 (null) >>= 0
+mbedtls_mpi_shift_r:16:"":0:16:"0"
+
+Test mbedtls_mpi_shift_r: 0 (null) >>= 1
+mbedtls_mpi_shift_r:16:"":1:16:"0"
+
+Test mbedtls_mpi_shift_r: 0 (null) >>= 64
+mbedtls_mpi_shift_r:16:"":64:16:"0"
+
 Base test mbedtls_mpi_mul_mpi #1
 mbedtls_mpi_mul_mpi:10:"5":10:"7":10:"35"
 
@@ -580,8 +958,131 @@
 Base test mbedtls_mpi_mul_mpi #4
 mbedtls_mpi_mul_mpi:10:"-5":10:"-7":10:"35"
 
+Test mbedtls_mpi_mul_mpi: 0 (null) * 0 (null)
+mbedtls_mpi_mul_mpi:16:"":16:"":16:"0"
+
+Test mbedtls_mpi_mul_mpi: 0 (null) * 0 (1 limb)
+mbedtls_mpi_mul_mpi:16:"":16:"00":16:"0"
+
+Test mbedtls_mpi_mul_mpi: 0 (null) * 1
+mbedtls_mpi_mul_mpi:16:"":16:"01":16:"0"
+
+Test mbedtls_mpi_mul_mpi: 0 (null) * -1
+mbedtls_mpi_mul_mpi:16:"":16:"-01":16:"0"
+
+Test mbedtls_mpi_mul_mpi: 0 (1 limb) * -1
+mbedtls_mpi_mul_mpi:16:"00":16:"-01":16:"0"
+
+Test mbedtls_mpi_mul_mpi: 0 (1 limb) * 0 (null)
+mbedtls_mpi_mul_mpi:16:"00":16:"":16:"0"
+
+Test mbedtls_mpi_mul_mpi: 1 * 0 (null)
+mbedtls_mpi_mul_mpi:16:"01":16:"":16:"0"
+
+Test mbedtls_mpi_mul_mpi: -1 * 0 (null)
+mbedtls_mpi_mul_mpi:16:"-01":16:"":16:"0"
+
+Test mbedtls_mpi_mul_mpi: -1 * 0 (1 limb)
+mbedtls_mpi_mul_mpi:16:"-01":16:"00":16:"0"
+
 Test mbedtls_mpi_mul_mpi #1
-mbedtls_mpi_mul_mpi:10:"28911710017320205966167820725313234361535259163045867986277478145081076845846493521348693253530011243988160148063424837895971948244167867236923919506962312185829914482993478947657472351461336729641485069323635424692930278888923450060546465883490944265147851036817433970984747733020522259537":10:"16471581891701794764704009719057349996270239948993452268812975037240586099924712715366967486587417803753916334331355573776945238871512026832810626226164346328807407669366029926221415383560814338828449642265377822759768011406757061063524768140567867350208554439342320410551341675119078050953":10:"476221599179424887669515829231223263939342135681791605842540429321038144633323941248706405375723482912535192363845116154236465184147599697841273424891410002781967962186252583311115708128167171262206919514587899883547279647025952837516324649656913580411611297312678955801899536937577476819667861053063432906071315727948826276092545739432005962781562403795455162483159362585281248265005441715080197800335757871588045959754547836825977169125866324128449699877076762316768127816074587766799018626179199776188490087103869164122906791440101822594139648973454716256383294690817576188761"
+mbedtls_mpi_mul_mpi:16:"02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb59"
+
+Test mbedtls_mpi_mul_mpi #1, leading 0 limb in B
+mbedtls_mpi_mul_mpi:16:"02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"000000000000000001b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb59"
+
+Test mbedtls_mpi_mul_mpi #1, leading 0 limb in B, A < 0
+mbedtls_mpi_mul_mpi:16:"-02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"000000000000000001b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"-0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb59"
+
+Test mbedtls_mpi_mul_mpi #1, leading 0 limb in B, B < 0
+mbedtls_mpi_mul_mpi:16:"02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"-000000000000000001b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"-0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb59"
+
+Test mbedtls_mpi_mul_mpi #1, leading 0 limb in B, A < 0, B < 0
+mbedtls_mpi_mul_mpi:16:"-02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"-000000000000000001b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb59"
+
+Test mbedtls_mpi_mul_mpi #1, leading 0 limb in A
+mbedtls_mpi_mul_mpi:16:"000000000000000002f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb59"
+
+Test mbedtls_mpi_mul_mpi #1, leading 0 limb in A, A < 0
+mbedtls_mpi_mul_mpi:16:"-000000000000000002f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"-0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb59"
+
+Test mbedtls_mpi_mul_mpi #1, leading 0 limb in A, B < 0
+mbedtls_mpi_mul_mpi:16:"000000000000000002f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"-01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"-0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb59"
+
+Test mbedtls_mpi_mul_mpi #1, leading 0 limb in A, A < 0, B < 0
+mbedtls_mpi_mul_mpi:16:"-000000000000000002f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"-01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb59"
+
+Test mbedtls_mpi_mul_mpi #1, leading 0 limb in A and B
+mbedtls_mpi_mul_mpi:16:"000000000000000002f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"000000000000000001b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb59"
+
+Test mbedtls_mpi_mul_mpi #1, leading 0 limb in A and B, A < 0
+mbedtls_mpi_mul_mpi:16:"-000000000000000002f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"000000000000000001b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"-0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb59"
+
+Test mbedtls_mpi_mul_mpi #1, leading 0 limb in A and B, B < 0
+mbedtls_mpi_mul_mpi:16:"000000000000000002f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"-000000000000000001b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"-0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb59"
+
+Test mbedtls_mpi_mul_mpi #1, leading 0 limb in A and B, A < 0, B < 0
+mbedtls_mpi_mul_mpi:16:"-000000000000000002f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"-000000000000000001b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb59"
+
+Test mbedtls_mpi_mul_mpi #2, trailing 0 limb in A
+mbedtls_mpi_mul_mpi:16:"02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf24510000000000000000":16:"01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb590000000000000000"
+
+Test mbedtls_mpi_mul_mpi #2, trailing 0 limb in A, A < 0
+mbedtls_mpi_mul_mpi:16:"-02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf24510000000000000000":16:"01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"-0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb590000000000000000"
+
+Test mbedtls_mpi_mul_mpi #2, trailing 0 limb in A, B < 0
+mbedtls_mpi_mul_mpi:16:"02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf24510000000000000000":16:"-01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"-0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb590000000000000000"
+
+Test mbedtls_mpi_mul_mpi #2, trailing 0 limb in A, A < 0, B < 0
+mbedtls_mpi_mul_mpi:16:"-02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf24510000000000000000":16:"-01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb590000000000000000"
+
+Test mbedtls_mpi_mul_mpi #2, trailing 0 limb in B
+mbedtls_mpi_mul_mpi:16:"02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c890000000000000000":16:"0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb590000000000000000"
+
+Test mbedtls_mpi_mul_mpi #2, trailing 0 limb in B, A < 0
+mbedtls_mpi_mul_mpi:16:"-02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c890000000000000000":16:"-0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb590000000000000000"
+
+Test mbedtls_mpi_mul_mpi #2, trailing 0 limb in B, B < 0
+mbedtls_mpi_mul_mpi:16:"02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"-01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c890000000000000000":16:"-0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb590000000000000000"
+
+Test mbedtls_mpi_mul_mpi #2, trailing 0 limb in B, A < 0, B < 0
+mbedtls_mpi_mul_mpi:16:"-02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"-01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c890000000000000000":16:"0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb590000000000000000"
+
+Test mbedtls_mpi_mul_mpi #2, trailing 0 limb in A and B
+mbedtls_mpi_mul_mpi:16:"02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf24510000000000000000":16:"01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c890000000000000000":16:"0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb5900000000000000000000000000000000"
+
+Test mbedtls_mpi_mul_mpi #2, trailing 0 limb in A and B, A < 0
+mbedtls_mpi_mul_mpi:16:"-02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf24510000000000000000":16:"01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c890000000000000000":16:"-0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb5900000000000000000000000000000000"
+
+Test mbedtls_mpi_mul_mpi #2, trailing 0 limb in A and B, B < 0
+mbedtls_mpi_mul_mpi:16:"02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf24510000000000000000":16:"-01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c890000000000000000":16:"-0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb5900000000000000000000000000000000"
+
+Test mbedtls_mpi_mul_mpi #2, trailing 0 limb in A and B, A < 0, B < 0
+mbedtls_mpi_mul_mpi:16:"-02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf24510000000000000000":16:"-01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c890000000000000000":16:"0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb5900000000000000000000000000000000"
+
+Test mbedtls_mpi_mul_mpi #3, trailing 0 limbs in A
+mbedtls_mpi_mul_mpi:16:"02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf245100000000000000000000000000000000":16:"01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb5900000000000000000000000000000000"
+
+Test mbedtls_mpi_mul_mpi #3, trailing 0 limbs in A, A < 0
+mbedtls_mpi_mul_mpi:16:"-02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf245100000000000000000000000000000000":16:"01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"-0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb5900000000000000000000000000000000"
+
+Test mbedtls_mpi_mul_mpi #3, trailing 0 limbs in A, B < 0
+mbedtls_mpi_mul_mpi:16:"02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf245100000000000000000000000000000000":16:"-01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"-0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb5900000000000000000000000000000000"
+
+Test mbedtls_mpi_mul_mpi #3, trailing 0 limbs in A, A < 0, B < 0
+mbedtls_mpi_mul_mpi:16:"-02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf245100000000000000000000000000000000":16:"-01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c89":16:"0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb5900000000000000000000000000000000"
+
+Test mbedtls_mpi_mul_mpi #3, trailing 0 limbs in B
+mbedtls_mpi_mul_mpi:16:"02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c8900000000000000000000000000000000":16:"0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb5900000000000000000000000000000000"
+
+Test mbedtls_mpi_mul_mpi #3, trailing 0 limbs in B, A < 0
+mbedtls_mpi_mul_mpi:16:"-02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c8900000000000000000000000000000000":16:"-0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb5900000000000000000000000000000000"
+
+Test mbedtls_mpi_mul_mpi #3, trailing 0 limbs in B, B < 0
+mbedtls_mpi_mul_mpi:16:"02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"-01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c8900000000000000000000000000000000":16:"-0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb5900000000000000000000000000000000"
+
+Test mbedtls_mpi_mul_mpi #3, trailing 0 limbs in B, A < 0, B < 0
+mbedtls_mpi_mul_mpi:16:"-02f77b94b179d4a51360f04fa56e2c0784ce3b8a742280b016904896a5605fbe9e0f0683f82c439d979ab14e11b34e05ae96232b18fb2e0d1319f4942732d7eadf92ae90cb8c68ec8ece154d334f553564b6f6db185b33b8d3635598c3d128acde8bbb7b13697e48d1a542e5f9168d2d83a8dd05ae1eaf2451":16:"-01b0b14c432710cde936e3fc100515e95dca61e10b8a68d9632bfa0546a9731a1ce6bebc6cb5fe6f5fd7e57b25f737f6a0ce5402e216b8b81c06f0c5ccce447d7f5631d14bff9dfa16f7cc72c56c84b636d00a5f35199d17ee9bf3f8746f44374ffd4ae22cf84089f04a9f7f356d6dc9f8cf8ef208a9b88c8900000000000000000000000000000000":16:"0503ae899d35ae5b7706b067aed7cb2952da37a5d4ad58f05f69abe14e8aaae88eab2baed858177cb4595c0edc92e5ac13c2bba2bfa23276dd023e9e52f547d4c9edb138d86aad329d7afb01e15eab7281e181cb249fc91bf09d621d86561301edda156f80e3bbff853a312852fe9e3d0541cb86801390aff1dc3c05bcb592c266f625b70e419b4c7e7e85399bb06c0e50b099b4292f9eaff4d869681faa1f745b5fcb3349ed93c572739a31dcf76b43370cf9f86cc54e982dfac9467bde915c697e60554e0d698be6bb2dd1f8bc64659f6baee7641b51f4b5ed7010c04600fcd382db84a93fe3d4d86e86a459c6cebb5900000000000000000000000000000000"
 
 Test mbedtls_mpi_mul_int #1
 mbedtls_mpi_mul_int:10:"2039568783564019774057658669290345772801939933143482630947726464532830627227012776329":9871232:10:"20133056642518226042310730101376278483547239130123806338055387803943342738063359782107667328":"=="
@@ -595,15 +1096,45 @@
 Test mbedtls_mpi_mul_int #4 (Unsigned, thus failure)
 mbedtls_mpi_mul_int:10:"-2039568783564019774057658669290345772801939933143482630947726464532830627227012776329":-9871232:10:"20133056642518226042310730101376278483547239130123806338055387803943342738063359782107667328":"!="
 
+Test mbedtls_mpi_mul_int: 0 (null) * 0
+mbedtls_mpi_mul_int:16:"":0:16:"":"=="
+
+Test mbedtls_mpi_mul_int: 0 (null) * 1
+mbedtls_mpi_mul_int:16:"":1:16:"":"=="
+
+Test mbedtls_mpi_mul_int: 0 (null) * 0x1234
+mbedtls_mpi_mul_int:16:"":0x1234:16:"":"=="
+
 Base test mbedtls_mpi_div_mpi #1
 mbedtls_mpi_div_mpi:10:"1000":10:"13":10:"76":10:"12":0
 
-Base test mbedtls_mpi_div_mpi #2 (Divide by zero)
+Base test mbedtls_mpi_div_mpi #2 (Divide by zero (1 limb))
 mbedtls_mpi_div_mpi:10:"1000":10:"0":10:"1":10:"1":MBEDTLS_ERR_MPI_DIVISION_BY_ZERO
 
+Base test mbedtls_mpi_div_mpi #2 (Divide by zero (null))
+mbedtls_mpi_div_mpi:10:"1000":10:"":10:"1":10:"1":MBEDTLS_ERR_MPI_DIVISION_BY_ZERO
+
 Base test mbedtls_mpi_div_mpi #3
 mbedtls_mpi_div_mpi:10:"1000":10:"-13":10:"-76":10:"12":0
 
+Test mbedtls_mpi_div_mpi: 0 (null) / 0 (null)
+mbedtls_mpi_div_mpi:16:"":16:"":16:"":16:"":MBEDTLS_ERR_MPI_DIVISION_BY_ZERO
+
+Test mbedtls_mpi_div_mpi: 0 (null) / 0 (1 limb)
+mbedtls_mpi_div_mpi:16:"":16:"0":16:"":16:"":MBEDTLS_ERR_MPI_DIVISION_BY_ZERO
+
+Test mbedtls_mpi_div_mpi: 0 (1 limb) / 0 (null)
+mbedtls_mpi_div_mpi:16:"0":16:"":16:"":16:"":MBEDTLS_ERR_MPI_DIVISION_BY_ZERO
+
+Test mbedtls_mpi_div_mpi: 0 (1 limb) / 0 (1 limb)
+mbedtls_mpi_div_mpi:16:"0":16:"0":16:"":16:"":MBEDTLS_ERR_MPI_DIVISION_BY_ZERO
+
+Test mbedtls_mpi_div_mpi: 0 (null) / 1
+mbedtls_mpi_div_mpi:16:"":16:"1":16:"":16:"":0
+
+Test mbedtls_mpi_div_mpi: 0 (null) / -1
+mbedtls_mpi_div_mpi:16:"":16:"-1":16:"":16:"":0
+
 Test mbedtls_mpi_div_mpi #1
 mbedtls_mpi_div_mpi:10:"20133056642518226042310730101376278483547239130123806338055387803943342738063359782107667328":10:"34":10:"592148724779947824773845002981655249516095268533053127589864347174804198178334111238460803":10:"26":0
 
@@ -631,10 +1162,22 @@
 Test mbedtls_mpi_div_int #2
 mbedtls_mpi_div_int:10:"20133056642518226042310730101376278483547239130123806338055387803943342738063359782107667328":-34:10:"-592148724779947824773845002981655249516095268533053127589864347174804198178334111238460803":10:"26":0
 
+Test mbedtls_mpi_div_int: 0 (null) / 0
+mbedtls_mpi_div_int:16:"":0:16:"":16:"":MBEDTLS_ERR_MPI_DIVISION_BY_ZERO
+
+Test mbedtls_mpi_div_int: 0 (1 limb) / 0
+mbedtls_mpi_div_int:16:"00":0:16:"":16:"":MBEDTLS_ERR_MPI_DIVISION_BY_ZERO
+
+Test mbedtls_mpi_div_int: 0 (null) / 1
+mbedtls_mpi_div_int:16:"":1:16:"":16:"":0
+
 Base test mbedtls_mpi_mod_mpi #1
 mbedtls_mpi_mod_mpi:10:"1000":10:"13":10:"12":0
 
-Base test mbedtls_mpi_mod_mpi #2 (Divide by zero)
+Base test mbedtls_mpi_mod_mpi #2 (Divide by zero (null))
+mbedtls_mpi_mod_mpi:10:"1000":10:"":10:"0":MBEDTLS_ERR_MPI_DIVISION_BY_ZERO
+
+Base test mbedtls_mpi_mod_mpi #2 (Divide by zero (1 limb))
 mbedtls_mpi_mod_mpi:10:"1000":10:"0":10:"0":MBEDTLS_ERR_MPI_DIVISION_BY_ZERO
 
 Base test mbedtls_mpi_mod_mpi #3
@@ -646,6 +1189,12 @@
 Base test mbedtls_mpi_mod_mpi #5 (Negative modulo)
 mbedtls_mpi_mod_mpi:10:"-1000":10:"-13":10:"-12":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
 
+Test mbedtls_mpi_mod_mpi: 0 (null) % 1
+mbedtls_mpi_mod_mpi:16:"":16:"1":16:"":0
+
+Test mbedtls_mpi_mod_mpi: 0 (null) % -1
+mbedtls_mpi_mod_mpi:16:"":16:"-1":16:"":MBEDTLS_ERR_MPI_NEGATIVE_VALUE
+
 Base test mbedtls_mpi_mod_int #1
 mbedtls_mpi_mod_int:10:"1000":13:12:0
 
@@ -670,23 +1219,74 @@
 Base test mbedtls_mpi_mod_int #8 (By 2)
 mbedtls_mpi_mod_int:10:"1000":2:0:0
 
+Test mbedtls_mpi_mod_int: 0 (null) % 1
+mbedtls_mpi_mod_int:16:"":1:0:0
+
+Test mbedtls_mpi_mod_int: 0 (null) % -1
+mbedtls_mpi_mod_int:16:"":-1:0:MBEDTLS_ERR_MPI_NEGATIVE_VALUE
+
 Base test mbedtls_mpi_exp_mod #1
-mbedtls_mpi_exp_mod:10:"23":10:"13":10:"29":10:"":10:"24":0
+mbedtls_mpi_exp_mod:10:"23":10:"13":10:"29":10:"24":0
 
 Base test mbedtls_mpi_exp_mod #2 (Even N)
-mbedtls_mpi_exp_mod:10:"23":10:"13":10:"30":10:"":10:"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+mbedtls_mpi_exp_mod:10:"23":10:"13":10:"30":10:"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+Base test mbedtls_mpi_exp_mod #2 (N = 0 (null))
+mbedtls_mpi_exp_mod:10:"23":10:"13":10:"":10:"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
 Base test mbedtls_mpi_exp_mod #3 (Negative N)
-mbedtls_mpi_exp_mod:10:"23":10:"13":10:"-29":10:"":10:"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+mbedtls_mpi_exp_mod:10:"23":10:"13":10:"-29":10:"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
 Base test mbedtls_mpi_exp_mod #4 (Negative base)
-mbedtls_mpi_exp_mod:10:"-23":10:"13":10:"29":10:"":10:"5":0
+mbedtls_mpi_exp_mod:10:"-23":10:"13":10:"29":10:"5":0
 
 Base test mbedtls_mpi_exp_mod #5 (Negative exponent)
-mbedtls_mpi_exp_mod:10:"23":10:"-13":10:"29":10:"":10:"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+mbedtls_mpi_exp_mod:10:"23":10:"-13":10:"29":10:"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
 Base test mbedtls_mpi_exp_mod #6 (Negative base + exponent)
-mbedtls_mpi_exp_mod:10:"-23":10:"-13":10:"29":10:"":10:"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+mbedtls_mpi_exp_mod:10:"-23":10:"-13":10:"29":10:"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+Test mbedtls_mpi_exp_mod: 0 (null) ^ 0 (null) mod 9
+mbedtls_mpi_exp_mod:16:"":16:"":16:"09":16:"1":0
+
+Test mbedtls_mpi_exp_mod: 0 (null) ^ 0 (1 limb) mod 9
+mbedtls_mpi_exp_mod:16:"":16:"00":16:"09":16:"1":0
+
+Test mbedtls_mpi_exp_mod: 0 (null) ^ 1 mod 9
+mbedtls_mpi_exp_mod:16:"":16:"01":16:"09":16:"":0
+
+Test mbedtls_mpi_exp_mod: 0 (null) ^ 2 mod 9
+mbedtls_mpi_exp_mod:16:"":16:"02":16:"09":16:"":0
+
+Test mbedtls_mpi_exp_mod: 0 (1 limb) ^ 0 (null) mod 9
+mbedtls_mpi_exp_mod:16:"00":16:"":16:"09":16:"1":0
+
+Test mbedtls_mpi_exp_mod: 0 (1 limb) ^ 0 (1 limb) mod 9
+mbedtls_mpi_exp_mod:16:"00":16:"00":16:"09":16:"1":0
+
+Test mbedtls_mpi_exp_mod: 0 (1 limb) ^ 1 mod 9
+mbedtls_mpi_exp_mod:16:"00":16:"01":16:"09":16:"":0
+
+Test mbedtls_mpi_exp_mod: 0 (1 limb) ^ 2 mod 9
+mbedtls_mpi_exp_mod:16:"00":16:"02":16:"09":16:"":0
+
+Test mbedtls_mpi_exp_mod: 1 ^ 0 (null) mod 9
+mbedtls_mpi_exp_mod:16:"01":16:"":16:"09":16:"1":0
+
+Test mbedtls_mpi_exp_mod: 4 ^ 0 (null) mod 9
+mbedtls_mpi_exp_mod:16:"04":16:"":16:"09":16:"1":0
+
+Test mbedtls_mpi_exp_mod: 10 ^ 0 (null) mod 9
+mbedtls_mpi_exp_mod:16:"0a":16:"":16:"09":16:"1":0
+
+Test mbedtls_mpi_exp_mod: 1 ^ 0 (1 limb) mod 9
+mbedtls_mpi_exp_mod:16:"01":16:"00":16:"09":16:"1":0
+
+Test mbedtls_mpi_exp_mod: 4 ^ 0 (1 limb) mod 9
+mbedtls_mpi_exp_mod:16:"04":16:"00":16:"09":16:"1":0
+
+Test mbedtls_mpi_exp_mod: 10 ^ 0 (1 limb) mod 9
+mbedtls_mpi_exp_mod:16:"0a":16:"00":16:"09":16:"1":0
 
 Test mbedtls_mpi_exp_mod: MAX_SIZE exponent
 mbedtls_mpi_exp_mod_size:2:MBEDTLS_MPI_MAX_SIZE:10:10:"":0
@@ -708,14 +1308,14 @@
 
 Test mbedtls_mpi_exp_mod #1
 depends_on:MPI_MAX_BITS_LARGER_THAN_792
-mbedtls_mpi_exp_mod:10:"433019240910377478217373572959560109819648647016096560523769010881172869083338285573756574557395862965095016483867813043663981946477698466501451832407592327356331263124555137732393938242285782144928753919588632679050799198937132922145084847":10:"5781538327977828897150909166778407659250458379645823062042492461576758526757490910073628008613977550546382774775570888130029763571528699574717583228939535960234464230882573615930384979100379102915657483866755371559811718767760594919456971354184113721":10:"583137007797276923956891216216022144052044091311388601652961409557516421612874571554415606746479105795833145583959622117418531166391184939066520869800857530421873250114773204354963864729386957427276448683092491947566992077136553066273207777134303397724679138833126700957":10:"":10:"114597449276684355144920670007147953232659436380163461553186940113929777196018164149703566472936578890991049344459204199888254907113495794730452699842273939581048142004834330369483813876618772578869083248061616444392091693787039636316845512292127097865026290173004860736":0
+mbedtls_mpi_exp_mod:10:"433019240910377478217373572959560109819648647016096560523769010881172869083338285573756574557395862965095016483867813043663981946477698466501451832407592327356331263124555137732393938242285782144928753919588632679050799198937132922145084847":10:"5781538327977828897150909166778407659250458379645823062042492461576758526757490910073628008613977550546382774775570888130029763571528699574717583228939535960234464230882573615930384979100379102915657483866755371559811718767760594919456971354184113721":10:"583137007797276923956891216216022144052044091311388601652961409557516421612874571554415606746479105795833145583959622117418531166391184939066520869800857530421873250114773204354963864729386957427276448683092491947566992077136553066273207777134303397724679138833126700957":10:"114597449276684355144920670007147953232659436380163461553186940113929777196018164149703566472936578890991049344459204199888254907113495794730452699842273939581048142004834330369483813876618772578869083248061616444392091693787039636316845512292127097865026290173004860736":0
 
 Test mbedtls_mpi_exp_mod (Negative base) [#1]
-mbedtls_mpi_exp_mod:10:"-10000000000":10:"10000000000":10:"99999":10:"":10:"1":0
+mbedtls_mpi_exp_mod:10:"-10000000000":10:"10000000000":10:"99999":10:"1":0
 
 Test mbedtls_mpi_exp_mod (Negative base) [#2]
 depends_on:MPI_MAX_BITS_LARGER_THAN_792
-mbedtls_mpi_exp_mod:16:"-9f13012cd92aa72fb86ac8879d2fde4f7fd661aaae43a00971f081cc60ca277059d5c37e89652e2af2585d281d66ef6a9d38a117e9608e9e7574cd142dc55278838a2161dd56db9470d4c1da2d5df15a908ee2eb886aaa890f23be16de59386663a12f1afbb325431a3e835e3fd89b98b96a6f77382f458ef9a37e1f84a03045c8676ab55291a94c2228ea15448ee96b626b998":16:"40a54d1b9e86789f06d9607fb158672d64867665c73ee9abb545fc7a785634b354c7bae5b962ce8040cf45f2c1f3d3659b2ee5ede17534c8fc2ec85c815e8df1fe7048d12c90ee31b88a68a081f17f0d8ce5f4030521e9400083bcea73a429031d4ca7949c2000d597088e0c39a6014d8bf962b73bb2e8083bd0390a4e00b9b3":16:"eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c256576d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089dad15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e57ec68edbc3c05726cc02fd4cbf4976eaa9afd5138fe8376435b9fc61d2fc0eb06e3":16:"":16:"21acc7199e1b90f9b4844ffe12c19f00ec548c5d32b21c647d48b6015d8eb9ec9db05b4f3d44db4227a2b5659c1a7cceb9d5fa8fa60376047953ce7397d90aaeb7465e14e820734f84aa52ad0fc66701bcbb991d57715806a11531268e1e83dd48288c72b424a6287e9ce4e5cc4db0dd67614aecc23b0124a5776d36e5c89483":0
+mbedtls_mpi_exp_mod:16:"-9f13012cd92aa72fb86ac8879d2fde4f7fd661aaae43a00971f081cc60ca277059d5c37e89652e2af2585d281d66ef6a9d38a117e9608e9e7574cd142dc55278838a2161dd56db9470d4c1da2d5df15a908ee2eb886aaa890f23be16de59386663a12f1afbb325431a3e835e3fd89b98b96a6f77382f458ef9a37e1f84a03045c8676ab55291a94c2228ea15448ee96b626b998":16:"40a54d1b9e86789f06d9607fb158672d64867665c73ee9abb545fc7a785634b354c7bae5b962ce8040cf45f2c1f3d3659b2ee5ede17534c8fc2ec85c815e8df1fe7048d12c90ee31b88a68a081f17f0d8ce5f4030521e9400083bcea73a429031d4ca7949c2000d597088e0c39a6014d8bf962b73bb2e8083bd0390a4e00b9b3":16:"eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c256576d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089dad15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e57ec68edbc3c05726cc02fd4cbf4976eaa9afd5138fe8376435b9fc61d2fc0eb06e3":16:"21acc7199e1b90f9b4844ffe12c19f00ec548c5d32b21c647d48b6015d8eb9ec9db05b4f3d44db4227a2b5659c1a7cceb9d5fa8fa60376047953ce7397d90aaeb7465e14e820734f84aa52ad0fc66701bcbb991d57715806a11531268e1e83dd48288c72b424a6287e9ce4e5cc4db0dd67614aecc23b0124a5776d36e5c89483":0
 
 Base test GCD #1
 mbedtls_mpi_gcd:10:"693":10:"609":10:"21"
@@ -726,24 +1326,105 @@
 Base test GCD #3
 mbedtls_mpi_gcd:10:"768454923":10:"542167814":10:"1"
 
-Test GCD #1
+Test GCD: 0 (null), 0 (null)
+mbedtls_mpi_gcd:16:"":16:"":16:"0"
+
+Test GCD: 0 (null), 0 (1 limb)
+mbedtls_mpi_gcd:16:"":16:"00":16:"0"
+
+Test GCD: 0 (null), 3
+mbedtls_mpi_gcd:16:"":16:"03":16:"3"
+
+Test GCD: 0 (null), 6
+mbedtls_mpi_gcd:16:"":16:"06":16:"6"
+
+Test GCD: 0 (1 limb), 0 (null)
+mbedtls_mpi_gcd:16:"00":16:"":16:"0"
+
+Test GCD: 0 (1 limb), 3
+mbedtls_mpi_gcd:16:"00":16:"03":16:"3"
+
+Test GCD: 0 (1 limb), 6
+mbedtls_mpi_gcd:16:"00":16:"06":16:"6"
+
+Test GCD: 3, 0 (null)
+mbedtls_mpi_gcd:16:"03":16:"":16:"3"
+
+Test GCD: 3, 0 (1 limb)
+mbedtls_mpi_gcd:16:"03":16:"00":16:"3"
+
+Test GCD: 6, 0 (null)
+mbedtls_mpi_gcd:16:"06":16:"":16:"6"
+
+Test GCD: 6, 0 (1 limb)
+mbedtls_mpi_gcd:16:"06":16:"00":16:"6"
+
+Test GCD: gcd=1, 0 < A < B
 mbedtls_mpi_gcd:10:"433019240910377478217373572959560109819648647016096560523769010881172869083338285573756574557395862965095016483867813043663981946477698466501451832407592327356331263124555137732393938242285782144928753919588632679050799198937132922145084847":10:"5781538327977828897150909166778407659250458379645823062042492461576758526757490910073628008613977550546382774775570888130029763571528699574717583228939535960234464230882573615930384979100379102915657483866755371559811718767760594919456971354184113721":10:"1"
 
+Test GCD: gcd=1, 0 < B < A
+mbedtls_mpi_gcd:10:"5781538327977828897150909166778407659250458379645823062042492461576758526757490910073628008613977550546382774775570888130029763571528699574717583228939535960234464230882573615930384979100379102915657483866755371559811718767760594919456971354184113721":10:"433019240910377478217373572959560109819648647016096560523769010881172869083338285573756574557395862965095016483867813043663981946477698466501451832407592327356331263124555137732393938242285782144928753919588632679050799198937132922145084847":10:"1"
+
+Test GCD: gcd=1, A > 0, B < 0
+mbedtls_mpi_gcd:10:"433019240910377478217373572959560109819648647016096560523769010881172869083338285573756574557395862965095016483867813043663981946477698466501451832407592327356331263124555137732393938242285782144928753919588632679050799198937132922145084847":10:"-5781538327977828897150909166778407659250458379645823062042492461576758526757490910073628008613977550546382774775570888130029763571528699574717583228939535960234464230882573615930384979100379102915657483866755371559811718767760594919456971354184113721":10:"1"
+
+Test GCD: gcd=1, A < 0 < B, |A| < |B|
+mbedtls_mpi_gcd:10:"-433019240910377478217373572959560109819648647016096560523769010881172869083338285573756574557395862965095016483867813043663981946477698466501451832407592327356331263124555137732393938242285782144928753919588632679050799198937132922145084847":10:"5781538327977828897150909166778407659250458379645823062042492461576758526757490910073628008613977550546382774775570888130029763571528699574717583228939535960234464230882573615930384979100379102915657483866755371559811718767760594919456971354184113721":10:"1"
+
+Test GCD: gcd=1, B < A < 0
+mbedtls_mpi_gcd:10:"-433019240910377478217373572959560109819648647016096560523769010881172869083338285573756574557395862965095016483867813043663981946477698466501451832407592327356331263124555137732393938242285782144928753919588632679050799198937132922145084847":10:"-5781538327977828897150909166778407659250458379645823062042492461576758526757490910073628008613977550546382774775570888130029763571528699574717583228939535960234464230882573615930384979100379102915657483866755371559811718767760594919456971354184113721":10:"1"
+
+Test GCD: gcd=2, 0 < A < B
+mbedtls_mpi_gcd:10:"866038481820754956434747145919120219639297294032193121047538021762345738166676571147513149114791725930190032967735626087327963892955396933002903664815184654712662526249110275464787876484571564289857507839177265358101598397874265844290169694":10:"11563076655955657794301818333556815318500916759291646124084984923153517053514981820147256017227955101092765549551141776260059527143057399149435166457879071920468928461765147231860769958200758205831314967733510743119623437535521189838913942708368227442":10:"2"
+
+Test GCD: gcd=2, 0 < B < A
+mbedtls_mpi_gcd:10:"11563076655955657794301818333556815318500916759291646124084984923153517053514981820147256017227955101092765549551141776260059527143057399149435166457879071920468928461765147231860769958200758205831314967733510743119623437535521189838913942708368227442":10:"866038481820754956434747145919120219639297294032193121047538021762345738166676571147513149114791725930190032967735626087327963892955396933002903664815184654712662526249110275464787876484571564289857507839177265358101598397874265844290169694":10:"2"
+
+Test GCD: gcd=3, 0 < A < B
+mbedtls_mpi_gcd:10:"1299057722731132434652120718878680329458945941048289681571307032643518607250014856721269723672187588895285049451603439130991945839433095399504355497222776982068993789373665413197181814726857346434786261758765898037152397596811398766435254541":10:"17344614983933486691452727500335222977751375138937469186127477384730275580272472730220884025841932651639148324326712664390089290714586098724152749686818607880703392692647720847791154937301137308746972451600266114679435156303281784758370914062552341163":10:"3"
+
+Test GCD: gcd=3, 0 < B < A
+mbedtls_mpi_gcd:10:"17344614983933486691452727500335222977751375138937469186127477384730275580272472730220884025841932651639148324326712664390089290714586098724152749686818607880703392692647720847791154937301137308746972451600266114679435156303281784758370914062552341163":10:"1299057722731132434652120718878680329458945941048289681571307032643518607250014856721269723672187588895285049451603439130991945839433095399504355497222776982068993789373665413197181814726857346434786261758765898037152397596811398766435254541":10:"3"
+
+Test GCD: gcd=4, 0 < A < B
+mbedtls_mpi_gcd:10:"1732076963641509912869494291838240439278594588064386242095076043524691476333353142295026298229583451860380065935471252174655927785910793866005807329630369309425325052498220550929575752969143128579715015678354530716203196795748531688580339388":10:"23126153311911315588603636667113630637001833518583292248169969846307034107029963640294512034455910202185531099102283552520119054286114798298870332915758143840937856923530294463721539916401516411662629935467021486239246875071042379677827885416736454884":10:"4"
+
+Test GCD: gcd=4, 0 < B < A
+mbedtls_mpi_gcd:10:"23126153311911315588603636667113630637001833518583292248169969846307034107029963640294512034455910202185531099102283552520119054286114798298870332915758143840937856923530294463721539916401516411662629935467021486239246875071042379677827885416736454884":10:"1732076963641509912869494291838240439278594588064386242095076043524691476333353142295026298229583451860380065935471252174655927785910793866005807329630369309425325052498220550929575752969143128579715015678354530716203196795748531688580339388":10:"4"
+
+Test GCD: gcd=6, 0 < A < B
+mbedtls_mpi_gcd:10:"2598115445462264869304241437757360658917891882096579363142614065287037214500029713442539447344375177790570098903206878261983891678866190799008710994445553964137987578747330826394363629453714692869572523517531796074304795193622797532870509082":10:"34689229967866973382905455000670445955502750277874938372254954769460551160544945460441768051683865303278296648653425328780178581429172197448305499373637215761406785385295441695582309874602274617493944903200532229358870312606563569516741828125104682326":10:"6"
+
+Test GCD: gcd=6, 0 < B < A
+mbedtls_mpi_gcd:10:"34689229967866973382905455000670445955502750277874938372254954769460551160544945460441768051683865303278296648653425328780178581429172197448305499373637215761406785385295441695582309874602274617493944903200532229358870312606563569516741828125104682326":10:"2598115445462264869304241437757360658917891882096579363142614065287037214500029713442539447344375177790570098903206878261983891678866190799008710994445553964137987578747330826394363629453714692869572523517531796074304795193622797532870509082":10:"6"
+
+Test GCD: 0 < A = B
+mbedtls_mpi_gcd:10:"433019240910377478217373572959560109819648647016096560523769010881172869083338285573756574557395862965095016483867813043663981946477698466501451832407592327356331263124555137732393938242285782144928753919588632679050799198937132922145084847":10:"433019240910377478217373572959560109819648647016096560523769010881172869083338285573756574557395862965095016483867813043663981946477698466501451832407592327356331263124555137732393938242285782144928753919588632679050799198937132922145084847":10:"433019240910377478217373572959560109819648647016096560523769010881172869083338285573756574557395862965095016483867813043663981946477698466501451832407592327356331263124555137732393938242285782144928753919588632679050799198937132922145084847"
+
 Base test mbedtls_mpi_inv_mod #1
 mbedtls_mpi_inv_mod:10:"3":10:"11":10:"4":0
 
-Base test mbedtls_mpi_inv_mod #2
+Test mbedtls_mpi_inv_mod: mod 0 (null)
+mbedtls_mpi_inv_mod:10:"3":10:"":10:"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+Test mbedtls_mpi_inv_mod: mod 0 (1 limb)
 mbedtls_mpi_inv_mod:10:"3":10:"0":10:"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
-Base test mbedtls_mpi_inv_mod #3
+Test mbedtls_mpi_inv_mod: mod negative
 mbedtls_mpi_inv_mod:10:"3":10:"-11":10:"4":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
-Base test mbedtls_mpi_inv_mod #4
+Test mbedtls_mpi_inv_mod: 2^-1 mod 4
 mbedtls_mpi_inv_mod:10:"2":10:"4":10:"0":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
 
-Base test mbedtls_mpi_inv_mod #5
+Test mbedtls_mpi_inv_mod: mod 1
 mbedtls_mpi_inv_mod:10:"3":10:"1":10:"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
+Test mbedtls_mpi_inv_mod: 0 (null) ^-1
+mbedtls_mpi_inv_mod:16:"":16:"11":16:"":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+
+Test mbedtls_mpi_inv_mod: 0 (1 limb) ^-1
+mbedtls_mpi_inv_mod:16:"00":16:"11":16:"":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+
 Test mbedtls_mpi_inv_mod #1
 mbedtls_mpi_inv_mod:16:"aa4df5cb14b4c31237f98bd1faf527c283c2d0f3eec89718664ba33f9762907c":16:"fffbbd660b94412ae61ead9c2906a344116e316a256fd387874c6c675b1d587d":16:"8d6a5c1d7adeae3e94b9bcd2c47e0d46e778bc8804a2cc25c02d775dc3d05b0c":0
 
@@ -928,6 +1609,9 @@
 Test bit getting (Larger and non-existing limb)
 mbedtls_mpi_get_bit:10:"49979687":500:0
 
+Test bit getting in 0 (null)
+mbedtls_mpi_get_bit:10:"":500:0
+
 Test bit getting (Value bit 24)
 mbedtls_mpi_get_bit:10:"49979687":24:0
 
@@ -946,6 +1630,12 @@
 Test bit set (Add above existing limbs with a 1)
 mbedtls_mpi_set_bit:10:"49979687":80:1:10:"1208925819614629224685863":0
 
+Test bit set (Add to 0 (null) with a 0)
+mbedtls_mpi_set_bit:16:"":65:0:16:"":0
+
+Test bit set (Add to 0 (null) with a 1)
+mbedtls_mpi_set_bit:16:"":65:1:16:"020000000000000000":0
+
 Test bit set (Bit index larger than 31 with a 0)
 mbedtls_mpi_set_bit:16:"FFFFFFFFFFFFFFFF":32:0:16:"FFFFFFFEFFFFFFFF":0
 
@@ -956,46 +1646,246 @@
 mbedtls_mpi_set_bit:16:"00":5:2:16:"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
 Fill random: 0 bytes
-mpi_fill_random:0:0:0
+mpi_fill_random:0:0:0:0
 
 Fill random: 1 byte, good
-mpi_fill_random:1:1:0
+mpi_fill_random:1:1:0:0
 
 Fill random: 2 bytes, good, no leading zero
-mpi_fill_random:2:2:0
+mpi_fill_random:2:2:0:0
 
 Fill random: 2 bytes, good, 1 leading zero
-mpi_fill_random:2:256:0
+mpi_fill_random:2:256:0:0
 
 Fill random: MAX_SIZE - 7, good
-mpi_fill_random:MBEDTLS_MPI_MAX_SIZE - 7:MBEDTLS_MPI_MAX_SIZE - 7:0
+mpi_fill_random:MBEDTLS_MPI_MAX_SIZE - 7:MBEDTLS_MPI_MAX_SIZE - 7:0:0
 
 Fill random: MAX_SIZE, good
-mpi_fill_random:MBEDTLS_MPI_MAX_SIZE:MBEDTLS_MPI_MAX_SIZE:0
+mpi_fill_random:MBEDTLS_MPI_MAX_SIZE:MBEDTLS_MPI_MAX_SIZE:0:0
+
+Fill random: 0 bytes, previously small >0
+mpi_fill_random:0:0:1:0
+
+Fill random: 0 bytes, previously small <0
+mpi_fill_random:0:0:-1:0
+
+Fill random: 0 bytes, previously large >0
+mpi_fill_random:0:0:65:0
+
+Fill random: 0 bytes, previously large <0
+mpi_fill_random:0:0:-65:0
+
+Fill random: 1 byte, previously small >0
+mpi_fill_random:1:1:1:0
+
+Fill random: 1 byte, previously small <0
+mpi_fill_random:1:1:-1:0
+
+Fill random: 1 byte, previously large >0
+mpi_fill_random:1:1:65:0
+
+Fill random: 1 byte, previously large <0
+mpi_fill_random:1:1:-65:0
+
+Fill random: 9 bytes, previously small >0
+mpi_fill_random:1:1:1:0
+
+Fill random: 9 bytes, previously small <0
+mpi_fill_random:1:1:-1:0
 
 Fill random: 1 byte, RNG failure
-mpi_fill_random:1:0:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+mpi_fill_random:1:0:0:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
 
 Fill random: 2 bytes, RNG failure after 1 byte
-mpi_fill_random:2:1:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+mpi_fill_random:2:1:0:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
 
 Fill random: 4 bytes, RNG failure after 3 bytes
-mpi_fill_random:4:3:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+mpi_fill_random:4:3:0:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
 
 Fill random: 8 bytes, RNG failure after 7 bytes
-mpi_fill_random:8:7:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+mpi_fill_random:8:7:0:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
 
 Fill random: 16 bytes, RNG failure after 1 bytes
-mpi_fill_random:16:1:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+mpi_fill_random:16:1:0:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
 
 Fill random: 16 bytes, RNG failure after 8 bytes
-mpi_fill_random:16:8:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+mpi_fill_random:16:8:0:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
 
 Fill random: 16 bytes, RNG failure after 15 bytes
-mpi_fill_random:16:15:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+mpi_fill_random:16:15:0:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
 
 Fill random: MAX_SIZE bytes, RNG failure after MAX_SIZE-1 bytes
-mpi_fill_random:MBEDTLS_MPI_MAX_SIZE:MBEDTLS_MPI_MAX_SIZE-1:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+mpi_fill_random:MBEDTLS_MPI_MAX_SIZE:MBEDTLS_MPI_MAX_SIZE-1:0:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+
+MPI random in range: 1..2
+mpi_random_many:1:"02":1000
+
+MPI random in range: 1..3
+mpi_random_many:1:"03":1000
+
+MPI random in range: 1..4
+mpi_random_many:1:"04":1000
+
+MPI random in range: 1..5
+mpi_random_many:1:"05":1000
+
+MPI random in range: 1..6
+mpi_random_many:1:"06":1000
+
+MPI random in range: 1..7
+mpi_random_many:1:"07":1000
+
+MPI random in range: 1..8
+mpi_random_many:1:"08":1000
+
+MPI random in range: 1..9
+mpi_random_many:1:"09":1000
+
+MPI random in range: 1..10
+mpi_random_many:1:"0a":1000
+
+MPI random in range: 1..11
+mpi_random_many:1:"0b":1000
+
+MPI random in range: 1..12
+mpi_random_many:1:"0c":1000
+
+MPI random in range: 1..255
+mpi_random_many:1:"ff":100
+
+MPI random in range: 1..256
+mpi_random_many:1:"0100":100
+
+MPI random in range: 1..257
+mpi_random_many:1:"0101":100
+
+MPI random in range: 1..272
+mpi_random_many:1:"0110":100
+
+MPI random in range: 1..2^64-1
+mpi_random_many:1:"ffffffffffffffff":100
+
+MPI random in range: 1..2^64
+mpi_random_many:1:"010000000000000000":100
+
+MPI random in range: 1..2^64+1
+mpi_random_many:1:"010000000000000001":100
+
+MPI random in range: 1..2^64+2^63
+mpi_random_many:1:"018000000000000000":100
+
+MPI random in range: 1..2^65-1
+mpi_random_many:1:"01ffffffffffffffff":100
+
+MPI random in range: 1..2^65
+mpi_random_many:1:"020000000000000000":100
+
+MPI random in range: 1..2^65+1
+mpi_random_many:1:"020000000000000001":100
+
+MPI random in range: 1..2^65+2^64
+mpi_random_many:1:"030000000000000000":100
+
+MPI random in range: 1..2^66+2^65
+mpi_random_many:1:"060000000000000000":100
+
+MPI random in range: 1..2^71-1
+mpi_random_many:1:"7fffffffffffffffff":100
+
+MPI random in range: 1..2^71
+mpi_random_many:1:"800000000000000000":100
+
+MPI random in range: 1..2^71+1
+mpi_random_many:1:"800000000000000001":100
+
+MPI random in range: 1..2^71+2^70
+mpi_random_many:1:"c00000000000000000":100
+
+MPI random in range: 1..2^72-1
+mpi_random_many:1:"ffffffffffffffffff":100
+
+MPI random in range: 1..2^72
+mpi_random_many:1:"01000000000000000000":100
+
+MPI random in range: 1..2^72+1
+mpi_random_many:1:"01000000000000000001":100
+
+MPI random in range: 1..2^72+2^71
+mpi_random_many:1:"01800000000000000000":100
+
+MPI random in range: 0..1
+mpi_random_many:0:"04":10000
+
+MPI random in range: 0..4
+mpi_random_many:0:"04":10000
+
+MPI random in range: 2..4
+mpi_random_many:2:"04":10000
+
+MPI random in range: 3..4
+mpi_random_many:3:"04":10000
+
+MPI random in range: smaller result
+mpi_random_sizes:1:"aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb":1:0
+
+MPI random in range: same size result (32-bit limbs)
+mpi_random_sizes:1:"aaaaaaaaaaaaaaaa":2:0
+
+MPI random in range: same size result (64-bit limbs)
+mpi_random_sizes:1:"aaaaaaaaaaaaaaaa":1:0
+
+MPI random in range: larger result
+mpi_random_sizes:1:"aaaaaaaaaaaaaaaa":3:0
+
+## The "0 limb in upper bound" tests rely on the fact that
+## mbedtls_mpi_read_binary() bases the size of the MPI on the size of
+## the input, without first checking for leading zeros. If this was
+## not the case, the tests would still pass, but would not exercise
+## the advertised behavior.
+MPI random in range: leading 0 limb in upper bound #0
+mpi_random_sizes:1:"00aaaaaaaaaaaaaaaa":0:0
+
+MPI random in range: leading 0 limb in upper bound #1
+mpi_random_sizes:1:"00aaaaaaaaaaaaaaaa":1:0
+
+MPI random in range: leading 0 limb in upper bound #2
+mpi_random_sizes:1:"00aaaaaaaaaaaaaaaa":2:0
+
+MPI random in range: leading 0 limb in upper bound #3
+mpi_random_sizes:1:"00aaaaaaaaaaaaaaaa":3:0
+
+MPI random in range: leading 0 limb in upper bound #4
+mpi_random_sizes:1:"00aaaaaaaaaaaaaaaa":4:0
+
+MPI random in range: previously small >0
+mpi_random_sizes:1:"1234567890":4:1
+
+MPI random in range: previously small <0
+mpi_random_sizes:1:"1234567890":4:-1
+
+MPI random in range: previously large >0
+mpi_random_sizes:1:"1234":4:65
+
+MPI random in range: previously large <0
+mpi_random_sizes:1:"1234":4:-65
+
+MPI random bad arguments: min < 0
+mpi_random_fail:-1:"04":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random bad arguments: min = N = 0
+mpi_random_fail:0:"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random bad arguments: min = N = 1
+mpi_random_fail:1:"01":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random bad arguments: min > N = 0
+mpi_random_fail:1:"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random bad arguments: min > N = 1
+mpi_random_fail:2:"01":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random bad arguments: min > N = 1, 0 limb in upper bound
+mpi_random_fail:2:"000000000000000001":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
 MPI Selftest
 depends_on:MBEDTLS_SELF_TEST
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_mpi.function b/third_party/mbedtls/repo/tests/suites/test_suite_mpi.function
index c5bb5a6..360916a 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_mpi.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_mpi.function
@@ -6,6 +6,18 @@
 #define MPI_MAX_BITS_LARGER_THAN_792
 #endif
 
+/* Check the validity of the sign bit in an MPI object. Reject representations
+ * that are not supported by the rest of the library and indicate a bug when
+ * constructing the value. */
+static int sign_is_valid( const mbedtls_mpi *X )
+{
+    if( X->s != 1 && X->s != -1 )
+        return( 0 ); // invalid sign bit, e.g. 0
+    if( mbedtls_mpi_bitlen( X ) == 0 && X->s != 1 )
+        return( 0 ); // negative zero
+    return( 1 );
+}
+
 typedef struct mbedtls_test_mpi_random
 {
     data_t *data;
@@ -64,6 +76,50 @@
     return( 0 );
 }
 
+/* Test whether bytes represents (in big-endian base 256) a number b that
+ * is significantly above a power of 2. That is, b must not have a long run
+ * of unset bits after the most significant bit.
+ *
+ * Let n be the bit-size of b, i.e. the integer such that 2^n <= b < 2^{n+1}.
+ * This function returns 1 if, when drawing a number between 0 and b,
+ * the probability that this number is at least 2^n is not negligible.
+ * This probability is (b - 2^n) / b and this function checks that this
+ * number is above some threshold A. The threshold value is heuristic and
+ * based on the needs of mpi_random_many().
+ */
+static int is_significantly_above_a_power_of_2( data_t *bytes )
+{
+    const uint8_t *p = bytes->x;
+    size_t len = bytes->len;
+    unsigned x;
+
+    /* Skip leading null bytes */
+    while( len > 0 && p[0] == 0 )
+    {
+        ++p;
+        --len;
+    }
+    /* 0 is not significantly above a power of 2 */
+    if( len == 0 )
+        return( 0 );
+    /* Extract the (up to) 2 most significant bytes */
+    if( len == 1 )
+        x = p[0];
+    else
+        x = ( p[0] << 8 ) | p[1];
+
+    /* Shift the most significant bit of x to position 8 and mask it out */
+    while( ( x & 0xfe00 ) != 0 )
+        x >>= 1;
+    x &= 0x00ff;
+
+    /* At this point, x = floor((b - 2^n) / 2^(n-8)). b is significantly above
+     * a power of 2 iff x is significantly above 0 compared to 2^8.
+     * Testing x >= 2^4 amounts to picking A = 1/16 in the function
+     * description above. */
+    return( x >= 0x10 );
+}
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -321,6 +377,7 @@
     TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == result_read );
     if( result_read == 0 )
     {
+        TEST_ASSERT( sign_is_valid( &X ) );
         TEST_ASSERT( mbedtls_mpi_write_string( &X, radix_A, str, output_size, &len ) == result_write );
         if( result_write == 0 )
         {
@@ -345,6 +402,7 @@
 
 
     TEST_ASSERT( mbedtls_mpi_read_binary( &X, buf->x, buf->len ) == 0 );
+    TEST_ASSERT( sign_is_valid( &X ) );
     TEST_ASSERT( mbedtls_mpi_write_string( &X, radix_A, str, sizeof( str ), &len ) == 0 );
     TEST_ASSERT( strcmp( (char *) str, input_A ) == 0 );
 
@@ -364,6 +422,7 @@
 
 
     TEST_ASSERT( mbedtls_mpi_read_binary_le( &X, buf->x, buf->len ) == 0 );
+    TEST_ASSERT( sign_is_valid( &X ) );
     TEST_ASSERT( mbedtls_mpi_write_string( &X, radix_A, str, sizeof( str ), &len ) == 0 );
     TEST_ASSERT( strcmp( (char *) str, input_A ) == 0 );
 
@@ -385,7 +444,7 @@
 
     mbedtls_mpi_init( &X );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
 
     buflen = mbedtls_mpi_size( &X );
     if( buflen > (size_t) output_size )
@@ -417,7 +476,7 @@
 
     mbedtls_mpi_init( &X );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
 
     buflen = mbedtls_mpi_size( &X );
     if( buflen > (size_t) output_size )
@@ -458,6 +517,7 @@
 
     if( result == 0 )
     {
+        TEST_ASSERT( sign_is_valid( &X ) );
         buflen = mbedtls_mpi_size( &X );
         TEST_ASSERT( mbedtls_mpi_write_binary( &X, buf, buflen ) == 0 );
 
@@ -481,7 +541,7 @@
 
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
 
     file_out = fopen( output_file, "w" );
     TEST_ASSERT( file_out != NULL );
@@ -507,7 +567,7 @@
 {
     mbedtls_mpi X;
     mbedtls_mpi_init( &X );
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
     TEST_ASSERT( mbedtls_mpi_get_bit( &X, pos ) == val );
 
 exit:
@@ -522,12 +582,13 @@
     mbedtls_mpi X, Y;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Y, radix_Y, output_Y ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y, radix_Y, output_Y ) == 0 );
     TEST_ASSERT( mbedtls_mpi_set_bit( &X, pos, val ) == result );
 
     if( result == 0 )
     {
+        TEST_ASSERT( sign_is_valid( &X ) );
         TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &Y ) == 0 );
     }
 
@@ -542,7 +603,7 @@
     mbedtls_mpi X;
     mbedtls_mpi_init( &X );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
     TEST_ASSERT( mbedtls_mpi_lsb( &X ) == (size_t) nr_bits );
 
 exit:
@@ -556,7 +617,7 @@
     mbedtls_mpi X;
     mbedtls_mpi_init( &X );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
     TEST_ASSERT( mbedtls_mpi_bitlen( &X ) == (size_t) nr_bits );
 
 exit:
@@ -571,10 +632,11 @@
     mbedtls_mpi A, X, Y, Z;
     mbedtls_mpi_init( &A ); mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Y, radix_Y, input_Y ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &A, radix_A, input_A ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y, radix_Y, input_Y ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, radix_A, input_A ) == 0 );
     TEST_ASSERT( mbedtls_mpi_gcd( &Z, &X, &Y ) == 0 );
+    TEST_ASSERT( sign_is_valid( &Z ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Z, &A ) == 0 );
 
 exit:
@@ -603,8 +665,8 @@
     mbedtls_mpi X, Y;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Y, radix_Y, input_Y ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y, radix_Y, input_Y ) == 0 );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &Y ) == input_A );
 
 exit:
@@ -622,8 +684,8 @@
     mbedtls_mpi X, Y;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, 16, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Y, 16, input_Y ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, 16, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y, 16, input_Y ) == 0 );
 
     TEST_ASSERT( mbedtls_mpi_grow( &X, size_X ) == 0 );
     TEST_ASSERT( mbedtls_mpi_grow( &Y, size_Y ) == 0 );
@@ -644,8 +706,8 @@
     mbedtls_mpi X, Y;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Y, radix_Y, input_Y ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y, radix_Y, input_Y ) == 0 );
     TEST_ASSERT( mbedtls_mpi_cmp_abs( &X, &Y ) == input_A );
 
 exit:
@@ -654,55 +716,125 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void mbedtls_mpi_copy_sint( int input_X, int input_Y )
+void mbedtls_mpi_copy( char *src_hex, char *dst_hex )
 {
-    mbedtls_mpi X, Y;
+    mbedtls_mpi src, dst, ref;
+    mbedtls_mpi_init( &src );
+    mbedtls_mpi_init( &dst );
+    mbedtls_mpi_init( &ref );
+
+    TEST_ASSERT( mbedtls_test_read_mpi( &src, 16, src_hex ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &ref, 16, dst_hex ) == 0 );
+
+    /* mbedtls_mpi_copy() */
+    TEST_ASSERT( mbedtls_test_read_mpi( &dst, 16, dst_hex ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_copy( &dst, &src ) == 0 );
+    TEST_ASSERT( sign_is_valid( &dst ) );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &dst, &src ) == 0 );
+
+    /* mbedtls_mpi_safe_cond_assign(), assignment done */
+    mbedtls_mpi_free( &dst );
+    TEST_ASSERT( mbedtls_test_read_mpi( &dst, 16, dst_hex ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_safe_cond_assign( &dst, &src, 1 ) == 0 );
+    TEST_ASSERT( sign_is_valid( &dst ) );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &dst, &src ) == 0 );
+
+    /* mbedtls_mpi_safe_cond_assign(), assignment not done */
+    mbedtls_mpi_free( &dst );
+    TEST_ASSERT( mbedtls_test_read_mpi( &dst, 16, dst_hex ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_safe_cond_assign( &dst, &src, 0 ) == 0 );
+    TEST_ASSERT( sign_is_valid( &dst ) );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &dst, &ref ) == 0 );
+
+exit:
+    mbedtls_mpi_free( &src );
+    mbedtls_mpi_free( &dst );
+    mbedtls_mpi_free( &ref );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_copy_self( char *input_X )
+{
+    mbedtls_mpi X, A;
+    mbedtls_mpi_init( &A );
+    mbedtls_mpi_init( &X );
+
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, 16, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_copy( &X, &X ) == 0 );
+
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, 16, input_X ) == 0 );
+    TEST_ASSERT( sign_is_valid( &X ) );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &A ) == 0 );
+
+exit:
+    mbedtls_mpi_free( &A );
+    mbedtls_mpi_free( &X );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mbedtls_mpi_swap( char *X_hex, char *Y_hex )
+{
+    mbedtls_mpi X, Y, X0, Y0;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y );
+    mbedtls_mpi_init( &X0 ); mbedtls_mpi_init( &Y0 );
 
-    TEST_ASSERT( mbedtls_mpi_lset( &X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_lset( &Y, input_Y ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X0, 16, X_hex ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y0, 16, Y_hex ) == 0 );
 
-    TEST_ASSERT( mbedtls_mpi_copy( &Y, &X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_int( &X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_int( &Y, input_X ) == 0 );
+    /* mbedtls_mpi_swap() */
+    TEST_ASSERT( mbedtls_test_read_mpi( &X,  16, X_hex ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y,  16, Y_hex ) == 0 );
+    mbedtls_mpi_swap( &X, &Y );
+    TEST_ASSERT( sign_is_valid( &X ) );
+    TEST_ASSERT( sign_is_valid( &Y ) );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &Y0 ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &X0 ) == 0 );
+
+    /* mbedtls_mpi_safe_cond_swap(), swap done */
+    mbedtls_mpi_free( &X );
+    mbedtls_mpi_free( &Y );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X,  16, X_hex ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y,  16, Y_hex ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_safe_cond_swap( &X, &Y, 1 ) == 0 );
+    TEST_ASSERT( sign_is_valid( &X ) );
+    TEST_ASSERT( sign_is_valid( &Y ) );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &Y0 ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &X0 ) == 0 );
+
+    /* mbedtls_mpi_safe_cond_swap(), swap not done */
+    mbedtls_mpi_free( &X );
+    mbedtls_mpi_free( &Y );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X,  16, X_hex ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y,  16, Y_hex ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_safe_cond_swap( &X, &Y, 0 ) == 0 );
+    TEST_ASSERT( sign_is_valid( &X ) );
+    TEST_ASSERT( sign_is_valid( &Y ) );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &X0 ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &Y0 ) == 0 );
 
 exit:
     mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y );
+    mbedtls_mpi_free( &X0 ); mbedtls_mpi_free( &Y0 );
 }
 /* END_CASE */
 
 /* BEGIN_CASE */
-void mbedtls_mpi_copy_binary( data_t *input_X, data_t *input_Y )
+void mpi_swap_self( char *X_hex )
 {
-    mbedtls_mpi X, Y, X0;
-    mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &X0 );
+    mbedtls_mpi X, X0;
+    mbedtls_mpi_init( &X ); mbedtls_mpi_init( &X0 );
 
-    TEST_ASSERT( mbedtls_mpi_read_binary( &X, input_X->x, input_X->len ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_binary( &Y, input_Y->x, input_Y->len ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_binary( &X0, input_X->x, input_X->len ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X,  16, X_hex ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X0, 16, X_hex ) == 0 );
+
+    mbedtls_mpi_swap( &X, &X );
+    TEST_ASSERT( sign_is_valid( &X ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &X0 ) == 0 );
 
-    TEST_ASSERT( mbedtls_mpi_copy( &Y, &X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &X0 ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &X0 ) == 0 );
-
 exit:
-    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &X0 );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void mpi_copy_self( int input_X )
-{
-    mbedtls_mpi X;
-    mbedtls_mpi_init( &X );
-
-    TEST_ASSERT( mbedtls_mpi_lset( &X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_copy( &X, &X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_int( &X, input_X ) == 0 );
-
-exit:
-    mbedtls_mpi_free( &X );
+    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &X0 );
 }
 /* END_CASE */
 
@@ -713,10 +845,14 @@
     mbedtls_mpi_init( &X );
 
     TEST_ASSERT( mbedtls_mpi_grow( &X, before ) == 0 );
-    TEST_ASSERT( used <= before );
-    memset( X.p, 0x2a, used * sizeof( mbedtls_mpi_uint ) );
+    if( used > 0 )
+    {
+        size_t used_bit_count = used * 8 * sizeof( mbedtls_mpi_uint );
+        TEST_ASSERT( mbedtls_mpi_set_bit( &X, used_bit_count - 1, 1 ) == 0 );
+    }
+    TEST_EQUAL( X.n, (size_t) before );
     TEST_ASSERT( mbedtls_mpi_shrink( &X, min ) == 0 );
-    TEST_ASSERT( X.n == (size_t) after );
+    TEST_EQUAL( X.n, (size_t) after );
 
 exit:
     mbedtls_mpi_free( &X );
@@ -724,139 +860,28 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void mbedtls_mpi_safe_cond_assign( int x_sign, char * x_str, int y_sign,
-                                   char * y_str )
-{
-    mbedtls_mpi X, Y, XX;
-    mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &XX );
-
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, 16, x_str ) == 0 );
-    X.s = x_sign;
-    TEST_ASSERT( mbedtls_mpi_read_string( &Y, 16, y_str ) == 0 );
-    Y.s = y_sign;
-    TEST_ASSERT( mbedtls_mpi_copy( &XX, &X ) == 0 );
-
-    TEST_ASSERT( mbedtls_mpi_safe_cond_assign( &X, &Y, 0 ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &XX ) == 0 );
-
-    TEST_ASSERT( mbedtls_mpi_safe_cond_assign( &X, &Y, 1 ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &Y ) == 0 );
-
-exit:
-    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &XX );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void mbedtls_mpi_safe_cond_swap( int x_sign, char * x_str, int y_sign,
-                                 char * y_str )
-{
-    mbedtls_mpi X, Y, XX, YY;
-
-    mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y );
-    mbedtls_mpi_init( &XX ); mbedtls_mpi_init( &YY );
-
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, 16, x_str ) == 0 );
-    X.s = x_sign;
-    TEST_ASSERT( mbedtls_mpi_read_string( &Y, 16, y_str ) == 0 );
-    Y.s = y_sign;
-
-    TEST_ASSERT( mbedtls_mpi_copy( &XX, &X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_copy( &YY, &Y ) == 0 );
-
-    TEST_ASSERT( mbedtls_mpi_safe_cond_swap( &X, &Y, 0 ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &XX ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &YY ) == 0 );
-
-    TEST_ASSERT( mbedtls_mpi_safe_cond_swap( &X, &Y, 1 ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &XX ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &YY ) == 0 );
-
-exit:
-    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y );
-    mbedtls_mpi_free( &XX ); mbedtls_mpi_free( &YY );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void mbedtls_mpi_swap_sint( int input_X, int input_Y )
-{
-    mbedtls_mpi X, Y;
-    mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y );
-
-    TEST_ASSERT( mbedtls_mpi_lset( &X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_lset( &Y, input_Y ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_int( &X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_int( &Y, input_Y ) == 0 );
-
-    mbedtls_mpi_swap( &X, &Y );
-    TEST_ASSERT( mbedtls_mpi_cmp_int( &X, input_Y ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_int( &Y, input_X ) == 0 );
-
-exit:
-    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void mbedtls_mpi_swap_binary( data_t *input_X, data_t *input_Y )
-{
-    mbedtls_mpi X, Y, X0, Y0;
-    mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y );
-    mbedtls_mpi_init( &X0 ); mbedtls_mpi_init( &Y0 );
-
-    TEST_ASSERT( mbedtls_mpi_read_binary( &X, input_X->x, input_X->len ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_binary( &Y, input_Y->x, input_Y->len ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_binary( &X0, input_X->x, input_X->len ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_binary( &Y0, input_Y->x, input_Y->len ) == 0 );
-
-    mbedtls_mpi_swap( &X, &Y );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &Y0 ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &X0 ) == 0 );
-
-exit:
-    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y );
-    mbedtls_mpi_free( &X0 ); mbedtls_mpi_free( &Y0 );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void mpi_swap_self( data_t *input_X )
-{
-    mbedtls_mpi X, X0;
-    mbedtls_mpi_init( &X ); mbedtls_mpi_init( &X0 );
-
-    TEST_ASSERT( mbedtls_mpi_read_binary( &X, input_X->x, input_X->len ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_binary( &X0, input_X->x, input_X->len ) == 0 );
-
-    mbedtls_mpi_swap( &X, &X );
-    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &X0 ) == 0 );
-
-exit:
-    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &X0 );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
 void mbedtls_mpi_add_mpi( int radix_X, char * input_X, int radix_Y,
                           char * input_Y, int radix_A, char * input_A )
 {
     mbedtls_mpi X, Y, Z, A;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); mbedtls_mpi_init( &A );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Y, radix_Y, input_Y ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &A, radix_A, input_A ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y, radix_Y, input_Y ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, radix_A, input_A ) == 0 );
     TEST_ASSERT( mbedtls_mpi_add_mpi( &Z, &X, &Y ) == 0 );
+    TEST_ASSERT( sign_is_valid( &Z ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Z, &A ) == 0 );
 
     /* result == first operand */
     TEST_ASSERT( mbedtls_mpi_add_mpi( &X, &X, &Y ) == 0 );
+    TEST_ASSERT( sign_is_valid( &X ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &A ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
 
     /* result == second operand */
     TEST_ASSERT( mbedtls_mpi_add_mpi( &Y, &X, &Y ) == 0 );
+    TEST_ASSERT( sign_is_valid( &Y ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &A ) == 0 );
 
 exit:
@@ -871,18 +896,21 @@
     mbedtls_mpi X, A;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &A );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &A, radix_A, input_A ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, radix_A, input_A ) == 0 );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
     TEST_ASSERT( mbedtls_mpi_sub_abs( &X, &X, &X ) == 0 );
     TEST_ASSERT( mbedtls_mpi_cmp_int( &X, 0 ) == 0 );
+    TEST_ASSERT( sign_is_valid( &X ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
     TEST_ASSERT( mbedtls_mpi_add_abs( &X, &X, &X ) == 0 );
+    TEST_ASSERT( sign_is_valid( &X ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &A ) == 0 );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
     TEST_ASSERT( mbedtls_mpi_add_mpi( &X, &X, &X ) == 0 );
+    TEST_ASSERT( sign_is_valid( &X ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &A ) == 0 );
 
 exit:
@@ -898,19 +926,22 @@
     mbedtls_mpi X, Y, Z, A;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); mbedtls_mpi_init( &A );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Y, radix_Y, input_Y ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &A, radix_A, input_A ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y, radix_Y, input_Y ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, radix_A, input_A ) == 0 );
     TEST_ASSERT( mbedtls_mpi_add_abs( &Z, &X, &Y ) == 0 );
+    TEST_ASSERT( sign_is_valid( &Z ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Z, &A ) == 0 );
 
     /* result == first operand */
     TEST_ASSERT( mbedtls_mpi_add_abs( &X, &X, &Y ) == 0 );
+    TEST_ASSERT( sign_is_valid( &X ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &A ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
 
     /* result == second operand */
     TEST_ASSERT( mbedtls_mpi_add_abs( &Y, &X, &Y ) == 0 );
+    TEST_ASSERT( sign_is_valid( &Y ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &A ) == 0 );
 
 exit:
@@ -925,9 +956,10 @@
     mbedtls_mpi X, Z, A;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Z ); mbedtls_mpi_init( &A );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &A, radix_A, input_A ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, radix_A, input_A ) == 0 );
     TEST_ASSERT( mbedtls_mpi_add_int( &Z, &X, input_Y ) == 0 );
+    TEST_ASSERT( sign_is_valid( &Z ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Z, &A ) == 0 );
 
 exit:
@@ -942,19 +974,22 @@
     mbedtls_mpi X, Y, Z, A;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); mbedtls_mpi_init( &A );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Y, radix_Y, input_Y ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &A, radix_A, input_A ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y, radix_Y, input_Y ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, radix_A, input_A ) == 0 );
     TEST_ASSERT( mbedtls_mpi_sub_mpi( &Z, &X, &Y ) == 0 );
+    TEST_ASSERT( sign_is_valid( &Z ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Z, &A ) == 0 );
 
     /* result == first operand */
     TEST_ASSERT( mbedtls_mpi_sub_mpi( &X, &X, &Y ) == 0 );
+    TEST_ASSERT( sign_is_valid( &X ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &A ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
 
     /* result == second operand */
     TEST_ASSERT( mbedtls_mpi_sub_mpi( &Y, &X, &Y ) == 0 );
+    TEST_ASSERT( sign_is_valid( &Y ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &A ) == 0 );
 
 exit:
@@ -971,23 +1006,26 @@
     int res;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); mbedtls_mpi_init( &A );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Y, radix_Y, input_Y ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &A, radix_A, input_A ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y, radix_Y, input_Y ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, radix_A, input_A ) == 0 );
 
     res = mbedtls_mpi_sub_abs( &Z, &X, &Y );
     TEST_ASSERT( res == sub_result );
+    TEST_ASSERT( sign_is_valid( &Z ) );
     if( res == 0 )
         TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Z, &A ) == 0 );
 
     /* result == first operand */
     TEST_ASSERT( mbedtls_mpi_sub_abs( &X, &X, &Y ) == sub_result );
+    TEST_ASSERT( sign_is_valid( &X ) );
     if( sub_result == 0 )
         TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &A ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
 
     /* result == second operand */
     TEST_ASSERT( mbedtls_mpi_sub_abs( &Y, &X, &Y ) == sub_result );
+    TEST_ASSERT( sign_is_valid( &Y ) );
     if( sub_result == 0 )
         TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &A ) == 0 );
 
@@ -1003,9 +1041,10 @@
     mbedtls_mpi X, Z, A;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Z ); mbedtls_mpi_init( &A );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &A, radix_A, input_A ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, radix_A, input_A ) == 0 );
     TEST_ASSERT( mbedtls_mpi_sub_int( &Z, &X, input_Y ) == 0 );
+    TEST_ASSERT( sign_is_valid( &Z ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Z, &A ) == 0 );
 
 exit:
@@ -1020,10 +1059,11 @@
     mbedtls_mpi X, Y, Z, A;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); mbedtls_mpi_init( &A );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Y, radix_Y, input_Y ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &A, radix_A, input_A ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y, radix_Y, input_Y ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, radix_A, input_A ) == 0 );
     TEST_ASSERT( mbedtls_mpi_mul_mpi( &Z, &X, &Y ) == 0 );
+    TEST_ASSERT( sign_is_valid( &Z ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Z, &A ) == 0 );
 
 exit:
@@ -1039,9 +1079,10 @@
     mbedtls_mpi X, Z, A;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Z ); mbedtls_mpi_init( &A );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &A, radix_A, input_A ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, radix_A, input_A ) == 0 );
     TEST_ASSERT( mbedtls_mpi_mul_int( &Z, &X, input_Y ) == 0 );
+    TEST_ASSERT( sign_is_valid( &Z ) );
     if( strcmp( result_comparison, "==" ) == 0 )
         TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Z, &A ) == 0 );
     else if( strcmp( result_comparison, "!=" ) == 0 )
@@ -1064,14 +1105,16 @@
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Q ); mbedtls_mpi_init( &R );
     mbedtls_mpi_init( &A ); mbedtls_mpi_init( &B );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Y, radix_Y, input_Y ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &A, radix_A, input_A ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &B, radix_B, input_B ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y, radix_Y, input_Y ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, radix_A, input_A ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &B, radix_B, input_B ) == 0 );
     res = mbedtls_mpi_div_mpi( &Q, &R, &X, &Y );
     TEST_ASSERT( res == div_result );
     if( res == 0 )
     {
+        TEST_ASSERT( sign_is_valid( &Q ) );
+        TEST_ASSERT( sign_is_valid( &R ) );
         TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Q, &A ) == 0 );
         TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R, &B ) == 0 );
     }
@@ -1092,13 +1135,15 @@
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Q ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &A );
     mbedtls_mpi_init( &B );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &A, radix_A, input_A ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &B, radix_B, input_B ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, radix_A, input_A ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &B, radix_B, input_B ) == 0 );
     res = mbedtls_mpi_div_int( &Q, &R, &X, input_Y );
     TEST_ASSERT( res == div_result );
     if( res == 0 )
     {
+        TEST_ASSERT( sign_is_valid( &Q ) );
+        TEST_ASSERT( sign_is_valid( &R ) );
         TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Q, &A ) == 0 );
         TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R, &B ) == 0 );
     }
@@ -1118,13 +1163,14 @@
     int res;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &A );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Y, radix_Y, input_Y ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &A, radix_A, input_A ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y, radix_Y, input_Y ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, radix_A, input_A ) == 0 );
     res = mbedtls_mpi_mod_mpi( &X, &X, &Y );
     TEST_ASSERT( res == div_result );
     if( res == 0 )
     {
+        TEST_ASSERT( sign_is_valid( &X ) );
         TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &A ) == 0 );
     }
 
@@ -1142,7 +1188,7 @@
     mbedtls_mpi_uint r;
     mbedtls_mpi_init( &X );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
     res = mbedtls_mpi_mod_int( &r, &X, input_Y );
     TEST_ASSERT( res == div_result );
     if( res == 0 )
@@ -1158,26 +1204,41 @@
 /* BEGIN_CASE */
 void mbedtls_mpi_exp_mod( int radix_A, char * input_A, int radix_E,
                           char * input_E, int radix_N, char * input_N,
-                          int radix_RR, char * input_RR, int radix_X,
-                          char * input_X, int div_result )
+                          int radix_X, char * input_X, int exp_result )
 {
     mbedtls_mpi A, E, N, RR, Z, X;
     int res;
     mbedtls_mpi_init( &A  ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N );
     mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &Z ); mbedtls_mpi_init( &X );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &A, radix_A, input_A ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, radix_A, input_A ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
 
-    if( strlen( input_RR ) )
-        TEST_ASSERT( mbedtls_mpi_read_string( &RR, radix_RR, input_RR ) == 0 );
-
-    res = mbedtls_mpi_exp_mod( &Z, &A, &E, &N, &RR );
-    TEST_ASSERT( res == div_result );
+    res = mbedtls_mpi_exp_mod( &Z, &A, &E, &N, NULL );
+    TEST_ASSERT( res == exp_result );
     if( res == 0 )
     {
+        TEST_ASSERT( sign_is_valid( &Z ) );
+        TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Z, &X ) == 0 );
+    }
+
+    /* Now test again with the speed-up parameter supplied as an output. */
+    res = mbedtls_mpi_exp_mod( &Z, &A, &E, &N, &RR );
+    TEST_ASSERT( res == exp_result );
+    if( res == 0 )
+    {
+        TEST_ASSERT( sign_is_valid( &Z ) );
+        TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Z, &X ) == 0 );
+    }
+
+    /* Now test again with the speed-up parameter supplied in calculated form. */
+    res = mbedtls_mpi_exp_mod( &Z, &A, &E, &N, &RR );
+    TEST_ASSERT( res == exp_result );
+    if( res == 0 )
+    {
+        TEST_ASSERT( sign_is_valid( &Z ) );
         TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Z, &X ) == 0 );
     }
 
@@ -1211,7 +1272,7 @@
     TEST_ASSERT( mbedtls_mpi_set_bit( &N, 0, 1 ) == 0 );
 
     if( strlen( input_RR ) )
-        TEST_ASSERT( mbedtls_mpi_read_string( &RR, radix_RR, input_RR ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &RR, radix_RR, input_RR ) == 0 );
 
     TEST_ASSERT( mbedtls_mpi_exp_mod( &Z, &A, &E, &N, &RR ) == exp_result );
 
@@ -1230,13 +1291,14 @@
     int res;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); mbedtls_mpi_init( &A );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Y, radix_Y, input_Y ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &A, radix_A, input_A ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Y, radix_Y, input_Y ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, radix_A, input_A ) == 0 );
     res = mbedtls_mpi_inv_mod( &Z, &X, &Y );
     TEST_ASSERT( res == div_result );
     if( res == 0 )
     {
+        TEST_ASSERT( sign_is_valid( &Z ) );
         TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Z, &A ) == 0 );
     }
 
@@ -1252,7 +1314,7 @@
     int res;
     mbedtls_mpi_init( &X );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
     res = mbedtls_mpi_is_prime_ext( &X, 40, mbedtls_test_rnd_std_rand, NULL );
     TEST_ASSERT( res == div_result );
 
@@ -1312,6 +1374,7 @@
 
         TEST_ASSERT( actual_bits >= (size_t) bits );
         TEST_ASSERT( actual_bits <= (size_t) bits + 1 );
+        TEST_ASSERT( sign_is_valid( &X ) );
 
         TEST_ASSERT( mbedtls_mpi_is_prime_ext( &X, 40,
                                                mbedtls_test_rnd_std_rand,
@@ -1338,9 +1401,10 @@
     mbedtls_mpi X, A;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &A );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &A, radix_A, input_A ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, radix_A, input_A ) == 0 );
     TEST_ASSERT( mbedtls_mpi_shift_l( &X, shift_X ) == 0 );
+    TEST_ASSERT( sign_is_valid( &X ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &A ) == 0 );
 
 exit:
@@ -1355,9 +1419,10 @@
     mbedtls_mpi X, A;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &A );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &X, radix_X, input_X ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &A, radix_A, input_A ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &X, radix_X, input_X ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &A, radix_A, input_A ) == 0 );
     TEST_ASSERT( mbedtls_mpi_shift_r( &X, shift_X ) == 0 );
+    TEST_ASSERT( sign_is_valid( &X ) );
     TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &A ) == 0 );
 
 exit:
@@ -1366,13 +1431,23 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void mpi_fill_random( int wanted_bytes, int rng_bytes, int expected_ret )
+void mpi_fill_random( int wanted_bytes, int rng_bytes,
+                      int before, int expected_ret )
 {
     mbedtls_mpi X;
     int ret;
     size_t bytes_left = rng_bytes;
     mbedtls_mpi_init( &X );
 
+    if( before != 0 )
+    {
+        /* Set X to sign(before) * 2^(|before|-1) */
+        TEST_ASSERT( mbedtls_mpi_lset( &X, before > 0 ? 1 : -1 ) == 0 );
+        if( before < 0 )
+            before = - before;
+        TEST_ASSERT( mbedtls_mpi_shift_l( &X, before - 1 ) == 0 );
+    }
+
     ret = mbedtls_mpi_fill_random( &X, wanted_bytes,
                                    f_rng_bytes_left, &bytes_left );
     TEST_ASSERT( ret == expected_ret );
@@ -1389,6 +1464,7 @@
         TEST_ASSERT( mbedtls_mpi_size( &X ) + leading_zeros ==
                      (size_t) wanted_bytes );
         TEST_ASSERT( (int) bytes_left == rng_bytes - wanted_bytes );
+        TEST_ASSERT( sign_is_valid( &X ) );
     }
 
 exit:
@@ -1396,6 +1472,170 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE */
+void mpi_random_many( int min, data_t *bound_bytes, int iterations )
+{
+    /* Generate numbers in the range 1..bound-1. Do it iterations times.
+     * This function assumes that the value of bound is at least 2 and
+     * that iterations is large enough that a one-in-2^iterations chance
+     * effectively never occurs.
+     */
+
+    mbedtls_mpi upper_bound;
+    size_t n_bits;
+    mbedtls_mpi result;
+    size_t b;
+    /* If upper_bound is small, stats[b] is the number of times the value b
+     * has been generated. Otherwise stats[b] is the number of times a
+     * value with bit b set has been generated. */
+    size_t *stats = NULL;
+    size_t stats_len;
+    int full_stats;
+    size_t i;
+
+    mbedtls_mpi_init( &upper_bound );
+    mbedtls_mpi_init( &result );
+
+    TEST_EQUAL( 0, mbedtls_mpi_read_binary( &upper_bound,
+                                            bound_bytes->x, bound_bytes->len ) );
+    n_bits = mbedtls_mpi_bitlen( &upper_bound );
+    /* Consider a bound "small" if it's less than 2^5. This value is chosen
+     * to be small enough that the probability of missing one value is
+     * negligible given the number of iterations. It must be less than
+     * 256 because some of the code below assumes that "small" values
+     * fit in a byte. */
+    if( n_bits <= 5 )
+    {
+        full_stats = 1;
+        stats_len = bound_bytes->x[bound_bytes->len - 1];
+    }
+    else
+    {
+        full_stats = 0;
+        stats_len = n_bits;
+    }
+    ASSERT_ALLOC( stats, stats_len );
+
+    for( i = 0; i < (size_t) iterations; i++ )
+    {
+        mbedtls_test_set_step( i );
+        TEST_EQUAL( 0, mbedtls_mpi_random( &result, min, &upper_bound,
+                                           mbedtls_test_rnd_std_rand, NULL ) );
+
+        TEST_ASSERT( sign_is_valid( &result ) );
+        TEST_ASSERT( mbedtls_mpi_cmp_mpi( &result, &upper_bound ) < 0 );
+        TEST_ASSERT( mbedtls_mpi_cmp_int( &result, min ) >= 0 );
+        if( full_stats )
+        {
+            uint8_t value;
+            TEST_EQUAL( 0, mbedtls_mpi_write_binary( &result, &value, 1 ) );
+            TEST_ASSERT( value < stats_len );
+            ++stats[value];
+        }
+        else
+        {
+            for( b = 0; b < n_bits; b++ )
+                stats[b] += mbedtls_mpi_get_bit( &result, b );
+        }
+    }
+
+    if( full_stats )
+    {
+        for( b = min; b < stats_len; b++ )
+        {
+            mbedtls_test_set_step( 1000000 + b );
+            /* Assert that each value has been reached at least once.
+             * This is almost guaranteed if the iteration count is large
+             * enough. This is a very crude way of checking the distribution.
+             */
+            TEST_ASSERT( stats[b] > 0 );
+        }
+    }
+    else
+    {
+        int statistically_safe_all_the_way =
+            is_significantly_above_a_power_of_2( bound_bytes );
+        for( b = 0; b < n_bits; b++ )
+        {
+            mbedtls_test_set_step( 1000000 + b );
+            /* Assert that each bit has been set in at least one result and
+             * clear in at least one result. Provided that iterations is not
+             * too small, it would be extremely unlikely for this not to be
+             * the case if the results are uniformly distributed.
+             *
+             * As an exception, the top bit may legitimately never be set
+             * if bound is a power of 2 or only slightly above.
+             */
+            if( statistically_safe_all_the_way || b != n_bits - 1 )
+            {
+                TEST_ASSERT( stats[b] > 0 );
+            }
+            TEST_ASSERT( stats[b] < (size_t) iterations );
+        }
+    }
+
+exit:
+    mbedtls_mpi_free( &upper_bound );
+    mbedtls_mpi_free( &result );
+    mbedtls_free( stats );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_random_sizes( int min, data_t *bound_bytes, int nlimbs, int before )
+{
+    mbedtls_mpi upper_bound;
+    mbedtls_mpi result;
+
+    mbedtls_mpi_init( &upper_bound );
+    mbedtls_mpi_init( &result );
+
+    if( before != 0 )
+    {
+        /* Set result to sign(before) * 2^(|before|-1) */
+        TEST_ASSERT( mbedtls_mpi_lset( &result, before > 0 ? 1 : -1 ) == 0 );
+        if( before < 0 )
+            before = - before;
+        TEST_ASSERT( mbedtls_mpi_shift_l( &result, before - 1 ) == 0 );
+    }
+
+    TEST_EQUAL( 0, mbedtls_mpi_grow( &result, nlimbs ) );
+    TEST_EQUAL( 0, mbedtls_mpi_read_binary( &upper_bound,
+                                            bound_bytes->x, bound_bytes->len ) );
+    TEST_EQUAL( 0, mbedtls_mpi_random( &result, min, &upper_bound,
+                                       mbedtls_test_rnd_std_rand, NULL ) );
+    TEST_ASSERT( sign_is_valid( &result ) );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &result, &upper_bound ) < 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_int( &result, min ) >= 0 );
+
+exit:
+    mbedtls_mpi_free( &upper_bound );
+    mbedtls_mpi_free( &result );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_random_fail( int min, data_t *bound_bytes, int expected_ret )
+{
+    mbedtls_mpi upper_bound;
+    mbedtls_mpi result;
+    int actual_ret;
+
+    mbedtls_mpi_init( &upper_bound );
+    mbedtls_mpi_init( &result );
+
+    TEST_EQUAL( 0, mbedtls_mpi_read_binary( &upper_bound,
+                                            bound_bytes->x, bound_bytes->len ) );
+    actual_ret = mbedtls_mpi_random( &result, min, &upper_bound,
+                                     mbedtls_test_rnd_std_rand, NULL );
+    TEST_EQUAL( expected_ret, actual_ret );
+
+exit:
+    mbedtls_mpi_free( &upper_bound );
+    mbedtls_mpi_free( &result );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
 void mpi_selftest(  )
 {
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_mps.data b/third_party/mbedtls/repo/tests/suites/test_suite_mps.data
new file mode 100644
index 0000000..442f321
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_mps.data
@@ -0,0 +1,125 @@
+MPS Reader: Single step, single round, pausing disabled
+mbedtls_mps_reader_no_pausing_single_step_single_round:0
+
+MPS Reader: Single step, single round, pausing enabled but unused
+mbedtls_mps_reader_no_pausing_single_step_single_round:1
+
+MPS Reader: Single step, multiple rounds, pausing disabled
+mbedtls_mps_reader_no_pausing_single_step_multiple_rounds:0
+
+MPS Reader: Single step, multiple rounds, pausing enabled but unused
+mbedtls_mps_reader_no_pausing_single_step_multiple_rounds:1
+
+MPS Reader: Multiple steps, single round, pausing disabled
+mbedtls_mps_reader_no_pausing_multiple_steps_single_round:0
+
+MPS Reader: Multiple steps, single round, pausing enabled but unused
+mbedtls_mps_reader_no_pausing_multiple_steps_single_round:1
+
+MPS Reader: Multiple steps, multiple rounds, pausing disabled
+mbedtls_mps_reader_no_pausing_multiple_steps_multiple_rounds:0
+
+MPS Reader: Multiple steps, multiple rounds, pausing enabled but unused
+mbedtls_mps_reader_no_pausing_multiple_steps_multiple_rounds:1
+
+MPS Reader: Pausing needed but disabled
+mbedtls_mps_reader_pausing_needed_disabled:
+
+MPS Reader: Pausing needed + enabled, but buffer too small
+mbedtls_mps_reader_pausing_needed_buffer_too_small:
+
+MPS Reader: Pausing, repeat single call without commit
+mbedtls_mps_reader_pausing:0
+
+MPS Reader: Pausing, repeat single call with commit
+mbedtls_mps_reader_pausing:1
+
+MPS Reader: Pausing, repeat multiple calls without commit
+mbedtls_mps_reader_pausing:2
+
+MPS Reader: Pausing, repeat multiple calls with commit #0
+mbedtls_mps_reader_pausing:3
+
+MPS Reader: Pausing, repeat multiple calls with commit #1
+mbedtls_mps_reader_pausing:4
+
+MPS Reader: Pausing, repeat multiple calls with commit #2
+mbedtls_mps_reader_pausing:5
+
+MPS Reader: Pausing, feed 50 bytes in 10b + 10b + 80b
+mbedtls_mps_reader_pausing_multiple_feeds:0
+
+MPS Reader: Pausing, feed 50 bytes in 50x1b
+mbedtls_mps_reader_pausing_multiple_feeds:1
+
+MPS Reader: Pausing, feed 50 bytes in 49x1b + 51b
+mbedtls_mps_reader_pausing_multiple_feeds:2
+
+MPS Reader: Reclaim with data remaining #0
+mbedtls_mps_reader_reclaim_data_left:0
+
+MPS Reader: Reclaim with data remaining #1
+mbedtls_mps_reader_reclaim_data_left:1
+
+MPS Reader: Reclaim with data remaining #2
+mbedtls_mps_reader_reclaim_data_left:2
+
+MPS Reader: Reclaim with data remaining, continue fetching
+mbedtls_mps_reader_reclaim_data_left_retry:
+
+MPS Reader: Pausing several times, #0
+mbedtls_mps_reader_multiple_pausing:0
+
+MPS Reader: Pausing several times, #1
+mbedtls_mps_reader_multiple_pausing:1
+
+MPS Reader: Pausing several times, #2
+mbedtls_mps_reader_multiple_pausing:2
+
+MPS Reader: Pausing several times, #3
+mbedtls_mps_reader_multiple_pausing:3
+
+MPS Reader: Random usage, 20 rds, feed 100, get 200, acc 50
+mbedtls_mps_reader_random_usage:20:100:200:50
+
+MPS Reader: Random usage, 1000 rds, feed 10, get 100, acc 80
+mbedtls_mps_reader_random_usage:1000:10:100:80
+
+MPS Reader: Random usage, 10000 rds, feed 1, get 100, acc 80
+mbedtls_mps_reader_random_usage:10000:1:100:80
+
+MPS Reader: Random usage, 100 rds, feed 100, get 1000, acc 500
+mbedtls_mps_reader_random_usage:100:100:1000:500
+
+MPS Reader: Pausing, inconsistent continuation, #0
+mbedtls_reader_inconsistent_usage:0
+
+MPS Reader: Pausing, inconsistent continuation, #1
+mbedtls_reader_inconsistent_usage:1
+
+MPS Reader: Pausing, inconsistent continuation, #2
+mbedtls_reader_inconsistent_usage:2
+
+MPS Reader: Pausing, inconsistent continuation, #3
+mbedtls_reader_inconsistent_usage:3
+
+MPS Reader: Pausing, inconsistent continuation, #4
+mbedtls_reader_inconsistent_usage:4
+
+MPS Reader: Pausing, inconsistent continuation, #5
+mbedtls_reader_inconsistent_usage:5
+
+MPS Reader: Pausing, inconsistent continuation, #6
+mbedtls_reader_inconsistent_usage:6
+
+MPS Reader: Pausing, inconsistent continuation, #7
+mbedtls_reader_inconsistent_usage:7
+
+MPS Reader: Pausing, inconsistent continuation, #8
+mbedtls_reader_inconsistent_usage:8
+
+MPS Reader: Feed with invalid buffer (NULL)
+mbedtls_mps_reader_feed_empty:
+
+MPS Reader: Excess request leading to integer overflow
+mbedtls_mps_reader_reclaim_overflow:
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_mps.function b/third_party/mbedtls/repo/tests/suites/test_suite_mps.function
new file mode 100644
index 0000000..9df8a3c
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_mps.function
@@ -0,0 +1,1148 @@
+/* BEGIN_HEADER */
+
+#include <stdlib.h>
+
+#include "mps_reader.h"
+
+/*
+ * Compile-time configuration for test suite.
+ */
+
+/* Comment/Uncomment this to disable/enable the
+ * testing of the various MPS layers.
+ * This can be useful for time-consuming instrumentation
+ * tasks such as the conversion of E-ACSL annotations
+ * into runtime assertions. */
+#define TEST_SUITE_MPS_READER
+
+/* End of compile-time configuration. */
+
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
+void mbedtls_mps_reader_no_pausing_single_step_single_round( int with_acc )
+{
+    /* This test exercises the most basic use of the MPS reader:
+     * - The 'producing' layer provides a buffer
+     * - The 'consuming' layer fetches it in a single go.
+     * - After processing, the consuming layer commits the data
+     *   and the reader is moved back to producing mode.
+     *
+     * Parameters:
+     * - with_acc: 0 if the reader should be initialized without accumulator.
+     *             1 if the reader should be initialized with accumulator.
+     *
+     *             Whether the accumulator is present or not should not matter,
+     *             since the consumer's request can be fulfilled from the data
+     *             that the producer has provided.
+     */
+    unsigned char bufA[100];
+    unsigned char acc[10];
+    unsigned char *tmp;
+    int paused;
+    mbedtls_mps_reader rd;
+    for( size_t i=0; (unsigned) i < sizeof( bufA ); i++ )
+        bufA[i] = (unsigned char) i;
+
+    /* Preparation (lower layer) */
+    if( with_acc == 0 )
+        mbedtls_mps_reader_init( &rd, NULL, 0 );
+    else
+        mbedtls_mps_reader_init( &rd, acc, sizeof( acc ) );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufA, sizeof( bufA ) ) == 0 );
+    /* Consumption (upper layer) */
+    /* Consume exactly what's available */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 100, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 100, bufA, 100 );
+    TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+    /* Wrapup (lower layer) */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, &paused ) == 0 );
+    TEST_ASSERT( paused == 0 );
+    mbedtls_mps_reader_free( &rd );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
+void mbedtls_mps_reader_no_pausing_single_step_multiple_rounds( int with_acc )
+{
+    /* This test exercises multiple rounds of the basic use of the MPS reader:
+     * - The 'producing' layer provides a buffer
+     * - The 'consuming' layer fetches it in a single go.
+     * - After processing, the consuming layer commits the data
+     *   and the reader is moved back to producing mode.
+     *
+     * Parameters:
+     * - with_acc: 0 if the reader should be initialized without accumulator.
+     *             1 if the reader should be initialized with accumulator.
+     *
+     *             Whether the accumulator is present or not should not matter,
+     *             since the consumer's request can be fulfilled from the data
+     *             that the producer has provided.
+     */
+
+    unsigned char bufA[100], bufB[100];
+    unsigned char acc[10];
+    unsigned char *tmp;
+    mbedtls_mps_reader rd;
+    for( size_t i=0; (unsigned) i < sizeof( bufA ); i++ )
+        bufA[i] = (unsigned char) i;
+    for( size_t i=0; (unsigned) i < sizeof( bufB ); i++ )
+        bufB[i] = ~ ((unsigned char) i);
+
+    /* Preparation (lower layer) */
+    if( with_acc == 0 )
+        mbedtls_mps_reader_init( &rd, NULL, 0 );
+    else
+        mbedtls_mps_reader_init( &rd, acc, sizeof( acc ) );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufA, sizeof( bufA ) ) == 0 );
+    /* Consumption (upper layer) */
+    /* Consume exactly what's available */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 100, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 100, bufA, 100 );
+    TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+    /* Preparation */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) == 0 );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufB, sizeof( bufB ) ) == 0 );
+    /* Consumption */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 100, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 100, bufB, 100 );
+    TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+    /* Wrapup (lower layer) */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) == 0 );
+    mbedtls_mps_reader_free( &rd );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
+void mbedtls_mps_reader_no_pausing_multiple_steps_single_round( int with_acc )
+{
+    /* This test exercises one round of the following:
+     * - The 'producing' layer provides a buffer
+     * - The 'consuming' layer fetches it in multiple calls
+     *   to `mbedtls_mps_reader_get()`, without committing in between.
+     * - After processing, the consuming layer commits the data
+     *   and the reader is moved back to producing mode.
+     *
+     * Parameters:
+     * - with_acc: 0 if the reader should be initialized without accumulator.
+     *             1 if the reader should be initialized with accumulator.
+     *
+     *             Whether the accumulator is present or not should not matter,
+     *             since the consumer's requests can be fulfilled from the data
+     *             that the producer has provided.
+     */
+
+    /* Lower layer provides data that the upper layer fully consumes
+     * through multiple `get` calls. */
+    unsigned char buf[100];
+    unsigned char acc[10];
+    unsigned char *tmp;
+    mbedtls_mps_size_t tmp_len;
+    mbedtls_mps_reader rd;
+    for( size_t i=0; (unsigned) i < sizeof( buf ); i++ )
+        buf[i] = (unsigned char) i;
+
+    /* Preparation (lower layer) */
+    if( with_acc == 0 )
+        mbedtls_mps_reader_init( &rd, NULL, 0 );
+    else
+        mbedtls_mps_reader_init( &rd, acc, sizeof( acc ) );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, buf, sizeof( buf ) ) == 0 );
+    /* Consumption (upper layer) */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 10, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 10, buf, 10 );
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 70, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 70, buf + 10, 70 );
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 30, &tmp, &tmp_len ) == 0 );
+    ASSERT_COMPARE( tmp, tmp_len, buf + 80, 20 );
+    TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+    /* Wrapup (lower layer) */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) == 0 );
+    mbedtls_mps_reader_free( &rd );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
+void mbedtls_mps_reader_no_pausing_multiple_steps_multiple_rounds( int with_acc )
+{
+    /* This test exercises one round of fetching a buffer in multiple chunks
+     * and passing it back to the producer afterwards, followed by another
+     * single-step sequence of feed-fetch-commit-reclaim.
+     */
+    unsigned char bufA[100], bufB[100];
+    unsigned char acc[10];
+    unsigned char *tmp;
+    mbedtls_mps_size_t tmp_len;
+    mbedtls_mps_reader rd;
+    for( size_t i=0; (unsigned) i < sizeof( bufA ); i++ )
+        bufA[i] = (unsigned char) i;
+    for( size_t i=0; (unsigned) i < sizeof( bufB ); i++ )
+        bufB[i] = ~ ((unsigned char) i);
+
+    /* Preparation (lower layer) */
+    if( with_acc == 0 )
+        mbedtls_mps_reader_init( &rd, NULL, 0 );
+    else
+        mbedtls_mps_reader_init( &rd, acc, sizeof( acc ) );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufA, sizeof( bufA ) ) == 0 );
+    /* Consumption (upper layer) */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 10, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 10, bufA, 10 );
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 70, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 70, bufA + 10, 70 );
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 30, &tmp, &tmp_len ) == 0 );
+    ASSERT_COMPARE( tmp, tmp_len, bufA + 80, 20 );
+    TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+    /* Preparation */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) == 0 );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufB, sizeof( bufB ) ) == 0 );
+    /* Consumption */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 100, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 100, bufB, 100 );
+    TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+    /* Wrapup */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) == 0 );
+    mbedtls_mps_reader_free( &rd );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
+void mbedtls_mps_reader_pausing_needed_disabled()
+{
+    /* This test exercises the behaviour of the MPS reader when a read request
+     * of the consumer exceeds what has been provided by the producer, and when
+     * no accumulator is available in the reader.
+     *
+     * In this case, we expect the reader to fail.
+     */
+
+    unsigned char buf[100];
+    unsigned char *tmp;
+    mbedtls_mps_reader rd;
+    for( size_t i=0; (unsigned) i < sizeof( buf ); i++ )
+        buf[i] = (unsigned char) i;
+
+    /* Preparation (lower layer) */
+    mbedtls_mps_reader_init( &rd, NULL, 0 );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, buf, sizeof( buf ) ) == 0 );
+    /* Consumption (upper layer) */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 50, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 50, buf, 50 );
+    TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 100, &tmp, NULL ) ==
+                 MBEDTLS_ERR_MPS_READER_OUT_OF_DATA );
+    /* Wrapup (lower layer) */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) ==
+                 MBEDTLS_ERR_MPS_READER_NEED_ACCUMULATOR );
+    mbedtls_mps_reader_free( &rd );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
+void mbedtls_mps_reader_pausing_needed_buffer_too_small()
+{
+    /* This test exercises the behaviour of the MPS reader with accumulator
+     * in the situation where a read request goes beyond the bounds of the
+     * current read buffer, _and_ the reader's accumulator is too small to
+     * hold the requested amount of data.
+     *
+     * In this case, we expect mbedtls_mps_reader_reclaim() to fail,
+     * but it should be possible to continue fetching data as if
+     * there had been no excess request via mbedtls_mps_reader_get()
+     * and the call to mbedtls_mps_reader_reclaim() had been rejected
+     * because of data remaining.
+     */
+
+    unsigned char buf[100];
+    unsigned char acc[10];
+    unsigned char *tmp;
+    mbedtls_mps_reader rd;
+    mbedtls_mps_size_t tmp_len;
+
+    for( size_t i=0; (unsigned) i < sizeof( buf ); i++ )
+        buf[i] = (unsigned char) i;
+
+    /* Preparation (lower layer) */
+    mbedtls_mps_reader_init( &rd, acc, sizeof( acc ) );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, buf, sizeof( buf ) ) == 0 );
+    /* Consumption (upper layer) */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 50, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 50, buf, 50 );
+    TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 10, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 10, buf + 50, 10 );
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 100, &tmp, NULL ) ==
+                 MBEDTLS_ERR_MPS_READER_OUT_OF_DATA );
+    /* Wrapup (lower layer) */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) ==
+                 MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL );
+
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 50, &tmp, &tmp_len ) == 0 );
+    ASSERT_COMPARE( tmp, tmp_len, buf + 50, 50 );
+
+    mbedtls_mps_reader_free( &rd );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
+void mbedtls_mps_reader_reclaim_overflow()
+{
+    /* This test exercises the behaviour of the MPS reader with accumulator
+     * in the situation where upon calling mbedtls_mps_reader_reclaim(), the
+     * uncommitted data together with the excess data missing in the last
+     * call to medtls_mps_reader_get() exceeds the bounds of the type
+     * holding the buffer length.
+     */
+
+    unsigned char buf[100];
+    unsigned char acc[50];
+    unsigned char *tmp;
+    mbedtls_mps_reader rd;
+
+    for( size_t i=0; (unsigned) i < sizeof( buf ); i++ )
+        buf[i] = (unsigned char) i;
+
+    /* Preparation (lower layer) */
+    mbedtls_mps_reader_init( &rd, acc, sizeof( acc ) );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, buf, sizeof( buf ) ) == 0 );
+    /* Consumption (upper layer) */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 50, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 50, buf, 50 );
+    /* Excess request */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, (mbedtls_mps_size_t) -1, &tmp, NULL ) ==
+                 MBEDTLS_ERR_MPS_READER_OUT_OF_DATA );
+    /* Wrapup (lower layer) */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) ==
+                 MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL );
+
+    mbedtls_mps_reader_free( &rd );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
+void mbedtls_mps_reader_pausing( int option )
+{
+    /* This test exercises the behaviour of the reader when the
+     * accumulator is used to fulfill a consumer's request.
+     *
+     * More detailed:
+     * - The producer feeds some data.
+     * - The consumer asks for more data than what's available.
+     * - The reader remembers the request and goes back to
+     *   producing mode, waiting for more data from the producer.
+     * - The producer provides another chunk of data which is
+     *   sufficient to fulfill the original read request.
+     * - The consumer retries the original read request, which
+     *   should now succeed.
+     *
+     * This test comes in multiple variants controlled by the
+     * `option` parameter and documented below.
+     */
+
+    unsigned char bufA[100], bufB[100];
+    unsigned char *tmp;
+    unsigned char acc[40];
+    int paused;
+    mbedtls_mps_reader rd;
+    for( size_t i=0; (unsigned) i < sizeof( bufA ); i++ )
+        bufA[i] = (unsigned char) i;
+    for( size_t i=0; (unsigned) i < sizeof( bufB ); i++ )
+        bufB[i] = ~ ((unsigned char) i);
+
+    /* Preparation (lower layer) */
+    mbedtls_mps_reader_init( &rd, acc, sizeof( acc ) );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufA, sizeof( bufA ) ) == 0 );
+
+    /* Consumption (upper layer) */
+    /* Ask for more than what's available. */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 80, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 80, bufA, 80 );
+    TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 10, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 10, bufA + 80, 10 );
+    switch( option )
+    {
+        case 0:  /* Single uncommitted fetch at pausing */
+        case 1:
+            TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+            break;
+        default: /* Multiple uncommitted fetches at pausing */
+            break;
+    }
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 20, &tmp, NULL ) ==
+                 MBEDTLS_ERR_MPS_READER_OUT_OF_DATA );
+
+    /* Preparation */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, &paused ) == 0 );
+    TEST_ASSERT( paused == 1 );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufB, sizeof( bufB ) ) == 0 );
+
+    /* Consumption */
+    switch( option )
+    {
+        case 0: /* Single fetch at pausing, re-fetch with commit. */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 20, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufA + 90, 10 );
+            ASSERT_COMPARE( tmp + 10, 10, bufB, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+            break;
+
+        case 1: /* Single fetch at pausing, re-fetch without commit. */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 20, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufA + 90, 10 );
+            ASSERT_COMPARE( tmp + 10, 10, bufB, 10 );
+            break;
+
+        case 2: /* Multiple fetches at pausing, repeat without commit. */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 10, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufA + 80, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 20, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufA + 90, 10 );
+            ASSERT_COMPARE( tmp + 10, 10, bufB, 10 );
+            break;
+
+        case 3: /* Multiple fetches at pausing, repeat with commit 1. */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 10, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufA + 80, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 20, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufA + 90, 10 );
+            ASSERT_COMPARE( tmp + 10, 10, bufB, 10 );
+            break;
+
+        case 4: /* Multiple fetches at pausing, repeat with commit 2. */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 10, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufA + 80, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 20, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufA + 90, 10 );
+            ASSERT_COMPARE( tmp + 10, 10, bufB, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+            break;
+
+        case 5: /* Multiple fetches at pausing, repeat with commit 3. */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 10, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufA + 80, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 20, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufA + 90, 10 );
+            ASSERT_COMPARE( tmp + 10, 10, bufB, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+            break;
+
+        default:
+            TEST_ASSERT( 0 );
+    }
+
+    /* In all cases, fetch the rest of the second buffer. */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 90, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 90, bufB + 10, 90 );
+    TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+
+    /* Wrapup */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) == 0 );
+    mbedtls_mps_reader_free( &rd );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
+void mbedtls_mps_reader_pausing_multiple_feeds( int option )
+{
+    /* This test exercises the behaviour of the MPS reader
+     * in the following situation:
+     * - The consumer has asked for more than what's available, so the
+     *   reader pauses and waits for further input data via
+     *   `mbedtls_mps_reader_feed()`
+     * - Multiple such calls to `mbedtls_mps_reader_feed()` are necessary
+     *   to fulfill the original request, and the reader needs to do
+     *   the necessary bookkeeping under the hood.
+     *
+     * This test comes in a few variants differing in the number and
+     * size of feed calls that the producer issues while the reader is
+     * accumulating the necessary data - see the comments below.
+     */
+
+    unsigned char bufA[100], bufB[100];
+    unsigned char *tmp;
+    unsigned char acc[70];
+    mbedtls_mps_reader rd;
+    mbedtls_mps_size_t fetch_len;
+    for( size_t i=0; (unsigned) i < sizeof( bufA ); i++ )
+        bufA[i] = (unsigned char) i;
+    for( size_t i=0; (unsigned) i < sizeof( bufB ); i++ )
+        bufB[i] = ~ ((unsigned char) i);
+
+    /* Preparation (lower layer) */
+    mbedtls_mps_reader_init( &rd, acc, sizeof( acc ) );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufA, sizeof( bufA ) ) == 0 );
+
+    /* Consumption (upper layer) */
+    /* Ask for more than what's available. */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 80, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 80, bufA, 80 );
+    TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+    /* 20 left, ask for 70 -> 50 overhead */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 70, &tmp, NULL ) ==
+                 MBEDTLS_ERR_MPS_READER_OUT_OF_DATA );
+
+    /* Preparation */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) == 0 );
+    switch( option )
+    {
+        case 0: /* 10 + 10 + 80 byte feed */
+            TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufB, 10 ) ==
+                         MBEDTLS_ERR_MPS_READER_NEED_MORE );
+            TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufB + 10, 10 ) ==
+                         MBEDTLS_ERR_MPS_READER_NEED_MORE );
+            TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufB + 20, 80 ) == 0 );
+            break;
+
+        case 1: /* 50 x 1byte */
+            for( size_t num_feed = 0; num_feed < 49; num_feed++ )
+            {
+                TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufB + num_feed, 1 ) ==
+                             MBEDTLS_ERR_MPS_READER_NEED_MORE );
+            }
+            TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufB + 49, 1 ) == 0 );
+            break;
+
+        case 2: /* 49 x 1byte + 51bytes */
+            for( size_t num_feed = 0; num_feed < 49; num_feed++ )
+            {
+                TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufB + num_feed, 1 ) ==
+                             MBEDTLS_ERR_MPS_READER_NEED_MORE );
+            }
+            TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufB + 49, 51 ) == 0 );
+            break;
+
+        default:
+            TEST_ASSERT( 0 );
+            break;
+    }
+
+    /* Consumption */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 70, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 20, bufA + 80, 20 );
+    ASSERT_COMPARE( tmp + 20, 50, bufB, 50 );
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 1000, &tmp, &fetch_len ) == 0 );
+    switch( option )
+    {
+        case 0:
+            TEST_ASSERT( fetch_len == 50 );
+            break;
+
+        case 1:
+            TEST_ASSERT( fetch_len == 0 );
+            break;
+
+        case 2:
+            TEST_ASSERT( fetch_len == 50 );
+            break;
+
+        default:
+            TEST_ASSERT( 0 );
+            break;
+    }
+    TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+
+    /* Wrapup */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) == 0 );
+    mbedtls_mps_reader_free( &rd );
+}
+/* END_CASE */
+
+
+/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
+void mbedtls_mps_reader_reclaim_data_left( int option )
+{
+    /* This test exercises the behaviour of the MPS reader when a
+     * call to mbedtls_mps_reader_reclaim() is made before all data
+     * provided by the producer has been fetched and committed. */
+
+    unsigned char buf[100];
+    unsigned char *tmp;
+    mbedtls_mps_reader rd;
+    for( size_t i=0; (unsigned) i < sizeof( buf ); i++ )
+        buf[i] = (unsigned char) i;
+
+    /* Preparation (lower layer) */
+    mbedtls_mps_reader_init( &rd, NULL, 0 );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, buf, sizeof( buf ) ) == 0 );
+
+    /* Consumption (upper layer) */
+    switch( option )
+    {
+        case 0:
+            /* Fetch (but not commit) the entire buffer. */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, sizeof( buf ), &tmp, NULL )
+                         == 0 );
+            ASSERT_COMPARE( tmp, 100, buf, 100 );
+            break;
+
+        case 1:
+            /* Fetch (but not commit) parts of the buffer. */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, sizeof( buf ) / 2,
+                                             &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, sizeof( buf ) / 2, buf, sizeof( buf ) / 2 );
+            break;
+
+        case 2:
+            /* Fetch and commit parts of the buffer, then
+             * fetch but not commit the rest of the buffer. */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, sizeof( buf ) / 2,
+                                             &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, sizeof( buf ) / 2, buf, sizeof( buf ) / 2 );
+            TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, sizeof( buf ) / 2,
+                                             &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, sizeof( buf ) / 2,
+                            buf + sizeof( buf ) / 2,
+                            sizeof( buf ) / 2 );
+            break;
+
+        default:
+            TEST_ASSERT( 0 );
+            break;
+    }
+
+    /* Wrapup */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) ==
+                 MBEDTLS_ERR_MPS_READER_DATA_LEFT );
+    mbedtls_mps_reader_free( &rd );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
+void mbedtls_mps_reader_reclaim_data_left_retry()
+{
+    /* This test exercises the behaviour of the MPS reader when an attempt
+     * by the producer to reclaim the reader fails because of more data pending
+     * to be processed, and the consumer subsequently fetches more data. */
+    unsigned char buf[100];
+    unsigned char *tmp;
+    mbedtls_mps_reader rd;
+
+    for( size_t i=0; (unsigned) i < sizeof( buf ); i++ )
+        buf[i] = (unsigned char) i;
+
+    /* Preparation (lower layer) */
+    mbedtls_mps_reader_init( &rd, NULL, 0 );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, buf, sizeof( buf ) ) == 0 );
+    /* Consumption (upper layer) */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 50, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 50, buf, 50 );
+    TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 50, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 50, buf + 50, 50 );
+    /* Preparation */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) ==
+                 MBEDTLS_ERR_MPS_READER_DATA_LEFT );
+    /* Consumption */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 50, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 50, buf + 50, 50 );
+    TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+    /* Wrapup */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) == 0 );
+    mbedtls_mps_reader_free( &rd );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
+void mbedtls_mps_reader_multiple_pausing( int option )
+{
+    /* This test exercises the behaviour of the MPS reader
+     * in the following situation:
+     * - A read request via `mbedtls_mps_reader_get()` can't
+     *   be served and the reader is paused to accumulate
+     *   the desired amount of data from the producer.
+     * - Once enough data is available, the consumer successfully
+     *   reads the data from the reader, but afterwards exceeds
+     *   the available data again - pausing is necessary for a
+     *   second time.
+     */
+
+    unsigned char bufA[100], bufB[20], bufC[10];
+    unsigned char *tmp;
+    unsigned char acc[50];
+    mbedtls_mps_size_t tmp_len;
+    mbedtls_mps_reader rd;
+    for( size_t i=0; (unsigned) i < sizeof( bufA ); i++ )
+        bufA[i] = (unsigned char) i;
+    for( size_t i=0; (unsigned) i < sizeof( bufB ); i++ )
+        bufB[i] = ~ ((unsigned char) i);
+    for( size_t i=0; (unsigned) i < sizeof( bufC ); i++ )
+        bufC[i] = ~ ((unsigned char) i);
+
+    /* Preparation (lower layer) */
+    mbedtls_mps_reader_init( &rd, acc, sizeof( acc ) );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufA, sizeof( bufA ) ) == 0 );
+
+    /* Consumption (upper layer) */
+    /* Ask for more than what's available. */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 80, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 80, bufA, 80 );
+    TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 10, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 10, bufA + 80, 10 );
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 20, &tmp, NULL ) ==
+                 MBEDTLS_ERR_MPS_READER_OUT_OF_DATA );
+
+    /* Preparation */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) == 0 );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufB, sizeof( bufB ) ) == 0 );
+
+    switch( option )
+    {
+        case 0: /* Fetch same chunks, commit afterwards, and
+                 * then exceed bounds of new buffer; accumulator
+                 * large enough. */
+
+            /* Consume */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 10, &tmp, &tmp_len ) == 0 );
+            ASSERT_COMPARE( tmp, tmp_len, bufA + 80, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 20, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufA + 90, 10 );
+            ASSERT_COMPARE( tmp + 10, 10, bufB, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 20, &tmp, NULL ) ==
+                         MBEDTLS_ERR_MPS_READER_OUT_OF_DATA );
+
+            /* Prepare */
+            TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) == 0 );
+            TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufC, sizeof( bufC ) ) == 0 );;
+
+            /* Consume */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 20, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufB + 10, 10 );
+            ASSERT_COMPARE( tmp + 10, 10, bufC, 10 );
+            break;
+
+        case 1: /* Fetch same chunks, commit afterwards, and
+                 * then exceed bounds of new buffer; accumulator
+                 * not large enough. */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 10, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufA + 80, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 20, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufA + 90, 10 );
+            ASSERT_COMPARE( tmp + 10, 10, bufB, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 51, &tmp, NULL ) ==
+                         MBEDTLS_ERR_MPS_READER_OUT_OF_DATA );
+
+            /* Prepare */
+            TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) ==
+                         MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL );
+            break;
+
+        case 2: /* Fetch same chunks, don't commit afterwards, and
+                 * then exceed bounds of new buffer; accumulator
+                 * large enough. */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 10, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufA + 80, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 20, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufA + 90, 10 );
+            ASSERT_COMPARE( tmp + 10, 10, bufB, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 20, &tmp, NULL ) ==
+                         MBEDTLS_ERR_MPS_READER_OUT_OF_DATA );
+
+            /* Prepare */
+            TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) == 0 );
+            TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufC, sizeof( bufC ) ) == 0 );;
+
+            /* Consume */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 50, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 20, bufA + 80, 20 );
+            ASSERT_COMPARE( tmp + 20, 20, bufB, 20 );
+            ASSERT_COMPARE( tmp + 40, 10, bufC, 10 );
+            break;
+
+        case 3: /* Fetch same chunks, don't commit afterwards, and
+                 * then exceed bounds of new buffer; accumulator
+                 * not large enough. */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 10, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufA + 80, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 20, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 10, bufA + 90, 10 );
+            ASSERT_COMPARE( tmp + 10, 10, bufB, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 21, &tmp, NULL ) ==
+                         MBEDTLS_ERR_MPS_READER_OUT_OF_DATA );
+
+            /* Prepare */
+            TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) ==
+                         MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL );
+            break;
+
+        default:
+            TEST_ASSERT( 0 );
+            break;
+    }
+
+    mbedtls_mps_reader_free( &rd );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER:MBEDTLS_MPS_STATE_VALIDATION */
+void mbedtls_mps_reader_random_usage( int num_out_chunks,
+                                      int max_chunk_size,
+                                      int max_request,
+                                      int acc_size )
+
+{
+    /* Randomly pass a reader object back and forth between lower and
+     * upper layer and let each of them call the respective reader API
+     * functions in a random fashion.
+     *
+     * On the lower layer, we're tracking and concatenating
+     * the data passed to successful feed calls.
+     *
+     * For the upper layer, we track and concatenate buffers
+     * obtained from successful get calls.
+     *
+     * As long as the lower layer calls reclaim at least once, (resetting the
+     * fetched but not-yet-committed data), this should always lead to the same
+     * stream of outgoing/incoming data for the lower/upper layers, even if
+     * most of the random calls fail.
+     *
+     * NOTE: This test uses rand() for random data, which is not optimal.
+     *       Instead, it would be better to get the random data from a
+     *       static buffer. This both eases reproducibility and allows
+     *       simple conversion to a fuzz target.
+     */
+    int ret;
+    unsigned char *acc = NULL;
+    unsigned char *outgoing = NULL, *incoming = NULL;
+    unsigned char *cur_chunk = NULL;
+    size_t cur_out_chunk, out_pos, in_commit, in_fetch;
+    int rand_op;  /* Lower layer:
+                   * - Reclaim (0)
+                   * - Feed (1)
+                   * Upper layer:
+                   * - Get, do tolerate smaller output (0)
+                   * - Get, don't tolerate smaller output (1)
+                   * - Commit (2) */
+    int mode = 0; /* Lower layer (0) or Upper layer (1) */
+    int reclaimed = 1; /* Have to call reclaim at least once before
+                        * returning the reader to the upper layer. */
+    mbedtls_mps_reader rd;
+
+    if( acc_size > 0 )
+    {
+        ASSERT_ALLOC( acc, acc_size );
+    }
+
+    /* This probably needs to be changed because we want
+     * our tests to be deterministic. */
+    //    srand( time( NULL ) );
+
+    ASSERT_ALLOC( outgoing, num_out_chunks * max_chunk_size );
+    ASSERT_ALLOC( incoming, num_out_chunks * max_chunk_size );
+
+    mbedtls_mps_reader_init( &rd, acc, acc_size );
+
+    cur_out_chunk = 0;
+    in_commit = 0;
+    in_fetch = 0;
+    out_pos = 0;
+    while( cur_out_chunk < (unsigned) num_out_chunks )
+    {
+        if( mode == 0 )
+        {
+            /* Choose randomly between reclaim and feed */
+            rand_op = rand() % 2;
+
+            if( rand_op == 0 )
+            {
+                /* Reclaim */
+                ret = mbedtls_mps_reader_reclaim( &rd, NULL );
+
+                if( ret == 0 )
+                {
+                    TEST_ASSERT( cur_chunk != NULL );
+                    mbedtls_free( cur_chunk );
+                    cur_chunk = NULL;
+                }
+                reclaimed = 1;
+            }
+            else
+            {
+                /* Feed reader with a random chunk */
+                unsigned char *tmp = NULL;
+                size_t tmp_size;
+                if( cur_out_chunk == (unsigned) num_out_chunks )
+                    continue;
+
+                tmp_size = ( rand() % max_chunk_size ) + 1;
+                ASSERT_ALLOC( tmp, tmp_size );
+
+                TEST_ASSERT( mbedtls_test_rnd_std_rand( NULL, tmp, tmp_size ) == 0 );
+                ret = mbedtls_mps_reader_feed( &rd, tmp, tmp_size );
+
+                if( ret == 0 || ret == MBEDTLS_ERR_MPS_READER_NEED_MORE )
+                {
+                    cur_out_chunk++;
+                    memcpy( outgoing + out_pos, tmp, tmp_size );
+                    out_pos += tmp_size;
+                }
+
+                if( ret == 0 )
+                {
+                    TEST_ASSERT( cur_chunk == NULL );
+                    cur_chunk = tmp;
+                }
+                else
+                {
+                    mbedtls_free( tmp );
+                }
+
+            }
+
+            /* Randomly switch to consumption mode if reclaim
+             * was called at least once. */
+            if( reclaimed == 1 && rand() % 3 == 0 )
+            {
+                in_fetch = 0;
+                mode = 1;
+            }
+        }
+        else
+        {
+            /* Choose randomly between get tolerating fewer data,
+             * get not tolerating fewer data, and commit. */
+            rand_op = rand() % 3;
+            if( rand_op == 0 || rand_op == 1 )
+            {
+                mbedtls_mps_size_t get_size, real_size;
+                unsigned char *chunk_get;
+                get_size = ( rand() % max_request ) + 1;
+                if( rand_op == 0 )
+                {
+                    ret = mbedtls_mps_reader_get( &rd, get_size, &chunk_get,
+                                              &real_size );
+                }
+                else
+                {
+                    real_size = get_size;
+                    ret = mbedtls_mps_reader_get( &rd, get_size, &chunk_get, NULL );
+                }
+
+                /* Check if output is in accordance with what was written */
+                if( ret == 0 )
+                {
+                    memcpy( incoming + in_commit + in_fetch,
+                            chunk_get, real_size );
+                    TEST_ASSERT( memcmp( incoming + in_commit + in_fetch,
+                                         outgoing + in_commit + in_fetch,
+                                         real_size ) == 0 );
+                    in_fetch += real_size;
+                }
+            }
+            else if( rand_op == 2 ) /* Commit */
+            {
+                ret = mbedtls_mps_reader_commit( &rd );
+                if( ret == 0 )
+                {
+                    in_commit += in_fetch;
+                    in_fetch = 0;
+                }
+            }
+
+            /* Randomly switch back to preparation */
+            if( rand() % 3 == 0 )
+            {
+                reclaimed = 0;
+                mode = 0;
+            }
+        }
+    }
+
+    /* Cleanup */
+    mbedtls_mps_reader_free( &rd );
+    mbedtls_free( incoming );
+    mbedtls_free( outgoing );
+    mbedtls_free( acc );
+    mbedtls_free( cur_chunk );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
+void mbedtls_reader_inconsistent_usage( int option )
+{
+    /* This test exercises the behaviour of the MPS reader
+     * in the following situation:
+     * - The consumer asks for more data than what's available
+     * - The reader is paused and receives more data from the
+     *   producer until the original read request can be fulfilled.
+     * - The consumer does not repeat the original request but
+     *   requests data in a different way.
+     *
+     * The reader does not guarantee that inconsistent read requests
+     * after pausing will succeed, and this test triggers some cases
+     * where the request fails.
+     */
+
+    unsigned char bufA[100], bufB[100];
+    unsigned char *tmp;
+    unsigned char acc[40];
+    mbedtls_mps_reader rd;
+    int success = 0;
+    for( size_t i=0; (unsigned) i < sizeof( bufA ); i++ )
+        bufA[i] = (unsigned char) i;
+    for( size_t i=0; (unsigned) i < sizeof( bufB ); i++ )
+        bufB[i] = ~ ((unsigned char) i);
+
+    /* Preparation (lower layer) */
+    mbedtls_mps_reader_init( &rd, acc, sizeof( acc ) );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufA, sizeof( bufA ) ) == 0 );
+    /* Consumption (upper layer) */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 80, &tmp, NULL ) == 0 );
+    TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 10, &tmp, NULL ) == 0 );
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 20, &tmp, NULL ) ==
+                 MBEDTLS_ERR_MPS_READER_OUT_OF_DATA );
+    /* Preparation */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) == 0 );
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, bufB, sizeof( bufB ) ) == 0 );
+    /* Consumption */
+    switch( option )
+    {
+        case 0:
+            /* Ask for buffered data in a single chunk, no commit */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 30, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 20, bufA + 80, 20 );
+            ASSERT_COMPARE( tmp + 20, 10, bufB, 10 );
+            success = 1;
+            break;
+
+        case 1:
+            /* Ask for buffered data in a single chunk, with commit */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 30, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 20, bufA + 80, 20 );
+            ASSERT_COMPARE( tmp + 20, 10, bufB, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+            success = 1;
+            break;
+
+        case 2:
+            /* Ask for more than was requested when pausing, #1 */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 31, &tmp, NULL ) ==
+                         MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS );
+            break;
+
+        case 3:
+            /* Ask for more than was requested when pausing #2 */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, (mbedtls_mps_size_t) -1, &tmp, NULL ) ==
+                         MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS );
+            break;
+
+        case 4:
+            /* Asking for buffered data in different
+             * chunks than before CAN fail. */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 15, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 15, bufA + 80, 15 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 10, &tmp, NULL ) ==
+                         MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS );
+            break;
+
+        case 5:
+            /* Asking for buffered data different chunks
+             * than before NEED NOT fail - no commits */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 15, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 15, bufA + 80, 15 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 15, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 5, bufA + 95, 5 );
+            ASSERT_COMPARE( tmp + 5, 10, bufB, 10 );
+            success = 1;
+            break;
+
+        case 6:
+            /* Asking for buffered data different chunks
+             * than before NEED NOT fail - intermediate commit */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 15, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 15, bufA + 80, 15 );
+            TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 15, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 5, bufA + 95, 5 );
+            ASSERT_COMPARE( tmp + 5, 10, bufB, 10 );
+            success = 1;
+            break;
+
+        case 7:
+            /* Asking for buffered data different chunks
+             * than before NEED NOT fail - end commit */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 15, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 15, bufA + 80, 15 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 15, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 5, bufA + 95, 5 );
+            ASSERT_COMPARE( tmp + 5, 10, bufB, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+            success = 1;
+            break;
+
+        case 8:
+            /* Asking for buffered data different chunks
+             * than before NEED NOT fail - intermediate & end commit */
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 15, &tmp, NULL ) == 0 );
+            ASSERT_COMPARE( tmp, 15, bufA + 80, 15 );
+            TEST_ASSERT( mbedtls_mps_reader_get( &rd, 15, &tmp, NULL ) == 0 );
+            TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+            ASSERT_COMPARE( tmp, 5, bufA + 95, 5 );
+            ASSERT_COMPARE( tmp + 5, 10, bufB, 10 );
+            TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+            success = 1;
+            break;
+
+        default:
+            TEST_ASSERT( 0 );
+            break;
+    }
+
+    if( success == 1 )
+    {
+        /* In all succeeding cases, fetch the rest of the second buffer. */
+        TEST_ASSERT( mbedtls_mps_reader_get( &rd, 90, &tmp, NULL ) == 0 );
+        ASSERT_COMPARE( tmp, 90, bufB + 10, 90 );
+        TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+
+        /* Wrapup */
+        TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) == 0 );
+    }
+
+    /* Wrapup */
+    mbedtls_mps_reader_free( &rd );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:TEST_SUITE_MPS_READER */
+void mbedtls_mps_reader_feed_empty()
+{
+    /* This test exercises the behaviour of the reader when it is
+     * fed with a NULL buffer. */
+    unsigned char buf[100];
+    unsigned char *tmp;
+    mbedtls_mps_reader rd;
+    for( size_t i=0; (unsigned) i < sizeof( buf ); i++ )
+        buf[i] = (unsigned char) i;
+
+    /* Preparation (lower layer) */
+    mbedtls_mps_reader_init( &rd, NULL, 0 );
+
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, NULL, sizeof( buf ) ) ==
+                 MBEDTLS_ERR_MPS_READER_INVALID_ARG );
+
+    /* Subsequent feed-calls should still succeed. */
+    TEST_ASSERT( mbedtls_mps_reader_feed( &rd, buf, sizeof( buf ) ) == 0 );
+
+    /* Consumption (upper layer) */
+    TEST_ASSERT( mbedtls_mps_reader_get( &rd, 100, &tmp, NULL ) == 0 );
+    ASSERT_COMPARE( tmp, 100, buf, 100 );
+    TEST_ASSERT( mbedtls_mps_reader_commit( &rd ) == 0 );
+
+    /* Wrapup */
+    TEST_ASSERT( mbedtls_mps_reader_reclaim( &rd, NULL ) == 0 );
+    mbedtls_mps_reader_free( &rd );
+}
+/* END_CASE */
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_net.data b/third_party/mbedtls/repo/tests/suites/test_suite_net.data
new file mode 100644
index 0000000..4f516c8
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_net.data
@@ -0,0 +1,8 @@
+Context init-free-free
+context_init_free:0
+
+Context init-free-init-free
+context_init_free:1
+
+net_poll beyond FD_SETSIZE
+poll_beyond_fd_setsize:
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_net.function b/third_party/mbedtls/repo/tests/suites/test_suite_net.function
new file mode 100644
index 0000000..513b723
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_net.function
@@ -0,0 +1,137 @@
+/* BEGIN_HEADER */
+
+#include "mbedtls/net_sockets.h"
+
+#if defined(unix) || defined(__unix__) || defined(__unix) || \
+    defined(__APPLE__) || defined(__QNXNTO__) || \
+    defined(__HAIKU__) || defined(__midipix__)
+#define MBEDTLS_PLATFORM_IS_UNIXLIKE
+#endif
+
+#if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE)
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+
+
+#if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE)
+/** Open a file on the given file descriptor.
+ *
+ * This is disruptive if there is already something open on that descriptor.
+ * Caller beware.
+ *
+ * \param ctx           An initialized, but unopened socket context.
+ *                      On success, it refers to the opened file (\p wanted_fd).
+ * \param wanted_fd     The desired file descriptor.
+ *
+ * \return              \c 0 on succes, a negative error code on error.
+ */
+static int open_file_on_fd( mbedtls_net_context *ctx, int wanted_fd )
+{
+    int got_fd = open( "/dev/null", O_RDONLY );
+    TEST_ASSERT( got_fd >= 0 );
+    if( got_fd != wanted_fd )
+    {
+        TEST_ASSERT( dup2( got_fd, wanted_fd ) >= 0 );
+        TEST_ASSERT( close( got_fd ) >= 0 );
+    }
+    ctx->fd = wanted_fd;
+    return( 0 );
+exit:
+    return( -1 );
+}
+#endif /* MBEDTLS_PLATFORM_IS_UNIXLIKE */
+
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_NET_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void context_init_free( int reinit )
+{
+    mbedtls_net_context ctx;
+
+    mbedtls_net_init( &ctx );
+    mbedtls_net_free( &ctx );
+
+    if( reinit )
+        mbedtls_net_init( &ctx );
+    mbedtls_net_free( &ctx );
+
+    /* This test case always succeeds, functionally speaking. A plausible
+     * bug might trigger an invalid pointer dereference or a memory leak. */
+    goto exit;
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PLATFORM_IS_UNIXLIKE */
+void poll_beyond_fd_setsize( )
+{
+    /* Test that mbedtls_net_poll does not misbehave when given a file
+     * descriptor greater or equal to FD_SETSIZE. This code is specific to
+     * platforms with a Unix-like select() function, which is where
+     * FD_SETSIZE is a concern. */
+
+    struct rlimit rlim_nofile;
+    int restore_rlim_nofile = 0;
+    int ret;
+    mbedtls_net_context ctx;
+    uint8_t buf[1];
+
+    mbedtls_net_init( &ctx );
+
+    /* On many systems, by default, the maximum permitted file descriptor
+     * number is less than FD_SETSIZE. If so, raise the limit if
+     * possible.
+     *
+     * If the limit can't be raised, a file descriptor opened by the
+     * net_sockets module will be less than FD_SETSIZE, so the test
+     * is not necessary and we mark it as skipped.
+     * A file descriptor could still be higher than FD_SETSIZE if it was
+     * opened before the limit was lowered (which is something an application
+     * might do); but we don't do such things in our test code, so the unit
+     * test will run if it can.
+     */
+    TEST_ASSERT( getrlimit( RLIMIT_NOFILE, &rlim_nofile ) == 0 );
+    if( rlim_nofile.rlim_cur < FD_SETSIZE + 1 )
+    {
+        rlim_t old_rlim_cur = rlim_nofile.rlim_cur;
+        rlim_nofile.rlim_cur = FD_SETSIZE + 1;
+        TEST_ASSUME( setrlimit( RLIMIT_NOFILE, &rlim_nofile ) == 0 );
+        rlim_nofile.rlim_cur = old_rlim_cur;
+        restore_rlim_nofile = 1;
+    }
+
+    TEST_ASSERT( open_file_on_fd( &ctx, FD_SETSIZE ) == 0 );
+
+    /* In principle, mbedtls_net_poll() with valid arguments should succeed.
+     * However, we know that on Unix-like platforms (and others), this function
+     * is implemented on top of select() and fd_set, which do not support
+     * file descriptors greater or equal to FD_SETSIZE. So we expect to hit
+     * this platform limitation.
+     *
+     * If mbedtls_net_poll() does not proprely check that ctx.fd is in range,
+     * it may still happen to return the expected failure code, but if this
+     * is problematic on the particular platform where the code is running,
+     * a memory sanitizer such as UBSan should catch it.
+     */
+    ret = mbedtls_net_poll( &ctx, MBEDTLS_NET_POLL_READ, 0 );
+    TEST_EQUAL( ret, MBEDTLS_ERR_NET_POLL_FAILED );
+
+    /* mbedtls_net_recv_timeout() uses select() and fd_set in the same way. */
+    ret = mbedtls_net_recv_timeout( &ctx, buf, sizeof( buf ), 0 );
+    TEST_EQUAL( ret, MBEDTLS_ERR_NET_POLL_FAILED );
+
+exit:
+    mbedtls_net_free( &ctx );
+    if( restore_rlim_nofile )
+        setrlimit( RLIMIT_NOFILE, &rlim_nofile );
+}
+/* END_CASE */
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_pk.function b/third_party/mbedtls/repo/tests/suites/test_suite_pk.function
index 98016c6..82d1573 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_pk.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_pk.function
@@ -15,18 +15,6 @@
  * unconditionally (https://github.com/ARMmbed/mbedtls/issues/2023). */
 #include "psa/crypto.h"
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-#include "mbedtls/psa_util.h"
-#include "test/psa_crypto_helpers.h"
-#define PSA_INIT( ) PSA_ASSERT( psa_crypto_init( ) )
-#else
-/* Define empty macros so that we can use them in the preamble and teardown
- * of every test function that uses PSA conditionally based on
- * MBEDTLS_USE_PSA_CRYPTO. */
-#define PSA_INIT( ) ( (void) 0 )
-#define PSA_DONE( ) ( (void) 0 )
-#endif
-
 #define RSA_KEY_SIZE 512
 #define RSA_KEY_LEN   64
 
@@ -208,7 +196,7 @@
 
     mbedtls_pk_free( &pk ); /* redundant except upon error */
     mbedtls_pk_free( &pk2 );
-    PSA_DONE( );
+    USE_PSA_DONE( );
 }
 /* END_CASE */
 
@@ -682,8 +670,8 @@
     rsa = mbedtls_pk_rsa( pk );
 
     rsa->len = mod / 8;
-    TEST_ASSERT( mbedtls_mpi_read_string( &rsa->N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &rsa->E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &rsa->N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &rsa->E, radix_E, input_E ) == 0 );
 
 
     if( mbedtls_md_info_from_type( digest ) != NULL )
@@ -725,8 +713,8 @@
     rsa = mbedtls_pk_rsa( pk );
 
     rsa->len = mod / 8;
-    TEST_ASSERT( mbedtls_mpi_read_string( &rsa->N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &rsa->E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &rsa->N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &rsa->E, radix_E, input_E ) == 0 );
 
 
     if( digest != MBEDTLS_MD_NONE )
@@ -770,7 +758,7 @@
     mbedtls_ecp_keypair *eckey;
 
     mbedtls_pk_init( &pk );
-    PSA_INIT( );
+    USE_PSA_INIT( );
 
     TEST_ASSERT( mbedtls_pk_setup( &pk, mbedtls_pk_info_from_type( type ) ) == 0 );
 
@@ -787,7 +775,7 @@
 
 exit:
     mbedtls_pk_free( &pk );
-    PSA_DONE( );
+    USE_PSA_DONE( );
 }
 /* END_CASE */
 
@@ -813,7 +801,7 @@
 
     TEST_ASSERT( mbedtls_pk_setup( &prv, mbedtls_pk_info_from_type( pk_type ) ) == 0 );
     TEST_ASSERT( mbedtls_ecp_group_load( &mbedtls_pk_ec( prv )->grp, grp_id ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &mbedtls_pk_ec( prv )->d, 16, d_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &mbedtls_pk_ec( prv )->d, 16, d_str ) == 0 );
 
     TEST_ASSERT( mbedtls_pk_setup( &pub, mbedtls_pk_info_from_type( pk_type ) ) == 0 );
     TEST_ASSERT( mbedtls_ecp_group_load( &mbedtls_pk_ec( pub )->grp, grp_id ) == 0 );
@@ -895,8 +883,9 @@
 void pk_sign_verify( int type, int parameter, int sign_ret, int verify_ret )
 {
     mbedtls_pk_context pk;
-    size_t sig_len;
-    unsigned char hash[MBEDTLS_MD_MAX_SIZE];
+    size_t sig_len, hash_len;
+    mbedtls_md_type_t md = MBEDTLS_MD_SHA256;
+    unsigned char *hash = NULL;
     unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE];
     void *rs_ctx = NULL;
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
@@ -910,40 +899,43 @@
     mbedtls_ecp_set_max_ops( 42000 );
 #endif
 
-    mbedtls_pk_init( &pk );
-    PSA_INIT( );
+    hash_len = mbedtls_md_get_size( mbedtls_md_info_from_type( md ) );
+    ASSERT_ALLOC( hash, hash_len );
 
-    memset( hash, 0x2a, sizeof hash );
+    mbedtls_pk_init( &pk );
+    USE_PSA_INIT( );
+
+    memset( hash, 0x2a, hash_len );
     memset( sig, 0, sizeof sig );
 
     TEST_ASSERT( mbedtls_pk_setup( &pk, mbedtls_pk_info_from_type( type ) ) == 0 );
     TEST_ASSERT( pk_genkey( &pk, parameter ) == 0 );
 
-    TEST_ASSERT( mbedtls_pk_sign_restartable( &pk, MBEDTLS_MD_SHA256,
-                 hash, sizeof hash, sig, &sig_len,
+    TEST_ASSERT( mbedtls_pk_sign_restartable( &pk, md,
+                 hash, hash_len, sig, &sig_len,
                  mbedtls_test_rnd_std_rand, NULL, rs_ctx ) == sign_ret );
     if( sign_ret == 0 )
         TEST_ASSERT( sig_len <= MBEDTLS_PK_SIGNATURE_MAX_SIZE );
     else
         sig_len = MBEDTLS_PK_SIGNATURE_MAX_SIZE;
 
-    TEST_ASSERT( mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256,
-                            hash, sizeof hash, sig, sig_len ) == verify_ret );
+    TEST_ASSERT( mbedtls_pk_verify( &pk, md,
+                            hash, hash_len, sig, sig_len ) == verify_ret );
 
     if( verify_ret == 0 )
     {
         hash[0]++;
-        TEST_ASSERT( mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256,
-                                hash, sizeof hash, sig, sig_len ) != 0 );
+        TEST_ASSERT( mbedtls_pk_verify( &pk, md,
+                                hash, hash_len, sig, sig_len ) != 0 );
         hash[0]--;
 
         sig[0]++;
-        TEST_ASSERT( mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256,
-                                hash, sizeof hash, sig, sig_len ) != 0 );
+        TEST_ASSERT( mbedtls_pk_verify( &pk, md,
+                                hash, hash_len, sig, sig_len ) != 0 );
         sig[0]--;
     }
 
-    TEST_ASSERT( mbedtls_pk_sign( &pk, MBEDTLS_MD_SHA256, hash, sizeof hash,
+    TEST_ASSERT( mbedtls_pk_sign( &pk, md, hash, hash_len,
                                   sig, &sig_len,
                                   mbedtls_test_rnd_std_rand,
                                   NULL ) == sign_ret );
@@ -952,19 +944,19 @@
     else
         sig_len = MBEDTLS_PK_SIGNATURE_MAX_SIZE;
 
-    TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, MBEDTLS_MD_SHA256,
-                 hash, sizeof hash, sig, sig_len, rs_ctx ) == verify_ret );
+    TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, md,
+                 hash, hash_len, sig, sig_len, rs_ctx ) == verify_ret );
 
     if( verify_ret == 0 )
     {
         hash[0]++;
-        TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, MBEDTLS_MD_SHA256,
-                     hash, sizeof hash, sig, sig_len, rs_ctx ) != 0 );
+        TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, md,
+                     hash, hash_len, sig, sig_len, rs_ctx ) != 0 );
         hash[0]--;
 
         sig[0]++;
-        TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, MBEDTLS_MD_SHA256,
-                     hash, sizeof hash, sig, sig_len, rs_ctx ) != 0 );
+        TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, md,
+                     hash, hash_len, sig, sig_len, rs_ctx ) != 0 );
         sig[0]--;
     }
 
@@ -973,7 +965,8 @@
     mbedtls_pk_restart_free( rs_ctx );
 #endif
     mbedtls_pk_free( &pk );
-    PSA_DONE( );
+    mbedtls_free( hash );
+    USE_PSA_DONE( );
 }
 /* END_CASE */
 
@@ -997,8 +990,8 @@
     rsa = mbedtls_pk_rsa( pk );
 
     rsa->len = mod / 8;
-    TEST_ASSERT( mbedtls_mpi_read_string( &rsa->N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &rsa->E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &rsa->N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &rsa->E, radix_E, input_E ) == 0 );
 
     TEST_ASSERT( mbedtls_pk_encrypt( &pk, message->x, message->len,
                             output, &olen, sizeof( output ),
@@ -1036,12 +1029,12 @@
     rsa = mbedtls_pk_rsa( pk );
 
     /* load public key */
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
 
     /* load private key */
-    TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &P, radix_P, input_P ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Q, radix_Q, input_Q ) == 0 );
     TEST_ASSERT( mbedtls_rsa_import( rsa, &N, &P, &Q, NULL, &E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_get_len( rsa ) == (size_t) ( mod / 8 ) );
     TEST_ASSERT( mbedtls_rsa_complete( rsa ) == 0 );
@@ -1302,6 +1295,6 @@
     psa_reset_key_attributes( &attributes );
 
     mbedtls_pk_free( &pk );
-    PSA_DONE( );
+    USE_PSA_DONE( );
 }
 /* END_CASE */
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_pkcs12.data b/third_party/mbedtls/repo/tests/suites/test_suite_pkcs12.data
new file mode 100644
index 0000000..a8c4bab
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_pkcs12.data
@@ -0,0 +1,35 @@
+PKCS#12 derive key : MD5: Zero length password and hash
+depends_on:MBEDTLS_MD5_C
+pkcs12_derive_key:MBEDTLS_MD_MD5:48:"":USE_GIVEN_INPUT:"":USE_GIVEN_INPUT:3:"6afdcbd5ebf943272134f1c3de2dc11b6afdcbd5ebf943272134f1c3de2dc11b6afdcbd5ebf943272134f1c3de2dc11b":0
+
+PKCS#12 derive key: MD5: NULL password and hash
+depends_on:MBEDTLS_MD5_C
+pkcs12_derive_key:MBEDTLS_MD_MD5:48:"":USE_NULL_INPUT:"":USE_NULL_INPUT:3:"6afdcbd5ebf943272134f1c3de2dc11b6afdcbd5ebf943272134f1c3de2dc11b6afdcbd5ebf943272134f1c3de2dc11b":0
+
+PKCS#12 derive key: MD5: Zero length password
+depends_on:MBEDTLS_MD5_C
+pkcs12_derive_key:MBEDTLS_MD_MD5:48:"":USE_GIVEN_INPUT:"0123456789abcdef":USE_GIVEN_INPUT:3:"832d8502114fcccfd3de0c2b2863b1c45fb92a8db2ed1e704727b324adc267bdd66ae4918a81fa2d1ba15febfb9e6c4e":0
+
+PKCS#12 derive key: MD5: NULL password
+depends_on:MBEDTLS_MD5_C
+pkcs12_derive_key:MBEDTLS_MD_MD5:48:"":USE_NULL_INPUT:"0123456789abcdef":USE_GIVEN_INPUT:3:"832d8502114fcccfd3de0c2b2863b1c45fb92a8db2ed1e704727b324adc267bdd66ae4918a81fa2d1ba15febfb9e6c4e":0
+
+PKCS#12 derive key: MD5: Invalid length NULL password
+depends_on:MBEDTLS_MD5_C
+pkcs12_derive_key:MBEDTLS_MD_MD5:48:"0123456789abcdef":USE_NULL_INPUT:"0123456789abcdef":USE_GIVEN_INPUT:3:"":MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA
+
+PKCS#12 derive key: MD5: Zero length salt
+depends_on:MBEDTLS_MD5_C
+pkcs12_derive_key:MBEDTLS_MD_MD5:48:"0123456789abcdef":USE_GIVEN_INPUT:"":USE_GIVEN_INPUT:3:"832d8502114fcccfd3de0c2b2863b1c45fb92a8db2ed1e704727b324adc267bdd66ae4918a81fa2d1ba15febfb9e6c4e":0
+
+PKCS#12 derive key: MD5: NULL salt
+depends_on:MBEDTLS_MD5_C
+pkcs12_derive_key:MBEDTLS_MD_MD5:48:"0123456789abcdef":USE_GIVEN_INPUT:"":USE_NULL_INPUT:3:"832d8502114fcccfd3de0c2b2863b1c45fb92a8db2ed1e704727b324adc267bdd66ae4918a81fa2d1ba15febfb9e6c4e":0
+
+PKCS#12 derive key: MD5: Invalid length NULL salt
+depends_on:MBEDTLS_MD5_C
+pkcs12_derive_key:MBEDTLS_MD_MD5:48:"0123456789abcdef":USE_GIVEN_INPUT:"0123456789abcdef":USE_NULL_INPUT:3:"":MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA
+
+PKCS#12 derive key: MD5: Valid password and salt
+depends_on:MBEDTLS_MD5_C
+pkcs12_derive_key:MBEDTLS_MD_MD5:48:"0123456789abcdef":USE_GIVEN_INPUT:"0123456789abcdef":USE_GIVEN_INPUT:3:"46559deeee036836ab1b633ec620178d4c70eacf42f72a2ad7360c812efa09ca3d7567b489a109050345c2dc6a262995":0
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_pkcs12.function b/third_party/mbedtls/repo/tests/suites/test_suite_pkcs12.function
new file mode 100644
index 0000000..a7b01f6
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_pkcs12.function
@@ -0,0 +1,69 @@
+/* BEGIN_HEADER */
+#include "mbedtls/pkcs12.h"
+#include "mbedtls/error.h"
+
+typedef enum
+{
+   USE_NULL_INPUT = 0,
+   USE_GIVEN_INPUT = 1,
+} input_usage_method_t;
+
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_PKCS12_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void pkcs12_derive_key( int md_type, int key_size_arg,
+                        data_t *password_arg, int password_usage,
+                        data_t *salt_arg, int salt_usage,
+                        int iterations,
+                        data_t* expected_output, int expected_status )
+
+{
+   int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+   unsigned char *output_data = NULL;
+
+   unsigned char *password = NULL;
+   size_t password_len = 0;
+   unsigned char *salt = NULL;
+   size_t salt_len = 0;
+   size_t key_size = key_size_arg;
+
+   if( password_usage == USE_GIVEN_INPUT )
+      password = password_arg->x;
+
+   password_len = password_arg->len;
+
+   if( salt_usage == USE_GIVEN_INPUT )
+      salt = salt_arg->x;
+
+   salt_len = salt_arg->len;
+
+   ASSERT_ALLOC( output_data, key_size );
+
+   ret = mbedtls_pkcs12_derivation( output_data,
+                                    key_size,
+                                    password,
+                                    password_len,
+                                    salt,
+                                    salt_len,
+                                    md_type,
+                                    MBEDTLS_PKCS12_DERIVE_KEY,
+                                    iterations );
+
+   TEST_EQUAL( ret, expected_status );
+
+   if( expected_status == 0 )
+   {
+      ASSERT_COMPARE( expected_output->x, expected_output->len,
+                      output_data, key_size );
+   }
+
+exit:
+   mbedtls_free( output_data );
+
+}
+/* END_CASE */
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_pkcs1_v15.function b/third_party/mbedtls/repo/tests/suites/test_suite_pkcs1_v15.function
index 068027b..d355340 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_pkcs1_v15.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_pkcs1_v15.function
@@ -19,6 +19,8 @@
     mbedtls_test_rnd_buf_info info;
     mbedtls_mpi N, E;
 
+    info.fallback_f_rng = mbedtls_test_rnd_std_rand;
+    info.fallback_p_rng = NULL;
     info.buf = rnd_buf->x;
     info.length = rnd_buf->len;
 
@@ -26,8 +28,8 @@
     mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, hash );
     memset( output, 0x00, sizeof( output ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, NULL, NULL, NULL, &E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( ( mod + 7 ) / 8 ) );
     TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == 0 );
@@ -74,10 +76,10 @@
     memset( output, 0x00, sizeof( output ) );
     memset( &rnd_info, 0, sizeof( mbedtls_test_rnd_pseudo_info ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &P, radix_P, input_P ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Q, radix_Q, input_Q ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
 
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, &P, &Q, NULL, &E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( ( mod + 7 ) / 8 ) );
@@ -275,6 +277,8 @@
     mbedtls_mpi N, P, Q, E;
     mbedtls_test_rnd_buf_info info;
 
+    info.fallback_f_rng = mbedtls_test_rnd_std_rand;
+    info.fallback_p_rng = NULL;
     info.buf = rnd_buf->x;
     info.length = rnd_buf->len;
 
@@ -285,10 +289,10 @@
     memset( hash_result, 0x00, sizeof( hash_result ) );
     memset( output, 0x00, sizeof( output ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &P, radix_P, input_P ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Q, radix_Q, input_Q ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
 
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, &P, &Q, NULL, &E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( ( mod + 7 ) / 8 ) );
@@ -331,8 +335,8 @@
     mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, hash );
     memset( hash_result, 0x00, sizeof( hash_result ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, NULL, NULL, NULL, &E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( ( mod + 7 ) / 8 ) );
     TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == 0 );
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_pkcs1_v21.data b/third_party/mbedtls/repo/tests/suites/test_suite_pkcs1_v21.data
index 2dde5e9..405e16b 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_pkcs1_v21.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_pkcs1_v21.data
@@ -1,885 +1,1042 @@
 RSAES-OAEP Encryption Test Vector Int
-pkcs1_rsaes_oaep_encrypt:1024:16:"bbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb":16:"11":MBEDTLS_MD_SHA1:"d436e99569fd32a7c8a05bbc90d32c49":"aafd12f659cae63489b479e5076ddec2f06cb58f":"1253e04dc0a5397bb44a7ab87e9bf2a039a33d1e996fc82a94ccd30074c95df763722017069e5268da5d1c0b4f872cf653c11df82314a67968dfeae28def04bb6d84b1c31d654a1970e5783bd6eb96a024c2ca2f4a90fe9f2ef5c9c140e5bb48da9536ad8700c84fc9130adea74e558d51a74ddf85d8b50de96838d6063e0955":0
+pkcs1_rsaes_oaep_encrypt:1024:"bbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb":"11":MBEDTLS_MD_SHA1:"d436e99569fd32a7c8a05bbc90d32c49":"aafd12f659cae63489b479e5076ddec2f06cb58f":"1253e04dc0a5397bb44a7ab87e9bf2a039a33d1e996fc82a94ccd30074c95df763722017069e5268da5d1c0b4f872cf653c11df82314a67968dfeae28def04bb6d84b1c31d654a1970e5783bd6eb96a024c2ca2f4a90fe9f2ef5c9c140e5bb48da9536ad8700c84fc9130adea74e558d51a74ddf85d8b50de96838d6063e0955":0
 
 RSAES-OAEP Encryption Test Vector Data just fits
-pkcs1_rsaes_oaep_encrypt:1024:16:"bbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb":16:"11":MBEDTLS_MD_SHA1:"d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd":"aafd12f659cae63489b479e5076ddec2f06cb58f":"3082f2288fff275213d53168f0a272573cff81837c249dc1f380a12ac124c8f217b700708a1ce7dce154265f31a126ebdd9ed3ef9145ae29124a25f4e65aa52c5a9ff34f6cf4de9ba937ae406dc7d1f277af4f6fb7ea73bfbab2bd397b6b2c53570e173ffcf3b9f0bb96837623a4f87bd81b41446c59e681a2f3da81239e9bdf":0
+pkcs1_rsaes_oaep_encrypt:1024:"bbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb":"11":MBEDTLS_MD_SHA1:"d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd":"aafd12f659cae63489b479e5076ddec2f06cb58f":"3082f2288fff275213d53168f0a272573cff81837c249dc1f380a12ac124c8f217b700708a1ce7dce154265f31a126ebdd9ed3ef9145ae29124a25f4e65aa52c5a9ff34f6cf4de9ba937ae406dc7d1f277af4f6fb7ea73bfbab2bd397b6b2c53570e173ffcf3b9f0bb96837623a4f87bd81b41446c59e681a2f3da81239e9bdf":0
 
 RSAES-OAEP Encryption Test Vector Data too long
-pkcs1_rsaes_oaep_encrypt:1024:16:"bbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb":16:"11":MBEDTLS_MD_SHA1:"d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd00":"aafd12f659cae63489b479e5076ddec2f06cb58f":"1253e04dc0a5397bb44a7ab87e9bf2a039a33d1e996fc82a94ccd30074c95df763722017069e5268da5d1c0b4f872cf653c11df82314a67968dfeae28def04bb6d84b1c31d654a1970e5783bd6eb96a024c2ca2f4a90fe9f2ef5c9c140e5bb48da9536ad8700c84fc9130adea74e558d51a74ddf85d8b50de96838d6063e0955":MBEDTLS_ERR_RSA_BAD_INPUT_DATA
+pkcs1_rsaes_oaep_encrypt:1024:"bbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb":"11":MBEDTLS_MD_SHA1:"d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd00":"aafd12f659cae63489b479e5076ddec2f06cb58f":"1253e04dc0a5397bb44a7ab87e9bf2a039a33d1e996fc82a94ccd30074c95df763722017069e5268da5d1c0b4f872cf653c11df82314a67968dfeae28def04bb6d84b1c31d654a1970e5783bd6eb96a024c2ca2f4a90fe9f2ef5c9c140e5bb48da9536ad8700c84fc9130adea74e558d51a74ddf85d8b50de96838d6063e0955":MBEDTLS_ERR_RSA_BAD_INPUT_DATA
 
 RSAES-OAEP Encryption Test Vector 1_1
-pkcs1_rsaes_oaep_encrypt:1024:16:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":16:"010001":MBEDTLS_MD_SHA1:"6628194e12073db03ba94cda9ef9532397d50dba79b987004afefe34":"18b776ea21069d69776a33e96bad48e1dda0a5ef":"354fe67b4a126d5d35fe36c777791a3f7ba13def484e2d3908aff722fad468fb21696de95d0be911c2d3174f8afcc201035f7b6d8e69402de5451618c21a535fa9d7bfc5b8dd9fc243f8cf927db31322d6e881eaa91a996170e657a05a266426d98c88003f8477c1227094a0d9fa1e8c4024309ce1ecccb5210035d47ac72e8a":0
+pkcs1_rsaes_oaep_encrypt:1024:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":"010001":MBEDTLS_MD_SHA1:"6628194e12073db03ba94cda9ef9532397d50dba79b987004afefe34":"18b776ea21069d69776a33e96bad48e1dda0a5ef":"354fe67b4a126d5d35fe36c777791a3f7ba13def484e2d3908aff722fad468fb21696de95d0be911c2d3174f8afcc201035f7b6d8e69402de5451618c21a535fa9d7bfc5b8dd9fc243f8cf927db31322d6e881eaa91a996170e657a05a266426d98c88003f8477c1227094a0d9fa1e8c4024309ce1ecccb5210035d47ac72e8a":0
 
 RSAES-OAEP Encryption Test Vector 1_2
-pkcs1_rsaes_oaep_encrypt:1024:16:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":16:"010001":MBEDTLS_MD_SHA1:"750c4047f547e8e41411856523298ac9bae245efaf1397fbe56f9dd5":"0cc742ce4a9b7f32f951bcb251efd925fe4fe35f":"640db1acc58e0568fe5407e5f9b701dff8c3c91e716c536fc7fcec6cb5b71c1165988d4a279e1577d730fc7a29932e3f00c81515236d8d8e31017a7a09df4352d904cdeb79aa583adcc31ea698a4c05283daba9089be5491f67c1a4ee48dc74bbbe6643aef846679b4cb395a352d5ed115912df696ffe0702932946d71492b44":0
+pkcs1_rsaes_oaep_encrypt:1024:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":"010001":MBEDTLS_MD_SHA1:"750c4047f547e8e41411856523298ac9bae245efaf1397fbe56f9dd5":"0cc742ce4a9b7f32f951bcb251efd925fe4fe35f":"640db1acc58e0568fe5407e5f9b701dff8c3c91e716c536fc7fcec6cb5b71c1165988d4a279e1577d730fc7a29932e3f00c81515236d8d8e31017a7a09df4352d904cdeb79aa583adcc31ea698a4c05283daba9089be5491f67c1a4ee48dc74bbbe6643aef846679b4cb395a352d5ed115912df696ffe0702932946d71492b44":0
 
 RSAES-OAEP Encryption Test Vector 1_3
-pkcs1_rsaes_oaep_encrypt:1024:16:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":16:"010001":MBEDTLS_MD_SHA1:"d94ae0832e6445ce42331cb06d531a82b1db4baad30f746dc916df24d4e3c2451fff59a6423eb0e1d02d4fe646cf699dfd818c6e97b051":"2514df4695755a67b288eaf4905c36eec66fd2fd":"423736ed035f6026af276c35c0b3741b365e5f76ca091b4e8c29e2f0befee603595aa8322d602d2e625e95eb81b2f1c9724e822eca76db8618cf09c5343503a4360835b5903bc637e3879fb05e0ef32685d5aec5067cd7cc96fe4b2670b6eac3066b1fcf5686b68589aafb7d629b02d8f8625ca3833624d4800fb081b1cf94eb":0
+pkcs1_rsaes_oaep_encrypt:1024:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":"010001":MBEDTLS_MD_SHA1:"d94ae0832e6445ce42331cb06d531a82b1db4baad30f746dc916df24d4e3c2451fff59a6423eb0e1d02d4fe646cf699dfd818c6e97b051":"2514df4695755a67b288eaf4905c36eec66fd2fd":"423736ed035f6026af276c35c0b3741b365e5f76ca091b4e8c29e2f0befee603595aa8322d602d2e625e95eb81b2f1c9724e822eca76db8618cf09c5343503a4360835b5903bc637e3879fb05e0ef32685d5aec5067cd7cc96fe4b2670b6eac3066b1fcf5686b68589aafb7d629b02d8f8625ca3833624d4800fb081b1cf94eb":0
 
 RSAES-OAEP Encryption Test Vector 1_4
-pkcs1_rsaes_oaep_encrypt:1024:16:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":16:"010001":MBEDTLS_MD_SHA1:"52e650d98e7f2a048b4f86852153b97e01dd316f346a19f67a85":"c4435a3e1a18a68b6820436290a37cefb85db3fb":"45ead4ca551e662c9800f1aca8283b0525e6abae30be4b4aba762fa40fd3d38e22abefc69794f6ebbbc05ddbb11216247d2f412fd0fba87c6e3acd888813646fd0e48e785204f9c3f73d6d8239562722dddd8771fec48b83a31ee6f592c4cfd4bc88174f3b13a112aae3b9f7b80e0fc6f7255ba880dc7d8021e22ad6a85f0755":0
+pkcs1_rsaes_oaep_encrypt:1024:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":"010001":MBEDTLS_MD_SHA1:"52e650d98e7f2a048b4f86852153b97e01dd316f346a19f67a85":"c4435a3e1a18a68b6820436290a37cefb85db3fb":"45ead4ca551e662c9800f1aca8283b0525e6abae30be4b4aba762fa40fd3d38e22abefc69794f6ebbbc05ddbb11216247d2f412fd0fba87c6e3acd888813646fd0e48e785204f9c3f73d6d8239562722dddd8771fec48b83a31ee6f592c4cfd4bc88174f3b13a112aae3b9f7b80e0fc6f7255ba880dc7d8021e22ad6a85f0755":0
 
 RSAES-OAEP Encryption Test Vector 1_5
-pkcs1_rsaes_oaep_encrypt:1024:16:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":16:"010001":MBEDTLS_MD_SHA1:"8da89fd9e5f974a29feffb462b49180f6cf9e802":"b318c42df3be0f83fea823f5a7b47ed5e425a3b5":"36f6e34d94a8d34daacba33a2139d00ad85a9345a86051e73071620056b920e219005855a213a0f23897cdcd731b45257c777fe908202befdd0b58386b1244ea0cf539a05d5d10329da44e13030fd760dcd644cfef2094d1910d3f433e1c7c6dd18bc1f2df7f643d662fb9dd37ead9059190f4fa66ca39e869c4eb449cbdc439":0
+pkcs1_rsaes_oaep_encrypt:1024:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":"010001":MBEDTLS_MD_SHA1:"8da89fd9e5f974a29feffb462b49180f6cf9e802":"b318c42df3be0f83fea823f5a7b47ed5e425a3b5":"36f6e34d94a8d34daacba33a2139d00ad85a9345a86051e73071620056b920e219005855a213a0f23897cdcd731b45257c777fe908202befdd0b58386b1244ea0cf539a05d5d10329da44e13030fd760dcd644cfef2094d1910d3f433e1c7c6dd18bc1f2df7f643d662fb9dd37ead9059190f4fa66ca39e869c4eb449cbdc439":0
 
 RSAES-OAEP Encryption Test Vector 1_6
-pkcs1_rsaes_oaep_encrypt:1024:16:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":16:"010001":MBEDTLS_MD_SHA1:"26521050844271":"e4ec0982c2336f3a677f6a356174eb0ce887abc2":"42cee2617b1ecea4db3f4829386fbd61dafbf038e180d837c96366df24c097b4ab0fac6bdf590d821c9f10642e681ad05b8d78b378c0f46ce2fad63f74e0ad3df06b075d7eb5f5636f8d403b9059ca761b5c62bb52aa45002ea70baace08ded243b9d8cbd62a68ade265832b56564e43a6fa42ed199a099769742df1539e8255":0
+pkcs1_rsaes_oaep_encrypt:1024:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":"010001":MBEDTLS_MD_SHA1:"26521050844271":"e4ec0982c2336f3a677f6a356174eb0ce887abc2":"42cee2617b1ecea4db3f4829386fbd61dafbf038e180d837c96366df24c097b4ab0fac6bdf590d821c9f10642e681ad05b8d78b378c0f46ce2fad63f74e0ad3df06b075d7eb5f5636f8d403b9059ca761b5c62bb52aa45002ea70baace08ded243b9d8cbd62a68ade265832b56564e43a6fa42ed199a099769742df1539e8255":0
 
 RSAES-OAEP Encryption Test Vector 2_1
-pkcs1_rsaes_oaep_encrypt:1025:16:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":16:"010001":MBEDTLS_MD_SHA1:"8ff00caa605c702830634d9a6c3d42c652b58cf1d92fec570beee7":"8c407b5ec2899e5099c53e8ce793bf94e71b1782":"0181af8922b9fcb4d79d92ebe19815992fc0c1439d8bcd491398a0f4ad3a329a5bd9385560db532683c8b7da04e4b12aed6aacdf471c34c9cda891addcc2df3456653aa6382e9ae59b54455257eb099d562bbe10453f2b6d13c59c02e10f1f8abb5da0d0570932dacf2d0901db729d0fefcc054e70968ea540c81b04bcaefe720e":0
+pkcs1_rsaes_oaep_encrypt:1025:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":"010001":MBEDTLS_MD_SHA1:"8ff00caa605c702830634d9a6c3d42c652b58cf1d92fec570beee7":"8c407b5ec2899e5099c53e8ce793bf94e71b1782":"0181af8922b9fcb4d79d92ebe19815992fc0c1439d8bcd491398a0f4ad3a329a5bd9385560db532683c8b7da04e4b12aed6aacdf471c34c9cda891addcc2df3456653aa6382e9ae59b54455257eb099d562bbe10453f2b6d13c59c02e10f1f8abb5da0d0570932dacf2d0901db729d0fefcc054e70968ea540c81b04bcaefe720e":0
 
 RSAES-OAEP Encryption Test Vector 2_2
-pkcs1_rsaes_oaep_encrypt:1025:16:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":16:"010001":MBEDTLS_MD_SHA1:"2d":"b600cf3c2e506d7f16778c910d3a8b003eee61d5":"018759ff1df63b2792410562314416a8aeaf2ac634b46f940ab82d64dbf165eee33011da749d4bab6e2fcd18129c9e49277d8453112b429a222a8471b070993998e758861c4d3f6d749d91c4290d332c7a4ab3f7ea35ff3a07d497c955ff0ffc95006b62c6d296810d9bfab024196c7934012c2df978ef299aba239940cba10245":0
+pkcs1_rsaes_oaep_encrypt:1025:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":"010001":MBEDTLS_MD_SHA1:"2d":"b600cf3c2e506d7f16778c910d3a8b003eee61d5":"018759ff1df63b2792410562314416a8aeaf2ac634b46f940ab82d64dbf165eee33011da749d4bab6e2fcd18129c9e49277d8453112b429a222a8471b070993998e758861c4d3f6d749d91c4290d332c7a4ab3f7ea35ff3a07d497c955ff0ffc95006b62c6d296810d9bfab024196c7934012c2df978ef299aba239940cba10245":0
 
 RSAES-OAEP Encryption Test Vector 2_3
-pkcs1_rsaes_oaep_encrypt:1025:16:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":16:"010001":MBEDTLS_MD_SHA1:"74fc88c51bc90f77af9d5e9a4a70133d4b4e0b34da3c37c7ef8e":"a73768aeeaa91f9d8c1ed6f9d2b63467f07ccae3":"018802bab04c60325e81c4962311f2be7c2adce93041a00719c88f957575f2c79f1b7bc8ced115c706b311c08a2d986ca3b6a9336b147c29c6f229409ddec651bd1fdd5a0b7f610c9937fdb4a3a762364b8b3206b4ea485fd098d08f63d4aa8bb2697d027b750c32d7f74eaf5180d2e9b66b17cb2fa55523bc280da10d14be2053":0
+pkcs1_rsaes_oaep_encrypt:1025:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":"010001":MBEDTLS_MD_SHA1:"74fc88c51bc90f77af9d5e9a4a70133d4b4e0b34da3c37c7ef8e":"a73768aeeaa91f9d8c1ed6f9d2b63467f07ccae3":"018802bab04c60325e81c4962311f2be7c2adce93041a00719c88f957575f2c79f1b7bc8ced115c706b311c08a2d986ca3b6a9336b147c29c6f229409ddec651bd1fdd5a0b7f610c9937fdb4a3a762364b8b3206b4ea485fd098d08f63d4aa8bb2697d027b750c32d7f74eaf5180d2e9b66b17cb2fa55523bc280da10d14be2053":0
 
 RSAES-OAEP Encryption Test Vector 2_4
-pkcs1_rsaes_oaep_encrypt:1025:16:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":16:"010001":MBEDTLS_MD_SHA1:"a7eb2a5036931d27d4e891326d99692ffadda9bf7efd3e34e622c4adc085f721dfe885072c78a203b151739be540fa8c153a10f00a":"9a7b3b0e708bd96f8190ecab4fb9b2b3805a8156":"00a4578cbc176318a638fba7d01df15746af44d4f6cd96d7e7c495cbf425b09c649d32bf886da48fbaf989a2117187cafb1fb580317690e3ccd446920b7af82b31db5804d87d01514acbfa9156e782f867f6bed9449e0e9a2c09bcecc6aa087636965e34b3ec766f2fe2e43018a2fddeb140616a0e9d82e5331024ee0652fc7641":0
+pkcs1_rsaes_oaep_encrypt:1025:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":"010001":MBEDTLS_MD_SHA1:"a7eb2a5036931d27d4e891326d99692ffadda9bf7efd3e34e622c4adc085f721dfe885072c78a203b151739be540fa8c153a10f00a":"9a7b3b0e708bd96f8190ecab4fb9b2b3805a8156":"00a4578cbc176318a638fba7d01df15746af44d4f6cd96d7e7c495cbf425b09c649d32bf886da48fbaf989a2117187cafb1fb580317690e3ccd446920b7af82b31db5804d87d01514acbfa9156e782f867f6bed9449e0e9a2c09bcecc6aa087636965e34b3ec766f2fe2e43018a2fddeb140616a0e9d82e5331024ee0652fc7641":0
 
 RSAES-OAEP Encryption Test Vector 2_5
-pkcs1_rsaes_oaep_encrypt:1025:16:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":16:"010001":MBEDTLS_MD_SHA1:"2ef2b066f854c33f3bdcbb5994a435e73d6c6c":"eb3cebbc4adc16bb48e88c8aec0e34af7f427fd3":"00ebc5f5fda77cfdad3c83641a9025e77d72d8a6fb33a810f5950f8d74c73e8d931e8634d86ab1246256ae07b6005b71b7f2fb98351218331ce69b8ffbdc9da08bbc9c704f876deb9df9fc2ec065cad87f9090b07acc17aa7f997b27aca48806e897f771d95141fe4526d8a5301b678627efab707fd40fbebd6e792a25613e7aec":0
+pkcs1_rsaes_oaep_encrypt:1025:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":"010001":MBEDTLS_MD_SHA1:"2ef2b066f854c33f3bdcbb5994a435e73d6c6c":"eb3cebbc4adc16bb48e88c8aec0e34af7f427fd3":"00ebc5f5fda77cfdad3c83641a9025e77d72d8a6fb33a810f5950f8d74c73e8d931e8634d86ab1246256ae07b6005b71b7f2fb98351218331ce69b8ffbdc9da08bbc9c704f876deb9df9fc2ec065cad87f9090b07acc17aa7f997b27aca48806e897f771d95141fe4526d8a5301b678627efab707fd40fbebd6e792a25613e7aec":0
 
 RSAES-OAEP Encryption Test Vector 2_6
-pkcs1_rsaes_oaep_encrypt:1025:16:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":16:"010001":MBEDTLS_MD_SHA1:"8a7fb344c8b6cb2cf2ef1f643f9a3218f6e19bba89c0":"4c45cf4d57c98e3d6d2095adc51c489eb50dff84":"010839ec20c27b9052e55befb9b77e6fc26e9075d7a54378c646abdf51e445bd5715de81789f56f1803d9170764a9e93cb78798694023ee7393ce04bc5d8f8c5a52c171d43837e3aca62f609eb0aa5ffb0960ef04198dd754f57f7fbe6abf765cf118b4ca443b23b5aab266f952326ac4581100644325f8b721acd5d04ff14ef3a":0
+pkcs1_rsaes_oaep_encrypt:1025:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":"010001":MBEDTLS_MD_SHA1:"8a7fb344c8b6cb2cf2ef1f643f9a3218f6e19bba89c0":"4c45cf4d57c98e3d6d2095adc51c489eb50dff84":"010839ec20c27b9052e55befb9b77e6fc26e9075d7a54378c646abdf51e445bd5715de81789f56f1803d9170764a9e93cb78798694023ee7393ce04bc5d8f8c5a52c171d43837e3aca62f609eb0aa5ffb0960ef04198dd754f57f7fbe6abf765cf118b4ca443b23b5aab266f952326ac4581100644325f8b721acd5d04ff14ef3a":0
 
 RSAES-OAEP Encryption Example 3_1
-pkcs1_rsaes_oaep_encrypt:1026:16:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":16:"010001":MBEDTLS_MD_SHA1:"087820b569e8fa8d":"8ced6b196290805790e909074015e6a20b0c4894":"026a0485d96aebd96b4382085099b962e6a2bdec3d90c8db625e14372de85e2d5b7baab65c8faf91bb5504fb495afce5c988b3f6a52e20e1d6cbd3566c5cd1f2b8318bb542cc0ea25c4aab9932afa20760eaddec784396a07ea0ef24d4e6f4d37e5052a7a31e146aa480a111bbe926401307e00f410033842b6d82fe5ce4dfae80":0
+pkcs1_rsaes_oaep_encrypt:1026:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":"010001":MBEDTLS_MD_SHA1:"087820b569e8fa8d":"8ced6b196290805790e909074015e6a20b0c4894":"026a0485d96aebd96b4382085099b962e6a2bdec3d90c8db625e14372de85e2d5b7baab65c8faf91bb5504fb495afce5c988b3f6a52e20e1d6cbd3566c5cd1f2b8318bb542cc0ea25c4aab9932afa20760eaddec784396a07ea0ef24d4e6f4d37e5052a7a31e146aa480a111bbe926401307e00f410033842b6d82fe5ce4dfae80":0
 
 RSAES-OAEP Encryption Example 3_2
-pkcs1_rsaes_oaep_encrypt:1026:16:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":16:"010001":MBEDTLS_MD_SHA1:"4653acaf171960b01f52a7be63a3ab21dc368ec43b50d82ec3781e04":"b4291d6567550848cc156967c809baab6ca507f0":"024db89c7802989be0783847863084941bf209d761987e38f97cb5f6f1bc88da72a50b73ebaf11c879c4f95df37b850b8f65d7622e25b1b889e80fe80baca2069d6e0e1d829953fc459069de98ea9798b451e557e99abf8fe3d9ccf9096ebbf3e5255d3b4e1c6d2ecadf067a359eea86405acd47d5e165517ccafd47d6dbee4bf5":0
+pkcs1_rsaes_oaep_encrypt:1026:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":"010001":MBEDTLS_MD_SHA1:"4653acaf171960b01f52a7be63a3ab21dc368ec43b50d82ec3781e04":"b4291d6567550848cc156967c809baab6ca507f0":"024db89c7802989be0783847863084941bf209d761987e38f97cb5f6f1bc88da72a50b73ebaf11c879c4f95df37b850b8f65d7622e25b1b889e80fe80baca2069d6e0e1d829953fc459069de98ea9798b451e557e99abf8fe3d9ccf9096ebbf3e5255d3b4e1c6d2ecadf067a359eea86405acd47d5e165517ccafd47d6dbee4bf5":0
 
 RSAES-OAEP Encryption Example 3_3
-pkcs1_rsaes_oaep_encrypt:1026:16:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":16:"010001":MBEDTLS_MD_SHA1:"d94cd0e08fa404ed89":"ce8928f6059558254008badd9794fadcd2fd1f65":"0239bce681032441528877d6d1c8bb28aa3bc97f1df584563618995797683844ca86664732f4bed7a0aab083aaabfb7238f582e30958c2024e44e57043b97950fd543da977c90cdde5337d618442f99e60d7783ab59ce6dd9d69c47ad1e962bec22d05895cff8d3f64ed5261d92b2678510393484990ba3f7f06818ae6ffce8a3a":0
+pkcs1_rsaes_oaep_encrypt:1026:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":"010001":MBEDTLS_MD_SHA1:"d94cd0e08fa404ed89":"ce8928f6059558254008badd9794fadcd2fd1f65":"0239bce681032441528877d6d1c8bb28aa3bc97f1df584563618995797683844ca86664732f4bed7a0aab083aaabfb7238f582e30958c2024e44e57043b97950fd543da977c90cdde5337d618442f99e60d7783ab59ce6dd9d69c47ad1e962bec22d05895cff8d3f64ed5261d92b2678510393484990ba3f7f06818ae6ffce8a3a":0
 
 RSAES-OAEP Encryption Example 3_4
-pkcs1_rsaes_oaep_encrypt:1026:16:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":16:"010001":MBEDTLS_MD_SHA1:"6cc641b6b61e6f963974dad23a9013284ef1":"6e2979f52d6814a57d83b090054888f119a5b9a3":"02994c62afd76f498ba1fd2cf642857fca81f4373cb08f1cbaee6f025c3b512b42c3e8779113476648039dbe0493f9246292fac28950600e7c0f32edf9c81b9dec45c3bde0cc8d8847590169907b7dc5991ceb29bb0714d613d96df0f12ec5d8d3507c8ee7ae78dd83f216fa61de100363aca48a7e914ae9f42ddfbe943b09d9a0":0
+pkcs1_rsaes_oaep_encrypt:1026:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":"010001":MBEDTLS_MD_SHA1:"6cc641b6b61e6f963974dad23a9013284ef1":"6e2979f52d6814a57d83b090054888f119a5b9a3":"02994c62afd76f498ba1fd2cf642857fca81f4373cb08f1cbaee6f025c3b512b42c3e8779113476648039dbe0493f9246292fac28950600e7c0f32edf9c81b9dec45c3bde0cc8d8847590169907b7dc5991ceb29bb0714d613d96df0f12ec5d8d3507c8ee7ae78dd83f216fa61de100363aca48a7e914ae9f42ddfbe943b09d9a0":0
 
 RSAES-OAEP Encryption Example 3_5
-pkcs1_rsaes_oaep_encrypt:1026:16:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":16:"010001":MBEDTLS_MD_SHA1:"df5151832b61f4f25891fb4172f328d2eddf8371ffcfdbe997939295f30eca6918017cfda1153bf7a6af87593223":"2d760bfe38c59de34cdc8b8c78a38e66284a2d27":"0162042ff6969592a6167031811a239834ce638abf54fec8b99478122afe2ee67f8c5b18b0339805bfdbc5a4e6720b37c59cfba942464c597ff532a119821545fd2e59b114e61daf71820529f5029cf524954327c34ec5e6f5ba7efcc4de943ab8ad4ed787b1454329f70db798a3a8f4d92f8274e2b2948ade627ce8ee33e43c60":0
+pkcs1_rsaes_oaep_encrypt:1026:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":"010001":MBEDTLS_MD_SHA1:"df5151832b61f4f25891fb4172f328d2eddf8371ffcfdbe997939295f30eca6918017cfda1153bf7a6af87593223":"2d760bfe38c59de34cdc8b8c78a38e66284a2d27":"0162042ff6969592a6167031811a239834ce638abf54fec8b99478122afe2ee67f8c5b18b0339805bfdbc5a4e6720b37c59cfba942464c597ff532a119821545fd2e59b114e61daf71820529f5029cf524954327c34ec5e6f5ba7efcc4de943ab8ad4ed787b1454329f70db798a3a8f4d92f8274e2b2948ade627ce8ee33e43c60":0
 
 RSAES-OAEP Encryption Example 3_6
-pkcs1_rsaes_oaep_encrypt:1026:16:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":16:"010001":MBEDTLS_MD_SHA1:"3c3bad893c544a6d520ab022319188c8d504b7a788b850903b85972eaa18552e1134a7ad6098826254ff7ab672b3d8eb3158fac6d4cbaef1":"f174779c5fd3cfe007badcb7a36c9b55bfcfbf0e":"00112051e75d064943bc4478075e43482fd59cee0679de6893eec3a943daa490b9691c93dfc0464b6623b9f3dbd3e70083264f034b374f74164e1a00763725e574744ba0b9db83434f31df96f6e2a26f6d8eba348bd4686c2238ac07c37aac3785d1c7eea2f819fd91491798ed8e9cef5e43b781b0e0276e37c43ff9492d005730":0
+pkcs1_rsaes_oaep_encrypt:1026:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":"010001":MBEDTLS_MD_SHA1:"3c3bad893c544a6d520ab022319188c8d504b7a788b850903b85972eaa18552e1134a7ad6098826254ff7ab672b3d8eb3158fac6d4cbaef1":"f174779c5fd3cfe007badcb7a36c9b55bfcfbf0e":"00112051e75d064943bc4478075e43482fd59cee0679de6893eec3a943daa490b9691c93dfc0464b6623b9f3dbd3e70083264f034b374f74164e1a00763725e574744ba0b9db83434f31df96f6e2a26f6d8eba348bd4686c2238ac07c37aac3785d1c7eea2f819fd91491798ed8e9cef5e43b781b0e0276e37c43ff9492d005730":0
 
 RSAES-OAEP Encryption Example 4_1
-pkcs1_rsaes_oaep_encrypt:1027:16:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":16:"010001":MBEDTLS_MD_SHA1:"4a86609534ee434a6cbca3f7e962e76d455e3264c19f605f6e5ff6137c65c56d7fb344cd52bc93374f3d166c9f0c6f9c506bad19330972d2":"1cac19ce993def55f98203f6852896c95ccca1f3":"04cce19614845e094152a3fe18e54e3330c44e5efbc64ae16886cb1869014cc5781b1f8f9e045384d0112a135ca0d12e9c88a8e4063416deaae3844f60d6e96fe155145f4525b9a34431ca3766180f70e15a5e5d8e8b1a516ff870609f13f896935ced188279a58ed13d07114277d75c6568607e0ab092fd803a223e4a8ee0b1a8":0
+pkcs1_rsaes_oaep_encrypt:1027:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":"010001":MBEDTLS_MD_SHA1:"4a86609534ee434a6cbca3f7e962e76d455e3264c19f605f6e5ff6137c65c56d7fb344cd52bc93374f3d166c9f0c6f9c506bad19330972d2":"1cac19ce993def55f98203f6852896c95ccca1f3":"04cce19614845e094152a3fe18e54e3330c44e5efbc64ae16886cb1869014cc5781b1f8f9e045384d0112a135ca0d12e9c88a8e4063416deaae3844f60d6e96fe155145f4525b9a34431ca3766180f70e15a5e5d8e8b1a516ff870609f13f896935ced188279a58ed13d07114277d75c6568607e0ab092fd803a223e4a8ee0b1a8":0
 
 RSAES-OAEP Encryption Example 4_2
-pkcs1_rsaes_oaep_encrypt:1027:16:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":16:"010001":MBEDTLS_MD_SHA1:"b0adc4f3fe11da59ce992773d9059943c03046497ee9d9f9a06df1166db46d98f58d27ec074c02eee6cbe2449c8b9fc5080c5c3f4433092512ec46aa793743c8":"f545d5897585e3db71aa0cb8da76c51d032ae963":"0097b698c6165645b303486fbf5a2a4479c0ee85889b541a6f0b858d6b6597b13b854eb4f839af03399a80d79bda6578c841f90d645715b280d37143992dd186c80b949b775cae97370e4ec97443136c6da484e970ffdb1323a20847821d3b18381de13bb49aaea66530c4a4b8271f3eae172cd366e07e6636f1019d2a28aed15e":0
+pkcs1_rsaes_oaep_encrypt:1027:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":"010001":MBEDTLS_MD_SHA1:"b0adc4f3fe11da59ce992773d9059943c03046497ee9d9f9a06df1166db46d98f58d27ec074c02eee6cbe2449c8b9fc5080c5c3f4433092512ec46aa793743c8":"f545d5897585e3db71aa0cb8da76c51d032ae963":"0097b698c6165645b303486fbf5a2a4479c0ee85889b541a6f0b858d6b6597b13b854eb4f839af03399a80d79bda6578c841f90d645715b280d37143992dd186c80b949b775cae97370e4ec97443136c6da484e970ffdb1323a20847821d3b18381de13bb49aaea66530c4a4b8271f3eae172cd366e07e6636f1019d2a28aed15e":0
 
 RSAES-OAEP Encryption Example 4_3
-pkcs1_rsaes_oaep_encrypt:1027:16:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":16:"010001":MBEDTLS_MD_SHA1:"bf6d42e701707b1d0206b0c8b45a1c72641ff12889219a82bdea965b5e79a96b0d0163ed9d578ec9ada20f2fbcf1ea3c4089d83419ba81b0c60f3606da99":"ad997feef730d6ea7be60d0dc52e72eacbfdd275":"0301f935e9c47abcb48acbbe09895d9f5971af14839da4ff95417ee453d1fd77319072bb7297e1b55d7561cd9d1bb24c1a9a37c619864308242804879d86ebd001dce5183975e1506989b70e5a83434154d5cbfd6a24787e60eb0c658d2ac193302d1192c6e622d4a12ad4b53923bca246df31c6395e37702c6a78ae081fb9d065":0
+pkcs1_rsaes_oaep_encrypt:1027:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":"010001":MBEDTLS_MD_SHA1:"bf6d42e701707b1d0206b0c8b45a1c72641ff12889219a82bdea965b5e79a96b0d0163ed9d578ec9ada20f2fbcf1ea3c4089d83419ba81b0c60f3606da99":"ad997feef730d6ea7be60d0dc52e72eacbfdd275":"0301f935e9c47abcb48acbbe09895d9f5971af14839da4ff95417ee453d1fd77319072bb7297e1b55d7561cd9d1bb24c1a9a37c619864308242804879d86ebd001dce5183975e1506989b70e5a83434154d5cbfd6a24787e60eb0c658d2ac193302d1192c6e622d4a12ad4b53923bca246df31c6395e37702c6a78ae081fb9d065":0
 
 RSAES-OAEP Encryption Example 4_4
-pkcs1_rsaes_oaep_encrypt:1027:16:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":16:"010001":MBEDTLS_MD_SHA1:"fb2ef112f5e766eb94019297934794f7be2f6fc1c58e":"136454df5730f73c807a7e40d8c1a312ac5b9dd3":"02d110ad30afb727beb691dd0cf17d0af1a1e7fa0cc040ec1a4ba26a42c59d0a796a2e22c8f357ccc98b6519aceb682e945e62cb734614a529407cd452bee3e44fece8423cc19e55548b8b994b849c7ecde4933e76037e1d0ce44275b08710c68e430130b929730ed77e09b015642c5593f04e4ffb9410798102a8e96ffdfe11e4":0
+pkcs1_rsaes_oaep_encrypt:1027:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":"010001":MBEDTLS_MD_SHA1:"fb2ef112f5e766eb94019297934794f7be2f6fc1c58e":"136454df5730f73c807a7e40d8c1a312ac5b9dd3":"02d110ad30afb727beb691dd0cf17d0af1a1e7fa0cc040ec1a4ba26a42c59d0a796a2e22c8f357ccc98b6519aceb682e945e62cb734614a529407cd452bee3e44fece8423cc19e55548b8b994b849c7ecde4933e76037e1d0ce44275b08710c68e430130b929730ed77e09b015642c5593f04e4ffb9410798102a8e96ffdfe11e4":0
 
 RSAES-OAEP Encryption Example 4_5
-pkcs1_rsaes_oaep_encrypt:1027:16:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":16:"010001":MBEDTLS_MD_SHA1:"28ccd447bb9e85166dabb9e5b7d1adadc4b9d39f204e96d5e440ce9ad928bc1c2284":"bca8057f824b2ea257f2861407eef63d33208681":"00dbb8a7439d90efd919a377c54fae8fe11ec58c3b858362e23ad1b8a44310799066b99347aa525691d2adc58d9b06e34f288c170390c5f0e11c0aa3645959f18ee79e8f2be8d7ac5c23d061f18dd74b8c5f2a58fcb5eb0c54f99f01a83247568292536583340948d7a8c97c4acd1e98d1e29dc320e97a260532a8aa7a758a1ec2":0
+pkcs1_rsaes_oaep_encrypt:1027:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":"010001":MBEDTLS_MD_SHA1:"28ccd447bb9e85166dabb9e5b7d1adadc4b9d39f204e96d5e440ce9ad928bc1c2284":"bca8057f824b2ea257f2861407eef63d33208681":"00dbb8a7439d90efd919a377c54fae8fe11ec58c3b858362e23ad1b8a44310799066b99347aa525691d2adc58d9b06e34f288c170390c5f0e11c0aa3645959f18ee79e8f2be8d7ac5c23d061f18dd74b8c5f2a58fcb5eb0c54f99f01a83247568292536583340948d7a8c97c4acd1e98d1e29dc320e97a260532a8aa7a758a1ec2":0
 
 RSAES-OAEP Encryption Example 4_6
-pkcs1_rsaes_oaep_encrypt:1027:16:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":16:"010001":MBEDTLS_MD_SHA1:"f22242751ec6b1":"2e7e1e17f647b5ddd033e15472f90f6812f3ac4e":"00a5ffa4768c8bbecaee2db77e8f2eec99595933545520835e5ba7db9493d3e17cddefe6a5f567624471908db4e2d83a0fbee60608fc84049503b2234a07dc83b27b22847ad8920ff42f674ef79b76280b00233d2b51b8cb2703a9d42bfbc8250c96ec32c051e57f1b4ba528db89c37e4c54e27e6e64ac69635ae887d9541619a9":0
+pkcs1_rsaes_oaep_encrypt:1027:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":"010001":MBEDTLS_MD_SHA1:"f22242751ec6b1":"2e7e1e17f647b5ddd033e15472f90f6812f3ac4e":"00a5ffa4768c8bbecaee2db77e8f2eec99595933545520835e5ba7db9493d3e17cddefe6a5f567624471908db4e2d83a0fbee60608fc84049503b2234a07dc83b27b22847ad8920ff42f674ef79b76280b00233d2b51b8cb2703a9d42bfbc8250c96ec32c051e57f1b4ba528db89c37e4c54e27e6e64ac69635ae887d9541619a9":0
 
 RSAES-OAEP Encryption Example 5_1
-pkcs1_rsaes_oaep_encrypt:1028:16:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":16:"010001":MBEDTLS_MD_SHA1:"af71a901e3a61d3132f0fc1fdb474f9ea6579257ffc24d164170145b3dbde8":"44c92e283f77b9499c603d963660c87d2f939461":"036046a4a47d9ed3ba9a89139c105038eb7492b05a5d68bfd53accff4597f7a68651b47b4a4627d927e485eed7b4566420e8b409879e5d606eae251d22a5df799f7920bfc117b992572a53b1263146bcea03385cc5e853c9a101c8c3e1bda31a519807496c6cb5e5efb408823a352b8fa0661fb664efadd593deb99fff5ed000e5":0
+pkcs1_rsaes_oaep_encrypt:1028:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":"010001":MBEDTLS_MD_SHA1:"af71a901e3a61d3132f0fc1fdb474f9ea6579257ffc24d164170145b3dbde8":"44c92e283f77b9499c603d963660c87d2f939461":"036046a4a47d9ed3ba9a89139c105038eb7492b05a5d68bfd53accff4597f7a68651b47b4a4627d927e485eed7b4566420e8b409879e5d606eae251d22a5df799f7920bfc117b992572a53b1263146bcea03385cc5e853c9a101c8c3e1bda31a519807496c6cb5e5efb408823a352b8fa0661fb664efadd593deb99fff5ed000e5":0
 
 RSAES-OAEP Encryption Example 5_2
-pkcs1_rsaes_oaep_encrypt:1028:16:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":16:"010001":MBEDTLS_MD_SHA1:"a3b844a08239a8ac41605af17a6cfda4d350136585903a417a79268760519a4b4ac3303ec73f0f87cfb32399":"cb28f5860659fceee49c3eeafce625a70803bd32":"03d6eb654edce615bc59f455265ed4e5a18223cbb9be4e4069b473804d5de96f54dcaaa603d049c5d94aa1470dfcd2254066b7c7b61ff1f6f6770e3215c51399fd4e34ec5082bc48f089840ad04354ae66dc0f1bd18e461a33cc1258b443a2837a6df26759aa2302334986f87380c9cc9d53be9f99605d2c9a97da7b0915a4a7ad":0
+pkcs1_rsaes_oaep_encrypt:1028:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":"010001":MBEDTLS_MD_SHA1:"a3b844a08239a8ac41605af17a6cfda4d350136585903a417a79268760519a4b4ac3303ec73f0f87cfb32399":"cb28f5860659fceee49c3eeafce625a70803bd32":"03d6eb654edce615bc59f455265ed4e5a18223cbb9be4e4069b473804d5de96f54dcaaa603d049c5d94aa1470dfcd2254066b7c7b61ff1f6f6770e3215c51399fd4e34ec5082bc48f089840ad04354ae66dc0f1bd18e461a33cc1258b443a2837a6df26759aa2302334986f87380c9cc9d53be9f99605d2c9a97da7b0915a4a7ad":0
 
 RSAES-OAEP Encryption Example 5_3
-pkcs1_rsaes_oaep_encrypt:1028:16:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":16:"010001":MBEDTLS_MD_SHA1:"308b0ecbd2c76cb77fc6f70c5edd233fd2f20929d629f026953bb62a8f4a3a314bde195de85b5f816da2aab074d26cb6acddf323ae3b9c678ac3cf12fbdde7":"2285f40d770482f9a9efa2c72cb3ac55716dc0ca":"0770952181649f9f9f07ff626ff3a22c35c462443d905d456a9fd0bff43cac2ca7a9f554e9478b9acc3ac838b02040ffd3e1847de2e4253929f9dd9ee4044325a9b05cabb808b2ee840d34e15d105a3f1f7b27695a1a07a2d73fe08ecaaa3c9c9d4d5a89ff890d54727d7ae40c0ec1a8dd86165d8ee2c6368141016a48b55b6967":0
+pkcs1_rsaes_oaep_encrypt:1028:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":"010001":MBEDTLS_MD_SHA1:"308b0ecbd2c76cb77fc6f70c5edd233fd2f20929d629f026953bb62a8f4a3a314bde195de85b5f816da2aab074d26cb6acddf323ae3b9c678ac3cf12fbdde7":"2285f40d770482f9a9efa2c72cb3ac55716dc0ca":"0770952181649f9f9f07ff626ff3a22c35c462443d905d456a9fd0bff43cac2ca7a9f554e9478b9acc3ac838b02040ffd3e1847de2e4253929f9dd9ee4044325a9b05cabb808b2ee840d34e15d105a3f1f7b27695a1a07a2d73fe08ecaaa3c9c9d4d5a89ff890d54727d7ae40c0ec1a8dd86165d8ee2c6368141016a48b55b6967":0
 
 RSAES-OAEP Encryption Example 5_4
-pkcs1_rsaes_oaep_encrypt:1028:16:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":16:"010001":MBEDTLS_MD_SHA1:"15c5b9ee1185":"49fa45d3a78dd10dfd577399d1eb00af7eed5513":"0812b76768ebcb642d040258e5f4441a018521bd96687e6c5e899fcd6c17588ff59a82cc8ae03a4b45b31299af1788c329f7dcd285f8cf4ced82606b97612671a45bedca133442144d1617d114f802857f0f9d739751c57a3f9ee400912c61e2e6992be031a43dd48fa6ba14eef7c422b5edc4e7afa04fdd38f402d1c8bb719abf":0
+pkcs1_rsaes_oaep_encrypt:1028:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":"010001":MBEDTLS_MD_SHA1:"15c5b9ee1185":"49fa45d3a78dd10dfd577399d1eb00af7eed5513":"0812b76768ebcb642d040258e5f4441a018521bd96687e6c5e899fcd6c17588ff59a82cc8ae03a4b45b31299af1788c329f7dcd285f8cf4ced82606b97612671a45bedca133442144d1617d114f802857f0f9d739751c57a3f9ee400912c61e2e6992be031a43dd48fa6ba14eef7c422b5edc4e7afa04fdd38f402d1c8bb719abf":0
 
 RSAES-OAEP Encryption Example 5_5
-pkcs1_rsaes_oaep_encrypt:1028:16:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":16:"010001":MBEDTLS_MD_SHA1:"21026e6800c7fa728fcaaba0d196ae28d7a2ac4ffd8abce794f0985f60c8a6737277365d3fea11db8923a2029a":"f0287413234cc5034724a094c4586b87aff133fc":"07b60e14ec954bfd29e60d0047e789f51d57186c63589903306793ced3f68241c743529aba6a6374f92e19e0163efa33697e196f7661dfaaa47aac6bde5e51deb507c72c589a2ca1693d96b1460381249b2cdb9eac44769f2489c5d3d2f99f0ee3c7ee5bf64a5ac79c42bd433f149be8cb59548361640595513c97af7bc2509723":0
+pkcs1_rsaes_oaep_encrypt:1028:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":"010001":MBEDTLS_MD_SHA1:"21026e6800c7fa728fcaaba0d196ae28d7a2ac4ffd8abce794f0985f60c8a6737277365d3fea11db8923a2029a":"f0287413234cc5034724a094c4586b87aff133fc":"07b60e14ec954bfd29e60d0047e789f51d57186c63589903306793ced3f68241c743529aba6a6374f92e19e0163efa33697e196f7661dfaaa47aac6bde5e51deb507c72c589a2ca1693d96b1460381249b2cdb9eac44769f2489c5d3d2f99f0ee3c7ee5bf64a5ac79c42bd433f149be8cb59548361640595513c97af7bc2509723":0
 
 RSAES-OAEP Encryption Example 5_6
-pkcs1_rsaes_oaep_encrypt:1028:16:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":16:"010001":MBEDTLS_MD_SHA1:"541e37b68b6c8872b84c02":"d9fba45c96f21e6e26d29eb2cdcb6585be9cb341":"08c36d4dda33423b2ed6830d85f6411ba1dcf470a1fae0ebefee7c089f256cef74cb96ea69c38f60f39abee44129bcb4c92de7f797623b20074e3d9c2899701ed9071e1efa0bdd84d4c3e5130302d8f0240baba4b84a71cc032f2235a5ff0fae277c3e8f9112bef44c9ae20d175fc9a4058bfc930ba31b02e2e4f444483710f24a":0
+pkcs1_rsaes_oaep_encrypt:1028:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":"010001":MBEDTLS_MD_SHA1:"541e37b68b6c8872b84c02":"d9fba45c96f21e6e26d29eb2cdcb6585be9cb341":"08c36d4dda33423b2ed6830d85f6411ba1dcf470a1fae0ebefee7c089f256cef74cb96ea69c38f60f39abee44129bcb4c92de7f797623b20074e3d9c2899701ed9071e1efa0bdd84d4c3e5130302d8f0240baba4b84a71cc032f2235a5ff0fae277c3e8f9112bef44c9ae20d175fc9a4058bfc930ba31b02e2e4f444483710f24a":0
 
 RSAES-OAEP Encryption Example 6_1
-pkcs1_rsaes_oaep_encrypt:1029:16:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":16:"010001":MBEDTLS_MD_SHA1:"4046ca8baa3347ca27f49e0d81f9cc1d71be9ba517d4":"dd0f6cfe415e88e5a469a51fbba6dfd40adb4384":"0630eebcd2856c24f798806e41f9e67345eda9ceda386acc9facaea1eeed06ace583709718d9d169fadf414d5c76f92996833ef305b75b1e4b95f662a20faedc3bae0c4827a8bf8a88edbd57ec203a27a841f02e43a615bab1a8cac0701de34debdef62a088089b55ec36ea7522fd3ec8d06b6a073e6df833153bc0aefd93bd1a3":0
+pkcs1_rsaes_oaep_encrypt:1029:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":"010001":MBEDTLS_MD_SHA1:"4046ca8baa3347ca27f49e0d81f9cc1d71be9ba517d4":"dd0f6cfe415e88e5a469a51fbba6dfd40adb4384":"0630eebcd2856c24f798806e41f9e67345eda9ceda386acc9facaea1eeed06ace583709718d9d169fadf414d5c76f92996833ef305b75b1e4b95f662a20faedc3bae0c4827a8bf8a88edbd57ec203a27a841f02e43a615bab1a8cac0701de34debdef62a088089b55ec36ea7522fd3ec8d06b6a073e6df833153bc0aefd93bd1a3":0
 
 RSAES-OAEP Encryption Example 6_2
-pkcs1_rsaes_oaep_encrypt:1029:16:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":16:"010001":MBEDTLS_MD_SHA1:"5cc72c60231df03b3d40f9b57931bc31109f972527f28b19e7480c7288cb3c92b22512214e4be6c914792ddabdf57faa8aa7":"8d14bd946a1351148f5cae2ed9a0c653e85ebd85":"0ebc37376173a4fd2f89cc55c2ca62b26b11d51c3c7ce49e8845f74e7607317c436bc8d23b9667dfeb9d087234b47bc6837175ae5c0559f6b81d7d22416d3e50f4ac533d8f0812f2db9e791fe9c775ac8b6ad0f535ad9ceb23a4a02014c58ab3f8d3161499a260f39348e714ae2a1d3443208fd8b722ccfdfb393e98011f99e63f":0
+pkcs1_rsaes_oaep_encrypt:1029:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":"010001":MBEDTLS_MD_SHA1:"5cc72c60231df03b3d40f9b57931bc31109f972527f28b19e7480c7288cb3c92b22512214e4be6c914792ddabdf57faa8aa7":"8d14bd946a1351148f5cae2ed9a0c653e85ebd85":"0ebc37376173a4fd2f89cc55c2ca62b26b11d51c3c7ce49e8845f74e7607317c436bc8d23b9667dfeb9d087234b47bc6837175ae5c0559f6b81d7d22416d3e50f4ac533d8f0812f2db9e791fe9c775ac8b6ad0f535ad9ceb23a4a02014c58ab3f8d3161499a260f39348e714ae2a1d3443208fd8b722ccfdfb393e98011f99e63f":0
 
 RSAES-OAEP Encryption Example 6_3
-pkcs1_rsaes_oaep_encrypt:1029:16:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":16:"010001":MBEDTLS_MD_SHA1:"b20e651303092f4bccb43070c0f86d23049362ed96642fc5632c27db4a52e3d831f2ab068b23b149879c002f6bf3feee97591112562c":"6c075bc45520f165c0bf5ea4c5df191bc9ef0e44":"0a98bf1093619394436cf68d8f38e2f158fde8ea54f3435f239b8d06b8321844202476aeed96009492480ce3a8d705498c4c8c68f01501dc81db608f60087350c8c3b0bd2e9ef6a81458b7c801b89f2e4fe99d4900ba6a4b5e5a96d865dc676c7755928794130d6280a8160a190f2df3ea7cf9aa0271d88e9e6905ecf1c5152d65":0
+pkcs1_rsaes_oaep_encrypt:1029:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":"010001":MBEDTLS_MD_SHA1:"b20e651303092f4bccb43070c0f86d23049362ed96642fc5632c27db4a52e3d831f2ab068b23b149879c002f6bf3feee97591112562c":"6c075bc45520f165c0bf5ea4c5df191bc9ef0e44":"0a98bf1093619394436cf68d8f38e2f158fde8ea54f3435f239b8d06b8321844202476aeed96009492480ce3a8d705498c4c8c68f01501dc81db608f60087350c8c3b0bd2e9ef6a81458b7c801b89f2e4fe99d4900ba6a4b5e5a96d865dc676c7755928794130d6280a8160a190f2df3ea7cf9aa0271d88e9e6905ecf1c5152d65":0
 
 RSAES-OAEP Encryption Example 6_4
-pkcs1_rsaes_oaep_encrypt:1029:16:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":16:"010001":MBEDTLS_MD_SHA1:"684e3038c5c041f7":"3bbc3bd6637dfe12846901029bf5b0c07103439c":"008e7a67cacfb5c4e24bec7dee149117f19598ce8c45808fef88c608ff9cd6e695263b9a3c0ad4b8ba4c95238e96a8422b8535629c8d5382374479ad13fa39974b242f9a759eeaf9c83ad5a8ca18940a0162ba755876df263f4bd50c6525c56090267c1f0e09ce0899a0cf359e88120abd9bf893445b3cae77d3607359ae9a52f8":0
+pkcs1_rsaes_oaep_encrypt:1029:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":"010001":MBEDTLS_MD_SHA1:"684e3038c5c041f7":"3bbc3bd6637dfe12846901029bf5b0c07103439c":"008e7a67cacfb5c4e24bec7dee149117f19598ce8c45808fef88c608ff9cd6e695263b9a3c0ad4b8ba4c95238e96a8422b8535629c8d5382374479ad13fa39974b242f9a759eeaf9c83ad5a8ca18940a0162ba755876df263f4bd50c6525c56090267c1f0e09ce0899a0cf359e88120abd9bf893445b3cae77d3607359ae9a52f8":0
 
 RSAES-OAEP Encryption Example 6_5
-pkcs1_rsaes_oaep_encrypt:1029:16:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":16:"010001":MBEDTLS_MD_SHA1:"32488cb262d041d6e4dd35f987bf3ca696db1f06ac29a44693":"b46b41893e8bef326f6759383a83071dae7fcabc":"00003474416c7b68bdf961c385737944d7f1f40cb395343c693cc0b4fe63b31fedf1eaeeac9ccc0678b31dc32e0977489514c4f09085f6298a9653f01aea4045ff582ee887be26ae575b73eef7f3774921e375a3d19adda0ca31aa1849887c1f42cac9677f7a2f4e923f6e5a868b38c084ef187594dc9f7f048fea2e02955384ab":0
+pkcs1_rsaes_oaep_encrypt:1029:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":"010001":MBEDTLS_MD_SHA1:"32488cb262d041d6e4dd35f987bf3ca696db1f06ac29a44693":"b46b41893e8bef326f6759383a83071dae7fcabc":"00003474416c7b68bdf961c385737944d7f1f40cb395343c693cc0b4fe63b31fedf1eaeeac9ccc0678b31dc32e0977489514c4f09085f6298a9653f01aea4045ff582ee887be26ae575b73eef7f3774921e375a3d19adda0ca31aa1849887c1f42cac9677f7a2f4e923f6e5a868b38c084ef187594dc9f7f048fea2e02955384ab":0
 
 RSAES-OAEP Encryption Example 6_6
-pkcs1_rsaes_oaep_encrypt:1029:16:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":16:"010001":MBEDTLS_MD_SHA1:"50ba14be8462720279c306ba":"0a2403312a41e3d52f060fbc13a67de5cf7609a7":"0a026dda5fc8785f7bd9bf75327b63e85e2c0fdee5dadb65ebdcac9ae1de95c92c672ab433aa7a8e69ce6a6d8897fac4ac4a54de841ae5e5bbce7687879d79634cea7a30684065c714d52409b928256bbf53eabcd5231eb7259504537399bd29164b726d33a46da701360a4168a091ccab72d44a62fed246c0ffea5b1348ab5470":0
+pkcs1_rsaes_oaep_encrypt:1029:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":"010001":MBEDTLS_MD_SHA1:"50ba14be8462720279c306ba":"0a2403312a41e3d52f060fbc13a67de5cf7609a7":"0a026dda5fc8785f7bd9bf75327b63e85e2c0fdee5dadb65ebdcac9ae1de95c92c672ab433aa7a8e69ce6a6d8897fac4ac4a54de841ae5e5bbce7687879d79634cea7a30684065c714d52409b928256bbf53eabcd5231eb7259504537399bd29164b726d33a46da701360a4168a091ccab72d44a62fed246c0ffea5b1348ab5470":0
 
 RSAES-OAEP Encryption Example 7_1
-pkcs1_rsaes_oaep_encrypt:1030:16:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":16:"010001":MBEDTLS_MD_SHA1:"47aae909":"43dd09a07ff4cac71caa4632ee5e1c1daee4cd8f":"1688e4ce7794bba6cb7014169ecd559cede2a30b56a52b68d9fe18cf1973ef97b2a03153951c755f6294aa49adbdb55845ab6875fb3986c93ecf927962840d282f9e54ce8b690f7c0cb8bbd73440d9571d1b16cd9260f9eab4783cc482e5223dc60973871783ec27b0ae0fd47732cbc286a173fc92b00fb4ba6824647cd93c85c1":0
+pkcs1_rsaes_oaep_encrypt:1030:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":"010001":MBEDTLS_MD_SHA1:"47aae909":"43dd09a07ff4cac71caa4632ee5e1c1daee4cd8f":"1688e4ce7794bba6cb7014169ecd559cede2a30b56a52b68d9fe18cf1973ef97b2a03153951c755f6294aa49adbdb55845ab6875fb3986c93ecf927962840d282f9e54ce8b690f7c0cb8bbd73440d9571d1b16cd9260f9eab4783cc482e5223dc60973871783ec27b0ae0fd47732cbc286a173fc92b00fb4ba6824647cd93c85c1":0
 
 RSAES-OAEP Encryption Example 7_2
-pkcs1_rsaes_oaep_encrypt:1030:16:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":16:"010001":MBEDTLS_MD_SHA1:"1d9b2e2223d9bc13bfb9f162ce735db48ba7c68f6822a0a1a7b6ae165834e7":"3a9c3cec7b84f9bd3adecbc673ec99d54b22bc9b":"1052ed397b2e01e1d0ee1c50bf24363f95e504f4a03434a08fd822574ed6b9736edbb5f390db10321479a8a139350e2bd4977c3778ef331f3e78ae118b268451f20a2f01d471f5d53c566937171b2dbc2d4bde459a5799f0372d6574239b2323d245d0bb81c286b63c89a361017337e4902f88a467f4c7f244bfd5ab46437ff3b6":0
+pkcs1_rsaes_oaep_encrypt:1030:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":"010001":MBEDTLS_MD_SHA1:"1d9b2e2223d9bc13bfb9f162ce735db48ba7c68f6822a0a1a7b6ae165834e7":"3a9c3cec7b84f9bd3adecbc673ec99d54b22bc9b":"1052ed397b2e01e1d0ee1c50bf24363f95e504f4a03434a08fd822574ed6b9736edbb5f390db10321479a8a139350e2bd4977c3778ef331f3e78ae118b268451f20a2f01d471f5d53c566937171b2dbc2d4bde459a5799f0372d6574239b2323d245d0bb81c286b63c89a361017337e4902f88a467f4c7f244bfd5ab46437ff3b6":0
 
 RSAES-OAEP Encryption Example 7_3
-pkcs1_rsaes_oaep_encrypt:1030:16:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":16:"010001":MBEDTLS_MD_SHA1:"d976fc":"76a75e5b6157a556cf8884bb2e45c293dd545cf5":"2155cd843ff24a4ee8badb7694260028a490813ba8b369a4cbf106ec148e5298707f5965be7d101c1049ea8584c24cd63455ad9c104d686282d3fb803a4c11c1c2e9b91c7178801d1b6640f003f5728df007b8a4ccc92bce05e41a27278d7c85018c52414313a5077789001d4f01910b72aad05d220aa14a58733a7489bc54556b":0
+pkcs1_rsaes_oaep_encrypt:1030:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":"010001":MBEDTLS_MD_SHA1:"d976fc":"76a75e5b6157a556cf8884bb2e45c293dd545cf5":"2155cd843ff24a4ee8badb7694260028a490813ba8b369a4cbf106ec148e5298707f5965be7d101c1049ea8584c24cd63455ad9c104d686282d3fb803a4c11c1c2e9b91c7178801d1b6640f003f5728df007b8a4ccc92bce05e41a27278d7c85018c52414313a5077789001d4f01910b72aad05d220aa14a58733a7489bc54556b":0
 
 RSAES-OAEP Encryption Example 7_4
-pkcs1_rsaes_oaep_encrypt:1030:16:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":16:"010001":MBEDTLS_MD_SHA1:"d4738623df223aa43843df8467534c41d013e0c803c624e263666b239bde40a5f29aeb8de79e3daa61dd0370f49bd4b013834b98212aef6b1c5ee373b3cb":"7866314a6ad6f2b250a35941db28f5864b585859":"0ab14c373aeb7d4328d0aaad8c094d88b9eb098b95f21054a29082522be7c27a312878b637917e3d819e6c3c568db5d843802b06d51d9e98a2be0bf40c031423b00edfbff8320efb9171bd2044653a4cb9c5122f6c65e83cda2ec3c126027a9c1a56ba874d0fea23f380b82cf240b8cf540004758c4c77d934157a74f3fc12bfac":0
+pkcs1_rsaes_oaep_encrypt:1030:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":"010001":MBEDTLS_MD_SHA1:"d4738623df223aa43843df8467534c41d013e0c803c624e263666b239bde40a5f29aeb8de79e3daa61dd0370f49bd4b013834b98212aef6b1c5ee373b3cb":"7866314a6ad6f2b250a35941db28f5864b585859":"0ab14c373aeb7d4328d0aaad8c094d88b9eb098b95f21054a29082522be7c27a312878b637917e3d819e6c3c568db5d843802b06d51d9e98a2be0bf40c031423b00edfbff8320efb9171bd2044653a4cb9c5122f6c65e83cda2ec3c126027a9c1a56ba874d0fea23f380b82cf240b8cf540004758c4c77d934157a74f3fc12bfac":0
 
 RSAES-OAEP Encryption Example 7_5
-pkcs1_rsaes_oaep_encrypt:1030:16:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":16:"010001":MBEDTLS_MD_SHA1:"bb47231ca5ea1d3ad46c99345d9a8a61":"b2166ed472d58db10cab2c6b000cccf10a7dc509":"028387a318277434798b4d97f460068df5298faba5041ba11761a1cb7316b24184114ec500257e2589ed3b607a1ebbe97a6cc2e02bf1b681f42312a33b7a77d8e7855c4a6de03e3c04643f786b91a264a0d6805e2cea91e68177eb7a64d9255e4f27e713b7ccec00dc200ebd21c2ea2bb890feae4942df941dc3f97890ed347478":0
+pkcs1_rsaes_oaep_encrypt:1030:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":"010001":MBEDTLS_MD_SHA1:"bb47231ca5ea1d3ad46c99345d9a8a61":"b2166ed472d58db10cab2c6b000cccf10a7dc509":"028387a318277434798b4d97f460068df5298faba5041ba11761a1cb7316b24184114ec500257e2589ed3b607a1ebbe97a6cc2e02bf1b681f42312a33b7a77d8e7855c4a6de03e3c04643f786b91a264a0d6805e2cea91e68177eb7a64d9255e4f27e713b7ccec00dc200ebd21c2ea2bb890feae4942df941dc3f97890ed347478":0
 
 RSAES-OAEP Encryption Example 7_6
-pkcs1_rsaes_oaep_encrypt:1030:16:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":16:"010001":MBEDTLS_MD_SHA1:"2184827095d35c3f86f600e8e59754013296":"52673bde2ca166c2aa46131ac1dc808d67d7d3b1":"14c678a94ad60525ef39e959b2f3ba5c097a94ff912b67dbace80535c187abd47d075420b1872152bba08f7fc31f313bbf9273c912fc4c0149a9b0cfb79807e346eb332069611bec0ff9bcd168f1f7c33e77313cea454b94e2549eecf002e2acf7f6f2d2845d4fe0aab2e5a92ddf68c480ae11247935d1f62574842216ae674115":0
+pkcs1_rsaes_oaep_encrypt:1030:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":"010001":MBEDTLS_MD_SHA1:"2184827095d35c3f86f600e8e59754013296":"52673bde2ca166c2aa46131ac1dc808d67d7d3b1":"14c678a94ad60525ef39e959b2f3ba5c097a94ff912b67dbace80535c187abd47d075420b1872152bba08f7fc31f313bbf9273c912fc4c0149a9b0cfb79807e346eb332069611bec0ff9bcd168f1f7c33e77313cea454b94e2549eecf002e2acf7f6f2d2845d4fe0aab2e5a92ddf68c480ae11247935d1f62574842216ae674115":0
 
 RSAES-OAEP Encryption Example 8_1
-pkcs1_rsaes_oaep_encrypt:1031:16:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":16:"010001":MBEDTLS_MD_SHA1:"050b755e5e6880f7b9e9d692a74c37aae449b31bfea6deff83747a897f6c2c825bb1adbf850a3c96994b5de5b33cbc7d4a17913a7967":"7706ffca1ecfb1ebee2a55e5c6e24cd2797a4125":"09b3683d8a2eb0fb295b62ed1fb9290b714457b7825319f4647872af889b30409472020ad12912bf19b11d4819f49614824ffd84d09c0a17e7d17309d12919790410aa2995699f6a86dbe3242b5acc23af45691080d6b1ae810fb3e3057087f0970092ce00be9562ff4053b6262ce0caa93e13723d2e3a5ba075d45f0d61b54b61":0
+pkcs1_rsaes_oaep_encrypt:1031:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":"010001":MBEDTLS_MD_SHA1:"050b755e5e6880f7b9e9d692a74c37aae449b31bfea6deff83747a897f6c2c825bb1adbf850a3c96994b5de5b33cbc7d4a17913a7967":"7706ffca1ecfb1ebee2a55e5c6e24cd2797a4125":"09b3683d8a2eb0fb295b62ed1fb9290b714457b7825319f4647872af889b30409472020ad12912bf19b11d4819f49614824ffd84d09c0a17e7d17309d12919790410aa2995699f6a86dbe3242b5acc23af45691080d6b1ae810fb3e3057087f0970092ce00be9562ff4053b6262ce0caa93e13723d2e3a5ba075d45f0d61b54b61":0
 
 RSAES-OAEP Encryption Example 8_2
-pkcs1_rsaes_oaep_encrypt:1031:16:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":16:"010001":MBEDTLS_MD_SHA1:"4eb68dcd93ca9b19df111bd43608f557026fe4aa1d5cfac227a3eb5ab9548c18a06dded23f81825986b2fcd71109ecef7eff88873f075c2aa0c469f69c92bc":"a3717da143b4dcffbc742665a8fa950585548343":"2ecf15c97c5a15b1476ae986b371b57a24284f4a162a8d0c8182e7905e792256f1812ba5f83f1f7a130e42dcc02232844edc14a31a68ee97ae564a383a3411656424c5f62ddb646093c367be1fcda426cf00a06d8acb7e57776fbbd855ac3df506fc16b1d7c3f2110f3d8068e91e186363831c8409680d8da9ecd8cf1fa20ee39d":0
+pkcs1_rsaes_oaep_encrypt:1031:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":"010001":MBEDTLS_MD_SHA1:"4eb68dcd93ca9b19df111bd43608f557026fe4aa1d5cfac227a3eb5ab9548c18a06dded23f81825986b2fcd71109ecef7eff88873f075c2aa0c469f69c92bc":"a3717da143b4dcffbc742665a8fa950585548343":"2ecf15c97c5a15b1476ae986b371b57a24284f4a162a8d0c8182e7905e792256f1812ba5f83f1f7a130e42dcc02232844edc14a31a68ee97ae564a383a3411656424c5f62ddb646093c367be1fcda426cf00a06d8acb7e57776fbbd855ac3df506fc16b1d7c3f2110f3d8068e91e186363831c8409680d8da9ecd8cf1fa20ee39d":0
 
 RSAES-OAEP Encryption Example 8_3
-pkcs1_rsaes_oaep_encrypt:1031:16:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":16:"010001":MBEDTLS_MD_SHA1:"8604ac56328c1ab5ad917861":"ee06209073cca026bb264e5185bf8c68b7739f86":"4bc89130a5b2dabb7c2fcf90eb5d0eaf9e681b7146a38f3173a3d9cfec52ea9e0a41932e648a9d69344c50da763f51a03c95762131e8052254dcd2248cba40fd31667786ce05a2b7b531ac9dac9ed584a59b677c1a8aed8c5d15d68c05569e2be780bf7db638fd2bfd2a85ab276860f3777338fca989ffd743d13ee08e0ca9893f":0
+pkcs1_rsaes_oaep_encrypt:1031:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":"010001":MBEDTLS_MD_SHA1:"8604ac56328c1ab5ad917861":"ee06209073cca026bb264e5185bf8c68b7739f86":"4bc89130a5b2dabb7c2fcf90eb5d0eaf9e681b7146a38f3173a3d9cfec52ea9e0a41932e648a9d69344c50da763f51a03c95762131e8052254dcd2248cba40fd31667786ce05a2b7b531ac9dac9ed584a59b677c1a8aed8c5d15d68c05569e2be780bf7db638fd2bfd2a85ab276860f3777338fca989ffd743d13ee08e0ca9893f":0
 
 RSAES-OAEP Encryption Example 8_4
-pkcs1_rsaes_oaep_encrypt:1031:16:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":16:"010001":MBEDTLS_MD_SHA1:"fdda5fbf6ec361a9d9a4ac68af216a0686f438b1e0e5c36b955f74e107f39c0dddcc":"990ad573dc48a973235b6d82543618f2e955105d":"2e456847d8fc36ff0147d6993594b9397227d577752c79d0f904fcb039d4d812fea605a7b574dd82ca786f93752348438ee9f5b5454985d5f0e1699e3e7ad175a32e15f03deb042ab9fe1dd9db1bb86f8c089ccb45e7ef0c5ee7ca9b7290ca6b15bed47039788a8a93ff83e0e8d6244c71006362deef69b6f416fb3c684383fbd0":0
+pkcs1_rsaes_oaep_encrypt:1031:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":"010001":MBEDTLS_MD_SHA1:"fdda5fbf6ec361a9d9a4ac68af216a0686f438b1e0e5c36b955f74e107f39c0dddcc":"990ad573dc48a973235b6d82543618f2e955105d":"2e456847d8fc36ff0147d6993594b9397227d577752c79d0f904fcb039d4d812fea605a7b574dd82ca786f93752348438ee9f5b5454985d5f0e1699e3e7ad175a32e15f03deb042ab9fe1dd9db1bb86f8c089ccb45e7ef0c5ee7ca9b7290ca6b15bed47039788a8a93ff83e0e8d6244c71006362deef69b6f416fb3c684383fbd0":0
 
 RSAES-OAEP Encryption Example 8_5
-pkcs1_rsaes_oaep_encrypt:1031:16:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":16:"010001":MBEDTLS_MD_SHA1:"4a5f4914bee25de3c69341de07":"ecc63b28f0756f22f52ac8e6ec1251a6ec304718":"1fb9356fd5c4b1796db2ebf7d0d393cc810adf6145defc2fce714f79d93800d5e2ac211ea8bbecca4b654b94c3b18b30dd576ce34dc95436ef57a09415645923359a5d7b4171ef22c24670f1b229d3603e91f76671b7df97e7317c97734476d5f3d17d21cf82b5ba9f83df2e588d36984fd1b584468bd23b2e875f32f68953f7b2":0
+pkcs1_rsaes_oaep_encrypt:1031:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":"010001":MBEDTLS_MD_SHA1:"4a5f4914bee25de3c69341de07":"ecc63b28f0756f22f52ac8e6ec1251a6ec304718":"1fb9356fd5c4b1796db2ebf7d0d393cc810adf6145defc2fce714f79d93800d5e2ac211ea8bbecca4b654b94c3b18b30dd576ce34dc95436ef57a09415645923359a5d7b4171ef22c24670f1b229d3603e91f76671b7df97e7317c97734476d5f3d17d21cf82b5ba9f83df2e588d36984fd1b584468bd23b2e875f32f68953f7b2":0
 
 RSAES-OAEP Encryption Example 8_6
-pkcs1_rsaes_oaep_encrypt:1031:16:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":16:"010001":MBEDTLS_MD_SHA1:"8e07d66f7b880a72563abcd3f35092bc33409fb7f88f2472be":"3925c71b362d40a0a6de42145579ba1e7dd459fc":"3afd9c6600147b21798d818c655a0f4c9212db26d0b0dfdc2a7594ccb3d22f5bf1d7c3e112cd73fc7d509c7a8bafdd3c274d1399009f9609ec4be6477e453f075aa33db382870c1c3409aef392d7386ae3a696b99a94b4da0589447e955d16c98b17602a59bd736279fcd8fb280c4462d590bfa9bf13fed570eafde97330a2c210":0
+pkcs1_rsaes_oaep_encrypt:1031:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":"010001":MBEDTLS_MD_SHA1:"8e07d66f7b880a72563abcd3f35092bc33409fb7f88f2472be":"3925c71b362d40a0a6de42145579ba1e7dd459fc":"3afd9c6600147b21798d818c655a0f4c9212db26d0b0dfdc2a7594ccb3d22f5bf1d7c3e112cd73fc7d509c7a8bafdd3c274d1399009f9609ec4be6477e453f075aa33db382870c1c3409aef392d7386ae3a696b99a94b4da0589447e955d16c98b17602a59bd736279fcd8fb280c4462d590bfa9bf13fed570eafde97330a2c210":0
 
 RSAES-OAEP Encryption Example 9_1
-pkcs1_rsaes_oaep_encrypt:1536:16:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":16:"010001":MBEDTLS_MD_SHA1:"f735fd55ba92592c3b52b8f9c4f69aaa1cbef8fe88add095595412467f9cf4ec0b896c59eda16210e7549c8abb10cdbc21a12ec9b6b5b8fd2f10399eb6":"8ec965f134a3ec9931e92a1ca0dc8169d5ea705c":"267bcd118acab1fc8ba81c85d73003cb8610fa55c1d97da8d48a7c7f06896a4db751aa284255b9d36ad65f37653d829f1b37f97b8001942545b2fc2c55a7376ca7a1be4b1760c8e05a33e5aa2526b8d98e317088e7834c755b2a59b12631a182c05d5d43ab1779264f8456f515ce57dfdf512d5493dab7b7338dc4b7d78db9c091ac3baf537a69fc7f549d979f0eff9a94fda4169bd4d1d19a69c99e33c3b55490d501b39b1edae118ff6793a153261584d3a5f39f6e682e3d17c8cd1261fa72":0
+pkcs1_rsaes_oaep_encrypt:1536:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":"010001":MBEDTLS_MD_SHA1:"f735fd55ba92592c3b52b8f9c4f69aaa1cbef8fe88add095595412467f9cf4ec0b896c59eda16210e7549c8abb10cdbc21a12ec9b6b5b8fd2f10399eb6":"8ec965f134a3ec9931e92a1ca0dc8169d5ea705c":"267bcd118acab1fc8ba81c85d73003cb8610fa55c1d97da8d48a7c7f06896a4db751aa284255b9d36ad65f37653d829f1b37f97b8001942545b2fc2c55a7376ca7a1be4b1760c8e05a33e5aa2526b8d98e317088e7834c755b2a59b12631a182c05d5d43ab1779264f8456f515ce57dfdf512d5493dab7b7338dc4b7d78db9c091ac3baf537a69fc7f549d979f0eff9a94fda4169bd4d1d19a69c99e33c3b55490d501b39b1edae118ff6793a153261584d3a5f39f6e682e3d17c8cd1261fa72":0
 
 RSAES-OAEP Encryption Example 9_2
-pkcs1_rsaes_oaep_encrypt:1536:16:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":16:"010001":MBEDTLS_MD_SHA1:"81b906605015a63aabe42ddf11e1978912f5404c7474b26dce3ed482bf961ecc818bf420c54659":"ecb1b8b25fa50cdab08e56042867f4af5826d16c":"93ac9f0671ec29acbb444effc1a5741351d60fdb0e393fbf754acf0de49761a14841df7772e9bc82773966a1584c4d72baea00118f83f35cca6e537cbd4d811f5583b29783d8a6d94cd31be70d6f526c10ff09c6fa7ce069795a3fcd0511fd5fcb564bcc80ea9c78f38b80012539d8a4ddf6fe81e9cddb7f50dbbbbcc7e5d86097ccf4ec49189fb8bf318be6d5a0715d516b49af191258cd32dc833ce6eb4673c03a19bbace88cc54895f636cc0c1ec89096d11ce235a265ca1764232a689ae8":0
+pkcs1_rsaes_oaep_encrypt:1536:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":"010001":MBEDTLS_MD_SHA1:"81b906605015a63aabe42ddf11e1978912f5404c7474b26dce3ed482bf961ecc818bf420c54659":"ecb1b8b25fa50cdab08e56042867f4af5826d16c":"93ac9f0671ec29acbb444effc1a5741351d60fdb0e393fbf754acf0de49761a14841df7772e9bc82773966a1584c4d72baea00118f83f35cca6e537cbd4d811f5583b29783d8a6d94cd31be70d6f526c10ff09c6fa7ce069795a3fcd0511fd5fcb564bcc80ea9c78f38b80012539d8a4ddf6fe81e9cddb7f50dbbbbcc7e5d86097ccf4ec49189fb8bf318be6d5a0715d516b49af191258cd32dc833ce6eb4673c03a19bbace88cc54895f636cc0c1ec89096d11ce235a265ca1764232a689ae8":0
 
 RSAES-OAEP Encryption Example 9_3
-pkcs1_rsaes_oaep_encrypt:1536:16:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":16:"010001":MBEDTLS_MD_SHA1:"fd326429df9b890e09b54b18b8f34f1e24":"e89bb032c6ce622cbdb53bc9466014ea77f777c0":"81ebdd95054b0c822ef9ad7693f5a87adfb4b4c4ce70df2df84ed49c04da58ba5fc20a19e1a6e8b7a3900b22796dc4e869ee6b42792d15a8eceb56c09c69914e813cea8f6931e4b8ed6f421af298d595c97f4789c7caa612c7ef360984c21b93edc5401068b5af4c78a8771b984d53b8ea8adf2f6a7d4a0ba76c75e1dd9f658f20ded4a46071d46d7791b56803d8fea7f0b0f8e41ae3f09383a6f9585fe7753eaaffd2bf94563108beecc207bbb535f5fcc705f0dde9f708c62f49a9c90371d3":0
+pkcs1_rsaes_oaep_encrypt:1536:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":"010001":MBEDTLS_MD_SHA1:"fd326429df9b890e09b54b18b8f34f1e24":"e89bb032c6ce622cbdb53bc9466014ea77f777c0":"81ebdd95054b0c822ef9ad7693f5a87adfb4b4c4ce70df2df84ed49c04da58ba5fc20a19e1a6e8b7a3900b22796dc4e869ee6b42792d15a8eceb56c09c69914e813cea8f6931e4b8ed6f421af298d595c97f4789c7caa612c7ef360984c21b93edc5401068b5af4c78a8771b984d53b8ea8adf2f6a7d4a0ba76c75e1dd9f658f20ded4a46071d46d7791b56803d8fea7f0b0f8e41ae3f09383a6f9585fe7753eaaffd2bf94563108beecc207bbb535f5fcc705f0dde9f708c62f49a9c90371d3":0
 
 RSAES-OAEP Encryption Example 9_4
-pkcs1_rsaes_oaep_encrypt:1536:16:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":16:"010001":MBEDTLS_MD_SHA1:"f1459b5f0c92f01a0f723a2e5662484d8f8c0a20fc29dad6acd43bb5f3effdf4e1b63e07fdfe6628d0d74ca19bf2d69e4a0abf86d293925a796772f8088e":"606f3b99c0b9ccd771eaa29ea0e4c884f3189ccc":"bcc35f94cde66cb1136625d625b94432a35b22f3d2fa11a613ff0fca5bd57f87b902ccdc1cd0aebcb0715ee869d1d1fe395f6793003f5eca465059c88660d446ff5f0818552022557e38c08a67ead991262254f10682975ec56397768537f4977af6d5f6aaceb7fb25dec5937230231fd8978af49119a29f29e424ab8272b47562792d5c94f774b8829d0b0d9f1a8c9eddf37574d5fa248eefa9c5271fc5ec2579c81bdd61b410fa61fe36e424221c113addb275664c801d34ca8c6351e4a858":0
+pkcs1_rsaes_oaep_encrypt:1536:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":"010001":MBEDTLS_MD_SHA1:"f1459b5f0c92f01a0f723a2e5662484d8f8c0a20fc29dad6acd43bb5f3effdf4e1b63e07fdfe6628d0d74ca19bf2d69e4a0abf86d293925a796772f8088e":"606f3b99c0b9ccd771eaa29ea0e4c884f3189ccc":"bcc35f94cde66cb1136625d625b94432a35b22f3d2fa11a613ff0fca5bd57f87b902ccdc1cd0aebcb0715ee869d1d1fe395f6793003f5eca465059c88660d446ff5f0818552022557e38c08a67ead991262254f10682975ec56397768537f4977af6d5f6aaceb7fb25dec5937230231fd8978af49119a29f29e424ab8272b47562792d5c94f774b8829d0b0d9f1a8c9eddf37574d5fa248eefa9c5271fc5ec2579c81bdd61b410fa61fe36e424221c113addb275664c801d34ca8c6351e4a858":0
 
 RSAES-OAEP Encryption Example 9_5
-pkcs1_rsaes_oaep_encrypt:1536:16:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":16:"010001":MBEDTLS_MD_SHA1:"53e6e8c729d6f9c319dd317e74b0db8e4ccca25f3c8305746e137ac63a63ef3739e7b595abb96e8d55e54f7bd41ab433378ffb911d":"fcbc421402e9ecabc6082afa40ba5f26522c840e":"232afbc927fa08c2f6a27b87d4a5cb09c07dc26fae73d73a90558839f4fd66d281b87ec734bce237ba166698ed829106a7de6942cd6cdce78fed8d2e4d81428e66490d036264cef92af941d3e35055fe3981e14d29cbb9a4f67473063baec79a1179f5a17c9c1832f2838fd7d5e59bb9659d56dce8a019edef1bb3accc697cc6cc7a778f60a064c7f6f5d529c6210262e003de583e81e3167b89971fb8c0e15d44fffef89b53d8d64dd797d159b56d2b08ea5307ea12c241bd58d4ee278a1f2e":0
+pkcs1_rsaes_oaep_encrypt:1536:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":"010001":MBEDTLS_MD_SHA1:"53e6e8c729d6f9c319dd317e74b0db8e4ccca25f3c8305746e137ac63a63ef3739e7b595abb96e8d55e54f7bd41ab433378ffb911d":"fcbc421402e9ecabc6082afa40ba5f26522c840e":"232afbc927fa08c2f6a27b87d4a5cb09c07dc26fae73d73a90558839f4fd66d281b87ec734bce237ba166698ed829106a7de6942cd6cdce78fed8d2e4d81428e66490d036264cef92af941d3e35055fe3981e14d29cbb9a4f67473063baec79a1179f5a17c9c1832f2838fd7d5e59bb9659d56dce8a019edef1bb3accc697cc6cc7a778f60a064c7f6f5d529c6210262e003de583e81e3167b89971fb8c0e15d44fffef89b53d8d64dd797d159b56d2b08ea5307ea12c241bd58d4ee278a1f2e":0
 
 RSAES-OAEP Encryption Example 9_6
-pkcs1_rsaes_oaep_encrypt:1536:16:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":16:"010001":MBEDTLS_MD_SHA1:"b6b28ea2198d0c1008bc64":"23aade0e1e08bb9b9a78d2302a52f9c21b2e1ba2":"438cc7dc08a68da249e42505f8573ba60e2c2773d5b290f4cf9dff718e842081c383e67024a0f29594ea987b9d25e4b738f285970d195abb3a8c8054e3d79d6b9c9a8327ba596f1259e27126674766907d8d582ff3a8476154929adb1e6d1235b2ccb4ec8f663ba9cc670a92bebd853c8dbf69c6436d016f61add836e94732450434207f9fd4c43dec2a12a958efa01efe2669899b5e604c255c55fb7166de5589e369597bb09168c06dd5db177e06a1740eb2d5c82faeca6d92fcee9931ba9f":0
+pkcs1_rsaes_oaep_encrypt:1536:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":"010001":MBEDTLS_MD_SHA1:"b6b28ea2198d0c1008bc64":"23aade0e1e08bb9b9a78d2302a52f9c21b2e1ba2":"438cc7dc08a68da249e42505f8573ba60e2c2773d5b290f4cf9dff718e842081c383e67024a0f29594ea987b9d25e4b738f285970d195abb3a8c8054e3d79d6b9c9a8327ba596f1259e27126674766907d8d582ff3a8476154929adb1e6d1235b2ccb4ec8f663ba9cc670a92bebd853c8dbf69c6436d016f61add836e94732450434207f9fd4c43dec2a12a958efa01efe2669899b5e604c255c55fb7166de5589e369597bb09168c06dd5db177e06a1740eb2d5c82faeca6d92fcee9931ba9f":0
 
 RSAES-OAEP Encryption Example 10_1
-pkcs1_rsaes_oaep_encrypt:2048:16:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":16:"010001":MBEDTLS_MD_SHA1:"8bba6bf82a6c0f86d5f1756e97956870b08953b06b4eb205bc1694ee":"47e1ab7119fee56c95ee5eaad86f40d0aa63bd33":"53ea5dc08cd260fb3b858567287fa91552c30b2febfba213f0ae87702d068d19bab07fe574523dfb42139d68c3c5afeee0bfe4cb7969cbf382b804d6e61396144e2d0e60741f8993c3014b58b9b1957a8babcd23af854f4c356fb1662aa72bfcc7e586559dc4280d160c126785a723ebeebeff71f11594440aaef87d10793a8774a239d4a04c87fe1467b9daf85208ec6c7255794a96cc29142f9a8bd418e3c1fd67344b0cd0829df3b2bec60253196293c6b34d3f75d32f213dd45c6273d505adf4cced1057cb758fc26aeefa441255ed4e64c199ee075e7f16646182fdb464739b68ab5daff0e63e9552016824f054bf4d3c8c90a97bb6b6553284eb429fcc":0
+pkcs1_rsaes_oaep_encrypt:2048:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":"010001":MBEDTLS_MD_SHA1:"8bba6bf82a6c0f86d5f1756e97956870b08953b06b4eb205bc1694ee":"47e1ab7119fee56c95ee5eaad86f40d0aa63bd33":"53ea5dc08cd260fb3b858567287fa91552c30b2febfba213f0ae87702d068d19bab07fe574523dfb42139d68c3c5afeee0bfe4cb7969cbf382b804d6e61396144e2d0e60741f8993c3014b58b9b1957a8babcd23af854f4c356fb1662aa72bfcc7e586559dc4280d160c126785a723ebeebeff71f11594440aaef87d10793a8774a239d4a04c87fe1467b9daf85208ec6c7255794a96cc29142f9a8bd418e3c1fd67344b0cd0829df3b2bec60253196293c6b34d3f75d32f213dd45c6273d505adf4cced1057cb758fc26aeefa441255ed4e64c199ee075e7f16646182fdb464739b68ab5daff0e63e9552016824f054bf4d3c8c90a97bb6b6553284eb429fcc":0
 
 RSAES-OAEP Encryption Example 10_2
-pkcs1_rsaes_oaep_encrypt:2048:16:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":16:"010001":MBEDTLS_MD_SHA1:"e6ad181f053b58a904f2457510373e57":"6d17f5b4c1ffac351d195bf7b09d09f09a4079cf":"a2b1a430a9d657e2fa1c2bb5ed43ffb25c05a308fe9093c01031795f5874400110828ae58fb9b581ce9dddd3e549ae04a0985459bde6c626594e7b05dc4278b2a1465c1368408823c85e96dc66c3a30983c639664fc4569a37fe21e5a195b5776eed2df8d8d361af686e750229bbd663f161868a50615e0c337bec0ca35fec0bb19c36eb2e0bbcc0582fa1d93aacdb061063f59f2ce1ee43605e5d89eca183d2acdfe9f81011022ad3b43a3dd417dac94b4e11ea81b192966e966b182082e71964607b4f8002f36299844a11f2ae0faeac2eae70f8f4f98088acdcd0ac556e9fccc511521908fad26f04c64201450305778758b0538bf8b5bb144a828e629795":0
+pkcs1_rsaes_oaep_encrypt:2048:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":"010001":MBEDTLS_MD_SHA1:"e6ad181f053b58a904f2457510373e57":"6d17f5b4c1ffac351d195bf7b09d09f09a4079cf":"a2b1a430a9d657e2fa1c2bb5ed43ffb25c05a308fe9093c01031795f5874400110828ae58fb9b581ce9dddd3e549ae04a0985459bde6c626594e7b05dc4278b2a1465c1368408823c85e96dc66c3a30983c639664fc4569a37fe21e5a195b5776eed2df8d8d361af686e750229bbd663f161868a50615e0c337bec0ca35fec0bb19c36eb2e0bbcc0582fa1d93aacdb061063f59f2ce1ee43605e5d89eca183d2acdfe9f81011022ad3b43a3dd417dac94b4e11ea81b192966e966b182082e71964607b4f8002f36299844a11f2ae0faeac2eae70f8f4f98088acdcd0ac556e9fccc511521908fad26f04c64201450305778758b0538bf8b5bb144a828e629795":0
 
 RSAES-OAEP Encryption Example 10_3
-pkcs1_rsaes_oaep_encrypt:2048:16:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":16:"010001":MBEDTLS_MD_SHA1:"510a2cf60e866fa2340553c94ea39fbc256311e83e94454b4124":"385387514deccc7c740dd8cdf9daee49a1cbfd54":"9886c3e6764a8b9a84e84148ebd8c3b1aa8050381a78f668714c16d9cfd2a6edc56979c535d9dee3b44b85c18be8928992371711472216d95dda98d2ee8347c9b14dffdff84aa48d25ac06f7d7e65398ac967b1ce90925f67dce049b7f812db0742997a74d44fe81dbe0e7a3feaf2e5c40af888d550ddbbe3bc20657a29543f8fc2913b9bd1a61b2ab2256ec409bbd7dc0d17717ea25c43f42ed27df8738bf4afc6766ff7aff0859555ee283920f4c8a63c4a7340cbafddc339ecdb4b0515002f96c932b5b79167af699c0ad3fccfdf0f44e85a70262bf2e18fe34b850589975e867ff969d48eabf212271546cdc05a69ecb526e52870c836f307bd798780ede":0
+pkcs1_rsaes_oaep_encrypt:2048:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":"010001":MBEDTLS_MD_SHA1:"510a2cf60e866fa2340553c94ea39fbc256311e83e94454b4124":"385387514deccc7c740dd8cdf9daee49a1cbfd54":"9886c3e6764a8b9a84e84148ebd8c3b1aa8050381a78f668714c16d9cfd2a6edc56979c535d9dee3b44b85c18be8928992371711472216d95dda98d2ee8347c9b14dffdff84aa48d25ac06f7d7e65398ac967b1ce90925f67dce049b7f812db0742997a74d44fe81dbe0e7a3feaf2e5c40af888d550ddbbe3bc20657a29543f8fc2913b9bd1a61b2ab2256ec409bbd7dc0d17717ea25c43f42ed27df8738bf4afc6766ff7aff0859555ee283920f4c8a63c4a7340cbafddc339ecdb4b0515002f96c932b5b79167af699c0ad3fccfdf0f44e85a70262bf2e18fe34b850589975e867ff969d48eabf212271546cdc05a69ecb526e52870c836f307bd798780ede":0
 
 RSAES-OAEP Encryption Example 10_4
-pkcs1_rsaes_oaep_encrypt:2048:16:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":16:"010001":MBEDTLS_MD_SHA1:"bcdd190da3b7d300df9a06e22caae2a75f10c91ff667b7c16bde8b53064a2649a94045c9":"5caca6a0f764161a9684f85d92b6e0ef37ca8b65":"6318e9fb5c0d05e5307e1683436e903293ac4642358aaa223d7163013aba87e2dfda8e60c6860e29a1e92686163ea0b9175f329ca3b131a1edd3a77759a8b97bad6a4f8f4396f28cf6f39ca58112e48160d6e203daa5856f3aca5ffed577af499408e3dfd233e3e604dbe34a9c4c9082de65527cac6331d29dc80e0508a0fa7122e7f329f6cca5cfa34d4d1da417805457e008bec549e478ff9e12a763c477d15bbb78f5b69bd57830fc2c4ed686d79bc72a95d85f88134c6b0afe56a8ccfbc855828bb339bd17909cf1d70de3335ae07039093e606d655365de6550b872cd6de1d440ee031b61945f629ad8a353b0d40939e96a3c450d2a8d5eee9f678093c8":0
+pkcs1_rsaes_oaep_encrypt:2048:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":"010001":MBEDTLS_MD_SHA1:"bcdd190da3b7d300df9a06e22caae2a75f10c91ff667b7c16bde8b53064a2649a94045c9":"5caca6a0f764161a9684f85d92b6e0ef37ca8b65":"6318e9fb5c0d05e5307e1683436e903293ac4642358aaa223d7163013aba87e2dfda8e60c6860e29a1e92686163ea0b9175f329ca3b131a1edd3a77759a8b97bad6a4f8f4396f28cf6f39ca58112e48160d6e203daa5856f3aca5ffed577af499408e3dfd233e3e604dbe34a9c4c9082de65527cac6331d29dc80e0508a0fa7122e7f329f6cca5cfa34d4d1da417805457e008bec549e478ff9e12a763c477d15bbb78f5b69bd57830fc2c4ed686d79bc72a95d85f88134c6b0afe56a8ccfbc855828bb339bd17909cf1d70de3335ae07039093e606d655365de6550b872cd6de1d440ee031b61945f629ad8a353b0d40939e96a3c450d2a8d5eee9f678093c8":0
 
 RSAES-OAEP Encryption Example 10_5
-pkcs1_rsaes_oaep_encrypt:2048:16:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":16:"010001":MBEDTLS_MD_SHA1:"a7dd6c7dc24b46f9dd5f1e91ada4c3b3df947e877232a9":"95bca9e3859894b3dd869fa7ecd5bbc6401bf3e4":"75290872ccfd4a4505660d651f56da6daa09ca1301d890632f6a992f3d565cee464afded40ed3b5be9356714ea5aa7655f4a1366c2f17c728f6f2c5a5d1f8e28429bc4e6f8f2cff8da8dc0e0a9808e45fd09ea2fa40cb2b6ce6ffff5c0e159d11b68d90a85f7b84e103b09e682666480c657505c0929259468a314786d74eab131573cf234bf57db7d9e66cc6748192e002dc0deea930585f0831fdcd9bc33d51f79ed2ffc16bcf4d59812fcebcaa3f9069b0e445686d644c25ccf63b456ee5fa6ffe96f19cdf751fed9eaf35957754dbf4bfea5216aa1844dc507cb2d080e722eba150308c2b5ff1193620f1766ecf4481bafb943bd292877f2136ca494aba0":0
+pkcs1_rsaes_oaep_encrypt:2048:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":"010001":MBEDTLS_MD_SHA1:"a7dd6c7dc24b46f9dd5f1e91ada4c3b3df947e877232a9":"95bca9e3859894b3dd869fa7ecd5bbc6401bf3e4":"75290872ccfd4a4505660d651f56da6daa09ca1301d890632f6a992f3d565cee464afded40ed3b5be9356714ea5aa7655f4a1366c2f17c728f6f2c5a5d1f8e28429bc4e6f8f2cff8da8dc0e0a9808e45fd09ea2fa40cb2b6ce6ffff5c0e159d11b68d90a85f7b84e103b09e682666480c657505c0929259468a314786d74eab131573cf234bf57db7d9e66cc6748192e002dc0deea930585f0831fdcd9bc33d51f79ed2ffc16bcf4d59812fcebcaa3f9069b0e445686d644c25ccf63b456ee5fa6ffe96f19cdf751fed9eaf35957754dbf4bfea5216aa1844dc507cb2d080e722eba150308c2b5ff1193620f1766ecf4481bafb943bd292877f2136ca494aba0":0
 
 RSAES-OAEP Encryption Example 10_6
-pkcs1_rsaes_oaep_encrypt:2048:16:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":16:"010001":MBEDTLS_MD_SHA1:"eaf1a73a1b0c4609537de69cd9228bbcfb9a8ca8c6c3efaf056fe4a7f4634ed00b7c39ec6922d7b8ea2c04ebac":"9f47ddf42e97eea856a9bdbc714eb3ac22f6eb32":"2d207a73432a8fb4c03051b3f73b28a61764098dfa34c47a20995f8115aa6816679b557e82dbee584908c6e69782d7deb34dbd65af063d57fca76a5fd069492fd6068d9984d209350565a62e5c77f23038c12cb10c6634709b547c46f6b4a709bd85ca122d74465ef97762c29763e06dbc7a9e738c78bfca0102dc5e79d65b973f28240caab2e161a78b57d262457ed8195d53e3c7ae9da021883c6db7c24afdd2322eac972ad3c354c5fcef1e146c3a0290fb67adf007066e00428d2cec18ce58f9328698defef4b2eb5ec76918fde1c198cbb38b7afc67626a9aefec4322bfd90d2563481c9a221f78c8272c82d1b62ab914e1c69f6af6ef30ca5260db4a46":0
+pkcs1_rsaes_oaep_encrypt:2048:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":"010001":MBEDTLS_MD_SHA1:"eaf1a73a1b0c4609537de69cd9228bbcfb9a8ca8c6c3efaf056fe4a7f4634ed00b7c39ec6922d7b8ea2c04ebac":"9f47ddf42e97eea856a9bdbc714eb3ac22f6eb32":"2d207a73432a8fb4c03051b3f73b28a61764098dfa34c47a20995f8115aa6816679b557e82dbee584908c6e69782d7deb34dbd65af063d57fca76a5fd069492fd6068d9984d209350565a62e5c77f23038c12cb10c6634709b547c46f6b4a709bd85ca122d74465ef97762c29763e06dbc7a9e738c78bfca0102dc5e79d65b973f28240caab2e161a78b57d262457ed8195d53e3c7ae9da021883c6db7c24afdd2322eac972ad3c354c5fcef1e146c3a0290fb67adf007066e00428d2cec18ce58f9328698defef4b2eb5ec76918fde1c198cbb38b7afc67626a9aefec4322bfd90d2563481c9a221f78c8272c82d1b62ab914e1c69f6af6ef30ca5260db4a46":0
 
 RSAES-OAEP Encryption input=NULL with length=0
 depends_on:MBEDTLS_SHA1_C
-pkcs1_rsaes_oaep_encrypt:2048:16:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":16:"010001":MBEDTLS_MD_SHA1:"":"9f47ddf42e97eea856a9bdbc714eb3ac22f6eb32":"32b75304e631e94d4b02819642c7ffa66116af504cb3c4687420cc4b7f069fc6cc3b1a254611995ce2914a9e88152d38bbf87ccedcad9b9890341284e56e802a1b1f8f6bd3d5c991bd92eb8a8ea0a1d8bae141088ff8dceaebdb73515cf06ce33baa37c53093f1d1edc3502818cc70edcfddb41646374beb5b4f67f7f773e43778d4d31012e5a207c474e762ac3251ea6ede9018ad6e8e9ea65a3528a62b694eb9d8becff220a7c6c70d33eaafa52cf67a8090f67b6f9c43c6fe0b0f2375cbb9e611c0fcfef5312feb5e53d4a89d3d7e06c966e0c92ab9e5838239f390bcfd918d94c224df8e8ccb57ee364389908b6a0e550133f7565016804fbd6cb338314a":0
+pkcs1_rsaes_oaep_encrypt:2048:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":"010001":MBEDTLS_MD_SHA1:"":"9f47ddf42e97eea856a9bdbc714eb3ac22f6eb32":"32b75304e631e94d4b02819642c7ffa66116af504cb3c4687420cc4b7f069fc6cc3b1a254611995ce2914a9e88152d38bbf87ccedcad9b9890341284e56e802a1b1f8f6bd3d5c991bd92eb8a8ea0a1d8bae141088ff8dceaebdb73515cf06ce33baa37c53093f1d1edc3502818cc70edcfddb41646374beb5b4f67f7f773e43778d4d31012e5a207c474e762ac3251ea6ede9018ad6e8e9ea65a3528a62b694eb9d8becff220a7c6c70d33eaafa52cf67a8090f67b6f9c43c6fe0b0f2375cbb9e611c0fcfef5312feb5e53d4a89d3d7e06c966e0c92ab9e5838239f390bcfd918d94c224df8e8ccb57ee364389908b6a0e550133f7565016804fbd6cb338314a":0
 
 RSAES-OAEP Decryption Test Vector Int
-pkcs1_rsaes_oaep_decrypt:1024:16:"eecfae81b1b9b3c908810b10a1b5600199eb9f44aef4fda493b81a9e3d84f632124ef0236e5d1e3b7e28fae7aa040a2d5b252176459d1f397541ba2a58fb6599":16:"c97fb1f027f453f6341233eaaad1d9353f6c42d08866b1d05a0f2035028b9d869840b41666b42e92ea0da3b43204b5cfce3352524d0416a5a441e700af461503":16:"bbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb":16:"11":MBEDTLS_MD_SHA1:"d436e99569fd32a7c8a05bbc90d32c49":"aafd12f659cae63489b479e5076ddec2f06cb58f":"1253e04dc0a5397bb44a7ab87e9bf2a039a33d1e996fc82a94ccd30074c95df763722017069e5268da5d1c0b4f872cf653c11df82314a67968dfeae28def04bb6d84b1c31d654a1970e5783bd6eb96a024c2ca2f4a90fe9f2ef5c9c140e5bb48da9536ad8700c84fc9130adea74e558d51a74ddf85d8b50de96838d6063e0955":0
+pkcs1_rsaes_oaep_decrypt:1024:"eecfae81b1b9b3c908810b10a1b5600199eb9f44aef4fda493b81a9e3d84f632124ef0236e5d1e3b7e28fae7aa040a2d5b252176459d1f397541ba2a58fb6599":"c97fb1f027f453f6341233eaaad1d9353f6c42d08866b1d05a0f2035028b9d869840b41666b42e92ea0da3b43204b5cfce3352524d0416a5a441e700af461503":"bbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb":"11":MBEDTLS_MD_SHA1:"d436e99569fd32a7c8a05bbc90d32c49":"aafd12f659cae63489b479e5076ddec2f06cb58f":"1253e04dc0a5397bb44a7ab87e9bf2a039a33d1e996fc82a94ccd30074c95df763722017069e5268da5d1c0b4f872cf653c11df82314a67968dfeae28def04bb6d84b1c31d654a1970e5783bd6eb96a024c2ca2f4a90fe9f2ef5c9c140e5bb48da9536ad8700c84fc9130adea74e558d51a74ddf85d8b50de96838d6063e0955":0
 
 RSAES-OAEP Decryption Test Vector 1_1
-pkcs1_rsaes_oaep_decrypt:1024:16:"d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d":16:"cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77":16:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":16:"010001":MBEDTLS_MD_SHA1:"6628194e12073db03ba94cda9ef9532397d50dba79b987004afefe34":"18b776ea21069d69776a33e96bad48e1dda0a5ef":"354fe67b4a126d5d35fe36c777791a3f7ba13def484e2d3908aff722fad468fb21696de95d0be911c2d3174f8afcc201035f7b6d8e69402de5451618c21a535fa9d7bfc5b8dd9fc243f8cf927db31322d6e881eaa91a996170e657a05a266426d98c88003f8477c1227094a0d9fa1e8c4024309ce1ecccb5210035d47ac72e8a":0
+pkcs1_rsaes_oaep_decrypt:1024:"d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d":"cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77":"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":"010001":MBEDTLS_MD_SHA1:"6628194e12073db03ba94cda9ef9532397d50dba79b987004afefe34":"18b776ea21069d69776a33e96bad48e1dda0a5ef":"354fe67b4a126d5d35fe36c777791a3f7ba13def484e2d3908aff722fad468fb21696de95d0be911c2d3174f8afcc201035f7b6d8e69402de5451618c21a535fa9d7bfc5b8dd9fc243f8cf927db31322d6e881eaa91a996170e657a05a266426d98c88003f8477c1227094a0d9fa1e8c4024309ce1ecccb5210035d47ac72e8a":0
 
 RSAES-OAEP Decryption Test Vector 1_2
-pkcs1_rsaes_oaep_decrypt:1024:16:"d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d":16:"cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77":16:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":16:"010001":MBEDTLS_MD_SHA1:"750c4047f547e8e41411856523298ac9bae245efaf1397fbe56f9dd5":"0cc742ce4a9b7f32f951bcb251efd925fe4fe35f":"640db1acc58e0568fe5407e5f9b701dff8c3c91e716c536fc7fcec6cb5b71c1165988d4a279e1577d730fc7a29932e3f00c81515236d8d8e31017a7a09df4352d904cdeb79aa583adcc31ea698a4c05283daba9089be5491f67c1a4ee48dc74bbbe6643aef846679b4cb395a352d5ed115912df696ffe0702932946d71492b44":0
+pkcs1_rsaes_oaep_decrypt:1024:"d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d":"cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77":"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":"010001":MBEDTLS_MD_SHA1:"750c4047f547e8e41411856523298ac9bae245efaf1397fbe56f9dd5":"0cc742ce4a9b7f32f951bcb251efd925fe4fe35f":"640db1acc58e0568fe5407e5f9b701dff8c3c91e716c536fc7fcec6cb5b71c1165988d4a279e1577d730fc7a29932e3f00c81515236d8d8e31017a7a09df4352d904cdeb79aa583adcc31ea698a4c05283daba9089be5491f67c1a4ee48dc74bbbe6643aef846679b4cb395a352d5ed115912df696ffe0702932946d71492b44":0
 
 RSAES-OAEP Decryption Test Vector 1_3
-pkcs1_rsaes_oaep_decrypt:1024:16:"d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d":16:"cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77":16:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":16:"010001":MBEDTLS_MD_SHA1:"d94ae0832e6445ce42331cb06d531a82b1db4baad30f746dc916df24d4e3c2451fff59a6423eb0e1d02d4fe646cf699dfd818c6e97b051":"2514df4695755a67b288eaf4905c36eec66fd2fd":"423736ed035f6026af276c35c0b3741b365e5f76ca091b4e8c29e2f0befee603595aa8322d602d2e625e95eb81b2f1c9724e822eca76db8618cf09c5343503a4360835b5903bc637e3879fb05e0ef32685d5aec5067cd7cc96fe4b2670b6eac3066b1fcf5686b68589aafb7d629b02d8f8625ca3833624d4800fb081b1cf94eb":0
+pkcs1_rsaes_oaep_decrypt:1024:"d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d":"cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77":"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":"010001":MBEDTLS_MD_SHA1:"d94ae0832e6445ce42331cb06d531a82b1db4baad30f746dc916df24d4e3c2451fff59a6423eb0e1d02d4fe646cf699dfd818c6e97b051":"2514df4695755a67b288eaf4905c36eec66fd2fd":"423736ed035f6026af276c35c0b3741b365e5f76ca091b4e8c29e2f0befee603595aa8322d602d2e625e95eb81b2f1c9724e822eca76db8618cf09c5343503a4360835b5903bc637e3879fb05e0ef32685d5aec5067cd7cc96fe4b2670b6eac3066b1fcf5686b68589aafb7d629b02d8f8625ca3833624d4800fb081b1cf94eb":0
 
 RSAES-OAEP Decryption Test Vector 1_4
-pkcs1_rsaes_oaep_decrypt:1024:16:"d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d":16:"cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77":16:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":16:"010001":MBEDTLS_MD_SHA1:"52e650d98e7f2a048b4f86852153b97e01dd316f346a19f67a85":"c4435a3e1a18a68b6820436290a37cefb85db3fb":"45ead4ca551e662c9800f1aca8283b0525e6abae30be4b4aba762fa40fd3d38e22abefc69794f6ebbbc05ddbb11216247d2f412fd0fba87c6e3acd888813646fd0e48e785204f9c3f73d6d8239562722dddd8771fec48b83a31ee6f592c4cfd4bc88174f3b13a112aae3b9f7b80e0fc6f7255ba880dc7d8021e22ad6a85f0755":0
+pkcs1_rsaes_oaep_decrypt:1024:"d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d":"cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77":"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":"010001":MBEDTLS_MD_SHA1:"52e650d98e7f2a048b4f86852153b97e01dd316f346a19f67a85":"c4435a3e1a18a68b6820436290a37cefb85db3fb":"45ead4ca551e662c9800f1aca8283b0525e6abae30be4b4aba762fa40fd3d38e22abefc69794f6ebbbc05ddbb11216247d2f412fd0fba87c6e3acd888813646fd0e48e785204f9c3f73d6d8239562722dddd8771fec48b83a31ee6f592c4cfd4bc88174f3b13a112aae3b9f7b80e0fc6f7255ba880dc7d8021e22ad6a85f0755":0
 
 RSAES-OAEP Decryption Test Vector 1_5
-pkcs1_rsaes_oaep_decrypt:1024:16:"d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d":16:"cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77":16:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":16:"010001":MBEDTLS_MD_SHA1:"8da89fd9e5f974a29feffb462b49180f6cf9e802":"b318c42df3be0f83fea823f5a7b47ed5e425a3b5":"36f6e34d94a8d34daacba33a2139d00ad85a9345a86051e73071620056b920e219005855a213a0f23897cdcd731b45257c777fe908202befdd0b58386b1244ea0cf539a05d5d10329da44e13030fd760dcd644cfef2094d1910d3f433e1c7c6dd18bc1f2df7f643d662fb9dd37ead9059190f4fa66ca39e869c4eb449cbdc439":0
+pkcs1_rsaes_oaep_decrypt:1024:"d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d":"cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77":"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":"010001":MBEDTLS_MD_SHA1:"8da89fd9e5f974a29feffb462b49180f6cf9e802":"b318c42df3be0f83fea823f5a7b47ed5e425a3b5":"36f6e34d94a8d34daacba33a2139d00ad85a9345a86051e73071620056b920e219005855a213a0f23897cdcd731b45257c777fe908202befdd0b58386b1244ea0cf539a05d5d10329da44e13030fd760dcd644cfef2094d1910d3f433e1c7c6dd18bc1f2df7f643d662fb9dd37ead9059190f4fa66ca39e869c4eb449cbdc439":0
 
 RSAES-OAEP Decryption Test Vector 1_6
-pkcs1_rsaes_oaep_decrypt:1024:16:"d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d":16:"cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77":16:"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":16:"010001":MBEDTLS_MD_SHA1:"26521050844271":"e4ec0982c2336f3a677f6a356174eb0ce887abc2":"42cee2617b1ecea4db3f4829386fbd61dafbf038e180d837c96366df24c097b4ab0fac6bdf590d821c9f10642e681ad05b8d78b378c0f46ce2fad63f74e0ad3df06b075d7eb5f5636f8d403b9059ca761b5c62bb52aa45002ea70baace08ded243b9d8cbd62a68ade265832b56564e43a6fa42ed199a099769742df1539e8255":0
+pkcs1_rsaes_oaep_decrypt:1024:"d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d":"cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77":"a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb":"010001":MBEDTLS_MD_SHA1:"26521050844271":"e4ec0982c2336f3a677f6a356174eb0ce887abc2":"42cee2617b1ecea4db3f4829386fbd61dafbf038e180d837c96366df24c097b4ab0fac6bdf590d821c9f10642e681ad05b8d78b378c0f46ce2fad63f74e0ad3df06b075d7eb5f5636f8d403b9059ca761b5c62bb52aa45002ea70baace08ded243b9d8cbd62a68ade265832b56564e43a6fa42ed199a099769742df1539e8255":0
 
 RSAES-OAEP Decryption Test Vector 2_1
-pkcs1_rsaes_oaep_decrypt:1025:16:"0159dbde04a33ef06fb608b80b190f4d3e22bcc13ac8e4a081033abfa416edb0b338aa08b57309ea5a5240e7dc6e54378c69414c31d97ddb1f406db3769cc41a43":16:"012b652f30403b38b40995fd6ff41a1acc8ada70373236b7202d39b2ee30cfb46db09511f6f307cc61cc21606c18a75b8a62f822df031ba0df0dafd5506f568bd7":16:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":16:"010001":MBEDTLS_MD_SHA1:"8ff00caa605c702830634d9a6c3d42c652b58cf1d92fec570beee7":"8c407b5ec2899e5099c53e8ce793bf94e71b1782":"0181af8922b9fcb4d79d92ebe19815992fc0c1439d8bcd491398a0f4ad3a329a5bd9385560db532683c8b7da04e4b12aed6aacdf471c34c9cda891addcc2df3456653aa6382e9ae59b54455257eb099d562bbe10453f2b6d13c59c02e10f1f8abb5da0d0570932dacf2d0901db729d0fefcc054e70968ea540c81b04bcaefe720e":0
+pkcs1_rsaes_oaep_decrypt:1025:"0159dbde04a33ef06fb608b80b190f4d3e22bcc13ac8e4a081033abfa416edb0b338aa08b57309ea5a5240e7dc6e54378c69414c31d97ddb1f406db3769cc41a43":"012b652f30403b38b40995fd6ff41a1acc8ada70373236b7202d39b2ee30cfb46db09511f6f307cc61cc21606c18a75b8a62f822df031ba0df0dafd5506f568bd7":"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":"010001":MBEDTLS_MD_SHA1:"8ff00caa605c702830634d9a6c3d42c652b58cf1d92fec570beee7":"8c407b5ec2899e5099c53e8ce793bf94e71b1782":"0181af8922b9fcb4d79d92ebe19815992fc0c1439d8bcd491398a0f4ad3a329a5bd9385560db532683c8b7da04e4b12aed6aacdf471c34c9cda891addcc2df3456653aa6382e9ae59b54455257eb099d562bbe10453f2b6d13c59c02e10f1f8abb5da0d0570932dacf2d0901db729d0fefcc054e70968ea540c81b04bcaefe720e":0
 
 RSAES-OAEP Decryption Test Vector 2_2
-pkcs1_rsaes_oaep_decrypt:1025:16:"0159dbde04a33ef06fb608b80b190f4d3e22bcc13ac8e4a081033abfa416edb0b338aa08b57309ea5a5240e7dc6e54378c69414c31d97ddb1f406db3769cc41a43":16:"012b652f30403b38b40995fd6ff41a1acc8ada70373236b7202d39b2ee30cfb46db09511f6f307cc61cc21606c18a75b8a62f822df031ba0df0dafd5506f568bd7":16:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":16:"010001":MBEDTLS_MD_SHA1:"2d":"b600cf3c2e506d7f16778c910d3a8b003eee61d5":"018759ff1df63b2792410562314416a8aeaf2ac634b46f940ab82d64dbf165eee33011da749d4bab6e2fcd18129c9e49277d8453112b429a222a8471b070993998e758861c4d3f6d749d91c4290d332c7a4ab3f7ea35ff3a07d497c955ff0ffc95006b62c6d296810d9bfab024196c7934012c2df978ef299aba239940cba10245":0
+pkcs1_rsaes_oaep_decrypt:1025:"0159dbde04a33ef06fb608b80b190f4d3e22bcc13ac8e4a081033abfa416edb0b338aa08b57309ea5a5240e7dc6e54378c69414c31d97ddb1f406db3769cc41a43":"012b652f30403b38b40995fd6ff41a1acc8ada70373236b7202d39b2ee30cfb46db09511f6f307cc61cc21606c18a75b8a62f822df031ba0df0dafd5506f568bd7":"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":"010001":MBEDTLS_MD_SHA1:"2d":"b600cf3c2e506d7f16778c910d3a8b003eee61d5":"018759ff1df63b2792410562314416a8aeaf2ac634b46f940ab82d64dbf165eee33011da749d4bab6e2fcd18129c9e49277d8453112b429a222a8471b070993998e758861c4d3f6d749d91c4290d332c7a4ab3f7ea35ff3a07d497c955ff0ffc95006b62c6d296810d9bfab024196c7934012c2df978ef299aba239940cba10245":0
 
 RSAES-OAEP Decryption Test Vector 2_3
-pkcs1_rsaes_oaep_decrypt:1025:16:"0159dbde04a33ef06fb608b80b190f4d3e22bcc13ac8e4a081033abfa416edb0b338aa08b57309ea5a5240e7dc6e54378c69414c31d97ddb1f406db3769cc41a43":16:"012b652f30403b38b40995fd6ff41a1acc8ada70373236b7202d39b2ee30cfb46db09511f6f307cc61cc21606c18a75b8a62f822df031ba0df0dafd5506f568bd7":16:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":16:"010001":MBEDTLS_MD_SHA1:"74fc88c51bc90f77af9d5e9a4a70133d4b4e0b34da3c37c7ef8e":"a73768aeeaa91f9d8c1ed6f9d2b63467f07ccae3":"018802bab04c60325e81c4962311f2be7c2adce93041a00719c88f957575f2c79f1b7bc8ced115c706b311c08a2d986ca3b6a9336b147c29c6f229409ddec651bd1fdd5a0b7f610c9937fdb4a3a762364b8b3206b4ea485fd098d08f63d4aa8bb2697d027b750c32d7f74eaf5180d2e9b66b17cb2fa55523bc280da10d14be2053":0
+pkcs1_rsaes_oaep_decrypt:1025:"0159dbde04a33ef06fb608b80b190f4d3e22bcc13ac8e4a081033abfa416edb0b338aa08b57309ea5a5240e7dc6e54378c69414c31d97ddb1f406db3769cc41a43":"012b652f30403b38b40995fd6ff41a1acc8ada70373236b7202d39b2ee30cfb46db09511f6f307cc61cc21606c18a75b8a62f822df031ba0df0dafd5506f568bd7":"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":"010001":MBEDTLS_MD_SHA1:"74fc88c51bc90f77af9d5e9a4a70133d4b4e0b34da3c37c7ef8e":"a73768aeeaa91f9d8c1ed6f9d2b63467f07ccae3":"018802bab04c60325e81c4962311f2be7c2adce93041a00719c88f957575f2c79f1b7bc8ced115c706b311c08a2d986ca3b6a9336b147c29c6f229409ddec651bd1fdd5a0b7f610c9937fdb4a3a762364b8b3206b4ea485fd098d08f63d4aa8bb2697d027b750c32d7f74eaf5180d2e9b66b17cb2fa55523bc280da10d14be2053":0
 
 RSAES-OAEP Decryption Test Vector 2_4
-pkcs1_rsaes_oaep_decrypt:1025:16:"0159dbde04a33ef06fb608b80b190f4d3e22bcc13ac8e4a081033abfa416edb0b338aa08b57309ea5a5240e7dc6e54378c69414c31d97ddb1f406db3769cc41a43":16:"012b652f30403b38b40995fd6ff41a1acc8ada70373236b7202d39b2ee30cfb46db09511f6f307cc61cc21606c18a75b8a62f822df031ba0df0dafd5506f568bd7":16:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":16:"010001":MBEDTLS_MD_SHA1:"a7eb2a5036931d27d4e891326d99692ffadda9bf7efd3e34e622c4adc085f721dfe885072c78a203b151739be540fa8c153a10f00a":"9a7b3b0e708bd96f8190ecab4fb9b2b3805a8156":"00a4578cbc176318a638fba7d01df15746af44d4f6cd96d7e7c495cbf425b09c649d32bf886da48fbaf989a2117187cafb1fb580317690e3ccd446920b7af82b31db5804d87d01514acbfa9156e782f867f6bed9449e0e9a2c09bcecc6aa087636965e34b3ec766f2fe2e43018a2fddeb140616a0e9d82e5331024ee0652fc7641":0
+pkcs1_rsaes_oaep_decrypt:1025:"0159dbde04a33ef06fb608b80b190f4d3e22bcc13ac8e4a081033abfa416edb0b338aa08b57309ea5a5240e7dc6e54378c69414c31d97ddb1f406db3769cc41a43":"012b652f30403b38b40995fd6ff41a1acc8ada70373236b7202d39b2ee30cfb46db09511f6f307cc61cc21606c18a75b8a62f822df031ba0df0dafd5506f568bd7":"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":"010001":MBEDTLS_MD_SHA1:"a7eb2a5036931d27d4e891326d99692ffadda9bf7efd3e34e622c4adc085f721dfe885072c78a203b151739be540fa8c153a10f00a":"9a7b3b0e708bd96f8190ecab4fb9b2b3805a8156":"00a4578cbc176318a638fba7d01df15746af44d4f6cd96d7e7c495cbf425b09c649d32bf886da48fbaf989a2117187cafb1fb580317690e3ccd446920b7af82b31db5804d87d01514acbfa9156e782f867f6bed9449e0e9a2c09bcecc6aa087636965e34b3ec766f2fe2e43018a2fddeb140616a0e9d82e5331024ee0652fc7641":0
 
 RSAES-OAEP Decryption Test Vector 2_5
-pkcs1_rsaes_oaep_decrypt:1025:16:"0159dbde04a33ef06fb608b80b190f4d3e22bcc13ac8e4a081033abfa416edb0b338aa08b57309ea5a5240e7dc6e54378c69414c31d97ddb1f406db3769cc41a43":16:"012b652f30403b38b40995fd6ff41a1acc8ada70373236b7202d39b2ee30cfb46db09511f6f307cc61cc21606c18a75b8a62f822df031ba0df0dafd5506f568bd7":16:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":16:"010001":MBEDTLS_MD_SHA1:"2ef2b066f854c33f3bdcbb5994a435e73d6c6c":"eb3cebbc4adc16bb48e88c8aec0e34af7f427fd3":"00ebc5f5fda77cfdad3c83641a9025e77d72d8a6fb33a810f5950f8d74c73e8d931e8634d86ab1246256ae07b6005b71b7f2fb98351218331ce69b8ffbdc9da08bbc9c704f876deb9df9fc2ec065cad87f9090b07acc17aa7f997b27aca48806e897f771d95141fe4526d8a5301b678627efab707fd40fbebd6e792a25613e7aec":0
+pkcs1_rsaes_oaep_decrypt:1025:"0159dbde04a33ef06fb608b80b190f4d3e22bcc13ac8e4a081033abfa416edb0b338aa08b57309ea5a5240e7dc6e54378c69414c31d97ddb1f406db3769cc41a43":"012b652f30403b38b40995fd6ff41a1acc8ada70373236b7202d39b2ee30cfb46db09511f6f307cc61cc21606c18a75b8a62f822df031ba0df0dafd5506f568bd7":"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":"010001":MBEDTLS_MD_SHA1:"2ef2b066f854c33f3bdcbb5994a435e73d6c6c":"eb3cebbc4adc16bb48e88c8aec0e34af7f427fd3":"00ebc5f5fda77cfdad3c83641a9025e77d72d8a6fb33a810f5950f8d74c73e8d931e8634d86ab1246256ae07b6005b71b7f2fb98351218331ce69b8ffbdc9da08bbc9c704f876deb9df9fc2ec065cad87f9090b07acc17aa7f997b27aca48806e897f771d95141fe4526d8a5301b678627efab707fd40fbebd6e792a25613e7aec":0
 
 RSAES-OAEP Decryption Test Vector 2_6
-pkcs1_rsaes_oaep_decrypt:1025:16:"0159dbde04a33ef06fb608b80b190f4d3e22bcc13ac8e4a081033abfa416edb0b338aa08b57309ea5a5240e7dc6e54378c69414c31d97ddb1f406db3769cc41a43":16:"012b652f30403b38b40995fd6ff41a1acc8ada70373236b7202d39b2ee30cfb46db09511f6f307cc61cc21606c18a75b8a62f822df031ba0df0dafd5506f568bd7":16:"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":16:"010001":MBEDTLS_MD_SHA1:"8a7fb344c8b6cb2cf2ef1f643f9a3218f6e19bba89c0":"4c45cf4d57c98e3d6d2095adc51c489eb50dff84":"010839ec20c27b9052e55befb9b77e6fc26e9075d7a54378c646abdf51e445bd5715de81789f56f1803d9170764a9e93cb78798694023ee7393ce04bc5d8f8c5a52c171d43837e3aca62f609eb0aa5ffb0960ef04198dd754f57f7fbe6abf765cf118b4ca443b23b5aab266f952326ac4581100644325f8b721acd5d04ff14ef3a":0
+pkcs1_rsaes_oaep_decrypt:1025:"0159dbde04a33ef06fb608b80b190f4d3e22bcc13ac8e4a081033abfa416edb0b338aa08b57309ea5a5240e7dc6e54378c69414c31d97ddb1f406db3769cc41a43":"012b652f30403b38b40995fd6ff41a1acc8ada70373236b7202d39b2ee30cfb46db09511f6f307cc61cc21606c18a75b8a62f822df031ba0df0dafd5506f568bd7":"01947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f45":"010001":MBEDTLS_MD_SHA1:"8a7fb344c8b6cb2cf2ef1f643f9a3218f6e19bba89c0":"4c45cf4d57c98e3d6d2095adc51c489eb50dff84":"010839ec20c27b9052e55befb9b77e6fc26e9075d7a54378c646abdf51e445bd5715de81789f56f1803d9170764a9e93cb78798694023ee7393ce04bc5d8f8c5a52c171d43837e3aca62f609eb0aa5ffb0960ef04198dd754f57f7fbe6abf765cf118b4ca443b23b5aab266f952326ac4581100644325f8b721acd5d04ff14ef3a":0
 
 RSAES-OAEP Decryption Example 3_1
-pkcs1_rsaes_oaep_decrypt:1026:16:"01bf01d216d73595cf0270c2beb78d40a0d8447d31da919a983f7eea781b77d85fe371b3e9373e7b69217d3150a02d8958de7fad9d555160958b4454127e0e7eaf":16:"018d3399658166db3829816d7b295416759e9c91987f5b2d8aecd63b04b48bd7b2fcf229bb7f8a6dc88ba13dd2e39ad55b6d1a06160708f9700be80b8fd3744ce7":16:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":16:"010001":MBEDTLS_MD_SHA1:"087820b569e8fa8d":"8ced6b196290805790e909074015e6a20b0c4894":"026a0485d96aebd96b4382085099b962e6a2bdec3d90c8db625e14372de85e2d5b7baab65c8faf91bb5504fb495afce5c988b3f6a52e20e1d6cbd3566c5cd1f2b8318bb542cc0ea25c4aab9932afa20760eaddec784396a07ea0ef24d4e6f4d37e5052a7a31e146aa480a111bbe926401307e00f410033842b6d82fe5ce4dfae80":0
+pkcs1_rsaes_oaep_decrypt:1026:"01bf01d216d73595cf0270c2beb78d40a0d8447d31da919a983f7eea781b77d85fe371b3e9373e7b69217d3150a02d8958de7fad9d555160958b4454127e0e7eaf":"018d3399658166db3829816d7b295416759e9c91987f5b2d8aecd63b04b48bd7b2fcf229bb7f8a6dc88ba13dd2e39ad55b6d1a06160708f9700be80b8fd3744ce7":"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":"010001":MBEDTLS_MD_SHA1:"087820b569e8fa8d":"8ced6b196290805790e909074015e6a20b0c4894":"026a0485d96aebd96b4382085099b962e6a2bdec3d90c8db625e14372de85e2d5b7baab65c8faf91bb5504fb495afce5c988b3f6a52e20e1d6cbd3566c5cd1f2b8318bb542cc0ea25c4aab9932afa20760eaddec784396a07ea0ef24d4e6f4d37e5052a7a31e146aa480a111bbe926401307e00f410033842b6d82fe5ce4dfae80":0
 
 RSAES-OAEP Decryption Example 3_2
-pkcs1_rsaes_oaep_decrypt:1026:16:"01bf01d216d73595cf0270c2beb78d40a0d8447d31da919a983f7eea781b77d85fe371b3e9373e7b69217d3150a02d8958de7fad9d555160958b4454127e0e7eaf":16:"018d3399658166db3829816d7b295416759e9c91987f5b2d8aecd63b04b48bd7b2fcf229bb7f8a6dc88ba13dd2e39ad55b6d1a06160708f9700be80b8fd3744ce7":16:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":16:"010001":MBEDTLS_MD_SHA1:"4653acaf171960b01f52a7be63a3ab21dc368ec43b50d82ec3781e04":"b4291d6567550848cc156967c809baab6ca507f0":"024db89c7802989be0783847863084941bf209d761987e38f97cb5f6f1bc88da72a50b73ebaf11c879c4f95df37b850b8f65d7622e25b1b889e80fe80baca2069d6e0e1d829953fc459069de98ea9798b451e557e99abf8fe3d9ccf9096ebbf3e5255d3b4e1c6d2ecadf067a359eea86405acd47d5e165517ccafd47d6dbee4bf5":0
+pkcs1_rsaes_oaep_decrypt:1026:"01bf01d216d73595cf0270c2beb78d40a0d8447d31da919a983f7eea781b77d85fe371b3e9373e7b69217d3150a02d8958de7fad9d555160958b4454127e0e7eaf":"018d3399658166db3829816d7b295416759e9c91987f5b2d8aecd63b04b48bd7b2fcf229bb7f8a6dc88ba13dd2e39ad55b6d1a06160708f9700be80b8fd3744ce7":"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":"010001":MBEDTLS_MD_SHA1:"4653acaf171960b01f52a7be63a3ab21dc368ec43b50d82ec3781e04":"b4291d6567550848cc156967c809baab6ca507f0":"024db89c7802989be0783847863084941bf209d761987e38f97cb5f6f1bc88da72a50b73ebaf11c879c4f95df37b850b8f65d7622e25b1b889e80fe80baca2069d6e0e1d829953fc459069de98ea9798b451e557e99abf8fe3d9ccf9096ebbf3e5255d3b4e1c6d2ecadf067a359eea86405acd47d5e165517ccafd47d6dbee4bf5":0
 
 RSAES-OAEP Decryption Example 3_3
-pkcs1_rsaes_oaep_decrypt:1026:16:"01bf01d216d73595cf0270c2beb78d40a0d8447d31da919a983f7eea781b77d85fe371b3e9373e7b69217d3150a02d8958de7fad9d555160958b4454127e0e7eaf":16:"018d3399658166db3829816d7b295416759e9c91987f5b2d8aecd63b04b48bd7b2fcf229bb7f8a6dc88ba13dd2e39ad55b6d1a06160708f9700be80b8fd3744ce7":16:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":16:"010001":MBEDTLS_MD_SHA1:"d94cd0e08fa404ed89":"ce8928f6059558254008badd9794fadcd2fd1f65":"0239bce681032441528877d6d1c8bb28aa3bc97f1df584563618995797683844ca86664732f4bed7a0aab083aaabfb7238f582e30958c2024e44e57043b97950fd543da977c90cdde5337d618442f99e60d7783ab59ce6dd9d69c47ad1e962bec22d05895cff8d3f64ed5261d92b2678510393484990ba3f7f06818ae6ffce8a3a":0
+pkcs1_rsaes_oaep_decrypt:1026:"01bf01d216d73595cf0270c2beb78d40a0d8447d31da919a983f7eea781b77d85fe371b3e9373e7b69217d3150a02d8958de7fad9d555160958b4454127e0e7eaf":"018d3399658166db3829816d7b295416759e9c91987f5b2d8aecd63b04b48bd7b2fcf229bb7f8a6dc88ba13dd2e39ad55b6d1a06160708f9700be80b8fd3744ce7":"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":"010001":MBEDTLS_MD_SHA1:"d94cd0e08fa404ed89":"ce8928f6059558254008badd9794fadcd2fd1f65":"0239bce681032441528877d6d1c8bb28aa3bc97f1df584563618995797683844ca86664732f4bed7a0aab083aaabfb7238f582e30958c2024e44e57043b97950fd543da977c90cdde5337d618442f99e60d7783ab59ce6dd9d69c47ad1e962bec22d05895cff8d3f64ed5261d92b2678510393484990ba3f7f06818ae6ffce8a3a":0
 
 RSAES-OAEP Decryption Example 3_4
-pkcs1_rsaes_oaep_decrypt:1026:16:"01bf01d216d73595cf0270c2beb78d40a0d8447d31da919a983f7eea781b77d85fe371b3e9373e7b69217d3150a02d8958de7fad9d555160958b4454127e0e7eaf":16:"018d3399658166db3829816d7b295416759e9c91987f5b2d8aecd63b04b48bd7b2fcf229bb7f8a6dc88ba13dd2e39ad55b6d1a06160708f9700be80b8fd3744ce7":16:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":16:"010001":MBEDTLS_MD_SHA1:"6cc641b6b61e6f963974dad23a9013284ef1":"6e2979f52d6814a57d83b090054888f119a5b9a3":"02994c62afd76f498ba1fd2cf642857fca81f4373cb08f1cbaee6f025c3b512b42c3e8779113476648039dbe0493f9246292fac28950600e7c0f32edf9c81b9dec45c3bde0cc8d8847590169907b7dc5991ceb29bb0714d613d96df0f12ec5d8d3507c8ee7ae78dd83f216fa61de100363aca48a7e914ae9f42ddfbe943b09d9a0":0
+pkcs1_rsaes_oaep_decrypt:1026:"01bf01d216d73595cf0270c2beb78d40a0d8447d31da919a983f7eea781b77d85fe371b3e9373e7b69217d3150a02d8958de7fad9d555160958b4454127e0e7eaf":"018d3399658166db3829816d7b295416759e9c91987f5b2d8aecd63b04b48bd7b2fcf229bb7f8a6dc88ba13dd2e39ad55b6d1a06160708f9700be80b8fd3744ce7":"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":"010001":MBEDTLS_MD_SHA1:"6cc641b6b61e6f963974dad23a9013284ef1":"6e2979f52d6814a57d83b090054888f119a5b9a3":"02994c62afd76f498ba1fd2cf642857fca81f4373cb08f1cbaee6f025c3b512b42c3e8779113476648039dbe0493f9246292fac28950600e7c0f32edf9c81b9dec45c3bde0cc8d8847590169907b7dc5991ceb29bb0714d613d96df0f12ec5d8d3507c8ee7ae78dd83f216fa61de100363aca48a7e914ae9f42ddfbe943b09d9a0":0
 
 RSAES-OAEP Decryption Example 3_5
-pkcs1_rsaes_oaep_decrypt:1026:16:"01bf01d216d73595cf0270c2beb78d40a0d8447d31da919a983f7eea781b77d85fe371b3e9373e7b69217d3150a02d8958de7fad9d555160958b4454127e0e7eaf":16:"018d3399658166db3829816d7b295416759e9c91987f5b2d8aecd63b04b48bd7b2fcf229bb7f8a6dc88ba13dd2e39ad55b6d1a06160708f9700be80b8fd3744ce7":16:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":16:"010001":MBEDTLS_MD_SHA1:"df5151832b61f4f25891fb4172f328d2eddf8371ffcfdbe997939295f30eca6918017cfda1153bf7a6af87593223":"2d760bfe38c59de34cdc8b8c78a38e66284a2d27":"0162042ff6969592a6167031811a239834ce638abf54fec8b99478122afe2ee67f8c5b18b0339805bfdbc5a4e6720b37c59cfba942464c597ff532a119821545fd2e59b114e61daf71820529f5029cf524954327c34ec5e6f5ba7efcc4de943ab8ad4ed787b1454329f70db798a3a8f4d92f8274e2b2948ade627ce8ee33e43c60":0
+pkcs1_rsaes_oaep_decrypt:1026:"01bf01d216d73595cf0270c2beb78d40a0d8447d31da919a983f7eea781b77d85fe371b3e9373e7b69217d3150a02d8958de7fad9d555160958b4454127e0e7eaf":"018d3399658166db3829816d7b295416759e9c91987f5b2d8aecd63b04b48bd7b2fcf229bb7f8a6dc88ba13dd2e39ad55b6d1a06160708f9700be80b8fd3744ce7":"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":"010001":MBEDTLS_MD_SHA1:"df5151832b61f4f25891fb4172f328d2eddf8371ffcfdbe997939295f30eca6918017cfda1153bf7a6af87593223":"2d760bfe38c59de34cdc8b8c78a38e66284a2d27":"0162042ff6969592a6167031811a239834ce638abf54fec8b99478122afe2ee67f8c5b18b0339805bfdbc5a4e6720b37c59cfba942464c597ff532a119821545fd2e59b114e61daf71820529f5029cf524954327c34ec5e6f5ba7efcc4de943ab8ad4ed787b1454329f70db798a3a8f4d92f8274e2b2948ade627ce8ee33e43c60":0
 
 RSAES-OAEP Decryption Example 3_6
-pkcs1_rsaes_oaep_decrypt:1026:16:"01bf01d216d73595cf0270c2beb78d40a0d8447d31da919a983f7eea781b77d85fe371b3e9373e7b69217d3150a02d8958de7fad9d555160958b4454127e0e7eaf":16:"018d3399658166db3829816d7b295416759e9c91987f5b2d8aecd63b04b48bd7b2fcf229bb7f8a6dc88ba13dd2e39ad55b6d1a06160708f9700be80b8fd3744ce7":16:"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":16:"010001":MBEDTLS_MD_SHA1:"3c3bad893c544a6d520ab022319188c8d504b7a788b850903b85972eaa18552e1134a7ad6098826254ff7ab672b3d8eb3158fac6d4cbaef1":"f174779c5fd3cfe007badcb7a36c9b55bfcfbf0e":"00112051e75d064943bc4478075e43482fd59cee0679de6893eec3a943daa490b9691c93dfc0464b6623b9f3dbd3e70083264f034b374f74164e1a00763725e574744ba0b9db83434f31df96f6e2a26f6d8eba348bd4686c2238ac07c37aac3785d1c7eea2f819fd91491798ed8e9cef5e43b781b0e0276e37c43ff9492d005730":0
+pkcs1_rsaes_oaep_decrypt:1026:"01bf01d216d73595cf0270c2beb78d40a0d8447d31da919a983f7eea781b77d85fe371b3e9373e7b69217d3150a02d8958de7fad9d555160958b4454127e0e7eaf":"018d3399658166db3829816d7b295416759e9c91987f5b2d8aecd63b04b48bd7b2fcf229bb7f8a6dc88ba13dd2e39ad55b6d1a06160708f9700be80b8fd3744ce7":"02b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9":"010001":MBEDTLS_MD_SHA1:"3c3bad893c544a6d520ab022319188c8d504b7a788b850903b85972eaa18552e1134a7ad6098826254ff7ab672b3d8eb3158fac6d4cbaef1":"f174779c5fd3cfe007badcb7a36c9b55bfcfbf0e":"00112051e75d064943bc4478075e43482fd59cee0679de6893eec3a943daa490b9691c93dfc0464b6623b9f3dbd3e70083264f034b374f74164e1a00763725e574744ba0b9db83434f31df96f6e2a26f6d8eba348bd4686c2238ac07c37aac3785d1c7eea2f819fd91491798ed8e9cef5e43b781b0e0276e37c43ff9492d005730":0
 
 RSAES-OAEP Decryption Example 4_1
-pkcs1_rsaes_oaep_decrypt:1027:16:"027458c19ec1636919e736c9af25d609a51b8f561d19c6bf6943dd1ee1ab8a4a3f232100bd40b88decc6ba235548b6ef792a11c9de823d0a7922c7095b6eba5701":16:"0210ee9b33ab61716e27d251bd465f4b35a1a232e2da00901c294bf22350ce490d099f642b5375612db63ba1f20386492bf04d34b3c22bceb909d13441b53b5139":16:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":16:"010001":MBEDTLS_MD_SHA1:"4a86609534ee434a6cbca3f7e962e76d455e3264c19f605f6e5ff6137c65c56d7fb344cd52bc93374f3d166c9f0c6f9c506bad19330972d2":"1cac19ce993def55f98203f6852896c95ccca1f3":"04cce19614845e094152a3fe18e54e3330c44e5efbc64ae16886cb1869014cc5781b1f8f9e045384d0112a135ca0d12e9c88a8e4063416deaae3844f60d6e96fe155145f4525b9a34431ca3766180f70e15a5e5d8e8b1a516ff870609f13f896935ced188279a58ed13d07114277d75c6568607e0ab092fd803a223e4a8ee0b1a8":0
+pkcs1_rsaes_oaep_decrypt:1027:"027458c19ec1636919e736c9af25d609a51b8f561d19c6bf6943dd1ee1ab8a4a3f232100bd40b88decc6ba235548b6ef792a11c9de823d0a7922c7095b6eba5701":"0210ee9b33ab61716e27d251bd465f4b35a1a232e2da00901c294bf22350ce490d099f642b5375612db63ba1f20386492bf04d34b3c22bceb909d13441b53b5139":"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":"010001":MBEDTLS_MD_SHA1:"4a86609534ee434a6cbca3f7e962e76d455e3264c19f605f6e5ff6137c65c56d7fb344cd52bc93374f3d166c9f0c6f9c506bad19330972d2":"1cac19ce993def55f98203f6852896c95ccca1f3":"04cce19614845e094152a3fe18e54e3330c44e5efbc64ae16886cb1869014cc5781b1f8f9e045384d0112a135ca0d12e9c88a8e4063416deaae3844f60d6e96fe155145f4525b9a34431ca3766180f70e15a5e5d8e8b1a516ff870609f13f896935ced188279a58ed13d07114277d75c6568607e0ab092fd803a223e4a8ee0b1a8":0
 
 RSAES-OAEP Decryption Example 4_2
-pkcs1_rsaes_oaep_decrypt:1027:16:"027458c19ec1636919e736c9af25d609a51b8f561d19c6bf6943dd1ee1ab8a4a3f232100bd40b88decc6ba235548b6ef792a11c9de823d0a7922c7095b6eba5701":16:"0210ee9b33ab61716e27d251bd465f4b35a1a232e2da00901c294bf22350ce490d099f642b5375612db63ba1f20386492bf04d34b3c22bceb909d13441b53b5139":16:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":16:"010001":MBEDTLS_MD_SHA1:"b0adc4f3fe11da59ce992773d9059943c03046497ee9d9f9a06df1166db46d98f58d27ec074c02eee6cbe2449c8b9fc5080c5c3f4433092512ec46aa793743c8":"f545d5897585e3db71aa0cb8da76c51d032ae963":"0097b698c6165645b303486fbf5a2a4479c0ee85889b541a6f0b858d6b6597b13b854eb4f839af03399a80d79bda6578c841f90d645715b280d37143992dd186c80b949b775cae97370e4ec97443136c6da484e970ffdb1323a20847821d3b18381de13bb49aaea66530c4a4b8271f3eae172cd366e07e6636f1019d2a28aed15e":0
+pkcs1_rsaes_oaep_decrypt:1027:"027458c19ec1636919e736c9af25d609a51b8f561d19c6bf6943dd1ee1ab8a4a3f232100bd40b88decc6ba235548b6ef792a11c9de823d0a7922c7095b6eba5701":"0210ee9b33ab61716e27d251bd465f4b35a1a232e2da00901c294bf22350ce490d099f642b5375612db63ba1f20386492bf04d34b3c22bceb909d13441b53b5139":"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":"010001":MBEDTLS_MD_SHA1:"b0adc4f3fe11da59ce992773d9059943c03046497ee9d9f9a06df1166db46d98f58d27ec074c02eee6cbe2449c8b9fc5080c5c3f4433092512ec46aa793743c8":"f545d5897585e3db71aa0cb8da76c51d032ae963":"0097b698c6165645b303486fbf5a2a4479c0ee85889b541a6f0b858d6b6597b13b854eb4f839af03399a80d79bda6578c841f90d645715b280d37143992dd186c80b949b775cae97370e4ec97443136c6da484e970ffdb1323a20847821d3b18381de13bb49aaea66530c4a4b8271f3eae172cd366e07e6636f1019d2a28aed15e":0
 
 RSAES-OAEP Decryption Example 4_3
-pkcs1_rsaes_oaep_decrypt:1027:16:"027458c19ec1636919e736c9af25d609a51b8f561d19c6bf6943dd1ee1ab8a4a3f232100bd40b88decc6ba235548b6ef792a11c9de823d0a7922c7095b6eba5701":16:"0210ee9b33ab61716e27d251bd465f4b35a1a232e2da00901c294bf22350ce490d099f642b5375612db63ba1f20386492bf04d34b3c22bceb909d13441b53b5139":16:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":16:"010001":MBEDTLS_MD_SHA1:"bf6d42e701707b1d0206b0c8b45a1c72641ff12889219a82bdea965b5e79a96b0d0163ed9d578ec9ada20f2fbcf1ea3c4089d83419ba81b0c60f3606da99":"ad997feef730d6ea7be60d0dc52e72eacbfdd275":"0301f935e9c47abcb48acbbe09895d9f5971af14839da4ff95417ee453d1fd77319072bb7297e1b55d7561cd9d1bb24c1a9a37c619864308242804879d86ebd001dce5183975e1506989b70e5a83434154d5cbfd6a24787e60eb0c658d2ac193302d1192c6e622d4a12ad4b53923bca246df31c6395e37702c6a78ae081fb9d065":0
+pkcs1_rsaes_oaep_decrypt:1027:"027458c19ec1636919e736c9af25d609a51b8f561d19c6bf6943dd1ee1ab8a4a3f232100bd40b88decc6ba235548b6ef792a11c9de823d0a7922c7095b6eba5701":"0210ee9b33ab61716e27d251bd465f4b35a1a232e2da00901c294bf22350ce490d099f642b5375612db63ba1f20386492bf04d34b3c22bceb909d13441b53b5139":"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":"010001":MBEDTLS_MD_SHA1:"bf6d42e701707b1d0206b0c8b45a1c72641ff12889219a82bdea965b5e79a96b0d0163ed9d578ec9ada20f2fbcf1ea3c4089d83419ba81b0c60f3606da99":"ad997feef730d6ea7be60d0dc52e72eacbfdd275":"0301f935e9c47abcb48acbbe09895d9f5971af14839da4ff95417ee453d1fd77319072bb7297e1b55d7561cd9d1bb24c1a9a37c619864308242804879d86ebd001dce5183975e1506989b70e5a83434154d5cbfd6a24787e60eb0c658d2ac193302d1192c6e622d4a12ad4b53923bca246df31c6395e37702c6a78ae081fb9d065":0
 
 RSAES-OAEP Decryption Example 4_4
-pkcs1_rsaes_oaep_decrypt:1027:16:"027458c19ec1636919e736c9af25d609a51b8f561d19c6bf6943dd1ee1ab8a4a3f232100bd40b88decc6ba235548b6ef792a11c9de823d0a7922c7095b6eba5701":16:"0210ee9b33ab61716e27d251bd465f4b35a1a232e2da00901c294bf22350ce490d099f642b5375612db63ba1f20386492bf04d34b3c22bceb909d13441b53b5139":16:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":16:"010001":MBEDTLS_MD_SHA1:"fb2ef112f5e766eb94019297934794f7be2f6fc1c58e":"136454df5730f73c807a7e40d8c1a312ac5b9dd3":"02d110ad30afb727beb691dd0cf17d0af1a1e7fa0cc040ec1a4ba26a42c59d0a796a2e22c8f357ccc98b6519aceb682e945e62cb734614a529407cd452bee3e44fece8423cc19e55548b8b994b849c7ecde4933e76037e1d0ce44275b08710c68e430130b929730ed77e09b015642c5593f04e4ffb9410798102a8e96ffdfe11e4":0
+pkcs1_rsaes_oaep_decrypt:1027:"027458c19ec1636919e736c9af25d609a51b8f561d19c6bf6943dd1ee1ab8a4a3f232100bd40b88decc6ba235548b6ef792a11c9de823d0a7922c7095b6eba5701":"0210ee9b33ab61716e27d251bd465f4b35a1a232e2da00901c294bf22350ce490d099f642b5375612db63ba1f20386492bf04d34b3c22bceb909d13441b53b5139":"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":"010001":MBEDTLS_MD_SHA1:"fb2ef112f5e766eb94019297934794f7be2f6fc1c58e":"136454df5730f73c807a7e40d8c1a312ac5b9dd3":"02d110ad30afb727beb691dd0cf17d0af1a1e7fa0cc040ec1a4ba26a42c59d0a796a2e22c8f357ccc98b6519aceb682e945e62cb734614a529407cd452bee3e44fece8423cc19e55548b8b994b849c7ecde4933e76037e1d0ce44275b08710c68e430130b929730ed77e09b015642c5593f04e4ffb9410798102a8e96ffdfe11e4":0
 
 RSAES-OAEP Decryption Example 4_5
-pkcs1_rsaes_oaep_decrypt:1027:16:"027458c19ec1636919e736c9af25d609a51b8f561d19c6bf6943dd1ee1ab8a4a3f232100bd40b88decc6ba235548b6ef792a11c9de823d0a7922c7095b6eba5701":16:"0210ee9b33ab61716e27d251bd465f4b35a1a232e2da00901c294bf22350ce490d099f642b5375612db63ba1f20386492bf04d34b3c22bceb909d13441b53b5139":16:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":16:"010001":MBEDTLS_MD_SHA1:"28ccd447bb9e85166dabb9e5b7d1adadc4b9d39f204e96d5e440ce9ad928bc1c2284":"bca8057f824b2ea257f2861407eef63d33208681":"00dbb8a7439d90efd919a377c54fae8fe11ec58c3b858362e23ad1b8a44310799066b99347aa525691d2adc58d9b06e34f288c170390c5f0e11c0aa3645959f18ee79e8f2be8d7ac5c23d061f18dd74b8c5f2a58fcb5eb0c54f99f01a83247568292536583340948d7a8c97c4acd1e98d1e29dc320e97a260532a8aa7a758a1ec2":0
+pkcs1_rsaes_oaep_decrypt:1027:"027458c19ec1636919e736c9af25d609a51b8f561d19c6bf6943dd1ee1ab8a4a3f232100bd40b88decc6ba235548b6ef792a11c9de823d0a7922c7095b6eba5701":"0210ee9b33ab61716e27d251bd465f4b35a1a232e2da00901c294bf22350ce490d099f642b5375612db63ba1f20386492bf04d34b3c22bceb909d13441b53b5139":"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":"010001":MBEDTLS_MD_SHA1:"28ccd447bb9e85166dabb9e5b7d1adadc4b9d39f204e96d5e440ce9ad928bc1c2284":"bca8057f824b2ea257f2861407eef63d33208681":"00dbb8a7439d90efd919a377c54fae8fe11ec58c3b858362e23ad1b8a44310799066b99347aa525691d2adc58d9b06e34f288c170390c5f0e11c0aa3645959f18ee79e8f2be8d7ac5c23d061f18dd74b8c5f2a58fcb5eb0c54f99f01a83247568292536583340948d7a8c97c4acd1e98d1e29dc320e97a260532a8aa7a758a1ec2":0
 
 RSAES-OAEP Decryption Example 4_6
-pkcs1_rsaes_oaep_decrypt:1027:16:"027458c19ec1636919e736c9af25d609a51b8f561d19c6bf6943dd1ee1ab8a4a3f232100bd40b88decc6ba235548b6ef792a11c9de823d0a7922c7095b6eba5701":16:"0210ee9b33ab61716e27d251bd465f4b35a1a232e2da00901c294bf22350ce490d099f642b5375612db63ba1f20386492bf04d34b3c22bceb909d13441b53b5139":16:"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":16:"010001":MBEDTLS_MD_SHA1:"f22242751ec6b1":"2e7e1e17f647b5ddd033e15472f90f6812f3ac4e":"00a5ffa4768c8bbecaee2db77e8f2eec99595933545520835e5ba7db9493d3e17cddefe6a5f567624471908db4e2d83a0fbee60608fc84049503b2234a07dc83b27b22847ad8920ff42f674ef79b76280b00233d2b51b8cb2703a9d42bfbc8250c96ec32c051e57f1b4ba528db89c37e4c54e27e6e64ac69635ae887d9541619a9":0
+pkcs1_rsaes_oaep_decrypt:1027:"027458c19ec1636919e736c9af25d609a51b8f561d19c6bf6943dd1ee1ab8a4a3f232100bd40b88decc6ba235548b6ef792a11c9de823d0a7922c7095b6eba5701":"0210ee9b33ab61716e27d251bd465f4b35a1a232e2da00901c294bf22350ce490d099f642b5375612db63ba1f20386492bf04d34b3c22bceb909d13441b53b5139":"051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb039":"010001":MBEDTLS_MD_SHA1:"f22242751ec6b1":"2e7e1e17f647b5ddd033e15472f90f6812f3ac4e":"00a5ffa4768c8bbecaee2db77e8f2eec99595933545520835e5ba7db9493d3e17cddefe6a5f567624471908db4e2d83a0fbee60608fc84049503b2234a07dc83b27b22847ad8920ff42f674ef79b76280b00233d2b51b8cb2703a9d42bfbc8250c96ec32c051e57f1b4ba528db89c37e4c54e27e6e64ac69635ae887d9541619a9":0
 
 RSAES-OAEP Decryption Example 5_1
-pkcs1_rsaes_oaep_decrypt:1028:16:"03b0d3962f6d17549cbfca11294348dcf0e7e39f8c2bc6824f2164b606d687860dae1e632393cfedf513228229069e2f60e4acd7e633a436063f82385f48993707":16:"02e4c32e2f517269b7072309f00c0e31365f7ce28b236b82912df239abf39572cf0ed604b02982e53564c52d6a05397de5c052a2fddc141ef7189836346aeb331f":16:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":16:"010001":MBEDTLS_MD_SHA1:"af71a901e3a61d3132f0fc1fdb474f9ea6579257ffc24d164170145b3dbde8":"44c92e283f77b9499c603d963660c87d2f939461":"036046a4a47d9ed3ba9a89139c105038eb7492b05a5d68bfd53accff4597f7a68651b47b4a4627d927e485eed7b4566420e8b409879e5d606eae251d22a5df799f7920bfc117b992572a53b1263146bcea03385cc5e853c9a101c8c3e1bda31a519807496c6cb5e5efb408823a352b8fa0661fb664efadd593deb99fff5ed000e5":0
+pkcs1_rsaes_oaep_decrypt:1028:"03b0d3962f6d17549cbfca11294348dcf0e7e39f8c2bc6824f2164b606d687860dae1e632393cfedf513228229069e2f60e4acd7e633a436063f82385f48993707":"02e4c32e2f517269b7072309f00c0e31365f7ce28b236b82912df239abf39572cf0ed604b02982e53564c52d6a05397de5c052a2fddc141ef7189836346aeb331f":"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":"010001":MBEDTLS_MD_SHA1:"af71a901e3a61d3132f0fc1fdb474f9ea6579257ffc24d164170145b3dbde8":"44c92e283f77b9499c603d963660c87d2f939461":"036046a4a47d9ed3ba9a89139c105038eb7492b05a5d68bfd53accff4597f7a68651b47b4a4627d927e485eed7b4566420e8b409879e5d606eae251d22a5df799f7920bfc117b992572a53b1263146bcea03385cc5e853c9a101c8c3e1bda31a519807496c6cb5e5efb408823a352b8fa0661fb664efadd593deb99fff5ed000e5":0
 
 RSAES-OAEP Decryption Example 5_2
-pkcs1_rsaes_oaep_decrypt:1028:16:"03b0d3962f6d17549cbfca11294348dcf0e7e39f8c2bc6824f2164b606d687860dae1e632393cfedf513228229069e2f60e4acd7e633a436063f82385f48993707":16:"02e4c32e2f517269b7072309f00c0e31365f7ce28b236b82912df239abf39572cf0ed604b02982e53564c52d6a05397de5c052a2fddc141ef7189836346aeb331f":16:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":16:"010001":MBEDTLS_MD_SHA1:"a3b844a08239a8ac41605af17a6cfda4d350136585903a417a79268760519a4b4ac3303ec73f0f87cfb32399":"cb28f5860659fceee49c3eeafce625a70803bd32":"03d6eb654edce615bc59f455265ed4e5a18223cbb9be4e4069b473804d5de96f54dcaaa603d049c5d94aa1470dfcd2254066b7c7b61ff1f6f6770e3215c51399fd4e34ec5082bc48f089840ad04354ae66dc0f1bd18e461a33cc1258b443a2837a6df26759aa2302334986f87380c9cc9d53be9f99605d2c9a97da7b0915a4a7ad":0
+pkcs1_rsaes_oaep_decrypt:1028:"03b0d3962f6d17549cbfca11294348dcf0e7e39f8c2bc6824f2164b606d687860dae1e632393cfedf513228229069e2f60e4acd7e633a436063f82385f48993707":"02e4c32e2f517269b7072309f00c0e31365f7ce28b236b82912df239abf39572cf0ed604b02982e53564c52d6a05397de5c052a2fddc141ef7189836346aeb331f":"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":"010001":MBEDTLS_MD_SHA1:"a3b844a08239a8ac41605af17a6cfda4d350136585903a417a79268760519a4b4ac3303ec73f0f87cfb32399":"cb28f5860659fceee49c3eeafce625a70803bd32":"03d6eb654edce615bc59f455265ed4e5a18223cbb9be4e4069b473804d5de96f54dcaaa603d049c5d94aa1470dfcd2254066b7c7b61ff1f6f6770e3215c51399fd4e34ec5082bc48f089840ad04354ae66dc0f1bd18e461a33cc1258b443a2837a6df26759aa2302334986f87380c9cc9d53be9f99605d2c9a97da7b0915a4a7ad":0
 
 RSAES-OAEP Decryption Example 5_3
-pkcs1_rsaes_oaep_decrypt:1028:16:"03b0d3962f6d17549cbfca11294348dcf0e7e39f8c2bc6824f2164b606d687860dae1e632393cfedf513228229069e2f60e4acd7e633a436063f82385f48993707":16:"02e4c32e2f517269b7072309f00c0e31365f7ce28b236b82912df239abf39572cf0ed604b02982e53564c52d6a05397de5c052a2fddc141ef7189836346aeb331f":16:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":16:"010001":MBEDTLS_MD_SHA1:"308b0ecbd2c76cb77fc6f70c5edd233fd2f20929d629f026953bb62a8f4a3a314bde195de85b5f816da2aab074d26cb6acddf323ae3b9c678ac3cf12fbdde7":"2285f40d770482f9a9efa2c72cb3ac55716dc0ca":"0770952181649f9f9f07ff626ff3a22c35c462443d905d456a9fd0bff43cac2ca7a9f554e9478b9acc3ac838b02040ffd3e1847de2e4253929f9dd9ee4044325a9b05cabb808b2ee840d34e15d105a3f1f7b27695a1a07a2d73fe08ecaaa3c9c9d4d5a89ff890d54727d7ae40c0ec1a8dd86165d8ee2c6368141016a48b55b6967":0
+pkcs1_rsaes_oaep_decrypt:1028:"03b0d3962f6d17549cbfca11294348dcf0e7e39f8c2bc6824f2164b606d687860dae1e632393cfedf513228229069e2f60e4acd7e633a436063f82385f48993707":"02e4c32e2f517269b7072309f00c0e31365f7ce28b236b82912df239abf39572cf0ed604b02982e53564c52d6a05397de5c052a2fddc141ef7189836346aeb331f":"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":"010001":MBEDTLS_MD_SHA1:"308b0ecbd2c76cb77fc6f70c5edd233fd2f20929d629f026953bb62a8f4a3a314bde195de85b5f816da2aab074d26cb6acddf323ae3b9c678ac3cf12fbdde7":"2285f40d770482f9a9efa2c72cb3ac55716dc0ca":"0770952181649f9f9f07ff626ff3a22c35c462443d905d456a9fd0bff43cac2ca7a9f554e9478b9acc3ac838b02040ffd3e1847de2e4253929f9dd9ee4044325a9b05cabb808b2ee840d34e15d105a3f1f7b27695a1a07a2d73fe08ecaaa3c9c9d4d5a89ff890d54727d7ae40c0ec1a8dd86165d8ee2c6368141016a48b55b6967":0
 
 RSAES-OAEP Decryption Example 5_4
-pkcs1_rsaes_oaep_decrypt:1028:16:"03b0d3962f6d17549cbfca11294348dcf0e7e39f8c2bc6824f2164b606d687860dae1e632393cfedf513228229069e2f60e4acd7e633a436063f82385f48993707":16:"02e4c32e2f517269b7072309f00c0e31365f7ce28b236b82912df239abf39572cf0ed604b02982e53564c52d6a05397de5c052a2fddc141ef7189836346aeb331f":16:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":16:"010001":MBEDTLS_MD_SHA1:"15c5b9ee1185":"49fa45d3a78dd10dfd577399d1eb00af7eed5513":"0812b76768ebcb642d040258e5f4441a018521bd96687e6c5e899fcd6c17588ff59a82cc8ae03a4b45b31299af1788c329f7dcd285f8cf4ced82606b97612671a45bedca133442144d1617d114f802857f0f9d739751c57a3f9ee400912c61e2e6992be031a43dd48fa6ba14eef7c422b5edc4e7afa04fdd38f402d1c8bb719abf":0
+pkcs1_rsaes_oaep_decrypt:1028:"03b0d3962f6d17549cbfca11294348dcf0e7e39f8c2bc6824f2164b606d687860dae1e632393cfedf513228229069e2f60e4acd7e633a436063f82385f48993707":"02e4c32e2f517269b7072309f00c0e31365f7ce28b236b82912df239abf39572cf0ed604b02982e53564c52d6a05397de5c052a2fddc141ef7189836346aeb331f":"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":"010001":MBEDTLS_MD_SHA1:"15c5b9ee1185":"49fa45d3a78dd10dfd577399d1eb00af7eed5513":"0812b76768ebcb642d040258e5f4441a018521bd96687e6c5e899fcd6c17588ff59a82cc8ae03a4b45b31299af1788c329f7dcd285f8cf4ced82606b97612671a45bedca133442144d1617d114f802857f0f9d739751c57a3f9ee400912c61e2e6992be031a43dd48fa6ba14eef7c422b5edc4e7afa04fdd38f402d1c8bb719abf":0
 
 RSAES-OAEP Decryption Example 5_5
-pkcs1_rsaes_oaep_decrypt:1028:16:"03b0d3962f6d17549cbfca11294348dcf0e7e39f8c2bc6824f2164b606d687860dae1e632393cfedf513228229069e2f60e4acd7e633a436063f82385f48993707":16:"02e4c32e2f517269b7072309f00c0e31365f7ce28b236b82912df239abf39572cf0ed604b02982e53564c52d6a05397de5c052a2fddc141ef7189836346aeb331f":16:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":16:"010001":MBEDTLS_MD_SHA1:"21026e6800c7fa728fcaaba0d196ae28d7a2ac4ffd8abce794f0985f60c8a6737277365d3fea11db8923a2029a":"f0287413234cc5034724a094c4586b87aff133fc":"07b60e14ec954bfd29e60d0047e789f51d57186c63589903306793ced3f68241c743529aba6a6374f92e19e0163efa33697e196f7661dfaaa47aac6bde5e51deb507c72c589a2ca1693d96b1460381249b2cdb9eac44769f2489c5d3d2f99f0ee3c7ee5bf64a5ac79c42bd433f149be8cb59548361640595513c97af7bc2509723":0
+pkcs1_rsaes_oaep_decrypt:1028:"03b0d3962f6d17549cbfca11294348dcf0e7e39f8c2bc6824f2164b606d687860dae1e632393cfedf513228229069e2f60e4acd7e633a436063f82385f48993707":"02e4c32e2f517269b7072309f00c0e31365f7ce28b236b82912df239abf39572cf0ed604b02982e53564c52d6a05397de5c052a2fddc141ef7189836346aeb331f":"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":"010001":MBEDTLS_MD_SHA1:"21026e6800c7fa728fcaaba0d196ae28d7a2ac4ffd8abce794f0985f60c8a6737277365d3fea11db8923a2029a":"f0287413234cc5034724a094c4586b87aff133fc":"07b60e14ec954bfd29e60d0047e789f51d57186c63589903306793ced3f68241c743529aba6a6374f92e19e0163efa33697e196f7661dfaaa47aac6bde5e51deb507c72c589a2ca1693d96b1460381249b2cdb9eac44769f2489c5d3d2f99f0ee3c7ee5bf64a5ac79c42bd433f149be8cb59548361640595513c97af7bc2509723":0
 
 RSAES-OAEP Decryption Example 5_6
-pkcs1_rsaes_oaep_decrypt:1028:16:"03b0d3962f6d17549cbfca11294348dcf0e7e39f8c2bc6824f2164b606d687860dae1e632393cfedf513228229069e2f60e4acd7e633a436063f82385f48993707":16:"02e4c32e2f517269b7072309f00c0e31365f7ce28b236b82912df239abf39572cf0ed604b02982e53564c52d6a05397de5c052a2fddc141ef7189836346aeb331f":16:"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":16:"010001":MBEDTLS_MD_SHA1:"541e37b68b6c8872b84c02":"d9fba45c96f21e6e26d29eb2cdcb6585be9cb341":"08c36d4dda33423b2ed6830d85f6411ba1dcf470a1fae0ebefee7c089f256cef74cb96ea69c38f60f39abee44129bcb4c92de7f797623b20074e3d9c2899701ed9071e1efa0bdd84d4c3e5130302d8f0240baba4b84a71cc032f2235a5ff0fae277c3e8f9112bef44c9ae20d175fc9a4058bfc930ba31b02e2e4f444483710f24a":0
+pkcs1_rsaes_oaep_decrypt:1028:"03b0d3962f6d17549cbfca11294348dcf0e7e39f8c2bc6824f2164b606d687860dae1e632393cfedf513228229069e2f60e4acd7e633a436063f82385f48993707":"02e4c32e2f517269b7072309f00c0e31365f7ce28b236b82912df239abf39572cf0ed604b02982e53564c52d6a05397de5c052a2fddc141ef7189836346aeb331f":"0aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed9":"010001":MBEDTLS_MD_SHA1:"541e37b68b6c8872b84c02":"d9fba45c96f21e6e26d29eb2cdcb6585be9cb341":"08c36d4dda33423b2ed6830d85f6411ba1dcf470a1fae0ebefee7c089f256cef74cb96ea69c38f60f39abee44129bcb4c92de7f797623b20074e3d9c2899701ed9071e1efa0bdd84d4c3e5130302d8f0240baba4b84a71cc032f2235a5ff0fae277c3e8f9112bef44c9ae20d175fc9a4058bfc930ba31b02e2e4f444483710f24a":0
 
 RSAES-OAEP Decryption Example 6_1
-pkcs1_rsaes_oaep_decrypt:1029:16:"04a6ce8b7358dfa69bdcf742617005afb5385f5f3a58a24ef74a22a8c05cb7cc38ebd4cc9d9a9d789a62cd0f60f0cb941d3423c9692efa4fe3adff290c4749a38b":16:"0404c9a803371fedb4c5be39f3c00b009e5e08a63be1e40035cdaca5011cc701cf7eebcb99f0ffe17cfd0a4bf7befd2dd536ac946db797fdbc4abe8f29349b91ed":16:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":16:"010001":MBEDTLS_MD_SHA1:"4046ca8baa3347ca27f49e0d81f9cc1d71be9ba517d4":"dd0f6cfe415e88e5a469a51fbba6dfd40adb4384":"0630eebcd2856c24f798806e41f9e67345eda9ceda386acc9facaea1eeed06ace583709718d9d169fadf414d5c76f92996833ef305b75b1e4b95f662a20faedc3bae0c4827a8bf8a88edbd57ec203a27a841f02e43a615bab1a8cac0701de34debdef62a088089b55ec36ea7522fd3ec8d06b6a073e6df833153bc0aefd93bd1a3":0
+pkcs1_rsaes_oaep_decrypt:1029:"04a6ce8b7358dfa69bdcf742617005afb5385f5f3a58a24ef74a22a8c05cb7cc38ebd4cc9d9a9d789a62cd0f60f0cb941d3423c9692efa4fe3adff290c4749a38b":"0404c9a803371fedb4c5be39f3c00b009e5e08a63be1e40035cdaca5011cc701cf7eebcb99f0ffe17cfd0a4bf7befd2dd536ac946db797fdbc4abe8f29349b91ed":"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":"010001":MBEDTLS_MD_SHA1:"4046ca8baa3347ca27f49e0d81f9cc1d71be9ba517d4":"dd0f6cfe415e88e5a469a51fbba6dfd40adb4384":"0630eebcd2856c24f798806e41f9e67345eda9ceda386acc9facaea1eeed06ace583709718d9d169fadf414d5c76f92996833ef305b75b1e4b95f662a20faedc3bae0c4827a8bf8a88edbd57ec203a27a841f02e43a615bab1a8cac0701de34debdef62a088089b55ec36ea7522fd3ec8d06b6a073e6df833153bc0aefd93bd1a3":0
 
 RSAES-OAEP Decryption Example 6_2
-pkcs1_rsaes_oaep_decrypt:1029:16:"04a6ce8b7358dfa69bdcf742617005afb5385f5f3a58a24ef74a22a8c05cb7cc38ebd4cc9d9a9d789a62cd0f60f0cb941d3423c9692efa4fe3adff290c4749a38b":16:"0404c9a803371fedb4c5be39f3c00b009e5e08a63be1e40035cdaca5011cc701cf7eebcb99f0ffe17cfd0a4bf7befd2dd536ac946db797fdbc4abe8f29349b91ed":16:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":16:"010001":MBEDTLS_MD_SHA1:"5cc72c60231df03b3d40f9b57931bc31109f972527f28b19e7480c7288cb3c92b22512214e4be6c914792ddabdf57faa8aa7":"8d14bd946a1351148f5cae2ed9a0c653e85ebd85":"0ebc37376173a4fd2f89cc55c2ca62b26b11d51c3c7ce49e8845f74e7607317c436bc8d23b9667dfeb9d087234b47bc6837175ae5c0559f6b81d7d22416d3e50f4ac533d8f0812f2db9e791fe9c775ac8b6ad0f535ad9ceb23a4a02014c58ab3f8d3161499a260f39348e714ae2a1d3443208fd8b722ccfdfb393e98011f99e63f":0
+pkcs1_rsaes_oaep_decrypt:1029:"04a6ce8b7358dfa69bdcf742617005afb5385f5f3a58a24ef74a22a8c05cb7cc38ebd4cc9d9a9d789a62cd0f60f0cb941d3423c9692efa4fe3adff290c4749a38b":"0404c9a803371fedb4c5be39f3c00b009e5e08a63be1e40035cdaca5011cc701cf7eebcb99f0ffe17cfd0a4bf7befd2dd536ac946db797fdbc4abe8f29349b91ed":"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":"010001":MBEDTLS_MD_SHA1:"5cc72c60231df03b3d40f9b57931bc31109f972527f28b19e7480c7288cb3c92b22512214e4be6c914792ddabdf57faa8aa7":"8d14bd946a1351148f5cae2ed9a0c653e85ebd85":"0ebc37376173a4fd2f89cc55c2ca62b26b11d51c3c7ce49e8845f74e7607317c436bc8d23b9667dfeb9d087234b47bc6837175ae5c0559f6b81d7d22416d3e50f4ac533d8f0812f2db9e791fe9c775ac8b6ad0f535ad9ceb23a4a02014c58ab3f8d3161499a260f39348e714ae2a1d3443208fd8b722ccfdfb393e98011f99e63f":0
 
 RSAES-OAEP Decryption Example 6_3
-pkcs1_rsaes_oaep_decrypt:1029:16:"04a6ce8b7358dfa69bdcf742617005afb5385f5f3a58a24ef74a22a8c05cb7cc38ebd4cc9d9a9d789a62cd0f60f0cb941d3423c9692efa4fe3adff290c4749a38b":16:"0404c9a803371fedb4c5be39f3c00b009e5e08a63be1e40035cdaca5011cc701cf7eebcb99f0ffe17cfd0a4bf7befd2dd536ac946db797fdbc4abe8f29349b91ed":16:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":16:"010001":MBEDTLS_MD_SHA1:"b20e651303092f4bccb43070c0f86d23049362ed96642fc5632c27db4a52e3d831f2ab068b23b149879c002f6bf3feee97591112562c":"6c075bc45520f165c0bf5ea4c5df191bc9ef0e44":"0a98bf1093619394436cf68d8f38e2f158fde8ea54f3435f239b8d06b8321844202476aeed96009492480ce3a8d705498c4c8c68f01501dc81db608f60087350c8c3b0bd2e9ef6a81458b7c801b89f2e4fe99d4900ba6a4b5e5a96d865dc676c7755928794130d6280a8160a190f2df3ea7cf9aa0271d88e9e6905ecf1c5152d65":0
+pkcs1_rsaes_oaep_decrypt:1029:"04a6ce8b7358dfa69bdcf742617005afb5385f5f3a58a24ef74a22a8c05cb7cc38ebd4cc9d9a9d789a62cd0f60f0cb941d3423c9692efa4fe3adff290c4749a38b":"0404c9a803371fedb4c5be39f3c00b009e5e08a63be1e40035cdaca5011cc701cf7eebcb99f0ffe17cfd0a4bf7befd2dd536ac946db797fdbc4abe8f29349b91ed":"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":"010001":MBEDTLS_MD_SHA1:"b20e651303092f4bccb43070c0f86d23049362ed96642fc5632c27db4a52e3d831f2ab068b23b149879c002f6bf3feee97591112562c":"6c075bc45520f165c0bf5ea4c5df191bc9ef0e44":"0a98bf1093619394436cf68d8f38e2f158fde8ea54f3435f239b8d06b8321844202476aeed96009492480ce3a8d705498c4c8c68f01501dc81db608f60087350c8c3b0bd2e9ef6a81458b7c801b89f2e4fe99d4900ba6a4b5e5a96d865dc676c7755928794130d6280a8160a190f2df3ea7cf9aa0271d88e9e6905ecf1c5152d65":0
 
 RSAES-OAEP Decryption Example 6_4
-pkcs1_rsaes_oaep_decrypt:1029:16:"04a6ce8b7358dfa69bdcf742617005afb5385f5f3a58a24ef74a22a8c05cb7cc38ebd4cc9d9a9d789a62cd0f60f0cb941d3423c9692efa4fe3adff290c4749a38b":16:"0404c9a803371fedb4c5be39f3c00b009e5e08a63be1e40035cdaca5011cc701cf7eebcb99f0ffe17cfd0a4bf7befd2dd536ac946db797fdbc4abe8f29349b91ed":16:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":16:"010001":MBEDTLS_MD_SHA1:"684e3038c5c041f7":"3bbc3bd6637dfe12846901029bf5b0c07103439c":"008e7a67cacfb5c4e24bec7dee149117f19598ce8c45808fef88c608ff9cd6e695263b9a3c0ad4b8ba4c95238e96a8422b8535629c8d5382374479ad13fa39974b242f9a759eeaf9c83ad5a8ca18940a0162ba755876df263f4bd50c6525c56090267c1f0e09ce0899a0cf359e88120abd9bf893445b3cae77d3607359ae9a52f8":0
+pkcs1_rsaes_oaep_decrypt:1029:"04a6ce8b7358dfa69bdcf742617005afb5385f5f3a58a24ef74a22a8c05cb7cc38ebd4cc9d9a9d789a62cd0f60f0cb941d3423c9692efa4fe3adff290c4749a38b":"0404c9a803371fedb4c5be39f3c00b009e5e08a63be1e40035cdaca5011cc701cf7eebcb99f0ffe17cfd0a4bf7befd2dd536ac946db797fdbc4abe8f29349b91ed":"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":"010001":MBEDTLS_MD_SHA1:"684e3038c5c041f7":"3bbc3bd6637dfe12846901029bf5b0c07103439c":"008e7a67cacfb5c4e24bec7dee149117f19598ce8c45808fef88c608ff9cd6e695263b9a3c0ad4b8ba4c95238e96a8422b8535629c8d5382374479ad13fa39974b242f9a759eeaf9c83ad5a8ca18940a0162ba755876df263f4bd50c6525c56090267c1f0e09ce0899a0cf359e88120abd9bf893445b3cae77d3607359ae9a52f8":0
 
 RSAES-OAEP Decryption Example 6_5
-pkcs1_rsaes_oaep_decrypt:1029:16:"04a6ce8b7358dfa69bdcf742617005afb5385f5f3a58a24ef74a22a8c05cb7cc38ebd4cc9d9a9d789a62cd0f60f0cb941d3423c9692efa4fe3adff290c4749a38b":16:"0404c9a803371fedb4c5be39f3c00b009e5e08a63be1e40035cdaca5011cc701cf7eebcb99f0ffe17cfd0a4bf7befd2dd536ac946db797fdbc4abe8f29349b91ed":16:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":16:"010001":MBEDTLS_MD_SHA1:"32488cb262d041d6e4dd35f987bf3ca696db1f06ac29a44693":"b46b41893e8bef326f6759383a83071dae7fcabc":"00003474416c7b68bdf961c385737944d7f1f40cb395343c693cc0b4fe63b31fedf1eaeeac9ccc0678b31dc32e0977489514c4f09085f6298a9653f01aea4045ff582ee887be26ae575b73eef7f3774921e375a3d19adda0ca31aa1849887c1f42cac9677f7a2f4e923f6e5a868b38c084ef187594dc9f7f048fea2e02955384ab":0
+pkcs1_rsaes_oaep_decrypt:1029:"04a6ce8b7358dfa69bdcf742617005afb5385f5f3a58a24ef74a22a8c05cb7cc38ebd4cc9d9a9d789a62cd0f60f0cb941d3423c9692efa4fe3adff290c4749a38b":"0404c9a803371fedb4c5be39f3c00b009e5e08a63be1e40035cdaca5011cc701cf7eebcb99f0ffe17cfd0a4bf7befd2dd536ac946db797fdbc4abe8f29349b91ed":"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":"010001":MBEDTLS_MD_SHA1:"32488cb262d041d6e4dd35f987bf3ca696db1f06ac29a44693":"b46b41893e8bef326f6759383a83071dae7fcabc":"00003474416c7b68bdf961c385737944d7f1f40cb395343c693cc0b4fe63b31fedf1eaeeac9ccc0678b31dc32e0977489514c4f09085f6298a9653f01aea4045ff582ee887be26ae575b73eef7f3774921e375a3d19adda0ca31aa1849887c1f42cac9677f7a2f4e923f6e5a868b38c084ef187594dc9f7f048fea2e02955384ab":0
 
 RSAES-OAEP Decryption Example 6_6
-pkcs1_rsaes_oaep_decrypt:1029:16:"04a6ce8b7358dfa69bdcf742617005afb5385f5f3a58a24ef74a22a8c05cb7cc38ebd4cc9d9a9d789a62cd0f60f0cb941d3423c9692efa4fe3adff290c4749a38b":16:"0404c9a803371fedb4c5be39f3c00b009e5e08a63be1e40035cdaca5011cc701cf7eebcb99f0ffe17cfd0a4bf7befd2dd536ac946db797fdbc4abe8f29349b91ed":16:"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":16:"010001":MBEDTLS_MD_SHA1:"50ba14be8462720279c306ba":"0a2403312a41e3d52f060fbc13a67de5cf7609a7":"0a026dda5fc8785f7bd9bf75327b63e85e2c0fdee5dadb65ebdcac9ae1de95c92c672ab433aa7a8e69ce6a6d8897fac4ac4a54de841ae5e5bbce7687879d79634cea7a30684065c714d52409b928256bbf53eabcd5231eb7259504537399bd29164b726d33a46da701360a4168a091ccab72d44a62fed246c0ffea5b1348ab5470":0
+pkcs1_rsaes_oaep_decrypt:1029:"04a6ce8b7358dfa69bdcf742617005afb5385f5f3a58a24ef74a22a8c05cb7cc38ebd4cc9d9a9d789a62cd0f60f0cb941d3423c9692efa4fe3adff290c4749a38b":"0404c9a803371fedb4c5be39f3c00b009e5e08a63be1e40035cdaca5011cc701cf7eebcb99f0ffe17cfd0a4bf7befd2dd536ac946db797fdbc4abe8f29349b91ed":"12b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af":"010001":MBEDTLS_MD_SHA1:"50ba14be8462720279c306ba":"0a2403312a41e3d52f060fbc13a67de5cf7609a7":"0a026dda5fc8785f7bd9bf75327b63e85e2c0fdee5dadb65ebdcac9ae1de95c92c672ab433aa7a8e69ce6a6d8897fac4ac4a54de841ae5e5bbce7687879d79634cea7a30684065c714d52409b928256bbf53eabcd5231eb7259504537399bd29164b726d33a46da701360a4168a091ccab72d44a62fed246c0ffea5b1348ab5470":0
 
 RSAES-OAEP Decryption Example 7_1
-pkcs1_rsaes_oaep_decrypt:1030:16:"0749262c111cd470ec2566e6b3732fc09329469aa19071d3b9c01906514c6f1d26baa14beab0971c8b7e611a4f79009d6fea776928ca25285b0de3643d1a3f8c71":16:"06bc1e50e96c02bf636e9eea8b899bbebf7651de77dd474c3e9bc23bad8182b61904c7d97dfbebfb1e00108878b6e67e415391d67942c2b2bf9b4435f88b0cb023":16:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":16:"010001":MBEDTLS_MD_SHA1:"47aae909":"43dd09a07ff4cac71caa4632ee5e1c1daee4cd8f":"1688e4ce7794bba6cb7014169ecd559cede2a30b56a52b68d9fe18cf1973ef97b2a03153951c755f6294aa49adbdb55845ab6875fb3986c93ecf927962840d282f9e54ce8b690f7c0cb8bbd73440d9571d1b16cd9260f9eab4783cc482e5223dc60973871783ec27b0ae0fd47732cbc286a173fc92b00fb4ba6824647cd93c85c1":0
+pkcs1_rsaes_oaep_decrypt:1030:"0749262c111cd470ec2566e6b3732fc09329469aa19071d3b9c01906514c6f1d26baa14beab0971c8b7e611a4f79009d6fea776928ca25285b0de3643d1a3f8c71":"06bc1e50e96c02bf636e9eea8b899bbebf7651de77dd474c3e9bc23bad8182b61904c7d97dfbebfb1e00108878b6e67e415391d67942c2b2bf9b4435f88b0cb023":"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":"010001":MBEDTLS_MD_SHA1:"47aae909":"43dd09a07ff4cac71caa4632ee5e1c1daee4cd8f":"1688e4ce7794bba6cb7014169ecd559cede2a30b56a52b68d9fe18cf1973ef97b2a03153951c755f6294aa49adbdb55845ab6875fb3986c93ecf927962840d282f9e54ce8b690f7c0cb8bbd73440d9571d1b16cd9260f9eab4783cc482e5223dc60973871783ec27b0ae0fd47732cbc286a173fc92b00fb4ba6824647cd93c85c1":0
 
 RSAES-OAEP Decryption Example 7_2
-pkcs1_rsaes_oaep_decrypt:1030:16:"0749262c111cd470ec2566e6b3732fc09329469aa19071d3b9c01906514c6f1d26baa14beab0971c8b7e611a4f79009d6fea776928ca25285b0de3643d1a3f8c71":16:"06bc1e50e96c02bf636e9eea8b899bbebf7651de77dd474c3e9bc23bad8182b61904c7d97dfbebfb1e00108878b6e67e415391d67942c2b2bf9b4435f88b0cb023":16:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":16:"010001":MBEDTLS_MD_SHA1:"1d9b2e2223d9bc13bfb9f162ce735db48ba7c68f6822a0a1a7b6ae165834e7":"3a9c3cec7b84f9bd3adecbc673ec99d54b22bc9b":"1052ed397b2e01e1d0ee1c50bf24363f95e504f4a03434a08fd822574ed6b9736edbb5f390db10321479a8a139350e2bd4977c3778ef331f3e78ae118b268451f20a2f01d471f5d53c566937171b2dbc2d4bde459a5799f0372d6574239b2323d245d0bb81c286b63c89a361017337e4902f88a467f4c7f244bfd5ab46437ff3b6":0
+pkcs1_rsaes_oaep_decrypt:1030:"0749262c111cd470ec2566e6b3732fc09329469aa19071d3b9c01906514c6f1d26baa14beab0971c8b7e611a4f79009d6fea776928ca25285b0de3643d1a3f8c71":"06bc1e50e96c02bf636e9eea8b899bbebf7651de77dd474c3e9bc23bad8182b61904c7d97dfbebfb1e00108878b6e67e415391d67942c2b2bf9b4435f88b0cb023":"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":"010001":MBEDTLS_MD_SHA1:"1d9b2e2223d9bc13bfb9f162ce735db48ba7c68f6822a0a1a7b6ae165834e7":"3a9c3cec7b84f9bd3adecbc673ec99d54b22bc9b":"1052ed397b2e01e1d0ee1c50bf24363f95e504f4a03434a08fd822574ed6b9736edbb5f390db10321479a8a139350e2bd4977c3778ef331f3e78ae118b268451f20a2f01d471f5d53c566937171b2dbc2d4bde459a5799f0372d6574239b2323d245d0bb81c286b63c89a361017337e4902f88a467f4c7f244bfd5ab46437ff3b6":0
 
 RSAES-OAEP Decryption Example 7_3
-pkcs1_rsaes_oaep_decrypt:1030:16:"0749262c111cd470ec2566e6b3732fc09329469aa19071d3b9c01906514c6f1d26baa14beab0971c8b7e611a4f79009d6fea776928ca25285b0de3643d1a3f8c71":16:"06bc1e50e96c02bf636e9eea8b899bbebf7651de77dd474c3e9bc23bad8182b61904c7d97dfbebfb1e00108878b6e67e415391d67942c2b2bf9b4435f88b0cb023":16:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":16:"010001":MBEDTLS_MD_SHA1:"d976fc":"76a75e5b6157a556cf8884bb2e45c293dd545cf5":"2155cd843ff24a4ee8badb7694260028a490813ba8b369a4cbf106ec148e5298707f5965be7d101c1049ea8584c24cd63455ad9c104d686282d3fb803a4c11c1c2e9b91c7178801d1b6640f003f5728df007b8a4ccc92bce05e41a27278d7c85018c52414313a5077789001d4f01910b72aad05d220aa14a58733a7489bc54556b":0
+pkcs1_rsaes_oaep_decrypt:1030:"0749262c111cd470ec2566e6b3732fc09329469aa19071d3b9c01906514c6f1d26baa14beab0971c8b7e611a4f79009d6fea776928ca25285b0de3643d1a3f8c71":"06bc1e50e96c02bf636e9eea8b899bbebf7651de77dd474c3e9bc23bad8182b61904c7d97dfbebfb1e00108878b6e67e415391d67942c2b2bf9b4435f88b0cb023":"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":"010001":MBEDTLS_MD_SHA1:"d976fc":"76a75e5b6157a556cf8884bb2e45c293dd545cf5":"2155cd843ff24a4ee8badb7694260028a490813ba8b369a4cbf106ec148e5298707f5965be7d101c1049ea8584c24cd63455ad9c104d686282d3fb803a4c11c1c2e9b91c7178801d1b6640f003f5728df007b8a4ccc92bce05e41a27278d7c85018c52414313a5077789001d4f01910b72aad05d220aa14a58733a7489bc54556b":0
 
 RSAES-OAEP Decryption Example 7_4
-pkcs1_rsaes_oaep_decrypt:1030:16:"0749262c111cd470ec2566e6b3732fc09329469aa19071d3b9c01906514c6f1d26baa14beab0971c8b7e611a4f79009d6fea776928ca25285b0de3643d1a3f8c71":16:"06bc1e50e96c02bf636e9eea8b899bbebf7651de77dd474c3e9bc23bad8182b61904c7d97dfbebfb1e00108878b6e67e415391d67942c2b2bf9b4435f88b0cb023":16:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":16:"010001":MBEDTLS_MD_SHA1:"d4738623df223aa43843df8467534c41d013e0c803c624e263666b239bde40a5f29aeb8de79e3daa61dd0370f49bd4b013834b98212aef6b1c5ee373b3cb":"7866314a6ad6f2b250a35941db28f5864b585859":"0ab14c373aeb7d4328d0aaad8c094d88b9eb098b95f21054a29082522be7c27a312878b637917e3d819e6c3c568db5d843802b06d51d9e98a2be0bf40c031423b00edfbff8320efb9171bd2044653a4cb9c5122f6c65e83cda2ec3c126027a9c1a56ba874d0fea23f380b82cf240b8cf540004758c4c77d934157a74f3fc12bfac":0
+pkcs1_rsaes_oaep_decrypt:1030:"0749262c111cd470ec2566e6b3732fc09329469aa19071d3b9c01906514c6f1d26baa14beab0971c8b7e611a4f79009d6fea776928ca25285b0de3643d1a3f8c71":"06bc1e50e96c02bf636e9eea8b899bbebf7651de77dd474c3e9bc23bad8182b61904c7d97dfbebfb1e00108878b6e67e415391d67942c2b2bf9b4435f88b0cb023":"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":"010001":MBEDTLS_MD_SHA1:"d4738623df223aa43843df8467534c41d013e0c803c624e263666b239bde40a5f29aeb8de79e3daa61dd0370f49bd4b013834b98212aef6b1c5ee373b3cb":"7866314a6ad6f2b250a35941db28f5864b585859":"0ab14c373aeb7d4328d0aaad8c094d88b9eb098b95f21054a29082522be7c27a312878b637917e3d819e6c3c568db5d843802b06d51d9e98a2be0bf40c031423b00edfbff8320efb9171bd2044653a4cb9c5122f6c65e83cda2ec3c126027a9c1a56ba874d0fea23f380b82cf240b8cf540004758c4c77d934157a74f3fc12bfac":0
 
 RSAES-OAEP Decryption Example 7_5
-pkcs1_rsaes_oaep_decrypt:1030:16:"0749262c111cd470ec2566e6b3732fc09329469aa19071d3b9c01906514c6f1d26baa14beab0971c8b7e611a4f79009d6fea776928ca25285b0de3643d1a3f8c71":16:"06bc1e50e96c02bf636e9eea8b899bbebf7651de77dd474c3e9bc23bad8182b61904c7d97dfbebfb1e00108878b6e67e415391d67942c2b2bf9b4435f88b0cb023":16:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":16:"010001":MBEDTLS_MD_SHA1:"bb47231ca5ea1d3ad46c99345d9a8a61":"b2166ed472d58db10cab2c6b000cccf10a7dc509":"028387a318277434798b4d97f460068df5298faba5041ba11761a1cb7316b24184114ec500257e2589ed3b607a1ebbe97a6cc2e02bf1b681f42312a33b7a77d8e7855c4a6de03e3c04643f786b91a264a0d6805e2cea91e68177eb7a64d9255e4f27e713b7ccec00dc200ebd21c2ea2bb890feae4942df941dc3f97890ed347478":0
+pkcs1_rsaes_oaep_decrypt:1030:"0749262c111cd470ec2566e6b3732fc09329469aa19071d3b9c01906514c6f1d26baa14beab0971c8b7e611a4f79009d6fea776928ca25285b0de3643d1a3f8c71":"06bc1e50e96c02bf636e9eea8b899bbebf7651de77dd474c3e9bc23bad8182b61904c7d97dfbebfb1e00108878b6e67e415391d67942c2b2bf9b4435f88b0cb023":"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":"010001":MBEDTLS_MD_SHA1:"bb47231ca5ea1d3ad46c99345d9a8a61":"b2166ed472d58db10cab2c6b000cccf10a7dc509":"028387a318277434798b4d97f460068df5298faba5041ba11761a1cb7316b24184114ec500257e2589ed3b607a1ebbe97a6cc2e02bf1b681f42312a33b7a77d8e7855c4a6de03e3c04643f786b91a264a0d6805e2cea91e68177eb7a64d9255e4f27e713b7ccec00dc200ebd21c2ea2bb890feae4942df941dc3f97890ed347478":0
 
 RSAES-OAEP Decryption Example 7_6
-pkcs1_rsaes_oaep_decrypt:1030:16:"0749262c111cd470ec2566e6b3732fc09329469aa19071d3b9c01906514c6f1d26baa14beab0971c8b7e611a4f79009d6fea776928ca25285b0de3643d1a3f8c71":16:"06bc1e50e96c02bf636e9eea8b899bbebf7651de77dd474c3e9bc23bad8182b61904c7d97dfbebfb1e00108878b6e67e415391d67942c2b2bf9b4435f88b0cb023":16:"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":16:"010001":MBEDTLS_MD_SHA1:"2184827095d35c3f86f600e8e59754013296":"52673bde2ca166c2aa46131ac1dc808d67d7d3b1":"14c678a94ad60525ef39e959b2f3ba5c097a94ff912b67dbace80535c187abd47d075420b1872152bba08f7fc31f313bbf9273c912fc4c0149a9b0cfb79807e346eb332069611bec0ff9bcd168f1f7c33e77313cea454b94e2549eecf002e2acf7f6f2d2845d4fe0aab2e5a92ddf68c480ae11247935d1f62574842216ae674115":0
+pkcs1_rsaes_oaep_decrypt:1030:"0749262c111cd470ec2566e6b3732fc09329469aa19071d3b9c01906514c6f1d26baa14beab0971c8b7e611a4f79009d6fea776928ca25285b0de3643d1a3f8c71":"06bc1e50e96c02bf636e9eea8b899bbebf7651de77dd474c3e9bc23bad8182b61904c7d97dfbebfb1e00108878b6e67e415391d67942c2b2bf9b4435f88b0cb023":"311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e373":"010001":MBEDTLS_MD_SHA1:"2184827095d35c3f86f600e8e59754013296":"52673bde2ca166c2aa46131ac1dc808d67d7d3b1":"14c678a94ad60525ef39e959b2f3ba5c097a94ff912b67dbace80535c187abd47d075420b1872152bba08f7fc31f313bbf9273c912fc4c0149a9b0cfb79807e346eb332069611bec0ff9bcd168f1f7c33e77313cea454b94e2549eecf002e2acf7f6f2d2845d4fe0aab2e5a92ddf68c480ae11247935d1f62574842216ae674115":0
 
 RSAES-OAEP Decryption Example 8_1
-pkcs1_rsaes_oaep_decrypt:1031:16:"0a02ef8448d9fad8bbd0d004c8c2aa9751ef9721c1b0d03236a54b0df947cbaed5a255ee9e8e20d491ea1723fe094704a9762e88afd16ebb5994412ca966dc4f9f":16:"092d362e7ed3a0bfd9e9fd0e6c0301b6df29159cf50cc83b9b0cf4d6eea71a61e002b46e0ae9f2de62d25b5d7452d498b81c9ac6fc58593d4c3fb4f5d72dfbb0a9":16:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":16:"010001":MBEDTLS_MD_SHA1:"050b755e5e6880f7b9e9d692a74c37aae449b31bfea6deff83747a897f6c2c825bb1adbf850a3c96994b5de5b33cbc7d4a17913a7967":"7706ffca1ecfb1ebee2a55e5c6e24cd2797a4125":"09b3683d8a2eb0fb295b62ed1fb9290b714457b7825319f4647872af889b30409472020ad12912bf19b11d4819f49614824ffd84d09c0a17e7d17309d12919790410aa2995699f6a86dbe3242b5acc23af45691080d6b1ae810fb3e3057087f0970092ce00be9562ff4053b6262ce0caa93e13723d2e3a5ba075d45f0d61b54b61":0
+pkcs1_rsaes_oaep_decrypt:1031:"0a02ef8448d9fad8bbd0d004c8c2aa9751ef9721c1b0d03236a54b0df947cbaed5a255ee9e8e20d491ea1723fe094704a9762e88afd16ebb5994412ca966dc4f9f":"092d362e7ed3a0bfd9e9fd0e6c0301b6df29159cf50cc83b9b0cf4d6eea71a61e002b46e0ae9f2de62d25b5d7452d498b81c9ac6fc58593d4c3fb4f5d72dfbb0a9":"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":"010001":MBEDTLS_MD_SHA1:"050b755e5e6880f7b9e9d692a74c37aae449b31bfea6deff83747a897f6c2c825bb1adbf850a3c96994b5de5b33cbc7d4a17913a7967":"7706ffca1ecfb1ebee2a55e5c6e24cd2797a4125":"09b3683d8a2eb0fb295b62ed1fb9290b714457b7825319f4647872af889b30409472020ad12912bf19b11d4819f49614824ffd84d09c0a17e7d17309d12919790410aa2995699f6a86dbe3242b5acc23af45691080d6b1ae810fb3e3057087f0970092ce00be9562ff4053b6262ce0caa93e13723d2e3a5ba075d45f0d61b54b61":0
 
 RSAES-OAEP Decryption Example 8_2
-pkcs1_rsaes_oaep_decrypt:1031:16:"0a02ef8448d9fad8bbd0d004c8c2aa9751ef9721c1b0d03236a54b0df947cbaed5a255ee9e8e20d491ea1723fe094704a9762e88afd16ebb5994412ca966dc4f9f":16:"092d362e7ed3a0bfd9e9fd0e6c0301b6df29159cf50cc83b9b0cf4d6eea71a61e002b46e0ae9f2de62d25b5d7452d498b81c9ac6fc58593d4c3fb4f5d72dfbb0a9":16:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":16:"010001":MBEDTLS_MD_SHA1:"4eb68dcd93ca9b19df111bd43608f557026fe4aa1d5cfac227a3eb5ab9548c18a06dded23f81825986b2fcd71109ecef7eff88873f075c2aa0c469f69c92bc":"a3717da143b4dcffbc742665a8fa950585548343":"2ecf15c97c5a15b1476ae986b371b57a24284f4a162a8d0c8182e7905e792256f1812ba5f83f1f7a130e42dcc02232844edc14a31a68ee97ae564a383a3411656424c5f62ddb646093c367be1fcda426cf00a06d8acb7e57776fbbd855ac3df506fc16b1d7c3f2110f3d8068e91e186363831c8409680d8da9ecd8cf1fa20ee39d":0
+pkcs1_rsaes_oaep_decrypt:1031:"0a02ef8448d9fad8bbd0d004c8c2aa9751ef9721c1b0d03236a54b0df947cbaed5a255ee9e8e20d491ea1723fe094704a9762e88afd16ebb5994412ca966dc4f9f":"092d362e7ed3a0bfd9e9fd0e6c0301b6df29159cf50cc83b9b0cf4d6eea71a61e002b46e0ae9f2de62d25b5d7452d498b81c9ac6fc58593d4c3fb4f5d72dfbb0a9":"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":"010001":MBEDTLS_MD_SHA1:"4eb68dcd93ca9b19df111bd43608f557026fe4aa1d5cfac227a3eb5ab9548c18a06dded23f81825986b2fcd71109ecef7eff88873f075c2aa0c469f69c92bc":"a3717da143b4dcffbc742665a8fa950585548343":"2ecf15c97c5a15b1476ae986b371b57a24284f4a162a8d0c8182e7905e792256f1812ba5f83f1f7a130e42dcc02232844edc14a31a68ee97ae564a383a3411656424c5f62ddb646093c367be1fcda426cf00a06d8acb7e57776fbbd855ac3df506fc16b1d7c3f2110f3d8068e91e186363831c8409680d8da9ecd8cf1fa20ee39d":0
 
 RSAES-OAEP Decryption Example 8_3
-pkcs1_rsaes_oaep_decrypt:1031:16:"0a02ef8448d9fad8bbd0d004c8c2aa9751ef9721c1b0d03236a54b0df947cbaed5a255ee9e8e20d491ea1723fe094704a9762e88afd16ebb5994412ca966dc4f9f":16:"092d362e7ed3a0bfd9e9fd0e6c0301b6df29159cf50cc83b9b0cf4d6eea71a61e002b46e0ae9f2de62d25b5d7452d498b81c9ac6fc58593d4c3fb4f5d72dfbb0a9":16:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":16:"010001":MBEDTLS_MD_SHA1:"8604ac56328c1ab5ad917861":"ee06209073cca026bb264e5185bf8c68b7739f86":"4bc89130a5b2dabb7c2fcf90eb5d0eaf9e681b7146a38f3173a3d9cfec52ea9e0a41932e648a9d69344c50da763f51a03c95762131e8052254dcd2248cba40fd31667786ce05a2b7b531ac9dac9ed584a59b677c1a8aed8c5d15d68c05569e2be780bf7db638fd2bfd2a85ab276860f3777338fca989ffd743d13ee08e0ca9893f":0
+pkcs1_rsaes_oaep_decrypt:1031:"0a02ef8448d9fad8bbd0d004c8c2aa9751ef9721c1b0d03236a54b0df947cbaed5a255ee9e8e20d491ea1723fe094704a9762e88afd16ebb5994412ca966dc4f9f":"092d362e7ed3a0bfd9e9fd0e6c0301b6df29159cf50cc83b9b0cf4d6eea71a61e002b46e0ae9f2de62d25b5d7452d498b81c9ac6fc58593d4c3fb4f5d72dfbb0a9":"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":"010001":MBEDTLS_MD_SHA1:"8604ac56328c1ab5ad917861":"ee06209073cca026bb264e5185bf8c68b7739f86":"4bc89130a5b2dabb7c2fcf90eb5d0eaf9e681b7146a38f3173a3d9cfec52ea9e0a41932e648a9d69344c50da763f51a03c95762131e8052254dcd2248cba40fd31667786ce05a2b7b531ac9dac9ed584a59b677c1a8aed8c5d15d68c05569e2be780bf7db638fd2bfd2a85ab276860f3777338fca989ffd743d13ee08e0ca9893f":0
 
 RSAES-OAEP Decryption Example 8_4
-pkcs1_rsaes_oaep_decrypt:1031:16:"0a02ef8448d9fad8bbd0d004c8c2aa9751ef9721c1b0d03236a54b0df947cbaed5a255ee9e8e20d491ea1723fe094704a9762e88afd16ebb5994412ca966dc4f9f":16:"092d362e7ed3a0bfd9e9fd0e6c0301b6df29159cf50cc83b9b0cf4d6eea71a61e002b46e0ae9f2de62d25b5d7452d498b81c9ac6fc58593d4c3fb4f5d72dfbb0a9":16:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":16:"010001":MBEDTLS_MD_SHA1:"fdda5fbf6ec361a9d9a4ac68af216a0686f438b1e0e5c36b955f74e107f39c0dddcc":"990ad573dc48a973235b6d82543618f2e955105d":"2e456847d8fc36ff0147d6993594b9397227d577752c79d0f904fcb039d4d812fea605a7b574dd82ca786f93752348438ee9f5b5454985d5f0e1699e3e7ad175a32e15f03deb042ab9fe1dd9db1bb86f8c089ccb45e7ef0c5ee7ca9b7290ca6b15bed47039788a8a93ff83e0e8d6244c71006362deef69b6f416fb3c684383fbd0":0
+pkcs1_rsaes_oaep_decrypt:1031:"0a02ef8448d9fad8bbd0d004c8c2aa9751ef9721c1b0d03236a54b0df947cbaed5a255ee9e8e20d491ea1723fe094704a9762e88afd16ebb5994412ca966dc4f9f":"092d362e7ed3a0bfd9e9fd0e6c0301b6df29159cf50cc83b9b0cf4d6eea71a61e002b46e0ae9f2de62d25b5d7452d498b81c9ac6fc58593d4c3fb4f5d72dfbb0a9":"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":"010001":MBEDTLS_MD_SHA1:"fdda5fbf6ec361a9d9a4ac68af216a0686f438b1e0e5c36b955f74e107f39c0dddcc":"990ad573dc48a973235b6d82543618f2e955105d":"2e456847d8fc36ff0147d6993594b9397227d577752c79d0f904fcb039d4d812fea605a7b574dd82ca786f93752348438ee9f5b5454985d5f0e1699e3e7ad175a32e15f03deb042ab9fe1dd9db1bb86f8c089ccb45e7ef0c5ee7ca9b7290ca6b15bed47039788a8a93ff83e0e8d6244c71006362deef69b6f416fb3c684383fbd0":0
 
 RSAES-OAEP Decryption Example 8_5
-pkcs1_rsaes_oaep_decrypt:1031:16:"0a02ef8448d9fad8bbd0d004c8c2aa9751ef9721c1b0d03236a54b0df947cbaed5a255ee9e8e20d491ea1723fe094704a9762e88afd16ebb5994412ca966dc4f9f":16:"092d362e7ed3a0bfd9e9fd0e6c0301b6df29159cf50cc83b9b0cf4d6eea71a61e002b46e0ae9f2de62d25b5d7452d498b81c9ac6fc58593d4c3fb4f5d72dfbb0a9":16:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":16:"010001":MBEDTLS_MD_SHA1:"4a5f4914bee25de3c69341de07":"ecc63b28f0756f22f52ac8e6ec1251a6ec304718":"1fb9356fd5c4b1796db2ebf7d0d393cc810adf6145defc2fce714f79d93800d5e2ac211ea8bbecca4b654b94c3b18b30dd576ce34dc95436ef57a09415645923359a5d7b4171ef22c24670f1b229d3603e91f76671b7df97e7317c97734476d5f3d17d21cf82b5ba9f83df2e588d36984fd1b584468bd23b2e875f32f68953f7b2":0
+pkcs1_rsaes_oaep_decrypt:1031:"0a02ef8448d9fad8bbd0d004c8c2aa9751ef9721c1b0d03236a54b0df947cbaed5a255ee9e8e20d491ea1723fe094704a9762e88afd16ebb5994412ca966dc4f9f":"092d362e7ed3a0bfd9e9fd0e6c0301b6df29159cf50cc83b9b0cf4d6eea71a61e002b46e0ae9f2de62d25b5d7452d498b81c9ac6fc58593d4c3fb4f5d72dfbb0a9":"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":"010001":MBEDTLS_MD_SHA1:"4a5f4914bee25de3c69341de07":"ecc63b28f0756f22f52ac8e6ec1251a6ec304718":"1fb9356fd5c4b1796db2ebf7d0d393cc810adf6145defc2fce714f79d93800d5e2ac211ea8bbecca4b654b94c3b18b30dd576ce34dc95436ef57a09415645923359a5d7b4171ef22c24670f1b229d3603e91f76671b7df97e7317c97734476d5f3d17d21cf82b5ba9f83df2e588d36984fd1b584468bd23b2e875f32f68953f7b2":0
 
 RSAES-OAEP Decryption Example 8_6
-pkcs1_rsaes_oaep_decrypt:1031:16:"0a02ef8448d9fad8bbd0d004c8c2aa9751ef9721c1b0d03236a54b0df947cbaed5a255ee9e8e20d491ea1723fe094704a9762e88afd16ebb5994412ca966dc4f9f":16:"092d362e7ed3a0bfd9e9fd0e6c0301b6df29159cf50cc83b9b0cf4d6eea71a61e002b46e0ae9f2de62d25b5d7452d498b81c9ac6fc58593d4c3fb4f5d72dfbb0a9":16:"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":16:"010001":MBEDTLS_MD_SHA1:"8e07d66f7b880a72563abcd3f35092bc33409fb7f88f2472be":"3925c71b362d40a0a6de42145579ba1e7dd459fc":"3afd9c6600147b21798d818c655a0f4c9212db26d0b0dfdc2a7594ccb3d22f5bf1d7c3e112cd73fc7d509c7a8bafdd3c274d1399009f9609ec4be6477e453f075aa33db382870c1c3409aef392d7386ae3a696b99a94b4da0589447e955d16c98b17602a59bd736279fcd8fb280c4462d590bfa9bf13fed570eafde97330a2c210":0
+pkcs1_rsaes_oaep_decrypt:1031:"0a02ef8448d9fad8bbd0d004c8c2aa9751ef9721c1b0d03236a54b0df947cbaed5a255ee9e8e20d491ea1723fe094704a9762e88afd16ebb5994412ca966dc4f9f":"092d362e7ed3a0bfd9e9fd0e6c0301b6df29159cf50cc83b9b0cf4d6eea71a61e002b46e0ae9f2de62d25b5d7452d498b81c9ac6fc58593d4c3fb4f5d72dfbb0a9":"5bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff7":"010001":MBEDTLS_MD_SHA1:"8e07d66f7b880a72563abcd3f35092bc33409fb7f88f2472be":"3925c71b362d40a0a6de42145579ba1e7dd459fc":"3afd9c6600147b21798d818c655a0f4c9212db26d0b0dfdc2a7594ccb3d22f5bf1d7c3e112cd73fc7d509c7a8bafdd3c274d1399009f9609ec4be6477e453f075aa33db382870c1c3409aef392d7386ae3a696b99a94b4da0589447e955d16c98b17602a59bd736279fcd8fb280c4462d590bfa9bf13fed570eafde97330a2c210":0
 
 RSAES-OAEP Decryption Example 9_1
-pkcs1_rsaes_oaep_decrypt:1536:16:"fc8d6c04bec4eb9a8192ca7900cbe536e2e8b519decf33b2459798c6909df4f176db7d23190fc72b8865a718af895f1bcd9145298027423b605e70a47cf58390a8c3e88fc8c48e8b32e3da210dfbe3e881ea5674b6a348c21e93f9e55ea65efd":16:"d200d45e788aacea606a401d0460f87dd5c1027e12dc1a0d7586e8939d9cf789b40f51ac0442961de7d21cc21e05c83155c1f2aa9193387cfdf956cb48d153ba270406f9bbba537d4987d9e2f9942d7a14cbfffea74fecdda928d23e259f5ee1":16:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":16:"010001":MBEDTLS_MD_SHA1:"f735fd55ba92592c3b52b8f9c4f69aaa1cbef8fe88add095595412467f9cf4ec0b896c59eda16210e7549c8abb10cdbc21a12ec9b6b5b8fd2f10399eb6":"8ec965f134a3ec9931e92a1ca0dc8169d5ea705c":"267bcd118acab1fc8ba81c85d73003cb8610fa55c1d97da8d48a7c7f06896a4db751aa284255b9d36ad65f37653d829f1b37f97b8001942545b2fc2c55a7376ca7a1be4b1760c8e05a33e5aa2526b8d98e317088e7834c755b2a59b12631a182c05d5d43ab1779264f8456f515ce57dfdf512d5493dab7b7338dc4b7d78db9c091ac3baf537a69fc7f549d979f0eff9a94fda4169bd4d1d19a69c99e33c3b55490d501b39b1edae118ff6793a153261584d3a5f39f6e682e3d17c8cd1261fa72":0
+pkcs1_rsaes_oaep_decrypt:1536:"fc8d6c04bec4eb9a8192ca7900cbe536e2e8b519decf33b2459798c6909df4f176db7d23190fc72b8865a718af895f1bcd9145298027423b605e70a47cf58390a8c3e88fc8c48e8b32e3da210dfbe3e881ea5674b6a348c21e93f9e55ea65efd":"d200d45e788aacea606a401d0460f87dd5c1027e12dc1a0d7586e8939d9cf789b40f51ac0442961de7d21cc21e05c83155c1f2aa9193387cfdf956cb48d153ba270406f9bbba537d4987d9e2f9942d7a14cbfffea74fecdda928d23e259f5ee1":"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":"010001":MBEDTLS_MD_SHA1:"f735fd55ba92592c3b52b8f9c4f69aaa1cbef8fe88add095595412467f9cf4ec0b896c59eda16210e7549c8abb10cdbc21a12ec9b6b5b8fd2f10399eb6":"8ec965f134a3ec9931e92a1ca0dc8169d5ea705c":"267bcd118acab1fc8ba81c85d73003cb8610fa55c1d97da8d48a7c7f06896a4db751aa284255b9d36ad65f37653d829f1b37f97b8001942545b2fc2c55a7376ca7a1be4b1760c8e05a33e5aa2526b8d98e317088e7834c755b2a59b12631a182c05d5d43ab1779264f8456f515ce57dfdf512d5493dab7b7338dc4b7d78db9c091ac3baf537a69fc7f549d979f0eff9a94fda4169bd4d1d19a69c99e33c3b55490d501b39b1edae118ff6793a153261584d3a5f39f6e682e3d17c8cd1261fa72":0
 
 RSAES-OAEP Decryption Example 9_2
-pkcs1_rsaes_oaep_decrypt:1536:16:"fc8d6c04bec4eb9a8192ca7900cbe536e2e8b519decf33b2459798c6909df4f176db7d23190fc72b8865a718af895f1bcd9145298027423b605e70a47cf58390a8c3e88fc8c48e8b32e3da210dfbe3e881ea5674b6a348c21e93f9e55ea65efd":16:"d200d45e788aacea606a401d0460f87dd5c1027e12dc1a0d7586e8939d9cf789b40f51ac0442961de7d21cc21e05c83155c1f2aa9193387cfdf956cb48d153ba270406f9bbba537d4987d9e2f9942d7a14cbfffea74fecdda928d23e259f5ee1":16:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":16:"010001":MBEDTLS_MD_SHA1:"81b906605015a63aabe42ddf11e1978912f5404c7474b26dce3ed482bf961ecc818bf420c54659":"ecb1b8b25fa50cdab08e56042867f4af5826d16c":"93ac9f0671ec29acbb444effc1a5741351d60fdb0e393fbf754acf0de49761a14841df7772e9bc82773966a1584c4d72baea00118f83f35cca6e537cbd4d811f5583b29783d8a6d94cd31be70d6f526c10ff09c6fa7ce069795a3fcd0511fd5fcb564bcc80ea9c78f38b80012539d8a4ddf6fe81e9cddb7f50dbbbbcc7e5d86097ccf4ec49189fb8bf318be6d5a0715d516b49af191258cd32dc833ce6eb4673c03a19bbace88cc54895f636cc0c1ec89096d11ce235a265ca1764232a689ae8":0
+pkcs1_rsaes_oaep_decrypt:1536:"fc8d6c04bec4eb9a8192ca7900cbe536e2e8b519decf33b2459798c6909df4f176db7d23190fc72b8865a718af895f1bcd9145298027423b605e70a47cf58390a8c3e88fc8c48e8b32e3da210dfbe3e881ea5674b6a348c21e93f9e55ea65efd":"d200d45e788aacea606a401d0460f87dd5c1027e12dc1a0d7586e8939d9cf789b40f51ac0442961de7d21cc21e05c83155c1f2aa9193387cfdf956cb48d153ba270406f9bbba537d4987d9e2f9942d7a14cbfffea74fecdda928d23e259f5ee1":"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":"010001":MBEDTLS_MD_SHA1:"81b906605015a63aabe42ddf11e1978912f5404c7474b26dce3ed482bf961ecc818bf420c54659":"ecb1b8b25fa50cdab08e56042867f4af5826d16c":"93ac9f0671ec29acbb444effc1a5741351d60fdb0e393fbf754acf0de49761a14841df7772e9bc82773966a1584c4d72baea00118f83f35cca6e537cbd4d811f5583b29783d8a6d94cd31be70d6f526c10ff09c6fa7ce069795a3fcd0511fd5fcb564bcc80ea9c78f38b80012539d8a4ddf6fe81e9cddb7f50dbbbbcc7e5d86097ccf4ec49189fb8bf318be6d5a0715d516b49af191258cd32dc833ce6eb4673c03a19bbace88cc54895f636cc0c1ec89096d11ce235a265ca1764232a689ae8":0
 
 RSAES-OAEP Decryption Example 9_3
-pkcs1_rsaes_oaep_decrypt:1536:16:"fc8d6c04bec4eb9a8192ca7900cbe536e2e8b519decf33b2459798c6909df4f176db7d23190fc72b8865a718af895f1bcd9145298027423b605e70a47cf58390a8c3e88fc8c48e8b32e3da210dfbe3e881ea5674b6a348c21e93f9e55ea65efd":16:"d200d45e788aacea606a401d0460f87dd5c1027e12dc1a0d7586e8939d9cf789b40f51ac0442961de7d21cc21e05c83155c1f2aa9193387cfdf956cb48d153ba270406f9bbba537d4987d9e2f9942d7a14cbfffea74fecdda928d23e259f5ee1":16:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":16:"010001":MBEDTLS_MD_SHA1:"fd326429df9b890e09b54b18b8f34f1e24":"e89bb032c6ce622cbdb53bc9466014ea77f777c0":"81ebdd95054b0c822ef9ad7693f5a87adfb4b4c4ce70df2df84ed49c04da58ba5fc20a19e1a6e8b7a3900b22796dc4e869ee6b42792d15a8eceb56c09c69914e813cea8f6931e4b8ed6f421af298d595c97f4789c7caa612c7ef360984c21b93edc5401068b5af4c78a8771b984d53b8ea8adf2f6a7d4a0ba76c75e1dd9f658f20ded4a46071d46d7791b56803d8fea7f0b0f8e41ae3f09383a6f9585fe7753eaaffd2bf94563108beecc207bbb535f5fcc705f0dde9f708c62f49a9c90371d3":0
+pkcs1_rsaes_oaep_decrypt:1536:"fc8d6c04bec4eb9a8192ca7900cbe536e2e8b519decf33b2459798c6909df4f176db7d23190fc72b8865a718af895f1bcd9145298027423b605e70a47cf58390a8c3e88fc8c48e8b32e3da210dfbe3e881ea5674b6a348c21e93f9e55ea65efd":"d200d45e788aacea606a401d0460f87dd5c1027e12dc1a0d7586e8939d9cf789b40f51ac0442961de7d21cc21e05c83155c1f2aa9193387cfdf956cb48d153ba270406f9bbba537d4987d9e2f9942d7a14cbfffea74fecdda928d23e259f5ee1":"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":"010001":MBEDTLS_MD_SHA1:"fd326429df9b890e09b54b18b8f34f1e24":"e89bb032c6ce622cbdb53bc9466014ea77f777c0":"81ebdd95054b0c822ef9ad7693f5a87adfb4b4c4ce70df2df84ed49c04da58ba5fc20a19e1a6e8b7a3900b22796dc4e869ee6b42792d15a8eceb56c09c69914e813cea8f6931e4b8ed6f421af298d595c97f4789c7caa612c7ef360984c21b93edc5401068b5af4c78a8771b984d53b8ea8adf2f6a7d4a0ba76c75e1dd9f658f20ded4a46071d46d7791b56803d8fea7f0b0f8e41ae3f09383a6f9585fe7753eaaffd2bf94563108beecc207bbb535f5fcc705f0dde9f708c62f49a9c90371d3":0
 
 RSAES-OAEP Decryption Example 9_4
-pkcs1_rsaes_oaep_decrypt:1536:16:"fc8d6c04bec4eb9a8192ca7900cbe536e2e8b519decf33b2459798c6909df4f176db7d23190fc72b8865a718af895f1bcd9145298027423b605e70a47cf58390a8c3e88fc8c48e8b32e3da210dfbe3e881ea5674b6a348c21e93f9e55ea65efd":16:"d200d45e788aacea606a401d0460f87dd5c1027e12dc1a0d7586e8939d9cf789b40f51ac0442961de7d21cc21e05c83155c1f2aa9193387cfdf956cb48d153ba270406f9bbba537d4987d9e2f9942d7a14cbfffea74fecdda928d23e259f5ee1":16:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":16:"010001":MBEDTLS_MD_SHA1:"f1459b5f0c92f01a0f723a2e5662484d8f8c0a20fc29dad6acd43bb5f3effdf4e1b63e07fdfe6628d0d74ca19bf2d69e4a0abf86d293925a796772f8088e":"606f3b99c0b9ccd771eaa29ea0e4c884f3189ccc":"bcc35f94cde66cb1136625d625b94432a35b22f3d2fa11a613ff0fca5bd57f87b902ccdc1cd0aebcb0715ee869d1d1fe395f6793003f5eca465059c88660d446ff5f0818552022557e38c08a67ead991262254f10682975ec56397768537f4977af6d5f6aaceb7fb25dec5937230231fd8978af49119a29f29e424ab8272b47562792d5c94f774b8829d0b0d9f1a8c9eddf37574d5fa248eefa9c5271fc5ec2579c81bdd61b410fa61fe36e424221c113addb275664c801d34ca8c6351e4a858":0
+pkcs1_rsaes_oaep_decrypt:1536:"fc8d6c04bec4eb9a8192ca7900cbe536e2e8b519decf33b2459798c6909df4f176db7d23190fc72b8865a718af895f1bcd9145298027423b605e70a47cf58390a8c3e88fc8c48e8b32e3da210dfbe3e881ea5674b6a348c21e93f9e55ea65efd":"d200d45e788aacea606a401d0460f87dd5c1027e12dc1a0d7586e8939d9cf789b40f51ac0442961de7d21cc21e05c83155c1f2aa9193387cfdf956cb48d153ba270406f9bbba537d4987d9e2f9942d7a14cbfffea74fecdda928d23e259f5ee1":"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":"010001":MBEDTLS_MD_SHA1:"f1459b5f0c92f01a0f723a2e5662484d8f8c0a20fc29dad6acd43bb5f3effdf4e1b63e07fdfe6628d0d74ca19bf2d69e4a0abf86d293925a796772f8088e":"606f3b99c0b9ccd771eaa29ea0e4c884f3189ccc":"bcc35f94cde66cb1136625d625b94432a35b22f3d2fa11a613ff0fca5bd57f87b902ccdc1cd0aebcb0715ee869d1d1fe395f6793003f5eca465059c88660d446ff5f0818552022557e38c08a67ead991262254f10682975ec56397768537f4977af6d5f6aaceb7fb25dec5937230231fd8978af49119a29f29e424ab8272b47562792d5c94f774b8829d0b0d9f1a8c9eddf37574d5fa248eefa9c5271fc5ec2579c81bdd61b410fa61fe36e424221c113addb275664c801d34ca8c6351e4a858":0
 
 RSAES-OAEP Decryption Example 9_5
-pkcs1_rsaes_oaep_decrypt:1536:16:"fc8d6c04bec4eb9a8192ca7900cbe536e2e8b519decf33b2459798c6909df4f176db7d23190fc72b8865a718af895f1bcd9145298027423b605e70a47cf58390a8c3e88fc8c48e8b32e3da210dfbe3e881ea5674b6a348c21e93f9e55ea65efd":16:"d200d45e788aacea606a401d0460f87dd5c1027e12dc1a0d7586e8939d9cf789b40f51ac0442961de7d21cc21e05c83155c1f2aa9193387cfdf956cb48d153ba270406f9bbba537d4987d9e2f9942d7a14cbfffea74fecdda928d23e259f5ee1":16:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":16:"010001":MBEDTLS_MD_SHA1:"53e6e8c729d6f9c319dd317e74b0db8e4ccca25f3c8305746e137ac63a63ef3739e7b595abb96e8d55e54f7bd41ab433378ffb911d":"fcbc421402e9ecabc6082afa40ba5f26522c840e":"232afbc927fa08c2f6a27b87d4a5cb09c07dc26fae73d73a90558839f4fd66d281b87ec734bce237ba166698ed829106a7de6942cd6cdce78fed8d2e4d81428e66490d036264cef92af941d3e35055fe3981e14d29cbb9a4f67473063baec79a1179f5a17c9c1832f2838fd7d5e59bb9659d56dce8a019edef1bb3accc697cc6cc7a778f60a064c7f6f5d529c6210262e003de583e81e3167b89971fb8c0e15d44fffef89b53d8d64dd797d159b56d2b08ea5307ea12c241bd58d4ee278a1f2e":0
+pkcs1_rsaes_oaep_decrypt:1536:"fc8d6c04bec4eb9a8192ca7900cbe536e2e8b519decf33b2459798c6909df4f176db7d23190fc72b8865a718af895f1bcd9145298027423b605e70a47cf58390a8c3e88fc8c48e8b32e3da210dfbe3e881ea5674b6a348c21e93f9e55ea65efd":"d200d45e788aacea606a401d0460f87dd5c1027e12dc1a0d7586e8939d9cf789b40f51ac0442961de7d21cc21e05c83155c1f2aa9193387cfdf956cb48d153ba270406f9bbba537d4987d9e2f9942d7a14cbfffea74fecdda928d23e259f5ee1":"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":"010001":MBEDTLS_MD_SHA1:"53e6e8c729d6f9c319dd317e74b0db8e4ccca25f3c8305746e137ac63a63ef3739e7b595abb96e8d55e54f7bd41ab433378ffb911d":"fcbc421402e9ecabc6082afa40ba5f26522c840e":"232afbc927fa08c2f6a27b87d4a5cb09c07dc26fae73d73a90558839f4fd66d281b87ec734bce237ba166698ed829106a7de6942cd6cdce78fed8d2e4d81428e66490d036264cef92af941d3e35055fe3981e14d29cbb9a4f67473063baec79a1179f5a17c9c1832f2838fd7d5e59bb9659d56dce8a019edef1bb3accc697cc6cc7a778f60a064c7f6f5d529c6210262e003de583e81e3167b89971fb8c0e15d44fffef89b53d8d64dd797d159b56d2b08ea5307ea12c241bd58d4ee278a1f2e":0
 
 RSAES-OAEP Decryption Example 9_6
-pkcs1_rsaes_oaep_decrypt:1536:16:"fc8d6c04bec4eb9a8192ca7900cbe536e2e8b519decf33b2459798c6909df4f176db7d23190fc72b8865a718af895f1bcd9145298027423b605e70a47cf58390a8c3e88fc8c48e8b32e3da210dfbe3e881ea5674b6a348c21e93f9e55ea65efd":16:"d200d45e788aacea606a401d0460f87dd5c1027e12dc1a0d7586e8939d9cf789b40f51ac0442961de7d21cc21e05c83155c1f2aa9193387cfdf956cb48d153ba270406f9bbba537d4987d9e2f9942d7a14cbfffea74fecdda928d23e259f5ee1":16:"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":16:"010001":MBEDTLS_MD_SHA1:"b6b28ea2198d0c1008bc64":"23aade0e1e08bb9b9a78d2302a52f9c21b2e1ba2":"438cc7dc08a68da249e42505f8573ba60e2c2773d5b290f4cf9dff718e842081c383e67024a0f29594ea987b9d25e4b738f285970d195abb3a8c8054e3d79d6b9c9a8327ba596f1259e27126674766907d8d582ff3a8476154929adb1e6d1235b2ccb4ec8f663ba9cc670a92bebd853c8dbf69c6436d016f61add836e94732450434207f9fd4c43dec2a12a958efa01efe2669899b5e604c255c55fb7166de5589e369597bb09168c06dd5db177e06a1740eb2d5c82faeca6d92fcee9931ba9f":0
+pkcs1_rsaes_oaep_decrypt:1536:"fc8d6c04bec4eb9a8192ca7900cbe536e2e8b519decf33b2459798c6909df4f176db7d23190fc72b8865a718af895f1bcd9145298027423b605e70a47cf58390a8c3e88fc8c48e8b32e3da210dfbe3e881ea5674b6a348c21e93f9e55ea65efd":"d200d45e788aacea606a401d0460f87dd5c1027e12dc1a0d7586e8939d9cf789b40f51ac0442961de7d21cc21e05c83155c1f2aa9193387cfdf956cb48d153ba270406f9bbba537d4987d9e2f9942d7a14cbfffea74fecdda928d23e259f5ee1":"cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d":"010001":MBEDTLS_MD_SHA1:"b6b28ea2198d0c1008bc64":"23aade0e1e08bb9b9a78d2302a52f9c21b2e1ba2":"438cc7dc08a68da249e42505f8573ba60e2c2773d5b290f4cf9dff718e842081c383e67024a0f29594ea987b9d25e4b738f285970d195abb3a8c8054e3d79d6b9c9a8327ba596f1259e27126674766907d8d582ff3a8476154929adb1e6d1235b2ccb4ec8f663ba9cc670a92bebd853c8dbf69c6436d016f61add836e94732450434207f9fd4c43dec2a12a958efa01efe2669899b5e604c255c55fb7166de5589e369597bb09168c06dd5db177e06a1740eb2d5c82faeca6d92fcee9931ba9f":0
 
 RSAES-OAEP Decryption Example 10_1
-pkcs1_rsaes_oaep_decrypt:2048:16:"ecf5aecd1e5515fffacbd75a2816c6ebf49018cdfb4638e185d66a7396b6f8090f8018c7fd95cc34b857dc17f0cc6516bb1346ab4d582cadad7b4103352387b70338d084047c9d9539b6496204b3dd6ea442499207bec01f964287ff6336c3984658336846f56e46861881c10233d2176bf15a5e96ddc780bc868aa77d3ce769":16:"bc46c464fc6ac4ca783b0eb08a3c841b772f7e9b2f28babd588ae885e1a0c61e4858a0fb25ac299990f35be85164c259ba1175cdd7192707135184992b6c29b746dd0d2cabe142835f7d148cc161524b4a09946d48b828473f1ce76b6cb6886c345c03e05f41d51b5c3a90a3f24073c7d74a4fe25d9cf21c75960f3fc3863183":16:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":16:"010001":MBEDTLS_MD_SHA1:"8bba6bf82a6c0f86d5f1756e97956870b08953b06b4eb205bc1694ee":"47e1ab7119fee56c95ee5eaad86f40d0aa63bd33":"53ea5dc08cd260fb3b858567287fa91552c30b2febfba213f0ae87702d068d19bab07fe574523dfb42139d68c3c5afeee0bfe4cb7969cbf382b804d6e61396144e2d0e60741f8993c3014b58b9b1957a8babcd23af854f4c356fb1662aa72bfcc7e586559dc4280d160c126785a723ebeebeff71f11594440aaef87d10793a8774a239d4a04c87fe1467b9daf85208ec6c7255794a96cc29142f9a8bd418e3c1fd67344b0cd0829df3b2bec60253196293c6b34d3f75d32f213dd45c6273d505adf4cced1057cb758fc26aeefa441255ed4e64c199ee075e7f16646182fdb464739b68ab5daff0e63e9552016824f054bf4d3c8c90a97bb6b6553284eb429fcc":0
+pkcs1_rsaes_oaep_decrypt:2048:"ecf5aecd1e5515fffacbd75a2816c6ebf49018cdfb4638e185d66a7396b6f8090f8018c7fd95cc34b857dc17f0cc6516bb1346ab4d582cadad7b4103352387b70338d084047c9d9539b6496204b3dd6ea442499207bec01f964287ff6336c3984658336846f56e46861881c10233d2176bf15a5e96ddc780bc868aa77d3ce769":"bc46c464fc6ac4ca783b0eb08a3c841b772f7e9b2f28babd588ae885e1a0c61e4858a0fb25ac299990f35be85164c259ba1175cdd7192707135184992b6c29b746dd0d2cabe142835f7d148cc161524b4a09946d48b828473f1ce76b6cb6886c345c03e05f41d51b5c3a90a3f24073c7d74a4fe25d9cf21c75960f3fc3863183":"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":"010001":MBEDTLS_MD_SHA1:"8bba6bf82a6c0f86d5f1756e97956870b08953b06b4eb205bc1694ee":"47e1ab7119fee56c95ee5eaad86f40d0aa63bd33":"53ea5dc08cd260fb3b858567287fa91552c30b2febfba213f0ae87702d068d19bab07fe574523dfb42139d68c3c5afeee0bfe4cb7969cbf382b804d6e61396144e2d0e60741f8993c3014b58b9b1957a8babcd23af854f4c356fb1662aa72bfcc7e586559dc4280d160c126785a723ebeebeff71f11594440aaef87d10793a8774a239d4a04c87fe1467b9daf85208ec6c7255794a96cc29142f9a8bd418e3c1fd67344b0cd0829df3b2bec60253196293c6b34d3f75d32f213dd45c6273d505adf4cced1057cb758fc26aeefa441255ed4e64c199ee075e7f16646182fdb464739b68ab5daff0e63e9552016824f054bf4d3c8c90a97bb6b6553284eb429fcc":0
 
 RSAES-OAEP Decryption Example 10_2
-pkcs1_rsaes_oaep_decrypt:2048:16:"ecf5aecd1e5515fffacbd75a2816c6ebf49018cdfb4638e185d66a7396b6f8090f8018c7fd95cc34b857dc17f0cc6516bb1346ab4d582cadad7b4103352387b70338d084047c9d9539b6496204b3dd6ea442499207bec01f964287ff6336c3984658336846f56e46861881c10233d2176bf15a5e96ddc780bc868aa77d3ce769":16:"bc46c464fc6ac4ca783b0eb08a3c841b772f7e9b2f28babd588ae885e1a0c61e4858a0fb25ac299990f35be85164c259ba1175cdd7192707135184992b6c29b746dd0d2cabe142835f7d148cc161524b4a09946d48b828473f1ce76b6cb6886c345c03e05f41d51b5c3a90a3f24073c7d74a4fe25d9cf21c75960f3fc3863183":16:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":16:"010001":MBEDTLS_MD_SHA1:"e6ad181f053b58a904f2457510373e57":"6d17f5b4c1ffac351d195bf7b09d09f09a4079cf":"a2b1a430a9d657e2fa1c2bb5ed43ffb25c05a308fe9093c01031795f5874400110828ae58fb9b581ce9dddd3e549ae04a0985459bde6c626594e7b05dc4278b2a1465c1368408823c85e96dc66c3a30983c639664fc4569a37fe21e5a195b5776eed2df8d8d361af686e750229bbd663f161868a50615e0c337bec0ca35fec0bb19c36eb2e0bbcc0582fa1d93aacdb061063f59f2ce1ee43605e5d89eca183d2acdfe9f81011022ad3b43a3dd417dac94b4e11ea81b192966e966b182082e71964607b4f8002f36299844a11f2ae0faeac2eae70f8f4f98088acdcd0ac556e9fccc511521908fad26f04c64201450305778758b0538bf8b5bb144a828e629795":0
+pkcs1_rsaes_oaep_decrypt:2048:"ecf5aecd1e5515fffacbd75a2816c6ebf49018cdfb4638e185d66a7396b6f8090f8018c7fd95cc34b857dc17f0cc6516bb1346ab4d582cadad7b4103352387b70338d084047c9d9539b6496204b3dd6ea442499207bec01f964287ff6336c3984658336846f56e46861881c10233d2176bf15a5e96ddc780bc868aa77d3ce769":"bc46c464fc6ac4ca783b0eb08a3c841b772f7e9b2f28babd588ae885e1a0c61e4858a0fb25ac299990f35be85164c259ba1175cdd7192707135184992b6c29b746dd0d2cabe142835f7d148cc161524b4a09946d48b828473f1ce76b6cb6886c345c03e05f41d51b5c3a90a3f24073c7d74a4fe25d9cf21c75960f3fc3863183":"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":"010001":MBEDTLS_MD_SHA1:"e6ad181f053b58a904f2457510373e57":"6d17f5b4c1ffac351d195bf7b09d09f09a4079cf":"a2b1a430a9d657e2fa1c2bb5ed43ffb25c05a308fe9093c01031795f5874400110828ae58fb9b581ce9dddd3e549ae04a0985459bde6c626594e7b05dc4278b2a1465c1368408823c85e96dc66c3a30983c639664fc4569a37fe21e5a195b5776eed2df8d8d361af686e750229bbd663f161868a50615e0c337bec0ca35fec0bb19c36eb2e0bbcc0582fa1d93aacdb061063f59f2ce1ee43605e5d89eca183d2acdfe9f81011022ad3b43a3dd417dac94b4e11ea81b192966e966b182082e71964607b4f8002f36299844a11f2ae0faeac2eae70f8f4f98088acdcd0ac556e9fccc511521908fad26f04c64201450305778758b0538bf8b5bb144a828e629795":0
 
 RSAES-OAEP Decryption Example 10_3
-pkcs1_rsaes_oaep_decrypt:2048:16:"ecf5aecd1e5515fffacbd75a2816c6ebf49018cdfb4638e185d66a7396b6f8090f8018c7fd95cc34b857dc17f0cc6516bb1346ab4d582cadad7b4103352387b70338d084047c9d9539b6496204b3dd6ea442499207bec01f964287ff6336c3984658336846f56e46861881c10233d2176bf15a5e96ddc780bc868aa77d3ce769":16:"bc46c464fc6ac4ca783b0eb08a3c841b772f7e9b2f28babd588ae885e1a0c61e4858a0fb25ac299990f35be85164c259ba1175cdd7192707135184992b6c29b746dd0d2cabe142835f7d148cc161524b4a09946d48b828473f1ce76b6cb6886c345c03e05f41d51b5c3a90a3f24073c7d74a4fe25d9cf21c75960f3fc3863183":16:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":16:"010001":MBEDTLS_MD_SHA1:"510a2cf60e866fa2340553c94ea39fbc256311e83e94454b4124":"385387514deccc7c740dd8cdf9daee49a1cbfd54":"9886c3e6764a8b9a84e84148ebd8c3b1aa8050381a78f668714c16d9cfd2a6edc56979c535d9dee3b44b85c18be8928992371711472216d95dda98d2ee8347c9b14dffdff84aa48d25ac06f7d7e65398ac967b1ce90925f67dce049b7f812db0742997a74d44fe81dbe0e7a3feaf2e5c40af888d550ddbbe3bc20657a29543f8fc2913b9bd1a61b2ab2256ec409bbd7dc0d17717ea25c43f42ed27df8738bf4afc6766ff7aff0859555ee283920f4c8a63c4a7340cbafddc339ecdb4b0515002f96c932b5b79167af699c0ad3fccfdf0f44e85a70262bf2e18fe34b850589975e867ff969d48eabf212271546cdc05a69ecb526e52870c836f307bd798780ede":0
+pkcs1_rsaes_oaep_decrypt:2048:"ecf5aecd1e5515fffacbd75a2816c6ebf49018cdfb4638e185d66a7396b6f8090f8018c7fd95cc34b857dc17f0cc6516bb1346ab4d582cadad7b4103352387b70338d084047c9d9539b6496204b3dd6ea442499207bec01f964287ff6336c3984658336846f56e46861881c10233d2176bf15a5e96ddc780bc868aa77d3ce769":"bc46c464fc6ac4ca783b0eb08a3c841b772f7e9b2f28babd588ae885e1a0c61e4858a0fb25ac299990f35be85164c259ba1175cdd7192707135184992b6c29b746dd0d2cabe142835f7d148cc161524b4a09946d48b828473f1ce76b6cb6886c345c03e05f41d51b5c3a90a3f24073c7d74a4fe25d9cf21c75960f3fc3863183":"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":"010001":MBEDTLS_MD_SHA1:"510a2cf60e866fa2340553c94ea39fbc256311e83e94454b4124":"385387514deccc7c740dd8cdf9daee49a1cbfd54":"9886c3e6764a8b9a84e84148ebd8c3b1aa8050381a78f668714c16d9cfd2a6edc56979c535d9dee3b44b85c18be8928992371711472216d95dda98d2ee8347c9b14dffdff84aa48d25ac06f7d7e65398ac967b1ce90925f67dce049b7f812db0742997a74d44fe81dbe0e7a3feaf2e5c40af888d550ddbbe3bc20657a29543f8fc2913b9bd1a61b2ab2256ec409bbd7dc0d17717ea25c43f42ed27df8738bf4afc6766ff7aff0859555ee283920f4c8a63c4a7340cbafddc339ecdb4b0515002f96c932b5b79167af699c0ad3fccfdf0f44e85a70262bf2e18fe34b850589975e867ff969d48eabf212271546cdc05a69ecb526e52870c836f307bd798780ede":0
 
 RSAES-OAEP Decryption Example 10_4
-pkcs1_rsaes_oaep_decrypt:2048:16:"ecf5aecd1e5515fffacbd75a2816c6ebf49018cdfb4638e185d66a7396b6f8090f8018c7fd95cc34b857dc17f0cc6516bb1346ab4d582cadad7b4103352387b70338d084047c9d9539b6496204b3dd6ea442499207bec01f964287ff6336c3984658336846f56e46861881c10233d2176bf15a5e96ddc780bc868aa77d3ce769":16:"bc46c464fc6ac4ca783b0eb08a3c841b772f7e9b2f28babd588ae885e1a0c61e4858a0fb25ac299990f35be85164c259ba1175cdd7192707135184992b6c29b746dd0d2cabe142835f7d148cc161524b4a09946d48b828473f1ce76b6cb6886c345c03e05f41d51b5c3a90a3f24073c7d74a4fe25d9cf21c75960f3fc3863183":16:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":16:"010001":MBEDTLS_MD_SHA1:"bcdd190da3b7d300df9a06e22caae2a75f10c91ff667b7c16bde8b53064a2649a94045c9":"5caca6a0f764161a9684f85d92b6e0ef37ca8b65":"6318e9fb5c0d05e5307e1683436e903293ac4642358aaa223d7163013aba87e2dfda8e60c6860e29a1e92686163ea0b9175f329ca3b131a1edd3a77759a8b97bad6a4f8f4396f28cf6f39ca58112e48160d6e203daa5856f3aca5ffed577af499408e3dfd233e3e604dbe34a9c4c9082de65527cac6331d29dc80e0508a0fa7122e7f329f6cca5cfa34d4d1da417805457e008bec549e478ff9e12a763c477d15bbb78f5b69bd57830fc2c4ed686d79bc72a95d85f88134c6b0afe56a8ccfbc855828bb339bd17909cf1d70de3335ae07039093e606d655365de6550b872cd6de1d440ee031b61945f629ad8a353b0d40939e96a3c450d2a8d5eee9f678093c8":0
+pkcs1_rsaes_oaep_decrypt:2048:"ecf5aecd1e5515fffacbd75a2816c6ebf49018cdfb4638e185d66a7396b6f8090f8018c7fd95cc34b857dc17f0cc6516bb1346ab4d582cadad7b4103352387b70338d084047c9d9539b6496204b3dd6ea442499207bec01f964287ff6336c3984658336846f56e46861881c10233d2176bf15a5e96ddc780bc868aa77d3ce769":"bc46c464fc6ac4ca783b0eb08a3c841b772f7e9b2f28babd588ae885e1a0c61e4858a0fb25ac299990f35be85164c259ba1175cdd7192707135184992b6c29b746dd0d2cabe142835f7d148cc161524b4a09946d48b828473f1ce76b6cb6886c345c03e05f41d51b5c3a90a3f24073c7d74a4fe25d9cf21c75960f3fc3863183":"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":"010001":MBEDTLS_MD_SHA1:"bcdd190da3b7d300df9a06e22caae2a75f10c91ff667b7c16bde8b53064a2649a94045c9":"5caca6a0f764161a9684f85d92b6e0ef37ca8b65":"6318e9fb5c0d05e5307e1683436e903293ac4642358aaa223d7163013aba87e2dfda8e60c6860e29a1e92686163ea0b9175f329ca3b131a1edd3a77759a8b97bad6a4f8f4396f28cf6f39ca58112e48160d6e203daa5856f3aca5ffed577af499408e3dfd233e3e604dbe34a9c4c9082de65527cac6331d29dc80e0508a0fa7122e7f329f6cca5cfa34d4d1da417805457e008bec549e478ff9e12a763c477d15bbb78f5b69bd57830fc2c4ed686d79bc72a95d85f88134c6b0afe56a8ccfbc855828bb339bd17909cf1d70de3335ae07039093e606d655365de6550b872cd6de1d440ee031b61945f629ad8a353b0d40939e96a3c450d2a8d5eee9f678093c8":0
 
 RSAES-OAEP Decryption Example 10_5
-pkcs1_rsaes_oaep_decrypt:2048:16:"ecf5aecd1e5515fffacbd75a2816c6ebf49018cdfb4638e185d66a7396b6f8090f8018c7fd95cc34b857dc17f0cc6516bb1346ab4d582cadad7b4103352387b70338d084047c9d9539b6496204b3dd6ea442499207bec01f964287ff6336c3984658336846f56e46861881c10233d2176bf15a5e96ddc780bc868aa77d3ce769":16:"bc46c464fc6ac4ca783b0eb08a3c841b772f7e9b2f28babd588ae885e1a0c61e4858a0fb25ac299990f35be85164c259ba1175cdd7192707135184992b6c29b746dd0d2cabe142835f7d148cc161524b4a09946d48b828473f1ce76b6cb6886c345c03e05f41d51b5c3a90a3f24073c7d74a4fe25d9cf21c75960f3fc3863183":16:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":16:"010001":MBEDTLS_MD_SHA1:"a7dd6c7dc24b46f9dd5f1e91ada4c3b3df947e877232a9":"95bca9e3859894b3dd869fa7ecd5bbc6401bf3e4":"75290872ccfd4a4505660d651f56da6daa09ca1301d890632f6a992f3d565cee464afded40ed3b5be9356714ea5aa7655f4a1366c2f17c728f6f2c5a5d1f8e28429bc4e6f8f2cff8da8dc0e0a9808e45fd09ea2fa40cb2b6ce6ffff5c0e159d11b68d90a85f7b84e103b09e682666480c657505c0929259468a314786d74eab131573cf234bf57db7d9e66cc6748192e002dc0deea930585f0831fdcd9bc33d51f79ed2ffc16bcf4d59812fcebcaa3f9069b0e445686d644c25ccf63b456ee5fa6ffe96f19cdf751fed9eaf35957754dbf4bfea5216aa1844dc507cb2d080e722eba150308c2b5ff1193620f1766ecf4481bafb943bd292877f2136ca494aba0":0
+pkcs1_rsaes_oaep_decrypt:2048:"ecf5aecd1e5515fffacbd75a2816c6ebf49018cdfb4638e185d66a7396b6f8090f8018c7fd95cc34b857dc17f0cc6516bb1346ab4d582cadad7b4103352387b70338d084047c9d9539b6496204b3dd6ea442499207bec01f964287ff6336c3984658336846f56e46861881c10233d2176bf15a5e96ddc780bc868aa77d3ce769":"bc46c464fc6ac4ca783b0eb08a3c841b772f7e9b2f28babd588ae885e1a0c61e4858a0fb25ac299990f35be85164c259ba1175cdd7192707135184992b6c29b746dd0d2cabe142835f7d148cc161524b4a09946d48b828473f1ce76b6cb6886c345c03e05f41d51b5c3a90a3f24073c7d74a4fe25d9cf21c75960f3fc3863183":"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":"010001":MBEDTLS_MD_SHA1:"a7dd6c7dc24b46f9dd5f1e91ada4c3b3df947e877232a9":"95bca9e3859894b3dd869fa7ecd5bbc6401bf3e4":"75290872ccfd4a4505660d651f56da6daa09ca1301d890632f6a992f3d565cee464afded40ed3b5be9356714ea5aa7655f4a1366c2f17c728f6f2c5a5d1f8e28429bc4e6f8f2cff8da8dc0e0a9808e45fd09ea2fa40cb2b6ce6ffff5c0e159d11b68d90a85f7b84e103b09e682666480c657505c0929259468a314786d74eab131573cf234bf57db7d9e66cc6748192e002dc0deea930585f0831fdcd9bc33d51f79ed2ffc16bcf4d59812fcebcaa3f9069b0e445686d644c25ccf63b456ee5fa6ffe96f19cdf751fed9eaf35957754dbf4bfea5216aa1844dc507cb2d080e722eba150308c2b5ff1193620f1766ecf4481bafb943bd292877f2136ca494aba0":0
 
 RSAES-OAEP Decryption Example 10_6
-pkcs1_rsaes_oaep_decrypt:2048:16:"ecf5aecd1e5515fffacbd75a2816c6ebf49018cdfb4638e185d66a7396b6f8090f8018c7fd95cc34b857dc17f0cc6516bb1346ab4d582cadad7b4103352387b70338d084047c9d9539b6496204b3dd6ea442499207bec01f964287ff6336c3984658336846f56e46861881c10233d2176bf15a5e96ddc780bc868aa77d3ce769":16:"bc46c464fc6ac4ca783b0eb08a3c841b772f7e9b2f28babd588ae885e1a0c61e4858a0fb25ac299990f35be85164c259ba1175cdd7192707135184992b6c29b746dd0d2cabe142835f7d148cc161524b4a09946d48b828473f1ce76b6cb6886c345c03e05f41d51b5c3a90a3f24073c7d74a4fe25d9cf21c75960f3fc3863183":16:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":16:"010001":MBEDTLS_MD_SHA1:"eaf1a73a1b0c4609537de69cd9228bbcfb9a8ca8c6c3efaf056fe4a7f4634ed00b7c39ec6922d7b8ea2c04ebac":"9f47ddf42e97eea856a9bdbc714eb3ac22f6eb32":"2d207a73432a8fb4c03051b3f73b28a61764098dfa34c47a20995f8115aa6816679b557e82dbee584908c6e69782d7deb34dbd65af063d57fca76a5fd069492fd6068d9984d209350565a62e5c77f23038c12cb10c6634709b547c46f6b4a709bd85ca122d74465ef97762c29763e06dbc7a9e738c78bfca0102dc5e79d65b973f28240caab2e161a78b57d262457ed8195d53e3c7ae9da021883c6db7c24afdd2322eac972ad3c354c5fcef1e146c3a0290fb67adf007066e00428d2cec18ce58f9328698defef4b2eb5ec76918fde1c198cbb38b7afc67626a9aefec4322bfd90d2563481c9a221f78c8272c82d1b62ab914e1c69f6af6ef30ca5260db4a46":0
+pkcs1_rsaes_oaep_decrypt:2048:"ecf5aecd1e5515fffacbd75a2816c6ebf49018cdfb4638e185d66a7396b6f8090f8018c7fd95cc34b857dc17f0cc6516bb1346ab4d582cadad7b4103352387b70338d084047c9d9539b6496204b3dd6ea442499207bec01f964287ff6336c3984658336846f56e46861881c10233d2176bf15a5e96ddc780bc868aa77d3ce769":"bc46c464fc6ac4ca783b0eb08a3c841b772f7e9b2f28babd588ae885e1a0c61e4858a0fb25ac299990f35be85164c259ba1175cdd7192707135184992b6c29b746dd0d2cabe142835f7d148cc161524b4a09946d48b828473f1ce76b6cb6886c345c03e05f41d51b5c3a90a3f24073c7d74a4fe25d9cf21c75960f3fc3863183":"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":"010001":MBEDTLS_MD_SHA1:"eaf1a73a1b0c4609537de69cd9228bbcfb9a8ca8c6c3efaf056fe4a7f4634ed00b7c39ec6922d7b8ea2c04ebac":"9f47ddf42e97eea856a9bdbc714eb3ac22f6eb32":"2d207a73432a8fb4c03051b3f73b28a61764098dfa34c47a20995f8115aa6816679b557e82dbee584908c6e69782d7deb34dbd65af063d57fca76a5fd069492fd6068d9984d209350565a62e5c77f23038c12cb10c6634709b547c46f6b4a709bd85ca122d74465ef97762c29763e06dbc7a9e738c78bfca0102dc5e79d65b973f28240caab2e161a78b57d262457ed8195d53e3c7ae9da021883c6db7c24afdd2322eac972ad3c354c5fcef1e146c3a0290fb67adf007066e00428d2cec18ce58f9328698defef4b2eb5ec76918fde1c198cbb38b7afc67626a9aefec4322bfd90d2563481c9a221f78c8272c82d1b62ab914e1c69f6af6ef30ca5260db4a46":0
 
 RSAES-OAEP Decryption empty output with NULL buffer
 depends_on:MBEDTLS_SHA1_C
-pkcs1_rsaes_oaep_decrypt:2048:16:"ecf5aecd1e5515fffacbd75a2816c6ebf49018cdfb4638e185d66a7396b6f8090f8018c7fd95cc34b857dc17f0cc6516bb1346ab4d582cadad7b4103352387b70338d084047c9d9539b6496204b3dd6ea442499207bec01f964287ff6336c3984658336846f56e46861881c10233d2176bf15a5e96ddc780bc868aa77d3ce769":16:"bc46c464fc6ac4ca783b0eb08a3c841b772f7e9b2f28babd588ae885e1a0c61e4858a0fb25ac299990f35be85164c259ba1175cdd7192707135184992b6c29b746dd0d2cabe142835f7d148cc161524b4a09946d48b828473f1ce76b6cb6886c345c03e05f41d51b5c3a90a3f24073c7d74a4fe25d9cf21c75960f3fc3863183":16:"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":16:"010001":MBEDTLS_MD_SHA1:"":"9f47ddf42e97eea856a9bdbc714eb3ac22f6eb32":"32b75304e631e94d4b02819642c7ffa66116af504cb3c4687420cc4b7f069fc6cc3b1a254611995ce2914a9e88152d38bbf87ccedcad9b9890341284e56e802a1b1f8f6bd3d5c991bd92eb8a8ea0a1d8bae141088ff8dceaebdb73515cf06ce33baa37c53093f1d1edc3502818cc70edcfddb41646374beb5b4f67f7f773e43778d4d31012e5a207c474e762ac3251ea6ede9018ad6e8e9ea65a3528a62b694eb9d8becff220a7c6c70d33eaafa52cf67a8090f67b6f9c43c6fe0b0f2375cbb9e611c0fcfef5312feb5e53d4a89d3d7e06c966e0c92ab9e5838239f390bcfd918d94c224df8e8ccb57ee364389908b6a0e550133f7565016804fbd6cb338314a":0
+pkcs1_rsaes_oaep_decrypt:2048:"ecf5aecd1e5515fffacbd75a2816c6ebf49018cdfb4638e185d66a7396b6f8090f8018c7fd95cc34b857dc17f0cc6516bb1346ab4d582cadad7b4103352387b70338d084047c9d9539b6496204b3dd6ea442499207bec01f964287ff6336c3984658336846f56e46861881c10233d2176bf15a5e96ddc780bc868aa77d3ce769":"bc46c464fc6ac4ca783b0eb08a3c841b772f7e9b2f28babd588ae885e1a0c61e4858a0fb25ac299990f35be85164c259ba1175cdd7192707135184992b6c29b746dd0d2cabe142835f7d148cc161524b4a09946d48b828473f1ce76b6cb6886c345c03e05f41d51b5c3a90a3f24073c7d74a4fe25d9cf21c75960f3fc3863183":"ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb":"010001":MBEDTLS_MD_SHA1:"":"9f47ddf42e97eea856a9bdbc714eb3ac22f6eb32":"32b75304e631e94d4b02819642c7ffa66116af504cb3c4687420cc4b7f069fc6cc3b1a254611995ce2914a9e88152d38bbf87ccedcad9b9890341284e56e802a1b1f8f6bd3d5c991bd92eb8a8ea0a1d8bae141088ff8dceaebdb73515cf06ce33baa37c53093f1d1edc3502818cc70edcfddb41646374beb5b4f67f7f773e43778d4d31012e5a207c474e762ac3251ea6ede9018ad6e8e9ea65a3528a62b694eb9d8becff220a7c6c70d33eaafa52cf67a8090f67b6f9c43c6fe0b0f2375cbb9e611c0fcfef5312feb5e53d4a89d3d7e06c966e0c92ab9e5838239f390bcfd918d94c224df8e8ccb57ee364389908b6a0e550133f7565016804fbd6cb338314a":0
 
 RSASSA-PSS Signing Test Vector Int
-pkcs1_rsassa_pss_sign:1024:16:"d17f655bf27c8b16d35462c905cc04a26f37e2a67fa9c0ce0dced472394a0df743fe7f929e378efdb368eddff453cf007af6d948e0ade757371f8a711e278f6b":16:"c6d92b6fee7414d1358ce1546fb62987530b90bd15e0f14963a5e2635adb69347ec0c01b2ab1763fd8ac1a592fb22757463a982425bb97a3a437c5bf86d03f2f":16:"a2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"859eef2fd78aca00308bdc471193bf55bf9d78db8f8a672b484634f3c9c26e6478ae10260fe0dd8c082e53a5293af2173cd50c6d5d354febf78b26021c25c02712e78cd4694c9f469777e451e7f8e9e04cd3739c6bbfedae487fb55644e9ca74ff77a53cb729802f6ed4a5ffa8ba159890fc":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"8daa627d3de7595d63056c7ec659e54406f10610128baae821c8b2a0f3936d54dc3bdce46689f6b7951bb18e840542769718d5715d210d85efbb596192032c42be4c29972c856275eb6d5a45f05f51876fc6743deddd28caec9bb30ea99e02c3488269604fe497f74ccd7c7fca1671897123cbd30def5d54a2b5536ad90a747e":0
+pkcs1_rsassa_pss_sign:1024:"d17f655bf27c8b16d35462c905cc04a26f37e2a67fa9c0ce0dced472394a0df743fe7f929e378efdb368eddff453cf007af6d948e0ade757371f8a711e278f6b":"c6d92b6fee7414d1358ce1546fb62987530b90bd15e0f14963a5e2635adb69347ec0c01b2ab1763fd8ac1a592fb22757463a982425bb97a3a437c5bf86d03f2f":"a2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"859eef2fd78aca00308bdc471193bf55bf9d78db8f8a672b484634f3c9c26e6478ae10260fe0dd8c082e53a5293af2173cd50c6d5d354febf78b26021c25c02712e78cd4694c9f469777e451e7f8e9e04cd3739c6bbfedae487fb55644e9ca74ff77a53cb729802f6ed4a5ffa8ba159890fc":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"8daa627d3de7595d63056c7ec659e54406f10610128baae821c8b2a0f3936d54dc3bdce46689f6b7951bb18e840542769718d5715d210d85efbb596192032c42be4c29972c856275eb6d5a45f05f51876fc6743deddd28caec9bb30ea99e02c3488269604fe497f74ccd7c7fca1671897123cbd30def5d54a2b5536ad90a747e":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Verification Test Vector Int
-pkcs1_rsassa_pss_verify:1024:16:"a2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"859eef2fd78aca00308bdc471193bf55bf9d78db8f8a672b484634f3c9c26e6478ae10260fe0dd8c082e53a5293af2173cd50c6d5d354febf78b26021c25c02712e78cd4694c9f469777e451e7f8e9e04cd3739c6bbfedae487fb55644e9ca74ff77a53cb729802f6ed4a5ffa8ba159890fc":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"8daa627d3de7595d63056c7ec659e54406f10610128baae821c8b2a0f3936d54dc3bdce46689f6b7951bb18e840542769718d5715d210d85efbb596192032c42be4c29972c856275eb6d5a45f05f51876fc6743deddd28caec9bb30ea99e02c3488269604fe497f74ccd7c7fca1671897123cbd30def5d54a2b5536ad90a747e":0
+pkcs1_rsassa_pss_verify:1024:"a2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"859eef2fd78aca00308bdc471193bf55bf9d78db8f8a672b484634f3c9c26e6478ae10260fe0dd8c082e53a5293af2173cd50c6d5d354febf78b26021c25c02712e78cd4694c9f469777e451e7f8e9e04cd3739c6bbfedae487fb55644e9ca74ff77a53cb729802f6ed4a5ffa8ba159890fc":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"8daa627d3de7595d63056c7ec659e54406f10610128baae821c8b2a0f3936d54dc3bdce46689f6b7951bb18e840542769718d5715d210d85efbb596192032c42be4c29972c856275eb6d5a45f05f51876fc6743deddd28caec9bb30ea99e02c3488269604fe497f74ccd7c7fca1671897123cbd30def5d54a2b5536ad90a747e":0
 
 RSASSA-PSS Signature RSA-1016, SHA-512: minimum salt size not met
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_sign:1016:16:"0e3cb6845e528229e19cfb24611e6859ac1cea7d35992b6e2e796823c52affa03400e42830f90697f084499c3e3587defc19e749e72433dd7b70c28b0c8280b7":16:"0c48f9e45ae38fdb4a5143be37d79a10cd4f1f9782ef26a4848a4449c72cfd712c68350818736385cb4a9ab6db5aef8e96c551039cfcc8915821aee069ed660d":16:"00aee7874a4db2f1510044405db29f14df0f37bbcf61fcbcc994a3d31caaf858a74cc8f2a40ac9a9ce7aa9a0680f62cf9d8d4b827114533fdbf86f16fc9dfe5cbf857d86135519a4611ffc59cb7473861619a78e3ec314715e804cff82d6f32e9f57ddf390563629883bd34f40e8db413209b151cee97d817a5d65c7da54734b":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd00":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"":MBEDTLS_ERR_RSA_BAD_INPUT_DATA
+pkcs1_rsassa_pss_sign:1016:"0e3cb6845e528229e19cfb24611e6859ac1cea7d35992b6e2e796823c52affa03400e42830f90697f084499c3e3587defc19e749e72433dd7b70c28b0c8280b7":"0c48f9e45ae38fdb4a5143be37d79a10cd4f1f9782ef26a4848a4449c72cfd712c68350818736385cb4a9ab6db5aef8e96c551039cfcc8915821aee069ed660d":"00aee7874a4db2f1510044405db29f14df0f37bbcf61fcbcc994a3d31caaf858a74cc8f2a40ac9a9ce7aa9a0680f62cf9d8d4b827114533fdbf86f16fc9dfe5cbf857d86135519a4611ffc59cb7473861619a78e3ec314715e804cff82d6f32e9f57ddf390563629883bd34f40e8db413209b151cee97d817a5d65c7da54734b":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd00":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"":MBEDTLS_RSA_SALT_LEN_ANY:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
 
 RSASSA-PSS Signature RSA-520, SHA-512: no possible salt size
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_sign:520:16:"0feea5f6220fac291b9508ec2ba8ed281eb39aee4d5dc693254106816ebc700ecf":16:"0d68918785c3aafe31eaaa2d8d8156dce645940ff7734a457337a51bd00bc88811":16:"00d5a06f86e5b9d87428540165ca966fa8893a62e2a59d0bfd7617780bb039f9165a373a8e119d0766f8de556710f33f67019153bad8223775e797d451d48206f3bf":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd00":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"":MBEDTLS_ERR_RSA_BAD_INPUT_DATA
+pkcs1_rsassa_pss_sign:520:"0feea5f6220fac291b9508ec2ba8ed281eb39aee4d5dc693254106816ebc700ecf":"0d68918785c3aafe31eaaa2d8d8156dce645940ff7734a457337a51bd00bc88811":"00d5a06f86e5b9d87428540165ca966fa8893a62e2a59d0bfd7617780bb039f9165a373a8e119d0766f8de556710f33f67019153bad8223775e797d451d48206f3bf":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd00":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"":MBEDTLS_RSA_SALT_LEN_ANY:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
 
 RSASSA-PSS Signature RSA-528, SHA-512: zero salt size
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_sign:528:16:"00d272aa28ed2085ac6df3c05c6719eed5deb618afa2e4ca4a6f7330b430ad48672d":16:"00c578836bab27145db9dd66f17470b62d4a6100f8ca0dedf457ee3639c3b9596325":16:"00a2554eba715bf66e5ecdf3d6d718e3e5d907e8666e7bf5a76b415106e04eb827ec4cb2199cff66491d45419082059aa5b54b0cf5eef4443402f3047c0b0e6f025081":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd00":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"":MBEDTLS_ERR_RSA_BAD_INPUT_DATA
+pkcs1_rsassa_pss_sign:528:"00d272aa28ed2085ac6df3c05c6719eed5deb618afa2e4ca4a6f7330b430ad48672d":"00c578836bab27145db9dd66f17470b62d4a6100f8ca0dedf457ee3639c3b9596325":"00a2554eba715bf66e5ecdf3d6d718e3e5d907e8666e7bf5a76b415106e04eb827ec4cb2199cff66491d45419082059aa5b54b0cf5eef4443402f3047c0b0e6f025081":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd00":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"":MBEDTLS_RSA_SALT_LEN_ANY:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
 
 RSASSA-PSS Signature Example 1_1
-pkcs1_rsassa_pss_sign:1024:16:"e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443":16:"b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd":16:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"cdc87da223d786df3b45e0bbbc721326d1ee2af806cc315475cc6f0d9c66e1b62371d45ce2392e1ac92844c310102f156a0d8d52c1f4c40ba3aa65095786cb769757a6563ba958fed0bcc984e8b517a3d5f515b23b8a41e74aa867693f90dfb061a6e86dfaaee64472c00e5f20945729cbebe77f06ce78e08f4098fba41f9d6193c0317e8b60d4b6084acb42d29e3808a3bc372d85e331170fcbf7cc72d0b71c296648b3a4d10f416295d0807aa625cab2744fd9ea8fd223c42537029828bd16be02546f130fd2e33b936d2676e08aed1b73318b750a0167d0":"dee959c7e06411361420ff80185ed57f3e6776af":"9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c":0
+pkcs1_rsassa_pss_sign:1024:"e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443":"b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd":"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"cdc87da223d786df3b45e0bbbc721326d1ee2af806cc315475cc6f0d9c66e1b62371d45ce2392e1ac92844c310102f156a0d8d52c1f4c40ba3aa65095786cb769757a6563ba958fed0bcc984e8b517a3d5f515b23b8a41e74aa867693f90dfb061a6e86dfaaee64472c00e5f20945729cbebe77f06ce78e08f4098fba41f9d6193c0317e8b60d4b6084acb42d29e3808a3bc372d85e331170fcbf7cc72d0b71c296648b3a4d10f416295d0807aa625cab2744fd9ea8fd223c42537029828bd16be02546f130fd2e33b936d2676e08aed1b73318b750a0167d0":"dee959c7e06411361420ff80185ed57f3e6776af":"9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 1_1 (verify)
-pkcs1_rsassa_pss_verify:1024:16:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"cdc87da223d786df3b45e0bbbc721326d1ee2af806cc315475cc6f0d9c66e1b62371d45ce2392e1ac92844c310102f156a0d8d52c1f4c40ba3aa65095786cb769757a6563ba958fed0bcc984e8b517a3d5f515b23b8a41e74aa867693f90dfb061a6e86dfaaee64472c00e5f20945729cbebe77f06ce78e08f4098fba41f9d6193c0317e8b60d4b6084acb42d29e3808a3bc372d85e331170fcbf7cc72d0b71c296648b3a4d10f416295d0807aa625cab2744fd9ea8fd223c42537029828bd16be02546f130fd2e33b936d2676e08aed1b73318b750a0167d0":"dee959c7e06411361420ff80185ed57f3e6776af":"9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c":0
+pkcs1_rsassa_pss_verify:1024:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"cdc87da223d786df3b45e0bbbc721326d1ee2af806cc315475cc6f0d9c66e1b62371d45ce2392e1ac92844c310102f156a0d8d52c1f4c40ba3aa65095786cb769757a6563ba958fed0bcc984e8b517a3d5f515b23b8a41e74aa867693f90dfb061a6e86dfaaee64472c00e5f20945729cbebe77f06ce78e08f4098fba41f9d6193c0317e8b60d4b6084acb42d29e3808a3bc372d85e331170fcbf7cc72d0b71c296648b3a4d10f416295d0807aa625cab2744fd9ea8fd223c42537029828bd16be02546f130fd2e33b936d2676e08aed1b73318b750a0167d0":"dee959c7e06411361420ff80185ed57f3e6776af":"9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c":0
 
 RSASSA-PSS Signature Example 1_2
-pkcs1_rsassa_pss_sign:1024:16:"e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443":16:"b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd":16:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"851384cdfe819c22ed6c4ccb30daeb5cf059bc8e1166b7e3530c4c233e2b5f8f71a1cca582d43ecc72b1bca16dfc7013226b9e":"ef2869fa40c346cb183dab3d7bffc98fd56df42d":"3ef7f46e831bf92b32274142a585ffcefbdca7b32ae90d10fb0f0c729984f04ef29a9df0780775ce43739b97838390db0a5505e63de927028d9d29b219ca2c4517832558a55d694a6d25b9dab66003c4cccd907802193be5170d26147d37b93590241be51c25055f47ef62752cfbe21418fafe98c22c4d4d47724fdb5669e843":0
+pkcs1_rsassa_pss_sign:1024:"e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443":"b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd":"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"851384cdfe819c22ed6c4ccb30daeb5cf059bc8e1166b7e3530c4c233e2b5f8f71a1cca582d43ecc72b1bca16dfc7013226b9e":"ef2869fa40c346cb183dab3d7bffc98fd56df42d":"3ef7f46e831bf92b32274142a585ffcefbdca7b32ae90d10fb0f0c729984f04ef29a9df0780775ce43739b97838390db0a5505e63de927028d9d29b219ca2c4517832558a55d694a6d25b9dab66003c4cccd907802193be5170d26147d37b93590241be51c25055f47ef62752cfbe21418fafe98c22c4d4d47724fdb5669e843":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 1_2 (verify)
-pkcs1_rsassa_pss_verify:1024:16:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"851384cdfe819c22ed6c4ccb30daeb5cf059bc8e1166b7e3530c4c233e2b5f8f71a1cca582d43ecc72b1bca16dfc7013226b9e":"ef2869fa40c346cb183dab3d7bffc98fd56df42d":"3ef7f46e831bf92b32274142a585ffcefbdca7b32ae90d10fb0f0c729984f04ef29a9df0780775ce43739b97838390db0a5505e63de927028d9d29b219ca2c4517832558a55d694a6d25b9dab66003c4cccd907802193be5170d26147d37b93590241be51c25055f47ef62752cfbe21418fafe98c22c4d4d47724fdb5669e843":0
+pkcs1_rsassa_pss_verify:1024:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"851384cdfe819c22ed6c4ccb30daeb5cf059bc8e1166b7e3530c4c233e2b5f8f71a1cca582d43ecc72b1bca16dfc7013226b9e":"ef2869fa40c346cb183dab3d7bffc98fd56df42d":"3ef7f46e831bf92b32274142a585ffcefbdca7b32ae90d10fb0f0c729984f04ef29a9df0780775ce43739b97838390db0a5505e63de927028d9d29b219ca2c4517832558a55d694a6d25b9dab66003c4cccd907802193be5170d26147d37b93590241be51c25055f47ef62752cfbe21418fafe98c22c4d4d47724fdb5669e843":0
 
 RSASSA-PSS Signature Example 1_3
-pkcs1_rsassa_pss_sign:1024:16:"e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443":16:"b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd":16:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"a4b159941761c40c6a82f2b80d1b94f5aa2654fd17e12d588864679b54cd04ef8bd03012be8dc37f4b83af7963faff0dfa225477437c48017ff2be8191cf3955fc07356eab3f322f7f620e21d254e5db4324279fe067e0910e2e81ca2cab31c745e67a54058eb50d993cdb9ed0b4d029c06d21a94ca661c3ce27fae1d6cb20f4564d66ce4767583d0e5f060215b59017be85ea848939127bd8c9c4d47b51056c031cf336f17c9980f3b8f5b9b6878e8b797aa43b882684333e17893fe9caa6aa299f7ed1a18ee2c54864b7b2b99b72618fb02574d139ef50f019c9eef416971338e7d470":"710b9c4747d800d4de87f12afdce6df18107cc77":"666026fba71bd3e7cf13157cc2c51a8e4aa684af9778f91849f34335d141c00154c4197621f9624a675b5abc22ee7d5baaffaae1c9baca2cc373b3f33e78e6143c395a91aa7faca664eb733afd14d8827259d99a7550faca501ef2b04e33c23aa51f4b9e8282efdb728cc0ab09405a91607c6369961bc8270d2d4f39fce612b1":0
+pkcs1_rsassa_pss_sign:1024:"e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443":"b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd":"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"a4b159941761c40c6a82f2b80d1b94f5aa2654fd17e12d588864679b54cd04ef8bd03012be8dc37f4b83af7963faff0dfa225477437c48017ff2be8191cf3955fc07356eab3f322f7f620e21d254e5db4324279fe067e0910e2e81ca2cab31c745e67a54058eb50d993cdb9ed0b4d029c06d21a94ca661c3ce27fae1d6cb20f4564d66ce4767583d0e5f060215b59017be85ea848939127bd8c9c4d47b51056c031cf336f17c9980f3b8f5b9b6878e8b797aa43b882684333e17893fe9caa6aa299f7ed1a18ee2c54864b7b2b99b72618fb02574d139ef50f019c9eef416971338e7d470":"710b9c4747d800d4de87f12afdce6df18107cc77":"666026fba71bd3e7cf13157cc2c51a8e4aa684af9778f91849f34335d141c00154c4197621f9624a675b5abc22ee7d5baaffaae1c9baca2cc373b3f33e78e6143c395a91aa7faca664eb733afd14d8827259d99a7550faca501ef2b04e33c23aa51f4b9e8282efdb728cc0ab09405a91607c6369961bc8270d2d4f39fce612b1":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 1_3 (verify)
-pkcs1_rsassa_pss_verify:1024:16:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"a4b159941761c40c6a82f2b80d1b94f5aa2654fd17e12d588864679b54cd04ef8bd03012be8dc37f4b83af7963faff0dfa225477437c48017ff2be8191cf3955fc07356eab3f322f7f620e21d254e5db4324279fe067e0910e2e81ca2cab31c745e67a54058eb50d993cdb9ed0b4d029c06d21a94ca661c3ce27fae1d6cb20f4564d66ce4767583d0e5f060215b59017be85ea848939127bd8c9c4d47b51056c031cf336f17c9980f3b8f5b9b6878e8b797aa43b882684333e17893fe9caa6aa299f7ed1a18ee2c54864b7b2b99b72618fb02574d139ef50f019c9eef416971338e7d470":"710b9c4747d800d4de87f12afdce6df18107cc77":"666026fba71bd3e7cf13157cc2c51a8e4aa684af9778f91849f34335d141c00154c4197621f9624a675b5abc22ee7d5baaffaae1c9baca2cc373b3f33e78e6143c395a91aa7faca664eb733afd14d8827259d99a7550faca501ef2b04e33c23aa51f4b9e8282efdb728cc0ab09405a91607c6369961bc8270d2d4f39fce612b1":0
+pkcs1_rsassa_pss_verify:1024:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"a4b159941761c40c6a82f2b80d1b94f5aa2654fd17e12d588864679b54cd04ef8bd03012be8dc37f4b83af7963faff0dfa225477437c48017ff2be8191cf3955fc07356eab3f322f7f620e21d254e5db4324279fe067e0910e2e81ca2cab31c745e67a54058eb50d993cdb9ed0b4d029c06d21a94ca661c3ce27fae1d6cb20f4564d66ce4767583d0e5f060215b59017be85ea848939127bd8c9c4d47b51056c031cf336f17c9980f3b8f5b9b6878e8b797aa43b882684333e17893fe9caa6aa299f7ed1a18ee2c54864b7b2b99b72618fb02574d139ef50f019c9eef416971338e7d470":"710b9c4747d800d4de87f12afdce6df18107cc77":"666026fba71bd3e7cf13157cc2c51a8e4aa684af9778f91849f34335d141c00154c4197621f9624a675b5abc22ee7d5baaffaae1c9baca2cc373b3f33e78e6143c395a91aa7faca664eb733afd14d8827259d99a7550faca501ef2b04e33c23aa51f4b9e8282efdb728cc0ab09405a91607c6369961bc8270d2d4f39fce612b1":0
 
 RSASSA-PSS Signature Example 1_4
-pkcs1_rsassa_pss_sign:1024:16:"e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443":16:"b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd":16:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"bc656747fa9eafb3f0":"056f00985de14d8ef5cea9e82f8c27bef720335e":"4609793b23e9d09362dc21bb47da0b4f3a7622649a47d464019b9aeafe53359c178c91cd58ba6bcb78be0346a7bc637f4b873d4bab38ee661f199634c547a1ad8442e03da015b136e543f7ab07c0c13e4225b8de8cce25d4f6eb8400f81f7e1833b7ee6e334d370964ca79fdb872b4d75223b5eeb08101591fb532d155a6de87":0
+pkcs1_rsassa_pss_sign:1024:"e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443":"b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd":"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"bc656747fa9eafb3f0":"056f00985de14d8ef5cea9e82f8c27bef720335e":"4609793b23e9d09362dc21bb47da0b4f3a7622649a47d464019b9aeafe53359c178c91cd58ba6bcb78be0346a7bc637f4b873d4bab38ee661f199634c547a1ad8442e03da015b136e543f7ab07c0c13e4225b8de8cce25d4f6eb8400f81f7e1833b7ee6e334d370964ca79fdb872b4d75223b5eeb08101591fb532d155a6de87":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 1_4 (verify)
-pkcs1_rsassa_pss_verify:1024:16:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"bc656747fa9eafb3f0":"056f00985de14d8ef5cea9e82f8c27bef720335e":"4609793b23e9d09362dc21bb47da0b4f3a7622649a47d464019b9aeafe53359c178c91cd58ba6bcb78be0346a7bc637f4b873d4bab38ee661f199634c547a1ad8442e03da015b136e543f7ab07c0c13e4225b8de8cce25d4f6eb8400f81f7e1833b7ee6e334d370964ca79fdb872b4d75223b5eeb08101591fb532d155a6de87":0
+pkcs1_rsassa_pss_verify:1024:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"bc656747fa9eafb3f0":"056f00985de14d8ef5cea9e82f8c27bef720335e":"4609793b23e9d09362dc21bb47da0b4f3a7622649a47d464019b9aeafe53359c178c91cd58ba6bcb78be0346a7bc637f4b873d4bab38ee661f199634c547a1ad8442e03da015b136e543f7ab07c0c13e4225b8de8cce25d4f6eb8400f81f7e1833b7ee6e334d370964ca79fdb872b4d75223b5eeb08101591fb532d155a6de87":0
 
 RSASSA-PSS Signature Example 1_5
-pkcs1_rsassa_pss_sign:1024:16:"e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443":16:"b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd":16:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"b45581547e5427770c768e8b82b75564e0ea4e9c32594d6bff706544de0a8776c7a80b4576550eee1b2acabc7e8b7d3ef7bb5b03e462c11047eadd00629ae575480ac1470fe046f13a2bf5af17921dc4b0aa8b02bee6334911651d7f8525d10f32b51d33be520d3ddf5a709955a3dfe78283b9e0ab54046d150c177f037fdccc5be4ea5f68b5e5a38c9d7edcccc4975f455a6909b4":"80e70ff86a08de3ec60972b39b4fbfdcea67ae8e":"1d2aad221ca4d31ddf13509239019398e3d14b32dc34dc5af4aeaea3c095af73479cf0a45e5629635a53a018377615b16cb9b13b3e09d671eb71e387b8545c5960da5a64776e768e82b2c93583bf104c3fdb23512b7b4e89f633dd0063a530db4524b01c3f384c09310e315a79dcd3d684022a7f31c865a664e316978b759fad":0
+pkcs1_rsassa_pss_sign:1024:"e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443":"b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd":"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"b45581547e5427770c768e8b82b75564e0ea4e9c32594d6bff706544de0a8776c7a80b4576550eee1b2acabc7e8b7d3ef7bb5b03e462c11047eadd00629ae575480ac1470fe046f13a2bf5af17921dc4b0aa8b02bee6334911651d7f8525d10f32b51d33be520d3ddf5a709955a3dfe78283b9e0ab54046d150c177f037fdccc5be4ea5f68b5e5a38c9d7edcccc4975f455a6909b4":"80e70ff86a08de3ec60972b39b4fbfdcea67ae8e":"1d2aad221ca4d31ddf13509239019398e3d14b32dc34dc5af4aeaea3c095af73479cf0a45e5629635a53a018377615b16cb9b13b3e09d671eb71e387b8545c5960da5a64776e768e82b2c93583bf104c3fdb23512b7b4e89f633dd0063a530db4524b01c3f384c09310e315a79dcd3d684022a7f31c865a664e316978b759fad":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 1_5 (verify)
-pkcs1_rsassa_pss_verify:1024:16:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"b45581547e5427770c768e8b82b75564e0ea4e9c32594d6bff706544de0a8776c7a80b4576550eee1b2acabc7e8b7d3ef7bb5b03e462c11047eadd00629ae575480ac1470fe046f13a2bf5af17921dc4b0aa8b02bee6334911651d7f8525d10f32b51d33be520d3ddf5a709955a3dfe78283b9e0ab54046d150c177f037fdccc5be4ea5f68b5e5a38c9d7edcccc4975f455a6909b4":"80e70ff86a08de3ec60972b39b4fbfdcea67ae8e":"1d2aad221ca4d31ddf13509239019398e3d14b32dc34dc5af4aeaea3c095af73479cf0a45e5629635a53a018377615b16cb9b13b3e09d671eb71e387b8545c5960da5a64776e768e82b2c93583bf104c3fdb23512b7b4e89f633dd0063a530db4524b01c3f384c09310e315a79dcd3d684022a7f31c865a664e316978b759fad":0
+pkcs1_rsassa_pss_verify:1024:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"b45581547e5427770c768e8b82b75564e0ea4e9c32594d6bff706544de0a8776c7a80b4576550eee1b2acabc7e8b7d3ef7bb5b03e462c11047eadd00629ae575480ac1470fe046f13a2bf5af17921dc4b0aa8b02bee6334911651d7f8525d10f32b51d33be520d3ddf5a709955a3dfe78283b9e0ab54046d150c177f037fdccc5be4ea5f68b5e5a38c9d7edcccc4975f455a6909b4":"80e70ff86a08de3ec60972b39b4fbfdcea67ae8e":"1d2aad221ca4d31ddf13509239019398e3d14b32dc34dc5af4aeaea3c095af73479cf0a45e5629635a53a018377615b16cb9b13b3e09d671eb71e387b8545c5960da5a64776e768e82b2c93583bf104c3fdb23512b7b4e89f633dd0063a530db4524b01c3f384c09310e315a79dcd3d684022a7f31c865a664e316978b759fad":0
 
 RSASSA-PSS Signature Example 1_6
-pkcs1_rsassa_pss_sign:1024:16:"e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443":16:"b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd":16:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"10aae9a0ab0b595d0841207b700d48d75faedde3b775cd6b4cc88ae06e4694ec74ba18f8520d4f5ea69cbbe7cc2beba43efdc10215ac4eb32dc302a1f53dc6c4352267e7936cfebf7c8d67035784a3909fa859c7b7b59b8e39c5c2349f1886b705a30267d402f7486ab4f58cad5d69adb17ab8cd0ce1caf5025af4ae24b1fb8794c6070cc09a51e2f9911311e3877d0044c71c57a993395008806b723ac38373d395481818528c1e7053739282053529510e935cd0fa77b8fa53cc2d474bd4fb3cc5c672d6ffdc90a00f9848712c4bcfe46c60573659b11e6457e861f0f604b6138d144f8ce4e2da73":"a8ab69dd801f0074c2a1fc60649836c616d99681":"2a34f6125e1f6b0bf971e84fbd41c632be8f2c2ace7de8b6926e31ff93e9af987fbc06e51e9be14f5198f91f3f953bd67da60a9df59764c3dc0fe08e1cbef0b75f868d10ad3fba749fef59fb6dac46a0d6e504369331586f58e4628f39aa278982543bc0eeb537dc61958019b394fb273f215858a0a01ac4d650b955c67f4c58":0
+pkcs1_rsassa_pss_sign:1024:"e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443":"b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd":"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"10aae9a0ab0b595d0841207b700d48d75faedde3b775cd6b4cc88ae06e4694ec74ba18f8520d4f5ea69cbbe7cc2beba43efdc10215ac4eb32dc302a1f53dc6c4352267e7936cfebf7c8d67035784a3909fa859c7b7b59b8e39c5c2349f1886b705a30267d402f7486ab4f58cad5d69adb17ab8cd0ce1caf5025af4ae24b1fb8794c6070cc09a51e2f9911311e3877d0044c71c57a993395008806b723ac38373d395481818528c1e7053739282053529510e935cd0fa77b8fa53cc2d474bd4fb3cc5c672d6ffdc90a00f9848712c4bcfe46c60573659b11e6457e861f0f604b6138d144f8ce4e2da73":"a8ab69dd801f0074c2a1fc60649836c616d99681":"2a34f6125e1f6b0bf971e84fbd41c632be8f2c2ace7de8b6926e31ff93e9af987fbc06e51e9be14f5198f91f3f953bd67da60a9df59764c3dc0fe08e1cbef0b75f868d10ad3fba749fef59fb6dac46a0d6e504369331586f58e4628f39aa278982543bc0eeb537dc61958019b394fb273f215858a0a01ac4d650b955c67f4c58":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 1_6 (verify)
-pkcs1_rsassa_pss_verify:1024:16:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"10aae9a0ab0b595d0841207b700d48d75faedde3b775cd6b4cc88ae06e4694ec74ba18f8520d4f5ea69cbbe7cc2beba43efdc10215ac4eb32dc302a1f53dc6c4352267e7936cfebf7c8d67035784a3909fa859c7b7b59b8e39c5c2349f1886b705a30267d402f7486ab4f58cad5d69adb17ab8cd0ce1caf5025af4ae24b1fb8794c6070cc09a51e2f9911311e3877d0044c71c57a993395008806b723ac38373d395481818528c1e7053739282053529510e935cd0fa77b8fa53cc2d474bd4fb3cc5c672d6ffdc90a00f9848712c4bcfe46c60573659b11e6457e861f0f604b6138d144f8ce4e2da73":"a8ab69dd801f0074c2a1fc60649836c616d99681":"2a34f6125e1f6b0bf971e84fbd41c632be8f2c2ace7de8b6926e31ff93e9af987fbc06e51e9be14f5198f91f3f953bd67da60a9df59764c3dc0fe08e1cbef0b75f868d10ad3fba749fef59fb6dac46a0d6e504369331586f58e4628f39aa278982543bc0eeb537dc61958019b394fb273f215858a0a01ac4d650b955c67f4c58":0
+pkcs1_rsassa_pss_verify:1024:"a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"10aae9a0ab0b595d0841207b700d48d75faedde3b775cd6b4cc88ae06e4694ec74ba18f8520d4f5ea69cbbe7cc2beba43efdc10215ac4eb32dc302a1f53dc6c4352267e7936cfebf7c8d67035784a3909fa859c7b7b59b8e39c5c2349f1886b705a30267d402f7486ab4f58cad5d69adb17ab8cd0ce1caf5025af4ae24b1fb8794c6070cc09a51e2f9911311e3877d0044c71c57a993395008806b723ac38373d395481818528c1e7053739282053529510e935cd0fa77b8fa53cc2d474bd4fb3cc5c672d6ffdc90a00f9848712c4bcfe46c60573659b11e6457e861f0f604b6138d144f8ce4e2da73":"a8ab69dd801f0074c2a1fc60649836c616d99681":"2a34f6125e1f6b0bf971e84fbd41c632be8f2c2ace7de8b6926e31ff93e9af987fbc06e51e9be14f5198f91f3f953bd67da60a9df59764c3dc0fe08e1cbef0b75f868d10ad3fba749fef59fb6dac46a0d6e504369331586f58e4628f39aa278982543bc0eeb537dc61958019b394fb273f215858a0a01ac4d650b955c67f4c58":0
 
 RSASSA-PSS Signature Example 2_1
-pkcs1_rsassa_pss_sign:1025:16:"016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1":16:"014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079":16:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"daba032066263faedb659848115278a52c44faa3a76f37515ed336321072c40a9d9b53bc05014078adf520875146aae70ff060226dcb7b1f1fc27e9360":"57bf160bcb02bb1dc7280cf0458530b7d2832ff7":"014c5ba5338328ccc6e7a90bf1c0ab3fd606ff4796d3c12e4b639ed9136a5fec6c16d8884bdd99cfdc521456b0742b736868cf90de099adb8d5ffd1deff39ba4007ab746cefdb22d7df0e225f54627dc65466131721b90af445363a8358b9f607642f78fab0ab0f43b7168d64bae70d8827848d8ef1e421c5754ddf42c2589b5b3":0
+pkcs1_rsassa_pss_sign:1025:"016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1":"014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079":"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"daba032066263faedb659848115278a52c44faa3a76f37515ed336321072c40a9d9b53bc05014078adf520875146aae70ff060226dcb7b1f1fc27e9360":"57bf160bcb02bb1dc7280cf0458530b7d2832ff7":"014c5ba5338328ccc6e7a90bf1c0ab3fd606ff4796d3c12e4b639ed9136a5fec6c16d8884bdd99cfdc521456b0742b736868cf90de099adb8d5ffd1deff39ba4007ab746cefdb22d7df0e225f54627dc65466131721b90af445363a8358b9f607642f78fab0ab0f43b7168d64bae70d8827848d8ef1e421c5754ddf42c2589b5b3":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 2_1 (verify)
-pkcs1_rsassa_pss_verify:1025:16:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"daba032066263faedb659848115278a52c44faa3a76f37515ed336321072c40a9d9b53bc05014078adf520875146aae70ff060226dcb7b1f1fc27e9360":"57bf160bcb02bb1dc7280cf0458530b7d2832ff7":"014c5ba5338328ccc6e7a90bf1c0ab3fd606ff4796d3c12e4b639ed9136a5fec6c16d8884bdd99cfdc521456b0742b736868cf90de099adb8d5ffd1deff39ba4007ab746cefdb22d7df0e225f54627dc65466131721b90af445363a8358b9f607642f78fab0ab0f43b7168d64bae70d8827848d8ef1e421c5754ddf42c2589b5b3":0
+pkcs1_rsassa_pss_verify:1025:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"daba032066263faedb659848115278a52c44faa3a76f37515ed336321072c40a9d9b53bc05014078adf520875146aae70ff060226dcb7b1f1fc27e9360":"57bf160bcb02bb1dc7280cf0458530b7d2832ff7":"014c5ba5338328ccc6e7a90bf1c0ab3fd606ff4796d3c12e4b639ed9136a5fec6c16d8884bdd99cfdc521456b0742b736868cf90de099adb8d5ffd1deff39ba4007ab746cefdb22d7df0e225f54627dc65466131721b90af445363a8358b9f607642f78fab0ab0f43b7168d64bae70d8827848d8ef1e421c5754ddf42c2589b5b3":0
 
 RSASSA-PSS Signature Example 2_2
-pkcs1_rsassa_pss_sign:1025:16:"016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1":16:"014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079":16:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e4f8601a8a6da1be34447c0959c058570c3668cfd51dd5f9ccd6ad4411fe8213486d78a6c49f93efc2ca2288cebc2b9b60bd04b1e220d86e3d4848d709d032d1e8c6a070c6af9a499fcf95354b14ba6127c739de1bb0fd16431e46938aec0cf8ad9eb72e832a7035de9b7807bdc0ed8b68eb0f5ac2216be40ce920c0db0eddd3860ed788efaccaca502d8f2bd6d1a7c1f41ff46f1681c8f1f818e9c4f6d91a0c7803ccc63d76a6544d843e084e363b8acc55aa531733edb5dee5b5196e9f03e8b731b3776428d9e457fe3fbcb3db7274442d785890e9cb0854b6444dace791d7273de1889719338a77fe":"7f6dd359e604e60870e898e47b19bf2e5a7b2a90":"010991656cca182b7f29d2dbc007e7ae0fec158eb6759cb9c45c5ff87c7635dd46d150882f4de1e9ae65e7f7d9018f6836954a47c0a81a8a6b6f83f2944d6081b1aa7c759b254b2c34b691da67cc0226e20b2f18b42212761dcd4b908a62b371b5918c5742af4b537e296917674fb914194761621cc19a41f6fb953fbcbb649dea":0
+pkcs1_rsassa_pss_sign:1025:"016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1":"014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079":"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e4f8601a8a6da1be34447c0959c058570c3668cfd51dd5f9ccd6ad4411fe8213486d78a6c49f93efc2ca2288cebc2b9b60bd04b1e220d86e3d4848d709d032d1e8c6a070c6af9a499fcf95354b14ba6127c739de1bb0fd16431e46938aec0cf8ad9eb72e832a7035de9b7807bdc0ed8b68eb0f5ac2216be40ce920c0db0eddd3860ed788efaccaca502d8f2bd6d1a7c1f41ff46f1681c8f1f818e9c4f6d91a0c7803ccc63d76a6544d843e084e363b8acc55aa531733edb5dee5b5196e9f03e8b731b3776428d9e457fe3fbcb3db7274442d785890e9cb0854b6444dace791d7273de1889719338a77fe":"7f6dd359e604e60870e898e47b19bf2e5a7b2a90":"010991656cca182b7f29d2dbc007e7ae0fec158eb6759cb9c45c5ff87c7635dd46d150882f4de1e9ae65e7f7d9018f6836954a47c0a81a8a6b6f83f2944d6081b1aa7c759b254b2c34b691da67cc0226e20b2f18b42212761dcd4b908a62b371b5918c5742af4b537e296917674fb914194761621cc19a41f6fb953fbcbb649dea":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 2_2 (verify)
-pkcs1_rsassa_pss_verify:1025:16:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e4f8601a8a6da1be34447c0959c058570c3668cfd51dd5f9ccd6ad4411fe8213486d78a6c49f93efc2ca2288cebc2b9b60bd04b1e220d86e3d4848d709d032d1e8c6a070c6af9a499fcf95354b14ba6127c739de1bb0fd16431e46938aec0cf8ad9eb72e832a7035de9b7807bdc0ed8b68eb0f5ac2216be40ce920c0db0eddd3860ed788efaccaca502d8f2bd6d1a7c1f41ff46f1681c8f1f818e9c4f6d91a0c7803ccc63d76a6544d843e084e363b8acc55aa531733edb5dee5b5196e9f03e8b731b3776428d9e457fe3fbcb3db7274442d785890e9cb0854b6444dace791d7273de1889719338a77fe":"7f6dd359e604e60870e898e47b19bf2e5a7b2a90":"010991656cca182b7f29d2dbc007e7ae0fec158eb6759cb9c45c5ff87c7635dd46d150882f4de1e9ae65e7f7d9018f6836954a47c0a81a8a6b6f83f2944d6081b1aa7c759b254b2c34b691da67cc0226e20b2f18b42212761dcd4b908a62b371b5918c5742af4b537e296917674fb914194761621cc19a41f6fb953fbcbb649dea":0
+pkcs1_rsassa_pss_verify:1025:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e4f8601a8a6da1be34447c0959c058570c3668cfd51dd5f9ccd6ad4411fe8213486d78a6c49f93efc2ca2288cebc2b9b60bd04b1e220d86e3d4848d709d032d1e8c6a070c6af9a499fcf95354b14ba6127c739de1bb0fd16431e46938aec0cf8ad9eb72e832a7035de9b7807bdc0ed8b68eb0f5ac2216be40ce920c0db0eddd3860ed788efaccaca502d8f2bd6d1a7c1f41ff46f1681c8f1f818e9c4f6d91a0c7803ccc63d76a6544d843e084e363b8acc55aa531733edb5dee5b5196e9f03e8b731b3776428d9e457fe3fbcb3db7274442d785890e9cb0854b6444dace791d7273de1889719338a77fe":"7f6dd359e604e60870e898e47b19bf2e5a7b2a90":"010991656cca182b7f29d2dbc007e7ae0fec158eb6759cb9c45c5ff87c7635dd46d150882f4de1e9ae65e7f7d9018f6836954a47c0a81a8a6b6f83f2944d6081b1aa7c759b254b2c34b691da67cc0226e20b2f18b42212761dcd4b908a62b371b5918c5742af4b537e296917674fb914194761621cc19a41f6fb953fbcbb649dea":0
 
 RSASSA-PSS Signature Example 2_3
-pkcs1_rsassa_pss_sign:1025:16:"016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1":16:"014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079":16:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"52a1d96c8ac39e41e455809801b927a5b445c10d902a0dcd3850d22a66d2bb0703e67d5867114595aabf5a7aeb5a8f87034bbb30e13cfd4817a9be76230023606d0286a3faf8a4d22b728ec518079f9e64526e3a0cc7941aa338c437997c680ccac67c66bfa1":"fca862068bce2246724b708a0519da17e648688c":"007f0030018f53cdc71f23d03659fde54d4241f758a750b42f185f87578520c30742afd84359b6e6e8d3ed959dc6fe486bedc8e2cf001f63a7abe16256a1b84df0d249fc05d3194ce5f0912742dbbf80dd174f6c51f6bad7f16cf3364eba095a06267dc3793803ac7526aebe0a475d38b8c2247ab51c4898df7047dc6adf52c6c4":0
+pkcs1_rsassa_pss_sign:1025:"016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1":"014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079":"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"52a1d96c8ac39e41e455809801b927a5b445c10d902a0dcd3850d22a66d2bb0703e67d5867114595aabf5a7aeb5a8f87034bbb30e13cfd4817a9be76230023606d0286a3faf8a4d22b728ec518079f9e64526e3a0cc7941aa338c437997c680ccac67c66bfa1":"fca862068bce2246724b708a0519da17e648688c":"007f0030018f53cdc71f23d03659fde54d4241f758a750b42f185f87578520c30742afd84359b6e6e8d3ed959dc6fe486bedc8e2cf001f63a7abe16256a1b84df0d249fc05d3194ce5f0912742dbbf80dd174f6c51f6bad7f16cf3364eba095a06267dc3793803ac7526aebe0a475d38b8c2247ab51c4898df7047dc6adf52c6c4":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 2_3 (verify)
-pkcs1_rsassa_pss_verify:1025:16:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"52a1d96c8ac39e41e455809801b927a5b445c10d902a0dcd3850d22a66d2bb0703e67d5867114595aabf5a7aeb5a8f87034bbb30e13cfd4817a9be76230023606d0286a3faf8a4d22b728ec518079f9e64526e3a0cc7941aa338c437997c680ccac67c66bfa1":"fca862068bce2246724b708a0519da17e648688c":"007f0030018f53cdc71f23d03659fde54d4241f758a750b42f185f87578520c30742afd84359b6e6e8d3ed959dc6fe486bedc8e2cf001f63a7abe16256a1b84df0d249fc05d3194ce5f0912742dbbf80dd174f6c51f6bad7f16cf3364eba095a06267dc3793803ac7526aebe0a475d38b8c2247ab51c4898df7047dc6adf52c6c4":0
+pkcs1_rsassa_pss_verify:1025:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"52a1d96c8ac39e41e455809801b927a5b445c10d902a0dcd3850d22a66d2bb0703e67d5867114595aabf5a7aeb5a8f87034bbb30e13cfd4817a9be76230023606d0286a3faf8a4d22b728ec518079f9e64526e3a0cc7941aa338c437997c680ccac67c66bfa1":"fca862068bce2246724b708a0519da17e648688c":"007f0030018f53cdc71f23d03659fde54d4241f758a750b42f185f87578520c30742afd84359b6e6e8d3ed959dc6fe486bedc8e2cf001f63a7abe16256a1b84df0d249fc05d3194ce5f0912742dbbf80dd174f6c51f6bad7f16cf3364eba095a06267dc3793803ac7526aebe0a475d38b8c2247ab51c4898df7047dc6adf52c6c4":0
 
 RSASSA-PSS Signature Example 2_4
-pkcs1_rsassa_pss_sign:1025:16:"016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1":16:"014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079":16:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"a7182c83ac18be6570a106aa9d5c4e3dbbd4afaeb0c60c4a23e1969d79ff":"8070ef2de945c02387684ba0d33096732235d440":"009cd2f4edbe23e12346ae8c76dd9ad3230a62076141f16c152ba18513a48ef6f010e0e37fd3df10a1ec629a0cb5a3b5d2893007298c30936a95903b6ba85555d9ec3673a06108fd62a2fda56d1ce2e85c4db6b24a81ca3b496c36d4fd06eb7c9166d8e94877c42bea622b3bfe9251fdc21d8d5371badad78a488214796335b40b":0
+pkcs1_rsassa_pss_sign:1025:"016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1":"014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079":"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"a7182c83ac18be6570a106aa9d5c4e3dbbd4afaeb0c60c4a23e1969d79ff":"8070ef2de945c02387684ba0d33096732235d440":"009cd2f4edbe23e12346ae8c76dd9ad3230a62076141f16c152ba18513a48ef6f010e0e37fd3df10a1ec629a0cb5a3b5d2893007298c30936a95903b6ba85555d9ec3673a06108fd62a2fda56d1ce2e85c4db6b24a81ca3b496c36d4fd06eb7c9166d8e94877c42bea622b3bfe9251fdc21d8d5371badad78a488214796335b40b":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 2_4 (verify)
-pkcs1_rsassa_pss_verify:1025:16:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"a7182c83ac18be6570a106aa9d5c4e3dbbd4afaeb0c60c4a23e1969d79ff":"8070ef2de945c02387684ba0d33096732235d440":"009cd2f4edbe23e12346ae8c76dd9ad3230a62076141f16c152ba18513a48ef6f010e0e37fd3df10a1ec629a0cb5a3b5d2893007298c30936a95903b6ba85555d9ec3673a06108fd62a2fda56d1ce2e85c4db6b24a81ca3b496c36d4fd06eb7c9166d8e94877c42bea622b3bfe9251fdc21d8d5371badad78a488214796335b40b":0
+pkcs1_rsassa_pss_verify:1025:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"a7182c83ac18be6570a106aa9d5c4e3dbbd4afaeb0c60c4a23e1969d79ff":"8070ef2de945c02387684ba0d33096732235d440":"009cd2f4edbe23e12346ae8c76dd9ad3230a62076141f16c152ba18513a48ef6f010e0e37fd3df10a1ec629a0cb5a3b5d2893007298c30936a95903b6ba85555d9ec3673a06108fd62a2fda56d1ce2e85c4db6b24a81ca3b496c36d4fd06eb7c9166d8e94877c42bea622b3bfe9251fdc21d8d5371badad78a488214796335b40b":0
 
 RSASSA-PSS Signature Example 2_5
-pkcs1_rsassa_pss_sign:1025:16:"016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1":16:"014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079":16:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"86a83d4a72ee932a4f5630af6579a386b78fe88999e0abd2d49034a4bfc854dd94f1094e2e8cd7a179d19588e4aefc1b1bd25e95e3dd461f":"17639a4e88d722c4fca24d079a8b29c32433b0c9":"00ec430824931ebd3baa43034dae98ba646b8c36013d1671c3cf1cf8260c374b19f8e1cc8d965012405e7e9bf7378612dfcc85fce12cda11f950bd0ba8876740436c1d2595a64a1b32efcfb74a21c873b3cc33aaf4e3dc3953de67f0674c0453b4fd9f604406d441b816098cb106fe3472bc251f815f59db2e4378a3addc181ecf":0
+pkcs1_rsassa_pss_sign:1025:"016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1":"014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079":"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"86a83d4a72ee932a4f5630af6579a386b78fe88999e0abd2d49034a4bfc854dd94f1094e2e8cd7a179d19588e4aefc1b1bd25e95e3dd461f":"17639a4e88d722c4fca24d079a8b29c32433b0c9":"00ec430824931ebd3baa43034dae98ba646b8c36013d1671c3cf1cf8260c374b19f8e1cc8d965012405e7e9bf7378612dfcc85fce12cda11f950bd0ba8876740436c1d2595a64a1b32efcfb74a21c873b3cc33aaf4e3dc3953de67f0674c0453b4fd9f604406d441b816098cb106fe3472bc251f815f59db2e4378a3addc181ecf":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 2_5 (verify)
-pkcs1_rsassa_pss_verify:1025:16:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"86a83d4a72ee932a4f5630af6579a386b78fe88999e0abd2d49034a4bfc854dd94f1094e2e8cd7a179d19588e4aefc1b1bd25e95e3dd461f":"17639a4e88d722c4fca24d079a8b29c32433b0c9":"00ec430824931ebd3baa43034dae98ba646b8c36013d1671c3cf1cf8260c374b19f8e1cc8d965012405e7e9bf7378612dfcc85fce12cda11f950bd0ba8876740436c1d2595a64a1b32efcfb74a21c873b3cc33aaf4e3dc3953de67f0674c0453b4fd9f604406d441b816098cb106fe3472bc251f815f59db2e4378a3addc181ecf":0
+pkcs1_rsassa_pss_verify:1025:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"86a83d4a72ee932a4f5630af6579a386b78fe88999e0abd2d49034a4bfc854dd94f1094e2e8cd7a179d19588e4aefc1b1bd25e95e3dd461f":"17639a4e88d722c4fca24d079a8b29c32433b0c9":"00ec430824931ebd3baa43034dae98ba646b8c36013d1671c3cf1cf8260c374b19f8e1cc8d965012405e7e9bf7378612dfcc85fce12cda11f950bd0ba8876740436c1d2595a64a1b32efcfb74a21c873b3cc33aaf4e3dc3953de67f0674c0453b4fd9f604406d441b816098cb106fe3472bc251f815f59db2e4378a3addc181ecf":0
 
 RSASSA-PSS Signature Example 2_6
-pkcs1_rsassa_pss_sign:1025:16:"016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1":16:"014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079":16:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"049f9154d871ac4a7c7ab45325ba7545a1ed08f70525b2667cf1":"37810def1055ed922b063df798de5d0aabf886ee":"00475b1648f814a8dc0abdc37b5527f543b666bb6e39d30e5b49d3b876dccc58eac14e32a2d55c2616014456ad2f246fc8e3d560da3ddf379a1c0bd200f10221df078c219a151bc8d4ec9d2fc2564467811014ef15d8ea01c2ebbff8c2c8efab38096e55fcbe3285c7aa558851254faffa92c1c72b78758663ef4582843139d7a6":0
+pkcs1_rsassa_pss_sign:1025:"016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1":"014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079":"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"049f9154d871ac4a7c7ab45325ba7545a1ed08f70525b2667cf1":"37810def1055ed922b063df798de5d0aabf886ee":"00475b1648f814a8dc0abdc37b5527f543b666bb6e39d30e5b49d3b876dccc58eac14e32a2d55c2616014456ad2f246fc8e3d560da3ddf379a1c0bd200f10221df078c219a151bc8d4ec9d2fc2564467811014ef15d8ea01c2ebbff8c2c8efab38096e55fcbe3285c7aa558851254faffa92c1c72b78758663ef4582843139d7a6":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 2_6 (verify)
-pkcs1_rsassa_pss_verify:1025:16:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"049f9154d871ac4a7c7ab45325ba7545a1ed08f70525b2667cf1":"37810def1055ed922b063df798de5d0aabf886ee":"00475b1648f814a8dc0abdc37b5527f543b666bb6e39d30e5b49d3b876dccc58eac14e32a2d55c2616014456ad2f246fc8e3d560da3ddf379a1c0bd200f10221df078c219a151bc8d4ec9d2fc2564467811014ef15d8ea01c2ebbff8c2c8efab38096e55fcbe3285c7aa558851254faffa92c1c72b78758663ef4582843139d7a6":0
+pkcs1_rsassa_pss_verify:1025:"01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"049f9154d871ac4a7c7ab45325ba7545a1ed08f70525b2667cf1":"37810def1055ed922b063df798de5d0aabf886ee":"00475b1648f814a8dc0abdc37b5527f543b666bb6e39d30e5b49d3b876dccc58eac14e32a2d55c2616014456ad2f246fc8e3d560da3ddf379a1c0bd200f10221df078c219a151bc8d4ec9d2fc2564467811014ef15d8ea01c2ebbff8c2c8efab38096e55fcbe3285c7aa558851254faffa92c1c72b78758663ef4582843139d7a6":0
 
 RSASSA-PSS Signature Example 3_1
-pkcs1_rsassa_pss_sign:1026:16:"01bd36e18ece4b0fdb2e9c9d548bd1a7d6e2c21c6fdc35074a1d05b1c6c8b3d558ea2639c9a9a421680169317252558bd148ad215aac550e2dcf12a82d0ebfe853":16:"01b1b656ad86d8e19d5dc86292b3a192fdf6e0dd37877bad14822fa00190cab265f90d3f02057b6f54d6ecb14491e5adeacebc48bf0ebd2a2ad26d402e54f61651":16:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"594b37333bbb2c84524a87c1a01f75fcec0e3256f108e38dca36d70d0057":"f31ad6c8cf89df78ed77feacbcc2f8b0a8e4cfaa":"0088b135fb1794b6b96c4a3e678197f8cac52b64b2fe907d6f27de761124964a99a01a882740ecfaed6c01a47464bb05182313c01338a8cd097214cd68ca103bd57d3bc9e816213e61d784f182467abf8a01cf253e99a156eaa8e3e1f90e3c6e4e3aa2d83ed0345b89fafc9c26077c14b6ac51454fa26e446e3a2f153b2b16797f":0
+pkcs1_rsassa_pss_sign:1026:"01bd36e18ece4b0fdb2e9c9d548bd1a7d6e2c21c6fdc35074a1d05b1c6c8b3d558ea2639c9a9a421680169317252558bd148ad215aac550e2dcf12a82d0ebfe853":"01b1b656ad86d8e19d5dc86292b3a192fdf6e0dd37877bad14822fa00190cab265f90d3f02057b6f54d6ecb14491e5adeacebc48bf0ebd2a2ad26d402e54f61651":"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"594b37333bbb2c84524a87c1a01f75fcec0e3256f108e38dca36d70d0057":"f31ad6c8cf89df78ed77feacbcc2f8b0a8e4cfaa":"0088b135fb1794b6b96c4a3e678197f8cac52b64b2fe907d6f27de761124964a99a01a882740ecfaed6c01a47464bb05182313c01338a8cd097214cd68ca103bd57d3bc9e816213e61d784f182467abf8a01cf253e99a156eaa8e3e1f90e3c6e4e3aa2d83ed0345b89fafc9c26077c14b6ac51454fa26e446e3a2f153b2b16797f":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 3_1 (verify)
-pkcs1_rsassa_pss_verify:1026:16:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"594b37333bbb2c84524a87c1a01f75fcec0e3256f108e38dca36d70d0057":"f31ad6c8cf89df78ed77feacbcc2f8b0a8e4cfaa":"0088b135fb1794b6b96c4a3e678197f8cac52b64b2fe907d6f27de761124964a99a01a882740ecfaed6c01a47464bb05182313c01338a8cd097214cd68ca103bd57d3bc9e816213e61d784f182467abf8a01cf253e99a156eaa8e3e1f90e3c6e4e3aa2d83ed0345b89fafc9c26077c14b6ac51454fa26e446e3a2f153b2b16797f":0
+pkcs1_rsassa_pss_verify:1026:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"594b37333bbb2c84524a87c1a01f75fcec0e3256f108e38dca36d70d0057":"f31ad6c8cf89df78ed77feacbcc2f8b0a8e4cfaa":"0088b135fb1794b6b96c4a3e678197f8cac52b64b2fe907d6f27de761124964a99a01a882740ecfaed6c01a47464bb05182313c01338a8cd097214cd68ca103bd57d3bc9e816213e61d784f182467abf8a01cf253e99a156eaa8e3e1f90e3c6e4e3aa2d83ed0345b89fafc9c26077c14b6ac51454fa26e446e3a2f153b2b16797f":0
 
 RSASSA-PSS Signature Example 3_2
-pkcs1_rsassa_pss_sign:1026:16:"01bd36e18ece4b0fdb2e9c9d548bd1a7d6e2c21c6fdc35074a1d05b1c6c8b3d558ea2639c9a9a421680169317252558bd148ad215aac550e2dcf12a82d0ebfe853":16:"01b1b656ad86d8e19d5dc86292b3a192fdf6e0dd37877bad14822fa00190cab265f90d3f02057b6f54d6ecb14491e5adeacebc48bf0ebd2a2ad26d402e54f61651":16:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"8b769528884a0d1ffd090cf102993e796dadcfbddd38e44ff6324ca451":"fcf9f0e1f199a3d1d0da681c5b8606fc642939f7":"02a5f0a858a0864a4f65017a7d69454f3f973a2999839b7bbc48bf78641169179556f595fa41f6ff18e286c2783079bc0910ee9cc34f49ba681124f923dfa88f426141a368a5f5a930c628c2c3c200e18a7644721a0cbec6dd3f6279bde3e8f2be5e2d4ee56f97e7ceaf33054be7042bd91a63bb09f897bd41e81197dee99b11af":0
+pkcs1_rsassa_pss_sign:1026:"01bd36e18ece4b0fdb2e9c9d548bd1a7d6e2c21c6fdc35074a1d05b1c6c8b3d558ea2639c9a9a421680169317252558bd148ad215aac550e2dcf12a82d0ebfe853":"01b1b656ad86d8e19d5dc86292b3a192fdf6e0dd37877bad14822fa00190cab265f90d3f02057b6f54d6ecb14491e5adeacebc48bf0ebd2a2ad26d402e54f61651":"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"8b769528884a0d1ffd090cf102993e796dadcfbddd38e44ff6324ca451":"fcf9f0e1f199a3d1d0da681c5b8606fc642939f7":"02a5f0a858a0864a4f65017a7d69454f3f973a2999839b7bbc48bf78641169179556f595fa41f6ff18e286c2783079bc0910ee9cc34f49ba681124f923dfa88f426141a368a5f5a930c628c2c3c200e18a7644721a0cbec6dd3f6279bde3e8f2be5e2d4ee56f97e7ceaf33054be7042bd91a63bb09f897bd41e81197dee99b11af":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 3_2 (verify)
-pkcs1_rsassa_pss_verify:1026:16:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"8b769528884a0d1ffd090cf102993e796dadcfbddd38e44ff6324ca451":"fcf9f0e1f199a3d1d0da681c5b8606fc642939f7":"02a5f0a858a0864a4f65017a7d69454f3f973a2999839b7bbc48bf78641169179556f595fa41f6ff18e286c2783079bc0910ee9cc34f49ba681124f923dfa88f426141a368a5f5a930c628c2c3c200e18a7644721a0cbec6dd3f6279bde3e8f2be5e2d4ee56f97e7ceaf33054be7042bd91a63bb09f897bd41e81197dee99b11af":0
+pkcs1_rsassa_pss_verify:1026:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"8b769528884a0d1ffd090cf102993e796dadcfbddd38e44ff6324ca451":"fcf9f0e1f199a3d1d0da681c5b8606fc642939f7":"02a5f0a858a0864a4f65017a7d69454f3f973a2999839b7bbc48bf78641169179556f595fa41f6ff18e286c2783079bc0910ee9cc34f49ba681124f923dfa88f426141a368a5f5a930c628c2c3c200e18a7644721a0cbec6dd3f6279bde3e8f2be5e2d4ee56f97e7ceaf33054be7042bd91a63bb09f897bd41e81197dee99b11af":0
 
 RSASSA-PSS Signature Example 3_3
-pkcs1_rsassa_pss_sign:1026:16:"01bd36e18ece4b0fdb2e9c9d548bd1a7d6e2c21c6fdc35074a1d05b1c6c8b3d558ea2639c9a9a421680169317252558bd148ad215aac550e2dcf12a82d0ebfe853":16:"01b1b656ad86d8e19d5dc86292b3a192fdf6e0dd37877bad14822fa00190cab265f90d3f02057b6f54d6ecb14491e5adeacebc48bf0ebd2a2ad26d402e54f61651":16:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"1abdba489c5ada2f995ed16f19d5a94d9e6ec34a8d84f84557d26e5ef9b02b22887e3f9a4b690ad1149209c20c61431f0c017c36c2657b35d7b07d3f5ad8708507a9c1b831df835a56f831071814ea5d3d8d8f6ade40cba38b42db7a2d3d7a29c8f0a79a7838cf58a9757fa2fe4c40df9baa193bfc6f92b123ad57b07ace3e6ac068c9f106afd9eeb03b4f37c25dbfbcfb3071f6f9771766d072f3bb070af6605532973ae25051":"986e7c43dbb671bd41b9a7f4b6afc80e805f2423":"0244bcd1c8c16955736c803be401272e18cb990811b14f72db964124d5fa760649cbb57afb8755dbb62bf51f466cf23a0a1607576e983d778fceffa92df7548aea8ea4ecad2c29dd9f95bc07fe91ecf8bee255bfe8762fd7690aa9bfa4fa0849ef728c2c42c4532364522df2ab7f9f8a03b63f7a499175828668f5ef5a29e3802c":0
+pkcs1_rsassa_pss_sign:1026:"01bd36e18ece4b0fdb2e9c9d548bd1a7d6e2c21c6fdc35074a1d05b1c6c8b3d558ea2639c9a9a421680169317252558bd148ad215aac550e2dcf12a82d0ebfe853":"01b1b656ad86d8e19d5dc86292b3a192fdf6e0dd37877bad14822fa00190cab265f90d3f02057b6f54d6ecb14491e5adeacebc48bf0ebd2a2ad26d402e54f61651":"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"1abdba489c5ada2f995ed16f19d5a94d9e6ec34a8d84f84557d26e5ef9b02b22887e3f9a4b690ad1149209c20c61431f0c017c36c2657b35d7b07d3f5ad8708507a9c1b831df835a56f831071814ea5d3d8d8f6ade40cba38b42db7a2d3d7a29c8f0a79a7838cf58a9757fa2fe4c40df9baa193bfc6f92b123ad57b07ace3e6ac068c9f106afd9eeb03b4f37c25dbfbcfb3071f6f9771766d072f3bb070af6605532973ae25051":"986e7c43dbb671bd41b9a7f4b6afc80e805f2423":"0244bcd1c8c16955736c803be401272e18cb990811b14f72db964124d5fa760649cbb57afb8755dbb62bf51f466cf23a0a1607576e983d778fceffa92df7548aea8ea4ecad2c29dd9f95bc07fe91ecf8bee255bfe8762fd7690aa9bfa4fa0849ef728c2c42c4532364522df2ab7f9f8a03b63f7a499175828668f5ef5a29e3802c":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 3_3 (verify)
-pkcs1_rsassa_pss_verify:1026:16:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"1abdba489c5ada2f995ed16f19d5a94d9e6ec34a8d84f84557d26e5ef9b02b22887e3f9a4b690ad1149209c20c61431f0c017c36c2657b35d7b07d3f5ad8708507a9c1b831df835a56f831071814ea5d3d8d8f6ade40cba38b42db7a2d3d7a29c8f0a79a7838cf58a9757fa2fe4c40df9baa193bfc6f92b123ad57b07ace3e6ac068c9f106afd9eeb03b4f37c25dbfbcfb3071f6f9771766d072f3bb070af6605532973ae25051":"986e7c43dbb671bd41b9a7f4b6afc80e805f2423":"0244bcd1c8c16955736c803be401272e18cb990811b14f72db964124d5fa760649cbb57afb8755dbb62bf51f466cf23a0a1607576e983d778fceffa92df7548aea8ea4ecad2c29dd9f95bc07fe91ecf8bee255bfe8762fd7690aa9bfa4fa0849ef728c2c42c4532364522df2ab7f9f8a03b63f7a499175828668f5ef5a29e3802c":0
+pkcs1_rsassa_pss_verify:1026:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"1abdba489c5ada2f995ed16f19d5a94d9e6ec34a8d84f84557d26e5ef9b02b22887e3f9a4b690ad1149209c20c61431f0c017c36c2657b35d7b07d3f5ad8708507a9c1b831df835a56f831071814ea5d3d8d8f6ade40cba38b42db7a2d3d7a29c8f0a79a7838cf58a9757fa2fe4c40df9baa193bfc6f92b123ad57b07ace3e6ac068c9f106afd9eeb03b4f37c25dbfbcfb3071f6f9771766d072f3bb070af6605532973ae25051":"986e7c43dbb671bd41b9a7f4b6afc80e805f2423":"0244bcd1c8c16955736c803be401272e18cb990811b14f72db964124d5fa760649cbb57afb8755dbb62bf51f466cf23a0a1607576e983d778fceffa92df7548aea8ea4ecad2c29dd9f95bc07fe91ecf8bee255bfe8762fd7690aa9bfa4fa0849ef728c2c42c4532364522df2ab7f9f8a03b63f7a499175828668f5ef5a29e3802c":0
 
 RSASSA-PSS Signature Example 3_4
-pkcs1_rsassa_pss_sign:1026:16:"01bd36e18ece4b0fdb2e9c9d548bd1a7d6e2c21c6fdc35074a1d05b1c6c8b3d558ea2639c9a9a421680169317252558bd148ad215aac550e2dcf12a82d0ebfe853":16:"01b1b656ad86d8e19d5dc86292b3a192fdf6e0dd37877bad14822fa00190cab265f90d3f02057b6f54d6ecb14491e5adeacebc48bf0ebd2a2ad26d402e54f61651":16:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"8fb431f5ee792b6c2ac7db53cc428655aeb32d03f4e889c5c25de683c461b53acf89f9f8d3aabdf6b9f0c2a1de12e15b49edb3919a652fe9491c25a7fce1f722c2543608b69dc375ec":"f8312d9c8eea13ec0a4c7b98120c87509087c478":"0196f12a005b98129c8df13c4cb16f8aa887d3c40d96df3a88e7532ef39cd992f273abc370bc1be6f097cfebbf0118fd9ef4b927155f3df22b904d90702d1f7ba7a52bed8b8942f412cd7bd676c9d18e170391dcd345c06a730964b3f30bcce0bb20ba106f9ab0eeb39cf8a6607f75c0347f0af79f16afa081d2c92d1ee6f836b8":0
+pkcs1_rsassa_pss_sign:1026:"01bd36e18ece4b0fdb2e9c9d548bd1a7d6e2c21c6fdc35074a1d05b1c6c8b3d558ea2639c9a9a421680169317252558bd148ad215aac550e2dcf12a82d0ebfe853":"01b1b656ad86d8e19d5dc86292b3a192fdf6e0dd37877bad14822fa00190cab265f90d3f02057b6f54d6ecb14491e5adeacebc48bf0ebd2a2ad26d402e54f61651":"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"8fb431f5ee792b6c2ac7db53cc428655aeb32d03f4e889c5c25de683c461b53acf89f9f8d3aabdf6b9f0c2a1de12e15b49edb3919a652fe9491c25a7fce1f722c2543608b69dc375ec":"f8312d9c8eea13ec0a4c7b98120c87509087c478":"0196f12a005b98129c8df13c4cb16f8aa887d3c40d96df3a88e7532ef39cd992f273abc370bc1be6f097cfebbf0118fd9ef4b927155f3df22b904d90702d1f7ba7a52bed8b8942f412cd7bd676c9d18e170391dcd345c06a730964b3f30bcce0bb20ba106f9ab0eeb39cf8a6607f75c0347f0af79f16afa081d2c92d1ee6f836b8":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 3_4 (verify)
-pkcs1_rsassa_pss_verify:1026:16:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"8fb431f5ee792b6c2ac7db53cc428655aeb32d03f4e889c5c25de683c461b53acf89f9f8d3aabdf6b9f0c2a1de12e15b49edb3919a652fe9491c25a7fce1f722c2543608b69dc375ec":"f8312d9c8eea13ec0a4c7b98120c87509087c478":"0196f12a005b98129c8df13c4cb16f8aa887d3c40d96df3a88e7532ef39cd992f273abc370bc1be6f097cfebbf0118fd9ef4b927155f3df22b904d90702d1f7ba7a52bed8b8942f412cd7bd676c9d18e170391dcd345c06a730964b3f30bcce0bb20ba106f9ab0eeb39cf8a6607f75c0347f0af79f16afa081d2c92d1ee6f836b8":0
+pkcs1_rsassa_pss_verify:1026:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"8fb431f5ee792b6c2ac7db53cc428655aeb32d03f4e889c5c25de683c461b53acf89f9f8d3aabdf6b9f0c2a1de12e15b49edb3919a652fe9491c25a7fce1f722c2543608b69dc375ec":"f8312d9c8eea13ec0a4c7b98120c87509087c478":"0196f12a005b98129c8df13c4cb16f8aa887d3c40d96df3a88e7532ef39cd992f273abc370bc1be6f097cfebbf0118fd9ef4b927155f3df22b904d90702d1f7ba7a52bed8b8942f412cd7bd676c9d18e170391dcd345c06a730964b3f30bcce0bb20ba106f9ab0eeb39cf8a6607f75c0347f0af79f16afa081d2c92d1ee6f836b8":0
 
 RSASSA-PSS Signature Example 3_5
-pkcs1_rsassa_pss_sign:1026:16:"01bd36e18ece4b0fdb2e9c9d548bd1a7d6e2c21c6fdc35074a1d05b1c6c8b3d558ea2639c9a9a421680169317252558bd148ad215aac550e2dcf12a82d0ebfe853":16:"01b1b656ad86d8e19d5dc86292b3a192fdf6e0dd37877bad14822fa00190cab265f90d3f02057b6f54d6ecb14491e5adeacebc48bf0ebd2a2ad26d402e54f61651":16:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"fef4161dfaaf9c5295051dfc1ff3810c8c9ec2e866f7075422c8ec4216a9c4ff49427d483cae10c8534a41b2fd15fee06960ec6fb3f7a7e94a2f8a2e3e43dc4a40576c3097ac953b1de86f0b4ed36d644f23ae14425529622464ca0cbf0b1741347238157fab59e4de5524096d62baec63ac64":"50327efec6292f98019fc67a2a6638563e9b6e2d":"021eca3ab4892264ec22411a752d92221076d4e01c0e6f0dde9afd26ba5acf6d739ef987545d16683e5674c9e70f1de649d7e61d48d0caeb4fb4d8b24fba84a6e3108fee7d0705973266ac524b4ad280f7ae17dc59d96d3351586b5a3bdb895d1e1f7820ac6135d8753480998382ba32b7349559608c38745290a85ef4e9f9bd83":0
+pkcs1_rsassa_pss_sign:1026:"01bd36e18ece4b0fdb2e9c9d548bd1a7d6e2c21c6fdc35074a1d05b1c6c8b3d558ea2639c9a9a421680169317252558bd148ad215aac550e2dcf12a82d0ebfe853":"01b1b656ad86d8e19d5dc86292b3a192fdf6e0dd37877bad14822fa00190cab265f90d3f02057b6f54d6ecb14491e5adeacebc48bf0ebd2a2ad26d402e54f61651":"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"fef4161dfaaf9c5295051dfc1ff3810c8c9ec2e866f7075422c8ec4216a9c4ff49427d483cae10c8534a41b2fd15fee06960ec6fb3f7a7e94a2f8a2e3e43dc4a40576c3097ac953b1de86f0b4ed36d644f23ae14425529622464ca0cbf0b1741347238157fab59e4de5524096d62baec63ac64":"50327efec6292f98019fc67a2a6638563e9b6e2d":"021eca3ab4892264ec22411a752d92221076d4e01c0e6f0dde9afd26ba5acf6d739ef987545d16683e5674c9e70f1de649d7e61d48d0caeb4fb4d8b24fba84a6e3108fee7d0705973266ac524b4ad280f7ae17dc59d96d3351586b5a3bdb895d1e1f7820ac6135d8753480998382ba32b7349559608c38745290a85ef4e9f9bd83":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 3_5 (verify)
-pkcs1_rsassa_pss_verify:1026:16:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"fef4161dfaaf9c5295051dfc1ff3810c8c9ec2e866f7075422c8ec4216a9c4ff49427d483cae10c8534a41b2fd15fee06960ec6fb3f7a7e94a2f8a2e3e43dc4a40576c3097ac953b1de86f0b4ed36d644f23ae14425529622464ca0cbf0b1741347238157fab59e4de5524096d62baec63ac64":"50327efec6292f98019fc67a2a6638563e9b6e2d":"021eca3ab4892264ec22411a752d92221076d4e01c0e6f0dde9afd26ba5acf6d739ef987545d16683e5674c9e70f1de649d7e61d48d0caeb4fb4d8b24fba84a6e3108fee7d0705973266ac524b4ad280f7ae17dc59d96d3351586b5a3bdb895d1e1f7820ac6135d8753480998382ba32b7349559608c38745290a85ef4e9f9bd83":0
+pkcs1_rsassa_pss_verify:1026:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"fef4161dfaaf9c5295051dfc1ff3810c8c9ec2e866f7075422c8ec4216a9c4ff49427d483cae10c8534a41b2fd15fee06960ec6fb3f7a7e94a2f8a2e3e43dc4a40576c3097ac953b1de86f0b4ed36d644f23ae14425529622464ca0cbf0b1741347238157fab59e4de5524096d62baec63ac64":"50327efec6292f98019fc67a2a6638563e9b6e2d":"021eca3ab4892264ec22411a752d92221076d4e01c0e6f0dde9afd26ba5acf6d739ef987545d16683e5674c9e70f1de649d7e61d48d0caeb4fb4d8b24fba84a6e3108fee7d0705973266ac524b4ad280f7ae17dc59d96d3351586b5a3bdb895d1e1f7820ac6135d8753480998382ba32b7349559608c38745290a85ef4e9f9bd83":0
 
 RSASSA-PSS Signature Example 3_6
-pkcs1_rsassa_pss_sign:1026:16:"01bd36e18ece4b0fdb2e9c9d548bd1a7d6e2c21c6fdc35074a1d05b1c6c8b3d558ea2639c9a9a421680169317252558bd148ad215aac550e2dcf12a82d0ebfe853":16:"01b1b656ad86d8e19d5dc86292b3a192fdf6e0dd37877bad14822fa00190cab265f90d3f02057b6f54d6ecb14491e5adeacebc48bf0ebd2a2ad26d402e54f61651":16:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"efd237bb098a443aeeb2bf6c3f8c81b8c01b7fcb3feb":"b0de3fc25b65f5af96b1d5cc3b27d0c6053087b3":"012fafec862f56e9e92f60ab0c77824f4299a0ca734ed26e0644d5d222c7f0bde03964f8e70a5cb65ed44e44d56ae0edf1ff86ca032cc5dd4404dbb76ab854586c44eed8336d08d457ce6c03693b45c0f1efef93624b95b8ec169c616d20e5538ebc0b6737a6f82b4bc0570924fc6b35759a3348426279f8b3d7744e2d222426ce":0
+pkcs1_rsassa_pss_sign:1026:"01bd36e18ece4b0fdb2e9c9d548bd1a7d6e2c21c6fdc35074a1d05b1c6c8b3d558ea2639c9a9a421680169317252558bd148ad215aac550e2dcf12a82d0ebfe853":"01b1b656ad86d8e19d5dc86292b3a192fdf6e0dd37877bad14822fa00190cab265f90d3f02057b6f54d6ecb14491e5adeacebc48bf0ebd2a2ad26d402e54f61651":"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"efd237bb098a443aeeb2bf6c3f8c81b8c01b7fcb3feb":"b0de3fc25b65f5af96b1d5cc3b27d0c6053087b3":"012fafec862f56e9e92f60ab0c77824f4299a0ca734ed26e0644d5d222c7f0bde03964f8e70a5cb65ed44e44d56ae0edf1ff86ca032cc5dd4404dbb76ab854586c44eed8336d08d457ce6c03693b45c0f1efef93624b95b8ec169c616d20e5538ebc0b6737a6f82b4bc0570924fc6b35759a3348426279f8b3d7744e2d222426ce":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 3_6 (verify)
-pkcs1_rsassa_pss_verify:1026:16:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"efd237bb098a443aeeb2bf6c3f8c81b8c01b7fcb3feb":"b0de3fc25b65f5af96b1d5cc3b27d0c6053087b3":"012fafec862f56e9e92f60ab0c77824f4299a0ca734ed26e0644d5d222c7f0bde03964f8e70a5cb65ed44e44d56ae0edf1ff86ca032cc5dd4404dbb76ab854586c44eed8336d08d457ce6c03693b45c0f1efef93624b95b8ec169c616d20e5538ebc0b6737a6f82b4bc0570924fc6b35759a3348426279f8b3d7744e2d222426ce":0
+pkcs1_rsassa_pss_verify:1026:"02f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a443":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"efd237bb098a443aeeb2bf6c3f8c81b8c01b7fcb3feb":"b0de3fc25b65f5af96b1d5cc3b27d0c6053087b3":"012fafec862f56e9e92f60ab0c77824f4299a0ca734ed26e0644d5d222c7f0bde03964f8e70a5cb65ed44e44d56ae0edf1ff86ca032cc5dd4404dbb76ab854586c44eed8336d08d457ce6c03693b45c0f1efef93624b95b8ec169c616d20e5538ebc0b6737a6f82b4bc0570924fc6b35759a3348426279f8b3d7744e2d222426ce":0
 
 RSASSA-PSS Signature Example 4_1
-pkcs1_rsassa_pss_sign:1027:16:"029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995":16:"020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1":16:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"9fb03b827c8217d9":"ed7c98c95f30974fbe4fbddcf0f28d6021c0e91d":"0323d5b7bf20ba4539289ae452ae4297080feff4518423ff4811a817837e7d82f1836cdfab54514ff0887bddeebf40bf99b047abc3ecfa6a37a3ef00f4a0c4a88aae0904b745c846c4107e8797723e8ac810d9e3d95dfa30ff4966f4d75d13768d20857f2b1406f264cfe75e27d7652f4b5ed3575f28a702f8c4ed9cf9b2d44948":0
+pkcs1_rsassa_pss_sign:1027:"029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995":"020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1":"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"9fb03b827c8217d9":"ed7c98c95f30974fbe4fbddcf0f28d6021c0e91d":"0323d5b7bf20ba4539289ae452ae4297080feff4518423ff4811a817837e7d82f1836cdfab54514ff0887bddeebf40bf99b047abc3ecfa6a37a3ef00f4a0c4a88aae0904b745c846c4107e8797723e8ac810d9e3d95dfa30ff4966f4d75d13768d20857f2b1406f264cfe75e27d7652f4b5ed3575f28a702f8c4ed9cf9b2d44948":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 4_1 (verify)
-pkcs1_rsassa_pss_verify:1027:16:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"9fb03b827c8217d9":"ed7c98c95f30974fbe4fbddcf0f28d6021c0e91d":"0323d5b7bf20ba4539289ae452ae4297080feff4518423ff4811a817837e7d82f1836cdfab54514ff0887bddeebf40bf99b047abc3ecfa6a37a3ef00f4a0c4a88aae0904b745c846c4107e8797723e8ac810d9e3d95dfa30ff4966f4d75d13768d20857f2b1406f264cfe75e27d7652f4b5ed3575f28a702f8c4ed9cf9b2d44948":0
+pkcs1_rsassa_pss_verify:1027:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"9fb03b827c8217d9":"ed7c98c95f30974fbe4fbddcf0f28d6021c0e91d":"0323d5b7bf20ba4539289ae452ae4297080feff4518423ff4811a817837e7d82f1836cdfab54514ff0887bddeebf40bf99b047abc3ecfa6a37a3ef00f4a0c4a88aae0904b745c846c4107e8797723e8ac810d9e3d95dfa30ff4966f4d75d13768d20857f2b1406f264cfe75e27d7652f4b5ed3575f28a702f8c4ed9cf9b2d44948":0
 
 RSASSA-PSS Signature Example 4_2
-pkcs1_rsassa_pss_sign:1027:16:"029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995":16:"020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1":16:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0ca2ad77797ece86de5bf768750ddb5ed6a3116ad99bbd17edf7f782f0db1cd05b0f677468c5ea420dc116b10e80d110de2b0461ea14a38be68620392e7e893cb4ea9393fb886c20ff790642305bf302003892e54df9f667509dc53920df583f50a3dd61abb6fab75d600377e383e6aca6710eeea27156e06752c94ce25ae99fcbf8592dbe2d7e27453cb44de07100ebb1a2a19811a478adbeab270f94e8fe369d90b3ca612f9f":"22d71d54363a4217aa55113f059b3384e3e57e44":"049d0185845a264d28feb1e69edaec090609e8e46d93abb38371ce51f4aa65a599bdaaa81d24fba66a08a116cb644f3f1e653d95c89db8bbd5daac2709c8984000178410a7c6aa8667ddc38c741f710ec8665aa9052be929d4e3b16782c1662114c5414bb0353455c392fc28f3db59054b5f365c49e1d156f876ee10cb4fd70598":0
+pkcs1_rsassa_pss_sign:1027:"029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995":"020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1":"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0ca2ad77797ece86de5bf768750ddb5ed6a3116ad99bbd17edf7f782f0db1cd05b0f677468c5ea420dc116b10e80d110de2b0461ea14a38be68620392e7e893cb4ea9393fb886c20ff790642305bf302003892e54df9f667509dc53920df583f50a3dd61abb6fab75d600377e383e6aca6710eeea27156e06752c94ce25ae99fcbf8592dbe2d7e27453cb44de07100ebb1a2a19811a478adbeab270f94e8fe369d90b3ca612f9f":"22d71d54363a4217aa55113f059b3384e3e57e44":"049d0185845a264d28feb1e69edaec090609e8e46d93abb38371ce51f4aa65a599bdaaa81d24fba66a08a116cb644f3f1e653d95c89db8bbd5daac2709c8984000178410a7c6aa8667ddc38c741f710ec8665aa9052be929d4e3b16782c1662114c5414bb0353455c392fc28f3db59054b5f365c49e1d156f876ee10cb4fd70598":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 4_2 (verify)
-pkcs1_rsassa_pss_verify:1027:16:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0ca2ad77797ece86de5bf768750ddb5ed6a3116ad99bbd17edf7f782f0db1cd05b0f677468c5ea420dc116b10e80d110de2b0461ea14a38be68620392e7e893cb4ea9393fb886c20ff790642305bf302003892e54df9f667509dc53920df583f50a3dd61abb6fab75d600377e383e6aca6710eeea27156e06752c94ce25ae99fcbf8592dbe2d7e27453cb44de07100ebb1a2a19811a478adbeab270f94e8fe369d90b3ca612f9f":"22d71d54363a4217aa55113f059b3384e3e57e44":"049d0185845a264d28feb1e69edaec090609e8e46d93abb38371ce51f4aa65a599bdaaa81d24fba66a08a116cb644f3f1e653d95c89db8bbd5daac2709c8984000178410a7c6aa8667ddc38c741f710ec8665aa9052be929d4e3b16782c1662114c5414bb0353455c392fc28f3db59054b5f365c49e1d156f876ee10cb4fd70598":0
+pkcs1_rsassa_pss_verify:1027:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0ca2ad77797ece86de5bf768750ddb5ed6a3116ad99bbd17edf7f782f0db1cd05b0f677468c5ea420dc116b10e80d110de2b0461ea14a38be68620392e7e893cb4ea9393fb886c20ff790642305bf302003892e54df9f667509dc53920df583f50a3dd61abb6fab75d600377e383e6aca6710eeea27156e06752c94ce25ae99fcbf8592dbe2d7e27453cb44de07100ebb1a2a19811a478adbeab270f94e8fe369d90b3ca612f9f":"22d71d54363a4217aa55113f059b3384e3e57e44":"049d0185845a264d28feb1e69edaec090609e8e46d93abb38371ce51f4aa65a599bdaaa81d24fba66a08a116cb644f3f1e653d95c89db8bbd5daac2709c8984000178410a7c6aa8667ddc38c741f710ec8665aa9052be929d4e3b16782c1662114c5414bb0353455c392fc28f3db59054b5f365c49e1d156f876ee10cb4fd70598":0
 
 RSASSA-PSS Signature Example 4_3
-pkcs1_rsassa_pss_sign:1027:16:"029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995":16:"020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1":16:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"288062afc08fcdb7c5f8650b29837300461dd5676c17a20a3c8fb5148949e3f73d66b3ae82c7240e27c5b3ec4328ee7d6ddf6a6a0c9b5b15bcda196a9d0c76b119d534d85abd123962d583b76ce9d180bce1ca":"4af870fbc6516012ca916c70ba862ac7e8243617":"03fbc410a2ced59500fb99f9e2af2781ada74e13145624602782e2994813eefca0519ecd253b855fb626a90d771eae028b0c47a199cbd9f8e3269734af4163599090713a3fa910fa0960652721432b971036a7181a2bc0cab43b0b598bc6217461d7db305ff7e954c5b5bb231c39e791af6bcfa76b147b081321f72641482a2aad":0
+pkcs1_rsassa_pss_sign:1027:"029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995":"020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1":"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"288062afc08fcdb7c5f8650b29837300461dd5676c17a20a3c8fb5148949e3f73d66b3ae82c7240e27c5b3ec4328ee7d6ddf6a6a0c9b5b15bcda196a9d0c76b119d534d85abd123962d583b76ce9d180bce1ca":"4af870fbc6516012ca916c70ba862ac7e8243617":"03fbc410a2ced59500fb99f9e2af2781ada74e13145624602782e2994813eefca0519ecd253b855fb626a90d771eae028b0c47a199cbd9f8e3269734af4163599090713a3fa910fa0960652721432b971036a7181a2bc0cab43b0b598bc6217461d7db305ff7e954c5b5bb231c39e791af6bcfa76b147b081321f72641482a2aad":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 4_3 (verify)
-pkcs1_rsassa_pss_verify:1027:16:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"288062afc08fcdb7c5f8650b29837300461dd5676c17a20a3c8fb5148949e3f73d66b3ae82c7240e27c5b3ec4328ee7d6ddf6a6a0c9b5b15bcda196a9d0c76b119d534d85abd123962d583b76ce9d180bce1ca":"4af870fbc6516012ca916c70ba862ac7e8243617":"03fbc410a2ced59500fb99f9e2af2781ada74e13145624602782e2994813eefca0519ecd253b855fb626a90d771eae028b0c47a199cbd9f8e3269734af4163599090713a3fa910fa0960652721432b971036a7181a2bc0cab43b0b598bc6217461d7db305ff7e954c5b5bb231c39e791af6bcfa76b147b081321f72641482a2aad":0
+pkcs1_rsassa_pss_verify:1027:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"288062afc08fcdb7c5f8650b29837300461dd5676c17a20a3c8fb5148949e3f73d66b3ae82c7240e27c5b3ec4328ee7d6ddf6a6a0c9b5b15bcda196a9d0c76b119d534d85abd123962d583b76ce9d180bce1ca":"4af870fbc6516012ca916c70ba862ac7e8243617":"03fbc410a2ced59500fb99f9e2af2781ada74e13145624602782e2994813eefca0519ecd253b855fb626a90d771eae028b0c47a199cbd9f8e3269734af4163599090713a3fa910fa0960652721432b971036a7181a2bc0cab43b0b598bc6217461d7db305ff7e954c5b5bb231c39e791af6bcfa76b147b081321f72641482a2aad":0
 
 RSASSA-PSS Signature Example 4_4
-pkcs1_rsassa_pss_sign:1027:16:"029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995":16:"020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1":16:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"6f4f9ab9501199cef55c6cf408fe7b36c557c49d420a4763d2463c8ad44b3cfc5be2742c0e7d9b0f6608f08c7f47b693ee":"40d2e180fae1eac439c190b56c2c0e14ddf9a226":"0486644bc66bf75d28335a6179b10851f43f09bded9fac1af33252bb9953ba4298cd6466b27539a70adaa3f89b3db3c74ab635d122f4ee7ce557a61e59b82ffb786630e5f9db53c77d9a0c12fab5958d4c2ce7daa807cd89ba2cc7fcd02ff470ca67b229fcce814c852c73cc93bea35be68459ce478e9d4655d121c8472f371d4f":0
+pkcs1_rsassa_pss_sign:1027:"029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995":"020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1":"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"6f4f9ab9501199cef55c6cf408fe7b36c557c49d420a4763d2463c8ad44b3cfc5be2742c0e7d9b0f6608f08c7f47b693ee":"40d2e180fae1eac439c190b56c2c0e14ddf9a226":"0486644bc66bf75d28335a6179b10851f43f09bded9fac1af33252bb9953ba4298cd6466b27539a70adaa3f89b3db3c74ab635d122f4ee7ce557a61e59b82ffb786630e5f9db53c77d9a0c12fab5958d4c2ce7daa807cd89ba2cc7fcd02ff470ca67b229fcce814c852c73cc93bea35be68459ce478e9d4655d121c8472f371d4f":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 4_4 (verify)
-pkcs1_rsassa_pss_verify:1027:16:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"6f4f9ab9501199cef55c6cf408fe7b36c557c49d420a4763d2463c8ad44b3cfc5be2742c0e7d9b0f6608f08c7f47b693ee":"40d2e180fae1eac439c190b56c2c0e14ddf9a226":"0486644bc66bf75d28335a6179b10851f43f09bded9fac1af33252bb9953ba4298cd6466b27539a70adaa3f89b3db3c74ab635d122f4ee7ce557a61e59b82ffb786630e5f9db53c77d9a0c12fab5958d4c2ce7daa807cd89ba2cc7fcd02ff470ca67b229fcce814c852c73cc93bea35be68459ce478e9d4655d121c8472f371d4f":0
+pkcs1_rsassa_pss_verify:1027:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"6f4f9ab9501199cef55c6cf408fe7b36c557c49d420a4763d2463c8ad44b3cfc5be2742c0e7d9b0f6608f08c7f47b693ee":"40d2e180fae1eac439c190b56c2c0e14ddf9a226":"0486644bc66bf75d28335a6179b10851f43f09bded9fac1af33252bb9953ba4298cd6466b27539a70adaa3f89b3db3c74ab635d122f4ee7ce557a61e59b82ffb786630e5f9db53c77d9a0c12fab5958d4c2ce7daa807cd89ba2cc7fcd02ff470ca67b229fcce814c852c73cc93bea35be68459ce478e9d4655d121c8472f371d4f":0
 
 RSASSA-PSS Signature Example 4_5
-pkcs1_rsassa_pss_sign:1027:16:"029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995":16:"020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1":16:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e17d20385d501955823c3f666254c1d3dd36ad5168b8f18d286fdcf67a7dad94097085fab7ed86fe2142a28771717997ef1a7a08884efc39356d76077aaf82459a7fad45848875f2819b098937fe923bcc9dc442d72d754d812025090c9bc03db3080c138dd63b355d0b4b85d6688ac19f4de15084a0ba4e373b93ef4a555096691915dc23c00e954cdeb20a47cd55d16c3d8681d46ed7f2ed5ea42795be17baed25f0f4d113b3636addd585f16a8b5aec0c8fa9c5f03cbf3b9b73":"2497dc2b4615dfae5a663d49ffd56bf7efc11304":"022a80045353904cb30cbb542d7d4990421a6eec16a8029a8422adfd22d6aff8c4cc0294af110a0c067ec86a7d364134459bb1ae8ff836d5a8a2579840996b320b19f13a13fad378d931a65625dae2739f0c53670b35d9d3cbac08e733e4ec2b83af4b9196d63e7c4ff1ddeae2a122791a125bfea8deb0de8ccf1f4ffaf6e6fb0a":0
+pkcs1_rsassa_pss_sign:1027:"029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995":"020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1":"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e17d20385d501955823c3f666254c1d3dd36ad5168b8f18d286fdcf67a7dad94097085fab7ed86fe2142a28771717997ef1a7a08884efc39356d76077aaf82459a7fad45848875f2819b098937fe923bcc9dc442d72d754d812025090c9bc03db3080c138dd63b355d0b4b85d6688ac19f4de15084a0ba4e373b93ef4a555096691915dc23c00e954cdeb20a47cd55d16c3d8681d46ed7f2ed5ea42795be17baed25f0f4d113b3636addd585f16a8b5aec0c8fa9c5f03cbf3b9b73":"2497dc2b4615dfae5a663d49ffd56bf7efc11304":"022a80045353904cb30cbb542d7d4990421a6eec16a8029a8422adfd22d6aff8c4cc0294af110a0c067ec86a7d364134459bb1ae8ff836d5a8a2579840996b320b19f13a13fad378d931a65625dae2739f0c53670b35d9d3cbac08e733e4ec2b83af4b9196d63e7c4ff1ddeae2a122791a125bfea8deb0de8ccf1f4ffaf6e6fb0a":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 4_5 (verify)
-pkcs1_rsassa_pss_verify:1027:16:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e17d20385d501955823c3f666254c1d3dd36ad5168b8f18d286fdcf67a7dad94097085fab7ed86fe2142a28771717997ef1a7a08884efc39356d76077aaf82459a7fad45848875f2819b098937fe923bcc9dc442d72d754d812025090c9bc03db3080c138dd63b355d0b4b85d6688ac19f4de15084a0ba4e373b93ef4a555096691915dc23c00e954cdeb20a47cd55d16c3d8681d46ed7f2ed5ea42795be17baed25f0f4d113b3636addd585f16a8b5aec0c8fa9c5f03cbf3b9b73":"2497dc2b4615dfae5a663d49ffd56bf7efc11304":"022a80045353904cb30cbb542d7d4990421a6eec16a8029a8422adfd22d6aff8c4cc0294af110a0c067ec86a7d364134459bb1ae8ff836d5a8a2579840996b320b19f13a13fad378d931a65625dae2739f0c53670b35d9d3cbac08e733e4ec2b83af4b9196d63e7c4ff1ddeae2a122791a125bfea8deb0de8ccf1f4ffaf6e6fb0a":0
+pkcs1_rsassa_pss_verify:1027:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e17d20385d501955823c3f666254c1d3dd36ad5168b8f18d286fdcf67a7dad94097085fab7ed86fe2142a28771717997ef1a7a08884efc39356d76077aaf82459a7fad45848875f2819b098937fe923bcc9dc442d72d754d812025090c9bc03db3080c138dd63b355d0b4b85d6688ac19f4de15084a0ba4e373b93ef4a555096691915dc23c00e954cdeb20a47cd55d16c3d8681d46ed7f2ed5ea42795be17baed25f0f4d113b3636addd585f16a8b5aec0c8fa9c5f03cbf3b9b73":"2497dc2b4615dfae5a663d49ffd56bf7efc11304":"022a80045353904cb30cbb542d7d4990421a6eec16a8029a8422adfd22d6aff8c4cc0294af110a0c067ec86a7d364134459bb1ae8ff836d5a8a2579840996b320b19f13a13fad378d931a65625dae2739f0c53670b35d9d3cbac08e733e4ec2b83af4b9196d63e7c4ff1ddeae2a122791a125bfea8deb0de8ccf1f4ffaf6e6fb0a":0
 
 RSASSA-PSS Signature Example 4_6
-pkcs1_rsassa_pss_sign:1027:16:"029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995":16:"020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1":16:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"afbc19d479249018fdf4e09f618726440495de11ddeee38872d775fcea74a23896b5343c9c38d46af0dba224d047580cc60a65e9391cf9b59b36a860598d4e8216722f993b91cfae87bc255af89a6a199bca4a391eadbc3a24903c0bd667368f6be78e3feabfb4ffd463122763740ffbbefeab9a25564bc5d1c24c93e422f75073e2ad72bf45b10df00b52a147128e73fee33fa3f0577d77f80fbc2df1bed313290c12777f50":"a334db6faebf11081a04f87c2d621cdec7930b9b":"00938dcb6d583046065f69c78da7a1f1757066a7fa75125a9d2929f0b79a60b627b082f11f5b196f28eb9daa6f21c05e5140f6aef1737d2023075c05ecf04a028c686a2ab3e7d5a0664f295ce12995e890908b6ad21f0839eb65b70393a7b5afd9871de0caa0cedec5b819626756209d13ab1e7bb9546a26ff37e9a51af9fd562e":0
+pkcs1_rsassa_pss_sign:1027:"029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995":"020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1":"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"afbc19d479249018fdf4e09f618726440495de11ddeee38872d775fcea74a23896b5343c9c38d46af0dba224d047580cc60a65e9391cf9b59b36a860598d4e8216722f993b91cfae87bc255af89a6a199bca4a391eadbc3a24903c0bd667368f6be78e3feabfb4ffd463122763740ffbbefeab9a25564bc5d1c24c93e422f75073e2ad72bf45b10df00b52a147128e73fee33fa3f0577d77f80fbc2df1bed313290c12777f50":"a334db6faebf11081a04f87c2d621cdec7930b9b":"00938dcb6d583046065f69c78da7a1f1757066a7fa75125a9d2929f0b79a60b627b082f11f5b196f28eb9daa6f21c05e5140f6aef1737d2023075c05ecf04a028c686a2ab3e7d5a0664f295ce12995e890908b6ad21f0839eb65b70393a7b5afd9871de0caa0cedec5b819626756209d13ab1e7bb9546a26ff37e9a51af9fd562e":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 4_6 (verify)
-pkcs1_rsassa_pss_verify:1027:16:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"afbc19d479249018fdf4e09f618726440495de11ddeee38872d775fcea74a23896b5343c9c38d46af0dba224d047580cc60a65e9391cf9b59b36a860598d4e8216722f993b91cfae87bc255af89a6a199bca4a391eadbc3a24903c0bd667368f6be78e3feabfb4ffd463122763740ffbbefeab9a25564bc5d1c24c93e422f75073e2ad72bf45b10df00b52a147128e73fee33fa3f0577d77f80fbc2df1bed313290c12777f50":"a334db6faebf11081a04f87c2d621cdec7930b9b":"00938dcb6d583046065f69c78da7a1f1757066a7fa75125a9d2929f0b79a60b627b082f11f5b196f28eb9daa6f21c05e5140f6aef1737d2023075c05ecf04a028c686a2ab3e7d5a0664f295ce12995e890908b6ad21f0839eb65b70393a7b5afd9871de0caa0cedec5b819626756209d13ab1e7bb9546a26ff37e9a51af9fd562e":0
+pkcs1_rsassa_pss_verify:1027:"054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"afbc19d479249018fdf4e09f618726440495de11ddeee38872d775fcea74a23896b5343c9c38d46af0dba224d047580cc60a65e9391cf9b59b36a860598d4e8216722f993b91cfae87bc255af89a6a199bca4a391eadbc3a24903c0bd667368f6be78e3feabfb4ffd463122763740ffbbefeab9a25564bc5d1c24c93e422f75073e2ad72bf45b10df00b52a147128e73fee33fa3f0577d77f80fbc2df1bed313290c12777f50":"a334db6faebf11081a04f87c2d621cdec7930b9b":"00938dcb6d583046065f69c78da7a1f1757066a7fa75125a9d2929f0b79a60b627b082f11f5b196f28eb9daa6f21c05e5140f6aef1737d2023075c05ecf04a028c686a2ab3e7d5a0664f295ce12995e890908b6ad21f0839eb65b70393a7b5afd9871de0caa0cedec5b819626756209d13ab1e7bb9546a26ff37e9a51af9fd562e":0
 
 RSASSA-PSS Signature Example 5_1
-pkcs1_rsassa_pss_sign:1028:16:"03f2f331f4142d4f24b43aa10279a89652d4e7537221a1a7b2a25deb551e5de9ac497411c227a94e45f91c2d1c13cc046cf4ce14e32d058734210d44a87ee1b73f":16:"034f090d73b55803030cf0361a5d8081bfb79f851523feac0a2124d08d4013ff08487771a870d0479dc0686c62f7718dfecf024b17c9267678059171339cc00839":16:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"30c7d557458b436decfdc14d06cb7b96b06718c48d7de57482a868ae7f065870a6216506d11b779323dfdf046cf5775129134b4d5689e4d9c0ce1e12d7d4b06cb5fc5820decfa41baf59bf257b32f025b7679b445b9499c92555145885992f1b76f84891ee4d3be0f5150fd5901e3a4c8ed43fd36b61d022e65ad5008dbf33293c22bfbfd07321f0f1d5fa9fdf0014c2fcb0358aad0e354b0d29":"081b233b43567750bd6e78f396a88b9f6a445151":"0ba373f76e0921b70a8fbfe622f0bf77b28a3db98e361051c3d7cb92ad0452915a4de9c01722f6823eeb6adf7e0ca8290f5de3e549890ac2a3c5950ab217ba58590894952de96f8df111b2575215da6c161590c745be612476ee578ed384ab33e3ece97481a252f5c79a98b5532ae00cdd62f2ecc0cd1baefe80d80b962193ec1d":0
+pkcs1_rsassa_pss_sign:1028:"03f2f331f4142d4f24b43aa10279a89652d4e7537221a1a7b2a25deb551e5de9ac497411c227a94e45f91c2d1c13cc046cf4ce14e32d058734210d44a87ee1b73f":"034f090d73b55803030cf0361a5d8081bfb79f851523feac0a2124d08d4013ff08487771a870d0479dc0686c62f7718dfecf024b17c9267678059171339cc00839":"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"30c7d557458b436decfdc14d06cb7b96b06718c48d7de57482a868ae7f065870a6216506d11b779323dfdf046cf5775129134b4d5689e4d9c0ce1e12d7d4b06cb5fc5820decfa41baf59bf257b32f025b7679b445b9499c92555145885992f1b76f84891ee4d3be0f5150fd5901e3a4c8ed43fd36b61d022e65ad5008dbf33293c22bfbfd07321f0f1d5fa9fdf0014c2fcb0358aad0e354b0d29":"081b233b43567750bd6e78f396a88b9f6a445151":"0ba373f76e0921b70a8fbfe622f0bf77b28a3db98e361051c3d7cb92ad0452915a4de9c01722f6823eeb6adf7e0ca8290f5de3e549890ac2a3c5950ab217ba58590894952de96f8df111b2575215da6c161590c745be612476ee578ed384ab33e3ece97481a252f5c79a98b5532ae00cdd62f2ecc0cd1baefe80d80b962193ec1d":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 5_1 (verify)
-pkcs1_rsassa_pss_verify:1028:16:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"30c7d557458b436decfdc14d06cb7b96b06718c48d7de57482a868ae7f065870a6216506d11b779323dfdf046cf5775129134b4d5689e4d9c0ce1e12d7d4b06cb5fc5820decfa41baf59bf257b32f025b7679b445b9499c92555145885992f1b76f84891ee4d3be0f5150fd5901e3a4c8ed43fd36b61d022e65ad5008dbf33293c22bfbfd07321f0f1d5fa9fdf0014c2fcb0358aad0e354b0d29":"081b233b43567750bd6e78f396a88b9f6a445151":"0ba373f76e0921b70a8fbfe622f0bf77b28a3db98e361051c3d7cb92ad0452915a4de9c01722f6823eeb6adf7e0ca8290f5de3e549890ac2a3c5950ab217ba58590894952de96f8df111b2575215da6c161590c745be612476ee578ed384ab33e3ece97481a252f5c79a98b5532ae00cdd62f2ecc0cd1baefe80d80b962193ec1d":0
+pkcs1_rsassa_pss_verify:1028:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"30c7d557458b436decfdc14d06cb7b96b06718c48d7de57482a868ae7f065870a6216506d11b779323dfdf046cf5775129134b4d5689e4d9c0ce1e12d7d4b06cb5fc5820decfa41baf59bf257b32f025b7679b445b9499c92555145885992f1b76f84891ee4d3be0f5150fd5901e3a4c8ed43fd36b61d022e65ad5008dbf33293c22bfbfd07321f0f1d5fa9fdf0014c2fcb0358aad0e354b0d29":"081b233b43567750bd6e78f396a88b9f6a445151":"0ba373f76e0921b70a8fbfe622f0bf77b28a3db98e361051c3d7cb92ad0452915a4de9c01722f6823eeb6adf7e0ca8290f5de3e549890ac2a3c5950ab217ba58590894952de96f8df111b2575215da6c161590c745be612476ee578ed384ab33e3ece97481a252f5c79a98b5532ae00cdd62f2ecc0cd1baefe80d80b962193ec1d":0
 
 RSASSA-PSS Signature Example 5_2
-pkcs1_rsassa_pss_sign:1028:16:"03f2f331f4142d4f24b43aa10279a89652d4e7537221a1a7b2a25deb551e5de9ac497411c227a94e45f91c2d1c13cc046cf4ce14e32d058734210d44a87ee1b73f":16:"034f090d73b55803030cf0361a5d8081bfb79f851523feac0a2124d08d4013ff08487771a870d0479dc0686c62f7718dfecf024b17c9267678059171339cc00839":16:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e7b32e1556ea1b2795046ac69739d22ac8966bf11c116f614b166740e96b90653e5750945fcf772186c03790a07fda323e1a61916b06ee2157db3dff80d67d5e39a53ae268c8f09ed99a732005b0bc6a04af4e08d57a00e7201b3060efaadb73113bfc087fd837093aa25235b8c149f56215f031c24ad5bde7f29960df7d524070f7449c6f785084be1a0f733047f336f9154738674547db02a9f44dfc6e60301081e1ce99847f3b5b601ff06b4d5776a9740b9aa0d34058fd3b906e4f7859dfb07d7173e5e6f6350adac21f27b2307469":"bd0ce19549d0700120cbe51077dbbbb00a8d8b09":"08180de825e4b8b014a32da8ba761555921204f2f90d5f24b712908ff84f3e220ad17997c0dd6e706630ba3e84add4d5e7ab004e58074b549709565d43ad9e97b5a7a1a29e85b9f90f4aafcdf58321de8c5974ef9abf2d526f33c0f2f82e95d158ea6b81f1736db8d1af3d6ac6a83b32d18bae0ff1b2fe27de4c76ed8c7980a34e":0
+pkcs1_rsassa_pss_sign:1028:"03f2f331f4142d4f24b43aa10279a89652d4e7537221a1a7b2a25deb551e5de9ac497411c227a94e45f91c2d1c13cc046cf4ce14e32d058734210d44a87ee1b73f":"034f090d73b55803030cf0361a5d8081bfb79f851523feac0a2124d08d4013ff08487771a870d0479dc0686c62f7718dfecf024b17c9267678059171339cc00839":"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e7b32e1556ea1b2795046ac69739d22ac8966bf11c116f614b166740e96b90653e5750945fcf772186c03790a07fda323e1a61916b06ee2157db3dff80d67d5e39a53ae268c8f09ed99a732005b0bc6a04af4e08d57a00e7201b3060efaadb73113bfc087fd837093aa25235b8c149f56215f031c24ad5bde7f29960df7d524070f7449c6f785084be1a0f733047f336f9154738674547db02a9f44dfc6e60301081e1ce99847f3b5b601ff06b4d5776a9740b9aa0d34058fd3b906e4f7859dfb07d7173e5e6f6350adac21f27b2307469":"bd0ce19549d0700120cbe51077dbbbb00a8d8b09":"08180de825e4b8b014a32da8ba761555921204f2f90d5f24b712908ff84f3e220ad17997c0dd6e706630ba3e84add4d5e7ab004e58074b549709565d43ad9e97b5a7a1a29e85b9f90f4aafcdf58321de8c5974ef9abf2d526f33c0f2f82e95d158ea6b81f1736db8d1af3d6ac6a83b32d18bae0ff1b2fe27de4c76ed8c7980a34e":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 5_2 (verify)
-pkcs1_rsassa_pss_verify:1028:16:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e7b32e1556ea1b2795046ac69739d22ac8966bf11c116f614b166740e96b90653e5750945fcf772186c03790a07fda323e1a61916b06ee2157db3dff80d67d5e39a53ae268c8f09ed99a732005b0bc6a04af4e08d57a00e7201b3060efaadb73113bfc087fd837093aa25235b8c149f56215f031c24ad5bde7f29960df7d524070f7449c6f785084be1a0f733047f336f9154738674547db02a9f44dfc6e60301081e1ce99847f3b5b601ff06b4d5776a9740b9aa0d34058fd3b906e4f7859dfb07d7173e5e6f6350adac21f27b2307469":"bd0ce19549d0700120cbe51077dbbbb00a8d8b09":"08180de825e4b8b014a32da8ba761555921204f2f90d5f24b712908ff84f3e220ad17997c0dd6e706630ba3e84add4d5e7ab004e58074b549709565d43ad9e97b5a7a1a29e85b9f90f4aafcdf58321de8c5974ef9abf2d526f33c0f2f82e95d158ea6b81f1736db8d1af3d6ac6a83b32d18bae0ff1b2fe27de4c76ed8c7980a34e":0
+pkcs1_rsassa_pss_verify:1028:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e7b32e1556ea1b2795046ac69739d22ac8966bf11c116f614b166740e96b90653e5750945fcf772186c03790a07fda323e1a61916b06ee2157db3dff80d67d5e39a53ae268c8f09ed99a732005b0bc6a04af4e08d57a00e7201b3060efaadb73113bfc087fd837093aa25235b8c149f56215f031c24ad5bde7f29960df7d524070f7449c6f785084be1a0f733047f336f9154738674547db02a9f44dfc6e60301081e1ce99847f3b5b601ff06b4d5776a9740b9aa0d34058fd3b906e4f7859dfb07d7173e5e6f6350adac21f27b2307469":"bd0ce19549d0700120cbe51077dbbbb00a8d8b09":"08180de825e4b8b014a32da8ba761555921204f2f90d5f24b712908ff84f3e220ad17997c0dd6e706630ba3e84add4d5e7ab004e58074b549709565d43ad9e97b5a7a1a29e85b9f90f4aafcdf58321de8c5974ef9abf2d526f33c0f2f82e95d158ea6b81f1736db8d1af3d6ac6a83b32d18bae0ff1b2fe27de4c76ed8c7980a34e":0
 
 RSASSA-PSS Signature Example 5_3
-pkcs1_rsassa_pss_sign:1028:16:"03f2f331f4142d4f24b43aa10279a89652d4e7537221a1a7b2a25deb551e5de9ac497411c227a94e45f91c2d1c13cc046cf4ce14e32d058734210d44a87ee1b73f":16:"034f090d73b55803030cf0361a5d8081bfb79f851523feac0a2124d08d4013ff08487771a870d0479dc0686c62f7718dfecf024b17c9267678059171339cc00839":16:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"8d8396e36507fe1ef6a19017548e0c716674c2fec233adb2f775665ec41f2bd0ba396b061a9daa7e866f7c23fd3531954300a342f924535ea1498c48f6c879932865fc02000c528723b7ad0335745b51209a0afed932af8f0887c219004d2abd894ea92559ee3198af3a734fe9b9638c263a728ad95a5ae8ce3eb15839f3aa7852bb390706e7760e43a71291a2e3f827237deda851874c517665f545f27238df86557f375d09ccd8bd15d8ccf61f5d78ca5c7f5cde782e6bf5d0057056d4bad98b3d2f9575e824ab7a33ff57b0ac100ab0d6ead7aa0b50f6e4d3e5ec0b966b":"815779a91b3a8bd049bf2aeb920142772222c9ca":"05e0fdbdf6f756ef733185ccfa8ced2eb6d029d9d56e35561b5db8e70257ee6fd019d2f0bbf669fe9b9821e78df6d41e31608d58280f318ee34f559941c8df13287574bac000b7e58dc4f414ba49fb127f9d0f8936638c76e85356c994f79750f7fa3cf4fd482df75e3fb9978cd061f7abb17572e6e63e0bde12cbdcf18c68b979":0
+pkcs1_rsassa_pss_sign:1028:"03f2f331f4142d4f24b43aa10279a89652d4e7537221a1a7b2a25deb551e5de9ac497411c227a94e45f91c2d1c13cc046cf4ce14e32d058734210d44a87ee1b73f":"034f090d73b55803030cf0361a5d8081bfb79f851523feac0a2124d08d4013ff08487771a870d0479dc0686c62f7718dfecf024b17c9267678059171339cc00839":"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"8d8396e36507fe1ef6a19017548e0c716674c2fec233adb2f775665ec41f2bd0ba396b061a9daa7e866f7c23fd3531954300a342f924535ea1498c48f6c879932865fc02000c528723b7ad0335745b51209a0afed932af8f0887c219004d2abd894ea92559ee3198af3a734fe9b9638c263a728ad95a5ae8ce3eb15839f3aa7852bb390706e7760e43a71291a2e3f827237deda851874c517665f545f27238df86557f375d09ccd8bd15d8ccf61f5d78ca5c7f5cde782e6bf5d0057056d4bad98b3d2f9575e824ab7a33ff57b0ac100ab0d6ead7aa0b50f6e4d3e5ec0b966b":"815779a91b3a8bd049bf2aeb920142772222c9ca":"05e0fdbdf6f756ef733185ccfa8ced2eb6d029d9d56e35561b5db8e70257ee6fd019d2f0bbf669fe9b9821e78df6d41e31608d58280f318ee34f559941c8df13287574bac000b7e58dc4f414ba49fb127f9d0f8936638c76e85356c994f79750f7fa3cf4fd482df75e3fb9978cd061f7abb17572e6e63e0bde12cbdcf18c68b979":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 5_3 (verify)
-pkcs1_rsassa_pss_verify:1028:16:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"8d8396e36507fe1ef6a19017548e0c716674c2fec233adb2f775665ec41f2bd0ba396b061a9daa7e866f7c23fd3531954300a342f924535ea1498c48f6c879932865fc02000c528723b7ad0335745b51209a0afed932af8f0887c219004d2abd894ea92559ee3198af3a734fe9b9638c263a728ad95a5ae8ce3eb15839f3aa7852bb390706e7760e43a71291a2e3f827237deda851874c517665f545f27238df86557f375d09ccd8bd15d8ccf61f5d78ca5c7f5cde782e6bf5d0057056d4bad98b3d2f9575e824ab7a33ff57b0ac100ab0d6ead7aa0b50f6e4d3e5ec0b966b":"815779a91b3a8bd049bf2aeb920142772222c9ca":"05e0fdbdf6f756ef733185ccfa8ced2eb6d029d9d56e35561b5db8e70257ee6fd019d2f0bbf669fe9b9821e78df6d41e31608d58280f318ee34f559941c8df13287574bac000b7e58dc4f414ba49fb127f9d0f8936638c76e85356c994f79750f7fa3cf4fd482df75e3fb9978cd061f7abb17572e6e63e0bde12cbdcf18c68b979":0
+pkcs1_rsassa_pss_verify:1028:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"8d8396e36507fe1ef6a19017548e0c716674c2fec233adb2f775665ec41f2bd0ba396b061a9daa7e866f7c23fd3531954300a342f924535ea1498c48f6c879932865fc02000c528723b7ad0335745b51209a0afed932af8f0887c219004d2abd894ea92559ee3198af3a734fe9b9638c263a728ad95a5ae8ce3eb15839f3aa7852bb390706e7760e43a71291a2e3f827237deda851874c517665f545f27238df86557f375d09ccd8bd15d8ccf61f5d78ca5c7f5cde782e6bf5d0057056d4bad98b3d2f9575e824ab7a33ff57b0ac100ab0d6ead7aa0b50f6e4d3e5ec0b966b":"815779a91b3a8bd049bf2aeb920142772222c9ca":"05e0fdbdf6f756ef733185ccfa8ced2eb6d029d9d56e35561b5db8e70257ee6fd019d2f0bbf669fe9b9821e78df6d41e31608d58280f318ee34f559941c8df13287574bac000b7e58dc4f414ba49fb127f9d0f8936638c76e85356c994f79750f7fa3cf4fd482df75e3fb9978cd061f7abb17572e6e63e0bde12cbdcf18c68b979":0
 
 RSASSA-PSS Signature Example 5_4
-pkcs1_rsassa_pss_sign:1028:16:"03f2f331f4142d4f24b43aa10279a89652d4e7537221a1a7b2a25deb551e5de9ac497411c227a94e45f91c2d1c13cc046cf4ce14e32d058734210d44a87ee1b73f":16:"034f090d73b55803030cf0361a5d8081bfb79f851523feac0a2124d08d4013ff08487771a870d0479dc0686c62f7718dfecf024b17c9267678059171339cc00839":16:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"328c659e0a6437433cceb73c14":"9aec4a7480d5bbc42920d7ca235db674989c9aac":"0bc989853bc2ea86873271ce183a923ab65e8a53100e6df5d87a24c4194eb797813ee2a187c097dd872d591da60c568605dd7e742d5af4e33b11678ccb63903204a3d080b0902c89aba8868f009c0f1c0cb85810bbdd29121abb8471ff2d39e49fd92d56c655c8e037ad18fafbdc92c95863f7f61ea9efa28fea401369d19daea1":0
+pkcs1_rsassa_pss_sign:1028:"03f2f331f4142d4f24b43aa10279a89652d4e7537221a1a7b2a25deb551e5de9ac497411c227a94e45f91c2d1c13cc046cf4ce14e32d058734210d44a87ee1b73f":"034f090d73b55803030cf0361a5d8081bfb79f851523feac0a2124d08d4013ff08487771a870d0479dc0686c62f7718dfecf024b17c9267678059171339cc00839":"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"328c659e0a6437433cceb73c14":"9aec4a7480d5bbc42920d7ca235db674989c9aac":"0bc989853bc2ea86873271ce183a923ab65e8a53100e6df5d87a24c4194eb797813ee2a187c097dd872d591da60c568605dd7e742d5af4e33b11678ccb63903204a3d080b0902c89aba8868f009c0f1c0cb85810bbdd29121abb8471ff2d39e49fd92d56c655c8e037ad18fafbdc92c95863f7f61ea9efa28fea401369d19daea1":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 5_4 (verify)
-pkcs1_rsassa_pss_verify:1028:16:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"328c659e0a6437433cceb73c14":"9aec4a7480d5bbc42920d7ca235db674989c9aac":"0bc989853bc2ea86873271ce183a923ab65e8a53100e6df5d87a24c4194eb797813ee2a187c097dd872d591da60c568605dd7e742d5af4e33b11678ccb63903204a3d080b0902c89aba8868f009c0f1c0cb85810bbdd29121abb8471ff2d39e49fd92d56c655c8e037ad18fafbdc92c95863f7f61ea9efa28fea401369d19daea1":0
+pkcs1_rsassa_pss_verify:1028:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"328c659e0a6437433cceb73c14":"9aec4a7480d5bbc42920d7ca235db674989c9aac":"0bc989853bc2ea86873271ce183a923ab65e8a53100e6df5d87a24c4194eb797813ee2a187c097dd872d591da60c568605dd7e742d5af4e33b11678ccb63903204a3d080b0902c89aba8868f009c0f1c0cb85810bbdd29121abb8471ff2d39e49fd92d56c655c8e037ad18fafbdc92c95863f7f61ea9efa28fea401369d19daea1":0
 
 RSASSA-PSS Signature Example 5_5
-pkcs1_rsassa_pss_sign:1028:16:"03f2f331f4142d4f24b43aa10279a89652d4e7537221a1a7b2a25deb551e5de9ac497411c227a94e45f91c2d1c13cc046cf4ce14e32d058734210d44a87ee1b73f":16:"034f090d73b55803030cf0361a5d8081bfb79f851523feac0a2124d08d4013ff08487771a870d0479dc0686c62f7718dfecf024b17c9267678059171339cc00839":16:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"f37b962379a47d415a376eec8973150bcb34edd5ab654041b61430560c2144582ba133c867d852d6b8e23321901302ecb45b09ec88b1527178fa043263f3067d9ffe973032a99f4cb08ad2c7e0a2456cdd57a7df56fe6053527a5aeb67d7e552063c1ca97b1beffa7b39e997caf27878ea0f62cbebc8c21df4c889a202851e949088490c249b6e9acf1d8063f5be2343989bf95c4da01a2be78b4ab6b378015bc37957f76948b5e58e440c28453d40d7cfd57e7d690600474ab5e75973b1ea0c5f1e45d14190afe2f4eb6d3bdf71f1d2f8bb156a1c295d04aaeb9d689dce79ed62bc443e":"e20c1e9878512c39970f58375e1549a68b64f31d":"0aefa943b698b9609edf898ad22744ac28dc239497cea369cbbd84f65c95c0ad776b594740164b59a739c6ff7c2f07c7c077a86d95238fe51e1fcf33574a4ae0684b42a3f6bf677d91820ca89874467b2c23add77969c80717430d0efc1d3695892ce855cb7f7011630f4df26def8ddf36fc23905f57fa6243a485c770d5681fcd":0
+pkcs1_rsassa_pss_sign:1028:"03f2f331f4142d4f24b43aa10279a89652d4e7537221a1a7b2a25deb551e5de9ac497411c227a94e45f91c2d1c13cc046cf4ce14e32d058734210d44a87ee1b73f":"034f090d73b55803030cf0361a5d8081bfb79f851523feac0a2124d08d4013ff08487771a870d0479dc0686c62f7718dfecf024b17c9267678059171339cc00839":"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"f37b962379a47d415a376eec8973150bcb34edd5ab654041b61430560c2144582ba133c867d852d6b8e23321901302ecb45b09ec88b1527178fa043263f3067d9ffe973032a99f4cb08ad2c7e0a2456cdd57a7df56fe6053527a5aeb67d7e552063c1ca97b1beffa7b39e997caf27878ea0f62cbebc8c21df4c889a202851e949088490c249b6e9acf1d8063f5be2343989bf95c4da01a2be78b4ab6b378015bc37957f76948b5e58e440c28453d40d7cfd57e7d690600474ab5e75973b1ea0c5f1e45d14190afe2f4eb6d3bdf71f1d2f8bb156a1c295d04aaeb9d689dce79ed62bc443e":"e20c1e9878512c39970f58375e1549a68b64f31d":"0aefa943b698b9609edf898ad22744ac28dc239497cea369cbbd84f65c95c0ad776b594740164b59a739c6ff7c2f07c7c077a86d95238fe51e1fcf33574a4ae0684b42a3f6bf677d91820ca89874467b2c23add77969c80717430d0efc1d3695892ce855cb7f7011630f4df26def8ddf36fc23905f57fa6243a485c770d5681fcd":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 5_5 (verify)
-pkcs1_rsassa_pss_verify:1028:16:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"f37b962379a47d415a376eec8973150bcb34edd5ab654041b61430560c2144582ba133c867d852d6b8e23321901302ecb45b09ec88b1527178fa043263f3067d9ffe973032a99f4cb08ad2c7e0a2456cdd57a7df56fe6053527a5aeb67d7e552063c1ca97b1beffa7b39e997caf27878ea0f62cbebc8c21df4c889a202851e949088490c249b6e9acf1d8063f5be2343989bf95c4da01a2be78b4ab6b378015bc37957f76948b5e58e440c28453d40d7cfd57e7d690600474ab5e75973b1ea0c5f1e45d14190afe2f4eb6d3bdf71f1d2f8bb156a1c295d04aaeb9d689dce79ed62bc443e":"e20c1e9878512c39970f58375e1549a68b64f31d":"0aefa943b698b9609edf898ad22744ac28dc239497cea369cbbd84f65c95c0ad776b594740164b59a739c6ff7c2f07c7c077a86d95238fe51e1fcf33574a4ae0684b42a3f6bf677d91820ca89874467b2c23add77969c80717430d0efc1d3695892ce855cb7f7011630f4df26def8ddf36fc23905f57fa6243a485c770d5681fcd":0
+pkcs1_rsassa_pss_verify:1028:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"f37b962379a47d415a376eec8973150bcb34edd5ab654041b61430560c2144582ba133c867d852d6b8e23321901302ecb45b09ec88b1527178fa043263f3067d9ffe973032a99f4cb08ad2c7e0a2456cdd57a7df56fe6053527a5aeb67d7e552063c1ca97b1beffa7b39e997caf27878ea0f62cbebc8c21df4c889a202851e949088490c249b6e9acf1d8063f5be2343989bf95c4da01a2be78b4ab6b378015bc37957f76948b5e58e440c28453d40d7cfd57e7d690600474ab5e75973b1ea0c5f1e45d14190afe2f4eb6d3bdf71f1d2f8bb156a1c295d04aaeb9d689dce79ed62bc443e":"e20c1e9878512c39970f58375e1549a68b64f31d":"0aefa943b698b9609edf898ad22744ac28dc239497cea369cbbd84f65c95c0ad776b594740164b59a739c6ff7c2f07c7c077a86d95238fe51e1fcf33574a4ae0684b42a3f6bf677d91820ca89874467b2c23add77969c80717430d0efc1d3695892ce855cb7f7011630f4df26def8ddf36fc23905f57fa6243a485c770d5681fcd":0
 
 RSASSA-PSS Signature Example 5_6
-pkcs1_rsassa_pss_sign:1028:16:"03f2f331f4142d4f24b43aa10279a89652d4e7537221a1a7b2a25deb551e5de9ac497411c227a94e45f91c2d1c13cc046cf4ce14e32d058734210d44a87ee1b73f":16:"034f090d73b55803030cf0361a5d8081bfb79f851523feac0a2124d08d4013ff08487771a870d0479dc0686c62f7718dfecf024b17c9267678059171339cc00839":16:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"c6103c330c1ef718c141e47b8fa859be4d5b96259e7d142070ecd485839dba5a8369c17c1114035e532d195c74f44a0476a2d3e8a4da210016caced0e367cb867710a4b5aa2df2b8e5daf5fdc647807d4d5ebb6c56b9763ccdae4dea3308eb0ac2a89501cb209d2639fa5bf87ce790747d3cb2d295e84564f2f637824f0c13028129b0aa4a422d162282":"23291e4a3307e8bbb776623ab34e4a5f4cc8a8db":"02802dccfa8dfaf5279bf0b4a29ba1b157611faeaaf419b8919d15941900c1339e7e92e6fae562c53e6cc8e84104b110bce03ad18525e3c49a0eadad5d3f28f244a8ed89edbafbb686277cfa8ae909714d6b28f4bf8e293aa04c41efe7c0a81266d5c061e2575be032aa464674ff71626219bd74cc45f0e7ed4e3ff96eee758e8f":0
+pkcs1_rsassa_pss_sign:1028:"03f2f331f4142d4f24b43aa10279a89652d4e7537221a1a7b2a25deb551e5de9ac497411c227a94e45f91c2d1c13cc046cf4ce14e32d058734210d44a87ee1b73f":"034f090d73b55803030cf0361a5d8081bfb79f851523feac0a2124d08d4013ff08487771a870d0479dc0686c62f7718dfecf024b17c9267678059171339cc00839":"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"c6103c330c1ef718c141e47b8fa859be4d5b96259e7d142070ecd485839dba5a8369c17c1114035e532d195c74f44a0476a2d3e8a4da210016caced0e367cb867710a4b5aa2df2b8e5daf5fdc647807d4d5ebb6c56b9763ccdae4dea3308eb0ac2a89501cb209d2639fa5bf87ce790747d3cb2d295e84564f2f637824f0c13028129b0aa4a422d162282":"23291e4a3307e8bbb776623ab34e4a5f4cc8a8db":"02802dccfa8dfaf5279bf0b4a29ba1b157611faeaaf419b8919d15941900c1339e7e92e6fae562c53e6cc8e84104b110bce03ad18525e3c49a0eadad5d3f28f244a8ed89edbafbb686277cfa8ae909714d6b28f4bf8e293aa04c41efe7c0a81266d5c061e2575be032aa464674ff71626219bd74cc45f0e7ed4e3ff96eee758e8f":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 5_6 (verify)
-pkcs1_rsassa_pss_verify:1028:16:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"c6103c330c1ef718c141e47b8fa859be4d5b96259e7d142070ecd485839dba5a8369c17c1114035e532d195c74f44a0476a2d3e8a4da210016caced0e367cb867710a4b5aa2df2b8e5daf5fdc647807d4d5ebb6c56b9763ccdae4dea3308eb0ac2a89501cb209d2639fa5bf87ce790747d3cb2d295e84564f2f637824f0c13028129b0aa4a422d162282":"23291e4a3307e8bbb776623ab34e4a5f4cc8a8db":"02802dccfa8dfaf5279bf0b4a29ba1b157611faeaaf419b8919d15941900c1339e7e92e6fae562c53e6cc8e84104b110bce03ad18525e3c49a0eadad5d3f28f244a8ed89edbafbb686277cfa8ae909714d6b28f4bf8e293aa04c41efe7c0a81266d5c061e2575be032aa464674ff71626219bd74cc45f0e7ed4e3ff96eee758e8f":0
+pkcs1_rsassa_pss_verify:1028:"0d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc507":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"c6103c330c1ef718c141e47b8fa859be4d5b96259e7d142070ecd485839dba5a8369c17c1114035e532d195c74f44a0476a2d3e8a4da210016caced0e367cb867710a4b5aa2df2b8e5daf5fdc647807d4d5ebb6c56b9763ccdae4dea3308eb0ac2a89501cb209d2639fa5bf87ce790747d3cb2d295e84564f2f637824f0c13028129b0aa4a422d162282":"23291e4a3307e8bbb776623ab34e4a5f4cc8a8db":"02802dccfa8dfaf5279bf0b4a29ba1b157611faeaaf419b8919d15941900c1339e7e92e6fae562c53e6cc8e84104b110bce03ad18525e3c49a0eadad5d3f28f244a8ed89edbafbb686277cfa8ae909714d6b28f4bf8e293aa04c41efe7c0a81266d5c061e2575be032aa464674ff71626219bd74cc45f0e7ed4e3ff96eee758e8f":0
 
 RSASSA-PSS Signature Example 6_1
-pkcs1_rsassa_pss_sign:1029:16:"04f0548c9626ab1ebf1244934741d99a06220efa2a5856aa0e75730b2ec96adc86be894fa2803b53a5e85d276acbd29ab823f80a7391bb54a5051672fb04eeb543":16:"0483e0ae47915587743ff345362b555d3962d98bb6f15f848b4c92b1771ca8ed107d8d3ee65ec44517dd0faa481a387e902f7a2e747c269e7ea44480bc538b8e5b":16:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0a20b774addc2fa51245ed7cb9da609e50cac6636a52543f97458eed7340f8d53ffc64918f949078ee03ef60d42b5fec246050bd5505cd8cb597bad3c4e713b0ef30644e76adabb0de01a1561efb255158c74fc801e6e919e581b46f0f0ddd08e4f34c7810b5ed8318f91d7c8c":"5b4ea2ef629cc22f3b538e016904b47b1e40bfd5":"04c0cfacec04e5badbece159a5a1103f69b3f32ba593cb4cc4b1b7ab455916a96a27cd2678ea0f46ba37f7fc9c86325f29733b389f1d97f43e7201c0f348fc45fe42892335362eee018b5b161f2f9393031225c713012a576bc88e23052489868d9010cbf033ecc568e8bc152bdc59d560e41291915d28565208e22aeec9ef85d1":0
+pkcs1_rsassa_pss_sign:1029:"04f0548c9626ab1ebf1244934741d99a06220efa2a5856aa0e75730b2ec96adc86be894fa2803b53a5e85d276acbd29ab823f80a7391bb54a5051672fb04eeb543":"0483e0ae47915587743ff345362b555d3962d98bb6f15f848b4c92b1771ca8ed107d8d3ee65ec44517dd0faa481a387e902f7a2e747c269e7ea44480bc538b8e5b":"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0a20b774addc2fa51245ed7cb9da609e50cac6636a52543f97458eed7340f8d53ffc64918f949078ee03ef60d42b5fec246050bd5505cd8cb597bad3c4e713b0ef30644e76adabb0de01a1561efb255158c74fc801e6e919e581b46f0f0ddd08e4f34c7810b5ed8318f91d7c8c":"5b4ea2ef629cc22f3b538e016904b47b1e40bfd5":"04c0cfacec04e5badbece159a5a1103f69b3f32ba593cb4cc4b1b7ab455916a96a27cd2678ea0f46ba37f7fc9c86325f29733b389f1d97f43e7201c0f348fc45fe42892335362eee018b5b161f2f9393031225c713012a576bc88e23052489868d9010cbf033ecc568e8bc152bdc59d560e41291915d28565208e22aeec9ef85d1":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 6_1 (verify)
-pkcs1_rsassa_pss_verify:1029:16:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0a20b774addc2fa51245ed7cb9da609e50cac6636a52543f97458eed7340f8d53ffc64918f949078ee03ef60d42b5fec246050bd5505cd8cb597bad3c4e713b0ef30644e76adabb0de01a1561efb255158c74fc801e6e919e581b46f0f0ddd08e4f34c7810b5ed8318f91d7c8c":"5b4ea2ef629cc22f3b538e016904b47b1e40bfd5":"04c0cfacec04e5badbece159a5a1103f69b3f32ba593cb4cc4b1b7ab455916a96a27cd2678ea0f46ba37f7fc9c86325f29733b389f1d97f43e7201c0f348fc45fe42892335362eee018b5b161f2f9393031225c713012a576bc88e23052489868d9010cbf033ecc568e8bc152bdc59d560e41291915d28565208e22aeec9ef85d1":0
+pkcs1_rsassa_pss_verify:1029:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0a20b774addc2fa51245ed7cb9da609e50cac6636a52543f97458eed7340f8d53ffc64918f949078ee03ef60d42b5fec246050bd5505cd8cb597bad3c4e713b0ef30644e76adabb0de01a1561efb255158c74fc801e6e919e581b46f0f0ddd08e4f34c7810b5ed8318f91d7c8c":"5b4ea2ef629cc22f3b538e016904b47b1e40bfd5":"04c0cfacec04e5badbece159a5a1103f69b3f32ba593cb4cc4b1b7ab455916a96a27cd2678ea0f46ba37f7fc9c86325f29733b389f1d97f43e7201c0f348fc45fe42892335362eee018b5b161f2f9393031225c713012a576bc88e23052489868d9010cbf033ecc568e8bc152bdc59d560e41291915d28565208e22aeec9ef85d1":0
 
 RSASSA-PSS Signature Example 6_2
-pkcs1_rsassa_pss_sign:1029:16:"04f0548c9626ab1ebf1244934741d99a06220efa2a5856aa0e75730b2ec96adc86be894fa2803b53a5e85d276acbd29ab823f80a7391bb54a5051672fb04eeb543":16:"0483e0ae47915587743ff345362b555d3962d98bb6f15f848b4c92b1771ca8ed107d8d3ee65ec44517dd0faa481a387e902f7a2e747c269e7ea44480bc538b8e5b":16:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"2aaff6631f621ce615760a9ebce94bb333077ad86488c861d4b76d29c1f48746c611ae1e03ced4445d7cfa1fe5f62e1b3f08452bde3b6ef81973bafbb57f97bceef873985395b8260589aa88cb7db50ab469262e551bdcd9a56f275a0ac4fe484700c35f3dbf2b469ede864741b86fa59172a360ba95a02e139be50ddfb7cf0b42faeabbfbbaa86a4497699c4f2dfd5b08406af7e14144427c253ec0efa20eaf9a8be8cd49ce1f1bc4e93e619cf2aa8ed4fb39bc8590d0f7b96488f7317ac9abf7bee4e3a0e715":"83146a9e782722c28b014f98b4267bda2ac9504f":"0a2314250cf52b6e4e908de5b35646bcaa24361da8160fb0f9257590ab3ace42b0dc3e77ad2db7c203a20bd952fbb56b1567046ecfaa933d7b1000c3de9ff05b7d989ba46fd43bc4c2d0a3986b7ffa13471d37eb5b47d64707bd290cfd6a9f393ad08ec1e3bd71bb5792615035cdaf2d8929aed3be098379377e777ce79aaa4773":0
+pkcs1_rsassa_pss_sign:1029:"04f0548c9626ab1ebf1244934741d99a06220efa2a5856aa0e75730b2ec96adc86be894fa2803b53a5e85d276acbd29ab823f80a7391bb54a5051672fb04eeb543":"0483e0ae47915587743ff345362b555d3962d98bb6f15f848b4c92b1771ca8ed107d8d3ee65ec44517dd0faa481a387e902f7a2e747c269e7ea44480bc538b8e5b":"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"2aaff6631f621ce615760a9ebce94bb333077ad86488c861d4b76d29c1f48746c611ae1e03ced4445d7cfa1fe5f62e1b3f08452bde3b6ef81973bafbb57f97bceef873985395b8260589aa88cb7db50ab469262e551bdcd9a56f275a0ac4fe484700c35f3dbf2b469ede864741b86fa59172a360ba95a02e139be50ddfb7cf0b42faeabbfbbaa86a4497699c4f2dfd5b08406af7e14144427c253ec0efa20eaf9a8be8cd49ce1f1bc4e93e619cf2aa8ed4fb39bc8590d0f7b96488f7317ac9abf7bee4e3a0e715":"83146a9e782722c28b014f98b4267bda2ac9504f":"0a2314250cf52b6e4e908de5b35646bcaa24361da8160fb0f9257590ab3ace42b0dc3e77ad2db7c203a20bd952fbb56b1567046ecfaa933d7b1000c3de9ff05b7d989ba46fd43bc4c2d0a3986b7ffa13471d37eb5b47d64707bd290cfd6a9f393ad08ec1e3bd71bb5792615035cdaf2d8929aed3be098379377e777ce79aaa4773":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 6_2 (verify)
-pkcs1_rsassa_pss_verify:1029:16:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"2aaff6631f621ce615760a9ebce94bb333077ad86488c861d4b76d29c1f48746c611ae1e03ced4445d7cfa1fe5f62e1b3f08452bde3b6ef81973bafbb57f97bceef873985395b8260589aa88cb7db50ab469262e551bdcd9a56f275a0ac4fe484700c35f3dbf2b469ede864741b86fa59172a360ba95a02e139be50ddfb7cf0b42faeabbfbbaa86a4497699c4f2dfd5b08406af7e14144427c253ec0efa20eaf9a8be8cd49ce1f1bc4e93e619cf2aa8ed4fb39bc8590d0f7b96488f7317ac9abf7bee4e3a0e715":"83146a9e782722c28b014f98b4267bda2ac9504f":"0a2314250cf52b6e4e908de5b35646bcaa24361da8160fb0f9257590ab3ace42b0dc3e77ad2db7c203a20bd952fbb56b1567046ecfaa933d7b1000c3de9ff05b7d989ba46fd43bc4c2d0a3986b7ffa13471d37eb5b47d64707bd290cfd6a9f393ad08ec1e3bd71bb5792615035cdaf2d8929aed3be098379377e777ce79aaa4773":0
+pkcs1_rsassa_pss_verify:1029:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"2aaff6631f621ce615760a9ebce94bb333077ad86488c861d4b76d29c1f48746c611ae1e03ced4445d7cfa1fe5f62e1b3f08452bde3b6ef81973bafbb57f97bceef873985395b8260589aa88cb7db50ab469262e551bdcd9a56f275a0ac4fe484700c35f3dbf2b469ede864741b86fa59172a360ba95a02e139be50ddfb7cf0b42faeabbfbbaa86a4497699c4f2dfd5b08406af7e14144427c253ec0efa20eaf9a8be8cd49ce1f1bc4e93e619cf2aa8ed4fb39bc8590d0f7b96488f7317ac9abf7bee4e3a0e715":"83146a9e782722c28b014f98b4267bda2ac9504f":"0a2314250cf52b6e4e908de5b35646bcaa24361da8160fb0f9257590ab3ace42b0dc3e77ad2db7c203a20bd952fbb56b1567046ecfaa933d7b1000c3de9ff05b7d989ba46fd43bc4c2d0a3986b7ffa13471d37eb5b47d64707bd290cfd6a9f393ad08ec1e3bd71bb5792615035cdaf2d8929aed3be098379377e777ce79aaa4773":0
 
 RSASSA-PSS Signature Example 6_3
-pkcs1_rsassa_pss_sign:1029:16:"04f0548c9626ab1ebf1244934741d99a06220efa2a5856aa0e75730b2ec96adc86be894fa2803b53a5e85d276acbd29ab823f80a7391bb54a5051672fb04eeb543":16:"0483e0ae47915587743ff345362b555d3962d98bb6f15f848b4c92b1771ca8ed107d8d3ee65ec44517dd0faa481a387e902f7a2e747c269e7ea44480bc538b8e5b":16:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0f6195d04a6e6fc7e2c9600dbf840c39ea8d4d624fd53507016b0e26858a5e0aecd7ada543ae5c0ab3a62599cba0a54e6bf446e262f989978f9ddf5e9a41":"a87b8aed07d7b8e2daf14ddca4ac68c4d0aabff8":"086df6b500098c120f24ff8423f727d9c61a5c9007d3b6a31ce7cf8f3cbec1a26bb20e2bd4a046793299e03e37a21b40194fb045f90b18bf20a47992ccd799cf9c059c299c0526854954aade8a6ad9d97ec91a1145383f42468b231f4d72f23706d9853c3fa43ce8ace8bfe7484987a1ec6a16c8daf81f7c8bf42774707a9df456":0
+pkcs1_rsassa_pss_sign:1029:"04f0548c9626ab1ebf1244934741d99a06220efa2a5856aa0e75730b2ec96adc86be894fa2803b53a5e85d276acbd29ab823f80a7391bb54a5051672fb04eeb543":"0483e0ae47915587743ff345362b555d3962d98bb6f15f848b4c92b1771ca8ed107d8d3ee65ec44517dd0faa481a387e902f7a2e747c269e7ea44480bc538b8e5b":"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0f6195d04a6e6fc7e2c9600dbf840c39ea8d4d624fd53507016b0e26858a5e0aecd7ada543ae5c0ab3a62599cba0a54e6bf446e262f989978f9ddf5e9a41":"a87b8aed07d7b8e2daf14ddca4ac68c4d0aabff8":"086df6b500098c120f24ff8423f727d9c61a5c9007d3b6a31ce7cf8f3cbec1a26bb20e2bd4a046793299e03e37a21b40194fb045f90b18bf20a47992ccd799cf9c059c299c0526854954aade8a6ad9d97ec91a1145383f42468b231f4d72f23706d9853c3fa43ce8ace8bfe7484987a1ec6a16c8daf81f7c8bf42774707a9df456":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 6_3 (verify)
-pkcs1_rsassa_pss_verify:1029:16:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0f6195d04a6e6fc7e2c9600dbf840c39ea8d4d624fd53507016b0e26858a5e0aecd7ada543ae5c0ab3a62599cba0a54e6bf446e262f989978f9ddf5e9a41":"a87b8aed07d7b8e2daf14ddca4ac68c4d0aabff8":"086df6b500098c120f24ff8423f727d9c61a5c9007d3b6a31ce7cf8f3cbec1a26bb20e2bd4a046793299e03e37a21b40194fb045f90b18bf20a47992ccd799cf9c059c299c0526854954aade8a6ad9d97ec91a1145383f42468b231f4d72f23706d9853c3fa43ce8ace8bfe7484987a1ec6a16c8daf81f7c8bf42774707a9df456":0
+pkcs1_rsassa_pss_verify:1029:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0f6195d04a6e6fc7e2c9600dbf840c39ea8d4d624fd53507016b0e26858a5e0aecd7ada543ae5c0ab3a62599cba0a54e6bf446e262f989978f9ddf5e9a41":"a87b8aed07d7b8e2daf14ddca4ac68c4d0aabff8":"086df6b500098c120f24ff8423f727d9c61a5c9007d3b6a31ce7cf8f3cbec1a26bb20e2bd4a046793299e03e37a21b40194fb045f90b18bf20a47992ccd799cf9c059c299c0526854954aade8a6ad9d97ec91a1145383f42468b231f4d72f23706d9853c3fa43ce8ace8bfe7484987a1ec6a16c8daf81f7c8bf42774707a9df456":0
 
 RSASSA-PSS Signature Example 6_4
-pkcs1_rsassa_pss_sign:1029:16:"04f0548c9626ab1ebf1244934741d99a06220efa2a5856aa0e75730b2ec96adc86be894fa2803b53a5e85d276acbd29ab823f80a7391bb54a5051672fb04eeb543":16:"0483e0ae47915587743ff345362b555d3962d98bb6f15f848b4c92b1771ca8ed107d8d3ee65ec44517dd0faa481a387e902f7a2e747c269e7ea44480bc538b8e5b":16:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"337d25fe9810ebca0de4d4658d3ceb8e0fe4c066aba3bcc48b105d3bf7e0257d44fecea6596f4d0c59a08402833678f70620f9138dfeb7ded905e4a6d5f05c473d55936652e2a5df43c0cfda7bacaf3087f4524b06cf42157d01539739f7fddec9d58125df31a32eab06c19b71f1d5bf":"a37932f8a7494a942d6f767438e724d6d0c0ef18":"0b5b11ad549863ffa9c51a14a1106c2a72cc8b646e5c7262509786105a984776534ca9b54c1cc64bf2d5a44fd7e8a69db699d5ea52087a4748fd2abc1afed1e5d6f7c89025530bdaa2213d7e030fa55df6f34bcf1ce46d2edf4e3ae4f3b01891a068c9e3a44bbc43133edad6ecb9f35400c4252a5762d65744b99cb9f4c559329f":0
+pkcs1_rsassa_pss_sign:1029:"04f0548c9626ab1ebf1244934741d99a06220efa2a5856aa0e75730b2ec96adc86be894fa2803b53a5e85d276acbd29ab823f80a7391bb54a5051672fb04eeb543":"0483e0ae47915587743ff345362b555d3962d98bb6f15f848b4c92b1771ca8ed107d8d3ee65ec44517dd0faa481a387e902f7a2e747c269e7ea44480bc538b8e5b":"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"337d25fe9810ebca0de4d4658d3ceb8e0fe4c066aba3bcc48b105d3bf7e0257d44fecea6596f4d0c59a08402833678f70620f9138dfeb7ded905e4a6d5f05c473d55936652e2a5df43c0cfda7bacaf3087f4524b06cf42157d01539739f7fddec9d58125df31a32eab06c19b71f1d5bf":"a37932f8a7494a942d6f767438e724d6d0c0ef18":"0b5b11ad549863ffa9c51a14a1106c2a72cc8b646e5c7262509786105a984776534ca9b54c1cc64bf2d5a44fd7e8a69db699d5ea52087a4748fd2abc1afed1e5d6f7c89025530bdaa2213d7e030fa55df6f34bcf1ce46d2edf4e3ae4f3b01891a068c9e3a44bbc43133edad6ecb9f35400c4252a5762d65744b99cb9f4c559329f":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 6_4 (verify)
-pkcs1_rsassa_pss_verify:1029:16:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"337d25fe9810ebca0de4d4658d3ceb8e0fe4c066aba3bcc48b105d3bf7e0257d44fecea6596f4d0c59a08402833678f70620f9138dfeb7ded905e4a6d5f05c473d55936652e2a5df43c0cfda7bacaf3087f4524b06cf42157d01539739f7fddec9d58125df31a32eab06c19b71f1d5bf":"a37932f8a7494a942d6f767438e724d6d0c0ef18":"0b5b11ad549863ffa9c51a14a1106c2a72cc8b646e5c7262509786105a984776534ca9b54c1cc64bf2d5a44fd7e8a69db699d5ea52087a4748fd2abc1afed1e5d6f7c89025530bdaa2213d7e030fa55df6f34bcf1ce46d2edf4e3ae4f3b01891a068c9e3a44bbc43133edad6ecb9f35400c4252a5762d65744b99cb9f4c559329f":0
+pkcs1_rsassa_pss_verify:1029:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"337d25fe9810ebca0de4d4658d3ceb8e0fe4c066aba3bcc48b105d3bf7e0257d44fecea6596f4d0c59a08402833678f70620f9138dfeb7ded905e4a6d5f05c473d55936652e2a5df43c0cfda7bacaf3087f4524b06cf42157d01539739f7fddec9d58125df31a32eab06c19b71f1d5bf":"a37932f8a7494a942d6f767438e724d6d0c0ef18":"0b5b11ad549863ffa9c51a14a1106c2a72cc8b646e5c7262509786105a984776534ca9b54c1cc64bf2d5a44fd7e8a69db699d5ea52087a4748fd2abc1afed1e5d6f7c89025530bdaa2213d7e030fa55df6f34bcf1ce46d2edf4e3ae4f3b01891a068c9e3a44bbc43133edad6ecb9f35400c4252a5762d65744b99cb9f4c559329f":0
 
 RSASSA-PSS Signature Example 6_5
-pkcs1_rsassa_pss_sign:1029:16:"04f0548c9626ab1ebf1244934741d99a06220efa2a5856aa0e75730b2ec96adc86be894fa2803b53a5e85d276acbd29ab823f80a7391bb54a5051672fb04eeb543":16:"0483e0ae47915587743ff345362b555d3962d98bb6f15f848b4c92b1771ca8ed107d8d3ee65ec44517dd0faa481a387e902f7a2e747c269e7ea44480bc538b8e5b":16:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"84ec502b072e8287789d8f9235829ea3b187afd4d4c785611bda5f9eb3cb96717efa7007227f1c08cbcb972e667235e0fb7d431a6570326d2ecce35adb373dc753b3be5f829b89175493193fab16badb41371b3aac0ae670076f24bef420c135add7cee8d35fbc944d79fafb9e307a13b0f556cb654a06f973ed22672330197ef5a748bf826a5db2383a25364b686b9372bb2339aeb1ac9e9889327d016f1670776db06201adbdcaf8a5e3b74e108b73":"7b790c1d62f7b84e94df6af28917cf571018110e":"02d71fa9b53e4654fefb7f08385cf6b0ae3a817942ebf66c35ac67f0b069952a3ce9c7e1f1b02e480a9500836de5d64cdb7ecde04542f7a79988787e24c2ba05f5fd482c023ed5c30e04839dc44bed2a3a3a4fee01113c891a47d32eb8025c28cb050b5cdb576c70fe76ef523405c08417faf350b037a43c379339fcb18d3a356b":0
+pkcs1_rsassa_pss_sign:1029:"04f0548c9626ab1ebf1244934741d99a06220efa2a5856aa0e75730b2ec96adc86be894fa2803b53a5e85d276acbd29ab823f80a7391bb54a5051672fb04eeb543":"0483e0ae47915587743ff345362b555d3962d98bb6f15f848b4c92b1771ca8ed107d8d3ee65ec44517dd0faa481a387e902f7a2e747c269e7ea44480bc538b8e5b":"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"84ec502b072e8287789d8f9235829ea3b187afd4d4c785611bda5f9eb3cb96717efa7007227f1c08cbcb972e667235e0fb7d431a6570326d2ecce35adb373dc753b3be5f829b89175493193fab16badb41371b3aac0ae670076f24bef420c135add7cee8d35fbc944d79fafb9e307a13b0f556cb654a06f973ed22672330197ef5a748bf826a5db2383a25364b686b9372bb2339aeb1ac9e9889327d016f1670776db06201adbdcaf8a5e3b74e108b73":"7b790c1d62f7b84e94df6af28917cf571018110e":"02d71fa9b53e4654fefb7f08385cf6b0ae3a817942ebf66c35ac67f0b069952a3ce9c7e1f1b02e480a9500836de5d64cdb7ecde04542f7a79988787e24c2ba05f5fd482c023ed5c30e04839dc44bed2a3a3a4fee01113c891a47d32eb8025c28cb050b5cdb576c70fe76ef523405c08417faf350b037a43c379339fcb18d3a356b":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 6_5 (verify)
-pkcs1_rsassa_pss_verify:1029:16:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"84ec502b072e8287789d8f9235829ea3b187afd4d4c785611bda5f9eb3cb96717efa7007227f1c08cbcb972e667235e0fb7d431a6570326d2ecce35adb373dc753b3be5f829b89175493193fab16badb41371b3aac0ae670076f24bef420c135add7cee8d35fbc944d79fafb9e307a13b0f556cb654a06f973ed22672330197ef5a748bf826a5db2383a25364b686b9372bb2339aeb1ac9e9889327d016f1670776db06201adbdcaf8a5e3b74e108b73":"7b790c1d62f7b84e94df6af28917cf571018110e":"02d71fa9b53e4654fefb7f08385cf6b0ae3a817942ebf66c35ac67f0b069952a3ce9c7e1f1b02e480a9500836de5d64cdb7ecde04542f7a79988787e24c2ba05f5fd482c023ed5c30e04839dc44bed2a3a3a4fee01113c891a47d32eb8025c28cb050b5cdb576c70fe76ef523405c08417faf350b037a43c379339fcb18d3a356b":0
+pkcs1_rsassa_pss_verify:1029:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"84ec502b072e8287789d8f9235829ea3b187afd4d4c785611bda5f9eb3cb96717efa7007227f1c08cbcb972e667235e0fb7d431a6570326d2ecce35adb373dc753b3be5f829b89175493193fab16badb41371b3aac0ae670076f24bef420c135add7cee8d35fbc944d79fafb9e307a13b0f556cb654a06f973ed22672330197ef5a748bf826a5db2383a25364b686b9372bb2339aeb1ac9e9889327d016f1670776db06201adbdcaf8a5e3b74e108b73":"7b790c1d62f7b84e94df6af28917cf571018110e":"02d71fa9b53e4654fefb7f08385cf6b0ae3a817942ebf66c35ac67f0b069952a3ce9c7e1f1b02e480a9500836de5d64cdb7ecde04542f7a79988787e24c2ba05f5fd482c023ed5c30e04839dc44bed2a3a3a4fee01113c891a47d32eb8025c28cb050b5cdb576c70fe76ef523405c08417faf350b037a43c379339fcb18d3a356b":0
 
 RSASSA-PSS Signature Example 6_6
-pkcs1_rsassa_pss_sign:1029:16:"04f0548c9626ab1ebf1244934741d99a06220efa2a5856aa0e75730b2ec96adc86be894fa2803b53a5e85d276acbd29ab823f80a7391bb54a5051672fb04eeb543":16:"0483e0ae47915587743ff345362b555d3962d98bb6f15f848b4c92b1771ca8ed107d8d3ee65ec44517dd0faa481a387e902f7a2e747c269e7ea44480bc538b8e5b":16:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"9906d89f97a9fdedd3ccd824db687326f30f00aa25a7fca2afcb3b0f86cd41e73f0e8ff7d2d83f59e28ed31a5a0d551523374de22e4c7e8ff568b386ee3dc41163f10bf67bb006261c9082f9af90bf1d9049a6b9fae71c7f84fbe6e55f02789de774f230f115026a4b4e96c55b04a95da3aacbb2cece8f81764a1f1c99515411087cf7d34aeded0932c183":"fbbe059025b69b89fb14ae2289e7aaafe60c0fcd":"0a40a16e2fe2b38d1df90546167cf9469c9e3c3681a3442b4b2c2f581deb385ce99fc6188bb02a841d56e76d301891e24560550fcc2a26b55f4ccb26d837d350a154bcaca8392d98fa67959e9727b78cad03269f56968fc56b68bd679926d83cc9cb215550645ccda31c760ff35888943d2d8a1d351e81e5d07b86182e751081ef":0
+pkcs1_rsassa_pss_sign:1029:"04f0548c9626ab1ebf1244934741d99a06220efa2a5856aa0e75730b2ec96adc86be894fa2803b53a5e85d276acbd29ab823f80a7391bb54a5051672fb04eeb543":"0483e0ae47915587743ff345362b555d3962d98bb6f15f848b4c92b1771ca8ed107d8d3ee65ec44517dd0faa481a387e902f7a2e747c269e7ea44480bc538b8e5b":"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"9906d89f97a9fdedd3ccd824db687326f30f00aa25a7fca2afcb3b0f86cd41e73f0e8ff7d2d83f59e28ed31a5a0d551523374de22e4c7e8ff568b386ee3dc41163f10bf67bb006261c9082f9af90bf1d9049a6b9fae71c7f84fbe6e55f02789de774f230f115026a4b4e96c55b04a95da3aacbb2cece8f81764a1f1c99515411087cf7d34aeded0932c183":"fbbe059025b69b89fb14ae2289e7aaafe60c0fcd":"0a40a16e2fe2b38d1df90546167cf9469c9e3c3681a3442b4b2c2f581deb385ce99fc6188bb02a841d56e76d301891e24560550fcc2a26b55f4ccb26d837d350a154bcaca8392d98fa67959e9727b78cad03269f56968fc56b68bd679926d83cc9cb215550645ccda31c760ff35888943d2d8a1d351e81e5d07b86182e751081ef":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 6_6 (verify)
-pkcs1_rsassa_pss_verify:1029:16:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"9906d89f97a9fdedd3ccd824db687326f30f00aa25a7fca2afcb3b0f86cd41e73f0e8ff7d2d83f59e28ed31a5a0d551523374de22e4c7e8ff568b386ee3dc41163f10bf67bb006261c9082f9af90bf1d9049a6b9fae71c7f84fbe6e55f02789de774f230f115026a4b4e96c55b04a95da3aacbb2cece8f81764a1f1c99515411087cf7d34aeded0932c183":"fbbe059025b69b89fb14ae2289e7aaafe60c0fcd":"0a40a16e2fe2b38d1df90546167cf9469c9e3c3681a3442b4b2c2f581deb385ce99fc6188bb02a841d56e76d301891e24560550fcc2a26b55f4ccb26d837d350a154bcaca8392d98fa67959e9727b78cad03269f56968fc56b68bd679926d83cc9cb215550645ccda31c760ff35888943d2d8a1d351e81e5d07b86182e751081ef":0
+pkcs1_rsassa_pss_verify:1029:"164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d1":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"9906d89f97a9fdedd3ccd824db687326f30f00aa25a7fca2afcb3b0f86cd41e73f0e8ff7d2d83f59e28ed31a5a0d551523374de22e4c7e8ff568b386ee3dc41163f10bf67bb006261c9082f9af90bf1d9049a6b9fae71c7f84fbe6e55f02789de774f230f115026a4b4e96c55b04a95da3aacbb2cece8f81764a1f1c99515411087cf7d34aeded0932c183":"fbbe059025b69b89fb14ae2289e7aaafe60c0fcd":"0a40a16e2fe2b38d1df90546167cf9469c9e3c3681a3442b4b2c2f581deb385ce99fc6188bb02a841d56e76d301891e24560550fcc2a26b55f4ccb26d837d350a154bcaca8392d98fa67959e9727b78cad03269f56968fc56b68bd679926d83cc9cb215550645ccda31c760ff35888943d2d8a1d351e81e5d07b86182e751081ef":0
 
 RSASSA-PSS Signature Example 7_1
-pkcs1_rsassa_pss_sign:1030:16:"07eefb424b0e3a40e4208ee5afb280b22317308114dde0b4b64f730184ec68da6ce2867a9f48ed7726d5e2614ed04a5410736c8c714ee702474298c6292af07535":16:"070830dbf947eac0228de26314b59b66994cc60e8360e75d3876298f8f8a7d141da064e5ca026a973e28f254738cee669c721b034cb5f8e244dadd7cd1e159d547":16:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"9ead0e01945640674eb41cad435e2374eaefa8ad7197d97913c44957d8d83f40d76ee60e39bf9c0f9eaf3021421a074d1ade962c6e9d3dc3bb174fe4dfe652b09115495b8fd2794174020a0602b5ca51848cfc96ce5eb57fc0a2adc1dda36a7cc452641a14911b37e45bfa11daa5c7ecdb74f6d0100d1d3e39e752800e203397de0233077b9a88855537fae927f924380d780f98e18dcff39c5ea741b17d6fdd1885bc9d581482d771ceb562d78a8bf88f0c75b11363e5e36cd479ceb0545f9da84203e0e6e508375cc9e844b88b7ac7a0a201ea0f1bee9a2c577920ca02c01b9d8320e974a56f4efb5763b96255abbf8037bf1802cf018f56379493e569a9":"b7867a59958cb54328f8775e6546ec06d27eaa50":"187f390723c8902591f0154bae6d4ecbffe067f0e8b795476ea4f4d51ccc810520bb3ca9bca7d0b1f2ea8a17d873fa27570acd642e3808561cb9e975ccfd80b23dc5771cdb3306a5f23159dacbd3aa2db93d46d766e09ed15d900ad897a8d274dc26b47e994a27e97e2268a766533ae4b5e42a2fcaf755c1c4794b294c60555823":0
+pkcs1_rsassa_pss_sign:1030:"07eefb424b0e3a40e4208ee5afb280b22317308114dde0b4b64f730184ec68da6ce2867a9f48ed7726d5e2614ed04a5410736c8c714ee702474298c6292af07535":"070830dbf947eac0228de26314b59b66994cc60e8360e75d3876298f8f8a7d141da064e5ca026a973e28f254738cee669c721b034cb5f8e244dadd7cd1e159d547":"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"9ead0e01945640674eb41cad435e2374eaefa8ad7197d97913c44957d8d83f40d76ee60e39bf9c0f9eaf3021421a074d1ade962c6e9d3dc3bb174fe4dfe652b09115495b8fd2794174020a0602b5ca51848cfc96ce5eb57fc0a2adc1dda36a7cc452641a14911b37e45bfa11daa5c7ecdb74f6d0100d1d3e39e752800e203397de0233077b9a88855537fae927f924380d780f98e18dcff39c5ea741b17d6fdd1885bc9d581482d771ceb562d78a8bf88f0c75b11363e5e36cd479ceb0545f9da84203e0e6e508375cc9e844b88b7ac7a0a201ea0f1bee9a2c577920ca02c01b9d8320e974a56f4efb5763b96255abbf8037bf1802cf018f56379493e569a9":"b7867a59958cb54328f8775e6546ec06d27eaa50":"187f390723c8902591f0154bae6d4ecbffe067f0e8b795476ea4f4d51ccc810520bb3ca9bca7d0b1f2ea8a17d873fa27570acd642e3808561cb9e975ccfd80b23dc5771cdb3306a5f23159dacbd3aa2db93d46d766e09ed15d900ad897a8d274dc26b47e994a27e97e2268a766533ae4b5e42a2fcaf755c1c4794b294c60555823":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 7_1 (verify)
-pkcs1_rsassa_pss_verify:1030:16:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"9ead0e01945640674eb41cad435e2374eaefa8ad7197d97913c44957d8d83f40d76ee60e39bf9c0f9eaf3021421a074d1ade962c6e9d3dc3bb174fe4dfe652b09115495b8fd2794174020a0602b5ca51848cfc96ce5eb57fc0a2adc1dda36a7cc452641a14911b37e45bfa11daa5c7ecdb74f6d0100d1d3e39e752800e203397de0233077b9a88855537fae927f924380d780f98e18dcff39c5ea741b17d6fdd1885bc9d581482d771ceb562d78a8bf88f0c75b11363e5e36cd479ceb0545f9da84203e0e6e508375cc9e844b88b7ac7a0a201ea0f1bee9a2c577920ca02c01b9d8320e974a56f4efb5763b96255abbf8037bf1802cf018f56379493e569a9":"b7867a59958cb54328f8775e6546ec06d27eaa50":"187f390723c8902591f0154bae6d4ecbffe067f0e8b795476ea4f4d51ccc810520bb3ca9bca7d0b1f2ea8a17d873fa27570acd642e3808561cb9e975ccfd80b23dc5771cdb3306a5f23159dacbd3aa2db93d46d766e09ed15d900ad897a8d274dc26b47e994a27e97e2268a766533ae4b5e42a2fcaf755c1c4794b294c60555823":0
+pkcs1_rsassa_pss_verify:1030:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"9ead0e01945640674eb41cad435e2374eaefa8ad7197d97913c44957d8d83f40d76ee60e39bf9c0f9eaf3021421a074d1ade962c6e9d3dc3bb174fe4dfe652b09115495b8fd2794174020a0602b5ca51848cfc96ce5eb57fc0a2adc1dda36a7cc452641a14911b37e45bfa11daa5c7ecdb74f6d0100d1d3e39e752800e203397de0233077b9a88855537fae927f924380d780f98e18dcff39c5ea741b17d6fdd1885bc9d581482d771ceb562d78a8bf88f0c75b11363e5e36cd479ceb0545f9da84203e0e6e508375cc9e844b88b7ac7a0a201ea0f1bee9a2c577920ca02c01b9d8320e974a56f4efb5763b96255abbf8037bf1802cf018f56379493e569a9":"b7867a59958cb54328f8775e6546ec06d27eaa50":"187f390723c8902591f0154bae6d4ecbffe067f0e8b795476ea4f4d51ccc810520bb3ca9bca7d0b1f2ea8a17d873fa27570acd642e3808561cb9e975ccfd80b23dc5771cdb3306a5f23159dacbd3aa2db93d46d766e09ed15d900ad897a8d274dc26b47e994a27e97e2268a766533ae4b5e42a2fcaf755c1c4794b294c60555823":0
 
 RSASSA-PSS Signature Example 7_2
-pkcs1_rsassa_pss_sign:1030:16:"07eefb424b0e3a40e4208ee5afb280b22317308114dde0b4b64f730184ec68da6ce2867a9f48ed7726d5e2614ed04a5410736c8c714ee702474298c6292af07535":16:"070830dbf947eac0228de26314b59b66994cc60e8360e75d3876298f8f8a7d141da064e5ca026a973e28f254738cee669c721b034cb5f8e244dadd7cd1e159d547":16:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"8d80d2d08dbd19c154df3f14673a14bd03735231f24e86bf153d0e69e74cbff7b1836e664de83f680124370fc0f96c9b65c07a366b644c4ab3":"0c09582266df086310821ba7e18df64dfee6de09":"10fd89768a60a67788abb5856a787c8561f3edcf9a83e898f7dc87ab8cce79429b43e56906941a886194f137e591fe7c339555361fbbe1f24feb2d4bcdb80601f3096bc9132deea60ae13082f44f9ad41cd628936a4d51176e42fc59cb76db815ce5ab4db99a104aafea68f5d330329ebf258d4ede16064bd1d00393d5e1570eb8":0
+pkcs1_rsassa_pss_sign:1030:"07eefb424b0e3a40e4208ee5afb280b22317308114dde0b4b64f730184ec68da6ce2867a9f48ed7726d5e2614ed04a5410736c8c714ee702474298c6292af07535":"070830dbf947eac0228de26314b59b66994cc60e8360e75d3876298f8f8a7d141da064e5ca026a973e28f254738cee669c721b034cb5f8e244dadd7cd1e159d547":"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"8d80d2d08dbd19c154df3f14673a14bd03735231f24e86bf153d0e69e74cbff7b1836e664de83f680124370fc0f96c9b65c07a366b644c4ab3":"0c09582266df086310821ba7e18df64dfee6de09":"10fd89768a60a67788abb5856a787c8561f3edcf9a83e898f7dc87ab8cce79429b43e56906941a886194f137e591fe7c339555361fbbe1f24feb2d4bcdb80601f3096bc9132deea60ae13082f44f9ad41cd628936a4d51176e42fc59cb76db815ce5ab4db99a104aafea68f5d330329ebf258d4ede16064bd1d00393d5e1570eb8":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 7_2 (verify)
-pkcs1_rsassa_pss_verify:1030:16:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"8d80d2d08dbd19c154df3f14673a14bd03735231f24e86bf153d0e69e74cbff7b1836e664de83f680124370fc0f96c9b65c07a366b644c4ab3":"0c09582266df086310821ba7e18df64dfee6de09":"10fd89768a60a67788abb5856a787c8561f3edcf9a83e898f7dc87ab8cce79429b43e56906941a886194f137e591fe7c339555361fbbe1f24feb2d4bcdb80601f3096bc9132deea60ae13082f44f9ad41cd628936a4d51176e42fc59cb76db815ce5ab4db99a104aafea68f5d330329ebf258d4ede16064bd1d00393d5e1570eb8":0
+pkcs1_rsassa_pss_verify:1030:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"8d80d2d08dbd19c154df3f14673a14bd03735231f24e86bf153d0e69e74cbff7b1836e664de83f680124370fc0f96c9b65c07a366b644c4ab3":"0c09582266df086310821ba7e18df64dfee6de09":"10fd89768a60a67788abb5856a787c8561f3edcf9a83e898f7dc87ab8cce79429b43e56906941a886194f137e591fe7c339555361fbbe1f24feb2d4bcdb80601f3096bc9132deea60ae13082f44f9ad41cd628936a4d51176e42fc59cb76db815ce5ab4db99a104aafea68f5d330329ebf258d4ede16064bd1d00393d5e1570eb8":0
 
 RSASSA-PSS Signature Example 7_3
-pkcs1_rsassa_pss_sign:1030:16:"07eefb424b0e3a40e4208ee5afb280b22317308114dde0b4b64f730184ec68da6ce2867a9f48ed7726d5e2614ed04a5410736c8c714ee702474298c6292af07535":16:"070830dbf947eac0228de26314b59b66994cc60e8360e75d3876298f8f8a7d141da064e5ca026a973e28f254738cee669c721b034cb5f8e244dadd7cd1e159d547":16:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"808405cdfc1a58b9bb0397c720722a81fffb76278f335917ef9c473814b3e016ba2973cd2765f8f3f82d6cc38aa7f8551827fe8d1e3884b7e61c94683b8f82f1843bdae2257eeec9812ad4c2cf283c34e0b0ae0fe3cb990cf88f2ef9":"28039dcfe106d3b8296611258c4a56651c9e92dd":"2b31fde99859b977aa09586d8e274662b25a2a640640b457f594051cb1e7f7a911865455242926cf88fe80dfa3a75ba9689844a11e634a82b075afbd69c12a0df9d25f84ad4945df3dc8fe90c3cefdf26e95f0534304b5bdba20d3e5640a2ebfb898aac35ae40f26fce5563c2f9f24f3042af76f3c7072d687bbfb959a88460af1":0
+pkcs1_rsassa_pss_sign:1030:"07eefb424b0e3a40e4208ee5afb280b22317308114dde0b4b64f730184ec68da6ce2867a9f48ed7726d5e2614ed04a5410736c8c714ee702474298c6292af07535":"070830dbf947eac0228de26314b59b66994cc60e8360e75d3876298f8f8a7d141da064e5ca026a973e28f254738cee669c721b034cb5f8e244dadd7cd1e159d547":"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"808405cdfc1a58b9bb0397c720722a81fffb76278f335917ef9c473814b3e016ba2973cd2765f8f3f82d6cc38aa7f8551827fe8d1e3884b7e61c94683b8f82f1843bdae2257eeec9812ad4c2cf283c34e0b0ae0fe3cb990cf88f2ef9":"28039dcfe106d3b8296611258c4a56651c9e92dd":"2b31fde99859b977aa09586d8e274662b25a2a640640b457f594051cb1e7f7a911865455242926cf88fe80dfa3a75ba9689844a11e634a82b075afbd69c12a0df9d25f84ad4945df3dc8fe90c3cefdf26e95f0534304b5bdba20d3e5640a2ebfb898aac35ae40f26fce5563c2f9f24f3042af76f3c7072d687bbfb959a88460af1":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 7_3 (verify)
-pkcs1_rsassa_pss_verify:1030:16:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"808405cdfc1a58b9bb0397c720722a81fffb76278f335917ef9c473814b3e016ba2973cd2765f8f3f82d6cc38aa7f8551827fe8d1e3884b7e61c94683b8f82f1843bdae2257eeec9812ad4c2cf283c34e0b0ae0fe3cb990cf88f2ef9":"28039dcfe106d3b8296611258c4a56651c9e92dd":"2b31fde99859b977aa09586d8e274662b25a2a640640b457f594051cb1e7f7a911865455242926cf88fe80dfa3a75ba9689844a11e634a82b075afbd69c12a0df9d25f84ad4945df3dc8fe90c3cefdf26e95f0534304b5bdba20d3e5640a2ebfb898aac35ae40f26fce5563c2f9f24f3042af76f3c7072d687bbfb959a88460af1":0
+pkcs1_rsassa_pss_verify:1030:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"808405cdfc1a58b9bb0397c720722a81fffb76278f335917ef9c473814b3e016ba2973cd2765f8f3f82d6cc38aa7f8551827fe8d1e3884b7e61c94683b8f82f1843bdae2257eeec9812ad4c2cf283c34e0b0ae0fe3cb990cf88f2ef9":"28039dcfe106d3b8296611258c4a56651c9e92dd":"2b31fde99859b977aa09586d8e274662b25a2a640640b457f594051cb1e7f7a911865455242926cf88fe80dfa3a75ba9689844a11e634a82b075afbd69c12a0df9d25f84ad4945df3dc8fe90c3cefdf26e95f0534304b5bdba20d3e5640a2ebfb898aac35ae40f26fce5563c2f9f24f3042af76f3c7072d687bbfb959a88460af1":0
 
 RSASSA-PSS Signature Example 7_4
-pkcs1_rsassa_pss_sign:1030:16:"07eefb424b0e3a40e4208ee5afb280b22317308114dde0b4b64f730184ec68da6ce2867a9f48ed7726d5e2614ed04a5410736c8c714ee702474298c6292af07535":16:"070830dbf947eac0228de26314b59b66994cc60e8360e75d3876298f8f8a7d141da064e5ca026a973e28f254738cee669c721b034cb5f8e244dadd7cd1e159d547":16:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"f337b9bad937de22a1a052dff11134a8ce26976202981939b91e0715ae5e609649da1adfcef3f4cca59b238360e7d1e496c7bf4b204b5acff9bbd6166a1d87a36ef2247373751039f8a800b8399807b3a85f44893497c0d05fb7017b82228152de6f25e6116dcc7503c786c875c28f3aa607e94ab0f19863ab1b5073770b0cd5f533acde30c6fb953cf3da680264e30fc11bff9a19bffab4779b6223c3fb3fe0f71abade4eb7c09c41e24c22d23fa148e6a173feb63984d1bc6ee3a02d915b752ceaf92a3015eceb38ca586c6801b37c34cefb2cff25ea23c08662dcab26a7a93a285d05d3044c":"a77821ebbbef24628e4e12e1d0ea96de398f7b0f":"32c7ca38ff26949a15000c4ba04b2b13b35a3810e568184d7ecabaa166b7ffabddf2b6cf4ba07124923790f2e5b1a5be040aea36fe132ec130e1f10567982d17ac3e89b8d26c3094034e762d2e031264f01170beecb3d1439e05846f25458367a7d9c02060444672671e64e877864559ca19b2074d588a281b5804d23772fbbe19":0
+pkcs1_rsassa_pss_sign:1030:"07eefb424b0e3a40e4208ee5afb280b22317308114dde0b4b64f730184ec68da6ce2867a9f48ed7726d5e2614ed04a5410736c8c714ee702474298c6292af07535":"070830dbf947eac0228de26314b59b66994cc60e8360e75d3876298f8f8a7d141da064e5ca026a973e28f254738cee669c721b034cb5f8e244dadd7cd1e159d547":"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"f337b9bad937de22a1a052dff11134a8ce26976202981939b91e0715ae5e609649da1adfcef3f4cca59b238360e7d1e496c7bf4b204b5acff9bbd6166a1d87a36ef2247373751039f8a800b8399807b3a85f44893497c0d05fb7017b82228152de6f25e6116dcc7503c786c875c28f3aa607e94ab0f19863ab1b5073770b0cd5f533acde30c6fb953cf3da680264e30fc11bff9a19bffab4779b6223c3fb3fe0f71abade4eb7c09c41e24c22d23fa148e6a173feb63984d1bc6ee3a02d915b752ceaf92a3015eceb38ca586c6801b37c34cefb2cff25ea23c08662dcab26a7a93a285d05d3044c":"a77821ebbbef24628e4e12e1d0ea96de398f7b0f":"32c7ca38ff26949a15000c4ba04b2b13b35a3810e568184d7ecabaa166b7ffabddf2b6cf4ba07124923790f2e5b1a5be040aea36fe132ec130e1f10567982d17ac3e89b8d26c3094034e762d2e031264f01170beecb3d1439e05846f25458367a7d9c02060444672671e64e877864559ca19b2074d588a281b5804d23772fbbe19":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 7_4 (verify)
-pkcs1_rsassa_pss_verify:1030:16:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"f337b9bad937de22a1a052dff11134a8ce26976202981939b91e0715ae5e609649da1adfcef3f4cca59b238360e7d1e496c7bf4b204b5acff9bbd6166a1d87a36ef2247373751039f8a800b8399807b3a85f44893497c0d05fb7017b82228152de6f25e6116dcc7503c786c875c28f3aa607e94ab0f19863ab1b5073770b0cd5f533acde30c6fb953cf3da680264e30fc11bff9a19bffab4779b6223c3fb3fe0f71abade4eb7c09c41e24c22d23fa148e6a173feb63984d1bc6ee3a02d915b752ceaf92a3015eceb38ca586c6801b37c34cefb2cff25ea23c08662dcab26a7a93a285d05d3044c":"a77821ebbbef24628e4e12e1d0ea96de398f7b0f":"32c7ca38ff26949a15000c4ba04b2b13b35a3810e568184d7ecabaa166b7ffabddf2b6cf4ba07124923790f2e5b1a5be040aea36fe132ec130e1f10567982d17ac3e89b8d26c3094034e762d2e031264f01170beecb3d1439e05846f25458367a7d9c02060444672671e64e877864559ca19b2074d588a281b5804d23772fbbe19":0
+pkcs1_rsassa_pss_verify:1030:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"f337b9bad937de22a1a052dff11134a8ce26976202981939b91e0715ae5e609649da1adfcef3f4cca59b238360e7d1e496c7bf4b204b5acff9bbd6166a1d87a36ef2247373751039f8a800b8399807b3a85f44893497c0d05fb7017b82228152de6f25e6116dcc7503c786c875c28f3aa607e94ab0f19863ab1b5073770b0cd5f533acde30c6fb953cf3da680264e30fc11bff9a19bffab4779b6223c3fb3fe0f71abade4eb7c09c41e24c22d23fa148e6a173feb63984d1bc6ee3a02d915b752ceaf92a3015eceb38ca586c6801b37c34cefb2cff25ea23c08662dcab26a7a93a285d05d3044c":"a77821ebbbef24628e4e12e1d0ea96de398f7b0f":"32c7ca38ff26949a15000c4ba04b2b13b35a3810e568184d7ecabaa166b7ffabddf2b6cf4ba07124923790f2e5b1a5be040aea36fe132ec130e1f10567982d17ac3e89b8d26c3094034e762d2e031264f01170beecb3d1439e05846f25458367a7d9c02060444672671e64e877864559ca19b2074d588a281b5804d23772fbbe19":0
 
 RSASSA-PSS Signature Example 7_5
-pkcs1_rsassa_pss_sign:1030:16:"07eefb424b0e3a40e4208ee5afb280b22317308114dde0b4b64f730184ec68da6ce2867a9f48ed7726d5e2614ed04a5410736c8c714ee702474298c6292af07535":16:"070830dbf947eac0228de26314b59b66994cc60e8360e75d3876298f8f8a7d141da064e5ca026a973e28f254738cee669c721b034cb5f8e244dadd7cd1e159d547":16:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"45013cebafd960b255476a8e2598b9aa32efbe6dc1f34f4a498d8cf5a2b4548d08c55d5f95f7bcc9619163056f2d58b52fa032":"9d5ad8eb452134b65dc3a98b6a73b5f741609cd6":"07eb651d75f1b52bc263b2e198336e99fbebc4f332049a922a10815607ee2d989db3a4495b7dccd38f58a211fb7e193171a3d891132437ebca44f318b280509e52b5fa98fcce8205d9697c8ee4b7ff59d4c59c79038a1970bd2a0d451ecdc5ef11d9979c9d35f8c70a6163717607890d586a7c6dc01c79f86a8f28e85235f8c2f1":0
+pkcs1_rsassa_pss_sign:1030:"07eefb424b0e3a40e4208ee5afb280b22317308114dde0b4b64f730184ec68da6ce2867a9f48ed7726d5e2614ed04a5410736c8c714ee702474298c6292af07535":"070830dbf947eac0228de26314b59b66994cc60e8360e75d3876298f8f8a7d141da064e5ca026a973e28f254738cee669c721b034cb5f8e244dadd7cd1e159d547":"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"45013cebafd960b255476a8e2598b9aa32efbe6dc1f34f4a498d8cf5a2b4548d08c55d5f95f7bcc9619163056f2d58b52fa032":"9d5ad8eb452134b65dc3a98b6a73b5f741609cd6":"07eb651d75f1b52bc263b2e198336e99fbebc4f332049a922a10815607ee2d989db3a4495b7dccd38f58a211fb7e193171a3d891132437ebca44f318b280509e52b5fa98fcce8205d9697c8ee4b7ff59d4c59c79038a1970bd2a0d451ecdc5ef11d9979c9d35f8c70a6163717607890d586a7c6dc01c79f86a8f28e85235f8c2f1":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 7_5 (verify)
-pkcs1_rsassa_pss_verify:1030:16:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"45013cebafd960b255476a8e2598b9aa32efbe6dc1f34f4a498d8cf5a2b4548d08c55d5f95f7bcc9619163056f2d58b52fa032":"9d5ad8eb452134b65dc3a98b6a73b5f741609cd6":"07eb651d75f1b52bc263b2e198336e99fbebc4f332049a922a10815607ee2d989db3a4495b7dccd38f58a211fb7e193171a3d891132437ebca44f318b280509e52b5fa98fcce8205d9697c8ee4b7ff59d4c59c79038a1970bd2a0d451ecdc5ef11d9979c9d35f8c70a6163717607890d586a7c6dc01c79f86a8f28e85235f8c2f1":0
+pkcs1_rsassa_pss_verify:1030:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"45013cebafd960b255476a8e2598b9aa32efbe6dc1f34f4a498d8cf5a2b4548d08c55d5f95f7bcc9619163056f2d58b52fa032":"9d5ad8eb452134b65dc3a98b6a73b5f741609cd6":"07eb651d75f1b52bc263b2e198336e99fbebc4f332049a922a10815607ee2d989db3a4495b7dccd38f58a211fb7e193171a3d891132437ebca44f318b280509e52b5fa98fcce8205d9697c8ee4b7ff59d4c59c79038a1970bd2a0d451ecdc5ef11d9979c9d35f8c70a6163717607890d586a7c6dc01c79f86a8f28e85235f8c2f1":0
 
 RSASSA-PSS Signature Example 7_6
-pkcs1_rsassa_pss_sign:1030:16:"07eefb424b0e3a40e4208ee5afb280b22317308114dde0b4b64f730184ec68da6ce2867a9f48ed7726d5e2614ed04a5410736c8c714ee702474298c6292af07535":16:"070830dbf947eac0228de26314b59b66994cc60e8360e75d3876298f8f8a7d141da064e5ca026a973e28f254738cee669c721b034cb5f8e244dadd7cd1e159d547":16:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"2358097086c899323e75d9c90d0c09f12d9d54edfbdf70a9c2eb5a04d8f36b9b2bdf2aabe0a5bda1968937f9d6ebd3b6b257efb3136d4131f9acb59b85e2602c2a3fcdc835494a1f4e5ec18b226c80232b36a75a45fdf09a7ea9e98efbde1450d1194bf12e15a4c5f9eb5c0bce5269e0c3b28cfab655d81a61a20b4be2f54459bb25a0db94c52218be109a7426de83014424789aaa90e5056e632a698115e282c1a56410f26c2072f193481a9dcd880572005e64f4082ecf":"3f2efc595880a7d47fcf3cba04983ea54c4b73fb":"18da3cdcfe79bfb77fd9c32f377ad399146f0a8e810620233271a6e3ed3248903f5cdc92dc79b55d3e11615aa056a795853792a3998c349ca5c457e8ca7d29d796aa24f83491709befcfb1510ea513c92829a3f00b104f655634f320752e130ec0ccf6754ff893db302932bb025eb60e87822598fc619e0e981737a9a4c4152d33":0
+pkcs1_rsassa_pss_sign:1030:"07eefb424b0e3a40e4208ee5afb280b22317308114dde0b4b64f730184ec68da6ce2867a9f48ed7726d5e2614ed04a5410736c8c714ee702474298c6292af07535":"070830dbf947eac0228de26314b59b66994cc60e8360e75d3876298f8f8a7d141da064e5ca026a973e28f254738cee669c721b034cb5f8e244dadd7cd1e159d547":"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"2358097086c899323e75d9c90d0c09f12d9d54edfbdf70a9c2eb5a04d8f36b9b2bdf2aabe0a5bda1968937f9d6ebd3b6b257efb3136d4131f9acb59b85e2602c2a3fcdc835494a1f4e5ec18b226c80232b36a75a45fdf09a7ea9e98efbde1450d1194bf12e15a4c5f9eb5c0bce5269e0c3b28cfab655d81a61a20b4be2f54459bb25a0db94c52218be109a7426de83014424789aaa90e5056e632a698115e282c1a56410f26c2072f193481a9dcd880572005e64f4082ecf":"3f2efc595880a7d47fcf3cba04983ea54c4b73fb":"18da3cdcfe79bfb77fd9c32f377ad399146f0a8e810620233271a6e3ed3248903f5cdc92dc79b55d3e11615aa056a795853792a3998c349ca5c457e8ca7d29d796aa24f83491709befcfb1510ea513c92829a3f00b104f655634f320752e130ec0ccf6754ff893db302932bb025eb60e87822598fc619e0e981737a9a4c4152d33":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 7_6 (verify)
-pkcs1_rsassa_pss_verify:1030:16:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"2358097086c899323e75d9c90d0c09f12d9d54edfbdf70a9c2eb5a04d8f36b9b2bdf2aabe0a5bda1968937f9d6ebd3b6b257efb3136d4131f9acb59b85e2602c2a3fcdc835494a1f4e5ec18b226c80232b36a75a45fdf09a7ea9e98efbde1450d1194bf12e15a4c5f9eb5c0bce5269e0c3b28cfab655d81a61a20b4be2f54459bb25a0db94c52218be109a7426de83014424789aaa90e5056e632a698115e282c1a56410f26c2072f193481a9dcd880572005e64f4082ecf":"3f2efc595880a7d47fcf3cba04983ea54c4b73fb":"18da3cdcfe79bfb77fd9c32f377ad399146f0a8e810620233271a6e3ed3248903f5cdc92dc79b55d3e11615aa056a795853792a3998c349ca5c457e8ca7d29d796aa24f83491709befcfb1510ea513c92829a3f00b104f655634f320752e130ec0ccf6754ff893db302932bb025eb60e87822598fc619e0e981737a9a4c4152d33":0
+pkcs1_rsassa_pss_verify:1030:"37c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab3":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"2358097086c899323e75d9c90d0c09f12d9d54edfbdf70a9c2eb5a04d8f36b9b2bdf2aabe0a5bda1968937f9d6ebd3b6b257efb3136d4131f9acb59b85e2602c2a3fcdc835494a1f4e5ec18b226c80232b36a75a45fdf09a7ea9e98efbde1450d1194bf12e15a4c5f9eb5c0bce5269e0c3b28cfab655d81a61a20b4be2f54459bb25a0db94c52218be109a7426de83014424789aaa90e5056e632a698115e282c1a56410f26c2072f193481a9dcd880572005e64f4082ecf":"3f2efc595880a7d47fcf3cba04983ea54c4b73fb":"18da3cdcfe79bfb77fd9c32f377ad399146f0a8e810620233271a6e3ed3248903f5cdc92dc79b55d3e11615aa056a795853792a3998c349ca5c457e8ca7d29d796aa24f83491709befcfb1510ea513c92829a3f00b104f655634f320752e130ec0ccf6754ff893db302932bb025eb60e87822598fc619e0e981737a9a4c4152d33":0
 
 RSASSA-PSS Signature Example 8_1
-pkcs1_rsassa_pss_sign:1031:16:"08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb":16:"0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d":16:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"81332f4be62948415ea1d899792eeacf6c6e1db1da8be13b5cea41db2fed467092e1ff398914c714259775f595f8547f735692a575e6923af78f22c6997ddb90fb6f72d7bb0dd5744a31decd3dc3685849836ed34aec596304ad11843c4f88489f209735f5fb7fdaf7cec8addc5818168f880acbf490d51005b7a8e84e43e54287977571dd99eea4b161eb2df1f5108f12a4142a83322edb05a75487a3435c9a78ce53ed93bc550857d7a9fb":"1d65491d79c864b373009be6f6f2467bac4c78fa":"0262ac254bfa77f3c1aca22c5179f8f040422b3c5bafd40a8f21cf0fa5a667ccd5993d42dbafb409c520e25fce2b1ee1e716577f1efa17f3da28052f40f0419b23106d7845aaf01125b698e7a4dfe92d3967bb00c4d0d35ba3552ab9a8b3eef07c7fecdbc5424ac4db1e20cb37d0b2744769940ea907e17fbbca673b20522380c5":0
+pkcs1_rsassa_pss_sign:1031:"08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb":"0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d":"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"81332f4be62948415ea1d899792eeacf6c6e1db1da8be13b5cea41db2fed467092e1ff398914c714259775f595f8547f735692a575e6923af78f22c6997ddb90fb6f72d7bb0dd5744a31decd3dc3685849836ed34aec596304ad11843c4f88489f209735f5fb7fdaf7cec8addc5818168f880acbf490d51005b7a8e84e43e54287977571dd99eea4b161eb2df1f5108f12a4142a83322edb05a75487a3435c9a78ce53ed93bc550857d7a9fb":"1d65491d79c864b373009be6f6f2467bac4c78fa":"0262ac254bfa77f3c1aca22c5179f8f040422b3c5bafd40a8f21cf0fa5a667ccd5993d42dbafb409c520e25fce2b1ee1e716577f1efa17f3da28052f40f0419b23106d7845aaf01125b698e7a4dfe92d3967bb00c4d0d35ba3552ab9a8b3eef07c7fecdbc5424ac4db1e20cb37d0b2744769940ea907e17fbbca673b20522380c5":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 8_1 (verify)
-pkcs1_rsassa_pss_verify:1031:16:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"81332f4be62948415ea1d899792eeacf6c6e1db1da8be13b5cea41db2fed467092e1ff398914c714259775f595f8547f735692a575e6923af78f22c6997ddb90fb6f72d7bb0dd5744a31decd3dc3685849836ed34aec596304ad11843c4f88489f209735f5fb7fdaf7cec8addc5818168f880acbf490d51005b7a8e84e43e54287977571dd99eea4b161eb2df1f5108f12a4142a83322edb05a75487a3435c9a78ce53ed93bc550857d7a9fb":"1d65491d79c864b373009be6f6f2467bac4c78fa":"0262ac254bfa77f3c1aca22c5179f8f040422b3c5bafd40a8f21cf0fa5a667ccd5993d42dbafb409c520e25fce2b1ee1e716577f1efa17f3da28052f40f0419b23106d7845aaf01125b698e7a4dfe92d3967bb00c4d0d35ba3552ab9a8b3eef07c7fecdbc5424ac4db1e20cb37d0b2744769940ea907e17fbbca673b20522380c5":0
+pkcs1_rsassa_pss_verify:1031:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"81332f4be62948415ea1d899792eeacf6c6e1db1da8be13b5cea41db2fed467092e1ff398914c714259775f595f8547f735692a575e6923af78f22c6997ddb90fb6f72d7bb0dd5744a31decd3dc3685849836ed34aec596304ad11843c4f88489f209735f5fb7fdaf7cec8addc5818168f880acbf490d51005b7a8e84e43e54287977571dd99eea4b161eb2df1f5108f12a4142a83322edb05a75487a3435c9a78ce53ed93bc550857d7a9fb":"1d65491d79c864b373009be6f6f2467bac4c78fa":"0262ac254bfa77f3c1aca22c5179f8f040422b3c5bafd40a8f21cf0fa5a667ccd5993d42dbafb409c520e25fce2b1ee1e716577f1efa17f3da28052f40f0419b23106d7845aaf01125b698e7a4dfe92d3967bb00c4d0d35ba3552ab9a8b3eef07c7fecdbc5424ac4db1e20cb37d0b2744769940ea907e17fbbca673b20522380c5":0
 
 RSASSA-PSS Signature Example 8_2
-pkcs1_rsassa_pss_sign:1031:16:"08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb":16:"0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d":16:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e2f96eaf0e05e7ba326ecca0ba7fd2f7c02356f3cede9d0faabf4fcc8e60a973e5595fd9ea08":"435c098aa9909eb2377f1248b091b68987ff1838":"2707b9ad5115c58c94e932e8ec0a280f56339e44a1b58d4ddcff2f312e5f34dcfe39e89c6a94dcee86dbbdae5b79ba4e0819a9e7bfd9d982e7ee6c86ee68396e8b3a14c9c8f34b178eb741f9d3f121109bf5c8172fada2e768f9ea1433032c004a8aa07eb990000a48dc94c8bac8aabe2b09b1aa46c0a2aa0e12f63fbba775ba7e":0
+pkcs1_rsassa_pss_sign:1031:"08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb":"0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d":"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e2f96eaf0e05e7ba326ecca0ba7fd2f7c02356f3cede9d0faabf4fcc8e60a973e5595fd9ea08":"435c098aa9909eb2377f1248b091b68987ff1838":"2707b9ad5115c58c94e932e8ec0a280f56339e44a1b58d4ddcff2f312e5f34dcfe39e89c6a94dcee86dbbdae5b79ba4e0819a9e7bfd9d982e7ee6c86ee68396e8b3a14c9c8f34b178eb741f9d3f121109bf5c8172fada2e768f9ea1433032c004a8aa07eb990000a48dc94c8bac8aabe2b09b1aa46c0a2aa0e12f63fbba775ba7e":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 8_2 (verify)
-pkcs1_rsassa_pss_verify:1031:16:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e2f96eaf0e05e7ba326ecca0ba7fd2f7c02356f3cede9d0faabf4fcc8e60a973e5595fd9ea08":"435c098aa9909eb2377f1248b091b68987ff1838":"2707b9ad5115c58c94e932e8ec0a280f56339e44a1b58d4ddcff2f312e5f34dcfe39e89c6a94dcee86dbbdae5b79ba4e0819a9e7bfd9d982e7ee6c86ee68396e8b3a14c9c8f34b178eb741f9d3f121109bf5c8172fada2e768f9ea1433032c004a8aa07eb990000a48dc94c8bac8aabe2b09b1aa46c0a2aa0e12f63fbba775ba7e":0
+pkcs1_rsassa_pss_verify:1031:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e2f96eaf0e05e7ba326ecca0ba7fd2f7c02356f3cede9d0faabf4fcc8e60a973e5595fd9ea08":"435c098aa9909eb2377f1248b091b68987ff1838":"2707b9ad5115c58c94e932e8ec0a280f56339e44a1b58d4ddcff2f312e5f34dcfe39e89c6a94dcee86dbbdae5b79ba4e0819a9e7bfd9d982e7ee6c86ee68396e8b3a14c9c8f34b178eb741f9d3f121109bf5c8172fada2e768f9ea1433032c004a8aa07eb990000a48dc94c8bac8aabe2b09b1aa46c0a2aa0e12f63fbba775ba7e":0
 
 RSASSA-PSS Signature Example 8_3
-pkcs1_rsassa_pss_sign:1031:16:"08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb":16:"0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d":16:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"c6ebbe76df0c4aea32c474175b2f136862d04529":"2ad20509d78cf26d1b6c406146086e4b0c91a91c2bd164c87b966b8faa42aa0ca446022323ba4b1a1b89706d7f4c3be57d7b69702d168ab5955ee290356b8c4a29ed467d547ec23cbadf286ccb5863c6679da467fc9324a151c7ec55aac6db4084f82726825cfe1aa421bc64049fb42f23148f9c25b2dc300437c38d428aa75f96":0
+pkcs1_rsassa_pss_sign:1031:"08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb":"0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d":"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"c6ebbe76df0c4aea32c474175b2f136862d04529":"2ad20509d78cf26d1b6c406146086e4b0c91a91c2bd164c87b966b8faa42aa0ca446022323ba4b1a1b89706d7f4c3be57d7b69702d168ab5955ee290356b8c4a29ed467d547ec23cbadf286ccb5863c6679da467fc9324a151c7ec55aac6db4084f82726825cfe1aa421bc64049fb42f23148f9c25b2dc300437c38d428aa75f96":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 8_3 (verify)
-pkcs1_rsassa_pss_verify:1031:16:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"c6ebbe76df0c4aea32c474175b2f136862d04529":"2ad20509d78cf26d1b6c406146086e4b0c91a91c2bd164c87b966b8faa42aa0ca446022323ba4b1a1b89706d7f4c3be57d7b69702d168ab5955ee290356b8c4a29ed467d547ec23cbadf286ccb5863c6679da467fc9324a151c7ec55aac6db4084f82726825cfe1aa421bc64049fb42f23148f9c25b2dc300437c38d428aa75f96":0
+pkcs1_rsassa_pss_verify:1031:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"c6ebbe76df0c4aea32c474175b2f136862d04529":"2ad20509d78cf26d1b6c406146086e4b0c91a91c2bd164c87b966b8faa42aa0ca446022323ba4b1a1b89706d7f4c3be57d7b69702d168ab5955ee290356b8c4a29ed467d547ec23cbadf286ccb5863c6679da467fc9324a151c7ec55aac6db4084f82726825cfe1aa421bc64049fb42f23148f9c25b2dc300437c38d428aa75f96":0
 
 RSASSA-PSS Signature Example 8_4
-pkcs1_rsassa_pss_sign:1031:16:"08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb":16:"0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d":16:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"dbc5f750a7a14be2b93e838d18d14a8695e52e8add9c0ac733b8f56d2747e529a0cca532dd49b902aefed514447f9e81d16195c2853868cb9b30f7d0d495c69d01b5c5d50b27045db3866c2324a44a110b1717746de457d1c8c45c3cd2a92970c3d59632055d4c98a41d6e99e2a3ddd5f7f9979ab3cd18f37505d25141de2a1bff17b3a7dce9419ecc385cf11d72840f19953fd0509251f6cafde2893d0e75c781ba7a5012ca401a4fa99e04b3c3249f926d5afe82cc87dab22c3c1b105de48e34ace9c9124e59597ac7ebf8":"021fdcc6ebb5e19b1cb16e9c67f27681657fe20a":"1e24e6e58628e5175044a9eb6d837d48af1260b0520e87327de7897ee4d5b9f0df0be3e09ed4dea8c1454ff3423bb08e1793245a9df8bf6ab3968c8eddc3b5328571c77f091cc578576912dfebd164b9de5454fe0be1c1f6385b328360ce67ec7a05f6e30eb45c17c48ac70041d2cab67f0a2ae7aafdcc8d245ea3442a6300ccc7":0
+pkcs1_rsassa_pss_sign:1031:"08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb":"0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d":"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"dbc5f750a7a14be2b93e838d18d14a8695e52e8add9c0ac733b8f56d2747e529a0cca532dd49b902aefed514447f9e81d16195c2853868cb9b30f7d0d495c69d01b5c5d50b27045db3866c2324a44a110b1717746de457d1c8c45c3cd2a92970c3d59632055d4c98a41d6e99e2a3ddd5f7f9979ab3cd18f37505d25141de2a1bff17b3a7dce9419ecc385cf11d72840f19953fd0509251f6cafde2893d0e75c781ba7a5012ca401a4fa99e04b3c3249f926d5afe82cc87dab22c3c1b105de48e34ace9c9124e59597ac7ebf8":"021fdcc6ebb5e19b1cb16e9c67f27681657fe20a":"1e24e6e58628e5175044a9eb6d837d48af1260b0520e87327de7897ee4d5b9f0df0be3e09ed4dea8c1454ff3423bb08e1793245a9df8bf6ab3968c8eddc3b5328571c77f091cc578576912dfebd164b9de5454fe0be1c1f6385b328360ce67ec7a05f6e30eb45c17c48ac70041d2cab67f0a2ae7aafdcc8d245ea3442a6300ccc7":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 8_4 (verify)
-pkcs1_rsassa_pss_verify:1031:16:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"dbc5f750a7a14be2b93e838d18d14a8695e52e8add9c0ac733b8f56d2747e529a0cca532dd49b902aefed514447f9e81d16195c2853868cb9b30f7d0d495c69d01b5c5d50b27045db3866c2324a44a110b1717746de457d1c8c45c3cd2a92970c3d59632055d4c98a41d6e99e2a3ddd5f7f9979ab3cd18f37505d25141de2a1bff17b3a7dce9419ecc385cf11d72840f19953fd0509251f6cafde2893d0e75c781ba7a5012ca401a4fa99e04b3c3249f926d5afe82cc87dab22c3c1b105de48e34ace9c9124e59597ac7ebf8":"021fdcc6ebb5e19b1cb16e9c67f27681657fe20a":"1e24e6e58628e5175044a9eb6d837d48af1260b0520e87327de7897ee4d5b9f0df0be3e09ed4dea8c1454ff3423bb08e1793245a9df8bf6ab3968c8eddc3b5328571c77f091cc578576912dfebd164b9de5454fe0be1c1f6385b328360ce67ec7a05f6e30eb45c17c48ac70041d2cab67f0a2ae7aafdcc8d245ea3442a6300ccc7":0
+pkcs1_rsassa_pss_verify:1031:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"dbc5f750a7a14be2b93e838d18d14a8695e52e8add9c0ac733b8f56d2747e529a0cca532dd49b902aefed514447f9e81d16195c2853868cb9b30f7d0d495c69d01b5c5d50b27045db3866c2324a44a110b1717746de457d1c8c45c3cd2a92970c3d59632055d4c98a41d6e99e2a3ddd5f7f9979ab3cd18f37505d25141de2a1bff17b3a7dce9419ecc385cf11d72840f19953fd0509251f6cafde2893d0e75c781ba7a5012ca401a4fa99e04b3c3249f926d5afe82cc87dab22c3c1b105de48e34ace9c9124e59597ac7ebf8":"021fdcc6ebb5e19b1cb16e9c67f27681657fe20a":"1e24e6e58628e5175044a9eb6d837d48af1260b0520e87327de7897ee4d5b9f0df0be3e09ed4dea8c1454ff3423bb08e1793245a9df8bf6ab3968c8eddc3b5328571c77f091cc578576912dfebd164b9de5454fe0be1c1f6385b328360ce67ec7a05f6e30eb45c17c48ac70041d2cab67f0a2ae7aafdcc8d245ea3442a6300ccc7":0
 
 RSASSA-PSS Signature Example 8_5
-pkcs1_rsassa_pss_sign:1031:16:"08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb":16:"0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d":16:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"04dc251be72e88e5723485b6383a637e2fefe07660c519a560b8bc18bdedb86eae2364ea53ba9dca6eb3d2e7d6b806af42b3e87f291b4a8881d5bf572cc9a85e19c86acb28f098f9da0383c566d3c0f58cfd8f395dcf602e5cd40e8c7183f714996e2297ef":"c558d7167cbb4508ada042971e71b1377eea4269":"33341ba3576a130a50e2a5cf8679224388d5693f5accc235ac95add68e5eb1eec31666d0ca7a1cda6f70a1aa762c05752a51950cdb8af3c5379f18cfe6b5bc55a4648226a15e912ef19ad77adeea911d67cfefd69ba43fa4119135ff642117ba985a7e0100325e9519f1ca6a9216bda055b5785015291125e90dcd07a2ca9673ee":0
+pkcs1_rsassa_pss_sign:1031:"08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb":"0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d":"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"04dc251be72e88e5723485b6383a637e2fefe07660c519a560b8bc18bdedb86eae2364ea53ba9dca6eb3d2e7d6b806af42b3e87f291b4a8881d5bf572cc9a85e19c86acb28f098f9da0383c566d3c0f58cfd8f395dcf602e5cd40e8c7183f714996e2297ef":"c558d7167cbb4508ada042971e71b1377eea4269":"33341ba3576a130a50e2a5cf8679224388d5693f5accc235ac95add68e5eb1eec31666d0ca7a1cda6f70a1aa762c05752a51950cdb8af3c5379f18cfe6b5bc55a4648226a15e912ef19ad77adeea911d67cfefd69ba43fa4119135ff642117ba985a7e0100325e9519f1ca6a9216bda055b5785015291125e90dcd07a2ca9673ee":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 8_5 (verify)
-pkcs1_rsassa_pss_verify:1031:16:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"04dc251be72e88e5723485b6383a637e2fefe07660c519a560b8bc18bdedb86eae2364ea53ba9dca6eb3d2e7d6b806af42b3e87f291b4a8881d5bf572cc9a85e19c86acb28f098f9da0383c566d3c0f58cfd8f395dcf602e5cd40e8c7183f714996e2297ef":"c558d7167cbb4508ada042971e71b1377eea4269":"33341ba3576a130a50e2a5cf8679224388d5693f5accc235ac95add68e5eb1eec31666d0ca7a1cda6f70a1aa762c05752a51950cdb8af3c5379f18cfe6b5bc55a4648226a15e912ef19ad77adeea911d67cfefd69ba43fa4119135ff642117ba985a7e0100325e9519f1ca6a9216bda055b5785015291125e90dcd07a2ca9673ee":0
+pkcs1_rsassa_pss_verify:1031:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"04dc251be72e88e5723485b6383a637e2fefe07660c519a560b8bc18bdedb86eae2364ea53ba9dca6eb3d2e7d6b806af42b3e87f291b4a8881d5bf572cc9a85e19c86acb28f098f9da0383c566d3c0f58cfd8f395dcf602e5cd40e8c7183f714996e2297ef":"c558d7167cbb4508ada042971e71b1377eea4269":"33341ba3576a130a50e2a5cf8679224388d5693f5accc235ac95add68e5eb1eec31666d0ca7a1cda6f70a1aa762c05752a51950cdb8af3c5379f18cfe6b5bc55a4648226a15e912ef19ad77adeea911d67cfefd69ba43fa4119135ff642117ba985a7e0100325e9519f1ca6a9216bda055b5785015291125e90dcd07a2ca9673ee":0
 
 RSASSA-PSS Signature Example 8_6
-pkcs1_rsassa_pss_sign:1031:16:"08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb":16:"0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d":16:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0ea37df9a6fea4a8b610373c24cf390c20fa6e2135c400c8a34f5c183a7e8ea4c9ae090ed31759f42dc77719cca400ecdcc517acfc7ac6902675b2ef30c509665f3321482fc69a9fb570d15e01c845d0d8e50d2a24cbf1cf0e714975a5db7b18d9e9e9cb91b5cb16869060ed18b7b56245503f0caf90352b8de81cb5a1d9c6336092f0cd":"76fd4e64fdc98eb927a0403e35a084e76ba9f92a":"1ed1d848fb1edb44129bd9b354795af97a069a7a00d0151048593e0c72c3517ff9ff2a41d0cb5a0ac860d736a199704f7cb6a53986a88bbd8abcc0076a2ce847880031525d449da2ac78356374c536e343faa7cba42a5aaa6506087791c06a8e989335aed19bfab2d5e67e27fb0c2875af896c21b6e8e7309d04e4f6727e69463e":0
+pkcs1_rsassa_pss_sign:1031:"08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb":"0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d":"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0ea37df9a6fea4a8b610373c24cf390c20fa6e2135c400c8a34f5c183a7e8ea4c9ae090ed31759f42dc77719cca400ecdcc517acfc7ac6902675b2ef30c509665f3321482fc69a9fb570d15e01c845d0d8e50d2a24cbf1cf0e714975a5db7b18d9e9e9cb91b5cb16869060ed18b7b56245503f0caf90352b8de81cb5a1d9c6336092f0cd":"76fd4e64fdc98eb927a0403e35a084e76ba9f92a":"1ed1d848fb1edb44129bd9b354795af97a069a7a00d0151048593e0c72c3517ff9ff2a41d0cb5a0ac860d736a199704f7cb6a53986a88bbd8abcc0076a2ce847880031525d449da2ac78356374c536e343faa7cba42a5aaa6506087791c06a8e989335aed19bfab2d5e67e27fb0c2875af896c21b6e8e7309d04e4f6727e69463e":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 8_6 (verify)
-pkcs1_rsassa_pss_verify:1031:16:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0ea37df9a6fea4a8b610373c24cf390c20fa6e2135c400c8a34f5c183a7e8ea4c9ae090ed31759f42dc77719cca400ecdcc517acfc7ac6902675b2ef30c509665f3321482fc69a9fb570d15e01c845d0d8e50d2a24cbf1cf0e714975a5db7b18d9e9e9cb91b5cb16869060ed18b7b56245503f0caf90352b8de81cb5a1d9c6336092f0cd":"76fd4e64fdc98eb927a0403e35a084e76ba9f92a":"1ed1d848fb1edb44129bd9b354795af97a069a7a00d0151048593e0c72c3517ff9ff2a41d0cb5a0ac860d736a199704f7cb6a53986a88bbd8abcc0076a2ce847880031525d449da2ac78356374c536e343faa7cba42a5aaa6506087791c06a8e989335aed19bfab2d5e67e27fb0c2875af896c21b6e8e7309d04e4f6727e69463e":0
+pkcs1_rsassa_pss_verify:1031:"495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0ea37df9a6fea4a8b610373c24cf390c20fa6e2135c400c8a34f5c183a7e8ea4c9ae090ed31759f42dc77719cca400ecdcc517acfc7ac6902675b2ef30c509665f3321482fc69a9fb570d15e01c845d0d8e50d2a24cbf1cf0e714975a5db7b18d9e9e9cb91b5cb16869060ed18b7b56245503f0caf90352b8de81cb5a1d9c6336092f0cd":"76fd4e64fdc98eb927a0403e35a084e76ba9f92a":"1ed1d848fb1edb44129bd9b354795af97a069a7a00d0151048593e0c72c3517ff9ff2a41d0cb5a0ac860d736a199704f7cb6a53986a88bbd8abcc0076a2ce847880031525d449da2ac78356374c536e343faa7cba42a5aaa6506087791c06a8e989335aed19bfab2d5e67e27fb0c2875af896c21b6e8e7309d04e4f6727e69463e":0
 
 RSASSA-PSS Signature Example 9_1
-pkcs1_rsassa_pss_sign:1536:16:"f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367":16:"ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d":16:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"a88e265855e9d7ca36c68795f0b31b591cd6587c71d060a0b3f7f3eaef43795922028bc2b6ad467cfc2d7f659c5385aa70ba3672cdde4cfe4970cc7904601b278872bf51321c4a972f3c95570f3445d4f57980e0f20df54846e6a52c668f1288c03f95006ea32f562d40d52af9feb32f0fa06db65b588a237b34e592d55cf979f903a642ef64d2ed542aa8c77dc1dd762f45a59303ed75e541ca271e2b60ca709e44fa0661131e8d5d4163fd8d398566ce26de8730e72f9cca737641c244159420637028df0a18079d6208ea8b4711a2c750f5":"c0a425313df8d7564bd2434d311523d5257eed80":"586107226c3ce013a7c8f04d1a6a2959bb4b8e205ba43a27b50f124111bc35ef589b039f5932187cb696d7d9a32c0c38300a5cdda4834b62d2eb240af33f79d13dfbf095bf599e0d9686948c1964747b67e89c9aba5cd85016236f566cc5802cb13ead51bc7ca6bef3b94dcbdbb1d570469771df0e00b1a8a06777472d2316279edae86474668d4e1efff95f1de61c6020da32ae92bbf16520fef3cf4d88f61121f24bbd9fe91b59caf1235b2a93ff81fc403addf4ebdea84934a9cdaf8e1a9e":0
+pkcs1_rsassa_pss_sign:1536:"f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367":"ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d":"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"a88e265855e9d7ca36c68795f0b31b591cd6587c71d060a0b3f7f3eaef43795922028bc2b6ad467cfc2d7f659c5385aa70ba3672cdde4cfe4970cc7904601b278872bf51321c4a972f3c95570f3445d4f57980e0f20df54846e6a52c668f1288c03f95006ea32f562d40d52af9feb32f0fa06db65b588a237b34e592d55cf979f903a642ef64d2ed542aa8c77dc1dd762f45a59303ed75e541ca271e2b60ca709e44fa0661131e8d5d4163fd8d398566ce26de8730e72f9cca737641c244159420637028df0a18079d6208ea8b4711a2c750f5":"c0a425313df8d7564bd2434d311523d5257eed80":"586107226c3ce013a7c8f04d1a6a2959bb4b8e205ba43a27b50f124111bc35ef589b039f5932187cb696d7d9a32c0c38300a5cdda4834b62d2eb240af33f79d13dfbf095bf599e0d9686948c1964747b67e89c9aba5cd85016236f566cc5802cb13ead51bc7ca6bef3b94dcbdbb1d570469771df0e00b1a8a06777472d2316279edae86474668d4e1efff95f1de61c6020da32ae92bbf16520fef3cf4d88f61121f24bbd9fe91b59caf1235b2a93ff81fc403addf4ebdea84934a9cdaf8e1a9e":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 9_1 (verify)
-pkcs1_rsassa_pss_verify:1536:16:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"a88e265855e9d7ca36c68795f0b31b591cd6587c71d060a0b3f7f3eaef43795922028bc2b6ad467cfc2d7f659c5385aa70ba3672cdde4cfe4970cc7904601b278872bf51321c4a972f3c95570f3445d4f57980e0f20df54846e6a52c668f1288c03f95006ea32f562d40d52af9feb32f0fa06db65b588a237b34e592d55cf979f903a642ef64d2ed542aa8c77dc1dd762f45a59303ed75e541ca271e2b60ca709e44fa0661131e8d5d4163fd8d398566ce26de8730e72f9cca737641c244159420637028df0a18079d6208ea8b4711a2c750f5":"c0a425313df8d7564bd2434d311523d5257eed80":"586107226c3ce013a7c8f04d1a6a2959bb4b8e205ba43a27b50f124111bc35ef589b039f5932187cb696d7d9a32c0c38300a5cdda4834b62d2eb240af33f79d13dfbf095bf599e0d9686948c1964747b67e89c9aba5cd85016236f566cc5802cb13ead51bc7ca6bef3b94dcbdbb1d570469771df0e00b1a8a06777472d2316279edae86474668d4e1efff95f1de61c6020da32ae92bbf16520fef3cf4d88f61121f24bbd9fe91b59caf1235b2a93ff81fc403addf4ebdea84934a9cdaf8e1a9e":0
+pkcs1_rsassa_pss_verify:1536:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"a88e265855e9d7ca36c68795f0b31b591cd6587c71d060a0b3f7f3eaef43795922028bc2b6ad467cfc2d7f659c5385aa70ba3672cdde4cfe4970cc7904601b278872bf51321c4a972f3c95570f3445d4f57980e0f20df54846e6a52c668f1288c03f95006ea32f562d40d52af9feb32f0fa06db65b588a237b34e592d55cf979f903a642ef64d2ed542aa8c77dc1dd762f45a59303ed75e541ca271e2b60ca709e44fa0661131e8d5d4163fd8d398566ce26de8730e72f9cca737641c244159420637028df0a18079d6208ea8b4711a2c750f5":"c0a425313df8d7564bd2434d311523d5257eed80":"586107226c3ce013a7c8f04d1a6a2959bb4b8e205ba43a27b50f124111bc35ef589b039f5932187cb696d7d9a32c0c38300a5cdda4834b62d2eb240af33f79d13dfbf095bf599e0d9686948c1964747b67e89c9aba5cd85016236f566cc5802cb13ead51bc7ca6bef3b94dcbdbb1d570469771df0e00b1a8a06777472d2316279edae86474668d4e1efff95f1de61c6020da32ae92bbf16520fef3cf4d88f61121f24bbd9fe91b59caf1235b2a93ff81fc403addf4ebdea84934a9cdaf8e1a9e":0
 
 RSASSA-PSS Signature Example 9_2
-pkcs1_rsassa_pss_sign:1536:16:"f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367":16:"ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d":16:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"c8c9c6af04acda414d227ef23e0820c3732c500dc87275e95b0d095413993c2658bc1d988581ba879c2d201f14cb88ced153a01969a7bf0a7be79c84c1486bc12b3fa6c59871b6827c8ce253ca5fefa8a8c690bf326e8e37cdb96d90a82ebab69f86350e1822e8bd536a2e":"b307c43b4850a8dac2f15f32e37839ef8c5c0e91":"80b6d643255209f0a456763897ac9ed259d459b49c2887e5882ecb4434cfd66dd7e1699375381e51cd7f554f2c271704b399d42b4be2540a0eca61951f55267f7c2878c122842dadb28b01bd5f8c025f7e228418a673c03d6bc0c736d0a29546bd67f786d9d692ccea778d71d98c2063b7a71092187a4d35af108111d83e83eae46c46aa34277e06044589903788f1d5e7cee25fb485e92949118814d6f2c3ee361489016f327fb5bc517eb50470bffa1afa5f4ce9aa0ce5b8ee19bf5501b958":0
+pkcs1_rsassa_pss_sign:1536:"f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367":"ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d":"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"c8c9c6af04acda414d227ef23e0820c3732c500dc87275e95b0d095413993c2658bc1d988581ba879c2d201f14cb88ced153a01969a7bf0a7be79c84c1486bc12b3fa6c59871b6827c8ce253ca5fefa8a8c690bf326e8e37cdb96d90a82ebab69f86350e1822e8bd536a2e":"b307c43b4850a8dac2f15f32e37839ef8c5c0e91":"80b6d643255209f0a456763897ac9ed259d459b49c2887e5882ecb4434cfd66dd7e1699375381e51cd7f554f2c271704b399d42b4be2540a0eca61951f55267f7c2878c122842dadb28b01bd5f8c025f7e228418a673c03d6bc0c736d0a29546bd67f786d9d692ccea778d71d98c2063b7a71092187a4d35af108111d83e83eae46c46aa34277e06044589903788f1d5e7cee25fb485e92949118814d6f2c3ee361489016f327fb5bc517eb50470bffa1afa5f4ce9aa0ce5b8ee19bf5501b958":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 9_2 (verify)
-pkcs1_rsassa_pss_verify:1536:16:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"c8c9c6af04acda414d227ef23e0820c3732c500dc87275e95b0d095413993c2658bc1d988581ba879c2d201f14cb88ced153a01969a7bf0a7be79c84c1486bc12b3fa6c59871b6827c8ce253ca5fefa8a8c690bf326e8e37cdb96d90a82ebab69f86350e1822e8bd536a2e":"b307c43b4850a8dac2f15f32e37839ef8c5c0e91":"80b6d643255209f0a456763897ac9ed259d459b49c2887e5882ecb4434cfd66dd7e1699375381e51cd7f554f2c271704b399d42b4be2540a0eca61951f55267f7c2878c122842dadb28b01bd5f8c025f7e228418a673c03d6bc0c736d0a29546bd67f786d9d692ccea778d71d98c2063b7a71092187a4d35af108111d83e83eae46c46aa34277e06044589903788f1d5e7cee25fb485e92949118814d6f2c3ee361489016f327fb5bc517eb50470bffa1afa5f4ce9aa0ce5b8ee19bf5501b958":0
+pkcs1_rsassa_pss_verify:1536:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"c8c9c6af04acda414d227ef23e0820c3732c500dc87275e95b0d095413993c2658bc1d988581ba879c2d201f14cb88ced153a01969a7bf0a7be79c84c1486bc12b3fa6c59871b6827c8ce253ca5fefa8a8c690bf326e8e37cdb96d90a82ebab69f86350e1822e8bd536a2e":"b307c43b4850a8dac2f15f32e37839ef8c5c0e91":"80b6d643255209f0a456763897ac9ed259d459b49c2887e5882ecb4434cfd66dd7e1699375381e51cd7f554f2c271704b399d42b4be2540a0eca61951f55267f7c2878c122842dadb28b01bd5f8c025f7e228418a673c03d6bc0c736d0a29546bd67f786d9d692ccea778d71d98c2063b7a71092187a4d35af108111d83e83eae46c46aa34277e06044589903788f1d5e7cee25fb485e92949118814d6f2c3ee361489016f327fb5bc517eb50470bffa1afa5f4ce9aa0ce5b8ee19bf5501b958":0
 
 RSASSA-PSS Signature Example 9_3
-pkcs1_rsassa_pss_sign:1536:16:"f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367":16:"ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d":16:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0afad42ccd4fc60654a55002d228f52a4a5fe03b8bbb08ca82daca558b44dbe1266e50c0e745a36d9d2904e3408abcd1fd569994063f4a75cc72f2fee2a0cd893a43af1c5b8b487df0a71610024e4f6ddf9f28ad0813c1aab91bcb3c9064d5ff742deffea657094139369e5ea6f4a96319a5cc8224145b545062758fefd1fe3409ae169259c6cdfd6b5f2958e314faecbe69d2cace58ee55179ab9b3e6d1ecc14a557c5febe988595264fc5da1c571462eca798a18a1a4940cdab4a3e92009ccd42e1e947b1314e32238a2dece7d23a89b5b30c751fd0a4a430d2c548594":"9a2b007e80978bbb192c354eb7da9aedfc74dbf5":"484408f3898cd5f53483f80819efbf2708c34d27a8b2a6fae8b322f9240237f981817aca1846f1084daa6d7c0795f6e5bf1af59c38e1858437ce1f7ec419b98c8736adf6dd9a00b1806d2bd3ad0a73775e05f52dfef3a59ab4b08143f0df05cd1ad9d04bececa6daa4a2129803e200cbc77787caf4c1d0663a6c5987b605952019782caf2ec1426d68fb94ed1d4be816a7ed081b77e6ab330b3ffc073820fecde3727fcbe295ee61a050a343658637c3fd659cfb63736de32d9f90d3c2f63eca":0
+pkcs1_rsassa_pss_sign:1536:"f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367":"ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d":"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0afad42ccd4fc60654a55002d228f52a4a5fe03b8bbb08ca82daca558b44dbe1266e50c0e745a36d9d2904e3408abcd1fd569994063f4a75cc72f2fee2a0cd893a43af1c5b8b487df0a71610024e4f6ddf9f28ad0813c1aab91bcb3c9064d5ff742deffea657094139369e5ea6f4a96319a5cc8224145b545062758fefd1fe3409ae169259c6cdfd6b5f2958e314faecbe69d2cace58ee55179ab9b3e6d1ecc14a557c5febe988595264fc5da1c571462eca798a18a1a4940cdab4a3e92009ccd42e1e947b1314e32238a2dece7d23a89b5b30c751fd0a4a430d2c548594":"9a2b007e80978bbb192c354eb7da9aedfc74dbf5":"484408f3898cd5f53483f80819efbf2708c34d27a8b2a6fae8b322f9240237f981817aca1846f1084daa6d7c0795f6e5bf1af59c38e1858437ce1f7ec419b98c8736adf6dd9a00b1806d2bd3ad0a73775e05f52dfef3a59ab4b08143f0df05cd1ad9d04bececa6daa4a2129803e200cbc77787caf4c1d0663a6c5987b605952019782caf2ec1426d68fb94ed1d4be816a7ed081b77e6ab330b3ffc073820fecde3727fcbe295ee61a050a343658637c3fd659cfb63736de32d9f90d3c2f63eca":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 9_3 (verify)
-pkcs1_rsassa_pss_verify:1536:16:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0afad42ccd4fc60654a55002d228f52a4a5fe03b8bbb08ca82daca558b44dbe1266e50c0e745a36d9d2904e3408abcd1fd569994063f4a75cc72f2fee2a0cd893a43af1c5b8b487df0a71610024e4f6ddf9f28ad0813c1aab91bcb3c9064d5ff742deffea657094139369e5ea6f4a96319a5cc8224145b545062758fefd1fe3409ae169259c6cdfd6b5f2958e314faecbe69d2cace58ee55179ab9b3e6d1ecc14a557c5febe988595264fc5da1c571462eca798a18a1a4940cdab4a3e92009ccd42e1e947b1314e32238a2dece7d23a89b5b30c751fd0a4a430d2c548594":"9a2b007e80978bbb192c354eb7da9aedfc74dbf5":"484408f3898cd5f53483f80819efbf2708c34d27a8b2a6fae8b322f9240237f981817aca1846f1084daa6d7c0795f6e5bf1af59c38e1858437ce1f7ec419b98c8736adf6dd9a00b1806d2bd3ad0a73775e05f52dfef3a59ab4b08143f0df05cd1ad9d04bececa6daa4a2129803e200cbc77787caf4c1d0663a6c5987b605952019782caf2ec1426d68fb94ed1d4be816a7ed081b77e6ab330b3ffc073820fecde3727fcbe295ee61a050a343658637c3fd659cfb63736de32d9f90d3c2f63eca":0
+pkcs1_rsassa_pss_verify:1536:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0afad42ccd4fc60654a55002d228f52a4a5fe03b8bbb08ca82daca558b44dbe1266e50c0e745a36d9d2904e3408abcd1fd569994063f4a75cc72f2fee2a0cd893a43af1c5b8b487df0a71610024e4f6ddf9f28ad0813c1aab91bcb3c9064d5ff742deffea657094139369e5ea6f4a96319a5cc8224145b545062758fefd1fe3409ae169259c6cdfd6b5f2958e314faecbe69d2cace58ee55179ab9b3e6d1ecc14a557c5febe988595264fc5da1c571462eca798a18a1a4940cdab4a3e92009ccd42e1e947b1314e32238a2dece7d23a89b5b30c751fd0a4a430d2c548594":"9a2b007e80978bbb192c354eb7da9aedfc74dbf5":"484408f3898cd5f53483f80819efbf2708c34d27a8b2a6fae8b322f9240237f981817aca1846f1084daa6d7c0795f6e5bf1af59c38e1858437ce1f7ec419b98c8736adf6dd9a00b1806d2bd3ad0a73775e05f52dfef3a59ab4b08143f0df05cd1ad9d04bececa6daa4a2129803e200cbc77787caf4c1d0663a6c5987b605952019782caf2ec1426d68fb94ed1d4be816a7ed081b77e6ab330b3ffc073820fecde3727fcbe295ee61a050a343658637c3fd659cfb63736de32d9f90d3c2f63eca":0
 
 RSASSA-PSS Signature Example 9_4
-pkcs1_rsassa_pss_sign:1536:16:"f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367":16:"ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d":16:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"1dfd43b46c93db82629bdae2bd0a12b882ea04c3b465f5cf93023f01059626dbbe99f26bb1be949dddd16dc7f3debb19a194627f0b224434df7d8700e9e98b06e360c12fdbe3d19f51c9684eb9089ecbb0a2f0450399d3f59eac7294085d044f5393c6ce737423d8b86c415370d389e30b9f0a3c02d25d0082e8ad6f3f1ef24a45c3cf82b383367063a4d4613e4264f01b2dac2e5aa42043f8fb5f69fa871d14fb273e767a531c40f02f343bc2fb45a0c7e0f6be2561923a77211d66a6e2dbb43c366350beae22da3ac2c1f5077096fcb5c4bf255f7574351ae0b1e1f03632817c0856d4a8ba97afbdc8b85855402bc56926fcec209f9ea8":"70f382bddf4d5d2dd88b3bc7b7308be632b84045":"84ebeb481be59845b46468bafb471c0112e02b235d84b5d911cbd1926ee5074ae0424495cb20e82308b8ebb65f419a03fb40e72b78981d88aad143053685172c97b29c8b7bf0ae73b5b2263c403da0ed2f80ff7450af7828eb8b86f0028bd2a8b176a4d228cccea18394f238b09ff758cc00bc04301152355742f282b54e663a919e709d8da24ade5500a7b9aa50226e0ca52923e6c2d860ec50ff480fa57477e82b0565f4379f79c772d5c2da80af9fbf325ece6fc20b00961614bee89a183e":0
+pkcs1_rsassa_pss_sign:1536:"f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367":"ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d":"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"1dfd43b46c93db82629bdae2bd0a12b882ea04c3b465f5cf93023f01059626dbbe99f26bb1be949dddd16dc7f3debb19a194627f0b224434df7d8700e9e98b06e360c12fdbe3d19f51c9684eb9089ecbb0a2f0450399d3f59eac7294085d044f5393c6ce737423d8b86c415370d389e30b9f0a3c02d25d0082e8ad6f3f1ef24a45c3cf82b383367063a4d4613e4264f01b2dac2e5aa42043f8fb5f69fa871d14fb273e767a531c40f02f343bc2fb45a0c7e0f6be2561923a77211d66a6e2dbb43c366350beae22da3ac2c1f5077096fcb5c4bf255f7574351ae0b1e1f03632817c0856d4a8ba97afbdc8b85855402bc56926fcec209f9ea8":"70f382bddf4d5d2dd88b3bc7b7308be632b84045":"84ebeb481be59845b46468bafb471c0112e02b235d84b5d911cbd1926ee5074ae0424495cb20e82308b8ebb65f419a03fb40e72b78981d88aad143053685172c97b29c8b7bf0ae73b5b2263c403da0ed2f80ff7450af7828eb8b86f0028bd2a8b176a4d228cccea18394f238b09ff758cc00bc04301152355742f282b54e663a919e709d8da24ade5500a7b9aa50226e0ca52923e6c2d860ec50ff480fa57477e82b0565f4379f79c772d5c2da80af9fbf325ece6fc20b00961614bee89a183e":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 9_4 (verify)
-pkcs1_rsassa_pss_verify:1536:16:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"1dfd43b46c93db82629bdae2bd0a12b882ea04c3b465f5cf93023f01059626dbbe99f26bb1be949dddd16dc7f3debb19a194627f0b224434df7d8700e9e98b06e360c12fdbe3d19f51c9684eb9089ecbb0a2f0450399d3f59eac7294085d044f5393c6ce737423d8b86c415370d389e30b9f0a3c02d25d0082e8ad6f3f1ef24a45c3cf82b383367063a4d4613e4264f01b2dac2e5aa42043f8fb5f69fa871d14fb273e767a531c40f02f343bc2fb45a0c7e0f6be2561923a77211d66a6e2dbb43c366350beae22da3ac2c1f5077096fcb5c4bf255f7574351ae0b1e1f03632817c0856d4a8ba97afbdc8b85855402bc56926fcec209f9ea8":"70f382bddf4d5d2dd88b3bc7b7308be632b84045":"84ebeb481be59845b46468bafb471c0112e02b235d84b5d911cbd1926ee5074ae0424495cb20e82308b8ebb65f419a03fb40e72b78981d88aad143053685172c97b29c8b7bf0ae73b5b2263c403da0ed2f80ff7450af7828eb8b86f0028bd2a8b176a4d228cccea18394f238b09ff758cc00bc04301152355742f282b54e663a919e709d8da24ade5500a7b9aa50226e0ca52923e6c2d860ec50ff480fa57477e82b0565f4379f79c772d5c2da80af9fbf325ece6fc20b00961614bee89a183e":0
+pkcs1_rsassa_pss_verify:1536:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"1dfd43b46c93db82629bdae2bd0a12b882ea04c3b465f5cf93023f01059626dbbe99f26bb1be949dddd16dc7f3debb19a194627f0b224434df7d8700e9e98b06e360c12fdbe3d19f51c9684eb9089ecbb0a2f0450399d3f59eac7294085d044f5393c6ce737423d8b86c415370d389e30b9f0a3c02d25d0082e8ad6f3f1ef24a45c3cf82b383367063a4d4613e4264f01b2dac2e5aa42043f8fb5f69fa871d14fb273e767a531c40f02f343bc2fb45a0c7e0f6be2561923a77211d66a6e2dbb43c366350beae22da3ac2c1f5077096fcb5c4bf255f7574351ae0b1e1f03632817c0856d4a8ba97afbdc8b85855402bc56926fcec209f9ea8":"70f382bddf4d5d2dd88b3bc7b7308be632b84045":"84ebeb481be59845b46468bafb471c0112e02b235d84b5d911cbd1926ee5074ae0424495cb20e82308b8ebb65f419a03fb40e72b78981d88aad143053685172c97b29c8b7bf0ae73b5b2263c403da0ed2f80ff7450af7828eb8b86f0028bd2a8b176a4d228cccea18394f238b09ff758cc00bc04301152355742f282b54e663a919e709d8da24ade5500a7b9aa50226e0ca52923e6c2d860ec50ff480fa57477e82b0565f4379f79c772d5c2da80af9fbf325ece6fc20b00961614bee89a183e":0
 
 RSASSA-PSS Signature Example 9_5
-pkcs1_rsassa_pss_sign:1536:16:"f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367":16:"ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d":16:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"1bdc6e7c98fb8cf54e9b097b66a831e9cfe52d9d4888448ee4b0978093ba1d7d73ae78b3a62ba4ad95cd289ccb9e005226bb3d178bccaa821fb044a4e21ee97696c14d0678c94c2dae93b0ad73922218553daa7e44ebe57725a7a45cc72b9b2138a6b17c8db411ce8279ee1241aff0a8bec6f77f87edb0c69cb27236e3435a800b192e4f11e519e3fe30fc30eaccca4fbb41769029bf708e817a9e683805be67fa100984683b74838e3bcffa79366eed1d481c76729118838f31ba8a048a93c1be4424598e8df6328b7a77880a3f9c7e2e8dfca8eb5a26fb86bdc556d42bbe01d9fa6ed80646491c9341":"d689257a86effa68212c5e0c619eca295fb91b67":"82102df8cb91e7179919a04d26d335d64fbc2f872c44833943241de8454810274cdf3db5f42d423db152af7135f701420e39b494a67cbfd19f9119da233a23da5c6439b5ba0d2bc373eee3507001378d4a4073856b7fe2aba0b5ee93b27f4afec7d4d120921c83f606765b02c19e4d6a1a3b95fa4c422951be4f52131077ef17179729cddfbdb56950dbaceefe78cb16640a099ea56d24389eef10f8fecb31ba3ea3b227c0a86698bb89e3e9363905bf22777b2a3aa521b65b4cef76d83bde4c":0
+pkcs1_rsassa_pss_sign:1536:"f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367":"ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d":"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"1bdc6e7c98fb8cf54e9b097b66a831e9cfe52d9d4888448ee4b0978093ba1d7d73ae78b3a62ba4ad95cd289ccb9e005226bb3d178bccaa821fb044a4e21ee97696c14d0678c94c2dae93b0ad73922218553daa7e44ebe57725a7a45cc72b9b2138a6b17c8db411ce8279ee1241aff0a8bec6f77f87edb0c69cb27236e3435a800b192e4f11e519e3fe30fc30eaccca4fbb41769029bf708e817a9e683805be67fa100984683b74838e3bcffa79366eed1d481c76729118838f31ba8a048a93c1be4424598e8df6328b7a77880a3f9c7e2e8dfca8eb5a26fb86bdc556d42bbe01d9fa6ed80646491c9341":"d689257a86effa68212c5e0c619eca295fb91b67":"82102df8cb91e7179919a04d26d335d64fbc2f872c44833943241de8454810274cdf3db5f42d423db152af7135f701420e39b494a67cbfd19f9119da233a23da5c6439b5ba0d2bc373eee3507001378d4a4073856b7fe2aba0b5ee93b27f4afec7d4d120921c83f606765b02c19e4d6a1a3b95fa4c422951be4f52131077ef17179729cddfbdb56950dbaceefe78cb16640a099ea56d24389eef10f8fecb31ba3ea3b227c0a86698bb89e3e9363905bf22777b2a3aa521b65b4cef76d83bde4c":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 9_5 (verify)
-pkcs1_rsassa_pss_verify:1536:16:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"1bdc6e7c98fb8cf54e9b097b66a831e9cfe52d9d4888448ee4b0978093ba1d7d73ae78b3a62ba4ad95cd289ccb9e005226bb3d178bccaa821fb044a4e21ee97696c14d0678c94c2dae93b0ad73922218553daa7e44ebe57725a7a45cc72b9b2138a6b17c8db411ce8279ee1241aff0a8bec6f77f87edb0c69cb27236e3435a800b192e4f11e519e3fe30fc30eaccca4fbb41769029bf708e817a9e683805be67fa100984683b74838e3bcffa79366eed1d481c76729118838f31ba8a048a93c1be4424598e8df6328b7a77880a3f9c7e2e8dfca8eb5a26fb86bdc556d42bbe01d9fa6ed80646491c9341":"d689257a86effa68212c5e0c619eca295fb91b67":"82102df8cb91e7179919a04d26d335d64fbc2f872c44833943241de8454810274cdf3db5f42d423db152af7135f701420e39b494a67cbfd19f9119da233a23da5c6439b5ba0d2bc373eee3507001378d4a4073856b7fe2aba0b5ee93b27f4afec7d4d120921c83f606765b02c19e4d6a1a3b95fa4c422951be4f52131077ef17179729cddfbdb56950dbaceefe78cb16640a099ea56d24389eef10f8fecb31ba3ea3b227c0a86698bb89e3e9363905bf22777b2a3aa521b65b4cef76d83bde4c":0
+pkcs1_rsassa_pss_verify:1536:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"1bdc6e7c98fb8cf54e9b097b66a831e9cfe52d9d4888448ee4b0978093ba1d7d73ae78b3a62ba4ad95cd289ccb9e005226bb3d178bccaa821fb044a4e21ee97696c14d0678c94c2dae93b0ad73922218553daa7e44ebe57725a7a45cc72b9b2138a6b17c8db411ce8279ee1241aff0a8bec6f77f87edb0c69cb27236e3435a800b192e4f11e519e3fe30fc30eaccca4fbb41769029bf708e817a9e683805be67fa100984683b74838e3bcffa79366eed1d481c76729118838f31ba8a048a93c1be4424598e8df6328b7a77880a3f9c7e2e8dfca8eb5a26fb86bdc556d42bbe01d9fa6ed80646491c9341":"d689257a86effa68212c5e0c619eca295fb91b67":"82102df8cb91e7179919a04d26d335d64fbc2f872c44833943241de8454810274cdf3db5f42d423db152af7135f701420e39b494a67cbfd19f9119da233a23da5c6439b5ba0d2bc373eee3507001378d4a4073856b7fe2aba0b5ee93b27f4afec7d4d120921c83f606765b02c19e4d6a1a3b95fa4c422951be4f52131077ef17179729cddfbdb56950dbaceefe78cb16640a099ea56d24389eef10f8fecb31ba3ea3b227c0a86698bb89e3e9363905bf22777b2a3aa521b65b4cef76d83bde4c":0
 
 RSASSA-PSS Signature Example 9_6
-pkcs1_rsassa_pss_sign:1536:16:"f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367":16:"ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d":16:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"88c7a9f1360401d90e53b101b61c5325c3c75db1b411fbeb8e830b75e96b56670ad245404e16793544ee354bc613a90cc9848715a73db5893e7f6d279815c0c1de83ef8e2956e3a56ed26a888d7a9cdcd042f4b16b7fa51ef1a0573662d16a302d0ec5b285d2e03ad96529c87b3d374db372d95b2443d061b6b1a350ba87807ed083afd1eb05c3f52f4eba5ed2227714fdb50b9d9d9dd6814f62f6272fcd5cdbce7a9ef797":"c25f13bf67d081671a0481a1f1820d613bba2276":"a7fdb0d259165ca2c88d00bbf1028a867d337699d061193b17a9648e14ccbbaadeacaacdec815e7571294ebb8a117af205fa078b47b0712c199e3ad05135c504c24b81705115740802487992ffd511d4afc6b854491eb3f0dd523139542ff15c3101ee85543517c6a3c79417c67e2dd9aa741e9a29b06dcb593c2336b3670ae3afbac7c3e76e215473e866e338ca244de00b62624d6b9426822ceae9f8cc460895f41250073fd45c5a1e7b425c204a423a699159f6903e710b37a7bb2bc8049f":0
+pkcs1_rsassa_pss_sign:1536:"f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367":"ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d":"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"88c7a9f1360401d90e53b101b61c5325c3c75db1b411fbeb8e830b75e96b56670ad245404e16793544ee354bc613a90cc9848715a73db5893e7f6d279815c0c1de83ef8e2956e3a56ed26a888d7a9cdcd042f4b16b7fa51ef1a0573662d16a302d0ec5b285d2e03ad96529c87b3d374db372d95b2443d061b6b1a350ba87807ed083afd1eb05c3f52f4eba5ed2227714fdb50b9d9d9dd6814f62f6272fcd5cdbce7a9ef797":"c25f13bf67d081671a0481a1f1820d613bba2276":"a7fdb0d259165ca2c88d00bbf1028a867d337699d061193b17a9648e14ccbbaadeacaacdec815e7571294ebb8a117af205fa078b47b0712c199e3ad05135c504c24b81705115740802487992ffd511d4afc6b854491eb3f0dd523139542ff15c3101ee85543517c6a3c79417c67e2dd9aa741e9a29b06dcb593c2336b3670ae3afbac7c3e76e215473e866e338ca244de00b62624d6b9426822ceae9f8cc460895f41250073fd45c5a1e7b425c204a423a699159f6903e710b37a7bb2bc8049f":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 9_6 (verify)
-pkcs1_rsassa_pss_verify:1536:16:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"88c7a9f1360401d90e53b101b61c5325c3c75db1b411fbeb8e830b75e96b56670ad245404e16793544ee354bc613a90cc9848715a73db5893e7f6d279815c0c1de83ef8e2956e3a56ed26a888d7a9cdcd042f4b16b7fa51ef1a0573662d16a302d0ec5b285d2e03ad96529c87b3d374db372d95b2443d061b6b1a350ba87807ed083afd1eb05c3f52f4eba5ed2227714fdb50b9d9d9dd6814f62f6272fcd5cdbce7a9ef797":"c25f13bf67d081671a0481a1f1820d613bba2276":"a7fdb0d259165ca2c88d00bbf1028a867d337699d061193b17a9648e14ccbbaadeacaacdec815e7571294ebb8a117af205fa078b47b0712c199e3ad05135c504c24b81705115740802487992ffd511d4afc6b854491eb3f0dd523139542ff15c3101ee85543517c6a3c79417c67e2dd9aa741e9a29b06dcb593c2336b3670ae3afbac7c3e76e215473e866e338ca244de00b62624d6b9426822ceae9f8cc460895f41250073fd45c5a1e7b425c204a423a699159f6903e710b37a7bb2bc8049f":0
+pkcs1_rsassa_pss_verify:1536:"e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"88c7a9f1360401d90e53b101b61c5325c3c75db1b411fbeb8e830b75e96b56670ad245404e16793544ee354bc613a90cc9848715a73db5893e7f6d279815c0c1de83ef8e2956e3a56ed26a888d7a9cdcd042f4b16b7fa51ef1a0573662d16a302d0ec5b285d2e03ad96529c87b3d374db372d95b2443d061b6b1a350ba87807ed083afd1eb05c3f52f4eba5ed2227714fdb50b9d9d9dd6814f62f6272fcd5cdbce7a9ef797":"c25f13bf67d081671a0481a1f1820d613bba2276":"a7fdb0d259165ca2c88d00bbf1028a867d337699d061193b17a9648e14ccbbaadeacaacdec815e7571294ebb8a117af205fa078b47b0712c199e3ad05135c504c24b81705115740802487992ffd511d4afc6b854491eb3f0dd523139542ff15c3101ee85543517c6a3c79417c67e2dd9aa741e9a29b06dcb593c2336b3670ae3afbac7c3e76e215473e866e338ca244de00b62624d6b9426822ceae9f8cc460895f41250073fd45c5a1e7b425c204a423a699159f6903e710b37a7bb2bc8049f":0
 
 RSASSA-PSS Signature Example 10_1
-pkcs1_rsassa_pss_sign:2048:16:"cfd50283feeeb97f6f08d73cbc7b3836f82bbcd499479f5e6f76fdfcb8b38c4f71dc9e88bd6a6f76371afd65d2af1862b32afb34a95f71b8b132043ffebe3a952baf7592448148c03f9c69b1d68e4ce5cf32c86baf46fed301ca1ab403069b32f456b91f71898ab081cd8c4252ef5271915c9794b8f295851da7510f99cb73eb":16:"cc4e90d2a1b3a065d3b2d1f5a8fce31b544475664eab561d2971b99fb7bef844e8ec1f360b8c2ac8359692971ea6a38f723fcc211f5dbcb177a0fdac5164a1d4ff7fbb4e829986353cb983659a148cdd420c7d31ba3822ea90a32be46c030e8c17e1fa0ad37859e06b0aa6fa3b216d9cbe6c0e22339769c0a615913e5da719cf":16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"883177e5126b9be2d9a9680327d5370c6f26861f5820c43da67a3ad609":"04e215ee6ff934b9da70d7730c8734abfcecde89":"82c2b160093b8aa3c0f7522b19f87354066c77847abf2a9fce542d0e84e920c5afb49ffdfdace16560ee94a1369601148ebad7a0e151cf16331791a5727d05f21e74e7eb811440206935d744765a15e79f015cb66c532c87a6a05961c8bfad741a9a6657022894393e7223739796c02a77455d0f555b0ec01ddf259b6207fd0fd57614cef1a5573baaff4ec00069951659b85f24300a25160ca8522dc6e6727e57d019d7e63629b8fe5e89e25cc15beb3a647577559299280b9b28f79b0409000be25bbd96408ba3b43cc486184dd1c8e62553fa1af4040f60663de7f5e49c04388e257f1ce89c95dab48a315d9b66b1b7628233876ff2385230d070d07e1666":0
+pkcs1_rsassa_pss_sign:2048:"cfd50283feeeb97f6f08d73cbc7b3836f82bbcd499479f5e6f76fdfcb8b38c4f71dc9e88bd6a6f76371afd65d2af1862b32afb34a95f71b8b132043ffebe3a952baf7592448148c03f9c69b1d68e4ce5cf32c86baf46fed301ca1ab403069b32f456b91f71898ab081cd8c4252ef5271915c9794b8f295851da7510f99cb73eb":"cc4e90d2a1b3a065d3b2d1f5a8fce31b544475664eab561d2971b99fb7bef844e8ec1f360b8c2ac8359692971ea6a38f723fcc211f5dbcb177a0fdac5164a1d4ff7fbb4e829986353cb983659a148cdd420c7d31ba3822ea90a32be46c030e8c17e1fa0ad37859e06b0aa6fa3b216d9cbe6c0e22339769c0a615913e5da719cf":"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"883177e5126b9be2d9a9680327d5370c6f26861f5820c43da67a3ad609":"04e215ee6ff934b9da70d7730c8734abfcecde89":"82c2b160093b8aa3c0f7522b19f87354066c77847abf2a9fce542d0e84e920c5afb49ffdfdace16560ee94a1369601148ebad7a0e151cf16331791a5727d05f21e74e7eb811440206935d744765a15e79f015cb66c532c87a6a05961c8bfad741a9a6657022894393e7223739796c02a77455d0f555b0ec01ddf259b6207fd0fd57614cef1a5573baaff4ec00069951659b85f24300a25160ca8522dc6e6727e57d019d7e63629b8fe5e89e25cc15beb3a647577559299280b9b28f79b0409000be25bbd96408ba3b43cc486184dd1c8e62553fa1af4040f60663de7f5e49c04388e257f1ce89c95dab48a315d9b66b1b7628233876ff2385230d070d07e1666":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 10_1 (verify)
-pkcs1_rsassa_pss_verify:2048:16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"883177e5126b9be2d9a9680327d5370c6f26861f5820c43da67a3ad609":"04e215ee6ff934b9da70d7730c8734abfcecde89":"82c2b160093b8aa3c0f7522b19f87354066c77847abf2a9fce542d0e84e920c5afb49ffdfdace16560ee94a1369601148ebad7a0e151cf16331791a5727d05f21e74e7eb811440206935d744765a15e79f015cb66c532c87a6a05961c8bfad741a9a6657022894393e7223739796c02a77455d0f555b0ec01ddf259b6207fd0fd57614cef1a5573baaff4ec00069951659b85f24300a25160ca8522dc6e6727e57d019d7e63629b8fe5e89e25cc15beb3a647577559299280b9b28f79b0409000be25bbd96408ba3b43cc486184dd1c8e62553fa1af4040f60663de7f5e49c04388e257f1ce89c95dab48a315d9b66b1b7628233876ff2385230d070d07e1666":0
+pkcs1_rsassa_pss_verify:2048:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"883177e5126b9be2d9a9680327d5370c6f26861f5820c43da67a3ad609":"04e215ee6ff934b9da70d7730c8734abfcecde89":"82c2b160093b8aa3c0f7522b19f87354066c77847abf2a9fce542d0e84e920c5afb49ffdfdace16560ee94a1369601148ebad7a0e151cf16331791a5727d05f21e74e7eb811440206935d744765a15e79f015cb66c532c87a6a05961c8bfad741a9a6657022894393e7223739796c02a77455d0f555b0ec01ddf259b6207fd0fd57614cef1a5573baaff4ec00069951659b85f24300a25160ca8522dc6e6727e57d019d7e63629b8fe5e89e25cc15beb3a647577559299280b9b28f79b0409000be25bbd96408ba3b43cc486184dd1c8e62553fa1af4040f60663de7f5e49c04388e257f1ce89c95dab48a315d9b66b1b7628233876ff2385230d070d07e1666":0
 
 RSASSA-PSS Signature Example 10_2
-pkcs1_rsassa_pss_sign:2048:16:"cfd50283feeeb97f6f08d73cbc7b3836f82bbcd499479f5e6f76fdfcb8b38c4f71dc9e88bd6a6f76371afd65d2af1862b32afb34a95f71b8b132043ffebe3a952baf7592448148c03f9c69b1d68e4ce5cf32c86baf46fed301ca1ab403069b32f456b91f71898ab081cd8c4252ef5271915c9794b8f295851da7510f99cb73eb":16:"cc4e90d2a1b3a065d3b2d1f5a8fce31b544475664eab561d2971b99fb7bef844e8ec1f360b8c2ac8359692971ea6a38f723fcc211f5dbcb177a0fdac5164a1d4ff7fbb4e829986353cb983659a148cdd420c7d31ba3822ea90a32be46c030e8c17e1fa0ad37859e06b0aa6fa3b216d9cbe6c0e22339769c0a615913e5da719cf":16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"dd670a01465868adc93f26131957a50c52fb777cdbaa30892c9e12361164ec13979d43048118e4445db87bee58dd987b3425d02071d8dbae80708b039dbb64dbd1de5657d9fed0c118a54143742e0ff3c87f74e45857647af3f79eb0a14c9d75ea9a1a04b7cf478a897a708fd988f48e801edb0b7039df8c23bb3c56f4e821ac":"8b2bdd4b40faf545c778ddf9bc1a49cb57f9b71b":"14ae35d9dd06ba92f7f3b897978aed7cd4bf5ff0b585a40bd46ce1b42cd2703053bb9044d64e813d8f96db2dd7007d10118f6f8f8496097ad75e1ff692341b2892ad55a633a1c55e7f0a0ad59a0e203a5b8278aec54dd8622e2831d87174f8caff43ee6c46445345d84a59659bfb92ecd4c818668695f34706f66828a89959637f2bf3e3251c24bdba4d4b7649da0022218b119c84e79a6527ec5b8a5f861c159952e23ec05e1e717346faefe8b1686825bd2b262fb2531066c0de09acde2e4231690728b5d85e115a2f6b92b79c25abc9bd9399ff8bcf825a52ea1f56ea76dd26f43baafa18bfa92a504cbd35699e26d1dcc5a2887385f3c63232f06f3244c3":0
+pkcs1_rsassa_pss_sign:2048:"cfd50283feeeb97f6f08d73cbc7b3836f82bbcd499479f5e6f76fdfcb8b38c4f71dc9e88bd6a6f76371afd65d2af1862b32afb34a95f71b8b132043ffebe3a952baf7592448148c03f9c69b1d68e4ce5cf32c86baf46fed301ca1ab403069b32f456b91f71898ab081cd8c4252ef5271915c9794b8f295851da7510f99cb73eb":"cc4e90d2a1b3a065d3b2d1f5a8fce31b544475664eab561d2971b99fb7bef844e8ec1f360b8c2ac8359692971ea6a38f723fcc211f5dbcb177a0fdac5164a1d4ff7fbb4e829986353cb983659a148cdd420c7d31ba3822ea90a32be46c030e8c17e1fa0ad37859e06b0aa6fa3b216d9cbe6c0e22339769c0a615913e5da719cf":"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"dd670a01465868adc93f26131957a50c52fb777cdbaa30892c9e12361164ec13979d43048118e4445db87bee58dd987b3425d02071d8dbae80708b039dbb64dbd1de5657d9fed0c118a54143742e0ff3c87f74e45857647af3f79eb0a14c9d75ea9a1a04b7cf478a897a708fd988f48e801edb0b7039df8c23bb3c56f4e821ac":"8b2bdd4b40faf545c778ddf9bc1a49cb57f9b71b":"14ae35d9dd06ba92f7f3b897978aed7cd4bf5ff0b585a40bd46ce1b42cd2703053bb9044d64e813d8f96db2dd7007d10118f6f8f8496097ad75e1ff692341b2892ad55a633a1c55e7f0a0ad59a0e203a5b8278aec54dd8622e2831d87174f8caff43ee6c46445345d84a59659bfb92ecd4c818668695f34706f66828a89959637f2bf3e3251c24bdba4d4b7649da0022218b119c84e79a6527ec5b8a5f861c159952e23ec05e1e717346faefe8b1686825bd2b262fb2531066c0de09acde2e4231690728b5d85e115a2f6b92b79c25abc9bd9399ff8bcf825a52ea1f56ea76dd26f43baafa18bfa92a504cbd35699e26d1dcc5a2887385f3c63232f06f3244c3":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 10_2 (verify)
-pkcs1_rsassa_pss_verify:2048:16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"dd670a01465868adc93f26131957a50c52fb777cdbaa30892c9e12361164ec13979d43048118e4445db87bee58dd987b3425d02071d8dbae80708b039dbb64dbd1de5657d9fed0c118a54143742e0ff3c87f74e45857647af3f79eb0a14c9d75ea9a1a04b7cf478a897a708fd988f48e801edb0b7039df8c23bb3c56f4e821ac":"8b2bdd4b40faf545c778ddf9bc1a49cb57f9b71b":"14ae35d9dd06ba92f7f3b897978aed7cd4bf5ff0b585a40bd46ce1b42cd2703053bb9044d64e813d8f96db2dd7007d10118f6f8f8496097ad75e1ff692341b2892ad55a633a1c55e7f0a0ad59a0e203a5b8278aec54dd8622e2831d87174f8caff43ee6c46445345d84a59659bfb92ecd4c818668695f34706f66828a89959637f2bf3e3251c24bdba4d4b7649da0022218b119c84e79a6527ec5b8a5f861c159952e23ec05e1e717346faefe8b1686825bd2b262fb2531066c0de09acde2e4231690728b5d85e115a2f6b92b79c25abc9bd9399ff8bcf825a52ea1f56ea76dd26f43baafa18bfa92a504cbd35699e26d1dcc5a2887385f3c63232f06f3244c3":0
+pkcs1_rsassa_pss_verify:2048:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"dd670a01465868adc93f26131957a50c52fb777cdbaa30892c9e12361164ec13979d43048118e4445db87bee58dd987b3425d02071d8dbae80708b039dbb64dbd1de5657d9fed0c118a54143742e0ff3c87f74e45857647af3f79eb0a14c9d75ea9a1a04b7cf478a897a708fd988f48e801edb0b7039df8c23bb3c56f4e821ac":"8b2bdd4b40faf545c778ddf9bc1a49cb57f9b71b":"14ae35d9dd06ba92f7f3b897978aed7cd4bf5ff0b585a40bd46ce1b42cd2703053bb9044d64e813d8f96db2dd7007d10118f6f8f8496097ad75e1ff692341b2892ad55a633a1c55e7f0a0ad59a0e203a5b8278aec54dd8622e2831d87174f8caff43ee6c46445345d84a59659bfb92ecd4c818668695f34706f66828a89959637f2bf3e3251c24bdba4d4b7649da0022218b119c84e79a6527ec5b8a5f861c159952e23ec05e1e717346faefe8b1686825bd2b262fb2531066c0de09acde2e4231690728b5d85e115a2f6b92b79c25abc9bd9399ff8bcf825a52ea1f56ea76dd26f43baafa18bfa92a504cbd35699e26d1dcc5a2887385f3c63232f06f3244c3":0
 
 RSASSA-PSS Signature Example 10_3
-pkcs1_rsassa_pss_sign:2048:16:"cfd50283feeeb97f6f08d73cbc7b3836f82bbcd499479f5e6f76fdfcb8b38c4f71dc9e88bd6a6f76371afd65d2af1862b32afb34a95f71b8b132043ffebe3a952baf7592448148c03f9c69b1d68e4ce5cf32c86baf46fed301ca1ab403069b32f456b91f71898ab081cd8c4252ef5271915c9794b8f295851da7510f99cb73eb":16:"cc4e90d2a1b3a065d3b2d1f5a8fce31b544475664eab561d2971b99fb7bef844e8ec1f360b8c2ac8359692971ea6a38f723fcc211f5dbcb177a0fdac5164a1d4ff7fbb4e829986353cb983659a148cdd420c7d31ba3822ea90a32be46c030e8c17e1fa0ad37859e06b0aa6fa3b216d9cbe6c0e22339769c0a615913e5da719cf":16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"48b2b6a57a63c84cea859d65c668284b08d96bdcaabe252db0e4a96cb1bac6019341db6fbefb8d106b0e90eda6bcc6c6262f37e7ea9c7e5d226bd7df85ec5e71efff2f54c5db577ff729ff91b842491de2741d0c631607df586b905b23b91af13da12304bf83eca8a73e871ff9db":"4e96fc1b398f92b44671010c0dc3efd6e20c2d73":"6e3e4d7b6b15d2fb46013b8900aa5bbb3939cf2c095717987042026ee62c74c54cffd5d7d57efbbf950a0f5c574fa09d3fc1c9f513b05b4ff50dd8df7edfa20102854c35e592180119a70ce5b085182aa02d9ea2aa90d1df03f2daae885ba2f5d05afdac97476f06b93b5bc94a1a80aa9116c4d615f333b098892b25fface266f5db5a5a3bcc10a824ed55aad35b727834fb8c07da28fcf416a5d9b2224f1f8b442b36f91e456fdea2d7cfe3367268de0307a4c74e924159ed33393d5e0655531c77327b89821bdedf880161c78cd4196b5419f7acc3f13e5ebf161b6e7c6724716ca33b85c2e25640192ac2859651d50bde7eb976e51cec828b98b6563b86bb":0
+pkcs1_rsassa_pss_sign:2048:"cfd50283feeeb97f6f08d73cbc7b3836f82bbcd499479f5e6f76fdfcb8b38c4f71dc9e88bd6a6f76371afd65d2af1862b32afb34a95f71b8b132043ffebe3a952baf7592448148c03f9c69b1d68e4ce5cf32c86baf46fed301ca1ab403069b32f456b91f71898ab081cd8c4252ef5271915c9794b8f295851da7510f99cb73eb":"cc4e90d2a1b3a065d3b2d1f5a8fce31b544475664eab561d2971b99fb7bef844e8ec1f360b8c2ac8359692971ea6a38f723fcc211f5dbcb177a0fdac5164a1d4ff7fbb4e829986353cb983659a148cdd420c7d31ba3822ea90a32be46c030e8c17e1fa0ad37859e06b0aa6fa3b216d9cbe6c0e22339769c0a615913e5da719cf":"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"48b2b6a57a63c84cea859d65c668284b08d96bdcaabe252db0e4a96cb1bac6019341db6fbefb8d106b0e90eda6bcc6c6262f37e7ea9c7e5d226bd7df85ec5e71efff2f54c5db577ff729ff91b842491de2741d0c631607df586b905b23b91af13da12304bf83eca8a73e871ff9db":"4e96fc1b398f92b44671010c0dc3efd6e20c2d73":"6e3e4d7b6b15d2fb46013b8900aa5bbb3939cf2c095717987042026ee62c74c54cffd5d7d57efbbf950a0f5c574fa09d3fc1c9f513b05b4ff50dd8df7edfa20102854c35e592180119a70ce5b085182aa02d9ea2aa90d1df03f2daae885ba2f5d05afdac97476f06b93b5bc94a1a80aa9116c4d615f333b098892b25fface266f5db5a5a3bcc10a824ed55aad35b727834fb8c07da28fcf416a5d9b2224f1f8b442b36f91e456fdea2d7cfe3367268de0307a4c74e924159ed33393d5e0655531c77327b89821bdedf880161c78cd4196b5419f7acc3f13e5ebf161b6e7c6724716ca33b85c2e25640192ac2859651d50bde7eb976e51cec828b98b6563b86bb":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 10_3 (verify)
-pkcs1_rsassa_pss_verify:2048:16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"48b2b6a57a63c84cea859d65c668284b08d96bdcaabe252db0e4a96cb1bac6019341db6fbefb8d106b0e90eda6bcc6c6262f37e7ea9c7e5d226bd7df85ec5e71efff2f54c5db577ff729ff91b842491de2741d0c631607df586b905b23b91af13da12304bf83eca8a73e871ff9db":"4e96fc1b398f92b44671010c0dc3efd6e20c2d73":"6e3e4d7b6b15d2fb46013b8900aa5bbb3939cf2c095717987042026ee62c74c54cffd5d7d57efbbf950a0f5c574fa09d3fc1c9f513b05b4ff50dd8df7edfa20102854c35e592180119a70ce5b085182aa02d9ea2aa90d1df03f2daae885ba2f5d05afdac97476f06b93b5bc94a1a80aa9116c4d615f333b098892b25fface266f5db5a5a3bcc10a824ed55aad35b727834fb8c07da28fcf416a5d9b2224f1f8b442b36f91e456fdea2d7cfe3367268de0307a4c74e924159ed33393d5e0655531c77327b89821bdedf880161c78cd4196b5419f7acc3f13e5ebf161b6e7c6724716ca33b85c2e25640192ac2859651d50bde7eb976e51cec828b98b6563b86bb":0
+pkcs1_rsassa_pss_verify:2048:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"48b2b6a57a63c84cea859d65c668284b08d96bdcaabe252db0e4a96cb1bac6019341db6fbefb8d106b0e90eda6bcc6c6262f37e7ea9c7e5d226bd7df85ec5e71efff2f54c5db577ff729ff91b842491de2741d0c631607df586b905b23b91af13da12304bf83eca8a73e871ff9db":"4e96fc1b398f92b44671010c0dc3efd6e20c2d73":"6e3e4d7b6b15d2fb46013b8900aa5bbb3939cf2c095717987042026ee62c74c54cffd5d7d57efbbf950a0f5c574fa09d3fc1c9f513b05b4ff50dd8df7edfa20102854c35e592180119a70ce5b085182aa02d9ea2aa90d1df03f2daae885ba2f5d05afdac97476f06b93b5bc94a1a80aa9116c4d615f333b098892b25fface266f5db5a5a3bcc10a824ed55aad35b727834fb8c07da28fcf416a5d9b2224f1f8b442b36f91e456fdea2d7cfe3367268de0307a4c74e924159ed33393d5e0655531c77327b89821bdedf880161c78cd4196b5419f7acc3f13e5ebf161b6e7c6724716ca33b85c2e25640192ac2859651d50bde7eb976e51cec828b98b6563b86bb":0
 
 RSASSA-PSS Signature Example 10_4
-pkcs1_rsassa_pss_sign:2048:16:"cfd50283feeeb97f6f08d73cbc7b3836f82bbcd499479f5e6f76fdfcb8b38c4f71dc9e88bd6a6f76371afd65d2af1862b32afb34a95f71b8b132043ffebe3a952baf7592448148c03f9c69b1d68e4ce5cf32c86baf46fed301ca1ab403069b32f456b91f71898ab081cd8c4252ef5271915c9794b8f295851da7510f99cb73eb":16:"cc4e90d2a1b3a065d3b2d1f5a8fce31b544475664eab561d2971b99fb7bef844e8ec1f360b8c2ac8359692971ea6a38f723fcc211f5dbcb177a0fdac5164a1d4ff7fbb4e829986353cb983659a148cdd420c7d31ba3822ea90a32be46c030e8c17e1fa0ad37859e06b0aa6fa3b216d9cbe6c0e22339769c0a615913e5da719cf":16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0b8777c7f839baf0a64bbbdbc5ce79755c57a205b845c174e2d2e90546a089c4e6ec8adffa23a7ea97bae6b65d782b82db5d2b5a56d22a29a05e7c4433e2b82a621abba90add05ce393fc48a840542451a":"c7cd698d84b65128d8835e3a8b1eb0e01cb541ec":"34047ff96c4dc0dc90b2d4ff59a1a361a4754b255d2ee0af7d8bf87c9bc9e7ddeede33934c63ca1c0e3d262cb145ef932a1f2c0a997aa6a34f8eaee7477d82ccf09095a6b8acad38d4eec9fb7eab7ad02da1d11d8e54c1825e55bf58c2a23234b902be124f9e9038a8f68fa45dab72f66e0945bf1d8bacc9044c6f07098c9fcec58a3aab100c805178155f030a124c450e5acbda47d0e4f10b80a23f803e774d023b0015c20b9f9bbe7c91296338d5ecb471cafb032007b67a60be5f69504a9f01abb3cb467b260e2bce860be8d95bf92c0c8e1496ed1e528593a4abb6df462dde8a0968dffe4683116857a232f5ebf6c85be238745ad0f38f767a5fdbf486fb":0
+pkcs1_rsassa_pss_sign:2048:"cfd50283feeeb97f6f08d73cbc7b3836f82bbcd499479f5e6f76fdfcb8b38c4f71dc9e88bd6a6f76371afd65d2af1862b32afb34a95f71b8b132043ffebe3a952baf7592448148c03f9c69b1d68e4ce5cf32c86baf46fed301ca1ab403069b32f456b91f71898ab081cd8c4252ef5271915c9794b8f295851da7510f99cb73eb":"cc4e90d2a1b3a065d3b2d1f5a8fce31b544475664eab561d2971b99fb7bef844e8ec1f360b8c2ac8359692971ea6a38f723fcc211f5dbcb177a0fdac5164a1d4ff7fbb4e829986353cb983659a148cdd420c7d31ba3822ea90a32be46c030e8c17e1fa0ad37859e06b0aa6fa3b216d9cbe6c0e22339769c0a615913e5da719cf":"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0b8777c7f839baf0a64bbbdbc5ce79755c57a205b845c174e2d2e90546a089c4e6ec8adffa23a7ea97bae6b65d782b82db5d2b5a56d22a29a05e7c4433e2b82a621abba90add05ce393fc48a840542451a":"c7cd698d84b65128d8835e3a8b1eb0e01cb541ec":"34047ff96c4dc0dc90b2d4ff59a1a361a4754b255d2ee0af7d8bf87c9bc9e7ddeede33934c63ca1c0e3d262cb145ef932a1f2c0a997aa6a34f8eaee7477d82ccf09095a6b8acad38d4eec9fb7eab7ad02da1d11d8e54c1825e55bf58c2a23234b902be124f9e9038a8f68fa45dab72f66e0945bf1d8bacc9044c6f07098c9fcec58a3aab100c805178155f030a124c450e5acbda47d0e4f10b80a23f803e774d023b0015c20b9f9bbe7c91296338d5ecb471cafb032007b67a60be5f69504a9f01abb3cb467b260e2bce860be8d95bf92c0c8e1496ed1e528593a4abb6df462dde8a0968dffe4683116857a232f5ebf6c85be238745ad0f38f767a5fdbf486fb":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 10_4 (verify)
-pkcs1_rsassa_pss_verify:2048:16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0b8777c7f839baf0a64bbbdbc5ce79755c57a205b845c174e2d2e90546a089c4e6ec8adffa23a7ea97bae6b65d782b82db5d2b5a56d22a29a05e7c4433e2b82a621abba90add05ce393fc48a840542451a":"c7cd698d84b65128d8835e3a8b1eb0e01cb541ec":"34047ff96c4dc0dc90b2d4ff59a1a361a4754b255d2ee0af7d8bf87c9bc9e7ddeede33934c63ca1c0e3d262cb145ef932a1f2c0a997aa6a34f8eaee7477d82ccf09095a6b8acad38d4eec9fb7eab7ad02da1d11d8e54c1825e55bf58c2a23234b902be124f9e9038a8f68fa45dab72f66e0945bf1d8bacc9044c6f07098c9fcec58a3aab100c805178155f030a124c450e5acbda47d0e4f10b80a23f803e774d023b0015c20b9f9bbe7c91296338d5ecb471cafb032007b67a60be5f69504a9f01abb3cb467b260e2bce860be8d95bf92c0c8e1496ed1e528593a4abb6df462dde8a0968dffe4683116857a232f5ebf6c85be238745ad0f38f767a5fdbf486fb":0
+pkcs1_rsassa_pss_verify:2048:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"0b8777c7f839baf0a64bbbdbc5ce79755c57a205b845c174e2d2e90546a089c4e6ec8adffa23a7ea97bae6b65d782b82db5d2b5a56d22a29a05e7c4433e2b82a621abba90add05ce393fc48a840542451a":"c7cd698d84b65128d8835e3a8b1eb0e01cb541ec":"34047ff96c4dc0dc90b2d4ff59a1a361a4754b255d2ee0af7d8bf87c9bc9e7ddeede33934c63ca1c0e3d262cb145ef932a1f2c0a997aa6a34f8eaee7477d82ccf09095a6b8acad38d4eec9fb7eab7ad02da1d11d8e54c1825e55bf58c2a23234b902be124f9e9038a8f68fa45dab72f66e0945bf1d8bacc9044c6f07098c9fcec58a3aab100c805178155f030a124c450e5acbda47d0e4f10b80a23f803e774d023b0015c20b9f9bbe7c91296338d5ecb471cafb032007b67a60be5f69504a9f01abb3cb467b260e2bce860be8d95bf92c0c8e1496ed1e528593a4abb6df462dde8a0968dffe4683116857a232f5ebf6c85be238745ad0f38f767a5fdbf486fb":0
 
 RSASSA-PSS Signature Example 10_5
-pkcs1_rsassa_pss_sign:2048:16:"cfd50283feeeb97f6f08d73cbc7b3836f82bbcd499479f5e6f76fdfcb8b38c4f71dc9e88bd6a6f76371afd65d2af1862b32afb34a95f71b8b132043ffebe3a952baf7592448148c03f9c69b1d68e4ce5cf32c86baf46fed301ca1ab403069b32f456b91f71898ab081cd8c4252ef5271915c9794b8f295851da7510f99cb73eb":16:"cc4e90d2a1b3a065d3b2d1f5a8fce31b544475664eab561d2971b99fb7bef844e8ec1f360b8c2ac8359692971ea6a38f723fcc211f5dbcb177a0fdac5164a1d4ff7fbb4e829986353cb983659a148cdd420c7d31ba3822ea90a32be46c030e8c17e1fa0ad37859e06b0aa6fa3b216d9cbe6c0e22339769c0a615913e5da719cf":16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"f1036e008e71e964dadc9219ed30e17f06b4b68a955c16b312b1eddf028b74976bed6b3f6a63d4e77859243c9cccdc98016523abb02483b35591c33aad81213bb7c7bb1a470aabc10d44256c4d4559d916":"efa8bff96212b2f4a3f371a10d574152655f5dfb":"7e0935ea18f4d6c1d17ce82eb2b3836c55b384589ce19dfe743363ac9948d1f346b7bfddfe92efd78adb21faefc89ade42b10f374003fe122e67429a1cb8cbd1f8d9014564c44d120116f4990f1a6e38774c194bd1b8213286b077b0499d2e7b3f434ab12289c556684deed78131934bb3dd6537236f7c6f3dcb09d476be07721e37e1ceed9b2f7b406887bd53157305e1c8b4f84d733bc1e186fe06cc59b6edb8f4bd7ffefdf4f7ba9cfb9d570689b5a1a4109a746a690893db3799255a0cb9215d2d1cd490590e952e8c8786aa0011265252470c041dfbc3eec7c3cbf71c24869d115c0cb4a956f56d530b80ab589acfefc690751ddf36e8d383f83cedd2cc":0
+pkcs1_rsassa_pss_sign:2048:"cfd50283feeeb97f6f08d73cbc7b3836f82bbcd499479f5e6f76fdfcb8b38c4f71dc9e88bd6a6f76371afd65d2af1862b32afb34a95f71b8b132043ffebe3a952baf7592448148c03f9c69b1d68e4ce5cf32c86baf46fed301ca1ab403069b32f456b91f71898ab081cd8c4252ef5271915c9794b8f295851da7510f99cb73eb":"cc4e90d2a1b3a065d3b2d1f5a8fce31b544475664eab561d2971b99fb7bef844e8ec1f360b8c2ac8359692971ea6a38f723fcc211f5dbcb177a0fdac5164a1d4ff7fbb4e829986353cb983659a148cdd420c7d31ba3822ea90a32be46c030e8c17e1fa0ad37859e06b0aa6fa3b216d9cbe6c0e22339769c0a615913e5da719cf":"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"f1036e008e71e964dadc9219ed30e17f06b4b68a955c16b312b1eddf028b74976bed6b3f6a63d4e77859243c9cccdc98016523abb02483b35591c33aad81213bb7c7bb1a470aabc10d44256c4d4559d916":"efa8bff96212b2f4a3f371a10d574152655f5dfb":"7e0935ea18f4d6c1d17ce82eb2b3836c55b384589ce19dfe743363ac9948d1f346b7bfddfe92efd78adb21faefc89ade42b10f374003fe122e67429a1cb8cbd1f8d9014564c44d120116f4990f1a6e38774c194bd1b8213286b077b0499d2e7b3f434ab12289c556684deed78131934bb3dd6537236f7c6f3dcb09d476be07721e37e1ceed9b2f7b406887bd53157305e1c8b4f84d733bc1e186fe06cc59b6edb8f4bd7ffefdf4f7ba9cfb9d570689b5a1a4109a746a690893db3799255a0cb9215d2d1cd490590e952e8c8786aa0011265252470c041dfbc3eec7c3cbf71c24869d115c0cb4a956f56d530b80ab589acfefc690751ddf36e8d383f83cedd2cc":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 10_5 (verify)
-pkcs1_rsassa_pss_verify:2048:16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"f1036e008e71e964dadc9219ed30e17f06b4b68a955c16b312b1eddf028b74976bed6b3f6a63d4e77859243c9cccdc98016523abb02483b35591c33aad81213bb7c7bb1a470aabc10d44256c4d4559d916":"efa8bff96212b2f4a3f371a10d574152655f5dfb":"7e0935ea18f4d6c1d17ce82eb2b3836c55b384589ce19dfe743363ac9948d1f346b7bfddfe92efd78adb21faefc89ade42b10f374003fe122e67429a1cb8cbd1f8d9014564c44d120116f4990f1a6e38774c194bd1b8213286b077b0499d2e7b3f434ab12289c556684deed78131934bb3dd6537236f7c6f3dcb09d476be07721e37e1ceed9b2f7b406887bd53157305e1c8b4f84d733bc1e186fe06cc59b6edb8f4bd7ffefdf4f7ba9cfb9d570689b5a1a4109a746a690893db3799255a0cb9215d2d1cd490590e952e8c8786aa0011265252470c041dfbc3eec7c3cbf71c24869d115c0cb4a956f56d530b80ab589acfefc690751ddf36e8d383f83cedd2cc":0
+pkcs1_rsassa_pss_verify:2048:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"f1036e008e71e964dadc9219ed30e17f06b4b68a955c16b312b1eddf028b74976bed6b3f6a63d4e77859243c9cccdc98016523abb02483b35591c33aad81213bb7c7bb1a470aabc10d44256c4d4559d916":"efa8bff96212b2f4a3f371a10d574152655f5dfb":"7e0935ea18f4d6c1d17ce82eb2b3836c55b384589ce19dfe743363ac9948d1f346b7bfddfe92efd78adb21faefc89ade42b10f374003fe122e67429a1cb8cbd1f8d9014564c44d120116f4990f1a6e38774c194bd1b8213286b077b0499d2e7b3f434ab12289c556684deed78131934bb3dd6537236f7c6f3dcb09d476be07721e37e1ceed9b2f7b406887bd53157305e1c8b4f84d733bc1e186fe06cc59b6edb8f4bd7ffefdf4f7ba9cfb9d570689b5a1a4109a746a690893db3799255a0cb9215d2d1cd490590e952e8c8786aa0011265252470c041dfbc3eec7c3cbf71c24869d115c0cb4a956f56d530b80ab589acfefc690751ddf36e8d383f83cedd2cc":0
 
 RSASSA-PSS Signature Example 10_6
-pkcs1_rsassa_pss_sign:2048:16:"cfd50283feeeb97f6f08d73cbc7b3836f82bbcd499479f5e6f76fdfcb8b38c4f71dc9e88bd6a6f76371afd65d2af1862b32afb34a95f71b8b132043ffebe3a952baf7592448148c03f9c69b1d68e4ce5cf32c86baf46fed301ca1ab403069b32f456b91f71898ab081cd8c4252ef5271915c9794b8f295851da7510f99cb73eb":16:"cc4e90d2a1b3a065d3b2d1f5a8fce31b544475664eab561d2971b99fb7bef844e8ec1f360b8c2ac8359692971ea6a38f723fcc211f5dbcb177a0fdac5164a1d4ff7fbb4e829986353cb983659a148cdd420c7d31ba3822ea90a32be46c030e8c17e1fa0ad37859e06b0aa6fa3b216d9cbe6c0e22339769c0a615913e5da719cf":16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"ad8b1523703646224b660b550885917ca2d1df28":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":0
+pkcs1_rsassa_pss_sign:2048:"cfd50283feeeb97f6f08d73cbc7b3836f82bbcd499479f5e6f76fdfcb8b38c4f71dc9e88bd6a6f76371afd65d2af1862b32afb34a95f71b8b132043ffebe3a952baf7592448148c03f9c69b1d68e4ce5cf32c86baf46fed301ca1ab403069b32f456b91f71898ab081cd8c4252ef5271915c9794b8f295851da7510f99cb73eb":"cc4e90d2a1b3a065d3b2d1f5a8fce31b544475664eab561d2971b99fb7bef844e8ec1f360b8c2ac8359692971ea6a38f723fcc211f5dbcb177a0fdac5164a1d4ff7fbb4e829986353cb983659a148cdd420c7d31ba3822ea90a32be46c030e8c17e1fa0ad37859e06b0aa6fa3b216d9cbe6c0e22339769c0a615913e5da719cf":"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"ad8b1523703646224b660b550885917ca2d1df28":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Signature Example 10_6 (verify)
-pkcs1_rsassa_pss_verify:2048:16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"ad8b1523703646224b660b550885917ca2d1df28":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":0
+pkcs1_rsassa_pss_verify:2048:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"ad8b1523703646224b660b550885917ca2d1df28":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":0
 
 RSASSA-PSS Signature verify options #1 (OK)
-pkcs1_rsassa_pss_verify_ext:2048:16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:20:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":0:0
+pkcs1_rsassa_pss_verify_ext:2048:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:20:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":0:0
 
 RSASSA-PSS Signature verify options #2 (ctx_hash none)
-pkcs1_rsassa_pss_verify_ext:2048:16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_NONE:MBEDTLS_MD_SHA1:20:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":0:0
+pkcs1_rsassa_pss_verify_ext:2048:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_NONE:MBEDTLS_MD_SHA1:20:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":0:0
 
 RSASSA-PSS Signature verify options #3 (ctx_hash diverging)
 depends_on:MBEDTLS_SHA256_C
-pkcs1_rsassa_pss_verify_ext:2048:16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA1:20:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":MBEDTLS_ERR_RSA_INVALID_PADDING:0
+pkcs1_rsassa_pss_verify_ext:2048:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA1:20:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":MBEDTLS_ERR_RSA_INVALID_PADDING:0
 
 RSASSA-PSS Signature verify options #4 (mgf1_hash diverging)
 depends_on:MBEDTLS_SHA256_C
-pkcs1_rsassa_pss_verify_ext:2048:16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA256:20:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":0:MBEDTLS_ERR_RSA_INVALID_PADDING
+pkcs1_rsassa_pss_verify_ext:2048:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA256:20:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":0:MBEDTLS_ERR_RSA_INVALID_PADDING
 
 RSASSA-PSS Signature verify options #5 (wrong msg_hash)
 depends_on:MBEDTLS_SHA256_C
-pkcs1_rsassa_pss_verify_ext:2048:16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:20:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":MBEDTLS_ERR_RSA_VERIFY_FAILED:MBEDTLS_ERR_RSA_VERIFY_FAILED
+pkcs1_rsassa_pss_verify_ext:2048:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:20:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":MBEDTLS_ERR_RSA_VERIFY_FAILED:MBEDTLS_ERR_RSA_VERIFY_FAILED
 
 RSASSA-PSS Signature verify options #6 (wrong expected_salt_len)
-pkcs1_rsassa_pss_verify_ext:2048:16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:21:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":0:MBEDTLS_ERR_RSA_INVALID_PADDING
+pkcs1_rsassa_pss_verify_ext:2048:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:21:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":0:MBEDTLS_ERR_RSA_INVALID_PADDING
 
 RSASSA-PSS Signature verify options #7 (wrong expected_salt_len)
-pkcs1_rsassa_pss_verify_ext:2048:16:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:19:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":0:MBEDTLS_ERR_RSA_INVALID_PADDING
+pkcs1_rsassa_pss_verify_ext:2048:"a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae05":"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:19:"25f10895a87716c137450bb9519dfaa1f207faa942ea88abf71e9c17980085b555aebab76264ae2a3ab93c2d12981191ddac6fb5949eb36aee3c5da940f00752c916d94608fa7d97ba6a2915b688f20323d4e9d96801d89a72ab5892dc2117c07434fcf972e058cf8c41ca4b4ff554f7d5068ad3155fced0f3125bc04f9193378a8f5c4c3b8cb4dd6d1cc69d30ecca6eaa51e36a05730e9e342e855baf099defb8afd7":"6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f":0:MBEDTLS_ERR_RSA_INVALID_PADDING
 
 RSASSA-PSS Signature verify options #8 (non-default salt_len: max)
 depends_on:MBEDTLS_SHA256_C
-pkcs1_rsassa_pss_verify_ext:1024:16:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":16:"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:94:"54657374206d657373616765":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":0:0
+pkcs1_rsassa_pss_verify_ext:1024:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:94:"54657374206d657373616765":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":0:0
 
 RSASSA-PSS Signature verify options #9 (non-default salt_len: 0)
 depends_on:MBEDTLS_SHA256_C
-pkcs1_rsassa_pss_verify_ext:1024:16:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":16:"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:0:"54657374206d657373616765":"7fc506d26ca3b22922a1ce39faaedd273161b82d9443c56f1a034f131ae4a18cae1474271cb4b66a17d9707ca58b0bdbd3c406b7e65bbcc9bbbce94dc45de807b4989b23b3e4db74ca29298137837eb90cc83d3219249bc7d480fceaf075203a86e54c4ecfa4e312e39f8f69d76534089a36ed9049ca9cfd5ab1db1fa75fe5c8":0:0
+pkcs1_rsassa_pss_verify_ext:1024:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:0:"54657374206d657373616765":"7fc506d26ca3b22922a1ce39faaedd273161b82d9443c56f1a034f131ae4a18cae1474271cb4b66a17d9707ca58b0bdbd3c406b7e65bbcc9bbbce94dc45de807b4989b23b3e4db74ca29298137837eb90cc83d3219249bc7d480fceaf075203a86e54c4ecfa4e312e39f8f69d76534089a36ed9049ca9cfd5ab1db1fa75fe5c8":0:0
 
 RSASSA-PSS Signature verify options #10 (non-default salt_len: 0, ANY)
 depends_on:MBEDTLS_SHA256_C
-pkcs1_rsassa_pss_verify_ext:1024:16:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":16:"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_RSA_SALT_LEN_ANY:"54657374206d657373616765":"7fc506d26ca3b22922a1ce39faaedd273161b82d9443c56f1a034f131ae4a18cae1474271cb4b66a17d9707ca58b0bdbd3c406b7e65bbcc9bbbce94dc45de807b4989b23b3e4db74ca29298137837eb90cc83d3219249bc7d480fceaf075203a86e54c4ecfa4e312e39f8f69d76534089a36ed9049ca9cfd5ab1db1fa75fe5c8":0:0
+pkcs1_rsassa_pss_verify_ext:1024:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_RSA_SALT_LEN_ANY:"54657374206d657373616765":"7fc506d26ca3b22922a1ce39faaedd273161b82d9443c56f1a034f131ae4a18cae1474271cb4b66a17d9707ca58b0bdbd3c406b7e65bbcc9bbbce94dc45de807b4989b23b3e4db74ca29298137837eb90cc83d3219249bc7d480fceaf075203a86e54c4ecfa4e312e39f8f69d76534089a36ed9049ca9cfd5ab1db1fa75fe5c8":0:0
 
 RSASSA-PSS Signature verify options #11 (MGF1 alg != MSG hash alg)
 depends_on:MBEDTLS_SHA256_C
-pkcs1_rsassa_pss_verify_ext:1024:16:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":16:"010001":MBEDTLS_MD_NONE:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_RSA_SALT_LEN_ANY:"c0719e9a8d5d838d861dc6f675c899d2b309a3a65bb9fe6b11e5afcbf9a2c0b1":"7fc506d26ca3b22922a1ce39faaedd273161b82d9443c56f1a034f131ae4a18cae1474271cb4b66a17d9707ca58b0bdbd3c406b7e65bbcc9bbbce94dc45de807b4989b23b3e4db74ca29298137837eb90cc83d3219249bc7d480fceaf075203a86e54c4ecfa4e312e39f8f69d76534089a36ed9049ca9cfd5ab1db1fa75fe5c8":0:0
+pkcs1_rsassa_pss_verify_ext:1024:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":"010001":MBEDTLS_MD_NONE:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_RSA_SALT_LEN_ANY:"c0719e9a8d5d838d861dc6f675c899d2b309a3a65bb9fe6b11e5afcbf9a2c0b1":"7fc506d26ca3b22922a1ce39faaedd273161b82d9443c56f1a034f131ae4a18cae1474271cb4b66a17d9707ca58b0bdbd3c406b7e65bbcc9bbbce94dc45de807b4989b23b3e4db74ca29298137837eb90cc83d3219249bc7d480fceaf075203a86e54c4ecfa4e312e39f8f69d76534089a36ed9049ca9cfd5ab1db1fa75fe5c8":0:0
 
 RSASSA-PSS Signature verify options #12 (MGF1 alg != MSG hash alg, ctx wrong)
 depends_on:MBEDTLS_SHA256_C
-pkcs1_rsassa_pss_verify_ext:1024:16:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":16:"010001":MBEDTLS_MD_NONE:MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA256:MBEDTLS_RSA_SALT_LEN_ANY:"c0719e9a8d5d838d861dc6f675c899d2b309a3a65bb9fe6b11e5afcbf9a2c0b1":"7fc506d26ca3b22922a1ce39faaedd273161b82d9443c56f1a034f131ae4a18cae1474271cb4b66a17d9707ca58b0bdbd3c406b7e65bbcc9bbbce94dc45de807b4989b23b3e4db74ca29298137837eb90cc83d3219249bc7d480fceaf075203a86e54c4ecfa4e312e39f8f69d76534089a36ed9049ca9cfd5ab1db1fa75fe5c8":MBEDTLS_ERR_RSA_INVALID_PADDING:0
+pkcs1_rsassa_pss_verify_ext:1024:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":"010001":MBEDTLS_MD_NONE:MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA256:MBEDTLS_RSA_SALT_LEN_ANY:"c0719e9a8d5d838d861dc6f675c899d2b309a3a65bb9fe6b11e5afcbf9a2c0b1":"7fc506d26ca3b22922a1ce39faaedd273161b82d9443c56f1a034f131ae4a18cae1474271cb4b66a17d9707ca58b0bdbd3c406b7e65bbcc9bbbce94dc45de807b4989b23b3e4db74ca29298137837eb90cc83d3219249bc7d480fceaf075203a86e54c4ecfa4e312e39f8f69d76534089a36ed9049ca9cfd5ab1db1fa75fe5c8":MBEDTLS_ERR_RSA_INVALID_PADDING:0
 
 RSASSA-PSS Signature verify options #13 (MGF1 alg != MSG hash alg, arg wrong)
 depends_on:MBEDTLS_SHA256_C
-pkcs1_rsassa_pss_verify_ext:1024:16:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":16:"010001":MBEDTLS_MD_NONE:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA1:MBEDTLS_RSA_SALT_LEN_ANY:"c0719e9a8d5d838d861dc6f675c899d2b309a3a65bb9fe6b11e5afcbf9a2c0b1":"7fc506d26ca3b22922a1ce39faaedd273161b82d9443c56f1a034f131ae4a18cae1474271cb4b66a17d9707ca58b0bdbd3c406b7e65bbcc9bbbce94dc45de807b4989b23b3e4db74ca29298137837eb90cc83d3219249bc7d480fceaf075203a86e54c4ecfa4e312e39f8f69d76534089a36ed9049ca9cfd5ab1db1fa75fe5c8":0:MBEDTLS_ERR_RSA_INVALID_PADDING
+pkcs1_rsassa_pss_verify_ext:1024:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":"010001":MBEDTLS_MD_NONE:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA1:MBEDTLS_RSA_SALT_LEN_ANY:"c0719e9a8d5d838d861dc6f675c899d2b309a3a65bb9fe6b11e5afcbf9a2c0b1":"7fc506d26ca3b22922a1ce39faaedd273161b82d9443c56f1a034f131ae4a18cae1474271cb4b66a17d9707ca58b0bdbd3c406b7e65bbcc9bbbce94dc45de807b4989b23b3e4db74ca29298137837eb90cc83d3219249bc7d480fceaf075203a86e54c4ecfa4e312e39f8f69d76534089a36ed9049ca9cfd5ab1db1fa75fe5c8":0:MBEDTLS_ERR_RSA_INVALID_PADDING
 
 RSASSA-PSS verify ext, 512-bit key, empty salt, good signature
 depends_on:MBEDTLS_SHA256_C
-pkcs1_rsassa_pss_verify_ext:512:16:"00b076d23250816f9aab02307e452b97f0cae7598369b41624e8afc7971a59a13892f64b07eaa6ec928c160b2d6ec8f9d0dd5b63c8b3ac0767b4f65c892f56c10f":16:"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:0:"":"ace8b03347da1b9a7a5e94a0d76359bb39c819bb170bef38ea84995ed653446c0ae87ede434cdf9d0cb2d7bf164cf427892363e6855a1d24d0ce5dd72acaf246":0:0
+pkcs1_rsassa_pss_verify_ext:512:"00b076d23250816f9aab02307e452b97f0cae7598369b41624e8afc7971a59a13892f64b07eaa6ec928c160b2d6ec8f9d0dd5b63c8b3ac0767b4f65c892f56c10f":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:0:"":"ace8b03347da1b9a7a5e94a0d76359bb39c819bb170bef38ea84995ed653446c0ae87ede434cdf9d0cb2d7bf164cf427892363e6855a1d24d0ce5dd72acaf246":0:0
 
 RSASSA-PSS verify ext, 512-bit key, empty salt, bad signature
 depends_on:MBEDTLS_SHA256_C
-pkcs1_rsassa_pss_verify_ext:512:16:"00b076d23250816f9aab02307e452b97f0cae7598369b41624e8afc7971a59a13892f64b07eaa6ec928c160b2d6ec8f9d0dd5b63c8b3ac0767b4f65c892f56c10f":16:"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:0:"":"ace8b03347da1b9a7a5e94a0d76359bb39c819bb170bef38ea84995ed653446c0ae87ede434cdf9d0cb2d7bf164cf427892363e6855a1d24d0ce5dd72acaf247":MBEDTLS_ERR_RSA_INVALID_PADDING:MBEDTLS_ERR_RSA_INVALID_PADDING
+pkcs1_rsassa_pss_verify_ext:512:"00b076d23250816f9aab02307e452b97f0cae7598369b41624e8afc7971a59a13892f64b07eaa6ec928c160b2d6ec8f9d0dd5b63c8b3ac0767b4f65c892f56c10f":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:0:"":"ace8b03347da1b9a7a5e94a0d76359bb39c819bb170bef38ea84995ed653446c0ae87ede434cdf9d0cb2d7bf164cf427892363e6855a1d24d0ce5dd72acaf247":MBEDTLS_ERR_RSA_INVALID_PADDING:MBEDTLS_ERR_RSA_INVALID_PADDING
 
 RSASSA-PSS verify ext, 522-bit key, SHA-512, empty salt, good signature
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_verify_ext:522:16:"02d302753e3dda28f42f4d9f92c8647420ea6fbc97c10f8498b966a953f357698d6581060dfe32c8ab98db4bc5ce2acdf0c1e6e404a75a13282550c1aa37d3cdc8bf":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:0:"":"016752ae0b5dfbade6bbd3dd37868d48c8d741f92dca41c360aeda553204c2212a117b1a3d77e0d3f48723503c46e16c8a64de00f1dee3e37e478417452630859486":0:0
+pkcs1_rsassa_pss_verify_ext:522:"02d302753e3dda28f42f4d9f92c8647420ea6fbc97c10f8498b966a953f357698d6581060dfe32c8ab98db4bc5ce2acdf0c1e6e404a75a13282550c1aa37d3cdc8bf":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:0:"":"016752ae0b5dfbade6bbd3dd37868d48c8d741f92dca41c360aeda553204c2212a117b1a3d77e0d3f48723503c46e16c8a64de00f1dee3e37e478417452630859486":0:0
 
 RSASSA-PSS verify ext, 522-bit key, SHA-512, saltlen=64, good signature with saltlen=0
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_verify_ext:522:16:"02d302753e3dda28f42f4d9f92c8647420ea6fbc97c10f8498b966a953f357698d6581060dfe32c8ab98db4bc5ce2acdf0c1e6e404a75a13282550c1aa37d3cdc8bf":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:64:"":"016752ae0b5dfbade6bbd3dd37868d48c8d741f92dca41c360aeda553204c2212a117b1a3d77e0d3f48723503c46e16c8a64de00f1dee3e37e478417452630859486":0:MBEDTLS_ERR_RSA_INVALID_PADDING
+pkcs1_rsassa_pss_verify_ext:522:"02d302753e3dda28f42f4d9f92c8647420ea6fbc97c10f8498b966a953f357698d6581060dfe32c8ab98db4bc5ce2acdf0c1e6e404a75a13282550c1aa37d3cdc8bf":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:64:"":"016752ae0b5dfbade6bbd3dd37868d48c8d741f92dca41c360aeda553204c2212a117b1a3d77e0d3f48723503c46e16c8a64de00f1dee3e37e478417452630859486":0:MBEDTLS_ERR_RSA_INVALID_PADDING
 
 RSASSA-PSS verify ext, 528-bit key, SHA-512, empty salt, good signature
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_verify_ext:528:16:"00e31c246d46485984261fd174cab3d4357344602ecd793c47dbe54252d37bb350bc634359b19515542080e4724a4b672291be57c7648f51629eaef234e847d99cc65f":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:0:"":"a9ad7994ba3a1071124153486924448cc67a5af3a5d34e9261d53770782cc85f58e2edde5f7004652a645e3e9606530eb57de41df7298ae2be9dec69cc0d613ab629":0:0
+pkcs1_rsassa_pss_verify_ext:528:"00e31c246d46485984261fd174cab3d4357344602ecd793c47dbe54252d37bb350bc634359b19515542080e4724a4b672291be57c7648f51629eaef234e847d99cc65f":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:0:"":"a9ad7994ba3a1071124153486924448cc67a5af3a5d34e9261d53770782cc85f58e2edde5f7004652a645e3e9606530eb57de41df7298ae2be9dec69cc0d613ab629":0:0
 
 RSASSA-PSS verify ext, 528-bit key, SHA-512, saltlen=64, good signature with saltlen=0
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_verify_ext:528:16:"00e31c246d46485984261fd174cab3d4357344602ecd793c47dbe54252d37bb350bc634359b19515542080e4724a4b672291be57c7648f51629eaef234e847d99cc65f":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:64:"":"a9ad7994ba3a1071124153486924448cc67a5af3a5d34e9261d53770782cc85f58e2edde5f7004652a645e3e9606530eb57de41df7298ae2be9dec69cc0d613ab629":0:MBEDTLS_ERR_RSA_INVALID_PADDING
+pkcs1_rsassa_pss_verify_ext:528:"00e31c246d46485984261fd174cab3d4357344602ecd793c47dbe54252d37bb350bc634359b19515542080e4724a4b672291be57c7648f51629eaef234e847d99cc65f":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:64:"":"a9ad7994ba3a1071124153486924448cc67a5af3a5d34e9261d53770782cc85f58e2edde5f7004652a645e3e9606530eb57de41df7298ae2be9dec69cc0d613ab629":0:MBEDTLS_ERR_RSA_INVALID_PADDING
 
 RSASSA-PSS verify ext, 512-bit key, SHA-512 (hash too large)
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_verify_ext:512:16:"00b076d23250816f9aab02307e452b97f0cae7598369b41624e8afc7971a59a13892f64b07eaa6ec928c160b2d6ec8f9d0dd5b63c8b3ac0767b4f65c892f56c10f":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:0:"":"ace8b03347da1b9a7a5e94a0d76359bb39c819bb170bef38ea84995ed653446c0ae87ede434cdf9d0cb2d7bf164cf427892363e6855a1d24d0ce5dd72acaf246":MBEDTLS_ERR_RSA_BAD_INPUT_DATA:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
+pkcs1_rsassa_pss_verify_ext:512:"00b076d23250816f9aab02307e452b97f0cae7598369b41624e8afc7971a59a13892f64b07eaa6ec928c160b2d6ec8f9d0dd5b63c8b3ac0767b4f65c892f56c10f":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:0:"":"ace8b03347da1b9a7a5e94a0d76359bb39c819bb170bef38ea84995ed653446c0ae87ede434cdf9d0cb2d7bf164cf427892363e6855a1d24d0ce5dd72acaf246":MBEDTLS_ERR_RSA_BAD_INPUT_DATA:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
 
 RSASSA-PSS verify ext, 521-bit key, SHA-512, empty salt, bad signature
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_verify_ext:521:16:"0131b69860f3cb9bf85ea358fdf2bd2990f1b77a80d6a4fdf817a43dd896bdf7dd26af8ac0237f526e0d33b105c971fdbd4ffa9ece99fc469f31ecf429e8f562c1c3":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:0:"":"00471794655837da498cbf27242807b40593a353c707eb22fd2cc5a3259e728ac4f1df676043eeec8e16c1175b3d9ac8cae72ec1d5772dd69de71c5677f19031568e":MBEDTLS_ERR_RSA_BAD_INPUT_DATA:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
+pkcs1_rsassa_pss_verify_ext:521:"0131b69860f3cb9bf85ea358fdf2bd2990f1b77a80d6a4fdf817a43dd896bdf7dd26af8ac0237f526e0d33b105c971fdbd4ffa9ece99fc469f31ecf429e8f562c1c3":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:0:"":"00471794655837da498cbf27242807b40593a353c707eb22fd2cc5a3259e728ac4f1df676043eeec8e16c1175b3d9ac8cae72ec1d5772dd69de71c5677f19031568e":MBEDTLS_ERR_RSA_BAD_INPUT_DATA:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
 
 RSASSA-PSS verify ext, 521-bit key, SHA-256, empty salt, good signature
 depends_on:MBEDTLS_SHA256_C
-pkcs1_rsassa_pss_verify_ext:521:16:"0131b69860f3cb9bf85ea358fdf2bd2990f1b77a80d6a4fdf817a43dd896bdf7dd26af8ac0237f526e0d33b105c971fdbd4ffa9ece99fc469f31ecf429e8f562c1c3":16:"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:0:"41":"009c4941157fa36288e467310b198ab0c615c40963d611ffeef03000549ded809235955ecc57adba44782e9497c004f480ba2b3d58db8335fe0b391075c02c843a6d":0:0
+pkcs1_rsassa_pss_verify_ext:521:"0131b69860f3cb9bf85ea358fdf2bd2990f1b77a80d6a4fdf817a43dd896bdf7dd26af8ac0237f526e0d33b105c971fdbd4ffa9ece99fc469f31ecf429e8f562c1c3":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:0:"41":"009c4941157fa36288e467310b198ab0c615c40963d611ffeef03000549ded809235955ecc57adba44782e9497c004f480ba2b3d58db8335fe0b391075c02c843a6d":0:0
 
 RSASSA-PSS verify ext, 521-bit key, SHA-256, empty salt, flipped-highest-bit signature
 depends_on:MBEDTLS_SHA256_C
-pkcs1_rsassa_pss_verify_ext:521:16:"0131b69860f3cb9bf85ea358fdf2bd2990f1b77a80d6a4fdf817a43dd896bdf7dd26af8ac0237f526e0d33b105c971fdbd4ffa9ece99fc469f31ecf429e8f562c1c3":16:"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:0:"41":"00e11a2403df681c44a1f73f014b6c9ad17847d0b673f7c2a801cee208d10ab5792c10cd0cd495a4b331aaa521409fca7cb1b0d978b3a84cd67e28078b98753e9466":MBEDTLS_ERR_RSA_BAD_INPUT_DATA:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
+pkcs1_rsassa_pss_verify_ext:521:"0131b69860f3cb9bf85ea358fdf2bd2990f1b77a80d6a4fdf817a43dd896bdf7dd26af8ac0237f526e0d33b105c971fdbd4ffa9ece99fc469f31ecf429e8f562c1c3":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:0:"41":"00e11a2403df681c44a1f73f014b6c9ad17847d0b673f7c2a801cee208d10ab5792c10cd0cd495a4b331aaa521409fca7cb1b0d978b3a84cd67e28078b98753e9466":MBEDTLS_ERR_RSA_BAD_INPUT_DATA:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
 
 RSASSA-PSS verify ext, all-zero padding, automatic salt length
 depends_on:MBEDTLS_SHA256_C
-pkcs1_rsassa_pss_verify_ext:512:16:"00b076d23250816f9aab02307e452b97f0cae7598369b41624e8afc7971a59a13892f64b07eaa6ec928c160b2d6ec8f9d0dd5b63c8b3ac0767b4f65c892f56c10f":16:"010001":MBEDTLS_MD_NONE:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_RSA_SALT_LEN_ANY:"":"63a35294577c7e593170378175b7df27c293dae583ec2a971426eb2d66f2af483e897bfae5dc20300a9d61a3644e08c3aee61a463690a3498901563c46041056":MBEDTLS_ERR_RSA_INVALID_PADDING:MBEDTLS_ERR_RSA_INVALID_PADDING
+pkcs1_rsassa_pss_verify_ext:512:"00b076d23250816f9aab02307e452b97f0cae7598369b41624e8afc7971a59a13892f64b07eaa6ec928c160b2d6ec8f9d0dd5b63c8b3ac0767b4f65c892f56c10f":"010001":MBEDTLS_MD_NONE:MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:MBEDTLS_RSA_SALT_LEN_ANY:"":"63a35294577c7e593170378175b7df27c293dae583ec2a971426eb2d66f2af483e897bfae5dc20300a9d61a3644e08c3aee61a463690a3498901563c46041056":MBEDTLS_ERR_RSA_INVALID_PADDING:MBEDTLS_ERR_RSA_INVALID_PADDING
 
 RSASSA-PSS Signature RSA-1024, SHA-512
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_sign:1024:16:"00e8f95a716c127d5147dcc241a7c1fe8d5487b3e8b6e95e48a83334d21d00c79ad0a90e29941c0c53065b20059de95e9e406061416f7ac12edca1983b9ee28cc3":16:"00d72348b297e7e5dc4329f6ab874b17982584e0ab43174070a9be983c0f040320d6f893c40d2717cb3044380cb3230b7133621eb1c55a3ea56d0e7cee694b5df3":16:"00c3c9873548543591c1f947e412c33da56b9d1b94a58c2f410a8a620e9b4f1d9197643ebf527f5f62b202b9d67a32654d05f326a9b61e0106efdf4829673c4f3d23655996e2424059916ab47aa67e406c129679e5979ca46708866608ffa21f619843b959b4442e422598a2faab54a8cef1f131992677d2cf5bcaf2b5564f7419":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"655d1cf86a7af5113d1791ab7b6627845ea2aa7efbae82705a3563e5ba0337a1d033cb9283b38c042056e0a1d0529891173e3df6621dd8b184930caec8b3cbe4d1068524dab0ec6854f6638d86b77434cd792ddec0d02327a9eebffcd6911ffd32ad9bcb569d3237398c8169d9c62e7eea81c1b456fd36019aad1e4b268c604d":0
+pkcs1_rsassa_pss_sign:1024:"00e8f95a716c127d5147dcc241a7c1fe8d5487b3e8b6e95e48a83334d21d00c79ad0a90e29941c0c53065b20059de95e9e406061416f7ac12edca1983b9ee28cc3":"00d72348b297e7e5dc4329f6ab874b17982584e0ab43174070a9be983c0f040320d6f893c40d2717cb3044380cb3230b7133621eb1c55a3ea56d0e7cee694b5df3":"00c3c9873548543591c1f947e412c33da56b9d1b94a58c2f410a8a620e9b4f1d9197643ebf527f5f62b202b9d67a32654d05f326a9b61e0106efdf4829673c4f3d23655996e2424059916ab47aa67e406c129679e5979ca46708866608ffa21f619843b959b4442e422598a2faab54a8cef1f131992677d2cf5bcaf2b5564f7419":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"655d1cf86a7af5113d1791ab7b6627845ea2aa7efbae82705a3563e5ba0337a1d033cb9283b38c042056e0a1d0529891173e3df6621dd8b184930caec8b3cbe4d1068524dab0ec6854f6638d86b77434cd792ddec0d02327a9eebffcd6911ffd32ad9bcb569d3237398c8169d9c62e7eea81c1b456fd36019aad1e4b268c604d":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Verification RSA-1024, SHA-512
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_verify:1022:16:"00c3c9873548543591c1f947e412c33da56b9d1b94a58c2f410a8a620e9b4f1d9197643ebf527f5f62b202b9d67a32654d05f326a9b61e0106efdf4829673c4f3d23655996e2424059916ab47aa67e406c129679e5979ca46708866608ffa21f619843b959b4442e422598a2faab54a8cef1f131992677d2cf5bcaf2b5564f7419":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"655d1cf86a7af5113d1791ab7b6627845ea2aa7efbae82705a3563e5ba0337a1d033cb9283b38c042056e0a1d0529891173e3df6621dd8b184930caec8b3cbe4d1068524dab0ec6854f6638d86b77434cd792ddec0d02327a9eebffcd6911ffd32ad9bcb569d3237398c8169d9c62e7eea81c1b456fd36019aad1e4b268c604d":0
+pkcs1_rsassa_pss_verify:1022:"00c3c9873548543591c1f947e412c33da56b9d1b94a58c2f410a8a620e9b4f1d9197643ebf527f5f62b202b9d67a32654d05f326a9b61e0106efdf4829673c4f3d23655996e2424059916ab47aa67e406c129679e5979ca46708866608ffa21f619843b959b4442e422598a2faab54a8cef1f131992677d2cf5bcaf2b5564f7419":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"655d1cf86a7af5113d1791ab7b6627845ea2aa7efbae82705a3563e5ba0337a1d033cb9283b38c042056e0a1d0529891173e3df6621dd8b184930caec8b3cbe4d1068524dab0ec6854f6638d86b77434cd792ddec0d02327a9eebffcd6911ffd32ad9bcb569d3237398c8169d9c62e7eea81c1b456fd36019aad1e4b268c604d":0
 
 RSASSA-PSS Signature RSA-1032, SHA-512
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_sign:1032:16:"0dfaedb709ada2105223e5e7764a5f31d07ae7a37bdc7b4a56c2499e1173147bcdcb165b8fb01a2528190cb6874656a936491898fca330db8af5a9ed5417268ed7":16:"0c339c56797a90c641292560d0ef675f71ac2c99fcaba6260c38e4f167dfd179eb7a9e255f9bdbc549e4181f9a2a19b1f30a80b292d5ef1ad75b9e658eaa6fb0bb":16:"00aa94ab91b4c26be257e469528228c4b0b6b4c99e73a84a272b3101892c07406911372b83ec4a7b8191f0ba4b4cb4cb3b732074e96c668297e1323b8ad0822a7e151182def03871a66a47b704b92845c6194142d4eeda19903e04043581f7a835dc288117863d21944c3aeded518458f1a30a41c7638aa4e098a88fdf2c2097270d":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"13ad40169494129b907f061d885fbe50ab654fc7b4be657ff8629d7ca291838159e9a7b7adc93560dda2bb9127966eb8d57377fb19d5b043dca67a07ba3c23069b391ddd921b507a8cca2d5eb7ccc84b90089092ca88530e074e629c3cb6902b2d0475000269a28c4cd89cec0dca66571fa7fbe4976373abe905cbe4c66c8d5fbb":0
+pkcs1_rsassa_pss_sign:1032:"0dfaedb709ada2105223e5e7764a5f31d07ae7a37bdc7b4a56c2499e1173147bcdcb165b8fb01a2528190cb6874656a936491898fca330db8af5a9ed5417268ed7":"0c339c56797a90c641292560d0ef675f71ac2c99fcaba6260c38e4f167dfd179eb7a9e255f9bdbc549e4181f9a2a19b1f30a80b292d5ef1ad75b9e658eaa6fb0bb":"00aa94ab91b4c26be257e469528228c4b0b6b4c99e73a84a272b3101892c07406911372b83ec4a7b8191f0ba4b4cb4cb3b732074e96c668297e1323b8ad0822a7e151182def03871a66a47b704b92845c6194142d4eeda19903e04043581f7a835dc288117863d21944c3aeded518458f1a30a41c7638aa4e098a88fdf2c2097270d":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"13ad40169494129b907f061d885fbe50ab654fc7b4be657ff8629d7ca291838159e9a7b7adc93560dda2bb9127966eb8d57377fb19d5b043dca67a07ba3c23069b391ddd921b507a8cca2d5eb7ccc84b90089092ca88530e074e629c3cb6902b2d0475000269a28c4cd89cec0dca66571fa7fbe4976373abe905cbe4c66c8d5fbb":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Verification RSA-1032, SHA-512
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_verify:1032:16:"00aa94ab91b4c26be257e469528228c4b0b6b4c99e73a84a272b3101892c07406911372b83ec4a7b8191f0ba4b4cb4cb3b732074e96c668297e1323b8ad0822a7e151182def03871a66a47b704b92845c6194142d4eeda19903e04043581f7a835dc288117863d21944c3aeded518458f1a30a41c7638aa4e098a88fdf2c2097270d":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"13ad40169494129b907f061d885fbe50ab654fc7b4be657ff8629d7ca291838159e9a7b7adc93560dda2bb9127966eb8d57377fb19d5b043dca67a07ba3c23069b391ddd921b507a8cca2d5eb7ccc84b90089092ca88530e074e629c3cb6902b2d0475000269a28c4cd89cec0dca66571fa7fbe4976373abe905cbe4c66c8d5fbb":0
+pkcs1_rsassa_pss_verify:1032:"00aa94ab91b4c26be257e469528228c4b0b6b4c99e73a84a272b3101892c07406911372b83ec4a7b8191f0ba4b4cb4cb3b732074e96c668297e1323b8ad0822a7e151182def03871a66a47b704b92845c6194142d4eeda19903e04043581f7a835dc288117863d21944c3aeded518458f1a30a41c7638aa4e098a88fdf2c2097270d":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"13ad40169494129b907f061d885fbe50ab654fc7b4be657ff8629d7ca291838159e9a7b7adc93560dda2bb9127966eb8d57377fb19d5b043dca67a07ba3c23069b391ddd921b507a8cca2d5eb7ccc84b90089092ca88530e074e629c3cb6902b2d0475000269a28c4cd89cec0dca66571fa7fbe4976373abe905cbe4c66c8d5fbb":0
 
 RSASSA-PSS Verification of OpenSSL-generated signature RSA-1032, SHA-512
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_verify:1032:16:"00aa94ab91b4c26be257e469528228c4b0b6b4c99e73a84a272b3101892c07406911372b83ec4a7b8191f0ba4b4cb4cb3b732074e96c668297e1323b8ad0822a7e151182def03871a66a47b704b92845c6194142d4eeda19903e04043581f7a835dc288117863d21944c3aeded518458f1a30a41c7638aa4e098a88fdf2c2097270d":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"1de40b1c452691dfd8ceb42ecf5f0cbda944d871141b4407c1e30a6657c58c2e496b2a3ad10e025d45ca9606d25602ac1de04af8e0d24aa06e57ec3fea5c961ecf1e0a4e442fda0cdaba42469288cde5d7d0c223facceaf4c7caabe93505acd5664c9b4fae64272af4d5b74326a01724a25fabdb10b177821d2273650a84426dbd":0
+pkcs1_rsassa_pss_verify:1032:"00aa94ab91b4c26be257e469528228c4b0b6b4c99e73a84a272b3101892c07406911372b83ec4a7b8191f0ba4b4cb4cb3b732074e96c668297e1323b8ad0822a7e151182def03871a66a47b704b92845c6194142d4eeda19903e04043581f7a835dc288117863d21944c3aeded518458f1a30a41c7638aa4e098a88fdf2c2097270d":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"1de40b1c452691dfd8ceb42ecf5f0cbda944d871141b4407c1e30a6657c58c2e496b2a3ad10e025d45ca9606d25602ac1de04af8e0d24aa06e57ec3fea5c961ecf1e0a4e442fda0cdaba42469288cde5d7d0c223facceaf4c7caabe93505acd5664c9b4fae64272af4d5b74326a01724a25fabdb10b177821d2273650a84426dbd":0
 
 RSASSA-PSS Signature RSA-1040, SHA-512
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_sign:1040:16:"00fc7f4b490b4d3ef729db23fb5afbb5f2fc620a472342d8b8ff310cfdc124be76dc22ab6f4be35a38ddd31f24d7f64d310f67ab3a375e83f4e0559e4cb5dc43e875":16:"00d51e8680ab71dc01e1a8a68a298636bb1658cfab8d73ce528a62697722d485ab90cdafc5e27768b761839ff93420458ae55f15a69465dbc0c7b524dc9a385ff925":16:"00d2340538231dcd5a61edf83ab94b2e4b3a784394c4ed35a424c050c294157b7625f9aca8258c21e2d0a7aa9b7c9db576404e63090dba50d998f9a3ec72b1a5cf28d83251ab93341c7d2c1a90403d70f67bc1a9e413bc62facccb52441e24c3f2bc9fdeca1a783012e70b9528176260580c4e1026c58209e8dcc4de3bf3f5be5565e9":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"13e695948d59ded5a975cd9fb14bffc48e4ff9725576a96a6693da1a3c4c90d17d6811a97a633180d76dba5b957d2244e3b97e7bf3463a77d0b6c39b28a88e0b6739113726cd74937ad5f693ae5a8fd77febc270a115df05c344ddffebc2438ae67a5eea6572f434881bdf350aed4ec8f3a530d279d3fff07bb78e510807114e6ee7":0
+pkcs1_rsassa_pss_sign:1040:"00fc7f4b490b4d3ef729db23fb5afbb5f2fc620a472342d8b8ff310cfdc124be76dc22ab6f4be35a38ddd31f24d7f64d310f67ab3a375e83f4e0559e4cb5dc43e875":"00d51e8680ab71dc01e1a8a68a298636bb1658cfab8d73ce528a62697722d485ab90cdafc5e27768b761839ff93420458ae55f15a69465dbc0c7b524dc9a385ff925":"00d2340538231dcd5a61edf83ab94b2e4b3a784394c4ed35a424c050c294157b7625f9aca8258c21e2d0a7aa9b7c9db576404e63090dba50d998f9a3ec72b1a5cf28d83251ab93341c7d2c1a90403d70f67bc1a9e413bc62facccb52441e24c3f2bc9fdeca1a783012e70b9528176260580c4e1026c58209e8dcc4de3bf3f5be5565e9":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"13e695948d59ded5a975cd9fb14bffc48e4ff9725576a96a6693da1a3c4c90d17d6811a97a633180d76dba5b957d2244e3b97e7bf3463a77d0b6c39b28a88e0b6739113726cd74937ad5f693ae5a8fd77febc270a115df05c344ddffebc2438ae67a5eea6572f434881bdf350aed4ec8f3a530d279d3fff07bb78e510807114e6ee7":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Verification RSA-1040, SHA-512
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_verify:1040:16:"00d2340538231dcd5a61edf83ab94b2e4b3a784394c4ed35a424c050c294157b7625f9aca8258c21e2d0a7aa9b7c9db576404e63090dba50d998f9a3ec72b1a5cf28d83251ab93341c7d2c1a90403d70f67bc1a9e413bc62facccb52441e24c3f2bc9fdeca1a783012e70b9528176260580c4e1026c58209e8dcc4de3bf3f5be5565e9":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"13e695948d59ded5a975cd9fb14bffc48e4ff9725576a96a6693da1a3c4c90d17d6811a97a633180d76dba5b957d2244e3b97e7bf3463a77d0b6c39b28a88e0b6739113726cd74937ad5f693ae5a8fd77febc270a115df05c344ddffebc2438ae67a5eea6572f434881bdf350aed4ec8f3a530d279d3fff07bb78e510807114e6ee7":0
+pkcs1_rsassa_pss_verify:1040:"00d2340538231dcd5a61edf83ab94b2e4b3a784394c4ed35a424c050c294157b7625f9aca8258c21e2d0a7aa9b7c9db576404e63090dba50d998f9a3ec72b1a5cf28d83251ab93341c7d2c1a90403d70f67bc1a9e413bc62facccb52441e24c3f2bc9fdeca1a783012e70b9528176260580c4e1026c58209e8dcc4de3bf3f5be5565e9":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"13e695948d59ded5a975cd9fb14bffc48e4ff9725576a96a6693da1a3c4c90d17d6811a97a633180d76dba5b957d2244e3b97e7bf3463a77d0b6c39b28a88e0b6739113726cd74937ad5f693ae5a8fd77febc270a115df05c344ddffebc2438ae67a5eea6572f434881bdf350aed4ec8f3a530d279d3fff07bb78e510807114e6ee7":0
 
 RSASSA-PSS Signature RSA-1048, SHA-512
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_sign:1048:16:"0f39b79809516becc2e3481b6b47584aa2299bd2027ab8a303b9de5b0adcb4a5d38e38edb8c1fac3ea1dbd7e1d50b84323e362cff4df3f5a5182dafa9bb9217a73d7":16:"0d18164f8bd0d58d019998c8cb17c4c0354e62b8a9462acca30816894f982c2ae114e73993e30698930437b4eec44adec24d32ccbcbae7cc4c9f8911b1eb2100685b":16:"00c75d0f9fa17d1d24b939537a434017f390c6604444c35a13360d6b1fc986baf40159b84275d37b883278df5064dd9eb0f29b0d325acc790c4b59672737dbbf3acb88f5e2f2d54c919cafd072272c494591d52e158993315e71e2ca60b1c74feff8f3d77842b415d4e71734a498206a5cd9315c87b23e583e25eb4ca97056b45c96856d":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"9442a8ec48f87ebc81cc1273b03e528e7643c9e2fcc60ed85827d9341c5a36e5c76059baa8e9891df437e44c4047a266b46bcaaad3de1f1d4d3576defff080b791b013491636187fc45a930b70a533ed92abfd168f050df91b4c35d68d160a243ce589807a7d32661fc18b9547cdc0fd86d33acd349c98b34fb016ddd1bff23c58170e":0
+pkcs1_rsassa_pss_sign:1048:"0f39b79809516becc2e3481b6b47584aa2299bd2027ab8a303b9de5b0adcb4a5d38e38edb8c1fac3ea1dbd7e1d50b84323e362cff4df3f5a5182dafa9bb9217a73d7":"0d18164f8bd0d58d019998c8cb17c4c0354e62b8a9462acca30816894f982c2ae114e73993e30698930437b4eec44adec24d32ccbcbae7cc4c9f8911b1eb2100685b":"00c75d0f9fa17d1d24b939537a434017f390c6604444c35a13360d6b1fc986baf40159b84275d37b883278df5064dd9eb0f29b0d325acc790c4b59672737dbbf3acb88f5e2f2d54c919cafd072272c494591d52e158993315e71e2ca60b1c74feff8f3d77842b415d4e71734a498206a5cd9315c87b23e583e25eb4ca97056b45c96856d":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"9442a8ec48f87ebc81cc1273b03e528e7643c9e2fcc60ed85827d9341c5a36e5c76059baa8e9891df437e44c4047a266b46bcaaad3de1f1d4d3576defff080b791b013491636187fc45a930b70a533ed92abfd168f050df91b4c35d68d160a243ce589807a7d32661fc18b9547cdc0fd86d33acd349c98b34fb016ddd1bff23c58170e":MBEDTLS_RSA_SALT_LEN_ANY:0
 
 RSASSA-PSS Verification RSA-1048, SHA-512
 depends_on:MBEDTLS_SHA512_C
-pkcs1_rsassa_pss_verify:1048:16:"00c75d0f9fa17d1d24b939537a434017f390c6604444c35a13360d6b1fc986baf40159b84275d37b883278df5064dd9eb0f29b0d325acc790c4b59672737dbbf3acb88f5e2f2d54c919cafd072272c494591d52e158993315e71e2ca60b1c74feff8f3d77842b415d4e71734a498206a5cd9315c87b23e583e25eb4ca97056b45c96856d":16:"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"9442a8ec48f87ebc81cc1273b03e528e7643c9e2fcc60ed85827d9341c5a36e5c76059baa8e9891df437e44c4047a266b46bcaaad3de1f1d4d3576defff080b791b013491636187fc45a930b70a533ed92abfd168f050df91b4c35d68d160a243ce589807a7d32661fc18b9547cdc0fd86d33acd349c98b34fb016ddd1bff23c58170e":0
+pkcs1_rsassa_pss_verify:1048:"00c75d0f9fa17d1d24b939537a434017f390c6604444c35a13360d6b1fc986baf40159b84275d37b883278df5064dd9eb0f29b0d325acc790c4b59672737dbbf3acb88f5e2f2d54c919cafd072272c494591d52e158993315e71e2ca60b1c74feff8f3d77842b415d4e71734a498206a5cd9315c87b23e583e25eb4ca97056b45c96856d":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e35c6ed98f64a6d5a648fcab8adb16331db32e5d15c74a40edf94c3dc4a4de792d190889f20f1e24ed12054a6b28798fcb42d1c548769b734c96373142092aed277603f4738df4dc1446586d0ec64da4fb60536db2ae17fc7e3c04bbfbbbd907bf117c08636fa16f95f51a6216934d3e34f85030f17bbbc5ba69144058aff081e0b19cf03c17195c5e888ba58f6fe0a02e5c3bda9719a7":"653df9730e14e03f2ffb3374d6b75295aa4a52c38540b2d501adc1eb659a4d7a050769a3d11d0d5d6f3efb734200ade241fdc271c0f5eeed85b4bf00b2327bc8":"9442a8ec48f87ebc81cc1273b03e528e7643c9e2fcc60ed85827d9341c5a36e5c76059baa8e9891df437e44c4047a266b46bcaaad3de1f1d4d3576defff080b791b013491636187fc45a930b70a533ed92abfd168f050df91b4c35d68d160a243ce589807a7d32661fc18b9547cdc0fd86d33acd349c98b34fb016ddd1bff23c58170e":0
+
+RSASSA-PSS Signature RSA-1024, SHA-224, Salt Length 20
+depends_on:MBEDTLS_SHA256_C
+pkcs1_rsassa_pss_sign:1024:"e5563b145db6ff5a16280d3e80eff02f181dbd03324ef247f596a4d4a7b8daa32b9934e3c7f4dcf6a3105462dec63839638618418b51db02693fabb4e6838725":"d2a4ec0fa2226cde82da77653b072cd098535d3e90ed4d7224dcb8cb8b9314768dc517e22d7c8fa13f253daa7465a79956098aa4cc3a6e35e8b1fcc4f97e774f":"bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda707a146b3b4e29989ddc660bd694865b932b71ca24a335cf4d339c719183e6222e4c9ea6875acd528a49ba21863fe08147c3a47e41990b51a03f77d22137f8d74c43a5a45f4e9e18a2d15db051dc89385db9cf8374b63a8cc88113710e6d8179075b7dc79ee76b":"010001":MBEDTLS_MD_SHA224:MBEDTLS_MD_SHA224:"1248f62a4389f42f7b4bb131053d6c88a994db2075b912ccbe3ea7dc611714f14e075c104858f2f6e6cfd6abdedf015a821d03608bf4eba3169a6725ec422cd9069498b5515a9608ae7cc30e3d2ecfc1db6825f3e996ce9a5092926bc1cf61aa42d7f240e6f7aa0edb38bf81aa929d66bb5d890018088458720d72d569247b0c":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"53d859c9f10abf1c00284a4b55bf2bd84d8e313b4f3c35b8dec7bc3afe39b9b8a155418ead1931895769ce2340be2091f2385bbcf10d9e92bcf5d0e2960d10e792e7d865c64e50d19ffa13e52817d7d8d8db34392c2374a2e9b69184f92a4ad9b1b8bae99ca614d204b65a438e38dbbfc8c7cc44ed5677af70ce6c4f951f0244":20:0
+
+RSASSA-PSS Signature RSA-1024, SHA-256, Salt Length 20
+depends_on:MBEDTLS_SHA256_C
+pkcs1_rsassa_pss_sign:1024:"e5563b145db6ff5a16280d3e80eff02f181dbd03324ef247f596a4d4a7b8daa32b9934e3c7f4dcf6a3105462dec63839638618418b51db02693fabb4e6838725":"d2a4ec0fa2226cde82da77653b072cd098535d3e90ed4d7224dcb8cb8b9314768dc517e22d7c8fa13f253daa7465a79956098aa4cc3a6e35e8b1fcc4f97e774f":"bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda707a146b3b4e29989ddc660bd694865b932b71ca24a335cf4d339c719183e6222e4c9ea6875acd528a49ba21863fe08147c3a47e41990b51a03f77d22137f8d74c43a5a45f4e9e18a2d15db051dc89385db9cf8374b63a8cc88113710e6d8179075b7dc79ee76b":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:"1248f62a4389f42f7b4bb131053d6c88a994db2075b912ccbe3ea7dc611714f14e075c104858f2f6e6cfd6abdedf015a821d03608bf4eba3169a6725ec422cd9069498b5515a9608ae7cc30e3d2ecfc1db6825f3e996ce9a5092926bc1cf61aa42d7f240e6f7aa0edb38bf81aa929d66bb5d890018088458720d72d569247b0c":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"7b1d37278e549898d4084e2210c4a9961edfe7b5963550cca1904248c8681513539017820f0e9bd074b9f8a067b9fefff7f1fa20bf2d0c75015ff020b2210cc7f79034fedf68e8d44a007abf4dd82c26e8b00393723aea15abfbc22941c8cf79481718c008da713fb8f54cb3fca890bde1137314334b9b0a18515bfa48e5ccd0":20:0
+
+RSASSA-PSS Signature RSA-1024, SHA-384, Salt Length 20
+depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+pkcs1_rsassa_pss_sign:1024:"e5563b145db6ff5a16280d3e80eff02f181dbd03324ef247f596a4d4a7b8daa32b9934e3c7f4dcf6a3105462dec63839638618418b51db02693fabb4e6838725":"d2a4ec0fa2226cde82da77653b072cd098535d3e90ed4d7224dcb8cb8b9314768dc517e22d7c8fa13f253daa7465a79956098aa4cc3a6e35e8b1fcc4f97e774f":"bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda707a146b3b4e29989ddc660bd694865b932b71ca24a335cf4d339c719183e6222e4c9ea6875acd528a49ba21863fe08147c3a47e41990b51a03f77d22137f8d74c43a5a45f4e9e18a2d15db051dc89385db9cf8374b63a8cc88113710e6d8179075b7dc79ee76b":"010001":MBEDTLS_MD_SHA384:MBEDTLS_MD_SHA384:"1248f62a4389f42f7b4bb131053d6c88a994db2075b912ccbe3ea7dc611714f14e075c104858f2f6e6cfd6abdedf015a821d03608bf4eba3169a6725ec422cd9069498b5515a9608ae7cc30e3d2ecfc1db6825f3e996ce9a5092926bc1cf61aa42d7f240e6f7aa0edb38bf81aa929d66bb5d890018088458720d72d569247b0c":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"8f16c807bef3ed6f74ee7ff5c360a5428c6c2f105178b58ff7d073e566dad6e7718d3129c768cd5a9666de2b6c947177b45709dc7cd0f43b0ba6fc75578e1196acc15ca3afe4a78c144cb6885c1cc815f7f98925bc04ad2ff20fc1068b045d9450e2a1dcf5a161ceabba2b0b66c7354fdb80fa1d729e5f976387f24a697a7e56":20:0
+
+RSASSA-PSS Signature RSA-1024, SHA-512, Salt Length 20
+depends_on:MBEDTLS_SHA512_C
+pkcs1_rsassa_pss_sign:1024:"e5563b145db6ff5a16280d3e80eff02f181dbd03324ef247f596a4d4a7b8daa32b9934e3c7f4dcf6a3105462dec63839638618418b51db02693fabb4e6838725":"d2a4ec0fa2226cde82da77653b072cd098535d3e90ed4d7224dcb8cb8b9314768dc517e22d7c8fa13f253daa7465a79956098aa4cc3a6e35e8b1fcc4f97e774f":"bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda707a146b3b4e29989ddc660bd694865b932b71ca24a335cf4d339c719183e6222e4c9ea6875acd528a49ba21863fe08147c3a47e41990b51a03f77d22137f8d74c43a5a45f4e9e18a2d15db051dc89385db9cf8374b63a8cc88113710e6d8179075b7dc79ee76b":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"1248f62a4389f42f7b4bb131053d6c88a994db2075b912ccbe3ea7dc611714f14e075c104858f2f6e6cfd6abdedf015a821d03608bf4eba3169a6725ec422cd9069498b5515a9608ae7cc30e3d2ecfc1db6825f3e996ce9a5092926bc1cf61aa42d7f240e6f7aa0edb38bf81aa929d66bb5d890018088458720d72d569247b0c":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"a833ba31634f8773e4fe6ea0c69e1a23766a939d34b32fc78b774b22e46a646c25e6e1062d234ed48b1aba0f830529ff6afc296cc8dc207bbc15391623beac5f6c3db557ca49d0e42c962de95b5ff548cff970f5c73f439cfe82d3907be60240f56b6a4259cc96dfd8fe02a0bfa26e0223f68214428fff0ae40162198cc5cbd1":20:0
+
+RSASSA-PSS Signature RSA-1536, SHA-224, Salt Length 20
+depends_on:MBEDTLS_SHA256_C
+pkcs1_rsassa_pss_sign:1536:"d3bde85f8718388de38c7e157c7200366224fd446ab590fb31dfd8135d3c561426b9966c164912bf0cd6537e877d59bb21fa3d3c5a6115ce971018db6be1033f14a4bb5849ccb070eb83838394e9d0851f3a33c43f48935a01c31c6fea72a6dd":"c342842ed13979fe948de3d31c21e5d4407db5f08524a1d04221500901e44b95274cbb84d80575ef1514332e27b0244a4154a8b561125439772a3d2fc9db73f19679cb92f9c5b5388154b0180aa339ff0bbec819da8a84d2bb617542cf097a8d":"a180ac4b5186df0b7b1cb7a95746a5af411efa16d1aed12468de15b747a0ff32c215dd08a99287b7788e91542d9059940e4b610f741cb9c7a86b4aa0b45a7b38450b6ea25070f98e70bb7833aecd1834a8e591bea207ec55d403c76213bd9f700ce25adb265ad383c443ed7a87a57d7e5c6495c32f51ae0cc8784352cfc56f2029cdd323393a153193f41f0408cdcd5b344d20942413bd97c3b0c04ab584f685b0e796ce9b5a0cf64441f00ee7586c62fe8442d522f7c6e3f314f84d557039b9":"010001":MBEDTLS_MD_SHA224:MBEDTLS_MD_SHA224:"11d9e77da9c83487f7de32110fb0ae0058d86f53e2f6244af9f59acefa90320d6514936534679c836b499cccf1dac6fb9e5cdf0c953b3a5ad44ae60409502694a7c321e33ad3db37f8ab64af98f350e1679966c198d19dc5db5a44463203802a006ffbc06315dbebc48af183ad0333f8da166d3892c033d338ac1a5d1db22815":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"1d85cec0da1a74825ab796480c6e1235808387106ac1411d68f313246c65040111d74a9a45ebae10ac7686fddf4a340c4f9d24685d708bbf7b0ab4563794f5f90e0405b5d7d56c998e996b8bde2b022ae45fecf29a21836fcf362042e77e13cbf67b8a4da3f1e378dfcab2143aa8b9a145c2ee7d593e31626baa47fe623a3c3f859bb63e9336e11c5ff398a6597623318e098230b09e553ba0a4257692a0bc0a1ce1c17b2d541b52d134627229c141d351c16f1bdfe33384a9e163ecaa13e2fa":20:0
+
+RSASSA-PSS Signature RSA-1536, SHA-256, Salt Length 20
+depends_on:MBEDTLS_SHA256_C
+pkcs1_rsassa_pss_sign:1536:"d3bde85f8718388de38c7e157c7200366224fd446ab590fb31dfd8135d3c561426b9966c164912bf0cd6537e877d59bb21fa3d3c5a6115ce971018db6be1033f14a4bb5849ccb070eb83838394e9d0851f3a33c43f48935a01c31c6fea72a6dd":"c342842ed13979fe948de3d31c21e5d4407db5f08524a1d04221500901e44b95274cbb84d80575ef1514332e27b0244a4154a8b561125439772a3d2fc9db73f19679cb92f9c5b5388154b0180aa339ff0bbec819da8a84d2bb617542cf097a8d":"a180ac4b5186df0b7b1cb7a95746a5af411efa16d1aed12468de15b747a0ff32c215dd08a99287b7788e91542d9059940e4b610f741cb9c7a86b4aa0b45a7b38450b6ea25070f98e70bb7833aecd1834a8e591bea207ec55d403c76213bd9f700ce25adb265ad383c443ed7a87a57d7e5c6495c32f51ae0cc8784352cfc56f2029cdd323393a153193f41f0408cdcd5b344d20942413bd97c3b0c04ab584f685b0e796ce9b5a0cf64441f00ee7586c62fe8442d522f7c6e3f314f84d557039b9":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:"b1e973f21303aa0011d416642cecd45511549b45bd22f910e44bdf7a94b960d8169db60d150786b801b465acb6269aa159fa2529837701e5a263a7f89c1ad3bcb5e18ab4b2775cc23eede79a8eb89c774105c60d8a4cc7be9028a5101566c65f565bf8cf337bb5859028a417fbc862408f1a83d918cad4047843e3ab49c4c229":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"8eb2ba2367b8f0b36b566c938b4d9948b4a0a87dd1c8300a160ec024ad0fa37174d1bba2ae6ee8c7fdbb4d172ac9615f1428599030a33515e2925a268b87c867242ccddcce6c9c03045eccbfee5eeb6e0ce2d89a9c51f40c1732927a6c7d283627dd87eca27270b117e658a3cc9d2ca7da46a76097213a7f3e2a58d7c9d306e796eee94809042bc6768d6cca4e003a40529bffa267914a232f315ddedd2768c60877bdcb05c8f2026179713084a0daf8b494959c347fb65a4414034d21c7a750":20:0
+
+RSASSA-PSS Signature RSA-1536, SHA-384, Salt Length 20
+depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+pkcs1_rsassa_pss_sign:1536:"d3bde85f8718388de38c7e157c7200366224fd446ab590fb31dfd8135d3c561426b9966c164912bf0cd6537e877d59bb21fa3d3c5a6115ce971018db6be1033f14a4bb5849ccb070eb83838394e9d0851f3a33c43f48935a01c31c6fea72a6dd":"c342842ed13979fe948de3d31c21e5d4407db5f08524a1d04221500901e44b95274cbb84d80575ef1514332e27b0244a4154a8b561125439772a3d2fc9db73f19679cb92f9c5b5388154b0180aa339ff0bbec819da8a84d2bb617542cf097a8d":"a180ac4b5186df0b7b1cb7a95746a5af411efa16d1aed12468de15b747a0ff32c215dd08a99287b7788e91542d9059940e4b610f741cb9c7a86b4aa0b45a7b38450b6ea25070f98e70bb7833aecd1834a8e591bea207ec55d403c76213bd9f700ce25adb265ad383c443ed7a87a57d7e5c6495c32f51ae0cc8784352cfc56f2029cdd323393a153193f41f0408cdcd5b344d20942413bd97c3b0c04ab584f685b0e796ce9b5a0cf64441f00ee7586c62fe8442d522f7c6e3f314f84d557039b9":"010001":MBEDTLS_MD_SHA384:MBEDTLS_MD_SHA384:"b1e973f21303aa0011d416642cecd45511549b45bd22f910e44bdf7a94b960d8169db60d150786b801b465acb6269aa159fa2529837701e5a263a7f89c1ad3bcb5e18ab4b2775cc23eede79a8eb89c774105c60d8a4cc7be9028a5101566c65f565bf8cf337bb5859028a417fbc862408f1a83d918cad4047843e3ab49c4c229":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"9fa4e64bab336017e19015ee7ea1e267bf426633fb2ac5f4d65bc754aba17f7a9f0f1ee2bf0a3b9f2dd354ed8eba596f5ca3e26495ef268658bd247474d3524b11a2953f591f8abb14ef4bcd44dadc36a41f9daef1bf88b7e441160278c8a39945524557b84ce5cdcb79eecbad63658e8470d8dc94b44aad1f04b05400ea04e5f959dd18f6f718311f6dfec98a7e1aaa7ba11771f61448b12d7901a2530e830dccc531fd0dbe222215b3f7b9dafa5fc20d5af15ab312b621d71b2106150a801b":20:0
+
+RSASSA-PSS Signature RSA-1536, SHA-512, Salt Length 20
+depends_on:MBEDTLS_SHA512_C
+pkcs1_rsassa_pss_sign:1536:"d3bde85f8718388de38c7e157c7200366224fd446ab590fb31dfd8135d3c561426b9966c164912bf0cd6537e877d59bb21fa3d3c5a6115ce971018db6be1033f14a4bb5849ccb070eb83838394e9d0851f3a33c43f48935a01c31c6fea72a6dd":"c342842ed13979fe948de3d31c21e5d4407db5f08524a1d04221500901e44b95274cbb84d80575ef1514332e27b0244a4154a8b561125439772a3d2fc9db73f19679cb92f9c5b5388154b0180aa339ff0bbec819da8a84d2bb617542cf097a8d":"a180ac4b5186df0b7b1cb7a95746a5af411efa16d1aed12468de15b747a0ff32c215dd08a99287b7788e91542d9059940e4b610f741cb9c7a86b4aa0b45a7b38450b6ea25070f98e70bb7833aecd1834a8e591bea207ec55d403c76213bd9f700ce25adb265ad383c443ed7a87a57d7e5c6495c32f51ae0cc8784352cfc56f2029cdd323393a153193f41f0408cdcd5b344d20942413bd97c3b0c04ab584f685b0e796ce9b5a0cf64441f00ee7586c62fe8442d522f7c6e3f314f84d557039b9":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"7224091b8f68b00d49d2ef1bfc5ca7352e852aee73a346768f7b80c8db0f9d24eab767c06b73adbb51808c523229ed56ede04fdd908dc73979264426bb801847c365b4d43be6b38d2ef21bf26d28dfb532eaa87004b3d494daaabfa18377429d45557abfc568cb6b265224637501843b45cabd0d96bc786ffc2e79a2fd9b240c":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"32e688063ea24ccb2ca998fb7091877c103ce6576b11a175bc896af454042a5731b91c1c58b4d8e38f0619f6ddc8ced6b5397545f9571a4c90767593d11c00b75eb58a0ae4932265f0ab1790be2c83dff65357a301b3b3e2ee2e3683afe0b4b35ee8b6e58a96b4009c98d8faba75f86ffb548f0501884f3528d8eabad353e28d0132c4c01fa3af5dec922f02eff22020481615e4cd35b9eccfd711cb3b0d65af95c0637d79aaa2433f2854de3560adb284248bac8cbd4717317011a5159c93ed":20:0
+
+RSASSA-PSS Signature RSA-2048, SHA-224, Salt Length 20
+depends_on:MBEDTLS_SHA256_C
+pkcs1_rsassa_pss_sign:2048:"f7b664093cabf8334b1c0ff824564db5c13f941a279733893a7e5abed536d2b51a2beac80730b5194a0c722f57354ce4b7db447ea3286b1cd1c754548ea3c91a0df1bde3ff70820b63ef3c74a0119671d14db3e2603868a0d607a81bf14f3f41f810c3a24bf52a94f9b694078a556194dd0cb36c56a91846d3569096c631b61f":"e0a1111aa114d5b1702e34d29565d65320e05c21d794f38572ad28a60b2ffe50d0dd3df3fb5a0eef048ec50e144bfe52be30ebf2eaceec9f110a600bb0c2bcacf6b4dabec09b9387c89a8fde19de5ceec780be38dca846d795f82608cf2844e9bced8d81da2d9258c3ef412154f9e590a158ea0ad9180ac6a798614ba3410937":"d95b71c9dfee453ba1b1a7de2c1f0b0a67579ee91d1d3ad97e481829b86edac750c48e12a8cdb026c82f273dafc222009f0db3b08b2db10a69c4b2dddaaeceac1b0c862682eef294e579f55aab871bc0a7eeabc923c9e80dddc22ec0a27002aee6a5ba66397f412bbaf5fb4eaf66a1a0f82eaf6827198caf49b347258b1283e8cbb10da2837f6ecc3490c728fe927f44455a6f194f3776bf79151d9ad7e2daf770b37d12627cc0c5fb62484f46258d9ce2c11b26256d09cb412f8d8f8f1fe91bb94ac27de6d26a83a8439e51b35dbee46b3b8ff991d667bb53eeee85ff1652c8981f141d47c8205791cef5b32d718ddc082ed0dd542826416b2271064ef437a9":"010001":MBEDTLS_MD_SHA224:MBEDTLS_MD_SHA224:"e2b81456c355c3f80a363a85cbf245e85a5ff2435e5548d627b5362242aaca4e4a2fa4c900d2a9319eb7fc7469df2a3586aaa4710e9b7362655c27a3c70210962391b1032dc37201af05951a1fc36baa77e5c888419ab4e8f1546380781468ea16e7254a70b08630e229efc016257210d61846d11ed8743276a5d4017e683813":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"cd1fe0acb89969ae139c178bfef1cc982993521b3a020ec847c89c0cc6c869d970f43f018d495b9e991457e7501a344c33c376fd2efcf05ad6eb2bd0b3c0e7cc3c88a4124398ca16585490a0817a36149cc82cdc01b20e9026261215dd06f9db4e13613c6a569c2187a0e00bc63c281149433ac7f061bd218e79f8eca9dd9c93ebc3cc013bf27aa0bf286e124593e76d3c7012f97ae1d0c4bf5823cf17fe76d505a54cef174add58ae616f47de825049e9916bf2ab7de4d443745763b0c314cfae3a6e57ad475cc5fae47cddcad7b526c2154a15f9ee8eab02f4c36f7a41d7a19b23c5996b627270ceb2c0dbed1a6b6dd2ff94868e073cb7b1a1fa3429e487ae":20:0
+
+RSASSA-PSS Signature RSA-2048, SHA-256, Salt Length 20
+depends_on:MBEDTLS_SHA256_C
+pkcs1_rsassa_pss_sign:2048:"f7b664093cabf8334b1c0ff824564db5c13f941a279733893a7e5abed536d2b51a2beac80730b5194a0c722f57354ce4b7db447ea3286b1cd1c754548ea3c91a0df1bde3ff70820b63ef3c74a0119671d14db3e2603868a0d607a81bf14f3f41f810c3a24bf52a94f9b694078a556194dd0cb36c56a91846d3569096c631b61f":"e0a1111aa114d5b1702e34d29565d65320e05c21d794f38572ad28a60b2ffe50d0dd3df3fb5a0eef048ec50e144bfe52be30ebf2eaceec9f110a600bb0c2bcacf6b4dabec09b9387c89a8fde19de5ceec780be38dca846d795f82608cf2844e9bced8d81da2d9258c3ef412154f9e590a158ea0ad9180ac6a798614ba3410937":"d95b71c9dfee453ba1b1a7de2c1f0b0a67579ee91d1d3ad97e481829b86edac750c48e12a8cdb026c82f273dafc222009f0db3b08b2db10a69c4b2dddaaeceac1b0c862682eef294e579f55aab871bc0a7eeabc923c9e80dddc22ec0a27002aee6a5ba66397f412bbaf5fb4eaf66a1a0f82eaf6827198caf49b347258b1283e8cbb10da2837f6ecc3490c728fe927f44455a6f194f3776bf79151d9ad7e2daf770b37d12627cc0c5fb62484f46258d9ce2c11b26256d09cb412f8d8f8f1fe91bb94ac27de6d26a83a8439e51b35dbee46b3b8ff991d667bb53eeee85ff1652c8981f141d47c8205791cef5b32d718ddc082ed0dd542826416b2271064ef437a9":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:"cd74ae6152d5fe5ce3d9073c921e861a24208f0c68477f49c825338e1ef877c0c977c1d2ffcb20e964db6fbedcccce449ec8538c8bfffce5bdece84762dac7f2cba69052c0c67226178a0ce185a2e050b3e1057e94411dd5f726878558e7d62afc8a81a93dcfdb5a2271466d32a8a4868af20fab2e13ca609d5a7710a8278aaf":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"6375755eff8d48afb3263b3b96988a2afd181ba061793ea009783bb1599d03944d987620a2668ac9714d6f2a21f7e5200d63923f42cb32e63301c8de58c70a203910640da967d03f4f6292f6cb199759822790c0c5bcfb1d4faa59465c3db2ea1fffd5e543335632b74745bf1e18473c0a8b4a89def6b27edf0d7d735ee13f887041c9d8a91e62186a9a1e0b1afb48e577f6887ca61b7c1bb26b4a8e2cc464a9af03444b3da5bed08b73f1262bd3d61f4c78f49fac6a3bfc9e8548b4bbe64cce6a6090fc480efd1f36c18c10bc09be9d957a79f707a10577a1bf6e9e2d4849693fa58d8877c8f1e55181955d6c2b94b1d6d9401b5fb80cc32b358934fec2aedb":20:0
+
+RSASSA-PSS Signature RSA-2048, SHA-384, Salt Length 20
+depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+pkcs1_rsassa_pss_sign:2048:"f7b664093cabf8334b1c0ff824564db5c13f941a279733893a7e5abed536d2b51a2beac80730b5194a0c722f57354ce4b7db447ea3286b1cd1c754548ea3c91a0df1bde3ff70820b63ef3c74a0119671d14db3e2603868a0d607a81bf14f3f41f810c3a24bf52a94f9b694078a556194dd0cb36c56a91846d3569096c631b61f":"e0a1111aa114d5b1702e34d29565d65320e05c21d794f38572ad28a60b2ffe50d0dd3df3fb5a0eef048ec50e144bfe52be30ebf2eaceec9f110a600bb0c2bcacf6b4dabec09b9387c89a8fde19de5ceec780be38dca846d795f82608cf2844e9bced8d81da2d9258c3ef412154f9e590a158ea0ad9180ac6a798614ba3410937":"d95b71c9dfee453ba1b1a7de2c1f0b0a67579ee91d1d3ad97e481829b86edac750c48e12a8cdb026c82f273dafc222009f0db3b08b2db10a69c4b2dddaaeceac1b0c862682eef294e579f55aab871bc0a7eeabc923c9e80dddc22ec0a27002aee6a5ba66397f412bbaf5fb4eaf66a1a0f82eaf6827198caf49b347258b1283e8cbb10da2837f6ecc3490c728fe927f44455a6f194f3776bf79151d9ad7e2daf770b37d12627cc0c5fb62484f46258d9ce2c11b26256d09cb412f8d8f8f1fe91bb94ac27de6d26a83a8439e51b35dbee46b3b8ff991d667bb53eeee85ff1652c8981f141d47c8205791cef5b32d718ddc082ed0dd542826416b2271064ef437a9":"010001":MBEDTLS_MD_SHA384:MBEDTLS_MD_SHA384:"4d41e81fe7729b79c1703ef84bfc5e842050213c31b188b02044f151ea22e026c9aefec05927626ff97910b67459bffde190e086c797dba285659c25f1854e17406b66ac2608e4763d9cd5daabcc1dc100f4738f5dbead59dbf43e532a92fd87792028cd963ea8f75781964c387dff384523e4413b4e853dea98e0c2dd7274df":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"b43d87deefa7df127a717f4065f831c58cd84bf78c916ba52ed32769abd541df52233b8583507c539b1d51e0437ab1a41e17fc1599b92aabdb5b040dc79027c60c9cc3ed3de36aeea28f20360635be5bf654d6c1b7fe6da77d0c45b9ea2802ad22eba182cbed95d33da7f78ac844f4891cebc0396caa2f8daaf55254fdafe98b5fe6c4dd3967d23ea99497060820e108e818cd0aa94e65770bde892c62233b96d87fe545162d6ba077f110274bddacb2a7cbf17d437bfe004b34c3ea24fb46e5ed9cce4de96b0694efd73832ec76e19e5a25c49c5843393ce6b919ea35e4d264e0a0855f518a63c008c183798ca612cd8f75688a09210413e0a23cafcf2d4158":20:0
+
+RSASSA-PSS Signature RSA-2048, SHA-512, Salt Length 20
+depends_on:MBEDTLS_SHA512_C
+pkcs1_rsassa_pss_sign:2048:"f7b664093cabf8334b1c0ff824564db5c13f941a279733893a7e5abed536d2b51a2beac80730b5194a0c722f57354ce4b7db447ea3286b1cd1c754548ea3c91a0df1bde3ff70820b63ef3c74a0119671d14db3e2603868a0d607a81bf14f3f41f810c3a24bf52a94f9b694078a556194dd0cb36c56a91846d3569096c631b61f":"e0a1111aa114d5b1702e34d29565d65320e05c21d794f38572ad28a60b2ffe50d0dd3df3fb5a0eef048ec50e144bfe52be30ebf2eaceec9f110a600bb0c2bcacf6b4dabec09b9387c89a8fde19de5ceec780be38dca846d795f82608cf2844e9bced8d81da2d9258c3ef412154f9e590a158ea0ad9180ac6a798614ba3410937":"d95b71c9dfee453ba1b1a7de2c1f0b0a67579ee91d1d3ad97e481829b86edac750c48e12a8cdb026c82f273dafc222009f0db3b08b2db10a69c4b2dddaaeceac1b0c862682eef294e579f55aab871bc0a7eeabc923c9e80dddc22ec0a27002aee6a5ba66397f412bbaf5fb4eaf66a1a0f82eaf6827198caf49b347258b1283e8cbb10da2837f6ecc3490c728fe927f44455a6f194f3776bf79151d9ad7e2daf770b37d12627cc0c5fb62484f46258d9ce2c11b26256d09cb412f8d8f8f1fe91bb94ac27de6d26a83a8439e51b35dbee46b3b8ff991d667bb53eeee85ff1652c8981f141d47c8205791cef5b32d718ddc082ed0dd542826416b2271064ef437a9":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"252433d4b72a33e1aa444aa9680454e9cdab208637ec2173dcf366d561a6cc65a82b7316e9aa6ef90454bf5d15a4823a49e468d0f1f4678bd547b02acb2ee22088597d3ab59a998346edd86507b6991077496e20daafd1798aa812768eec94446db6398844831b4817177d0865c20133ffe11bbd1aa7c507a21e7403d1684b98":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"2cdb0d5ea5f0aad1f7af8108bff56eec5c0dcd0522c5dc6ae4c6e0f66821cdf698ccfeace65fd6e47f95febd879e580e5ee648972cc265f9a117fc720db4f2545a432eae24a367b0aaa70a011ac8fdec94a95c3cd48cfa7102de8dc26c877e974688b3919de6cf06e27028995ac85da88cb3851a5761e17f215e5c593e13e481088c7d747ecb34d3ce61a5b56eb2a65be5363363294eb365f83c4c709644d857e2ccb14a5851724420fc81178144ef3f9e1138b5750eb7196eba3319d799c3494a7e399115a62b1ca4f1d5da079b495d35fd651a1de78d54000b06bdd3122d7404013f2ed8fdf8a7d012f9812b8e4c2e0b24192d5f899d70a3cc5c7e08c81be7":20:0
+
+RSASSA-PSS Signature RSA-3072, SHA-224, Salt Length 20
+depends_on:MBEDTLS_SHA256_C
+pkcs1_rsassa_pss_sign:3072:"ca7b50c5f65f2115fea7691f7d90c124866e774e68e9eb89306538956fc217593d46017b7dd7942d636e384a34c802a14d5fd9916798d7d6193ef1a29e2fdbefd955261496d8ac9713922d43bfc43a7a410752ccbc854cc85268f411e793f9b5279007bbcaca30fb16fd9033a6ea31566b4f2c27f0161107e2cd890bcf563a522ee0eb96a016e9007595a94172a4aeded11fadcb8ab5f03cd154f8b8e0e0666ff62b1ccda02599ea44bbfcfaea541a5ac26bf267a56a8177a50f6b87b460a54d":"c591723042d4b8737f4ef9dfeb40c6d62d439ee8688158a4be24c0ad130f851113cc53d776c63cd782b95ccfd266bdb2578b78439c121de34e8955a7fbd2c6ae1a1c37b24c12f5dce15175dd9e203a3abd5bf9e736b1fc183d10c4540c5cf2cbe26768e94c1eab2ba3008b32d6d50716699c6bfcbec5bbeb94a054dbcd16d10f74972ca5fe53256cd0ade8f502eceaed633414a9bdb623035a234f65c6662a23d792cc0eeb21a1f55ebca26ffa1c56c96fbb7d870fc3ffb181de8398238ab1b5":"9c43ef522cab18022297d3d70fa491d03b975b844b76cedba35d8d885ddb2825e31fd5c101bd9e9a215520bb8cdddeb6ab2cf2dc86065179477d80f733016929d7334cdfdf818c1378a4b9428fa1ee2e525321f905d0b949d3abc9e93d3f30b077795338bd55c28a1ced134bb2d575bfa44b2fd8cf1d5c54168a12a1d6c511f62ca973cdb704c233487e1fd39e5adc8870af352ec3c6a6a64152fc82a1c16ecc43d1d5817f76a1b46a5fab9db8923311edd3cc032fed7eb6252e77db69d7bf9ee35dc4ddd0fbdb9a76afe25a82f4495aa4f072cef9b1247cb368bcc8677565a47095242702e6341281f506805e20e8c89e9af28adff21c804c70cab10ee2fe5212ec07987d13e7d4b60529611e4d33a062d724cdfb16cdc48b964ba07dfa2620d5a8805d0be93380850c66f3fada059802a5946bfe3b0b10e19a8289ec01f6514abb883bb53c49dadbba42d412ea264c8a5122fda1ea9b742289642b0ea34ceb76ae8256a97845d37594cfbff8c7a4430176223bacc3bef395ceda13fd211c71":"010001":MBEDTLS_MD_SHA224:MBEDTLS_MD_SHA224:"1e4f71d67b8041845a6741a2e84b313f035f04d64e8c922e84718d7f0ca9b6d6ce4c50ba46b8d510d691e93c61068c89155693cb8893594307a7b2c22b942011ac004a917af0a91f0ad4853aeec42068a90931d5c1df933e16793f0d714678c6607345a142b124799e38fde4b90b55a4677ec43e21f6a9e858f11ca8094624bb":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"7171c74df24272dfe6b34db78f24507a68062bd791f68796d5001be354de6fddab81e9252e151884f4cc1f3cd3e7760e263c0c34e63c557eb32c8336e0cef40855c5e279dbba3170da5a14ac60e4cc8d402633a383b88709f3306fb02708e39f3039e7e614edcb89609c8c71137de5211659a41e9e5682cfe0463f3bc97558d3bf77bd798976f09db69153123923835ac9bbd7648c2773e38b5228640fde6df005e9f44819eca31f41ccddbd45d61ae7e1ed0640f0736f52bf5fc1c62f5430de6a96d5aabccfcfef508ac299c7f3f0f7d222ef1f19b288273690b3275b68f874301afa95d243316284ed117bded69da11f5ce1435dd67717bae82ed468ff1b6ac7f2483397d310ffe91775189f671a82b493039d8c233830d20e290bc9be880a47f0b36bf2e1da2c1f23dafeb9f42d9f084feb808a98e894e8501937ba932594a6d202e20a0afddcef8fa48c1682d3179edebf8ea44ea1216a2f55c305cdf487249010909fa8a21d9ba9e3dbbeec046a823922390b7d902d77ec176bb447b05d":20:0
+
+RSASSA-PSS Signature RSA-3072, SHA-256, Salt Length 20
+depends_on:MBEDTLS_SHA256_C
+pkcs1_rsassa_pss_sign:3072:"ca7b50c5f65f2115fea7691f7d90c124866e774e68e9eb89306538956fc217593d46017b7dd7942d636e384a34c802a14d5fd9916798d7d6193ef1a29e2fdbefd955261496d8ac9713922d43bfc43a7a410752ccbc854cc85268f411e793f9b5279007bbcaca30fb16fd9033a6ea31566b4f2c27f0161107e2cd890bcf563a522ee0eb96a016e9007595a94172a4aeded11fadcb8ab5f03cd154f8b8e0e0666ff62b1ccda02599ea44bbfcfaea541a5ac26bf267a56a8177a50f6b87b460a54d":"c591723042d4b8737f4ef9dfeb40c6d62d439ee8688158a4be24c0ad130f851113cc53d776c63cd782b95ccfd266bdb2578b78439c121de34e8955a7fbd2c6ae1a1c37b24c12f5dce15175dd9e203a3abd5bf9e736b1fc183d10c4540c5cf2cbe26768e94c1eab2ba3008b32d6d50716699c6bfcbec5bbeb94a054dbcd16d10f74972ca5fe53256cd0ade8f502eceaed633414a9bdb623035a234f65c6662a23d792cc0eeb21a1f55ebca26ffa1c56c96fbb7d870fc3ffb181de8398238ab1b5":"9c43ef522cab18022297d3d70fa491d03b975b844b76cedba35d8d885ddb2825e31fd5c101bd9e9a215520bb8cdddeb6ab2cf2dc86065179477d80f733016929d7334cdfdf818c1378a4b9428fa1ee2e525321f905d0b949d3abc9e93d3f30b077795338bd55c28a1ced134bb2d575bfa44b2fd8cf1d5c54168a12a1d6c511f62ca973cdb704c233487e1fd39e5adc8870af352ec3c6a6a64152fc82a1c16ecc43d1d5817f76a1b46a5fab9db8923311edd3cc032fed7eb6252e77db69d7bf9ee35dc4ddd0fbdb9a76afe25a82f4495aa4f072cef9b1247cb368bcc8677565a47095242702e6341281f506805e20e8c89e9af28adff21c804c70cab10ee2fe5212ec07987d13e7d4b60529611e4d33a062d724cdfb16cdc48b964ba07dfa2620d5a8805d0be93380850c66f3fada059802a5946bfe3b0b10e19a8289ec01f6514abb883bb53c49dadbba42d412ea264c8a5122fda1ea9b742289642b0ea34ceb76ae8256a97845d37594cfbff8c7a4430176223bacc3bef395ceda13fd211c71":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:"e2f6dfa5014fee6b1b04108682e85619ded7c4647faf4ae8f19cf6cbd199677fe033859f56906f1979b1b5926df4c8064eddaeaf7c15fa2936b3fcd36bbb3578cce40d2f269fc97fef54b7c71fefabdd419baff6c9cdf7c6a88513e81ed1687fcf92e11e1a82e2e5a6767eed3de1e9e7de9a30ff0ddf27076e99a3d192e1eadc":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"3a0622ddff5a0c1f5b545d684054e46211786a2e40627e0cb6795ea0d176f3c97e6536fb64c5eca7b28b7ac52e48e3d50b916d2fccb87d70cd8eda7c15c2308734254716e5b400592cc2e5e033ba27866cb14fefbdcbc35d5d85d4eee8ba6bc2da995e8ebcc27d50c48aa988bf45fde27311a9e2ec029d0fa6fa6d3efea460fc1a90e443d807d209a4c06bf3022d529ab2e4a877325fcccb3f86ac16200ab95628bf0c1c8c70f6fe1a9f288bbc0162a392f40ad1109cdbbaf03d9b2d514a60983874350be9aef886c3c481a66325f137aecb4c82a8a73046dbc1dd8598ffbdb828a3d638f9dd8139a768dcd8d30d79740ef345c1644d03e6fb86a46367f6d82a7a819057ae490e1b100b5842ed385845f379101e37ce604531c61de423df66200d45b7229662fd0ec3572593b09a5213ec14c1d7b2338ca9c763c0d18946f04eaaf57ea2ebc79e093f2fd4c64cb1c1a7f0e888dc2d87a15eb769f56dc180cfe1597cc3e4e1811d4e27852fa188c8fec4fc917d4724d33ce5f3211895cf7e8b8c":20:0
+
+RSASSA-PSS Signature RSA-3072, SHA-384, Salt Length 20
+depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+pkcs1_rsassa_pss_sign:3072:"ca7b50c5f65f2115fea7691f7d90c124866e774e68e9eb89306538956fc217593d46017b7dd7942d636e384a34c802a14d5fd9916798d7d6193ef1a29e2fdbefd955261496d8ac9713922d43bfc43a7a410752ccbc854cc85268f411e793f9b5279007bbcaca30fb16fd9033a6ea31566b4f2c27f0161107e2cd890bcf563a522ee0eb96a016e9007595a94172a4aeded11fadcb8ab5f03cd154f8b8e0e0666ff62b1ccda02599ea44bbfcfaea541a5ac26bf267a56a8177a50f6b87b460a54d":"c591723042d4b8737f4ef9dfeb40c6d62d439ee8688158a4be24c0ad130f851113cc53d776c63cd782b95ccfd266bdb2578b78439c121de34e8955a7fbd2c6ae1a1c37b24c12f5dce15175dd9e203a3abd5bf9e736b1fc183d10c4540c5cf2cbe26768e94c1eab2ba3008b32d6d50716699c6bfcbec5bbeb94a054dbcd16d10f74972ca5fe53256cd0ade8f502eceaed633414a9bdb623035a234f65c6662a23d792cc0eeb21a1f55ebca26ffa1c56c96fbb7d870fc3ffb181de8398238ab1b5":"9c43ef522cab18022297d3d70fa491d03b975b844b76cedba35d8d885ddb2825e31fd5c101bd9e9a215520bb8cdddeb6ab2cf2dc86065179477d80f733016929d7334cdfdf818c1378a4b9428fa1ee2e525321f905d0b949d3abc9e93d3f30b077795338bd55c28a1ced134bb2d575bfa44b2fd8cf1d5c54168a12a1d6c511f62ca973cdb704c233487e1fd39e5adc8870af352ec3c6a6a64152fc82a1c16ecc43d1d5817f76a1b46a5fab9db8923311edd3cc032fed7eb6252e77db69d7bf9ee35dc4ddd0fbdb9a76afe25a82f4495aa4f072cef9b1247cb368bcc8677565a47095242702e6341281f506805e20e8c89e9af28adff21c804c70cab10ee2fe5212ec07987d13e7d4b60529611e4d33a062d724cdfb16cdc48b964ba07dfa2620d5a8805d0be93380850c66f3fada059802a5946bfe3b0b10e19a8289ec01f6514abb883bb53c49dadbba42d412ea264c8a5122fda1ea9b742289642b0ea34ceb76ae8256a97845d37594cfbff8c7a4430176223bacc3bef395ceda13fd211c71":"010001":MBEDTLS_MD_SHA384:MBEDTLS_MD_SHA384:"692acaaf5e277cdd4b3fdc0a1ff1785bfd28a3a8ec1bc97fd072ff6c99aade77baba92efdcf72e66d43542fdd32fb0e2dd29bb167dd36174b671ebef3c39c21be5fc84ef5a0957c9124f7eb281c12ae38cff9289413245c6c537bff88d013b3dd138c9373e26a00cecd4b5b18f708d69f1f24f88a0001d7de30ea40ff3c9f2e7":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"3f90aeabfa9a5f00e241f3f65dfe61baf67c1356353042c3566edacb11c7649737e5adf94cfb05f2619aecc8895db45190fbdf35dab01144e207b6f0923927a6148d3f16eaad05e73bccb562dc087e2d82db3dce130a83e8303bd7c3447b3ae4d3700d4763ba6981d82618ac82a6e66423f294781a59b20cc978c79e2d5c103bfb9d47119294c3c85b1d3c45a36897d42e183514cc8edbbfa1be9ef17b78280b5b6214dad79d60db057f22506515b6843ce7d4dd6bd861a889b36164c325147baeed714d7a3f55ae51ef6e6d4ae9e862d677caba1a2df369c23d3ffe33dd42fe707e1fd8ba6283aaa0b570353b48a8e39ff72a09f700e024150ce87c044a3ec745b212ae81aa5743b981a8bb95deb6b3e15c2487f7900178d5840f8e794662706dcdb19bc0bdd56cb7fdf0e21d10b03adac41b749f31bd3e7c4d07d5d4ec8e79d424812b6e83f1c7b59779e58029f9b07da3e77795fcff6ae8bb098b1c00d1d2a5bc0cb005ef3d8aab63ddd883d38bacdc64307e911c6e51946744f361fe978d":20:0
+
+RSASSA-PSS Signature RSA-3072, SHA-512, Salt Length 20
+depends_on:MBEDTLS_SHA512_C
+pkcs1_rsassa_pss_sign:3072:"ca7b50c5f65f2115fea7691f7d90c124866e774e68e9eb89306538956fc217593d46017b7dd7942d636e384a34c802a14d5fd9916798d7d6193ef1a29e2fdbefd955261496d8ac9713922d43bfc43a7a410752ccbc854cc85268f411e793f9b5279007bbcaca30fb16fd9033a6ea31566b4f2c27f0161107e2cd890bcf563a522ee0eb96a016e9007595a94172a4aeded11fadcb8ab5f03cd154f8b8e0e0666ff62b1ccda02599ea44bbfcfaea541a5ac26bf267a56a8177a50f6b87b460a54d":"c591723042d4b8737f4ef9dfeb40c6d62d439ee8688158a4be24c0ad130f851113cc53d776c63cd782b95ccfd266bdb2578b78439c121de34e8955a7fbd2c6ae1a1c37b24c12f5dce15175dd9e203a3abd5bf9e736b1fc183d10c4540c5cf2cbe26768e94c1eab2ba3008b32d6d50716699c6bfcbec5bbeb94a054dbcd16d10f74972ca5fe53256cd0ade8f502eceaed633414a9bdb623035a234f65c6662a23d792cc0eeb21a1f55ebca26ffa1c56c96fbb7d870fc3ffb181de8398238ab1b5":"9c43ef522cab18022297d3d70fa491d03b975b844b76cedba35d8d885ddb2825e31fd5c101bd9e9a215520bb8cdddeb6ab2cf2dc86065179477d80f733016929d7334cdfdf818c1378a4b9428fa1ee2e525321f905d0b949d3abc9e93d3f30b077795338bd55c28a1ced134bb2d575bfa44b2fd8cf1d5c54168a12a1d6c511f62ca973cdb704c233487e1fd39e5adc8870af352ec3c6a6a64152fc82a1c16ecc43d1d5817f76a1b46a5fab9db8923311edd3cc032fed7eb6252e77db69d7bf9ee35dc4ddd0fbdb9a76afe25a82f4495aa4f072cef9b1247cb368bcc8677565a47095242702e6341281f506805e20e8c89e9af28adff21c804c70cab10ee2fe5212ec07987d13e7d4b60529611e4d33a062d724cdfb16cdc48b964ba07dfa2620d5a8805d0be93380850c66f3fada059802a5946bfe3b0b10e19a8289ec01f6514abb883bb53c49dadbba42d412ea264c8a5122fda1ea9b742289642b0ea34ceb76ae8256a97845d37594cfbff8c7a4430176223bacc3bef395ceda13fd211c71":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"e990c8835f18b18562323ba5096a4e7b99bd84899e5cdd1f3badb47cbf93f13678ef81dccc6703d98566c49b6d63eef51b67fcc20cc971ccf63ccaec580db17256a573c6c455b4508153629606ffe7a43e6ba3b1991b99ff5c0968033bec7ec629ba888b6f6c2cb2fb01fbdcfbc5a150abd35f9e6bd9bc82151b770a8dbbbffb":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"607b7731ecb232f9b8e9ea03be28cc1e948acc3ec12a1222ba0f63935440c3effeaf460d7066d260d174d0ed18a9193550000c2fa0119712fb1ab1e27b4e6f5f84be9b63a1ede17a01174060e2d9e46121cc5d10515a342a26649539341eb1b44b82e346a0102e7ca45be3149b5f1444bd7fdf43da441c59deb37da9a223bcd7a8244237bb5404ea532eb470e80891c0fe9403d12734100284e99cfd96de2ab4058529d91bf348c6cbdb7fcfeea3f9925e93efd6adb3ef6946008738f4577a49c42ac0203a2d982fd77cb421ae030b81b97dd04490605179626903471cf68835dd5e4ac41acfe54e048878df89db9c2de5f1e822266c325e0be0991c7f18cd3de4b2110e14f56100e45f8ba19edf917150c2074f379293f73cb587ff77ad63e4cbec9eeaed77ca90261b2813ae8e6533b09b223a68abe2beeec888088ff91fea5c63de3b55238aef018c368f98651572bc7b8cf3d14c15b24bb5534ae07a6c4c9d5ecd0b86961b550859036ba6fa8e50d06228d89bcc943581b26e302795d1e3":20:0
+
+RSASSA-PSS Signature RSA-4096, SHA-224, Salt Length 20
+depends_on:MBEDTLS_SHA256_C
+pkcs1_rsassa_pss_sign:4096:"f00102d29990fb36bf66dcab57fa4e05745e307c031fe6acb86df4e0487bcb8fd929e227b6e1090a48befbd642f432ea1b6cff26c1aed9f18c04f68170dc1857786faa086fa00b43e0272a1042ee53566cbb48a04f109420e3501cf56222f7a9b51a7ffe2b97a8ea71e791e0bfb259514f953473130dbe41a7978fc385150f8f78748b90538c8906e24759ce2106ede4ac40eb26776cff5abf227673407d0910a9c3f6464d48569f1b8faa62d0b3b7156b059441e1f701751339fa8dfd218c343050e8a88293b6be0407ab2534815eee742c574cbb7469998b23439a23ca4104f563883f5a35ab88d789dcba4073aebf2e1855abb839908874c1a10f150d56b7":"dda4491b56bdad20f032c8a61bc326995ee7353c3f1b4c1e677aeb4b028e45bf6566fb20f3e82bac4169a970787b8cbafb06edd24a9bebe52704f242f7203ec96aee9a9f5ee76e270191f82e3651da663b80d51688c2d40ffa932ce2302322503664ae0260617e7b79d13e4a1dec1784647d7571c1390e86294f20937740f93e0ff1bdb0c1ff648ef152022bf5f54bfcbf24564cbca7a130fb5f56be921fcc7a3ebd51114968274ab13bcc3986137eb6949eff0d42b596f7baec56c94a67a2ec0aeff18dc044cf9500b525dc98efb9992b13f81e1b0bf4c2ac1da91e67c0847cbdaf268ced549c2febd08b661140af9bf45458d13d4717eb61de86b555856ad5":"cfcae49f88b80dc12186d53c57162dbecba6e348094f9fb3743e39d99d5355d87e3efca9d488d39d705671e58634309cbd7cf53fccd52d9a84edb99ffdad0680e9ec826d625728370717b39321c7d4b6882785cf6884275f6c7b6d681bfa710593679e99b67d5bc28121dd603617dc8cfdb2557c2a04533893f593f0f7e59cbe6d46623d22642a7161a4c685b293c7edcc9aaec48e3810ec74a884a41108610d000b591fbf5da44b5501e63781264edf3c73706321ecf44d0e14b5932a2d69ca3d180c5cee86b4ccad850c766e0beb5f20e6b142055d551aeb453bd099eac67eb92cf13e34ef0d0e34fc599a6e5d4d14f74e08190c66c66ad3473de9ae8f53dd2c1c0c41f4b4a8d4690f4b77354c76e05ab76b7a6c7c9edf0955fee799a2bb42c86c6a06631398d38cceb71ec9aaa9a0fb83850f62342f3f781f9d453229b1a709bbce83a44c225ebffd4f518f94a7935f4669f65d02ff3defbbd1d5efd9191365808cdf9460371ede1eae735af03f21431239d5cd57cc0cc88fb3965d187eba98359409aaa944a7af8e85e20b67c43c82e78fa967fc0d629bcd7483d17dcaa25915571a15c3f0c730e81095139d71a28858dd9d83b65bf9c9273a8a40b12a2c87107a71f984818f7dc766374d31b4c3a1d284adb2a17f8ac85dbe3f58cf78b14c0fdce00a79daf348aa0557290ef5f9dd305c15fa73d40c6822b75fda13ec43":"010001":MBEDTLS_MD_SHA224:MBEDTLS_MD_SHA224:"11bafee5c6534fe14d973d2f60a674983434ee03ace7c4f1cd00444b723e455d40ffb722dda97ec25d488159fd79fdfa148620f446d2d353fb78d7aa0f2f1310cc712c6915dc57e7e3d86bd0f67a3b81c4a822b3b67edffd93f1a39a3cb2696d9b558642d6b38157c88d241bb172d3352ce21dc862b391f57eb4d3a26191ef7a":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"3742d8a9627e2e10145c31a3548977f87f8019b1d9093c42f806c8df5ef7fad8330e2a05846c346cb64d9e8af2cd3806eb0df40cd097b3f8841525786ed53746498aa565f8945cf55e24944e8e3d86eb219f65c3385e1e7d45fe3a403773f3057bf22839d5903cd64c95a417c00b429ee068f0fe8ec17305a122979cabee8c3ad31b597da7c71fa1db3da842f7f7048f4396e1768197ccd84c5d9a0450d66f0bc88da7605cc8cdfe52bce60793704dafea504349ff14c481bea73dd761c848387d12f2d1b9227a959fec8b9eef0e9780cb6a427af946597d7e6059a07d50e878d7ae14eed8b571ac88e1c5d1a00d16c0de1c5148ec5781036676c6355e0cbca06346eebaf6c7de938cedd47a244f908ba1189bfbd97bd2667e8eba95e007a64b165dbfc4bf35878cd606732fd469f922ec141e5bc6a7d5c1875233cff612d336c28466c271764ef94e9c07e701923f1f68f39e2f003487dbe41d5505862eb4e90402e50f7b3cb918ef3eff893d0f00b203e2a511cfea4ca54c043ed0598d022c947cad5129fc47f5e79db97a0eea5afd7bb801a367a7bb8d929de1c12a54865e1e183ed926bb8da9d454c7a52b30cfcfe9ed3479799276f4a65b30f430e61fcf520e46e4eb9bea59ba064e7c9c72c9b58bf4ff633897d3ea46d989cec31ce4fc32e46e5a3d1805c35a30b387fb77afe20dba19be37252e40b252d346b69d3cf2":20:0
+
+RSASSA-PSS Signature RSA-4096, SHA-256, Salt Length 20
+depends_on:MBEDTLS_SHA256_C
+pkcs1_rsassa_pss_sign:4096:"f00102d29990fb36bf66dcab57fa4e05745e307c031fe6acb86df4e0487bcb8fd929e227b6e1090a48befbd642f432ea1b6cff26c1aed9f18c04f68170dc1857786faa086fa00b43e0272a1042ee53566cbb48a04f109420e3501cf56222f7a9b51a7ffe2b97a8ea71e791e0bfb259514f953473130dbe41a7978fc385150f8f78748b90538c8906e24759ce2106ede4ac40eb26776cff5abf227673407d0910a9c3f6464d48569f1b8faa62d0b3b7156b059441e1f701751339fa8dfd218c343050e8a88293b6be0407ab2534815eee742c574cbb7469998b23439a23ca4104f563883f5a35ab88d789dcba4073aebf2e1855abb839908874c1a10f150d56b7":"dda4491b56bdad20f032c8a61bc326995ee7353c3f1b4c1e677aeb4b028e45bf6566fb20f3e82bac4169a970787b8cbafb06edd24a9bebe52704f242f7203ec96aee9a9f5ee76e270191f82e3651da663b80d51688c2d40ffa932ce2302322503664ae0260617e7b79d13e4a1dec1784647d7571c1390e86294f20937740f93e0ff1bdb0c1ff648ef152022bf5f54bfcbf24564cbca7a130fb5f56be921fcc7a3ebd51114968274ab13bcc3986137eb6949eff0d42b596f7baec56c94a67a2ec0aeff18dc044cf9500b525dc98efb9992b13f81e1b0bf4c2ac1da91e67c0847cbdaf268ced549c2febd08b661140af9bf45458d13d4717eb61de86b555856ad5":"cfcae49f88b80dc12186d53c57162dbecba6e348094f9fb3743e39d99d5355d87e3efca9d488d39d705671e58634309cbd7cf53fccd52d9a84edb99ffdad0680e9ec826d625728370717b39321c7d4b6882785cf6884275f6c7b6d681bfa710593679e99b67d5bc28121dd603617dc8cfdb2557c2a04533893f593f0f7e59cbe6d46623d22642a7161a4c685b293c7edcc9aaec48e3810ec74a884a41108610d000b591fbf5da44b5501e63781264edf3c73706321ecf44d0e14b5932a2d69ca3d180c5cee86b4ccad850c766e0beb5f20e6b142055d551aeb453bd099eac67eb92cf13e34ef0d0e34fc599a6e5d4d14f74e08190c66c66ad3473de9ae8f53dd2c1c0c41f4b4a8d4690f4b77354c76e05ab76b7a6c7c9edf0955fee799a2bb42c86c6a06631398d38cceb71ec9aaa9a0fb83850f62342f3f781f9d453229b1a709bbce83a44c225ebffd4f518f94a7935f4669f65d02ff3defbbd1d5efd9191365808cdf9460371ede1eae735af03f21431239d5cd57cc0cc88fb3965d187eba98359409aaa944a7af8e85e20b67c43c82e78fa967fc0d629bcd7483d17dcaa25915571a15c3f0c730e81095139d71a28858dd9d83b65bf9c9273a8a40b12a2c87107a71f984818f7dc766374d31b4c3a1d284adb2a17f8ac85dbe3f58cf78b14c0fdce00a79daf348aa0557290ef5f9dd305c15fa73d40c6822b75fda13ec43":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:"466d2621acc8a91c729334f1ca433bdb5605058d4851f86cc8c217fb9625c996f0d0dc64b635c987ccb63a95c0bbc94cac020b815e37cd5ab7c59dbd51eb8d0864123303eb5ef413028383b093daa41831b4364544ee701d67c56bea0eece0096cdc34e6946cb128dea117288cc753a8adc08ec2429d691ea06b8768154f4d01":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"2e512f73d198e623afe019bd4cea9192ff8b24ab555099d31bd52d705fc808229a269bf749c8061a3dc7ffae9ef7c6bdcd8c34910f92f0a0fcd6d73017ca3388ca5e99a1735e005ff5d5eade3ec0ea0c2436f0e78b197c2d999ba4351b9e37a09195504b63a42762bea22d307a0328fc9c80acdc28fc8f4050e25fbd5890233028f97ea3a2669ff4d5f4232c1e48571499af28ed6f5a92e7936de39d913e12c5cef51e25f90a1e903f3f60a6a9cddbc56564b146aca6af6236b899c2cb7223a6941f0beaa3aa787b2333e4f3e66b334b99b90825153ebd0095f27691880f44e4e77135f26df376e261adfe0d8354cfa15b49138d624d9f62a9751221ee0598097891c9864ad3651e89723bc9ec6086f571e199619ceb6720ab5a4998254cb807dce75a5a5203d38a9f5d56adee4239ff50cefe3e927eba91de7e1f8e1ae8b0505c077788372af7d8ef00735cc531fd46dbe86702ac49171f0a921f4626442ae960e972a5594ee3bcbfbf687cd96ed300aa9df1b9487607b5bae0f1abecbc1d2291fe93b9f8a091ffac8469b0f00ba561f0628f5e004ed1fd8713650e147c4b2cab7f4d69a4ad57b145c1e5e4c1412e86fbbda5a6096f66293203207e35098bf94dafff75ed094d10e6034cd22179d94655004fa4bf4de774807b6f5cd27d90255468cf01db7b6f82607df597f72d1f9c9c91d17740a14a4816ae65e63fde480d":20:0
+
+RSASSA-PSS Signature RSA-4096, SHA-384, Salt Length 20
+depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+pkcs1_rsassa_pss_sign:4096:"f00102d29990fb36bf66dcab57fa4e05745e307c031fe6acb86df4e0487bcb8fd929e227b6e1090a48befbd642f432ea1b6cff26c1aed9f18c04f68170dc1857786faa086fa00b43e0272a1042ee53566cbb48a04f109420e3501cf56222f7a9b51a7ffe2b97a8ea71e791e0bfb259514f953473130dbe41a7978fc385150f8f78748b90538c8906e24759ce2106ede4ac40eb26776cff5abf227673407d0910a9c3f6464d48569f1b8faa62d0b3b7156b059441e1f701751339fa8dfd218c343050e8a88293b6be0407ab2534815eee742c574cbb7469998b23439a23ca4104f563883f5a35ab88d789dcba4073aebf2e1855abb839908874c1a10f150d56b7":"dda4491b56bdad20f032c8a61bc326995ee7353c3f1b4c1e677aeb4b028e45bf6566fb20f3e82bac4169a970787b8cbafb06edd24a9bebe52704f242f7203ec96aee9a9f5ee76e270191f82e3651da663b80d51688c2d40ffa932ce2302322503664ae0260617e7b79d13e4a1dec1784647d7571c1390e86294f20937740f93e0ff1bdb0c1ff648ef152022bf5f54bfcbf24564cbca7a130fb5f56be921fcc7a3ebd51114968274ab13bcc3986137eb6949eff0d42b596f7baec56c94a67a2ec0aeff18dc044cf9500b525dc98efb9992b13f81e1b0bf4c2ac1da91e67c0847cbdaf268ced549c2febd08b661140af9bf45458d13d4717eb61de86b555856ad5":"cfcae49f88b80dc12186d53c57162dbecba6e348094f9fb3743e39d99d5355d87e3efca9d488d39d705671e58634309cbd7cf53fccd52d9a84edb99ffdad0680e9ec826d625728370717b39321c7d4b6882785cf6884275f6c7b6d681bfa710593679e99b67d5bc28121dd603617dc8cfdb2557c2a04533893f593f0f7e59cbe6d46623d22642a7161a4c685b293c7edcc9aaec48e3810ec74a884a41108610d000b591fbf5da44b5501e63781264edf3c73706321ecf44d0e14b5932a2d69ca3d180c5cee86b4ccad850c766e0beb5f20e6b142055d551aeb453bd099eac67eb92cf13e34ef0d0e34fc599a6e5d4d14f74e08190c66c66ad3473de9ae8f53dd2c1c0c41f4b4a8d4690f4b77354c76e05ab76b7a6c7c9edf0955fee799a2bb42c86c6a06631398d38cceb71ec9aaa9a0fb83850f62342f3f781f9d453229b1a709bbce83a44c225ebffd4f518f94a7935f4669f65d02ff3defbbd1d5efd9191365808cdf9460371ede1eae735af03f21431239d5cd57cc0cc88fb3965d187eba98359409aaa944a7af8e85e20b67c43c82e78fa967fc0d629bcd7483d17dcaa25915571a15c3f0c730e81095139d71a28858dd9d83b65bf9c9273a8a40b12a2c87107a71f984818f7dc766374d31b4c3a1d284adb2a17f8ac85dbe3f58cf78b14c0fdce00a79daf348aa0557290ef5f9dd305c15fa73d40c6822b75fda13ec43":"010001":MBEDTLS_MD_SHA384:MBEDTLS_MD_SHA384:"344a458b48d68949ab0effd488443eb54ef367d74e005aec85402a0bb63bcf9ebd2f1b7b1f58f051e56faf46ab71f3def4a1801fc0d076f361dccbcd8a77f78fa929f1ac76985b89cc08f92ab91e680ad1e90d4ac7234b0e3eb3f925dc7713e8a041af64761f33bb09e0c6c7d9d304018dd2f6a18a7f4107c4ce9d5ad4c4896f":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"364ad106da2cec6ce94e141e16af855f6d6e31ac6d7bdb2649695645a3d7f176a9b55f60b861776d49077dcfda4db42bb584767606f90de7289e71f188ff139b138bbd24f7a7f50192a137f2c648e19fe78a836bd2a01d31b248857cd29dbf3d1251c2d4cb339f2ff78add26304fbc3e44f8a2f04b47dc754b984169fba4a091d70f956074880c709ee849a05f8f2dcffee09b221078e98b6e28a965a2d44fcde72c6b27ff0a3def818d80aaba17915d37ad1d72755548310062e73da15a8d2544b311060b404683c00394666dc3a890f60ec9d85b2d0fca8a76fc96c4cfd0e3c4a83594957bac42866c395f8feab3b40c9bc9a675f47a1cd62fc43ebe0fff2bbd239130bbbe5257c5c3756044eb2190db7a309cddc4ef410e9abccd0f93158e0edfab2f0a50e80d814a428f61c531b2b747e64feb41523c5802a53c374f35df21abe67a877d062f56a001b47ee6ab571b0bbe7141e0b49cfdc97a15dc19138863d140cc772074c12b3d751985b7852fe76932be1f44a165f4fe58a341d28c3f86924defab4cf2458ba4cc3fb92558511ceee6d91c672b24b8727b867132bf6b8d7af714ab668f06f046448c1e854ae98e59cf21f2b7370c9378ee0eb34b031f9f4795057557773af0f7fc18ddeec7e95c2ccdd5f66ed224d08fbdfb37995e87f4df9691e499d77afaa8d5b93f3275c43f69edbe37672cf192f94509df0a4e9b":20:0
+
+RSASSA-PSS Signature RSA-4096, SHA-512, Salt Length 20
+depends_on:MBEDTLS_SHA512_C
+pkcs1_rsassa_pss_sign:4096:"f00102d29990fb36bf66dcab57fa4e05745e307c031fe6acb86df4e0487bcb8fd929e227b6e1090a48befbd642f432ea1b6cff26c1aed9f18c04f68170dc1857786faa086fa00b43e0272a1042ee53566cbb48a04f109420e3501cf56222f7a9b51a7ffe2b97a8ea71e791e0bfb259514f953473130dbe41a7978fc385150f8f78748b90538c8906e24759ce2106ede4ac40eb26776cff5abf227673407d0910a9c3f6464d48569f1b8faa62d0b3b7156b059441e1f701751339fa8dfd218c343050e8a88293b6be0407ab2534815eee742c574cbb7469998b23439a23ca4104f563883f5a35ab88d789dcba4073aebf2e1855abb839908874c1a10f150d56b7":"dda4491b56bdad20f032c8a61bc326995ee7353c3f1b4c1e677aeb4b028e45bf6566fb20f3e82bac4169a970787b8cbafb06edd24a9bebe52704f242f7203ec96aee9a9f5ee76e270191f82e3651da663b80d51688c2d40ffa932ce2302322503664ae0260617e7b79d13e4a1dec1784647d7571c1390e86294f20937740f93e0ff1bdb0c1ff648ef152022bf5f54bfcbf24564cbca7a130fb5f56be921fcc7a3ebd51114968274ab13bcc3986137eb6949eff0d42b596f7baec56c94a67a2ec0aeff18dc044cf9500b525dc98efb9992b13f81e1b0bf4c2ac1da91e67c0847cbdaf268ced549c2febd08b661140af9bf45458d13d4717eb61de86b555856ad5":"cfcae49f88b80dc12186d53c57162dbecba6e348094f9fb3743e39d99d5355d87e3efca9d488d39d705671e58634309cbd7cf53fccd52d9a84edb99ffdad0680e9ec826d625728370717b39321c7d4b6882785cf6884275f6c7b6d681bfa710593679e99b67d5bc28121dd603617dc8cfdb2557c2a04533893f593f0f7e59cbe6d46623d22642a7161a4c685b293c7edcc9aaec48e3810ec74a884a41108610d000b591fbf5da44b5501e63781264edf3c73706321ecf44d0e14b5932a2d69ca3d180c5cee86b4ccad850c766e0beb5f20e6b142055d551aeb453bd099eac67eb92cf13e34ef0d0e34fc599a6e5d4d14f74e08190c66c66ad3473de9ae8f53dd2c1c0c41f4b4a8d4690f4b77354c76e05ab76b7a6c7c9edf0955fee799a2bb42c86c6a06631398d38cceb71ec9aaa9a0fb83850f62342f3f781f9d453229b1a709bbce83a44c225ebffd4f518f94a7935f4669f65d02ff3defbbd1d5efd9191365808cdf9460371ede1eae735af03f21431239d5cd57cc0cc88fb3965d187eba98359409aaa944a7af8e85e20b67c43c82e78fa967fc0d629bcd7483d17dcaa25915571a15c3f0c730e81095139d71a28858dd9d83b65bf9c9273a8a40b12a2c87107a71f984818f7dc766374d31b4c3a1d284adb2a17f8ac85dbe3f58cf78b14c0fdce00a79daf348aa0557290ef5f9dd305c15fa73d40c6822b75fda13ec43":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"fc5b9da74a8afff53e53f7558b69fcad8a924d948cace26f6eeea2d96e71d6493cefdeee55ca22de8c504c70e93db5e6b7811c50d9449ead5d28e25254ce9590e09b16918ebc7283e66792f84164b38ddbcd17ca2912fa4a6d3fc81c87828d680ee8ad569f67d52b752131b63ae7e0ea1dfca5cc251cdf90c5bdbbfeb095a81b":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"6edfb6bfb20da2621e7ca0b8e13bfc3801d8bcb43ef3822be960b96a67d3e8afbbe2ef22e206b328ce99dd8f9758052d42a8ee93e16d8e160a50687e8ffce72d258610064ebde4c4cc2ab96c8e516ec2c1eed816c8e6ac537a0570c9eff81a38147bcd8f4747390676f9d755f613687ac59dbac14f69ca6e56a26727699fa11c200eb77339ead56fc6883acf9b92c6deb6f4d79f82ccdc493fedc6165f78c174adcf32941eeb237a4ae369dbbafb4553c98e413823f6f46da0d47d47a164b792aaf1324a8be4f01601bceb809f8c08f3458b1de2c6378cf93fb293212f6bd4a7b1fd1bfa14a1af29575a5ecc4281420179758e96b4465ec07f6cce4e5e5c2307d531e400e494725eb7dceb1d8dac1000d92f62f319534063c01aec9c6ec0c7675351f2883e462b0454db364f03700d6593c9be195fbea5800ebb81578c765409ac2c37f78fabe8783c5d324fa4dfabe4f192866e34037901615304237f08028a75f00a3904bea03219ef9dbfeb48d10ec59d481eb0429cfc9ae835cc578377e61023d5ceedfd3d0a05aceddb274c13782dda9299d6197519e14791208f8d86d63e0ab7fb42a1e14f8f37f49732e23d4b7d4f07cd0bc828649a12748e8d70f53683580bca87290992a349730370bbed6ed743e705759734872c54ff03c1a97037a7b9ee3c8c42d12c3ebe0c1bf3b42854d04a9177d1a24000bd388fa289fd77d5":20:0
+
+RSASSA-PSS Signature RSA-2048, SHA-224, Salt Length 15
+depends_on:MBEDTLS_SHA256_C
+pkcs1_rsassa_pss_sign:2048:"e28da1aa250390bc8fd27d6f601830febbdd5a309bcd5d1d3cebda111110851563d1fb4d141e8129bf25721aa144b104b7c5adbb8540f02a7402788ae72c93c9f59d6d1bcf1541c3354b5cd3dcb91e35ed100d78857cf2ab6ed04b2dc1cc81fa1307bb18c635fdacfb7f656d0b4743d9f487048a8aaf5d5ec6fd09a01b28d4b1":"dea1faf22b760cbfa9ba11a486edd9b9faee04f22f15abfff5b2c079a2c932cfa641660da16213adfbbb568ecbaac18511031f428cd3ae4e0bf01928a1db6360511c26501c7bda7bf4fc4cc792d79efb86ec15ba2fc82aa41bce08e0807859a41b57e9e3f15804c81bf8ed017dea62e53489f955949651ddcb1da5297465ac9f":"c5062b58d8539c765e1e5dbaf14cf75dd56c2e13105fecfd1a930bbb5948ff328f126abe779359ca59bca752c308d281573bc6178b6c0fef7dc445e4f826430437b9f9d790581de5749c2cb9cb26d42b2fee15b6b26f09c99670336423b86bc5bec71113157be2d944d7ff3eebffb28413143ea36755db0ae62ff5b724eecb3d316b6bac67e89cacd8171937e2ab19bd353a89acea8c36f81c89a620d5fd2effea896601c7f9daca7f033f635a3a943331d1b1b4f5288790b53af352f1121ca1bef205f40dc012c412b40bdd27585b946466d75f7ee0a7f9d549b4bece6f43ac3ee65fe7fd37123359d9f1a850ad450aaf5c94eb11dea3fc0fc6e9856b1805ef":"86c94f":MBEDTLS_MD_SHA224:MBEDTLS_MD_SHA224:"37ddd9901478ae5c16878702cea4a19e786d35582de44ae65a16cd5370fbe3ffdd9e7ee83c7d2f27c8333bbe1754f090059939b1ee3d71e020a675528f48fdb2cbc72c65305b65125c796162e7b07e044ed15af52f52a1febcf4237e6aa42a69e99f0a9159daf924bba12176a57ef4013a5cc0ab5aec83471648005d67d7122e":"463729b3eaf43502d9cff129925681":"7e628bcbe6ff83a937b8961197d8bdbb322818aa8bdf30cdfb67ca6bf025ef6f09a99dba4c3ee2807d0b7c77776cfeff33b68d7e3fa859c4688626b2441897d26e5d6b559dd72a596e7dad7def9278419db375f7c67cee0740394502212ebdd4a6c8d3af6ee2fd696d8523de6908492b7cbf2254f15a348956c19840dc15a3d732ef862b62ede022290de3af11ca5e79a3392fff06f75aca8c88a2de1858b35a216d8f73fd70e9d67958ed39a6f8976fb94ec6e61f238a52f9d42241e8354f89e3ece94d6fa5bfbba1eeb70e1698bff31a685fbe799fb44efe21338ed6eea2129155aabc0943bc9f69a8e58897db6a8abcc2879d5d0c5d3e6dc5eb48cf16dac8":15:0
+
+RSASSA-PSS Signature RSA-2048, SHA-384, Salt Length 25
+depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+pkcs1_rsassa_pss_sign:2048:"e28da1aa250390bc8fd27d6f601830febbdd5a309bcd5d1d3cebda111110851563d1fb4d141e8129bf25721aa144b104b7c5adbb8540f02a7402788ae72c93c9f59d6d1bcf1541c3354b5cd3dcb91e35ed100d78857cf2ab6ed04b2dc1cc81fa1307bb18c635fdacfb7f656d0b4743d9f487048a8aaf5d5ec6fd09a01b28d4b1":"dea1faf22b760cbfa9ba11a486edd9b9faee04f22f15abfff5b2c079a2c932cfa641660da16213adfbbb568ecbaac18511031f428cd3ae4e0bf01928a1db6360511c26501c7bda7bf4fc4cc792d79efb86ec15ba2fc82aa41bce08e0807859a41b57e9e3f15804c81bf8ed017dea62e53489f955949651ddcb1da5297465ac9f":"c5062b58d8539c765e1e5dbaf14cf75dd56c2e13105fecfd1a930bbb5948ff328f126abe779359ca59bca752c308d281573bc6178b6c0fef7dc445e4f826430437b9f9d790581de5749c2cb9cb26d42b2fee15b6b26f09c99670336423b86bc5bec71113157be2d944d7ff3eebffb28413143ea36755db0ae62ff5b724eecb3d316b6bac67e89cacd8171937e2ab19bd353a89acea8c36f81c89a620d5fd2effea896601c7f9daca7f033f635a3a943331d1b1b4f5288790b53af352f1121ca1bef205f40dc012c412b40bdd27585b946466d75f7ee0a7f9d549b4bece6f43ac3ee65fe7fd37123359d9f1a850ad450aaf5c94eb11dea3fc0fc6e9856b1805ef":"86c94f":MBEDTLS_MD_SHA384:MBEDTLS_MD_SHA384:"833aa2b1dcc77607a44e804ee77d45408586c536861f6648adcd2fb65063368767c55c6fe2f237f6404250d75dec8fa68bcaf3b6e561863ae01c91aa23d80c6999a558a4c4cb317d540cde69f829aad674a89812f4d353689f04648c7020a73941620018295a4ae4083590cc603e801867a51c105a7fb319130f1022de44f13e":"b750587671afd76886e8ffb7865e78f706641b2e4251b48706":"2ca37a3d6abd28c1eaf9bde5e7ac17f1fa799ce1b4b899d19985c2ff7c8ba959fe54e5afb8bc4021a1f1c687eebb8cba800d1c51636b1f68dc3e48f63e2da6bc6d09c6668f68e508c5d8c19bef154759e2f89ade152717370a8944f537578296380d1fe6be809e8b113d2b9d89e6a46f5c333d4fd48770fc1ea1c548104575b84cf071042bfe5acf496392be8351a41c46a2cab0864c4c1c5b5e0c7b27e7b88c69f37ffa7e1a8cd98f343ac84a4ad67025a40ed8f664e9d630337de6e48bb2125e2552123609491f183afd92634487f0b2cf971f2626e88858879d45a29b0fefb66cd41b2e4e968385bd9fc8c7211976bc6bd3e1ad6df60856985a825f4726d2":25:0
+
+RSASSA-PSS Signature RSA-2048, SHA-512, Salt Length 30
+depends_on:MBEDTLS_SHA512_C
+pkcs1_rsassa_pss_sign:2048:"e28da1aa250390bc8fd27d6f601830febbdd5a309bcd5d1d3cebda111110851563d1fb4d141e8129bf25721aa144b104b7c5adbb8540f02a7402788ae72c93c9f59d6d1bcf1541c3354b5cd3dcb91e35ed100d78857cf2ab6ed04b2dc1cc81fa1307bb18c635fdacfb7f656d0b4743d9f487048a8aaf5d5ec6fd09a01b28d4b1":"dea1faf22b760cbfa9ba11a486edd9b9faee04f22f15abfff5b2c079a2c932cfa641660da16213adfbbb568ecbaac18511031f428cd3ae4e0bf01928a1db6360511c26501c7bda7bf4fc4cc792d79efb86ec15ba2fc82aa41bce08e0807859a41b57e9e3f15804c81bf8ed017dea62e53489f955949651ddcb1da5297465ac9f":"c5062b58d8539c765e1e5dbaf14cf75dd56c2e13105fecfd1a930bbb5948ff328f126abe779359ca59bca752c308d281573bc6178b6c0fef7dc445e4f826430437b9f9d790581de5749c2cb9cb26d42b2fee15b6b26f09c99670336423b86bc5bec71113157be2d944d7ff3eebffb28413143ea36755db0ae62ff5b724eecb3d316b6bac67e89cacd8171937e2ab19bd353a89acea8c36f81c89a620d5fd2effea896601c7f9daca7f033f635a3a943331d1b1b4f5288790b53af352f1121ca1bef205f40dc012c412b40bdd27585b946466d75f7ee0a7f9d549b4bece6f43ac3ee65fe7fd37123359d9f1a850ad450aaf5c94eb11dea3fc0fc6e9856b1805ef":"86c94f":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"5f0fe2afa61b628c43ea3b6ba60567b1ae95f682076f01dfb64de011f25e9c4b3602a78b94cecbc14cd761339d2dc320dba504a3c2dcdedb0a78eb493bb11879c31158e5467795163562ec0ca26c19e0531530a815c28f9b52061076e61f831e2fc45b86631ea7d3271444be5dcb513a3d6de457a72afb67b77db65f9bb1c380":"aa10fec3f83b7a97e092877a5bf9081283f502a0a46b50e395ab983a49ac":"5e0712bb363e5034ef6b23c119e3b498644445faab5a4c0b4e217e4c832ab34c142d7f81dbf8affdb2dacefabb2f83524c5aa883fc5f06e528b232d90fbea9ca08ae5ac180d477eaed27d137e2b51bd613b69c543d555bfc7cd81a4f795753c8c64c6b5d2acd9e26d6225f5b26e4e66a945fd6477a277b580dbeaa46d0be498df9a093392926c905641945ec5b9597525e449af3743f80554788fc358bc0401a968ff98aaf34e50b352751f32274750ff5c1fba503050204cec9c77deede7f8fa20845d95f5177030bc91d51f26f29d2a65b870dc72b81e5ef9eeef990d7c7145bbf1a3bc7aedd19fa7cbb020756525f1802216c13296fd6aac11bf2d2d90494":30:0
+
+RSASSA-PSS Signature RSA-3072, SHA-512, Salt Length 62
+depends_on:MBEDTLS_SHA512_C
+pkcs1_rsassa_pss_sign:3072:"dd553696db8ccb107609b8917e688bdd8373a8926bc9d114c1c77f7958070e236ca1bd2025ded59a71093b63afbfce39e92bde9ffca983959e7c3e18d75650612258c24eebb61a1b4a68603a2721e3e2483d6da27475a228b1341c78f140948b5c922822ccaed76dae338dddec1e4c5c34b9c53f34a09ff0b2b61a62254e73e6f0ac8013edc2cfa7ecbeb86fcc7309cb0f5b5eddb707af4b9337d34d672af413f3b6efd11e3b49c978f06a356f6f4e0ea50a90797fe32ccaa983547ff18ea167":"c1e3089e1bea1141638ca912da01c134f67231a2f737d97e28486e004a43e9c5592ff968ee18109fc71aa4c1a97aa88ece5c4734352bc0c1f67726bc4aac59c19301f23a705be5b3f7825fb284e58a950d795f63d18fe72231eaba9d6a5f90866f8dd34b2b0dfc132db8348efa5a62634e5584a788aebbf073ccb4f3e9f5cde8d0c2e831412485c7f8cf1473abffabcc5d51d8a2a87a22f39d1a250b3cb66d90c573669071aeba9b1080dc079243094a9ae0e5a62e4e8b653cb57f54f4eeaf3d":"a7a1882a7fb896786034d07fb1b9f6327c27bdd7ce6fe39c285ae3b6c34259adc0dc4f7b9c7dec3ca4a20d3407339eedd7a12a421da18f5954673cac2ff059156ecc73c6861ec761e6a0f2a5a033a6768c6a42d8b459e1b4932349e84efd92df59b45935f3d0e30817c66201aa99d07ae36c5d74f408d69cc08f044151ff4960e531360cb19077833adf7bce77ecfaa133c0ccc63c93b856814569e0b9884ee554061b9a20ab46c38263c094dae791aa61a17f8d16f0e85b7e5ce3b067ece89e20bc4e8f1ae814b276d234e04f4e766f501da74ea7e3817c24ea35d016676cece652b823b051625573ca92757fc720d254ecf1dcbbfd21d98307561ecaab545480c7c52ad7e9fa6b597f5fe550559c2fe923205ac1761a99737ca02d7b19822e008a8969349c87fb874c81620e38f613c8521f0381fe5ba55b74827dad3e1cf2aa29c6933629f2b286ad11be88fa6436e7e3f64a75e3595290dc0d1cd5eee7aaac54959cc53bd5a934a365e72dd81a2bd4fb9a67821bffedf2ef2bd94913de8b":"1415a7":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"44240ce519f00239bd66ba03c84d3160b1ce39e3932866e531a62b1c37cf4170c3dc4809236fb1ade181db49fc9c7ccd794b433d1ad0bc056e14738e0ae45c0e155972a40a989fa4b9bcdc308f11990818835fa2c256b47ee4173fb4fed22ccf4385d2dd54d593c74f0004df08134eb8965dd53a122317f59b95d6b69d017958":"2d0c49b20789f39502eefd092a2b6a9b2757c1456147569a685fca4492a8d5b0e6234308385d3d629644ca37e3399616c266f199b6521a9987b2be9ee783":"8f47abc2326e22cf62404508b442e81ad45afff7274096b9a13e478cdd0a72f99a76bf517f1bb0f872a523d8c588d4402569e948fd6a108ae1a45c65830828a10e94d432765314ba82ead310fc87ac99a5b39f30ab8820bf69e6934a9c1c915c19f36ea7717eaff7af67b4991315b1873ba929bedf18a975be808e7aa14a6726126c79cc93f69541c5cefdeb5b67ec279d8f5a446583e4b4faed1685140ee4b3b757c8ff4a1ef9cd76a88e05319ee62003d2d77290c94c579b0ca2ab0deb3176ef10a3fdb85c80ffbc9e2a665a23744fc836f9a9a103cd9fb756952356a2f1acdd68a645e20179006558b5d4d0b9b0bd3adf5e290f49dae60b9d19920953ea8bb237d5b3dcfe149a60f12a4ee3a889b33bcd3a3b753d610757cbcd093dd5a734255333689695ab636963e3d215a8e77ff31973718a4944a1e9e44f45754d39f6fa431c53f9a2ef36e16a5f70636eb5fba54e15c20a714f2809a7cff4b8dc1165f836607eb5a5a3bb0c4567eee26941fef46fb41e73b565c0cf8c72e404221264":62:0
+
+RSASSA-PSS Signature RSA-1024, SHA-256, Salt Length 0
+depends_on:MBEDTLS_SHA256_C
+pkcs1_rsassa_pss_sign:1024:"e5563b145db6ff5a16280d3e80eff02f181dbd03324ef247f596a4d4a7b8daa32b9934e3c7f4dcf6a3105462dec63839638618418b51db02693fabb4e6838725":"d2a4ec0fa2226cde82da77653b072cd098535d3e90ed4d7224dcb8cb8b9314768dc517e22d7c8fa13f253daa7465a79956098aa4cc3a6e35e8b1fcc4f97e774f":"bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda707a146b3b4e29989ddc660bd694865b932b71ca24a335cf4d339c719183e6222e4c9ea6875acd528a49ba21863fe08147c3a47e41990b51a03f77d22137f8d74c43a5a45f4e9e18a2d15db051dc89385db9cf8374b63a8cc88113710e6d8179075b7dc79ee76b":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:"1248f62a4389f42f7b4bb131053d6c88a994db2075b912ccbe3ea7dc611714f14e075c104858f2f6e6cfd6abdedf015a821d03608bf4eba3169a6725ec422cd9069498b5515a9608ae7cc30e3d2ecfc1db6825f3e996ce9a5092926bc1cf61aa42d7f240e6f7aa0edb38bf81aa929d66bb5d890018088458720d72d569247b0c":"6f2841166a64471d4f0b8ed0dbb7db32161da13b3af3c4bd6d4cfcad8a03290e237b0cb3f05a4640d4ff655aa36fd36b4089817a7d4538ea9134971c37c12a5b3c360e2c90546c6553d2bff7419262821ce3fc99283483b9691ad5a0dbff":"ac777fd1f72fb4598b30ec1d343488e83bc03cac3380492225efad8c0d7e2c15a0031b8e027bf4e80747ce3de188b405dfeec2b4b5439599bef733a120fd80532e0fcc0629f86cc990e312b2b73ee1f3586198bf81f3af05ef0cfbed3d1b5c620927d2084f31847784c2ba8d55a0f038a5eaf8c2ea85ea81eebdc0fe1f0d75c1":0:0
+
+RSASSA-PSS Signature RSA-1024, SHA-256, Salt Length = max
+depends_on:MBEDTLS_SHA256_C
+pkcs1_rsassa_pss_sign:1024:"e5563b145db6ff5a16280d3e80eff02f181dbd03324ef247f596a4d4a7b8daa32b9934e3c7f4dcf6a3105462dec63839638618418b51db02693fabb4e6838725":"d2a4ec0fa2226cde82da77653b072cd098535d3e90ed4d7224dcb8cb8b9314768dc517e22d7c8fa13f253daa7465a79956098aa4cc3a6e35e8b1fcc4f97e774f":"bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda707a146b3b4e29989ddc660bd694865b932b71ca24a335cf4d339c719183e6222e4c9ea6875acd528a49ba21863fe08147c3a47e41990b51a03f77d22137f8d74c43a5a45f4e9e18a2d15db051dc89385db9cf8374b63a8cc88113710e6d8179075b7dc79ee76b":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:"1248f62a4389f42f7b4bb131053d6c88a994db2075b912ccbe3ea7dc611714f14e075c104858f2f6e6cfd6abdedf015a821d03608bf4eba3169a6725ec422cd9069498b5515a9608ae7cc30e3d2ecfc1db6825f3e996ce9a5092926bc1cf61aa42d7f240e6f7aa0edb38bf81aa929d66bb5d890018088458720d72d569247b0c":"6f2841166a64471d4f0b8ed0dbb7db32161da13b3af3c4bd6d4cfcad8a03290e237b0cb3f05a4640d4ff655aa36fd36b4089817a7d4538ea9134971c37c12a5b3c360e2c90546c6553d2bff7419262821ce3fc99283483b9691ad5a0dbff":"6708ae77c8c32056d89d8186f1d74d84a02cf69a084516c3525901e7c2c8359c1e8939f95b1184ca8e57508a28673243f1580f0eaef13a8eb64c9b78c8a5c2249f7601faa9a55743d056c08bbf213bd5d461e134078b11458a76707fe80df58ca477c2455665734cb498dde2a87065d8bdb8851f7943f4c38ae243752dc79da3":94:0
+
+RSASSA-PSS Signature RSA-1024, SHA-256, Salt Length = max+1
+depends_on:MBEDTLS_SHA256_C
+pkcs1_rsassa_pss_sign:1024:"e5563b145db6ff5a16280d3e80eff02f181dbd03324ef247f596a4d4a7b8daa32b9934e3c7f4dcf6a3105462dec63839638618418b51db02693fabb4e6838725":"d2a4ec0fa2226cde82da77653b072cd098535d3e90ed4d7224dcb8cb8b9314768dc517e22d7c8fa13f253daa7465a79956098aa4cc3a6e35e8b1fcc4f97e774f":"bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda707a146b3b4e29989ddc660bd694865b932b71ca24a335cf4d339c719183e6222e4c9ea6875acd528a49ba21863fe08147c3a47e41990b51a03f77d22137f8d74c43a5a45f4e9e18a2d15db051dc89385db9cf8374b63a8cc88113710e6d8179075b7dc79ee76b":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:"1248f62a4389f42f7b4bb131053d6c88a994db2075b912ccbe3ea7dc611714f14e075c104858f2f6e6cfd6abdedf015a821d03608bf4eba3169a6725ec422cd9069498b5515a9608ae7cc30e3d2ecfc1db6825f3e996ce9a5092926bc1cf61aa42d7f240e6f7aa0edb38bf81aa929d66bb5d890018088458720d72d569247b0c":"6f2841166a64471d4f0b8ed0dbb7db32161da13b3af3c4bd6d4cfcad8a03290e237b0cb3f05a4640d4ff655aa36fd36b4089817a7d4538ea9134971c37c12a5b3c360e2c90546c6553d2bff7419262821ce3fc99283483b9691ad5a0dbff":"":95:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
+
+RSASSA-PSS Signature RSA-2048, SHA-256, Salt Length = 0
+depends_on:MBEDTLS_SHA256_C
+pkcs1_rsassa_pss_sign:2048:"f7b664093cabf8334b1c0ff824564db5c13f941a279733893a7e5abed536d2b51a2beac80730b5194a0c722f57354ce4b7db447ea3286b1cd1c754548ea3c91a0df1bde3ff70820b63ef3c74a0119671d14db3e2603868a0d607a81bf14f3f41f810c3a24bf52a94f9b694078a556194dd0cb36c56a91846d3569096c631b61f":"e0a1111aa114d5b1702e34d29565d65320e05c21d794f38572ad28a60b2ffe50d0dd3df3fb5a0eef048ec50e144bfe52be30ebf2eaceec9f110a600bb0c2bcacf6b4dabec09b9387c89a8fde19de5ceec780be38dca846d795f82608cf2844e9bced8d81da2d9258c3ef412154f9e590a158ea0ad9180ac6a798614ba3410937":"d95b71c9dfee453ba1b1a7de2c1f0b0a67579ee91d1d3ad97e481829b86edac750c48e12a8cdb026c82f273dafc222009f0db3b08b2db10a69c4b2dddaaeceac1b0c862682eef294e579f55aab871bc0a7eeabc923c9e80dddc22ec0a27002aee6a5ba66397f412bbaf5fb4eaf66a1a0f82eaf6827198caf49b347258b1283e8cbb10da2837f6ecc3490c728fe927f44455a6f194f3776bf79151d9ad7e2daf770b37d12627cc0c5fb62484f46258d9ce2c11b26256d09cb412f8d8f8f1fe91bb94ac27de6d26a83a8439e51b35dbee46b3b8ff991d667bb53eeee85ff1652c8981f141d47c8205791cef5b32d718ddc082ed0dd542826416b2271064ef437a9":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:"cd74ae6152d5fe5ce3d9073c921e861a24208f0c68477f49c825338e1ef877c0c977c1d2ffcb20e964db6fbedcccce449ec8538c8bfffce5bdece84762dac7f2cba69052c0c67226178a0ce185a2e050b3e1057e94411dd5f726878558e7d62afc8a81a93dcfdb5a2271466d32a8a4868af20fab2e13ca609d5a7710a8278aaf":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"293c65933fb46e6bc50d9c34a266a5e1b9e3b3ff3c99c691a88eb2d1b652ab28144e9e6a18468995febb5ce84b38efb295b1ebf1b7b4b7bce29c35dfbdc81b0944bdb3cdba914215de4380cf5226c6c7af172bf82dbebade614d710be5b4256d588d12d3a0f4494b863b09e8962bbc1d97cdaebd92d40a0485476178acbb943d1bec59aabfb60a15b1cb8f17f600fc10ec1f97148ecacca4b3715ec173e641525a1331b1b5b504bc9f930b7061f10e63509d2223c49c3050bab6edba11dc426a8b5dbfdb31b43ab3dedc392f3d4d0401f67b83cdb59e592dbedad5ed407854310e1304b4e998b8e4074caafba6fb006335c64666758401a508813d307f466e3a":0:0
+
+RSASSA-PSS Signature RSA-2048, SHA-256, Salt Length = max
+depends_on:MBEDTLS_SHA256_C
+pkcs1_rsassa_pss_sign:2048:"f7b664093cabf8334b1c0ff824564db5c13f941a279733893a7e5abed536d2b51a2beac80730b5194a0c722f57354ce4b7db447ea3286b1cd1c754548ea3c91a0df1bde3ff70820b63ef3c74a0119671d14db3e2603868a0d607a81bf14f3f41f810c3a24bf52a94f9b694078a556194dd0cb36c56a91846d3569096c631b61f":"e0a1111aa114d5b1702e34d29565d65320e05c21d794f38572ad28a60b2ffe50d0dd3df3fb5a0eef048ec50e144bfe52be30ebf2eaceec9f110a600bb0c2bcacf6b4dabec09b9387c89a8fde19de5ceec780be38dca846d795f82608cf2844e9bced8d81da2d9258c3ef412154f9e590a158ea0ad9180ac6a798614ba3410937":"d95b71c9dfee453ba1b1a7de2c1f0b0a67579ee91d1d3ad97e481829b86edac750c48e12a8cdb026c82f273dafc222009f0db3b08b2db10a69c4b2dddaaeceac1b0c862682eef294e579f55aab871bc0a7eeabc923c9e80dddc22ec0a27002aee6a5ba66397f412bbaf5fb4eaf66a1a0f82eaf6827198caf49b347258b1283e8cbb10da2837f6ecc3490c728fe927f44455a6f194f3776bf79151d9ad7e2daf770b37d12627cc0c5fb62484f46258d9ce2c11b26256d09cb412f8d8f8f1fe91bb94ac27de6d26a83a8439e51b35dbee46b3b8ff991d667bb53eeee85ff1652c8981f141d47c8205791cef5b32d718ddc082ed0dd542826416b2271064ef437a9":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:"cd74ae6152d5fe5ce3d9073c921e861a24208f0c68477f49c825338e1ef877c0c977c1d2ffcb20e964db6fbedcccce449ec8538c8bfffce5bdece84762dac7f2cba69052c0c67226178a0ce185a2e050b3e1057e94411dd5f726878558e7d62afc8a81a93dcfdb5a2271466d32a8a4868af20fab2e13ca609d5a7710a8278aaf":"6f2841166a64471d4f0b8ed0dbb7db32161da13b3f04e3159073f7ad2fe70738168779091facbabfc4df54d6f49c7c7849a2e888a6cb9d363e94e46d7ceba692721f9b92cc56519035a5662941e2a18a8489122b55af6193444501c030a752a3c6ed3592438623782c89a16d6c42f8f0cc0a1b21ba7db4fec2b5bef35c109623fdcbb54151d8b97d625bebce9de3be69edda8aa7573fa519f4630c5173a274716d29b2bf026b3c64c62732640af0cdf8ca589f2197453b8ba847dc1cea508d577a3f167caa53e0717a12d58502a27dcdfa1cee9161291d0a71f9265b4ab3":"558dcb8c4ed92d22618fb2169a552bf5ada493ad66890639caecce025839f44d2f8b7004d70586296fd94278e478dfbb63a6867f3fd909a558cca1fba1b329a3f230c2874886eb0b5a3de01e02100a939f216a07a445f9e8f7279b8cc31966de23c912c477bed5ac99996f09ec817bd02acb671310b33d5a9bf79bfc14a0e38abef9169c01e7743a408868f42705743023ec7892c2e437b918b40d873d99c56faa58543a8eb41d91d38ab8ca5165b95ac84b30624a6517b2893f432c63d34352059c9a6ad3353fe3859d0b51a971e3d58a287612b1a7b6eeb76b7101850f809960c1c137ea396ede4c570817bef93b2ff901c2d175909f48a6b6a73dc3aa6cef":222:0
+
+RSASSA-PSS Signature RSA-2048, SHA-256, Salt Length = max+1
+depends_on:MBEDTLS_SHA256_C
+pkcs1_rsassa_pss_sign:2048:"f7b664093cabf8334b1c0ff824564db5c13f941a279733893a7e5abed536d2b51a2beac80730b5194a0c722f57354ce4b7db447ea3286b1cd1c754548ea3c91a0df1bde3ff70820b63ef3c74a0119671d14db3e2603868a0d607a81bf14f3f41f810c3a24bf52a94f9b694078a556194dd0cb36c56a91846d3569096c631b61f":"e0a1111aa114d5b1702e34d29565d65320e05c21d794f38572ad28a60b2ffe50d0dd3df3fb5a0eef048ec50e144bfe52be30ebf2eaceec9f110a600bb0c2bcacf6b4dabec09b9387c89a8fde19de5ceec780be38dca846d795f82608cf2844e9bced8d81da2d9258c3ef412154f9e590a158ea0ad9180ac6a798614ba3410937":"d95b71c9dfee453ba1b1a7de2c1f0b0a67579ee91d1d3ad97e481829b86edac750c48e12a8cdb026c82f273dafc222009f0db3b08b2db10a69c4b2dddaaeceac1b0c862682eef294e579f55aab871bc0a7eeabc923c9e80dddc22ec0a27002aee6a5ba66397f412bbaf5fb4eaf66a1a0f82eaf6827198caf49b347258b1283e8cbb10da2837f6ecc3490c728fe927f44455a6f194f3776bf79151d9ad7e2daf770b37d12627cc0c5fb62484f46258d9ce2c11b26256d09cb412f8d8f8f1fe91bb94ac27de6d26a83a8439e51b35dbee46b3b8ff991d667bb53eeee85ff1652c8981f141d47c8205791cef5b32d718ddc082ed0dd542826416b2271064ef437a9":"010001":MBEDTLS_MD_SHA256:MBEDTLS_MD_SHA256:"cd74ae6152d5fe5ce3d9073c921e861a24208f0c68477f49c825338e1ef877c0c977c1d2ffcb20e964db6fbedcccce449ec8538c8bfffce5bdece84762dac7f2cba69052c0c67226178a0ce185a2e050b3e1057e94411dd5f726878558e7d62afc8a81a93dcfdb5a2271466d32a8a4868af20fab2e13ca609d5a7710a8278aaf":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"":223:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
+
+RSASSA-PSS Signature RSA-1024, SHA-512, Salt Length 0
+depends_on:MBEDTLS_SHA512_C
+pkcs1_rsassa_pss_sign:1024:"e5563b145db6ff5a16280d3e80eff02f181dbd03324ef247f596a4d4a7b8daa32b9934e3c7f4dcf6a3105462dec63839638618418b51db02693fabb4e6838725":"d2a4ec0fa2226cde82da77653b072cd098535d3e90ed4d7224dcb8cb8b9314768dc517e22d7c8fa13f253daa7465a79956098aa4cc3a6e35e8b1fcc4f97e774f":"bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda707a146b3b4e29989ddc660bd694865b932b71ca24a335cf4d339c719183e6222e4c9ea6875acd528a49ba21863fe08147c3a47e41990b51a03f77d22137f8d74c43a5a45f4e9e18a2d15db051dc89385db9cf8374b63a8cc88113710e6d8179075b7dc79ee76b":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"1248f62a4389f42f7b4bb131053d6c88a994db2075b912ccbe3ea7dc611714f14e075c104858f2f6e6cfd6abdedf015a821d03608bf4eba3169a6725ec422cd9069498b5515a9608ae7cc30e3d2ecfc1db6825f3e996ce9a5092926bc1cf61aa42d7f240e6f7aa0edb38bf81aa929d66bb5d890018088458720d72d569247b0c":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"7289bf65540f4925c608e62c8d077789828560945a27fd3f3918e4258b38be488d54b546bfe46d56e519583e77fbf3988538e26fd05793cea925934d714e748a23c429356d3c09e51e08d425923e4237c0f00c3c9f77d8544b8e089d265497a683c2f19b80776671ad36d1cadd38e24c3049461f3d3d964ddc9afdf1d4b9022a":0:0
+
+RSASSA-PSS Signature RSA-1024, SHA-512, Salt Length max
+depends_on:MBEDTLS_SHA512_C
+pkcs1_rsassa_pss_sign:1024:"e5563b145db6ff5a16280d3e80eff02f181dbd03324ef247f596a4d4a7b8daa32b9934e3c7f4dcf6a3105462dec63839638618418b51db02693fabb4e6838725":"d2a4ec0fa2226cde82da77653b072cd098535d3e90ed4d7224dcb8cb8b9314768dc517e22d7c8fa13f253daa7465a79956098aa4cc3a6e35e8b1fcc4f97e774f":"bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda707a146b3b4e29989ddc660bd694865b932b71ca24a335cf4d339c719183e6222e4c9ea6875acd528a49ba21863fe08147c3a47e41990b51a03f77d22137f8d74c43a5a45f4e9e18a2d15db051dc89385db9cf8374b63a8cc88113710e6d8179075b7dc79ee76b":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"1248f62a4389f42f7b4bb131053d6c88a994db2075b912ccbe3ea7dc611714f14e075c104858f2f6e6cfd6abdedf015a821d03608bf4eba3169a6725ec422cd9069498b5515a9608ae7cc30e3d2ecfc1db6825f3e996ce9a5092926bc1cf61aa42d7f240e6f7aa0edb38bf81aa929d66bb5d890018088458720d72d569247b0c":"6f2841166a64471d4f0b8ed0dbb7db32161da13bc5bd8f242a193ead499173ae97c2313d53874c791b13e0adda0ee89fef3668b5f3f7d91d1117cb5aa93e":"a063080224f2659a25ce69417f3240779712d93a69461eb7712c137ed5d4ed7c8490b3e4e7e70e560921da59899a542d1f28db68c1247fd7a0db983ded9f6db9a8d9445c28ba3e4afffb4ed6fd4c93e774082a6dadc8052f3d48cb899d63b9a82f34315f999deb065da600207ea78bfd199e2249f86a55c79761933ee87337aa":62:0
+
+RSASSA-PSS Signature RSA-1024, SHA-512, Salt Length max+1
+depends_on:MBEDTLS_SHA512_C
+pkcs1_rsassa_pss_sign:1024:"e5563b145db6ff5a16280d3e80eff02f181dbd03324ef247f596a4d4a7b8daa32b9934e3c7f4dcf6a3105462dec63839638618418b51db02693fabb4e6838725":"d2a4ec0fa2226cde82da77653b072cd098535d3e90ed4d7224dcb8cb8b9314768dc517e22d7c8fa13f253daa7465a79956098aa4cc3a6e35e8b1fcc4f97e774f":"bcb47b2e0dafcba81ff2a2b5cb115ca7e757184c9d72bcdcda707a146b3b4e29989ddc660bd694865b932b71ca24a335cf4d339c719183e6222e4c9ea6875acd528a49ba21863fe08147c3a47e41990b51a03f77d22137f8d74c43a5a45f4e9e18a2d15db051dc89385db9cf8374b63a8cc88113710e6d8179075b7dc79ee76b":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"1248f62a4389f42f7b4bb131053d6c88a994db2075b912ccbe3ea7dc611714f14e075c104858f2f6e6cfd6abdedf015a821d03608bf4eba3169a6725ec422cd9069498b5515a9608ae7cc30e3d2ecfc1db6825f3e996ce9a5092926bc1cf61aa42d7f240e6f7aa0edb38bf81aa929d66bb5d890018088458720d72d569247b0c":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"":63:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
+
+RSASSA-PSS Signature RSA-3072, SHA-384, Salt Length 0
+depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+pkcs1_rsassa_pss_sign:3072:"ca7b50c5f65f2115fea7691f7d90c124866e774e68e9eb89306538956fc217593d46017b7dd7942d636e384a34c802a14d5fd9916798d7d6193ef1a29e2fdbefd955261496d8ac9713922d43bfc43a7a410752ccbc854cc85268f411e793f9b5279007bbcaca30fb16fd9033a6ea31566b4f2c27f0161107e2cd890bcf563a522ee0eb96a016e9007595a94172a4aeded11fadcb8ab5f03cd154f8b8e0e0666ff62b1ccda02599ea44bbfcfaea541a5ac26bf267a56a8177a50f6b87b460a54d":"c591723042d4b8737f4ef9dfeb40c6d62d439ee8688158a4be24c0ad130f851113cc53d776c63cd782b95ccfd266bdb2578b78439c121de34e8955a7fbd2c6ae1a1c37b24c12f5dce15175dd9e203a3abd5bf9e736b1fc183d10c4540c5cf2cbe26768e94c1eab2ba3008b32d6d50716699c6bfcbec5bbeb94a054dbcd16d10f74972ca5fe53256cd0ade8f502eceaed633414a9bdb623035a234f65c6662a23d792cc0eeb21a1f55ebca26ffa1c56c96fbb7d870fc3ffb181de8398238ab1b5":"9c43ef522cab18022297d3d70fa491d03b975b844b76cedba35d8d885ddb2825e31fd5c101bd9e9a215520bb8cdddeb6ab2cf2dc86065179477d80f733016929d7334cdfdf818c1378a4b9428fa1ee2e525321f905d0b949d3abc9e93d3f30b077795338bd55c28a1ced134bb2d575bfa44b2fd8cf1d5c54168a12a1d6c511f62ca973cdb704c233487e1fd39e5adc8870af352ec3c6a6a64152fc82a1c16ecc43d1d5817f76a1b46a5fab9db8923311edd3cc032fed7eb6252e77db69d7bf9ee35dc4ddd0fbdb9a76afe25a82f4495aa4f072cef9b1247cb368bcc8677565a47095242702e6341281f506805e20e8c89e9af28adff21c804c70cab10ee2fe5212ec07987d13e7d4b60529611e4d33a062d724cdfb16cdc48b964ba07dfa2620d5a8805d0be93380850c66f3fada059802a5946bfe3b0b10e19a8289ec01f6514abb883bb53c49dadbba42d412ea264c8a5122fda1ea9b742289642b0ea34ceb76ae8256a97845d37594cfbff8c7a4430176223bacc3bef395ceda13fd211c71":"010001":MBEDTLS_MD_SHA384:MBEDTLS_MD_SHA384:"692acaaf5e277cdd4b3fdc0a1ff1785bfd28a3a8ec1bc97fd072ff6c99aade77baba92efdcf72e66d43542fdd32fb0e2dd29bb167dd36174b671ebef3c39c21be5fc84ef5a0957c9124f7eb281c12ae38cff9289413245c6c537bff88d013b3dd138c9373e26a00cecd4b5b18f708d69f1f24f88a0001d7de30ea40ff3c9f2e7":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"9110b39c1ffc2d8a5f24e965e3985b06871c2be23e677bb3ea879b7b6b25c327ebdd9434387cfe5f64bcb6900a5c8395549e3681390583786b709257ff0ad90507a02ec6abb40e33dec80097322876a84ee98b1fe79ced62ba4f983bb9b52758bf9856098af527924ea83291762b179894f1fab6d8c9867b0244393fa32b5871836fa4446b247153bc117ccaf7cd51c5ec026bcaf9b634182cd19a0eb95ec40dd5e4274750c9ee3b1379fb339fa4ed8348b104936396355bea0a00337b83f47d2fd7e7353f3009752f970eebc1bbade601b912f7b0984bccc68941ed23bd31fcd23a7d0f2b0cfaabdb3d361969f485e5d198442661ee71eef258ae9fc27a19d995a5695c668f9ab78622486d6ccfe4ae11de9240588fafbc75f8bd0d04de5f2959c126b7c672eac8bb65031ea22ebb4a4e36c12f427d2dc4619eb30ef1c90ec951337a364566f0d2e32f311b425a68fd5277a85dc8d8041ab2a0165c39fd4e39160498d5eae98965e8745b77390e5ddeff0aeffc0fb18839455d524826a1f366":0:0
+
+RSASSA-PSS Signature RSA-3072, SHA-384, Salt Length max
+depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+pkcs1_rsassa_pss_sign:3072:"ca7b50c5f65f2115fea7691f7d90c124866e774e68e9eb89306538956fc217593d46017b7dd7942d636e384a34c802a14d5fd9916798d7d6193ef1a29e2fdbefd955261496d8ac9713922d43bfc43a7a410752ccbc854cc85268f411e793f9b5279007bbcaca30fb16fd9033a6ea31566b4f2c27f0161107e2cd890bcf563a522ee0eb96a016e9007595a94172a4aeded11fadcb8ab5f03cd154f8b8e0e0666ff62b1ccda02599ea44bbfcfaea541a5ac26bf267a56a8177a50f6b87b460a54d":"c591723042d4b8737f4ef9dfeb40c6d62d439ee8688158a4be24c0ad130f851113cc53d776c63cd782b95ccfd266bdb2578b78439c121de34e8955a7fbd2c6ae1a1c37b24c12f5dce15175dd9e203a3abd5bf9e736b1fc183d10c4540c5cf2cbe26768e94c1eab2ba3008b32d6d50716699c6bfcbec5bbeb94a054dbcd16d10f74972ca5fe53256cd0ade8f502eceaed633414a9bdb623035a234f65c6662a23d792cc0eeb21a1f55ebca26ffa1c56c96fbb7d870fc3ffb181de8398238ab1b5":"9c43ef522cab18022297d3d70fa491d03b975b844b76cedba35d8d885ddb2825e31fd5c101bd9e9a215520bb8cdddeb6ab2cf2dc86065179477d80f733016929d7334cdfdf818c1378a4b9428fa1ee2e525321f905d0b949d3abc9e93d3f30b077795338bd55c28a1ced134bb2d575bfa44b2fd8cf1d5c54168a12a1d6c511f62ca973cdb704c233487e1fd39e5adc8870af352ec3c6a6a64152fc82a1c16ecc43d1d5817f76a1b46a5fab9db8923311edd3cc032fed7eb6252e77db69d7bf9ee35dc4ddd0fbdb9a76afe25a82f4495aa4f072cef9b1247cb368bcc8677565a47095242702e6341281f506805e20e8c89e9af28adff21c804c70cab10ee2fe5212ec07987d13e7d4b60529611e4d33a062d724cdfb16cdc48b964ba07dfa2620d5a8805d0be93380850c66f3fada059802a5946bfe3b0b10e19a8289ec01f6514abb883bb53c49dadbba42d412ea264c8a5122fda1ea9b742289642b0ea34ceb76ae8256a97845d37594cfbff8c7a4430176223bacc3bef395ceda13fd211c71":"010001":MBEDTLS_MD_SHA384:MBEDTLS_MD_SHA384:"692acaaf5e277cdd4b3fdc0a1ff1785bfd28a3a8ec1bc97fd072ff6c99aade77baba92efdcf72e66d43542fdd32fb0e2dd29bb167dd36174b671ebef3c39c21be5fc84ef5a0957c9124f7eb281c12ae38cff9289413245c6c537bff88d013b3dd138c9373e26a00cecd4b5b18f708d69f1f24f88a0001d7de30ea40ff3c9f2e7":"6f2841166a64471d4f0b8ed0dbb7db32161da13b3fe26ee600cfb2d187384e529f280485cf84830af8cb015878cb7c4c74ad6ab38fd8998fa74b612e84af8123d785a8a60a2bb002f7b15a6f7cd6bbf18325a412fd3ea2a48903d30db2543089d9d82fe304dfe5fb903f6a0d1625fe994aa2ac47e04eeb6a51be770312a88cec80bbcf849ab57f2af4e9370a0e35a458d8509fb89e8b22ef499af25c427e48c2391747d3ccc6fdc1b035cbbe6a6f1742bfb6fb5d411d4c8bb73ee7f9bc2fbcf54603c813c9c6d479fb9f38650f4fa8ce05a32c47c078d278b7b97173e82d692e303141faf71573f2b5ab58c4fa009200a3be47633719dbeed24d61ba7acae8abfc2aa5f33f18e6f4c43eb8be3e4bbee1090544401e202ef06d90aae75a939256bd374afc5030f1146ea9d2acf4918dfe96d13eb5f16da55efd504657e3d8aea010f89c60288d74963746422bd7cf":"57a5511992b30d39e150b6a7a760a74136db0a24bc635f3a700a74f865a7c9c0ed2e2e196022a6d17ad7c2d3f12946828458015beffb0c0652de2cc9c3366aaeb7634c5d6ccbdf6c7c93b8feff21a7d2831ac3ee73fd98f9c972dcb833ac61323b77ec249db0e4fb9bf33c71aef9d2aaef40aafab2cb3870f0224c8d0c3ada2abb9d3dd601a038594d290177277a8b791ebcc211d7e5379323a633c62fe9cc2394bd7a977a604122ee9799e5368cc17e1af1795046e76899aa6e7be8f27b1a3e96daa81784d967e9a36cf1912936d7ae11f80aed79c27c53237e7fa009daf9240fb205f83e8c6f8f57d3c3520e0e60213a203432c18d92979b13555ce6eab075ddb38b6d820e378ac4e3afcb3d57e5c6d3c11f165745996fdb61e36b842c6ec81d6437073fe9fc96a4dbc3b188ca766a7f7ef786f39729cadcc5700fb0fffeca0eb0bc47243783f129917948df9bee23da83fadadfa87708e0a839a62965a5d2b9a7cd16b4675cef6afc8fbc2615d97d11ede47f4dfd83e74847dc184ccdc4fd":334:0
+
+RSASSA-PSS Signature RSA-3072, SHA-384, Salt Length max + 1
+depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+pkcs1_rsassa_pss_sign:3072:"ca7b50c5f65f2115fea7691f7d90c124866e774e68e9eb89306538956fc217593d46017b7dd7942d636e384a34c802a14d5fd9916798d7d6193ef1a29e2fdbefd955261496d8ac9713922d43bfc43a7a410752ccbc854cc85268f411e793f9b5279007bbcaca30fb16fd9033a6ea31566b4f2c27f0161107e2cd890bcf563a522ee0eb96a016e9007595a94172a4aeded11fadcb8ab5f03cd154f8b8e0e0666ff62b1ccda02599ea44bbfcfaea541a5ac26bf267a56a8177a50f6b87b460a54d":"c591723042d4b8737f4ef9dfeb40c6d62d439ee8688158a4be24c0ad130f851113cc53d776c63cd782b95ccfd266bdb2578b78439c121de34e8955a7fbd2c6ae1a1c37b24c12f5dce15175dd9e203a3abd5bf9e736b1fc183d10c4540c5cf2cbe26768e94c1eab2ba3008b32d6d50716699c6bfcbec5bbeb94a054dbcd16d10f74972ca5fe53256cd0ade8f502eceaed633414a9bdb623035a234f65c6662a23d792cc0eeb21a1f55ebca26ffa1c56c96fbb7d870fc3ffb181de8398238ab1b5":"9c43ef522cab18022297d3d70fa491d03b975b844b76cedba35d8d885ddb2825e31fd5c101bd9e9a215520bb8cdddeb6ab2cf2dc86065179477d80f733016929d7334cdfdf818c1378a4b9428fa1ee2e525321f905d0b949d3abc9e93d3f30b077795338bd55c28a1ced134bb2d575bfa44b2fd8cf1d5c54168a12a1d6c511f62ca973cdb704c233487e1fd39e5adc8870af352ec3c6a6a64152fc82a1c16ecc43d1d5817f76a1b46a5fab9db8923311edd3cc032fed7eb6252e77db69d7bf9ee35dc4ddd0fbdb9a76afe25a82f4495aa4f072cef9b1247cb368bcc8677565a47095242702e6341281f506805e20e8c89e9af28adff21c804c70cab10ee2fe5212ec07987d13e7d4b60529611e4d33a062d724cdfb16cdc48b964ba07dfa2620d5a8805d0be93380850c66f3fada059802a5946bfe3b0b10e19a8289ec01f6514abb883bb53c49dadbba42d412ea264c8a5122fda1ea9b742289642b0ea34ceb76ae8256a97845d37594cfbff8c7a4430176223bacc3bef395ceda13fd211c71":"010001":MBEDTLS_MD_SHA384:MBEDTLS_MD_SHA384:"692acaaf5e277cdd4b3fdc0a1ff1785bfd28a3a8ec1bc97fd072ff6c99aade77baba92efdcf72e66d43542fdd32fb0e2dd29bb167dd36174b671ebef3c39c21be5fc84ef5a0957c9124f7eb281c12ae38cff9289413245c6c537bff88d013b3dd138c9373e26a00cecd4b5b18f708d69f1f24f88a0001d7de30ea40ff3c9f2e7":"6f2841166a64471d4f0b8ed0dbb7db32161da13b":"":335:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
+
+RSASSA-PSS Sign. RSA-520 SHA-512: Salt Len. 0, no possible salt size
+depends_on:MBEDTLS_SHA512_C
+pkcs1_rsassa_pss_sign:520:"0feea5f6220fac291b9508ec2ba8ed281eb39aee4d5dc693254106816ebc700ecf":"0d68918785c3aafe31eaaa2d8d8156dce645940ff7734a457337a51bd00bc88811":"00d5a06f86e5b9d87428540165ca966fa8893a62e2a59d0bfd7617780bb039f9165a373a8e119d0766f8de556710f33f67019153bad8223775e797d451d48206f3bf":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd00":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"":0:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
+
+RSASSA-PSS Sign. RSA-528 SHA-512: Salt Len. 0, only room for empty salt
+depends_on:MBEDTLS_SHA512_C
+pkcs1_rsassa_pss_sign:528:"00d272aa28ed2085ac6df3c05c6719eed5deb618afa2e4ca4a6f7330b430ad48672d":"00c578836bab27145db9dd66f17470b62d4a6100f8ca0dedf457ee3639c3b9596325":"00a2554eba715bf66e5ecdf3d6d718e3e5d907e8666e7bf5a76b415106e04eb827ec4cb2199cff66491d45419082059aa5b54b0cf5eef4443402f3047c0b0e6f025081":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd00":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"5bf02a1ff652052be266d0630fb802bde71d363904e2e001267dba592c88e755befb9b8004ecf1c5de07ad8cd260ede04971b201d524434e657396d6bfd8917def84":0:0
+
+RSASSA-PSS Sign. RSA-528 SHA-512: Salt Len. 1, only room for empty salt
+depends_on:MBEDTLS_SHA512_C
+pkcs1_rsassa_pss_sign:528:"00d272aa28ed2085ac6df3c05c6719eed5deb618afa2e4ca4a6f7330b430ad48672d":"00c578836bab27145db9dd66f17470b62d4a6100f8ca0dedf457ee3639c3b9596325":"00a2554eba715bf66e5ecdf3d6d718e3e5d907e8666e7bf5a76b415106e04eb827ec4cb2199cff66491d45419082059aa5b54b0cf5eef4443402f3047c0b0e6f025081":"010001":MBEDTLS_MD_SHA512:MBEDTLS_MD_SHA512:"d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd32a7c8a05bbc90d32c49d436e99569fd00":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"":1:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
+
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_pkcs1_v21.function b/third_party/mbedtls/repo/tests/suites/test_suite_pkcs1_v21.function
index c28cf08..c23a4ad 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_pkcs1_v21.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_pkcs1_v21.function
@@ -9,9 +9,8 @@
  */
 
 /* BEGIN_CASE */
-void pkcs1_rsaes_oaep_encrypt( int mod, int radix_N, char * input_N,
-                               int radix_E, char * input_E, int hash,
-                               data_t * message_str, data_t * rnd_buf,
+void pkcs1_rsaes_oaep_encrypt( int mod, data_t * input_N, data_t * input_E,
+                               int hash, data_t * message_str, data_t * rnd_buf,
                                data_t * result_str, int result )
 {
     unsigned char output[256];
@@ -19,6 +18,8 @@
     mbedtls_test_rnd_buf_info info;
     mbedtls_mpi N, E;
 
+    info.fallback_f_rng = mbedtls_test_rnd_std_rand;
+    info.fallback_p_rng = NULL;
     info.buf = rnd_buf->x;
     info.length = rnd_buf->len;
 
@@ -26,8 +27,8 @@
     mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V21, hash );
     memset( output, 0x00, sizeof( output ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &N, input_N->x, input_N->len ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &E, input_E->x, input_E->len ) == 0 );
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, NULL, NULL, NULL, &E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( ( mod + 7 ) / 8 ) );
     TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == 0 );
@@ -41,8 +42,7 @@
                                             output ) == result );
     if( result == 0 )
     {
-        TEST_ASSERT( mbedtls_test_hexcmp( output, result_str->x,
-                                          ctx.len, result_str->len ) == 0 );
+        ASSERT_COMPARE( output, ctx.len, result_str->x, result_str->len );
     }
 
 exit:
@@ -52,11 +52,9 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void pkcs1_rsaes_oaep_decrypt( int mod, int radix_P, char * input_P,
-                               int radix_Q, char * input_Q, int radix_N,
-                               char * input_N, int radix_E, char * input_E,
-                               int hash, data_t * result_str,
-                               char * seed, data_t * message_str,
+void pkcs1_rsaes_oaep_decrypt( int mod, data_t * input_P, data_t * input_Q,
+                               data_t * input_N, data_t * input_E, int hash,
+                               data_t * result_str, char * seed, data_t * message_str,
                                int result )
 {
     unsigned char output[64];
@@ -74,10 +72,10 @@
     memset( output, 0x00, sizeof( output ) );
     memset( &rnd_info, 0, sizeof( mbedtls_test_rnd_pseudo_info ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &P, input_P->x, input_P->len ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &Q, input_Q->x, input_Q->len ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &N, input_N->x, input_N->len ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &E, input_E->x, input_E->len ) == 0 );
 
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, &P, &Q, NULL, &E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( ( mod + 7 ) / 8 ) );
@@ -104,9 +102,7 @@
                                                 sizeof( output ) ) == result );
         if( result == 0 )
         {
-            TEST_ASSERT( mbedtls_test_hexcmp( output, result_str->x,
-                                              output_len,
-                                              result_str->len ) == 0 );
+            ASSERT_COMPARE( output, output_len, result_str->x, result_str->len );
         }
     }
 
@@ -118,18 +114,20 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void pkcs1_rsassa_pss_sign( int mod, int radix_P, char * input_P, int radix_Q,
-                            char * input_Q, int radix_N, char * input_N,
-                            int radix_E, char * input_E, int digest, int hash,
-                            data_t * message_str, data_t * rnd_buf,
-                            data_t * result_str, int result )
+void pkcs1_rsassa_pss_sign( int mod, data_t * input_P, data_t * input_Q,
+                            data_t * input_N, data_t * input_E, int digest,
+                            int hash, data_t * message_str, data_t * rnd_buf,
+                            data_t * result_str, int fixed_salt_length,
+                            int result )
 {
     unsigned char hash_result[MBEDTLS_MD_MAX_SIZE];
-    unsigned char output[256];
+    unsigned char output[512];
     mbedtls_rsa_context ctx;
     mbedtls_test_rnd_buf_info info;
     mbedtls_mpi N, P, Q, E;
 
+    info.fallback_f_rng = mbedtls_test_rnd_std_rand;
+    info.fallback_p_rng = NULL;
     info.buf = rnd_buf->x;
     info.length = rnd_buf->len;
 
@@ -140,28 +138,39 @@
     memset( hash_result, 0x00, sizeof( hash_result ) );
     memset( output, 0x00, sizeof( output ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &P, input_P->x, input_P->len ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &Q, input_Q->x, input_Q->len ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &N, input_N->x, input_N->len ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &E, input_E->x, input_E->len ) == 0 );
 
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, &P, &Q, NULL, &E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( ( mod + 7 ) / 8 ) );
     TEST_ASSERT( mbedtls_rsa_complete( &ctx ) == 0 );
     TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx ) == 0 );
 
-
     if( mbedtls_md_info_from_type( digest ) != NULL )
         TEST_ASSERT( mbedtls_md( mbedtls_md_info_from_type( digest ), message_str->x, message_str->len, hash_result ) == 0 );
 
-    TEST_ASSERT( mbedtls_rsa_pkcs1_sign( &ctx, &mbedtls_test_rnd_buffer_rand,
-                                         &info, MBEDTLS_RSA_PRIVATE, digest, 0,
-                                         hash_result, output ) == result );
+    if (fixed_salt_length == MBEDTLS_RSA_SALT_LEN_ANY)
+    {
+        TEST_ASSERT( mbedtls_rsa_pkcs1_sign( &ctx, &mbedtls_test_rnd_buffer_rand,
+                                             &info, MBEDTLS_RSA_PRIVATE, digest, 0,
+                                             hash_result, output ) == result );
+        if( result == 0 )
+        {
+            ASSERT_COMPARE( output, ctx.len, result_str->x, result_str->len );
+        }
+
+        info.buf = rnd_buf->x;
+        info.length = rnd_buf->len;
+    }
+
+    TEST_ASSERT( mbedtls_rsa_rsassa_pss_sign_ext( &ctx, &mbedtls_test_rnd_buffer_rand,
+                                                  &info, digest, 0, hash_result,
+                                                  fixed_salt_length, output ) == result );
     if( result == 0 )
     {
-
-        TEST_ASSERT( mbedtls_test_hexcmp( output, result_str->x,
-                                          ctx.len, result_str->len ) == 0 );
+        ASSERT_COMPARE( output, ctx.len, result_str->x, result_str->len );
     }
 
 exit:
@@ -172,10 +181,9 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void pkcs1_rsassa_pss_verify( int mod, int radix_N, char * input_N,
-                              int radix_E, char * input_E, int digest,
-                              int hash, data_t * message_str, char * salt,
-                              data_t * result_str, int result )
+void pkcs1_rsassa_pss_verify( int mod, data_t * input_N, data_t * input_E,
+                              int digest, int hash, data_t * message_str,
+                              char * salt, data_t * result_str, int result )
 {
     unsigned char hash_result[MBEDTLS_MD_MAX_SIZE];
     mbedtls_rsa_context ctx;
@@ -186,8 +194,8 @@
     mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V21, hash );
     memset( hash_result, 0x00, sizeof( hash_result ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &N, input_N->x, input_N->len ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &E, input_E->x, input_E->len ) == 0 );
 
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, NULL, NULL, NULL, &E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( ( mod + 7 ) / 8 ) );
@@ -206,8 +214,7 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void pkcs1_rsassa_pss_verify_ext( int mod, int radix_N, char * input_N,
-                                  int radix_E, char * input_E,
+void pkcs1_rsassa_pss_verify_ext( int mod, data_t * input_N, data_t * input_E,
                                   int msg_digest_id, int ctx_hash,
                                   int mgf_hash, int salt_len,
                                   data_t * message_str,
@@ -223,8 +230,8 @@
     mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V21, ctx_hash );
     memset( hash_result, 0x00, sizeof( hash_result ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &N, input_N->x, input_N->len ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_read_binary( &E, input_E->x, input_E->len ) == 0 );
 
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, NULL, NULL, NULL, &E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( ( mod + 7 ) / 8 ) );
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_pkparse.data b/third_party/mbedtls/repo/tests/suites/test_suite_pkparse.data
index 91d5197..4964bfa 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_pkparse.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_pkparse.data
@@ -989,7 +989,7 @@
 pk_parse_public_keyfile_ec:"data_files/ec_bp512_pub.pem":0
 
 Parse EC Key #1 (SEC1 DER)
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 pk_parse_keyfile_ec:"data_files/ec_prv.sec1.der":"NULL":0
 
 Parse EC Key #2 (SEC1 PEM)
@@ -1005,15 +1005,15 @@
 pk_parse_keyfile_ec:"data_files/ec_prv.pk8.der":"NULL":0
 
 Parse EC Key #4a (PKCS8 DER, no public key)
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
 pk_parse_keyfile_ec:"data_files/ec_prv.pk8nopub.der":"NULL":0
 
 Parse EC Key #4b (PKCS8 DER, no public key, with parameters)
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
 pk_parse_keyfile_ec:"data_files/ec_prv.pk8nopubparam.der":"NULL":0
 
 Parse EC Key #4c (PKCS8 DER, with parameters)
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
 pk_parse_keyfile_ec:"data_files/ec_prv.pk8param.der":"NULL":0
 
 Parse EC Key #5 (PKCS8 PEM)
@@ -1069,7 +1069,7 @@
 pk_parse_keyfile_ec:"data_files/ec_bp512_prv.pem":"NULL":0
 
 Parse EC Key #15 (SEC1 DER, secp256k1, SpecifiedECDomain)
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256K1_ENABLED:MBEDTLS_PK_PARSE_EC_EXTENDED
+depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256K1_ENABLED:MBEDTLS_PK_PARSE_EC_EXTENDED
 pk_parse_keyfile_ec:"data_files/ec_prv.specdom.der":"NULL":0
 
 Key ASN1 (No data)
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto.data b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto.data
index f267c15..c666d4a 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto.data
@@ -1,33 +1,6 @@
 PSA compile-time sanity checks
 static_checks:
 
-PSA key attributes structure
-attributes_set_get:0xffff1234:0x6963:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:128
-
-PSA key attributes: id only
-persistence_attributes:0x1234:0x5678:-1:-1:0:0x1234:0x5678:PSA_KEY_LIFETIME_PERSISTENT
-
-PSA key attributes: lifetime=3 only
-persistence_attributes:-1:0:3:-1:0:0:0:3
-
-PSA key attributes: id then back to volatile
-persistence_attributes:0x1234:0x5678:PSA_KEY_LIFETIME_VOLATILE:-1:0:0:0x5678:PSA_KEY_LIFETIME_VOLATILE
-
-PSA key attributes: id then back to non local volatile
-persistence_attributes:0x1234:0x5678:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_VOLATILE,1):-1:0:0:0x5678:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_VOLATILE,1)
-
-PSA key attributes: id then lifetime
-persistence_attributes:0x1234:0x5678:3:-1:0:0x1234:0x5678:3
-
-PSA key attributes: lifetime then id
-persistence_attributes:0x1234:0x5678:3:0x1235:0x5679:0x1235:0x5679:3
-
-PSA key attributes: non local volatile lifetime then id
-persistence_attributes:0x1234:0x5678:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_VOLATILE,3):0x1235:0x5679:0x1235:0x5679:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_PERSISTENT,3)
-
-PSA key attributes: slot number
-slot_number_attribute:
-
 PSA import/export raw: 1 bytes
 import_export:"2a":PSA_KEY_TYPE_RAW_DATA:PSA_KEY_USAGE_EXPORT:0:8:0:PSA_SUCCESS:1
 
@@ -38,120 +11,114 @@
 import_export:"2a2b":PSA_KEY_TYPE_RAW_DATA:PSA_KEY_USAGE_EXPORT:0:16:-1:PSA_ERROR_BUFFER_TOO_SMALL:1
 
 PSA import/export AES-128
-depends_on:MBEDTLS_AES_C
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 import_export:"0123456789abcdef0123456789abcdef":PSA_KEY_TYPE_AES:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:128:0:PSA_SUCCESS:1
 
 PSA import/export AES-192
-depends_on:MBEDTLS_AES_C
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 import_export:"0123456789abcdef0123456789abcdef0123456789abcdef":PSA_KEY_TYPE_AES:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:192:0:PSA_SUCCESS:1
 
 PSA import/export AES-256
-depends_on:MBEDTLS_AES_C
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 import_export:"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef":PSA_KEY_TYPE_AES:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:256:0:PSA_SUCCESS:1
 
 PSA import: bad usage flag
 import_with_policy:PSA_KEY_TYPE_RAW_DATA:0x40000000:0:PSA_ERROR_INVALID_ARGUMENT
 
-PSA import: invalid type (0)
-import_with_policy:PSA_KEY_TYPE_NONE:0:0:PSA_ERROR_NOT_SUPPORTED
-
-PSA import: invalid type (PSA_KEY_TYPE_CATEGORY_MASK)
-import_with_policy:PSA_KEY_TYPE_CATEGORY_MASK:0:0:PSA_ERROR_NOT_SUPPORTED
-
 PSA import AES: bad key size
-depends_on:MBEDTLS_AES_C
+depends_on:PSA_WANT_KEY_TYPE_AES
 import_with_data:"0123456789abcdef":PSA_KEY_TYPE_AES:0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import/export RSA public key: good, 1024-bit
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:0:PSA_SUCCESS:1
 
 PSA import/export RSA public key: good, larger buffer (+1 byte)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:1:PSA_SUCCESS:1
 
 PSA import/export RSA public key: good, larger buffer (*2-1)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:161:PSA_SUCCESS:1
 
 PSA import/export RSA public key: good, larger buffer (*2)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:162:PSA_SUCCESS:1
 
 PSA import/export RSA public key: good, larger buffer (*2+1)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:163:PSA_SUCCESS:1
 
 PSA import/export RSA public key: export buffer too small
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:-1:PSA_ERROR_BUFFER_TOO_SMALL:1
 
 PSA import/export RSA keypair: good, 1024-bit
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:0:PSA_SUCCESS:1
 
 PSA import/export RSA keypair: good, larger buffer (+1 byte)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:1:PSA_SUCCESS:1
 
 PSA import/export RSA keypair: good, larger buffer (*2-1)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:609:PSA_SUCCESS:1
 
 PSA import/export RSA keypair: good, larger buffer (*2)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:610:PSA_SUCCESS:1
 
 PSA import/export RSA keypair: good, larger buffer (*2+1)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:611:PSA_SUCCESS:1
 
 PSA import/export RSA keypair: export buffer too small
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:-1:PSA_ERROR_BUFFER_TOO_SMALL:1
 
 PSA import/export RSA keypair: trailing garbage ignored
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b2400":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:-1:PSA_SUCCESS:0
 
 PSA import RSA keypair: truncated
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 import_with_data:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import RSA keypair: public key
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 import_with_data:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import RSA public key: key pair
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C
 import_with_data:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b":PSA_KEY_TYPE_RSA_PUBLIC_KEY:0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import RSA keypair: valid key but EC
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 import_with_data:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import/export-public RSA public key: good, 1024-bit
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export_public_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0:PSA_SUCCESS:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001"
 
 PSA import/export-public RSA keypair: good, 1024-bit
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export_public_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0:PSA_SUCCESS:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001"
 
 PSA import/export-public RSA public key: buffer too small
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export_public_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:-1:PSA_ERROR_BUFFER_TOO_SMALL:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001"
 
 PSA import/export-public RSA keypair: buffer too small
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export_public_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:-1:PSA_ERROR_BUFFER_TOO_SMALL:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001"
 
 PSA import/export RSA public key: 1016-bit (good)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export:"30818802818000cde684f1aee96917b89c8a0a72523cfce4686ed5a5fbd32abab12038fc75148e45314b7e31fe60d8258e7e78234a23df0f00cc20fd008b64cb5b0f4ced8c47aa048f767f859961adc22b3df14e63bd9e08c9707bbf4e0eba32b1cc35a020e7e815ca47e0d39601a80d683ab4a07f4d3a7acebaba6c87d25bce2d091ee115c50203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1016:0:PSA_SUCCESS:1
 
 PSA import/export RSA keypair: 1016-bit (good)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export:"3082025802010002818000cde684f1aee96917b89c8a0a72523cfce4686ed5a5fbd32abab12038fc75148e45314b7e31fe60d8258e7e78234a23df0f00cc20fd008b64cb5b0f4ced8c47aa048f767f859961adc22b3df14e63bd9e08c9707bbf4e0eba32b1cc35a020e7e815ca47e0d39601a80d683ab4a07f4d3a7acebaba6c87d25bce2d091ee115c50203010001028180009dd9c34411e769a540e7e9c03682abb4e95ad2d5c2297c6b7eb2fa5415dfa081adb42bff344ea36a31e8bb36593fa69e843f053fa916f8c6ae4c423fa4c1edbcfa7e8079bc19a738f4f861c198cf277d2c89fe3deab06db5a3a09f8d1622033a618fbfbab92b50a13f77cdb53b56d38bec4cdd8cbe65e8b30ab4e77565842102400eec9285833f973372458f354bff7d35bcb04f3b26f5b58a025887a966ca951b6667651a46034bbc99f9d688dfbcb4297a4d86824dd73abdfa7deeb232b1642902400dcbe74d51f3b93afe2a22e2be0c3c56911ef771fd8eb01f64d95d018315baf4144aeb957be95a77f17f2b8a12c2d3b87a1281f9c66d839fa603fbbe7381783d0240035398154a7c1227d580cbbb05859d532d0bdf9d3fc1e5052e20ad9c84dd02ff6884037527c5f44bc5c67a9b67c39824e6ae011d6a5c5f2b997a188a7fe22a810240076bf41ec5023e57bcd87ff1c7d89f30d65a793469f933478021ea056135f45f4ef74aaa1c8158b883422cf2d6cad5c83c6aee5ea65ecd5ab99d14f4cc000ee5024006d13905db5556627066596da3383458aea6ba5e2f94ccc5b922117a1ed3ae7a26c59e68c3885a41b366f1a5c8bff7ec8853ef8d32addb818141352b2da553dc":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1016:0:PSA_SUCCESS:1
 
 PSA import RSA public key: 1022-bit (not supported)
@@ -171,121 +138,121 @@
 import_with_data:"3082025a0201000281806c49704e91f3df44fc99e9b3c0fee5025cc04d09529a1dd05754f2da2751d7a9aa5a79f7070132f2c47b31963e37cd74675f9c93ee7c85a143fefe303e94d1ee0e4d30898d17ab3a229e8457ef21fd179039f748305babe7f134f6d58ce5d721a1a5da98f63503d2466c6a515e53494a41180a91e535bd5b55d4dce2c17419870203010001028180491b277413fb35efe82dace68b544a9dd6aa8917d329731955ec66ec3b0178fcf5a29196e1a6c093bf6c8064b36a8f0d9840a78003d11392754a70a77788975515a1442a6c806cafa2f07fe99cac78a86fa868888d654cec4baf205352cf8255acaa47e2455f23b58c0e5ae43fa297bbffe5b970caa80f71e82084fd35425479024100ef27f3fb2df90ac4910ed95fdde4877d09b0dc4e95079f12a7e2041300a8884a39372a1c79691338cd5c3965bcf3a24f2ce9e10de19d4cb87c7546d60ca0aa0d024073e9e1283475e9ab3075da0b005ca7c7b05e76325f8deb648238831c8353041d594307f784cd527cfee9187b997713d71c0ff98f01beac4d1a85583be52e90e302402f0c801e311c2677274671933f96fee4a56c6adaf6ccaa09c4875d5fd3a8542fadf3e14ffabea62e6d90302688b6b17ebc0a42e1353a79e66d6db102d9371e5d02406731ef3c8607fbf266806590a9cfd3a79a435ee355e2d9906fc6b4236c5f3a288ed178844a7d295512f49ed15b3d82325e4f729478af3262aa9bd083f273d49502410090a32c0e8ca3bcd4c66f092cdc369cd1abb4a05b9a6f0e65e5a51da1d96d5aca8c1525b3f11322c0588062fc8592ebf25b7950f918d39018e82b8acccc8f7e7a":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_NOT_SUPPORTED
 
 PSA import/export EC secp224r1 key pair: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP224R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_224
 import_export:"6849f97d1066f6997759637c7e3899464cee3ec7ac970653a0be0742":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA_ANY:224:0:PSA_SUCCESS:1
 
 PSA import/export-public EC secp224r1: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP224R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_224
 import_export_public_key:"6849f97d1066f6997759637c7e3899464cee3ec7ac970653a0be0742":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_ECDSA_ANY:0:PSA_SUCCESS:"041693a290f7f0b571fe2b41d5d84b01327631f4a860f995fa332c097f54192bb10f00113f2affb13c1a24ce44914571a95440ae014a00cbf7"
 
 PSA import/export EC secp256r1 key pair: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_256
 import_export:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA_ANY:256:0:PSA_SUCCESS:1
 
 PSA import/export-public EC secp256r1: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_256
 import_export_public_key:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_ECDSA_ANY:0:PSA_SUCCESS:"047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45"
 
 PSA import/export EC secp384r1 key pair: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_384
 import_export:"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA_ANY:384:0:PSA_SUCCESS:1
 
 PSA import/export-public EC secp384r1: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_384
 import_export_public_key:"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_ECDSA_ANY:0:PSA_SUCCESS:"04d9c662b50ba29ca47990450e043aeaf4f0c69b15676d112f622a71c93059af999691c5680d2b44d111579db12f4a413a2ed5c45fcfb67b5b63e00b91ebe59d09a6b1ac2c0c4282aa12317ed5914f999bc488bb132e8342cc36f2ca5e3379c747"
 
 PSA import/export EC secp521r1 key pair: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_521
 import_export:"01b1b6ad07bb79e7320da59860ea28e055284f6058f279de666e06d435d2af7bda28d99fa47b7dd0963e16b0073078ee8b8a38d966a582f46d19ff95df3ad9685aae":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA_ANY:521:0:PSA_SUCCESS:1
 
 PSA import/export-public EC secp521r1: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_521
 import_export_public_key:"01b1b6ad07bb79e7320da59860ea28e055284f6058f279de666e06d435d2af7bda28d99fa47b7dd0963e16b0073078ee8b8a38d966a582f46d19ff95df3ad9685aae":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_ECDSA_ANY:0:PSA_SUCCESS:"04001de142d54f69eb038ee4b7af9d3ca07736fd9cf719eb354d69879ee7f3c136fb0fbf9f08f86be5fa128ec1a051d3e6c643e85ada8ffacf3663c260bd2c844b6f5600cee8e48a9e65d09cadd89f235dee05f3b8a646be715f1f67d5b434e0ff23a1fc07ef7740193e40eeff6f3bcdfd765aa9155033524fe4f205f5444e292c4c2f6ac1"
 
 PSA import/export EC brainpool256r1 key pair: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP256R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_BRAINPOOL_P_R1_256
 import_export:"2161d6f2db76526fa62c16f356a80f01f32f776784b36aa99799a8b7662080ff":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA_ANY:256:0:PSA_SUCCESS:1
 
 PSA import/export-public EC brainpool256r1: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP256R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_BRAINPOOL_P_R1_256
 import_export_public_key:"2161d6f2db76526fa62c16f356a80f01f32f776784b36aa99799a8b7662080ff":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):PSA_ALG_ECDSA_ANY:0:PSA_SUCCESS:"04768c8cae4abca6306db0ed81b0c4a6215c378066ec6d616c146e13f1c7df809b96ab6911c27d8a02339f0926840e55236d3d1efbe2669d090e4c4c660fada91d"
 
 PSA import/export EC brainpool384r1 key pair: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP384R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_BRAINPOOL_P_R1_384
 import_export:"3dd92e750d90d7d39fc1885cd8ad12ea9441f22b9334b4d965202adb1448ce24c5808a85dd9afc229af0a3124f755bcb":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA_ANY:384:0:PSA_SUCCESS:1
 
 PSA import/export-public EC brainpool384r1: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP384R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_BRAINPOOL_P_R1_384
 import_export_public_key:"3dd92e750d90d7d39fc1885cd8ad12ea9441f22b9334b4d965202adb1448ce24c5808a85dd9afc229af0a3124f755bcb":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):PSA_ALG_ECDSA_ANY:0:PSA_SUCCESS:"04719f9d093a627e0d350385c661cebf00c61923566fe9006a3107af1d871bc6bb68985fd722ea32be316f8e783b7cd1957785f66cfc0cb195dd5c99a8e7abaa848553a584dfd2b48e76d445fe00dd8be59096d877d4696d23b4bc8db14724e66a"
 
 PSA import/export EC brainpool512r1 key pair: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP512R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_BRAINPOOL_P_R1_512
 import_export:"372c9778f69f726cbca3f4a268f16b4d617d10280d79a6a029cd51879fe1012934dfe5395455337df6906dc7d6d2eea4dbb2065c0228f73b3ed716480e7d71d2":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA_ANY:512:0:PSA_SUCCESS:1
 
 PSA import/export-public EC brainpool512r1: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP512R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_BRAINPOOL_P_R1_512
 import_export_public_key:"372c9778f69f726cbca3f4a268f16b4d617d10280d79a6a029cd51879fe1012934dfe5395455337df6906dc7d6d2eea4dbb2065c0228f73b3ed716480e7d71d2":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):PSA_ALG_ECDSA_ANY:0:PSA_SUCCESS:"0438b7ec92b61c5c6c7fbc28a4ec759d48fcd4e2e374defd5c4968a54dbef7510e517886fbfc38ea39aa529359d70a7156c35d3cbac7ce776bdb251dd64bce71234424ee7049eed072f0dbc4d79996e175d557e263763ae97095c081e73e7db2e38adc3d4c9a0487b1ede876dc1fca61c902e9a1d8722b8612928f18a24845591a"
 
 PSA import/export EC curve25519 key pair: good (already properly masked)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_MONTGOMERY_255
 import_export:"70076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c6a":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDH:255:0:PSA_SUCCESS:1
 
 PSA import/export EC curve25519 key pair: unmasked input (check export-import-export yields properly masked output)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_MONTGOMERY_255
 import_export:"77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDH:255:0:PSA_SUCCESS:0
 
 PSA import/export-public EC curve25519: accept unmasked input
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_MONTGOMERY_255
 import_export_public_key:"77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):PSA_ALG_ECDH:0:PSA_SUCCESS:"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"
 
 PSA import/export-public EC curve25519: accept masked input
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_MONTGOMERY_255
 import_export_public_key:"70076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c6a":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):PSA_ALG_ECDH:0:PSA_SUCCESS:"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"
 
 PSA import/export-public: cannot export-public a symmetric key
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
-import_export_public_key:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:PSA_ALG_CBC_NO_PADDING:0:PSA_ERROR_INVALID_ARGUMENT:""
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
+import_export_public_key:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:PSA_ALG_CBC_NO_PADDING:0:PSA_ERROR_INVALID_ARGUMENT:"2b7e151628aed2a6abf7158809cf4f3c"
 
 PSA import/export EC secp256r1 public key: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_256
 import_export:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA_ANY:256:0:PSA_SUCCESS:1
 
 PSA import/export EC secp521r1 public key: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_521
 import_export:"04001de142d54f69eb038ee4b7af9d3ca07736fd9cf719eb354d69879ee7f3c136fb0fbf9f08f86be5fa128ec1a051d3e6c643e85ada8ffacf3663c260bd2c844b6f5600cee8e48a9e65d09cadd89f235dee05f3b8a646be715f1f67d5b434e0ff23a1fc07ef7740193e40eeff6f3bcdfd765aa9155033524fe4f205f5444e292c4c2f6ac1":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA_ANY:521:0:PSA_SUCCESS:1
 
 PSA import/export EC brainpoolP256r1 public key: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP256R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_BRAINPOOL_P_R1_256
 import_export:"04768c8cae4abca6306db0ed81b0c4a6215c378066ec6d616c146e13f1c7df809b96ab6911c27d8a02339f0926840e55236d3d1efbe2669d090e4c4c660fada91d":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA_ANY:256:0:PSA_SUCCESS:1
 
 PSA import/export curve25519 public key: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_MONTGOMERY_255
 import_export:"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_MONTGOMERY):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDH:255:0:PSA_SUCCESS:1
 
 PSA import/export AES key: policy forbids export
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 import_export:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:128:0:PSA_ERROR_NOT_PERMITTED:1
 
 PSA import/export HMAC key: policy forbids export
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
 import_export:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_HMAC:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_HMAC(PSA_ALG_SHA_256):256:0:PSA_ERROR_NOT_PERMITTED:1
 
 PSA import/export RSA keypair: policy forbids export (crypt)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:1024:0:PSA_ERROR_NOT_PERMITTED:1
 
 PSA import/export RSA keypair: policy forbids export (sign)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:0:PSA_ERROR_NOT_PERMITTED:1
 
 # Test PEM import. Note that this is not a PSA feature, it's an Mbed TLS
 # extension which we may drop in the future.
 PSA import/export RSA public key: import PEM
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PEM_PARSE_C:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export:"2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d4947664d413047435371475349623344514542415155414134474e4144434269514b4267514376425830356275685074312f6274634b7850482f6c706c53710a69714a4843315165346636777353306c7835635255784a4a34524b574b41517475376242494e46454e5354765441357548596c57377249486576456a536433750a355553447641624378686c497a514b7941756557727232553036664c2b466e43775947634d6b79344b357a545474346d4f69712f2f6b637a384865476e6f5a670a3939614454615539615137336d46397277774944415141420a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a00":PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:0:PSA_SUCCESS:0
 
 PSA import/export RSA keypair: import PEM
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PEM_PARSE_C:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b2400":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1024:0:PSA_SUCCESS:0
 
 PSA import: reject raw data key of length 0
@@ -300,68 +267,86 @@
 # The spec allows either INVALID_ARGUMENT or NOT_SUPPORTED
 import_with_data:"":PSA_KEY_TYPE_RAW_DATA:8:PSA_ERROR_INVALID_ARGUMENT
 
-PSA import EC keypair: DER format
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-import_with_data:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):0:PSA_ERROR_INVALID_ARGUMENT
+PSA import EC keypair: explicit bit-size=255 for secp256r1
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+import_with_data:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):255:PSA_ERROR_NOT_SUPPORTED
 
-PSA import EC keypair: too short
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-import_with_data:"0123456789abcdef0123456789abcdef":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):0:PSA_ERROR_INVALID_ARGUMENT
+PSA import EC keypair: explicit bit-size=521 for secp521r1 (good)
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_521
+import_with_data:"01b1b6ad07bb79e7320da59860ea28e055284f6058f279de666e06d435d2af7bda28d99fa47b7dd0963e16b0073078ee8b8a38d966a582f46d19ff95df3ad9685aae":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):521:PSA_SUCCESS
 
-PSA import EC keypair: public key
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-import_with_data:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):0:PSA_ERROR_INVALID_ARGUMENT
+PSA import EC keypair: explicit bit-size=528 for secp521r1 (bad)
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_521
+import_with_data:"01b1b6ad07bb79e7320da59860ea28e055284f6058f279de666e06d435d2af7bda28d99fa47b7dd0963e16b0073078ee8b8a38d966a582f46d19ff95df3ad9685aae":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):528:PSA_ERROR_NOT_SUPPORTED
+
+PSA import EC keypair: explicit bit-size, DER format
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+import_with_data:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ERROR_INVALID_ARGUMENT
+
+PSA import EC keypair: explicit bit-size, too short
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+import_with_data:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13e":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ERROR_INVALID_ARGUMENT
+
+PSA import EC keypair: explicit bit-size, too long (00 start)
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+import_with_data:"0049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ERROR_INVALID_ARGUMENT
+
+PSA import EC keypair: explicit bit-size, too long (00 end)
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+import_with_data:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee00":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ERROR_INVALID_ARGUMENT
+
+PSA import EC keypair: explicit bit-size, public key
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+import_with_data:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ERROR_INVALID_ARGUMENT
+
+PSA import EC keypair: implicit bit-size, not a valid length
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+import_with_data:"0123456789abcdef0123456789abcdef":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):0:PSA_ERROR_NOT_SUPPORTED
 
 PSA import EC keypair: secp256r1, all-bits-zero (bad)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 import_with_data:"0000000000000000000000000000000000000000000000000000000000000000":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import EC keypair: secp256r1, d == n - 1 (good)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 import_with_data:"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):0:PSA_SUCCESS
 
 PSA import EC keypair: secp256r1, d == n (bad)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 import_with_data:"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import EC keypair: secp256r1, d > n (bad)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 import_with_data:"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import EC public key: key pair
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 import_with_data:"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):0:PSA_ERROR_INVALID_ARGUMENT
 
-PSA import EC keypair: valid key but RSA
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP512R1_ENABLED:MBEDTLS_RSA_C
-import_with_data:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):0:PSA_ERROR_INVALID_ARGUMENT
-
 PSA import AES: bits=0 ok
-depends_on:MBEDTLS_AES_C
+depends_on:PSA_WANT_KEY_TYPE_AES
 import_with_data:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:0:PSA_SUCCESS
 
 PSA import AES: bits=128 ok
-depends_on:MBEDTLS_AES_C
+depends_on:PSA_WANT_KEY_TYPE_AES
 import_with_data:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:128:PSA_SUCCESS
 
 PSA import AES: bits=256 wrong
-depends_on:MBEDTLS_AES_C
+depends_on:PSA_WANT_KEY_TYPE_AES
 import_with_data:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:256:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import AES: bits=256 ok
-depends_on:MBEDTLS_AES_C
+depends_on:PSA_WANT_KEY_TYPE_AES
 import_with_data:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:256:PSA_SUCCESS
 
 PSA import AES: bits=128 wrong
-depends_on:MBEDTLS_AES_C
+depends_on:PSA_WANT_KEY_TYPE_AES
 import_with_data:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:128:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import large key: raw, 65528 bits (ok)
-depends_on:HAVE_RAM_AVAILABLE_128K
 import_large_key:PSA_KEY_TYPE_RAW_DATA:8191:PSA_SUCCESS
 
 PSA import large key: raw, 65536 bits (not supported)
-depends_on:HAVE_RAM_AVAILABLE_128K
 import_large_key:PSA_KEY_TYPE_RAW_DATA:8192:PSA_ERROR_NOT_SUPPORTED
 
 PSA import RSA key pair: maximum size exceeded
@@ -373,413 +358,742 @@
 import_rsa_made_up:PSA_VENDOR_RSA_MAX_KEY_BITS+8:0:PSA_ERROR_NOT_SUPPORTED
 
 PSA key policy: AES ECB
-depends_on:MBEDTLS_AES_C
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
 check_key_policy:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_ECB_NO_PADDING
 
 PSA key policy: AES CBC
-depends_on:MBEDTLS_AES_C
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
 check_key_policy:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CBC_NO_PADDING
 
-PSA key policy: ECC SECP256R1, sign
-depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+PSA key policy: ECC SECP256R1, SIGN_HASH -> SIGN_HASH+MESSAGE
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
 check_key_policy:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ):256:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDSA_ANY
 
-PSA key policy: ECC SECP256R1, sign+verify
-depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+PSA key policy: ECC SECP256R1, VERIFY_HASH -> VERIFY_HASH+MESSAGE
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+check_key_policy:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ):256:PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY
+
+PSA key policy: ECC SECP256R1, SIGN+VERIFY_HASH -> {SIGN,VERIFY}_{HASH,MESSAGE}
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
 check_key_policy:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ):256:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY
 
+PSA key policy: ECC SECP256R1, {SIGN,VERIFY}_{HASH,MESSAGE}
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+check_key_policy:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ):256:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA_ANY
+
+PSA key policy: ECC SECP256R1, SIGN_MESSAGE
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+check_key_policy:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ):256:PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256)
+
+PSA key policy: ECC SECP256R1, VERIFY_MESSAGE
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+check_key_policy:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ):256:PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256)
+
+PSA key policy: ECC SECP256R1, SIGN+VERIFY_MESSAGE
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+check_key_policy:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ):256:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256)
+
 Key attributes initializers zero properly
 key_attributes_init:
 
-PSA key policy: MAC, sign | verify
-depends_on:MBEDTLS_SHA256_C
-mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256)
+PSA key policy: MAC, SIGN_HASH -> SIGN_HASH+MESSAGE
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_SUCCESS:PSA_ERROR_NOT_PERMITTED
 
-PSA key policy: MAC, wrong algorithm
-depends_on:MBEDTLS_SHA256_C
-mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_224)
+PSA key policy: MAC, VERIFY_HASH -> VERIFY_HASH+MESSAGE
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_ERROR_NOT_PERMITTED:PSA_SUCCESS
 
-PSA key policy: MAC, alg=0 in policy
-depends_on:MBEDTLS_SHA256_C
-mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:0:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256)
+PSA key policy: MAC, SIGN+VERIFY_HASH -> {SIGN,VERIFY}_{HASH,MESSAGE}
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_SUCCESS:PSA_SUCCESS
 
-PSA key policy: MAC, ANY_HASH in policy is not meaningful
-depends_on:MBEDTLS_SHA256_C
-mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_HMAC(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256)
+PSA key policy: MAC, {SIGN,VERIFY}_{HASH,MESSAGE}
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_SUCCESS:PSA_SUCCESS
 
-PSA key policy: MAC, sign but not verify
-depends_on:MBEDTLS_SHA256_C
-mac_key_policy:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256)
+PSA key policy: MAC, SIGN_MESSAGE
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_SUCCESS:PSA_ERROR_NOT_PERMITTED
 
-PSA key policy: MAC, verify but not sign
-depends_on:MBEDTLS_SHA256_C
-mac_key_policy:PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256)
+PSA key policy: MAC, VERIFY_MESSAGE
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_ERROR_NOT_PERMITTED:PSA_SUCCESS
+
+PSA key policy: MAC, SIGN+VERIFY_MESSAGE
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_SUCCESS:PSA_SUCCESS
 
 PSA key policy: MAC, neither sign nor verify
-depends_on:MBEDTLS_SHA256_C
-mac_key_policy:0:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:0:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_ERROR_NOT_PERMITTED:PSA_ERROR_NOT_PERMITTED
+
+PSA key policy: MAC, wrong algorithm
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_224):PSA_ERROR_NOT_PERMITTED:PSA_ERROR_NOT_PERMITTED
+
+PSA key policy: MAC, alg=0 in policy
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_ERROR_NOT_PERMITTED:PSA_ERROR_NOT_PERMITTED
+
+PSA key policy: MAC, ANY_HASH in policy is not meaningful
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_HMAC(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_ERROR_NOT_PERMITTED:PSA_ERROR_NOT_PERMITTED
+
+PSA key policy: HMAC, sign-verify, tag length > min-length policy
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 30):PSA_SUCCESS:PSA_SUCCESS
+
+PSA key policy: HMAC, sign-verify, tag length = min-length policy
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):PSA_SUCCESS:PSA_SUCCESS
+
+PSA key policy: HMAC, sign-verify, tag length < min-length policy
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 10):PSA_ERROR_NOT_PERMITTED:PSA_ERROR_NOT_PERMITTED
+
+PSA key policy: CMAC, sign-verify, tag length > min-length policy
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CMAC, 10):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, 16):PSA_SUCCESS:PSA_SUCCESS
+
+PSA key policy: CMAC, sign-verify, tag length = min-length policy
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CMAC, 10):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, 10):PSA_SUCCESS:PSA_SUCCESS
+
+PSA key policy: CMAC, sign-verify, tag length < min-length policy
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CMAC, 10):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, 8):PSA_ERROR_NOT_PERMITTED:PSA_ERROR_NOT_PERMITTED
+
+PSA key policy: HMAC, sign-verify, default tag length > min-length policy
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 31):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_SUCCESS:PSA_SUCCESS
+
+PSA key policy: HMAC, sign-verify, default tag length = min-length policy
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 32):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_SUCCESS:PSA_SUCCESS
+
+PSA key policy: HMAC, sign-verify, default tag length < min-length policy
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 33):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_ERROR_NOT_PERMITTED:PSA_ERROR_NOT_PERMITTED
+
+PSA key policy: HMAC, sign-verify, min-length policy, unmatched base alg
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, 20):PSA_ERROR_NOT_PERMITTED:PSA_ERROR_NOT_PERMITTED
+
+PSA key policy: HMAC, sign-verify, min-length policy, unmatched base alg (different hash base)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_224), 20):PSA_ERROR_NOT_PERMITTED:PSA_ERROR_NOT_PERMITTED
+
+PSA key policy: HMAC, sign-verify, min-length policy, unmatched base alg (different algorithm)
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 10):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_CMAC:PSA_ERROR_NOT_PERMITTED:PSA_ERROR_NOT_PERMITTED
+
+PSA key policy: HMAC, sign-verify, min-length policy used as algorithm
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):PSA_ERROR_INVALID_ARGUMENT:PSA_ERROR_INVALID_ARGUMENT
+
+PSA key policy: HMAC, sign-verify, tag length > exact-length policy
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 10):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):PSA_ERROR_NOT_PERMITTED:PSA_ERROR_NOT_PERMITTED
+
+PSA key policy: HMAC, sign-verify, tag length = exact-length policy
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):PSA_SUCCESS:PSA_SUCCESS
+
+PSA key policy: HMAC, sign-verify, tag length < exact-length policy
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+mac_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 10):PSA_ERROR_NOT_PERMITTED:PSA_ERROR_NOT_PERMITTED
 
 PSA key policy: cipher, encrypt | decrypt
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 cipher_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_CTR
 
 PSA key policy: cipher, wrong algorithm
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR:MBEDTLS_CIPHER_MODE_CBC
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 cipher_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_CBC_NO_PADDING
 
 PSA key policy: cipher, encrypt but not decrypt
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 cipher_key_policy:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_CTR
 
 PSA key policy: cipher, decrypt but not encrypt
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 cipher_key_policy:PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_CTR
 
 PSA key policy: cipher, neither encrypt nor decrypt
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 cipher_key_policy:0:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_CTR
 
 PSA key policy: cipher, alg=0 in policy
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 cipher_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_CTR
 
 PSA key policy: AEAD, encrypt | decrypt
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:16:PSA_ALG_CCM
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:16:PSA_ALG_CCM:PSA_SUCCESS
 
 PSA key policy: AEAD, wrong algorithm
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C:MBEDTLS_GCM_C
-aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":16:16:PSA_ALG_GCM
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":16:16:PSA_ALG_GCM:PSA_ERROR_NOT_PERMITTED
 
 PSA key policy: AEAD, alg=0 in policy
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":16:16:PSA_ALG_CCM
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":16:16:PSA_ALG_CCM:PSA_ERROR_NOT_PERMITTED
 
 PSA key policy: AEAD, encrypt but not decrypt
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_key_policy:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:16:PSA_ALG_CCM
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:16:PSA_ALG_CCM:PSA_SUCCESS
 
 PSA key policy: AEAD, decrypt but not encrypt
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_key_policy:PSA_KEY_USAGE_DECRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:16:PSA_ALG_CCM
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_DECRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:16:PSA_ALG_CCM:PSA_SUCCESS
 
 PSA key policy: AEAD, neither encrypt nor decrypt
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_key_policy:0:PSA_ALG_CCM:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:16:PSA_ALG_CCM
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:0:PSA_ALG_CCM:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:16:PSA_ALG_CCM:PSA_ERROR_NOT_PERMITTED
+
+PSA key policy: AEAD, tag length > min-length policy, CCM
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 4):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:8:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 8):PSA_SUCCESS
+
+PSA key policy: AEAD, tag length = min-length policy, CCM
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 4):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:4:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 4):PSA_SUCCESS
+
+PSA key policy: AEAD, tag length < min-length policy, CCM
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:4:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 4):PSA_ERROR_NOT_PERMITTED
+
+PSA key policy: AEAD, tag length > min-length policy, GCM
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_GCM, 4):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":12:8:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 8):PSA_SUCCESS
+
+PSA key policy: AEAD, tag length = min-length policy, GCM
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_GCM, 4):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":12:4:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 4):PSA_SUCCESS
+
+PSA key policy: AEAD, tag length < min-length policy, GCM
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_GCM, 8):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":12:4:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 4):PSA_ERROR_NOT_PERMITTED
+
+PSA key policy: AEAD, default tag length > min-length policy
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:16:PSA_ALG_CCM:PSA_SUCCESS
+
+PSA key policy: AEAD, default tag length = min-length policy
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 16):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:16:PSA_ALG_CCM:PSA_SUCCESS
+
+PSA key policy: AEAD, default tag length < min-length policy
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 17):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:16:PSA_ALG_CCM:PSA_ERROR_NOT_PERMITTED
+
+PSA key policy: AEAD, min-length policy, unmatched base alg
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 4):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:4:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 4):PSA_ERROR_NOT_PERMITTED
+
+PSA key policy: AEAD, min-length policy used as algorithm
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:8:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):PSA_ERROR_NOT_SUPPORTED
+
+PSA key policy: AEAD, tag length > exact-length policy
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 4):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:8:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 8):PSA_ERROR_NOT_PERMITTED
+
+PSA key policy: AEAD, tag length = exact-length policy
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 4):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:4:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 4):PSA_SUCCESS
+
+PSA key policy: AEAD, tag length < exact-length policy
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 8):PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":13:4:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 4):PSA_ERROR_NOT_PERMITTED
 
 PSA key policy: asymmetric encryption, encrypt | decrypt
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
 asymmetric_encryption_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_CRYPT
 
 PSA key policy: asymmetric encryption, wrong algorithm (v1.5/OAEP)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_MD_C
 asymmetric_encryption_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256)
 
 PSA key policy: asymmetric encryption, wrong algorithm (OAEP with different hash)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_224:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_MD_C
 asymmetric_encryption_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_224):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256)
 
 PSA key policy: asymmetric encryption, alg=0 in policy
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
 asymmetric_encryption_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_CRYPT
 
 PSA key policy: asymmetric encryption, ANY_HASH in policy is not meaningful
-depends_on:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_MD_C
 asymmetric_encryption_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_OAEP(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256)
 
 PSA key policy: asymmetric encryption, encrypt but not decrypt
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
 asymmetric_encryption_key_policy:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_CRYPT
 
 PSA key policy: asymmetric encryption, decrypt but not encrypt
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
 asymmetric_encryption_key_policy:PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_CRYPT
 
 PSA key policy: asymmetric encryption, neither encrypt nor decrypt
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
 asymmetric_encryption_key_policy:0:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_CRYPT
 
-PSA key policy: asymmetric signature, sign | verify
-depends_on:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15
-asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1
+PSA key policy: asymmetric signature, sign | verify hash, PKCS#1v1.5 SHA-256
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_MD_C
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):32:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
 
-PSA key policy: asymmetric signature, wrong algorithm family
-depends_on:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
-asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0
+PSA key policy: asymmetric signature, sign | verify hash, PKCS#1v1.5 raw
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_MD_C
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):32:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
 
-PSA key policy: asymmetric signature, wildcard in policy, wrong algorithm family
-depends_on:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
-asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0
+PSA key policy: asymmetric signature, sign | verify hash, ECDSA SHA-256
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_ECDSA(PSA_ALG_SHA_256):32:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
+
+PSA key policy: asymmetric signature, sign, key usage extension
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_MD_C
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):32:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
+
+PSA key policy: asymmetric signature, verify, key usage extension
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_MD_C
+asymmetric_signature_key_policy:PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):32:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE
+
+PSA key policy: asymmetric signature, sign | verify, key usage extension
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_MD_C
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):32:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
+
+PSA key policy: asymmetric signature, wrong alg family (PSS std/any salt)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
+
+PSA key policy: asymmetric signature, wrong alg family (PSS any/std salt)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
+
+PSA key policy: asymmetric signature, wrong alg family (RSA v15/PSS)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
+
+PSA key policy: asymmetric signature, wildcard in policy, wrong alg family
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA key policy: asymmetric signature, wildcard in policy, ECDSA SHA-256
-depends_on:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_ECDSA(PSA_ALG_SHA_256):32
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_ECDSA(PSA_ALG_SHA_256):32:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA key policy: asymmetric signature, wildcard in policy, PKCS#1v1.5 SHA-256
-depends_on:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):32
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_MD_C
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):32:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA key policy: asymmetric signature, wildcard in policy, PKCS#1v1.5 raw
-depends_on:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_MD_C
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA key policy: asymmetric signature, wrong hash algorithm
-depends_on:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
-asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_384):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA key policy: asymmetric signature, alg=0 in policy
-depends_on:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15
-asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_MD_C
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA key policy: asymmetric signature, sign but not verify
-depends_on:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15
-asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_MD_C
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):32:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
 
 PSA key policy: asymmetric signature, verify but not sign
-depends_on:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15
-asymmetric_signature_key_policy:PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_MD_C
+asymmetric_signature_key_policy:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):32:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA key policy: asymmetric signature, neither sign nor verify
-depends_on:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15
-asymmetric_signature_key_policy:0:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:1
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_MD_C
+asymmetric_signature_key_policy:0:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):32:0
+
+PSA key policy: msg asymmetric signature, sign | verify
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
+
+PSA key policy: msg asymmetric signature, wrong alg family (PSS std/any salt)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
+
+PSA key policy: msg asymmetric signature, wrong alg family (PSS any/std salt)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
+
+PSA key policy: msg asymmetric signature, wrong alg family (RSA v15/PSS)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
+
+PSA key policy: msg asymmetric signature, wildcard in policy, wrong alg family
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
+
+PSA key policy: msg asymmetric signature, wildcard in policy, ECDSA SHA-256
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_ECDSA(PSA_ALG_SHA_256):32:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
+
+PSA key policy: msg asymmetric signature, wildcard in policy, PKCS#1v1.5 SHA-256
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):32:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
+
+PSA key policy: msg asymmetric signature, wrong hash algorithm
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_384):0:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
+
+PSA key policy: msg asymmetric signature, alg=0 in policy
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
+
+PSA key policy: msg asymmetric signature, sign but not verify
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+asymmetric_signature_key_policy:PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):1:PSA_KEY_USAGE_SIGN_MESSAGE
+
+PSA key policy: msg asymmetric signature, verify but not sign
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+asymmetric_signature_key_policy:PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):1:PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA key policy: derive via HKDF, permitted
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_TYPE_DERIVE:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HKDF(PSA_ALG_SHA_256)
 
 PSA key policy: derive via TLS 1.2 PRF, permitted
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_TYPE_DERIVE:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)
 
 PSA key policy: derive via HKDF, not permitted
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_key_policy:0:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_TYPE_DERIVE:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HKDF(PSA_ALG_SHA_256)
 
 PSA key policy: derive via TLS 1.2 PRF, not permitted
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_key_policy:0:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_TYPE_DERIVE:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)
 
 PSA key policy: derive via HKDF, wrong algorithm
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_224:PSA_WANT_ALG_SHA_256
 derive_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_TYPE_DERIVE:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HKDF(PSA_ALG_SHA_224)
 
 PSA key policy: derive via TLS 1.2 PRF, wrong algorithm
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_224:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_TYPE_DERIVE:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HKDF(PSA_ALG_SHA_224)
 
 PSA key policy: agreement + KDF, permitted
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_SUCCESS
 
 PSA key policy: agreement + KDF, not permitted
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 agreement_key_policy:0:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_ERROR_NOT_PERMITTED
 
 PSA key policy: agreement + KDF, wrong agreement algorithm
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_FFDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_KEY_AGREEMENT(PSA_ALG_FFDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_ERROR_NOT_PERMITTED
 
 PSA key policy: agreement + KDF, wrong KDF algorithm
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_224:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_224)):PSA_ERROR_NOT_PERMITTED
 
 PSA key policy: agreement + KDF, key permits raw agreement
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_SUCCESS
 
 PSA key policy: raw agreement, permitted
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 raw_agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_ECDH:PSA_SUCCESS
 
 PSA key policy: raw agreement, not permitted
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 raw_agreement_key_policy:0:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_ECDH:PSA_ERROR_NOT_PERMITTED
 
 PSA key policy: raw agreement, wrong algorithm
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_FFDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 raw_agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_FFDH:PSA_ERROR_NOT_PERMITTED
 
 PSA key policy: raw agreement, key permits raw agreement, but algorithm is not raw
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C
+depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_ECDH_C
 raw_agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_ERROR_NOT_SUPPORTED
 
 PSA key policy: raw agreement, key specifies KDF
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 raw_agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_ECDH:PSA_ERROR_NOT_PERMITTED
 
 PSA key policy algorithm2: CTR, CBC
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR:MBEDTLS_CIPHER_MODE_CBC
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 key_policy_alg2:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_ALG_CBC_NO_PADDING
 
-PSA key policy algorithm2: ECDH, ECDSA
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_ECDSA_C
-key_policy_alg2:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDH:PSA_ALG_ECDSA_ANY
+PSA key policy algorithm2: ECDH, ECDSA, HASH usage
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+key_policy_alg2:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_SHA_256)
+
+PSA key policy algorithm2: ECDH, ECDSA, HASH+MESSAGE usage
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+key_policy_alg2:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_SHA_256)
+
+PSA key policy algorithm2: ECDH, ECDSA, MESSAGE usage
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+key_policy_alg2:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_SHA_256)
 
 Copy key: raw, 1 byte
 copy_success:PSA_KEY_USAGE_COPY:0:0:PSA_KEY_TYPE_RAW_DATA:"2a":1:-1:-1:0:PSA_KEY_USAGE_COPY:0:0
 
 Copy key: AES, copy attributes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":1:-1:-1:0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0
 
 Copy key: AES, same usage flags
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0
 
 Copy key: AES, fewer usage flags (-EXPORT)
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:0
 
 Copy key: AES, fewer usage flags (-COPY)
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0
 
 Copy key: AES, 1 more usage flag
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:0:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:0
 
 Copy key: AES, 2 more usage flags
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:0:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:0
 
 Copy key: AES, intersect usage flags #1
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:0
 
 Copy key: AES, intersect usage flags #2
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:0:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:0
 
 Copy key: RSA key pair, same usage flags
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_MD_C
+copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
+
+Copy key: RSA key pair, extended usage flags
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_MD_C
+copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
 
 Copy key: RSA key pair, fewer usage flags
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_MD_C
+copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
 
 Copy key: RSA key pair, more usage flags
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_MD_C
+copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
 
 Copy key: RSA key pair, intersect usage flags #0
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:0:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_MD_C
+copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:0:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
 
 Copy key: RSA key pair, intersect usage flags #1
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_MD_C
+copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
 
 Copy key: RSA key pair, wildcard algorithm in source
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_MD_C
+copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
 
 Copy key: RSA key pair, wildcard algorithm in target
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_MD_C
+copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
 
 Copy key: RSA key pair, wildcard algorithm in source and target
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_MD_C
+copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):0
 
 Copy key: source=ECDSA+ECDH, target=ECDSA+ECDH
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
-copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_256
+copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH
+
+Copy key: source=ECDSA+ECDH, target=ECDSA+ECDH, extended usage flags
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_256
+copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH
 
 Copy key: source=ECDSA+ECDH, target=ECDSA+0
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
-copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_256
+copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0
 
 Copy key: source=ECDSA+ECDH, target=0+ECDH
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
-copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT:0:PSA_ALG_ECDH:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE:0:PSA_ALG_ECDH
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_256
+copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT:0:PSA_ALG_ECDH:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DERIVE:0:PSA_ALG_ECDH
 
 Copy key: source=ECDSA(any)+ECDH, target=ECDSA(SHA256)+ECDH
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
-copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_256
+copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH
 
 Copy key: source=ECDH+ECDSA(any), target=ECDH+ECDSA(SHA256)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
-copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_SHA_256)
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_256
+copy_success:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_SHA_256)
 
 Copy fail: raw data, no COPY flag
-copy_fail:PSA_KEY_USAGE_EXPORT:0:0:PSA_KEY_TYPE_RAW_DATA:"404142434445464748494a4b4c4d4e4f":0:0:PSA_KEY_USAGE_EXPORT:0:0:PSA_ERROR_NOT_PERMITTED
+copy_fail:PSA_KEY_USAGE_EXPORT:0:0:PSA_KEY_TYPE_RAW_DATA:"404142434445464748494a4b4c4d4e4f":0:0:PSA_KEY_USAGE_EXPORT:0:0:0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_NOT_PERMITTED
 
 Copy key: AES, no COPY flag
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-copy_fail:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:0:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":0:0:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:0:PSA_ERROR_NOT_PERMITTED
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+copy_fail:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:0:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":0:0:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:0:0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_NOT_PERMITTED
 
 Copy fail: AES, incompatible target policy
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR:MBEDTLS_CIPHER_MODE_CBC
-copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":0:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_CBC_NO_PADDING:0:PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":0:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_CBC_NO_PADDING:0:0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_INVALID_ARGUMENT
+
+Copy key: source=MAC, target=MAC extended usage flags
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+copy_success:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_SHA_256):0:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_SHA_256):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_SHA_256):0
+
+Copy key: source=MAC min-length, target=MAC length > min-length
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+copy_success:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):0:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 24):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 24):0
+
+Copy key: source=MAC min-length, target=MAC length = min-length
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+copy_success:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):0:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):0
+
+Copy fail: source=MAC min-length, target=MAC length < min-length
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+copy_fail:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):0:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_HMAC:256:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 16):0:0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_INVALID_ARGUMENT
+
+Copy key: source=MAC min-length, target=MAC min-length, src > tgt
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+copy_success:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 24):0:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 24):0
+
+Copy key: source=MAC min-length, target=MAC min-length, src = tgt
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+copy_success:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):0:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):0
+
+Copy key: source=MAC min-length, target=MAC min-length, src < tgt
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+copy_success:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):0:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 24):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 24):0
+
+Copy fail: source=MAC, target=MAC min-length > length
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+copy_fail:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):0:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_HMAC:256:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 24):0:0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_INVALID_ARGUMENT
+
+Copy key: source=MAC, target=MAC min-length = length
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+copy_success:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):0:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):0
+
+Copy key: source=MAC, target=MAC min-length < length
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+copy_success:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):0:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 16):0:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 20):0
+
+Copy key: source=AEAD min-length, target=AEAD length > min-length
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+copy_success:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 4):0:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 8):0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 8):0
+
+Copy key: source=AEAD min-length, target=AEAD length = min-length
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+copy_success:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 4):0:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 4):0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 4):0
+
+Copy fail: source=AEAD min-length, target=AEAD length < min-length
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+copy_fail:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):0:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 4):0:0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_INVALID_ARGUMENT
+
+Copy key: source=AEAD min-length, target=AEAD min-length, src > tgt
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+copy_success:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):0:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 4):0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):0
+
+Copy key: source=AEAD min-length, target=AEAD min-length, src = tgt
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+copy_success:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):0:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):0
+
+Copy key: source=AEAD min-length, target=AEAD min-length, src < tgt
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+copy_success:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 4):0:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):0
+
+Copy fail: source=AEAD, target=AEAD min-length > length
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+copy_fail:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 4):0:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):0:0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_INVALID_ARGUMENT
+
+Copy key: source=AEAD, target=AEAD min-length = length
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+copy_success:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 8):0:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 8):0
+
+Copy key: source=AEAD, target=AEAD min-length < length
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+copy_success:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 12):0:PSA_KEY_TYPE_AES:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8):0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 12):0
 
 Copy fail: RSA, incompatible target policy (source wildcard)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
-copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0:PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
+copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0:0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_INVALID_ARGUMENT
 
 Copy fail: RSA, incompatible target policy (target wildcard)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
-copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):0:PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
+copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):0:0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_INVALID_ARGUMENT
 
 Copy fail: RSA, incompatible target policy (source and target wildcard)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
-copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):0:PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
+copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):0:0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_INVALID_ARGUMENT
 
 Copy fail: RSA, ANY_HASH is not meaningful with OAEP
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
-copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_ANY_HASH):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):0:PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
+copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_ANY_HASH):0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):0:0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_INVALID_ARGUMENT
 
 Copy fail: incorrect type in attributes
-copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:0:0:PSA_KEY_TYPE_RAW_DATA:"404142434445464748494a4b4c4d4e4f":PSA_KEY_TYPE_AES:0:PSA_KEY_USAGE_EXPORT:0:0:PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_KEY_TYPE_AES
+copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:0:0:PSA_KEY_TYPE_RAW_DATA:"404142434445464748494a4b4c4d4e4f":PSA_KEY_TYPE_AES:0:PSA_KEY_USAGE_EXPORT:0:0:0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_INVALID_ARGUMENT
 
 Copy fail: incorrect size in attributes
-copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:0:0:PSA_KEY_TYPE_RAW_DATA:"404142434445464748494a4b4c4d4e4f":0:42:PSA_KEY_USAGE_EXPORT:0:0:PSA_ERROR_INVALID_ARGUMENT
+copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT:0:0:PSA_KEY_TYPE_RAW_DATA:"404142434445464748494a4b4c4d4e4f":0:42:PSA_KEY_USAGE_EXPORT:0:0:0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_INVALID_ARGUMENT
 
 Copy fail: source=ECDSA(SHA224)+ECDH, target=ECDSA(SHA256)+ECDH
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
-copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_SHA_224):PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":0:0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH:PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_256
+copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDSA(PSA_ALG_SHA_224):PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":0:0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_ECDH:0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_INVALID_ARGUMENT
 
 Copy fail: source=ECDH+ECDSA(SHA224), target=ECDH+ECDSA(SHA256)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
-copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_SHA_224):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":0:0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_256
+copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_SHA_224):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":0:0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_INVALID_ARGUMENT
+
+Copy fail: AES, invalid persistent key identifier in attributes
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_CRYPTO_STORAGE_C
+copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_TYPE_AES:0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0:0:PSA_KEY_LIFETIME_PERSISTENT:PSA_ERROR_INVALID_ARGUMENT
+
+Copy fail: AES, invalid lifetime (unknown location) in attributes
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_CRYPTO_STORAGE_C
+copy_fail:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_TYPE_AES:0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0:1:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_PERSISTENT, 11):PSA_ERROR_INVALID_ARGUMENT
 
 Hash operation object initializers zero properly
 hash_operation_init:
 
 PSA hash setup: good, SHA-1
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_setup:PSA_ALG_SHA_1:PSA_SUCCESS
 
 PSA hash setup: good, SHA-224
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_setup:PSA_ALG_SHA_224:PSA_SUCCESS
 
 PSA hash setup: good, SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_setup:PSA_ALG_SHA_256:PSA_SUCCESS
 
 PSA hash setup: good, SHA-384
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_setup:PSA_ALG_SHA_384:PSA_SUCCESS
 
 PSA hash setup: good, SHA-512
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_setup:PSA_ALG_SHA_512:PSA_SUCCESS
 
 PSA hash setup: good, MD2
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_setup:PSA_ALG_MD2:PSA_SUCCESS
 
 PSA hash setup: good, MD4
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_setup:PSA_ALG_MD4:PSA_SUCCESS
 
 PSA hash setup: good, MD5
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_setup:PSA_ALG_MD5:PSA_SUCCESS
 
 PSA hash setup: good, RIPEMD160
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_setup:PSA_ALG_RIPEMD160:PSA_SUCCESS
 
 PSA hash setup: bad (unknown hash algorithm)
@@ -791,11 +1105,10 @@
 hash_setup:PSA_ALG_ANY_HASH:PSA_ERROR_NOT_SUPPORTED
 
 PSA hash setup: bad (not a hash algorithm)
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256
 hash_setup:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_ERROR_INVALID_ARGUMENT
 
 PSA hash: bad order function calls
-depends_on:MBEDTLS_SHA256_C
 hash_bad_order:
 
 PSA hash verify: bad arguments
@@ -811,14 +1124,15 @@
 hash_compute_fail:PSA_ALG_ANY_HASH:"":32:PSA_ERROR_NOT_SUPPORTED
 
 PSA hash compute: bad algorithm (not a hash)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256
 hash_compute_fail:PSA_ALG_HMAC(PSA_ALG_SHA_256):"":32:PSA_ERROR_INVALID_ARGUMENT
 
 PSA hash compute: output buffer empty
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_compute_fail:PSA_ALG_SHA_256:"":0:PSA_ERROR_BUFFER_TOO_SMALL
 
 PSA hash compute: output buffer too small
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_compute_fail:PSA_ALG_SHA_256:"":31:PSA_ERROR_BUFFER_TOO_SMALL
 
 PSA hash compare: bad algorithm (unknown hash)
@@ -828,66 +1142,67 @@
 hash_compare_fail:PSA_ALG_ANY_HASH:"":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855":PSA_ERROR_NOT_SUPPORTED
 
 PSA hash compare: bad algorithm (not a hash)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256
 hash_compare_fail:PSA_ALG_HMAC(PSA_ALG_SHA_256):"":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855":PSA_ERROR_INVALID_ARGUMENT
 
 PSA hash compare: hash of a prefix
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_compare_fail:PSA_ALG_SHA_256:"00":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855":PSA_ERROR_INVALID_SIGNATURE
 
 PSA hash compare: hash with flipped bit
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_compare_fail:PSA_ALG_SHA_256:"":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b854":PSA_ERROR_INVALID_SIGNATURE
 
 PSA hash compare: hash with trailing garbage
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_compare_fail:PSA_ALG_SHA_256:"":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85500":PSA_ERROR_INVALID_SIGNATURE
 
 PSA hash compare: truncated hash
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_compare_fail:PSA_ALG_SHA_256:"":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8":PSA_ERROR_INVALID_SIGNATURE
 
 PSA hash compare: empty hash
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_compare_fail:PSA_ALG_SHA_256:"":"":PSA_ERROR_INVALID_SIGNATURE
 
 PSA hash compare: good
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_compare_fail:PSA_ALG_SHA_256:"":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855":PSA_SUCCESS
 
 PSA hash compute: good, SHA-1
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_compute_compare:PSA_ALG_SHA_1:"42749e":"a444319e9b6cc1e8464c511ec0969c37d6bb2619"
 
 PSA hash compute: good, SHA-224
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_compute_compare:PSA_ALG_SHA_224:"50efd0":"b5a9820413c2bf8211fbbf5df1337043b32fa4eafaf61a0c8e9ccede"
 
 PSA hash compute: good, SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_compute_compare:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803"
 
 PSA hash compute: good, SHA-384
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_compute_compare:PSA_ALG_SHA_384:"31f5ca":"78d54b943421fdf7ba90a7fb9637c2073aa480454bd841d39ff72f4511fc21fb67797b652c0c823229342873d3bef955"
 
 PSA hash compute: good, SHA-512
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_compute_compare:PSA_ALG_SHA_512:"de4c90":"33ce98281045a5c4c9df0363d8196f1d7dfcd5ee46ac89776fd8a4344c12f123a66788af5bd41ceff1941aa5637654b4064c88c14e00465ab79a2fc6c97e1014"
 
 PSA hash compute: good, MD2
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_compute_compare:PSA_ALG_MD2:"616263":"da853b0d3f88d99b30283a69e6ded6bb"
 
 PSA hash compute: good, MD4
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_compute_compare:PSA_ALG_MD4:"616263":"a448017aaf21d8525fc10ae87aa6729d"
 
 PSA hash compute: good, MD5
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_compute_compare:PSA_ALG_MD5:"616263":"900150983cd24fb0d6963f7d28e17f72"
 
 PSA hash compute: good, RIPEMD160
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_compute_compare:PSA_ALG_RIPEMD160:"616263":"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"
 
 PSA hash clone: source state
@@ -900,18 +1215,23 @@
 mac_operation_init:
 
 PSA MAC setup: good, HMAC-SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
 mac_setup:PSA_KEY_TYPE_HMAC:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f":PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_SUCCESS
 
 PSA MAC setup: good, AES-CMAC
-depends_on:MBEDTLS_AES_C:MBEDTLS_CMAC_C
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
 mac_setup:PSA_KEY_TYPE_AES:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CMAC:PSA_SUCCESS
 
-PSA MAC setup: bad algorithm (unknown MAC algorithm)
+PSA MAC setup: bad algorithm (HMAC without specified hash)
+# Either INVALID_ARGUMENT or NOT_SUPPORTED would be reasonable here
 mac_setup:PSA_KEY_TYPE_HMAC:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f":PSA_ALG_HMAC(0):PSA_ERROR_NOT_SUPPORTED
 
+PSA MAC setup: bad algorithm (unsupported HMAC hash algorithm)
+depends_on:!PSA_WANT_ALG_MD2
+mac_setup:PSA_KEY_TYPE_HMAC:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f":PSA_ALG_HMAC(PSA_ALG_MD2):PSA_ERROR_NOT_SUPPORTED
+
 PSA MAC setup: bad algorithm (not a MAC algorithm)
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
 mac_setup:PSA_KEY_TYPE_AES:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CBC_NO_PADDING:PSA_ERROR_INVALID_ARGUMENT
 
 PSA MAC setup: truncated MAC too small (1 byte)
@@ -919,227 +1239,242 @@
 mac_setup:PSA_KEY_TYPE_HMAC:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f":PSA_ALG_TRUNCATED_MAC( PSA_ALG_HMAC( PSA_ALG_SHA_256 ), 1 ):PSA_ERROR_NOT_SUPPORTED
 
 PSA MAC setup: truncated MAC too large (33 bytes for SHA-256)
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
 mac_setup:PSA_KEY_TYPE_HMAC:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f":PSA_ALG_TRUNCATED_MAC( PSA_ALG_HMAC( PSA_ALG_SHA_256 ), 33 ):PSA_ERROR_INVALID_ARGUMENT
 
 PSA MAC setup: invalid key type, HMAC-SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256
 mac_setup:PSA_KEY_TYPE_RAW_DATA:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f":PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_ERROR_INVALID_ARGUMENT
 
 PSA MAC setup: incompatible key HMAC for CMAC
-depends_on:MBEDTLS_CMAC_C
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_HMAC
 # Either INVALID_ARGUMENT or NOT_SUPPORTED would be reasonable here
-mac_setup:PSA_KEY_TYPE_HMAC:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CMAC:PSA_ERROR_NOT_SUPPORTED
+mac_setup:PSA_KEY_TYPE_HMAC:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CMAC:PSA_ERROR_INVALID_ARGUMENT
 
 PSA MAC setup: algorithm known but not supported, long key
-depends_on:!MBEDTLS_MD5_C
+depends_on:!PSA_WANT_ALG_MD5
 mac_setup:PSA_KEY_TYPE_HMAC:"000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f":PSA_ALG_HMAC(PSA_ALG_MD5):PSA_ERROR_NOT_SUPPORTED
 
 PSA MAC setup: algorithm known but not supported, short key
-depends_on:!MBEDTLS_MD5_C
+depends_on:!PSA_WANT_ALG_MD5
 mac_setup:PSA_KEY_TYPE_HMAC:"000102030405060708":PSA_ALG_HMAC(PSA_ALG_MD5):PSA_ERROR_NOT_SUPPORTED
 
 PSA MAC: bad order function calls
-depends_on:MBEDTLS_SHA256_C
 mac_bad_order:
 
 PSA MAC sign: RFC4231 Test case 1 - HMAC-SHA-224
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
 mac_sign:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_224):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22"
 
 PSA MAC verify: RFC4231 Test case 1 - HMAC-SHA-224
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_224):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22"
 
 PSA MAC sign: RFC4231 Test case 1 - HMAC-SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
 mac_sign:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_256):"4869205468657265":"b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"
 
 PSA MAC verify: RFC4231 Test case 1 - HMAC-SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_256):"4869205468657265":"b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"
 
 PSA MAC sign: RFC4231 Test case 1 - HMAC-SHA-384
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_HMAC
 mac_sign:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_384):"4869205468657265":"afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6"
 
 PSA MAC verify: RFC4231 Test case 1 - HMAC-SHA-384
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_384):"4869205468657265":"afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6"
 
 PSA MAC sign: RFC4231 Test case 1 - HMAC-SHA-512
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_HMAC
 mac_sign:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_512):"4869205468657265":"87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854"
 
 PSA MAC verify: RFC4231 Test case 1 - HMAC-SHA-512
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_512):"4869205468657265":"87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854"
 
 PSA MAC verify: RFC4231 Test case 2 - HMAC-SHA-224
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"4a656665":PSA_ALG_HMAC(PSA_ALG_SHA_224):"7768617420646f2079612077616e7420666f72206e6f7468696e673f":"a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44"
 
 PSA MAC verify: RFC4231 Test case 2 - HMAC-SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"4a656665":PSA_ALG_HMAC(PSA_ALG_SHA_256):"7768617420646f2079612077616e7420666f72206e6f7468696e673f":"5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"
 
 PSA MAC verify: RFC4231 Test case 2 - HMAC-SHA-384
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"4a656665":PSA_ALG_HMAC(PSA_ALG_SHA_384):"7768617420646f2079612077616e7420666f72206e6f7468696e673f":"af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649"
 
 PSA MAC verify: RFC4231 Test case 2 - HMAC-SHA-512
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"4a656665":PSA_ALG_HMAC(PSA_ALG_SHA_512):"7768617420646f2079612077616e7420666f72206e6f7468696e673f":"164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737"
 
 PSA MAC verify: RFC4231 Test case 3 - HMAC-SHA-224
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_224):"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd":"7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea"
 
 PSA MAC verify: RFC4231 Test case 3 - HMAC-SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd":"773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe"
 
 PSA MAC verify: RFC4231 Test case 3 - HMAC-SHA-384
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_384):"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd":"88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc13814b94e3ab6e101a34f27"
 
 PSA MAC verify: RFC4231 Test case 3 - HMAC-SHA-512
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_512):"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd":"fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb"
 
 PSA MAC verify: RFC4231 Test case 4 - HMAC-SHA-224
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"0102030405060708090a0b0c0d0e0f10111213141516171819":PSA_ALG_HMAC(PSA_ALG_SHA_224):"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd":"6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a"
 
 PSA MAC verify: RFC4231 Test case 4 - HMAC-SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"0102030405060708090a0b0c0d0e0f10111213141516171819":PSA_ALG_HMAC(PSA_ALG_SHA_256):"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd":"82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b"
 
 PSA MAC verify: RFC4231 Test case 4 - HMAC-SHA-384
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"0102030405060708090a0b0c0d0e0f10111213141516171819":PSA_ALG_HMAC(PSA_ALG_SHA_384):"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd":"3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb"
 
 PSA MAC verify: RFC4231 Test case 4 - HMAC-SHA-512
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"0102030405060708090a0b0c0d0e0f10111213141516171819":PSA_ALG_HMAC(PSA_ALG_SHA_512):"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd":"b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd"
 
 PSA MAC verify: RFC4231 Test case 6 - HMAC-SHA-224
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_224):"54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374":"95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e"
 
 PSA MAC verify: RFC4231 Test case 6 - HMAC-SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):"54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374":"60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54"
 
 PSA MAC verify: RFC4231 Test case 6 - HMAC-SHA-384
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_384):"54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374":"4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c60c2ef6ab4030fe8296248df163f44952"
 
 PSA MAC verify: RFC4231 Test case 6 - HMAC-SHA-512
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_512):"54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374":"80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598"
 
 PSA MAC verify: RFC4231 Test case 7 - HMAC-SHA-224
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_224):"5468697320697320612074657374207573696e672061206c6172676572207468616e20626c6f636b2d73697a65206b657920616e642061206c6172676572207468616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565647320746f20626520686173686564206265666f7265206265696e6720757365642062792074686520484d414320616c676f726974686d2e":"3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1"
 
 PSA MAC verify: RFC4231 Test case 7 - HMAC-SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_256):"5468697320697320612074657374207573696e672061206c6172676572207468616e20626c6f636b2d73697a65206b657920616e642061206c6172676572207468616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565647320746f20626520686173686564206265666f7265206265696e6720757365642062792074686520484d414320616c676f726974686d2e":"9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"
 
 PSA MAC verify: RFC4231 Test case 7 - HMAC-SHA-384
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_384):"5468697320697320612074657374207573696e672061206c6172676572207468616e20626c6f636b2d73697a65206b657920616e642061206c6172676572207468616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565647320746f20626520686173686564206265666f7265206265696e6720757365642062792074686520484d414320616c676f726974686d2e":"6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5a678cc31e799176d3860e6110c46523e"
 
 PSA MAC verify: RFC4231 Test case 7 - HMAC-SHA-512
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_ALG_HMAC(PSA_ALG_SHA_512):"5468697320697320612074657374207573696e672061206c6172676572207468616e20626c6f636b2d73697a65206b657920616e642061206c6172676572207468616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565647320746f20626520686173686564206265666f7265206265696e6720757365642062792074686520484d414320616c676f726974686d2e":"e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58"
 
 PSA MAC sign: HMAC-SHA-224, truncated to 28 bytes (actual size)
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
 mac_sign:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_224), 28):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22"
 
 PSA MAC verify: HMAC-SHA-224, truncated to 28 bytes (actual size)
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_224), 28):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22"
 
 PSA MAC sign: HMAC-SHA-512, truncated to 64 bytes (actual size)
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_HMAC
 mac_sign:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_512), 64):"4869205468657265":"87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854"
 
 PSA MAC verify: HMAC-SHA-512, truncated to 64 bytes (actual size)
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_512), 64):"4869205468657265":"87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854"
 
 PSA MAC sign: HMAC-SHA-224, truncated to 27 bytes
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
 mac_sign:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_224), 27):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b"
 
 PSA MAC verify: HMAC-SHA-224, truncated to 27 bytes
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_224), 27):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b"
 
 PSA MAC sign: HMAC-SHA-512, truncated to 63 bytes
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_HMAC
 mac_sign:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_512), 63):"4869205468657265":"87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a1268"
 
 PSA MAC verify: HMAC-SHA-512, truncated to 63 bytes
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_512), 63):"4869205468657265":"87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a1268"
 
 PSA MAC sign: HMAC-SHA-224, truncated to 4 bytes
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
 mac_sign:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_224), 4):"4869205468657265":"896fb112"
 
 PSA MAC verify: HMAC-SHA-224, truncated to 4 bytes
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_224), 4):"4869205468657265":"896fb112"
 
 PSA MAC sign: HMAC-SHA-512, truncated to 4 bytes
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_HMAC
 mac_sign:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_512), 4):"4869205468657265":"87aa7cde"
 
 PSA MAC verify: HMAC-SHA-512, truncated to 4 bytes
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_HMAC
 mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_512), 4):"4869205468657265":"87aa7cde"
 
+PSA MAC sign: CMAC-3DES (CAVP vector #95)
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_DES
+mac_sign:PSA_KEY_TYPE_DES:"7c34e67a2a8fef581cc4f7dceaea130dad52c189739e401f":PSA_ALG_CMAC:"eb3365a0a9d141270334065547418fe64c47823c024082b94d54a66d149f2af1":"e1d7c3736739e726"
+
+PSA MAC verify: CMAC-3DES (CAVP vector #95)
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_DES
+mac_verify:PSA_KEY_TYPE_DES:"7c34e67a2a8fef581cc4f7dceaea130dad52c189739e401f":PSA_ALG_CMAC:"eb3365a0a9d141270334065547418fe64c47823c024082b94d54a66d149f2af1":"e1d7c3736739e726"
+
+PSA MAC: CMAC-3DES-2key (not supported in PSA)
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_DES
+mac_setup:PSA_KEY_TYPE_DES:"89fe91f1c1ef2f01efc4c18f5715894c":PSA_ALG_CMAC:PSA_ERROR_NOT_SUPPORTED
+
+PSA MAC: CMAC-DES (not supported in PSA)
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_DES
+mac_setup:PSA_KEY_TYPE_DES:"89fe91f1c1ef2f01":PSA_ALG_CMAC:PSA_ERROR_NOT_SUPPORTED
+
 PSA MAC sign: CMAC-AES-128
-depends_on:MBEDTLS_CMAC_C:MBEDTLS_AES_C
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
 mac_sign:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_CMAC:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827"
 
 PSA MAC verify: CMAC-AES-128
-depends_on:MBEDTLS_CMAC_C:MBEDTLS_AES_C
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
 mac_verify:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_CMAC:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827"
 
 PSA MAC sign: CMAC-AES-128, truncated to 16 bytes (actual size)
-depends_on:MBEDTLS_CMAC_C:MBEDTLS_AES_C
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
 mac_sign:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, 16):"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827"
 
 PSA MAC verify: CMAC-AES-128, truncated to 16 bytes (actual size)
-depends_on:MBEDTLS_CMAC_C:MBEDTLS_AES_C
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
 mac_verify:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, 16):"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827"
 
 PSA MAC sign: CMAC-AES-128, truncated to 15 bytes
-depends_on:MBEDTLS_CMAC_C:MBEDTLS_AES_C
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
 mac_sign:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, 15):"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c8"
 
 PSA MAC verify: CMAC-AES-128, truncated to 15 bytes
-depends_on:MBEDTLS_CMAC_C:MBEDTLS_AES_C
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
 mac_verify:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, 15):"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c8"
 
 PSA MAC sign: CMAC-AES-128, truncated to 4 bytes
-depends_on:MBEDTLS_CMAC_C:MBEDTLS_AES_C
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
 mac_sign:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, 4):"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747"
 
 PSA MAC verify: CMAC-AES-128, truncated to 4 bytes
-depends_on:MBEDTLS_CMAC_C:MBEDTLS_AES_C
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
 mac_verify:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, 4):"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747"
 
 Cipher operation object initializers zero properly
 cipher_operation_init:
 
 PSA cipher setup: good, AES-CTR
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 cipher_setup:PSA_KEY_TYPE_AES:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CTR:PSA_SUCCESS
 
 PSA cipher setup: bad algorithm (unknown cipher algorithm)
@@ -1147,7 +1482,7 @@
 cipher_setup:PSA_KEY_TYPE_AES:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CATEGORY_CIPHER:PSA_ERROR_NOT_SUPPORTED
 
 PSA cipher setup: bad algorithm (not a cipher algorithm)
-depends_on:MBEDTLS_AES_C
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
 cipher_setup:PSA_KEY_TYPE_AES:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CMAC:PSA_ERROR_INVALID_ARGUMENT
 
 PSA cipher setup: invalid key type, CTR
@@ -1161,331 +1496,531 @@
 cipher_setup:PSA_KEY_TYPE_ARC4:"000102030405060708090a0b0c0d0e0f":PSA_ALG_CTR:PSA_ERROR_NOT_SUPPORTED
 
 PSA cipher: bad order function calls
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
 cipher_bad_order:
 
-PSA symmetric encrypt: AES-ECB, 0 bytes, good
-depends_on:MBEDTLS_AES_C
-cipher_encrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"":"":PSA_SUCCESS
+PSA cipher: incorrect key type (HMAC)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256
+cipher_bad_key:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_KEY_TYPE_HMAC:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
 
-PSA symmetric encrypt: AES-ECB, 16 bytes, good
-depends_on:MBEDTLS_AES_C
-cipher_encrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e117393172a":"3ad77bb40d7a3660a89ecaf32466ef97":PSA_SUCCESS
+PSA cipher: incorrect key type (RSA)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+cipher_bad_key:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24"
 
-PSA symmetric encrypt: AES-ECB, 32 bytes, good
-depends_on:MBEDTLS_AES_C
-cipher_encrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e117393172a3ad77bb40d7a3660a89ecaf32466ef97":"3ad77bb40d7a3660a89ecaf32466ef972249a2638c6f1c755a84f9681a9f08c1":PSA_SUCCESS
+PSA cipher: incorrect key type (ECC Family Sep R1)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+cipher_bad_key:PSA_ALG_ECDSA_ANY:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320"
 
-PSA symmetric encrypt: AES-CBC-nopad, 16 bytes, good
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_encrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"a076ec9dfbe47d52afc357336f20743b":PSA_SUCCESS
+PSA cipher encrypt: without initialization
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_fail:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"":"":PSA_ERROR_BAD_STATE
 
-PSA symmetric encrypt: AES-CBC-PKCS#7, 16 bytes, good
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_encrypt:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"a076ec9dfbe47d52afc357336f20743bca7e8a15dc3c776436314293031cd4f3":PSA_SUCCESS
+PSA cipher encrypt: invalid key type
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING
+cipher_encrypt_fail:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_RAW_DATA:"2b7e151628aed2a6abf7158809cf4f3c":"":PSA_ERROR_NOT_SUPPORTED
 
-PSA symmetric encrypt: AES-CBC-PKCS#7, 15 bytes, good
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_encrypt:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"6279b49d7f7a8dd87b685175d4276e24":PSA_SUCCESS
+PSA cipher encrypt: incompatible key ARC4 for CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_ARC4
+# Either INVALID_ARGUMENT or NOT_SUPPORTED would be reasonable here
+cipher_encrypt_fail:PSA_ALG_CTR:PSA_KEY_TYPE_ARC4:"2b7e151628aed2a6abf7158809cf4f3c":"":PSA_ERROR_NOT_SUPPORTED
+
+PSA cipher encrypt: bad algorithm (unknown cipher algorithm)
+depends_on:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_fail:PSA_ALG_CATEGORY_CIPHER:PSA_KEY_TYPE_RAW_DATA:"2b7e151628aed2a6abf7158809cf4f3c":"":PSA_ERROR_NOT_SUPPORTED
+
+PSA cipher encrypt: bad algorithm (not a cipher algorithm)
+depends_on:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_fail:PSA_ALG_MD4:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":PSA_ERROR_INVALID_ARGUMENT
 
 PSA symmetric encrypt: AES-ECB, input too short (15 bytes)
-depends_on:MBEDTLS_AES_C
-cipher_encrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e11739317":"":PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_fail:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e11739317":PSA_ERROR_INVALID_ARGUMENT
 
 PSA symmetric encrypt: AES-CBC-nopad, input too short
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_encrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee223":"6bc1bee223":PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_fail:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee223":PSA_ERROR_INVALID_ARGUMENT
 
-PSA symmetric encrypt: AES-CTR, 16 bytes, good
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":PSA_SUCCESS
+PSA symmetric encrypt: AES-ECB, 0 bytes, good
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_alg_without_iv:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":""
 
-PSA symmetric encrypt: AES-CTR, 15 bytes, good
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"8f9408fe80a81d3e813da3c7b0b2bd":PSA_SUCCESS
+PSA symmetric encrypt: AES-ECB, 16 bytes, good
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_alg_without_iv:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":"3ad77bb40d7a3660a89ecaf32466ef97"
 
-PSA symmetric encrypt: DES-CBC-nopad, 8 bytes, good
-depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_encrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0e":"2a2a2a2a2a2a2a2a":"eda4011239bc3ac9":"64f917b0152f8f05":PSA_SUCCESS
-
-PSA symmetric encrypt: 2-key 3DES-CBC-nopad, 8 bytes, good
-depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_encrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"2a2a2a2a2a2a2a2a":"eda4011239bc3ac9":"5d0652429c5b0ac7":PSA_SUCCESS
-
-PSA symmetric encrypt: 3-key 3DES-CBC-nopad, 8 bytes, good
-depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_encrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"2a2a2a2a2a2a2a2a":"eda4011239bc3ac9":"817ca7d69b80d86a":PSA_SUCCESS
+PSA symmetric encrypt: AES-ECB, 32 bytes, good
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_alg_without_iv:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a3ad77bb40d7a3660a89ecaf32466ef97":"3ad77bb40d7a3660a89ecaf32466ef972249a2638c6f1c755a84f9681a9f08c1"
 
 PSA symmetric encrypt: 2-key 3DES-ECB, 8 bytes, good
-depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_encrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"":"c78e2b38139610e3":"5d0652429c5b0ac7":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_encrypt_alg_without_iv:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"c78e2b38139610e3":"5d0652429c5b0ac7"
 
 PSA symmetric encrypt: 3-key 3DES-ECB, 8 bytes, good
-depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_encrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"":"c78e2b38139610e3":"817ca7d69b80d86a":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_encrypt_alg_without_iv:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"c78e2b38139610e3":"817ca7d69b80d86a"
 
-PSA symmetric decrypt: AES-ECB, 0 bytes, good
-depends_on:MBEDTLS_AES_C
-cipher_decrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"":"":PSA_SUCCESS
+PSA symmetric encrypt validation: AES-CBC-nopad, 16 bytes, good
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_validation:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a"
 
-PSA symmetric decrypt: AES-ECB, 16 bytes, good
-depends_on:MBEDTLS_AES_C
-cipher_decrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"396ee84fb75fdbb5c2b13c7fe5a654aa":"63cecc46a382414d5fa7d2b79387437f":PSA_SUCCESS
+PSA symmetric encrypt validation: AES-CBC-PKCS#7, 16 bytes, good
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_validation:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a"
 
-PSA symmetric decrypt: AES-ECB, 32 bytes, good
-depends_on:MBEDTLS_AES_C
-cipher_decrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"3ad77bb40d7a3660a89ecaf32466ef972249a2638c6f1c755a84f9681a9f08c1":"6bc1bee22e409f96e93d7e117393172a3ad77bb40d7a3660a89ecaf32466ef97":PSA_SUCCESS
+PSA symmetric encrypt validation: AES-CBC-PKCS#7, 15 bytes, good
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_validation:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e11739317"
 
-PSA symmetric decrypt: AES-CBC-nopad, 16 bytes, good
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_decrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"49e4e66c89a86b67758df89db9ad6955":PSA_SUCCESS
+PSA symmetric encrypt validation: AES-CTR, 16 bytes, good
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_validation:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a"
 
-PSA symmetric decrypt: AES-CBC-PKCS#7, 16 bytes, good
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_decrypt:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743bca7e8a15dc3c776436314293031cd4f3":"6bc1bee22e409f96e93d7e117393172a":PSA_SUCCESS
+PSA symmetric encrypt validation: AES-CTR, 15 bytes, good
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_validation:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e11739317"
 
-PSA symmetric decrypt: AES-CBC-PKCS#7, 15 bytes, good
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_decrypt:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6279b49d7f7a8dd87b685175d4276e24":"6bc1bee22e409f96e93d7e11739317":PSA_SUCCESS
+PSA symmetric encrypt validation: DES-CBC-nopad, 8 bytes, good
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_encrypt_validation:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0e":"eda4011239bc3ac9"
+
+PSA symmetric encrypt validation: 2-key 3DES-CBC-nopad, 8 bytes, good
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_encrypt_validation:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"eda4011239bc3ac9"
+
+PSA symmetric encrypt validation: 3-key 3DES-CBC-nopad, 8 bytes, good
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_encrypt_validation:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"eda4011239bc3ac9"
+
+PSA symmetric encrypt multipart: AES-ECB, 0 bytes, good
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"":0:0:0:"":PSA_SUCCESS
+
+PSA symmetric encrypt multipart: AES-ECB, 16 bytes, good
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"3ad77bb40d7a3660a89ecaf32466ef97":PSA_SUCCESS
+
+PSA symmetric encrypt multipart: AES-ECB, 32 bytes, good
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e117393172a3ad77bb40d7a3660a89ecaf32466ef97":32:32:0:"3ad77bb40d7a3660a89ecaf32466ef972249a2638c6f1c755a84f9681a9f08c1":PSA_SUCCESS
+
+PSA symmetric encrypt multipart: AES-CBC-nopad, 16 bytes, good
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"a076ec9dfbe47d52afc357336f20743b":PSA_SUCCESS
+
+PSA symmetric encrypt multipart: AES-CBC-PKCS#7, 16 bytes, good
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"a076ec9dfbe47d52afc357336f20743bca7e8a15dc3c776436314293031cd4f3":PSA_SUCCESS
+
+PSA symmetric encrypt multipart: AES-CBC-PKCS#7, 15 bytes, good
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":15:0:0:"6279b49d7f7a8dd87b685175d4276e24":PSA_SUCCESS
+
+PSA symmetric encrypt multipart: AES-ECB, input too short (15 bytes)
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e11739317":0:0:0:"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA symmetric encrypt multipart: AES-CBC-nopad, input too short
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee223":0:0:0:"6bc1bee223":PSA_ERROR_INVALID_ARGUMENT
+
+PSA symmetric encrypt multipart: AES-CTR, 16 bytes, good
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"8f9408fe80a81d3e813da3c7b0b2bd32":PSA_SUCCESS
+
+PSA symmetric encrypt multipart: AES-CTR, 15 bytes, good
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":15:15:0:"8f9408fe80a81d3e813da3c7b0b2bd":PSA_SUCCESS
+
+PSA symmetric encrypt multipart: DES-CBC-nopad, 8 bytes, good
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0e":"2a2a2a2a2a2a2a2a":"eda4011239bc3ac9":8:8:0:"64f917b0152f8f05":PSA_SUCCESS
+
+PSA symmetric encrypt multipart: 2-key 3DES-CBC-nopad, 8 bytes, good
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"2a2a2a2a2a2a2a2a":"eda4011239bc3ac9":8:8:0:"5d0652429c5b0ac7":PSA_SUCCESS
+
+PSA symmetric encrypt multipart: 3-key 3DES-CBC-nopad, 8 bytes, good
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"2a2a2a2a2a2a2a2a":"eda4011239bc3ac9":8:8:0:"817ca7d69b80d86a":PSA_SUCCESS
+
+PSA symmetric encrypt multipart: 2-key 3DES-ECB, 8 bytes, good
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_encrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"":"c78e2b38139610e3":8:8:0:"5d0652429c5b0ac7":PSA_SUCCESS
+
+PSA symmetric encrypt multipart: 3-key 3DES-ECB, 8 bytes, good
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_encrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"":"c78e2b38139610e3":8:8:0:"817ca7d69b80d86a":PSA_SUCCESS
+
+PSA cipher decrypt: without initialization
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_fail:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"":"":"":PSA_ERROR_BAD_STATE
+
+PSA cipher decrypt: invalid key type
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING
+cipher_decrypt_fail:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_RAW_DATA:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"":PSA_ERROR_NOT_SUPPORTED
+
+PSA cipher decrypt: incompatible key ARC4 for CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_ARC4
+# Either INVALID_ARGUMENT or NOT_SUPPORTED would be reasonable here
+cipher_decrypt_fail:PSA_ALG_CTR:PSA_KEY_TYPE_ARC4:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"":PSA_ERROR_NOT_SUPPORTED
+
+PSA cipher decrypt: bad algorithm (unknown cipher algorithm)
+cipher_decrypt_fail:PSA_ALG_CATEGORY_CIPHER:PSA_KEY_TYPE_RAW_DATA:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"":PSA_ERROR_NOT_SUPPORTED
+
+PSA cipher decrypt: bad algorithm (not a cipher algorithm)
+depends_on:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_fail:PSA_ALG_MD4:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"":PSA_ERROR_INVALID_ARGUMENT
 
 PSA symmetric decrypt: AES-CBC-PKCS#7, input too short (15 bytes)
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_decrypt:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"49e4e66c89a86b67758df89db9ad6955":PSA_ERROR_INVALID_ARGUMENT
-
-PSA symmetric decrypt: AES-CTR, 16 bytes, good
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_fail:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":PSA_ERROR_INVALID_ARGUMENT
 
 PSA symmetric decrypt: AES-ECB, input too short (15 bytes)
-depends_on:MBEDTLS_AES_C
-cipher_decrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"396ee84fb75fdbb5c2b13c7fe5a654":"63cecc46a382414d5fa7d2b7938743":PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_fail:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"396ee84fb75fdbb5c2b13c7fe5a654":PSA_ERROR_INVALID_ARGUMENT
 
 PSA symmetric decrypt: AES-CBC-nopad, input too short (5 bytes)
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_decrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee223":"6bc1bee223":PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_fail:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee223":PSA_ERROR_INVALID_ARGUMENT
+
+PSA symmetric decrypt: AES-ECB, 0 bytes, good
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"":""
+
+PSA symmetric decrypt: AES-ECB, 16 bytes, good
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"396ee84fb75fdbb5c2b13c7fe5a654aa":"63cecc46a382414d5fa7d2b79387437f"
+
+PSA symmetric decrypt: AES-ECB, 32 bytes, good
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"3ad77bb40d7a3660a89ecaf32466ef972249a2638c6f1c755a84f9681a9f08c1":"6bc1bee22e409f96e93d7e117393172a3ad77bb40d7a3660a89ecaf32466ef97"
+
+PSA symmetric decrypt: AES-CBC-nopad, 16 bytes, good
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"49e4e66c89a86b67758df89db9ad6955"
+
+PSA symmetric decrypt: AES-CBC-PKCS#7, 16 bytes, good
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743bca7e8a15dc3c776436314293031cd4f3":"6bc1bee22e409f96e93d7e117393172a"
+
+PSA symmetric decrypt: AES-CBC-PKCS#7, 15 bytes, good
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6279b49d7f7a8dd87b685175d4276e24":"6bc1bee22e409f96e93d7e11739317"
+
+PSA symmetric decrypt: AES-CTR, 16 bytes, good
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2"
 
 PSA symmetric decrypt: DES-CBC-nopad, 8 bytes, good
-depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_decrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0e":"2a2a2a2a2a2a2a2a":"64f917b0152f8f05":"eda4011239bc3ac9":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_decrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0e":"2a2a2a2a2a2a2a2a":"64f917b0152f8f05":"eda4011239bc3ac9"
 
 PSA symmetric decrypt: 2-key 3DES-CBC-nopad, 8 bytes, good
-depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_decrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"2a2a2a2a2a2a2a2a":"5d0652429c5b0ac7":"eda4011239bc3ac9":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_decrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"2a2a2a2a2a2a2a2a":"5d0652429c5b0ac7":"eda4011239bc3ac9"
 
 PSA symmetric decrypt: 3-key 3DES-CBC-nopad, 8 bytes, good
-depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_decrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"2a2a2a2a2a2a2a2a":"817ca7d69b80d86a":"eda4011239bc3ac9":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_decrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"2a2a2a2a2a2a2a2a":"817ca7d69b80d86a":"eda4011239bc3ac9"
 
 PSA symmetric decrypt: 2-key 3DES-ECB, 8 bytes, good
-depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_decrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"":"5d0652429c5b0ac7":"c78e2b38139610e3":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_decrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"":"5d0652429c5b0ac7":"c78e2b38139610e3"
 
 PSA symmetric decrypt: 3-key 3DES-ECB, 8 bytes, good
-depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_decrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"":"817ca7d69b80d86a":"c78e2b38139610e3":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_decrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"":"817ca7d69b80d86a":"c78e2b38139610e3"
+
+PSA symmetric decrypt multipart: AES-ECB, 0 bytes, good
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"":0:0:0:"":PSA_SUCCESS
+
+PSA symmetric decrypt multipart: AES-ECB, 16 bytes, good
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"396ee84fb75fdbb5c2b13c7fe5a654aa":16:16:0:"63cecc46a382414d5fa7d2b79387437f":PSA_SUCCESS
+
+PSA symmetric decrypt multipart: AES-ECB, 32 bytes, good
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"3ad77bb40d7a3660a89ecaf32466ef972249a2638c6f1c755a84f9681a9f08c1":32:32:0:"6bc1bee22e409f96e93d7e117393172a3ad77bb40d7a3660a89ecaf32466ef97":PSA_SUCCESS
+
+PSA symmetric decrypt multipart: AES-CBC-nopad, 16 bytes, good
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":16:16:0:"49e4e66c89a86b67758df89db9ad6955":PSA_SUCCESS
+
+PSA symmetric decrypt multipart: AES-CBC-PKCS#7, 16 bytes, good
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743bca7e8a15dc3c776436314293031cd4f3":16:0:16:"6bc1bee22e409f96e93d7e117393172a":PSA_SUCCESS
+
+PSA symmetric decrypt multipart: AES-CBC-PKCS#7, 15 bytes, good
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6279b49d7f7a8dd87b685175d4276e24":16:0:0:"6bc1bee22e409f96e93d7e11739317":PSA_SUCCESS
+
+PSA symmetric decrypt multipart: AES-CBC-PKCS#7, input too short (15 bytes)
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":0:0:0:"49e4e66c89a86b67758df89db9ad6955":PSA_ERROR_INVALID_ARGUMENT
+
+PSA symmetric decrypt multipart: AES-CTR, 16 bytes, good
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":16:16:0:"dd3b5e5319b7591daab1e1a92687feb2":PSA_SUCCESS
+
+PSA symmetric decrypt multipart: AES-ECB, input too short (15 bytes)
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"396ee84fb75fdbb5c2b13c7fe5a654":0:0:0:"63cecc46a382414d5fa7d2b7938743":PSA_ERROR_INVALID_ARGUMENT
+
+PSA symmetric decrypt multipart: AES-CBC-nopad, input too short (5 bytes)
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee223":0:0:0:"6bc1bee223":PSA_ERROR_INVALID_ARGUMENT
+
+PSA symmetric decrypt multipart: DES-CBC-nopad, 8 bytes, good
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0e":"2a2a2a2a2a2a2a2a":"64f917b0152f8f05":8:8:0:"eda4011239bc3ac9":PSA_SUCCESS
+
+PSA symmetric decrypt multipart: 2-key 3DES-CBC-nopad, 8 bytes, good
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"2a2a2a2a2a2a2a2a":"5d0652429c5b0ac7":8:8:0:"eda4011239bc3ac9":PSA_SUCCESS
+
+PSA symmetric decrypt multipart: 3-key 3DES-CBC-nopad, 8 bytes, good
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"2a2a2a2a2a2a2a2a":"817ca7d69b80d86a":8:8:0:"eda4011239bc3ac9":PSA_SUCCESS
+
+PSA symmetric decrypt multipart: 2-key 3DES-ECB, 8 bytes, good
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_decrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"":"5d0652429c5b0ac7":8:8:0:"c78e2b38139610e3":PSA_SUCCESS
+
+PSA symmetric decrypt multipart: 3-key 3DES-ECB, 8 bytes, good
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+cipher_decrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"":"817ca7d69b80d86a":8:8:0:"c78e2b38139610e3":PSA_SUCCESS
 
 PSA symmetric encrypt/decrypt: AES-ECB, 16 bytes, good
-depends_on:MBEDTLS_AES_C
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
 cipher_verify_output:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a"
 
 PSA symmetric encrypt/decrypt: AES-CBC-nopad, 16 bytes, good
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
 cipher_verify_output:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a"
 
 PSA symmetric encrypt/decrypt: AES-CBC-PKCS#7, 16 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES
 cipher_verify_output:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a"
 
 PSA symmetric encrypt/decrypt: AES-CBC-PKCS#7, 15 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES
 cipher_verify_output:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e11739317"
 
 PSA symmetric encrypt/decrypt: AES-CTR
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 cipher_verify_output:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a"
 
 PSA symmetric encryption multipart: AES-ECB, 16+16 bytes
-depends_on:MBEDTLS_AES_C
-cipher_encrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c"
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-ECB, 13+19 bytes
-depends_on:MBEDTLS_AES_C
-cipher_encrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":13:0:32:"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c"
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":13:0:32:"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-ECB, 24+12 bytes
-depends_on:MBEDTLS_AES_C
-cipher_encrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":24:16:16:"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c"
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":24:16:16:"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CBC-nopad, 7+9 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":7:0:16:"a076ec9dfbe47d52afc357336f20743b"
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":7:0:16:"a076ec9dfbe47d52afc357336f20743b":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CBC-nopad, 3+13 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":3:0:16:"a076ec9dfbe47d52afc357336f20743b"
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":3:0:16:"a076ec9dfbe47d52afc357336f20743b":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CBC-nopad, 4+12 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":4:0:16:"a076ec9dfbe47d52afc357336f20743b"
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":4:0:16:"a076ec9dfbe47d52afc357336f20743b":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CBC-nopad, 11+5 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":11:0:16:"a076ec9dfbe47d52afc357336f20743b"
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":11:0:16:"a076ec9dfbe47d52afc357336f20743b":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CBC-nopad, 16+16 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"a076ec9dfbe47d52afc357336f20743b89906f2f9207ac02aa658cb4ef19c61f"
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"a076ec9dfbe47d52afc357336f20743b89906f2f9207ac02aa658cb4ef19c61f":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CBC-nopad, 12+20 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":12:0:32:"a076ec9dfbe47d52afc357336f20743b89906f2f9207ac02aa658cb4ef19c61f"
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":12:0:32:"a076ec9dfbe47d52afc357336f20743b89906f2f9207ac02aa658cb4ef19c61f":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CBC-nopad, 20+12 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":20:16:16:"a076ec9dfbe47d52afc357336f20743b89906f2f9207ac02aa658cb4ef19c61f"
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":20:16:16:"a076ec9dfbe47d52afc357336f20743b89906f2f9207ac02aa658cb4ef19c61f":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CTR, 11+5 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":11:11:5:"8f9408fe80a81d3e813da3c7b0b2bd32"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":11:11:5:"8f9408fe80a81d3e813da3c7b0b2bd32":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CTR, 16+16 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CTR, 12+20 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":12:12:20:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":12:12:20:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CTR, 20+12 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":20:20:12:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":20:20:12:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CTR, 12+10 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597":12:12:10:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7b"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597":12:12:10:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7b":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CTR, 0+15 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":0:0:15:"8f9408fe80a81d3e813da3c7b0b2bd"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":0:0:15:"8f9408fe80a81d3e813da3c7b0b2bd":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CTR, 15+0 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":15:15:0:"8f9408fe80a81d3e813da3c7b0b2bd"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":15:15:0:"8f9408fe80a81d3e813da3c7b0b2bd":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CTR, 0+16 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":0:0:16:"8f9408fe80a81d3e813da3c7b0b2bd32"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":0:0:16:"8f9408fe80a81d3e813da3c7b0b2bd32":PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CTR, 16+0 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"8f9408fe80a81d3e813da3c7b0b2bd32"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"8f9408fe80a81d3e813da3c7b0b2bd32":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-ECB, 16+16 bytes
-depends_on:MBEDTLS_AES_C
-cipher_decrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c":16:16:16:"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef"
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c":16:16:16:"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-ECB, 11+21 bytes
-depends_on:MBEDTLS_AES_C
-cipher_decrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c":11:0:32:"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef"
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c":11:0:32:"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-ECB, 28+4 bytes
-depends_on:MBEDTLS_AES_C
-cipher_decrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c":28:16:16:"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef"
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c":28:16:16:"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CBC-nopad, 7+9 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743b":7:0:16:"6bc1bee22e409f96e93d7e117393172a"
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743b":7:0:16:"6bc1bee22e409f96e93d7e117393172a":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CBC-nopad, 3+13 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743b":3:0:16:"6bc1bee22e409f96e93d7e117393172a"
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743b":3:0:16:"6bc1bee22e409f96e93d7e117393172a":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CBC-nopad, 11+5 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743b":11:0:16:"6bc1bee22e409f96e93d7e117393172a"
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743b":11:0:16:"6bc1bee22e409f96e93d7e117393172a":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CBC-nopad, 16+16 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743b89906f2f9207ac02aa658cb4ef19c61f":16:16:16:"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef"
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743b89906f2f9207ac02aa658cb4ef19c61f":16:16:16:"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CBC-nopad, 12+20 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743b89906f2f9207ac02aa658cb4ef19c61f":12:0:32:"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef"
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743b89906f2f9207ac02aa658cb4ef19c61f":12:0:32:"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CBC-nopad, 20+12 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
-cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743b89906f2f9207ac02aa658cb4ef19c61f":20:16:16:"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef"
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743b89906f2f9207ac02aa658cb4ef19c61f":20:16:16:"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 11+5 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":11:11:5:"8f9408fe80a81d3e813da3c7b0b2bd32"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":11:11:5:"8f9408fe80a81d3e813da3c7b0b2bd32":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 16+16 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 12+20 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":12:12:20:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":12:12:20:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 20+12 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":20:20:12:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":20:20:12:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 12+10 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597":12:12:10:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7b"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597":12:12:10:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7b":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 0+15 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":0:0:15:"8f9408fe80a81d3e813da3c7b0b2bd"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":0:0:15:"8f9408fe80a81d3e813da3c7b0b2bd":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 15+0 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":15:15:0:"8f9408fe80a81d3e813da3c7b0b2bd"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":15:15:0:"8f9408fe80a81d3e813da3c7b0b2bd":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 0+16 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":0:0:16:"8f9408fe80a81d3e813da3c7b0b2bd32"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":0:0:16:"8f9408fe80a81d3e813da3c7b0b2bd32":PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 16+0 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"8f9408fe80a81d3e813da3c7b0b2bd32"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"8f9408fe80a81d3e813da3c7b0b2bd32":PSA_SUCCESS
+
+PSA symmetric encrypt/decrypt multipart: AES-ECB, 16 bytes, good
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_verify_output_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":16
+
+PSA symmetric encrypt/decrypt multipart: AES-CBC-nopad, 16 bytes, good
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_verify_output_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":16
+
+PSA symmetric encrypt/decrypt multipart: AES-CBC-PKCS#7, 16 bytes
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES
+cipher_verify_output_multipart:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":16
+
+PSA symmetric encrypt/decrypt multipart: AES-CBC-PKCS#7, 15 bytes
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES
+cipher_verify_output_multipart:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e11739317":15
+
+PSA symmetric encrypt/decrypt multipart: AES-CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_verify_output_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":16
 
 PSA symmetric encrypt/decrypt multipart: AES-CBC-nopad, 11+5 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
 cipher_verify_output_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"a076ec9dfbe47d52afc357336f20743b":11
 
 PSA symmetric encrypt/decrypt multipart: AES-CBC-PKCS#7 padding, 4+12 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES
 cipher_verify_output_multipart:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"a076ec9dfbe47d52afc357336f20743b":4
 
-PSA symmetric encrypt: ChaCha20, K=0 N=0
-depends_on:MBEDTLS_CHACHA20_C
-cipher_encrypt:PSA_ALG_STREAM_CIPHER:PSA_KEY_TYPE_CHACHA20:"0000000000000000000000000000000000000000000000000000000000000000":"000000000000000000000000":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586":PSA_SUCCESS
+PSA symmetric encrypt validation: ChaCha20, K=0 N=0
+depends_on:PSA_WANT_ALG_STREAM_CIPHER:PSA_WANT_KEY_TYPE_CHACHA20
+cipher_encrypt_validation:PSA_ALG_STREAM_CIPHER:PSA_KEY_TYPE_CHACHA20:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
 
-PSA symmetric encrypt: ChaCha20, K=rand N=rand
-depends_on:MBEDTLS_CHACHA20_C
-cipher_encrypt:PSA_ALG_STREAM_CIPHER:PSA_KEY_TYPE_CHACHA20:"4bddc98c551a95395ef719557f813656b566bc45aac04eca3866324cc75489f2":"a170d9349d24955aa4501891":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"9ba7d8de0c6b579fc436e368619e09228070d23246c836d6c6b4c476af6f5eb2b78fbe809d03f7881e6af28cfe3746e8dcf1eb7f762fe7d003141f1539a6cec4":PSA_SUCCESS
+PSA symmetric encrypt validation: ChaCha20, K=rand N=rand
+depends_on:PSA_WANT_ALG_STREAM_CIPHER:PSA_WANT_KEY_TYPE_CHACHA20
+cipher_encrypt_validation:PSA_ALG_STREAM_CIPHER:PSA_KEY_TYPE_CHACHA20:"4bddc98c551a95395ef719557f813656b566bc45aac04eca3866324cc75489f2":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+
+PSA symmetric encrypt multipart: ChaCha20, K=0 N=0
+depends_on:PSA_WANT_ALG_STREAM_CIPHER:PSA_WANT_KEY_TYPE_CHACHA20
+cipher_encrypt_multipart:PSA_ALG_STREAM_CIPHER:PSA_KEY_TYPE_CHACHA20:"0000000000000000000000000000000000000000000000000000000000000000":"000000000000000000000000":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":64:64:0:"76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586":PSA_SUCCESS
+
+PSA symmetric encrypt multipart: ChaCha20, K=rand N=rand
+depends_on:PSA_WANT_ALG_STREAM_CIPHER:PSA_WANT_KEY_TYPE_CHACHA20
+cipher_encrypt_multipart:PSA_ALG_STREAM_CIPHER:PSA_KEY_TYPE_CHACHA20:"4bddc98c551a95395ef719557f813656b566bc45aac04eca3866324cc75489f2":"a170d9349d24955aa4501891":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":64:64:0:"9ba7d8de0c6b579fc436e368619e09228070d23246c836d6c6b4c476af6f5eb2b78fbe809d03f7881e6af28cfe3746e8dcf1eb7f762fe7d003141f1539a6cec4":PSA_SUCCESS
 
 PSA symmetric encryption multipart: ChaCha20, 14+50 bytes
-depends_on:MBEDTLS_CHACHA20_C
-cipher_encrypt_multipart:PSA_ALG_STREAM_CIPHER:PSA_KEY_TYPE_CHACHA20:"4bddc98c551a95395ef719557f813656b566bc45aac04eca3866324cc75489f2":"a170d9349d24955aa4501891":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":14:14:50:"9ba7d8de0c6b579fc436e368619e09228070d23246c836d6c6b4c476af6f5eb2b78fbe809d03f7881e6af28cfe3746e8dcf1eb7f762fe7d003141f1539a6cec4"
+depends_on:PSA_WANT_ALG_STREAM_CIPHER:PSA_WANT_KEY_TYPE_CHACHA20
+cipher_encrypt_multipart:PSA_ALG_STREAM_CIPHER:PSA_KEY_TYPE_CHACHA20:"4bddc98c551a95395ef719557f813656b566bc45aac04eca3866324cc75489f2":"a170d9349d24955aa4501891":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":14:14:50:"9ba7d8de0c6b579fc436e368619e09228070d23246c836d6c6b4c476af6f5eb2b78fbe809d03f7881e6af28cfe3746e8dcf1eb7f762fe7d003141f1539a6cec4":PSA_SUCCESS
 
-PSA symmetric decrypt: ChaCha20, K=rand N=rand
-depends_on:MBEDTLS_CHACHA20_C
-cipher_decrypt:PSA_ALG_STREAM_CIPHER:PSA_KEY_TYPE_CHACHA20:"4bddc98c551a95395ef719557f813656b566bc45aac04eca3866324cc75489f2":"a170d9349d24955aa4501891":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"9ba7d8de0c6b579fc436e368619e09228070d23246c836d6c6b4c476af6f5eb2b78fbe809d03f7881e6af28cfe3746e8dcf1eb7f762fe7d003141f1539a6cec4":PSA_SUCCESS
+PSA symmetric decrypt multipart: ChaCha20, K=rand N=rand
+depends_on:PSA_WANT_ALG_STREAM_CIPHER:PSA_WANT_KEY_TYPE_CHACHA20
+cipher_decrypt_multipart:PSA_ALG_STREAM_CIPHER:PSA_KEY_TYPE_CHACHA20:"4bddc98c551a95395ef719557f813656b566bc45aac04eca3866324cc75489f2":"a170d9349d24955aa4501891":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":64:64:0:"9ba7d8de0c6b579fc436e368619e09228070d23246c836d6c6b4c476af6f5eb2b78fbe809d03f7881e6af28cfe3746e8dcf1eb7f762fe7d003141f1539a6cec4":PSA_SUCCESS
 
 PSA symmetric decryption multipart: ChaCha20, 14+50 bytes
-depends_on:MBEDTLS_CHACHA20_C
-cipher_decrypt_multipart:PSA_ALG_STREAM_CIPHER:PSA_KEY_TYPE_CHACHA20:"4bddc98c551a95395ef719557f813656b566bc45aac04eca3866324cc75489f2":"a170d9349d24955aa4501891":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":14:14:50:"9ba7d8de0c6b579fc436e368619e09228070d23246c836d6c6b4c476af6f5eb2b78fbe809d03f7881e6af28cfe3746e8dcf1eb7f762fe7d003141f1539a6cec4"
+depends_on:PSA_WANT_ALG_STREAM_CIPHER:PSA_WANT_KEY_TYPE_CHACHA20
+cipher_decrypt_multipart:PSA_ALG_STREAM_CIPHER:PSA_KEY_TYPE_CHACHA20:"4bddc98c551a95395ef719557f813656b566bc45aac04eca3866324cc75489f2":"a170d9349d24955aa4501891":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":14:14:50:"9ba7d8de0c6b579fc436e368619e09228070d23246c836d6c6b4c476af6f5eb2b78fbe809d03f7881e6af28cfe3746e8dcf1eb7f762fe7d003141f1539a6cec4":PSA_SUCCESS
 
 PSA AEAD encrypt/decrypt: AES-CCM, 19 bytes #1
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
 aead_encrypt_decrypt:PSA_KEY_TYPE_AES:"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF":PSA_ALG_CCM:"000102030405060708090A0B":"000102030405060708090A0B":"0C0D0E0F101112131415161718191A1B1C1D1E":PSA_SUCCESS
 
 PSA AEAD encrypt/decrypt: AES-CCM, 19 bytes #2
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
 aead_encrypt_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CCM:"000102030405060708090A0B":"EC46BB63B02520C33C49FD70":"B96B49E21D621741632875DB7F6C9243D2D7C2":PSA_SUCCESS
 
 PSA AEAD encrypt/decrypt: DES-CCM not supported
@@ -1493,193 +2028,397 @@
 aead_encrypt_decrypt:PSA_KEY_TYPE_DES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CCM:"000102030405060708090A0B":"EC46BB63B02520C33C49FD70":"B96B49E21D621741632875DB7F6C9243D2D7C2":PSA_ERROR_NOT_SUPPORTED
 
 PSA AEAD encrypt: AES-CCM, 23 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
 aead_encrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CCM:"00412B4EA9CDBE3C9696766CFA":"0BE1A88BACE018B1":"08E8CF97D820EA258460E96AD9CF5289054D895CEAC47C":"4CB97F86A2A4689A877947AB8091EF5386A6FFBDD080F8120333D1FCB691F3406CBF531F83A4D8"
 
 PSA AEAD encrypt: AES-CCM, 24 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
 aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9"
 
 PSA AEAD encrypt: AES-CCM, 24 bytes, T=4
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 4 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6643b4f39"
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 4 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6643b4f39"
 
 PSA AEAD encrypt: AES-CCM, 24 bytes, T=6
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 6 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b63fdffcd729bc"
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 6 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b63fdffcd729bc"
 
 PSA AEAD encrypt: AES-CCM, 24 bytes, T=8
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 8 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b64cf2c3bf5f220776"
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 8 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b64cf2c3bf5f220776"
 
 PSA AEAD encrypt: AES-CCM, 24 bytes, T=10
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 10 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b69613343621327defd18e"
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 10 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b69613343621327defd18e"
 
 PSA AEAD encrypt: AES-CCM, 24 bytes, T=12
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 12 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b69a2e5d8faee3138fa5cf9846"
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 12 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b69a2e5d8faee3138fa5cf9846"
 
 PSA AEAD encrypt: AES-CCM, 24 bytes, T=14
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 14 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6c99af01cdb6aa76df73c8646c27f"
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 14 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6c99af01cdb6aa76df73c8646c27f"
 
 PSA AEAD encrypt: AES-CCM, 24 bytes, T=16
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 16 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9"
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 16 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9"
 
 PSA AEAD decrypt: AES-CCM, 39 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
 aead_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CCM:"00412B4EA9CDBE3C9696766CFA":"0BE1A88BACE018B1":"4CB97F86A2A4689A877947AB8091EF5386A6FFBDD080F8120333D1FCB691F3406CBF531F83A4D8":"08E8CF97D820EA258460E96AD9CF5289054D895CEAC47C":PSA_SUCCESS
 
 PSA AEAD decrypt, AES-CCM, 40 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
 aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_SUCCESS
 
 PSA AEAD decrypt: AES-CCM, 24 bytes, T=4
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 4 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6643b4f39":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 4 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6643b4f39":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_SUCCESS
 
 PSA AEAD decrypt: AES-CCM, 24 bytes, T=6
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 6 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b63fdffcd729bc":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 6 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b63fdffcd729bc":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_SUCCESS
 
 PSA AEAD decrypt: AES-CCM, 24 bytes, T=8
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 8 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b64cf2c3bf5f220776":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 8 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b64cf2c3bf5f220776":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_SUCCESS
 
 PSA AEAD decrypt: AES-CCM, 24 bytes, T=10
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 10 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b69613343621327defd18e":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 10 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b69613343621327defd18e":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_SUCCESS
 
 PSA AEAD decrypt: AES-CCM, 24 bytes, T=12
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 12 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b69a2e5d8faee3138fa5cf9846":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 12 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b69a2e5d8faee3138fa5cf9846":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_SUCCESS
 
 PSA AEAD decrypt: AES-CCM, 24 bytes, T=14
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 14 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6c99af01cdb6aa76df73c8646c27f":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 14 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6c99af01cdb6aa76df73c8646c27f":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_SUCCESS
 
 PSA AEAD decrypt: AES-CCM, 24 bytes, T=16
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 16 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 16 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_SUCCESS
 
 PSA AEAD decrypt: AES-CCM, invalid signature
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
 aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26d56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_SIGNATURE
 
 PSA AEAD decrypt: AES-CCM, invalid signature, T=4
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 4 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6643b4f38":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_SIGNATURE
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 4 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6643b4f38":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_SIGNATURE
 
 PSA AEAD decrypt: AES-CCM, T=4, tag is truncated tag for T=16
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 4 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_SIGNATURE
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 4 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_SIGNATURE
 
 PSA AEAD decrypt: AES-CCM, invalid tag length 0
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 0 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
 
 PSA AEAD decrypt: AES-CCM, invalid tag length 2
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 2 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 2 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
 
 PSA AEAD decrypt: AES-CCM, invalid tag length 15
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 15 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 15 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
 
 PSA AEAD decrypt: AES-CCM, invalid tag length 18
-depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, 18 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 18 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
+
+PSA AEAD decrypt: AES-CCM, invalid nonce length 6
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"48c090693056":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
+
+PSA AEAD decrypt: AES-CCM, invalid nonce length 14
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"48c0906930561e0ab0ef4cd97200":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
+
+PSA AEAD decrypt: AES-CCM_8, invalid nonce length 6
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 8 ):"48c090693056":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
+
+PSA AEAD decrypt: AES-CCM_8, invalid nonce length 14
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 8 ):"48c0906930561e0ab0ef4cd97200":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
 
 PSA AEAD encrypt/decrypt, AES-GCM, 19 bytes #1
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
 aead_encrypt_decrypt:PSA_KEY_TYPE_AES:"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF":PSA_ALG_GCM:"000102030405060708090A0B0C0D0E0F":"000102030405060708090A0B":"0C0D0E0F101112131415161718191A1B1C1D1E":PSA_SUCCESS
 
 PSA AEAD encrypt/decrypt, AES GCM, 19 bytes #2
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
 aead_encrypt_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_GCM:"000102030405060708090A0B0C0D0E0F":"EC46BB63B02520C33C49FD70":"B96B49E21D621741632875DB7F6C9243D2D7C2":PSA_SUCCESS
 
+PSA AEAD encrypt/decrypt, AES-GCM, 19 bytes, 12 byte nonce , 1
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt_decrypt:PSA_KEY_TYPE_AES:"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF":PSA_ALG_GCM:"E462C58482FE8264AEEB7231":"000102030405060708090A0B":"0C0D0E0F101112131415161718191A1B1C1D1E":PSA_SUCCESS
+
+PSA AEAD encrypt/decrypt, AES GCM, 19 bytes, 12 byte nonce , 2
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_GCM:"E462C58482FE8264AEEB7231":"EC46BB63B02520C33C49FD70":"B96B49E21D621741632875DB7F6C9243D2D7C2":PSA_SUCCESS
+
 PSA AEAD encrypt, AES-GCM, 128 bytes #1
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
 aead_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96"
 
 PSA AEAD encrypt, AES-GCM, 128 bytes #2
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
 aead_encrypt:PSA_KEY_TYPE_AES:"fe96eab10ff48c7942025422583d0377":PSA_ALG_GCM:"97ce3f848276783599c6875de324361e":"127628b6dcbce6fc8a8ef60798eb67b2088415635119697d20bb878c24d9c6f9c29e148521cb5e0feff892c7855d4f1c0bfb32ad33420976714dce87a0bbc18e4378bd1ef35197d0ca73051148f1199010f63caf122df5f71ad8d9c71df3eb2fbe3b2529d0ba657570358d3776f687bdb9c96d5e0e9e00c4b42d5d7a268d6a08":"194c8bbbfae4a671386b8cd38f390f46f9df6b8661b470c310921a1c858a938045834bb10380037fbf5f5e00688554537be0fcafe8270b9b59068fa056ab1268fc166c2d729243a06650a171c929c7845c85330c04568d62977eedf3b1ba9dca13bdb8f9522817c8cb99e635e37465ec1c9f6f148d51437aa9f994a62e1bd013":"12495120056ca3cac70d583603a476821bac6c57c9733b81cfb83538dc9e850f8bdf46065069591c23ebcbc6d1e2523375fb7efc80c09507fa25477ed07cee54fc4eb90168b3ef988f651fc40652474a644b1b311decf899660aef2347bb081af48950f06ebf799911e37120de94c55c20e5f0a77119be06e2b6e557f872fa0f6bac793bdc2190a195122c98544ccf56"
 
 PSA AEAD encrypt, AES-GCM, 128 bytes #1, T=4
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
-aead_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 4 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847f"
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 4 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847f"
 
 PSA AEAD encrypt, AES-GCM, 128 bytes #1, T=15
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
-aead_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 15 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a"
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a"
 
 PSA AEAD encrypt, AES-GCM, 128 bytes #1, T=16
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
-aead_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 16 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96"
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=0, AAD=0, TAG=16,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"aa740abfadcda779220d3b406c5d7ec09a77fe9d94104539":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"ab2265b4c168955561f04315":"":"":"f149e2b5f0adaa9842ca5f45b768a8fc"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=0, AAD=16, TAG=16,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"41c5da8667ef725220ffe39ae0ac590ac9fca729ab60ada0":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"05ad13a5e2c2ab667e1a6fbc":"8b5c124bef6e2f0fe4d8c95cd5fa4cf1":"":"204bdb1bd62154bf08922aaa54eed705"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=0, AAD=20, TAG=16,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"093ef7551ebbff8eb0c0a8a4a62b198f0c2e838de10eeeee":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"e656e93930ed5210ba3f0322":"3da22dacfd11b21b0a713157f60aec0cd22f1add":"":"1b2d2764573e20ae640bf29d48e5fe05"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=0, AAD=48, TAG=15,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"31389612d244c9792a510eca3f9c94f9f48c97ed67ae965a":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"df6b54ec8b58114df5b09279":"0863bec42ee93385efbec665adfc46dafcd793f29e859e3b531c15b168f1888dd13e905cd7d5bc03f9f1f6495717df62":"":"77e5682a49243d5b9016eb1adafa2d"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=0, TAG=16,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"fbc0b4c56a714c83217b2d1bcadd2ed2e9efb0dcac6cc19f":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"5f4b43e811da9c470d6a9b01":"":"d2ae38c4375954835d75b8e4c2f9bbb4":"69482957e6be5c54882d00314e0259cf191e9f29bef63a26860c1e020a21137e"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=0, TAG=8,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"c50ac59e50556e47b834380018c0dc0380af9df3bf6714e6":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 8 ):"f303bf4b6cfbba7104cd9436":"":"d3f3f57033df30c22860231334b099cb":"2269c72d77f2b6f9d57da1820ec5a5d3d62d4491e3e4e9e7"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=16, TAG=14,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"8ef391e4b7a2fe05b959be27823357080f963ed2f64b9e59":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"0080052a2a5bb0e95222a419":"290322092d57479e20f6281e331d95a9":"e7fb0631eebf9bdba87045b33650c4ce":"88d674044031414af7ba9da8b89dd68e69897d99d8e1706f38c613896c18"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=16, TAG=4,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"1cb5a0db778d3eb430b2816ceef9e455f519a8977b074183":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 4 ):"c1df5e9e2e3165c54242a306":"7134e5ddc396c2a8a7da23906c8f7b40":"636871d4c0aae3da7b55abd8b5f21297":"14eb02562aa1d963d0033626cdc8a5c8972f4bdf"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=20, TAG=13,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"45148f42669f8ab8fad689d9b9180e39d7ea8fc95696297e":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 13 ):"5afcb134acc78b4eb9d11e79":"aec409e5fd82e50b824ebc1f45e75188d80615c6":"3d952be11deb421b56e0ce9d7ce99553":"077c0d53869869e191df116fd7baa8a293d2b577a29b0953c91b5d3b9d"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=48, TAG=15,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"5255428457fe75e64447971ec5af0d13c5b60a07ee2d07b0":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"40cb6ebafc202f82223db097":"b2da2bd05ab1f3e39613efc8d80c5d0f240ee08f6abad5791649e9c1d0f48fa3dc59c1e535d1db1a4d3fa2263f5a1117":"fdd8a462c86d4365c8bfee0e25fc8a62":"9ca4a6d08267038f6f7999c84105bb5eaf8f7b3b9310ec688e033088a03482"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=0, TAG=16,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"b52c505a37d78eda5dd34f20c22540ea1b58963cf8e5bf8ffa85f9f2492505b4":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"516c33929df5a3284ff463d7":"":"":"bdc1ac884d332457a1d2664f168c76f0"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=0, TAG=12,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"98ebf7a58db8b8371d9069171190063cc1fdc1927e49a3385f890d41a838619c":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 12 ):"3e6db953bd4e641de644e50a":"":"":"2fb9c3e41fff24ef07437c47"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=20, TAG=16,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"886cff5f3e6b8d0e1ad0a38fcdb26de97e8acbe79f6bed66959a598fa5047d65":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"3a8efa1cd74bbab5448f9945":"519fee519d25c7a304d6c6aa1897ee1eb8c59655":"":"f6d47505ec96c98a42dc3ae719877b87"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=20, TAG=13,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"a7c928738b89c3258b910ac31bc465338b2e133b143fd52d9c9859eb1d01f2a0":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 13 ):"a483a7e94fbb2d694d3c4a8d":"bdb613cd3c2f0edd37b3ed43041bacb949ee51fa":"":"5233f95bdcf5d666fb957acdcb"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=48, TAG=15,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"16a5b58a1dbb273a8fc6a4af722d46dbb898dd86ab128cb93d8388a8647a80a3":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"59e0c40d6675923cf5e004d5":"5b4b4ffc9c66bd394abeed3f03b695b949b3b69a42198cc3bfad971174915df913b967ccf36ee1f001f54efbcd117b68":"":"d57e27914ecb4a764359d3c0f8d4d6"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=48, TAG=4,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"5dd13092dd695b90ab835ed6343031c4cdb710d32f4d3804d72b46d921fcfa18":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 4 ):"1de4bd816c8ec6bffc1e6453":"1b63d6278702abacf8b6c2faf542a808659fd5da03cdc1061a8593ea8ce9fc8ff54ffef6ebf3e15f7a832b4ae750a6ce":"":"72901467"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=16, AAD=0, TAG=15,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"ef9f9284cf599eac3b119905a7d18851e7e374cf63aea04358586b0f757670f8":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"b6ac8e4963f49207ffd6374c":"":"722ee47da4b77424733546c2d400c4e5":"1224dfefb72a20d49e09256908874979882eafea22adf8dbed06a2265f907b"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=16, AAD=0, TAG=12,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"b33b0e4c5b9f7ef77cec1a29ed5844bda3853238bdf7766e7645029931f169f0":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 12 ):"f226d65e8654fdf5193ed721":"":"bcf48ddcfe9d011a1003973d68d2d78a":"d2eb20898a301b5d8e69e9926272021393af01abb6a970047a7fc010"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=16, AAD=16, TAG=14,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"c6e126a65faec77ab62318e30d8a50c39a664670039a66ae5a6874201bc68f9f":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"0ba5193b2d3a8378d67163ce":"5844b289dc74327f9fd93f7aae1c3d39":"c37aada3d4408e880d47e41df77da9b9":"b5cd7563989b460a2fe187e90c41fc3179c73d0d1e3a4484909969de93b0"
+
+PSA AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=16, AAD=48, TAG=15,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"2e6942d537f1a98444c2f9dbdb5d8db42a503a00a17b57d516399569e044a703":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"7eb67721581ed52cfcfc2c4d":"a96cc73451502c7278b467ac85d5fc14fc1a2f51bc685645b173f0cd9af02d383095de063e6eaa50374ce9bc951e9e61":"e5f410fe939e79b7ad33fbd3aaf5856f":"727f5e19a5582e5782bbbe73517f0c04c492319abf12b03b380724ff1483a3"
 
 PSA AEAD decrypt, AES-GCM, 144 bytes #1
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
 aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_SUCCESS
 
 PSA AEAD decrypt, AES-GCM, 144 bytes #2
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
 aead_decrypt:PSA_KEY_TYPE_AES:"fe96eab10ff48c7942025422583d0377":PSA_ALG_GCM:"97ce3f848276783599c6875de324361e":"127628b6dcbce6fc8a8ef60798eb67b2088415635119697d20bb878c24d9c6f9c29e148521cb5e0feff892c7855d4f1c0bfb32ad33420976714dce87a0bbc18e4378bd1ef35197d0ca73051148f1199010f63caf122df5f71ad8d9c71df3eb2fbe3b2529d0ba657570358d3776f687bdb9c96d5e0e9e00c4b42d5d7a268d6a08":"12495120056ca3cac70d583603a476821bac6c57c9733b81cfb83538dc9e850f8bdf46065069591c23ebcbc6d1e2523375fb7efc80c09507fa25477ed07cee54fc4eb90168b3ef988f651fc40652474a644b1b311decf899660aef2347bb081af48950f06ebf799911e37120de94c55c20e5f0a77119be06e2b6e557f872fa0f6bac793bdc2190a195122c98544ccf56":"194c8bbbfae4a671386b8cd38f390f46f9df6b8661b470c310921a1c858a938045834bb10380037fbf5f5e00688554537be0fcafe8270b9b59068fa056ab1268fc166c2d729243a06650a171c929c7845c85330c04568d62977eedf3b1ba9dca13bdb8f9522817c8cb99e635e37465ec1c9f6f148d51437aa9f994a62e1bd013":PSA_SUCCESS
 
 PSA AEAD decrypt, AES-GCM, 144 bytes, T=4
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 4 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847f":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 4 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847f":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_SUCCESS
 
 PSA AEAD decrypt, AES-GCM, 144 bytes, T=15
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 15 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_SUCCESS
 
 PSA AEAD decrypt, AES-GCM, 144 bytes, T=16
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 16 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_SUCCESS
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_SUCCESS
 
 PSA AEAD decrypt, AES-GCM, invalid signature
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
 aead_decrypt:PSA_KEY_TYPE_AES:"fe96eab10ff48c7942025422583d0377":PSA_ALG_GCM:"97ce3f848276783599c6875de324361e":"127628b6dcbce6fc8a8ef60798eb67b2088415635119697d20bb878c24d9c6f9c29e148521cb5e0feff892c7855d4f1c0bfb32ad33420976714dce87a0bbc18e4378bd1ef35197d0ca73051148f1199010f63caf122df5f71ad8d9c71df3eb2fbe3b2529d0ba657570358d3776f687bdb9c96d5e0e9e00c4b42d5d7a268d6a08":"12195120056ca3cac70d583603a476821bac6c57c9733b81cfb83538dc9e850f8bdf46065069591c23ebcbc6d1e2523375fb7efc80c09507fa25477ed07cee54fc4eb90168b3ef988f651fc40652474a644b1b311decf899660aef2347bb081af48950f06ebf799911e37120de94c55c20e5f0a77119be06e2b6e557f872fa0f6bac793bdc2190a195122c98544ccf56":"194c8bbbfae4a671386b8cd38f390f46f9df6b8661b470c310921a1c858a938045834bb10380037fbf5f5e00688554537be0fcafe8270b9b59068fa056ab1268fc166c2d729243a06650a171c929c7845c85330c04568d62977eedf3b1ba9dca13bdb8f9522817c8cb99e635e37465ec1c9f6f148d51437aa9f994a62e1bd013":PSA_ERROR_INVALID_SIGNATURE
 
 PSA AEAD decrypt, AES-GCM, T=15 but passing 16 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 15 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_ERROR_INVALID_SIGNATURE
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_ERROR_INVALID_SIGNATURE
 
 PSA AEAD decrypt: AES-GCM, invalid tag length 0
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 0 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
 
 PSA AEAD decrypt: AES-GCM, invalid tag length 2
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 2 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 2 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
+
+PSA AEAD decrypt: AES-GCM, nonce=0 (bad)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA AEAD decrypt: AES-GCM, nonce=0 (bad), TAG=12
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 12 ):"":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"":PSA_ERROR_INVALID_ARGUMENT
 
 PSA AEAD decrypt: AES-GCM, invalid tag length 18
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
-aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, 18 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 18 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=0, AAD=0, TAG=16
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"0e5d6e68f82f32bea3f0b69498c1a31ef6d955cd3d27a2a8":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"caf72ee1e62e1001e8cfbc63":"":"db1a74ffb5f7de26f5742e0942b1b9cb":"":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=0, AAD=48, TAG=14
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"e79fb7defce4f650402e6b521170686d3eb2a0b9514f3a64":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"40e0d2d836c0519e7042419b":"41c5b5d971c0723bc1b63a259fe7e06c2961de1241bc34c13965f43636e4da3da8c75ed5956abe3a42f3039af005925a":"434ff68f2436f48418fd69f52158":"":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=16, AAD=0, TAG=15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"e41d1f533d5b342ffe434b94b1372683bfd5d9d8cb79f9ee":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"5fe11a596dfcd3a305c1d711":"":"1847f64fff986476d1d2f758692f856da4a0ff98c0c1101694c84fd86680c9":"b03c2c20f758a93a8d1220232ad87098":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=16, AAD=20, TAG=15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"8e7da473c057a2a4669a0d22bf9b7c9913fba48930ca0c9b":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"f9ff8ef80d76c50f9ca0e9ff":"f141bae18a1b54f065554fd34aa02c91c90f505c":"5deb093b6e7c766a64bb9d5170af1ff8bf130b64eebdce06a9bdb2cf1da15a":"b22b2dcdcc18adc30d16297b84b459d8":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=16, AAD=48, TAG=12
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"01bf150add51bb11623e3bfbebd62a7ea81c5b192b8eb6de":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 12 ):"dfacbc6791b785d324c646b7":"e35412a625324257bef35399a7eacca34fec2d2d24166e6bb3e94d96f5c57599ded45e2a74503f07116caa1692398a07":"77579db3c6da769e17731faac4732d7cce65d960a49f94f6b583e54a":"7e5fd8b595ddc4753676107951d900e2":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=16, AAD=48, TAG=8
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"551266c4ed166fe1c43761927801ed50cb9c0b3864fc97df":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 8 ):"e711afbeccd567f866340abb":"562d1697237ebc563941076d459727dfa094eb9ac00d30ed5836825d163dd27517c7660a01056b2d868c7fc5d0343830":"2b54cc27f6ee71882e8b1ead207d2b042d262e87eac97b58":"37245449db8f72b1ecdb420f629d3d80":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=13, AAD=0, TAG=15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"78fa4a2a5b5b1b1d9580ea527f2e1653e9336e15cc5462f5":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"98b774f7110e0bea624b487f":"":"a642aabed8b99e15e297ee705a40c3e2e506cb889727b327b7e044a8":"496909523f574b205d757659c5":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=13, AAD=16, TAG=15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"61f4c2e55d729c4657e503dfe2b604e2853675dbdeb0982a":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"0c4d5548aa2d8d54964e1e63":"5affdf8886dabb14790aff3dbfcbdd80":"0d4eacc3db304f46cb7a9eba6ec105bf86d9dc0639b7cebbd5260f47":"b6e056de521a27266dffbc0d96":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=13, AAD=20, TAG=13
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"73245c4f115a74fe71d6fefb9094c57c75f28033a3c7372b":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 13 ):"536a82485999b93b0bb7ef24":"64dcad870a42eeec0730fd7a7e4154638a85d739":"29333e87bfe65d0e37da2936f695824d4e3f37fab3b8e2b868f6":"f6d56f8c86f27d957fa63aea22":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=13, AAD=48, TAG=4
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"9002e74638e09dd1f091439518e1460cdd5905bd9e1a37ae":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 4 ):"76c81a95d24be5c8bac63b50":"aa3ae4531aaac8f3eb07f748712c55a680bc8df5cf845edc66d09049500b41688b8023f5746879b45bdd586af29c4ede":"31bf37acbc53ca3fdbc9e5eaaebbb85a7f":"bd94b34511bc65ae47684805cb":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=0, AAD=0, TAG=16
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"f5a2b27c74355872eb3ef6c5feafaa740e6ae990d9d48c3bd9bb8235e589f010":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"58d2240f580a31c1d24948e9":"":"15e051a5e4a5f5da6cea92e2ebee5bac":"":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=0, AAD=16, TAG=15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"3395a1485315c5b5e6353acb05ae9499c440a2e9f5c57494662f827235ea314c":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"3b7e632571602456b49880f0":"f283f80226dacb69c8af089ec6b59e81":"84c8beff4b0d160ee68ac613097f51":"":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=0, AAD=20, TAG=15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4dc46ca55c1c1fcb4720c274c0e675c2ac5bf93d8dd5e951ca9f6b61f884edc9":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"6473ab77dc885127422f5594":"e2cf8172ab4cf77eba45cd2c8ff939b938080a90":"8d6351f18d873242204c20144e2b83":"":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=0, AAD=48, TAG=14
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"a7f95798434f9a0fe6fd8acd30b8bad96dbdcfacee4594f01cbf26479be7d154":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"9ef5a77b02137b46e8461d09":"5595a16fa12d4dcdba6b128480dce2d39c1211c3fb6068cde6013f6a80dfcda5eb92af8879e40ee9c177fd0e446fc8ca":"3bfd3d99fe2063e8ef8255519fe0":"":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=16, AAD=0, TAG=16
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4c8ebfe1444ec1b2d503c6986659af2c94fafe945f72c1e8486a5acfedb8a0f8":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"473360e0ad24889959858995":"":"d2c78110ac7e8f107c0df0570bd7c90cc26a379b6d98ef2852ead8ce83a833a7":"7789b41cb3ee548814ca0b388c10b343":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=16, AAD=0, TAG=4
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"57805f98aae1b8b64bb49756529ab8181b3ada674a90c55422e9eb26c48bcd7b":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 4 ):"9735945d8ca161777206632a":"":"58375442ab1c0e6a8952c83d128d9fc5f45bb315":"4860116a6d2deb9bf794bfd6ac5bbbd6":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=16, AAD=16, TAG=8
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"f913bb823a1d0c10b0b72d56866907b893f2266f15de1abc17f93600824db55a":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 8 ):"d4fe686a14592b6ca1bd6b42":"e35d880c1c53688eb83869de9dd8a473":"35af9b502ea6b56269f896bf98affdd59c2aa418b38bc7fd":"ff426dd751190ff826e8b4a0792d746e":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=16, AAD=20, TAG=14
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"74e9d9d7cd0728cea94e169af485f21f9d2447e022f16008f803dcf5c4f7cc0c":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"ecba39edc96667da726122c0":"ae9ab021f86f5b81bb2e0fcbd4b855e1501e9f82":"e5745ce0e02dbba05363b548c3ac7047eacca7e61db6f72fc9b9e5bdb2bb":"0a0b284515694188b6b6c15bc8a09036":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=13, AAD=0, TAG=14
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"60667fce64b8c7169ddf45f335e46951248f69abc4e0f4f292d0ffe3dfd5219f":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"1057322a39f08ef761c3c8fc":"":"501b033c841acb430c52d88fe9cb44c751f2f1641d1e801a534ac8":"f386b28e7eb4c2fb8eb5dc66a2":PSA_SUCCESS
+
+PSA AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=13, AAD=20, TAG=15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"e67590da399cbcdcddcc56110562ade8665b50287a8ab38e8b9ee7520531b560":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"2c36ab6b686a66fba1805196":"823493d42f4f60b2d1433ad75eccaafd7e7c7d12":"cff6b6f03c67152f3ce1030653d9bd9a6559f5b04b48d77c2a1fc364":"da1c61fbfcdb73445ad4c7d889":PSA_SUCCESS
 
 PSA AEAD encrypt: ChaCha20-Poly1305 (RFC7539)
-depends_on:MBEDTLS_CHACHAPOLY_C
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
 aead_encrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"070000004041424344454647":"50515253c0c1c2c3c4c5c6c7":"4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e":"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691"
 
 PSA AEAD encrypt: ChaCha20-Poly1305 (zero-length input)
-depends_on:MBEDTLS_CHACHAPOLY_C
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
 aead_encrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"070000004041424344454647":"":"":"a0784d7a4716f3feb4f64e7f4b39bf04"
 
 PSA AEAD decrypt: ChaCha20-Poly1305 (RFC7539, good tag)
-depends_on:MBEDTLS_CHACHAPOLY_C
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
 aead_decrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"070000004041424344454647":"50515253c0c1c2c3c4c5c6c7":"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691":"4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e":PSA_SUCCESS
 
 PSA AEAD decrypt: ChaCha20-Poly1305 (RFC7539, bad tag)
-depends_on:MBEDTLS_CHACHAPOLY_C
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
 aead_decrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"070000004041424344454647":"50515253c0c1c2c3c4c5c6c7":"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600690":"4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e":PSA_ERROR_INVALID_SIGNATURE
 
 PSA AEAD decrypt: ChaCha20-Poly1305 (good tag, zero-length input)
-depends_on:MBEDTLS_CHACHAPOLY_C
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
 aead_decrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"070000004041424344454647":"":"a0784d7a4716f3feb4f64e7f4b39bf04":"":PSA_SUCCESS
 
+PSA AEAD decrypt: ChaCha20-Poly1305 (nonce=8, not supported)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_decrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"0700000040414243":"":"a0784d7a4716f3feb4f64e7f4b39bf04":"":PSA_ERROR_NOT_SUPPORTED
+
+PSA AEAD decrypt: ChaCha20-Poly1305 (nonce=11, too short)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_decrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"0700000040414243444546":"":"a0784d7a4716f3feb4f64e7f4b39bf04":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA AEAD decrypt: ChaCha20-Poly1305 (nonce=13, too long)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_decrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"07000000404142434445464700":"":"a0784d7a4716f3feb4f64e7f4b39bf04":"":PSA_ERROR_INVALID_ARGUMENT
+
 PSA AEAD encrypt/decrypt: invalid algorithm (CTR)
 depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
 aead_encrypt_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CTR:"000102030405060708090A0B0C0D0E0F":"":"":PSA_ERROR_NOT_SUPPORTED
@@ -1689,426 +2428,778 @@
 aead_encrypt_decrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_STREAM_CIPHER:"":"":"":PSA_ERROR_NOT_SUPPORTED
 
 PSA signature size: RSA keypair, 1024 bits, PKCS#1 v1.5 raw
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
 signature_size:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:128
 
 PSA signature size: RSA public key, 1024 bits, PKCS#1 v1.5 raw
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
 signature_size:PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:128
 
 PSA signature size: RSA keypair, 1024 bits, PKCS#1 v1.5 SHA-256
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
 signature_size:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):128
 
 PSA signature size: RSA keypair, 1024 bits, PSS
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
 signature_size:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_ALG_RSA_PSS( PSA_ALG_SHA_256 ):128
 
+PSA signature size: RSA keypair, 1024 bits, PSS-any-salt
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+signature_size:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_ALG_RSA_PSS_ANY_SALT( PSA_ALG_SHA_256 ):128
+
 PSA signature size: RSA keypair, 1023 bits, PKCS#1 v1.5 raw
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
 signature_size:PSA_KEY_TYPE_RSA_KEY_PAIR:1023:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:128
 
 PSA signature size: RSA keypair, 1025 bits, PKCS#1 v1.5 raw
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
 signature_size:PSA_KEY_TYPE_RSA_KEY_PAIR:1025:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:129
 
 PSA import/exercise RSA keypair, PKCS#1 v1.5 raw
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 import_and_exercise_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_ALG_RSA_PKCS1V15_SIGN_RAW
 
 PSA import/exercise RSA keypair, PSS-SHA-256
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+import_and_exercise_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256)
+
+PSA import/exercise RSA keypair, PSS-any-salt-SHA-256
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 import_and_exercise_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256)
 
 PSA import/exercise RSA public key, PKCS#1 v1.5 raw
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 import_and_exercise_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:PSA_ALG_RSA_PKCS1V15_SIGN_RAW
 
 PSA import/exercise RSA public key, PSS-SHA-256
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 import_and_exercise_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256)
 
+PSA import/exercise RSA public key, PSS-any-salt-SHA-256
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+import_and_exercise_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256)
+
 PSA import/exercise: ECP SECP256R1 keypair, ECDSA
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 import_and_exercise_key:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ALG_ECDSA_ANY
 
 PSA import/exercise: ECP SECP256R1 keypair, deterministic ECDSA
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_MD_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C
 import_and_exercise_key:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 )
 
 PSA import/exercise: ECP SECP256R1 keypair, ECDH
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 import_and_exercise_key:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ALG_ECDH
 
 PSA import/exercise: HKDF SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 import_and_exercise_key:"c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0":PSA_KEY_TYPE_DERIVE:192:PSA_ALG_HKDF(PSA_ALG_SHA_256)
 
 PSA import/exercise: TLS 1.2 PRF SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 import_and_exercise_key:"c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0":PSA_KEY_TYPE_DERIVE:192:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)
 
-PSA sign: RSA PKCS#1 v1.5, raw
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15
-sign_deterministic:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"616263":"2c7744983f023ac7bb1c55529d83ed11a76a7898a1bb5ce191375a4aa7495a633d27879ff58eba5a57371c34feb1180e8b850d552476ebb5634df620261992f12ebee9097041dbbea85a42d45b344be5073ceb772ffc604954b9158ba81ec3dc4d9d65e3ab7aa318165f38c36f841f1c69cb1cfa494aa5cbb4d6c0efbafb043a"
+PSA sign hash: RSA PKCS#1 v1.5, raw
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_hash_deterministic:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"616263":"2c7744983f023ac7bb1c55529d83ed11a76a7898a1bb5ce191375a4aa7495a633d27879ff58eba5a57371c34feb1180e8b850d552476ebb5634df620261992f12ebee9097041dbbea85a42d45b344be5073ceb772ffc604954b9158ba81ec3dc4d9d65e3ab7aa318165f38c36f841f1c69cb1cfa494aa5cbb4d6c0efbafb043a"
 
-PSA sign: RSA PKCS#1 v1.5 SHA-256
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-sign_deterministic:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311"
+PSA sign hash: RSA PKCS#1 v1.5 SHA-256
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_hash_deterministic:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311"
 
-PSA sign: deterministic ECDSA SECP256R1 SHA-256
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_MD_C:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C
-sign_deterministic:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f"
+PSA sign hash: deterministic ECDSA SECP256R1 SHA-256
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C
+sign_hash_deterministic:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f"
 
-PSA sign: deterministic ECDSA SECP256R1 SHA-384
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_MD_C:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384:MBEDTLS_ECDSA_C
-sign_deterministic:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_384 ):"59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f":"cd40ba1b555ca5994d30ddffc4ad734b1f5c604675b0f249814aa5de3992ef3ddf4d5dc5d2aab1979ce210b560754df671363d99795475882894c048e3b986ca"
+PSA sign hash: deterministic ECDSA SECP256R1 SHA-384
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C:MBEDLTS_PSA_BUILTIN_ALG_SHA_384
+sign_hash_deterministic:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_384 ):"59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f":"cd40ba1b555ca5994d30ddffc4ad734b1f5c604675b0f249814aa5de3992ef3ddf4d5dc5d2aab1979ce210b560754df671363d99795475882894c048e3b986ca"
 
-PSA sign: deterministic ECDSA SECP384R1 SHA-256
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_MD_C:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C
-sign_deterministic:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824":"52d92aac1fcc0fea3ecce01a9ed4bc9ac342f92470fd3f54d0d6d2fa5d2940405057a9d49a817c2b193322f05fc93ac1c7a055edac93bec0ade6814ab27b86b5295ac1ddb323818200f00c3d94d959f714f128b64a2e19628037ac009b14774f"
+PSA sign hash: deterministic ECDSA SECP384R1 SHA-256
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384:MBEDTLS_MD_C
+sign_hash_deterministic:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824":"52d92aac1fcc0fea3ecce01a9ed4bc9ac342f92470fd3f54d0d6d2fa5d2940405057a9d49a817c2b193322f05fc93ac1c7a055edac93bec0ade6814ab27b86b5295ac1ddb323818200f00c3d94d959f714f128b64a2e19628037ac009b14774f"
 
-PSA sign: RSA PKCS#1 v1.5 SHA-256, wrong hash size
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-sign_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015":128:PSA_ERROR_INVALID_ARGUMENT
+PSA sign hash: RSA PKCS#1 v1.5 SHA-256, wrong hash size
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_hash_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015":128:PSA_ERROR_INVALID_ARGUMENT
 
-PSA sign: RSA PKCS#1 v1.5, invalid hash (wildcard)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15
-# Arguably the error should be INVALID_ARGUMENT, but NOT_SUPPORTED is simpler
-# to implement.
-sign_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":128:PSA_ERROR_NOT_SUPPORTED
+PSA sign hash: RSA PKCS#1 v1.5, invalid hash (wildcard)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_hash_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":128:PSA_ERROR_INVALID_ARGUMENT
 
-PSA sign: RSA PKCS#1 v1.5 raw, input too large
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15
-sign_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":128:PSA_ERROR_INVALID_ARGUMENT
+PSA sign hash: RSA PKCS#1 v1.5 raw, input too large
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_hash_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":128:PSA_ERROR_INVALID_ARGUMENT
 
-PSA sign: RSA PKCS#1 v1.5 SHA-256, output buffer too small
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-sign_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":127:PSA_ERROR_BUFFER_TOO_SMALL
+PSA sign hash: RSA PKCS#1 v1.5 SHA-256, output buffer too small
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_hash_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":127:PSA_ERROR_BUFFER_TOO_SMALL
 
-PSA sign: deterministic ECDSA SECP256R1 SHA-256, output buffer too small
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC
-sign_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":63:PSA_ERROR_BUFFER_TOO_SMALL
+PSA sign hash: RSA PSS SHA-256, wrong hash length (0 bytes)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_hash_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"":127:PSA_ERROR_INVALID_ARGUMENT
 
-PSA sign: RSA PKCS#1 v1.5 SHA-256, empty output buffer
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-sign_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":0:PSA_ERROR_BUFFER_TOO_SMALL
+PSA sign hash: RSA PSS-any-salt SHA-256, wrong hash length (0 bytes)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_hash_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):"":127:PSA_ERROR_INVALID_ARGUMENT
 
-PSA sign: deterministic ECDSA SECP256R1 SHA-256, empty output buffer
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C
-sign_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":0:PSA_ERROR_BUFFER_TOO_SMALL
+PSA sign hash: RSA PSS SHA-256, wrong hash length (129 bytes)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_hash_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":127:PSA_ERROR_INVALID_ARGUMENT
 
-PSA sign: deterministic ECDSA SECP256R1, invalid hash algorithm (0)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_MD_C
-sign_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( 0 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":72:PSA_ERROR_INVALID_ARGUMENT
+PSA sign hash: RSA PSS-any-salt SHA-256, wrong hash length (129 bytes)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_hash_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":127:PSA_ERROR_INVALID_ARGUMENT
 
-PSA sign: deterministic ECDSA SECP256R1, invalid hash algorithm (wildcard)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_MD_C
-sign_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_ANY_HASH ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":72:PSA_ERROR_INVALID_ARGUMENT
+PSA sign hash: deterministic ECDSA SECP256R1 SHA-256, output buffer too small
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_hash_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":63:PSA_ERROR_BUFFER_TOO_SMALL
 
-PSA sign: invalid key type, signing with a public key
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-sign_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":72:PSA_ERROR_INVALID_ARGUMENT
+PSA sign hash: RSA PKCS#1 v1.5 SHA-256, empty output buffer
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_hash_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":0:PSA_ERROR_BUFFER_TOO_SMALL
 
-PSA sign: invalid algorithm for ECC key
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21
-sign_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":72:PSA_ERROR_INVALID_ARGUMENT
+PSA sign hash: deterministic ECDSA SECP256R1 SHA-256, empty output buffer
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_hash_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":0:PSA_ERROR_BUFFER_TOO_SMALL
 
-PSA sign/verify: RSA PKCS#1 v1.5, raw
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15
-sign_verify:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"616263"
+PSA sign hash: deterministic ECDSA SECP256R1, invalid hash algorithm (0)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C
+sign_hash_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( 0 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":72:PSA_ERROR_INVALID_ARGUMENT
 
-PSA sign/verify: RSA PKCS#1 v1.5 SHA-256
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-sign_verify:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
+PSA sign hash: deterministic ECDSA SECP256R1, invalid hash algorithm (wildcard)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C
+sign_hash_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_ANY_HASH ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":72:PSA_ERROR_INVALID_ARGUMENT
 
-PSA sign/verify: RSA PSS SHA-256, 0 bytes
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
-sign_verify:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):""
+PSA sign hash: invalid key type, signing with a public key
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C
+sign_hash_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":72:PSA_ERROR_INVALID_ARGUMENT
 
-PSA sign/verify: RSA PSS SHA-256, 32 bytes (hash size)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
-sign_verify:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
+PSA sign hash: invalid algorithm for ECC key
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_hash_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":72:PSA_ERROR_INVALID_ARGUMENT
 
-PSA sign/verify: RSA PSS SHA-256, 129 bytes
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
-sign_verify:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+PSA sign hash: deterministic ECDSA not supported
+depends_on:!PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_MD_C
+sign_hash_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824":96:PSA_ERROR_NOT_SUPPORTED
 
-PSA sign/verify: randomized ECDSA SECP256R1 SHA-256
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C
-sign_verify:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b"
+PSA sign/verify hash: RSA PKCS#1 v1.5, raw
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_verify_hash:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"616263"
 
-PSA sign/verify: deterministic ECDSA SECP256R1 SHA-256
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_MD_C:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C
-sign_verify:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b"
+PSA sign/verify hash: RSA PKCS#1 v1.5 SHA-256
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_verify_hash:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
 
-PSA sign/verify: randomized ECDSA SECP256R1 SHA-384
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
-sign_verify:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA( PSA_ALG_SHA_384 ):"59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f"
+PSA sign/verify hash: RSA PSS SHA-256, 32 bytes (hash size)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_verify_hash:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
 
-PSA sign/verify: deterministic ECDSA SECP256R1 SHA-384
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_MD_C:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384:MBEDTLS_ECDSA_C
-sign_verify:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_384 ):"59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f"
+PSA sign/verify hash: RSA PSS-any-salt SHA-256, 32 bytes (hash size)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_verify_hash:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
 
-PSA sign/verify: randomized ECDSA SECP384R1 SHA-256
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C
-sign_verify:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b"
+PSA sign/verify hash: randomized ECDSA SECP256R1 SHA-256
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_verify_hash:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b"
 
-PSA sign/verify: deterministic ECDSA SECP384R1 SHA-256
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_MD_C:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C
-sign_verify:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b"
+PSA sign/verify hash: deterministic ECDSA SECP256R1 SHA-256
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C
+sign_verify_hash:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b"
 
-PSA verify: RSA PKCS#1 v1.5 SHA-256, good signature
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-asymmetric_verify:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311"
+PSA sign/verify hash: randomized ECDSA SECP256R1 SHA-384
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PSA_BUILTIN_ALG_SHA_384
+sign_verify_hash:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA( PSA_ALG_SHA_384 ):"59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f"
 
-PSA verify with keypair: RSA PKCS#1 v1.5 SHA-256, good signature
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-asymmetric_verify:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311"
+PSA sign/verify hash: deterministic ECDSA SECP256R1 SHA-384
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C:MBEDTLS_PSA_BUILTIN_ALG_SHA_384
+sign_verify_hash:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_384 ):"59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f"
 
-PSA verify: RSA PKCS#1 v1.5 SHA-256, wrong hash length
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA1_C
-asymmetric_verify_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_1):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311":PSA_ERROR_INVALID_ARGUMENT
+PSA sign/verify hash: randomized ECDSA SECP384R1 SHA-256
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384
+sign_verify_hash:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b"
 
-PSA verify: RSA PKCS#1 v1.5 SHA-256, wrong signature (same size)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-asymmetric_verify_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"111164d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311":PSA_ERROR_INVALID_SIGNATURE
+PSA sign/verify hash: deterministic ECDSA SECP384R1 SHA-256
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384:MBEDTLS_MD_C
+sign_verify_hash:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b"
 
-PSA verify: RSA PKCS#1 v1.5 SHA-256, wrong signature (empty)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-asymmetric_verify_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"":PSA_ERROR_INVALID_SIGNATURE
+PSA verify hash: RSA PKCS#1 v1.5 SHA-256, good signature
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311"
 
-PSA verify: RSA PKCS#1 v1.5 SHA-256, wrong signature (truncated)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-asymmetric_verify_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc73":PSA_ERROR_INVALID_SIGNATURE
+PSA verify hash with keypair: RSA PKCS#1 v1.5 SHA-256, good signature
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311"
 
-PSA verify: RSA PKCS#1 v1.5 SHA-256, wrong signature (trailing junk)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-asymmetric_verify_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc731121":PSA_ERROR_INVALID_SIGNATURE
+PSA verify hash: RSA PKCS#1 v1.5 SHA-256, wrong hash length
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C:MBEDTLS_PSA_BUILTIN_ALG_SHA_1
+verify_hash_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_1):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311":PSA_ERROR_INVALID_ARGUMENT
 
-PSA verify: RSA PKCS#1 v1.5 SHA-256, wrong signature (leading junk)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-asymmetric_verify_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"21a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311":PSA_ERROR_INVALID_SIGNATURE
+PSA verify hash: RSA PKCS#1 v1.5 SHA-256, wrong signature (same size)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"111164d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311":PSA_ERROR_INVALID_SIGNATURE
 
-PSA verify: RSA PSS SHA-256, good signature, 0 bytes
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
-asymmetric_verify:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"":"34c011b625c32d992f4ab8fcfa52b616ea66270b5b75a4fc71af712f9b8806bcdd374ce50eafcbb489562b93347885f93c2de1d404c45cacccefceb112ff6ffdfe4264f91d66320bbbe09304b851b8ad6280bbccc571eebcd49c7db5dfa399a6289e1978407904598751613d9870770cdd8507e3dc7b46851dbf05ae1df2988d"
+PSA verify hash: RSA PKCS#1 v1.5 SHA-256, wrong signature (empty)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"":PSA_ERROR_INVALID_SIGNATURE
 
-PSA verify: RSA PSS SHA-256, good signature, 32 bytes (hash size)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
-asymmetric_verify:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"1967ae568cc071dfebeeca76b11d40bd1ec5af241c50b3dcceff21f4536c0693a7179a8d5d163a7625fefd37c161127800edeebc24fa73ca772096827bd3f75e8ccf2c64f07b7171b5c99022a4d73b760f34a385ccff0bd5ed7997d2a29d2847acb0767f93a2a404bc046c97de66d95dc9f7646fdb216b627b2ea0de8afcefb7"
+PSA verify hash: RSA PKCS#1 v1.5 SHA-256, wrong signature (truncated)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc73":PSA_ERROR_INVALID_SIGNATURE
 
-PSA verify: RSA PSS SHA-256, good signature, 129 bytes
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
-asymmetric_verify:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"1491cead330b4ad5b092f8351518141ac11d0888591572669c1e79d6e932c488acd62d44479b0e14cd91a048778bc02398a772ad6bdb4f7764780cf0afe70293d0cac86f2695a1dcb54568bb37d7086f9e86f95a6802d2ee5a4facaa762beff5261bb2816b62cb5af86404974c3f6b67985ac1fbfdf46d6de54f6e29d9274308"
+PSA verify hash: RSA PKCS#1 v1.5 SHA-256, wrong signature (trailing junk)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc731121":PSA_ERROR_INVALID_SIGNATURE
 
-PSA verify: ECDSA SECP256R1, good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C
-asymmetric_verify:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f"
+PSA verify hash: RSA PKCS#1 v1.5 SHA-256, wrong signature (leading junk)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"21a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311":PSA_ERROR_INVALID_SIGNATURE
 
-PSA verify with keypair: ECDSA SECP256R1, good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C
-asymmetric_verify:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f"
+PSA verify hash: RSA-1024 PSS SHA-256, slen=0 (bad)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"abc4b612c6b71e13fa5965b2e25ee6adec5b1f211b2db158e9f3c4547d6cbef909a73dfb474b8caaf6c8fcafa10ec0bbadfd1883289ce33ad08ad533c61ea004fef4d9b76a1efc267efd066ae8918cb8e994faad30ff5e340e14c941926ba7ca9422b86e8055df1c1b90a5959a59cc7a5fc15cbd0d848cd40f7857b7629b668b":PSA_ERROR_INVALID_SIGNATURE
 
-PSA verify: ECDSA SECP256R1, wrong signature size (correct but ASN1-encoded)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C
-asymmetric_verify_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_INVALID_SIGNATURE
+PSA verify hash: RSA-1024 PSS-any-salt SHA-256, slen=0
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"abc4b612c6b71e13fa5965b2e25ee6adec5b1f211b2db158e9f3c4547d6cbef909a73dfb474b8caaf6c8fcafa10ec0bbadfd1883289ce33ad08ad533c61ea004fef4d9b76a1efc267efd066ae8918cb8e994faad30ff5e340e14c941926ba7ca9422b86e8055df1c1b90a5959a59cc7a5fc15cbd0d848cd40f7857b7629b668b"
 
-PSA verify: ECDSA SECP256R1, wrong signature of correct size
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C
-asymmetric_verify_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50e":PSA_ERROR_INVALID_SIGNATURE
+PSA verify hash: RSA-1024 PSS SHA-256, slen=31 (bad)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"797914eadbbe8293a7b0fe29d2db9fb246b519128d46d3ec93142a1a08a2992ba5325ad9b5ce55344b37996dbb81eb89628263cae4e3fc0e947dec0b8b0c7b0ee94bca02dd287f9cc619e2d88fb2279fb2a8f8301271c58009bb1223f3cfa730cb852947685678cfdef2968c82a9b8bffd8c0d518476b1ea2a5ad6c100045d8e":PSA_ERROR_INVALID_SIGNATURE
 
-PSA verify: ECDSA SECP256R1, wrong signature (empty)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C
-asymmetric_verify_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"":PSA_ERROR_INVALID_SIGNATURE
+PSA verify hash: RSA-1024 PSS-any-salt SHA-256, slen=31
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"797914eadbbe8293a7b0fe29d2db9fb246b519128d46d3ec93142a1a08a2992ba5325ad9b5ce55344b37996dbb81eb89628263cae4e3fc0e947dec0b8b0c7b0ee94bca02dd287f9cc619e2d88fb2279fb2a8f8301271c58009bb1223f3cfa730cb852947685678cfdef2968c82a9b8bffd8c0d518476b1ea2a5ad6c100045d8e"
 
-PSA verify: ECDSA SECP256R1, wrong signature (truncated)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C
-asymmetric_verify_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f5":PSA_ERROR_INVALID_SIGNATURE
+PSA verify hash: RSA-1024 PSS SHA-256, slen=32
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"6b201c50637962338d1b218c1d26f031205a0e3c47bc4c54856aa037e5a332d2981e80a51648e902e46046e5507a255c4c73f5ff40d5a54c0a11d2eca7804e1767b20ea12c945a23f5473181d379689c1ba634a2c47c0a8ec90c922ca6466ae9e9fb92871c9043b5858ae34828bceb4ead82db8f21a18ebe1d95b469bbdef1df"
 
-PSA verify: ECDSA SECP256R1, wrong signature (trailing junk)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C
-asymmetric_verify_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f21":PSA_ERROR_INVALID_SIGNATURE
+PSA verify hash: RSA-1024 PSS-any-salt SHA-256, slen=32
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"6b201c50637962338d1b218c1d26f031205a0e3c47bc4c54856aa037e5a332d2981e80a51648e902e46046e5507a255c4c73f5ff40d5a54c0a11d2eca7804e1767b20ea12c945a23f5473181d379689c1ba634a2c47c0a8ec90c922ca6466ae9e9fb92871c9043b5858ae34828bceb4ead82db8f21a18ebe1d95b469bbdef1df"
 
-PSA verify: ECDSA SECP256R1, wrong signature (leading junk)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C
-asymmetric_verify_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"216a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_INVALID_SIGNATURE
+PSA verify hash: RSA-1024 PSS SHA-256, slen=94 (bad)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"44a09fa66f1b2e790474960e90517e418747cfcd18423dff957516a598569d74f26ef1eae4a200d12d801e16fc6fde375330c79c0d8430825e0a7f69c664faefccfa25e7fbfc68af02af0f67fe4c49f68f6abc68c8f66d3fd77fc838961f4415827340c66e39c79ed7dae0738c08ce8272aebe50c72e31994b9b6db640b51800":PSA_ERROR_INVALID_SIGNATURE
 
-PSA verify: invalid algorithm for ECC key
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21
-asymmetric_verify_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"":"":PSA_ERROR_INVALID_ARGUMENT
+PSA verify hash: RSA-1024 PSS-any-salt SHA-256, slen=94
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"44a09fa66f1b2e790474960e90517e418747cfcd18423dff957516a598569d74f26ef1eae4a200d12d801e16fc6fde375330c79c0d8430825e0a7f69c664faefccfa25e7fbfc68af02af0f67fe4c49f68f6abc68c8f66d3fd77fc838961f4415827340c66e39c79ed7dae0738c08ce8272aebe50c72e31994b9b6db640b51800"
+
+PSA verify hash: RSA-1024 PSS SHA-512, slen=61 (bad)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C:MBEDTLS_PSA_BUILTIN_ALG_SHA_512
+verify_hash_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_512):"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f":"23f5b30c8d612d8f31206c177ac2023c4f44754d03c7ff67daff99f24fa369b3e5f7c15b228a4417a1ff1c93fb8d645d619c2f4f559ac6c7f7bac20ba9df32353d19941265a4e74261adaf45d48682c0bc86cea6128f11ad172ff461fb1d97bded615861843996e2a98e7b8313b695519d001ae35305d6cbf3c0ee6c7ab06d1a":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify hash: RSA-1024 PSS-any-salt SHA-512, slen=61
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C:MBEDTLS_PSA_BUILTIN_ALG_SHA_512
+verify_hash:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_512):"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f":"23f5b30c8d612d8f31206c177ac2023c4f44754d03c7ff67daff99f24fa369b3e5f7c15b228a4417a1ff1c93fb8d645d619c2f4f559ac6c7f7bac20ba9df32353d19941265a4e74261adaf45d48682c0bc86cea6128f11ad172ff461fb1d97bded615861843996e2a98e7b8313b695519d001ae35305d6cbf3c0ee6c7ab06d1a"
+
+PSA verify hash: RSA-1024 PSS SHA-512, slen=62
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C:MBEDTLS_PSA_BUILTIN_ALG_SHA_512
+verify_hash:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_512):"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f":"6b215d77cf88b2d08be53b4f3ac6e72ebfbf7e0dc6c1e77b238cfb661c247a011b8746709fbefe4bc05d37343391683e9489d720ecbb7df37f4e36967918958996939461703465c2014a4c12faf875f8def70070e55b765b165c7e9c6f2eb05c98351b1e82219c31a2fb3ddce05f8988f552ff92f0b3471f63c0e53824c550a4"
+
+PSA verify hash: RSA-1024 PSS-any-salt SHA-512, slen=62
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C:MBEDTLS_PSA_BUILTIN_ALG_SHA_512
+verify_hash:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_512):"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f":"6b215d77cf88b2d08be53b4f3ac6e72ebfbf7e0dc6c1e77b238cfb661c247a011b8746709fbefe4bc05d37343391683e9489d720ecbb7df37f4e36967918958996939461703465c2014a4c12faf875f8def70070e55b765b165c7e9c6f2eb05c98351b1e82219c31a2fb3ddce05f8988f552ff92f0b3471f63c0e53824c550a4"
+
+PSA verify hash: RSA-528 PSS SHA-512, slen=0
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C:MBEDTLS_PSA_BUILTIN_ALG_SHA_512
+verify_hash:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"304a024300e31c246d46485984261fd174cab3d4357344602ecd793c47dbe54252d37bb350bc634359b19515542080e4724a4b672291be57c7648f51629eaef234e847d99cc65f0203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_512):"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f":"a14ad0fef77d36c28658a66129ee632e40e1032003eefe7fcda8e52b06675a051c80b2ca1cb99ed0762e90c9a48c434cd1063638eed7895a9c770e5435af750a1955"
+
+PSA verify hash: RSA-528 PSS-any-salt SHA-512, slen=0
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C:MBEDTLS_PSA_BUILTIN_ALG_SHA_512
+verify_hash:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"304a024300e31c246d46485984261fd174cab3d4357344602ecd793c47dbe54252d37bb350bc634359b19515542080e4724a4b672291be57c7648f51629eaef234e847d99cc65f0203010001":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_512):"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f":"a14ad0fef77d36c28658a66129ee632e40e1032003eefe7fcda8e52b06675a051c80b2ca1cb99ed0762e90c9a48c434cd1063638eed7895a9c770e5435af750a1955"
+
+PSA verify hash: RSA-520 PSS SHA-512 (hash too large)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C:MBEDTLS_PSA_BUILTIN_ALG_SHA_512
+verify_hash_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"3049024200d5a06f86e5b9d87428540165ca966fa8893a62e2a59d0bfd7617780bb039f9165a373a8e119d0766f8de556710f33f67019153bad8223775e797d451d48206f3bf0203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_512):"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f":"deaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddead42":PSA_ERROR_INVALID_ARGUMENT
+
+PSA verify hash: RSA-520 PSS-any-salt SHA-512 (hash too large)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C:MBEDTLS_PSA_BUILTIN_ALG_SHA_512
+verify_hash_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"3049024200d5a06f86e5b9d87428540165ca966fa8893a62e2a59d0bfd7617780bb039f9165a373a8e119d0766f8de556710f33f67019153bad8223775e797d451d48206f3bf0203010001":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_512):"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f":"deaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddead42":PSA_ERROR_INVALID_ARGUMENT
+
+PSA verify hash: RSA PSS SHA-256, wrong hash length (0 bytes)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"":"34c011b625c32d992f4ab8fcfa52b616ea66270b5b75a4fc71af712f9b8806bcdd374ce50eafcbb489562b93347885f93c2de1d404c45cacccefceb112ff6ffdfe4264f91d66320bbbe09304b851b8ad6280bbccc571eebcd49c7db5dfa399a6289e1978407904598751613d9870770cdd8507e3dc7b46851dbf05ae1df2988d":PSA_ERROR_INVALID_ARGUMENT
+
+PSA verify hash: RSA PSS-any-salt SHA-256, wrong hash length (0 bytes)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):"":"34c011b625c32d992f4ab8fcfa52b616ea66270b5b75a4fc71af712f9b8806bcdd374ce50eafcbb489562b93347885f93c2de1d404c45cacccefceb112ff6ffdfe4264f91d66320bbbe09304b851b8ad6280bbccc571eebcd49c7db5dfa399a6289e1978407904598751613d9870770cdd8507e3dc7b46851dbf05ae1df2988d":PSA_ERROR_INVALID_ARGUMENT
+
+PSA verify hash: RSA PSS SHA-256, wrong hash length (129 bytes)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"1491cead330b4ad5b092f8351518141ac11d0888591572669c1e79d6e932c488acd62d44479b0e14cd91a048778bc02398a772ad6bdb4f7764780cf0afe70293d0cac86f2695a1dcb54568bb37d7086f9e86f95a6802d2ee5a4facaa762beff5261bb2816b62cb5af86404974c3f6b67985ac1fbfdf46d6de54f6e29d9274308":PSA_ERROR_INVALID_ARGUMENT
+
+PSA verify hash: RSA PSS-any-salt SHA-256, wrong hash length (129 bytes)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_hash_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"1491cead330b4ad5b092f8351518141ac11d0888591572669c1e79d6e932c488acd62d44479b0e14cd91a048778bc02398a772ad6bdb4f7764780cf0afe70293d0cac86f2695a1dcb54568bb37d7086f9e86f95a6802d2ee5a4facaa762beff5261bb2816b62cb5af86404974c3f6b67985ac1fbfdf46d6de54f6e29d9274308":PSA_ERROR_INVALID_ARGUMENT
+
+PSA verify hash: ECDSA SECP256R1, good
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f"
+
+PSA verify hash with keypair: ECDSA SECP256R1, good
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f"
+
+PSA verify hash: ECDSA SECP256R1, wrong signature size (correct but ASN1-encoded)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"304502206a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151022100ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify hash: ECDSA SECP256R1, wrong signature of correct size
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50e":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify hash: ECDSA SECP256R1, wrong signature (empty)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify hash: ECDSA SECP256R1, wrong signature (truncated)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f5":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify hash: ECDSA SECP256R1, wrong signature (trailing junk)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f21":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify hash: ECDSA SECP256R1, wrong signature (leading junk)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_hash_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"216a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify hash: invalid algorithm for ECC key
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C
+verify_hash_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA sign message: RSA PKCS#1 v1.5 SHA-256
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_message_deterministic:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"616263":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311"
+
+PSA sign message: deterministic ECDSA SECP256R1 SHA-256
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C
+sign_message_deterministic:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):"616263":"36e5b5a7da1c9c265dc447de3a5a704fcb8c03f7a3749dde48d84c9bf736fc1ed48d8b3660e7d3cbc6b1870730b7ce2a043f69e37ccb340b98d1e65184e03548"
+
+PSA sign message: deterministic ECDSA SECP256R1 SHA-384
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C:MBEDLTS_PSA_BUILTIN_ALG_SHA_384
+sign_message_deterministic:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384):"616263":"7ea712a20e3a8cbe0c6e64195362ba7635bbe78af51ddedd7a5fd858395250c592654c35d3b0614ae0e3b329c25cf5b4a5fcb243af3e3ad15c8446fe401be066"
+
+PSA sign message: deterministic ECDSA SECP384R1 SHA-256
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384:MBEDTLS_MD_C
+sign_message_deterministic:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):"616263":"3548ea85eb66d756ae90fd64a3104b5b9a17aa282f8722409762e9da4811ec5d3060a97d3450b4bc484cd21ac588f563c4873843506fed8609b7d093db0e9a2496c36995ee74c906528af6898feb502f45bfb1e9ccf371416c68d32bb5ebc1b6"
+
+PSA sign message: RSA PKCS#1 v1.5, invalid hash (wildcard)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_message_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):"616263":128:PSA_ERROR_INVALID_ARGUMENT
+
+PSA sign message: RSA PKCS#1 v1.5, invalid hash algorithm (0)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_message_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(0):"616263":128:PSA_ERROR_INVALID_ARGUMENT
+
+PSA sign message: RSA PKCS#1 v1.5 SHA-256, output buffer too small
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_message_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"616263":127:PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA sign message: RSA PKCS#1 v1.5 SHA-256, empty output buffer
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_message_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"616263":0:PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA sign message: RSA PKCS#1 v1.5 without hash
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_message_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"616263":0:PSA_ERROR_INVALID_ARGUMENT
+
+PSA sign message: RSA PKCS#1 v1.5 SHA-256, invalid key type
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_CHACHA20:MBEDTLS_MD_C
+sign_message_fail:PSA_KEY_TYPE_CHACHA20:"4bddc98c551a95395ef719557f813656b566bc45aac04eca3866324cc75489f2":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"616263":128:PSA_ERROR_INVALID_ARGUMENT
+
+PSA sign message: ECDSA SECP256R1 SHA-256, invalid hash (wildcard)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C
+sign_message_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):"616263":64:PSA_ERROR_INVALID_ARGUMENT
+
+PSA sign message: ECDSA SECP256R1 SHA-256, invalid hash algorithm (0)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C
+sign_message_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(0):"616263":64:PSA_ERROR_INVALID_ARGUMENT
+
+PSA sign message: ECDSA SECP256R1 SHA-256, output buffer too small
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C
+sign_message_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"616263":63:PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA sign message: ECDSA SECP256R1 SHA-256, empty output buffer
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C
+sign_message_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"616263":0:PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA sign message: ECDSA SECP256R1 SHA-256, invalid key type
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_CHACHA20:MBEDTLS_MD_C
+sign_message_fail:PSA_KEY_TYPE_CHACHA20:"4bddc98c551a95395ef719557f813656b566bc45aac04eca3866324cc75489f2":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"616263":64:PSA_ERROR_INVALID_ARGUMENT
+
+PSA sign message: invalid algorithm for ECC key
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_message_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"616263":72:PSA_ERROR_INVALID_ARGUMENT
+
+PSA sign message: deterministic ECDSA not supported
+depends_on:!PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_MD_C
+sign_message_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):"616263":96:PSA_ERROR_NOT_SUPPORTED
+
+PSA sign message: ECDSA without hash
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C
+sign_message_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA_ANY:"616263":96:PSA_ERROR_INVALID_ARGUMENT
+
+PSA sign/verify message: RSA PKCS#1 v1.5 SHA-256
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_verify_message:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"616263"
+
+PSA sign/verify message: RSA PSS SHA-256
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_verify_message:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"616263"
+
+PSA sign/verify message: RSA PSS-any-salt SHA-256
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_verify_message:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):"616263"
+
+PSA sign/verify message: RSA PSS SHA-256, 0 bytes
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_verify_message:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):""
+
+PSA sign/verify message: RSA PSS SHA-256, 32 bytes
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_verify_message:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+PSA sign/verify message: RSA PSS SHA-256, 128 bytes
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_verify_message:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+PSA sign/verify message: RSA PSS SHA-256, 129 bytes
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+sign_verify_message:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+PSA sign/verify message: randomized ECDSA SECP256R1 SHA-256
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_verify_message:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"616263"
+
+PSA sign/verify message: randomized ECDSA SECP256R1 SHA-256, 0 bytes
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_verify_message:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_SHA_256):""
+
+PSA sign/verify message: randomized ECDSA SECP256R1 SHA-256, 32 bytes
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_verify_message:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+PSA sign/verify message: randomized ECDSA SECP256R1 SHA-256, 64 bytes
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_verify_message:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+PSA sign/verify message: randomized ECDSA SECP256R1 SHA-256, 65 bytes
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_verify_message:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+PSA sign/verify message: deterministic ECDSA SECP256R1 SHA-256
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C
+sign_verify_message:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):"616263"
+
+PSA sign/verify message: randomized ECDSA SECP256R1 SHA-384
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+sign_verify_message:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_SHA_384):"616263"
+
+PSA sign/verify message: deterministic ECDSA SECP256R1 SHA-384
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C:MBEDLTS_PSA_BUILTIN_ALG_SHA_384
+sign_verify_message:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384):"616263"
+
+PSA sign/verify message: randomized ECDSA SECP384R1 SHA-256
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384
+sign_verify_message:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"616263"
+
+PSA sign/verify message: deterministic ECDSA SECP384R1 SHA-256
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384:MBEDTLS_MD_C
+sign_verify_message:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):"616263"
+
+PSA verify message: RSA PKCS#1 v1.5 SHA-256, good signature
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"616263":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311"
+
+PSA verify message with keypair: RSA PKCS#1 v1.5 SHA-256, good signature
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"616263":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311"
+
+PSA verify message: RSA-1024 PSS SHA-256, slen=0 (bad)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"616263":"abc4b612c6b71e13fa5965b2e25ee6adec5b1f211b2db158e9f3c4547d6cbef909a73dfb474b8caaf6c8fcafa10ec0bbadfd1883289ce33ad08ad533c61ea004fef4d9b76a1efc267efd066ae8918cb8e994faad30ff5e340e14c941926ba7ca9422b86e8055df1c1b90a5959a59cc7a5fc15cbd0d848cd40f7857b7629b668b":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify message: RSA-1024 PSS-any-salt SHA-256, slen=0
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):"616263":"abc4b612c6b71e13fa5965b2e25ee6adec5b1f211b2db158e9f3c4547d6cbef909a73dfb474b8caaf6c8fcafa10ec0bbadfd1883289ce33ad08ad533c61ea004fef4d9b76a1efc267efd066ae8918cb8e994faad30ff5e340e14c941926ba7ca9422b86e8055df1c1b90a5959a59cc7a5fc15cbd0d848cd40f7857b7629b668b"
+
+PSA verify message: RSA-1024 PSS SHA-256, slen=32
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"616263":"6b201c50637962338d1b218c1d26f031205a0e3c47bc4c54856aa037e5a332d2981e80a51648e902e46046e5507a255c4c73f5ff40d5a54c0a11d2eca7804e1767b20ea12c945a23f5473181d379689c1ba634a2c47c0a8ec90c922ca6466ae9e9fb92871c9043b5858ae34828bceb4ead82db8f21a18ebe1d95b469bbdef1df"
+
+PSA verify message: RSA-1024 PSS-any-salt SHA-256, slen=32
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):"616263":"6b201c50637962338d1b218c1d26f031205a0e3c47bc4c54856aa037e5a332d2981e80a51648e902e46046e5507a255c4c73f5ff40d5a54c0a11d2eca7804e1767b20ea12c945a23f5473181d379689c1ba634a2c47c0a8ec90c922ca6466ae9e9fb92871c9043b5858ae34828bceb4ead82db8f21a18ebe1d95b469bbdef1df"
+
+PSA verify message: RSA PSS SHA-256, good signature, 32 bytes (hash size)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"6b65e1fdc900dce8a2b82130ae8ccfac27b6d0eb5f2c0c1085b80f34ceaaf064c8ff237e74a24a3c6fb7a842f172e5146315616281bbbeeae90febaab139a212decf1c68923f2a48e242b1fd72105e3a3f2329c30d78abe8673335ad08c5ba1aa515360bb5660050f1994bb08d3dd17e3407a379403bafa4e229b3c851283f6d"
+
+PSA verify message: RSA PSS-any-salt SHA-256, good signature, 32 bytes (hash size)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"6b65e1fdc900dce8a2b82130ae8ccfac27b6d0eb5f2c0c1085b80f34ceaaf064c8ff237e74a24a3c6fb7a842f172e5146315616281bbbeeae90febaab139a212decf1c68923f2a48e242b1fd72105e3a3f2329c30d78abe8673335ad08c5ba1aa515360bb5660050f1994bb08d3dd17e3407a379403bafa4e229b3c851283f6d"
+
+PSA verify message: RSA PSS SHA-256, good signature, 128 bytes (signature size)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"29b65db0936b7fe408bda672077b0bc5e176177ba9a550fb548c292f7b4af1bb6475e0a979ba43dd644780801fabe5b62a1359cf7692918f30013e90c2362235765abc2078905d13b345dd689bf15e4e94ca51535d12f0675d5f13e9f254ba7696f0096d62deb023d106e9a96a5da3162bead6a745c8b9000868d2f9a447d5c5"
+
+PSA verify message: RSA-any-salt PSS SHA-256, good signature, 128 bytes (signature size)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"29b65db0936b7fe408bda672077b0bc5e176177ba9a550fb548c292f7b4af1bb6475e0a979ba43dd644780801fabe5b62a1359cf7692918f30013e90c2362235765abc2078905d13b345dd689bf15e4e94ca51535d12f0675d5f13e9f254ba7696f0096d62deb023d106e9a96a5da3162bead6a745c8b9000868d2f9a447d5c5"
+
+PSA verify message: RSA PSS SHA-256, good signature, 129 bytes
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"43286cc0fc599603fbb0cd1fd70c3a17b08d2adf4f90202dddfa4b9d74be8c720bbb1c714665466de6452d401ca061b68225785ff387c2615f03c81351cc3838cd3014a031a4f4c9f70bba06f504c6a9942ac2dbfed2329e590d526a9be26b4025a6d7c4151b4e795cfe756c9a8a5e8fa9228a6f5f6f427a5a070e5c0ea69830"
+
+PSA verify message: RSA PSS-any-salt SHA-256, good signature, 129 bytes
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":"43286cc0fc599603fbb0cd1fd70c3a17b08d2adf4f90202dddfa4b9d74be8c720bbb1c714665466de6452d401ca061b68225785ff387c2615f03c81351cc3838cd3014a031a4f4c9f70bba06f504c6a9942ac2dbfed2329e590d526a9be26b4025a6d7c4151b4e795cfe756c9a8a5e8fa9228a6f5f6f427a5a070e5c0ea69830"
+
+PSA verify message: ECDSA SECP256R1 SHA-256, good
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ALG_SHA_256:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_message:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"616263":"0f8c19f5affea6d593a33e176aa52717bff8d5875165fc63e80a2d65580d295789db5ffb5397ba4c67834e2731ee268ea6f7e83846fbb02145b35442db18cf0b"
+
+PSA verify message with keypair: ECDSA SECP256R1 SHA-256, good
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ALG_SHA_256:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_message:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"616263":"0f8c19f5affea6d593a33e176aa52717bff8d5875165fc63e80a2d65580d295789db5ffb5397ba4c67834e2731ee268ea6f7e83846fbb02145b35442db18cf0b"
+
+PSA verify message: RSA PKCS#1 v1.5 SHA-256, wrong signature (same size)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"616263":"111164d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify message: RSA PKCS#1 v1.5 SHA-256, wrong signature (empty)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"616263":"":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify message: RSA PKCS#1 v1.5 SHA-256, wrong signature (truncated)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"616263":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc73":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify message: RSA PKCS#1 v1.5 SHA-256, wrong signature (trailing junk)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"616263":"a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc731121":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify message: RSA PKCS#1 v1.5 SHA-256, wrong signature (leading junk)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"616263":"21a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify message: RSA PKCS#1 v1.5 without hash
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
+verify_message_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"616263":"21a73664d55b39c7ea6c1e5b5011724a11e1d7073d3a68f48c836fad153a1d91b6abdbc8f69da13b206cc96af6363b114458b026af14b24fab8929ed634c6a2acace0bcc62d9bb6a984afbcbfcd3a0608d32a2bae535b9cd1ecdf9dd281db1e0025c3bfb5512963ec3b98ddaa69e38bc3c84b1b61a04e5648640856aacc6fc7311":PSA_ERROR_INVALID_ARGUMENT
+
+PSA verify message: ECDSA SECP256R1, wrong signature size (correct but ASN1-encoded)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_message_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"616263":"304502200b295f3dc3ac2bde92f550b7e73a2de15a753b4ebc761c521a32d1ed9bf5800a022100fe7301254058347c3dec7768f62dfc63f7c049d28bfdd1d6712126fd888e9f04":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify message: ECDSA SECP256R1, wrong signature of correct size
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_message_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"616263":"0f8c19f5affea6d593a33e176aa52717bff8d5875165fc63e80a2d65580d295789db5ffb5397ba4c67834e2731ee268ea6f7e83846fbb02145b35442db18cf00":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify message: ECDSA SECP256R1, wrong signature (empty)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_message_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"616263":"":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify message: ECDSA SECP256R1, wrong signature (truncated)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_message_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"616263":"0f8c19f5affea6d593a33e176aa52717bff8d5875165fc63e80a2d65580d295789db5ffb5397ba4c67834e2731ee268ea6f7e83846fbb02145b35442db18cf":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify message: ECDSA SECP256R1, wrong signature (trailing junk)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_message_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"616263":"0f8c19f5affea6d593a33e176aa52717bff8d5875165fc63e80a2d65580d295789db5ffb5397ba4c67834e2731ee268ea6f7e83846fbb02145b35442db18cf0bff":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify message: ECDSA SECP256R1, wrong signature (leading junk)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_message_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA(PSA_ALG_SHA_256):"616263":"ff0f8c19f5affea6d593a33e176aa52717bff8d5875165fc63e80a2d65580d295789db5ffb5397ba4c67834e2731ee268ea6f7e83846fbb02145b35442db18cf0b":PSA_ERROR_INVALID_SIGNATURE
+
+PSA verify message: invalid algorithm for ECC key
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_MD_C
+verify_message_fail:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA verify message: ECDSA without hash
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+verify_message_fail:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_ALG_ECDSA_ANY:"":"":PSA_ERROR_INVALID_ARGUMENT
 
 PSA encrypt: RSA PKCS#1 v1.5, good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C
 asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_CRYPT:"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"":128:PSA_SUCCESS
 
 PSA encrypt: RSA OAEP-SHA-256, good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"":128:PSA_SUCCESS
 
 PSA encrypt: RSA OAEP-SHA-256, good, with label
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"746869730069730061006c6162656c00":128:PSA_SUCCESS
 
 PSA encrypt: RSA OAEP-SHA-384, good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C:MBEDTLS_PSA_BUILTIN_ALG_SHA_384
 asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_384):"0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e":"":128:PSA_SUCCESS
 
 PSA encrypt: RSA OAEP-SHA-384, good, with label
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C:MBEDTLS_PSA_BUILTIN_ALG_SHA_384
 asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_384):"0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e":"746869730069730061006c6162656c00":128:PSA_SUCCESS
 
 PSA encrypt: RSA PKCS#1 v1.5, key pair
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 asymmetric_encrypt:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"":128:PSA_SUCCESS
 
 PSA encrypt: RSA OAEP-SHA-256, key pair
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 asymmetric_encrypt:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"":128:PSA_SUCCESS
 
 PSA encrypt: RSA PKCS#1 v1.5, input too large
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C
 asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_CRYPT:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":"":0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA encrypt: RSA PKCS#1 v1.5: salt not allowed
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C
 asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_CRYPT:"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee":0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA encrypt: RSA OAEP-SHA-384, input too large
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C:MBEDTLS_PSA_BUILTIN_ALG_SHA_384
 asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_384):"0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f":"":0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA encrypt: invalid algorithm
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C
 asymmetric_encrypt:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_SHA_256:"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"":0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA encrypt: RSA PKCS#1 v1.5: invalid key type
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PK_PARSE_C
 asymmetric_encrypt:PSA_KEY_TYPE_AES:"3082025e02010002818100af057d396e":PSA_ALG_RSA_PKCS1V15_CRYPT:"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"":0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA encrypt-decrypt: RSA PKCS#1 v1.5 vector #1
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 asymmetric_encrypt_decrypt:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":""
 
 PSA encrypt-decrypt: RSA PKCS#1 v1.5 vector #2
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 asymmetric_encrypt_decrypt:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"99e8a6144bcb9a29660303bdc4305bb5eca8c64b96788cad062be9967bdab2f7ffff":""
 
 PSA encrypt-decrypt: RSA OAEP-SHA-256
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 asymmetric_encrypt_decrypt:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":""
 
 PSA encrypt-decrypt: RSA OAEP-SHA-256, with label
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 asymmetric_encrypt_decrypt:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad":"746869730069730061006c6162656c00"
 
 PSA encrypt-decrypt: RSA OAEP-SHA-384
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C:MBEDTLS_PSA_BUILTIN_ALG_SHA_384
 asymmetric_encrypt_decrypt:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_384):"0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e":""
 
 PSA decrypt: RSA PKCS#1 v1.5: good #1
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 asymmetric_decrypt:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"99ffde2fcc00c9cc01972ebfa7779b298dbbaf7f50707a7405296dd2783456fc792002f462e760500e02afa25a859ace8701cb5d3b0262116431c43af8eb08f5a88301057cf1c156a2a5193c143e7a5b03fac132b7e89e6dcd8f4c82c9b28452329c260d30bc39b3816b7c46b41b37b4850d2ae74e729f99c6621fbbe2e46872":"":"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
 
 PSA decrypt: RSA PKCS#1 v1.5: good #2
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 asymmetric_decrypt:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"adeecba2db7f867a733853f0136c554e5e01c7a2015721a9bfe30c3ad163b93a9c7589170311209f91420ad8a1a8280c7e890a6d7bca3c500b4da4f53a17bd84a21d58f979a9b4b8f2246b482d930804f12b3aeb2ac8b5ac7938d452ca13be8eb8e973c4e2b19fd454058cbae037bcef7ef68a5fbabf050de5f283cf1998c695":"":"99e8a6144bcb9a29660303bdc4305bb5eca8c64b96788cad062be9967bdab2f7ffff"
 
 PSA decrypt: RSA PKCS#1 v1.5, 0 bytes, output too small
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"adeecba2db7f867a733853f0136c554e5e01c7a2015721a9bfe30c3ad163b93a9c7589170311209f91420ad8a1a8280c7e890a6d7bca3c500b4da4f53a17bd84a21d58f979a9b4b8f2246b482d930804f12b3aeb2ac8b5ac7938d452ca13be8eb8e973c4e2b19fd454058cbae037bcef7ef68a5fbabf050de5f283cf1998c695":"":0:PSA_ERROR_BUFFER_TOO_SMALL
 
 PSA decrypt: RSA PKCS#1 v1.5, 0 bytes, good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 asymmetric_decrypt:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_ALG_RSA_PKCS1V15_CRYPT:"1b4c1d06439b99f886048b8544607b5e8e5ac6828ad9d0b7ad4ec0b314a4d8052f8bbeab6c85dbddff0b90cc76395a7a0c4f9cc29cd7be20be0b38ff611800d6":"":""
 
 PSA decrypt: RSA OAEP-SHA-256, 0 bytes
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 asymmetric_decrypt:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"3d3146b1c982004273a9ebb9b063e6ae53b1a85bfc802324bcdd04faa0f7211fb2bdeea40358095554df9c250866c7361e738f0d270eaa27738e87928c5e31815506346727900ff03cef0be6f9dd6bba63ce89074e8194fe68b5a5739422d4f138bbbb61f49b76cf1f18def2c993e3113b08c191ea1da0feb94f8fd9b30109a1":"":""
 
 PSA decrypt: RSA OAEP-SHA-256, 0 bytes, with label
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 asymmetric_decrypt:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"14e57648fbbd3c2c195d71fcb9b6c332e2ad9e3402aa701e7270b05775e9ddd025e2330d7b84e67866524c67f9c38b11e4679e28a38574b47f8d218a1a04a7466754d6ea7f959ab1f5b85d066d3f90076e8219f66653f7b78a9789d76213505b4e75ec28081608ed2f1ea1238e3eeab011ce4ec147327cd0ca029c2818133cb6":"746869730069730061006c6162656c00":""
 
 PSA decrypt: RSA OAEP-SHA-256, 30 bytes
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 asymmetric_decrypt:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"3fd3c81e3919a19014400d91098090f273312e0150e09eff7f66fb9624d2ec9764fc80befcb592e9d102493c882b8bc0334a257e73aba23a0ee13f826cbc64f8200b9150784d004ccb2955c877c95ab888e3917f423dd52f3c8a49cb61c1966ec04f336068729ae0bce7d7fb3e680f9d15d658db9b906efcbf2c2fae45e75429":"":"74686973206973206e6f2073717565616d697368206f7373696672616765"
 
 PSA decrypt: RSA OAEP-SHA-256, 30 bytes, with label
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 asymmetric_decrypt:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"46edc9984a6d4b7c7fd88fda9ea91ddbd30b28a0793cc75a9fcdd94d867c69090a697d46a6f336a3e48a122dd3ee3b51566b445ff78adb613d09b7d8c59c25a27d8cf7f5e36455f2e71ff6c6ee98d5740e66b23794acc72906561951c2be5064f6a250646ab627ecbfa48c02f82c29fe9b8c8e6be8eb752432124974373b542c":"746869730069730061006c6162656c00":"74686973206973206e6f2073717565616d697368206f7373696672616765"
 
 PSA decrypt: RSA OAEP-SHA-384, 30 bytes
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C:MBEDTLS_PSA_BUILTIN_ALG_SHA_384
 asymmetric_decrypt:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_384):"0df6750b8fed749359c016887d2cf097cc512c065526a91a7ee9b345a1bfff833737e7326e54d03f6bb65971962885a7661a16858d53ea55821052f4c7798d395b5c5495332fd4174451a1a437f36c27f446b96f309ff1cb6837274aa8ae2b51a8a479d736d25b8d2ca8ab96fe589553a3e52818b7df75544eb5469977b29aa4":"":"74686973206973206e6f2073717565616d697368206f7373696672616765"
 
 PSA decrypt: RSA OAEP-SHA-256, 30 bytes, wrong label (should be empty)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"3fd3c81e3919a19014400d91098090f273312e0150e09eff7f66fb9624d2ec9764fc80befcb592e9d102493c882b8bc0334a257e73aba23a0ee13f826cbc64f8200b9150784d004ccb2955c877c95ab888e3917f423dd52f3c8a49cb61c1966ec04f336068729ae0bce7d7fb3e680f9d15d658db9b906efcbf2c2fae45e75429":"00":128:PSA_ERROR_INVALID_PADDING
 
 PSA decrypt: RSA OAEP-SHA-256, 30 bytes, wrong label (empty)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"46edc9984a6d4b7c7fd88fda9ea91ddbd30b28a0793cc75a9fcdd94d867c69090a697d46a6f336a3e48a122dd3ee3b51566b445ff78adb613d09b7d8c59c25a27d8cf7f5e36455f2e71ff6c6ee98d5740e66b23794acc72906561951c2be5064f6a250646ab627ecbfa48c02f82c29fe9b8c8e6be8eb752432124974373b542c":"":128:PSA_ERROR_INVALID_PADDING
 
 PSA decrypt: RSA OAEP-SHA-256, 30 bytes, wrong label (same length)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"46edc9984a6d4b7c7fd88fda9ea91ddbd30b28a0793cc75a9fcdd94d867c69090a697d46a6f336a3e48a122dd3ee3b51566b445ff78adb613d09b7d8c59c25a27d8cf7f5e36455f2e71ff6c6ee98d5740e66b23794acc72906561951c2be5064f6a250646ab627ecbfa48c02f82c29fe9b8c8e6be8eb752432124974373b542c":"746869730069730061006c6162656c01":128:PSA_ERROR_INVALID_PADDING
 
 PSA decrypt: RSA PKCS#1 v1.5, invalid padding
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"99ffde2fcc00c9cc01972ebfa7779b298dbbaf7f50707a7405296dd2783456fc792002f462e760500e02afa25a859ace8701cb5d3b0262116431c43af8eb08f5a88301057cf1c156a2a5193c143e7a5b03fac132b7e89e6dcd8f4c82c9b28452329c260d30bc39b3816b7c46b41b37b4850d2ae74e729f99c6621fbbe2e46873":"":128:PSA_ERROR_INVALID_PADDING
 
 PSA decrypt: RSA PKCS#1 v1.5: salt not allowed
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"99ffde2fcc00c9cc01972ebfa7779b298dbbaf7f50707a7405296dd2783456fc792002f462e760500e02afa25a859ace8701cb5d3b0262116431c43af8eb08f5a88301057cf1c156a2a5193c143e7a5b03fac132b7e89e6dcd8f4c82c9b28452329c260d30bc39b3816b7c46b41b37b4850d2ae74e729f99c6621fbbe2e46872":"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee":128:PSA_ERROR_INVALID_ARGUMENT
 
 PSA decrypt: RSA OAEP-SHA-256, invalid padding
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"3fd3c81e3919a19014400d91098090f273312e0150e09eff7f66fb9624d2ec9764fc80befcb592e9d102493c882b8bc0334a257e73aba23a0ee13f826cbc64f8200b9150784d004ccb2955c877c95ab888e3917f423dd52f3c8a49cb61c1966ec04f336068729ae0bce7d7fb3e680f9d15d658db9b906efcbf2c2fae45e75428":"":128:PSA_ERROR_INVALID_PADDING
 
 PSA decrypt: invalid algorithm
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_SHA_256:"adeecba2db7f867a733853f0136c554e5e01c7a2015721a9bfe30c3ad163b93a9c7589170311209f91420ad8a1a8280c7e890a6d7bca3c500b4da4f53a17bd84a21d58f979a9b4b8f2246b482d930804f12b3aeb2ac8b5ac7938d452ca13be8eb8e973c4e2b19fd454058cbae037bcef7ef68a5fbabf050de5f283cf1998c695":"":128:PSA_ERROR_INVALID_ARGUMENT
 
 PSA decrypt: RSA PKCS#1 v1.5, invalid key type (RSA public key)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C
 asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_PKCS1V15_CRYPT:"adeecba2db7f867a733853f0136c554e5e01c7a2015721a9bfe30c3ad163b93a9c7589170311209f91420ad8a1a8280c7e890a6d7bca3c500b4da4f53a17bd84a21d58f979a9b4b8f2246b482d930804f12b3aeb2ac8b5ac7938d452ca13be8eb8e973c4e2b19fd454058cbae037bcef7ef68a5fbabf050de5f283cf1998c695":"":128:PSA_ERROR_INVALID_ARGUMENT
 
 PSA decrypt: RSA OAEP, invalid key type (RSA public key)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"adeecba2db7f867a733853f0136c554e5e01c7a2015721a9bfe30c3ad163b93a9c7589170311209f91420ad8a1a8280c7e890a6d7bca3c500b4da4f53a17bd84a21d58f979a9b4b8f2246b482d930804f12b3aeb2ac8b5ac7938d452ca13be8eb8e973c4e2b19fd454058cbae037bcef7ef68a5fbabf050de5f283cf1998c695":"":128:PSA_ERROR_INVALID_ARGUMENT
 
 PSA decrypt: RSA PKCS#1 v1.5: invalid key type (AES)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PK_PARSE_C
 asymmetric_decrypt_fail:PSA_KEY_TYPE_AES:"3082025e02010002818100af057d396e":PSA_ALG_RSA_PKCS1V15_CRYPT:"3082025e02010002818100af057d396e":"":16:PSA_ERROR_INVALID_ARGUMENT
 
 PSA decrypt: RSA PKCS#1 v1.5, input too small
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"ffde2fcc00c9cc01972ebfa7779b298dbbaf7f50707a7405296dd2783456fc792002f462e760500e02afa25a859ace8701cb5d3b0262116431c43af8eb08f5a88301057cf1c156a2a5193c143e7a5b03fac132b7e89e6dcd8f4c82c9b28452329c260d30bc39b3816b7c46b41b37b4850d2ae74e729f99c6621fbbe2e46872":"":127:PSA_ERROR_INVALID_ARGUMENT
 
 PSA decrypt: RSA PKCS#1 v1.5, input too large
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C
 asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_CRYPT:"0099ffde2fcc00c9cc01972ebfa7779b298dbbaf7f50707a7405296dd2783456fc792002f462e760500e02afa25a859ace8701cb5d3b0262116431c43af8eb08f5a88301057cf1c156a2a5193c143e7a5b03fac132b7e89e6dcd8f4c82c9b28452329c260d30bc39b3816b7c46b41b37b4850d2ae74e729f99c6621fbbe2e46872":"":129:PSA_ERROR_INVALID_ARGUMENT
 
 PSA decrypt: RSA OAEP-SHA-256, input too small
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"ffde2fcc00c9cc01972ebfa7779b298dbbaf7f50707a7405296dd2783456fc792002f462e760500e02afa25a859ace8701cb5d3b0262116431c43af8eb08f5a88301057cf1c156a2a5193c143e7a5b03fac132b7e89e6dcd8f4c82c9b28452329c260d30bc39b3816b7c46b41b37b4850d2ae74e729f99c6621fbbe2e46872":"":127:PSA_ERROR_INVALID_ARGUMENT
 
 PSA decrypt: RSA OAEP-SHA-256, input too large
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_C
 asymmetric_decrypt_fail:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"0099ffde2fcc00c9cc01972ebfa7779b298dbbaf7f50707a7405296dd2783456fc792002f462e760500e02afa25a859ace8701cb5d3b0262116431c43af8eb08f5a88301057cf1c156a2a5193c143e7a5b03fac132b7e89e6dcd8f4c82c9b28452329c260d30bc39b3816b7c46b41b37b4850d2ae74e729f99c6621fbbe2e46872":"":129:PSA_ERROR_INVALID_ARGUMENT
 
 Crypto derivation operation object initializers zero properly
 key_derivation_init:
 
 PSA key derivation setup: HKDF-SHA-256, good case
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_setup:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_SUCCESS
 
 PSA key derivation setup: HKDF-SHA-512, good case
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_512
 derive_setup:PSA_ALG_HKDF(PSA_ALG_SHA_512):PSA_SUCCESS
 
 PSA key derivation setup: TLS 1.2 PRF SHA-256, good case
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_setup:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_SUCCESS
 
 PSA key derivation setup: not a key derivation algorithm (HMAC)
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256
 derive_setup:PSA_ALG_HMAC(PSA_ALG_SHA_256):PSA_ERROR_INVALID_ARGUMENT
 
 PSA key derivation setup: algorithm from bad hash
@@ -2120,503 +3211,618 @@
 derive_setup:PSA_ALG_CATEGORY_KEY_DERIVATION:PSA_ERROR_NOT_SUPPORTED
 
 PSA key derivation: HKDF-SHA-256, good case, direct output
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_SUCCESS
 
+PSA key derivation: HKDF-SHA-256, good case, omitted salt
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):0:UNUSED:"":UNUSED:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_SUCCESS
+
+PSA key derivation: HKDF-SHA-256, good case, info first
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_SUCCESS
+
+PSA key derivation: HKDF-SHA-256, good case, info after salt
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_SUCCESS
+
+PSA key derivation: HKDF-SHA-256, good case, omitted salt, info first
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:0:UNUSED:"":UNUSED:PSA_KEY_TYPE_NONE:PSA_SUCCESS
+
 PSA key derivation: HKDF-SHA-256, good case, key output
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_DERIVE:PSA_SUCCESS
 
 PSA key derivation: HKDF-SHA-512, good case
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_512
 derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_512):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_DERIVE:PSA_SUCCESS
 
 PSA key derivation: HKDF-SHA-256, bad key type
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_RAW_DATA:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
 
 PSA key derivation: HKDF-SHA-256, bad key type, key output
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 # Whether we get NOT_PERMITTED or BAD_STATE for the output is an implementation
 # detail.
-derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_RAW_DATA:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_RAW_DATA:PSA_ERROR_NOT_PERMITTED
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_RAW_DATA:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_RAW_DATA:PSA_ERROR_BAD_STATE
 
 PSA key derivation: HKDF-SHA-256, direct secret, direct output
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_SUCCESS
 
 PSA key derivation: HKDF-SHA-256, direct empty secret, direct output
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_SUCCESS
 
 PSA key derivation: HKDF-SHA-256, direct secret, key output
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_RAW_DATA:PSA_ERROR_NOT_PERMITTED
 
 PSA key derivation: HKDF-SHA-256, direct empty secret, key output
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_RAW_DATA:PSA_ERROR_NOT_PERMITTED
 
+PSA key derivation: HKDF-SHA-256, missing secret, key output
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:0:UNUSED:"":UNUSED:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_RAW_DATA:PSA_ERROR_NOT_PERMITTED
+
 PSA key derivation: HKDF-SHA-256, RAW_DATA key as salt
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_RAW_DATA:"412073616c74":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_DERIVE:PSA_SUCCESS
 
 PSA key derivation: HKDF-SHA-256, RAW_DATA key as info
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_RAW_DATA:"4120696e666f":PSA_SUCCESS:PSA_KEY_TYPE_DERIVE:PSA_SUCCESS
 
 PSA key derivation: HKDF-SHA-256, DERIVE key as salt, direct output
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_DERIVE:"412073616c74":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
 
 PSA key derivation: HKDF-SHA-256, DERIVE key as salt, key output
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 # Whether we get NOT_PERMITTED or BAD_STATE for the output is an implementation
 # detail.
 derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_DERIVE:"412073616c74":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_RAW_DATA:PSA_ERROR_BAD_STATE
 
 PSA key derivation: HKDF-SHA-256, DERIVE key as info
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_DERIVE:"4120696e666f":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
 
+PSA key derivation: HKDF-SHA-256, salt after secret
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: HKDF-SHA-256, missing secret
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:0:UNUSED:"":UNUSED:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: HKDF-SHA-256, missing info
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:0:UNUSED:"":UNUSED:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: HKDF-SHA-256, duplicate salt step
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: HKDF-SHA-256, duplicate secret step (direct, direct)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: HKDF-SHA-256, duplicate secret step (direct, key)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: HKDF-SHA-256, duplicate secret step (key, direct)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0a0a0a0a":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: HKDF-SHA-256, duplicate secret step (key, key)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0a0a0a0a":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: HKDF-SHA-256, duplicate info step (non-consecutive)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: HKDF-SHA-256, duplicate info step (consecutive)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: HKDF-SHA-256, reject label step
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_LABEL:PSA_KEY_TYPE_NONE:"":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: HKDF-SHA-256, reject seed step
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
 PSA key derivation: TLS 1.2 PRF SHA-256, good case
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_input:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_LABEL:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_DERIVE:PSA_SUCCESS
 
+PSA key derivation: ECDH with TLS 1.2 PRF SHA-256, good case
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+derive_input:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_LABEL:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_SUCCESS
+
+PSA key derivation: TLS 1.2 PRF SHA-256, missing label
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
+derive_input:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:0:UNUSED:"":UNUSED:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: ECDH with TLS 1.2 PRF SHA-256, missing label
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+derive_input:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":PSA_SUCCESS:0:UNUSED:"":UNUSED:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: TLS 1.2 PRF SHA-256, missing label and secret
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
+derive_input:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:0:UNUSED:"":UNUSED:0:UNUSED:"":UNUSED:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: ECDH with TLS 1.2 PRF SHA-256, missing label and secret
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+derive_input:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:0:UNUSED:"":UNUSED:0:UNUSED:"":UNUSED:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: TLS 1.2 PRF SHA-256, no inputs
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
+derive_input:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):0:UNUSED:"":UNUSED:0:UNUSED:"":UNUSED:0:UNUSED:"":UNUSED:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
+PSA key derivation: ECDH with TLS 1.2 PRF SHA-256, no inputs
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+derive_input:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)):0:UNUSED:"":UNUSED:0:UNUSED:"":UNUSED:0:UNUSED:"":UNUSED:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
 PSA key derivation: TLS 1.2 PRF SHA-256, key first
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_input:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_LABEL:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
 
+PSA key derivation: ECDH with TLS 1.2 PRF SHA-256, key first
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+derive_input:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)):PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_LABEL:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
+
 PSA key derivation: TLS 1.2 PRF SHA-256, label first
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_input:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_LABEL:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
 
 PSA key derivation: TLS 1.2 PRF SHA-256, early label
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_input:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_LABEL:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
 
 PSA key derivation: TLS 1.2 PRF SHA-256, double seed
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_input:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
 
 PSA key derivation: TLS 1.2 PRF SHA-256, double key
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_input:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
 
 PSA key derivation: TLS 1.2 PRF SHA-256, bad key type
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_input:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_RAW_DATA:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_LABEL:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
 
 PSA key derivation: TLS 1.2 PRF SHA-256, direct secret
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_input:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_LABEL:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_SUCCESS
 
 PSA key derivation: TLS 1.2 PRF SHA-256, direct empty secret
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_input:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_LABEL:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_SUCCESS
 
 PSA key derivation: TLS 1.2 PRF SHA-256, RAW_DATA key as seed
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_input:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_RAW_DATA:"612073656564":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_LABEL:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_DERIVE:PSA_SUCCESS
 
 PSA key derivation: TLS 1.2 PRF SHA-256, RAW_DATA key as label
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_input:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_LABEL:PSA_KEY_TYPE_RAW_DATA:"61206c6162656c":PSA_SUCCESS:PSA_KEY_TYPE_DERIVE:PSA_SUCCESS
 
 PSA key derivation: TLS 1.2 PRF SHA-256, DERIVE key as seed
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_input:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_DERIVE:"612073656564":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_LABEL:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
 
 PSA key derivation: TLS 1.2 PRF SHA-256, DERIVE key as label
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_input:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_LABEL:PSA_KEY_TYPE_DERIVE:"61206c6162656c":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
 
 PSA key derivation: TLS 1.2 PSK-to-MS, SHA-256, PSK too long (160 Bytes)
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS
 derive_input:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"01020304050607080102030405060708010203040506070801020304050607080102030405060708010203040506070801020304050607080102030405060708010203040506070801020304050607080102030405060708010203040506070801020304050607080102030405060708010203040506070801020304050607080102030405060708010203040506070801020304050607080102030405060708":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_LABEL:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
 
 PSA key derivation: ECDH on P256 with HKDF-SHA256, raw output
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 derive_input:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_SUCCESS
 
+PSA key derivation: ECDH on P256 with HKDF-SHA256, omitted salt
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+derive_input:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):0:UNUSED:"":UNUSED:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_SUCCESS
+
+PSA key derivation: ECDH on P256 with HKDF-SHA256, info first
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+derive_input:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_SUCCESS
+
 PSA key derivation: ECDH on P256 with HKDF-SHA256, key output
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 derive_input:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_RAW_DATA:PSA_SUCCESS
 
-PSA key derivation: HKDF invalid state (double generate + read past capacity)
-depends_on:MBEDTLS_SHA256_C
-test_derive_invalid_key_derivation_state:PSA_ALG_HKDF(PSA_ALG_SHA_256)
+PSA key derivation: ECDH on P256 with HKDF-SHA256, salt after secret
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+derive_input:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
 
-PSA key derivation: TLS 1.2 PRF invalid state (double generate + read past capacity)
-depends_on:MBEDTLS_SHA256_C
-test_derive_invalid_key_derivation_state:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)
+PSA key derivation: ECDH on P256 with HKDF-SHA256, missing info
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+derive_input:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":PSA_SUCCESS:0:UNUSED:"":UNUSED:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE
 
-PSA key derivation: invalid state (call read/get_capacity after init and abort)
-depends_on:MBEDTLS_SHA256_C
-test_derive_invalid_key_derivation_tests:
+PSA key derivation over capacity: HKDF
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_over_capacity:PSA_ALG_HKDF(PSA_ALG_SHA_256)
+
+PSA key derivation over capacity: TLS 1.2 PRF
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
+derive_over_capacity:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)
+
+PSA key derivation: actions without setup
+derive_actions_without_setup:
 
 PSA key derivation: HKDF SHA-256, RFC5869 #1, output 42+0
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"000102030405060708090a0b0c":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"f0f1f2f3f4f5f6f7f8f9":42:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865":""
 
 PSA key derivation: HKDF SHA-256, RFC5869 #1, output 32+10
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"000102030405060708090a0b0c":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"f0f1f2f3f4f5f6f7f8f9":42:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf":"34007208d5b887185865"
 
 PSA key derivation: HKDF SHA-256, RFC5869 #1, output 0+42
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"000102030405060708090a0b0c":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"f0f1f2f3f4f5f6f7f8f9":42:"":"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"
 
 PSA key derivation: HKDF SHA-256, RFC5869 #1, output 1+41
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"000102030405060708090a0b0c":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"f0f1f2f3f4f5f6f7f8f9":42:"3c":"b25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"
 
 PSA key derivation: HKDF SHA-256, RFC5869 #1, output 41+0
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"000102030405060708090a0b0c":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"f0f1f2f3f4f5f6f7f8f9":42:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b8871858":""
 
 PSA key derivation: HKDF SHA-256, RFC5869 #1, output 1+40
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"000102030405060708090a0b0c":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"f0f1f2f3f4f5f6f7f8f9":42:"3c":"b25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b8871858"
 
 PSA key derivation: HKDF SHA-256, RFC5869 #2, output 82+0
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf":PSA_KEY_DERIVATION_INPUT_SECRET:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f":PSA_KEY_DERIVATION_INPUT_INFO:"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":82:"b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87":""
 
 PSA key derivation: HKDF SHA-256, RFC5869 #3, output 42+0
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"":42:"8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8":""
 
 PSA key derivation: HKDF SHA-1, RFC5869 #4, output 42+0
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_1
 derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_1):PSA_KEY_DERIVATION_INPUT_SALT:"000102030405060708090a0b0c":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"f0f1f2f3f4f5f6f7f8f9":42:"085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896":""
 
 PSA key derivation: HKDF SHA-1, RFC5869 #5, output 82+0
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_1
 derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_1):PSA_KEY_DERIVATION_INPUT_SALT:"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf":PSA_KEY_DERIVATION_INPUT_SECRET:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f":PSA_KEY_DERIVATION_INPUT_INFO:"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":82:"0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4":""
 
 PSA key derivation: HKDF SHA-1, RFC5869 #6, output 42+0
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_1
 derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_1):PSA_KEY_DERIVATION_INPUT_SALT:"":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"":42:"0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918":""
 
 PSA key derivation: HKDF SHA-1, RFC5869 #7, output 42+0
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_1
 derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_1):PSA_KEY_DERIVATION_INPUT_SALT:"":PSA_KEY_DERIVATION_INPUT_SECRET:"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c":PSA_KEY_DERIVATION_INPUT_INFO:"":42:"2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48":""
 
 # Test vectors taken from https://www.ietf.org/mail-archive/web/tls/current/msg03416.html
 PSA key derivation: TLS 1.2 PRF SHA-256, output 100+0
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:"a0ba9f936cda311827a6f796ffd5198c":PSA_KEY_DERIVATION_INPUT_SECRET:"9bbe436ba940f017b17652849a71db35":PSA_KEY_DERIVATION_INPUT_LABEL:"74657374206c6162656c":100:"e3f229ba727be17b8d122620557cd453c2aab21d07c3d495329b52d4e61edb5a6b301791e90d35c9c9a46b4e14baf9af0fa022f7077def17abfd3797c0564bab4fbc91666e9def9b97fce34f796789baa48082d122ee42c5a72e5a5110fff70187347b66":""
 
 PSA key derivation: TLS 1.2 PRF SHA-256, output 99+1
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:"a0ba9f936cda311827a6f796ffd5198c":PSA_KEY_DERIVATION_INPUT_SECRET:"9bbe436ba940f017b17652849a71db35":PSA_KEY_DERIVATION_INPUT_LABEL:"74657374206c6162656c":100:"e3f229ba727be17b8d122620557cd453c2aab21d07c3d495329b52d4e61edb5a6b301791e90d35c9c9a46b4e14baf9af0fa022f7077def17abfd3797c0564bab4fbc91666e9def9b97fce34f796789baa48082d122ee42c5a72e5a5110fff70187347b":"66"
 
 PSA key derivation: TLS 1.2 PRF SHA-256, output 1+99
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:"a0ba9f936cda311827a6f796ffd5198c":PSA_KEY_DERIVATION_INPUT_SECRET:"9bbe436ba940f017b17652849a71db35":PSA_KEY_DERIVATION_INPUT_LABEL:"74657374206c6162656c":100:"e3":"f229ba727be17b8d122620557cd453c2aab21d07c3d495329b52d4e61edb5a6b301791e90d35c9c9a46b4e14baf9af0fa022f7077def17abfd3797c0564bab4fbc91666e9def9b97fce34f796789baa48082d122ee42c5a72e5a5110fff70187347b66"
 
 PSA key derivation: TLS 1.2 PRF SHA-256, output 50+50
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:"a0ba9f936cda311827a6f796ffd5198c":PSA_KEY_DERIVATION_INPUT_SECRET:"9bbe436ba940f017b17652849a71db35":PSA_KEY_DERIVATION_INPUT_LABEL:"74657374206c6162656c":100:"e3f229ba727be17b8d122620557cd453c2aab21d07c3d495329b52d4e61edb5a6b301791e90d35c9c9a46b4e14baf9af0fa0":"22f7077def17abfd3797c0564bab4fbc91666e9def9b97fce34f796789baa48082d122ee42c5a72e5a5110fff70187347b66"
 
 PSA key derivation: TLS 1.2 PRF SHA-256, output 50+49
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:"a0ba9f936cda311827a6f796ffd5198c":PSA_KEY_DERIVATION_INPUT_SECRET:"9bbe436ba940f017b17652849a71db35":PSA_KEY_DERIVATION_INPUT_LABEL:"74657374206c6162656c":100:"e3f229ba727be17b8d122620557cd453c2aab21d07c3d495329b52d4e61edb5a6b301791e90d35c9c9a46b4e14baf9af0fa0":"22f7077def17abfd3797c0564bab4fbc91666e9def9b97fce34f796789baa48082d122ee42c5a72e5a5110fff70187347b"
 
 PSA key derivation: TLS 1.2 PRF SHA-384, output 148+0
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PRF
 derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384):PSA_KEY_DERIVATION_INPUT_SEED:"cd665cf6a8447dd6ff8b27555edb7465":PSA_KEY_DERIVATION_INPUT_SECRET:"b80b733d6ceefcdc71566ea48e5567df":PSA_KEY_DERIVATION_INPUT_LABEL:"74657374206c6162656c":148:"7b0c18e9ced410ed1804f2cfa34a336a1c14dffb4900bb5fd7942107e81c83cde9ca0faa60be9fe34f82b1233c9146a0e534cb400fed2700884f9dc236f80edd8bfa961144c9e8d792eca722a7b32fc3d416d473ebc2c5fd4abfdad05d9184259b5bf8cd4d90fa0d31e2dec479e4f1a26066f2eea9a69236a3e52655c9e9aee691c8f3a26854308d5eaa3be85e0990703d73e56f":""
 
 PSA key derivation: TLS 1.2 PRF SHA-384, output 147+1
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PRF
 derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384):PSA_KEY_DERIVATION_INPUT_SEED:"cd665cf6a8447dd6ff8b27555edb7465":PSA_KEY_DERIVATION_INPUT_SECRET:"b80b733d6ceefcdc71566ea48e5567df":PSA_KEY_DERIVATION_INPUT_LABEL:"74657374206c6162656c":148:"7b0c18e9ced410ed1804f2cfa34a336a1c14dffb4900bb5fd7942107e81c83cde9ca0faa60be9fe34f82b1233c9146a0e534cb400fed2700884f9dc236f80edd8bfa961144c9e8d792eca722a7b32fc3d416d473ebc2c5fd4abfdad05d9184259b5bf8cd4d90fa0d31e2dec479e4f1a26066f2eea9a69236a3e52655c9e9aee691c8f3a26854308d5eaa3be85e0990703d73e5":"6f"
 
 PSA key derivation: TLS 1.2 PRF SHA-384, output 1+147
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PRF
 derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384):PSA_KEY_DERIVATION_INPUT_SEED:"cd665cf6a8447dd6ff8b27555edb7465":PSA_KEY_DERIVATION_INPUT_SECRET:"b80b733d6ceefcdc71566ea48e5567df":PSA_KEY_DERIVATION_INPUT_LABEL:"74657374206c6162656c":148:"7b":"0c18e9ced410ed1804f2cfa34a336a1c14dffb4900bb5fd7942107e81c83cde9ca0faa60be9fe34f82b1233c9146a0e534cb400fed2700884f9dc236f80edd8bfa961144c9e8d792eca722a7b32fc3d416d473ebc2c5fd4abfdad05d9184259b5bf8cd4d90fa0d31e2dec479e4f1a26066f2eea9a69236a3e52655c9e9aee691c8f3a26854308d5eaa3be85e0990703d73e56f"
 
 PSA key derivation: TLS 1.2 PRF SHA-384, output 74+74
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PRF
 derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384):PSA_KEY_DERIVATION_INPUT_SEED:"cd665cf6a8447dd6ff8b27555edb7465":PSA_KEY_DERIVATION_INPUT_SECRET:"b80b733d6ceefcdc71566ea48e5567df":PSA_KEY_DERIVATION_INPUT_LABEL:"74657374206c6162656c":148:"7b0c18e9ced410ed1804f2cfa34a336a1c14dffb4900bb5fd7942107e81c83cde9ca0faa60be9fe34f82b1233c9146a0e534cb400fed2700884f9dc236f80edd8bfa961144c9e8d792ec":"a722a7b32fc3d416d473ebc2c5fd4abfdad05d9184259b5bf8cd4d90fa0d31e2dec479e4f1a26066f2eea9a69236a3e52655c9e9aee691c8f3a26854308d5eaa3be85e0990703d73e56f"
 
 PSA key derivation: TLS 1.2 PRF SHA-384, output 74+73
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PRF
 derive_output:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384):PSA_KEY_DERIVATION_INPUT_SEED:"cd665cf6a8447dd6ff8b27555edb7465":PSA_KEY_DERIVATION_INPUT_SECRET:"b80b733d6ceefcdc71566ea48e5567df":PSA_KEY_DERIVATION_INPUT_LABEL:"74657374206c6162656c":148:"7b0c18e9ced410ed1804f2cfa34a336a1c14dffb4900bb5fd7942107e81c83cde9ca0faa60be9fe34f82b1233c9146a0e534cb400fed2700884f9dc236f80edd8bfa961144c9e8d792ec":"a722a7b32fc3d416d473ebc2c5fd4abfdad05d9184259b5bf8cd4d90fa0d31e2dec479e4f1a26066f2eea9a69236a3e52655c9e9aee691c8f3a26854308d5eaa3be85e0990703d73e5"
 
 # Test case manually extracted from debug output of TLS-PSK run
 # Label: "master secret"
 # Salt: Concatenation of ClientHello.Random and ServerHello.Random
 PSA key derivation: TLS 1.2 PSK-to-MS, SHA-256, 48+0
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS
 derive_output:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:"5bc0b19b4a8b24b07afe7ec65c471e94a7d518fcef06c3574315255c52afe21b5bc0b19b872b9b26508458f03603744d575f463a11ae7f1b090c012606fd3e9f":PSA_KEY_DERIVATION_INPUT_SECRET:"01020304":PSA_KEY_DERIVATION_INPUT_LABEL:"6d617374657220736563726574":48:"5a9dd5ffa78b4d1f28f40d91b4e6e6ed37849042d61ba32ca43d866e744cee7cd1baaa497e1ecd5c2e60f9f13030a710":""
 
 PSA key derivation: TLS 1.2 PSK-to-MS, SHA-256, 24+24
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS
 derive_output:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:"5bc0b19b4a8b24b07afe7ec65c471e94a7d518fcef06c3574315255c52afe21b5bc0b19b872b9b26508458f03603744d575f463a11ae7f1b090c012606fd3e9f":PSA_KEY_DERIVATION_INPUT_SECRET:"01020304":PSA_KEY_DERIVATION_INPUT_LABEL:"6d617374657220736563726574":48:"5a9dd5ffa78b4d1f28f40d91b4e6e6ed37849042d61ba32c":"a43d866e744cee7cd1baaa497e1ecd5c2e60f9f13030a710"
 
 PSA key derivation: TLS 1.2 PSK-to-MS, SHA-256, 0+48
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS
 derive_output:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SEED:"5bc0b19b4a8b24b07afe7ec65c471e94a7d518fcef06c3574315255c52afe21b5bc0b19b872b9b26508458f03603744d575f463a11ae7f1b090c012606fd3e9f":PSA_KEY_DERIVATION_INPUT_SECRET:"01020304":PSA_KEY_DERIVATION_INPUT_LABEL:"6d617374657220736563726574":48:"":"5a9dd5ffa78b4d1f28f40d91b4e6e6ed37849042d61ba32ca43d866e744cee7cd1baaa497e1ecd5c2e60f9f13030a710"
 
 PSA key derivation: TLS 1.2 PSK-to-MS, SHA-384, 48+0
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PSK_TO_MS
 derive_output:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384):PSA_KEY_DERIVATION_INPUT_SEED:"5bed47716a11a49a6268a8350b085929116ad9ccc8181f09a05b07a7741576d65bed47718dfd82f2d3f57544afe52decae6819b970dc716ada72ae0dd3072e9a":PSA_KEY_DERIVATION_INPUT_SECRET:"01020304":PSA_KEY_DERIVATION_INPUT_LABEL:"6d617374657220736563726574":48:"f5a61fbdd2ec415762abb8042a6c16645a53d2edb6dec8c85ca71689301f9f4d875128c87608b75250b20a9550e4fe18":""
 
 PSA key derivation: TLS 1.2 PSK-to-MS, SHA-384, 24+24
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PSK_TO_MS
 derive_output:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384):PSA_KEY_DERIVATION_INPUT_SEED:"5bed47716a11a49a6268a8350b085929116ad9ccc8181f09a05b07a7741576d65bed47718dfd82f2d3f57544afe52decae6819b970dc716ada72ae0dd3072e9a":PSA_KEY_DERIVATION_INPUT_SECRET:"01020304":PSA_KEY_DERIVATION_INPUT_LABEL:"6d617374657220736563726574":48:"":"f5a61fbdd2ec415762abb8042a6c16645a53d2edb6dec8c85ca71689301f9f4d875128c87608b75250b20a9550e4fe18"
 
 PSA key derivation: TLS 1.2 PSK-to-MS, SHA-384, 0+48
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PSK_TO_MS
 derive_output:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384):PSA_KEY_DERIVATION_INPUT_SEED:"5bed47716a11a49a6268a8350b085929116ad9ccc8181f09a05b07a7741576d65bed47718dfd82f2d3f57544afe52decae6819b970dc716ada72ae0dd3072e9a":PSA_KEY_DERIVATION_INPUT_SECRET:"01020304":PSA_KEY_DERIVATION_INPUT_LABEL:"6d617374657220736563726574":48:"f5a61fbdd2ec415762abb8042a6c16645a53d2edb6dec8c8":"5ca71689301f9f4d875128c87608b75250b20a9550e4fe18"
 
 PSA key derivation: HKDF SHA-256, request maximum capacity
-depends_on:MBEDTLS_SHA256_C
-derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"000102030405060708090a0b0c":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"f0f1f2f3f4f5f6f7f8f9":255 * 32:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865":""
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"000102030405060708090a0b0c":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"f0f1f2f3f4f5f6f7f8f9":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256):"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865":""
 
 PSA key derivation: HKDF SHA-1, request maximum capacity
-depends_on:MBEDTLS_SHA1_C
-derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_1):PSA_KEY_DERIVATION_INPUT_SALT:"":PSA_KEY_DERIVATION_INPUT_SECRET:"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c":PSA_KEY_DERIVATION_INPUT_INFO:"":255 * 20:"2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48":""
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_1
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_1):PSA_KEY_DERIVATION_INPUT_SALT:"":PSA_KEY_DERIVATION_INPUT_SECRET:"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c":PSA_KEY_DERIVATION_INPUT_INFO:"":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_1):"2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48":""
 
 PSA key derivation: HKDF SHA-256, request too much capacity
-depends_on:MBEDTLS_SHA256_C
-derive_set_capacity:PSA_ALG_HKDF(PSA_ALG_SHA_256):255 * 32 + 1:PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_set_capacity:PSA_ALG_HKDF(PSA_ALG_SHA_256):255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256) + 1:PSA_ERROR_INVALID_ARGUMENT
 
 PSA key derivation: HKDF SHA-1, request too much capacity
-depends_on:MBEDTLS_SHA1_C
-derive_set_capacity:PSA_ALG_HKDF(PSA_ALG_SHA_1):255 * 20 + 1:PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_1
+derive_set_capacity:PSA_ALG_HKDF(PSA_ALG_SHA_1):255 * PSA_HASH_LENGTH(PSA_ALG_SHA_1) + 1:PSA_ERROR_INVALID_ARGUMENT
 
 PSA key derivation: over capacity 42: output 42+1
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"000102030405060708090a0b0c":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"f0f1f2f3f4f5f6f7f8f9":42:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865":"ff"
 
 PSA key derivation: over capacity 42: output 41+2
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"000102030405060708090a0b0c":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"f0f1f2f3f4f5f6f7f8f9":42:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b8871858":"65ff"
 
 PSA key derivation: over capacity 42: output 43+0
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"000102030405060708090a0b0c":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"f0f1f2f3f4f5f6f7f8f9":42:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865ff":""
 
 PSA key derivation: over capacity 42: output 43+1
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"000102030405060708090a0b0c":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"f0f1f2f3f4f5f6f7f8f9":42:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865ff":"ff"
 
 PSA key derivation: HKDF SHA-256, read maximum capacity minus 1
-depends_on:MBEDTLS_SHA256_C
-derive_full:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * 32 - 1
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_full:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256) - 1
 
 PSA key derivation: HKDF SHA-256, read maximum capacity
-depends_on:MBEDTLS_SHA256_C
-derive_full:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * 32
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_full:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256)
 
 PSA key derivation: TLS 1.2 PRF SHA-256, read maximum capacity minus 1
-depends_on:MBEDTLS_SHA256_C
-derive_full:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * 32 - 1
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
+derive_full:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256) - 1
 
 PSA key derivation: TLS 1.2 PRF SHA-256, read maximum capacity
-depends_on:MBEDTLS_SHA256_C
-derive_full:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * 32
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
+derive_full:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256)
 
 PSA key derivation: HKDF SHA-256, exercise AES128-CTR
-depends_on:MBEDTLS_SHA256_C:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_AES
 derive_key_exercise:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
 
 PSA key derivation: HKDF SHA-256, exercise AES256-CTR
-depends_on:MBEDTLS_SHA256_C:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_AES
 derive_key_exercise:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_AES:256:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
 
 PSA key derivation: HKDF SHA-256, exercise DES-CBC
-depends_on:MBEDTLS_SHA256_C:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_DES
 derive_key_exercise:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_DES:64:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CBC_PKCS7
 
 PSA key derivation: HKDF SHA-256, exercise 2-key 3DES-CBC
-depends_on:MBEDTLS_SHA256_C:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_DES
 derive_key_exercise:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_DES:128:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CBC_PKCS7
 
 PSA key derivation: HKDF SHA-256, exercise 3-key 3DES-CBC
-depends_on:MBEDTLS_SHA256_C:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_DES
 derive_key_exercise:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_DES:192:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CBC_PKCS7
 
 PSA key derivation: HKDF SHA-256, exercise HMAC-SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
 derive_key_exercise:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_HMAC:256:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_HMAC(PSA_ALG_SHA_256)
 
 PSA key derivation: TLS 1.2 PRF SHA-256, exercise AES128-CTR
-depends_on:MBEDTLS_SHA256_C:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_AES
 derive_key_exercise:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
 
 PSA key derivation: TLS 1.2 PRF SHA-256, exercise AES256-CTR
-depends_on:MBEDTLS_SHA256_C:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_AES
 derive_key_exercise:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_AES:256:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
 
 PSA key derivation: TLS 1.2 PRF SHA-256, exercise DES-CBC
-depends_on:MBEDTLS_SHA256_C:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_DES
 derive_key_exercise:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_DES:64:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CBC_PKCS7
 
 PSA key derivation: TLS 1.2 PRF SHA-256, exercise 2-key 3DES-CBC
-depends_on:MBEDTLS_SHA256_C:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_DES
 derive_key_exercise:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_DES:128:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CBC_PKCS7
 
 PSA key derivation: TLS 1.2 PRF SHA-256, exercise 3-key 3DES-CBC
-depends_on:MBEDTLS_SHA256_C:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_DES
 derive_key_exercise:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_DES:192:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CBC_PKCS7
 
 PSA key derivation: TLS 1.2 PRF SHA-256, exercise HMAC-SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_HMAC
 derive_key_exercise:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_HMAC:256:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_HMAC(PSA_ALG_SHA_256)
 
 PSA key derivation: TLS 1.2 PRF SHA-256, exercise HKDF-SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_key_exercise:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_DERIVE:400:PSA_KEY_USAGE_DERIVE:PSA_ALG_HKDF(PSA_ALG_SHA_256)
 
 PSA key derivation: HKDF SHA-256, derive key export, 16+32
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_key_export:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":16:32
 
 PSA key derivation: HKDF SHA-256, derive key export, 1+41
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_key_export:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":1:41
 
 PSA key derivation: TLS 1.2 PRF SHA-256, derive key export, 16+32
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_key_export:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":16:32
 
 PSA key derivation: TLS 1.2 PRF SHA-256, derive key export, 1+41
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 derive_key_export:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":1:41
 
 PSA key derivation: invalid type (0)
-depends_on:MBEDTLS_SHA256_C
-derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_NONE:128:PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_NONE:128:PSA_ERROR_INVALID_ARGUMENT:0
 
 PSA key derivation: invalid type (PSA_KEY_TYPE_CATEGORY_MASK)
-depends_on:MBEDTLS_SHA256_C
-derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_CATEGORY_MASK:128:PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_CATEGORY_MASK:128:PSA_ERROR_INVALID_ARGUMENT:0
 
 PSA key derivation: invalid length (0)
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 # The spec allows either INVALID_ARGUMENT or NOT_SUPPORTED
-derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_RAW_DATA:0:PSA_ERROR_INVALID_ARGUMENT
+derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_RAW_DATA:0:PSA_ERROR_INVALID_ARGUMENT:0
 
 PSA key derivation: invalid length (7 bits)
-depends_on:MBEDTLS_SHA256_C
-derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_RAW_DATA:7:PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_RAW_DATA:7:PSA_ERROR_INVALID_ARGUMENT:0
 
 PSA key derivation: raw data, 8 bits
-depends_on:MBEDTLS_SHA256_C
-derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_RAW_DATA:8:PSA_SUCCESS
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_RAW_DATA:8:PSA_SUCCESS:0
 
 PSA key derivation: invalid length (9 bits)
-depends_on:MBEDTLS_SHA256_C
-derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_RAW_DATA:9:PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_RAW_DATA:9:PSA_ERROR_INVALID_ARGUMENT:0
 
 # This test assumes that PSA_MAX_KEY_BITS (currently 65536-8 bits = 8191 bytes
 # and not expected to be raised any time soon) is less than the maximum
 # output from HKDF-SHA512 (255*64 = 16320 bytes).
 PSA key derivation: largest possible key
-depends_on:MBEDTLS_SHA512_C
-derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_512):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_RAW_DATA:PSA_MAX_KEY_BITS:PSA_SUCCESS
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_512
+derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_512):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_RAW_DATA:PSA_MAX_KEY_BITS:PSA_SUCCESS:1
 
 PSA key derivation: key too large
-depends_on:MBEDTLS_SHA512_C
-derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_512):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_RAW_DATA:PSA_MAX_KEY_BITS + 1:PSA_ERROR_NOT_SUPPORTED
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_512
+derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_512):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_RAW_DATA:PSA_MAX_KEY_BITS + 1:PSA_ERROR_NOT_SUPPORTED:0
 
 PSA key agreement setup: ECDH + HKDF-SHA-256: good
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 key_agreement_setup:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_SUCCESS
 
 PSA key agreement setup: ECDH + HKDF-SHA-256: good, key algorithm broader than required
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 key_agreement_setup:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_ECDH:"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_SUCCESS
 
 PSA key agreement setup: ECDH + HKDF-SHA-256: key algorithm KDF mismatch
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 key_agreement_setup:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_512)):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_ERROR_NOT_PERMITTED
 
 PSA key agreement setup: ECDH + HKDF-SHA-256: public key not on curve
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 key_agreement_setup:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ff":PSA_ERROR_INVALID_ARGUMENT
 
 PSA key agreement setup: ECDH + HKDF-SHA-256: public key on different curve
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ECC_SECP_R1_384
 key_agreement_setup:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04e558dbef53eecde3d3fccfc1aea08a89a987475d12fd950d83cfa41732bc509d0d1ac43a0336def96fda41d0774a3571dcfbec7aacf3196472169e838430367f66eebe3c6e70c416dd5f0c68759dd1fff83fa40142209dff5eaad96db9e6386c":PSA_ERROR_INVALID_ARGUMENT
 
 PSA key agreement setup: ECDH + HKDF-SHA-256: public key instead of private key
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 key_agreement_setup:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_ERROR_INVALID_ARGUMENT
 
 PSA key agreement setup: ECDH, unknown KDF
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C
+depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_ECDH_C
 key_agreement_setup:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(0)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(0)):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_ERROR_NOT_SUPPORTED
 
 PSA key agreement setup: bad key agreement algorithm
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 key_agreement_setup:PSA_ALG_KEY_AGREEMENT(0, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_KEY_AGREEMENT(0, PSA_ALG_HKDF(PSA_ALG_SHA_256)):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_ERROR_INVALID_ARGUMENT
 
 PSA key agreement setup: KDF instead of a key agreement algorithm
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 key_agreement_setup:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_HKDF(PSA_ALG_SHA_256):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_ERROR_INVALID_ARGUMENT
 
 PSA raw key agreement: ECDH SECP256R1 (RFC 5903)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 raw_key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de"
 
 PSA raw key agreement: ECDH SECP384R1 (RFC 5903)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_384
 raw_key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"099f3c7034d4a2c699884d73a375a67f7624ef7c6b3c0f160647b67414dce655e35b538041e649ee3faef896783ab194":"04e558dbef53eecde3d3fccfc1aea08a89a987475d12fd950d83cfa41732bc509d0d1ac43a0336def96fda41d0774a3571dcfbec7aacf3196472169e838430367f66eebe3c6e70c416dd5f0c68759dd1fff83fa40142209dff5eaad96db9e6386c":"11187331c279962d93d604243fd592cb9d0a926f422e47187521287e7156c5c4d603135569b9e9d09cf5d4a270f59746"
 
 PSA raw key agreement: ECDH SECP521R1 (RFC 5903)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_521
 raw_key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"0037ade9319a89f4dabdb3ef411aaccca5123c61acab57b5393dce47608172a095aa85a30fe1c2952c6771d937ba9777f5957b2639bab072462f68c27a57382d4a52":"0400d0b3975ac4b799f5bea16d5e13e9af971d5e9b984c9f39728b5e5739735a219b97c356436adc6e95bb0352f6be64a6c2912d4ef2d0433ced2b6171640012d9460f015c68226383956e3bd066e797b623c27ce0eac2f551a10c2c724d9852077b87220b6536c5c408a1d2aebb8e86d678ae49cb57091f4732296579ab44fcd17f0fc56a":"01144c7d79ae6956bc8edb8e7c787c4521cb086fa64407f97894e5e6b2d79b04d1427e73ca4baa240a34786859810c06b3c715a3a8cc3151f2bee417996d19f3ddea"
 
 PSA raw key agreement: ECDH brainpoolP256r1 (RFC 7027)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP256R1_ENABLED:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_BRAINPOOL_P_R1_256
 raw_key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"81db1ee100150ff2ea338d708271be38300cb54241d79950f77b063039804f1d":"048d2d688c6cf93e1160ad04cc4429117dc2c41825e1e9fca0addd34e6f1b39f7b990c57520812be512641e47034832106bc7d3e8dd0e4c7f1136d7006547cec6a":"89afc39d41d3b327814b80940b042590f96556ec91e6ae7939bce31f3a18bf2b"
 
 PSA raw key agreement: ECDH brainpoolP384r1 (RFC 7027)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP384R1_ENABLED:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_BRAINPOOL_P_R1_384
 raw_key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"1e20f5e048a5886f1f157c74e91bde2b98c8b52d58e5003d57053fc4b0bd65d6f15eb5d1ee1610df870795143627d042":"044d44326f269a597a5b58bba565da5556ed7fd9a8a9eb76c25f46db69d19dc8ce6ad18e404b15738b2086df37e71d1eb462d692136de56cbe93bf5fa3188ef58bc8a3a0ec6c1e151a21038a42e9185329b5b275903d192f8d4e1f32fe9cc78c48":"0bd9d3a7ea0b3d519d09d8e48d0785fb744a6b355e6304bc51c229fbbce239bbadf6403715c35d4fb2a5444f575d4f42"
 
 PSA raw key agreement: ECDH brainpoolP512r1 (RFC 7027)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP512R1_ENABLED:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_BRAINPOOL_P_R1_512
 raw_key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"16302ff0dbbb5a8d733dab7141c1b45acbc8715939677f6a56850a38bd87bd59b09e80279609ff333eb9d4c061231fb26f92eeb04982a5f1d1764cad57665422":"049d45f66de5d67e2e6db6e93a59ce0bb48106097ff78a081de781cdb31fce8ccbaaea8dd4320c4119f1e9cd437a2eab3731fa9668ab268d871deda55a5473199f2fdc313095bcdd5fb3a91636f07a959c8e86b5636a1e930e8396049cb481961d365cc11453a06c719835475b12cb52fc3c383bce35e27ef194512b71876285fa":"a7927098655f1f9976fa50a9d566865dc530331846381c87256baf3226244b76d36403c024d7bbf0aa0803eaff405d3d24f11a9b5c0bef679fe1454b21c4cd1f"
 
 PSA raw key agreement: X25519 (RFC 7748: Alice)
-depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_CURVE25519_ENABLED:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_MONTGOMERY_255
 raw_key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):"77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a":"de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f":"4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"
 
 PSA raw key agreement: X25519 (RFC 7748: Bob)
-depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_CURVE25519_ENABLED:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_MONTGOMERY_255
 raw_key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):"5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb":"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a":"4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"
 
 PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: capacity=8160
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 key_agreement_capacity:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":8160
 
 PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 32+0
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 key_agreement_output:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"3bf511eebadf44c1f7b0282a1262fe4ddd9da23bb1555cfda591ac46b088c441":""
 
 PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 31+1
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 key_agreement_output:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"3bf511eebadf44c1f7b0282a1262fe4ddd9da23bb1555cfda591ac46b088c4":"41"
 
 PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 1+31
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 key_agreement_output:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"3b":"f511eebadf44c1f7b0282a1262fe4ddd9da23bb1555cfda591ac46b088c441"
 
 PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 0+32
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 key_agreement_output:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"":"3bf511eebadf44c1f7b0282a1262fe4ddd9da23bb1555cfda591ac46b088c441"
 
 PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 32+32
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 key_agreement_output:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"3bf511eebadf44c1f7b0282a1262fe4ddd9da23bb1555cfda591ac46b088c441":"7883c010f6e37cd6942c63bd8a65d8648c736bf8330b539760e18db13888d992"
 
 PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: read 64+0
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 key_agreement_output:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"3bf511eebadf44c1f7b0282a1262fe4ddd9da23bb1555cfda591ac46b088c4417883c010f6e37cd6942c63bd8a65d8648c736bf8330b539760e18db13888d992":""
 
 PSA generate random: 0 bytes
@@ -2646,115 +3852,113 @@
 PSA generate random: 2*MBEDTLS_CTR_DRBG_MAX_REQUEST+1 bytes
 generate_random:2 * MBEDTLS_CTR_DRBG_MAX_REQUEST + 1
 
-PSA generate key: bad type (0)
-generate_key:PSA_KEY_TYPE_NONE:128:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED
-
-PSA generate key: bad type (PSA_KEY_TYPE_CATEGORY_MASK)
-generate_key:PSA_KEY_TYPE_CATEGORY_MASK:128:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED
-
 PSA generate key: bad type (RSA public key)
-generate_key:PSA_KEY_TYPE_RSA_PUBLIC_KEY:512:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED
+depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
+generate_key:PSA_KEY_TYPE_RSA_PUBLIC_KEY:512:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_ARGUMENT:0
 
 PSA generate key: raw data, 0 bits: invalid argument
 # The spec allows either INVALID_ARGUMENT or NOT_SUPPORTED
-generate_key:PSA_KEY_TYPE_RAW_DATA:0:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_ARGUMENT
+generate_key:PSA_KEY_TYPE_RAW_DATA:0:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_ARGUMENT:0
 
 PSA generate key: raw data, 7 bits: invalid argument
-generate_key:PSA_KEY_TYPE_RAW_DATA:7:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_ARGUMENT
+generate_key:PSA_KEY_TYPE_RAW_DATA:7:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_ARGUMENT:0
 
 PSA generate key: raw data, 8 bits
-generate_key:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS
+generate_key:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS:0
 
 PSA generate key: raw data, 9 bits: invalid argument
-generate_key:PSA_KEY_TYPE_RAW_DATA:9:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_ARGUMENT
+generate_key:PSA_KEY_TYPE_RAW_DATA:9:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_ARGUMENT:0
 
 PSA generate key: raw data, (MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8 bits
-generate_key:PSA_KEY_TYPE_RAW_DATA:(MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS
+generate_key:PSA_KEY_TYPE_RAW_DATA:(MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS:0
 
 PSA generate key: raw data, (2 * MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8 bits
-generate_key:PSA_KEY_TYPE_RAW_DATA:(2 * MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS
+generate_key:PSA_KEY_TYPE_RAW_DATA:(2 * MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS:0
 
-PSA generate key: raw data, 65528 bits (ok)
-depends_on:HAVE_RAM_AVAILABLE_128K
-generate_key:PSA_KEY_TYPE_RAW_DATA:65528:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS
+PSA generate key: raw data, 65528 bits (large key, ok if it fits)
+generate_key:PSA_KEY_TYPE_RAW_DATA:65528:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS:1
 
 PSA generate key: raw data, 65536 bits (not supported)
-generate_key:PSA_KEY_TYPE_RAW_DATA:65536:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED
+generate_key:PSA_KEY_TYPE_RAW_DATA:65536:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED:0
 
 PSA generate key: AES, 128 bits, CTR
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-generate_key:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_SUCCESS
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+generate_key:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_SUCCESS:0
 
 PSA generate key: AES, 128 bits, GCM
-depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
-generate_key:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_GCM:PSA_SUCCESS
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+generate_key:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_GCM:PSA_SUCCESS:0
 
 PSA generate key: DES, 64 bits, CBC-nopad
-depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
-generate_key:PSA_KEY_TYPE_DES:64:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CBC_NO_PADDING:PSA_SUCCESS
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+generate_key:PSA_KEY_TYPE_DES:64:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CBC_NO_PADDING:PSA_SUCCESS:0
 
 PSA generate key: DES, 128 bits, CBC-nopad
-depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
-generate_key:PSA_KEY_TYPE_DES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CBC_NO_PADDING:PSA_SUCCESS
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+generate_key:PSA_KEY_TYPE_DES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CBC_NO_PADDING:PSA_SUCCESS:0
 
 PSA generate key: DES, 192 bits, CBC-nopad
-depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
-generate_key:PSA_KEY_TYPE_DES:192:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CBC_NO_PADDING:PSA_SUCCESS
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES
+generate_key:PSA_KEY_TYPE_DES:192:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CBC_NO_PADDING:PSA_SUCCESS:0
 
 PSA generate key: invalid key size: AES, 64 bits
-depends_on:MBEDTLS_AES_C
-generate_key:PSA_KEY_TYPE_AES:64:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_ERROR_INVALID_ARGUMENT
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+generate_key:PSA_KEY_TYPE_AES:64:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_ERROR_INVALID_ARGUMENT:0
 
 PSA generate key: RSA, 512 bits, good, sign (PKCS#1 v1.5)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
-generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:512:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_SUCCESS
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_GENPRIME
+generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:512:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_SUCCESS:0
 
 PSA generate key: RSA, 1016 bits, good, sign (PKCS#1 v1.5)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_MD_C:MBEDTLS_PKCS1_V15
-generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:1016:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_SUCCESS
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_GENPRIME:MBEDTLS_MD_C
+generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:1016:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_SUCCESS:0
 
 PSA generate key: RSA, 1024 bits, good, sign (PSS SHA-256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
-generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_SUCCESS
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_GENPRIME:MBEDTLS_MD_C
+generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_SUCCESS:0
+
+PSA generate key: RSA, 1024 bits, good, sign (PSS-any-salt SHA-256)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_GENPRIME:MBEDTLS_MD_C
+generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):PSA_SUCCESS:0
 
 PSA generate key: RSA, 512 bits, good, encrypt (PKCS#1 v1.5)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
-generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:512:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_SUCCESS
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_GENPRIME
+generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:512:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_SUCCESS:0
 
 PSA generate key: RSA, 1024 bits, good, encrypt (OAEP SHA-256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
-generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):PSA_SUCCESS
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_GENPRIME:MBEDTLS_MD_C
+generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):PSA_SUCCESS:0
 
 PSA generate key: RSA, 0 bits: invalid
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_GENPRIME
 # The spec allows either INVALID_ARGUMENT or NOT_SUPPORTED
-generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ERROR_INVALID_ARGUMENT
+generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ERROR_INVALID_ARGUMENT:0
 
 PSA generate key: RSA, 1022 bits: not supported
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:1022:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ERROR_NOT_SUPPORTED
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_GENPRIME
+generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:1022:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ERROR_NOT_SUPPORTED:0
 
 PSA generate key: RSA, 1023 bits: not supported
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:1023:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ERROR_NOT_SUPPORTED
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_GENPRIME
+generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:1023:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ERROR_NOT_SUPPORTED:0
 
 PSA generate key: RSA, maximum size exceeded
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_MAX_KEY_BITS+1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ERROR_NOT_SUPPORTED
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_GENPRIME
+generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_MAX_KEY_BITS+1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ERROR_NOT_SUPPORTED:0
 
 PSA generate key: ECC, SECP256R1, good
-depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C
-generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:PSA_SUCCESS
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:PSA_SUCCESS:0
 
 PSA generate key: ECC, SECP256R1, incorrect bit size
-depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
 # INVALID_ARGUMENT would make more sense, but our code as currently structured
 # doesn't fully relate the curve with its size.
-generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:PSA_ERROR_NOT_SUPPORTED
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:PSA_ERROR_NOT_SUPPORTED:0
 
 PSA generate key: ECC, Curve25519, good
-depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_CURVE25519_ENABLED:MBEDTLS_ECDH_C
-generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):255:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_SUCCESS
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_MONTGOMERY_255
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):255:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_SUCCESS:0
 
 PSA generate key: RSA, default e
 generate_key_rsa:512:"":PSA_SUCCESS
@@ -2775,15 +3979,15 @@
 generate_key_rsa:512:"01":PSA_ERROR_INVALID_ARGUMENT
 
 PSA import persistent key: raw data, 8 bits
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
+depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
 persistent_key_load_key_from_storage:"2a":PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:IMPORT_KEY
 
 PSA import persistent key: AES, 128 bits, exportable
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
 persistent_key_load_key_from_storage:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:IMPORT_KEY
 
 PSA import persistent key: AES, 128 bits, non-exportable
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
 persistent_key_load_key_from_storage:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:IMPORT_KEY
 
 PSA generate persistent key: raw data, 8 bits, exportable
@@ -2791,25 +3995,24 @@
 persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:GENERATE_KEY
 
 PSA generate persistent key: AES, 128 bits, exportable
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR:MBEDTLS_PSA_CRYPTO_STORAGE_C
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_CRYPTO_STORAGE_C
 persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:GENERATE_KEY
 
 PSA generate persistent key: AES, 128 bits, non-exportable
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR:MBEDTLS_PSA_CRYPTO_STORAGE_C
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_CRYPTO_STORAGE_C
 persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:GENERATE_KEY
 
 PSA generate persistent key: DES, 64 bits, exportable
-depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_PSA_CRYPTO_STORAGE_C
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES:MBEDTLS_PSA_CRYPTO_STORAGE_C
 persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_DES:64:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CBC_NO_PADDING:GENERATE_KEY
 
 PSA generate persistent key: RSA, 1024 bits, exportable
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_MD_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_GENPRIME:MBEDTLS_MD_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
 persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):GENERATE_KEY
 
 PSA generate persistent key: ECC, SECP256R1, exportable
-depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PSA_CRYPTO_STORAGE_C
 persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:GENERATE_KEY
 
 PSA derive persistent key: HKDF SHA-256, exportable
-depends_on:MBEDTLS_SHA256_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
 persistent_key_load_key_from_storage:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_TYPE_RAW_DATA:1024:PSA_KEY_USAGE_EXPORT:0:DERIVE_KEY
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto.function b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto.function
index 8e71610..eb9458f 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto.function
@@ -9,118 +9,24 @@
  * uses mbedtls_ctr_drbg internally. */
 #include "mbedtls/ctr_drbg.h"
 
-#include "test/psa_crypto_helpers.h"
-
-/* Tests that require more than 128kB of RAM plus change have this symbol
- * as a dependency. Currently we always define this symbol, so the tests
- * are always executed. In the future we should make this conditional
- * so that tests that require a lot of memory are skipped on constrained
- * platforms. */
-#define HAVE_RAM_AVAILABLE_128K
-
 #include "psa/crypto.h"
 #include "psa_crypto_slot_management.h"
 
+#include "test/asn1_helpers.h"
+#include "test/psa_crypto_helpers.h"
+#include "test/psa_exercise_key.h"
+
+/* If this comes up, it's a bug in the test code or in the test data. */
+#define UNUSED 0xdeadbeef
+
+/* Assert that an operation is (not) active.
+ * This serves as a proxy for checking if the operation is aborted. */
+#define ASSERT_OPERATION_IS_ACTIVE(   operation ) TEST_ASSERT( operation.id != 0 )
+#define ASSERT_OPERATION_IS_INACTIVE( operation ) TEST_ASSERT( operation.id == 0 )
+
 /** An invalid export length that will never be set by psa_export_key(). */
 static const size_t INVALID_EXPORT_LENGTH = ~0U;
 
-/* A hash algorithm that is known to be supported.
- *
- * This is used in some smoke tests.
- */
-#if defined(MBEDTLS_MD2_C)
-#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_MD2
-#elif defined(MBEDTLS_MD4_C)
-#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_MD4
-#elif defined(MBEDTLS_MD5_C)
-#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_MD5
-/* MBEDTLS_RIPEMD160_C omitted. This is necessary for the sake of
- * exercise_signature_key() because Mbed TLS doesn't support RIPEMD160
- * in RSA PKCS#1v1.5 signatures. A RIPEMD160-only configuration would be
- * implausible anyway. */
-#elif defined(MBEDTLS_SHA1_C)
-#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_1
-#elif defined(MBEDTLS_SHA256_C)
-#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_256
-#elif defined(MBEDTLS_SHA512_C)
-#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_384
-#elif defined(MBEDTLS_SHA3_C)
-#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA3_256
-#else
-#undef KNOWN_SUPPORTED_HASH_ALG
-#endif
-
-/* A block cipher that is known to be supported.
- *
- * For simplicity's sake, stick to block ciphers with 16-byte blocks.
- */
-#if defined(MBEDTLS_AES_C)
-#define KNOWN_SUPPORTED_BLOCK_CIPHER PSA_KEY_TYPE_AES
-#elif defined(MBEDTLS_ARIA_C)
-#define KNOWN_SUPPORTED_BLOCK_CIPHER PSA_KEY_TYPE_ARIA
-#elif defined(MBEDTLS_CAMELLIA_C)
-#define KNOWN_SUPPORTED_BLOCK_CIPHER PSA_KEY_TYPE_CAMELLIA
-#undef KNOWN_SUPPORTED_BLOCK_CIPHER
-#endif
-
-/* A MAC mode that is known to be supported.
- *
- * It must either be HMAC with #KNOWN_SUPPORTED_HASH_ALG or
- * a block cipher-based MAC with #KNOWN_SUPPORTED_BLOCK_CIPHER.
- *
- * This is used in some smoke tests.
- */
-#if defined(KNOWN_SUPPORTED_HASH_ALG)
-#define KNOWN_SUPPORTED_MAC_ALG ( PSA_ALG_HMAC( KNOWN_SUPPORTED_HASH_ALG ) )
-#define KNOWN_SUPPORTED_MAC_KEY_TYPE PSA_KEY_TYPE_HMAC
-#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CMAC_C)
-#define KNOWN_SUPPORTED_MAC_ALG PSA_ALG_CMAC
-#define KNOWN_SUPPORTED_MAC_KEY_TYPE KNOWN_SUPPORTED_BLOCK_CIPHER
-#else
-#undef KNOWN_SUPPORTED_MAC_ALG
-#undef KNOWN_SUPPORTED_MAC_KEY_TYPE
-#endif
-
-/* A cipher algorithm and key type that are known to be supported.
- *
- * This is used in some smoke tests.
- */
-#if defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CIPHER_MODE_CTR)
-#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_CTR
-#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CIPHER_MODE_CBC)
-#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_CBC_NO_PADDING
-#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CIPHER_MODE_CFB)
-#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_CFB
-#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CIPHER_MODE_OFB)
-#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_OFB
-#else
-#undef KNOWN_SUPPORTED_BLOCK_CIPHER_ALG
-#endif
-#if defined(KNOWN_SUPPORTED_BLOCK_CIPHER_ALG)
-#define KNOWN_SUPPORTED_CIPHER_ALG KNOWN_SUPPORTED_BLOCK_CIPHER_ALG
-#define KNOWN_SUPPORTED_CIPHER_KEY_TYPE KNOWN_SUPPORTED_BLOCK_CIPHER
-#elif defined(MBEDTLS_RC4_C)
-#define KNOWN_SUPPORTED_CIPHER_ALG PSA_ALG_RC4
-#define KNOWN_SUPPORTED_CIPHER_KEY_TYPE PSA_KEY_TYPE_RC4
-#else
-#undef KNOWN_SUPPORTED_CIPHER_ALG
-#undef KNOWN_SUPPORTED_CIPHER_KEY_TYPE
-#endif
-
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-int lifetime_is_dynamic_secure_element( psa_key_lifetime_t lifetime )
-{
-    return( PSA_KEY_LIFETIME_GET_LOCATION( lifetime ) !=
-            PSA_KEY_LOCATION_LOCAL_STORAGE );
-}
-#else
-int lifetime_is_secure_element( psa_key_lifetime_t lifetime )
-{
-    (void) lifetime;
-    return( 0 );
-}
-#endif
-
 /** Test if a buffer contains a constant byte value.
  *
  * `mem_is_char(buffer, c, size)` is true after `memset(buffer, c, size)`.
@@ -227,80 +133,6 @@
     return( len );
 }
 
-int check_key_attributes_sanity( mbedtls_svc_key_id_t key )
-{
-    int ok = 0;
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_lifetime_t lifetime;
-    mbedtls_svc_key_id_t id;
-    psa_key_type_t type;
-    psa_key_type_t bits;
-
-    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
-    lifetime = psa_get_key_lifetime( &attributes );
-    id = psa_get_key_id( &attributes );
-    type = psa_get_key_type( &attributes );
-    bits = psa_get_key_bits( &attributes );
-
-    /* Persistence */
-    if( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) )
-    {
-        TEST_ASSERT(
-            ( PSA_KEY_ID_VOLATILE_MIN <=
-              MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ) &&
-            ( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) <=
-              PSA_KEY_ID_VOLATILE_MAX ) );
-    }
-    else
-    {
-        TEST_ASSERT(
-            ( PSA_KEY_ID_USER_MIN <= MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ) &&
-            ( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) <= PSA_KEY_ID_USER_MAX ) );
-    }
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    /* randomly-generated 64-bit constant, should never appear in test data */
-    psa_key_slot_number_t slot_number = 0xec94d4a5058a1a21;
-    psa_status_t status = psa_get_key_slot_number( &attributes, &slot_number );
-    if( lifetime_is_dynamic_secure_element( lifetime ) )
-    {
-        /* Mbed Crypto currently always exposes the slot number to
-         * applications. This is not mandated by the PSA specification
-         * and may change in future versions. */
-        TEST_EQUAL( status, 0 );
-        TEST_ASSERT( slot_number != 0xec94d4a5058a1a21 );
-    }
-    else
-    {
-        TEST_EQUAL( status, PSA_ERROR_INVALID_ARGUMENT );
-    }
-#endif
-
-    /* Type and size */
-    TEST_ASSERT( type != 0 );
-    TEST_ASSERT( bits != 0 );
-    TEST_ASSERT( bits <= PSA_MAX_KEY_BITS );
-    if( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) )
-        TEST_ASSERT( bits % 8 == 0 );
-
-    /* MAX macros concerning specific key types */
-    if( PSA_KEY_TYPE_IS_ECC( type ) )
-        TEST_ASSERT( bits <= PSA_VENDOR_ECC_MAX_CURVE_BITS );
-    else if( PSA_KEY_TYPE_IS_RSA( type ) )
-        TEST_ASSERT( bits <= PSA_VENDOR_RSA_MAX_KEY_BITS );
-    TEST_ASSERT( PSA_BLOCK_CIPHER_BLOCK_SIZE( type ) <= PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE );
-
-    ok = 1;
-
-exit:
-    /*
-     * Key attributes may have been returned by psa_get_key_attributes()
-     * thus reset them as required.
-     */
-    psa_reset_key_attributes( &attributes );
-
-    return( ok );
-}
-
 int exercise_mac_setup( psa_key_type_t key_type,
                         const unsigned char *key_bytes,
                         size_t key_length,
@@ -368,836 +200,6 @@
     return( 0 );
 }
 
-static int exercise_mac_key( mbedtls_svc_key_id_t key,
-                             psa_key_usage_t usage,
-                             psa_algorithm_t alg )
-{
-    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
-    const unsigned char input[] = "foo";
-    unsigned char mac[PSA_MAC_MAX_SIZE] = {0};
-    size_t mac_length = sizeof( mac );
-
-    if( usage & PSA_KEY_USAGE_SIGN_HASH )
-    {
-        PSA_ASSERT( psa_mac_sign_setup( &operation, key, alg ) );
-        PSA_ASSERT( psa_mac_update( &operation,
-                                    input, sizeof( input ) ) );
-        PSA_ASSERT( psa_mac_sign_finish( &operation,
-                                         mac, sizeof( mac ),
-                                         &mac_length ) );
-    }
-
-    if( usage & PSA_KEY_USAGE_VERIFY_HASH )
-    {
-        psa_status_t verify_status =
-            ( usage & PSA_KEY_USAGE_SIGN_HASH ?
-              PSA_SUCCESS :
-              PSA_ERROR_INVALID_SIGNATURE );
-        PSA_ASSERT( psa_mac_verify_setup( &operation, key, alg ) );
-        PSA_ASSERT( psa_mac_update( &operation,
-                                    input, sizeof( input ) ) );
-        TEST_EQUAL( psa_mac_verify_finish( &operation, mac, mac_length ),
-                    verify_status );
-    }
-
-    return( 1 );
-
-exit:
-    psa_mac_abort( &operation );
-    return( 0 );
-}
-
-static int exercise_cipher_key( mbedtls_svc_key_id_t key,
-                                psa_key_usage_t usage,
-                                psa_algorithm_t alg )
-{
-    psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
-    unsigned char iv[16] = {0};
-    size_t iv_length = sizeof( iv );
-    const unsigned char plaintext[16] = "Hello, world...";
-    unsigned char ciphertext[32] = "(wabblewebblewibblewobblewubble)";
-    size_t ciphertext_length = sizeof( ciphertext );
-    unsigned char decrypted[sizeof( ciphertext )];
-    size_t part_length;
-
-    if( usage & PSA_KEY_USAGE_ENCRYPT )
-    {
-        PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
-        PSA_ASSERT( psa_cipher_generate_iv( &operation,
-                                            iv, sizeof( iv ),
-                                            &iv_length ) );
-        PSA_ASSERT( psa_cipher_update( &operation,
-                                       plaintext, sizeof( plaintext ),
-                                       ciphertext, sizeof( ciphertext ),
-                                       &ciphertext_length ) );
-        PSA_ASSERT( psa_cipher_finish( &operation,
-                                       ciphertext + ciphertext_length,
-                                       sizeof( ciphertext ) - ciphertext_length,
-                                       &part_length ) );
-        ciphertext_length += part_length;
-    }
-
-    if( usage & PSA_KEY_USAGE_DECRYPT )
-    {
-        psa_status_t status;
-        int maybe_invalid_padding = 0;
-        if( ! ( usage & PSA_KEY_USAGE_ENCRYPT ) )
-        {
-            psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-            PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
-            /* This should be PSA_CIPHER_GET_IV_SIZE but the API doesn't
-             * have this macro yet. */
-            iv_length = PSA_BLOCK_CIPHER_BLOCK_SIZE(
-                psa_get_key_type( &attributes ) );
-            maybe_invalid_padding = ! PSA_ALG_IS_STREAM_CIPHER( alg );
-            psa_reset_key_attributes( &attributes );
-        }
-        PSA_ASSERT( psa_cipher_decrypt_setup( &operation, key, alg ) );
-        PSA_ASSERT( psa_cipher_set_iv( &operation,
-                                       iv, iv_length ) );
-        PSA_ASSERT( psa_cipher_update( &operation,
-                                       ciphertext, ciphertext_length,
-                                       decrypted, sizeof( decrypted ),
-                                       &part_length ) );
-        status = psa_cipher_finish( &operation,
-                                    decrypted + part_length,
-                                    sizeof( decrypted ) - part_length,
-                                    &part_length );
-        /* For a stream cipher, all inputs are valid. For a block cipher,
-         * if the input is some aribtrary data rather than an actual
-         ciphertext, a padding error is likely.  */
-        if( maybe_invalid_padding )
-            TEST_ASSERT( status == PSA_SUCCESS ||
-                         status == PSA_ERROR_INVALID_PADDING );
-        else
-            PSA_ASSERT( status );
-    }
-
-    return( 1 );
-
-exit:
-    psa_cipher_abort( &operation );
-    return( 0 );
-}
-
-static int exercise_aead_key( mbedtls_svc_key_id_t key,
-                              psa_key_usage_t usage,
-                              psa_algorithm_t alg )
-{
-    unsigned char nonce[16] = {0};
-    size_t nonce_length = sizeof( nonce );
-    unsigned char plaintext[16] = "Hello, world...";
-    unsigned char ciphertext[48] = "(wabblewebblewibblewobblewubble)";
-    size_t ciphertext_length = sizeof( ciphertext );
-    size_t plaintext_length = sizeof( ciphertext );
-
-    if( usage & PSA_KEY_USAGE_ENCRYPT )
-    {
-        PSA_ASSERT( psa_aead_encrypt( key, alg,
-                                      nonce, nonce_length,
-                                      NULL, 0,
-                                      plaintext, sizeof( plaintext ),
-                                      ciphertext, sizeof( ciphertext ),
-                                      &ciphertext_length ) );
-    }
-
-    if( usage & PSA_KEY_USAGE_DECRYPT )
-    {
-        psa_status_t verify_status =
-            ( usage & PSA_KEY_USAGE_ENCRYPT ?
-              PSA_SUCCESS :
-              PSA_ERROR_INVALID_SIGNATURE );
-        TEST_EQUAL( psa_aead_decrypt( key, alg,
-                                      nonce, nonce_length,
-                                      NULL, 0,
-                                      ciphertext, ciphertext_length,
-                                      plaintext, sizeof( plaintext ),
-                                      &plaintext_length ),
-                    verify_status );
-    }
-
-    return( 1 );
-
-exit:
-    return( 0 );
-}
-
-static int exercise_signature_key( mbedtls_svc_key_id_t key,
-                                   psa_key_usage_t usage,
-                                   psa_algorithm_t alg )
-{
-    unsigned char payload[PSA_HASH_MAX_SIZE] = {1};
-    size_t payload_length = 16;
-    unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = {0};
-    size_t signature_length = sizeof( signature );
-    psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
-
-    /* If the policy allows signing with any hash, just pick one. */
-    if( PSA_ALG_IS_HASH_AND_SIGN( alg ) && hash_alg == PSA_ALG_ANY_HASH )
-    {
-#if defined(KNOWN_SUPPORTED_HASH_ALG)
-        hash_alg = KNOWN_SUPPORTED_HASH_ALG;
-        alg ^= PSA_ALG_ANY_HASH ^ hash_alg;
-#else
-        test_fail( "No hash algorithm for hash-and-sign testing", __LINE__, __FILE__ );
-        return( 1 );
-#endif
-    }
-
-    if( usage & PSA_KEY_USAGE_SIGN_HASH )
-    {
-        /* Some algorithms require the payload to have the size of
-         * the hash encoded in the algorithm. Use this input size
-         * even for algorithms that allow other input sizes. */
-        if( hash_alg != 0 )
-            payload_length = PSA_HASH_SIZE( hash_alg );
-        PSA_ASSERT( psa_sign_hash( key, alg,
-                                   payload, payload_length,
-                                   signature, sizeof( signature ),
-                                   &signature_length ) );
-    }
-
-    if( usage & PSA_KEY_USAGE_VERIFY_HASH )
-    {
-        psa_status_t verify_status =
-            ( usage & PSA_KEY_USAGE_SIGN_HASH ?
-              PSA_SUCCESS :
-              PSA_ERROR_INVALID_SIGNATURE );
-        TEST_EQUAL( psa_verify_hash( key, alg,
-                                     payload, payload_length,
-                                     signature, signature_length ),
-                    verify_status );
-    }
-
-    return( 1 );
-
-exit:
-    return( 0 );
-}
-
-static int exercise_asymmetric_encryption_key( mbedtls_svc_key_id_t key,
-                                               psa_key_usage_t usage,
-                                               psa_algorithm_t alg )
-{
-    unsigned char plaintext[256] = "Hello, world...";
-    unsigned char ciphertext[256] = "(wabblewebblewibblewobblewubble)";
-    size_t ciphertext_length = sizeof( ciphertext );
-    size_t plaintext_length = 16;
-
-    if( usage & PSA_KEY_USAGE_ENCRYPT )
-    {
-        PSA_ASSERT( psa_asymmetric_encrypt( key, alg,
-                                            plaintext, plaintext_length,
-                                            NULL, 0,
-                                            ciphertext, sizeof( ciphertext ),
-                                            &ciphertext_length ) );
-    }
-
-    if( usage & PSA_KEY_USAGE_DECRYPT )
-    {
-        psa_status_t status =
-            psa_asymmetric_decrypt( key, alg,
-                                    ciphertext, ciphertext_length,
-                                    NULL, 0,
-                                    plaintext, sizeof( plaintext ),
-                                    &plaintext_length );
-        TEST_ASSERT( status == PSA_SUCCESS ||
-                     ( ( usage & PSA_KEY_USAGE_ENCRYPT ) == 0 &&
-                       ( status == PSA_ERROR_INVALID_ARGUMENT ||
-                         status == PSA_ERROR_INVALID_PADDING ) ) );
-    }
-
-    return( 1 );
-
-exit:
-    return( 0 );
-}
-
-static int setup_key_derivation_wrap( psa_key_derivation_operation_t* operation,
-                                      mbedtls_svc_key_id_t key,
-                                      psa_algorithm_t alg,
-                                      unsigned char* input1, size_t input1_length,
-                                      unsigned char* input2, size_t input2_length,
-                                      size_t capacity )
-{
-    PSA_ASSERT( psa_key_derivation_setup( operation, alg ) );
-    if( PSA_ALG_IS_HKDF( alg ) )
-    {
-        PSA_ASSERT( psa_key_derivation_input_bytes( operation,
-                                                    PSA_KEY_DERIVATION_INPUT_SALT,
-                                                    input1, input1_length ) );
-        PSA_ASSERT( psa_key_derivation_input_key( operation,
-                                                  PSA_KEY_DERIVATION_INPUT_SECRET,
-                                                  key ) );
-        PSA_ASSERT( psa_key_derivation_input_bytes( operation,
-                                                    PSA_KEY_DERIVATION_INPUT_INFO,
-                                                    input2,
-                                                    input2_length ) );
-    }
-    else if( PSA_ALG_IS_TLS12_PRF( alg ) ||
-             PSA_ALG_IS_TLS12_PSK_TO_MS( alg ) )
-    {
-        PSA_ASSERT( psa_key_derivation_input_bytes( operation,
-                                                    PSA_KEY_DERIVATION_INPUT_SEED,
-                                                    input1, input1_length ) );
-        PSA_ASSERT( psa_key_derivation_input_key( operation,
-                                                  PSA_KEY_DERIVATION_INPUT_SECRET,
-                                                  key ) );
-        PSA_ASSERT( psa_key_derivation_input_bytes( operation,
-                                                    PSA_KEY_DERIVATION_INPUT_LABEL,
-                                                    input2, input2_length ) );
-    }
-    else
-    {
-        TEST_ASSERT( ! "Key derivation algorithm not supported" );
-    }
-
-    if( capacity != SIZE_MAX )
-        PSA_ASSERT( psa_key_derivation_set_capacity( operation, capacity ) );
-
-    return( 1 );
-
-exit:
-    return( 0 );
-}
-
-
-static int exercise_key_derivation_key( mbedtls_svc_key_id_t key,
-                                        psa_key_usage_t usage,
-                                        psa_algorithm_t alg )
-{
-    psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
-    unsigned char input1[] = "Input 1";
-    size_t input1_length = sizeof( input1 );
-    unsigned char input2[] = "Input 2";
-    size_t input2_length = sizeof( input2 );
-    unsigned char output[1];
-    size_t capacity = sizeof( output );
-
-    if( usage & PSA_KEY_USAGE_DERIVE )
-    {
-        if( !setup_key_derivation_wrap( &operation, key, alg,
-                                        input1, input1_length,
-                                        input2, input2_length, capacity ) )
-            goto exit;
-
-        PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
-                                                     output,
-                                                     capacity ) );
-        PSA_ASSERT( psa_key_derivation_abort( &operation ) );
-    }
-
-    return( 1 );
-
-exit:
-    return( 0 );
-}
-
-/* We need two keys to exercise key agreement. Exercise the
- * private key against its own public key. */
-static psa_status_t key_agreement_with_self(
-    psa_key_derivation_operation_t *operation,
-    mbedtls_svc_key_id_t key )
-{
-    psa_key_type_t private_key_type;
-    psa_key_type_t public_key_type;
-    size_t key_bits;
-    uint8_t *public_key = NULL;
-    size_t public_key_length;
-    /* Return GENERIC_ERROR if something other than the final call to
-     * psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
-     * but it's good enough: callers will report it as a failed test anyway. */
-    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-
-    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
-    private_key_type = psa_get_key_type( &attributes );
-    key_bits = psa_get_key_bits( &attributes );
-    public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( private_key_type );
-    public_key_length = PSA_KEY_EXPORT_MAX_SIZE( public_key_type, key_bits );
-    ASSERT_ALLOC( public_key, public_key_length );
-    PSA_ASSERT( psa_export_public_key( key, public_key, public_key_length,
-                                       &public_key_length ) );
-
-    status = psa_key_derivation_key_agreement(
-        operation, PSA_KEY_DERIVATION_INPUT_SECRET, key,
-        public_key, public_key_length );
-exit:
-    /*
-     * Key attributes may have been returned by psa_get_key_attributes()
-     * thus reset them as required.
-     */
-    psa_reset_key_attributes( &attributes );
-
-    mbedtls_free( public_key );
-    return( status );
-}
-
-/* We need two keys to exercise key agreement. Exercise the
- * private key against its own public key. */
-static psa_status_t raw_key_agreement_with_self( psa_algorithm_t alg,
-                                                 mbedtls_svc_key_id_t key )
-{
-    psa_key_type_t private_key_type;
-    psa_key_type_t public_key_type;
-    size_t key_bits;
-    uint8_t *public_key = NULL;
-    size_t public_key_length;
-    uint8_t output[1024];
-    size_t output_length;
-    /* Return GENERIC_ERROR if something other than the final call to
-     * psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
-     * but it's good enough: callers will report it as a failed test anyway. */
-    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-
-    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
-    private_key_type = psa_get_key_type( &attributes );
-    key_bits = psa_get_key_bits( &attributes );
-    public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( private_key_type );
-    public_key_length = PSA_KEY_EXPORT_MAX_SIZE( public_key_type, key_bits );
-    ASSERT_ALLOC( public_key, public_key_length );
-    PSA_ASSERT( psa_export_public_key( key,
-                                       public_key, public_key_length,
-                                       &public_key_length ) );
-
-    status = psa_raw_key_agreement( alg, key,
-                                    public_key, public_key_length,
-                                    output, sizeof( output ), &output_length );
-exit:
-    /*
-     * Key attributes may have been returned by psa_get_key_attributes()
-     * thus reset them as required.
-     */
-    psa_reset_key_attributes( &attributes );
-
-    mbedtls_free( public_key );
-    return( status );
-}
-
-static int exercise_raw_key_agreement_key( mbedtls_svc_key_id_t key,
-                                           psa_key_usage_t usage,
-                                           psa_algorithm_t alg )
-{
-    int ok = 0;
-
-    if( usage & PSA_KEY_USAGE_DERIVE )
-    {
-        /* We need two keys to exercise key agreement. Exercise the
-         * private key against its own public key. */
-        PSA_ASSERT( raw_key_agreement_with_self( alg, key ) );
-    }
-    ok = 1;
-
-exit:
-    return( ok );
-}
-
-static int exercise_key_agreement_key( mbedtls_svc_key_id_t key,
-                                       psa_key_usage_t usage,
-                                       psa_algorithm_t alg )
-{
-    psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
-    unsigned char output[1];
-    int ok = 0;
-
-    if( usage & PSA_KEY_USAGE_DERIVE )
-    {
-        /* We need two keys to exercise key agreement. Exercise the
-         * private key against its own public key. */
-        PSA_ASSERT( psa_key_derivation_setup( &operation, alg ) );
-        PSA_ASSERT( key_agreement_with_self( &operation, key ) );
-        PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
-                                                     output,
-                                                     sizeof( output ) ) );
-        PSA_ASSERT( psa_key_derivation_abort( &operation ) );
-    }
-    ok = 1;
-
-exit:
-    return( ok );
-}
-
-int asn1_skip_integer( unsigned char **p, const unsigned char *end,
-                       size_t min_bits, size_t max_bits,
-                       int must_be_odd )
-{
-    size_t len;
-    size_t actual_bits;
-    unsigned char msb;
-    TEST_EQUAL( mbedtls_asn1_get_tag( p, end, &len,
-                                      MBEDTLS_ASN1_INTEGER ),
-                0 );
-
-    /* Check if the retrieved length doesn't extend the actual buffer's size.
-     * It is assumed here, that end >= p, which validates casting to size_t. */
-    TEST_ASSERT( len <= (size_t)( end - *p) );
-
-    /* Tolerate a slight departure from DER encoding:
-     * - 0 may be represented by an empty string or a 1-byte string.
-     * - The sign bit may be used as a value bit. */
-    if( ( len == 1 && ( *p )[0] == 0 ) ||
-        ( len > 1 && ( *p )[0] == 0 && ( ( *p )[1] & 0x80 ) != 0 ) )
-    {
-        ++( *p );
-        --len;
-    }
-    if( min_bits == 0 && len == 0 )
-        return( 1 );
-    msb = ( *p )[0];
-    TEST_ASSERT( msb != 0 );
-    actual_bits = 8 * ( len - 1 );
-    while( msb != 0 )
-    {
-        msb >>= 1;
-        ++actual_bits;
-    }
-    TEST_ASSERT( actual_bits >= min_bits );
-    TEST_ASSERT( actual_bits <= max_bits );
-    if( must_be_odd )
-        TEST_ASSERT( ( ( *p )[len-1] & 1 ) != 0 );
-    *p += len;
-    return( 1 );
-exit:
-    return( 0 );
-}
-
-static int exported_key_sanity_check( psa_key_type_t type, size_t bits,
-                                      uint8_t *exported, size_t exported_length )
-{
-    if( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) )
-        TEST_EQUAL( exported_length, ( bits + 7 ) / 8 );
-    else
-        TEST_ASSERT( exported_length <= PSA_KEY_EXPORT_MAX_SIZE( type, bits ) );
-
-#if defined(MBEDTLS_DES_C)
-    if( type == PSA_KEY_TYPE_DES )
-    {
-        /* Check the parity bits. */
-        unsigned i;
-        for( i = 0; i < bits / 8; i++ )
-        {
-            unsigned bit_count = 0;
-            unsigned m;
-            for( m = 1; m <= 0x100; m <<= 1 )
-            {
-                if( exported[i] & m )
-                    ++bit_count;
-            }
-            TEST_ASSERT( bit_count % 2 != 0 );
-        }
-    }
-    else
-#endif
-
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C)
-    if( type == PSA_KEY_TYPE_RSA_KEY_PAIR )
-    {
-        uint8_t *p = exported;
-        uint8_t *end = exported + exported_length;
-        size_t len;
-        /*   RSAPrivateKey ::= SEQUENCE {
-         *       version             INTEGER,  -- must be 0
-         *       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
-         *   }
-         */
-        TEST_EQUAL( mbedtls_asn1_get_tag( &p, end, &len,
-                                          MBEDTLS_ASN1_SEQUENCE |
-                                          MBEDTLS_ASN1_CONSTRUCTED ), 0 );
-        TEST_EQUAL( p + len, end );
-        if( ! asn1_skip_integer( &p, end, 0, 0, 0 ) )
-            goto exit;
-        if( ! asn1_skip_integer( &p, end, bits, bits, 1 ) )
-            goto exit;
-        if( ! asn1_skip_integer( &p, end, 2, bits, 1 ) )
-            goto exit;
-        /* Require d to be at least half the size of n. */
-        if( ! asn1_skip_integer( &p, end, bits / 2, bits, 1 ) )
-            goto exit;
-        /* Require p and q to be at most half the size of n, rounded up. */
-        if( ! asn1_skip_integer( &p, end, bits / 2, bits / 2 + 1, 1 ) )
-            goto exit;
-        if( ! asn1_skip_integer( &p, end, bits / 2, bits / 2 + 1, 1 ) )
-            goto exit;
-        if( ! asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
-            goto exit;
-        if( ! asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
-            goto exit;
-        if( ! asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
-            goto exit;
-        TEST_EQUAL( p, end );
-    }
-    else
-#endif /* MBEDTLS_RSA_C */
-
-#if defined(MBEDTLS_ECP_C)
-    if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( type ) )
-    {
-        /* Just the secret value */
-        TEST_EQUAL( exported_length, PSA_BITS_TO_BYTES( bits ) );
-    }
-    else
-#endif /* MBEDTLS_ECP_C */
-
-    if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) )
-    {
-        uint8_t *p = exported;
-        uint8_t *end = exported + exported_length;
-#if defined(MBEDTLS_RSA_C)
-        if( type == PSA_KEY_TYPE_RSA_PUBLIC_KEY )
-        {
-            size_t len;
-            /*   RSAPublicKey ::= SEQUENCE {
-             *      modulus            INTEGER,    -- n
-             *      publicExponent     INTEGER  }  -- e
-             */
-            TEST_EQUAL( mbedtls_asn1_get_tag( &p, end, &len,
-                                              MBEDTLS_ASN1_SEQUENCE |
-                                              MBEDTLS_ASN1_CONSTRUCTED ),
-                        0 );
-            TEST_EQUAL( p + len, end );
-            if( ! asn1_skip_integer( &p, end, bits, bits, 1 ) )
-                goto exit;
-            if( ! asn1_skip_integer( &p, end, 2, bits, 1 ) )
-                goto exit;
-            TEST_EQUAL( p, end );
-        }
-        else
-#endif /* MBEDTLS_RSA_C */
-#if defined(MBEDTLS_ECP_C)
-        if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( type ) )
-        {
-            if( PSA_KEY_TYPE_ECC_GET_FAMILY( type ) == PSA_ECC_FAMILY_MONTGOMERY )
-            {
-                /* The representation of an ECC Montgomery public key is
-                 * the raw compressed point */
-                 TEST_EQUAL( p + PSA_BITS_TO_BYTES( bits ), end );
-            }
-            else
-            {
-                /* The representation of an ECC Weierstrass public key is:
-                 *      - 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;
-                 *      - where m is the bit size associated with the curve.
-                 */
-                TEST_EQUAL( p + 1 + 2 * PSA_BITS_TO_BYTES( bits ), end );
-                TEST_EQUAL( p[0], 4 );
-            }
-        }
-        else
-#endif /* MBEDTLS_ECP_C */
-        {
-            char message[47];
-            mbedtls_snprintf( message, sizeof( message ),
-                              "No sanity check for public key type=0x%08lx",
-                              (unsigned long) type );
-            test_fail( message, __LINE__, __FILE__ );
-            (void) p;
-            (void) end;
-            return( 0 );
-        }
-    }
-    else
-
-    {
-        /* No sanity checks for other types */
-    }
-
-    return( 1 );
-
-exit:
-    return( 0 );
-}
-
-static int exercise_export_key( mbedtls_svc_key_id_t key,
-                                psa_key_usage_t usage )
-{
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    uint8_t *exported = NULL;
-    size_t exported_size = 0;
-    size_t exported_length = 0;
-    int ok = 0;
-
-    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
-
-    if( ( usage & PSA_KEY_USAGE_EXPORT ) == 0 &&
-        ! PSA_KEY_TYPE_IS_PUBLIC_KEY( psa_get_key_type( &attributes ) ) )
-    {
-        TEST_EQUAL( psa_export_key( key, NULL, 0, &exported_length ),
-                    PSA_ERROR_NOT_PERMITTED );
-        ok = 1;
-        goto exit;
-    }
-
-    exported_size = PSA_KEY_EXPORT_MAX_SIZE( psa_get_key_type( &attributes ),
-                                             psa_get_key_bits( &attributes ) );
-    ASSERT_ALLOC( exported, exported_size );
-
-    PSA_ASSERT( psa_export_key( key,
-                                exported, exported_size,
-                                &exported_length ) );
-    ok = exported_key_sanity_check( psa_get_key_type( &attributes ),
-                                    psa_get_key_bits( &attributes ),
-                                    exported, exported_length );
-
-exit:
-    /*
-     * Key attributes may have been returned by psa_get_key_attributes()
-     * thus reset them as required.
-     */
-    psa_reset_key_attributes( &attributes );
-
-    mbedtls_free( exported );
-    return( ok );
-}
-
-static int exercise_export_public_key( mbedtls_svc_key_id_t key )
-{
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_type_t public_type;
-    uint8_t *exported = NULL;
-    size_t exported_size = 0;
-    size_t exported_length = 0;
-    int ok = 0;
-
-    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
-    if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( psa_get_key_type( &attributes ) ) )
-    {
-        TEST_EQUAL( psa_export_public_key( key, NULL, 0, &exported_length ),
-                    PSA_ERROR_INVALID_ARGUMENT );
-        return( 1 );
-    }
-
-    public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(
-        psa_get_key_type( &attributes ) );
-    exported_size = PSA_KEY_EXPORT_MAX_SIZE( public_type,
-                                             psa_get_key_bits( &attributes ) );
-    ASSERT_ALLOC( exported, exported_size );
-
-    PSA_ASSERT( psa_export_public_key( key,
-                                       exported, exported_size,
-                                       &exported_length ) );
-    ok = exported_key_sanity_check( public_type,
-                                    psa_get_key_bits( &attributes ),
-                                    exported, exported_length );
-
-exit:
-    /*
-     * Key attributes may have been returned by psa_get_key_attributes()
-     * thus reset them as required.
-     */
-    psa_reset_key_attributes( &attributes );
-
-    mbedtls_free( exported );
-    return( ok );
-}
-
-/** Do smoke tests on a key.
- *
- * Perform one of each operation indicated by \p alg (decrypt/encrypt,
- * sign/verify, or derivation) that is permitted according to \p usage.
- * \p usage and \p alg should correspond to the expected policy on the
- * key.
- *
- * Export the key if permitted by \p usage, and check that the output
- * looks sensible. If \p usage forbids export, check that
- * \p psa_export_key correctly rejects the attempt. If the key is
- * asymmetric, also check \p psa_export_public_key.
- *
- * If the key fails the tests, this function calls the test framework's
- * `test_fail` function and returns false. Otherwise this function returns
- * true. Therefore it should be used as follows:
- * ```
- * if( ! exercise_key( ... ) ) goto exit;
- * ```
- *
- * \param key       The key to exercise. It should be capable of performing
- *                  \p alg.
- * \param usage     The usage flags to assume.
- * \param alg       The algorithm to exercise.
- *
- * \retval 0 The key failed the smoke tests.
- * \retval 1 The key passed the smoke tests.
- */
-static int exercise_key( mbedtls_svc_key_id_t key,
-                         psa_key_usage_t usage,
-                         psa_algorithm_t alg )
-{
-    int ok;
-
-    if( ! check_key_attributes_sanity( key ) )
-        return( 0 );
-
-    if( alg == 0 )
-        ok = 1; /* If no algorihm, do nothing (used for raw data "keys"). */
-    else if( PSA_ALG_IS_MAC( alg ) )
-        ok = exercise_mac_key( key, usage, alg );
-    else if( PSA_ALG_IS_CIPHER( alg ) )
-        ok = exercise_cipher_key( key, usage, alg );
-    else if( PSA_ALG_IS_AEAD( alg ) )
-        ok = exercise_aead_key( key, usage, alg );
-    else if( PSA_ALG_IS_SIGN( alg ) )
-        ok = exercise_signature_key( key, usage, alg );
-    else if( PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) )
-        ok = exercise_asymmetric_encryption_key( key, usage, alg );
-    else if( PSA_ALG_IS_KEY_DERIVATION( alg ) )
-        ok = exercise_key_derivation_key( key, usage, alg );
-    else if( PSA_ALG_IS_RAW_KEY_AGREEMENT( alg ) )
-        ok = exercise_raw_key_agreement_key( key, usage, alg );
-    else if( PSA_ALG_IS_KEY_AGREEMENT( alg ) )
-        ok = exercise_key_agreement_key( key, usage, alg );
-    else
-    {
-        char message[40];
-        mbedtls_snprintf( message, sizeof( message ),
-                          "No code to exercise alg=0x%08lx",
-                          (unsigned long) alg );
-        test_fail( message, __LINE__, __FILE__ );
-        ok = 0;
-    }
-
-    ok = ok && exercise_export_key( key, usage );
-    ok = ok && exercise_export_public_key( key );
-
-    return( ok );
-}
-
-static psa_key_usage_t usage_to_exercise( psa_key_type_t type,
-                                          psa_algorithm_t alg )
-{
-    if( PSA_ALG_IS_MAC( alg ) || PSA_ALG_IS_SIGN( alg ) )
-    {
-        return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
-                PSA_KEY_USAGE_VERIFY_HASH :
-                PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH );
-    }
-    else if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) ||
-             PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) )
-    {
-        return( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ?
-                PSA_KEY_USAGE_ENCRYPT :
-                PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
-    }
-    else if( PSA_ALG_IS_KEY_DERIVATION( alg ) ||
-             PSA_ALG_IS_KEY_AGREEMENT( alg ) )
-    {
-        return( PSA_KEY_USAGE_DERIVE );
-    }
-    else
-    {
-        return( 0 );
-    }
-
-}
-
 static int test_operations_on_invalid_key( mbedtls_svc_key_id_t key )
 {
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -1211,7 +213,7 @@
     psa_set_key_algorithm( &attributes, PSA_ALG_CTR );
     psa_set_key_type( &attributes, PSA_KEY_TYPE_AES );
     TEST_EQUAL( psa_get_key_attributes( key, &attributes ),
-                PSA_ERROR_DOES_NOT_EXIST );
+                PSA_ERROR_INVALID_HANDLE );
     TEST_EQUAL(
         MBEDTLS_SVC_KEY_ID_GET_KEY_ID( psa_get_key_id( &attributes ) ), 0 );
     TEST_EQUAL(
@@ -1223,10 +225,10 @@
     TEST_EQUAL( psa_get_key_bits( &attributes ), 0 );
 
     TEST_EQUAL( psa_export_key( key, buffer, sizeof( buffer ), &length ),
-                PSA_ERROR_DOES_NOT_EXIST );
+                PSA_ERROR_INVALID_HANDLE );
     TEST_EQUAL( psa_export_public_key( key,
                                        buffer, sizeof( buffer ), &length ),
-                PSA_ERROR_DOES_NOT_EXIST );
+                PSA_ERROR_INVALID_HANDLE );
 
     ok = 1;
 
@@ -1352,127 +354,6 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void attributes_set_get( int owner_id_arg, int id_arg, int lifetime_arg,
-                         int usage_flags_arg, int alg_arg,
-                         int type_arg, int bits_arg )
-{
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( owner_id_arg, id_arg );
-    psa_key_lifetime_t lifetime = lifetime_arg;
-    psa_key_usage_t usage_flags = usage_flags_arg;
-    psa_algorithm_t alg = alg_arg;
-    psa_key_type_t type = type_arg;
-    size_t bits = bits_arg;
-
-    TEST_EQUAL(
-        MBEDTLS_SVC_KEY_ID_GET_KEY_ID( psa_get_key_id( &attributes ) ), 0 );
-    TEST_EQUAL(
-        MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( psa_get_key_id( &attributes ) ), 0 );
-    TEST_EQUAL( psa_get_key_lifetime( &attributes ), 0 );
-    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 );
-    TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
-    TEST_EQUAL( psa_get_key_type( &attributes ), 0 );
-    TEST_EQUAL( psa_get_key_bits( &attributes ), 0 );
-
-    psa_set_key_id( &attributes, id );
-    psa_set_key_lifetime( &attributes, lifetime );
-    psa_set_key_usage_flags( &attributes, usage_flags );
-    psa_set_key_algorithm( &attributes, alg );
-    psa_set_key_type( &attributes, type );
-    psa_set_key_bits( &attributes, bits );
-
-    TEST_ASSERT( mbedtls_svc_key_id_equal(
-                     psa_get_key_id( &attributes ), id ) );
-    TEST_EQUAL( psa_get_key_lifetime( &attributes ), lifetime );
-    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage_flags );
-    TEST_EQUAL( psa_get_key_algorithm( &attributes ), alg );
-    TEST_EQUAL( psa_get_key_type( &attributes ), type );
-    TEST_EQUAL( psa_get_key_bits( &attributes ), bits );
-
-    psa_reset_key_attributes( &attributes );
-
-    TEST_EQUAL(
-        MBEDTLS_SVC_KEY_ID_GET_KEY_ID( psa_get_key_id( &attributes ) ), 0 );
-    TEST_EQUAL(
-        MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( psa_get_key_id( &attributes ) ), 0 );
-    TEST_EQUAL( psa_get_key_lifetime( &attributes ), 0 );
-    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 );
-    TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
-    TEST_EQUAL( psa_get_key_type( &attributes ), 0 );
-    TEST_EQUAL( psa_get_key_bits( &attributes ), 0 );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void persistence_attributes( int id1_arg, int owner_id1_arg, int lifetime_arg,
-                             int id2_arg, int owner_id2_arg,
-                             int expected_id_arg, int expected_owner_id_arg,
-                             int expected_lifetime_arg )
-{
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    mbedtls_svc_key_id_t id1 =
-        mbedtls_svc_key_id_make( owner_id1_arg, id1_arg );
-    psa_key_lifetime_t lifetime = lifetime_arg;
-    mbedtls_svc_key_id_t id2 =
-        mbedtls_svc_key_id_make( owner_id2_arg, id2_arg );
-    mbedtls_svc_key_id_t expected_id =
-        mbedtls_svc_key_id_make( expected_owner_id_arg, expected_id_arg );
-    psa_key_lifetime_t expected_lifetime = expected_lifetime_arg;
-
-    if( id1_arg != -1 )
-        psa_set_key_id( &attributes, id1 );
-    if( lifetime_arg != -1 )
-        psa_set_key_lifetime( &attributes, lifetime );
-    if( id2_arg != -1 )
-        psa_set_key_id( &attributes, id2 );
-
-    TEST_ASSERT( mbedtls_svc_key_id_equal(
-                     psa_get_key_id( &attributes ), expected_id ) );
-    TEST_EQUAL( psa_get_key_lifetime( &attributes ), expected_lifetime );
-}
-/* END_CASE */
-
-/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_SE_C */
-void slot_number_attribute( )
-{
-    psa_key_slot_number_t slot_number = 0xdeadbeef;
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-
-    /* Initially, there is no slot number. */
-    TEST_EQUAL( psa_get_key_slot_number( &attributes, &slot_number ),
-                PSA_ERROR_INVALID_ARGUMENT );
-
-    /* Test setting a slot number. */
-    psa_set_key_slot_number( &attributes, 0 );
-    PSA_ASSERT( psa_get_key_slot_number( &attributes, &slot_number ) );
-    TEST_EQUAL( slot_number, 0 );
-
-    /* Test changing the slot number. */
-    psa_set_key_slot_number( &attributes, 42 );
-    PSA_ASSERT( psa_get_key_slot_number( &attributes, &slot_number ) );
-    TEST_EQUAL( slot_number, 42 );
-
-    /* Test clearing the slot number. */
-    psa_clear_key_slot_number( &attributes );
-    TEST_EQUAL( psa_get_key_slot_number( &attributes, &slot_number ),
-                PSA_ERROR_INVALID_ARGUMENT );
-
-    /* Clearing again should have no effect. */
-    psa_clear_key_slot_number( &attributes );
-    TEST_EQUAL( psa_get_key_slot_number( &attributes, &slot_number ),
-                PSA_ERROR_INVALID_ARGUMENT );
-
-    /* Test that reset clears the slot number. */
-    psa_set_key_slot_number( &attributes, 42 );
-    PSA_ASSERT( psa_get_key_slot_number( &attributes, &slot_number ) );
-    TEST_EQUAL( slot_number, 42 );
-    psa_reset_key_attributes( &attributes );
-    TEST_EQUAL( psa_get_key_slot_number( &attributes, &slot_number ),
-                PSA_ERROR_INVALID_ARGUMENT );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
 void import_with_policy( int type_arg,
                          int usage_arg, int alg_arg,
                          int expected_status_arg )
@@ -1502,7 +383,8 @@
 
     PSA_ASSERT( psa_get_key_attributes( key, &got_attributes ) );
     TEST_EQUAL( psa_get_key_type( &got_attributes ), type );
-    TEST_EQUAL( psa_get_key_usage_flags( &got_attributes ), usage );
+    TEST_EQUAL( psa_get_key_usage_flags( &got_attributes ),
+                mbedtls_test_update_key_usage_flags( usage ) );
     TEST_EQUAL( psa_get_key_algorithm( &got_attributes ), alg );
     ASSERT_NO_SLOT_NUMBER( &got_attributes );
 
@@ -1579,9 +461,9 @@
     size_t buffer_size = byte_size + 1;
     size_t n;
 
-    /* It would be better to skip the test than fail it if the allocation
-     * fails, but the test framework doesn't support this yet. */
-    ASSERT_ALLOC( buffer, buffer_size );
+    /* Skip the test case if the target running the test cannot
+     * accomodate large keys due to heap size constraints */
+    ASSERT_ALLOC_WEAK( buffer, buffer_size );
     memset( buffer, 'K', byte_size );
 
     PSA_ASSERT( psa_crypto_init( ) );
@@ -1590,6 +472,7 @@
     psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT );
     psa_set_key_type( &attributes, type );
     status = psa_import_key( &attributes, buffer, byte_size, &key );
+    TEST_ASSUME( status != PSA_ERROR_INSUFFICIENT_MEMORY );
     TEST_EQUAL( status, expected_status );
 
     if( status == PSA_SUCCESS )
@@ -1717,7 +600,11 @@
         goto destroy;
     }
 
-    if( ! exercise_export_key( key, usage_arg ) )
+    /* Run sanity checks on the exported key. For non-canonical inputs,
+     * this validates the canonical representations. For canonical inputs,
+     * this doesn't directly validate the implementation, but it still helps
+     * by cross-validating the test data with the sanity check code. */
+    if( ! mbedtls_test_psa_exercise_key( key, usage_arg, 0 ) )
         goto exit;
 
     if( canonical_input )
@@ -1735,7 +622,10 @@
                         reexported, reexported_length );
         PSA_ASSERT( psa_destroy_key( key2 ) );
     }
-    TEST_ASSERT( exported_length <= PSA_KEY_EXPORT_MAX_SIZE( type, psa_get_key_bits( &got_attributes ) ) );
+    TEST_ASSERT( exported_length <=
+                 PSA_EXPORT_KEY_OUTPUT_SIZE( type,
+                                             psa_get_key_bits( &got_attributes ) ) );
+    TEST_ASSERT( exported_length <= PSA_EXPORT_KEY_PAIR_MAX_SIZE );
 
 destroy:
     /* Destroy the key */
@@ -1795,7 +685,11 @@
         PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
         bits = psa_get_key_bits( &attributes );
         TEST_ASSERT( expected_public_key->len <=
-                     PSA_KEY_EXPORT_MAX_SIZE( public_type, bits ) );
+                     PSA_EXPORT_KEY_OUTPUT_SIZE( public_type, bits ) );
+        TEST_ASSERT( expected_public_key->len <=
+                     PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( public_type, bits ) );
+        TEST_ASSERT( expected_public_key->len <=
+                     PSA_EXPORT_PUBLIC_KEY_MAX_SIZE );
         ASSERT_COMPARE( expected_public_key->x, expected_public_key->len,
                         exported, exported_length );
     }
@@ -1823,7 +717,7 @@
     psa_key_type_t type = type_arg;
     size_t bits = bits_arg;
     psa_algorithm_t alg = alg_arg;
-    psa_key_usage_t usage = usage_to_exercise( type, alg );
+    psa_key_usage_t usage = mbedtls_test_psa_usage_to_exercise( type, alg );
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
 
@@ -1842,7 +736,7 @@
     TEST_EQUAL( psa_get_key_bits( &got_attributes ), bits );
 
     /* Do something with the key according to its type and permitted usage. */
-    if( ! exercise_key( key, usage, alg ) )
+    if( ! mbedtls_test_psa_exercise_key( key, usage, alg ) )
         goto exit;
 
     PSA_ASSERT( psa_destroy_key( key ) );
@@ -1911,7 +805,9 @@
                        int usage_arg, int alg_arg )
 {
     test_effective_key_attributes( type_arg, type_arg, bits_arg, bits_arg,
-                                   usage_arg, usage_arg, alg_arg, alg_arg );
+                                   usage_arg,
+                                   mbedtls_test_update_key_usage_flags( usage_arg ),
+                                   alg_arg, alg_arg );
     goto exit;
 }
 /* END_CASE */
@@ -1952,16 +848,24 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void mac_key_policy( int policy_usage,
-                     int policy_alg,
-                     int key_type,
+void mac_key_policy( int policy_usage_arg,
+                     int policy_alg_arg,
+                     int key_type_arg,
                      data_t *key_data,
-                     int exercise_alg )
+                     int exercise_alg_arg,
+                     int expected_status_sign_arg,
+                     int expected_status_verify_arg )
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t policy_alg = policy_alg_arg;
+    psa_algorithm_t exercise_alg = exercise_alg_arg;
+    psa_key_usage_t policy_usage = policy_usage_arg;
     psa_status_t status;
+    psa_status_t expected_status_sign = expected_status_sign_arg;
+    psa_status_t expected_status_verify = expected_status_verify_arg;
     unsigned char mac[PSA_MAC_MAX_SIZE];
 
     PSA_ASSERT( psa_crypto_init( ) );
@@ -1973,21 +877,34 @@
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &key ) );
 
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ),
+                mbedtls_test_update_key_usage_flags( policy_usage ) );
+
     status = psa_mac_sign_setup( &operation, key, exercise_alg );
-    if( policy_alg == exercise_alg &&
-        ( policy_usage & PSA_KEY_USAGE_SIGN_HASH ) != 0 )
-        PSA_ASSERT( status );
+    TEST_EQUAL( status, expected_status_sign );
+
+    /* Calculate the MAC, one-shot case. */
+    uint8_t input[128] = {0};
+    size_t mac_len;
+    TEST_EQUAL( psa_mac_compute( key, exercise_alg,
+                                 input, 128,
+                                 mac, PSA_MAC_MAX_SIZE, &mac_len ),
+                expected_status_sign );
+
+    /* Verify correct MAC, one-shot case. */
+    status = psa_mac_verify( key, exercise_alg, input, 128,
+                                mac, mac_len );
+
+    if( expected_status_sign != PSA_SUCCESS && expected_status_verify == PSA_SUCCESS )
+        TEST_EQUAL( status, PSA_ERROR_INVALID_SIGNATURE );
     else
-        TEST_EQUAL( status, PSA_ERROR_NOT_PERMITTED );
+        TEST_EQUAL( status, expected_status_verify );
+
     psa_mac_abort( &operation );
 
     memset( mac, 0, sizeof( mac ) );
     status = psa_mac_verify_setup( &operation, key, exercise_alg );
-    if( policy_alg == exercise_alg &&
-        ( policy_usage & PSA_KEY_USAGE_VERIFY_HASH ) != 0 )
-        PSA_ASSERT( status );
-    else
-        TEST_EQUAL( status, PSA_ERROR_NOT_PERMITTED );
+    TEST_EQUAL( status, expected_status_verify );
 
 exit:
     psa_mac_abort( &operation );
@@ -1997,7 +914,7 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void cipher_key_policy( int policy_usage,
+void cipher_key_policy( int policy_usage_arg,
                         int policy_alg,
                         int key_type,
                         data_t *key_data,
@@ -2006,6 +923,7 @@
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
+    psa_key_usage_t policy_usage = policy_usage_arg;
     psa_status_t status;
 
     PSA_ASSERT( psa_crypto_init( ) );
@@ -2017,6 +935,10 @@
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &key ) );
 
+    /* Check if no key usage flag implication is done */
+    TEST_EQUAL( policy_usage,
+                mbedtls_test_update_key_usage_flags( policy_usage ) );
+
     status = psa_cipher_encrypt_setup( &operation, key, exercise_alg );
     if( policy_alg == exercise_alg &&
         ( policy_usage & PSA_KEY_USAGE_ENCRYPT ) != 0 )
@@ -2040,17 +962,20 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void aead_key_policy( int policy_usage,
+void aead_key_policy( int policy_usage_arg,
                       int policy_alg,
                       int key_type,
                       data_t *key_data,
                       int nonce_length_arg,
                       int tag_length_arg,
-                      int exercise_alg )
+                      int exercise_alg,
+                      int expected_status_arg )
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_usage_t policy_usage = policy_usage_arg;
     psa_status_t status;
+    psa_status_t expected_status = expected_status_arg;
     unsigned char nonce[16] = {0};
     size_t nonce_length = nonce_length_arg;
     unsigned char tag[16];
@@ -2069,15 +994,18 @@
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &key ) );
 
+    /* Check if no key usage implication is done */
+    TEST_EQUAL( policy_usage,
+                mbedtls_test_update_key_usage_flags( policy_usage ) );
+
     status = psa_aead_encrypt( key, exercise_alg,
                                nonce, nonce_length,
                                NULL, 0,
                                NULL, 0,
                                tag, tag_length,
                                &output_length );
-    if( policy_alg == exercise_alg &&
-        ( policy_usage & PSA_KEY_USAGE_ENCRYPT ) != 0 )
-        PSA_ASSERT( status );
+    if( ( policy_usage & PSA_KEY_USAGE_ENCRYPT ) != 0 )
+        TEST_EQUAL( status, expected_status );
     else
         TEST_EQUAL( status, PSA_ERROR_NOT_PERMITTED );
 
@@ -2088,11 +1016,12 @@
                                tag, tag_length,
                                NULL, 0,
                                &output_length );
-    if( policy_alg == exercise_alg &&
-        ( policy_usage & PSA_KEY_USAGE_DECRYPT ) != 0 )
+    if( ( policy_usage & PSA_KEY_USAGE_DECRYPT ) == 0 )
+        TEST_EQUAL( status, PSA_ERROR_NOT_PERMITTED );
+    else if( expected_status == PSA_SUCCESS )
         TEST_EQUAL( status, PSA_ERROR_INVALID_SIGNATURE );
     else
-        TEST_EQUAL( status, PSA_ERROR_NOT_PERMITTED );
+        TEST_EQUAL( status, expected_status );
 
 exit:
     psa_destroy_key( key );
@@ -2101,7 +1030,7 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void asymmetric_encryption_key_policy( int policy_usage,
+void asymmetric_encryption_key_policy( int policy_usage_arg,
                                        int policy_alg,
                                        int key_type,
                                        data_t *key_data,
@@ -2109,6 +1038,7 @@
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_usage_t policy_usage = policy_usage_arg;
     psa_status_t status;
     size_t key_bits;
     size_t buffer_length;
@@ -2124,6 +1054,10 @@
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &key ) );
 
+    /* Check if no key usage implication is done */
+    TEST_EQUAL( policy_usage,
+                mbedtls_test_update_key_usage_flags( policy_usage ) );
+
     PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
     key_bits = psa_get_key_bits( &attributes );
     buffer_length = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE( key_type, key_bits,
@@ -2168,15 +1102,18 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void asymmetric_signature_key_policy( int policy_usage,
+void asymmetric_signature_key_policy( int policy_usage_arg,
                                       int policy_alg,
                                       int key_type,
                                       data_t *key_data,
                                       int exercise_alg,
-                                      int payload_length_arg )
+                                      int payload_length_arg,
+                                      int expected_usage_arg )
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_usage_t policy_usage = policy_usage_arg;
+    psa_key_usage_t expected_usage = expected_usage_arg;
     psa_status_t status;
     unsigned char payload[PSA_HASH_MAX_SIZE] = {1};
     /* If `payload_length_arg > 0`, `exercise_alg` is supposed to be
@@ -2188,6 +1125,11 @@
     unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = {0};
     size_t signature_length;
 
+    /* Check if all implicit usage flags are deployed
+       in the expected usage flags. */
+    TEST_EQUAL( expected_usage,
+                mbedtls_test_update_key_usage_flags( policy_usage ) );
+
     PSA_ASSERT( psa_crypto_init( ) );
 
     psa_set_key_usage_flags( &attributes, policy_usage );
@@ -2197,11 +1139,13 @@
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &key ) );
 
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), expected_usage );
+
     status = psa_sign_hash( key, exercise_alg,
                             payload, payload_length,
                             signature, sizeof( signature ),
                             &signature_length );
-    if( compatible_alg && ( policy_usage & PSA_KEY_USAGE_SIGN_HASH ) != 0 )
+    if( compatible_alg && ( expected_usage & PSA_KEY_USAGE_SIGN_HASH ) != 0 )
         PSA_ASSERT( status );
     else
         TEST_EQUAL( status, PSA_ERROR_NOT_PERMITTED );
@@ -2210,11 +1154,33 @@
     status = psa_verify_hash( key, exercise_alg,
                               payload, payload_length,
                               signature, sizeof( signature ) );
-    if( compatible_alg && ( policy_usage & PSA_KEY_USAGE_VERIFY_HASH ) != 0 )
+    if( compatible_alg && ( expected_usage & PSA_KEY_USAGE_VERIFY_HASH ) != 0 )
         TEST_EQUAL( status, PSA_ERROR_INVALID_SIGNATURE );
     else
         TEST_EQUAL( status, PSA_ERROR_NOT_PERMITTED );
 
+    if( PSA_ALG_IS_SIGN_HASH( exercise_alg ) &&
+        PSA_ALG_IS_HASH( PSA_ALG_SIGN_GET_HASH( exercise_alg ) ) )
+    {
+        status = psa_sign_message( key, exercise_alg,
+                                   payload, payload_length,
+                                   signature, sizeof( signature ),
+                                   &signature_length );
+        if( compatible_alg && ( expected_usage & PSA_KEY_USAGE_SIGN_MESSAGE ) != 0 )
+            PSA_ASSERT( status );
+        else
+            TEST_EQUAL( status, PSA_ERROR_NOT_PERMITTED );
+
+        memset( signature, 0, sizeof( signature ) );
+        status = psa_verify_message( key, exercise_alg,
+                                     payload, payload_length,
+                                     signature, sizeof( signature ) );
+        if( compatible_alg && ( expected_usage & PSA_KEY_USAGE_VERIFY_MESSAGE ) != 0 )
+            TEST_EQUAL( status, PSA_ERROR_INVALID_SIGNATURE );
+        else
+            TEST_EQUAL( status, PSA_ERROR_NOT_PERMITTED );
+    }
+
 exit:
     psa_destroy_key( key );
     PSA_DONE( );
@@ -2295,7 +1261,7 @@
                                 &key ) );
 
     PSA_ASSERT( psa_key_derivation_setup( &operation, exercise_alg ) );
-    status = key_agreement_with_self( &operation, key );
+    status = mbedtls_test_psa_key_agreement_with_self( &operation, key );
 
     TEST_EQUAL( status, expected_status );
 
@@ -2327,14 +1293,16 @@
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &key ) );
 
+    /* Update the usage flags to obtain implicit usage flags */
+    usage = mbedtls_test_update_key_usage_flags( usage );
     PSA_ASSERT( psa_get_key_attributes( key, &got_attributes ) );
     TEST_EQUAL( psa_get_key_usage_flags( &got_attributes ), usage );
     TEST_EQUAL( psa_get_key_algorithm( &got_attributes ), alg );
     TEST_EQUAL( psa_get_key_enrollment_algorithm( &got_attributes ), alg2 );
 
-    if( ! exercise_key( key, usage, alg ) )
+    if( ! mbedtls_test_psa_exercise_key( key, usage, alg ) )
         goto exit;
-    if( ! exercise_key( key, usage, alg2 ) )
+    if( ! mbedtls_test_psa_exercise_key( key, usage, alg2 ) )
         goto exit;
 
 exit:
@@ -2373,7 +1341,7 @@
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &key ) );
 
-    status = raw_key_agreement_with_self( exercise_alg, key );
+    status = mbedtls_test_psa_raw_key_agreement_with_self( exercise_alg, key );
 
     TEST_EQUAL( status, expected_status );
 
@@ -2456,9 +1424,10 @@
         ASSERT_COMPARE( material->x, material->len,
                         export_buffer, length );
     }
-    if( ! exercise_key( target_key, expected_usage, expected_alg ) )
+
+    if( ! mbedtls_test_psa_exercise_key( target_key, expected_usage, expected_alg ) )
         goto exit;
-    if( ! exercise_key( target_key, expected_usage, expected_alg2 ) )
+    if( ! mbedtls_test_psa_exercise_key( target_key, expected_usage, expected_alg2 ) )
         goto exit;
 
     PSA_ASSERT( psa_destroy_key( target_key ) );
@@ -2483,12 +1452,14 @@
                 int target_type_arg, int target_bits_arg,
                 int target_usage_arg,
                 int target_alg_arg, int target_alg2_arg,
+                int target_id_arg, int target_lifetime_arg,
                 int expected_status_arg )
 {
     psa_key_attributes_t source_attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_attributes_t target_attributes = PSA_KEY_ATTRIBUTES_INIT;
     mbedtls_svc_key_id_t source_key = MBEDTLS_SVC_KEY_ID_INIT;
     mbedtls_svc_key_id_t target_key = MBEDTLS_SVC_KEY_ID_INIT;
+    mbedtls_svc_key_id_t key_id = mbedtls_svc_key_id_make( 1, target_id_arg );
 
     PSA_ASSERT( psa_crypto_init( ) );
 
@@ -2502,6 +1473,8 @@
                                 &source_key ) );
 
     /* Prepare the target attributes. */
+    psa_set_key_id( &target_attributes, key_id );
+    psa_set_key_lifetime( &target_attributes, target_lifetime_arg );
     psa_set_key_type( &target_attributes, target_type_arg );
     psa_set_key_bits( &target_attributes, target_bits_arg );
     psa_set_key_usage_flags( &target_attributes, target_usage_arg );
@@ -2643,9 +1616,9 @@
 
     /* Compute with tight buffer */
     PSA_ASSERT( psa_hash_compute( alg, input->x, input->len,
-                                  output, PSA_HASH_SIZE( alg ),
+                                  output, PSA_HASH_LENGTH( alg ),
                                   &output_length ) );
-    TEST_EQUAL( output_length, PSA_HASH_SIZE( alg ) );
+    TEST_EQUAL( output_length, PSA_HASH_LENGTH( alg ) );
     ASSERT_COMPARE( output, output_length,
                     expected_output->x, expected_output->len );
 
@@ -2653,7 +1626,7 @@
     PSA_ASSERT( psa_hash_compute( alg, input->x, input->len,
                                   output, sizeof( output ),
                                   &output_length ) );
-    TEST_EQUAL( output_length, PSA_HASH_SIZE( alg ) );
+    TEST_EQUAL( output_length, PSA_HASH_LENGTH( alg ) );
     ASSERT_COMPARE( output, output_length,
                     expected_output->x, expected_output->len );
 
@@ -2674,7 +1647,7 @@
     /* Compare with corrupted value */
     for( i = 0; i < output_length; i++ )
     {
-        test_set_step( i );
+        mbedtls_test_set_step( i );
         output[i] ^= 1;
         TEST_EQUAL( psa_hash_compare( alg, input->x, input->len,
                                       output, output_length ),
@@ -2687,7 +1660,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:PSA_WANT_ALG_SHA_256 */
 void hash_bad_order( )
 {
     psa_algorithm_t alg = PSA_ALG_SHA_256;
@@ -2705,15 +1678,28 @@
 
     /* Call setup twice in a row. */
     PSA_ASSERT( psa_hash_setup( &operation, alg ) );
+    ASSERT_OPERATION_IS_ACTIVE( operation );
     TEST_EQUAL( psa_hash_setup( &operation, alg ),
                 PSA_ERROR_BAD_STATE );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
     PSA_ASSERT( psa_hash_abort( &operation ) );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
 
     /* Call update without calling setup beforehand. */
     TEST_EQUAL( psa_hash_update( &operation, input, sizeof( input ) ),
                 PSA_ERROR_BAD_STATE );
     PSA_ASSERT( psa_hash_abort( &operation ) );
 
+    /* Check that update calls abort on error. */
+    PSA_ASSERT( psa_hash_setup( &operation, alg ) );
+    operation.id = UINT_MAX;
+    ASSERT_OPERATION_IS_ACTIVE( operation );
+    TEST_EQUAL( psa_hash_update( &operation, input, sizeof( input ) ),
+                PSA_ERROR_BAD_STATE );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
+    PSA_ASSERT( psa_hash_abort( &operation ) );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
+
     /* Call update after finish. */
     PSA_ASSERT( psa_hash_setup( &operation, alg ) );
     PSA_ASSERT( psa_hash_finish( &operation,
@@ -2739,11 +1725,14 @@
 
     /* Call verify twice in a row. */
     PSA_ASSERT( psa_hash_setup( &operation, alg ) );
+    ASSERT_OPERATION_IS_ACTIVE( operation );
     PSA_ASSERT( psa_hash_verify( &operation,
                                  valid_hash, sizeof( valid_hash ) ) );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
     TEST_EQUAL( psa_hash_verify( &operation,
                                  valid_hash, sizeof( valid_hash ) ),
                 PSA_ERROR_BAD_STATE );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
     PSA_ASSERT( psa_hash_abort( &operation ) );
 
     /* Call finish without calling setup beforehand. */
@@ -2775,7 +1764,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_SHA256_C */
+/* BEGIN_CASE depends_on:PSA_WANT_ALG_SHA_256 */
 void hash_verify_bad_args( )
 {
     psa_algorithm_t alg = PSA_ALG_SHA_256;
@@ -2785,15 +1774,19 @@
         0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8,
         0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
         0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55, 0xaa, 0xbb };
-    size_t expected_size = PSA_HASH_SIZE( alg );
+    size_t expected_size = PSA_HASH_LENGTH( alg );
     psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
     /* psa_hash_verify with a smaller hash than expected */
     PSA_ASSERT( psa_hash_setup( &operation, alg ) );
+    ASSERT_OPERATION_IS_ACTIVE( operation );
     TEST_EQUAL( psa_hash_verify( &operation, hash, expected_size - 1 ),
                 PSA_ERROR_INVALID_SIGNATURE );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
+    PSA_ASSERT( psa_hash_abort( &operation ) );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
 
     /* psa_hash_verify with a non-matching hash */
     PSA_ASSERT( psa_hash_setup( &operation, alg ) );
@@ -2810,12 +1803,12 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_SHA256_C */
+/* BEGIN_CASE depends_on:PSA_WANT_ALG_SHA_256 */
 void hash_finish_bad_args( )
 {
     psa_algorithm_t alg = PSA_ALG_SHA_256;
     unsigned char hash[PSA_HASH_MAX_SIZE];
-    size_t expected_size = PSA_HASH_SIZE( alg );
+    size_t expected_size = PSA_HASH_LENGTH( alg );
     psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
     size_t hash_len;
 
@@ -2832,7 +1825,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_SHA256_C */
+/* BEGIN_CASE depends_on:PSA_WANT_ALG_SHA_256 */
 void hash_clone_source_state( )
 {
     psa_algorithm_t alg = PSA_ALG_SHA_256;
@@ -2877,7 +1870,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_SHA256_C */
+/* BEGIN_CASE depends_on:PSA_WANT_ALG_SHA_256 */
 void hash_clone_target_state( )
 {
     psa_algorithm_t alg = PSA_ALG_SHA_256;
@@ -2989,7 +1982,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:PSA_WANT_KEY_TYPE_HMAC:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256 */
 void mac_bad_order( )
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
@@ -3036,9 +2029,12 @@
 
     /* Call setup twice in a row. */
     PSA_ASSERT( psa_mac_sign_setup( &operation, key, alg ) );
+    ASSERT_OPERATION_IS_ACTIVE( operation );
     TEST_EQUAL( psa_mac_sign_setup( &operation, key, alg ),
                 PSA_ERROR_BAD_STATE );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
     PSA_ASSERT( psa_mac_abort( &operation ) );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
 
     /* Call update after sign finish. */
     PSA_ASSERT( psa_mac_sign_setup( &operation, key, alg ) );
@@ -3084,19 +2080,25 @@
     /* Setup sign but try verify. */
     PSA_ASSERT( psa_mac_sign_setup( &operation, key, alg ) );
     PSA_ASSERT( psa_mac_update( &operation, input, sizeof( input ) ) );
+    ASSERT_OPERATION_IS_ACTIVE( operation );
     TEST_EQUAL( psa_mac_verify_finish( &operation,
                                        verify_mac, sizeof( verify_mac ) ),
                 PSA_ERROR_BAD_STATE );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
     PSA_ASSERT( psa_mac_abort( &operation ) );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
 
     /* Setup verify but try sign. */
     PSA_ASSERT( psa_mac_verify_setup( &operation, key, alg ) );
     PSA_ASSERT( psa_mac_update( &operation, input, sizeof( input ) ) );
+    ASSERT_OPERATION_IS_ACTIVE( operation );
     TEST_EQUAL( psa_mac_sign_finish( &operation,
                                      sign_mac, sizeof( sign_mac ),
                                      &sign_mac_length ),
                 PSA_ERROR_BAD_STATE );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
     PSA_ASSERT( psa_mac_abort( &operation ) );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
 
     PSA_ASSERT( psa_destroy_key( key ) );
 
@@ -3119,7 +2121,7 @@
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     uint8_t *actual_mac = NULL;
     size_t mac_buffer_size =
-        PSA_MAC_FINAL_SIZE( key_type, PSA_BYTES_TO_BITS( key_data->len ), alg );
+        PSA_MAC_LENGTH( key_type, PSA_BYTES_TO_BITS( key_data->len ), alg );
     size_t mac_length = 0;
     const size_t output_sizes_to_test[] = {
         0,
@@ -3130,7 +2132,7 @@
     };
 
     TEST_ASSERT( mac_buffer_size <= PSA_MAC_MAX_SIZE );
-    /* We expect PSA_MAC_FINAL_SIZE to be exact. */
+    /* We expect PSA_MAC_LENGTH to be exact. */
     TEST_ASSERT( expected_mac->len == mac_buffer_size );
 
     PSA_ASSERT( psa_crypto_init( ) );
@@ -3149,10 +2151,24 @@
             ( output_size >= expected_mac->len ? PSA_SUCCESS :
               PSA_ERROR_BUFFER_TOO_SMALL );
 
-        test_set_step( output_size );
+        mbedtls_test_set_step( output_size );
         ASSERT_ALLOC( actual_mac, output_size );
 
-        /* Calculate the MAC. */
+        /* Calculate the MAC, one-shot case. */
+        TEST_EQUAL( psa_mac_compute( key, alg,
+                                     input->x, input->len,
+                                     actual_mac, output_size, &mac_length ),
+                    expected_status );
+        if( expected_status == PSA_SUCCESS )
+        {
+            ASSERT_COMPARE( expected_mac->x, expected_mac->len,
+                            actual_mac, mac_length );
+        }
+
+        if( output_size > 0 )
+            memset( actual_mac, 0, output_size );
+
+        /* Calculate the MAC, multi-part case. */
         PSA_ASSERT( psa_mac_sign_setup( &operation, key, alg ) );
         PSA_ASSERT( psa_mac_update( &operation,
                                     input->x, input->len ) );
@@ -3204,7 +2220,11 @@
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &key ) );
 
-    /* Test the correct MAC. */
+    /* Verify correct MAC, one-shot case. */
+    PSA_ASSERT( psa_mac_verify( key, alg, input->x, input->len,
+                                expected_mac->x, expected_mac->len ) );
+
+    /* Verify correct MAC, multi-part case. */
     PSA_ASSERT( psa_mac_verify_setup( &operation, key, alg ) );
     PSA_ASSERT( psa_mac_update( &operation,
                                 input->x, input->len ) );
@@ -3212,7 +2232,14 @@
                                        expected_mac->x,
                                        expected_mac->len ) );
 
-    /* Test a MAC that's too short. */
+    /* Test a MAC that's too short, one-shot case. */
+    TEST_EQUAL( psa_mac_verify( key, alg,
+                                input->x, input->len,
+                                expected_mac->x,
+                                expected_mac->len - 1 ),
+                PSA_ERROR_INVALID_SIGNATURE );
+
+    /* Test a MAC that's too short, multi-part case. */
     PSA_ASSERT( psa_mac_verify_setup( &operation, key, alg ) );
     PSA_ASSERT( psa_mac_update( &operation,
                                 input->x, input->len ) );
@@ -3221,9 +2248,15 @@
                                        expected_mac->len - 1 ),
                 PSA_ERROR_INVALID_SIGNATURE );
 
-    /* Test a MAC that's too long. */
+    /* Test a MAC that's too long, one-shot case. */
     ASSERT_ALLOC( perturbed_mac, expected_mac->len + 1 );
     memcpy( perturbed_mac, expected_mac->x, expected_mac->len );
+    TEST_EQUAL( psa_mac_verify( key, alg,
+                                input->x, input->len,
+                                 perturbed_mac, expected_mac->len + 1 ),
+                PSA_ERROR_INVALID_SIGNATURE );
+
+    /* Test a MAC that's too long, multi-part case. */
     PSA_ASSERT( psa_mac_verify_setup( &operation, key, alg ) );
     PSA_ASSERT( psa_mac_update( &operation,
                                 input->x, input->len ) );
@@ -3235,8 +2268,14 @@
     /* Test changing one byte. */
     for( size_t i = 0; i < expected_mac->len; i++ )
     {
-        test_set_step( i );
+        mbedtls_test_set_step( i );
         perturbed_mac[i] ^= 1;
+
+        TEST_EQUAL( psa_mac_verify( key, alg,
+                                    input->x, input->len,
+                                    perturbed_mac, expected_mac->len ),
+                    PSA_ERROR_INVALID_SIGNATURE );
+
         PSA_ASSERT( psa_mac_verify_setup( &operation, key, alg ) );
         PSA_ASSERT( psa_mac_update( &operation,
                                     input->x, input->len ) );
@@ -3306,7 +2345,7 @@
     psa_status_t expected_status = expected_status_arg;
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
     psa_status_t status;
-#if defined(KNOWN_SUPPORTED_MAC_ALG)
+#if defined(KNOWN_SUPPORTED_CIPHER_ALG)
     const uint8_t smoke_test_key_data[16] = "kkkkkkkkkkkkkkkk";
 #endif
 
@@ -3334,7 +2373,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_CBC_PKCS7 */
 void cipher_bad_order( )
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
@@ -3342,14 +2381,14 @@
     psa_algorithm_t alg = PSA_ALG_CBC_PKCS7;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
-    unsigned char iv[PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES)] = { 0 };
+    unsigned char iv[PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES)] = { 0 };
     const uint8_t key_data[] = {
         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
         0xaa, 0xaa, 0xaa, 0xaa };
     const uint8_t text[] = {
         0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
         0xbb, 0xbb, 0xbb, 0xbb };
-    uint8_t buffer[PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES)] = { 0 };
+    uint8_t buffer[PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES)] = { 0 };
     size_t length = 0;
 
     PSA_ASSERT( psa_crypto_init( ) );
@@ -3361,15 +2400,21 @@
 
     /* Call encrypt setup twice in a row. */
     PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
+    ASSERT_OPERATION_IS_ACTIVE( operation );
     TEST_EQUAL( psa_cipher_encrypt_setup( &operation, key, alg ),
                 PSA_ERROR_BAD_STATE );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
     PSA_ASSERT( psa_cipher_abort( &operation ) );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
 
     /* Call decrypt setup twice in a row. */
     PSA_ASSERT( psa_cipher_decrypt_setup( &operation, key, alg ) );
+    ASSERT_OPERATION_IS_ACTIVE( operation );
     TEST_EQUAL( psa_cipher_decrypt_setup( &operation, key, alg ),
                 PSA_ERROR_BAD_STATE );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
     PSA_ASSERT( psa_cipher_abort( &operation ) );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
 
     /* Generate an IV without calling setup beforehand. */
     TEST_EQUAL( psa_cipher_generate_iv( &operation,
@@ -3383,11 +2428,14 @@
     PSA_ASSERT( psa_cipher_generate_iv( &operation,
                                         buffer, sizeof( buffer ),
                                         &length ) );
+    ASSERT_OPERATION_IS_ACTIVE( operation );
     TEST_EQUAL( psa_cipher_generate_iv( &operation,
                                         buffer, sizeof( buffer ),
                                         &length ),
                 PSA_ERROR_BAD_STATE );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
     PSA_ASSERT( psa_cipher_abort( &operation ) );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
 
     /* Generate an IV after it's already set. */
     PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
@@ -3409,10 +2457,13 @@
     PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
     PSA_ASSERT( psa_cipher_set_iv( &operation,
                                    iv, sizeof( iv ) ) );
+    ASSERT_OPERATION_IS_ACTIVE( operation );
     TEST_EQUAL( psa_cipher_set_iv( &operation,
                                    iv, sizeof( iv ) ),
                 PSA_ERROR_BAD_STATE );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
     PSA_ASSERT( psa_cipher_abort( &operation ) );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
 
     /* Set an IV after it's already generated. */
     PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
@@ -3433,12 +2484,16 @@
     PSA_ASSERT( psa_cipher_abort( &operation ) );
 
     /* Call update without an IV where an IV is required. */
+    PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
+    ASSERT_OPERATION_IS_ACTIVE( operation );
     TEST_EQUAL( psa_cipher_update( &operation,
                                    text, sizeof( text ),
                                    buffer, sizeof( buffer ),
                                    &length ),
                 PSA_ERROR_BAD_STATE );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
     PSA_ASSERT( psa_cipher_abort( &operation ) );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
 
     /* Call update after finish. */
     PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
@@ -3463,10 +2518,13 @@
     PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
     /* Not calling update means we are encrypting an empty buffer, which is OK
      * for cipher modes with padding. */
+    ASSERT_OPERATION_IS_ACTIVE( operation );
     TEST_EQUAL( psa_cipher_finish( &operation,
                                    buffer, sizeof( buffer ), &length ),
                 PSA_ERROR_BAD_STATE );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
     PSA_ASSERT( psa_cipher_abort( &operation ) );
+    ASSERT_OPERATION_IS_INACTIVE( operation );
 
     /* Call finish twice in a row. */
     PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
@@ -3488,10 +2546,11 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void cipher_encrypt( int alg_arg, int key_type_arg,
-                     data_t *key_data, data_t *iv,
-                     data_t *input, data_t *expected_output,
-                     int expected_status_arg )
+void cipher_encrypt_fail( int alg_arg,
+                          int key_type_arg,
+                          data_t *key_data,
+                          data_t *input,
+                          int expected_status_arg )
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_status_t status;
@@ -3500,8 +2559,148 @@
     psa_status_t expected_status = expected_status_arg;
     unsigned char *output = NULL;
     size_t output_buffer_size = 0;
+    size_t output_length = 0;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    if ( PSA_ERROR_BAD_STATE != expected_status )
+    {
+        PSA_ASSERT( psa_crypto_init( ) );
+
+        psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT );
+        psa_set_key_algorithm( &attributes, alg );
+        psa_set_key_type( &attributes, key_type );
+
+        output_buffer_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE( key_type, alg,
+                                                             input->len );
+        ASSERT_ALLOC( output, output_buffer_size );
+
+        PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                    &key ) );
+    }
+
+    status = psa_cipher_encrypt( key, alg, input->x, input->len, output,
+                                 output_buffer_size, &output_length );
+
+    TEST_EQUAL( status, expected_status );
+
+exit:
+    mbedtls_free( output );
+    psa_destroy_key( key );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_encrypt_alg_without_iv( int alg_arg,
+                                    int key_type_arg,
+                                    data_t *key_data,
+                                    data_t *input,
+                                    data_t *expected_output )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
+    uint8_t iv[1] = { 0x5a };
+    size_t iv_length;
+    unsigned char *output = NULL;
+    size_t output_buffer_size = 0;
+    size_t output_length = 0;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    output_buffer_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE( key_type, alg, input->len );
+    ASSERT_ALLOC( output, output_buffer_size );
+
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+
+    PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
+    TEST_EQUAL( psa_cipher_set_iv( &operation, iv, sizeof( iv ) ),
+                PSA_ERROR_BAD_STATE );
+    PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
+    TEST_EQUAL( psa_cipher_generate_iv( &operation, iv, sizeof( iv ),
+                                        &iv_length ),
+                PSA_ERROR_BAD_STATE );
+
+    PSA_ASSERT( psa_cipher_encrypt( key, alg, input->x, input->len, output,
+                                    output_buffer_size, &output_length ) );
+    TEST_ASSERT( output_length <=
+                 PSA_CIPHER_ENCRYPT_OUTPUT_SIZE( key_type, alg, input->len ) );
+    TEST_ASSERT( output_length <=
+                 PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE( input->len ) );
+
+    ASSERT_COMPARE( expected_output->x, expected_output->len,
+                    output, output_length );
+exit:
+    mbedtls_free( output );
+    psa_destroy_key( key );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_bad_key( int alg_arg, int key_type_arg, data_t *key_data )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_algorithm_t alg = alg_arg;
+    psa_key_type_t key_type = key_type_arg;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
+    psa_status_t status;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    /* Usage of either of these two size macros would cause divide by zero
+     * with incorrect key types previously. Input length should be irrelevant
+     * here. */
+    TEST_EQUAL( PSA_CIPHER_ENCRYPT_OUTPUT_SIZE( key_type, alg, 16 ),
+                0 );
+    TEST_EQUAL( PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, 16 ), 0 );
+
+
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+
+    /* Should fail due to invalid alg type (to support invalid key type).
+     * Encrypt or decrypt will end up in the same place. */
+    status = psa_cipher_encrypt_setup( &operation, key, alg );
+
+    TEST_EQUAL( status, PSA_ERROR_INVALID_ARGUMENT );
+
+exit:
+    psa_cipher_abort( &operation );
+    psa_destroy_key( key );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_encrypt_validation( int alg_arg,
+                                int key_type_arg,
+                                data_t *key_data,
+                                data_t *input )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    size_t iv_size = PSA_CIPHER_IV_LENGTH ( key_type, alg );
+    unsigned char *output1 = NULL;
+    size_t output1_buffer_size = 0;
+    size_t output1_length = 0;
+    unsigned char *output2 = NULL;
+    size_t output2_buffer_size = 0;
+    size_t output2_length = 0;
     size_t function_output_length = 0;
-    size_t total_output_length = 0;
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
@@ -3511,42 +2710,55 @@
     psa_set_key_algorithm( &attributes, alg );
     psa_set_key_type( &attributes, key_type );
 
+    output1_buffer_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE( key_type, alg, input->len );
+    output2_buffer_size = PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, input->len ) +
+                          PSA_CIPHER_FINISH_OUTPUT_SIZE( key_type, alg );
+    ASSERT_ALLOC( output1, output1_buffer_size );
+    ASSERT_ALLOC( output2, output2_buffer_size );
+
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &key ) );
 
+    /* The one-shot cipher encryption uses generated iv so validating
+       the output is not possible. Validating with multipart encryption. */
+    PSA_ASSERT( psa_cipher_encrypt( key, alg, input->x, input->len, output1,
+                                    output1_buffer_size, &output1_length ) );
+    TEST_ASSERT( output1_length <=
+                 PSA_CIPHER_ENCRYPT_OUTPUT_SIZE( key_type, alg, input->len ) );
+    TEST_ASSERT( output1_length <=
+                 PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE( input->len ) );
+
     PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
-
-    if( iv->len > 0 )
-    {
-        PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
-    }
-
-    output_buffer_size = ( (size_t) input->len +
-                           PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
-    ASSERT_ALLOC( output, output_buffer_size );
+    PSA_ASSERT( psa_cipher_set_iv( &operation, output1, iv_size ) );
 
     PSA_ASSERT( psa_cipher_update( &operation,
                                    input->x, input->len,
-                                   output, output_buffer_size,
+                                   output2, output2_buffer_size,
                                    &function_output_length ) );
-    total_output_length += function_output_length;
-    status = psa_cipher_finish( &operation,
-                                output + total_output_length,
-                                output_buffer_size - total_output_length,
-                                &function_output_length );
-    total_output_length += function_output_length;
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, input->len ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE( input->len ) );
+    output2_length += function_output_length;
 
-    TEST_EQUAL( status, expected_status );
-    if( expected_status == PSA_SUCCESS )
-    {
-        PSA_ASSERT( psa_cipher_abort( &operation ) );
-        ASSERT_COMPARE( expected_output->x, expected_output->len,
-                        output, total_output_length );
-    }
+    PSA_ASSERT( psa_cipher_finish( &operation,
+                                   output2 + output2_length,
+                                   output2_buffer_size - output2_length,
+                                   &function_output_length ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_FINISH_OUTPUT_SIZE( key_type, alg ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE );
+    output2_length += function_output_length;
+
+    PSA_ASSERT( psa_cipher_abort( &operation ) );
+    ASSERT_COMPARE( output1 + iv_size, output1_length - iv_size,
+                    output2, output2_length );
 
 exit:
     psa_cipher_abort( &operation );
-    mbedtls_free( output );
+    mbedtls_free( output1 );
+    mbedtls_free( output2 );
     psa_destroy_key( key );
     PSA_DONE( );
 }
@@ -3558,11 +2770,14 @@
                                data_t *input,
                                int first_part_size_arg,
                                int output1_length_arg, int output2_length_arg,
-                               data_t *expected_output )
+                               data_t *expected_output,
+                               int expected_status_arg )
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
+    psa_status_t status;
+    psa_status_t expected_status = expected_status_arg;
     size_t first_part_size = first_part_size_arg;
     size_t output1_length = output1_length_arg;
     size_t output2_length = output2_length_arg;
@@ -3589,8 +2804,8 @@
         PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
     }
 
-    output_buffer_size = ( (size_t) input->len +
-                           PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
+    output_buffer_size = PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, input->len ) +
+                         PSA_CIPHER_FINISH_OUTPUT_SIZE( key_type, alg );
     ASSERT_ALLOC( output, output_buffer_size );
 
     TEST_ASSERT( first_part_size <= input->len );
@@ -3598,24 +2813,50 @@
                                    output, output_buffer_size,
                                    &function_output_length ) );
     TEST_ASSERT( function_output_length == output1_length );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, first_part_size ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE( first_part_size) );
     total_output_length += function_output_length;
-    PSA_ASSERT( psa_cipher_update( &operation,
-                                   input->x + first_part_size,
-                                   input->len - first_part_size,
-                                   output + total_output_length,
-                                   output_buffer_size - total_output_length,
-                                   &function_output_length ) );
-    TEST_ASSERT( function_output_length == output2_length );
-    total_output_length += function_output_length;
-    PSA_ASSERT( psa_cipher_finish( &operation,
-                                   output + total_output_length,
-                                   output_buffer_size - total_output_length,
-                                   &function_output_length ) );
-    total_output_length += function_output_length;
-    PSA_ASSERT( psa_cipher_abort( &operation ) );
 
-    ASSERT_COMPARE( expected_output->x, expected_output->len,
-                    output, total_output_length );
+    if( first_part_size < input->len )
+    {
+        PSA_ASSERT( psa_cipher_update( &operation,
+                                       input->x + first_part_size,
+                                       input->len - first_part_size,
+                                       ( output_buffer_size == 0 ? NULL :
+                                         output + total_output_length ),
+                                       output_buffer_size - total_output_length,
+                                       &function_output_length ) );
+        TEST_ASSERT( function_output_length == output2_length );
+        TEST_ASSERT( function_output_length <=
+                     PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type,
+                                                    alg,
+                                                    input->len - first_part_size ) );
+        TEST_ASSERT( function_output_length <=
+                     PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE( input->len ) );
+        total_output_length += function_output_length;
+    }
+
+    status = psa_cipher_finish( &operation,
+                                ( output_buffer_size == 0 ? NULL :
+                                  output + total_output_length ),
+                                output_buffer_size - total_output_length,
+                                &function_output_length );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_FINISH_OUTPUT_SIZE( key_type, alg ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE );
+    total_output_length += function_output_length;
+    TEST_EQUAL( status, expected_status );
+
+    if( expected_status == PSA_SUCCESS )
+    {
+        PSA_ASSERT( psa_cipher_abort( &operation ) );
+
+        ASSERT_COMPARE( expected_output->x, expected_output->len,
+                        output, total_output_length );
+    }
 
 exit:
     psa_cipher_abort( &operation );
@@ -3631,11 +2872,14 @@
                                data_t *input,
                                int first_part_size_arg,
                                int output1_length_arg, int output2_length_arg,
-                               data_t *expected_output )
+                               data_t *expected_output,
+                               int expected_status_arg )
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
+    psa_status_t status;
+    psa_status_t expected_status = expected_status_arg;
     size_t first_part_size = first_part_size_arg;
     size_t output1_length = output1_length_arg;
     size_t output2_length = output2_length_arg;
@@ -3662,8 +2906,8 @@
         PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
     }
 
-    output_buffer_size = ( (size_t) input->len +
-                           PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
+    output_buffer_size = PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, input->len ) +
+                         PSA_CIPHER_FINISH_OUTPUT_SIZE( key_type, alg );
     ASSERT_ALLOC( output, output_buffer_size );
 
     TEST_ASSERT( first_part_size <= input->len );
@@ -3672,86 +2916,47 @@
                                    output, output_buffer_size,
                                    &function_output_length ) );
     TEST_ASSERT( function_output_length == output1_length );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, first_part_size ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE( first_part_size ) );
     total_output_length += function_output_length;
-    PSA_ASSERT( psa_cipher_update( &operation,
-                                   input->x + first_part_size,
-                                   input->len - first_part_size,
-                                   output + total_output_length,
-                                   output_buffer_size - total_output_length,
-                                   &function_output_length ) );
-    TEST_ASSERT( function_output_length == output2_length );
-    total_output_length += function_output_length;
-    PSA_ASSERT( psa_cipher_finish( &operation,
-                                   output + total_output_length,
-                                   output_buffer_size - total_output_length,
-                                   &function_output_length ) );
-    total_output_length += function_output_length;
-    PSA_ASSERT( psa_cipher_abort( &operation ) );
 
-    ASSERT_COMPARE( expected_output->x, expected_output->len,
-                    output, total_output_length );
-
-exit:
-    psa_cipher_abort( &operation );
-    mbedtls_free( output );
-    psa_destroy_key( key );
-    PSA_DONE( );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void cipher_decrypt( int alg_arg, int key_type_arg,
-                     data_t *key_data, data_t *iv,
-                     data_t *input, data_t *expected_output,
-                     int expected_status_arg )
-{
-    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
-    psa_status_t status;
-    psa_key_type_t key_type = key_type_arg;
-    psa_algorithm_t alg = alg_arg;
-    psa_status_t expected_status = expected_status_arg;
-    unsigned char *output = NULL;
-    size_t output_buffer_size = 0;
-    size_t function_output_length = 0;
-    size_t total_output_length = 0;
-    psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-
-    PSA_ASSERT( psa_crypto_init( ) );
-
-    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DECRYPT );
-    psa_set_key_algorithm( &attributes, alg );
-    psa_set_key_type( &attributes, key_type );
-
-    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
-                                &key ) );
-
-    PSA_ASSERT( psa_cipher_decrypt_setup( &operation, key, alg ) );
-
-    if( iv->len > 0 )
+    if( first_part_size < input->len )
     {
-        PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
+        PSA_ASSERT( psa_cipher_update( &operation,
+                                       input->x + first_part_size,
+                                       input->len - first_part_size,
+                                       ( output_buffer_size == 0 ? NULL :
+                                         output + total_output_length ),
+                                       output_buffer_size - total_output_length,
+                                       &function_output_length ) );
+        TEST_ASSERT( function_output_length == output2_length );
+        TEST_ASSERT( function_output_length <=
+                     PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type,
+                                                    alg,
+                                                    input->len - first_part_size ) );
+        TEST_ASSERT( function_output_length <=
+                     PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE( input->len ) );
+        total_output_length += function_output_length;
     }
 
-    output_buffer_size = ( (size_t) input->len +
-                           PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
-    ASSERT_ALLOC( output, output_buffer_size );
-
-    PSA_ASSERT( psa_cipher_update( &operation,
-                                   input->x, input->len,
-                                   output, output_buffer_size,
-                                   &function_output_length ) );
-    total_output_length += function_output_length;
     status = psa_cipher_finish( &operation,
-                                output + total_output_length,
+                                ( output_buffer_size == 0 ? NULL :
+                                  output + total_output_length ),
                                 output_buffer_size - total_output_length,
                                 &function_output_length );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_FINISH_OUTPUT_SIZE( key_type, alg ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE );
     total_output_length += function_output_length;
     TEST_EQUAL( status, expected_status );
 
     if( expected_status == PSA_SUCCESS )
     {
         PSA_ASSERT( psa_cipher_abort( &operation ) );
+
         ASSERT_COMPARE( expected_output->x, expected_output->len,
                         output, total_output_length );
     }
@@ -3765,25 +2970,132 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void cipher_verify_output( int alg_arg, int key_type_arg,
+void cipher_decrypt_fail( int alg_arg,
+                          int key_type_arg,
+                          data_t *key_data,
+                          data_t *iv,
+                          data_t *input_arg,
+                          int expected_status_arg )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_status_t status;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_status_t expected_status = expected_status_arg;
+    unsigned char *input = NULL;
+    size_t input_buffer_size = 0;
+    unsigned char *output = NULL;
+    size_t output_buffer_size = 0;
+    size_t output_length = 0;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    if ( PSA_ERROR_BAD_STATE != expected_status )
+    {
+        PSA_ASSERT( psa_crypto_init( ) );
+
+        psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DECRYPT );
+        psa_set_key_algorithm( &attributes, alg );
+        psa_set_key_type( &attributes, key_type );
+
+        PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                    &key ) );
+    }
+
+    /* Allocate input buffer and copy the iv and the plaintext */
+    input_buffer_size = ( (size_t) input_arg->len + (size_t) iv->len );
+    if ( input_buffer_size > 0 )
+    {
+        ASSERT_ALLOC( input, input_buffer_size );
+        memcpy( input, iv->x, iv->len );
+        memcpy( input + iv->len, input_arg->x, input_arg->len );
+    }
+
+    output_buffer_size = PSA_CIPHER_DECRYPT_OUTPUT_SIZE( key_type, alg, input_buffer_size );
+    ASSERT_ALLOC( output, output_buffer_size );
+
+    status = psa_cipher_decrypt( key, alg, input, input_buffer_size, output,
+                                 output_buffer_size, &output_length );
+    TEST_EQUAL( status, expected_status );
+
+exit:
+    mbedtls_free( input );
+    mbedtls_free( output );
+    psa_destroy_key( key );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_decrypt( int alg_arg,
+                     int key_type_arg,
+                     data_t *key_data,
+                     data_t *iv,
+                     data_t *input_arg,
+                     data_t *expected_output )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    unsigned char *input = NULL;
+    size_t input_buffer_size = 0;
+    unsigned char *output = NULL;
+    size_t output_buffer_size = 0;
+    size_t output_length = 0;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DECRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    /* Allocate input buffer and copy the iv and the plaintext */
+    input_buffer_size = ( (size_t) input_arg->len + (size_t) iv->len );
+    if ( input_buffer_size > 0 )
+    {
+        ASSERT_ALLOC( input, input_buffer_size );
+        memcpy( input, iv->x, iv->len );
+        memcpy( input + iv->len, input_arg->x, input_arg->len );
+    }
+
+    output_buffer_size = PSA_CIPHER_DECRYPT_OUTPUT_SIZE( key_type, alg, input_buffer_size );
+    ASSERT_ALLOC( output, output_buffer_size );
+
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+
+    PSA_ASSERT( psa_cipher_decrypt( key, alg, input, input_buffer_size, output,
+                                    output_buffer_size, &output_length ) );
+    TEST_ASSERT( output_length <=
+                 PSA_CIPHER_DECRYPT_OUTPUT_SIZE( key_type, alg, input_buffer_size ) );
+    TEST_ASSERT( output_length <=
+                 PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE( input_buffer_size ) );
+
+    ASSERT_COMPARE( expected_output->x, expected_output->len,
+                    output, output_length );
+exit:
+    mbedtls_free( input );
+    mbedtls_free( output );
+    psa_destroy_key( key );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_verify_output( int alg_arg,
+                           int key_type_arg,
                            data_t *key_data,
                            data_t *input )
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
-    unsigned char iv[16] = {0};
-    size_t iv_size = 16;
-    size_t iv_length = 0;
     unsigned char *output1 = NULL;
     size_t output1_size = 0;
     size_t output1_length = 0;
     unsigned char *output2 = NULL;
     size_t output2_size = 0;
     size_t output2_length = 0;
-    size_t function_output_length = 0;
-    psa_cipher_operation_t operation1 = PSA_CIPHER_OPERATION_INIT;
-    psa_cipher_operation_t operation2 = PSA_CIPHER_OPERATION_INIT;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
@@ -3794,59 +3106,31 @@
 
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &key ) );
-
-    PSA_ASSERT( psa_cipher_encrypt_setup( &operation1, key, alg ) );
-    PSA_ASSERT( psa_cipher_decrypt_setup( &operation2, key, alg ) );
-
-    if( alg != PSA_ALG_ECB_NO_PADDING )
-    {
-        PSA_ASSERT( psa_cipher_generate_iv( &operation1,
-                                            iv, iv_size,
-                                            &iv_length ) );
-    }
-    output1_size = ( (size_t) input->len +
-                     PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
+    output1_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE( key_type, alg, input->len );
     ASSERT_ALLOC( output1, output1_size );
 
-    PSA_ASSERT( psa_cipher_update( &operation1, input->x, input->len,
-                                   output1, output1_size,
-                                   &output1_length ) );
-    PSA_ASSERT( psa_cipher_finish( &operation1,
-                                   output1 + output1_length,
-                                   output1_size - output1_length,
-                                   &function_output_length ) );
-
-    output1_length += function_output_length;
-
-    PSA_ASSERT( psa_cipher_abort( &operation1 ) );
+    PSA_ASSERT( psa_cipher_encrypt( key, alg, input->x, input->len,
+                                    output1, output1_size,
+                                    &output1_length ) );
+    TEST_ASSERT( output1_length <=
+                 PSA_CIPHER_ENCRYPT_OUTPUT_SIZE( key_type, alg, input->len ) );
+    TEST_ASSERT( output1_length <=
+                 PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE( input->len ) );
 
     output2_size = output1_length;
     ASSERT_ALLOC( output2, output2_size );
 
-    if( iv_length > 0 )
-    {
-        PSA_ASSERT( psa_cipher_set_iv( &operation2,
-                                       iv, iv_length ) );
-    }
-
-    PSA_ASSERT( psa_cipher_update( &operation2, output1, output1_length,
-                                   output2, output2_size,
-                                   &output2_length ) );
-    function_output_length = 0;
-    PSA_ASSERT( psa_cipher_finish( &operation2,
-                                   output2 + output2_length,
-                                   output2_size - output2_length,
-                                   &function_output_length ) );
-
-    output2_length += function_output_length;
-
-    PSA_ASSERT( psa_cipher_abort( &operation2 ) );
+    PSA_ASSERT( psa_cipher_decrypt( key, alg, output1, output1_length,
+                                    output2, output2_size,
+                                    &output2_length ) );
+    TEST_ASSERT( output2_length <=
+                 PSA_CIPHER_DECRYPT_OUTPUT_SIZE( key_type, alg, output1_length ) );
+    TEST_ASSERT( output2_length <=
+                 PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE( output1_length ) );
 
     ASSERT_COMPARE( input->x, input->len, output2, output2_length );
 
 exit:
-    psa_cipher_abort( &operation1 );
-    psa_cipher_abort( &operation2 );
     mbedtls_free( output1 );
     mbedtls_free( output2 );
     psa_destroy_key( key );
@@ -3898,8 +3182,9 @@
                                             &iv_length ) );
     }
 
-    output1_buffer_size = ( (size_t) input->len +
-                            PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
+    output1_buffer_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE( key_type, alg, input->len );
+    TEST_ASSERT( output1_buffer_size <=
+                 PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE( input->len ) );
     ASSERT_ALLOC( output1, output1_buffer_size );
 
     TEST_ASSERT( first_part_size <= input->len );
@@ -3907,6 +3192,10 @@
     PSA_ASSERT( psa_cipher_update( &operation1, input->x, first_part_size,
                                    output1, output1_buffer_size,
                                    &function_output_length ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, first_part_size ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE( first_part_size ) );
     output1_length += function_output_length;
 
     PSA_ASSERT( psa_cipher_update( &operation1,
@@ -3914,17 +3203,31 @@
                                    input->len - first_part_size,
                                    output1, output1_buffer_size,
                                    &function_output_length ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type,
+                                                alg,
+                                                input->len - first_part_size ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE( input->len - first_part_size ) );
     output1_length += function_output_length;
 
     PSA_ASSERT( psa_cipher_finish( &operation1,
                                    output1 + output1_length,
                                    output1_buffer_size - output1_length,
                                    &function_output_length ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_FINISH_OUTPUT_SIZE( key_type, alg ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE );
     output1_length += function_output_length;
 
     PSA_ASSERT( psa_cipher_abort( &operation1 ) );
 
     output2_buffer_size = output1_length;
+    TEST_ASSERT( output2_buffer_size <=
+                 PSA_CIPHER_DECRYPT_OUTPUT_SIZE( key_type, alg, output1_length ) );
+    TEST_ASSERT( output2_buffer_size <=
+                 PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE( output1_length ) );
     ASSERT_ALLOC( output2, output2_buffer_size );
 
     if( iv_length > 0 )
@@ -3936,6 +3239,10 @@
     PSA_ASSERT( psa_cipher_update( &operation2, output1, first_part_size,
                                    output2, output2_buffer_size,
                                    &function_output_length ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, first_part_size ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE( first_part_size ) );
     output2_length += function_output_length;
 
     PSA_ASSERT( psa_cipher_update( &operation2,
@@ -3943,12 +3250,22 @@
                                    output1_length - first_part_size,
                                    output2, output2_buffer_size,
                                    &function_output_length ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type,
+                                                alg,
+                                                output1_length - first_part_size ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE( output1_length - first_part_size ) );
     output2_length += function_output_length;
 
     PSA_ASSERT( psa_cipher_finish( &operation2,
                                    output2 + output2_length,
                                    output2_buffer_size - output2_length,
                                    &function_output_length ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_FINISH_OUTPUT_SIZE( key_type, alg ) );
+    TEST_ASSERT( function_output_length <=
+                 PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE );
     output2_length += function_output_length;
 
     PSA_ASSERT( psa_cipher_abort( &operation2 ) );
@@ -3976,23 +3293,16 @@
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
+    size_t key_bits;
     unsigned char *output_data = NULL;
     size_t output_size = 0;
     size_t output_length = 0;
     unsigned char *output_data2 = NULL;
     size_t output_length2 = 0;
-    size_t tag_length = PSA_AEAD_TAG_LENGTH( alg );
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
     psa_status_t expected_result = expected_result_arg;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-    output_size = input_data->len + tag_length;
-    /* For all currently defined algorithms, PSA_AEAD_ENCRYPT_OUTPUT_SIZE
-     * should be exact. */
-    if( expected_result != PSA_ERROR_INVALID_ARGUMENT )
-        TEST_EQUAL( output_size,
-                    PSA_AEAD_ENCRYPT_OUTPUT_SIZE( alg, input_data->len ) );
-    ASSERT_ALLOC( output_data, output_size );
-
     PSA_ASSERT( psa_crypto_init( ) );
 
     psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
@@ -4001,15 +3311,41 @@
 
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &key ) );
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+    key_bits = psa_get_key_bits( &attributes );
 
-    TEST_EQUAL( psa_aead_encrypt( key, alg,
-                                  nonce->x, nonce->len,
-                                  additional_data->x,
-                                  additional_data->len,
-                                  input_data->x, input_data->len,
-                                  output_data, output_size,
-                                  &output_length ),
-                expected_result );
+    output_size = input_data->len + PSA_AEAD_TAG_LENGTH( key_type, key_bits,
+                                                         alg );
+    /* For all currently defined algorithms, PSA_AEAD_ENCRYPT_OUTPUT_SIZE
+     * should be exact. */
+    if( expected_result != PSA_ERROR_INVALID_ARGUMENT &&
+        expected_result != PSA_ERROR_NOT_SUPPORTED )
+    {
+        TEST_EQUAL( output_size,
+                    PSA_AEAD_ENCRYPT_OUTPUT_SIZE( key_type, alg, input_data->len ) );
+        TEST_ASSERT( output_size <=
+                     PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE( input_data->len ) );
+    }
+    ASSERT_ALLOC( output_data, output_size );
+
+    status = psa_aead_encrypt( key, alg,
+                               nonce->x, nonce->len,
+                               additional_data->x,
+                               additional_data->len,
+                               input_data->x, input_data->len,
+                               output_data, output_size,
+                               &output_length );
+
+    /* If the operation is not supported, just skip and not fail in case the
+     * encryption involves a common limitation of cryptography hardwares and
+     * an alternative implementation. */
+    if( status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192( key_type, key_data->len * 8 );
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE( alg, nonce->len );
+    }
+
+    TEST_EQUAL( status, expected_result );
 
     if( PSA_SUCCESS == expected_result )
     {
@@ -4018,7 +3354,10 @@
         /* For all currently defined algorithms, PSA_AEAD_DECRYPT_OUTPUT_SIZE
          * should be exact. */
         TEST_EQUAL( input_data->len,
-                    PSA_AEAD_DECRYPT_OUTPUT_SIZE( alg, output_length ) );
+                    PSA_AEAD_DECRYPT_OUTPUT_SIZE( key_type, alg, output_length ) );
+
+        TEST_ASSERT( input_data->len <=
+                     PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE( output_length ) );
 
         TEST_EQUAL( psa_aead_decrypt( key, alg,
                                       nonce->x, nonce->len,
@@ -4052,18 +3391,12 @@
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
+    size_t key_bits;
     unsigned char *output_data = NULL;
     size_t output_size = 0;
     size_t output_length = 0;
-    size_t tag_length = PSA_AEAD_TAG_LENGTH( alg );
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-
-    output_size = input_data->len + tag_length;
-    /* For all currently defined algorithms, PSA_AEAD_ENCRYPT_OUTPUT_SIZE
-     * should be exact. */
-    TEST_EQUAL( output_size,
-                PSA_AEAD_ENCRYPT_OUTPUT_SIZE( alg, input_data->len ) );
-    ASSERT_ALLOC( output_data, output_size );
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
@@ -4073,14 +3406,36 @@
 
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &key ) );
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+    key_bits = psa_get_key_bits( &attributes );
 
-    PSA_ASSERT( psa_aead_encrypt( key, alg,
-                                  nonce->x, nonce->len,
-                                  additional_data->x, additional_data->len,
-                                  input_data->x, input_data->len,
-                                  output_data, output_size,
-                                  &output_length ) );
+    output_size = input_data->len + PSA_AEAD_TAG_LENGTH( key_type, key_bits,
+                                                         alg );
+    /* For all currently defined algorithms, PSA_AEAD_ENCRYPT_OUTPUT_SIZE
+     * should be exact. */
+    TEST_EQUAL( output_size,
+                PSA_AEAD_ENCRYPT_OUTPUT_SIZE( key_type, alg, input_data->len ) );
+    TEST_ASSERT( output_size <=
+                 PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE( input_data->len ) );
+    ASSERT_ALLOC( output_data, output_size );
 
+    status = psa_aead_encrypt( key, alg,
+                               nonce->x, nonce->len,
+                               additional_data->x, additional_data->len,
+                               input_data->x, input_data->len,
+                               output_data, output_size,
+                               &output_length );
+
+    /* If the operation is not supported, just skip and not fail in case the
+     * encryption involves a common limitation of cryptography hardwares and
+     * an alternative implementation. */
+    if( status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192( key_type, key_data->len * 8 );
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE( alg, nonce->len );
+    }
+
+    PSA_ASSERT( status );
     ASSERT_COMPARE( expected_result->x, expected_result->len,
                     output_data, output_length );
 
@@ -4103,20 +3458,13 @@
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
+    size_t key_bits;
     unsigned char *output_data = NULL;
     size_t output_size = 0;
     size_t output_length = 0;
-    size_t tag_length = PSA_AEAD_TAG_LENGTH( alg );
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_status_t expected_result = expected_result_arg;
-
-    output_size = input_data->len - tag_length;
-    /* For all currently defined algorithms, PSA_AEAD_DECRYPT_OUTPUT_SIZE
-     * should be exact. */
-    if( expected_result != PSA_ERROR_INVALID_ARGUMENT )
-        TEST_EQUAL( output_size,
-                    PSA_AEAD_DECRYPT_OUTPUT_SIZE( alg, input_data->len ) );
-    ASSERT_ALLOC( output_data, output_size );
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
@@ -4126,15 +3474,41 @@
 
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &key ) );
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+    key_bits = psa_get_key_bits( &attributes );
 
-    TEST_EQUAL( psa_aead_decrypt( key, alg,
-                                  nonce->x, nonce->len,
-                                  additional_data->x,
-                                  additional_data->len,
-                                  input_data->x, input_data->len,
-                                  output_data, output_size,
-                                  &output_length ),
-                expected_result );
+    output_size = input_data->len - PSA_AEAD_TAG_LENGTH( key_type, key_bits,
+                                                         alg );
+    if( expected_result != PSA_ERROR_INVALID_ARGUMENT &&
+        expected_result != PSA_ERROR_NOT_SUPPORTED )
+    {
+        /* For all currently defined algorithms, PSA_AEAD_DECRYPT_OUTPUT_SIZE
+         * should be exact. */
+        TEST_EQUAL( output_size,
+                    PSA_AEAD_DECRYPT_OUTPUT_SIZE( key_type, alg, input_data->len ) );
+        TEST_ASSERT( output_size <=
+                     PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE( input_data->len ) );
+    }
+    ASSERT_ALLOC( output_data, output_size );
+
+    status = psa_aead_decrypt( key, alg,
+                               nonce->x, nonce->len,
+                               additional_data->x,
+                               additional_data->len,
+                               input_data->x, input_data->len,
+                               output_data, output_size,
+                               &output_length );
+
+    /* If the operation is not supported, just skip and not fail in case the
+     * decryption involves a common limitation of cryptography hardwares and
+     * an alternative implementation. */
+    if( status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192( key_type, key_data->len * 8 );
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE( alg, nonce->len );
+    }
+
+    TEST_EQUAL( status, expected_result );
 
     if( expected_result == PSA_SUCCESS )
         ASSERT_COMPARE( expected_data->x, expected_data->len,
@@ -4169,9 +3543,9 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void sign_deterministic( int key_type_arg, data_t *key_data,
-                         int alg_arg, data_t *input_data,
-                         data_t *output_data )
+void sign_hash_deterministic( int key_type_arg, data_t *key_data,
+                              int alg_arg, data_t *input_data,
+                              data_t *output_data )
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_type_t key_type = key_type_arg;
@@ -4235,9 +3609,9 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void sign_fail( int key_type_arg, data_t *key_data,
-                int alg_arg, data_t *input_data,
-                int signature_size_arg, int expected_status_arg )
+void sign_hash_fail( int key_type_arg, data_t *key_data,
+                     int alg_arg, data_t *input_data,
+                     int signature_size_arg, int expected_status_arg )
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_type_t key_type = key_type_arg;
@@ -4290,8 +3664,8 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void sign_verify( int key_type_arg, data_t *key_data,
-                  int alg_arg, data_t *input_data )
+void sign_verify_hash( int key_type_arg, data_t *key_data,
+                       int alg_arg, data_t *input_data )
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_type_t key_type = key_type_arg;
@@ -4361,9 +3735,9 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void asymmetric_verify( int key_type_arg, data_t *key_data,
-                        int alg_arg, data_t *hash_data,
-                        data_t *signature_data )
+void verify_hash( int key_type_arg, data_t *key_data,
+                  int alg_arg, data_t *hash_data,
+                  data_t *signature_data )
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_type_t key_type = key_type_arg;
@@ -4401,10 +3775,10 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void asymmetric_verify_fail( int key_type_arg, data_t *key_data,
-                             int alg_arg, data_t *hash_data,
-                             data_t *signature_data,
-                             int expected_status_arg )
+void verify_hash_fail( int key_type_arg, data_t *key_data,
+                       int alg_arg, data_t *hash_data,
+                       data_t *signature_data,
+                       int expected_status_arg )
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_type_t key_type = key_type_arg;
@@ -4442,6 +3816,239 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void sign_message_deterministic( int key_type_arg,
+                                 data_t *key_data,
+                                 int alg_arg,
+                                 data_t *input_data,
+                                 data_t *output_data )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    size_t key_bits;
+    unsigned char *signature = NULL;
+    size_t signature_size;
+    size_t signature_length = 0xdeadbeef;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_MESSAGE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+    key_bits = psa_get_key_bits( &attributes );
+
+    signature_size = PSA_SIGN_OUTPUT_SIZE( key_type, key_bits, alg );
+    TEST_ASSERT( signature_size != 0 );
+    TEST_ASSERT( signature_size <= PSA_SIGNATURE_MAX_SIZE );
+    ASSERT_ALLOC( signature, signature_size );
+
+    PSA_ASSERT( psa_sign_message( key, alg,
+                                  input_data->x, input_data->len,
+                                  signature, signature_size,
+                                  &signature_length ) );
+
+    ASSERT_COMPARE( output_data->x, output_data->len,
+                    signature, signature_length );
+
+exit:
+    psa_reset_key_attributes( &attributes );
+
+    psa_destroy_key( key );
+    mbedtls_free( signature );
+    PSA_DONE( );
+
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void sign_message_fail( int key_type_arg,
+                        data_t *key_data,
+                        int alg_arg,
+                        data_t *input_data,
+                        int signature_size_arg,
+                        int expected_status_arg )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    size_t signature_size = signature_size_arg;
+    psa_status_t actual_status;
+    psa_status_t expected_status = expected_status_arg;
+    unsigned char *signature = NULL;
+    size_t signature_length = 0xdeadbeef;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    ASSERT_ALLOC( signature, signature_size );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_MESSAGE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+
+    actual_status = psa_sign_message( key, alg,
+                                      input_data->x, input_data->len,
+                                      signature, signature_size,
+                                      &signature_length );
+    TEST_EQUAL( actual_status, expected_status );
+    /* The value of *signature_length is unspecified on error, but
+     * whatever it is, it should be less than signature_size, so that
+     * if the caller tries to read *signature_length bytes without
+     * checking the error code then they don't overflow a buffer. */
+    TEST_ASSERT( signature_length <= signature_size );
+
+exit:
+    psa_reset_key_attributes( &attributes );
+    psa_destroy_key( key );
+    mbedtls_free( signature );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void sign_verify_message( int key_type_arg,
+                          data_t *key_data,
+                          int alg_arg,
+                          data_t *input_data )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    size_t key_bits;
+    unsigned char *signature = NULL;
+    size_t signature_size;
+    size_t signature_length = 0xdeadbeef;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_MESSAGE |
+                                          PSA_KEY_USAGE_VERIFY_MESSAGE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+    key_bits = psa_get_key_bits( &attributes );
+
+    signature_size = PSA_SIGN_OUTPUT_SIZE( key_type, key_bits, alg );
+    TEST_ASSERT( signature_size != 0 );
+    TEST_ASSERT( signature_size <= PSA_SIGNATURE_MAX_SIZE );
+    ASSERT_ALLOC( signature, signature_size );
+
+    PSA_ASSERT( psa_sign_message( key, alg,
+                                  input_data->x, input_data->len,
+                                  signature, signature_size,
+                                  &signature_length ) );
+    TEST_ASSERT( signature_length <= signature_size );
+    TEST_ASSERT( signature_length > 0 );
+
+    PSA_ASSERT( psa_verify_message( key, alg,
+                                    input_data->x, input_data->len,
+                                    signature, signature_length ) );
+
+    if( input_data->len != 0 )
+    {
+        /* Flip a bit in the input and verify that the signature is now
+         * detected as invalid. Flip a bit at the beginning, not at the end,
+         * because ECDSA may ignore the last few bits of the input. */
+        input_data->x[0] ^= 1;
+        TEST_EQUAL( psa_verify_message( key, alg,
+                                        input_data->x, input_data->len,
+                                        signature, signature_length ),
+                    PSA_ERROR_INVALID_SIGNATURE );
+    }
+
+exit:
+    psa_reset_key_attributes( &attributes );
+
+    psa_destroy_key( key );
+    mbedtls_free( signature );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void verify_message( int key_type_arg,
+                     data_t *key_data,
+                     int alg_arg,
+                     data_t *input_data,
+                     data_t *signature_data )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    TEST_ASSERT( signature_data->len <= PSA_SIGNATURE_MAX_SIZE );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_MESSAGE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+
+    PSA_ASSERT( psa_verify_message( key, alg,
+                                    input_data->x, input_data->len,
+                                    signature_data->x, signature_data->len ) );
+
+exit:
+    psa_reset_key_attributes( &attributes );
+    psa_destroy_key( key );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void verify_message_fail( int key_type_arg,
+                          data_t *key_data,
+                          int alg_arg,
+                          data_t *hash_data,
+                          data_t *signature_data,
+                          int expected_status_arg )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_status_t actual_status;
+    psa_status_t expected_status = expected_status_arg;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_MESSAGE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+
+    actual_status = psa_verify_message( key, alg,
+                                        hash_data->x, hash_data->len,
+                                        signature_data->x,
+                                        signature_data->len );
+    TEST_EQUAL( actual_status, expected_status );
+
+exit:
+    psa_reset_key_attributes( &attributes );
+    psa_destroy_key( key );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void asymmetric_encrypt( int key_type_arg,
                          data_t *key_data,
                          int alg_arg,
@@ -4474,7 +4081,9 @@
     /* Determine the maximum output length */
     PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
     key_bits = psa_get_key_bits( &attributes );
+
     output_size = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE( key_type, key_bits, alg );
+    TEST_ASSERT( output_size <= PSA_ASYMMETRIC_ENCRYPT_OUTPUT_MAX_SIZE );
     ASSERT_ALLOC( output, output_size );
 
     /* Encrypt the input */
@@ -4546,9 +4155,15 @@
     /* Determine the maximum ciphertext length */
     PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
     key_bits = psa_get_key_bits( &attributes );
+
     output_size = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE( key_type, key_bits, alg );
+    TEST_ASSERT( output_size <= PSA_ASYMMETRIC_ENCRYPT_OUTPUT_MAX_SIZE );
     ASSERT_ALLOC( output, output_size );
+
     output2_size = input_data->len;
+    TEST_ASSERT( output2_size <=
+                 PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE( key_type, key_bits, alg ) );
+    TEST_ASSERT( output2_size <= PSA_ASYMMETRIC_DECRYPT_OUTPUT_MAX_SIZE );
     ASSERT_ALLOC( output2, output2_size );
 
     /* We test encryption by checking that encrypt-then-decrypt gives back
@@ -4596,14 +4211,12 @@
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
+    size_t key_bits;
     unsigned char *output = NULL;
     size_t output_size = 0;
     size_t output_length = ~0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-    output_size = expected_data->len;
-    ASSERT_ALLOC( output, output_size );
-
     PSA_ASSERT( psa_crypto_init( ) );
 
     psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DECRYPT );
@@ -4613,6 +4226,14 @@
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &key ) );
 
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+    key_bits = psa_get_key_bits( &attributes );
+
+    /* Determine the maximum ciphertext length */
+    output_size = PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE( key_type, key_bits, alg );
+    TEST_ASSERT( output_size <= PSA_ASYMMETRIC_DECRYPT_OUTPUT_MAX_SIZE );
+    ASSERT_ALLOC( output, output_size );
+
     PSA_ASSERT( psa_asymmetric_decrypt( key, alg,
                                         input_data->x, input_data->len,
                                         label->x, label->len,
@@ -4815,7 +4436,12 @@
 
     for( i = 0; i < ARRAY_LENGTH( steps ); i++ )
     {
-        if( key_types[i] != PSA_KEY_TYPE_NONE )
+        mbedtls_test_set_step( i );
+        if( steps[i] == 0 )
+        {
+            /* Skip this step */
+        }
+        else if( key_types[i] != PSA_KEY_TYPE_NONE )
         {
             psa_set_key_type( &attributes, key_types[i] );
             PSA_ASSERT( psa_import_key( &attributes,
@@ -4826,7 +4452,8 @@
             {
                 // When taking a private key as secret input, use key agreement
                 // to add the shared secret to the derivation
-                TEST_EQUAL( key_agreement_with_self( &operation, keys[i] ),
+                TEST_EQUAL( mbedtls_test_psa_key_agreement_with_self(
+                                &operation, keys[i] ),
                             expected_statuses[i] );
             }
             else
@@ -4848,7 +4475,7 @@
     if( output_key_type != PSA_KEY_TYPE_NONE )
     {
         psa_reset_key_attributes( &attributes );
-        psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA );
+        psa_set_key_type( &attributes, output_key_type );
         psa_set_key_bits( &attributes, 8 );
         actual_output_status =
             psa_key_derivation_output_key( &attributes, &operation,
@@ -4873,7 +4500,7 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void test_derive_invalid_key_derivation_state( int alg_arg )
+void derive_over_capacity( int alg_arg )
 {
     psa_algorithm_t alg = alg_arg;
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
@@ -4901,10 +4528,10 @@
                                 &key ) );
 
     /* valid key derivation */
-    if( !setup_key_derivation_wrap( &operation, key, alg,
-                                    input1, input1_length,
-                                    input2, input2_length,
-                                    capacity ) )
+    if( !mbedtls_test_psa_setup_key_derivation_wrap( &operation, key, alg,
+                                                     input1, input1_length,
+                                                     input2, input2_length,
+                                                     capacity ) )
         goto exit;
 
     /* state of operation shouldn't allow additional generation */
@@ -4924,7 +4551,7 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void test_derive_invalid_key_derivation_tests( )
+void derive_actions_without_setup( )
 {
     uint8_t output_buffer[16];
     size_t buffer_size = 16;
@@ -5009,6 +4636,14 @@
                 PSA_ASSERT( psa_import_key( &attributes,
                                             inputs[i]->x, inputs[i]->len,
                                             &keys[i] ) );
+
+                if ( PSA_ALG_IS_TLS12_PSK_TO_MS( alg ) )
+                {
+                    PSA_ASSERT( psa_get_key_attributes( keys[i], &attributes ) );
+                    TEST_ASSERT( PSA_BITS_TO_BYTES( psa_get_key_bits( &attributes ) ) <=
+                                 PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE );
+                }
+
                 PSA_ASSERT( psa_key_derivation_input_key(
                                 &operation, steps[i], keys[i] ) );
                 break;
@@ -5093,10 +4728,10 @@
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &key ) );
 
-    if( !setup_key_derivation_wrap( &operation, key, alg,
-                                    input1->x, input1->len,
-                                    input2->x, input2->len,
-                                    requested_capacity ) )
+    if( !mbedtls_test_psa_setup_key_derivation_wrap( &operation, key, alg,
+                                                     input1->x, input1->len,
+                                                     input2->x, input2->len,
+                                                     requested_capacity ) )
         goto exit;
 
     PSA_ASSERT( psa_key_derivation_get_capacity( &operation,
@@ -5162,9 +4797,10 @@
                                 &base_key ) );
 
     /* Derive a key. */
-    if ( setup_key_derivation_wrap( &operation, base_key, alg,
-                                    input1->x, input1->len,
-                                    input2->x, input2->len, capacity ) )
+    if ( mbedtls_test_psa_setup_key_derivation_wrap( &operation, base_key, alg,
+                                                     input1->x, input1->len,
+                                                     input2->x, input2->len,
+                                                     capacity ) )
         goto exit;
 
     psa_set_key_usage_flags( &attributes, derived_usage );
@@ -5180,7 +4816,7 @@
     TEST_EQUAL( psa_get_key_bits( &got_attributes ), derived_bits );
 
     /* Exercise the derived key. */
-    if( ! exercise_key( derived_key, derived_usage, derived_alg ) )
+    if( ! mbedtls_test_psa_exercise_key( derived_key, derived_usage, derived_alg ) )
         goto exit;
 
 exit:
@@ -5229,9 +4865,10 @@
                                 &base_key ) );
 
     /* Derive some material and output it. */
-    if( !setup_key_derivation_wrap( &operation, base_key, alg,
-                                    input1->x, input1->len,
-                                    input2->x, input2->len, capacity ) )
+    if( !mbedtls_test_psa_setup_key_derivation_wrap( &operation, base_key, alg,
+                                                     input1->x, input1->len,
+                                                     input2->x, input2->len,
+                                                     capacity ) )
         goto exit;
 
     PSA_ASSERT( psa_key_derivation_output_bytes( &operation,
@@ -5240,9 +4877,10 @@
     PSA_ASSERT( psa_key_derivation_abort( &operation ) );
 
     /* Derive the same output again, but this time store it in key objects. */
-    if( !setup_key_derivation_wrap( &operation, base_key, alg,
-                                    input1->x, input1->len,
-                                    input2->x, input2->len, capacity ) )
+    if( !mbedtls_test_psa_setup_key_derivation_wrap( &operation, base_key, alg,
+                                                     input1->x, input1->len,
+                                                     input2->x, input2->len,
+                                                     capacity ) )
         goto exit;
 
     psa_set_key_usage_flags( &derived_attributes, PSA_KEY_USAGE_EXPORT );
@@ -5282,7 +4920,8 @@
 void derive_key( int alg_arg,
                  data_t *key_data, data_t *input1, data_t *input2,
                  int type_arg, int bits_arg,
-                 int expected_status_arg )
+                 int expected_status_arg,
+                 int is_large_output )
 {
     mbedtls_svc_key_id_t base_key = MBEDTLS_SVC_KEY_ID_INIT;
     mbedtls_svc_key_id_t derived_key = MBEDTLS_SVC_KEY_ID_INIT;
@@ -5302,18 +4941,24 @@
     PSA_ASSERT( psa_import_key( &base_attributes, key_data->x, key_data->len,
                                 &base_key ) );
 
-    if( !setup_key_derivation_wrap( &operation, base_key, alg,
-                                    input1->x, input1->len,
-                                    input2->x, input2->len, SIZE_MAX ) )
+    if( !mbedtls_test_psa_setup_key_derivation_wrap( &operation, base_key, alg,
+                                                     input1->x, input1->len,
+                                                     input2->x, input2->len,
+                                                     SIZE_MAX ) )
         goto exit;
 
     psa_set_key_usage_flags( &derived_attributes, PSA_KEY_USAGE_EXPORT );
     psa_set_key_algorithm( &derived_attributes, 0 );
     psa_set_key_type( &derived_attributes, type );
     psa_set_key_bits( &derived_attributes, bits );
-    TEST_EQUAL( psa_key_derivation_output_key( &derived_attributes, &operation,
-                                               &derived_key ),
-                expected_status );
+
+    psa_status_t status =
+      psa_key_derivation_output_key( &derived_attributes,
+                                     &operation,
+                                     &derived_key );
+    if( is_large_output > 0 )
+      TEST_ASSUME( status != PSA_ERROR_INSUFFICIENT_MEMORY );
+    TEST_EQUAL( status, expected_status );
 
 exit:
     psa_key_derivation_abort( &operation );
@@ -5384,6 +5029,7 @@
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     unsigned char *output = NULL;
     size_t output_length = ~0;
+    size_t key_bits;
 
     ASSERT_ALLOC( output, expected_output->len );
     PSA_ASSERT( psa_crypto_init( ) );
@@ -5395,12 +5041,19 @@
                                 our_key_data->x, our_key_data->len,
                                 &our_key ) );
 
+    PSA_ASSERT( psa_get_key_attributes( our_key, &attributes ) );
+    key_bits = psa_get_key_bits( &attributes );
+
     PSA_ASSERT( psa_raw_key_agreement( alg, our_key,
                                        peer_key_data->x, peer_key_data->len,
                                        output, expected_output->len,
                                        &output_length ) );
     ASSERT_COMPARE( output, output_length,
                     expected_output->x, expected_output->len );
+    TEST_ASSERT( output_length <=
+                 PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE( our_key_type, key_bits ) );
+    TEST_ASSERT( output_length <=
+                 PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE );
 
 exit:
     mbedtls_free( output );
@@ -5533,7 +5186,6 @@
 void generate_random( int bytes_arg )
 {
     size_t bytes = bytes_arg;
-    const unsigned char trail[] = "don't overwrite me";
     unsigned char *output = NULL;
     unsigned char *changed = NULL;
     size_t i;
@@ -5541,9 +5193,8 @@
 
     TEST_ASSERT( bytes_arg >= 0 );
 
-    ASSERT_ALLOC( output, bytes + sizeof( trail ) );
+    ASSERT_ALLOC( output, bytes );
     ASSERT_ALLOC( changed, bytes );
-    memcpy( output + bytes, trail, sizeof( trail ) );
 
     PSA_ASSERT( psa_crypto_init( ) );
 
@@ -5556,10 +5207,6 @@
             memset( output, 0, bytes );
         PSA_ASSERT( psa_generate_random( output, bytes ) );
 
-        /* Check that no more than bytes have been overwritten */
-        ASSERT_COMPARE( output + bytes, sizeof( trail ),
-                        trail, sizeof( trail ) );
-
         for( i = 0; i < bytes; i++ )
         {
             if( output[i] != 0 )
@@ -5587,7 +5234,8 @@
                    int bits_arg,
                    int usage_arg,
                    int alg_arg,
-                   int expected_status_arg )
+                   int expected_status_arg,
+                   int is_large_key )
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_type_t type = type_arg;
@@ -5606,7 +5254,11 @@
     psa_set_key_bits( &attributes, bits );
 
     /* Generate a key */
-    TEST_EQUAL( psa_generate_key( &attributes, &key ), expected_status );
+    psa_status_t status = psa_generate_key( &attributes, &key );
+
+    if( is_large_key > 0 )
+      TEST_ASSUME( status != PSA_ERROR_INSUFFICIENT_MEMORY );
+    TEST_EQUAL( status , expected_status );
     if( expected_status != PSA_SUCCESS )
         goto exit;
 
@@ -5616,7 +5268,7 @@
     TEST_EQUAL( psa_get_key_bits( &got_attributes ), bits );
 
     /* Do something with the key according to its type and permitted usage. */
-    if( ! exercise_key( key, usage, alg ) )
+    if( ! mbedtls_test_psa_exercise_key( key, usage, alg ) )
         goto exit;
 
 exit:
@@ -5631,7 +5283,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15 */
+/* BEGIN_CASE depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:MBEDTLS_GENPRIME */
 void generate_key_rsa( int bits_arg,
                        data_t *e_arg,
                        int expected_status_arg )
@@ -5645,7 +5297,7 @@
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     uint8_t *exported = NULL;
     size_t exported_size =
-        PSA_KEY_EXPORT_MAX_SIZE( PSA_KEY_TYPE_RSA_PUBLIC_KEY, bits );
+        PSA_EXPORT_KEY_OUTPUT_SIZE( PSA_KEY_TYPE_RSA_PUBLIC_KEY, bits );
     size_t exported_length = SIZE_MAX;
     uint8_t *e_read_buffer = NULL;
     int is_default_public_exponent = 0;
@@ -5688,7 +5340,7 @@
         ASSERT_COMPARE( e_read_buffer, e_read_length, e_arg->x, e_arg->len );
 
     /* Do something with the key according to its type and permitted usage. */
-    if( ! exercise_key( key, usage, alg ) )
+    if( ! mbedtls_test_psa_exercise_key( key, usage, alg ) )
         goto exit;
 
     /* Export the key and check the public exponent. */
@@ -5706,7 +5358,7 @@
         TEST_EQUAL( 0, mbedtls_asn1_get_tag( &p, end, &len,
                                              MBEDTLS_ASN1_SEQUENCE |
                                              MBEDTLS_ASN1_CONSTRUCTED ) );
-        TEST_ASSERT( asn1_skip_integer( &p, end, bits, bits, 1 ) );
+        TEST_ASSERT( mbedtls_test_asn1_skip_integer( &p, end, bits, bits, 1 ) );
         TEST_EQUAL( 0, mbedtls_asn1_get_tag( &p, end, &len,
                                              MBEDTLS_ASN1_INTEGER ) );
         if( len >= 1 && p[0] == 0 )
@@ -5756,7 +5408,7 @@
     psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
     unsigned char *first_export = NULL;
     unsigned char *second_export = NULL;
-    size_t export_size = PSA_KEY_EXPORT_MAX_SIZE( type, bits );
+    size_t export_size = PSA_EXPORT_KEY_OUTPUT_SIZE( type, bits );
     size_t first_exported_length;
     size_t second_exported_length;
 
@@ -5788,6 +5440,7 @@
             break;
 
         case DERIVE_KEY:
+#if defined(PSA_WANT_ALG_HKDF) && defined(PSA_WANT_ALG_SHA_256)
             {
                 /* Create base key */
                 psa_algorithm_t derive_alg = PSA_ALG_HKDF( PSA_ALG_SHA_256 );
@@ -5814,7 +5467,14 @@
                 PSA_ASSERT( psa_destroy_key( base_key ) );
                 base_key = MBEDTLS_SVC_KEY_ID_INIT;
             }
-        break;
+#else
+            TEST_ASSUME( ! "KDF not supported in this configuration" );
+#endif
+            break;
+
+        default:
+            TEST_ASSERT( ! "generation_method not implemented in test" );
+            break;
     }
     psa_reset_key_attributes( &attributes );
 
@@ -5842,7 +5502,8 @@
                 PSA_KEY_LIFETIME_PERSISTENT );
     TEST_EQUAL( psa_get_key_type( &attributes ), type );
     TEST_EQUAL( psa_get_key_bits( &attributes ), bits );
-    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage_flags );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ),
+                mbedtls_test_update_key_usage_flags( usage_flags ) );
     TEST_EQUAL( psa_get_key_algorithm( &attributes ), alg );
 
     /* Export the key again if permitted by the key policy. */
@@ -5856,7 +5517,7 @@
     }
 
     /* Do something with the key according to its type and permitted usage. */
-    if( ! exercise_key( key, usage_flags, alg ) )
+    if( ! mbedtls_test_psa_exercise_key( key, usage_flags, alg ) )
         goto exit;
 
 exit:
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_attributes.data b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_attributes.data
new file mode 100644
index 0000000..a710971
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_attributes.data
@@ -0,0 +1,27 @@
+PSA key attributes structure
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+attributes_set_get:0xffff1234:0x6963:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:128
+
+PSA key attributes: id only
+persistence_attributes:0x1234:0x5678:-1:-1:0:0x1234:0x5678:PSA_KEY_LIFETIME_PERSISTENT
+
+PSA key attributes: lifetime=3 only
+persistence_attributes:-1:0:3:-1:0:0:0:3
+
+PSA key attributes: id then back to volatile
+persistence_attributes:0x1234:0x5678:PSA_KEY_LIFETIME_VOLATILE:-1:0:0:0x5678:PSA_KEY_LIFETIME_VOLATILE
+
+PSA key attributes: id then back to non local volatile
+persistence_attributes:0x1234:0x5678:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_VOLATILE,1):-1:0:0:0x5678:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_VOLATILE,1)
+
+PSA key attributes: id then lifetime
+persistence_attributes:0x1234:0x5678:3:-1:0:0x1234:0x5678:3
+
+PSA key attributes: lifetime then id
+persistence_attributes:0x1234:0x5678:3:0x1235:0x5679:0x1235:0x5679:3
+
+PSA key attributes: non local volatile lifetime then id
+persistence_attributes:0x1234:0x5678:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_VOLATILE,3):0x1235:0x5679:0x1235:0x5679:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_PERSISTENT,3)
+
+PSA key attributes: slot number
+slot_number_attribute:
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_attributes.function b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_attributes.function
new file mode 100644
index 0000000..ce34fae
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_attributes.function
@@ -0,0 +1,129 @@
+/* BEGIN_HEADER */
+#include "psa/crypto.h"
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_PSA_CRYPTO_CLIENT
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void attributes_set_get( int owner_id_arg, int id_arg, int lifetime_arg,
+                         int usage_flags_arg, int alg_arg,
+                         int type_arg, int bits_arg )
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( owner_id_arg, id_arg );
+    psa_key_lifetime_t lifetime = lifetime_arg;
+    psa_key_usage_t usage_flags = usage_flags_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_key_type_t type = type_arg;
+    size_t bits = bits_arg;
+
+    TEST_EQUAL(
+        MBEDTLS_SVC_KEY_ID_GET_KEY_ID( psa_get_key_id( &attributes ) ), 0 );
+    TEST_EQUAL(
+        MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( psa_get_key_id( &attributes ) ), 0 );
+    TEST_EQUAL( psa_get_key_lifetime( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_type( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_bits( &attributes ), 0 );
+
+    psa_set_key_id( &attributes, id );
+    psa_set_key_lifetime( &attributes, lifetime );
+    psa_set_key_usage_flags( &attributes, usage_flags );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, type );
+    psa_set_key_bits( &attributes, bits );
+
+    TEST_ASSERT( mbedtls_svc_key_id_equal(
+                     psa_get_key_id( &attributes ), id ) );
+    TEST_EQUAL( psa_get_key_lifetime( &attributes ), lifetime );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage_flags );
+    TEST_EQUAL( psa_get_key_algorithm( &attributes ), alg );
+    TEST_EQUAL( psa_get_key_type( &attributes ), type );
+    TEST_EQUAL( psa_get_key_bits( &attributes ), bits );
+
+    psa_reset_key_attributes( &attributes );
+
+    TEST_EQUAL(
+        MBEDTLS_SVC_KEY_ID_GET_KEY_ID( psa_get_key_id( &attributes ) ), 0 );
+    TEST_EQUAL(
+        MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( psa_get_key_id( &attributes ) ), 0 );
+    TEST_EQUAL( psa_get_key_lifetime( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_type( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_bits( &attributes ), 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void persistence_attributes( int id1_arg, int owner_id1_arg, int lifetime_arg,
+                             int id2_arg, int owner_id2_arg,
+                             int expected_id_arg, int expected_owner_id_arg,
+                             int expected_lifetime_arg )
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t id1 =
+        mbedtls_svc_key_id_make( owner_id1_arg, id1_arg );
+    psa_key_lifetime_t lifetime = lifetime_arg;
+    mbedtls_svc_key_id_t id2 =
+        mbedtls_svc_key_id_make( owner_id2_arg, id2_arg );
+    mbedtls_svc_key_id_t expected_id =
+        mbedtls_svc_key_id_make( expected_owner_id_arg, expected_id_arg );
+    psa_key_lifetime_t expected_lifetime = expected_lifetime_arg;
+
+    if( id1_arg != -1 )
+        psa_set_key_id( &attributes, id1 );
+    if( lifetime_arg != -1 )
+        psa_set_key_lifetime( &attributes, lifetime );
+    if( id2_arg != -1 )
+        psa_set_key_id( &attributes, id2 );
+
+    TEST_ASSERT( mbedtls_svc_key_id_equal(
+                     psa_get_key_id( &attributes ), expected_id ) );
+    TEST_EQUAL( psa_get_key_lifetime( &attributes ), expected_lifetime );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_SE_C */
+void slot_number_attribute( )
+{
+    psa_key_slot_number_t slot_number = 0xdeadbeef;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    /* Initially, there is no slot number. */
+    TEST_EQUAL( psa_get_key_slot_number( &attributes, &slot_number ),
+                PSA_ERROR_INVALID_ARGUMENT );
+
+    /* Test setting a slot number. */
+    psa_set_key_slot_number( &attributes, 0 );
+    PSA_ASSERT( psa_get_key_slot_number( &attributes, &slot_number ) );
+    TEST_EQUAL( slot_number, 0 );
+
+    /* Test changing the slot number. */
+    psa_set_key_slot_number( &attributes, 42 );
+    PSA_ASSERT( psa_get_key_slot_number( &attributes, &slot_number ) );
+    TEST_EQUAL( slot_number, 42 );
+
+    /* Test clearing the slot number. */
+    psa_clear_key_slot_number( &attributes );
+    TEST_EQUAL( psa_get_key_slot_number( &attributes, &slot_number ),
+                PSA_ERROR_INVALID_ARGUMENT );
+
+    /* Clearing again should have no effect. */
+    psa_clear_key_slot_number( &attributes );
+    TEST_EQUAL( psa_get_key_slot_number( &attributes, &slot_number ),
+                PSA_ERROR_INVALID_ARGUMENT );
+
+    /* Test that reset clears the slot number. */
+    psa_set_key_slot_number( &attributes, 42 );
+    PSA_ASSERT( psa_get_key_slot_number( &attributes, &slot_number ) );
+    TEST_EQUAL( slot_number, 42 );
+    psa_reset_key_attributes( &attributes );
+    TEST_EQUAL( psa_get_key_slot_number( &attributes, &slot_number ),
+                PSA_ERROR_INVALID_ARGUMENT );
+}
+/* END_CASE */
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_driver_wrappers.data b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_driver_wrappers.data
index 2b1400b..ea6c9b3 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_driver_wrappers.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_driver_wrappers.data
@@ -1,32 +1,68 @@
 sign_hash through transparent driver: calculate in driver
-ecdsa_sign:PSA_SUCCESS:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":0:PSA_SUCCESS
+ecdsa_sign_hash:PSA_SUCCESS:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":0:PSA_SUCCESS
 
 sign_hash through transparent driver: fallback
-ecdsa_sign:PSA_ERROR_NOT_SUPPORTED:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":0:PSA_SUCCESS
+depends_on:MBEDTLS_PSA_BUILTIN_ALG_ECDSA
+ecdsa_sign_hash:PSA_ERROR_NOT_SUPPORTED:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":0:PSA_SUCCESS
 
 sign_hash through transparent driver: error
-ecdsa_sign:PSA_ERROR_GENERIC_ERROR:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":0:PSA_ERROR_GENERIC_ERROR
+ecdsa_sign_hash:PSA_ERROR_GENERIC_ERROR:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":0:PSA_ERROR_GENERIC_ERROR
 
 sign_hash through transparent driver: fake
-ecdsa_sign:PSA_SUCCESS:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"000102030405060708090A0B0C0D0E0F":1:PSA_SUCCESS
+ecdsa_sign_hash:PSA_SUCCESS:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"000102030405060708090A0B0C0D0E0F":1:PSA_SUCCESS
 
 verify_hash using private key through transparent driver: calculate in driver
-ecdsa_verify:PSA_SUCCESS:0:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_SUCCESS
+ecdsa_verify_hash:PSA_SUCCESS:0:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_SUCCESS
 
 verify_hash using private key through transparent driver: fallback
-ecdsa_verify:PSA_ERROR_NOT_SUPPORTED:0:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_SUCCESS
+depends_on:MBEDTLS_PSA_BUILTIN_ALG_ECDSA
+ecdsa_verify_hash:PSA_ERROR_NOT_SUPPORTED:0:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_SUCCESS
 
 verify_hash using private key through transparent driver: error
-ecdsa_verify:PSA_ERROR_GENERIC_ERROR:0:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_GENERIC_ERROR
+ecdsa_verify_hash:PSA_ERROR_GENERIC_ERROR:0:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_GENERIC_ERROR
 
 verify_hash using public key through transparent driver: calculate in driver
-ecdsa_verify:PSA_SUCCESS:1:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_SUCCESS
+ecdsa_verify_hash:PSA_SUCCESS:1:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_SUCCESS
 
 verify_hash using public key through transparent driver: fallback
-ecdsa_verify:PSA_ERROR_NOT_SUPPORTED:1:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_SUCCESS
+depends_on:MBEDTLS_PSA_BUILTIN_ALG_ECDSA
+ecdsa_verify_hash:PSA_ERROR_NOT_SUPPORTED:1:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_SUCCESS
 
 verify_hash using public key through transparent driver: error
-ecdsa_verify:PSA_ERROR_GENERIC_ERROR:1:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_GENERIC_ERROR
+ecdsa_verify_hash:PSA_ERROR_GENERIC_ERROR:1:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_GENERIC_ERROR
+
+sign_message through transparent driver: calculate in driver
+ecdsa_sign_message:PSA_SUCCESS:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"616263":"36e5b5a7da1c9c265dc447de3a5a704fcb8c03f7a3749dde48d84c9bf736fc1ed48d8b3660e7d3cbc6b1870730b7ce2a043f69e37ccb340b98d1e65184e03548":0:PSA_SUCCESS
+
+sign_message through transparent driver: fallback
+depends_on:MBEDTLS_PSA_BUILTIN_ALG_ECDSA
+ecdsa_sign_message:PSA_ERROR_NOT_SUPPORTED:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"616263":"36e5b5a7da1c9c265dc447de3a5a704fcb8c03f7a3749dde48d84c9bf736fc1ed48d8b3660e7d3cbc6b1870730b7ce2a043f69e37ccb340b98d1e65184e03548":0:PSA_SUCCESS
+
+sign_message through transparent driver: error
+ecdsa_sign_message:PSA_ERROR_GENERIC_ERROR:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"616263":"36e5b5a7da1c9c265dc447de3a5a704fcb8c03f7a3749dde48d84c9bf736fc1ed48d8b3660e7d3cbc6b1870730b7ce2a043f69e37ccb340b98d1e65184e03548":0:PSA_ERROR_GENERIC_ERROR
+
+sign_message through transparent driver: fake
+ecdsa_sign_message:PSA_SUCCESS:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"616263":"000102030405060708090A0B0C0D0E0F":1:PSA_SUCCESS
+
+verify_message using private key through transparent driver: calculate in driver
+ecdsa_verify_message:PSA_SUCCESS:0:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"616263":"36e5b5a7da1c9c265dc447de3a5a704fcb8c03f7a3749dde48d84c9bf736fc1ed48d8b3660e7d3cbc6b1870730b7ce2a043f69e37ccb340b98d1e65184e03548":PSA_SUCCESS
+
+verify_message using private key through transparent driver: fallback
+depends_on:MBEDTLS_PSA_BUILTIN_ALG_ECDSA
+ecdsa_verify_message:PSA_ERROR_NOT_SUPPORTED:0:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"616263":"36e5b5a7da1c9c265dc447de3a5a704fcb8c03f7a3749dde48d84c9bf736fc1ed48d8b3660e7d3cbc6b1870730b7ce2a043f69e37ccb340b98d1e65184e03548":PSA_SUCCESS
+
+verify_message using private key through transparent driver: error
+ecdsa_verify_message:PSA_ERROR_GENERIC_ERROR:0:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"616263":"36e5b5a7da1c9c265dc447de3a5a704fcb8c03f7a3749dde48d84c9bf736fc1ed48d8b3660e7d3cbc6b1870730b7ce2a043f69e37ccb340b98d1e65184e03548":PSA_ERROR_GENERIC_ERROR
+
+verify_message using public key through transparent driver: calculate in driver
+ecdsa_verify_message:PSA_SUCCESS:1:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":"616263":"36e5b5a7da1c9c265dc447de3a5a704fcb8c03f7a3749dde48d84c9bf736fc1ed48d8b3660e7d3cbc6b1870730b7ce2a043f69e37ccb340b98d1e65184e03548":PSA_SUCCESS
+
+verify_message using public key through transparent driver: fallback
+depends_on:MBEDTLS_PSA_BUILTIN_ALG_ECDSA
+ecdsa_verify_message:PSA_ERROR_NOT_SUPPORTED:1:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":"616263":"36e5b5a7da1c9c265dc447de3a5a704fcb8c03f7a3749dde48d84c9bf736fc1ed48d8b3660e7d3cbc6b1870730b7ce2a043f69e37ccb340b98d1e65184e03548":PSA_SUCCESS
+
+verify_message using public key through transparent driver: error
+ecdsa_verify_message:PSA_ERROR_GENERIC_ERROR:1:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":"616263":"36e5b5a7da1c9c265dc447de3a5a704fcb8c03f7a3749dde48d84c9bf736fc1ed48d8b3660e7d3cbc6b1870730b7ce2a043f69e37ccb340b98d1e65184e03548":PSA_ERROR_GENERIC_ERROR
 
 generate_key through transparent driver: fake
 generate_key:PSA_SUCCESS:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_SUCCESS
@@ -35,153 +71,370 @@
 generate_key:PSA_SUCCESS:"":PSA_SUCCESS
 
 generate_key through transparent driver: fallback
+depends_on:MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR
 generate_key:PSA_ERROR_NOT_SUPPORTED:"":PSA_SUCCESS
 
+generate_key through transparent driver: fallback not available
+depends_on:!MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR
+generate_key:PSA_ERROR_NOT_SUPPORTED:"":PSA_ERROR_NOT_SUPPORTED
+
 generate_key through transparent driver: error
 generate_key:PSA_ERROR_GENERIC_ERROR:"":PSA_ERROR_GENERIC_ERROR
 
 validate key through transparent driver: good private key
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_256
 validate_key:PSA_SUCCESS:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_SUCCESS
 
 validate key through transparent driver: good public key
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_256
 validate_key:PSA_SUCCESS:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_SUCCESS
 
 validate key through transparent driver: fallback private key
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256
 validate_key:PSA_ERROR_NOT_SUPPORTED:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_SUCCESS
 
 validate key through transparent driver: fallback public key
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256
 validate_key:PSA_ERROR_NOT_SUPPORTED:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_SUCCESS
 
 validate key through transparent driver: error
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
 validate_key:PSA_ERROR_GENERIC_ERROR:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ERROR_GENERIC_ERROR
 
 export_key private to public through driver: fake
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_256
 export_key:PSA_SUCCESS:"0102030405":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"":PSA_SUCCESS
 
 export_key private to public through driver: in-driver
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_256
 export_key:PSA_SUCCESS:"":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_SUCCESS
 
 export_key private to public through driver: fallback
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256
 export_key:PSA_ERROR_NOT_SUPPORTED:"":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_SUCCESS
 
 export_key private to public through driver: error
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_256
 export_key:PSA_ERROR_GENERIC_ERROR:"":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"":PSA_ERROR_GENERIC_ERROR
 
-PSA symmetric encrypt: AES-CTR, 16 bytes, good
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":0:PSA_SUCCESS:PSA_SUCCESS
+PSA symmetric encrypt validation: AES-CTR, 16 bytes, good
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_validation:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a"
 
-PSA symmetric encrypt: AES-CTR, 15 bytes, good
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"8f9408fe80a81d3e813da3c7b0b2bd":0:PSA_SUCCESS:PSA_SUCCESS
+PSA symmetric encrypt validation: AES-CTR, 15 bytes, good
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_validation:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e11739317"
 
-PSA symmetric encrypt: AES-CTR, 16 bytes, fallback
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":0:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS
+PSA symmetric encrypt validation: AES-CTR, 16 bytes, fallback
+depends_on:MBEDTLS_PSA_BUILTIN_ALG_CTR:MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES
+cipher_encrypt_validation:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a"
 
-PSA symmetric encrypt: AES-CTR, 15 bytes, fallback
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"8f9408fe80a81d3e813da3c7b0b2bd":0:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS
+PSA symmetric encrypt validation: AES-CTR, 15 bytes, fallback
+depends_on:MBEDTLS_PSA_BUILTIN_ALG_CTR:MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES
+cipher_encrypt_validation:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e11739317"
 
-PSA symmetric encrypt: AES-CTR, 16 bytes, fake
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"d07a6a6e2687feb2":1:PSA_SUCCESS:PSA_SUCCESS
+PSA symmetric encrypt multipart: AES-CTR, 16 bytes, good
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"8f9408fe80a81d3e813da3c7b0b2bd32":0:PSA_SUCCESS:PSA_SUCCESS
 
-PSA symmetric encrypt: AES-CTR, 15 bytes, fake
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"d07a6a6e2687feb2":1:PSA_SUCCESS:PSA_SUCCESS
+PSA symmetric encrypt multipart: AES-CTR, 15 bytes, good
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":15:15:0:"8f9408fe80a81d3e813da3c7b0b2bd":0:PSA_SUCCESS:PSA_SUCCESS
+
+PSA symmetric encrypt multipart: AES-CTR, 16 bytes, fallback
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_BUILTIN_CIPHER
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"8f9408fe80a81d3e813da3c7b0b2bd32":0:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS
+
+PSA symmetric encrypt multipart: AES-CTR, 15 bytes, fallback
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_BUILTIN_CIPHER
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":15:15:0:"8f9408fe80a81d3e813da3c7b0b2bd":0:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS
+
+PSA symmetric encrypt multipart: AES-CTR, 16 bytes, fake
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:8:0:"d07a6a6e2687feb2":1:PSA_SUCCESS:PSA_SUCCESS
+
+PSA symmetric encrypt multipart: AES-CTR, 15 bytes, fake
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":15:8:0:"d07a6a6e2687feb2":1:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric decrypt: AES-CTR, 16 bytes, good
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric decrypt: AES-CTR, 16 bytes, fallback
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR
+depends_on:MBEDTLS_PSA_BUILTIN_ALG_CTR:MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES
 cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":0:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS
 
 PSA symmetric decrypt: AES-CTR, 16 bytes, fake
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"d07a6a6e2687feb2":1:PSA_SUCCESS:PSA_SUCCESS
 
+PSA symmetric decrypt multipart: AES-CTR, 16 bytes, good
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":16:16:0:"dd3b5e5319b7591daab1e1a92687feb2":0:PSA_SUCCESS:PSA_SUCCESS
+
+PSA symmetric decrypt multipart: AES-CTR, 16 bytes, fallback
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_BUILTIN_CIPHER
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":16:16:0:"dd3b5e5319b7591daab1e1a92687feb2":0:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS
+
+PSA symmetric decrypt multipart: AES-CTR, 16 bytes, fake
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":16:8:0:"d07a6a6e2687feb2":1:PSA_SUCCESS:PSA_SUCCESS
+
 PSA symmetric encryption multipart: AES-CTR, 11+5 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":11:11:5:"8f9408fe80a81d3e813da3c7b0b2bd32"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":11:11:5:"8f9408fe80a81d3e813da3c7b0b2bd32":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CTR, 16+16 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CTR, 12+20 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":12:12:20:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":12:12:20:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CTR, 20+12 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":20:20:12:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":20:20:12:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CTR, 12+10 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597":12:12:10:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7b"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597":12:12:10:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7b":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CTR, 0+15 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":0:0:15:"8f9408fe80a81d3e813da3c7b0b2bd"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":0:0:15:"8f9408fe80a81d3e813da3c7b0b2bd":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CTR, 15+0 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":15:15:0:"8f9408fe80a81d3e813da3c7b0b2bd"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":15:15:0:"8f9408fe80a81d3e813da3c7b0b2bd":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CTR, 0+16 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":0:0:16:"8f9408fe80a81d3e813da3c7b0b2bd32"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":0:0:16:"8f9408fe80a81d3e813da3c7b0b2bd32":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric encryption multipart: AES-CTR, 16+0 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"8f9408fe80a81d3e813da3c7b0b2bd32"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"8f9408fe80a81d3e813da3c7b0b2bd32":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 11+5 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":11:11:5:"8f9408fe80a81d3e813da3c7b0b2bd32"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":11:11:5:"8f9408fe80a81d3e813da3c7b0b2bd32":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 16+16 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 12+20 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":12:12:20:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":12:12:20:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 20+12 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":20:20:12:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":20:20:12:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 12+10 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597":12:12:10:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7b"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597":12:12:10:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7b":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 0+15 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":0:0:15:"8f9408fe80a81d3e813da3c7b0b2bd"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":0:0:15:"8f9408fe80a81d3e813da3c7b0b2bd":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 15+0 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":15:15:0:"8f9408fe80a81d3e813da3c7b0b2bd"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":15:15:0:"8f9408fe80a81d3e813da3c7b0b2bd":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 0+16 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":0:0:16:"8f9408fe80a81d3e813da3c7b0b2bd32"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":0:0:16:"8f9408fe80a81d3e813da3c7b0b2bd32":0:PSA_SUCCESS:PSA_SUCCESS
 
 PSA symmetric decryption multipart: AES-CTR, 16+0 bytes
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"8f9408fe80a81d3e813da3c7b0b2bd32"
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"8f9408fe80a81d3e813da3c7b0b2bd32":0:PSA_SUCCESS:PSA_SUCCESS
 
 Cipher driver: negative testing on all entry points
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 cipher_entry_points:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a"
+
+PSA AEAD encrypt: AES-CCM, 24 bytes
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9":PSA_SUCCESS
+
+PSA AEAD encrypt: AES-CCM, 24 bytes, fallback
+depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9":PSA_ERROR_NOT_SUPPORTED
+
+PSA AEAD encrypt: AES-CCM, 24 bytes, INSUFFICIENT_MEMORY
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9":PSA_ERROR_INSUFFICIENT_MEMORY
+
+PSA AEAD encrypt, AES-GCM, 128 bytes #1
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":PSA_SUCCESS
+
+PSA AEAD encrypt, AES-GCM, 128 bytes #1, fallback
+depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+aead_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":PSA_ERROR_NOT_SUPPORTED
+
+PSA AEAD encrypt, AES-GCM, 128 bytes #1, INSUFFICIENT_MEMORY
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":PSA_ERROR_INSUFFICIENT_MEMORY
+
+PSA AEAD decrypt: AES-CCM, 39 bytes
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CCM:"00412B4EA9CDBE3C9696766CFA":"0BE1A88BACE018B1":"4CB97F86A2A4689A877947AB8091EF5386A6FFBDD080F8120333D1FCB691F3406CBF531F83A4D8":"08E8CF97D820EA258460E96AD9CF5289054D895CEAC47C":PSA_SUCCESS
+
+PSA AEAD decrypt: AES-CCM, 39 bytes, fallback
+depends_on:MBEDTLS_AES_C:MBEDTLS_CCM_C
+aead_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CCM:"00412B4EA9CDBE3C9696766CFA":"0BE1A88BACE018B1":"4CB97F86A2A4689A877947AB8091EF5386A6FFBDD080F8120333D1FCB691F3406CBF531F83A4D8":"08E8CF97D820EA258460E96AD9CF5289054D895CEAC47C":PSA_ERROR_NOT_SUPPORTED
+
+PSA AEAD decrypt: AES-CCM, 39 bytes, INSUFFICIENT_MEMORY
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CCM:"00412B4EA9CDBE3C9696766CFA":"0BE1A88BACE018B1":"4CB97F86A2A4689A877947AB8091EF5386A6FFBDD080F8120333D1FCB691F3406CBF531F83A4D8":"08E8CF97D820EA258460E96AD9CF5289054D895CEAC47C":PSA_ERROR_INSUFFICIENT_MEMORY
+
+PSA AEAD decrypt, AES-GCM, 144 bytes #1
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_SUCCESS
+
+PSA AEAD decrypt, AES-GCM, 144 bytes #1, fallback
+depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_ERROR_NOT_SUPPORTED
+
+PSA AEAD decrypt, AES-GCM, 144 bytes #1, INSUFFICIENT_MEMORY
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":PSA_ERROR_INSUFFICIENT_MEMORY
+
+PSA MAC sign, through driver: HMAC-SHA-224
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC:MBEDTLS_PSA_ACCEL_ALG_HMAC
+mac_sign:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_224):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22":PSA_SUCCESS
+
+PSA MAC sign, fallback: HMAC-SHA-224
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC:MBEDTLS_PSA_BUILTIN_ALG_HMAC
+mac_sign:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_224):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22":PSA_ERROR_NOT_SUPPORTED
+
+PSA MAC sign, driver reports error: RFC4231 Test case 1 - HMAC-SHA-224
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
+mac_sign:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_224):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22":PSA_ERROR_GENERIC_ERROR
+
+PSA MAC sign, through driver: CMAC-AES-128
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_ACCEL_ALG_CMAC
+mac_sign:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_CMAC:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827":PSA_SUCCESS
+
+PSA MAC sign, fallback: CMAC-AES-128
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_BUILTIN_ALG_CMAC
+mac_sign:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_CMAC:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827":PSA_ERROR_NOT_SUPPORTED
+
+PSA MAC sign, driver reports error: CMAC-AES-128
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
+mac_sign:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_CMAC:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827":PSA_ERROR_GENERIC_ERROR
+
+PSA MAC verify, through driver: HMAC-SHA-224
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC:MBEDTLS_PSA_ACCEL_ALG_HMAC
+mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_224):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22":PSA_SUCCESS
+
+PSA MAC verify, fallback: HMAC-SHA-224
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC:MBEDTLS_PSA_BUILTIN_ALG_HMAC
+mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_224):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22":PSA_ERROR_NOT_SUPPORTED
+
+PSA MAC verify, driver reports error: RFC4231 Test case 1 - HMAC-SHA-224
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
+mac_verify:PSA_KEY_TYPE_HMAC:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ALG_HMAC(PSA_ALG_SHA_224):"4869205468657265":"896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22":PSA_ERROR_GENERIC_ERROR
+
+PSA MAC verify, through driver: CMAC-AES-128
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_ACCEL_ALG_CMAC
+mac_verify:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_CMAC:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827":PSA_SUCCESS
+
+PSA MAC verify, fallback: CMAC-AES-128
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_BUILTIN_ALG_CMAC
+mac_verify:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_CMAC:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827":PSA_ERROR_NOT_SUPPORTED
+
+PSA MAC verify, driver reports error: CMAC-AES-128
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
+mac_verify:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":PSA_ALG_CMAC:"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411":"dfa66747de9ae63030ca32611497c827":PSA_ERROR_GENERIC_ERROR
+
+PSA opaque driver builtin key export: AES
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+builtin_key_export:MBEDTLS_PSA_KEY_ID_BUILTIN_MIN:PSA_KEY_TYPE_AES:128:PSA_ALG_CTR:"3677397A24432646294A404E63526655":PSA_SUCCESS
+
+PSA opaque driver builtin key export: AES (registered to ID_MAX-1)
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+builtin_key_export:MBEDTLS_PSA_KEY_ID_BUILTIN_MAX - 1:PSA_KEY_TYPE_AES:128:PSA_ALG_CTR:"3677397A24432646294A404E63526655":PSA_SUCCESS
+
+PSA opaque driver builtin key export: AES (registered to ID_MAX)
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+builtin_key_export:MBEDTLS_PSA_KEY_ID_BUILTIN_MAX:PSA_KEY_TYPE_AES:128:PSA_ALG_CTR:"3677397A24432646294A404E63526655":PSA_SUCCESS
+
+PSA opaque driver builtin key export: key ID out of range (ID_MIN - 1)
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+builtin_key_export:MBEDTLS_PSA_KEY_ID_BUILTIN_MIN - 1:PSA_KEY_TYPE_AES:128:PSA_ALG_CTR:"3677397A24432646294A404E63526655":PSA_ERROR_INVALID_HANDLE
+
+PSA opaque driver builtin key export: key ID out of range (ID_MAX + 1)
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+builtin_key_export:MBEDTLS_PSA_KEY_ID_BUILTIN_MAX + 1:PSA_KEY_TYPE_AES:128:PSA_ALG_CTR:"3677397A24432646294A404E63526655":PSA_ERROR_INVALID_HANDLE
+
+PSA opaque driver builtin key export: secp256r1
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+builtin_key_export:MBEDTLS_PSA_KEY_ID_BUILTIN_MIN + 1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):"dc7d9d26d67a4f632c34c2dc0b6986183882c206df04cdb7d69aabe28be4f81a":PSA_SUCCESS
+
+PSA opaque driver builtin pubkey export: secp256r1
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+builtin_pubkey_export:MBEDTLS_PSA_KEY_ID_BUILTIN_MIN + 1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):"0485f64d89f00be66c88dd937efd6d7c445648dcb701150b8a9509295850f41c1931e571fb8f8c78317a20b380e866584bbc2516c3d2702d792f131a922095fd6c":PSA_SUCCESS
+
+PSA opaque driver builtin pubkey export: not a public key
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+builtin_pubkey_export:MBEDTLS_PSA_KEY_ID_BUILTIN_MIN:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):"0485f64d89f00be66c88dd937efd6d7c445648dcb701150b8a9509295850f41c1931e571fb8f8c78317a20b380e866584bbc2516c3d2702d792f131a922095fd6c":PSA_ERROR_INVALID_ARGUMENT
+
+Hash compute: SHA-256, computed by the driver
+depends_on:MBEDTLS_PSA_ACCEL_ALG_SHA_256
+hash_compute:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803":PSA_SUCCESS:PSA_SUCCESS
+
+Hash compute: SHA-256, fallback
+depends_on:MBEDTLS_PSA_BUILTIN_ALG_SHA_256
+hash_compute:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803":PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS
+
+Hash compute: SHA-256, no fallback
+depends_on:!MBEDTLS_PSA_BUILTIN_ALG_SHA_256
+hash_compute:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803":PSA_ERROR_NOT_SUPPORTED:PSA_ERROR_NOT_SUPPORTED
+
+Hash compute: SHA-256, INSUFFICIENT_MEMORY
+hash_compute:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803":PSA_ERROR_INSUFFICIENT_MEMORY:PSA_ERROR_INSUFFICIENT_MEMORY
+
+Hash multi-part setup: SHA-256, computed by the driver
+depends_on:MBEDTLS_PSA_ACCEL_ALG_SHA_256
+hash_multipart_setup:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803":PSA_SUCCESS:PSA_SUCCESS
+
+Hash multi-part setup: SHA-256, fallback
+depends_on:MBEDTLS_PSA_BUILTIN_ALG_SHA_256
+hash_multipart_setup:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803":PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS
+
+Hash multi-part setup: SHA-256, no fallback
+depends_on:!MBEDTLS_PSA_BUILTIN_ALG_SHA_256
+hash_multipart_setup:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803":PSA_ERROR_NOT_SUPPORTED:PSA_ERROR_NOT_SUPPORTED
+
+Hash multi-part setup: SHA-256, INSUFFICIENT_MEMORY
+hash_multipart_setup:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803":PSA_ERROR_INSUFFICIENT_MEMORY:PSA_ERROR_INSUFFICIENT_MEMORY
+
+Hash multi-part update: SHA-256, update successful
+depends_on:MBEDTLS_PSA_ACCEL_ALG_SHA_256
+hash_multipart_update:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803":PSA_SUCCESS
+
+Hash multi-part update: SHA-256, update failure
+depends_on:MBEDTLS_PSA_ACCEL_ALG_SHA_256
+hash_multipart_update:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803":PSA_ERROR_NOT_SUPPORTED
+
+Hash multi-part finish: SHA-256, finish successful
+depends_on:MBEDTLS_PSA_ACCEL_ALG_SHA_256
+hash_multipart_update:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803":PSA_SUCCESS
+
+Hash multi-part finish: SHA-256, finish failure
+depends_on:MBEDTLS_PSA_ACCEL_ALG_SHA_256
+hash_multipart_update:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803":PSA_ERROR_NOT_SUPPORTED
+
+Hash clone: SHA-256, clone successful
+depends_on:MBEDTLS_PSA_ACCEL_ALG_SHA_256
+hash_clone:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803":PSA_SUCCESS
+
+Hash clone: SHA-256, clone failure
+depends_on:MBEDTLS_PSA_ACCEL_ALG_SHA_256
+hash_clone:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803":PSA_ERROR_NOT_SUPPORTED
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_driver_wrappers.function
index 6d20eff..38c154e 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_driver_wrappers.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_driver_wrappers.function
@@ -1,6 +1,4 @@
 /* BEGIN_HEADER */
-#include "test/psa_crypto_helpers.h"
-
 #include "test/drivers/test_driver.h"
 /* END_HEADER */
 
@@ -9,13 +7,13 @@
  * END_DEPENDENCIES
  */
 
-/* BEGIN_CASE depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C */
-void ecdsa_sign( int force_status_arg,
-                 data_t *key_input,
-                 data_t *data_input,
-                 data_t *expected_output,
-                 int fake_output,
-                 int expected_status_arg )
+/* BEGIN_CASE depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256 */
+void ecdsa_sign_hash( int force_status_arg,
+                      data_t *key_input,
+                      data_t *data_input,
+                      data_t *expected_output,
+                      int fake_output,
+                      int expected_status_arg )
 {
     psa_status_t force_status = force_status_arg;
     psa_status_t expected_status = expected_status_arg;
@@ -25,22 +23,25 @@
     uint8_t signature[64];
     size_t signature_length = 0xdeadbeef;
     psa_status_t actual_status;
-    test_driver_signature_sign_hooks = test_driver_signature_hooks_init();
+    mbedtls_test_driver_signature_sign_hooks =
+        mbedtls_test_driver_signature_hooks_init();
 
     PSA_ASSERT( psa_crypto_init( ) );
     psa_set_key_type( &attributes,
-                      PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_CURVE_SECP_R1 ) );
+                      PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ) );
     psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH );
     psa_set_key_algorithm( &attributes, alg );
     psa_import_key( &attributes,
                     key_input->x, key_input->len,
                     &key );
 
-    test_driver_signature_sign_hooks.forced_status = force_status;
+    mbedtls_test_driver_signature_sign_hooks.forced_status = force_status;
     if( fake_output == 1 )
     {
-        test_driver_signature_sign_hooks.forced_output = expected_output->x;
-        test_driver_signature_sign_hooks.forced_output_length = expected_output->len;
+        mbedtls_test_driver_signature_sign_hooks.forced_output =
+            expected_output->x;
+        mbedtls_test_driver_signature_sign_hooks.forced_output_length =
+            expected_output->len;
     }
 
     actual_status = psa_sign_hash( key, alg,
@@ -53,37 +54,39 @@
         ASSERT_COMPARE( signature, signature_length,
                         expected_output->x, expected_output->len );
     }
-    TEST_EQUAL( test_driver_signature_sign_hooks.hits, 1 );
+    TEST_EQUAL( mbedtls_test_driver_signature_sign_hooks.hits, 1 );
 
 exit:
     psa_reset_key_attributes( &attributes );
     psa_destroy_key( key );
     PSA_DONE( );
-    test_driver_signature_sign_hooks = test_driver_signature_hooks_init();
+    mbedtls_test_driver_signature_sign_hooks =
+        mbedtls_test_driver_signature_hooks_init();
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C */
-void ecdsa_verify( int force_status_arg,
-                   int register_public_key,
-                   data_t *key_input,
-                   data_t *data_input,
-                   data_t *signature_input,
-                   int expected_status_arg )
+/* BEGIN_CASE depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256 */
+void ecdsa_verify_hash( int force_status_arg,
+                        int register_public_key,
+                        data_t *key_input,
+                        data_t *data_input,
+                        data_t *signature_input,
+                        int expected_status_arg )
 {
     psa_status_t force_status = force_status_arg;
     psa_status_t expected_status = expected_status_arg;
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_algorithm_t alg = PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 );
+    psa_algorithm_t alg = PSA_ALG_ECDSA( PSA_ALG_SHA_256 );
     psa_status_t actual_status;
-    test_driver_signature_verify_hooks = test_driver_signature_hooks_init();
+    mbedtls_test_driver_signature_verify_hooks =
+        mbedtls_test_driver_signature_hooks_init();
 
     PSA_ASSERT( psa_crypto_init( ) );
     if( register_public_key )
     {
         psa_set_key_type( &attributes,
-                      PSA_KEY_TYPE_ECC_PUBLIC_KEY( PSA_ECC_CURVE_SECP_R1 ) );
+                      PSA_KEY_TYPE_ECC_PUBLIC_KEY( PSA_ECC_FAMILY_SECP_R1 ) );
         psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH );
         psa_set_key_algorithm( &attributes, alg );
         psa_import_key( &attributes,
@@ -93,7 +96,7 @@
     else
     {
         psa_set_key_type( &attributes,
-                      PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_CURVE_SECP_R1 ) );
+                      PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ) );
         psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH );
         psa_set_key_algorithm( &attributes, alg );
         psa_import_key( &attributes,
@@ -101,23 +104,142 @@
                         &key );
     }
 
-    test_driver_signature_verify_hooks.forced_status = force_status;
+    mbedtls_test_driver_signature_verify_hooks.forced_status = force_status;
 
     actual_status = psa_verify_hash( key, alg,
                                      data_input->x, data_input->len,
                                      signature_input->x, signature_input->len );
     TEST_EQUAL( actual_status, expected_status );
-    TEST_EQUAL( test_driver_signature_verify_hooks.hits, 1 );
+    TEST_EQUAL( mbedtls_test_driver_signature_verify_hooks.hits, 1 );
 
 exit:
     psa_reset_key_attributes( &attributes );
     psa_destroy_key( key );
     PSA_DONE( );
-    test_driver_signature_verify_hooks = test_driver_signature_hooks_init();
+    mbedtls_test_driver_signature_verify_hooks =
+        mbedtls_test_driver_signature_hooks_init();
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+/* BEGIN_CASE depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256 */
+void ecdsa_sign_message( int force_status_arg,
+                         data_t *key_input,
+                         data_t *data_input,
+                         data_t *expected_output,
+                         int fake_output,
+                         int expected_status_arg )
+{
+    psa_status_t force_status = force_status_arg;
+    psa_status_t expected_status = expected_status_arg;
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_algorithm_t alg = PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 );
+    uint8_t signature[64];
+    size_t signature_length = 0xdeadbeef;
+    psa_status_t actual_status;
+    mbedtls_test_driver_signature_sign_hooks =
+        mbedtls_test_driver_signature_hooks_init();
+
+    PSA_ASSERT( psa_crypto_init( ) );
+    psa_set_key_type( &attributes,
+                      PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_MESSAGE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_import_key( &attributes,
+                    key_input->x, key_input->len,
+                    &key );
+
+    mbedtls_test_driver_signature_sign_hooks.forced_status = force_status;
+    if( fake_output == 1 )
+    {
+        mbedtls_test_driver_signature_sign_hooks.forced_output =
+            expected_output->x;
+        mbedtls_test_driver_signature_sign_hooks.forced_output_length =
+            expected_output->len;
+    }
+
+    actual_status = psa_sign_message( key, alg,
+                                      data_input->x, data_input->len,
+                                      signature, sizeof( signature ),
+                                      &signature_length );
+    TEST_EQUAL( actual_status, expected_status );
+    if( expected_status == PSA_SUCCESS )
+    {
+        ASSERT_COMPARE( signature, signature_length,
+                        expected_output->x, expected_output->len );
+    }
+    /* In the builtin algorithm the driver is called twice. */
+    TEST_EQUAL( mbedtls_test_driver_signature_sign_hooks.hits,
+                force_status == PSA_ERROR_NOT_SUPPORTED ? 2 : 1 );
+
+exit:
+    psa_reset_key_attributes( &attributes );
+    psa_destroy_key( key );
+    PSA_DONE( );
+    mbedtls_test_driver_signature_sign_hooks =
+        mbedtls_test_driver_signature_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256 */
+void ecdsa_verify_message( int force_status_arg,
+                           int register_public_key,
+                           data_t *key_input,
+                           data_t *data_input,
+                           data_t *signature_input,
+                           int expected_status_arg )
+{
+    psa_status_t force_status = force_status_arg;
+    psa_status_t expected_status = expected_status_arg;
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_algorithm_t alg = PSA_ALG_ECDSA( PSA_ALG_SHA_256 );
+    psa_status_t actual_status;
+    mbedtls_test_driver_signature_verify_hooks =
+        mbedtls_test_driver_signature_hooks_init();
+
+    PSA_ASSERT( psa_crypto_init( ) );
+    if( register_public_key )
+    {
+        psa_set_key_type( &attributes,
+                      PSA_KEY_TYPE_ECC_PUBLIC_KEY( PSA_ECC_FAMILY_SECP_R1 ) );
+        psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_MESSAGE );
+        psa_set_key_algorithm( &attributes, alg );
+        psa_import_key( &attributes,
+                        key_input->x, key_input->len,
+                        &key );
+    }
+    else
+    {
+        psa_set_key_type( &attributes,
+                      PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ) );
+        psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_MESSAGE );
+        psa_set_key_algorithm( &attributes, alg );
+        psa_import_key( &attributes,
+                        key_input->x, key_input->len,
+                        &key );
+    }
+
+    mbedtls_test_driver_signature_verify_hooks.forced_status = force_status;
+
+    actual_status = psa_verify_message( key, alg,
+                                        data_input->x, data_input->len,
+                                        signature_input->x, signature_input->len );
+    TEST_EQUAL( actual_status, expected_status );
+    /* In the builtin algorithm the driver is called twice. */
+    TEST_EQUAL( mbedtls_test_driver_signature_verify_hooks.hits,
+                force_status == PSA_ERROR_NOT_SUPPORTED ? 2 : 1 );
+
+exit:
+    psa_reset_key_attributes( &attributes );
+    psa_destroy_key( key );
+    PSA_DONE( );
+    mbedtls_test_driver_signature_verify_hooks =
+        mbedtls_test_driver_signature_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ECC_SECP_R1_256 */
 void generate_key( int force_status_arg,
                    data_t *fake_output,
                    int expected_status_arg )
@@ -132,28 +254,33 @@
     psa_status_t actual_status;
     uint8_t actual_output[PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(256)] = {0};
     size_t actual_output_length;
-    test_driver_key_management_hooks = test_driver_key_management_hooks_init();
+    mbedtls_test_driver_key_management_hooks =
+        mbedtls_test_driver_key_management_hooks_init();
 
     psa_set_key_type( &attributes,
-                      PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_CURVE_SECP_R1 ) );
+                      PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ) );
     psa_set_key_bits( &attributes, 256 );
     psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT );
     psa_set_key_algorithm( &attributes, alg );
 
     if( fake_output->len > 0 )
     {
-        expected_output = test_driver_key_management_hooks.forced_output = fake_output->x;
-        expected_output_length = test_driver_key_management_hooks.forced_output_length =
+        expected_output =
+            mbedtls_test_driver_key_management_hooks.forced_output =
+            fake_output->x;
+
+        expected_output_length =
+            mbedtls_test_driver_key_management_hooks.forced_output_length =
             fake_output->len;
     }
 
-    test_driver_key_management_hooks.hits = 0;
-    test_driver_key_management_hooks.forced_status = force_status;
+    mbedtls_test_driver_key_management_hooks.hits = 0;
+    mbedtls_test_driver_key_management_hooks.forced_status = force_status;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
     actual_status = psa_generate_key( &attributes, &key );
-    TEST_EQUAL( test_driver_key_management_hooks.hits, 1 );
+    TEST_EQUAL( mbedtls_test_driver_key_management_hooks.hits, 1 );
     TEST_EQUAL( actual_status, expected_status );
 
     if( actual_status == PSA_SUCCESS )
@@ -180,11 +307,12 @@
     psa_reset_key_attributes( &attributes );
     psa_destroy_key( key );
     PSA_DONE( );
-    test_driver_key_management_hooks = test_driver_key_management_hooks_init();
+    mbedtls_test_driver_key_management_hooks =
+        mbedtls_test_driver_key_management_hooks_init();
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+/* BEGIN_CASE */
 void validate_key( int force_status_arg,
                    int key_type_arg,
                    data_t *key_input,
@@ -196,29 +324,31 @@
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_status_t actual_status;
-    test_driver_key_management_hooks = test_driver_key_management_hooks_init();
+    mbedtls_test_driver_key_management_hooks =
+        mbedtls_test_driver_key_management_hooks_init();
 
     psa_set_key_type( &attributes,
                       key_type );
     psa_set_key_bits( &attributes, 0 );
     psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT );
 
-    test_driver_key_management_hooks.forced_status = force_status;
+    mbedtls_test_driver_key_management_hooks.forced_status = force_status;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
     actual_status = psa_import_key( &attributes, key_input->x, key_input->len, &key );
-    TEST_EQUAL( test_driver_key_management_hooks.hits, 1 );
+    TEST_EQUAL( mbedtls_test_driver_key_management_hooks.hits, 1 );
     TEST_EQUAL( actual_status, expected_status );
 exit:
     psa_reset_key_attributes( &attributes );
     psa_destroy_key( key );
     PSA_DONE( );
-    test_driver_key_management_hooks = test_driver_key_management_hooks_init();
+    mbedtls_test_driver_key_management_hooks =
+        mbedtls_test_driver_key_management_hooks_init();
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+/* BEGIN_CASE */
 void export_key( int force_status_arg,
                  data_t *fake_output,
                  int key_in_type_arg,
@@ -238,7 +368,8 @@
     psa_status_t actual_status;
     uint8_t actual_output[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(256)] = {0};
     size_t actual_output_length;
-    test_driver_key_management_hooks = test_driver_key_management_hooks_init();
+    mbedtls_test_driver_key_management_hooks =
+        mbedtls_test_driver_key_management_hooks_init();
 
     psa_set_key_type( &attributes, input_key_type );
     psa_set_key_bits( &attributes, 256 );
@@ -249,8 +380,12 @@
 
     if( fake_output->len > 0 )
     {
-        expected_output_ptr = test_driver_key_management_hooks.forced_output = fake_output->x;
-        expected_output_length = test_driver_key_management_hooks.forced_output_length =
+        expected_output_ptr =
+            mbedtls_test_driver_key_management_hooks.forced_output =
+            fake_output->x;
+
+        expected_output_length =
+            mbedtls_test_driver_key_management_hooks.forced_output_length =
             fake_output->len;
     }
     else
@@ -259,8 +394,8 @@
         expected_output_length = expected_output->len;
     }
 
-    test_driver_key_management_hooks.hits = 0;
-    test_driver_key_management_hooks.forced_status = force_status;
+    mbedtls_test_driver_key_management_hooks.hits = 0;
+    mbedtls_test_driver_key_management_hooks.forced_status = force_status;
 
     if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( output_key_type ) )
         actual_status = psa_export_public_key( handle, actual_output, sizeof(actual_output), &actual_output_length );
@@ -270,7 +405,7 @@
 
     if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( output_key_type ) &&
         !PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( input_key_type ) )
-        TEST_EQUAL( test_driver_key_management_hooks.hits, 1 );
+        TEST_EQUAL( mbedtls_test_driver_key_management_hooks.hits, 1 );
 
     if( actual_status == PSA_SUCCESS )
     {
@@ -281,32 +416,139 @@
     psa_reset_key_attributes( &attributes );
     psa_destroy_key( handle );
     PSA_DONE( );
-    test_driver_key_management_hooks = test_driver_key_management_hooks_init();
+    mbedtls_test_driver_key_management_hooks =
+        mbedtls_test_driver_key_management_hooks_init();
 }
 /* END_CASE */
 
 /* BEGIN_CASE */
-void cipher_encrypt( int alg_arg, int key_type_arg,
-                     data_t *key_data, data_t *iv,
-                     data_t *input, data_t *expected_output,
-                     int mock_output_arg,
-                     int force_status_arg,
-                     int expected_status_arg )
+void cipher_encrypt_validation( int alg_arg,
+                                int key_type_arg,
+                                data_t *key_data,
+                                data_t *input )
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
-    psa_status_t status;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
+    size_t iv_size = PSA_CIPHER_IV_LENGTH ( key_type, alg );
+    unsigned char *output1 = NULL;
+    size_t output1_buffer_size = 0;
+    size_t output1_length = 0;
+    unsigned char *output2 = NULL;
+    size_t output2_buffer_size = 0;
+    size_t output2_length = 0;
+    size_t function_output_length = 0;
+    psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_test_driver_cipher_hooks = mbedtls_test_driver_cipher_hooks_init();
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    output1_buffer_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE( key_type, alg, input->len );
+    output2_buffer_size = PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, input->len ) +
+                          PSA_CIPHER_FINISH_OUTPUT_SIZE( key_type, alg );
+    ASSERT_ALLOC( output1, output1_buffer_size );
+    ASSERT_ALLOC( output2, output2_buffer_size );
+
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+
+    PSA_ASSERT( psa_cipher_encrypt( key, alg, input->x, input->len, output1,
+                                    output1_buffer_size, &output1_length ) );
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
+
+    PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
+
+    PSA_ASSERT( psa_cipher_set_iv( &operation, output1, iv_size ) );
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
+
+    PSA_ASSERT( psa_cipher_update( &operation,
+                                   input->x, input->len,
+                                   output2, output2_buffer_size,
+                                   &function_output_length ) );
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
+
+    output2_length += function_output_length;
+    PSA_ASSERT( psa_cipher_finish( &operation,
+                                   output2 + output2_length,
+                                   output2_buffer_size - output2_length,
+                                   &function_output_length ) );
+    /* Finish will have called abort as well, so expecting two hits here */
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 2 );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
+
+    output2_length += function_output_length;
+
+    PSA_ASSERT( psa_cipher_abort( &operation ) );
+    // driver function should've been called as part of the finish() core routine
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 0 );
+    ASSERT_COMPARE( output1 + iv_size, output1_length - iv_size,
+                    output2, output2_length );
+
+exit:
+    psa_cipher_abort( &operation );
+    mbedtls_free( output1 );
+    mbedtls_free( output2 );
+    psa_destroy_key( key );
+    PSA_DONE( );
+    mbedtls_test_driver_cipher_hooks = mbedtls_test_driver_cipher_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_encrypt_multipart( int alg_arg,
+                               int key_type_arg,
+                               data_t *key_data,
+                               data_t *iv,
+                               data_t *input,
+                               int first_part_size_arg,
+                               int output1_length_arg,
+                               int output2_length_arg,
+                               data_t *expected_output,
+                               int mock_output_arg,
+                               int force_status_arg,
+                               int expected_status_arg )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_status_t status;
     psa_status_t expected_status = expected_status_arg;
     psa_status_t force_status = force_status_arg;
+    size_t first_part_size = first_part_size_arg;
+    size_t output1_length = output1_length_arg;
+    size_t output2_length = output2_length_arg;
     unsigned char *output = NULL;
     size_t output_buffer_size = 0;
     size_t function_output_length = 0;
     size_t total_output_length = 0;
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
-    test_driver_cipher_hooks.forced_status = force_status;
+    mbedtls_test_driver_cipher_hooks = mbedtls_test_driver_cipher_hooks_init();
+    mbedtls_test_driver_cipher_hooks.forced_status = force_status;
+
+    /* Test operation initialization */
+    mbedtls_psa_cipher_operation_t mbedtls_operation =
+            MBEDTLS_PSA_CIPHER_OPERATION_INIT;
+
+    mbedtls_transparent_test_driver_cipher_operation_t tranparent_operation =
+            MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT;
+
+    mbedtls_opaque_test_driver_cipher_operation_t opaque_operation =
+            MBEDTLS_OPAQUE_TEST_DRIVER_CIPHER_OPERATION_INIT;
+
+    operation.ctx.mbedtls_ctx = mbedtls_operation;
+    operation.ctx.transparent_test_driver_ctx = tranparent_operation;
+    operation.ctx.opaque_test_driver_ctx = opaque_operation;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
@@ -318,53 +560,69 @@
                                 &key ) );
 
     PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    test_driver_cipher_hooks.hits = 0;
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
 
     PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) );
-    test_driver_cipher_hooks.hits = 0;
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
 
     output_buffer_size = ( (size_t) input->len +
-                           PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
+                           PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type ) );
     ASSERT_ALLOC( output, output_buffer_size );
 
     if( mock_output_arg )
     {
-        test_driver_cipher_hooks.forced_output = expected_output->x;
-        test_driver_cipher_hooks.forced_output_length = expected_output->len;
+        mbedtls_test_driver_cipher_hooks.forced_output = expected_output->x;
+        mbedtls_test_driver_cipher_hooks.forced_output_length = expected_output->len;
     }
 
-    PSA_ASSERT( psa_cipher_update( &operation,
-                                   input->x, input->len,
+    TEST_ASSERT( first_part_size <= input->len );
+    PSA_ASSERT( psa_cipher_update( &operation, input->x, first_part_size,
                                    output, output_buffer_size,
                                    &function_output_length ) );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) );
-    test_driver_cipher_hooks.hits = 0;
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
+
+    TEST_ASSERT( function_output_length == output1_length );
+    total_output_length += function_output_length;
+
+    if( first_part_size < input->len )
+    {
+        PSA_ASSERT( psa_cipher_update( &operation,
+                                       input->x + first_part_size,
+                                       input->len - first_part_size,
+                                       output + total_output_length,
+                                       output_buffer_size - total_output_length,
+                                       &function_output_length ) );
+        TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+        mbedtls_test_driver_cipher_hooks.hits = 0;
+
+        TEST_ASSERT( function_output_length == output2_length );
+        total_output_length += function_output_length;
+    }
 
     if( mock_output_arg )
     {
-        test_driver_cipher_hooks.forced_output = NULL;
-        test_driver_cipher_hooks.forced_output_length = 0;
+        mbedtls_test_driver_cipher_hooks.forced_output = NULL;
+        mbedtls_test_driver_cipher_hooks.forced_output_length = 0;
     }
 
-    total_output_length += function_output_length;
-    status = psa_cipher_finish( &operation,
-                                output + total_output_length,
-                                output_buffer_size - total_output_length,
-                                &function_output_length );
+    status =  psa_cipher_finish( &operation,
+                                 output + total_output_length,
+                                 output_buffer_size - total_output_length,
+                                 &function_output_length );
     /* Finish will have called abort as well, so expecting two hits here */
-    TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 2 : 0 ) );
-    test_driver_cipher_hooks.hits = 0;
-
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 2 : 0 ) );
+    mbedtls_test_driver_cipher_hooks.hits = 0 ;
     total_output_length += function_output_length;
-
     TEST_EQUAL( status, expected_status );
+
     if( expected_status == PSA_SUCCESS )
     {
         PSA_ASSERT( psa_cipher_abort( &operation ) );
-        // driver function should've been called as part of the finish() core routine
-        TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+        TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 0 );
+
         ASSERT_COMPARE( expected_output->x, expected_output->len,
                         output, total_output_length );
     }
@@ -374,21 +632,30 @@
     mbedtls_free( output );
     psa_destroy_key( key );
     PSA_DONE( );
-    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
+    mbedtls_test_driver_cipher_hooks = mbedtls_test_driver_cipher_hooks_init();
 }
 /* END_CASE */
 
 /* BEGIN_CASE */
-void cipher_encrypt_multipart( int alg_arg, int key_type_arg,
-                               data_t *key_data, data_t *iv,
+void cipher_decrypt_multipart( int alg_arg,
+                               int key_type_arg,
+                               data_t *key_data,
+                               data_t *iv,
                                data_t *input,
                                int first_part_size_arg,
-                               int output1_length_arg, int output2_length_arg,
-                               data_t *expected_output )
+                               int output1_length_arg,
+                               int output2_length_arg,
+                               data_t *expected_output,
+                               int mock_output_arg,
+                               int force_status_arg,
+                               int expected_status_arg )
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
+    psa_status_t status;
+    psa_status_t expected_status = expected_status_arg;
+    psa_status_t force_status = force_status_arg;
     size_t first_part_size = first_part_size_arg;
     size_t output1_length = output1_length_arg;
     size_t output2_length = output2_length_arg;
@@ -398,92 +665,22 @@
     size_t total_output_length = 0;
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
+    mbedtls_test_driver_cipher_hooks = mbedtls_test_driver_cipher_hooks_init();
+    mbedtls_test_driver_cipher_hooks.forced_status = force_status;
 
-    PSA_ASSERT( psa_crypto_init( ) );
+    /* Test operation initialization */
+    mbedtls_psa_cipher_operation_t mbedtls_operation =
+            MBEDTLS_PSA_CIPHER_OPERATION_INIT;
 
-    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT );
-    psa_set_key_algorithm( &attributes, alg );
-    psa_set_key_type( &attributes, key_type );
+    mbedtls_transparent_test_driver_cipher_operation_t tranparent_operation =
+            MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT;
 
-    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
-                                &key ) );
+    mbedtls_opaque_test_driver_cipher_operation_t opaque_operation =
+            MBEDTLS_OPAQUE_TEST_DRIVER_CIPHER_OPERATION_INIT;
 
-    PSA_ASSERT( psa_cipher_encrypt_setup( &operation, key, alg ) );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    test_driver_cipher_hooks.hits = 0;
-
-    PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    test_driver_cipher_hooks.hits = 0;
-
-    output_buffer_size = ( (size_t) input->len +
-                           PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
-    ASSERT_ALLOC( output, output_buffer_size );
-
-    TEST_ASSERT( first_part_size <= input->len );
-    PSA_ASSERT( psa_cipher_update( &operation, input->x, first_part_size,
-                                   output, output_buffer_size,
-                                   &function_output_length ) );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    test_driver_cipher_hooks.hits = 0;
-
-    TEST_ASSERT( function_output_length == output1_length );
-    total_output_length += function_output_length;
-    PSA_ASSERT( psa_cipher_update( &operation,
-                                   input->x + first_part_size,
-                                   input->len - first_part_size,
-                                   output + total_output_length,
-                                   output_buffer_size - total_output_length,
-                                   &function_output_length ) );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    test_driver_cipher_hooks.hits = 0;
-    TEST_ASSERT( function_output_length == output2_length );
-    total_output_length += function_output_length;
-    PSA_ASSERT( psa_cipher_finish( &operation,
-                                   output + total_output_length,
-                                   output_buffer_size - total_output_length,
-                                   &function_output_length ) );
-    /* Finish will have called abort as well, so expecting two hits here */
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 2 );
-    test_driver_cipher_hooks.hits = 0 ;
-    total_output_length += function_output_length;
-    PSA_ASSERT( psa_cipher_abort( &operation ) );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
-
-    ASSERT_COMPARE( expected_output->x, expected_output->len,
-                    output, total_output_length );
-
-exit:
-    psa_cipher_abort( &operation );
-    mbedtls_free( output );
-    psa_destroy_key( key );
-    PSA_DONE( );
-    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void cipher_decrypt_multipart( int alg_arg, int key_type_arg,
-                               data_t *key_data, data_t *iv,
-                               data_t *input,
-                               int first_part_size_arg,
-                               int output1_length_arg, int output2_length_arg,
-                               data_t *expected_output )
-{
-    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
-    psa_key_type_t key_type = key_type_arg;
-    psa_algorithm_t alg = alg_arg;
-    size_t first_part_size = first_part_size_arg;
-    size_t output1_length = output1_length_arg;
-    size_t output2_length = output2_length_arg;
-    unsigned char *output = NULL;
-    size_t output_buffer_size = 0;
-    size_t function_output_length = 0;
-    size_t total_output_length = 0;
-    psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
+    operation.ctx.mbedtls_ctx = mbedtls_operation;
+    operation.ctx.transparent_test_driver_ctx = tranparent_operation;
+    operation.ctx.opaque_test_driver_ctx = opaque_operation;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
@@ -495,65 +692,90 @@
                                 &key ) );
 
     PSA_ASSERT( psa_cipher_decrypt_setup( &operation, key, alg ) );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    test_driver_cipher_hooks.hits = 0;
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
 
     PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    test_driver_cipher_hooks.hits = 0;
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
 
     output_buffer_size = ( (size_t) input->len +
-                           PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
+                           PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type ) );
     ASSERT_ALLOC( output, output_buffer_size );
 
+    if( mock_output_arg )
+    {
+        mbedtls_test_driver_cipher_hooks.forced_output = expected_output->x;
+        mbedtls_test_driver_cipher_hooks.forced_output_length = expected_output->len;
+    }
+
     TEST_ASSERT( first_part_size <= input->len );
     PSA_ASSERT( psa_cipher_update( &operation,
                                    input->x, first_part_size,
                                    output, output_buffer_size,
                                    &function_output_length ) );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    test_driver_cipher_hooks.hits = 0;
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
 
     TEST_ASSERT( function_output_length == output1_length );
     total_output_length += function_output_length;
-    PSA_ASSERT( psa_cipher_update( &operation,
-                                   input->x + first_part_size,
-                                   input->len - first_part_size,
-                                   output + total_output_length,
-                                   output_buffer_size - total_output_length,
-                                   &function_output_length ) );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    test_driver_cipher_hooks.hits = 0;
 
-    TEST_ASSERT( function_output_length == output2_length );
-    total_output_length += function_output_length;
-    PSA_ASSERT( psa_cipher_finish( &operation,
-                                   output + total_output_length,
-                                   output_buffer_size - total_output_length,
-                                   &function_output_length ) );
+    if( first_part_size < input->len )
+    {
+        PSA_ASSERT( psa_cipher_update( &operation,
+                                       input->x + first_part_size,
+                                       input->len - first_part_size,
+                                       output + total_output_length,
+                                       output_buffer_size - total_output_length,
+                                       &function_output_length ) );
+        TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) );
+        mbedtls_test_driver_cipher_hooks.hits = 0;
+
+        TEST_ASSERT( function_output_length == output2_length );
+        total_output_length += function_output_length;
+    }
+
+    if( mock_output_arg )
+    {
+        mbedtls_test_driver_cipher_hooks.forced_output = NULL;
+        mbedtls_test_driver_cipher_hooks.forced_output_length = 0;
+    }
+
+    status = psa_cipher_finish( &operation,
+                                output + total_output_length,
+                                output_buffer_size - total_output_length,
+                                &function_output_length );
     /* Finish will have called abort as well, so expecting two hits here */
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 2 );
-    test_driver_cipher_hooks.hits = 0;
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 2 : 0 ) );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
     total_output_length += function_output_length;
-    PSA_ASSERT( psa_cipher_abort( &operation ) );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+    TEST_EQUAL( status, expected_status );
 
-    ASSERT_COMPARE( expected_output->x, expected_output->len,
-                    output, total_output_length );
+    if( expected_status == PSA_SUCCESS )
+    {
+        PSA_ASSERT( psa_cipher_abort( &operation ) );
+        TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 0 );
+
+        ASSERT_COMPARE( expected_output->x, expected_output->len,
+                        output, total_output_length );
+    }
 
 exit:
     psa_cipher_abort( &operation );
     mbedtls_free( output );
     psa_destroy_key( key );
     PSA_DONE( );
-    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
+    mbedtls_test_driver_cipher_hooks = mbedtls_test_driver_cipher_hooks_init();
 }
 /* END_CASE */
 
 /* BEGIN_CASE */
-void cipher_decrypt( int alg_arg, int key_type_arg,
-                     data_t *key_data, data_t *iv,
-                     data_t *input, data_t *expected_output,
+void cipher_decrypt( int alg_arg,
+                     int key_type_arg,
+                     data_t *key_data,
+                     data_t *iv,
+                     data_t *input_arg,
+                     data_t *expected_output,
                      int mock_output_arg,
                      int force_status_arg,
                      int expected_status_arg )
@@ -564,14 +786,14 @@
     psa_algorithm_t alg = alg_arg;
     psa_status_t expected_status = expected_status_arg;
     psa_status_t force_status = force_status_arg;
+    unsigned char *input = NULL;
+    size_t input_buffer_size = 0;
     unsigned char *output = NULL;
     size_t output_buffer_size = 0;
-    size_t function_output_length = 0;
-    size_t total_output_length = 0;
-    psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
+    size_t output_length = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
-    test_driver_cipher_hooks.forced_status = force_status;
+    mbedtls_test_driver_cipher_hooks = mbedtls_test_driver_cipher_hooks_init();
+    mbedtls_test_driver_cipher_hooks.forced_status = force_status;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
@@ -579,66 +801,46 @@
     psa_set_key_algorithm( &attributes, alg );
     psa_set_key_type( &attributes, key_type );
 
+    /* Allocate input buffer and copy the iv and the plaintext */
+    input_buffer_size = ( (size_t) input_arg->len + (size_t) iv->len );
+    if ( input_buffer_size > 0 )
+    {
+        ASSERT_ALLOC( input, input_buffer_size );
+        memcpy( input, iv->x, iv->len );
+        memcpy( input + iv->len, input_arg->x, input_arg->len );
+    }
+
+    output_buffer_size = PSA_CIPHER_DECRYPT_OUTPUT_SIZE( key_type, alg, input_buffer_size );
+    ASSERT_ALLOC( output, output_buffer_size );
+
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &key ) );
 
-    PSA_ASSERT( psa_cipher_decrypt_setup( &operation, key, alg ) );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    test_driver_cipher_hooks.hits = 0;
-
-    PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) );
-    test_driver_cipher_hooks.hits = 0;
-
-    output_buffer_size = ( (size_t) input->len +
-                           PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
-    ASSERT_ALLOC( output, output_buffer_size );
-
     if( mock_output_arg )
     {
-        test_driver_cipher_hooks.forced_output = expected_output->x;
-        test_driver_cipher_hooks.forced_output_length = expected_output->len;
+        mbedtls_test_driver_cipher_hooks.forced_output = expected_output->x;
+        mbedtls_test_driver_cipher_hooks.forced_output_length = expected_output->len;
     }
 
-    PSA_ASSERT( psa_cipher_update( &operation,
-                                   input->x, input->len,
-                                   output, output_buffer_size,
-                                   &function_output_length ) );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) );
-    test_driver_cipher_hooks.hits = 0;
+    status = psa_cipher_decrypt( key, alg, input, input_buffer_size, output,
+                                 output_buffer_size, &output_length );
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
 
-    if( mock_output_arg )
-    {
-        test_driver_cipher_hooks.forced_output = NULL;
-        test_driver_cipher_hooks.forced_output_length = 0;
-    }
-
-    total_output_length += function_output_length;
-    status = psa_cipher_finish( &operation,
-                                output + total_output_length,
-                                output_buffer_size - total_output_length,
-                                &function_output_length );
-    /* Finish will have called abort as well, so expecting two hits here */
-    TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 2 : 0 ) );
-    test_driver_cipher_hooks.hits = 0;
-
-    total_output_length += function_output_length;
     TEST_EQUAL( status, expected_status );
 
     if( expected_status == PSA_SUCCESS )
     {
-        PSA_ASSERT( psa_cipher_abort( &operation ) );
-        TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
         ASSERT_COMPARE( expected_output->x, expected_output->len,
-                        output, total_output_length );
+                        output, output_length );
     }
 
 exit:
-    psa_cipher_abort( &operation );
+    mbedtls_free( input );
     mbedtls_free( output );
     psa_destroy_key( key );
     PSA_DONE( );
-    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
+    mbedtls_test_driver_cipher_hooks = mbedtls_test_driver_cipher_hooks_init();
 }
 /* END_CASE */
 
@@ -656,7 +858,7 @@
     size_t function_output_length = 0;
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
+    mbedtls_test_driver_cipher_hooks = mbedtls_test_driver_cipher_hooks_init();
 
     ASSERT_ALLOC( output, input->len + 16 );
     output_buffer_size = input->len + 16;
@@ -670,137 +872,183 @@
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &key ) );
 
+    /*
+     * Test encrypt failure
+     * First test that if we don't force a driver error, encryption is
+     * successfull, then force driver error.
+     */
+    status = psa_cipher_encrypt(
+        key, alg, input->x, input->len,
+        output, output_buffer_size, &function_output_length );
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, PSA_SUCCESS );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
+
+    mbedtls_test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR;
+    /* Set the output buffer in a given state. */
+    for( size_t i = 0; i < output_buffer_size; i++ )
+        output[i] = 0xa5;
+
+    status = psa_cipher_encrypt(
+        key, alg, input->x, input->len,
+        output, output_buffer_size, &function_output_length );
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, PSA_ERROR_GENERIC_ERROR );
+    /*
+     * Check that the output buffer is still in the same state.
+     * This will fail if the output buffer is used by the core to pass the IV
+     * it generated to the driver (and is not restored).
+     */
+    for( size_t i = 0; i < output_buffer_size; i++ )
+    {
+        TEST_EQUAL( output[i], 0xa5 );
+    }
+    mbedtls_test_driver_cipher_hooks.hits = 0;
+
     /* Test setup call, encrypt */
-    test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR;
+    mbedtls_test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR;
     status = psa_cipher_encrypt_setup( &operation, key, alg );
     /* When setup fails, it shouldn't call any further entry points */
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
-    test_driver_cipher_hooks.hits = 0;
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, mbedtls_test_driver_cipher_hooks.forced_status );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
     status = psa_cipher_set_iv( &operation, iv->x, iv->len );
     TEST_EQUAL( status, PSA_ERROR_BAD_STATE );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 0 );
 
     /* Test setup call failure, decrypt */
     status = psa_cipher_decrypt_setup( &operation, key, alg );
     /* When setup fails, it shouldn't call any further entry points */
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
-    test_driver_cipher_hooks.hits = 0;
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, mbedtls_test_driver_cipher_hooks.forced_status );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
     status = psa_cipher_set_iv( &operation, iv->x, iv->len );
     TEST_EQUAL( status, PSA_ERROR_BAD_STATE );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 0 );
 
     /* Test IV setting failure */
-    test_driver_cipher_hooks.forced_status = PSA_SUCCESS;
+    mbedtls_test_driver_cipher_hooks.forced_status = PSA_SUCCESS;
     status = psa_cipher_encrypt_setup( &operation, key, alg );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
-    test_driver_cipher_hooks.hits = 0;
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, mbedtls_test_driver_cipher_hooks.forced_status );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
 
-    test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR;
+    mbedtls_test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR;
     status = psa_cipher_set_iv( &operation, iv->x, iv->len );
     /* When setting the IV fails, it should call abort too */
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 2 );
-    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 2 );
+    TEST_EQUAL( status, mbedtls_test_driver_cipher_hooks.forced_status );
     /* Failure should prevent further operations from executing on the driver */
-    test_driver_cipher_hooks.hits = 0;
+    mbedtls_test_driver_cipher_hooks.hits = 0;
     status = psa_cipher_update( &operation,
                                 input->x, input->len,
                                 output, output_buffer_size,
                                 &function_output_length );
     TEST_EQUAL( status, PSA_ERROR_BAD_STATE );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 0 );
     psa_cipher_abort( &operation );
 
     /* Test IV generation failure */
-    test_driver_cipher_hooks.forced_status = PSA_SUCCESS;
+    mbedtls_test_driver_cipher_hooks.forced_status = PSA_SUCCESS;
     status = psa_cipher_encrypt_setup( &operation, key, alg );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
-    test_driver_cipher_hooks.hits = 0;
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, mbedtls_test_driver_cipher_hooks.forced_status );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
 
-    test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR;
+    mbedtls_test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR;
+    /* Set the output buffer in a given state. */
+    for( size_t i = 0; i < 16; i++ )
+        output[i] = 0xa5;
+
     status = psa_cipher_generate_iv( &operation, output, 16, &function_output_length );
     /* When generating the IV fails, it should call abort too */
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 2 );
-    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 2 );
+    TEST_EQUAL( status, mbedtls_test_driver_cipher_hooks.forced_status );
+    /*
+     * Check that the output buffer is still in the same state.
+     * This will fail if the output buffer is used by the core to pass the IV
+     * it generated to the driver (and is not restored).
+     */
+    for( size_t i = 0; i < 16; i++ )
+    {
+        TEST_EQUAL( output[i], 0xa5 );
+    }
     /* Failure should prevent further operations from executing on the driver */
-    test_driver_cipher_hooks.hits = 0;
+    mbedtls_test_driver_cipher_hooks.hits = 0;
     status = psa_cipher_update( &operation,
                                 input->x, input->len,
                                 output, output_buffer_size,
                                 &function_output_length );
     TEST_EQUAL( status, PSA_ERROR_BAD_STATE );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 0 );
     psa_cipher_abort( &operation );
 
     /* Test update failure */
-    test_driver_cipher_hooks.forced_status = PSA_SUCCESS;
+    mbedtls_test_driver_cipher_hooks.forced_status = PSA_SUCCESS;
     status = psa_cipher_encrypt_setup( &operation, key, alg );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
-    test_driver_cipher_hooks.hits = 0;
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, mbedtls_test_driver_cipher_hooks.forced_status );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
 
     status = psa_cipher_set_iv( &operation, iv->x, iv->len );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
-    test_driver_cipher_hooks.hits = 0;
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, mbedtls_test_driver_cipher_hooks.forced_status );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
 
-    test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR;
+    mbedtls_test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR;
     status = psa_cipher_update( &operation,
                                 input->x, input->len,
                                 output, output_buffer_size,
                                 &function_output_length );
     /* When the update call fails, it should call abort too */
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 2 );
-    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 2 );
+    TEST_EQUAL( status, mbedtls_test_driver_cipher_hooks.forced_status );
     /* Failure should prevent further operations from executing on the driver */
-    test_driver_cipher_hooks.hits = 0;
+    mbedtls_test_driver_cipher_hooks.hits = 0;
     status = psa_cipher_update( &operation,
                                 input->x, input->len,
                                 output, output_buffer_size,
                                 &function_output_length );
     TEST_EQUAL( status, PSA_ERROR_BAD_STATE );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 0 );
     psa_cipher_abort( &operation );
 
     /* Test finish failure */
-    test_driver_cipher_hooks.forced_status = PSA_SUCCESS;
+    mbedtls_test_driver_cipher_hooks.forced_status = PSA_SUCCESS;
     status = psa_cipher_encrypt_setup( &operation, key, alg );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
-    test_driver_cipher_hooks.hits = 0;
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, mbedtls_test_driver_cipher_hooks.forced_status );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
 
     status = psa_cipher_set_iv( &operation, iv->x, iv->len );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
-    test_driver_cipher_hooks.hits = 0;
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, mbedtls_test_driver_cipher_hooks.forced_status );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
 
     status = psa_cipher_update( &operation,
                                 input->x, input->len,
                                 output, output_buffer_size,
                                 &function_output_length );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
-    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
-    test_driver_cipher_hooks.hits = 0;
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, mbedtls_test_driver_cipher_hooks.forced_status );
+    mbedtls_test_driver_cipher_hooks.hits = 0;
 
-    test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR;
+    mbedtls_test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR;
     status = psa_cipher_finish( &operation,
                                 output + function_output_length,
                                 output_buffer_size - function_output_length,
                                 &function_output_length );
     /* When the finish call fails, it should call abort too */
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 2 );
-    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 2 );
+    TEST_EQUAL( status, mbedtls_test_driver_cipher_hooks.forced_status );
     /* Failure should prevent further operations from executing on the driver */
-    test_driver_cipher_hooks.hits = 0;
+    mbedtls_test_driver_cipher_hooks.hits = 0;
     status = psa_cipher_update( &operation,
                                 input->x, input->len,
                                 output, output_buffer_size,
                                 &function_output_length );
     TEST_EQUAL( status, PSA_ERROR_BAD_STATE );
-    TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+    TEST_EQUAL( mbedtls_test_driver_cipher_hooks.hits, 0 );
     psa_cipher_abort( &operation );
 
 exit:
@@ -808,6 +1056,731 @@
     mbedtls_free( output );
     psa_destroy_key( key );
     PSA_DONE( );
-    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
+    mbedtls_test_driver_cipher_hooks = mbedtls_test_driver_cipher_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void aead_encrypt( int key_type_arg, data_t *key_data,
+                   int alg_arg,
+                   data_t *nonce,
+                   data_t *additional_data,
+                   data_t *input_data,
+                   data_t *expected_result,
+                   int forced_status_arg )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    size_t key_bits;
+    psa_status_t forced_status = forced_status_arg;
+    unsigned char *output_data = NULL;
+    size_t output_size = 0;
+    size_t output_length = 0;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    mbedtls_test_driver_aead_hooks = mbedtls_test_driver_aead_hooks_init();
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT  );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+    key_bits = psa_get_key_bits( &attributes );
+
+    output_size = input_data->len + PSA_AEAD_TAG_LENGTH( key_type, key_bits,
+                                                         alg );
+    /* For all currently defined algorithms, PSA_AEAD_ENCRYPT_OUTPUT_SIZE
+     * should be exact. */
+    TEST_EQUAL( output_size,
+                PSA_AEAD_ENCRYPT_OUTPUT_SIZE( key_type, alg, input_data->len ) );
+    TEST_ASSERT( output_size <=
+                 PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE( input_data->len ) );
+    ASSERT_ALLOC( output_data, output_size );
+
+    mbedtls_test_driver_aead_hooks.forced_status = forced_status;
+    status = psa_aead_encrypt( key, alg,
+                               nonce->x, nonce->len,
+                               additional_data->x, additional_data->len,
+                               input_data->x, input_data->len,
+                               output_data, output_size,
+                               &output_length );
+    TEST_EQUAL( mbedtls_test_driver_aead_hooks.hits, 1 );
+    TEST_EQUAL( mbedtls_test_driver_aead_hooks.driver_status, forced_status );
+
+    TEST_EQUAL( status, ( forced_status == PSA_ERROR_NOT_SUPPORTED ) ?
+                        PSA_SUCCESS : forced_status );
+
+    if( status == PSA_SUCCESS )
+    {
+        ASSERT_COMPARE( expected_result->x, expected_result->len,
+                        output_data, output_length );
+    }
+
+exit:
+    psa_destroy_key( key );
+    mbedtls_free( output_data );
+    PSA_DONE( );
+    mbedtls_test_driver_aead_hooks = mbedtls_test_driver_aead_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void aead_decrypt( int key_type_arg, data_t *key_data,
+                   int alg_arg,
+                   data_t *nonce,
+                   data_t *additional_data,
+                   data_t *input_data,
+                   data_t *expected_data,
+                   int forced_status_arg )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    size_t key_bits;
+    psa_status_t forced_status = forced_status_arg;
+    unsigned char *output_data = NULL;
+    size_t output_size = 0;
+    size_t output_length = 0;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    mbedtls_test_driver_aead_hooks = mbedtls_test_driver_aead_hooks_init();
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DECRYPT  );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+    key_bits = psa_get_key_bits( &attributes );
+
+    output_size = input_data->len - PSA_AEAD_TAG_LENGTH( key_type, key_bits,
+                                                         alg );
+    ASSERT_ALLOC( output_data, output_size );
+
+    mbedtls_test_driver_aead_hooks.forced_status = forced_status;
+    status = psa_aead_decrypt( key, alg,
+                               nonce->x, nonce->len,
+                               additional_data->x,
+                               additional_data->len,
+                               input_data->x, input_data->len,
+                               output_data, output_size,
+                               &output_length );
+    TEST_EQUAL( mbedtls_test_driver_aead_hooks.hits, 1 );
+    TEST_EQUAL( mbedtls_test_driver_aead_hooks.driver_status, forced_status );
+
+    TEST_EQUAL( status, ( forced_status == PSA_ERROR_NOT_SUPPORTED ) ?
+                        PSA_SUCCESS : forced_status );
+
+    if( status == PSA_SUCCESS )
+    {
+        ASSERT_COMPARE( expected_data->x, expected_data->len,
+                        output_data, output_length );
+    }
+
+exit:
+    psa_destroy_key( key );
+    mbedtls_free( output_data );
+    PSA_DONE( );
+    mbedtls_test_driver_aead_hooks = mbedtls_test_driver_aead_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mac_sign( int key_type_arg,
+               data_t *key_data,
+               int alg_arg,
+               data_t *input,
+               data_t *expected_mac,
+               int forced_status_arg )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    uint8_t *actual_mac = NULL;
+    size_t mac_buffer_size =
+        PSA_MAC_LENGTH( key_type, PSA_BYTES_TO_BITS( key_data->len ), alg );
+    size_t mac_length = 0;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t forced_status = forced_status_arg;
+    mbedtls_test_driver_mac_hooks = mbedtls_test_driver_mac_hooks_init();
+
+    TEST_ASSERT( mac_buffer_size <= PSA_MAC_MAX_SIZE );
+    /* We expect PSA_MAC_LENGTH to be exact. */
+    TEST_ASSERT( expected_mac->len == mac_buffer_size );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+
+    ASSERT_ALLOC( actual_mac, mac_buffer_size );
+    mbedtls_test_driver_mac_hooks.forced_status = forced_status;
+
+    /*
+     * Calculate the MAC, one-shot case.
+     */
+    status = psa_mac_compute( key, alg,
+                              input->x, input->len,
+                              actual_mac, mac_buffer_size,
+                              &mac_length );
+
+    TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+    if( forced_status == PSA_SUCCESS ||
+        forced_status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        PSA_ASSERT( status );
+    }
+    else
+        TEST_EQUAL( forced_status, status );
+
+    if( mac_buffer_size > 0 )
+        memset( actual_mac, 0, mac_buffer_size );
+    mbedtls_test_driver_mac_hooks = mbedtls_test_driver_mac_hooks_init();
+    mbedtls_test_driver_mac_hooks.forced_status = forced_status;
+
+    /*
+     * Calculate the MAC, multipart case.
+     */
+    status = psa_mac_sign_setup( &operation, key, alg );
+    TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+
+    if( forced_status == PSA_SUCCESS ||
+        forced_status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        PSA_ASSERT( status );
+    }
+    else
+        TEST_EQUAL( forced_status, status );
+
+    status = psa_mac_update( &operation,
+                             input->x, input->len );
+    if( forced_status == PSA_SUCCESS )
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 2 );
+    else
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+    if( forced_status == PSA_SUCCESS ||
+        forced_status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        PSA_ASSERT( status );
+    }
+    else
+        TEST_EQUAL( PSA_ERROR_BAD_STATE, status );
+
+    status = psa_mac_sign_finish( &operation,
+                                  actual_mac, mac_buffer_size,
+                                  &mac_length );
+    if( forced_status == PSA_SUCCESS )
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 4 );
+    else
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+
+    if( forced_status == PSA_SUCCESS ||
+        forced_status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        PSA_ASSERT( status );
+    }
+    else
+        TEST_EQUAL( PSA_ERROR_BAD_STATE, status );
+
+    PSA_ASSERT( psa_mac_abort( &operation ) );
+    if( forced_status == PSA_SUCCESS )
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 4 );
+    else
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+
+    if( forced_status == PSA_SUCCESS )
+    {
+        ASSERT_COMPARE( expected_mac->x, expected_mac->len,
+                        actual_mac, mac_length );
+    }
+
+    mbedtls_free( actual_mac );
+    actual_mac = NULL;
+
+exit:
+    psa_mac_abort( &operation );
+    psa_destroy_key( key );
+    PSA_DONE( );
+    mbedtls_free( actual_mac );
+    mbedtls_test_driver_mac_hooks = mbedtls_test_driver_mac_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mac_verify( int key_type_arg,
+                 data_t *key_data,
+                 int alg_arg,
+                 data_t *input,
+                 data_t *expected_mac,
+                 int forced_status_arg )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    psa_status_t forced_status = forced_status_arg;
+    mbedtls_test_driver_mac_hooks = mbedtls_test_driver_mac_hooks_init();
+
+    TEST_ASSERT( expected_mac->len <= PSA_MAC_MAX_SIZE );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+
+    mbedtls_test_driver_mac_hooks.forced_status = forced_status;
+
+    /*
+     * Verify the MAC, one-shot case.
+     */
+    status = psa_mac_verify( key, alg,
+                             input->x, input->len,
+                             expected_mac->x, expected_mac->len );
+    TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+    if( forced_status == PSA_SUCCESS ||
+        forced_status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        PSA_ASSERT( status );
+    }
+    else
+        TEST_EQUAL( forced_status, status );
+
+    mbedtls_test_driver_mac_hooks = mbedtls_test_driver_mac_hooks_init();
+    mbedtls_test_driver_mac_hooks.forced_status = forced_status;
+
+    /*
+     * Verify the MAC, multi-part case.
+     */
+    status = psa_mac_verify_setup( &operation, key, alg );
+    TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+
+    if( forced_status == PSA_SUCCESS ||
+        forced_status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        PSA_ASSERT( status );
+    }
+    else
+        TEST_EQUAL( forced_status, status );
+
+    status = psa_mac_update( &operation,
+                             input->x, input->len );
+    if( forced_status == PSA_SUCCESS )
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 2 );
+    else
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+
+    if( forced_status == PSA_SUCCESS ||
+        forced_status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        PSA_ASSERT( status );
+    }
+    else
+        TEST_EQUAL( PSA_ERROR_BAD_STATE, status );
+
+    status = psa_mac_verify_finish( &operation,
+                                    expected_mac->x,
+                                    expected_mac->len );
+    if( forced_status == PSA_SUCCESS )
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 4 );
+    else
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+
+    if( forced_status == PSA_SUCCESS ||
+        forced_status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        PSA_ASSERT( status );
+    }
+    else
+        TEST_EQUAL( PSA_ERROR_BAD_STATE, status );
+
+
+    PSA_ASSERT( psa_mac_abort( &operation ) );
+    if( forced_status == PSA_SUCCESS )
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 4 );
+    else
+        TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
+
+exit:
+    psa_mac_abort( &operation );
+    psa_destroy_key( key );
+    PSA_DONE( );
+    mbedtls_test_driver_mac_hooks = mbedtls_test_driver_mac_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:PSA_CRYPTO_DRIVER_TEST:MBEDTLS_PSA_CRYPTO_DRIVERS:MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
+void builtin_key_export( int builtin_key_id_arg,
+                         int builtin_key_type_arg,
+                         int builtin_key_bits_arg,
+                         int builtin_key_algorithm_arg,
+                         data_t *expected_output,
+                         int expected_status_arg )
+{
+    psa_key_id_t builtin_key_id = (psa_key_id_t) builtin_key_id_arg;
+    psa_key_type_t builtin_key_type = (psa_key_type_t) builtin_key_type_arg;
+    psa_algorithm_t builtin_key_alg = (psa_algorithm_t) builtin_key_algorithm_arg;
+    size_t builtin_key_bits = (size_t) builtin_key_bits_arg;
+    psa_status_t expected_status = expected_status_arg;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    mbedtls_svc_key_id_t key = mbedtls_svc_key_id_make( 0, builtin_key_id );
+    uint8_t* output_buffer = NULL;
+    size_t output_size = 0;
+    psa_status_t actual_status;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+    ASSERT_ALLOC( output_buffer, expected_output->len );
+
+    actual_status = psa_export_key( key, output_buffer, expected_output->len, &output_size );
+
+    if( expected_status == PSA_SUCCESS )
+    {
+        PSA_ASSERT( actual_status );
+        TEST_EQUAL( output_size, expected_output->len );
+        ASSERT_COMPARE( output_buffer, output_size,
+                        expected_output->x, expected_output->len );
+
+        PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+        TEST_EQUAL( psa_get_key_bits( &attributes ), builtin_key_bits );
+        TEST_EQUAL( psa_get_key_type( &attributes ), builtin_key_type );
+        TEST_EQUAL( psa_get_key_algorithm( &attributes ), builtin_key_alg );
+    }
+    else
+    {
+        if( actual_status != expected_status )
+            fprintf( stderr, "Expected %d but got %d\n", expected_status, actual_status );
+        TEST_EQUAL( actual_status, expected_status );
+        TEST_EQUAL( output_size, 0 );
+    }
+
+exit:
+    mbedtls_free( output_buffer );
+    psa_reset_key_attributes( &attributes );
+    psa_destroy_key( key );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:PSA_CRYPTO_DRIVER_TEST:MBEDTLS_PSA_CRYPTO_DRIVERS:MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
+void builtin_pubkey_export( int builtin_key_id_arg,
+                            int builtin_key_type_arg,
+                            int builtin_key_bits_arg,
+                            int builtin_key_algorithm_arg,
+                            data_t *expected_output,
+                            int expected_status_arg )
+{
+    psa_key_id_t builtin_key_id = (psa_key_id_t) builtin_key_id_arg;
+    psa_key_type_t builtin_key_type = (psa_key_type_t) builtin_key_type_arg;
+    psa_algorithm_t builtin_key_alg = (psa_algorithm_t) builtin_key_algorithm_arg;
+    size_t builtin_key_bits = (size_t) builtin_key_bits_arg;
+    psa_status_t expected_status = expected_status_arg;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    mbedtls_svc_key_id_t key = mbedtls_svc_key_id_make( 0, builtin_key_id );
+    uint8_t* output_buffer = NULL;
+    size_t output_size = 0;
+    psa_status_t actual_status;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+    ASSERT_ALLOC( output_buffer, expected_output->len );
+
+    actual_status = psa_export_public_key( key, output_buffer, expected_output->len, &output_size );
+
+    if( expected_status == PSA_SUCCESS )
+    {
+        PSA_ASSERT( actual_status );
+        TEST_EQUAL( output_size, expected_output->len );
+        ASSERT_COMPARE( output_buffer, output_size,
+                        expected_output->x, expected_output->len );
+
+        PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+        TEST_EQUAL( psa_get_key_bits( &attributes ), builtin_key_bits );
+        TEST_EQUAL( psa_get_key_type( &attributes ), builtin_key_type );
+        TEST_EQUAL( psa_get_key_algorithm( &attributes ), builtin_key_alg );
+    }
+    else
+    {
+        TEST_EQUAL( actual_status, expected_status );
+        TEST_EQUAL( output_size, 0 );
+    }
+
+exit:
+    mbedtls_free( output_buffer );
+    psa_reset_key_attributes( &attributes );
+    psa_destroy_key( key );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void hash_compute( int alg_arg,
+                   data_t *input, data_t *hash,
+                   int forced_status_arg,
+                   int expected_status_arg )
+{
+    psa_algorithm_t alg = alg_arg;
+    psa_status_t forced_status = forced_status_arg;
+    psa_status_t expected_status = expected_status_arg;
+    unsigned char *output = NULL;
+    size_t output_length;
+
+    mbedtls_test_driver_hash_hooks = mbedtls_test_driver_hash_hooks_init();
+    mbedtls_test_driver_hash_hooks.forced_status = forced_status;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+    ASSERT_ALLOC( output, PSA_HASH_LENGTH( alg ) );
+
+    TEST_EQUAL( psa_hash_compute( alg, input->x, input->len,
+                                  output, PSA_HASH_LENGTH( alg ),
+                                  &output_length ), expected_status );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.hits, 1 );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.driver_status, forced_status );
+
+    if( expected_status == PSA_SUCCESS )
+    {
+        ASSERT_COMPARE( output, output_length, hash->x, hash->len );
+    }
+
+exit:
+    mbedtls_free( output );
+    PSA_DONE( );
+    mbedtls_test_driver_hash_hooks = mbedtls_test_driver_hash_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void hash_multipart_setup( int alg_arg,
+                           data_t *input, data_t *hash,
+                           int forced_status_arg,
+                           int expected_status_arg )
+{
+    psa_algorithm_t alg = alg_arg;
+    psa_status_t forced_status = forced_status_arg;
+    psa_status_t expected_status = expected_status_arg;
+    unsigned char *output = NULL;
+    psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
+    size_t output_length;
+
+    mbedtls_test_driver_hash_hooks = mbedtls_test_driver_hash_hooks_init();
+    ASSERT_ALLOC( output, PSA_HASH_LENGTH( alg ) );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    mbedtls_test_driver_hash_hooks.forced_status = forced_status;
+    TEST_EQUAL( psa_hash_setup( &operation, alg ), expected_status );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.hits, 1 );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.driver_status, forced_status );
+
+    if( expected_status == PSA_SUCCESS )
+    {
+        PSA_ASSERT( psa_hash_update( &operation, input->x, input->len ) );
+        TEST_EQUAL( mbedtls_test_driver_hash_hooks.hits,
+                    forced_status == PSA_ERROR_NOT_SUPPORTED ? 1 : 2 );
+        TEST_EQUAL( mbedtls_test_driver_hash_hooks.driver_status, forced_status );
+
+        PSA_ASSERT( psa_hash_finish( &operation,
+                                     output, PSA_HASH_LENGTH( alg ),
+                                     &output_length ) );
+        TEST_EQUAL( mbedtls_test_driver_hash_hooks.hits,
+                    forced_status == PSA_ERROR_NOT_SUPPORTED ? 1 : 4 );
+        TEST_EQUAL( mbedtls_test_driver_hash_hooks.driver_status, forced_status );
+
+        ASSERT_COMPARE( output, output_length, hash->x, hash->len );
+    }
+
+exit:
+    psa_hash_abort( &operation );
+    mbedtls_free( output );
+    PSA_DONE( );
+    mbedtls_test_driver_hash_hooks = mbedtls_test_driver_hash_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void hash_multipart_update( int alg_arg,
+                            data_t *input, data_t *hash,
+                            int forced_status_arg )
+{
+    psa_algorithm_t alg = alg_arg;
+    psa_status_t forced_status = forced_status_arg;
+    unsigned char *output = NULL;
+    psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
+    size_t output_length;
+
+    mbedtls_test_driver_hash_hooks = mbedtls_test_driver_hash_hooks_init();
+    ASSERT_ALLOC( output, PSA_HASH_LENGTH( alg ) );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    /*
+     * Update inactive operation, the driver shouldn't be called.
+     */
+    TEST_EQUAL( psa_hash_update( &operation, input->x, input->len ),
+                PSA_ERROR_BAD_STATE );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.hits, 0 );
+
+    PSA_ASSERT( psa_hash_setup( &operation, alg ) );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.hits, 1 );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.driver_status, PSA_SUCCESS );
+
+    mbedtls_test_driver_hash_hooks.forced_status = forced_status;
+    TEST_EQUAL( psa_hash_update( &operation, input->x, input->len ),
+                forced_status );
+    /* One or two more calls to the driver interface: update or update + abort */
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.hits,
+                forced_status == PSA_SUCCESS ? 2 : 3 );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.driver_status, forced_status );
+
+    if( forced_status == PSA_SUCCESS )
+    {
+        mbedtls_test_driver_hash_hooks = mbedtls_test_driver_hash_hooks_init();
+        PSA_ASSERT( psa_hash_finish( &operation,
+                                     output, PSA_HASH_LENGTH( alg ),
+                                     &output_length ) );
+        /* Two calls to the driver interface: update + abort */
+        TEST_EQUAL( mbedtls_test_driver_hash_hooks.hits, 2 );
+        TEST_EQUAL( mbedtls_test_driver_hash_hooks.driver_status, PSA_SUCCESS );
+
+        ASSERT_COMPARE( output, output_length, hash->x, hash->len );
+    }
+
+exit:
+    psa_hash_abort( &operation );
+    mbedtls_free( output );
+    PSA_DONE( );
+    mbedtls_test_driver_hash_hooks = mbedtls_test_driver_hash_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void hash_multipart_finish( int alg_arg,
+                            data_t *input, data_t *hash,
+                            int forced_status_arg )
+{
+    psa_algorithm_t alg = alg_arg;
+    psa_status_t forced_status = forced_status_arg;
+    unsigned char *output = NULL;
+    psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
+    size_t output_length;
+
+    mbedtls_test_driver_hash_hooks = mbedtls_test_driver_hash_hooks_init();
+    ASSERT_ALLOC( output, PSA_HASH_LENGTH( alg ) );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    /*
+     * Finish inactive operation, the driver shouldn't be called.
+     */
+    TEST_EQUAL( psa_hash_finish( &operation, output, PSA_HASH_LENGTH( alg ),
+                                 &output_length ),
+                PSA_ERROR_BAD_STATE );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.hits, 0 );
+
+    PSA_ASSERT( psa_hash_setup( &operation, alg ) );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.hits, 1 );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.driver_status, PSA_SUCCESS );
+
+    PSA_ASSERT( psa_hash_update( &operation, input->x, input->len ) );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.hits, 2 );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.driver_status, PSA_SUCCESS );
+
+    mbedtls_test_driver_hash_hooks.forced_status = forced_status;
+    TEST_EQUAL( psa_hash_finish( &operation,
+                                 output, PSA_HASH_LENGTH( alg ),
+                                 &output_length ),
+                forced_status );
+    /* Two more calls to the driver interface: finish + abort */
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.hits, 4 );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.driver_status, forced_status );
+
+    if( forced_status == PSA_SUCCESS )
+        ASSERT_COMPARE( output, output_length, hash->x, hash->len );
+
+exit:
+    psa_hash_abort( &operation );
+    mbedtls_free( output );
+    PSA_DONE( );
+    mbedtls_test_driver_hash_hooks = mbedtls_test_driver_hash_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void hash_clone( int alg_arg,
+                 data_t *input, data_t *hash,
+                 int forced_status_arg )
+{
+    psa_algorithm_t alg = alg_arg;
+    psa_status_t forced_status = forced_status_arg;
+    unsigned char *output = NULL;
+    psa_hash_operation_t source_operation = PSA_HASH_OPERATION_INIT;
+    psa_hash_operation_t target_operation = PSA_HASH_OPERATION_INIT;
+    size_t output_length;
+
+    mbedtls_test_driver_hash_hooks = mbedtls_test_driver_hash_hooks_init();
+    ASSERT_ALLOC( output, PSA_HASH_LENGTH( alg ) );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    /*
+     * Clone inactive operation, the driver shouldn't be called.
+     */
+    TEST_EQUAL( psa_hash_clone( &source_operation, &target_operation ),
+                PSA_ERROR_BAD_STATE );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.hits, 0 );
+
+    PSA_ASSERT( psa_hash_setup( &source_operation, alg ) );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.hits, 1 );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.driver_status, PSA_SUCCESS );
+
+    mbedtls_test_driver_hash_hooks.forced_status = forced_status;
+    TEST_EQUAL( psa_hash_clone( &source_operation, &target_operation ),
+                forced_status );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.hits,
+                forced_status == PSA_SUCCESS ? 2 : 3 );
+    TEST_EQUAL( mbedtls_test_driver_hash_hooks.driver_status, forced_status );
+
+    if( forced_status == PSA_SUCCESS )
+    {
+        mbedtls_test_driver_hash_hooks = mbedtls_test_driver_hash_hooks_init();
+        PSA_ASSERT( psa_hash_update( &target_operation,
+                                     input->x, input->len ) );
+        TEST_EQUAL( mbedtls_test_driver_hash_hooks.hits, 1 );
+        TEST_EQUAL( mbedtls_test_driver_hash_hooks.driver_status, PSA_SUCCESS );
+
+        PSA_ASSERT( psa_hash_finish( &target_operation,
+                                     output, PSA_HASH_LENGTH( alg ),
+                                     &output_length ) );
+        TEST_EQUAL( mbedtls_test_driver_hash_hooks.hits, 3 );
+        TEST_EQUAL( mbedtls_test_driver_hash_hooks.driver_status, PSA_SUCCESS );
+
+        ASSERT_COMPARE( output, output_length, hash->x, hash->len );
+    }
+
+exit:
+    psa_hash_abort( &source_operation );
+    psa_hash_abort( &target_operation );
+    mbedtls_free( output );
+    PSA_DONE( );
+    mbedtls_test_driver_hash_hooks = mbedtls_test_driver_hash_hooks_init();
 }
 /* END_CASE */
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_entropy.data b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_entropy.data
index 61593e9..49d3f69 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_entropy.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_entropy.data
@@ -1,3 +1,30 @@
+PSA external RNG failure: generate random and key
+external_rng_failure_generate:
+
+# When verifying the impact of a forced RNG failure, depend on the built-in
+# implementation of the algorithm that uses randomization, whether it's
+# because the algorithm is randomized or because our implementation uses
+# randomization for (e.g.) blinding. An external implementation could use
+# its own randomness source which is not affected by the forced failure of
+# the RNG driver.
+# Key types and non-randomized auxilary algorithms (in practice, hashes) can
+# use an external implementation.
+PSA external RNG failure: randomized ECDSA
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PSA_BUILTIN_ALG_ECDSA:PSA_WANT_ECC_SECP_R1_256
+external_rng_failure_sign:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA_ANY:32
+
+PSA external RNG failure: deterministic ECDSA (software implementation)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ECC_SECP_R1_256
+external_rng_failure_sign:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):32
+
+PSA external RNG failure: RSA-PSS
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS
+external_rng_failure_sign:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):32
+
+PSA external RNG failure: RSA PKCS#1v1.5 (software implementation)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN
+external_rng_failure_sign:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:32
+
 PSA validate entropy injection: good, minimum size
 validate_entropy_seed_injection:MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE:PSA_SUCCESS:MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE:PSA_ERROR_NOT_PERMITTED
 
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_entropy.function b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_entropy.function
index 66c241e..4dcbb36 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_entropy.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_entropy.function
@@ -1,19 +1,23 @@
 /* BEGIN_HEADER */
 #include <stdint.h>
+#include <string.h>
+
+#include <psa/crypto.h>
 
 #include "mbedtls/entropy.h"
 #include "mbedtls/entropy_poll.h"
 
-#include "test/psa_crypto_helpers.h"
+/* Calculating the minimum allowed entropy size in bytes */
+#define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE)
+
+#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
+
 #if defined(MBEDTLS_PSA_ITS_FILE_C)
 #include <stdio.h>
 #else
 #include <psa/internal_trusted_storage.h>
 #endif
 
-/* Calculating the minimum allowed entropy size in bytes */
-#define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE)
-
 /* Remove the entropy seed file. Since the library does not expose a way
  * to do this (it would be a security risk if such a function was ever
  * accessible in production), implement this functionality in a white-box
@@ -30,14 +34,89 @@
 #endif
 }
 
+#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
+
 /* END_HEADER */
 
-/* BEGIN_DEPENDENCIES
- * depends_on:MBEDTLS_PSA_INJECT_ENTROPY
- * END_DEPENDENCIES
- */
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+void external_rng_failure_generate( )
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_DERIVE );
+    psa_set_key_bits( &attributes, 128 );
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    uint8_t output[1];
 
-/* BEGIN_CASE */
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    PSA_ASSERT( psa_generate_random( output, sizeof( output ) ) );
+    PSA_ASSERT( psa_generate_key( &attributes, &key ) );
+    PSA_ASSERT( psa_destroy_key( key ) );
+
+    mbedtls_test_disable_insecure_external_rng( );
+    TEST_EQUAL( PSA_ERROR_INSUFFICIENT_ENTROPY,
+                psa_generate_random( output, sizeof( output ) ) );
+    TEST_EQUAL( PSA_ERROR_INSUFFICIENT_ENTROPY,
+                psa_generate_key( &attributes, &key ) );
+
+exit:
+    psa_destroy_key( key );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+void external_rng_failure_sign( int key_type, data_t *key_data, int alg,
+                                int input_size_arg )
+{
+    /* This test case is only expected to pass if the signature mechanism
+     * requires randomness, either because it is a randomized signature
+     * or because the implementation uses blinding. */
+
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_set_key_type( &attributes, key_type );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH );
+    psa_set_key_algorithm( &attributes, alg );
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    size_t input_size = input_size_arg;
+    uint8_t *input = NULL;
+    uint8_t *signature = NULL;
+    size_t signature_size = PSA_SIGNATURE_MAX_SIZE;
+    size_t signature_length;
+
+    ASSERT_ALLOC( input, input_size );
+    ASSERT_ALLOC( signature, signature_size );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+    PSA_ASSERT( psa_sign_hash( key, alg,
+                               input, input_size,
+                               signature, signature_size,
+                               &signature_length ) );
+    PSA_ASSERT( psa_destroy_key( key ) );
+
+    mbedtls_test_disable_insecure_external_rng( );
+    /* Import the key again, because for RSA Mbed TLS caches blinding values
+     * in the key object and this could perturb the test. */
+    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
+                                &key ) );
+    TEST_EQUAL( PSA_ERROR_INSUFFICIENT_ENTROPY,
+                psa_sign_hash( key, alg,
+                               input, input_size,
+                               signature, signature_size,
+                               &signature_length ) );
+    PSA_ASSERT( psa_destroy_key( key ) );
+
+exit:
+    psa_destroy_key( key );
+    PSA_DONE( );
+    mbedtls_free( input );
+    mbedtls_free( signature );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_INJECT_ENTROPY */
 void validate_entropy_seed_injection( int seed_length_a,
                                       int expected_status_a,
                                       int seed_length_b,
@@ -81,7 +160,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_INJECT_ENTROPY */
 void run_entropy_inject_with_crypto_init( )
 {
     psa_status_t status;
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_generate_key.function b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_generate_key.function
new file mode 100644
index 0000000..dbe9a0e
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_generate_key.function
@@ -0,0 +1,49 @@
+/* BEGIN_HEADER */
+
+#include "psa/crypto.h"
+#include "test/psa_crypto_helpers.h"
+
+#define INVALID_KEY_ID mbedtls_svc_key_id_make( 0, 0xfedcba98 )
+
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_PSA_CRYPTO_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void generate_key( int key_type_arg, int bits_arg, int expected_status_arg)
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t key_id = INVALID_KEY_ID;
+
+    // key lifetiem, usage flags, algorithm are irrelevant for this test
+    psa_key_type_t key_type = key_type_arg;
+    size_t bits = bits_arg;
+    psa_status_t expected_status = expected_status_arg;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+    psa_set_key_type( &attributes, key_type );
+    psa_set_key_bits( &attributes, bits );
+    TEST_EQUAL( psa_generate_key( &attributes, &key_id ),
+                expected_status );
+
+    // Verify attributes of the created key on success
+    if ( expected_status == PSA_SUCCESS )
+    {
+        psa_reset_key_attributes(&attributes);
+        PSA_ASSERT( psa_get_key_attributes( key_id, &attributes ) );
+        TEST_EQUAL( psa_get_key_lifetime( &attributes ), PSA_KEY_LIFETIME_VOLATILE );
+        TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 );
+        TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
+        TEST_EQUAL( psa_get_key_type( &attributes ), key_type );
+        TEST_EQUAL( psa_get_key_bits( &attributes ), bits );
+    }
+
+exit:
+    psa_reset_key_attributes(&attributes);
+    psa_destroy_key( key_id );
+    PSA_DONE( );
+}
+/* END_CASE */
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_generate_key.generated.data b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_generate_key.generated.data
new file mode 100644
index 0000000..7199c68
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_generate_key.generated.data
@@ -0,0 +1,342 @@
+# Automatically generated by generate_psa_tests.py. Do not edit!
+
+PSA AES 128-bit
+depends_on:PSA_WANT_KEY_TYPE_AES
+generate_key:PSA_KEY_TYPE_AES:128:PSA_SUCCESS:
+
+PSA AES 192-bit
+depends_on:PSA_WANT_KEY_TYPE_AES
+generate_key:PSA_KEY_TYPE_AES:192:PSA_SUCCESS:
+
+PSA AES 256-bit
+depends_on:PSA_WANT_KEY_TYPE_AES
+generate_key:PSA_KEY_TYPE_AES:256:PSA_SUCCESS:
+
+PSA ARC4 8-bit
+depends_on:PSA_WANT_KEY_TYPE_ARC4
+generate_key:PSA_KEY_TYPE_ARC4:8:PSA_SUCCESS:
+
+PSA ARC4 128-bit
+depends_on:PSA_WANT_KEY_TYPE_ARC4
+generate_key:PSA_KEY_TYPE_ARC4:128:PSA_SUCCESS:
+
+PSA ARC4 2048-bit
+depends_on:PSA_WANT_KEY_TYPE_ARC4
+generate_key:PSA_KEY_TYPE_ARC4:2048:PSA_SUCCESS:
+
+PSA ARIA 128-bit
+depends_on:PSA_WANT_KEY_TYPE_ARIA
+generate_key:PSA_KEY_TYPE_ARIA:128:PSA_SUCCESS:
+
+PSA ARIA 192-bit
+depends_on:PSA_WANT_KEY_TYPE_ARIA
+generate_key:PSA_KEY_TYPE_ARIA:192:PSA_SUCCESS:
+
+PSA ARIA 256-bit
+depends_on:PSA_WANT_KEY_TYPE_ARIA
+generate_key:PSA_KEY_TYPE_ARIA:256:PSA_SUCCESS:
+
+PSA CAMELLIA 128-bit
+depends_on:PSA_WANT_KEY_TYPE_CAMELLIA
+generate_key:PSA_KEY_TYPE_CAMELLIA:128:PSA_SUCCESS:
+
+PSA CAMELLIA 192-bit
+depends_on:PSA_WANT_KEY_TYPE_CAMELLIA
+generate_key:PSA_KEY_TYPE_CAMELLIA:192:PSA_SUCCESS:
+
+PSA CAMELLIA 256-bit
+depends_on:PSA_WANT_KEY_TYPE_CAMELLIA
+generate_key:PSA_KEY_TYPE_CAMELLIA:256:PSA_SUCCESS:
+
+PSA CHACHA20 256-bit
+depends_on:PSA_WANT_KEY_TYPE_CHACHA20
+generate_key:PSA_KEY_TYPE_CHACHA20:256:PSA_SUCCESS:
+
+PSA DERIVE 120-bit
+depends_on:PSA_WANT_KEY_TYPE_DERIVE
+generate_key:PSA_KEY_TYPE_DERIVE:120:PSA_SUCCESS:
+
+PSA DERIVE 128-bit
+depends_on:PSA_WANT_KEY_TYPE_DERIVE
+generate_key:PSA_KEY_TYPE_DERIVE:128:PSA_SUCCESS:
+
+PSA DES 64-bit
+depends_on:PSA_WANT_KEY_TYPE_DES
+generate_key:PSA_KEY_TYPE_DES:64:PSA_SUCCESS:
+
+PSA DES 128-bit
+depends_on:PSA_WANT_KEY_TYPE_DES
+generate_key:PSA_KEY_TYPE_DES:128:PSA_SUCCESS:
+
+PSA DES 192-bit
+depends_on:PSA_WANT_KEY_TYPE_DES
+generate_key:PSA_KEY_TYPE_DES:192:PSA_SUCCESS:
+
+PSA HMAC 128-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+generate_key:PSA_KEY_TYPE_HMAC:128:PSA_SUCCESS:
+
+PSA HMAC 160-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+generate_key:PSA_KEY_TYPE_HMAC:160:PSA_SUCCESS:
+
+PSA HMAC 224-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+generate_key:PSA_KEY_TYPE_HMAC:224:PSA_SUCCESS:
+
+PSA HMAC 256-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+generate_key:PSA_KEY_TYPE_HMAC:256:PSA_SUCCESS:
+
+PSA HMAC 384-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+generate_key:PSA_KEY_TYPE_HMAC:384:PSA_SUCCESS:
+
+PSA HMAC 512-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+generate_key:PSA_KEY_TYPE_HMAC:512:PSA_SUCCESS:
+
+PSA RAW_DATA 8-bit
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+generate_key:PSA_KEY_TYPE_RAW_DATA:8:PSA_SUCCESS:
+
+PSA RAW_DATA 40-bit
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+generate_key:PSA_KEY_TYPE_RAW_DATA:40:PSA_SUCCESS:
+
+PSA RAW_DATA 128-bit
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+generate_key:PSA_KEY_TYPE_RAW_DATA:128:PSA_SUCCESS:
+
+PSA RSA_KEY_PAIR 1024-bit
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_GENPRIME
+generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_SUCCESS:
+
+PSA RSA_KEY_PAIR 1536-bit
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_GENPRIME
+generate_key:PSA_KEY_TYPE_RSA_KEY_PAIR:1536:PSA_SUCCESS:
+
+PSA RSA_PUBLIC_KEY 1024-bit
+generate_key:PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA RSA_PUBLIC_KEY 1536-bit
+generate_key:PSA_KEY_TYPE_RSA_PUBLIC_KEY:1536:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_KEY_PAIR(BRAINPOOL_P_R1) 160-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_160:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):160:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(BRAINPOOL_P_R1) 192-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_192:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):192:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(BRAINPOOL_P_R1) 224-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_224:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):224:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(BRAINPOOL_P_R1) 256-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_256
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):256:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(BRAINPOOL_P_R1) 320-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_320:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):320:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(BRAINPOOL_P_R1) 384-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_384
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):384:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(BRAINPOOL_P_R1) 512-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_512
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):512:PSA_SUCCESS:
+
+PSA ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 160-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):160:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 192-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):192:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 224-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):224:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 256-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):256:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 320-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):320:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 384-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):384:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 512-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):512:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_KEY_PAIR(MONTGOMERY) 255-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_MONTGOMERY_255
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):255:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(MONTGOMERY) 448-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_MONTGOMERY_448
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):448:PSA_SUCCESS:
+
+PSA ECC_PUBLIC_KEY(MONTGOMERY) 255-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_MONTGOMERY):255:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(MONTGOMERY) 448-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_MONTGOMERY):448:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_KEY_PAIR(SECP_K1) 192-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_K1_192
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):192:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(SECP_K1) 224-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_K1_224
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):224:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(SECP_K1) 256-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_K1_256
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):256:PSA_SUCCESS:
+
+PSA ECC_PUBLIC_KEY(SECP_K1) 192-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_K1):192:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(SECP_K1) 224-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_K1):224:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(SECP_K1) 256-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_K1):256:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_KEY_PAIR(SECP_R1) 225-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_225:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):225:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(SECP_R1) 256-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(SECP_R1) 384-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_384
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):384:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(SECP_R1) 521-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_521
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):521:PSA_SUCCESS:
+
+PSA ECC_PUBLIC_KEY(SECP_R1) 225-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):225:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(SECP_R1) 256-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):256:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(SECP_R1) 384-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):384:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(SECP_R1) 521-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):521:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_KEY_PAIR(SECP_R2) 160-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R2_160:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R2):160:PSA_SUCCESS:
+
+PSA ECC_PUBLIC_KEY(SECP_R2) 160-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R2):160:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_KEY_PAIR(SECT_K1) 163-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):163:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(SECT_K1) 233-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_233:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):233:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(SECT_K1) 239-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_239:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):239:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(SECT_K1) 283-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_283:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):283:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(SECT_K1) 409-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_409:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):409:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(SECT_K1) 571-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_571:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):571:PSA_SUCCESS:
+
+PSA ECC_PUBLIC_KEY(SECT_K1) 163-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):163:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(SECT_K1) 233-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):233:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(SECT_K1) 239-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):239:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(SECT_K1) 283-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):283:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(SECT_K1) 409-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):409:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(SECT_K1) 571-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):571:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_KEY_PAIR(SECT_R1) 163-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R1_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):163:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(SECT_R1) 233-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R1_233:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):233:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(SECT_R1) 283-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R1_283:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):283:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(SECT_R1) 409-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R1_409:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):409:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(SECT_R1) 571-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R1_571:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):571:PSA_SUCCESS:
+
+PSA ECC_PUBLIC_KEY(SECT_R1) 163-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):163:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(SECT_R1) 233-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):233:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(SECT_R1) 283-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):283:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(SECT_R1) 409-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):409:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(SECT_R1) 571-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):571:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_KEY_PAIR(SECT_R2) 163-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R2_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R2):163:PSA_SUCCESS:
+
+PSA ECC_PUBLIC_KEY(SECT_R2) 163-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R2):163:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_KEY_PAIR(TWISTED_EDWARDS) 255-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_TWISTED_EDWARDS_255:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):255:PSA_SUCCESS:
+
+PSA ECC_KEY_PAIR(TWISTED_EDWARDS) 448-bit
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_TWISTED_EDWARDS_448:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):448:PSA_SUCCESS:
+
+PSA ECC_PUBLIC_KEY(TWISTED_EDWARDS) 255-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS):255:PSA_ERROR_INVALID_ARGUMENT:
+
+PSA ECC_PUBLIC_KEY(TWISTED_EDWARDS) 448-bit
+generate_key:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS):448:PSA_ERROR_INVALID_ARGUMENT:
+
+# End of automatically generated file.
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_hash.data b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_hash.data
index 0e2d1b0..67158d0 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_hash.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_hash.data
@@ -1,587 +1,587 @@
 PSA hash finish: SHA-1 Test Vector NIST CAVS #1
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_finish:PSA_ALG_SHA_1:"":"da39a3ee5e6b4b0d3255bfef95601890afd80709"
 
 PSA hash finish: SHA-1 Test Vector NIST CAVS #2
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_finish:PSA_ALG_SHA_1:"a8":"99f2aa95e36f95c2acb0eaf23998f030638f3f15"
 
 PSA hash finish: SHA-1 Test Vector NIST CAVS #3
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_finish:PSA_ALG_SHA_1:"3000":"f944dcd635f9801f7ac90a407fbc479964dec024"
 
 PSA hash finish: SHA-1 Test Vector NIST CAVS #4
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_finish:PSA_ALG_SHA_1:"42749e":"a444319e9b6cc1e8464c511ec0969c37d6bb2619"
 
 PSA hash finish: SHA-1 Test Vector NIST CAVS #5
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_finish:PSA_ALG_SHA_1:"9fc3fe08":"16a0ff84fcc156fd5d3ca3a744f20a232d172253"
 
 PSA hash finish: SHA-1 Test Vector NIST CAVS #6
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_finish:PSA_ALG_SHA_1:"b5c1c6f1af":"fec9deebfcdedaf66dda525e1be43597a73a1f93"
 
 PSA hash finish: SHA-1 Test Vector NIST CAVS #7
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_finish:PSA_ALG_SHA_1:"ec29561244ede706b6eb30a1c371d74450a105c3f9735f7fa9fe38cf67f304a5736a106e92e17139a6813b1c81a4f3d3fb9546ab4296fa9f722826c066869edacd73b2548035185813e22634a9da44000d95a281ff9f264ecce0a931222162d021cca28db5f3c2aa24945ab1e31cb413ae29810fd794cad5dfaf29ec43cb38d198fe4ae1da2359780221405bd6712a5305da4b1b737fce7cd21c0eb7728d08235a9011":"970111c4e77bcc88cc20459c02b69b4aa8f58217"
 
 PSA hash finish: SHA-1 Test Vector NIST CAVS #8
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_finish:PSA_ALG_SHA_1:"5fc2c3f6a7e79dc94be526e5166a238899d54927ce470018fbfd668fd9dd97cbf64e2c91584d01da63be3cc9fdff8adfefc3ac728e1e335b9cdc87f069172e323d094b47fa1e652afe4d6aa147a9f46fda33cacb65f3aa12234746b9007a8c85fe982afed7815221e43dba553d8fe8a022cdac1b99eeeea359e5a9d2e72e382dffa6d19f359f4f27dc3434cd27daeeda8e38594873398678065fbb23665aba9309d946135da0e4a4afdadff14db18e85e71dd93c3bf9faf7f25c8194c4269b1ee3d9934097ab990025d9c3aaf63d5109f52335dd3959d38ae485050e4bbb6235574fc0102be8f7a306d6e8de6ba6becf80f37415b57f9898a5824e77414197422be3d36a6080":"0423dc76a8791107d14e13f5265b343f24cc0f19"
 
 PSA hash finish: SHA-1 Test Vector NIST CAVS #9
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_finish:PSA_ALG_SHA_1:"0f865f46a8f3aed2da18482aa09a8f390dc9da07d51d1bd10fe0bf5f3928d5927d08733d32075535a6d1c8ac1b2dc6ba0f2f633dc1af68e3f0fa3d85e6c60cb7b56c239dc1519a007ea536a07b518ecca02a6c31b46b76f021620ef3fc6976804018380e5ab9c558ebfc5cb1c9ed2d974722bf8ab6398f1f2b82fa5083f85c16a5767a3a07271d67743f00850ce8ec428c7f22f1cf01f99895c0c844845b06a06cecb0c6cf83eb55a1d4ebc44c2c13f6f7aa5e0e08abfd84e7864279057abc471ee4a45dbbb5774afa24e51791a0eada11093b88681fe30baa3b2e94113dc63342c51ca5d1a6096d0897b626e42cb91761058008f746f35465465540ad8c6b8b60f7e1461b3ce9e6529625984cb8c7d46f07f735be067588a0117f23e34ff57800e2bbe9a1605fde6087fb15d22c5d3ac47566b8c448b0cee40373e5ba6eaa21abee71366afbb27dbbd300477d70c371e7b8963812f5ed4fb784fb2f3bd1d3afe883cdd47ef32beaea":"6692a71d73e00f27df976bc56df4970650d90e45"
 
 PSA hash finish: SHA-1 Test Vector NIST CAVS #10
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_finish:PSA_ALG_SHA_1:"8236153781bd2f1b81ffe0def1beb46f5a70191142926651503f1b3bb1016acdb9e7f7acced8dd168226f118ff664a01a8800116fd023587bfba52a2558393476f5fc69ce9c65001f23e70476d2cc81c97ea19caeb194e224339bcb23f77a83feac5096f9b3090c51a6ee6d204b735aa71d7e996d380b80822e4dfd43683af9c7442498cacbea64842dfda238cb099927c6efae07fdf7b23a4e4456e0152b24853fe0d5de4179974b2b9d4a1cdbefcbc01d8d311b5dda059136176ea698ab82acf20dd490be47130b1235cb48f8a6710473cfc923e222d94b582f9ae36d4ca2a32d141b8e8cc36638845fbc499bce17698c3fecae2572dbbd470552430d7ef30c238c2124478f1f780483839b4fb73d63a9460206824a5b6b65315b21e3c2f24c97ee7c0e78faad3df549c7ca8ef241876d9aafe9a309f6da352bec2caaa92ee8dca392899ba67dfed90aef33d41fc2494b765cb3e2422c8e595dabbfaca217757453fb322a13203f425f6073a9903e2dc5818ee1da737afc345f0057744e3a56e1681c949eb12273a3bfc20699e423b96e44bd1ff62e50a848a890809bfe1611c6787d3d741103308f849a790f9c015098286dbacfc34c1718b2c2b77e32194a75dda37954a320fa68764027852855a7e5b5274eb1e2cbcd27161d98b59ad245822015f48af82a45c0ed59be94f9af03d9736048570d6e3ef63b1770bc98dfb77de84b1bb1708d872b625d9ab9b06c18e5dbbf34399391f0f8aa26ec0dac7ff4cb8ec97b52bcb942fa6db2385dcd1b3b9d567aaeb425d567b0ebe267235651a1ed9bf78fd93d3c1dd077fe340bb04b00529c58f45124b717c168d07e9826e33376988bc5cf62845c2009980a4dfa69fbc7e5a0b1bb20a5958ca967aec68eb31dd8fccca9afcd30a26bab26279f1bf6724ff":"11863b483809ef88413ca9b0084ac4a5390640af"
 
 PSA hash finish: SHA-224 Test Vector NIST CAVS #1
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_finish:PSA_ALG_SHA_224:"":"d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"
 
 PSA hash finish: SHA-224 Test Vector NIST CAVS #2
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_finish:PSA_ALG_SHA_224:"ff":"e33f9d75e6ae1369dbabf81b96b4591ae46bba30b591a6b6c62542b5"
 
 PSA hash finish: SHA-224 Test Vector NIST CAVS #3
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_finish:PSA_ALG_SHA_224:"984c":"2fa9df9157d9e027cfbc4c6a9df32e1adc0cbe2328ec2a63c5ae934e"
 
 PSA hash finish: SHA-224 Test Vector NIST CAVS #4
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_finish:PSA_ALG_SHA_224:"50efd0":"b5a9820413c2bf8211fbbf5df1337043b32fa4eafaf61a0c8e9ccede"
 
 PSA hash finish: SHA-224 Test Vector NIST CAVS #5
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_finish:PSA_ALG_SHA_224:"e5e09924":"fd19e74690d291467ce59f077df311638f1c3a46e510d0e49a67062d"
 
 PSA hash finish: SHA-224 Test Vector NIST CAVS #6
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_finish:PSA_ALG_SHA_224:"21ebecb914":"78f4a71c21c694499ce1c7866611b14ace70d905012c356323c7c713"
 
 PSA hash finish: SHA-224 Test Vector NIST CAVS #7
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_finish:PSA_ALG_SHA_224:"fc488947c1a7a589726b15436b4f3d9556262f98fc6422fc5cdf20f0fad7fe427a3491c86d101ffe6b7514f06268f65b2d269b0f69ad9a97847eff1c16a2438775eb7be6847ccf11cb8b2e8dcd6640b095b49c0693fe3cf4a66e2d9b7ad68bff14f3ad69abf49d0aba36cbe0535202deb6599a47225ef05beb351335cd7bc0f480d691198c7e71305ffd53b39d33242bb79cfd98bfd69e137b5d18b2b89ac9ace01c8dbdcf2533cce3682ecc52118de0c1062ec2126c2e657d6ea3d9e2398e705d4b0b1f1ceecb266dffc4f31bf42744fb1e938dc22a889919ee1e73f463f7871fed720519e32186264b7ef2a0e5d9a18e6c95c0781894f77967f048951dec3b4d892a38710b1e3436d3c29088eb8b3da1789c25db3d3bc6c26081206e7155d210a89b80ca6ea877c41ff9947c0f25625dcb118294a163501f6239c326661a958fd12da4cd15a899f8b88cc723589056eaec5aa04a4cf5dbb6f480f9660423ccf38c486e210707e0fb25e1f126ceb2616f63e147a647dab0af9ebe89d65458bf636154a46e4cab95f5ee62da2c7974cd14b90d3e4f99f81733e85b3c1d5da2b508d9b90f5eed7eff0d9c7649de62bee00375454fee4a39576a5bbfdae428e7f8097bdf7797f167686cb68407e49079e4611ff3402b6384ba7b7e522bd2bb11ce8fd02ea4c1604d163ac4f6dde50b8b1f593f7edaadeac0868ed97df690200680c25f0f5d85431a529e4f339089dcdeda105e4ee51dead704cdf5a605c55fb055c9b0e86b8ba1b564c0dea3eb790a595cb103cb292268b07c5e59371e1a7ef597cd4b22977a820694c9f9aeb55d9de3ef62b75d6e656e3336698d960a3787bf8cf5b926a7faeef52ae128bcb5dc9e66d94b016c7b8e034879171a2d91c381f57e6a815b63b5ee6a6d2ff435b49f14c963966960194430d78f8f87627a67757fb3532b289550894da6dce4817a4e07f4d56877a1102ffcc8befa5c9f8fca6a4574d93ff70376c8861e0f8108cf907fce77ecb49728f86f034f80224b9695682e0824462f76cdb1fd1af151337b0d85419047a7aa284791718a4860cd586f7824b95bc837b6fd4f9be5aade68456e20356aa4d943dac36bf8b67b9e8f9d01a00fcda74b798bafa746c661b010f75b59904b29d0c8041504811c4065f82cf2ead58d2f595cbd8bc3e7043f4d94577b373b7cfe16a36fe564f505c03b70cfeb5e5f411c79481338aa67e86b3f5a2e77c21e454c333ae3da943ab723ab5f4c940395319534a5575f64acba0d0ecc43f60221ed3badf7289c9b3a7b903a2d6c94e15fa4c310dc4fa7faa0c24f405160a1002dbef20e4105d481db982f7243f79400a6e4cd9753c4b9732a47575f504b20c328fe9add7f432a4f075829da07b53b695037dc51737d3cd731934df333cd1a53fcf65aa31baa450ca501a6fae26e322347e618c5a444d92e9fec5a8261ae38b98fee5be77c02cec09ddccd5b3de92036":"1302149d1e197c41813b054c942329d420e366530f5517b470e964fe"
 
 PSA hash finish: SHA-256 Test Vector NIST CAVS #1
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_finish:PSA_ALG_SHA_256:"":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
 
 PSA hash finish: SHA-256 Test Vector NIST CAVS #2
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_finish:PSA_ALG_SHA_256:"bd":"68325720aabd7c82f30f554b313d0570c95accbb7dc4b5aae11204c08ffe732b"
 
 PSA hash finish: SHA-256 Test Vector NIST CAVS #3
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_finish:PSA_ALG_SHA_256:"5fd4":"7c4fbf484498d21b487b9d61de8914b2eadaf2698712936d47c3ada2558f6788"
 
 PSA hash finish: SHA-256 Test Vector NIST CAVS #4
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_finish:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803"
 
 PSA hash finish: SHA-256 Test Vector NIST CAVS #5
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_finish:PSA_ALG_SHA_256:"c98c8e55":"7abc22c0ae5af26ce93dbb94433a0e0b2e119d014f8e7f65bd56c61ccccd9504"
 
 PSA hash finish: SHA-256 Test Vector NIST CAVS #6
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_finish:PSA_ALG_SHA_256:"81a723d966":"7516fb8bb11350df2bf386bc3c33bd0f52cb4c67c6e4745e0488e62c2aea2605"
 
 PSA hash finish: SHA-256 Test Vector NIST CAVS #7
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_finish:PSA_ALG_SHA_256:"8390cf0be07661cc7669aac54ce09a37733a629d45f5d983ef201f9b2d13800e555d9b1097fec3b783d7a50dcb5e2b644b96a1e9463f177cf34906bf388f366db5c2deee04a30e283f764a97c3b377a034fefc22c259214faa99babaff160ab0aaa7e2ccb0ce09c6b32fe08cbc474694375aba703fadbfa31cf685b30a11c57f3cf4edd321e57d3ae6ebb1133c8260e75b9224fa47a2bb205249add2e2e62f817491482ae152322be0900355cdcc8d42a98f82e961a0dc6f537b7b410eff105f59673bfb787bf042aa071f7af68d944d27371c64160fe9382772372516c230c1f45c0d6b6cca7f274b394da9402d3eafdf733994ec58ab22d71829a98399574d4b5908a447a5a681cb0dd50a31145311d92c22a16de1ead66a5499f2dceb4cae694772ce90762ef8336afec653aa9b1a1c4820b221136dfce80dce2ba920d88a530c9410d0a4e0358a3a11052e58dd73b0b179ef8f56fe3b5a2d117a73a0c38a1392b6938e9782e0d86456ee4884e3c39d4d75813f13633bc79baa07c0d2d555afbf207f52b7dca126d015aa2b9873b3eb065e90b9b065a5373fe1fb1b20d594327d19fba56cb81e7b6696605ffa56eba3c27a438697cc21b201fd7e09f18deea1b3ea2f0d1edc02df0e20396a145412cd6b13c32d2e605641c948b714aec30c0649dc44143511f35ab0fd5dd64c34d06fe86f3836dfe9edeb7f08cfc3bd40956826356242191f99f53473f32b0cc0cf9321d6c92a112e8db90b86ee9e87cc32d0343db01e32ce9eb782cb24efbbbeb440fe929e8f2bf8dfb1550a3a2e742e8b455a3e5730e9e6a7a9824d17acc0f72a7f67eae0f0970f8bde46dcdefaed3047cf807e7f00a42e5fd11d40f5e98533d7574425b7d2bc3b3845c443008b58980e768e464e17cc6f6b3939eee52f713963d07d8c4abf02448ef0b889c9671e2f8a436ddeeffcca7176e9bf9d1005ecd377f2fa67c23ed1f137e60bf46018a8bd613d038e883704fc26e798969df35ec7bbc6a4fe46d8910bd82fa3cded265d0a3b6d399e4251e4d8233daa21b5812fded6536198ff13aa5a1cd46a5b9a17a4ddc1d9f85544d1d1cc16f3df858038c8e071a11a7e157a85a6a8dc47e88d75e7009a8b26fdb73f33a2a70f1e0c259f8f9533b9b8f9af9288b7274f21baeec78d396f8bacdcc22471207d9b4efccd3fedc5c5a2214ff5e51c553f35e21ae696fe51e8df733a8e06f50f419e599e9f9e4b37ce643fc810faaa47989771509d69a110ac916261427026369a21263ac4460fb4f708f8ae28599856db7cb6a43ac8e03d64a9609807e76c5f312b9d1863bfa304e8953647648b4f4ab0ed995e":"4109cdbec3240ad74cc6c37f39300f70fede16e21efc77f7865998714aad0b5e"
 
 PSA hash finish: SHA-384 Test Vector NIST CAVS #1
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_finish:PSA_ALG_SHA_384:"":"38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"
 
 PSA hash finish: SHA-384 Test Vector NIST CAVS #2
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_finish:PSA_ALG_SHA_384:"ab":"fb94d5be118865f6fcbc978b825da82cff188faec2f66cb84b2537d74b4938469854b0ca89e66fa2e182834736629f3d"
 
 PSA hash finish: SHA-384 Test Vector NIST CAVS #3
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_finish:PSA_ALG_SHA_384:"7c27":"3d80be467df86d63abb9ea1d3f9cb39cd19890e7f2c53a6200bedc5006842b35e820dc4e0ca90ca9b97ab23ef07080fc"
 
 PSA hash finish: SHA-384 Test Vector NIST CAVS #4
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_finish:PSA_ALG_SHA_384:"31f5ca":"78d54b943421fdf7ba90a7fb9637c2073aa480454bd841d39ff72f4511fc21fb67797b652c0c823229342873d3bef955"
 
 PSA hash finish: SHA-384 Test Vector NIST CAVS #5
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_finish:PSA_ALG_SHA_384:"7bdee3f8":"8bdafba0777ee446c3431c2d7b1fbb631089f71d2ca417abc1d230e1aba64ec2f1c187474a6f4077d372c14ad407f99a"
 
 PSA hash finish: SHA-384 Test Vector NIST CAVS #6
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_finish:PSA_ALG_SHA_384:"8f05604915":"504e414bf1db1060f14c8c799e25b1e0c4dcf1504ebbd129998f0ae283e6de86e0d3c7e879c73ec3b1836c3ee89c2649"
 
 PSA hash finish: SHA-384 Test Vector NIST CAVS #7
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_finish:PSA_ALG_SHA_384:"665da6eda214":"4c022f112010908848312f8b8f1072625fd5c105399d562ea1d56130619a7eac8dfc3748fd05ee37e4b690be9daa9980"
 
 PSA hash finish: SHA-384 Test Vector NIST CAVS #8
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_finish:PSA_ALG_SHA_384:"7f46ce506d593c4ed53c82edeb602037e0485befbee03f7f930fe532d18ff2a3f5fd6076672c8145a1bf40dd94f7abab47c9ae71c234213d2ad1069c2dac0b0ba15257ae672b8245960ae55bd50315c0097daa3a318745788d70d14706910809ca6e396237fe4934fa46f9ce782d66606d8bd6b2d283b1160513ce9c24e9f084b97891f99d4cdefc169a029e431ca772ba1bba426fce6f01d8e286014e5acc66b799e4db62bd4783322f8a32ff78e0de3957df50ce10871f4e0680df4e8ca3960af9bc6f4efa8eb3962d18f474eb178c3265cc46b8f2ff5ab1a7449fea297dfcfabfa01f28abbb7289bb354b691b5664ec6d098af51be19947ec5ba7ebd66380d1141953ba78d4aa5401679fa7b0a44db1981f864d3535c45afe4c61183d5b0ad51fae71ca07e34240283959f7530a32c70d95a088e501c230059f333b0670825009e7e22103ef22935830df1fac8ef877f5f3426dd54f7d1128dd871ad9a7d088f94c0e8712013295b8d69ae7623b880978c2d3c6ad26dc478f8dc47f5c0adcc618665dc3dc205a9071b2f2191e16cac5bd89bb59148fc719633752303aa08e518dbc389f0a5482caaa4c507b8729a6f3edd061efb39026cecc6399f51971cf7381d605e144a5928c8c2d1ad7467b05da2f202f4f3234e1aff19a0198a28685721c3d2d52311c721e3fdcbaf30214cdc3acff8c433880e104fb63f2df7ce69a97857819ba7ac00ac8eae1969764fde8f68cf8e0916d7e0c151147d4944f99f42ae50f30e1c79a42d2b6c5188d133d3cbbf69094027b354b295ccd0f7dc5a87d73638bd98ebfb00383ca0fa69cb8dcb35a12510e5e07ad8789047d0b63841a1bb928737e8b0a0c33254f47aa8bfbe3341a09c2b76dbcefa67e30df300d34f7b8465c4f869e51b6bcfe6cf68b238359a645036bf7f63f02924e087ce7457e483b6025a859903cb484574aa3b12cf946f32127d537c33bee3141b5db96d10a148c50ae045f287210757710d6846e04b202f79e87dd9a56bc6da15f84a77a7f63935e1dee00309cd276a8e7176cb04da6bb0e9009534438732cb42d008008853d38d19beba46e61006e30f7efd1bc7c2906b024e4ff898a1b58c448d68b43c6ab63f34f85b3ac6aa4475867e51b583844cb23829f4b30f4bdd817d88e2ef3e7b4fc0a624395b05ec5e8686082b24d29fef2b0d3c29e031d5f94f504b1d3df9361eb5ffbadb242e66c39a8094cfe62f85f639f3fd65fc8ae0c74a8f4c6e1d070b9183a434c722caaa0225f8bcd68614d6f0738ed62f8484ec96077d155c08e26c46be262a73e3551698bd70d8d5610cf37c4c306eed04ba6a040a9c3e6d7e15e8acda17f477c2484cf5c56b813313927be8387b1024f995e98fc87f1029091c01424bdc2b296c2eadb7d25b3e762a2fd0c2dcd1727ddf91db97c5984305265f3695a7f5472f2d72c94d68c27914f14f82aa8dd5fe4e2348b0ca967a3f98626a091552f5d0ffa2bf10350d23c996256c01fdeffb2c2c612519869f877e4929c6e95ff15040f1485e22ed14119880232fef3b57b3848f15b1766a5552879df8f06":"cba9e3eb12a6f83db11e8a6ff40d1049854ee094416bc527fea931d8585428a8ed6242ce81f6769b36e2123a5c23483e"
 
 PSA hash finish: SHA-512 Test Vector NIST CAVS #1
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_finish:PSA_ALG_SHA_512:"":"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
 
 PSA hash finish: SHA-512 Test Vector NIST CAVS #2
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_finish:PSA_ALG_SHA_512:"8f":"e4cd2d19931b5aad9c920f45f56f6ce34e3d38c6d319a6e11d0588ab8b838576d6ce6d68eea7c830de66e2bd96458bfa7aafbcbec981d4ed040498c3dd95f22a"
 
 PSA hash finish: SHA-512 Test Vector NIST CAVS #3
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_finish:PSA_ALG_SHA_512:"e724":"7dbb520221a70287b23dbcf62bfc1b73136d858e86266732a7fffa875ecaa2c1b8f673b5c065d360c563a7b9539349f5f59bef8c0c593f9587e3cd50bb26a231"
 
 PSA hash finish: SHA-512 Test Vector NIST CAVS #4
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_finish:PSA_ALG_SHA_512:"de4c90":"33ce98281045a5c4c9df0363d8196f1d7dfcd5ee46ac89776fd8a4344c12f123a66788af5bd41ceff1941aa5637654b4064c88c14e00465ab79a2fc6c97e1014"
 
 PSA hash finish: SHA-512 Test Vector NIST CAVS #5
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_finish:PSA_ALG_SHA_512:"a801e94b":"dadb1b5a27f9fece8d86adb2a51879beb1787ff28f4e8ce162cad7fee0f942efcabbf738bc6f797fc7cc79a3a75048cd4c82ca0757a324695bfb19a557e56e2f"
 
 PSA hash finish: SHA-512 Test Vector NIST CAVS #6
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_finish:PSA_ALG_SHA_512:"94390d3502":"b6175c4c4cccf69e0ce5f0312010886ea6b34d43673f942ae42483f9cbb7da817de4e11b5d58e25a3d9bd721a22cdffe1c40411cc45df1911fa5506129b69297"
 
 PSA hash finish: SHA-512 Test Vector NIST CAVS #7
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_finish:PSA_ALG_SHA_512:"49297dd63e5f":"1fcc1e6f6870859d11649f5e5336a9cd16329c029baf04d5a6edf257889a2e9522b497dd656bb402da461307c4ee382e2e89380c8e6e6e7697f1e439f650fa94"
 
 PSA hash finish: SHA-512 Test Vector NIST CAVS #8
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_finish:PSA_ALG_SHA_512:"990d1ae71a62d7bda9bfdaa1762a68d296eee72a4cd946f287a898fbabc002ea941fd8d4d991030b4d27a637cce501a834bb95eab1b7889a3e784c7968e67cbf552006b206b68f76d9191327524fcc251aeb56af483d10b4e0c6c5e599ee8c0fe4faeca8293844a8547c6a9a90d093f2526873a19ad4a5e776794c68c742fb834793d2dfcb7fea46c63af4b70fd11cb6e41834e72ee40edb067b292a794990c288d5007e73f349fb383af6a756b8301ad6e5e0aa8cd614399bb3a452376b1575afa6bdaeaafc286cb064bb91edef97c632b6c1113d107fa93a0905098a105043c2f05397f702514439a08a9e5ddc196100721d45c8fc17d2ed659376f8a00bd5cb9a0860e26d8a29d8d6aaf52de97e9346033d6db501a35dbbaf97c20b830cd2d18c2532f3a59cc497ee64c0e57d8d060e5069b28d86edf1adcf59144b221ce3ddaef134b3124fbc7dd000240eff0f5f5f41e83cd7f5bb37c9ae21953fe302b0f6e8b68fa91c6ab99265c64b2fd9cd4942be04321bb5d6d71932376c6f2f88e02422ba6a5e2cb765df93fd5dd0728c6abdaf03bce22e0678a544e2c3636f741b6f4447ee58a8fc656b43ef817932176adbfc2e04b2c812c273cd6cbfa4098f0be036a34221fa02643f5ee2e0b38135f2a18ecd2f16ebc45f8eb31b8ab967a1567ee016904188910861ca1fa205c7adaa194b286893ffe2f4fbe0384c2aef72a4522aeafd3ebc71f9db71eeeef86c48394a1c86d5b36c352cc33a0a2c800bc99e62fd65b3a2fd69e0b53996ec13d8ce483ce9319efd9a85acefabdb5342226febb83fd1daf4b24265f50c61c6de74077ef89b6fecf9f29a1f871af1e9f89b2d345cda7499bd45c42fa5d195a1e1a6ba84851889e730da3b2b916e96152ae0c92154b49719841db7e7cc707ba8a5d7b101eb4ac7b629bb327817910fff61580b59aab78182d1a2e33473d05b00b170b29e331870826cfe45af206aa7d0246bbd8566ca7cfb2d3c10bfa1db7dd48dd786036469ce7282093d78b5e1a5b0fc81a54c8ed4ceac1e5305305e78284ac276f5d7862727aff246e17addde50c670028d572cbfc0be2e4f8b2eb28fa68ad7b4c6c2a239c460441bfb5ea049f23b08563b4e47729a59e5986a61a6093dbd54f8c36ebe87edae01f251cb060ad1364ce677d7e8d5a4a4ca966a7241cc360bc2acb280e5f9e9c1b032ad6a180a35e0c5180b9d16d026c865b252098cc1d99ba7375ca31c7702c0d943d5e3dd2f6861fa55bd46d94b67ed3e52eccd8dd06d968e01897d6de97ed3058d91dd":"8e4bc6f8b8c60fe4d68c61d9b159c8693c3151c46749af58da228442d927f23359bd6ccd6c2ec8fa3f00a86cecbfa728e1ad60b821ed22fcd309ba91a4138bc9"
 
 PSA hash finish: MD2 Test vector RFC1319 #1
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_finish:PSA_ALG_MD2:"":"8350e5a3e24c153df2275c9f80692773"
 
 PSA hash finish: MD2 Test vector RFC1319 #2
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_finish:PSA_ALG_MD2:"61":"32ec01ec4a6dac72c0ab96fb34c0b5d1"
 
 PSA hash finish: MD2 Test vector RFC1319 #3
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_finish:PSA_ALG_MD2:"616263":"da853b0d3f88d99b30283a69e6ded6bb"
 
 PSA hash finish: MD2 Test vector RFC1319 #4
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_finish:PSA_ALG_MD2:"6d65737361676520646967657374":"ab4f496bfb2a530b219ff33031fe06b0"
 
 PSA hash finish: MD2 Test vector RFC1319 #5
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_finish:PSA_ALG_MD2:"6162636465666768696a6b6c6d6e6f707172737475767778797a":"4e8ddff3650292ab5a4108c3aa47940b"
 
 PSA hash finish: MD2 Test vector RFC1319 #6
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_finish:PSA_ALG_MD2:"4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a30313233343536373839":"da33def2a42df13975352846c30338cd"
 
 PSA hash finish: MD2 Test vector RFC1319 #7
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_finish:PSA_ALG_MD2:"3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930":"d5976f79d83d3a0dc9806c3c66f3efd8"
 
 PSA hash finish: MD4 Test vector RFC1320 #1
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_finish:PSA_ALG_MD4:"":"31d6cfe0d16ae931b73c59d7e0c089c0"
 
 PSA hash finish: MD4 Test vector RFC1320 #2
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_finish:PSA_ALG_MD4:"61":"bde52cb31de33e46245e05fbdbd6fb24"
 
 PSA hash finish: MD4 Test vector RFC1320 #3
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_finish:PSA_ALG_MD4:"616263":"a448017aaf21d8525fc10ae87aa6729d"
 
 PSA hash finish: MD4 Test vector RFC1320 #4
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_finish:PSA_ALG_MD4:"6d65737361676520646967657374":"d9130a8164549fe818874806e1c7014b"
 
 PSA hash finish: MD4 Test vector RFC1320 #5
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_finish:PSA_ALG_MD4:"6162636465666768696a6b6c6d6e6f707172737475767778797a":"d79e1c308aa5bbcdeea8ed63df412da9"
 
 PSA hash finish: MD4 Test vector RFC1320 #6
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_finish:PSA_ALG_MD4:"4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a30313233343536373839":"043f8582f241db351ce627e153e7f0e4"
 
 PSA hash finish: MD4 Test vector RFC1320 #7
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_finish:PSA_ALG_MD4:"3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930":"e33b4ddc9c38f2199c3e7b164fcc0536"
 
 PSA hash finish: MD5 Test vector RFC1321 #1
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_finish:PSA_ALG_MD5:"":"d41d8cd98f00b204e9800998ecf8427e"
 
 PSA hash finish: MD5 Test vector RFC1321 #2
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_finish:PSA_ALG_MD5:"61":"0cc175b9c0f1b6a831c399e269772661"
 
 PSA hash finish: MD5 Test vector RFC1321 #3
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_finish:PSA_ALG_MD5:"616263":"900150983cd24fb0d6963f7d28e17f72"
 
 PSA hash finish: MD5 Test vector RFC1321 #4
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_finish:PSA_ALG_MD5:"6d65737361676520646967657374":"f96b697d7cb7938d525a2f31aaf161d0"
 
 PSA hash finish: MD5 Test vector RFC1321 #5
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_finish:PSA_ALG_MD5:"6162636465666768696a6b6c6d6e6f707172737475767778797a":"c3fcd3d76192e4007dfb496cca67e13b"
 
 PSA hash finish: MD5 Test vector RFC1321 #6
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_finish:PSA_ALG_MD5:"4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a30313233343536373839":"d174ab98d277d9f5a5611c2c9f419d9f"
 
 PSA hash finish: MD5 Test vector RFC1321 #7
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_finish:PSA_ALG_MD5:"3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930":"57edf4a22be3c955ac49da2e2107b67a"
 
 PSA hash finish: RIPEMD160 Test vector from paper #1
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_finish:PSA_ALG_RIPEMD160:"":"9c1185a5c5e9fc54612808977ee8f548b2258d31"
 
 PSA hash finish: RIPEMD160 Test vector from paper #2
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_finish:PSA_ALG_RIPEMD160:"61":"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"
 
 PSA hash finish: RIPEMD160 Test vector from paper #3
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_finish:PSA_ALG_RIPEMD160:"616263":"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"
 
 PSA hash finish: RIPEMD160 Test vector from paper #4
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_finish:PSA_ALG_RIPEMD160:"6d65737361676520646967657374":"5d0689ef49d2fae572b881b123a85ffa21595f36"
 
 PSA hash finish: RIPEMD160 Test vector from paper #5
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_finish:PSA_ALG_RIPEMD160:"6162636465666768696a6b6c6d6e6f707172737475767778797a":"f71c27109c692c1b56bbdceb5b9d2865b3708dbc"
 
 PSA hash finish: RIPEMD160 Test vector from paper #6
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_finish:PSA_ALG_RIPEMD160:"6162636462636465636465666465666765666768666768696768696a68696a6b696a6b6c6a6b6c6d6b6c6d6e6c6d6e6f6d6e6f706e6f7071":"12a053384a9c0c88e405a06c27dcf49ada62eb2b"
 
 PSA hash finish: RIPEMD160 Test vector from paper #7
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_finish:PSA_ALG_RIPEMD160:"4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a30313233343536373839":"b0e20b6e3116640286ed3a87a5713079b21f5189"
 
 PSA hash finish: RIPEMD160 Test vector from paper #8
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_finish:PSA_ALG_RIPEMD160:"3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930":"9b752e45573d4b39f4dbd3323cab82bf63326bfb"
 
 PSA hash verify: SHA-1
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_verify:PSA_ALG_SHA_1:"bd":"9034aaf45143996a2b14465c352ab0c6fa26b221"
 
 PSA hash verify: SHA-224
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_verify:PSA_ALG_SHA_224:"bd":"b1e46bb9efe45af554363449c6945a0d6169fc3a5a396a56cb97cb57"
 
 PSA hash verify: SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_verify:PSA_ALG_SHA_256:"bd":"68325720aabd7c82f30f554b313d0570c95accbb7dc4b5aae11204c08ffe732b"
 
 PSA hash verify: SHA-384
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_verify:PSA_ALG_SHA_384:"bd":"4372e38a92a28b5d2c391e62452a86d50e0267228be176c77d2402effe9fa50de407bbb851b37d5904aba2dede74da2a"
 
 PSA hash verify: SHA-512
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_verify:PSA_ALG_SHA_512:"bd":"296e2267d74c278daaaa940d17b0cfb74a5083f8e069726d8c841cbe596e0431cb7741a5b50f71666cfd54bacb7b00aea891499cf4ef6a03c8a83fe37c3f7baf"
 
 PSA hash verify: MD2
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_verify:PSA_ALG_MD2:"bd":"8c9c17665d25b35fc413c41805c679cf"
 
 PSA hash verify: MD4
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_verify:PSA_ALG_MD4:"bd":"18c33f97297efe5f8a732258289fda25"
 
 PSA hash verify: MD5
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_verify:PSA_ALG_MD5:"bd":"abae57cb562ecf295b4a37a76efe61fb"
 
 PSA hash verify: RIPEMD160
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_verify:PSA_ALG_RIPEMD160:"bd":"5089265ee5d9af75d12dbf7ea2f27dbdee435b37"
 
 PSA hash multi part: SHA-1 Test Vector NIST CAVS #1
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_multi_part:PSA_ALG_SHA_1:"":"da39a3ee5e6b4b0d3255bfef95601890afd80709"
 
 PSA hash multi part: SHA-1 Test Vector NIST CAVS #2
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_multi_part:PSA_ALG_SHA_1:"a8":"99f2aa95e36f95c2acb0eaf23998f030638f3f15"
 
 PSA hash multi part: SHA-1 Test Vector NIST CAVS #3
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_multi_part:PSA_ALG_SHA_1:"3000":"f944dcd635f9801f7ac90a407fbc479964dec024"
 
 PSA hash multi part: SHA-1 Test Vector NIST CAVS #4
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_multi_part:PSA_ALG_SHA_1:"42749e":"a444319e9b6cc1e8464c511ec0969c37d6bb2619"
 
 PSA hash multi part: SHA-1 Test Vector NIST CAVS #5
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_multi_part:PSA_ALG_SHA_1:"9fc3fe08":"16a0ff84fcc156fd5d3ca3a744f20a232d172253"
 
 PSA hash multi part: SHA-1 Test Vector NIST CAVS #6
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_multi_part:PSA_ALG_SHA_1:"b5c1c6f1af":"fec9deebfcdedaf66dda525e1be43597a73a1f93"
 
 PSA hash multi part: SHA-1 Test Vector NIST CAVS #7
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_multi_part:PSA_ALG_SHA_1:"ec29561244ede706b6eb30a1c371d74450a105c3f9735f7fa9fe38cf67f304a5736a106e92e17139a6813b1c81a4f3d3fb9546ab4296fa9f722826c066869edacd73b2548035185813e22634a9da44000d95a281ff9f264ecce0a931222162d021cca28db5f3c2aa24945ab1e31cb413ae29810fd794cad5dfaf29ec43cb38d198fe4ae1da2359780221405bd6712a5305da4b1b737fce7cd21c0eb7728d08235a9011":"970111c4e77bcc88cc20459c02b69b4aa8f58217"
 
 PSA hash multi part: SHA-1 Test Vector NIST CAVS #8
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_multi_part:PSA_ALG_SHA_1:"5fc2c3f6a7e79dc94be526e5166a238899d54927ce470018fbfd668fd9dd97cbf64e2c91584d01da63be3cc9fdff8adfefc3ac728e1e335b9cdc87f069172e323d094b47fa1e652afe4d6aa147a9f46fda33cacb65f3aa12234746b9007a8c85fe982afed7815221e43dba553d8fe8a022cdac1b99eeeea359e5a9d2e72e382dffa6d19f359f4f27dc3434cd27daeeda8e38594873398678065fbb23665aba9309d946135da0e4a4afdadff14db18e85e71dd93c3bf9faf7f25c8194c4269b1ee3d9934097ab990025d9c3aaf63d5109f52335dd3959d38ae485050e4bbb6235574fc0102be8f7a306d6e8de6ba6becf80f37415b57f9898a5824e77414197422be3d36a6080":"0423dc76a8791107d14e13f5265b343f24cc0f19"
 
 PSA hash multi part: SHA-1 Test Vector NIST CAVS #9
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_multi_part:PSA_ALG_SHA_1:"0f865f46a8f3aed2da18482aa09a8f390dc9da07d51d1bd10fe0bf5f3928d5927d08733d32075535a6d1c8ac1b2dc6ba0f2f633dc1af68e3f0fa3d85e6c60cb7b56c239dc1519a007ea536a07b518ecca02a6c31b46b76f021620ef3fc6976804018380e5ab9c558ebfc5cb1c9ed2d974722bf8ab6398f1f2b82fa5083f85c16a5767a3a07271d67743f00850ce8ec428c7f22f1cf01f99895c0c844845b06a06cecb0c6cf83eb55a1d4ebc44c2c13f6f7aa5e0e08abfd84e7864279057abc471ee4a45dbbb5774afa24e51791a0eada11093b88681fe30baa3b2e94113dc63342c51ca5d1a6096d0897b626e42cb91761058008f746f35465465540ad8c6b8b60f7e1461b3ce9e6529625984cb8c7d46f07f735be067588a0117f23e34ff57800e2bbe9a1605fde6087fb15d22c5d3ac47566b8c448b0cee40373e5ba6eaa21abee71366afbb27dbbd300477d70c371e7b8963812f5ed4fb784fb2f3bd1d3afe883cdd47ef32beaea":"6692a71d73e00f27df976bc56df4970650d90e45"
 
 PSA hash multi part: SHA-1 Test Vector NIST CAVS #10
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_multi_part:PSA_ALG_SHA_1:"8236153781bd2f1b81ffe0def1beb46f5a70191142926651503f1b3bb1016acdb9e7f7acced8dd168226f118ff664a01a8800116fd023587bfba52a2558393476f5fc69ce9c65001f23e70476d2cc81c97ea19caeb194e224339bcb23f77a83feac5096f9b3090c51a6ee6d204b735aa71d7e996d380b80822e4dfd43683af9c7442498cacbea64842dfda238cb099927c6efae07fdf7b23a4e4456e0152b24853fe0d5de4179974b2b9d4a1cdbefcbc01d8d311b5dda059136176ea698ab82acf20dd490be47130b1235cb48f8a6710473cfc923e222d94b582f9ae36d4ca2a32d141b8e8cc36638845fbc499bce17698c3fecae2572dbbd470552430d7ef30c238c2124478f1f780483839b4fb73d63a9460206824a5b6b65315b21e3c2f24c97ee7c0e78faad3df549c7ca8ef241876d9aafe9a309f6da352bec2caaa92ee8dca392899ba67dfed90aef33d41fc2494b765cb3e2422c8e595dabbfaca217757453fb322a13203f425f6073a9903e2dc5818ee1da737afc345f0057744e3a56e1681c949eb12273a3bfc20699e423b96e44bd1ff62e50a848a890809bfe1611c6787d3d741103308f849a790f9c015098286dbacfc34c1718b2c2b77e32194a75dda37954a320fa68764027852855a7e5b5274eb1e2cbcd27161d98b59ad245822015f48af82a45c0ed59be94f9af03d9736048570d6e3ef63b1770bc98dfb77de84b1bb1708d872b625d9ab9b06c18e5dbbf34399391f0f8aa26ec0dac7ff4cb8ec97b52bcb942fa6db2385dcd1b3b9d567aaeb425d567b0ebe267235651a1ed9bf78fd93d3c1dd077fe340bb04b00529c58f45124b717c168d07e9826e33376988bc5cf62845c2009980a4dfa69fbc7e5a0b1bb20a5958ca967aec68eb31dd8fccca9afcd30a26bab26279f1bf6724ff":"11863b483809ef88413ca9b0084ac4a5390640af"
 
 PSA hash multi part: SHA-224 Test Vector NIST CAVS #1
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_multi_part:PSA_ALG_SHA_224:"":"d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"
 
 PSA hash multi part: SHA-224 Test Vector NIST CAVS #2
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_multi_part:PSA_ALG_SHA_224:"ff":"e33f9d75e6ae1369dbabf81b96b4591ae46bba30b591a6b6c62542b5"
 
 PSA hash multi part: SHA-224 Test Vector NIST CAVS #3
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_multi_part:PSA_ALG_SHA_224:"984c":"2fa9df9157d9e027cfbc4c6a9df32e1adc0cbe2328ec2a63c5ae934e"
 
 PSA hash multi part: SHA-224 Test Vector NIST CAVS #4
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_multi_part:PSA_ALG_SHA_224:"50efd0":"b5a9820413c2bf8211fbbf5df1337043b32fa4eafaf61a0c8e9ccede"
 
 PSA hash multi part: SHA-224 Test Vector NIST CAVS #5
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_multi_part:PSA_ALG_SHA_224:"e5e09924":"fd19e74690d291467ce59f077df311638f1c3a46e510d0e49a67062d"
 
 PSA hash multi part: SHA-224 Test Vector NIST CAVS #6
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_multi_part:PSA_ALG_SHA_224:"21ebecb914":"78f4a71c21c694499ce1c7866611b14ace70d905012c356323c7c713"
 
 PSA hash multi part: SHA-224 Test Vector NIST CAVS #7
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_multi_part:PSA_ALG_SHA_224:"fc488947c1a7a589726b15436b4f3d9556262f98fc6422fc5cdf20f0fad7fe427a3491c86d101ffe6b7514f06268f65b2d269b0f69ad9a97847eff1c16a2438775eb7be6847ccf11cb8b2e8dcd6640b095b49c0693fe3cf4a66e2d9b7ad68bff14f3ad69abf49d0aba36cbe0535202deb6599a47225ef05beb351335cd7bc0f480d691198c7e71305ffd53b39d33242bb79cfd98bfd69e137b5d18b2b89ac9ace01c8dbdcf2533cce3682ecc52118de0c1062ec2126c2e657d6ea3d9e2398e705d4b0b1f1ceecb266dffc4f31bf42744fb1e938dc22a889919ee1e73f463f7871fed720519e32186264b7ef2a0e5d9a18e6c95c0781894f77967f048951dec3b4d892a38710b1e3436d3c29088eb8b3da1789c25db3d3bc6c26081206e7155d210a89b80ca6ea877c41ff9947c0f25625dcb118294a163501f6239c326661a958fd12da4cd15a899f8b88cc723589056eaec5aa04a4cf5dbb6f480f9660423ccf38c486e210707e0fb25e1f126ceb2616f63e147a647dab0af9ebe89d65458bf636154a46e4cab95f5ee62da2c7974cd14b90d3e4f99f81733e85b3c1d5da2b508d9b90f5eed7eff0d9c7649de62bee00375454fee4a39576a5bbfdae428e7f8097bdf7797f167686cb68407e49079e4611ff3402b6384ba7b7e522bd2bb11ce8fd02ea4c1604d163ac4f6dde50b8b1f593f7edaadeac0868ed97df690200680c25f0f5d85431a529e4f339089dcdeda105e4ee51dead704cdf5a605c55fb055c9b0e86b8ba1b564c0dea3eb790a595cb103cb292268b07c5e59371e1a7ef597cd4b22977a820694c9f9aeb55d9de3ef62b75d6e656e3336698d960a3787bf8cf5b926a7faeef52ae128bcb5dc9e66d94b016c7b8e034879171a2d91c381f57e6a815b63b5ee6a6d2ff435b49f14c963966960194430d78f8f87627a67757fb3532b289550894da6dce4817a4e07f4d56877a1102ffcc8befa5c9f8fca6a4574d93ff70376c8861e0f8108cf907fce77ecb49728f86f034f80224b9695682e0824462f76cdb1fd1af151337b0d85419047a7aa284791718a4860cd586f7824b95bc837b6fd4f9be5aade68456e20356aa4d943dac36bf8b67b9e8f9d01a00fcda74b798bafa746c661b010f75b59904b29d0c8041504811c4065f82cf2ead58d2f595cbd8bc3e7043f4d94577b373b7cfe16a36fe564f505c03b70cfeb5e5f411c79481338aa67e86b3f5a2e77c21e454c333ae3da943ab723ab5f4c940395319534a5575f64acba0d0ecc43f60221ed3badf7289c9b3a7b903a2d6c94e15fa4c310dc4fa7faa0c24f405160a1002dbef20e4105d481db982f7243f79400a6e4cd9753c4b9732a47575f504b20c328fe9add7f432a4f075829da07b53b695037dc51737d3cd731934df333cd1a53fcf65aa31baa450ca501a6fae26e322347e618c5a444d92e9fec5a8261ae38b98fee5be77c02cec09ddccd5b3de92036":"1302149d1e197c41813b054c942329d420e366530f5517b470e964fe"
 
 PSA hash multi part: SHA-256 Test Vector NIST CAVS #1
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_multi_part:PSA_ALG_SHA_256:"":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
 
 PSA hash multi part: SHA-256 Test Vector NIST CAVS #2
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_multi_part:PSA_ALG_SHA_256:"bd":"68325720aabd7c82f30f554b313d0570c95accbb7dc4b5aae11204c08ffe732b"
 
 PSA hash multi part: SHA-256 Test Vector NIST CAVS #3
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_multi_part:PSA_ALG_SHA_256:"5fd4":"7c4fbf484498d21b487b9d61de8914b2eadaf2698712936d47c3ada2558f6788"
 
 PSA hash multi part: SHA-256 Test Vector NIST CAVS #4
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_multi_part:PSA_ALG_SHA_256:"b0bd69":"4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803"
 
 PSA hash multi part: SHA-256 Test Vector NIST CAVS #5
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_multi_part:PSA_ALG_SHA_256:"c98c8e55":"7abc22c0ae5af26ce93dbb94433a0e0b2e119d014f8e7f65bd56c61ccccd9504"
 
 PSA hash multi part: SHA-256 Test Vector NIST CAVS #6
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_multi_part:PSA_ALG_SHA_256:"81a723d966":"7516fb8bb11350df2bf386bc3c33bd0f52cb4c67c6e4745e0488e62c2aea2605"
 
 PSA hash multi part: SHA-256 Test Vector NIST CAVS #7
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_multi_part:PSA_ALG_SHA_256:"8390cf0be07661cc7669aac54ce09a37733a629d45f5d983ef201f9b2d13800e555d9b1097fec3b783d7a50dcb5e2b644b96a1e9463f177cf34906bf388f366db5c2deee04a30e283f764a97c3b377a034fefc22c259214faa99babaff160ab0aaa7e2ccb0ce09c6b32fe08cbc474694375aba703fadbfa31cf685b30a11c57f3cf4edd321e57d3ae6ebb1133c8260e75b9224fa47a2bb205249add2e2e62f817491482ae152322be0900355cdcc8d42a98f82e961a0dc6f537b7b410eff105f59673bfb787bf042aa071f7af68d944d27371c64160fe9382772372516c230c1f45c0d6b6cca7f274b394da9402d3eafdf733994ec58ab22d71829a98399574d4b5908a447a5a681cb0dd50a31145311d92c22a16de1ead66a5499f2dceb4cae694772ce90762ef8336afec653aa9b1a1c4820b221136dfce80dce2ba920d88a530c9410d0a4e0358a3a11052e58dd73b0b179ef8f56fe3b5a2d117a73a0c38a1392b6938e9782e0d86456ee4884e3c39d4d75813f13633bc79baa07c0d2d555afbf207f52b7dca126d015aa2b9873b3eb065e90b9b065a5373fe1fb1b20d594327d19fba56cb81e7b6696605ffa56eba3c27a438697cc21b201fd7e09f18deea1b3ea2f0d1edc02df0e20396a145412cd6b13c32d2e605641c948b714aec30c0649dc44143511f35ab0fd5dd64c34d06fe86f3836dfe9edeb7f08cfc3bd40956826356242191f99f53473f32b0cc0cf9321d6c92a112e8db90b86ee9e87cc32d0343db01e32ce9eb782cb24efbbbeb440fe929e8f2bf8dfb1550a3a2e742e8b455a3e5730e9e6a7a9824d17acc0f72a7f67eae0f0970f8bde46dcdefaed3047cf807e7f00a42e5fd11d40f5e98533d7574425b7d2bc3b3845c443008b58980e768e464e17cc6f6b3939eee52f713963d07d8c4abf02448ef0b889c9671e2f8a436ddeeffcca7176e9bf9d1005ecd377f2fa67c23ed1f137e60bf46018a8bd613d038e883704fc26e798969df35ec7bbc6a4fe46d8910bd82fa3cded265d0a3b6d399e4251e4d8233daa21b5812fded6536198ff13aa5a1cd46a5b9a17a4ddc1d9f85544d1d1cc16f3df858038c8e071a11a7e157a85a6a8dc47e88d75e7009a8b26fdb73f33a2a70f1e0c259f8f9533b9b8f9af9288b7274f21baeec78d396f8bacdcc22471207d9b4efccd3fedc5c5a2214ff5e51c553f35e21ae696fe51e8df733a8e06f50f419e599e9f9e4b37ce643fc810faaa47989771509d69a110ac916261427026369a21263ac4460fb4f708f8ae28599856db7cb6a43ac8e03d64a9609807e76c5f312b9d1863bfa304e8953647648b4f4ab0ed995e":"4109cdbec3240ad74cc6c37f39300f70fede16e21efc77f7865998714aad0b5e"
 
 PSA hash multi part: SHA-384 Test Vector NIST CAVS #1
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_multi_part:PSA_ALG_SHA_384:"":"38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"
 
 PSA hash multi part: SHA-384 Test Vector NIST CAVS #2
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_multi_part:PSA_ALG_SHA_384:"ab":"fb94d5be118865f6fcbc978b825da82cff188faec2f66cb84b2537d74b4938469854b0ca89e66fa2e182834736629f3d"
 
 PSA hash multi part: SHA-384 Test Vector NIST CAVS #3
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_multi_part:PSA_ALG_SHA_384:"7c27":"3d80be467df86d63abb9ea1d3f9cb39cd19890e7f2c53a6200bedc5006842b35e820dc4e0ca90ca9b97ab23ef07080fc"
 
 PSA hash multi part: SHA-384 Test Vector NIST CAVS #4
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_multi_part:PSA_ALG_SHA_384:"31f5ca":"78d54b943421fdf7ba90a7fb9637c2073aa480454bd841d39ff72f4511fc21fb67797b652c0c823229342873d3bef955"
 
 PSA hash multi part: SHA-384 Test Vector NIST CAVS #5
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_multi_part:PSA_ALG_SHA_384:"7bdee3f8":"8bdafba0777ee446c3431c2d7b1fbb631089f71d2ca417abc1d230e1aba64ec2f1c187474a6f4077d372c14ad407f99a"
 
 PSA hash multi part: SHA-384 Test Vector NIST CAVS #6
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_multi_part:PSA_ALG_SHA_384:"8f05604915":"504e414bf1db1060f14c8c799e25b1e0c4dcf1504ebbd129998f0ae283e6de86e0d3c7e879c73ec3b1836c3ee89c2649"
 
 PSA hash multi part: SHA-384 Test Vector NIST CAVS #7
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_multi_part:PSA_ALG_SHA_384:"665da6eda214":"4c022f112010908848312f8b8f1072625fd5c105399d562ea1d56130619a7eac8dfc3748fd05ee37e4b690be9daa9980"
 
 PSA hash multi part: SHA-384 Test Vector NIST CAVS #8
-depends_on:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
+depends_on:PSA_WANT_ALG_SHA_384
 hash_multi_part:PSA_ALG_SHA_384:"7f46ce506d593c4ed53c82edeb602037e0485befbee03f7f930fe532d18ff2a3f5fd6076672c8145a1bf40dd94f7abab47c9ae71c234213d2ad1069c2dac0b0ba15257ae672b8245960ae55bd50315c0097daa3a318745788d70d14706910809ca6e396237fe4934fa46f9ce782d66606d8bd6b2d283b1160513ce9c24e9f084b97891f99d4cdefc169a029e431ca772ba1bba426fce6f01d8e286014e5acc66b799e4db62bd4783322f8a32ff78e0de3957df50ce10871f4e0680df4e8ca3960af9bc6f4efa8eb3962d18f474eb178c3265cc46b8f2ff5ab1a7449fea297dfcfabfa01f28abbb7289bb354b691b5664ec6d098af51be19947ec5ba7ebd66380d1141953ba78d4aa5401679fa7b0a44db1981f864d3535c45afe4c61183d5b0ad51fae71ca07e34240283959f7530a32c70d95a088e501c230059f333b0670825009e7e22103ef22935830df1fac8ef877f5f3426dd54f7d1128dd871ad9a7d088f94c0e8712013295b8d69ae7623b880978c2d3c6ad26dc478f8dc47f5c0adcc618665dc3dc205a9071b2f2191e16cac5bd89bb59148fc719633752303aa08e518dbc389f0a5482caaa4c507b8729a6f3edd061efb39026cecc6399f51971cf7381d605e144a5928c8c2d1ad7467b05da2f202f4f3234e1aff19a0198a28685721c3d2d52311c721e3fdcbaf30214cdc3acff8c433880e104fb63f2df7ce69a97857819ba7ac00ac8eae1969764fde8f68cf8e0916d7e0c151147d4944f99f42ae50f30e1c79a42d2b6c5188d133d3cbbf69094027b354b295ccd0f7dc5a87d73638bd98ebfb00383ca0fa69cb8dcb35a12510e5e07ad8789047d0b63841a1bb928737e8b0a0c33254f47aa8bfbe3341a09c2b76dbcefa67e30df300d34f7b8465c4f869e51b6bcfe6cf68b238359a645036bf7f63f02924e087ce7457e483b6025a859903cb484574aa3b12cf946f32127d537c33bee3141b5db96d10a148c50ae045f287210757710d6846e04b202f79e87dd9a56bc6da15f84a77a7f63935e1dee00309cd276a8e7176cb04da6bb0e9009534438732cb42d008008853d38d19beba46e61006e30f7efd1bc7c2906b024e4ff898a1b58c448d68b43c6ab63f34f85b3ac6aa4475867e51b583844cb23829f4b30f4bdd817d88e2ef3e7b4fc0a624395b05ec5e8686082b24d29fef2b0d3c29e031d5f94f504b1d3df9361eb5ffbadb242e66c39a8094cfe62f85f639f3fd65fc8ae0c74a8f4c6e1d070b9183a434c722caaa0225f8bcd68614d6f0738ed62f8484ec96077d155c08e26c46be262a73e3551698bd70d8d5610cf37c4c306eed04ba6a040a9c3e6d7e15e8acda17f477c2484cf5c56b813313927be8387b1024f995e98fc87f1029091c01424bdc2b296c2eadb7d25b3e762a2fd0c2dcd1727ddf91db97c5984305265f3695a7f5472f2d72c94d68c27914f14f82aa8dd5fe4e2348b0ca967a3f98626a091552f5d0ffa2bf10350d23c996256c01fdeffb2c2c612519869f877e4929c6e95ff15040f1485e22ed14119880232fef3b57b3848f15b1766a5552879df8f06":"cba9e3eb12a6f83db11e8a6ff40d1049854ee094416bc527fea931d8585428a8ed6242ce81f6769b36e2123a5c23483e"
 
 PSA hash multi part: SHA-512 Test Vector NIST CAVS #1
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_multi_part:PSA_ALG_SHA_512:"":"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
 
 PSA hash multi part: SHA-512 Test Vector NIST CAVS #2
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_multi_part:PSA_ALG_SHA_512:"8f":"e4cd2d19931b5aad9c920f45f56f6ce34e3d38c6d319a6e11d0588ab8b838576d6ce6d68eea7c830de66e2bd96458bfa7aafbcbec981d4ed040498c3dd95f22a"
 
 PSA hash multi part: SHA-512 Test Vector NIST CAVS #3
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_multi_part:PSA_ALG_SHA_512:"e724":"7dbb520221a70287b23dbcf62bfc1b73136d858e86266732a7fffa875ecaa2c1b8f673b5c065d360c563a7b9539349f5f59bef8c0c593f9587e3cd50bb26a231"
 
 PSA hash multi part: SHA-512 Test Vector NIST CAVS #4
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_multi_part:PSA_ALG_SHA_512:"de4c90":"33ce98281045a5c4c9df0363d8196f1d7dfcd5ee46ac89776fd8a4344c12f123a66788af5bd41ceff1941aa5637654b4064c88c14e00465ab79a2fc6c97e1014"
 
 PSA hash multi part: SHA-512 Test Vector NIST CAVS #5
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_multi_part:PSA_ALG_SHA_512:"a801e94b":"dadb1b5a27f9fece8d86adb2a51879beb1787ff28f4e8ce162cad7fee0f942efcabbf738bc6f797fc7cc79a3a75048cd4c82ca0757a324695bfb19a557e56e2f"
 
 PSA hash multi part: SHA-512 Test Vector NIST CAVS #6
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_multi_part:PSA_ALG_SHA_512:"94390d3502":"b6175c4c4cccf69e0ce5f0312010886ea6b34d43673f942ae42483f9cbb7da817de4e11b5d58e25a3d9bd721a22cdffe1c40411cc45df1911fa5506129b69297"
 
 PSA hash multi part: SHA-512 Test Vector NIST CAVS #7
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_multi_part:PSA_ALG_SHA_512:"49297dd63e5f":"1fcc1e6f6870859d11649f5e5336a9cd16329c029baf04d5a6edf257889a2e9522b497dd656bb402da461307c4ee382e2e89380c8e6e6e7697f1e439f650fa94"
 
 PSA hash multi part: SHA-512 Test Vector NIST CAVS #8
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_multi_part:PSA_ALG_SHA_512:"990d1ae71a62d7bda9bfdaa1762a68d296eee72a4cd946f287a898fbabc002ea941fd8d4d991030b4d27a637cce501a834bb95eab1b7889a3e784c7968e67cbf552006b206b68f76d9191327524fcc251aeb56af483d10b4e0c6c5e599ee8c0fe4faeca8293844a8547c6a9a90d093f2526873a19ad4a5e776794c68c742fb834793d2dfcb7fea46c63af4b70fd11cb6e41834e72ee40edb067b292a794990c288d5007e73f349fb383af6a756b8301ad6e5e0aa8cd614399bb3a452376b1575afa6bdaeaafc286cb064bb91edef97c632b6c1113d107fa93a0905098a105043c2f05397f702514439a08a9e5ddc196100721d45c8fc17d2ed659376f8a00bd5cb9a0860e26d8a29d8d6aaf52de97e9346033d6db501a35dbbaf97c20b830cd2d18c2532f3a59cc497ee64c0e57d8d060e5069b28d86edf1adcf59144b221ce3ddaef134b3124fbc7dd000240eff0f5f5f41e83cd7f5bb37c9ae21953fe302b0f6e8b68fa91c6ab99265c64b2fd9cd4942be04321bb5d6d71932376c6f2f88e02422ba6a5e2cb765df93fd5dd0728c6abdaf03bce22e0678a544e2c3636f741b6f4447ee58a8fc656b43ef817932176adbfc2e04b2c812c273cd6cbfa4098f0be036a34221fa02643f5ee2e0b38135f2a18ecd2f16ebc45f8eb31b8ab967a1567ee016904188910861ca1fa205c7adaa194b286893ffe2f4fbe0384c2aef72a4522aeafd3ebc71f9db71eeeef86c48394a1c86d5b36c352cc33a0a2c800bc99e62fd65b3a2fd69e0b53996ec13d8ce483ce9319efd9a85acefabdb5342226febb83fd1daf4b24265f50c61c6de74077ef89b6fecf9f29a1f871af1e9f89b2d345cda7499bd45c42fa5d195a1e1a6ba84851889e730da3b2b916e96152ae0c92154b49719841db7e7cc707ba8a5d7b101eb4ac7b629bb327817910fff61580b59aab78182d1a2e33473d05b00b170b29e331870826cfe45af206aa7d0246bbd8566ca7cfb2d3c10bfa1db7dd48dd786036469ce7282093d78b5e1a5b0fc81a54c8ed4ceac1e5305305e78284ac276f5d7862727aff246e17addde50c670028d572cbfc0be2e4f8b2eb28fa68ad7b4c6c2a239c460441bfb5ea049f23b08563b4e47729a59e5986a61a6093dbd54f8c36ebe87edae01f251cb060ad1364ce677d7e8d5a4a4ca966a7241cc360bc2acb280e5f9e9c1b032ad6a180a35e0c5180b9d16d026c865b252098cc1d99ba7375ca31c7702c0d943d5e3dd2f6861fa55bd46d94b67ed3e52eccd8dd06d968e01897d6de97ed3058d91dd":"8e4bc6f8b8c60fe4d68c61d9b159c8693c3151c46749af58da228442d927f23359bd6ccd6c2ec8fa3f00a86cecbfa728e1ad60b821ed22fcd309ba91a4138bc9"
 
 PSA hash multi part: MD2 Test vector RFC1319 #1
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_multi_part:PSA_ALG_MD2:"":"8350e5a3e24c153df2275c9f80692773"
 
 PSA hash multi part: MD2 Test vector RFC1319 #2
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_multi_part:PSA_ALG_MD2:"61":"32ec01ec4a6dac72c0ab96fb34c0b5d1"
 
 PSA hash multi part: MD2 Test vector RFC1319 #3
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_multi_part:PSA_ALG_MD2:"616263":"da853b0d3f88d99b30283a69e6ded6bb"
 
 PSA hash multi part: MD2 Test vector RFC1319 #4
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_multi_part:PSA_ALG_MD2:"6d65737361676520646967657374":"ab4f496bfb2a530b219ff33031fe06b0"
 
 PSA hash multi part: MD2 Test vector RFC1319 #5
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_multi_part:PSA_ALG_MD2:"6162636465666768696a6b6c6d6e6f707172737475767778797a":"4e8ddff3650292ab5a4108c3aa47940b"
 
 PSA hash multi part: MD2 Test vector RFC1319 #6
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_multi_part:PSA_ALG_MD2:"4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a30313233343536373839":"da33def2a42df13975352846c30338cd"
 
 PSA hash multi part: MD2 Test vector RFC1319 #7
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_multi_part:PSA_ALG_MD2:"3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930":"d5976f79d83d3a0dc9806c3c66f3efd8"
 
 PSA hash multi part: MD4 Test vector RFC1320 #1
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_multi_part:PSA_ALG_MD4:"":"31d6cfe0d16ae931b73c59d7e0c089c0"
 
 PSA hash multi part: MD4 Test vector RFC1320 #2
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_multi_part:PSA_ALG_MD4:"61":"bde52cb31de33e46245e05fbdbd6fb24"
 
 PSA hash multi part: MD4 Test vector RFC1320 #3
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_multi_part:PSA_ALG_MD4:"616263":"a448017aaf21d8525fc10ae87aa6729d"
 
 PSA hash multi part: MD4 Test vector RFC1320 #4
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_multi_part:PSA_ALG_MD4:"6d65737361676520646967657374":"d9130a8164549fe818874806e1c7014b"
 
 PSA hash multi part: MD4 Test vector RFC1320 #5
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_multi_part:PSA_ALG_MD4:"6162636465666768696a6b6c6d6e6f707172737475767778797a":"d79e1c308aa5bbcdeea8ed63df412da9"
 
 PSA hash multi part: MD4 Test vector RFC1320 #6
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_multi_part:PSA_ALG_MD4:"4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a30313233343536373839":"043f8582f241db351ce627e153e7f0e4"
 
 PSA hash multi part: MD4 Test vector RFC1320 #7
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_multi_part:PSA_ALG_MD4:"3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930":"e33b4ddc9c38f2199c3e7b164fcc0536"
 
 PSA hash multi part: MD5 Test vector RFC1321 #1
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_multi_part:PSA_ALG_MD5:"":"d41d8cd98f00b204e9800998ecf8427e"
 
 PSA hash multi part: MD5 Test vector RFC1321 #2
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_multi_part:PSA_ALG_MD5:"61":"0cc175b9c0f1b6a831c399e269772661"
 
 PSA hash multi part: MD5 Test vector RFC1321 #3
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_multi_part:PSA_ALG_MD5:"616263":"900150983cd24fb0d6963f7d28e17f72"
 
 PSA hash multi part: MD5 Test vector RFC1321 #4
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_multi_part:PSA_ALG_MD5:"6d65737361676520646967657374":"f96b697d7cb7938d525a2f31aaf161d0"
 
 PSA hash multi part: MD5 Test vector RFC1321 #5
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_multi_part:PSA_ALG_MD5:"6162636465666768696a6b6c6d6e6f707172737475767778797a":"c3fcd3d76192e4007dfb496cca67e13b"
 
 PSA hash multi part: MD5 Test vector RFC1321 #6
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_multi_part:PSA_ALG_MD5:"4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a30313233343536373839":"d174ab98d277d9f5a5611c2c9f419d9f"
 
 PSA hash multi part: MD5 Test vector RFC1321 #7
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_multi_part:PSA_ALG_MD5:"3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930":"57edf4a22be3c955ac49da2e2107b67a"
 
 PSA hash multi part: RIPEMD160 Test vector from paper #1
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_multi_part:PSA_ALG_RIPEMD160:"":"9c1185a5c5e9fc54612808977ee8f548b2258d31"
 
 PSA hash multi part: RIPEMD160 Test vector from paper #2
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_multi_part:PSA_ALG_RIPEMD160:"61":"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"
 
 PSA hash multi part: RIPEMD160 Test vector from paper #3
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_multi_part:PSA_ALG_RIPEMD160:"616263":"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"
 
 PSA hash multi part: RIPEMD160 Test vector from paper #4
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_multi_part:PSA_ALG_RIPEMD160:"6d65737361676520646967657374":"5d0689ef49d2fae572b881b123a85ffa21595f36"
 
 PSA hash multi part: RIPEMD160 Test vector from paper #5
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_multi_part:PSA_ALG_RIPEMD160:"6162636465666768696a6b6c6d6e6f707172737475767778797a":"f71c27109c692c1b56bbdceb5b9d2865b3708dbc"
 
 PSA hash multi part: RIPEMD160 Test vector from paper #6
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_multi_part:PSA_ALG_RIPEMD160:"6162636462636465636465666465666765666768666768696768696a68696a6b696a6b6c6a6b6c6d6b6c6d6e6c6d6e6f6d6e6f706e6f7071":"12a053384a9c0c88e405a06c27dcf49ada62eb2b"
 
 PSA hash multi part: RIPEMD160 Test vector from paper #7
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_multi_part:PSA_ALG_RIPEMD160:"4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a30313233343536373839":"b0e20b6e3116640286ed3a87a5713079b21f5189"
 
 PSA hash multi part: RIPEMD160 Test vector from paper #8
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_multi_part:PSA_ALG_RIPEMD160:"3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930":"9b752e45573d4b39f4dbd3323cab82bf63326bfb"
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_hash.function b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_hash.function
index 1bc9331..b0da2bf 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_hash.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_hash.function
@@ -2,8 +2,6 @@
 
 #include <stdint.h>
 
-#include "test/psa_crypto_helpers.h"
-
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_init.function b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_init.function
index 62ef6e2..40efb87 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_init.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_init.function
@@ -1,7 +1,6 @@
 /* BEGIN_HEADER */
 #include <stdint.h>
 
-#include "test/psa_crypto_helpers.h"
 /* Some tests in this module configure entropy sources. */
 #include "psa_crypto_invasive.h"
 
@@ -11,11 +10,23 @@
 #define ENTROPY_MIN_NV_SEED_SIZE                                        \
     MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE)
 
+#include "psa_crypto_random_impl.h"
+#if defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE)
+/* PSA crypto uses the HMAC_DRBG module. It reads from the entropy source twice:
+ * once for the initial entropy and once for a nonce. The nonce length is
+ * half the entropy length. For SHA-256, SHA-384 or SHA-512, the
+ * entropy length is 256 per the documentation of mbedtls_hmac_drbg_seed(),
+ * and PSA crypto doesn't support other hashes for HMAC_DRBG. */
+#define ENTROPY_NONCE_LEN ( 256 / 2 )
+#else
 /* PSA crypto uses the CTR_DRBG module. In some configurations, it needs
  * to read from the entropy source twice: once for the initial entropy
  * and once for a nonce. */
 #include "mbedtls/ctr_drbg.h"
 #define ENTROPY_NONCE_LEN MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN
+#endif
+
+#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
 
 typedef struct
 {
@@ -118,6 +129,8 @@
                                     MBEDTLS_ENTROPY_SOURCE_STRONG );
 }
 
+#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -125,7 +138,7 @@
  * END_DEPENDENCIES
  */
 
-/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED */
+/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
 void create_nv_seed( )
 {
     static unsigned char seed[ENTROPY_MIN_NV_SEED_SIZE];
@@ -201,7 +214,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
 void custom_entropy_sources( int sources_arg, int expected_init_status_arg )
 {
     psa_status_t expected_init_status = expected_init_status_arg;
@@ -222,7 +235,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
 void fake_entropy_source( int threshold,
                           int amount1,
                           int amount2,
@@ -262,7 +275,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED */
+/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
 void entropy_from_nv_seed( int seed_size_arg,
                            int expected_init_status_arg )
 {
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_metadata.data b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_metadata.data
index 006389f..72a11ab 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_metadata.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_metadata.data
@@ -1,281 +1,371 @@
 Hash: MD2
-depends_on:MBEDTLS_MD2_C
+depends_on:PSA_WANT_ALG_MD2
 hash_algorithm:PSA_ALG_MD2:16
 
 Hash: MD4
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_MD4
 hash_algorithm:PSA_ALG_MD4:16
 
 Hash: MD5
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_MD5
 hash_algorithm:PSA_ALG_MD5:16
 
 Hash: RIPEMD160
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_RIPEMD160
 hash_algorithm:PSA_ALG_RIPEMD160:20
 
 Hash: SHA-1
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_SHA_1
 hash_algorithm:PSA_ALG_SHA_1:20
 
 Hash: SHA-2 SHA-224
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_224
 hash_algorithm:PSA_ALG_SHA_224:28
 
 Hash: SHA-2 SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256
 hash_algorithm:PSA_ALG_SHA_256:32
 
 Hash: SHA-2 SHA-384
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_384
 hash_algorithm:PSA_ALG_SHA_384:48
 
 Hash: SHA-2 SHA-512
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_512
 hash_algorithm:PSA_ALG_SHA_512:64
 
 MAC: HMAC-MD2
-depends_on:MBEDTLS_MD2_C
-hmac_algorithm:PSA_ALG_HMAC( PSA_ALG_MD2 ):16:64
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD2
+hmac_algorithm:PSA_ALG_HMAC( PSA_ALG_MD2 ):16:16
 
 MAC: HMAC-MD4
-depends_on:MBEDTLS_MD4_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD4
 hmac_algorithm:PSA_ALG_HMAC( PSA_ALG_MD4 ):16:64
 
 MAC: HMAC-MD5
-depends_on:MBEDTLS_MD5_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD5
 hmac_algorithm:PSA_ALG_HMAC( PSA_ALG_MD5 ):16:64
 
 MAC: HMAC-RIPEMD160
-depends_on:MBEDTLS_RIPEMD160_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_RIPEMD160
 hmac_algorithm:PSA_ALG_HMAC( PSA_ALG_RIPEMD160 ):20:64
 
 MAC: HMAC-SHA-1
-depends_on:MBEDTLS_SHA1_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_1
 hmac_algorithm:PSA_ALG_HMAC( PSA_ALG_SHA_1 ):20:64
 
 MAC: HMAC-SHA-224
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224
 hmac_algorithm:PSA_ALG_HMAC( PSA_ALG_SHA_224 ):28:64
 
 MAC: HMAC-SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256
 hmac_algorithm:PSA_ALG_HMAC( PSA_ALG_SHA_256 ):32:64
 
 MAC: HMAC-SHA-384
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384
 hmac_algorithm:PSA_ALG_HMAC( PSA_ALG_SHA_384 ):48:128
 
 MAC: HMAC-SHA-512
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512
 hmac_algorithm:PSA_ALG_HMAC( PSA_ALG_SHA_512 ):64:128
 
 MAC: CBC_MAC-AES-128
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_C
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_AES:MBEDTLS_CIPHER_C
 mac_algorithm:PSA_ALG_CBC_MAC:ALG_IS_BLOCK_CIPHER_MAC:16:PSA_KEY_TYPE_AES:128
 
 MAC: CBC_MAC-AES-192
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_C
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_AES:MBEDTLS_CIPHER_C
 mac_algorithm:PSA_ALG_CBC_MAC:ALG_IS_BLOCK_CIPHER_MAC:16:PSA_KEY_TYPE_AES:192
 
 MAC: CBC_MAC-AES-256
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_C
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_AES:MBEDTLS_CIPHER_C
 mac_algorithm:PSA_ALG_CBC_MAC:ALG_IS_BLOCK_CIPHER_MAC:16:PSA_KEY_TYPE_AES:256
 
 MAC: CBC_MAC-3DES
-depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_C
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_DES:MBEDTLS_CIPHER_C
 mac_algorithm:PSA_ALG_CBC_MAC:ALG_IS_BLOCK_CIPHER_MAC:8:PSA_KEY_TYPE_DES:192
 
 MAC: CMAC-AES-128
-depends_on:MBEDTLS_AES_C:MBEDTLS_CMAC_C
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
 mac_algorithm:PSA_ALG_CMAC:ALG_IS_BLOCK_CIPHER_MAC:16:PSA_KEY_TYPE_AES:128
 
 MAC: CMAC-AES-192
-depends_on:MBEDTLS_AES_C:MBEDTLS_CMAC_C
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
 mac_algorithm:PSA_ALG_CMAC:ALG_IS_BLOCK_CIPHER_MAC:16:PSA_KEY_TYPE_AES:192
 
 MAC: CMAC-AES-256
-depends_on:MBEDTLS_AES_C:MBEDTLS_CMAC_C
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES
 mac_algorithm:PSA_ALG_CMAC:ALG_IS_BLOCK_CIPHER_MAC:16:PSA_KEY_TYPE_AES:256
 
 MAC: CMAC-3DES
-depends_on:MBEDTLS_DES_C:MBEDTLS_CMAC_C
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_DES
 mac_algorithm:PSA_ALG_CMAC:ALG_IS_BLOCK_CIPHER_MAC:8:PSA_KEY_TYPE_DES:192
 
 Cipher: STREAM_CIPHER
+depends_on:PSA_WANT_ALG_STREAM_CIPHER
 cipher_algorithm:PSA_ALG_STREAM_CIPHER:ALG_IS_STREAM_CIPHER
 
 Cipher: CTR
-depends_on:MBEDTLS_CIPHER_C:MBEDTLS_CIPHER_MODE_CTR
+depends_on:PSA_WANT_ALG_CTR:MBEDTLS_CIPHER_C
 cipher_algorithm:PSA_ALG_CTR:ALG_IS_STREAM_CIPHER
 
 Cipher: CFB
-depends_on:MBEDTLS_CIPHER_C:MBEDTLS_CIPHER_MODE_CFB
+depends_on:PSA_WANT_ALG_CFB:MBEDTLS_CIPHER_C
 cipher_algorithm:PSA_ALG_CFB:ALG_IS_STREAM_CIPHER
 
 Cipher: OFB
-depends_on:MBEDTLS_CIPHER_C:MBEDTLS_CIPHER_MODE_OFB
+depends_on:PSA_WANT_ALG_OFB:MBEDTLS_CIPHER_C
 cipher_algorithm:PSA_ALG_OFB:ALG_IS_STREAM_CIPHER
 
 Cipher: ECB-nopad
-depends_on:MBEDTLS_CIPHER_C
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:MBEDTLS_CIPHER_C
 cipher_algorithm:PSA_ALG_ECB_NO_PADDING:0
 
 Cipher: CBC-nopad
-depends_on:MBEDTLS_CIPHER_C:MBEDTLS_CIPHER_MODE_CBC
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:MBEDTLS_CIPHER_C
 cipher_algorithm:PSA_ALG_CBC_NO_PADDING:0
 
 Cipher: CBC-PKCS#7
-depends_on:MBEDTLS_CIPHER_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
+depends_on:PSA_WANT_ALG_CBC_PKCS7:MBEDTLS_CIPHER_C
 cipher_algorithm:PSA_ALG_CBC_PKCS7:0
 
 Cipher: XTS
-depends_on:MBEDTLS_CIPHER_C:MBEDTLS_CIPHER_MODE_XTS
+depends_on:PSA_WANT_ALG_XTS:MBEDTLS_CIPHER_C
 cipher_algorithm:PSA_ALG_XTS:0
 
-AEAD: CCM
-depends_on:MBEDTLS_CCM_C
-aead_algorithm:PSA_ALG_CCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16
+AEAD: CCM-AES-128
+depends_on:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_CCM
+aead_algorithm:PSA_ALG_CCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_AES:128
 
-AEAD: GCM
-depends_on:MBEDTLS_GCM_C
-aead_algorithm:PSA_ALG_GCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16
+AEAD: CCM-AES-192
+depends_on:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_CCM
+aead_algorithm:PSA_ALG_CCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_AES:192
+
+AEAD: CCM-AES-256
+depends_on:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_CCM
+aead_algorithm:PSA_ALG_CCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_AES:256
+
+AEAD: CCM-ARIA-128
+depends_on:PSA_WANT_KEY_TYPE_ARIA:PSA_WANT_ALG_CCM
+aead_algorithm:PSA_ALG_CCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_ARIA:128
+
+AEAD: CCM-ARIA-192
+depends_on:PSA_WANT_KEY_TYPE_ARIA:PSA_WANT_ALG_CCM
+aead_algorithm:PSA_ALG_CCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_ARIA:192
+
+AEAD: CCM-ARIA-256
+depends_on:PSA_WANT_KEY_TYPE_ARIA:PSA_WANT_ALG_CCM
+aead_algorithm:PSA_ALG_CCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_ARIA:256
+
+AEAD: CCM-CAMELLIA-128
+depends_on:PSA_WANT_KEY_TYPE_CAMELLIA:PSA_WANT_ALG_CCM
+aead_algorithm:PSA_ALG_CCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_CAMELLIA:128
+
+AEAD: CCM-CAMELLIA-192
+depends_on:PSA_WANT_KEY_TYPE_CAMELLIA:PSA_WANT_ALG_CCM
+aead_algorithm:PSA_ALG_CCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_CAMELLIA:192
+
+AEAD: CCM-CAMELLIA-256
+depends_on:PSA_WANT_KEY_TYPE_CAMELLIA:PSA_WANT_ALG_CCM
+aead_algorithm:PSA_ALG_CCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_CAMELLIA:256
+
+AEAD: GCM-AES-128
+depends_on:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_GCM
+aead_algorithm:PSA_ALG_GCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_AES:128
+
+AEAD: GCM-AES-192
+depends_on:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_GCM
+aead_algorithm:PSA_ALG_GCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_AES:192
+
+AEAD: GCM-AES-256
+depends_on:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_GCM
+aead_algorithm:PSA_ALG_GCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_AES:256
+
+AEAD: GCM-ARIA-128
+depends_on:PSA_WANT_KEY_TYPE_ARIA:PSA_WANT_ALG_GCM
+aead_algorithm:PSA_ALG_GCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_ARIA:128
+
+AEAD: GCM-ARIA-192
+depends_on:PSA_WANT_KEY_TYPE_ARIA:PSA_WANT_ALG_GCM
+aead_algorithm:PSA_ALG_GCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_ARIA:192
+
+AEAD: GCM-ARIA-256
+depends_on:PSA_WANT_KEY_TYPE_ARIA:PSA_WANT_ALG_GCM
+aead_algorithm:PSA_ALG_GCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_ARIA:256
+
+AEAD: GCM-CAMELLIA-128
+depends_on:PSA_WANT_KEY_TYPE_CAMELLIA:PSA_WANT_ALG_GCM
+aead_algorithm:PSA_ALG_GCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_CAMELLIA:128
+
+AEAD: GCM-CAMELLIA-192
+depends_on:PSA_WANT_KEY_TYPE_CAMELLIA:PSA_WANT_ALG_GCM
+aead_algorithm:PSA_ALG_GCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_CAMELLIA:192
+
+AEAD: GCM-CAMELLIA-256
+depends_on:PSA_WANT_KEY_TYPE_CAMELLIA:PSA_WANT_ALG_GCM
+aead_algorithm:PSA_ALG_GCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_CAMELLIA:256
 
 AEAD: ChaCha20_Poly1305
-depends_on:MBEDTLS_CHACHAPOLY_C
-aead_algorithm:PSA_ALG_CHACHA20_POLY1305:0:16
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305
+aead_algorithm:PSA_ALG_CHACHA20_POLY1305:0:16:PSA_KEY_TYPE_CHACHA20:256
 
 Asymmetric signature: RSA PKCS#1 v1.5 raw
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
-asymmetric_signature_algorithm:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:ALG_IS_RSA_PKCS1V15_SIGN | ALG_IS_HASH_AND_SIGN
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+asymmetric_signature_algorithm:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:ALG_IS_RSA_PKCS1V15_SIGN | ALG_IS_SIGN_HASH
 
 Asymmetric signature: RSA PKCS#1 v1.5 SHA-256
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-asymmetric_signature_algorithm:PSA_ALG_RSA_PKCS1V15_SIGN( PSA_ALG_SHA_256 ):ALG_IS_RSA_PKCS1V15_SIGN | ALG_IS_HASH_AND_SIGN
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256
+asymmetric_signature_algorithm:PSA_ALG_RSA_PKCS1V15_SIGN( PSA_ALG_SHA_256 ):ALG_IS_RSA_PKCS1V15_SIGN | ALG_IS_SIGN_HASH | ALG_IS_HASH_AND_SIGN
 
 Asymmetric signature: RSA PSS SHA-256
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
-asymmetric_signature_algorithm:PSA_ALG_RSA_PSS( PSA_ALG_SHA_256 ):ALG_IS_RSA_PSS | ALG_IS_HASH_AND_SIGN
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256
+asymmetric_signature_algorithm:PSA_ALG_RSA_PSS( PSA_ALG_SHA_256 ):ALG_IS_RSA_PSS | ALG_IS_RSA_PSS_STANDARD_SALT | ALG_IS_SIGN_HASH | ALG_IS_HASH_AND_SIGN
+
+Asymmetric signature: RSA PSS-any-salt SHA-256
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256
+asymmetric_signature_algorithm:PSA_ALG_RSA_PSS_ANY_SALT( PSA_ALG_SHA_256 ):ALG_IS_RSA_PSS | ALG_IS_RSA_PSS_ANY_SALT | ALG_IS_SIGN_HASH | ALG_IS_HASH_AND_SIGN
 
 Asymmetric signature: randomized ECDSA (no hashing)
-depends_on:MBEDTLS_ECDSA_C
-asymmetric_signature_algorithm:PSA_ALG_ECDSA_ANY:ALG_IS_ECDSA | ALG_IS_RANDOMIZED_ECDSA | ALG_IS_HASH_AND_SIGN
+depends_on:PSA_WANT_ALG_ECDSA
+asymmetric_signature_algorithm:PSA_ALG_ECDSA_ANY:ALG_IS_ECDSA | ALG_IS_RANDOMIZED_ECDSA | ALG_IS_SIGN_HASH
 
 Asymmetric signature: SHA-256 + randomized ECDSA
-depends_on:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C
-asymmetric_signature_algorithm:PSA_ALG_ECDSA( PSA_ALG_SHA_256 ):ALG_IS_ECDSA | ALG_IS_RANDOMIZED_ECDSA | ALG_IS_HASH_AND_SIGN
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256
+asymmetric_signature_algorithm:PSA_ALG_ECDSA( PSA_ALG_SHA_256 ):ALG_IS_ECDSA | ALG_IS_RANDOMIZED_ECDSA | ALG_IS_SIGN_HASH | ALG_IS_HASH_AND_SIGN
 
 Asymmetric signature: SHA-256 + deterministic ECDSA using SHA-256
-depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_SHA256_C
-asymmetric_signature_algorithm:PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):ALG_IS_ECDSA | ALG_IS_DETERMINISTIC_ECDSA | ALG_ECDSA_IS_DETERMINISTIC | ALG_IS_HASH_AND_SIGN
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256
+asymmetric_signature_algorithm:PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):ALG_IS_ECDSA | ALG_IS_DETERMINISTIC_ECDSA | ALG_ECDSA_IS_DETERMINISTIC | ALG_IS_SIGN_HASH | ALG_IS_HASH_AND_SIGN
+
+Asymmetric signature: pure EdDSA
+depends_on:PSA_WANT_ALG_EDDSA
+asymmetric_signature_algorithm:PSA_ALG_PURE_EDDSA:0
+
+Asymmetric signature: Ed25519ph
+depends_on:PSA_WANT_ALG_EDDSA
+asymmetric_signature_algorithm:PSA_ALG_ED25519PH:ALG_IS_HASH_EDDSA | ALG_IS_SIGN_HASH | ALG_IS_HASH_AND_SIGN
+
+Asymmetric signature: Ed448ph
+depends_on:PSA_WANT_ALG_EDDSA
+asymmetric_signature_algorithm:PSA_ALG_ED448PH:ALG_IS_HASH_EDDSA | ALG_IS_SIGN_HASH | ALG_IS_HASH_AND_SIGN
 
 Asymmetric signature: RSA PKCS#1 v1.5 with wildcard hash
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
 asymmetric_signature_wildcard:PSA_ALG_RSA_PKCS1V15_SIGN( PSA_ALG_ANY_HASH ):ALG_IS_RSA_PKCS1V15_SIGN
 
 Asymmetric signature: RSA PSS with wildcard hash
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21
-asymmetric_signature_wildcard:PSA_ALG_RSA_PSS( PSA_ALG_ANY_HASH ):ALG_IS_RSA_PSS
+depends_on:PSA_WANT_ALG_RSA_PSS
+asymmetric_signature_wildcard:PSA_ALG_RSA_PSS( PSA_ALG_ANY_HASH ):ALG_IS_RSA_PSS | ALG_IS_RSA_PSS_STANDARD_SALT
+
+Asymmetric signature: RSA PSS-any-salt with wildcard hash
+depends_on:PSA_WANT_ALG_RSA_PSS
+asymmetric_signature_wildcard:PSA_ALG_RSA_PSS_ANY_SALT( PSA_ALG_ANY_HASH ):ALG_IS_RSA_PSS | ALG_IS_RSA_PSS_ANY_SALT
 
 Asymmetric signature: randomized ECDSA with wildcard hash
-depends_on:MBEDTLS_ECDSA_C
+depends_on:PSA_WANT_ALG_ECDSA
 asymmetric_signature_wildcard:PSA_ALG_ECDSA( PSA_ALG_ANY_HASH ):ALG_IS_ECDSA | ALG_IS_RANDOMIZED_ECDSA
 
 Asymmetric signature: deterministic ECDSA with wildcard hash
-depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA
 asymmetric_signature_wildcard:PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_ANY_HASH ):ALG_IS_ECDSA | ALG_IS_DETERMINISTIC_ECDSA | ALG_ECDSA_IS_DETERMINISTIC
 
 Asymmetric encryption: RSA PKCS#1 v1.5
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
 asymmetric_encryption_algorithm:PSA_ALG_RSA_PKCS1V15_CRYPT:0
 
 Asymmetric encryption: RSA OAEP using SHA-256
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256
 asymmetric_encryption_algorithm:PSA_ALG_RSA_OAEP( PSA_ALG_SHA_256 ):ALG_IS_RSA_OAEP
 
 Key derivation: HKDF using SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 key_derivation_algorithm:PSA_ALG_HKDF( PSA_ALG_SHA_256 ):ALG_IS_HKDF
 
 Key derivation: HKDF using SHA-384
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_384
 key_derivation_algorithm:PSA_ALG_HKDF( PSA_ALG_SHA_384 ):ALG_IS_HKDF
 
 Key derivation: TLS 1.2 PRF using SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 key_derivation_algorithm:PSA_ALG_TLS12_PRF( PSA_ALG_SHA_256 ):ALG_IS_TLS12_PRF
 
 Key derivation: TLS 1.2 PRF using SHA-384
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PRF
 key_derivation_algorithm:PSA_ALG_TLS12_PRF( PSA_ALG_SHA_384 ):ALG_IS_TLS12_PRF
 
 Key derivation: TLS 1.2 PSK-to-MS using SHA-256
-depends_on:MBEDTLS_SHA256_C
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS
 key_derivation_algorithm:PSA_ALG_TLS12_PSK_TO_MS( PSA_ALG_SHA_256 ):ALG_IS_TLS12_PSK_TO_MS
 
 Key derivation: TLS 1.2 PSK-to-MS using SHA-384
-depends_on:MBEDTLS_SHA512_C
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PSK_TO_MS
 key_derivation_algorithm:PSA_ALG_TLS12_PSK_TO_MS( PSA_ALG_SHA_384 ):ALG_IS_TLS12_PSK_TO_MS
 
 Key agreement: FFDH, raw output
-depends_on:MBEDTLS_DHM_C
+depends_on:PSA_WANT_ALG_FFDH
 key_agreement_algorithm:PSA_ALG_FFDH:ALG_IS_FFDH | ALG_IS_RAW_KEY_AGREEMENT:PSA_ALG_FFDH:PSA_ALG_CATEGORY_KEY_DERIVATION
 
 Key agreement: FFDH, HKDF using SHA-256
-depends_on:MBEDTLS_DHM_C
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 key_agreement_algorithm:PSA_ALG_KEY_AGREEMENT( PSA_ALG_FFDH, PSA_ALG_HKDF( PSA_ALG_SHA_256 ) ):ALG_IS_FFDH:PSA_ALG_FFDH:PSA_ALG_HKDF( PSA_ALG_SHA_256 )
 
 Key agreement: FFDH, HKDF using SHA-384
-depends_on:MBEDTLS_DHM_C
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_384
 key_agreement_algorithm:PSA_ALG_KEY_AGREEMENT( PSA_ALG_FFDH, PSA_ALG_HKDF( PSA_ALG_SHA_384 ) ):ALG_IS_FFDH:PSA_ALG_FFDH:PSA_ALG_HKDF( PSA_ALG_SHA_384 )
 
 Key agreement: ECDH, raw output
-depends_on:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH
 key_agreement_algorithm:PSA_ALG_ECDH:ALG_IS_ECDH | ALG_IS_RAW_KEY_AGREEMENT:PSA_ALG_ECDH:PSA_ALG_CATEGORY_KEY_DERIVATION
 
 Key agreement: ECDH, HKDF using SHA-256
-depends_on:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 key_agreement_algorithm:PSA_ALG_KEY_AGREEMENT( PSA_ALG_ECDH, PSA_ALG_HKDF( PSA_ALG_SHA_256 ) ):ALG_IS_ECDH:PSA_ALG_ECDH:PSA_ALG_HKDF( PSA_ALG_SHA_256 )
 
 Key agreement: ECDH, HKDF using SHA-384
-depends_on:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_384
 key_agreement_algorithm:PSA_ALG_KEY_AGREEMENT( PSA_ALG_ECDH, PSA_ALG_HKDF( PSA_ALG_SHA_384 ) ):ALG_IS_ECDH:PSA_ALG_ECDH:PSA_ALG_HKDF( PSA_ALG_SHA_384 )
 
 Key type: raw data
 key_type:PSA_KEY_TYPE_RAW_DATA:KEY_TYPE_IS_UNSTRUCTURED
 
 Key type: HMAC
+depends_on:PSA_WANT_KEY_TYPE_HMAC
 key_type:PSA_KEY_TYPE_HMAC:KEY_TYPE_IS_UNSTRUCTURED
 
 Key type: secret for key derivation
 key_type:PSA_KEY_TYPE_DERIVE:KEY_TYPE_IS_UNSTRUCTURED
 
 Block cipher key type: AES
-depends_on:MBEDTLS_AES_C
+depends_on:PSA_WANT_KEY_TYPE_AES
 block_cipher_key_type:PSA_KEY_TYPE_AES:16
 
+Block cipher key type: ARIA
+depends_on:PSA_WANT_KEY_TYPE_ARIA
+block_cipher_key_type:PSA_KEY_TYPE_ARIA:16
+
 Block cipher key type: DES
-depends_on:MBEDTLS_DES_C
+depends_on:PSA_WANT_KEY_TYPE_DES
 block_cipher_key_type:PSA_KEY_TYPE_DES:8
 
 Block cipher key type: Camellia
-depends_on:MBEDTLS_CAMELLIA_C
+depends_on:PSA_WANT_KEY_TYPE_CAMELLIA
 block_cipher_key_type:PSA_KEY_TYPE_CAMELLIA:16
 
 Stream cipher key type: ARC4
-depends_on:MBEDTLS_ARC4_C
+depends_on:PSA_WANT_KEY_TYPE_ARC4
 stream_cipher_key_type:PSA_KEY_TYPE_ARC4
 
 Stream cipher key type: ChaCha20
-depends_on:MBEDTLS_CHACHA20_C
+depends_on:PSA_WANT_KEY_TYPE_CHACHA20
 stream_cipher_key_type:PSA_KEY_TYPE_CHACHA20
 
 Key type: RSA public key
-depends_on:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
 key_type:PSA_KEY_TYPE_RSA_PUBLIC_KEY:KEY_TYPE_IS_PUBLIC_KEY | KEY_TYPE_IS_RSA
 
 Key type: RSA key pair
-depends_on:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
 key_type:PSA_KEY_TYPE_RSA_KEY_PAIR:KEY_TYPE_IS_KEY_PAIR | KEY_TYPE_IS_RSA
 
 ECC key family: SECP K1
@@ -302,5 +392,44 @@
 ECC key family: Montgomery (Curve25519, Curve448)
 ecc_key_family:PSA_ECC_FAMILY_MONTGOMERY
 
+ECC key family: Twisted Edwards (Ed25519, Ed448)
+ecc_key_family:PSA_ECC_FAMILY_TWISTED_EDWARDS
+
 DH group family: RFC 7919
 dh_key_family:PSA_DH_FAMILY_RFC7919
+
+Lifetime: VOLATILE
+lifetime:PSA_KEY_LIFETIME_VOLATILE:KEY_LIFETIME_IS_VOLATILE:PSA_KEY_PERSISTENCE_VOLATILE:PSA_KEY_LOCATION_LOCAL_STORAGE
+
+Lifetime: PERSISTENT
+lifetime:PSA_KEY_LIFETIME_PERSISTENT:0:PSA_KEY_PERSISTENCE_DEFAULT:PSA_KEY_LOCATION_LOCAL_STORAGE
+
+Lifetime: volatile, local storage
+lifetime:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_VOLATILE, PSA_KEY_LOCATION_LOCAL_STORAGE):KEY_LIFETIME_IS_VOLATILE:PSA_KEY_PERSISTENCE_VOLATILE:PSA_KEY_LOCATION_LOCAL_STORAGE
+
+Lifetime: default, local storage
+lifetime:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_DEFAULT, PSA_KEY_LOCATION_LOCAL_STORAGE):0:PSA_KEY_PERSISTENCE_DEFAULT:PSA_KEY_LOCATION_LOCAL_STORAGE
+
+Lifetime: 2, local storage
+lifetime:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(2, PSA_KEY_LOCATION_LOCAL_STORAGE):0:2:PSA_KEY_LOCATION_LOCAL_STORAGE
+
+Lifetime: 254, local storage
+lifetime:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(254, PSA_KEY_LOCATION_LOCAL_STORAGE):0:254:PSA_KEY_LOCATION_LOCAL_STORAGE
+
+Lifetime: read-only, local storage
+lifetime:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_READ_ONLY, PSA_KEY_LOCATION_LOCAL_STORAGE):KEY_LIFETIME_IS_READ_ONLY:PSA_KEY_PERSISTENCE_READ_ONLY:PSA_KEY_LOCATION_LOCAL_STORAGE
+
+Lifetime: volatile, 0x123456
+lifetime:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_VOLATILE, 0x123456):KEY_LIFETIME_IS_VOLATILE:PSA_KEY_PERSISTENCE_VOLATILE:0x123456
+
+Lifetime: default, 0x123456
+lifetime:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_DEFAULT, 0x123456):0:PSA_KEY_PERSISTENCE_DEFAULT:0x123456
+
+Lifetime: 2, 0x123456
+lifetime:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(2, 0x123456):0:2:0x123456
+
+Lifetime: 254, 0x123456
+lifetime:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(254, 0x123456):0:254:0x123456
+
+Lifetime: read-only, 0x123456
+lifetime:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_READ_ONLY, 0x123456):KEY_LIFETIME_IS_READ_ONLY:PSA_KEY_PERSISTENCE_READ_ONLY:0x123456
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_metadata.function b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_metadata.function
index 7c0929e..f2ba16a 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_metadata.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_metadata.function
@@ -9,6 +9,7 @@
 #endif
 
 #include "psa/crypto.h"
+#include "psa_crypto_invasive.h"
 
 /* Flags for algorithm classification macros. There is a flag for every
  * algorithm classification macro PSA_ALG_IS_xxx except for the
@@ -21,24 +22,29 @@
 #define ALG_IS_STREAM_CIPHER            ( 1u << 3 )
 #define ALG_IS_RSA_PKCS1V15_SIGN        ( 1u << 4 )
 #define ALG_IS_RSA_PSS                  ( 1u << 5 )
-#define ALG_IS_DSA                      ( 1u << 6 )
-#define ALG_DSA_IS_DETERMINISTIC        ( 1u << 7 )
-#define ALG_IS_DETERMINISTIC_DSA        ( 1u << 8 )
-#define ALG_IS_RANDOMIZED_DSA           ( 1u << 9 )
-#define ALG_IS_ECDSA                    ( 1u << 10 )
-#define ALG_ECDSA_IS_DETERMINISTIC      ( 1u << 11 )
-#define ALG_IS_DETERMINISTIC_ECDSA      ( 1u << 12 )
-#define ALG_IS_RANDOMIZED_ECDSA         ( 1u << 13 )
-#define ALG_IS_HASH_AND_SIGN            ( 1u << 14 )
-#define ALG_IS_RSA_OAEP                 ( 1u << 15 )
-#define ALG_IS_HKDF                     ( 1u << 16 )
-#define ALG_IS_FFDH                     ( 1u << 17 )
-#define ALG_IS_ECDH                     ( 1u << 18 )
-#define ALG_IS_WILDCARD                 ( 1u << 19 )
-#define ALG_IS_RAW_KEY_AGREEMENT        ( 1u << 20 )
-#define ALG_IS_AEAD_ON_BLOCK_CIPHER     ( 1u << 21 )
-#define ALG_IS_TLS12_PRF                ( 1u << 22 )
-#define ALG_IS_TLS12_PSK_TO_MS          ( 1u << 23 )
+#define ALG_IS_RSA_PSS_ANY_SALT         ( 1u << 6 )
+#define ALG_IS_RSA_PSS_STANDARD_SALT    ( 1u << 7 )
+#define ALG_IS_DSA                      ( 1u << 8 )
+#define ALG_DSA_IS_DETERMINISTIC        ( 1u << 9 )
+#define ALG_IS_DETERMINISTIC_DSA        ( 1u << 10 )
+#define ALG_IS_RANDOMIZED_DSA           ( 1u << 11 )
+#define ALG_IS_ECDSA                    ( 1u << 12 )
+#define ALG_ECDSA_IS_DETERMINISTIC      ( 1u << 13 )
+#define ALG_IS_DETERMINISTIC_ECDSA      ( 1u << 14 )
+#define ALG_IS_RANDOMIZED_ECDSA         ( 1u << 15 )
+#define ALG_IS_HASH_EDDSA               ( 1u << 16 )
+#define ALG_IS_SIGN_HASH                ( 1u << 17 )
+#define ALG_IS_HASH_AND_SIGN            ( 1u << 18 )
+#define ALG_IS_RSA_OAEP                 ( 1u << 19 )
+#define ALG_IS_HKDF                     ( 1u << 20 )
+#define ALG_IS_FFDH                     ( 1u << 21 )
+#define ALG_IS_ECDH                     ( 1u << 22 )
+#define ALG_IS_WILDCARD                 ( 1u << 23 )
+#define ALG_IS_RAW_KEY_AGREEMENT        ( 1u << 24 )
+#define ALG_IS_AEAD_ON_BLOCK_CIPHER     ( 1u << 25 )
+#define ALG_IS_TLS12_PRF                ( 1u << 26 )
+#define ALG_IS_TLS12_PSK_TO_MS          ( 1u << 27 )
+#define ALG_FLAG_MASK_PLUS_ONE          ( 1u << 28 ) /* must be last! */
 
 /* Flags for key type classification macros. There is a flag for every
  * key type classification macro PSA_KEY_TYPE_IS_xxx except for some that
@@ -47,14 +53,44 @@
 #define KEY_TYPE_IS_VENDOR_DEFINED      ( 1u << 0 )
 #define KEY_TYPE_IS_UNSTRUCTURED        ( 1u << 1 )
 #define KEY_TYPE_IS_PUBLIC_KEY          ( 1u << 2 )
-#define KEY_TYPE_IS_KEY_PAIR             ( 1u << 3 )
+#define KEY_TYPE_IS_KEY_PAIR            ( 1u << 3 )
 #define KEY_TYPE_IS_RSA                 ( 1u << 4 )
 #define KEY_TYPE_IS_DSA                 ( 1u << 5 )
 #define KEY_TYPE_IS_ECC                 ( 1u << 6 )
 #define KEY_TYPE_IS_DH                  ( 1u << 7 )
+#define KEY_TYPE_FLAG_MASK_PLUS_ONE     ( 1u << 8 ) /* must be last! */
 
-#define TEST_CLASSIFICATION_MACRO( flag, alg, flags )           \
-    TEST_ASSERT( PSA_##flag( alg ) == !! ( ( flags ) & flag ) )
+/* Flags for lifetime classification macros. There is a flag for every
+ * lifetime classification macro PSA_KEY_LIFETIME_IS_xxx. The name of the
+ * flag is the name of the classification macro without the PSA_ prefix. */
+#define KEY_LIFETIME_IS_VOLATILE        ( 1u << 0 )
+#define KEY_LIFETIME_IS_READ_ONLY       ( 1u << 1 )
+#define KEY_LIFETIME_FLAG_MASK_PLUS_ONE ( 1u << 2 ) /* must be last! */
+
+/* Check that in the value of flags, the bit flag (which should be a macro
+ * expanding to a number of the form 1 << k) is set if and only if
+ * PSA_##flag(alg) is true.
+ *
+ * Only perform this check if cond is true. Typically cond is 1, but it can
+ * be different if the value of the flag bit is only specified under specific
+ * conditions.
+ *
+ * Unconditionally mask flag into the ambient variable
+ * classification_flags_tested.
+ */
+#define TEST_CLASSIFICATION_MACRO( cond, flag, alg, flags )     \
+    do                                                          \
+    {                                                           \
+        if( cond )                                              \
+        {                                                       \
+            if( ( flags ) & ( flag ) )                          \
+                TEST_ASSERT( PSA_##flag( alg ) );               \
+            else                                                \
+                TEST_ASSERT( ! PSA_##flag( alg ) );             \
+        }                                                       \
+        classification_flags_tested |= ( flag );                \
+    }                                                           \
+    while( 0 )
 
 /* Check the parity of value.
  *
@@ -80,43 +116,55 @@
 
 void algorithm_classification( psa_algorithm_t alg, unsigned flags )
 {
-    TEST_CLASSIFICATION_MACRO( ALG_IS_VENDOR_DEFINED, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_HMAC, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_BLOCK_CIPHER_MAC, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_STREAM_CIPHER, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_RSA_PKCS1V15_SIGN, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_RSA_PSS, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_DSA, alg, flags );
-    if ( PSA_ALG_IS_DSA( alg ) )
-        TEST_CLASSIFICATION_MACRO( ALG_DSA_IS_DETERMINISTIC, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_DETERMINISTIC_DSA, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_RANDOMIZED_DSA, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_ECDSA, alg, flags );
-    if ( PSA_ALG_IS_ECDSA( alg ) )
-        TEST_CLASSIFICATION_MACRO( ALG_ECDSA_IS_DETERMINISTIC, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_DETERMINISTIC_ECDSA, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_RANDOMIZED_ECDSA, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_HASH_AND_SIGN, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_RSA_OAEP, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_HKDF, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_WILDCARD, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_ECDH, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_FFDH, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_RAW_KEY_AGREEMENT, alg, flags );
-    TEST_CLASSIFICATION_MACRO( ALG_IS_AEAD_ON_BLOCK_CIPHER, alg, flags );
+    unsigned classification_flags_tested = 0;
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_VENDOR_DEFINED, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_HMAC, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_BLOCK_CIPHER_MAC, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_STREAM_CIPHER, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RSA_PKCS1V15_SIGN, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RSA_PSS, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RSA_PSS_ANY_SALT, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RSA_PSS_STANDARD_SALT, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_DSA, alg, flags );
+    TEST_CLASSIFICATION_MACRO( PSA_ALG_IS_DSA( alg ),
+                               ALG_DSA_IS_DETERMINISTIC, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_DETERMINISTIC_DSA, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RANDOMIZED_DSA, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_ECDSA, alg, flags );
+    TEST_CLASSIFICATION_MACRO( PSA_ALG_IS_ECDSA( alg ),
+                               ALG_ECDSA_IS_DETERMINISTIC, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_DETERMINISTIC_ECDSA, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RANDOMIZED_ECDSA, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_HASH_EDDSA, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_SIGN_HASH, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_HASH_AND_SIGN, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RSA_OAEP, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_HKDF, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_WILDCARD, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_ECDH, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_FFDH, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_RAW_KEY_AGREEMENT, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_AEAD_ON_BLOCK_CIPHER, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_TLS12_PRF, alg, flags );
+    TEST_CLASSIFICATION_MACRO( 1, ALG_IS_TLS12_PSK_TO_MS, alg, flags );
+    TEST_EQUAL( classification_flags_tested, ALG_FLAG_MASK_PLUS_ONE - 1 );
 exit: ;
 }
 
 void key_type_classification( psa_key_type_t type, unsigned flags )
 {
+    unsigned classification_flags_tested = 0;
+
     /* Macros tested based on the test case parameter */
-    TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_VENDOR_DEFINED, type, flags );
-    TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_UNSTRUCTURED, type, flags );
-    TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_PUBLIC_KEY, type, flags );
-    TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_KEY_PAIR, type, flags );
-    TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_RSA, type, flags );
-    TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_ECC, type, flags );
-    TEST_CLASSIFICATION_MACRO( KEY_TYPE_IS_DH, type, flags );
+    TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_VENDOR_DEFINED, type, flags );
+    TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_UNSTRUCTURED, type, flags );
+    TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_PUBLIC_KEY, type, flags );
+    TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_KEY_PAIR, type, flags );
+    TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_RSA, type, flags );
+    TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_DSA, type, flags );
+    TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_ECC, type, flags );
+    TEST_CLASSIFICATION_MACRO( 1, KEY_TYPE_IS_DH, type, flags );
+    TEST_EQUAL( classification_flags_tested, KEY_TYPE_FLAG_MASK_PLUS_ONE - 1 );
 
     /* Macros with derived semantics */
     TEST_EQUAL( PSA_KEY_TYPE_IS_ASYMMETRIC( type ),
@@ -156,12 +204,17 @@
     algorithm_classification( alg, classification_flags );
 
     /* Length */
-    TEST_EQUAL( length, PSA_MAC_FINAL_SIZE( key_type, key_bits, alg ) );
+    TEST_EQUAL( length, PSA_MAC_LENGTH( key_type, key_bits, alg ) );
+
+#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C)
+    PSA_ASSERT( psa_mac_key_can_do( alg, key_type ) );
+#endif
 
 exit: ;
 }
 
 void aead_algorithm_core( psa_algorithm_t alg, int classification_flags,
+                          psa_key_type_t key_type, size_t key_bits,
                           size_t tag_length )
 {
     /* Algorithm classification */
@@ -176,7 +229,7 @@
     algorithm_classification( alg, classification_flags );
 
     /* Tag length */
-    TEST_EQUAL( tag_length, PSA_AEAD_TAG_LENGTH( alg ) );
+    TEST_EQUAL( tag_length, PSA_AEAD_TAG_LENGTH( key_type, key_bits, alg ) );
 
 exit: ;
 }
@@ -184,7 +237,7 @@
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
- * depends_on:MBEDTLS_PSA_CRYPTO_C
+ * depends_on:MBEDTLS_PSA_CRYPTO_CLIENT
  * END_DEPENDENCIES
  */
 
@@ -226,7 +279,7 @@
     TEST_EQUAL( PSA_ALG_HKDF_GET_HASH( hkdf_alg ), alg );
 
     /* Hash length */
-    TEST_EQUAL( length, PSA_HASH_SIZE( alg ) );
+    TEST_EQUAL( length, PSA_HASH_LENGTH( alg ) );
     TEST_ASSERT( length <= PSA_HASH_MAX_SIZE );
 }
 /* END_CASE */
@@ -263,6 +316,52 @@
                     PSA_ALG_TRUNCATED_MAC( alg, length - 1) );
         TEST_EQUAL( PSA_ALG_TRUNCATED_MAC( truncated_alg, length ),
                     PSA_ALG_TRUNCATED_MAC( alg, length ) );
+
+        /* Check that calling PSA_ALG_TRUNCATED_MAC on an algorithm
+         * earlier constructed with PSA_ALG_AT_LEAST_THIS_LENGTH_MAC gives the
+         * length of the outer truncation (even if the outer length is smaller
+         * than the inner length). */
+        TEST_EQUAL( PSA_ALG_TRUNCATED_MAC(
+                        PSA_ALG_AT_LEAST_THIS_LENGTH_MAC( truncated_alg, n ), 1 ),
+                    PSA_ALG_TRUNCATED_MAC( alg, 1 ) );
+        TEST_EQUAL( PSA_ALG_TRUNCATED_MAC(
+                        PSA_ALG_AT_LEAST_THIS_LENGTH_MAC( truncated_alg, n ), length - 1 ),
+                    PSA_ALG_TRUNCATED_MAC( alg, length - 1) );
+        TEST_EQUAL( PSA_ALG_TRUNCATED_MAC(
+                        PSA_ALG_AT_LEAST_THIS_LENGTH_MAC( truncated_alg, n ), length ),
+                    PSA_ALG_TRUNCATED_MAC( alg, length ) );
+    }
+
+    /* At-leat-this-length versions */
+    for( n = 1; n <= length; n++ )
+    {
+        psa_algorithm_t policy_alg = PSA_ALG_AT_LEAST_THIS_LENGTH_MAC( alg, n );
+        mac_algorithm_core( policy_alg, classification_flags | ALG_IS_WILDCARD,
+                            key_type, key_bits, n );
+        TEST_EQUAL( PSA_ALG_FULL_LENGTH_MAC( policy_alg ), alg );
+        /* Check that calling PSA_ALG_AT_LEAST_THIS_LENGTH_MAC twice gives the
+         * length of the outer truncation (even if the outer length is smaller
+         * than the inner length). */
+        TEST_EQUAL( PSA_ALG_AT_LEAST_THIS_LENGTH_MAC( policy_alg, 1 ),
+                    PSA_ALG_AT_LEAST_THIS_LENGTH_MAC( alg, 1 ) );
+        TEST_EQUAL( PSA_ALG_AT_LEAST_THIS_LENGTH_MAC( policy_alg, length - 1 ),
+                    PSA_ALG_AT_LEAST_THIS_LENGTH_MAC( alg, length - 1) );
+        TEST_EQUAL( PSA_ALG_AT_LEAST_THIS_LENGTH_MAC( policy_alg, length ),
+                    PSA_ALG_AT_LEAST_THIS_LENGTH_MAC( alg, length ) );
+
+        /* Check that calling PSA_ALG_AT_LEAST_THIS_LENGTH_MAC on an algorithm
+         * earlier constructed with PSA_ALG_TRUNCATED_MAC gives the length of
+         * the outer truncation (even if the outer length is smaller than the
+         * inner length). */
+        TEST_EQUAL( PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(
+                        PSA_ALG_TRUNCATED_MAC( policy_alg, n ), 1),
+                    PSA_ALG_AT_LEAST_THIS_LENGTH_MAC( alg, 1 ) );
+        TEST_EQUAL( PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(
+                        PSA_ALG_TRUNCATED_MAC( policy_alg, n ), length - 1 ),
+                    PSA_ALG_AT_LEAST_THIS_LENGTH_MAC( alg, length - 1) );
+        TEST_EQUAL( PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(
+                        PSA_ALG_TRUNCATED_MAC( policy_alg, n ), length ),
+                    PSA_ALG_AT_LEAST_THIS_LENGTH_MAC( alg, length ) );
     }
 }
 /* END_CASE */
@@ -281,6 +380,7 @@
     TEST_ASSERT( PSA_ALG_IS_HASH( hash_alg ) );
     TEST_EQUAL( PSA_ALG_HMAC( hash_alg ), alg );
 
+    TEST_ASSERT( block_size == PSA_HASH_BLOCK_LENGTH( alg ) );
     TEST_ASSERT( block_size <= PSA_HMAC_MAX_HASH_BLOCK_SIZE );
 
     test_mac_algorithm( alg_arg, ALG_IS_HMAC, length,
@@ -314,30 +414,82 @@
 
 /* BEGIN_CASE */
 void aead_algorithm( int alg_arg, int classification_flags,
-                     int tag_length_arg )
+                     int tag_length_arg,
+                     int key_type_arg, int key_bits_arg )
 {
     psa_algorithm_t alg = alg_arg;
     size_t tag_length = tag_length_arg;
     size_t n;
+    psa_key_type_t key_type = key_type_arg;
+    size_t key_bits = key_bits_arg;
 
-    aead_algorithm_core( alg, classification_flags, tag_length );
+    aead_algorithm_core( alg, classification_flags,
+                         key_type, key_bits, tag_length );
 
     /* Truncated versions */
     for( n = 1; n <= tag_length; n++ )
     {
-        psa_algorithm_t truncated_alg = PSA_ALG_AEAD_WITH_TAG_LENGTH( alg, n );
-        aead_algorithm_core( truncated_alg, classification_flags, n );
-        TEST_EQUAL( PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH( truncated_alg ),
+        psa_algorithm_t truncated_alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, n );
+        aead_algorithm_core( truncated_alg, classification_flags,
+                             key_type, key_bits, n );
+        TEST_EQUAL( PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG( truncated_alg ),
                     alg );
-        /* Check that calling PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH twice gives
+        /* Check that calling PSA_ALG_AEAD_WITH_SHORTENED_TAG twice gives
          * the length of the outer truncation (even if the outer length is
          * smaller than the inner length). */
-        TEST_EQUAL( PSA_ALG_AEAD_WITH_TAG_LENGTH( truncated_alg, 1 ),
-                    PSA_ALG_AEAD_WITH_TAG_LENGTH( alg, 1 ) );
-        TEST_EQUAL( PSA_ALG_AEAD_WITH_TAG_LENGTH( truncated_alg, tag_length - 1 ),
-                    PSA_ALG_AEAD_WITH_TAG_LENGTH( alg, tag_length - 1) );
-        TEST_EQUAL( PSA_ALG_AEAD_WITH_TAG_LENGTH( truncated_alg, tag_length ),
-                    PSA_ALG_AEAD_WITH_TAG_LENGTH( alg, tag_length ) );
+        TEST_EQUAL( PSA_ALG_AEAD_WITH_SHORTENED_TAG( truncated_alg, 1 ),
+                    PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 1 ) );
+        TEST_EQUAL( PSA_ALG_AEAD_WITH_SHORTENED_TAG( truncated_alg, tag_length - 1 ),
+                    PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, tag_length - 1) );
+        TEST_EQUAL( PSA_ALG_AEAD_WITH_SHORTENED_TAG( truncated_alg, tag_length ),
+                    PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, tag_length ) );
+
+        /* Check that calling PSA_ALG_AEAD_WITH_SHORTENED_TAG on an algorithm
+         * earlier constructed with PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG
+         * gives the length of the outer truncation (even if the outer length is
+         * smaller than the inner length). */
+        TEST_EQUAL( PSA_ALG_AEAD_WITH_SHORTENED_TAG(
+                        PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG( truncated_alg, n ), 1 ),
+                    PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 1 ) );
+        TEST_EQUAL( PSA_ALG_AEAD_WITH_SHORTENED_TAG(
+                        PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG( truncated_alg, n ), tag_length - 1 ),
+                    PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, tag_length - 1) );
+        TEST_EQUAL( PSA_ALG_AEAD_WITH_SHORTENED_TAG(
+                        PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG( truncated_alg, n ), tag_length ),
+                    PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, tag_length ) );
+    }
+
+    /* At-leat-this-length versions */
+    for( n = 1; n <= tag_length; n++ )
+    {
+        psa_algorithm_t policy_alg = PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG( alg, n );
+        aead_algorithm_core( policy_alg, classification_flags | ALG_IS_WILDCARD,
+                             key_type, key_bits, n );
+        TEST_EQUAL( PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG( policy_alg ),
+                    alg );
+        /* Check that calling PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG twice
+         * gives the length of the outer truncation (even if the outer length is
+         * smaller than the inner length). */
+        TEST_EQUAL( PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG( policy_alg, 1 ),
+                    PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG( alg, 1 ) );
+        TEST_EQUAL( PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG( policy_alg, tag_length - 1 ),
+                    PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG( alg, tag_length - 1) );
+        TEST_EQUAL( PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG( policy_alg, tag_length ),
+                    PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG( alg, tag_length ) );
+
+        /* Check that calling PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG on an
+         * algorithm earlier constructed with PSA_ALG_AEAD_WITH_SHORTENED_TAG
+         * gives the length of the outer truncation (even if the outer length is
+         * smaller than the inner length). */
+        TEST_EQUAL( PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(
+                        PSA_ALG_AEAD_WITH_SHORTENED_TAG( policy_alg, n ), 1),
+                    PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG( alg, 1 ) );
+        TEST_EQUAL( PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(
+                        PSA_ALG_AEAD_WITH_SHORTENED_TAG( policy_alg, n ), tag_length - 1 ),
+                    PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG( alg, tag_length - 1) );
+        TEST_EQUAL( PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(
+                        PSA_ALG_AEAD_WITH_SHORTENED_TAG( policy_alg, n ), tag_length ),
+                    PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG( alg, tag_length ) );
     }
 }
 /* END_CASE */
@@ -363,7 +515,9 @@
 /* BEGIN_CASE */
 void asymmetric_signature_wildcard( int alg_arg, int classification_flags )
 {
-    classification_flags |= ALG_IS_HASH_AND_SIGN | ALG_IS_WILDCARD;
+    classification_flags |= ALG_IS_WILDCARD;
+    classification_flags |= ALG_IS_SIGN_HASH;
+    classification_flags |= ALG_IS_HASH_AND_SIGN;
     test_asymmetric_signature_algorithm( alg_arg, classification_flags );
     /* Any failure of this test function comes from
      * asymmetric_signature_algorithm. Pacify -Werror=unused-label. */
@@ -483,7 +637,11 @@
 
     TEST_EQUAL( type & PSA_KEY_TYPE_CATEGORY_MASK,
                 PSA_KEY_TYPE_CATEGORY_SYMMETRIC );
-    TEST_EQUAL( PSA_BLOCK_CIPHER_BLOCK_SIZE( type ), block_size );
+    TEST_EQUAL( PSA_BLOCK_CIPHER_BLOCK_LENGTH( type ), block_size );
+
+    /* Check that the block size is a power of 2. This is required, at least,
+    for PSA_ROUND_UP_TO_MULTIPLE(block_size, length) in crypto_sizes.h. */
+    TEST_ASSERT( ( ( block_size - 1 ) & block_size ) == 0 );
 }
 /* END_CASE */
 
@@ -496,11 +654,11 @@
 
     TEST_EQUAL( type & PSA_KEY_TYPE_CATEGORY_MASK,
                 PSA_KEY_TYPE_CATEGORY_SYMMETRIC );
-    TEST_EQUAL( PSA_BLOCK_CIPHER_BLOCK_SIZE( type ), 1 );
+    TEST_EQUAL( PSA_BLOCK_CIPHER_BLOCK_LENGTH( type ), 1 );
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_ECP_C */
+/* BEGIN_CASE depends_on:PSA_KEY_TYPE_ECC_PUBLIC_KEY:PSA_KEY_TYPE_ECC_KEY_PAIR */
 void ecc_key_family( int curve_arg )
 {
     psa_ecc_family_t curve = curve_arg;
@@ -533,3 +691,23 @@
     TEST_EQUAL( PSA_KEY_TYPE_DH_GET_FAMILY( pair_type ), group );
 }
 /* END_CASE */
+
+/* BEGIN_CASE */
+void lifetime( int lifetime_arg, int classification_flags,
+               int persistence_arg, int location_arg )
+{
+    psa_key_lifetime_t lifetime = lifetime_arg;
+    psa_key_persistence_t persistence = persistence_arg;
+    psa_key_location_t location = location_arg;
+    unsigned flags = classification_flags;
+    unsigned classification_flags_tested = 0;
+
+    TEST_CLASSIFICATION_MACRO( 1, KEY_LIFETIME_IS_VOLATILE, lifetime, flags );
+    TEST_CLASSIFICATION_MACRO( 1, KEY_LIFETIME_IS_READ_ONLY, lifetime, flags );
+    TEST_EQUAL( classification_flags_tested,
+                KEY_LIFETIME_FLAG_MASK_PLUS_ONE - 1 );
+
+    TEST_EQUAL( PSA_KEY_LIFETIME_GET_PERSISTENCE( lifetime ), persistence );
+    TEST_EQUAL( PSA_KEY_LIFETIME_GET_LOCATION( lifetime ), location );
+}
+/* END_CASE */
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_not_supported.function b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_not_supported.function
new file mode 100644
index 0000000..e3253d8
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_not_supported.function
@@ -0,0 +1,52 @@
+/* BEGIN_HEADER */
+
+#include "psa/crypto.h"
+#include "test/psa_crypto_helpers.h"
+
+#define INVALID_KEY_ID mbedtls_svc_key_id_make( 0, 0xfedcba98 )
+
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_PSA_CRYPTO_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void import_not_supported( int key_type, data_t *key_material )
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t key_id = INVALID_KEY_ID;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+    psa_set_key_type( &attributes, key_type );
+    TEST_EQUAL( psa_import_key( &attributes,
+                                key_material->x, key_material->len,
+                                &key_id ),
+                PSA_ERROR_NOT_SUPPORTED );
+    TEST_ASSERT( mbedtls_svc_key_id_equal( key_id, MBEDTLS_SVC_KEY_ID_INIT ) );
+
+exit:
+    psa_destroy_key( key_id );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void generate_not_supported( int key_type, int bits )
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t key_id = INVALID_KEY_ID;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+    psa_set_key_type( &attributes, key_type );
+    psa_set_key_bits( &attributes, bits );
+    TEST_EQUAL( psa_generate_key( &attributes, &key_id ),
+                PSA_ERROR_NOT_SUPPORTED );
+    TEST_ASSERT( mbedtls_svc_key_id_equal( key_id, MBEDTLS_SVC_KEY_ID_INIT ) );
+
+exit:
+    psa_destroy_key( key_id );
+    PSA_DONE( );
+}
+/* END_CASE */
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_not_supported.generated.data b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_not_supported.generated.data
new file mode 100644
index 0000000..b5c8a52
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_not_supported.generated.data
@@ -0,0 +1,947 @@
+# Automatically generated by generate_psa_tests.py. Do not edit!
+
+PSA import AES 128-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_AES
+import_not_supported:PSA_KEY_TYPE_AES:"48657265006973206b6579a064617461"
+
+PSA generate AES 128-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_AES
+generate_not_supported:PSA_KEY_TYPE_AES:128
+
+PSA import AES 192-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_AES
+import_not_supported:PSA_KEY_TYPE_AES:"48657265006973206b6579a0646174614865726500697320"
+
+PSA generate AES 192-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_AES
+generate_not_supported:PSA_KEY_TYPE_AES:192
+
+PSA import AES 256-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_AES
+import_not_supported:PSA_KEY_TYPE_AES:"48657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA generate AES 256-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_AES
+generate_not_supported:PSA_KEY_TYPE_AES:256
+
+PSA import ARC4 8-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_ARC4
+import_not_supported:PSA_KEY_TYPE_ARC4:"48"
+
+PSA generate ARC4 8-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_ARC4
+generate_not_supported:PSA_KEY_TYPE_ARC4:8
+
+PSA import ARC4 128-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_ARC4
+import_not_supported:PSA_KEY_TYPE_ARC4:"48657265006973206b6579a064617461"
+
+PSA generate ARC4 128-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_ARC4
+generate_not_supported:PSA_KEY_TYPE_ARC4:128
+
+PSA import ARC4 2048-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_ARC4
+import_not_supported:PSA_KEY_TYPE_ARC4:"48657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA generate ARC4 2048-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_ARC4
+generate_not_supported:PSA_KEY_TYPE_ARC4:2048
+
+PSA import ARIA 128-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_ARIA
+import_not_supported:PSA_KEY_TYPE_ARIA:"48657265006973206b6579a064617461"
+
+PSA generate ARIA 128-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_ARIA
+generate_not_supported:PSA_KEY_TYPE_ARIA:128
+
+PSA import ARIA 192-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_ARIA
+import_not_supported:PSA_KEY_TYPE_ARIA:"48657265006973206b6579a0646174614865726500697320"
+
+PSA generate ARIA 192-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_ARIA
+generate_not_supported:PSA_KEY_TYPE_ARIA:192
+
+PSA import ARIA 256-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_ARIA
+import_not_supported:PSA_KEY_TYPE_ARIA:"48657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA generate ARIA 256-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_ARIA
+generate_not_supported:PSA_KEY_TYPE_ARIA:256
+
+PSA import CAMELLIA 128-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_CAMELLIA
+import_not_supported:PSA_KEY_TYPE_CAMELLIA:"48657265006973206b6579a064617461"
+
+PSA generate CAMELLIA 128-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_CAMELLIA
+generate_not_supported:PSA_KEY_TYPE_CAMELLIA:128
+
+PSA import CAMELLIA 192-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_CAMELLIA
+import_not_supported:PSA_KEY_TYPE_CAMELLIA:"48657265006973206b6579a0646174614865726500697320"
+
+PSA generate CAMELLIA 192-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_CAMELLIA
+generate_not_supported:PSA_KEY_TYPE_CAMELLIA:192
+
+PSA import CAMELLIA 256-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_CAMELLIA
+import_not_supported:PSA_KEY_TYPE_CAMELLIA:"48657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA generate CAMELLIA 256-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_CAMELLIA
+generate_not_supported:PSA_KEY_TYPE_CAMELLIA:256
+
+PSA import CHACHA20 256-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_CHACHA20
+import_not_supported:PSA_KEY_TYPE_CHACHA20:"48657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA generate CHACHA20 256-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_CHACHA20
+generate_not_supported:PSA_KEY_TYPE_CHACHA20:256
+
+PSA import DES 64-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_DES
+import_not_supported:PSA_KEY_TYPE_DES:"644573206b457901"
+
+PSA generate DES 64-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_DES
+generate_not_supported:PSA_KEY_TYPE_DES:64
+
+PSA import DES 128-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_DES
+import_not_supported:PSA_KEY_TYPE_DES:"644573206b457901644573206b457902"
+
+PSA generate DES 128-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_DES
+generate_not_supported:PSA_KEY_TYPE_DES:128
+
+PSA import DES 192-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_DES
+import_not_supported:PSA_KEY_TYPE_DES:"644573206b457901644573206b457902644573206b457904"
+
+PSA generate DES 192-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_DES
+generate_not_supported:PSA_KEY_TYPE_DES:192
+
+PSA import HMAC 128-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_HMAC
+import_not_supported:PSA_KEY_TYPE_HMAC:"48657265006973206b6579a064617461"
+
+PSA generate HMAC 128-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_HMAC
+generate_not_supported:PSA_KEY_TYPE_HMAC:128
+
+PSA import HMAC 160-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_HMAC
+import_not_supported:PSA_KEY_TYPE_HMAC:"48657265006973206b6579a06461746148657265"
+
+PSA generate HMAC 160-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_HMAC
+generate_not_supported:PSA_KEY_TYPE_HMAC:160
+
+PSA import HMAC 224-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_HMAC
+import_not_supported:PSA_KEY_TYPE_HMAC:"48657265006973206b6579a06461746148657265006973206b6579a0"
+
+PSA generate HMAC 224-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_HMAC
+generate_not_supported:PSA_KEY_TYPE_HMAC:224
+
+PSA import HMAC 256-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_HMAC
+import_not_supported:PSA_KEY_TYPE_HMAC:"48657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA generate HMAC 256-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_HMAC
+generate_not_supported:PSA_KEY_TYPE_HMAC:256
+
+PSA import HMAC 384-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_HMAC
+import_not_supported:PSA_KEY_TYPE_HMAC:"48657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA generate HMAC 384-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_HMAC
+generate_not_supported:PSA_KEY_TYPE_HMAC:384
+
+PSA import HMAC 512-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_HMAC
+import_not_supported:PSA_KEY_TYPE_HMAC:"48657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA generate HMAC 512-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_HMAC
+generate_not_supported:PSA_KEY_TYPE_HMAC:512
+
+PSA import RSA_KEY_PAIR 1024-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+import_not_supported:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24"
+
+PSA generate RSA_KEY_PAIR 1024-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+generate_not_supported:PSA_KEY_TYPE_RSA_KEY_PAIR:1024
+
+PSA import RSA_KEY_PAIR 1536-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+import_not_supported:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082037b0201000281c100c870feb6ca6b1d2bd9f2dd99e20f1fe2d7e5192de662229dbe162bd1ba66336a7182903ca0b72796cd441c83d24bcdc3e9a2f5e4399c8a043f1c3ddf04754a66d4cfe7b3671a37dd31a9b4c13bfe06ee90f9d94ddaa06de67a52ac863e68f756736ceb014405a6160579640f831dddccc34ad0b05070e3f9954a58d1815813e1b83bcadba814789c87f1ef2ba5d738b793ec456a67360eea1b5faf1c7cc7bf24f3b2a9d0f8958b1096e0f0c335f8888d0c63a51c3c0337214fa3f5efdf6dcc3502030100010281c06d2d670047973a87752a9d5bc14f3dae00acb01f593aa0e24cf4a49f932931de4bbfb332e2d38083da80bc0b6d538edba479f7f77d0deffb4a28e6e67ff6273585bb4cd862535c946605ab0809d65f0e38f76e4ec2c3d9b8cd6e14bcf667943892cd4b34cc6420a439abbf3d7d35ef73976dd6f9cbde35a51fa5213f0107f83e3425835d16d3c9146fc9e36ce75a09bb66cdff21dd5a776899f1cb07e282cca27be46510e9c799f0d8db275a6be085d9f3f803218ee3384265bfb1a3640e8ca1026100e6848c31d466fffefc547e3a3b0d3785de6f78b0dd12610843512e495611a0675509b1650b27415009838dd8e68eec6e7530553b637d602424643b33e8bc5b762e1799bc79d56b13251d36d4f201da2182416ce13574e88278ff04467ad602d9026100de994fdf181f02be2bf9e5f5e4e517a94993b827d1eaf609033e3a6a6f2396ae7c44e9eb594cf1044cb3ad32ea258f0c82963b27bb650ed200cde82cb993374be34be5b1c7ead5446a2b82a4486e8c1810a0b01551609fb0841d474bada802bd026076ddae751b73a959d0bfb8ff49e7fcd378e9be30652ecefe35c82cb8003bc29cc60ae3809909baf20c95db9516fe680865417111d8b193dbcf30281f1249de57c858bf1ba32f5bb1599800e8398a9ef25c7a642c95261da6f9c17670e97265b10260732482b837d5f2a9443e23c1aa0106d83e82f6c3424673b5fdc3769c0f992d1c5c93991c7038e882fcda04414df4d7a5f4f698ead87851ce37344b60b72d7b70f9c60cae8566e7a257f8e1bef0e89df6e4c2f9d24d21d9f8889e4c7eccf91751026009050d94493da8f00a4ddbe9c800afe3d44b43f78a48941a79b2814a1f0b81a18a8b2347642a03b27998f5a18de9abc9ae0e54ab8294feac66dc87e854cce6f7278ac2710cb5878b592ffeb1f4f0a1853e4e8d1d0561b6efcc831a296cf7eeaf"
+
+PSA generate RSA_KEY_PAIR 1536-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+generate_not_supported:PSA_KEY_TYPE_RSA_KEY_PAIR:1536
+
+PSA import RSA_PUBLIC_KEY 1024-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
+import_not_supported:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001"
+
+PSA import RSA_PUBLIC_KEY 1536-bit not supported
+depends_on:!PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
+import_not_supported:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"3081c90281c100c870feb6ca6b1d2bd9f2dd99e20f1fe2d7e5192de662229dbe162bd1ba66336a7182903ca0b72796cd441c83d24bcdc3e9a2f5e4399c8a043f1c3ddf04754a66d4cfe7b3671a37dd31a9b4c13bfe06ee90f9d94ddaa06de67a52ac863e68f756736ceb014405a6160579640f831dddccc34ad0b05070e3f9954a58d1815813e1b83bcadba814789c87f1ef2ba5d738b793ec456a67360eea1b5faf1c7cc7bf24f3b2a9d0f8958b1096e0f0c335f8888d0c63a51c3c0337214fa3f5efdf6dcc350203010001"
+
+PSA import ECC_KEY_PAIR(BRAINPOOL_P_R1) 160-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_160:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"69502c4fdaf48d4fa617bdd24498b0406d0eeaac"
+
+PSA generate ECC_KEY_PAIR(BRAINPOOL_P_R1) 160-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_160:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):160
+
+PSA import ECC_KEY_PAIR(BRAINPOOL_P_R1) 192-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_192:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"1688a2c5fbf4a3c851d76a98c3ec88f445a97996283db59f"
+
+PSA generate ECC_KEY_PAIR(BRAINPOOL_P_R1) 192-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_192:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):192
+
+PSA import ECC_KEY_PAIR(BRAINPOOL_P_R1) 224-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_224:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"a69835dafeb5da5ab89c59860dddebcfd80b529a99f59b880882923c"
+
+PSA generate ECC_KEY_PAIR(BRAINPOOL_P_R1) 224-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_224:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):224
+
+PSA import ECC_KEY_PAIR(BRAINPOOL_P_R1) 256-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_256
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"2161d6f2db76526fa62c16f356a80f01f32f776784b36aa99799a8b7662080ff"
+
+PSA generate ECC_KEY_PAIR(BRAINPOOL_P_R1) 256-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_256
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):256
+
+PSA import ECC_KEY_PAIR(BRAINPOOL_P_R1) 320-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_320:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"61b8daa7a6e5aa9fccf1ef504220b2e5a5b8c6dc7475d16d3172d7db0b2778414e4f6e8fa2032ead"
+
+PSA generate ECC_KEY_PAIR(BRAINPOOL_P_R1) 320-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_320:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):320
+
+PSA import ECC_KEY_PAIR(BRAINPOOL_P_R1) 384-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_384
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"3dd92e750d90d7d39fc1885cd8ad12ea9441f22b9334b4d965202adb1448ce24c5808a85dd9afc229af0a3124f755bcb"
+
+PSA generate ECC_KEY_PAIR(BRAINPOOL_P_R1) 384-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_384
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):384
+
+PSA import ECC_KEY_PAIR(BRAINPOOL_P_R1) 512-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_512
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"372c9778f69f726cbca3f4a268f16b4d617d10280d79a6a029cd51879fe1012934dfe5395455337df6906dc7d6d2eea4dbb2065c0228f73b3ed716480e7d71d2"
+
+PSA generate ECC_KEY_PAIR(BRAINPOOL_P_R1) 512-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_BRAINPOOL_P_R1_512
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):512
+
+PSA import ECC_KEY_PAIR(BRAINPOOL_P_R1) 160-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_BRAINPOOL_P_R1_160:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"69502c4fdaf48d4fa617bdd24498b0406d0eeaac"
+
+PSA generate ECC_KEY_PAIR(BRAINPOOL_P_R1) 160-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_BRAINPOOL_P_R1_160:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):160
+
+PSA import ECC_KEY_PAIR(BRAINPOOL_P_R1) 192-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_BRAINPOOL_P_R1_192:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"1688a2c5fbf4a3c851d76a98c3ec88f445a97996283db59f"
+
+PSA generate ECC_KEY_PAIR(BRAINPOOL_P_R1) 192-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_BRAINPOOL_P_R1_192:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):192
+
+PSA import ECC_KEY_PAIR(BRAINPOOL_P_R1) 224-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_BRAINPOOL_P_R1_224:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"a69835dafeb5da5ab89c59860dddebcfd80b529a99f59b880882923c"
+
+PSA generate ECC_KEY_PAIR(BRAINPOOL_P_R1) 224-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_BRAINPOOL_P_R1_224:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):224
+
+PSA import ECC_KEY_PAIR(BRAINPOOL_P_R1) 256-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_BRAINPOOL_P_R1_256
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"2161d6f2db76526fa62c16f356a80f01f32f776784b36aa99799a8b7662080ff"
+
+PSA generate ECC_KEY_PAIR(BRAINPOOL_P_R1) 256-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_BRAINPOOL_P_R1_256
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):256
+
+PSA import ECC_KEY_PAIR(BRAINPOOL_P_R1) 320-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_BRAINPOOL_P_R1_320:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"61b8daa7a6e5aa9fccf1ef504220b2e5a5b8c6dc7475d16d3172d7db0b2778414e4f6e8fa2032ead"
+
+PSA generate ECC_KEY_PAIR(BRAINPOOL_P_R1) 320-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_BRAINPOOL_P_R1_320:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):320
+
+PSA import ECC_KEY_PAIR(BRAINPOOL_P_R1) 384-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_BRAINPOOL_P_R1_384
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"3dd92e750d90d7d39fc1885cd8ad12ea9441f22b9334b4d965202adb1448ce24c5808a85dd9afc229af0a3124f755bcb"
+
+PSA generate ECC_KEY_PAIR(BRAINPOOL_P_R1) 384-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_BRAINPOOL_P_R1_384
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):384
+
+PSA import ECC_KEY_PAIR(BRAINPOOL_P_R1) 512-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_BRAINPOOL_P_R1_512
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"372c9778f69f726cbca3f4a268f16b4d617d10280d79a6a029cd51879fe1012934dfe5395455337df6906dc7d6d2eea4dbb2065c0228f73b3ed716480e7d71d2"
+
+PSA generate ECC_KEY_PAIR(BRAINPOOL_P_R1) 512-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_BRAINPOOL_P_R1_512
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):512
+
+PSA import ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 160-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_BRAINPOOL_P_R1_160:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"04d4b9186816358e2f9c59cf70748cb70641b22fbab65473db4b4e22a361ed7e3de7e8a8ddc4130c5c"
+
+PSA import ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 192-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_BRAINPOOL_P_R1_192:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"043fdd168c179ff5363dd71dcd58de9617caad791ae0c37328be9ca0bfc79cebabf6a95d1c52df5b5f3c8b1a2441cf6c88"
+
+PSA import ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 224-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_BRAINPOOL_P_R1_224:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"045fbea378fc8583b3837e3f21a457c31eaf20a54e18eb11d104b3adc47f9d1c97eb9ea4ac21740d70d88514b98bf0bc31addac1d19c4ab3cc"
+
+PSA import ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 256-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_BRAINPOOL_P_R1_256
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"04768c8cae4abca6306db0ed81b0c4a6215c378066ec6d616c146e13f1c7df809b96ab6911c27d8a02339f0926840e55236d3d1efbe2669d090e4c4c660fada91d"
+
+PSA import ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 320-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_BRAINPOOL_P_R1_320:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"049caed8fb4742956cc2ad12a9a1c995e21759ef26a07bc2054136d3d2f28bb331a70e26c4c687275ab1f434be7871e115d2350c0c5f61d4d06d2bcdb67f5cb63fdb794e5947c87dc6849a58694e37e6cd"
+
+PSA import ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 384-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_BRAINPOOL_P_R1_384
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"04719f9d093a627e0d350385c661cebf00c61923566fe9006a3107af1d871bc6bb68985fd722ea32be316f8e783b7cd1957785f66cfc0cb195dd5c99a8e7abaa848553a584dfd2b48e76d445fe00dd8be59096d877d4696d23b4bc8db14724e66a"
+
+PSA import ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 512-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_BRAINPOOL_P_R1_512
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"0438b7ec92b61c5c6c7fbc28a4ec759d48fcd4e2e374defd5c4968a54dbef7510e517886fbfc38ea39aa529359d70a7156c35d3cbac7ce776bdb251dd64bce71234424ee7049eed072f0dbc4d79996e175d557e263763ae97095c081e73e7db2e38adc3d4c9a0487b1ede876dc1fca61c902e9a1d8722b8612928f18a24845591a"
+
+PSA import ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 160-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_BRAINPOOL_P_R1_160:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"04d4b9186816358e2f9c59cf70748cb70641b22fbab65473db4b4e22a361ed7e3de7e8a8ddc4130c5c"
+
+PSA import ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 192-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_BRAINPOOL_P_R1_192:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"043fdd168c179ff5363dd71dcd58de9617caad791ae0c37328be9ca0bfc79cebabf6a95d1c52df5b5f3c8b1a2441cf6c88"
+
+PSA import ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 224-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_BRAINPOOL_P_R1_224:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"045fbea378fc8583b3837e3f21a457c31eaf20a54e18eb11d104b3adc47f9d1c97eb9ea4ac21740d70d88514b98bf0bc31addac1d19c4ab3cc"
+
+PSA import ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 256-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_BRAINPOOL_P_R1_256
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"04768c8cae4abca6306db0ed81b0c4a6215c378066ec6d616c146e13f1c7df809b96ab6911c27d8a02339f0926840e55236d3d1efbe2669d090e4c4c660fada91d"
+
+PSA import ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 320-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_BRAINPOOL_P_R1_320:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"049caed8fb4742956cc2ad12a9a1c995e21759ef26a07bc2054136d3d2f28bb331a70e26c4c687275ab1f434be7871e115d2350c0c5f61d4d06d2bcdb67f5cb63fdb794e5947c87dc6849a58694e37e6cd"
+
+PSA import ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 384-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_BRAINPOOL_P_R1_384
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"04719f9d093a627e0d350385c661cebf00c61923566fe9006a3107af1d871bc6bb68985fd722ea32be316f8e783b7cd1957785f66cfc0cb195dd5c99a8e7abaa848553a584dfd2b48e76d445fe00dd8be59096d877d4696d23b4bc8db14724e66a"
+
+PSA import ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 512-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_BRAINPOOL_P_R1_512
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):"0438b7ec92b61c5c6c7fbc28a4ec759d48fcd4e2e374defd5c4968a54dbef7510e517886fbfc38ea39aa529359d70a7156c35d3cbac7ce776bdb251dd64bce71234424ee7049eed072f0dbc4d79996e175d557e263763ae97095c081e73e7db2e38adc3d4c9a0487b1ede876dc1fca61c902e9a1d8722b8612928f18a24845591a"
+
+PSA import ECC_KEY_PAIR(MONTGOMERY) 255-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_MONTGOMERY_255
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):"70076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c6a"
+
+PSA generate ECC_KEY_PAIR(MONTGOMERY) 255-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_MONTGOMERY_255
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):255
+
+PSA import ECC_KEY_PAIR(MONTGOMERY) 448-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_MONTGOMERY_448
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):"e4e49f52686f9ee3b638528f721f1596196ffd0a1cddb64c3f216f06541805cfeb1a286dc78018095cdfec050e8007b5f4908962ba20d6c1"
+
+PSA generate ECC_KEY_PAIR(MONTGOMERY) 448-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_MONTGOMERY_448
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):448
+
+PSA import ECC_KEY_PAIR(MONTGOMERY) 255-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_MONTGOMERY_255
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):"70076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c6a"
+
+PSA generate ECC_KEY_PAIR(MONTGOMERY) 255-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_MONTGOMERY_255
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):255
+
+PSA import ECC_KEY_PAIR(MONTGOMERY) 448-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_MONTGOMERY_448
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):"e4e49f52686f9ee3b638528f721f1596196ffd0a1cddb64c3f216f06541805cfeb1a286dc78018095cdfec050e8007b5f4908962ba20d6c1"
+
+PSA generate ECC_KEY_PAIR(MONTGOMERY) 448-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_MONTGOMERY_448
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):448
+
+PSA import ECC_PUBLIC_KEY(MONTGOMERY) 255-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_MONTGOMERY_255
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_MONTGOMERY):"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"
+
+PSA import ECC_PUBLIC_KEY(MONTGOMERY) 448-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_MONTGOMERY_448
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_MONTGOMERY):"c0d3a5a2b416a573dc9909f92f134ac01323ab8f8e36804e578588ba2d09fe7c3e737f771ca112825b548a0ffded6d6a2fd09a3e77dec30e"
+
+PSA import ECC_PUBLIC_KEY(MONTGOMERY) 255-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_MONTGOMERY_255
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_MONTGOMERY):"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"
+
+PSA import ECC_PUBLIC_KEY(MONTGOMERY) 448-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_MONTGOMERY_448
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_MONTGOMERY):"c0d3a5a2b416a573dc9909f92f134ac01323ab8f8e36804e578588ba2d09fe7c3e737f771ca112825b548a0ffded6d6a2fd09a3e77dec30e"
+
+PSA import ECC_KEY_PAIR(SECP_K1) 192-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_K1_192
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):"297ac1722ccac7589ecb240dc719842538ca974beb79f228"
+
+PSA generate ECC_KEY_PAIR(SECP_K1) 192-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_K1_192
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):192
+
+PSA import ECC_KEY_PAIR(SECP_K1) 224-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_K1_224
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):"0024122bf020fa113f6c0ac978dfbd41f749257a9468febdbe0dc9f7e8"
+
+PSA generate ECC_KEY_PAIR(SECP_K1) 224-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_K1_224
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):224
+
+PSA import ECC_KEY_PAIR(SECP_K1) 256-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_K1_256
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):"7fa06fa02d0e911b9a47fdc17d2d962ca01e2f31d60c6212d0ed7e3bba23a7b9"
+
+PSA generate ECC_KEY_PAIR(SECP_K1) 256-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_K1_256
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):256
+
+PSA import ECC_KEY_PAIR(SECP_K1) 192-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECP_K1_192
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):"297ac1722ccac7589ecb240dc719842538ca974beb79f228"
+
+PSA generate ECC_KEY_PAIR(SECP_K1) 192-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECP_K1_192
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):192
+
+PSA import ECC_KEY_PAIR(SECP_K1) 224-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECP_K1_224
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):"0024122bf020fa113f6c0ac978dfbd41f749257a9468febdbe0dc9f7e8"
+
+PSA generate ECC_KEY_PAIR(SECP_K1) 224-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECP_K1_224
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):224
+
+PSA import ECC_KEY_PAIR(SECP_K1) 256-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECP_K1_256
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):"7fa06fa02d0e911b9a47fdc17d2d962ca01e2f31d60c6212d0ed7e3bba23a7b9"
+
+PSA generate ECC_KEY_PAIR(SECP_K1) 256-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECP_K1_256
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):256
+
+PSA import ECC_PUBLIC_KEY(SECP_K1) 192-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECP_K1_192
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_K1):"0426b7bb38da649ac2138fc050c6548b32553dab68afebc36105d325b75538c12323cb0764789ecb992671beb2b6bef2f5"
+
+PSA import ECC_PUBLIC_KEY(SECP_K1) 224-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECP_K1_224
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_K1):"042cc7335f4b76042bed44ef45959a62aa215f7a5ff0c8111b8c44ed654ee71c1918326ad485b2d599fe2a6eab096ee26d977334d2bac6d61d"
+
+PSA import ECC_PUBLIC_KEY(SECP_K1) 256-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECP_K1_256
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_K1):"045c39154579efd667adc73a81015a797d2c8682cdfbd3c3553c4a185d481cdc50e42a0e1cbc3ca29a32a645e927f54beaed14c9dbbf8279d725f5495ca924b24d"
+
+PSA import ECC_PUBLIC_KEY(SECP_K1) 192-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECP_K1_192
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_K1):"0426b7bb38da649ac2138fc050c6548b32553dab68afebc36105d325b75538c12323cb0764789ecb992671beb2b6bef2f5"
+
+PSA import ECC_PUBLIC_KEY(SECP_K1) 224-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECP_K1_224
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_K1):"042cc7335f4b76042bed44ef45959a62aa215f7a5ff0c8111b8c44ed654ee71c1918326ad485b2d599fe2a6eab096ee26d977334d2bac6d61d"
+
+PSA import ECC_PUBLIC_KEY(SECP_K1) 256-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECP_K1_256
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_K1):"045c39154579efd667adc73a81015a797d2c8682cdfbd3c3553c4a185d481cdc50e42a0e1cbc3ca29a32a645e927f54beaed14c9dbbf8279d725f5495ca924b24d"
+
+PSA import ECC_KEY_PAIR(SECP_R1) 225-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_225:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"872f203b3ad35b7f2ecc803c3a0e1e0b1ed61cc1afe71b189cd4c995"
+
+PSA generate ECC_KEY_PAIR(SECP_R1) 225-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_225:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):225
+
+PSA import ECC_KEY_PAIR(SECP_R1) 256-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee"
+
+PSA generate ECC_KEY_PAIR(SECP_R1) 256-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256
+
+PSA import ECC_KEY_PAIR(SECP_R1) 384-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_384
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a"
+
+PSA generate ECC_KEY_PAIR(SECP_R1) 384-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_384
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):384
+
+PSA import ECC_KEY_PAIR(SECP_R1) 521-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_521
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"01b1b6ad07bb79e7320da59860ea28e055284f6058f279de666e06d435d2af7bda28d99fa47b7dd0963e16b0073078ee8b8a38d966a582f46d19ff95df3ad9685aae"
+
+PSA generate ECC_KEY_PAIR(SECP_R1) 521-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_521
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):521
+
+PSA import ECC_KEY_PAIR(SECP_R1) 225-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECP_R1_225:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"872f203b3ad35b7f2ecc803c3a0e1e0b1ed61cc1afe71b189cd4c995"
+
+PSA generate ECC_KEY_PAIR(SECP_R1) 225-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECP_R1_225:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):225
+
+PSA import ECC_KEY_PAIR(SECP_R1) 256-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECP_R1_256
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee"
+
+PSA generate ECC_KEY_PAIR(SECP_R1) 256-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECP_R1_256
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256
+
+PSA import ECC_KEY_PAIR(SECP_R1) 384-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECP_R1_384
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a"
+
+PSA generate ECC_KEY_PAIR(SECP_R1) 384-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECP_R1_384
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):384
+
+PSA import ECC_KEY_PAIR(SECP_R1) 521-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECP_R1_521
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"01b1b6ad07bb79e7320da59860ea28e055284f6058f279de666e06d435d2af7bda28d99fa47b7dd0963e16b0073078ee8b8a38d966a582f46d19ff95df3ad9685aae"
+
+PSA generate ECC_KEY_PAIR(SECP_R1) 521-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECP_R1_521
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):521
+
+PSA import ECC_PUBLIC_KEY(SECP_R1) 225-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECP_R1_225:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"046f00eadaa949fee3e9e1c7fa1247eecec86a0dce46418b9bd3117b981d4bd0ae7a990de912f9d060d6cb531a42d22e394ac29e81804bf160"
+
+PSA import ECC_PUBLIC_KEY(SECP_R1) 256-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECP_R1_256
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45"
+
+PSA import ECC_PUBLIC_KEY(SECP_R1) 384-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECP_R1_384
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04d9c662b50ba29ca47990450e043aeaf4f0c69b15676d112f622a71c93059af999691c5680d2b44d111579db12f4a413a2ed5c45fcfb67b5b63e00b91ebe59d09a6b1ac2c0c4282aa12317ed5914f999bc488bb132e8342cc36f2ca5e3379c747"
+
+PSA import ECC_PUBLIC_KEY(SECP_R1) 521-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECP_R1_521
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04001de142d54f69eb038ee4b7af9d3ca07736fd9cf719eb354d69879ee7f3c136fb0fbf9f08f86be5fa128ec1a051d3e6c643e85ada8ffacf3663c260bd2c844b6f5600cee8e48a9e65d09cadd89f235dee05f3b8a646be715f1f67d5b434e0ff23a1fc07ef7740193e40eeff6f3bcdfd765aa9155033524fe4f205f5444e292c4c2f6ac1"
+
+PSA import ECC_PUBLIC_KEY(SECP_R1) 225-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECP_R1_225:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"046f00eadaa949fee3e9e1c7fa1247eecec86a0dce46418b9bd3117b981d4bd0ae7a990de912f9d060d6cb531a42d22e394ac29e81804bf160"
+
+PSA import ECC_PUBLIC_KEY(SECP_R1) 256-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECP_R1_256
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45"
+
+PSA import ECC_PUBLIC_KEY(SECP_R1) 384-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECP_R1_384
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04d9c662b50ba29ca47990450e043aeaf4f0c69b15676d112f622a71c93059af999691c5680d2b44d111579db12f4a413a2ed5c45fcfb67b5b63e00b91ebe59d09a6b1ac2c0c4282aa12317ed5914f999bc488bb132e8342cc36f2ca5e3379c747"
+
+PSA import ECC_PUBLIC_KEY(SECP_R1) 521-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECP_R1_521
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04001de142d54f69eb038ee4b7af9d3ca07736fd9cf719eb354d69879ee7f3c136fb0fbf9f08f86be5fa128ec1a051d3e6c643e85ada8ffacf3663c260bd2c844b6f5600cee8e48a9e65d09cadd89f235dee05f3b8a646be715f1f67d5b434e0ff23a1fc07ef7740193e40eeff6f3bcdfd765aa9155033524fe4f205f5444e292c4c2f6ac1"
+
+PSA import ECC_KEY_PAIR(SECP_R2) 160-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R2_160:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R2):"00bf539a1cdda0d7f71a50a3f98aec0a2e8e4ced1e"
+
+PSA generate ECC_KEY_PAIR(SECP_R2) 160-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R2_160:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R2):160
+
+PSA import ECC_KEY_PAIR(SECP_R2) 160-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECP_R2_160:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R2):"00bf539a1cdda0d7f71a50a3f98aec0a2e8e4ced1e"
+
+PSA generate ECC_KEY_PAIR(SECP_R2) 160-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECP_R2_160:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R2):160
+
+PSA import ECC_PUBLIC_KEY(SECP_R2) 160-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECP_R2_160:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R2):"049570d541398665adb5cfa16f5af73b3196926bbd4b876bdb80f8eab20d0f540c22f4de9c140f6d7b"
+
+PSA import ECC_PUBLIC_KEY(SECP_R2) 160-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECP_R2_160:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R2):"049570d541398665adb5cfa16f5af73b3196926bbd4b876bdb80f8eab20d0f540c22f4de9c140f6d7b"
+
+PSA import ECC_KEY_PAIR(SECT_K1) 163-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):"03ebc8fcded2d6ab72ec0f75bdb4fd080481273e71"
+
+PSA generate ECC_KEY_PAIR(SECT_K1) 163-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):163
+
+PSA import ECC_KEY_PAIR(SECT_K1) 233-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_233:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):"41f08485ce587b06061c087e76e247c359de2ba9927ee013b2f1ed9ca8"
+
+PSA generate ECC_KEY_PAIR(SECT_K1) 233-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_233:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):233
+
+PSA import ECC_KEY_PAIR(SECT_K1) 239-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_239:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):"1a8069ce2c2c8bdd7087f2a6ab49588797e6294e979495602ab9650b9c61"
+
+PSA generate ECC_KEY_PAIR(SECT_K1) 239-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_239:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):239
+
+PSA import ECC_KEY_PAIR(SECT_K1) 283-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_283:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):"006d627885dd48b9ec6facb5b3865377d755b75a5d51440e45211c1f600e15eff8a881a0"
+
+PSA generate ECC_KEY_PAIR(SECT_K1) 283-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_283:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):283
+
+PSA import ECC_KEY_PAIR(SECT_K1) 409-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_409:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):"3ff5e74d932fa77db139b7c948c81e4069c72c24845574064beea8976b70267f1c6f9a503e3892ea1dcbb71fcea423faa370a8"
+
+PSA generate ECC_KEY_PAIR(SECT_K1) 409-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_409:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):409
+
+PSA import ECC_KEY_PAIR(SECT_K1) 571-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_571:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):"005008c97b4a161c0db1bac6452c72846d57337aa92d8ecb4a66eb01d2f29555ffb61a5317225dcc8ca6917d91789e227efc0bfe9eeda7ee21998cd11c3c9885056b0e55b4f75d51"
+
+PSA generate ECC_KEY_PAIR(SECT_K1) 571-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_K1_571:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):571
+
+PSA import ECC_KEY_PAIR(SECT_K1) 163-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_K1_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):"03ebc8fcded2d6ab72ec0f75bdb4fd080481273e71"
+
+PSA generate ECC_KEY_PAIR(SECT_K1) 163-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_K1_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):163
+
+PSA import ECC_KEY_PAIR(SECT_K1) 233-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_K1_233:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):"41f08485ce587b06061c087e76e247c359de2ba9927ee013b2f1ed9ca8"
+
+PSA generate ECC_KEY_PAIR(SECT_K1) 233-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_K1_233:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):233
+
+PSA import ECC_KEY_PAIR(SECT_K1) 239-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_K1_239:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):"1a8069ce2c2c8bdd7087f2a6ab49588797e6294e979495602ab9650b9c61"
+
+PSA generate ECC_KEY_PAIR(SECT_K1) 239-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_K1_239:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):239
+
+PSA import ECC_KEY_PAIR(SECT_K1) 283-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_K1_283:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):"006d627885dd48b9ec6facb5b3865377d755b75a5d51440e45211c1f600e15eff8a881a0"
+
+PSA generate ECC_KEY_PAIR(SECT_K1) 283-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_K1_283:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):283
+
+PSA import ECC_KEY_PAIR(SECT_K1) 409-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_K1_409:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):"3ff5e74d932fa77db139b7c948c81e4069c72c24845574064beea8976b70267f1c6f9a503e3892ea1dcbb71fcea423faa370a8"
+
+PSA generate ECC_KEY_PAIR(SECT_K1) 409-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_K1_409:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):409
+
+PSA import ECC_KEY_PAIR(SECT_K1) 571-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_K1_571:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):"005008c97b4a161c0db1bac6452c72846d57337aa92d8ecb4a66eb01d2f29555ffb61a5317225dcc8ca6917d91789e227efc0bfe9eeda7ee21998cd11c3c9885056b0e55b4f75d51"
+
+PSA generate ECC_KEY_PAIR(SECT_K1) 571-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_K1_571:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):571
+
+PSA import ECC_PUBLIC_KEY(SECT_K1) 163-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECT_K1_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):"0406f88f90b4b65950f06ce433afdb097e320f433dc2062b8a65db8fafd3c110f46bc45663fbf021ee7eb9"
+
+PSA import ECC_PUBLIC_KEY(SECT_K1) 233-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECT_K1_233:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):"0401e9d7189189f773bd8f71be2c10774ba18842434dfa9312595ea545104400f45a9d5675647513ba75b079fe66a29daac2ec86a6a5d4e75c5f290c1f"
+
+PSA import ECC_PUBLIC_KEY(SECT_K1) 239-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECT_K1_239:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):"04068d76b9f4508762c2379db9ee8b87ad8d86d9535132ffba3b5680440cfa28eb133d4232faf1c9aba96af11aefe634a551440800d5f8185105d3072d"
+
+PSA import ECC_PUBLIC_KEY(SECT_K1) 283-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECT_K1_283:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):"0405f48374debceaadb46ba385fd92048fcc5b9af1a1c90408bf94a68b9378df1cbfdfb6fb026a96bea06d8f181bf10c020adbcc88b6ecff96bdc564a9649c247cede601c4be63afc3"
+
+PSA import ECC_PUBLIC_KEY(SECT_K1) 409-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECT_K1_409:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):"04012c587f69f68b308ba6dcb238797f4e22290ca939ae806604e2b5ab4d9caef5a74a98fd87c4f88d292dd39d92e556e16c6ecc3c019a105826eef507cd9a04119f54d5d850b3720b3792d5d03410e9105610f7e4b420166ed45604a7a1f229d80975ba6be2060e8b"
+
+PSA import ECC_PUBLIC_KEY(SECT_K1) 571-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECT_K1_571:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):"04050172a7fd7adf98e4e2ed2742faa5cd12731a15fb0dbbdf75b1c3cc771a4369af6f2fa00e802735650881735759ea9c79961ded18e0daa0ac59afb1d513b5bbda9962e435f454fc020b4afe1445c2302ada07d295ec2580f8849b2dfa7f956b09b4cbe4c88d3b1c217049f75d3900d36df0fa12689256b58dd2ef784ebbeb0564600cf47a841485f8cf897a68accd5a"
+
+PSA import ECC_PUBLIC_KEY(SECT_K1) 163-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECT_K1_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):"0406f88f90b4b65950f06ce433afdb097e320f433dc2062b8a65db8fafd3c110f46bc45663fbf021ee7eb9"
+
+PSA import ECC_PUBLIC_KEY(SECT_K1) 233-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECT_K1_233:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):"0401e9d7189189f773bd8f71be2c10774ba18842434dfa9312595ea545104400f45a9d5675647513ba75b079fe66a29daac2ec86a6a5d4e75c5f290c1f"
+
+PSA import ECC_PUBLIC_KEY(SECT_K1) 239-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECT_K1_239:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):"04068d76b9f4508762c2379db9ee8b87ad8d86d9535132ffba3b5680440cfa28eb133d4232faf1c9aba96af11aefe634a551440800d5f8185105d3072d"
+
+PSA import ECC_PUBLIC_KEY(SECT_K1) 283-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECT_K1_283:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):"0405f48374debceaadb46ba385fd92048fcc5b9af1a1c90408bf94a68b9378df1cbfdfb6fb026a96bea06d8f181bf10c020adbcc88b6ecff96bdc564a9649c247cede601c4be63afc3"
+
+PSA import ECC_PUBLIC_KEY(SECT_K1) 409-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECT_K1_409:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):"04012c587f69f68b308ba6dcb238797f4e22290ca939ae806604e2b5ab4d9caef5a74a98fd87c4f88d292dd39d92e556e16c6ecc3c019a105826eef507cd9a04119f54d5d850b3720b3792d5d03410e9105610f7e4b420166ed45604a7a1f229d80975ba6be2060e8b"
+
+PSA import ECC_PUBLIC_KEY(SECT_K1) 571-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECT_K1_571:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):"04050172a7fd7adf98e4e2ed2742faa5cd12731a15fb0dbbdf75b1c3cc771a4369af6f2fa00e802735650881735759ea9c79961ded18e0daa0ac59afb1d513b5bbda9962e435f454fc020b4afe1445c2302ada07d295ec2580f8849b2dfa7f956b09b4cbe4c88d3b1c217049f75d3900d36df0fa12689256b58dd2ef784ebbeb0564600cf47a841485f8cf897a68accd5a"
+
+PSA import ECC_KEY_PAIR(SECT_R1) 163-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R1_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):"009b05dc82d46d64a04a22e6e5ca70ca1231e68c50"
+
+PSA generate ECC_KEY_PAIR(SECT_R1) 163-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R1_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):163
+
+PSA import ECC_KEY_PAIR(SECT_R1) 233-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R1_233:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):"00e5e42834e3c78758088b905deea975f28dc20ef6173e481f96e88afe7f"
+
+PSA generate ECC_KEY_PAIR(SECT_R1) 233-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R1_233:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):233
+
+PSA import ECC_KEY_PAIR(SECT_R1) 283-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R1_283:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):"004cecad915f6f3c9bbbd92d1eb101eda23f16c7dad60a57c87c7e1fd2b29b22f6d666ad"
+
+PSA generate ECC_KEY_PAIR(SECT_R1) 283-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R1_283:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):283
+
+PSA import ECC_KEY_PAIR(SECT_R1) 409-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R1_409:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):"00c22422d265721a3ae2b3b2baeb77bee50416e19877af97b5fc1c700a0a88916ecb9050135883accb5e64edc77a3703f4f67a64"
+
+PSA generate ECC_KEY_PAIR(SECT_R1) 409-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R1_409:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):409
+
+PSA import ECC_KEY_PAIR(SECT_R1) 571-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R1_571:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):"026ac1cdf92a13a1b8d282da9725847908745138f5c6706b52d164e3675fcfbf86fc3e6ab2de732193267db029dd35a0599a94a118f480231cfc6ccca2ebfc1d8f54176e0f5656a1"
+
+PSA generate ECC_KEY_PAIR(SECT_R1) 571-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R1_571:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):571
+
+PSA import ECC_KEY_PAIR(SECT_R1) 163-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_R1_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):"009b05dc82d46d64a04a22e6e5ca70ca1231e68c50"
+
+PSA generate ECC_KEY_PAIR(SECT_R1) 163-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_R1_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):163
+
+PSA import ECC_KEY_PAIR(SECT_R1) 233-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_R1_233:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):"00e5e42834e3c78758088b905deea975f28dc20ef6173e481f96e88afe7f"
+
+PSA generate ECC_KEY_PAIR(SECT_R1) 233-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_R1_233:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):233
+
+PSA import ECC_KEY_PAIR(SECT_R1) 283-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_R1_283:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):"004cecad915f6f3c9bbbd92d1eb101eda23f16c7dad60a57c87c7e1fd2b29b22f6d666ad"
+
+PSA generate ECC_KEY_PAIR(SECT_R1) 283-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_R1_283:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):283
+
+PSA import ECC_KEY_PAIR(SECT_R1) 409-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_R1_409:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):"00c22422d265721a3ae2b3b2baeb77bee50416e19877af97b5fc1c700a0a88916ecb9050135883accb5e64edc77a3703f4f67a64"
+
+PSA generate ECC_KEY_PAIR(SECT_R1) 409-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_R1_409:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):409
+
+PSA import ECC_KEY_PAIR(SECT_R1) 571-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_R1_571:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):"026ac1cdf92a13a1b8d282da9725847908745138f5c6706b52d164e3675fcfbf86fc3e6ab2de732193267db029dd35a0599a94a118f480231cfc6ccca2ebfc1d8f54176e0f5656a1"
+
+PSA generate ECC_KEY_PAIR(SECT_R1) 571-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_R1_571:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):571
+
+PSA import ECC_PUBLIC_KEY(SECT_R1) 163-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECT_R1_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):"0400465eeb9e7258b11e33c02266bfe834b20bcb118700772796ee4704ec67651bd447e3011959a79a04cb"
+
+PSA import ECC_PUBLIC_KEY(SECT_R1) 233-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECT_R1_233:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):"0400cd68c8af4430c92ec7a7048becfdf00a6bae8d1b4c37286f2d336f2a0e017eca3748f4ad6d435c85867aa014eea1bd6d9d005bbd8319cab629001d"
+
+PSA import ECC_PUBLIC_KEY(SECT_R1) 283-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECT_R1_283:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):"04052f9ff887254c2d1440ba9e30f13e2185ba53c373b2c410dae21cf8c167f796c08134f601cbc4c570bffbc2433082cf4d9eb5ba173ecb8caec15d66a02673f60807b2daa729b765"
+
+PSA import ECC_PUBLIC_KEY(SECT_R1) 409-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECT_R1_409:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):"0401aa25466b1d291846db365957b25431591e50d9c109fe2106e93bb369775896925b15a7bfec397406ab4fe6f6b1a13bf8fdcb9300fa5500a813228676b0a6c572ed96b0f4aec7e87832e7e20f17ca98ecdfd36f59c82bddb8665f1f357a73900e827885ec9e1f22"
+
+PSA import ECC_PUBLIC_KEY(SECT_R1) 571-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECT_R1_571:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):"040708f3403ee9948114855c17572152a08f8054d486defef5f29cbffcfb7cfd9280746a1ac5f751a6ad902ec1e0525120e9be56f03437af196fbe60ee7856e3542ab2cf87880632d80290e39b1a2bd03c6bbf6225511c567bd2ff41d2325dc58346f2b60b1feee4dc8b2af2296c2dc52b153e0556b5d24152b07f690c3fa24e4d1d19efbdeb1037833a733654d2366c74"
+
+PSA import ECC_PUBLIC_KEY(SECT_R1) 163-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECT_R1_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):"0400465eeb9e7258b11e33c02266bfe834b20bcb118700772796ee4704ec67651bd447e3011959a79a04cb"
+
+PSA import ECC_PUBLIC_KEY(SECT_R1) 233-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECT_R1_233:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):"0400cd68c8af4430c92ec7a7048becfdf00a6bae8d1b4c37286f2d336f2a0e017eca3748f4ad6d435c85867aa014eea1bd6d9d005bbd8319cab629001d"
+
+PSA import ECC_PUBLIC_KEY(SECT_R1) 283-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECT_R1_283:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):"04052f9ff887254c2d1440ba9e30f13e2185ba53c373b2c410dae21cf8c167f796c08134f601cbc4c570bffbc2433082cf4d9eb5ba173ecb8caec15d66a02673f60807b2daa729b765"
+
+PSA import ECC_PUBLIC_KEY(SECT_R1) 409-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECT_R1_409:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):"0401aa25466b1d291846db365957b25431591e50d9c109fe2106e93bb369775896925b15a7bfec397406ab4fe6f6b1a13bf8fdcb9300fa5500a813228676b0a6c572ed96b0f4aec7e87832e7e20f17ca98ecdfd36f59c82bddb8665f1f357a73900e827885ec9e1f22"
+
+PSA import ECC_PUBLIC_KEY(SECT_R1) 571-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECT_R1_571:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):"040708f3403ee9948114855c17572152a08f8054d486defef5f29cbffcfb7cfd9280746a1ac5f751a6ad902ec1e0525120e9be56f03437af196fbe60ee7856e3542ab2cf87880632d80290e39b1a2bd03c6bbf6225511c567bd2ff41d2325dc58346f2b60b1feee4dc8b2af2296c2dc52b153e0556b5d24152b07f690c3fa24e4d1d19efbdeb1037833a733654d2366c74"
+
+PSA import ECC_KEY_PAIR(SECT_R2) 163-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R2_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R2):"0210b482a458b4822d0cb21daa96819a67c8062d34"
+
+PSA generate ECC_KEY_PAIR(SECT_R2) 163-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECT_R2_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R2):163
+
+PSA import ECC_KEY_PAIR(SECT_R2) 163-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_R2_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R2):"0210b482a458b4822d0cb21daa96819a67c8062d34"
+
+PSA generate ECC_KEY_PAIR(SECT_R2) 163-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_SECT_R2_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R2):163
+
+PSA import ECC_PUBLIC_KEY(SECT_R2) 163-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_SECT_R2_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R2):"0403692601144c32a6cfa369ae20ae5d43c1c764678c037bafe80c6fd2e42b7ced96171d9c5367fd3dca6f"
+
+PSA import ECC_PUBLIC_KEY(SECT_R2) 163-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_SECT_R2_163:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R2):"0403692601144c32a6cfa369ae20ae5d43c1c764678c037bafe80c6fd2e42b7ced96171d9c5367fd3dca6f"
+
+PSA import ECC_KEY_PAIR(TWISTED_EDWARDS) 255-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_TWISTED_EDWARDS_255:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"
+
+PSA generate ECC_KEY_PAIR(TWISTED_EDWARDS) 255-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_TWISTED_EDWARDS_255:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):255
+
+PSA import ECC_KEY_PAIR(TWISTED_EDWARDS) 448-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_TWISTED_EDWARDS_448:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):"6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b"
+
+PSA generate ECC_KEY_PAIR(TWISTED_EDWARDS) 448-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_TWISTED_EDWARDS_448:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):448
+
+PSA import ECC_KEY_PAIR(TWISTED_EDWARDS) 255-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_TWISTED_EDWARDS_255:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"
+
+PSA generate ECC_KEY_PAIR(TWISTED_EDWARDS) 255-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_TWISTED_EDWARDS_255:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):255
+
+PSA import ECC_KEY_PAIR(TWISTED_EDWARDS) 448-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_TWISTED_EDWARDS_448:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):"6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b"
+
+PSA generate ECC_KEY_PAIR(TWISTED_EDWARDS) 448-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:!PSA_WANT_ECC_TWISTED_EDWARDS_448:DEPENDENCY_NOT_IMPLEMENTED_YET
+generate_not_supported:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):448
+
+PSA import ECC_PUBLIC_KEY(TWISTED_EDWARDS) 255-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_TWISTED_EDWARDS_255:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS):"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"
+
+PSA import ECC_PUBLIC_KEY(TWISTED_EDWARDS) 448-bit type not supported
+depends_on:!PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:PSA_WANT_ECC_TWISTED_EDWARDS_448:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS):"5fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180"
+
+PSA import ECC_PUBLIC_KEY(TWISTED_EDWARDS) 255-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_TWISTED_EDWARDS_255:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS):"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"
+
+PSA import ECC_PUBLIC_KEY(TWISTED_EDWARDS) 448-bit curve not supported
+depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:!PSA_WANT_ECC_TWISTED_EDWARDS_448:DEPENDENCY_NOT_IMPLEMENTED_YET
+import_not_supported:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS):"5fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180"
+
+# End of automatically generated file.
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_not_supported.misc.data b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_not_supported.misc.data
new file mode 100644
index 0000000..2c3673e
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_not_supported.misc.data
@@ -0,0 +1,11 @@
+PSA import PSA_KEY_TYPE_NONE never supported
+import_not_supported:PSA_KEY_TYPE_NONE:"1234"
+
+PSA generate PSA_KEY_TYPE_NONE never supported
+generate_not_supported:PSA_KEY_TYPE_NONE:16
+
+PSA import PSA_KEY_TYPE_CATEGORY_SYMMETRIC never supported
+import_not_supported:PSA_KEY_TYPE_CATEGORY_SYMMETRIC:"1234"
+
+PSA generate PSA_KEY_TYPE_CATEGORY_SYMMETRIC never supported
+generate_not_supported:PSA_KEY_TYPE_CATEGORY_SYMMETRIC:16
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_persistent_key.data b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_persistent_key.data
index 80035d8..b250634 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_persistent_key.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_persistent_key.data
@@ -11,16 +11,22 @@
 parse_storage_data_check:"505341004b45590000000000010000000024800000030000000250050000000010000000404142434445464748494a4b4c4d4e4f":"404142434445464748494a4b4c4d4e4f":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_GCM:0:PSA_SUCCESS
 
 Parse storage: wrong version
-parse_storage_data_check:"505341004b455900ffffffff0100000001700004010000000000001200000010620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_STORAGE_FAILURE
+parse_storage_data_check:"505341004b455900ffffffff0100000001700004010000000000001200000010620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_DATA_INVALID
 
 Parse storage: data too big
-parse_storage_data_check:"505341004b455900000000000100000001700000010000000000001200000010ffffffff3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_STORAGE_FAILURE
+parse_storage_data_check:"505341004b455900000000000100000001700000010000000000001200000010ffffffff3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_DATA_INVALID
 
 Parse storage: bad magic
-parse_storage_data_check:"645341004b455900000000000100000001700004010000000000001200000010620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_STORAGE_FAILURE
+parse_storage_data_check:"645341004b455900000000000100000001700004010000000000001200000010620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_DATA_INVALID
 
 Parse storage: truncated magic
-parse_storage_data_check:"505341004b4559":"":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_STORAGE_FAILURE
+parse_storage_data_check:"505341004b4559":"":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_DATA_INVALID
+
+Parse storage: truncated header
+parse_storage_data_check:"505341004b455900000000000100000001700000010000000000001200000010620200":"":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_DATA_INVALID
+
+Parse storage: truncated key
+parse_storage_data_check:"505341004b455900000000000100000001700000010000000000001200000010620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b":"":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION:PSA_ALG_CATEGORY_SIGN:PSA_ERROR_DATA_INVALID
 
 # Not specific to files, but only run this test in an environment where the maximum size could be reached.
 Save maximum-size persistent raw key
@@ -31,85 +37,94 @@
 save_large_persistent_key:PSA_CRYPTO_MAX_STORAGE_SIZE + 1:PSA_ERROR_NOT_SUPPORTED
 
 Persistent key destroy
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
 persistent_key_destroy:2:1:0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RAW_DATA:"deadbeef"
 
 Persistent key destroy after restart
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
 persistent_key_destroy:17:1:1:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RAW_DATA:"deadbeef"
 
 Persistent key import (RSA)
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
 persistent_key_import:256:1:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_SUCCESS
 
 Persistent key import with restart (RSA)
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
 persistent_key_import:256:1:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":1:PSA_SUCCESS
 
 Persistent key import (RSA) invalid key id (VENDOR_MIN)
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-persistent_key_import:256:PSA_KEY_ID_VENDOR_MIN:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_ERROR_INVALID_HANDLE
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
+persistent_key_import:256:PSA_KEY_ID_VENDOR_MIN:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_ERROR_INVALID_ARGUMENT
 
 Persistent key import (RSA) invalid key id (VOLATILE_MIN)
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-persistent_key_import:256:PSA_KEY_ID_VOLATILE_MIN:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_ERROR_INVALID_HANDLE
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
+persistent_key_import:256:PSA_KEY_ID_VOLATILE_MIN:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_ERROR_INVALID_ARGUMENT
 
 Persistent key import (RSA) invalid key id (VENDOR_MAX)
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-persistent_key_import:256:PSA_KEY_ID_VENDOR_MAX:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_ERROR_INVALID_HANDLE
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
+persistent_key_import:256:PSA_KEY_ID_VENDOR_MAX:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_ERROR_INVALID_ARGUMENT
 
 Persistent key import garbage data, should fail
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
 persistent_key_import:256:1:PSA_KEY_TYPE_RSA_KEY_PAIR:"11111111":0:PSA_ERROR_INVALID_ARGUMENT
 
 import/export persistent raw key: 1 byte
 import_export_persistent_key:"2a":PSA_KEY_TYPE_RAW_DATA:8:0:0
 
 import/export persistent key RSA public key: good, 1024-bit
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
 import_export_persistent_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:0:0
 
 import/export persistent key RSA keypair: good, 1024-bit
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
 import_export_persistent_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:1024:0:0
 
 import/export persistent raw key file not exist: 1 byte
 import_export_persistent_key:"2a":PSA_KEY_TYPE_RAW_DATA:8:0:1
 
 import/export persistent key RSA public key file not exist: 1024-bit
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
 import_export_persistent_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:0:1
 
 import/export persistent key RSA keypair file not exist: 1024-bit
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
 import_export_persistent_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:1024:0:1
 
 import/export-persistent symmetric key: 16 bytes
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
 import_export_persistent_key:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:128:0:0
 
 import/export persistent raw key with restart: 1 byte
 import_export_persistent_key:"2a":PSA_KEY_TYPE_RAW_DATA:8:1:0
 
 import/export persistent key RSA public key with restart: good, 1024-bit
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
 import_export_persistent_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:1:0
 
 import/export persistent key RSA keypair with restart: good, 1024-bit
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
 import_export_persistent_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:1024:1:0
 
 import/export persistent raw key file not exist with restart: 1 byte
 import_export_persistent_key:"2a":PSA_KEY_TYPE_RAW_DATA:8:1:1
 
 import/export persistent key RSA public key file not exist with restart: 1024-bit
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
 import_export_persistent_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:1:1
 
 import/export persistent key RSA keypair file not exist with restart: 1024-bit
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
 import_export_persistent_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:1024:1:1
 
 import/export-persistent symmetric key with restart: 16 bytes
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+depends_on:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C
 import_export_persistent_key:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:128:1:0
+
+Destroy invalid id: 0
+destroy_nonexistent:0:PSA_SUCCESS
+
+Destroy non-existent key
+destroy_nonexistent:1:PSA_ERROR_INVALID_HANDLE
+
+Destroy invalid id: 0xffffffff
+destroy_nonexistent:0xffffffff:PSA_ERROR_INVALID_HANDLE
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_persistent_key.function b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_persistent_key.function
index 8e10158..bd9b9c9 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_persistent_key.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_persistent_key.function
@@ -9,7 +9,6 @@
 
 #include <stdint.h>
 
-#include "test/psa_crypto_helpers.h"
 #include "psa_crypto_slot_management.h"
 #include "psa_crypto_storage.h"
 
@@ -324,3 +323,18 @@
     psa_destroy_persistent_key( key_id );
 }
 /* END_CASE */
+
+/* BEGIN_CASE */
+void destroy_nonexistent( int id_arg, int expected_status_arg )
+{
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, id_arg );
+    psa_status_t expected_status = expected_status_arg;
+
+    PSA_INIT( );
+
+    TEST_EQUAL( expected_status, psa_destroy_key( id ) );
+
+exit:
+    PSA_DONE( );
+}
+/* END_CASE */
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_se_driver_hal.data b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_se_driver_hal.data
index 18d1d74..2bcf4e4 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_se_driver_hal.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_se_driver_hal.data
@@ -78,6 +78,21 @@
 Key import smoke test: AES-GCM
 import_key_smoke:PSA_KEY_TYPE_AES:PSA_ALG_GCM:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
 
+Key import smoke test: ARIA-CTR
+import_key_smoke:PSA_KEY_TYPE_ARIA:PSA_ALG_CTR:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+Key import smoke test: ARIA-CBC
+import_key_smoke:PSA_KEY_TYPE_ARIA:PSA_ALG_CBC_NO_PADDING:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+Key import smoke test: ARIA-CMAC
+import_key_smoke:PSA_KEY_TYPE_ARIA:PSA_ALG_CMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+Key import smoke test: ARIA-CCM
+import_key_smoke:PSA_KEY_TYPE_ARIA:PSA_ALG_CCM:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+Key import smoke test: ARIA-GCM
+import_key_smoke:PSA_KEY_TYPE_ARIA:PSA_ALG_GCM:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
 Key import smoke test: CAMELLIA-CTR
 import_key_smoke:PSA_KEY_TYPE_CAMELLIA:PSA_ALG_CTR:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
 
@@ -148,40 +163,40 @@
 register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:7:1:-1:PSA_ERROR_NOT_SUPPORTED
 
 Key registration: key id out of range
-register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:7:PSA_KEY_ID_VENDOR_MAX+1:-1:PSA_ERROR_INVALID_HANDLE
+register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:7:PSA_KEY_ID_VENDOR_MAX+1:-1:PSA_ERROR_INVALID_ARGUMENT
 
 Key registration: key id min vendor
-register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:7:PSA_KEY_ID_VENDOR_MIN:1:PSA_ERROR_INVALID_HANDLE
+register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:7:PSA_KEY_ID_VENDOR_MIN:1:PSA_ERROR_INVALID_ARGUMENT
 
 Key registration: key id max vendor except volatile
-register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:7:PSA_KEY_ID_VOLATILE_MIN-1:1:PSA_ERROR_INVALID_HANDLE
+register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:7:PSA_KEY_ID_VOLATILE_MIN-1:1:PSA_ERROR_INVALID_ARGUMENT
 
 Key registration: key id min volatile
-register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:7:PSA_KEY_ID_VOLATILE_MIN:1:PSA_ERROR_INVALID_HANDLE
+register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:7:PSA_KEY_ID_VOLATILE_MIN:1:PSA_ERROR_INVALID_ARGUMENT
 
 Key registration: key id max volatile
-register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:7:PSA_KEY_ID_VOLATILE_MAX:1:PSA_ERROR_INVALID_HANDLE
+register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:7:PSA_KEY_ID_VOLATILE_MAX:1:PSA_ERROR_INVALID_ARGUMENT
 
 Import-sign-verify: sign in driver, ECDSA
-depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:PSA_WANT_ECC_SECP_R1_256
 sign_verify:SIGN_IN_DRIVER_AND_PARALLEL_CREATION:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ):PSA_ALG_ECDSA_ANY:0:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":"54686973206973206e6f74206120686173682e"
 
 Import-sign-verify: sign in driver then export_public, ECDSA
-depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:PSA_WANT_ECC_SECP_R1_256
 sign_verify:SIGN_IN_DRIVER_THEN_EXPORT_PUBLIC:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ):PSA_ALG_ECDSA_ANY:0:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":"54686973206973206e6f74206120686173682e"
 
 Import-sign-verify: sign in software, ECDSA
-depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:PSA_WANT_ECC_SECP_R1_256
 sign_verify:SIGN_IN_SOFTWARE_AND_PARALLEL_CREATION:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ):PSA_ALG_ECDSA_ANY:0:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":"54686973206973206e6f74206120686173682e"
 
 Generate-sign-verify: sign in driver, ECDSA
-depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:PSA_WANT_ECC_SECP_R1_256
 sign_verify:SIGN_IN_DRIVER_AND_PARALLEL_CREATION:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ):PSA_ALG_ECDSA_ANY:256:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":"54686973206973206e6f74206120686173682e"
 
 Generate-sign-verify: sign in driver then export_public, ECDSA
-depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:PSA_WANT_ECC_SECP_R1_256
 sign_verify:SIGN_IN_DRIVER_THEN_EXPORT_PUBLIC:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ):PSA_ALG_ECDSA_ANY:256:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":"54686973206973206e6f74206120686173682e"
 
 Generate-sign-verify: sign in software, ECDSA
-depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:PSA_WANT_ECC_SECP_R1_256
 sign_verify:SIGN_IN_SOFTWARE_AND_PARALLEL_CREATION:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1 ):PSA_ALG_ECDSA_ANY:256:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":"54686973206973206e6f74206120686173682e"
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_se_driver_hal.function b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_se_driver_hal.function
index 1add9b4..79d658f 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_se_driver_hal.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_se_driver_hal.function
@@ -1,5 +1,4 @@
 /* BEGIN_HEADER */
-#include "test/psa_crypto_helpers.h"
 #include "psa/crypto_se_driver.h"
 
 #include "psa_crypto_se.h"
@@ -46,7 +45,7 @@
     do {                                                    \
        if( ! (TEST) )                                       \
        {                                                    \
-          test_fail( #TEST, __LINE__, __FILE__ );           \
+          mbedtls_test_fail( #TEST, __LINE__, __FILE__ );   \
           return( PSA_ERROR_DETECTED_BY_DRIVER );           \
        }                                                    \
     } while( 0 )
@@ -62,7 +61,7 @@
     do {                                                    \
        if( ! (TEST) )                                       \
        {                                                    \
-          test_fail( #TEST, __LINE__, __FILE__ );           \
+          mbedtls_test_fail( #TEST, __LINE__, __FILE__ );   \
           status = PSA_ERROR_DETECTED_BY_DRIVER;            \
           goto exit;                                        \
        }                                                    \
@@ -73,10 +72,10 @@
  * Run the code \p expr. If this returns \p expected_status,
  * do nothing. If this returns #PSA_ERROR_DETECTED_BY_DRIVER,
  * jump directly to the `exit` label. If this returns any other
- * status, call test_fail() then jump to `exit`.
+ * status, call mbedtls_test_fail() then jump to `exit`.
  *
  * The special case for #PSA_ERROR_DETECTED_BY_DRIVER is because in this
- * case, the test driver code is expected to have called test_fail()
+ * case, the test driver code is expected to have called mbedtls_test_fail()
  * already, so we make sure not to overwrite the failure information.
  */
 #define PSA_ASSERT_VIA_DRIVER( expr, expected_status )                  \
@@ -86,7 +85,7 @@
             goto exit;                                                  \
         if( PSA_ASSERT_VIA_DRIVER_status != ( expected_status ) )       \
         {                                                               \
-            test_fail( #expr, __LINE__, __FILE__ );                     \
+            mbedtls_test_fail( #expr, __LINE__, __FILE__ );                     \
             goto exit;                                                  \
         }                                                               \
     } while( 0 )
@@ -293,8 +292,8 @@
 {
     psa_status_t status;
     size_t required_storage =
-        PSA_KEY_EXPORT_MAX_SIZE( psa_get_key_type( attributes ),
-                                 psa_get_key_bits( attributes ) );
+        PSA_EXPORT_KEY_OUTPUT_SIZE( psa_get_key_type( attributes ),
+                                    psa_get_key_bits( attributes ) );
 
     DRIVER_ASSERT_RETURN( *pubkey_length == 0 );
     if( ! PSA_KEY_TYPE_IS_KEY_PAIR( psa_get_key_type( attributes ) ) )
@@ -768,41 +767,12 @@
     return( ok );
 }
 
-static mbedtls_svc_key_id_t key_ids_used_in_test[10];
-static size_t num_key_ids_used;
-
-/* Record a key id as potentially used in a test case. */
-static int test_uses_key_id( mbedtls_svc_key_id_t key_id )
-{
-    size_t i;
-
-    for( i = 0; i < num_key_ids_used ; i++ )
-    {
-        if( mbedtls_svc_key_id_equal( key_id, key_ids_used_in_test[i] ) )
-            return( 1 );
-    }
-
-    if( num_key_ids_used >= ARRAY_LENGTH( key_ids_used_in_test ) )
-        return( 0 );
-
-    key_ids_used_in_test[num_key_ids_used] = key_id;
-    ++num_key_ids_used;
-
-    return( 1 );
-}
-
-#define TEST_USES_KEY_ID( key_id )                       \
-    TEST_ASSERT( test_uses_key_id( key_id ) )
-
 static void psa_purge_storage( void )
 {
-    size_t i;
+    /* The generic code in mbedtls_test_psa_purge_key_storage()
+     * (which is called by PSA_DONE()) doesn't take care of things that are
+     * specific to dynamic secure elements. */
     psa_key_location_t location;
-
-    for( i = 0; i < num_key_ids_used; i++ )
-        psa_destroy_persistent_key( key_ids_used_in_test[i] );
-    num_key_ids_used = 0;
-
     /* Purge the transaction file. */
     psa_crypto_stop_transaction( );
     /* Purge driver persistent data. */
@@ -1497,6 +1467,7 @@
             ( validate > 0 ? PSA_SUCCESS : PSA_ERROR_NOT_PERMITTED );
     }
 
+    mbedtls_test_set_step( 1 );
     PSA_ASSERT( psa_register_se_driver( MIN_DRIVER_LOCATION, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
 
@@ -1526,7 +1497,8 @@
     PSA_ASSERT( psa_purge_key( id ) );
 
     /* Restart and try again. */
-    PSA_DONE( );
+    mbedtls_test_set_step( 2 );
+    PSA_SESSION_DONE( );
     PSA_ASSERT( psa_register_se_driver( location, &driver ) );
     PSA_ASSERT( psa_crypto_init( ) );
     if( ! check_key_attributes( id, &attributes ) )
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
index 629c924..12c58eb 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
@@ -1,5 +1,4 @@
 /* BEGIN_HEADER */
-#include "test/psa_crypto_helpers.h"
 #include "psa/crypto_se_driver.h"
 
 #include "psa_crypto_se.h"
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_slot_management.data b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_slot_management.data
index 396cdfb..1477734 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_slot_management.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_slot_management.data
@@ -47,37 +47,58 @@
 persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:131:PSA_KEY_ID_USER_MAX:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":INVALIDATE_BY_SHUTDOWN
 
 Persistent slot: ECP keypair (ECDSA, exportable), close
-depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
 persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:132:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:0:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":INVALIDATE_BY_CLOSING
 
 Persistent slot: ECP keypair (ECDSA, exportable), close+restart
-depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
 persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:133:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:0:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":INVALIDATE_BY_CLOSING_WITH_SHUTDOWN
 
 Persistent slot: ECP keypair (ECDSA, exportable), purge
-depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
 persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:132:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:0:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":INVALIDATE_BY_PURGING
 
 Persistent slot: ECP keypair (ECDSA, exportable), restart
-depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
 persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:134:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:0:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":INVALIDATE_BY_SHUTDOWN
 
 Persistent slot: ECP keypair (ECDH+ECDSA, exportable), close
-depends_on:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
 persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:135:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_ALG_ECDSA_ANY:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":INVALIDATE_BY_CLOSING
 
 Persistent slot: ECP keypair (ECDH+ECDSA, exportable), close+restart
-depends_on:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
 persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:136:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_ALG_ECDSA_ANY:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":INVALIDATE_BY_CLOSING_WITH_SHUTDOWN
 
 Persistent slot: ECP keypair (ECDH+ECDSA, exportable), purge
-depends_on:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
 persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:135:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_ALG_ECDSA_ANY:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":INVALIDATE_BY_PURGING
 
 Persistent slot: ECP keypair (ECDH+ECDSA, exportable), restart
-depends_on:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
 persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:137:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_ALG_ECDSA_ANY:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":INVALIDATE_BY_SHUTDOWN
 
+Persistent slot, check after closing, persistence=2
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(2, PSA_KEY_LOCATION_LOCAL_STORAGE):124:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":INVALIDATE_BY_CLOSING
+
+Persistent slot, check after closing and restarting, persistence=2
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(2, PSA_KEY_LOCATION_LOCAL_STORAGE):125:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":INVALIDATE_BY_CLOSING_WITH_SHUTDOWN
+
+Persistent slot, check after destroying, persistence=2
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(2, PSA_KEY_LOCATION_LOCAL_STORAGE):126:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":INVALIDATE_BY_DESTROYING
+
+Persistent slot, check after destroying and restarting, persistence=2
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(2, PSA_KEY_LOCATION_LOCAL_STORAGE):127:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":INVALIDATE_BY_DESTROYING_WITH_SHUTDOWN
+
+Persistent slot, check after purging, persistence=2
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(2, PSA_KEY_LOCATION_LOCAL_STORAGE):200:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":INVALIDATE_BY_PURGING
+
+Persistent slot, check after purging and restarting, persistence=2
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(2, PSA_KEY_LOCATION_LOCAL_STORAGE):201:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":INVALIDATE_BY_PURGING_WITH_SHUTDOWN
+
+Persistent slot, check after restart with live handle, persistence=2
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(2, PSA_KEY_LOCATION_LOCAL_STORAGE):128:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":INVALIDATE_BY_SHUTDOWN
+
 Attempt to overwrite: close before
 create_existent:PSA_KEY_LIFETIME_PERSISTENT:0x1736:1:CLOSE_BEFORE
 
@@ -89,15 +110,15 @@
 
 Open failure: invalid identifier (0)
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
-open_fail:0:PSA_ERROR_INVALID_HANDLE
+open_fail:0:PSA_ERROR_DOES_NOT_EXIST
 
 Open failure: invalid identifier (random seed UID)
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
-open_fail:PSA_CRYPTO_ITS_RANDOM_SEED_UID:PSA_ERROR_INVALID_HANDLE
+open_fail:PSA_CRYPTO_ITS_RANDOM_SEED_UID:PSA_ERROR_DOES_NOT_EXIST
 
 Open failure: invalid identifier (reserved range)
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
-open_fail:PSA_KEY_ID_VENDOR_MAX + 1:PSA_ERROR_INVALID_HANDLE
+open_fail:PSA_KEY_ID_VENDOR_MAX + 1:PSA_ERROR_DOES_NOT_EXIST
 
 Open failure: invalid identifier (implementation range)
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
@@ -107,30 +128,39 @@
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
 open_fail:1:PSA_ERROR_DOES_NOT_EXIST
 
-Create failure: invalid lifetime
-create_fail:0x7fffffff:0:PSA_ERROR_INVALID_ARGUMENT
-
-Create failure: invalid key id (0)
+Create failure: read-only key
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
-create_fail:PSA_KEY_LIFETIME_PERSISTENT:0:PSA_ERROR_INVALID_HANDLE
+create_fail:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_READ_ONLY, PSA_KEY_LOCATION_LOCAL_STORAGE):1:PSA_ERROR_INVALID_ARGUMENT
+
+Create failure: invalid location for a persistent key
+depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
+create_fail:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_DEFAULT, 0xbad10cU):1:PSA_ERROR_INVALID_ARGUMENT
+
+Create failure: invalid location for a volatile key
+depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
+create_fail:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_VOLATILE, 0xbad10cU):0:PSA_ERROR_INVALID_ARGUMENT
+
+Create failure: invalid key id (0) for a persistent key
+depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
+create_fail:PSA_KEY_LIFETIME_PERSISTENT:0:PSA_ERROR_INVALID_ARGUMENT
 
 Create failure: invalid key id (1) for a volatile key
 create_fail:PSA_KEY_LIFETIME_VOLATILE:1:PSA_ERROR_INVALID_ARGUMENT
 
 Create failure: invalid key id (random seed UID)
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
-create_fail:PSA_KEY_LIFETIME_PERSISTENT:PSA_CRYPTO_ITS_RANDOM_SEED_UID:PSA_ERROR_INVALID_HANDLE
+create_fail:PSA_KEY_LIFETIME_PERSISTENT:PSA_CRYPTO_ITS_RANDOM_SEED_UID:PSA_ERROR_INVALID_ARGUMENT
 
 Create failure: invalid key id (reserved range)
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
-create_fail:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_VENDOR_MAX + 1:PSA_ERROR_INVALID_HANDLE
+create_fail:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_VENDOR_MAX + 1:PSA_ERROR_INVALID_ARGUMENT
 
 Create failure: invalid key id (implementation range)
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
-create_fail:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_USER_MAX + 1:PSA_ERROR_INVALID_HANDLE
+create_fail:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_USER_MAX + 1:PSA_ERROR_INVALID_ARGUMENT
 
 Open not supported
-depends_on:!MBEDTLS_PSA_CRYPTO_STORAGE_C
+depends_on:!MBEDTLS_PSA_CRYPTO_STORAGE_C:!MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS
 open_fail:1:PSA_ERROR_NOT_SUPPORTED
 
 Create not supported
@@ -157,32 +187,32 @@
 copy_across_lifetimes:PSA_KEY_LIFETIME_PERSISTENT:0x10000:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY:0:0:PSA_KEY_TYPE_RAW_DATA:"4142434445":PSA_KEY_LIFETIME_PERSISTENT:0x10001:1:PSA_KEY_USAGE_EXPORT:0:0:PSA_KEY_USAGE_EXPORT:0:0
 
 Copy persistent to persistent with enrollment algorithm
-depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR:MBEDTLS_CIPHER_MODE_CBC
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_CRYPTO_STORAGE_C
 copy_across_lifetimes:PSA_KEY_LIFETIME_PERSISTENT:0x100000:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY:PSA_ALG_CTR:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_LIFETIME_PERSISTENT:0x100000:2:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_ALG_CBC_NO_PADDING:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_ALG_CBC_NO_PADDING
 
 Copy volatile to occupied
-depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_CRYPTO_STORAGE_C
 copy_to_occupied:PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_LIFETIME_PERSISTENT:2:PSA_KEY_USAGE_EXPORT:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"606162636465666768696a6b6c6d6e6f"
 
 Copy persistent to occupied
-depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_CRYPTO_STORAGE_C
 copy_to_occupied:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_LIFETIME_PERSISTENT:2:PSA_KEY_USAGE_EXPORT:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"606162636465666768696a6b6c6d6e6f"
 
 Copy persistent to same
-depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PSA_CRYPTO_STORAGE_C
 copy_to_occupied:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f"
 
 invalid handle: 0
-invalid_handle:INVALID_HANDLE_0:PSA_SUCCESS:PSA_ERROR_INVALID_HANDLE
+invalid_handle:INVALID_HANDLE_0:PSA_SUCCESS
 
 invalid handle: never opened
-invalid_handle:INVALID_HANDLE_UNOPENED:PSA_ERROR_DOES_NOT_EXIST:PSA_ERROR_DOES_NOT_EXIST
+invalid_handle:INVALID_HANDLE_UNOPENED:PSA_ERROR_INVALID_HANDLE
 
 invalid handle: already closed
-invalid_handle:INVALID_HANDLE_CLOSED:PSA_ERROR_DOES_NOT_EXIST:PSA_ERROR_DOES_NOT_EXIST
+invalid_handle:INVALID_HANDLE_CLOSED:PSA_ERROR_INVALID_HANDLE
 
 invalid handle: huge
-invalid_handle:INVALID_HANDLE_HUGE:PSA_ERROR_INVALID_HANDLE:PSA_ERROR_INVALID_HANDLE
+invalid_handle:INVALID_HANDLE_HUGE:PSA_ERROR_INVALID_HANDLE
 
 Open many transient keys
 many_transient_keys:42
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_slot_management.function b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_slot_management.function
index 57d4789..aa3ce28 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_slot_management.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_slot_management.function
@@ -1,7 +1,6 @@
 /* BEGIN_HEADER */
 #include <stdint.h>
 
-#include "test/psa_crypto_helpers.h"
 #include "psa_crypto_slot_management.h"
 #include "psa_crypto_storage.h"
 
@@ -44,51 +43,6 @@
     INVALID_HANDLE_HUGE,
 } invalid_handle_construction_t;
 
-/* All test functions that create persistent keys must call
- * `TEST_USES_KEY_ID( key_id )` before creating a persistent key with this
- * identifier, and must call psa_purge_key_storage() in their cleanup
- * code. */
-
-#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-static mbedtls_svc_key_id_t key_ids_used_in_test[9];
-static size_t num_key_ids_used;
-
-/* Record a key id as potentially used in a test case. */
-static int test_uses_key_id( mbedtls_svc_key_id_t key_id )
-{
-    size_t i;
-    if( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key_id ) >
-        PSA_MAX_PERSISTENT_KEY_IDENTIFIER )
-    {
-        /* Don't touch key id values that designate non-key files. */
-        return( 1 );
-    }
-    for( i = 0; i < num_key_ids_used ; i++ )
-    {
-        if( mbedtls_svc_key_id_equal( key_id, key_ids_used_in_test[i] ) )
-            return( 1 );
-    }
-    if( num_key_ids_used == ARRAY_LENGTH( key_ids_used_in_test ) )
-        return( 0 );
-    key_ids_used_in_test[num_key_ids_used] = key_id;
-    ++num_key_ids_used;
-    return( 1 );
-}
-#define TEST_USES_KEY_ID( key_id )                       \
-    TEST_ASSERT( test_uses_key_id( key_id ) )
-
-/* Destroy all key ids that may have been created by the current test case. */
-static void psa_purge_key_storage( void )
-{
-    size_t i;
-    for( i = 0; i < num_key_ids_used; i++ )
-        psa_destroy_persistent_key( key_ids_used_in_test[i] );
-    num_key_ids_used = 0;
-}
-#else
-#define TEST_USES_KEY_ID( key_id ) ( (void) ( key_id ) )
-#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
-
 /** Apply \p invalidate_method to invalidate the specified key:
  * close it, destroy it, or do nothing;
  */
@@ -132,7 +86,7 @@
         case INVALIDATE_BY_DESTROYING_WITH_SHUTDOWN:
         case INVALIDATE_BY_PURGING_WITH_SHUTDOWN:
             /* All keys must have been closed. */
-            PSA_DONE( );
+            PSA_SESSION_DONE( );
             break;
         case INVALIDATE_BY_SHUTDOWN:
             /* Some keys may remain behind, and we're testing that this
@@ -169,6 +123,7 @@
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
+    mbedtls_test_set_step( 1 );
     PSA_ASSERT( psa_crypto_init( ) );
 
     /* Import a key. */
@@ -215,6 +170,7 @@
     psa_reset_key_attributes( &attributes );
 
     /* Do something that invalidates the key. */
+    mbedtls_test_set_step( 2 );
     if( ! invalidate_key( invalidate_method, key ) )
         goto exit;
     if( ! invalidate_psa( invalidate_method ) )
@@ -222,8 +178,8 @@
 
     /* Test that the key is now invalid. */
     TEST_EQUAL( psa_get_key_attributes( key, &attributes ),
-                PSA_ERROR_DOES_NOT_EXIST );
-    TEST_EQUAL( psa_close_key( key ), PSA_ERROR_DOES_NOT_EXIST );
+                PSA_ERROR_INVALID_HANDLE );
+    TEST_EQUAL( psa_close_key( key ), PSA_ERROR_INVALID_HANDLE );
 
 exit:
     /*
@@ -264,6 +220,7 @@
 
     TEST_USES_KEY_ID( id );
 
+    mbedtls_test_set_step( 1 );
     PSA_ASSERT( psa_crypto_init( ) );
 
     psa_set_key_id( &attributes, id );
@@ -285,7 +242,8 @@
     TEST_EQUAL( psa_get_key_lifetime( &attributes ), lifetime );
     TEST_ASSERT( mbedtls_svc_key_id_equal(
                      psa_get_key_id( &attributes ), id ) );
-    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage_flags );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ),
+                mbedtls_test_update_key_usage_flags( usage_flags ) );
     TEST_EQUAL( psa_get_key_algorithm( &attributes ), alg );
     TEST_EQUAL( psa_get_key_enrollment_algorithm( &attributes ), alg2 );
     TEST_EQUAL( psa_get_key_type( &attributes ), type );
@@ -304,7 +262,8 @@
     TEST_EQUAL( psa_get_key_lifetime( &attributes ), lifetime );
     TEST_ASSERT( mbedtls_svc_key_id_equal(
                      psa_get_key_id( &attributes ), id ) );
-    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage_flags );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ),
+                mbedtls_test_update_key_usage_flags( usage_flags ) );
     TEST_EQUAL( psa_get_key_algorithm( &attributes ), alg );
     TEST_EQUAL( psa_get_key_enrollment_algorithm( &attributes ), alg2 );
     TEST_EQUAL( psa_get_key_type( &attributes ), type );
@@ -313,6 +272,7 @@
      * Do something that wipes key data in volatile memory or destroy the
      * key.
      */
+    mbedtls_test_set_step( 2 );
     if( ! invalidate_key( invalidate_method, id ) )
         goto exit;
     if( ! invalidate_psa( invalidate_method ) )
@@ -335,7 +295,8 @@
             TEST_ASSERT( mbedtls_svc_key_id_equal(
                              psa_get_key_id( &attributes ),
                              psa_get_key_id( &read_attributes ) ) );
-            TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage_flags );
+            TEST_EQUAL( psa_get_key_usage_flags( &attributes ),
+                        mbedtls_test_update_key_usage_flags( usage_flags ) );
             TEST_EQUAL( psa_get_key_algorithm( &attributes ),
                         psa_get_key_algorithm( &read_attributes ) );
             TEST_EQUAL( psa_get_key_enrollment_algorithm( &attributes ),
@@ -344,9 +305,9 @@
                         psa_get_key_type( &read_attributes ) );
             TEST_EQUAL( psa_get_key_bits( &attributes ),
                         psa_get_key_bits( &read_attributes ) );
+            ASSERT_ALLOC( reexported, key_data->len );
             if( usage_flags & PSA_KEY_USAGE_EXPORT )
             {
-                ASSERT_ALLOC( reexported, key_data->len );
                 PSA_ASSERT( psa_export_key( id, reexported, key_data->len,
                                             &reexported_length ) );
                 ASSERT_COMPARE( key_data->x, key_data->len,
@@ -354,7 +315,8 @@
             }
             else
             {
-                TEST_EQUAL( psa_export_key( id, NULL, 0, &reexported_length ),
+                TEST_EQUAL( psa_export_key( id, reexported,
+                                key_data->len, &reexported_length ),
                             PSA_ERROR_NOT_PERMITTED );
             }
             PSA_ASSERT( psa_close_key( handle ) );
@@ -367,10 +329,10 @@
              * existing key.
              */
             TEST_EQUAL( psa_get_key_attributes( handle, &read_attributes ),
-                        PSA_ERROR_DOES_NOT_EXIST );
-            TEST_EQUAL( psa_close_key( handle ), PSA_ERROR_DOES_NOT_EXIST );
+                        PSA_ERROR_INVALID_HANDLE );
+            TEST_EQUAL( psa_close_key( handle ), PSA_ERROR_INVALID_HANDLE );
             TEST_EQUAL( psa_get_key_attributes( id, &read_attributes ),
-                        PSA_ERROR_DOES_NOT_EXIST );
+                        PSA_ERROR_INVALID_HANDLE );
             break;
     }
 
@@ -383,7 +345,6 @@
     psa_reset_key_attributes( &read_attributes );
 
     PSA_DONE( );
-    psa_purge_key_storage( );
     mbedtls_free( reexported );
 }
 /* END_CASE */
@@ -457,7 +418,6 @@
     psa_reset_key_attributes( &attributes );
 
     PSA_DONE( );
-    psa_purge_key_storage( );
 }
 /* END_CASE */
 
@@ -516,9 +476,6 @@
 
 exit:
     PSA_DONE( );
-#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-    psa_purge_key_storage( );
-#endif
 }
 /* END_CASE */
 
@@ -654,9 +611,6 @@
 
     PSA_DONE( );
     mbedtls_free( export_buffer );
-#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-    psa_purge_key_storage( );
-#endif
 }
 /* END_CASE */
 
@@ -772,21 +726,17 @@
 
     PSA_DONE( );
     mbedtls_free( export_buffer );
-#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-    psa_purge_key_storage( );
-#endif
 }
 /* END_CASE */
 
 /* BEGIN_CASE */
 void invalid_handle( int handle_construction,
-                     int close_status_arg, int usage_status_arg )
+                     int close_status_arg )
 {
     psa_key_handle_t valid_handle = PSA_KEY_HANDLE_INIT;
     psa_key_handle_t invalid_handle = PSA_KEY_HANDLE_INIT;
     psa_key_id_t key_id;
     psa_status_t close_status = close_status_arg;
-    psa_status_t usage_status = usage_status_arg;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     uint8_t material[1] = "a";
 
@@ -845,7 +795,7 @@
 
     /* Attempt to use the invalid handle. */
     TEST_EQUAL( psa_get_key_attributes( invalid_handle, &attributes ),
-                usage_status );
+                PSA_ERROR_INVALID_HANDLE );
     TEST_EQUAL( psa_close_key( invalid_handle ), close_status );
     TEST_EQUAL( psa_destroy_key( invalid_handle ), close_status );
 
@@ -933,9 +883,9 @@
     psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA );
 
     /*
-     * Create PSA_KEY_SLOT_COUNT persistent keys.
+     * Create MBEDTLS_PSA_KEY_SLOT_COUNT persistent keys.
      */
-    for( i = 0; i < PSA_KEY_SLOT_COUNT; i++ )
+    for( i = 0; i < MBEDTLS_PSA_KEY_SLOT_COUNT; i++ )
     {
         key = mbedtls_svc_key_id_make( i, i + 1 );
         psa_set_key_id( &attributes, key );
@@ -951,7 +901,7 @@
      * is removed from the RAM key slots. This makes room to store its
      * description in RAM.
      */
-    i = PSA_KEY_SLOT_COUNT;
+    i = MBEDTLS_PSA_KEY_SLOT_COUNT;
     key = mbedtls_svc_key_id_make( i, i + 1 );
     psa_set_key_id( &attributes, key );
     psa_set_key_lifetime( &attributes, lifetime );
@@ -966,15 +916,15 @@
                      MBEDTLS_SVC_KEY_ID_GET_KEY_ID( returned_key_id ) ) );
 
     /*
-     * Check that we can export all ( PSA_KEY_SLOT_COUNT + 1 ) keys,
+     * Check that we can export all ( MBEDTLS_PSA_KEY_SLOT_COUNT + 1 ) keys,
      * that they have the expected value and destroy them. In that process,
      * the description of the persistent key that was evicted from the RAM
      * slots when creating the last key is restored in a RAM slot to export
      * its value.
      */
-    for( i = 0; i <= PSA_KEY_SLOT_COUNT; i++ )
+    for( i = 0; i <= MBEDTLS_PSA_KEY_SLOT_COUNT; i++ )
     {
-        if( i < PSA_KEY_SLOT_COUNT )
+        if( i < MBEDTLS_PSA_KEY_SLOT_COUNT )
             key = mbedtls_svc_key_id_make( i, i + 1 );
         else
             key = returned_key_id;
@@ -1005,9 +955,9 @@
     mbedtls_svc_key_id_t returned_key_id = MBEDTLS_SVC_KEY_ID_INIT;
     mbedtls_svc_key_id_t *keys = NULL;
 
-    TEST_ASSERT( PSA_KEY_SLOT_COUNT >= 1 );
+    TEST_ASSERT( MBEDTLS_PSA_KEY_SLOT_COUNT >= 1 );
 
-    ASSERT_ALLOC( keys, PSA_KEY_SLOT_COUNT );
+    ASSERT_ALLOC( keys, MBEDTLS_PSA_KEY_SLOT_COUNT );
     PSA_ASSERT( psa_crypto_init( ) );
 
     psa_set_key_usage_flags( &attributes,
@@ -1027,10 +977,10 @@
     TEST_ASSERT( mbedtls_svc_key_id_equal( returned_key_id, persistent_key ) );
 
     /*
-     * Create PSA_KEY_SLOT_COUNT volatile keys
+     * Create MBEDTLS_PSA_KEY_SLOT_COUNT volatile keys
      */
     psa_set_key_lifetime( &attributes, PSA_KEY_LIFETIME_VOLATILE );
-    for( i = 0; i < PSA_KEY_SLOT_COUNT; i++ )
+    for( i = 0; i < MBEDTLS_PSA_KEY_SLOT_COUNT; i++ )
     {
         PSA_ASSERT( psa_import_key( &attributes,
                                     (uint8_t *) &i, sizeof( i ),
@@ -1050,12 +1000,12 @@
      * Check we can export the volatile key created last and that it has the
      * expected value. Then, destroy it.
      */
-    PSA_ASSERT( psa_export_key( keys[PSA_KEY_SLOT_COUNT - 1],
+    PSA_ASSERT( psa_export_key( keys[MBEDTLS_PSA_KEY_SLOT_COUNT - 1],
                                 exported, sizeof( exported ),
                                 &exported_length ) );
-    i = PSA_KEY_SLOT_COUNT - 1;
+    i = MBEDTLS_PSA_KEY_SLOT_COUNT - 1;
     ASSERT_COMPARE( exported, exported_length, (uint8_t *) &i, sizeof( i ) );
-    PSA_ASSERT( psa_destroy_key( keys[PSA_KEY_SLOT_COUNT - 1] ) );
+    PSA_ASSERT( psa_destroy_key( keys[MBEDTLS_PSA_KEY_SLOT_COUNT - 1] ) );
 
     /*
      * Check that we can now access the persistent key again.
@@ -1078,7 +1028,7 @@
      * Check we can export the remaining volatile keys and that they have the
      * expected values.
      */
-    for( i = 0; i < ( PSA_KEY_SLOT_COUNT - 1 ); i++ )
+    for( i = 0; i < ( MBEDTLS_PSA_KEY_SLOT_COUNT - 1 ); i++ )
     {
         PSA_ASSERT( psa_export_key( keys[i],
                                     exported, sizeof( exported ),
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_storage_format.current.data b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_storage_format.current.data
new file mode 100644
index 0000000..737b4a7
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_storage_format.current.data
@@ -0,0 +1,1999 @@
+# Automatically generated by generate_psa_tests.py. Do not edit!
+
+PSA storage save: lifetime: (DEFAULT, LOCAL_STORAGE)
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_DEFAULT, PSA_KEY_LOCATION_LOCAL_STORAGE):PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"4c":"505341004b455900000000000100000001100800010000000000000000000000010000004c"
+
+PSA storage save: lifetime: (2, LOCAL_STORAGE)
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(2, PSA_KEY_LOCATION_LOCAL_STORAGE):PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"4c":"505341004b455900000000000200000001100800010000000000000000000000010000004c"
+
+PSA storage save: lifetime: (254, LOCAL_STORAGE)
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(254, PSA_KEY_LOCATION_LOCAL_STORAGE):PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"4c":"505341004b45590000000000fe00000001100800010000000000000000000000010000004c"
+
+PSA storage save: lifetime: PERSISTENT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"4c":"505341004b455900000000000100000001100800010000000000000000000000010000004c"
+
+PSA storage save: usage: 0
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:0:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800000000000000000000000000010000004b"
+
+PSA storage save: usage: COPY
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_COPY:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800020000000000000000000000010000004b"
+
+PSA storage save: usage: DECRYPT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_DECRYPT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800000200000000000000000000010000004b"
+
+PSA storage save: usage: DERIVE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_DERIVE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800004000000000000000000000010000004b"
+
+PSA storage save: usage: ENCRYPT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_ENCRYPT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800000100000000000000000000010000004b"
+
+PSA storage save: usage: EXPORT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800010000000000000000000000010000004b"
+
+PSA storage save: usage: SIGN_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800001400000000000000000000010000004b"
+
+PSA storage save: usage: SIGN_MESSAGE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_MESSAGE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800000400000000000000000000010000004b"
+
+PSA storage save: usage: VERIFY_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800002800000000000000000000010000004b"
+
+PSA storage save: usage: VERIFY_MESSAGE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_MESSAGE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800000800000000000000000000010000004b"
+
+PSA storage save: usage: COPY | DECRYPT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800020200000000000000000000010000004b"
+
+PSA storage save: usage: DECRYPT | DERIVE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_DERIVE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800004200000000000000000000010000004b"
+
+PSA storage save: usage: DERIVE | ENCRYPT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_ENCRYPT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800004100000000000000000000010000004b"
+
+PSA storage save: usage: ENCRYPT | EXPORT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800010100000000000000000000010000004b"
+
+PSA storage save: usage: EXPORT | SIGN_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800011400000000000000000000010000004b"
+
+PSA storage save: usage: SIGN_HASH | SIGN_MESSAGE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800001400000000000000000000010000004b"
+
+PSA storage save: usage: SIGN_MESSAGE | VERIFY_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800002c00000000000000000000010000004b"
+
+PSA storage save: usage: VERIFY_HASH | VERIFY_MESSAGE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800002800000000000000000000010000004b"
+
+PSA storage save: usage: VERIFY_MESSAGE | COPY
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800020800000000000000000000010000004b"
+
+PSA storage save: usage: all known
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800037f00000000000000000000010000004b"
+
+PSA storage save: type: AES 128-bit
+depends_on:PSA_WANT_KEY_TYPE_AES
+key_storage_save:0x0001:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000002480000100000000000000000000001000000048657265006973206b6579a064617461"
+
+PSA storage save: type: AES 192-bit
+depends_on:PSA_WANT_KEY_TYPE_AES
+key_storage_save:0x0001:PSA_KEY_TYPE_AES:192:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a0646174614865726500697320":"505341004b45590000000000010000000024c0000100000000000000000000001800000048657265006973206b6579a0646174614865726500697320"
+
+PSA storage save: type: AES 256-bit
+depends_on:PSA_WANT_KEY_TYPE_AES
+key_storage_save:0x0001:PSA_KEY_TYPE_AES:256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000002400010100000000000000000000002000000048657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA storage save: type: ARC4 8-bit
+depends_on:PSA_WANT_KEY_TYPE_ARC4
+key_storage_save:0x0001:PSA_KEY_TYPE_ARC4:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48":"505341004b4559000000000001000000022008000100000000000000000000000100000048"
+
+PSA storage save: type: ARC4 128-bit
+depends_on:PSA_WANT_KEY_TYPE_ARC4
+key_storage_save:0x0001:PSA_KEY_TYPE_ARC4:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000022080000100000000000000000000001000000048657265006973206b6579a064617461"
+
+PSA storage save: type: ARC4 2048-bit
+depends_on:PSA_WANT_KEY_TYPE_ARC4
+key_storage_save:0x0001:PSA_KEY_TYPE_ARC4:2048:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000022000080100000000000000000000000001000048657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA storage save: type: ARIA 128-bit
+depends_on:PSA_WANT_KEY_TYPE_ARIA
+key_storage_save:0x0001:PSA_KEY_TYPE_ARIA:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000062480000100000000000000000000001000000048657265006973206b6579a064617461"
+
+PSA storage save: type: ARIA 192-bit
+depends_on:PSA_WANT_KEY_TYPE_ARIA
+key_storage_save:0x0001:PSA_KEY_TYPE_ARIA:192:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a0646174614865726500697320":"505341004b45590000000000010000000624c0000100000000000000000000001800000048657265006973206b6579a0646174614865726500697320"
+
+PSA storage save: type: ARIA 256-bit
+depends_on:PSA_WANT_KEY_TYPE_ARIA
+key_storage_save:0x0001:PSA_KEY_TYPE_ARIA:256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000062400010100000000000000000000002000000048657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA storage save: type: CAMELLIA 128-bit
+depends_on:PSA_WANT_KEY_TYPE_CAMELLIA
+key_storage_save:0x0001:PSA_KEY_TYPE_CAMELLIA:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000032480000100000000000000000000001000000048657265006973206b6579a064617461"
+
+PSA storage save: type: CAMELLIA 192-bit
+depends_on:PSA_WANT_KEY_TYPE_CAMELLIA
+key_storage_save:0x0001:PSA_KEY_TYPE_CAMELLIA:192:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a0646174614865726500697320":"505341004b45590000000000010000000324c0000100000000000000000000001800000048657265006973206b6579a0646174614865726500697320"
+
+PSA storage save: type: CAMELLIA 256-bit
+depends_on:PSA_WANT_KEY_TYPE_CAMELLIA
+key_storage_save:0x0001:PSA_KEY_TYPE_CAMELLIA:256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000032400010100000000000000000000002000000048657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA storage save: type: CHACHA20 256-bit
+depends_on:PSA_WANT_KEY_TYPE_CHACHA20
+key_storage_save:0x0001:PSA_KEY_TYPE_CHACHA20:256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000042000010100000000000000000000002000000048657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA storage save: type: DERIVE 120-bit
+depends_on:PSA_WANT_KEY_TYPE_DERIVE
+key_storage_save:0x0001:PSA_KEY_TYPE_DERIVE:120:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a0646174":"505341004b4559000000000001000000001278000100000000000000000000000f00000048657265006973206b6579a0646174"
+
+PSA storage save: type: DERIVE 128-bit
+depends_on:PSA_WANT_KEY_TYPE_DERIVE
+key_storage_save:0x0001:PSA_KEY_TYPE_DERIVE:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000001280000100000000000000000000001000000048657265006973206b6579a064617461"
+
+PSA storage save: type: DES 64-bit
+depends_on:PSA_WANT_KEY_TYPE_DES
+key_storage_save:0x0001:PSA_KEY_TYPE_DES:64:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"644573206b457901":"505341004b45590000000000010000000123400001000000000000000000000008000000644573206b457901"
+
+PSA storage save: type: DES 128-bit
+depends_on:PSA_WANT_KEY_TYPE_DES
+key_storage_save:0x0001:PSA_KEY_TYPE_DES:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"644573206b457901644573206b457902":"505341004b45590000000000010000000123800001000000000000000000000010000000644573206b457901644573206b457902"
+
+PSA storage save: type: DES 192-bit
+depends_on:PSA_WANT_KEY_TYPE_DES
+key_storage_save:0x0001:PSA_KEY_TYPE_DES:192:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"644573206b457901644573206b457902644573206b457904":"505341004b45590000000000010000000123c00001000000000000000000000018000000644573206b457901644573206b457902644573206b457904"
+
+PSA storage save: type: ECC_KEY_PAIR(BRAINPOOL_P_R1) 160-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_160:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):160:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"69502c4fdaf48d4fa617bdd24498b0406d0eeaac":"505341004b45590000000000010000003071a0000100000000000000000000001400000069502c4fdaf48d4fa617bdd24498b0406d0eeaac"
+
+PSA storage save: type: ECC_KEY_PAIR(BRAINPOOL_P_R1) 192-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_192:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):192:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"1688a2c5fbf4a3c851d76a98c3ec88f445a97996283db59f":"505341004b45590000000000010000003071c000010000000000000000000000180000001688a2c5fbf4a3c851d76a98c3ec88f445a97996283db59f"
+
+PSA storage save: type: ECC_KEY_PAIR(BRAINPOOL_P_R1) 224-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_224:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):224:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"a69835dafeb5da5ab89c59860dddebcfd80b529a99f59b880882923c":"505341004b45590000000000010000003071e0000100000000000000000000001c000000a69835dafeb5da5ab89c59860dddebcfd80b529a99f59b880882923c"
+
+PSA storage save: type: ECC_KEY_PAIR(BRAINPOOL_P_R1) 256-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"2161d6f2db76526fa62c16f356a80f01f32f776784b36aa99799a8b7662080ff":"505341004b455900000000000100000030710001010000000000000000000000200000002161d6f2db76526fa62c16f356a80f01f32f776784b36aa99799a8b7662080ff"
+
+PSA storage save: type: ECC_KEY_PAIR(BRAINPOOL_P_R1) 320-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_320:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):320:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"61b8daa7a6e5aa9fccf1ef504220b2e5a5b8c6dc7475d16d3172d7db0b2778414e4f6e8fa2032ead":"505341004b4559000000000001000000307140010100000000000000000000002800000061b8daa7a6e5aa9fccf1ef504220b2e5a5b8c6dc7475d16d3172d7db0b2778414e4f6e8fa2032ead"
+
+PSA storage save: type: ECC_KEY_PAIR(BRAINPOOL_P_R1) 384-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):384:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"3dd92e750d90d7d39fc1885cd8ad12ea9441f22b9334b4d965202adb1448ce24c5808a85dd9afc229af0a3124f755bcb":"505341004b455900000000000100000030718001010000000000000000000000300000003dd92e750d90d7d39fc1885cd8ad12ea9441f22b9334b4d965202adb1448ce24c5808a85dd9afc229af0a3124f755bcb"
+
+PSA storage save: type: ECC_KEY_PAIR(BRAINPOOL_P_R1) 512-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_512:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):512:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"372c9778f69f726cbca3f4a268f16b4d617d10280d79a6a029cd51879fe1012934dfe5395455337df6906dc7d6d2eea4dbb2065c0228f73b3ed716480e7d71d2":"505341004b45590000000000010000003071000201000000000000000000000040000000372c9778f69f726cbca3f4a268f16b4d617d10280d79a6a029cd51879fe1012934dfe5395455337df6906dc7d6d2eea4dbb2065c0228f73b3ed716480e7d71d2"
+
+PSA storage save: type: ECC_KEY_PAIR(MONTGOMERY) 255-bit
+depends_on:PSA_WANT_ECC_MONTGOMERY_255:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):255:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"70076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c6a":"505341004b45590000000000010000004171ff000100000000000000000000002000000070076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c6a"
+
+PSA storage save: type: ECC_KEY_PAIR(MONTGOMERY) 448-bit
+depends_on:PSA_WANT_ECC_MONTGOMERY_448:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):448:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"e4e49f52686f9ee3b638528f721f1596196ffd0a1cddb64c3f216f06541805cfeb1a286dc78018095cdfec050e8007b5f4908962ba20d6c1":"505341004b45590000000000010000004171c00101000000000000000000000038000000e4e49f52686f9ee3b638528f721f1596196ffd0a1cddb64c3f216f06541805cfeb1a286dc78018095cdfec050e8007b5f4908962ba20d6c1"
+
+PSA storage save: type: ECC_KEY_PAIR(SECP_K1) 192-bit
+depends_on:PSA_WANT_ECC_SECP_K1_192:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):192:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"297ac1722ccac7589ecb240dc719842538ca974beb79f228":"505341004b45590000000000010000001771c00001000000000000000000000018000000297ac1722ccac7589ecb240dc719842538ca974beb79f228"
+
+PSA storage save: type: ECC_KEY_PAIR(SECP_K1) 224-bit
+depends_on:PSA_WANT_ECC_SECP_K1_224:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):224:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0024122bf020fa113f6c0ac978dfbd41f749257a9468febdbe0dc9f7e8":"505341004b45590000000000010000001771e0000100000000000000000000001d0000000024122bf020fa113f6c0ac978dfbd41f749257a9468febdbe0dc9f7e8"
+
+PSA storage save: type: ECC_KEY_PAIR(SECP_K1) 256-bit
+depends_on:PSA_WANT_ECC_SECP_K1_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"7fa06fa02d0e911b9a47fdc17d2d962ca01e2f31d60c6212d0ed7e3bba23a7b9":"505341004b455900000000000100000017710001010000000000000000000000200000007fa06fa02d0e911b9a47fdc17d2d962ca01e2f31d60c6212d0ed7e3bba23a7b9"
+
+PSA storage save: type: ECC_KEY_PAIR(SECP_R1) 225-bit
+depends_on:PSA_WANT_ECC_SECP_R1_225:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):225:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"872f203b3ad35b7f2ecc803c3a0e1e0b1ed61cc1afe71b189cd4c995":"505341004b45590000000000010000001271e1000100000000000000000000001c000000872f203b3ad35b7f2ecc803c3a0e1e0b1ed61cc1afe71b189cd4c995"
+
+PSA storage save: type: ECC_KEY_PAIR(SECP_R1) 256-bit
+depends_on:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":"505341004b4559000000000001000000127100010100000000000000000000002000000049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee"
+
+PSA storage save: type: ECC_KEY_PAIR(SECP_R1) 384-bit
+depends_on:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):384:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":"505341004b455900000000000100000012718001010000000000000000000000300000003f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a"
+
+PSA storage save: type: ECC_KEY_PAIR(SECP_R1) 521-bit
+depends_on:PSA_WANT_ECC_SECP_R1_521:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):521:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"01b1b6ad07bb79e7320da59860ea28e055284f6058f279de666e06d435d2af7bda28d99fa47b7dd0963e16b0073078ee8b8a38d966a582f46d19ff95df3ad9685aae":"505341004b4559000000000001000000127109020100000000000000000000004200000001b1b6ad07bb79e7320da59860ea28e055284f6058f279de666e06d435d2af7bda28d99fa47b7dd0963e16b0073078ee8b8a38d966a582f46d19ff95df3ad9685aae"
+
+PSA storage save: type: ECC_KEY_PAIR(SECP_R2) 160-bit
+depends_on:PSA_WANT_ECC_SECP_R2_160:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R2):160:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"00bf539a1cdda0d7f71a50a3f98aec0a2e8e4ced1e":"505341004b45590000000000010000001b71a0000100000000000000000000001500000000bf539a1cdda0d7f71a50a3f98aec0a2e8e4ced1e"
+
+PSA storage save: type: ECC_KEY_PAIR(SECT_K1) 163-bit
+depends_on:PSA_WANT_ECC_SECT_K1_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):163:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"03ebc8fcded2d6ab72ec0f75bdb4fd080481273e71":"505341004b45590000000000010000002771a3000100000000000000000000001500000003ebc8fcded2d6ab72ec0f75bdb4fd080481273e71"
+
+PSA storage save: type: ECC_KEY_PAIR(SECT_K1) 233-bit
+depends_on:PSA_WANT_ECC_SECT_K1_233:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):233:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"41f08485ce587b06061c087e76e247c359de2ba9927ee013b2f1ed9ca8":"505341004b45590000000000010000002771e9000100000000000000000000001d00000041f08485ce587b06061c087e76e247c359de2ba9927ee013b2f1ed9ca8"
+
+PSA storage save: type: ECC_KEY_PAIR(SECT_K1) 239-bit
+depends_on:PSA_WANT_ECC_SECT_K1_239:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):239:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"1a8069ce2c2c8bdd7087f2a6ab49588797e6294e979495602ab9650b9c61":"505341004b45590000000000010000002771ef000100000000000000000000001e0000001a8069ce2c2c8bdd7087f2a6ab49588797e6294e979495602ab9650b9c61"
+
+PSA storage save: type: ECC_KEY_PAIR(SECT_K1) 283-bit
+depends_on:PSA_WANT_ECC_SECT_K1_283:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):283:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"006d627885dd48b9ec6facb5b3865377d755b75a5d51440e45211c1f600e15eff8a881a0":"505341004b455900000000000100000027711b0101000000000000000000000024000000006d627885dd48b9ec6facb5b3865377d755b75a5d51440e45211c1f600e15eff8a881a0"
+
+PSA storage save: type: ECC_KEY_PAIR(SECT_K1) 409-bit
+depends_on:PSA_WANT_ECC_SECT_K1_409:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):409:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"3ff5e74d932fa77db139b7c948c81e4069c72c24845574064beea8976b70267f1c6f9a503e3892ea1dcbb71fcea423faa370a8":"505341004b455900000000000100000027719901010000000000000000000000330000003ff5e74d932fa77db139b7c948c81e4069c72c24845574064beea8976b70267f1c6f9a503e3892ea1dcbb71fcea423faa370a8"
+
+PSA storage save: type: ECC_KEY_PAIR(SECT_K1) 571-bit
+depends_on:PSA_WANT_ECC_SECT_K1_571:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):571:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"005008c97b4a161c0db1bac6452c72846d57337aa92d8ecb4a66eb01d2f29555ffb61a5317225dcc8ca6917d91789e227efc0bfe9eeda7ee21998cd11c3c9885056b0e55b4f75d51":"505341004b455900000000000100000027713b0201000000000000000000000048000000005008c97b4a161c0db1bac6452c72846d57337aa92d8ecb4a66eb01d2f29555ffb61a5317225dcc8ca6917d91789e227efc0bfe9eeda7ee21998cd11c3c9885056b0e55b4f75d51"
+
+PSA storage save: type: ECC_KEY_PAIR(SECT_R1) 163-bit
+depends_on:PSA_WANT_ECC_SECT_R1_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):163:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"009b05dc82d46d64a04a22e6e5ca70ca1231e68c50":"505341004b45590000000000010000002271a30001000000000000000000000015000000009b05dc82d46d64a04a22e6e5ca70ca1231e68c50"
+
+PSA storage save: type: ECC_KEY_PAIR(SECT_R1) 233-bit
+depends_on:PSA_WANT_ECC_SECT_R1_233:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):233:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"00e5e42834e3c78758088b905deea975f28dc20ef6173e481f96e88afe7f":"505341004b45590000000000010000002271e9000100000000000000000000001e00000000e5e42834e3c78758088b905deea975f28dc20ef6173e481f96e88afe7f"
+
+PSA storage save: type: ECC_KEY_PAIR(SECT_R1) 283-bit
+depends_on:PSA_WANT_ECC_SECT_R1_283:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):283:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"004cecad915f6f3c9bbbd92d1eb101eda23f16c7dad60a57c87c7e1fd2b29b22f6d666ad":"505341004b455900000000000100000022711b0101000000000000000000000024000000004cecad915f6f3c9bbbd92d1eb101eda23f16c7dad60a57c87c7e1fd2b29b22f6d666ad"
+
+PSA storage save: type: ECC_KEY_PAIR(SECT_R1) 409-bit
+depends_on:PSA_WANT_ECC_SECT_R1_409:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):409:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"00c22422d265721a3ae2b3b2baeb77bee50416e19877af97b5fc1c700a0a88916ecb9050135883accb5e64edc77a3703f4f67a64":"505341004b4559000000000001000000227199010100000000000000000000003400000000c22422d265721a3ae2b3b2baeb77bee50416e19877af97b5fc1c700a0a88916ecb9050135883accb5e64edc77a3703f4f67a64"
+
+PSA storage save: type: ECC_KEY_PAIR(SECT_R1) 571-bit
+depends_on:PSA_WANT_ECC_SECT_R1_571:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):571:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"026ac1cdf92a13a1b8d282da9725847908745138f5c6706b52d164e3675fcfbf86fc3e6ab2de732193267db029dd35a0599a94a118f480231cfc6ccca2ebfc1d8f54176e0f5656a1":"505341004b455900000000000100000022713b0201000000000000000000000048000000026ac1cdf92a13a1b8d282da9725847908745138f5c6706b52d164e3675fcfbf86fc3e6ab2de732193267db029dd35a0599a94a118f480231cfc6ccca2ebfc1d8f54176e0f5656a1"
+
+PSA storage save: type: ECC_KEY_PAIR(SECT_R2) 163-bit
+depends_on:PSA_WANT_ECC_SECT_R2_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R2):163:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0210b482a458b4822d0cb21daa96819a67c8062d34":"505341004b45590000000000010000002b71a300010000000000000000000000150000000210b482a458b4822d0cb21daa96819a67c8062d34"
+
+PSA storage save: type: ECC_KEY_PAIR(TWISTED_EDWARDS) 255-bit
+depends_on:PSA_WANT_ECC_TWISTED_EDWARDS_255:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):255:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60":"505341004b45590000000000010000004271ff00010000000000000000000000200000009d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"
+
+PSA storage save: type: ECC_KEY_PAIR(TWISTED_EDWARDS) 448-bit
+depends_on:PSA_WANT_ECC_TWISTED_EDWARDS_448:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):448:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b":"505341004b45590000000000010000004271c001010000000000000000000000390000006c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b"
+
+PSA storage save: type: ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 160-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_160:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):160:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04d4b9186816358e2f9c59cf70748cb70641b22fbab65473db4b4e22a361ed7e3de7e8a8ddc4130c5c":"505341004b45590000000000010000003041a0000100000000000000000000002900000004d4b9186816358e2f9c59cf70748cb70641b22fbab65473db4b4e22a361ed7e3de7e8a8ddc4130c5c"
+
+PSA storage save: type: ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 192-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_192:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):192:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"043fdd168c179ff5363dd71dcd58de9617caad791ae0c37328be9ca0bfc79cebabf6a95d1c52df5b5f3c8b1a2441cf6c88":"505341004b45590000000000010000003041c00001000000000000000000000031000000043fdd168c179ff5363dd71dcd58de9617caad791ae0c37328be9ca0bfc79cebabf6a95d1c52df5b5f3c8b1a2441cf6c88"
+
+PSA storage save: type: ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 224-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_224:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):224:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"045fbea378fc8583b3837e3f21a457c31eaf20a54e18eb11d104b3adc47f9d1c97eb9ea4ac21740d70d88514b98bf0bc31addac1d19c4ab3cc":"505341004b45590000000000010000003041e00001000000000000000000000039000000045fbea378fc8583b3837e3f21a457c31eaf20a54e18eb11d104b3adc47f9d1c97eb9ea4ac21740d70d88514b98bf0bc31addac1d19c4ab3cc"
+
+PSA storage save: type: ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 256-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04768c8cae4abca6306db0ed81b0c4a6215c378066ec6d616c146e13f1c7df809b96ab6911c27d8a02339f0926840e55236d3d1efbe2669d090e4c4c660fada91d":"505341004b4559000000000001000000304100010100000000000000000000004100000004768c8cae4abca6306db0ed81b0c4a6215c378066ec6d616c146e13f1c7df809b96ab6911c27d8a02339f0926840e55236d3d1efbe2669d090e4c4c660fada91d"
+
+PSA storage save: type: ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 320-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_320:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):320:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"049caed8fb4742956cc2ad12a9a1c995e21759ef26a07bc2054136d3d2f28bb331a70e26c4c687275ab1f434be7871e115d2350c0c5f61d4d06d2bcdb67f5cb63fdb794e5947c87dc6849a58694e37e6cd":"505341004b45590000000000010000003041400101000000000000000000000051000000049caed8fb4742956cc2ad12a9a1c995e21759ef26a07bc2054136d3d2f28bb331a70e26c4c687275ab1f434be7871e115d2350c0c5f61d4d06d2bcdb67f5cb63fdb794e5947c87dc6849a58694e37e6cd"
+
+PSA storage save: type: ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 384-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_384:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):384:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04719f9d093a627e0d350385c661cebf00c61923566fe9006a3107af1d871bc6bb68985fd722ea32be316f8e783b7cd1957785f66cfc0cb195dd5c99a8e7abaa848553a584dfd2b48e76d445fe00dd8be59096d877d4696d23b4bc8db14724e66a":"505341004b4559000000000001000000304180010100000000000000000000006100000004719f9d093a627e0d350385c661cebf00c61923566fe9006a3107af1d871bc6bb68985fd722ea32be316f8e783b7cd1957785f66cfc0cb195dd5c99a8e7abaa848553a584dfd2b48e76d445fe00dd8be59096d877d4696d23b4bc8db14724e66a"
+
+PSA storage save: type: ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 512-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_512:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):512:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0438b7ec92b61c5c6c7fbc28a4ec759d48fcd4e2e374defd5c4968a54dbef7510e517886fbfc38ea39aa529359d70a7156c35d3cbac7ce776bdb251dd64bce71234424ee7049eed072f0dbc4d79996e175d557e263763ae97095c081e73e7db2e38adc3d4c9a0487b1ede876dc1fca61c902e9a1d8722b8612928f18a24845591a":"505341004b455900000000000100000030410002010000000000000000000000810000000438b7ec92b61c5c6c7fbc28a4ec759d48fcd4e2e374defd5c4968a54dbef7510e517886fbfc38ea39aa529359d70a7156c35d3cbac7ce776bdb251dd64bce71234424ee7049eed072f0dbc4d79996e175d557e263763ae97095c081e73e7db2e38adc3d4c9a0487b1ede876dc1fca61c902e9a1d8722b8612928f18a24845591a"
+
+PSA storage save: type: ECC_PUBLIC_KEY(MONTGOMERY) 255-bit
+depends_on:PSA_WANT_ECC_MONTGOMERY_255:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_MONTGOMERY):255:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a":"505341004b45590000000000010000004141ff00010000000000000000000000200000008520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"
+
+PSA storage save: type: ECC_PUBLIC_KEY(MONTGOMERY) 448-bit
+depends_on:PSA_WANT_ECC_MONTGOMERY_448:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_MONTGOMERY):448:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"c0d3a5a2b416a573dc9909f92f134ac01323ab8f8e36804e578588ba2d09fe7c3e737f771ca112825b548a0ffded6d6a2fd09a3e77dec30e":"505341004b45590000000000010000004141c00101000000000000000000000038000000c0d3a5a2b416a573dc9909f92f134ac01323ab8f8e36804e578588ba2d09fe7c3e737f771ca112825b548a0ffded6d6a2fd09a3e77dec30e"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECP_K1) 192-bit
+depends_on:PSA_WANT_ECC_SECP_K1_192:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_K1):192:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0426b7bb38da649ac2138fc050c6548b32553dab68afebc36105d325b75538c12323cb0764789ecb992671beb2b6bef2f5":"505341004b45590000000000010000001741c000010000000000000000000000310000000426b7bb38da649ac2138fc050c6548b32553dab68afebc36105d325b75538c12323cb0764789ecb992671beb2b6bef2f5"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECP_K1) 224-bit
+depends_on:PSA_WANT_ECC_SECP_K1_224:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_K1):224:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"042cc7335f4b76042bed44ef45959a62aa215f7a5ff0c8111b8c44ed654ee71c1918326ad485b2d599fe2a6eab096ee26d977334d2bac6d61d":"505341004b45590000000000010000001741e00001000000000000000000000039000000042cc7335f4b76042bed44ef45959a62aa215f7a5ff0c8111b8c44ed654ee71c1918326ad485b2d599fe2a6eab096ee26d977334d2bac6d61d"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECP_K1) 256-bit
+depends_on:PSA_WANT_ECC_SECP_K1_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_K1):256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"045c39154579efd667adc73a81015a797d2c8682cdfbd3c3553c4a185d481cdc50e42a0e1cbc3ca29a32a645e927f54beaed14c9dbbf8279d725f5495ca924b24d":"505341004b45590000000000010000001741000101000000000000000000000041000000045c39154579efd667adc73a81015a797d2c8682cdfbd3c3553c4a185d481cdc50e42a0e1cbc3ca29a32a645e927f54beaed14c9dbbf8279d725f5495ca924b24d"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECP_R1) 225-bit
+depends_on:PSA_WANT_ECC_SECP_R1_225:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):225:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"046f00eadaa949fee3e9e1c7fa1247eecec86a0dce46418b9bd3117b981d4bd0ae7a990de912f9d060d6cb531a42d22e394ac29e81804bf160":"505341004b45590000000000010000001241e10001000000000000000000000039000000046f00eadaa949fee3e9e1c7fa1247eecec86a0dce46418b9bd3117b981d4bd0ae7a990de912f9d060d6cb531a42d22e394ac29e81804bf160"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECP_R1) 256-bit
+depends_on:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":"505341004b45590000000000010000001241000101000000000000000000000041000000047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECP_R1) 384-bit
+depends_on:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):384:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04d9c662b50ba29ca47990450e043aeaf4f0c69b15676d112f622a71c93059af999691c5680d2b44d111579db12f4a413a2ed5c45fcfb67b5b63e00b91ebe59d09a6b1ac2c0c4282aa12317ed5914f999bc488bb132e8342cc36f2ca5e3379c747":"505341004b4559000000000001000000124180010100000000000000000000006100000004d9c662b50ba29ca47990450e043aeaf4f0c69b15676d112f622a71c93059af999691c5680d2b44d111579db12f4a413a2ed5c45fcfb67b5b63e00b91ebe59d09a6b1ac2c0c4282aa12317ed5914f999bc488bb132e8342cc36f2ca5e3379c747"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECP_R1) 521-bit
+depends_on:PSA_WANT_ECC_SECP_R1_521:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):521:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04001de142d54f69eb038ee4b7af9d3ca07736fd9cf719eb354d69879ee7f3c136fb0fbf9f08f86be5fa128ec1a051d3e6c643e85ada8ffacf3663c260bd2c844b6f5600cee8e48a9e65d09cadd89f235dee05f3b8a646be715f1f67d5b434e0ff23a1fc07ef7740193e40eeff6f3bcdfd765aa9155033524fe4f205f5444e292c4c2f6ac1":"505341004b4559000000000001000000124109020100000000000000000000008500000004001de142d54f69eb038ee4b7af9d3ca07736fd9cf719eb354d69879ee7f3c136fb0fbf9f08f86be5fa128ec1a051d3e6c643e85ada8ffacf3663c260bd2c844b6f5600cee8e48a9e65d09cadd89f235dee05f3b8a646be715f1f67d5b434e0ff23a1fc07ef7740193e40eeff6f3bcdfd765aa9155033524fe4f205f5444e292c4c2f6ac1"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECP_R2) 160-bit
+depends_on:PSA_WANT_ECC_SECP_R2_160:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R2):160:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"049570d541398665adb5cfa16f5af73b3196926bbd4b876bdb80f8eab20d0f540c22f4de9c140f6d7b":"505341004b45590000000000010000001b41a00001000000000000000000000029000000049570d541398665adb5cfa16f5af73b3196926bbd4b876bdb80f8eab20d0f540c22f4de9c140f6d7b"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECT_K1) 163-bit
+depends_on:PSA_WANT_ECC_SECT_K1_163:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):163:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0406f88f90b4b65950f06ce433afdb097e320f433dc2062b8a65db8fafd3c110f46bc45663fbf021ee7eb9":"505341004b45590000000000010000002741a3000100000000000000000000002b0000000406f88f90b4b65950f06ce433afdb097e320f433dc2062b8a65db8fafd3c110f46bc45663fbf021ee7eb9"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECT_K1) 233-bit
+depends_on:PSA_WANT_ECC_SECT_K1_233:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):233:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0401e9d7189189f773bd8f71be2c10774ba18842434dfa9312595ea545104400f45a9d5675647513ba75b079fe66a29daac2ec86a6a5d4e75c5f290c1f":"505341004b45590000000000010000002741e9000100000000000000000000003d0000000401e9d7189189f773bd8f71be2c10774ba18842434dfa9312595ea545104400f45a9d5675647513ba75b079fe66a29daac2ec86a6a5d4e75c5f290c1f"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECT_K1) 239-bit
+depends_on:PSA_WANT_ECC_SECT_K1_239:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):239:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04068d76b9f4508762c2379db9ee8b87ad8d86d9535132ffba3b5680440cfa28eb133d4232faf1c9aba96af11aefe634a551440800d5f8185105d3072d":"505341004b45590000000000010000002741ef000100000000000000000000003d00000004068d76b9f4508762c2379db9ee8b87ad8d86d9535132ffba3b5680440cfa28eb133d4232faf1c9aba96af11aefe634a551440800d5f8185105d3072d"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECT_K1) 283-bit
+depends_on:PSA_WANT_ECC_SECT_K1_283:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):283:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0405f48374debceaadb46ba385fd92048fcc5b9af1a1c90408bf94a68b9378df1cbfdfb6fb026a96bea06d8f181bf10c020adbcc88b6ecff96bdc564a9649c247cede601c4be63afc3":"505341004b455900000000000100000027411b01010000000000000000000000490000000405f48374debceaadb46ba385fd92048fcc5b9af1a1c90408bf94a68b9378df1cbfdfb6fb026a96bea06d8f181bf10c020adbcc88b6ecff96bdc564a9649c247cede601c4be63afc3"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECT_K1) 409-bit
+depends_on:PSA_WANT_ECC_SECT_K1_409:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):409:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04012c587f69f68b308ba6dcb238797f4e22290ca939ae806604e2b5ab4d9caef5a74a98fd87c4f88d292dd39d92e556e16c6ecc3c019a105826eef507cd9a04119f54d5d850b3720b3792d5d03410e9105610f7e4b420166ed45604a7a1f229d80975ba6be2060e8b":"505341004b4559000000000001000000274199010100000000000000000000006900000004012c587f69f68b308ba6dcb238797f4e22290ca939ae806604e2b5ab4d9caef5a74a98fd87c4f88d292dd39d92e556e16c6ecc3c019a105826eef507cd9a04119f54d5d850b3720b3792d5d03410e9105610f7e4b420166ed45604a7a1f229d80975ba6be2060e8b"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECT_K1) 571-bit
+depends_on:PSA_WANT_ECC_SECT_K1_571:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):571:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04050172a7fd7adf98e4e2ed2742faa5cd12731a15fb0dbbdf75b1c3cc771a4369af6f2fa00e802735650881735759ea9c79961ded18e0daa0ac59afb1d513b5bbda9962e435f454fc020b4afe1445c2302ada07d295ec2580f8849b2dfa7f956b09b4cbe4c88d3b1c217049f75d3900d36df0fa12689256b58dd2ef784ebbeb0564600cf47a841485f8cf897a68accd5a":"505341004b455900000000000100000027413b020100000000000000000000009100000004050172a7fd7adf98e4e2ed2742faa5cd12731a15fb0dbbdf75b1c3cc771a4369af6f2fa00e802735650881735759ea9c79961ded18e0daa0ac59afb1d513b5bbda9962e435f454fc020b4afe1445c2302ada07d295ec2580f8849b2dfa7f956b09b4cbe4c88d3b1c217049f75d3900d36df0fa12689256b58dd2ef784ebbeb0564600cf47a841485f8cf897a68accd5a"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECT_R1) 163-bit
+depends_on:PSA_WANT_ECC_SECT_R1_163:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):163:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0400465eeb9e7258b11e33c02266bfe834b20bcb118700772796ee4704ec67651bd447e3011959a79a04cb":"505341004b45590000000000010000002241a3000100000000000000000000002b0000000400465eeb9e7258b11e33c02266bfe834b20bcb118700772796ee4704ec67651bd447e3011959a79a04cb"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECT_R1) 233-bit
+depends_on:PSA_WANT_ECC_SECT_R1_233:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):233:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0400cd68c8af4430c92ec7a7048becfdf00a6bae8d1b4c37286f2d336f2a0e017eca3748f4ad6d435c85867aa014eea1bd6d9d005bbd8319cab629001d":"505341004b45590000000000010000002241e9000100000000000000000000003d0000000400cd68c8af4430c92ec7a7048becfdf00a6bae8d1b4c37286f2d336f2a0e017eca3748f4ad6d435c85867aa014eea1bd6d9d005bbd8319cab629001d"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECT_R1) 283-bit
+depends_on:PSA_WANT_ECC_SECT_R1_283:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):283:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04052f9ff887254c2d1440ba9e30f13e2185ba53c373b2c410dae21cf8c167f796c08134f601cbc4c570bffbc2433082cf4d9eb5ba173ecb8caec15d66a02673f60807b2daa729b765":"505341004b455900000000000100000022411b010100000000000000000000004900000004052f9ff887254c2d1440ba9e30f13e2185ba53c373b2c410dae21cf8c167f796c08134f601cbc4c570bffbc2433082cf4d9eb5ba173ecb8caec15d66a02673f60807b2daa729b765"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECT_R1) 409-bit
+depends_on:PSA_WANT_ECC_SECT_R1_409:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):409:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0401aa25466b1d291846db365957b25431591e50d9c109fe2106e93bb369775896925b15a7bfec397406ab4fe6f6b1a13bf8fdcb9300fa5500a813228676b0a6c572ed96b0f4aec7e87832e7e20f17ca98ecdfd36f59c82bddb8665f1f357a73900e827885ec9e1f22":"505341004b455900000000000100000022419901010000000000000000000000690000000401aa25466b1d291846db365957b25431591e50d9c109fe2106e93bb369775896925b15a7bfec397406ab4fe6f6b1a13bf8fdcb9300fa5500a813228676b0a6c572ed96b0f4aec7e87832e7e20f17ca98ecdfd36f59c82bddb8665f1f357a73900e827885ec9e1f22"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECT_R1) 571-bit
+depends_on:PSA_WANT_ECC_SECT_R1_571:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):571:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"040708f3403ee9948114855c17572152a08f8054d486defef5f29cbffcfb7cfd9280746a1ac5f751a6ad902ec1e0525120e9be56f03437af196fbe60ee7856e3542ab2cf87880632d80290e39b1a2bd03c6bbf6225511c567bd2ff41d2325dc58346f2b60b1feee4dc8b2af2296c2dc52b153e0556b5d24152b07f690c3fa24e4d1d19efbdeb1037833a733654d2366c74":"505341004b455900000000000100000022413b0201000000000000000000000091000000040708f3403ee9948114855c17572152a08f8054d486defef5f29cbffcfb7cfd9280746a1ac5f751a6ad902ec1e0525120e9be56f03437af196fbe60ee7856e3542ab2cf87880632d80290e39b1a2bd03c6bbf6225511c567bd2ff41d2325dc58346f2b60b1feee4dc8b2af2296c2dc52b153e0556b5d24152b07f690c3fa24e4d1d19efbdeb1037833a733654d2366c74"
+
+PSA storage save: type: ECC_PUBLIC_KEY(SECT_R2) 163-bit
+depends_on:PSA_WANT_ECC_SECT_R2_163:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R2):163:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0403692601144c32a6cfa369ae20ae5d43c1c764678c037bafe80c6fd2e42b7ced96171d9c5367fd3dca6f":"505341004b45590000000000010000002b41a3000100000000000000000000002b0000000403692601144c32a6cfa369ae20ae5d43c1c764678c037bafe80c6fd2e42b7ced96171d9c5367fd3dca6f"
+
+PSA storage save: type: ECC_PUBLIC_KEY(TWISTED_EDWARDS) 255-bit
+depends_on:PSA_WANT_ECC_TWISTED_EDWARDS_255:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS):255:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a":"505341004b45590000000000010000004241ff0001000000000000000000000020000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"
+
+PSA storage save: type: ECC_PUBLIC_KEY(TWISTED_EDWARDS) 448-bit
+depends_on:PSA_WANT_ECC_TWISTED_EDWARDS_448:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS):448:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"5fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180":"505341004b45590000000000010000004241c001010000000000000000000000390000005fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180"
+
+PSA storage save: type: HMAC 128-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+key_storage_save:0x0001:PSA_KEY_TYPE_HMAC:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000001180000100000000000000000000001000000048657265006973206b6579a064617461"
+
+PSA storage save: type: HMAC 160-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+key_storage_save:0x0001:PSA_KEY_TYPE_HMAC:160:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265":"505341004b45590000000000010000000011a0000100000000000000000000001400000048657265006973206b6579a06461746148657265"
+
+PSA storage save: type: HMAC 224-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+key_storage_save:0x0001:PSA_KEY_TYPE_HMAC:224:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a0":"505341004b45590000000000010000000011e0000100000000000000000000001c00000048657265006973206b6579a06461746148657265006973206b6579a0"
+
+PSA storage save: type: HMAC 256-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+key_storage_save:0x0001:PSA_KEY_TYPE_HMAC:256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000001100010100000000000000000000002000000048657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA storage save: type: HMAC 384-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+key_storage_save:0x0001:PSA_KEY_TYPE_HMAC:384:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000001180010100000000000000000000003000000048657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA storage save: type: HMAC 512-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+key_storage_save:0x0001:PSA_KEY_TYPE_HMAC:512:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000001100020100000000000000000000004000000048657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461"
+
+PSA storage save: type: RAW_DATA 8-bit
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48":"505341004b4559000000000001000000011008000100000000000000000000000100000048"
+
+PSA storage save: type: RAW_DATA 40-bit
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:40:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"4865726500":"505341004b455900000000000100000001102800010000000000000000000000050000004865726500"
+
+PSA storage save: type: RAW_DATA 128-bit
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000011080000100000000000000000000001000000048657265006973206b6579a064617461"
+
+PSA storage save: type: RSA_KEY_PAIR 1024-bit
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"505341004b455900000000000100000001700004010000000000000000000000620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24"
+
+PSA storage save: type: RSA_KEY_PAIR 1536-bit
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+key_storage_save:0x0001:PSA_KEY_TYPE_RSA_KEY_PAIR:1536:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"3082037b0201000281c100c870feb6ca6b1d2bd9f2dd99e20f1fe2d7e5192de662229dbe162bd1ba66336a7182903ca0b72796cd441c83d24bcdc3e9a2f5e4399c8a043f1c3ddf04754a66d4cfe7b3671a37dd31a9b4c13bfe06ee90f9d94ddaa06de67a52ac863e68f756736ceb014405a6160579640f831dddccc34ad0b05070e3f9954a58d1815813e1b83bcadba814789c87f1ef2ba5d738b793ec456a67360eea1b5faf1c7cc7bf24f3b2a9d0f8958b1096e0f0c335f8888d0c63a51c3c0337214fa3f5efdf6dcc3502030100010281c06d2d670047973a87752a9d5bc14f3dae00acb01f593aa0e24cf4a49f932931de4bbfb332e2d38083da80bc0b6d538edba479f7f77d0deffb4a28e6e67ff6273585bb4cd862535c946605ab0809d65f0e38f76e4ec2c3d9b8cd6e14bcf667943892cd4b34cc6420a439abbf3d7d35ef73976dd6f9cbde35a51fa5213f0107f83e3425835d16d3c9146fc9e36ce75a09bb66cdff21dd5a776899f1cb07e282cca27be46510e9c799f0d8db275a6be085d9f3f803218ee3384265bfb1a3640e8ca1026100e6848c31d466fffefc547e3a3b0d3785de6f78b0dd12610843512e495611a0675509b1650b27415009838dd8e68eec6e7530553b637d602424643b33e8bc5b762e1799bc79d56b13251d36d4f201da2182416ce13574e88278ff04467ad602d9026100de994fdf181f02be2bf9e5f5e4e517a94993b827d1eaf609033e3a6a6f2396ae7c44e9eb594cf1044cb3ad32ea258f0c82963b27bb650ed200cde82cb993374be34be5b1c7ead5446a2b82a4486e8c1810a0b01551609fb0841d474bada802bd026076ddae751b73a959d0bfb8ff49e7fcd378e9be30652ecefe35c82cb8003bc29cc60ae3809909baf20c95db9516fe680865417111d8b193dbcf30281f1249de57c858bf1ba32f5bb1599800e8398a9ef25c7a642c95261da6f9c17670e97265b10260732482b837d5f2a9443e23c1aa0106d83e82f6c3424673b5fdc3769c0f992d1c5c93991c7038e882fcda04414df4d7a5f4f698ead87851ce37344b60b72d7b70f9c60cae8566e7a257f8e1bef0e89df6e4c2f9d24d21d9f8889e4c7eccf91751026009050d94493da8f00a4ddbe9c800afe3d44b43f78a48941a79b2814a1f0b81a18a8b2347642a03b27998f5a18de9abc9ae0e54ab8294feac66dc87e854cce6f7278ac2710cb5878b592ffeb1f4f0a1853e4e8d1d0561b6efcc831a296cf7eeaf":"505341004b4559000000000001000000017000060100000000000000000000007f0300003082037b0201000281c100c870feb6ca6b1d2bd9f2dd99e20f1fe2d7e5192de662229dbe162bd1ba66336a7182903ca0b72796cd441c83d24bcdc3e9a2f5e4399c8a043f1c3ddf04754a66d4cfe7b3671a37dd31a9b4c13bfe06ee90f9d94ddaa06de67a52ac863e68f756736ceb014405a6160579640f831dddccc34ad0b05070e3f9954a58d1815813e1b83bcadba814789c87f1ef2ba5d738b793ec456a67360eea1b5faf1c7cc7bf24f3b2a9d0f8958b1096e0f0c335f8888d0c63a51c3c0337214fa3f5efdf6dcc3502030100010281c06d2d670047973a87752a9d5bc14f3dae00acb01f593aa0e24cf4a49f932931de4bbfb332e2d38083da80bc0b6d538edba479f7f77d0deffb4a28e6e67ff6273585bb4cd862535c946605ab0809d65f0e38f76e4ec2c3d9b8cd6e14bcf667943892cd4b34cc6420a439abbf3d7d35ef73976dd6f9cbde35a51fa5213f0107f83e3425835d16d3c9146fc9e36ce75a09bb66cdff21dd5a776899f1cb07e282cca27be46510e9c799f0d8db275a6be085d9f3f803218ee3384265bfb1a3640e8ca1026100e6848c31d466fffefc547e3a3b0d3785de6f78b0dd12610843512e495611a0675509b1650b27415009838dd8e68eec6e7530553b637d602424643b33e8bc5b762e1799bc79d56b13251d36d4f201da2182416ce13574e88278ff04467ad602d9026100de994fdf181f02be2bf9e5f5e4e517a94993b827d1eaf609033e3a6a6f2396ae7c44e9eb594cf1044cb3ad32ea258f0c82963b27bb650ed200cde82cb993374be34be5b1c7ead5446a2b82a4486e8c1810a0b01551609fb0841d474bada802bd026076ddae751b73a959d0bfb8ff49e7fcd378e9be30652ecefe35c82cb8003bc29cc60ae3809909baf20c95db9516fe680865417111d8b193dbcf30281f1249de57c858bf1ba32f5bb1599800e8398a9ef25c7a642c95261da6f9c17670e97265b10260732482b837d5f2a9443e23c1aa0106d83e82f6c3424673b5fdc3769c0f992d1c5c93991c7038e882fcda04414df4d7a5f4f698ead87851ce37344b60b72d7b70f9c60cae8566e7a257f8e1bef0e89df6e4c2f9d24d21d9f8889e4c7eccf91751026009050d94493da8f00a4ddbe9c800afe3d44b43f78a48941a79b2814a1f0b81a18a8b2347642a03b27998f5a18de9abc9ae0e54ab8294feac66dc87e854cce6f7278ac2710cb5878b592ffeb1f4f0a1853e4e8d1d0561b6efcc831a296cf7eeaf"
+
+PSA storage save: type: RSA_PUBLIC_KEY 1024-bit
+depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":"505341004b4559000000000001000000014000040100000000000000000000008c00000030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001"
+
+PSA storage save: type: RSA_PUBLIC_KEY 1536-bit
+depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
+key_storage_save:0x0001:PSA_KEY_TYPE_RSA_PUBLIC_KEY:1536:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"3081c90281c100c870feb6ca6b1d2bd9f2dd99e20f1fe2d7e5192de662229dbe162bd1ba66336a7182903ca0b72796cd441c83d24bcdc3e9a2f5e4399c8a043f1c3ddf04754a66d4cfe7b3671a37dd31a9b4c13bfe06ee90f9d94ddaa06de67a52ac863e68f756736ceb014405a6160579640f831dddccc34ad0b05070e3f9954a58d1815813e1b83bcadba814789c87f1ef2ba5d738b793ec456a67360eea1b5faf1c7cc7bf24f3b2a9d0f8958b1096e0f0c335f8888d0c63a51c3c0337214fa3f5efdf6dcc350203010001":"505341004b455900000000000100000001400006010000000000000000000000cc0000003081c90281c100c870feb6ca6b1d2bd9f2dd99e20f1fe2d7e5192de662229dbe162bd1ba66336a7182903ca0b72796cd441c83d24bcdc3e9a2f5e4399c8a043f1c3ddf04754a66d4cfe7b3671a37dd31a9b4c13bfe06ee90f9d94ddaa06de67a52ac863e68f756736ceb014405a6160579640f831dddccc34ad0b05070e3f9954a58d1815813e1b83bcadba814789c87f1ef2ba5d738b793ec456a67360eea1b5faf1c7cc7bf24f3b2a9d0f8958b1096e0f0c335f8888d0c63a51c3c0337214fa3f5efdf6dcc350203010001"
+
+PSA storage save: alg: AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(CCM, 1)
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000081410500000000010000004b"
+
+PSA storage save: alg2: AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(CCM, 1)
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 1):"4c":"505341004b455900000000000100000001100800010000000000000000814105010000004c"
+
+PSA storage save: alg: AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(CHACHA20_POLY1305, 1)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CHACHA20_POLY1305, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000085010500000000010000004b"
+
+PSA storage save: alg2: AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(CHACHA20_POLY1305, 1)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CHACHA20_POLY1305, 1):"4c":"505341004b455900000000000100000001100800010000000000000000850105010000004c"
+
+PSA storage save: alg: AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(GCM, 1)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_GCM, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000082410500000000010000004b"
+
+PSA storage save: alg2: AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(GCM, 1)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_GCM, 1):"4c":"505341004b455900000000000100000001100800010000000000000000824105010000004c"
+
+PSA storage save: alg: AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(CCM, 63)
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 63):0x0000:"4b":"505341004b4559000000000001000000011008000100000000817f0500000000010000004b"
+
+PSA storage save: alg2: AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(CCM, 63)
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 63):"4c":"505341004b455900000000000100000001100800010000000000000000817f05010000004c"
+
+PSA storage save: alg: AEAD_WITH_SHORTENED_TAG(CCM, 1)
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000001410500000000010000004b"
+
+PSA storage save: alg2: AEAD_WITH_SHORTENED_TAG(CCM, 1)
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 1):"4c":"505341004b455900000000000100000001100800010000000000000000014105010000004c"
+
+PSA storage save: alg: AEAD_WITH_SHORTENED_TAG(CHACHA20_POLY1305, 1)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000005010500000000010000004b"
+
+PSA storage save: alg2: AEAD_WITH_SHORTENED_TAG(CHACHA20_POLY1305, 1)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 1):"4c":"505341004b455900000000000100000001100800010000000000000000050105010000004c"
+
+PSA storage save: alg: AEAD_WITH_SHORTENED_TAG(GCM, 1)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000002410500000000010000004b"
+
+PSA storage save: alg2: AEAD_WITH_SHORTENED_TAG(GCM, 1)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 1):"4c":"505341004b455900000000000100000001100800010000000000000000024105010000004c"
+
+PSA storage save: alg: AEAD_WITH_SHORTENED_TAG(CCM, 63)
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 63):0x0000:"4b":"505341004b4559000000000001000000011008000100000000017f0500000000010000004b"
+
+PSA storage save: alg2: AEAD_WITH_SHORTENED_TAG(CCM, 63)
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 63):"4c":"505341004b455900000000000100000001100800010000000000000000017f05010000004c"
+
+PSA storage save: alg: ANY_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ANY_HASH:0x0000:"4b":"505341004b45590000000000010000000110080001000000ff00000200000000010000004b"
+
+PSA storage save: alg2: ANY_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ANY_HASH:"4c":"505341004b4559000000000001000000011008000100000000000000ff000002010000004c"
+
+PSA storage save: alg: AT_LEAST_THIS_LENGTH_MAC(CBC_MAC, 1)
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CBC_MAC, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000081c10300000000010000004b"
+
+PSA storage save: alg2: AT_LEAST_THIS_LENGTH_MAC(CBC_MAC, 1)
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CBC_MAC, 1):"4c":"505341004b45590000000000010000000110080001000000000000000081c103010000004c"
+
+PSA storage save: alg: AT_LEAST_THIS_LENGTH_MAC(CMAC, 1)
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CMAC, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000082c10300000000010000004b"
+
+PSA storage save: alg2: AT_LEAST_THIS_LENGTH_MAC(CMAC, 1)
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CMAC, 1):"4c":"505341004b45590000000000010000000110080001000000000000000082c103010000004c"
+
+PSA storage save: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(MD2), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_MD2), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000180810300000000010000004b"
+
+PSA storage save: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(MD2), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_MD2), 1):"4c":"505341004b455900000000000100000001100800010000000000000001808103010000004c"
+
+PSA storage save: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(MD4), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_MD4), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000280810300000000010000004b"
+
+PSA storage save: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(MD4), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_MD4), 1):"4c":"505341004b455900000000000100000001100800010000000000000002808103010000004c"
+
+PSA storage save: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(MD5), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_MD5), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000380810300000000010000004b"
+
+PSA storage save: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(MD5), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_MD5), 1):"4c":"505341004b455900000000000100000001100800010000000000000003808103010000004c"
+
+PSA storage save: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(RIPEMD160), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_RIPEMD160), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000480810300000000010000004b"
+
+PSA storage save: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(RIPEMD160), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_RIPEMD160), 1):"4c":"505341004b455900000000000100000001100800010000000000000004808103010000004c"
+
+PSA storage save: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_1), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_1), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000580810300000000010000004b"
+
+PSA storage save: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_1), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_1), 1):"4c":"505341004b455900000000000100000001100800010000000000000005808103010000004c"
+
+PSA storage save: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_224), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_224), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000880810300000000010000004b"
+
+PSA storage save: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_224), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_224), 1):"4c":"505341004b455900000000000100000001100800010000000000000008808103010000004c"
+
+PSA storage save: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_256), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000980810300000000010000004b"
+
+PSA storage save: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_256), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 1):"4c":"505341004b455900000000000100000001100800010000000000000009808103010000004c"
+
+PSA storage save: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_384), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_384), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000a80810300000000010000004b"
+
+PSA storage save: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_384), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_384), 1):"4c":"505341004b45590000000000010000000110080001000000000000000a808103010000004c"
+
+PSA storage save: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_512), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_512), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000b80810300000000010000004b"
+
+PSA storage save: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_512), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_512), 1):"4c":"505341004b45590000000000010000000110080001000000000000000b808103010000004c"
+
+PSA storage save: alg: AT_LEAST_THIS_LENGTH_MAC(CBC_MAC, 63)
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CBC_MAC, 63):0x0000:"4b":"505341004b455900000000000100000001100800010000000081ff0300000000010000004b"
+
+PSA storage save: alg2: AT_LEAST_THIS_LENGTH_MAC(CBC_MAC, 63)
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CBC_MAC, 63):"4c":"505341004b45590000000000010000000110080001000000000000000081ff03010000004c"
+
+PSA storage save: alg: CBC_MAC
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_CBC_MAC:0x0000:"4b":"505341004b455900000000000100000001100800010000000001c00300000000010000004b"
+
+PSA storage save: alg2: CBC_MAC
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_CBC_MAC:"4c":"505341004b45590000000000010000000110080001000000000000000001c003010000004c"
+
+PSA storage save: alg: CBC_NO_PADDING
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_CBC_NO_PADDING:0x0000:"4b":"505341004b455900000000000100000001100800010000000040400400000000010000004b"
+
+PSA storage save: alg2: CBC_NO_PADDING
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_CBC_NO_PADDING:"4c":"505341004b455900000000000100000001100800010000000000000000404004010000004c"
+
+PSA storage save: alg: CBC_PKCS7
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_CBC_PKCS7:0x0000:"4b":"505341004b455900000000000100000001100800010000000041400400000000010000004b"
+
+PSA storage save: alg2: CBC_PKCS7
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_CBC_PKCS7:"4c":"505341004b455900000000000100000001100800010000000000000000414004010000004c"
+
+PSA storage save: alg: CCM
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_CCM:0x0000:"4b":"505341004b455900000000000100000001100800010000000001500500000000010000004b"
+
+PSA storage save: alg2: CCM
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_CCM:"4c":"505341004b455900000000000100000001100800010000000000000000015005010000004c"
+
+PSA storage save: alg: CFB
+depends_on:PSA_WANT_ALG_CFB:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_CFB:0x0000:"4b":"505341004b455900000000000100000001100800010000000011c00400000000010000004b"
+
+PSA storage save: alg2: CFB
+depends_on:PSA_WANT_ALG_CFB:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_CFB:"4c":"505341004b45590000000000010000000110080001000000000000000011c004010000004c"
+
+PSA storage save: alg: CHACHA20_POLY1305
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_CHACHA20_POLY1305:0x0000:"4b":"505341004b455900000000000100000001100800010000000005100500000000010000004b"
+
+PSA storage save: alg2: CHACHA20_POLY1305
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_CHACHA20_POLY1305:"4c":"505341004b455900000000000100000001100800010000000000000000051005010000004c"
+
+PSA storage save: alg: CMAC
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_CMAC:0x0000:"4b":"505341004b455900000000000100000001100800010000000002c00300000000010000004b"
+
+PSA storage save: alg2: CMAC
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_CMAC:"4c":"505341004b45590000000000010000000110080001000000000000000002c003010000004c"
+
+PSA storage save: alg: CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0x0000:"4b":"505341004b455900000000000100000001100800010000000010c00400000000010000004b"
+
+PSA storage save: alg2: CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_CTR:"4c":"505341004b45590000000000010000000110080001000000000000000010c004010000004c"
+
+PSA storage save: alg: DETERMINISTIC_DSA(MD2)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000105000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_DSA(MD2)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001050006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_DSA(MD4)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000205000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_DSA(MD4)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002050006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_DSA(MD5)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000305000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_DSA(MD5)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003050006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_DSA(RIPEMD160)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000405000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_DSA(RIPEMD160)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004050006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_DSA(SHA_1)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000505000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_DSA(SHA_1)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005050006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_DSA(SHA_224)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000805000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_DSA(SHA_224)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008050006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_DSA(SHA_256)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000905000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_DSA(SHA_256)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009050006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_DSA(SHA_384)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a05000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_DSA(SHA_384)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a050006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_DSA(SHA_512)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b05000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_DSA(SHA_512)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b050006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_ECDSA(MD2)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000107000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_ECDSA(MD2)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001070006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_ECDSA(MD4)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000207000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_ECDSA(MD4)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002070006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_ECDSA(MD5)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000307000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_ECDSA(MD5)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003070006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_ECDSA(RIPEMD160)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000407000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_ECDSA(RIPEMD160)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004070006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_ECDSA(SHA_1)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000507000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_ECDSA(SHA_1)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005070006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_ECDSA(SHA_224)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000807000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_ECDSA(SHA_224)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008070006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_ECDSA(SHA_256)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000907000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_ECDSA(SHA_256)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009070006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_ECDSA(SHA_384)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a07000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_ECDSA(SHA_384)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a070006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_ECDSA(SHA_512)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b07000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_ECDSA(SHA_512)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b070006010000004c"
+
+PSA storage save: alg: DETERMINISTIC_ECDSA(ANY_HASH)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH):0x0000:"4b":"505341004b45590000000000010000000110080001000000ff07000600000000010000004b"
+
+PSA storage save: alg2: DETERMINISTIC_ECDSA(ANY_HASH)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH):"4c":"505341004b4559000000000001000000011008000100000000000000ff070006010000004c"
+
+PSA storage save: alg: DSA(MD2)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000104000600000000010000004b"
+
+PSA storage save: alg2: DSA(MD2)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001040006010000004c"
+
+PSA storage save: alg: DSA(MD4)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000204000600000000010000004b"
+
+PSA storage save: alg2: DSA(MD4)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002040006010000004c"
+
+PSA storage save: alg: DSA(MD5)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000304000600000000010000004b"
+
+PSA storage save: alg2: DSA(MD5)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003040006010000004c"
+
+PSA storage save: alg: DSA(RIPEMD160)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000404000600000000010000004b"
+
+PSA storage save: alg2: DSA(RIPEMD160)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004040006010000004c"
+
+PSA storage save: alg: DSA(SHA_1)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000504000600000000010000004b"
+
+PSA storage save: alg2: DSA(SHA_1)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005040006010000004c"
+
+PSA storage save: alg: DSA(SHA_224)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000804000600000000010000004b"
+
+PSA storage save: alg2: DSA(SHA_224)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008040006010000004c"
+
+PSA storage save: alg: DSA(SHA_256)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000904000600000000010000004b"
+
+PSA storage save: alg2: DSA(SHA_256)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009040006010000004c"
+
+PSA storage save: alg: DSA(SHA_384)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a04000600000000010000004b"
+
+PSA storage save: alg2: DSA(SHA_384)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a040006010000004c"
+
+PSA storage save: alg: DSA(SHA_512)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b04000600000000010000004b"
+
+PSA storage save: alg2: DSA(SHA_512)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b040006010000004c"
+
+PSA storage save: alg: ECB_NO_PADDING
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECB_NO_PADDING:0x0000:"4b":"505341004b455900000000000100000001100800010000000044400400000000010000004b"
+
+PSA storage save: alg2: ECB_NO_PADDING
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECB_NO_PADDING:"4c":"505341004b455900000000000100000001100800010000000000000000444004010000004c"
+
+PSA storage save: alg: ECDH
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDH:0x0000:"4b":"505341004b455900000000000100000001100800010000000000020900000000010000004b"
+
+PSA storage save: alg2: ECDH
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDH:"4c":"505341004b455900000000000100000001100800010000000000000000000209010000004c"
+
+PSA storage save: alg: ECDSA(MD2)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000106000600000000010000004b"
+
+PSA storage save: alg2: ECDSA(MD2)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001060006010000004c"
+
+PSA storage save: alg: ECDSA(MD4)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000206000600000000010000004b"
+
+PSA storage save: alg2: ECDSA(MD4)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002060006010000004c"
+
+PSA storage save: alg: ECDSA(MD5)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000306000600000000010000004b"
+
+PSA storage save: alg2: ECDSA(MD5)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003060006010000004c"
+
+PSA storage save: alg: ECDSA(RIPEMD160)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000406000600000000010000004b"
+
+PSA storage save: alg2: ECDSA(RIPEMD160)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004060006010000004c"
+
+PSA storage save: alg: ECDSA(SHA_1)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000506000600000000010000004b"
+
+PSA storage save: alg2: ECDSA(SHA_1)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005060006010000004c"
+
+PSA storage save: alg: ECDSA(SHA_224)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000806000600000000010000004b"
+
+PSA storage save: alg2: ECDSA(SHA_224)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008060006010000004c"
+
+PSA storage save: alg: ECDSA(SHA_256)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000906000600000000010000004b"
+
+PSA storage save: alg2: ECDSA(SHA_256)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009060006010000004c"
+
+PSA storage save: alg: ECDSA(SHA_384)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a06000600000000010000004b"
+
+PSA storage save: alg2: ECDSA(SHA_384)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a060006010000004c"
+
+PSA storage save: alg: ECDSA(SHA_512)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b06000600000000010000004b"
+
+PSA storage save: alg2: ECDSA(SHA_512)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b060006010000004c"
+
+PSA storage save: alg: ECDSA(ANY_HASH)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0x0000:"4b":"505341004b45590000000000010000000110080001000000ff06000600000000010000004b"
+
+PSA storage save: alg2: ECDSA(ANY_HASH)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):"4c":"505341004b4559000000000001000000011008000100000000000000ff060006010000004c"
+
+PSA storage save: alg: ECDSA_ANY
+depends_on:PSA_WANT_ALG_ECDSA_ANY:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA_ANY:0x0000:"4b":"505341004b455900000000000100000001100800010000000006000600000000010000004b"
+
+PSA storage save: alg2: ECDSA_ANY
+depends_on:PSA_WANT_ALG_ECDSA_ANY:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA_ANY:"4c":"505341004b455900000000000100000001100800010000000000000000060006010000004c"
+
+PSA storage save: alg: ED25519PH
+depends_on:PSA_WANT_ALG_ED25519PH:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ED25519PH:0x0000:"4b":"505341004b455900000000000100000001100800010000000b09000600000000010000004b"
+
+PSA storage save: alg2: ED25519PH
+depends_on:PSA_WANT_ALG_ED25519PH:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ED25519PH:"4c":"505341004b45590000000000010000000110080001000000000000000b090006010000004c"
+
+PSA storage save: alg: ED448PH
+depends_on:PSA_WANT_ALG_ED448PH:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ED448PH:0x0000:"4b":"505341004b455900000000000100000001100800010000001509000600000000010000004b"
+
+PSA storage save: alg2: ED448PH
+depends_on:PSA_WANT_ALG_ED448PH:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ED448PH:"4c":"505341004b455900000000000100000001100800010000000000000015090006010000004c"
+
+PSA storage save: alg: FFDH
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_FFDH:0x0000:"4b":"505341004b455900000000000100000001100800010000000000010900000000010000004b"
+
+PSA storage save: alg2: FFDH
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_FFDH:"4c":"505341004b455900000000000100000001100800010000000000000000000109010000004c"
+
+PSA storage save: alg: GCM
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_GCM:0x0000:"4b":"505341004b455900000000000100000001100800010000000002500500000000010000004b"
+
+PSA storage save: alg2: GCM
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_GCM:"4c":"505341004b455900000000000100000001100800010000000000000000025005010000004c"
+
+PSA storage save: alg: HKDF(MD2)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000101000800000000010000004b"
+
+PSA storage save: alg2: HKDF(MD2)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001010008010000004c"
+
+PSA storage save: alg: HKDF(MD4)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000201000800000000010000004b"
+
+PSA storage save: alg2: HKDF(MD4)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002010008010000004c"
+
+PSA storage save: alg: HKDF(MD5)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000301000800000000010000004b"
+
+PSA storage save: alg2: HKDF(MD5)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003010008010000004c"
+
+PSA storage save: alg: HKDF(RIPEMD160)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000401000800000000010000004b"
+
+PSA storage save: alg2: HKDF(RIPEMD160)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004010008010000004c"
+
+PSA storage save: alg: HKDF(SHA_1)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000501000800000000010000004b"
+
+PSA storage save: alg2: HKDF(SHA_1)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005010008010000004c"
+
+PSA storage save: alg: HKDF(SHA_224)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000801000800000000010000004b"
+
+PSA storage save: alg2: HKDF(SHA_224)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008010008010000004c"
+
+PSA storage save: alg: HKDF(SHA_256)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000901000800000000010000004b"
+
+PSA storage save: alg2: HKDF(SHA_256)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009010008010000004c"
+
+PSA storage save: alg: HKDF(SHA_384)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a01000800000000010000004b"
+
+PSA storage save: alg2: HKDF(SHA_384)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a010008010000004c"
+
+PSA storage save: alg: HKDF(SHA_512)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b01000800000000010000004b"
+
+PSA storage save: alg2: HKDF(SHA_512)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b010008010000004c"
+
+PSA storage save: alg: HMAC(MD2)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000100800300000000010000004b"
+
+PSA storage save: alg2: HMAC(MD2)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001008003010000004c"
+
+PSA storage save: alg: HMAC(MD4)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000200800300000000010000004b"
+
+PSA storage save: alg2: HMAC(MD4)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002008003010000004c"
+
+PSA storage save: alg: HMAC(MD5)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000300800300000000010000004b"
+
+PSA storage save: alg2: HMAC(MD5)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003008003010000004c"
+
+PSA storage save: alg: HMAC(RIPEMD160)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000400800300000000010000004b"
+
+PSA storage save: alg2: HMAC(RIPEMD160)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004008003010000004c"
+
+PSA storage save: alg: HMAC(SHA_1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000500800300000000010000004b"
+
+PSA storage save: alg2: HMAC(SHA_1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005008003010000004c"
+
+PSA storage save: alg: HMAC(SHA_224)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000800800300000000010000004b"
+
+PSA storage save: alg2: HMAC(SHA_224)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008008003010000004c"
+
+PSA storage save: alg: HMAC(SHA_256)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000900800300000000010000004b"
+
+PSA storage save: alg2: HMAC(SHA_256)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009008003010000004c"
+
+PSA storage save: alg: HMAC(SHA_384)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a00800300000000010000004b"
+
+PSA storage save: alg2: HMAC(SHA_384)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a008003010000004c"
+
+PSA storage save: alg: HMAC(SHA_512)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b00800300000000010000004b"
+
+PSA storage save: alg2: HMAC(SHA_512)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b008003010000004c"
+
+PSA storage save: alg: KEY_AGREEMENT(ECDH, HKDF(SHA_256))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):0x0000:"4b":"505341004b455900000000000100000001100800010000000901020900000000010000004b"
+
+PSA storage save: alg2: KEY_AGREEMENT(ECDH, HKDF(SHA_256))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):"4c":"505341004b455900000000000100000001100800010000000000000009010209010000004c"
+
+PSA storage save: alg: KEY_AGREEMENT(FFDH, HKDF(SHA_256))
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_KEY_AGREEMENT(PSA_ALG_FFDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):0x0000:"4b":"505341004b455900000000000100000001100800010000000901010900000000010000004b"
+
+PSA storage save: alg2: KEY_AGREEMENT(FFDH, HKDF(SHA_256))
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_KEY_AGREEMENT(PSA_ALG_FFDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):"4c":"505341004b455900000000000100000001100800010000000000000009010109010000004c"
+
+PSA storage save: alg: KEY_AGREEMENT(ECDH, HKDF(SHA_384))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_384)):0x0000:"4b":"505341004b455900000000000100000001100800010000000a01020900000000010000004b"
+
+PSA storage save: alg2: KEY_AGREEMENT(ECDH, HKDF(SHA_384))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_384)):"4c":"505341004b45590000000000010000000110080001000000000000000a010209010000004c"
+
+PSA storage save: alg: KEY_AGREEMENT(ECDH, TLS12_PRF(SHA_256))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)):0x0000:"4b":"505341004b455900000000000100000001100800010000000902020900000000010000004b"
+
+PSA storage save: alg2: KEY_AGREEMENT(ECDH, TLS12_PRF(SHA_256))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)):"4c":"505341004b455900000000000100000001100800010000000000000009020209010000004c"
+
+PSA storage save: alg: KEY_AGREEMENT(ECDH, TLS12_PRF(SHA_384))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384)):0x0000:"4b":"505341004b455900000000000100000001100800010000000a02020900000000010000004b"
+
+PSA storage save: alg2: KEY_AGREEMENT(ECDH, TLS12_PRF(SHA_384))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384)):"4c":"505341004b45590000000000010000000110080001000000000000000a020209010000004c"
+
+PSA storage save: alg: KEY_AGREEMENT(ECDH, TLS12_PSK_TO_MS(SHA_256))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256)):0x0000:"4b":"505341004b455900000000000100000001100800010000000903020900000000010000004b"
+
+PSA storage save: alg2: KEY_AGREEMENT(ECDH, TLS12_PSK_TO_MS(SHA_256))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256)):"4c":"505341004b455900000000000100000001100800010000000000000009030209010000004c"
+
+PSA storage save: alg: KEY_AGREEMENT(ECDH, TLS12_PSK_TO_MS(SHA_384))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384)):0x0000:"4b":"505341004b455900000000000100000001100800010000000a03020900000000010000004b"
+
+PSA storage save: alg2: KEY_AGREEMENT(ECDH, TLS12_PSK_TO_MS(SHA_384))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384)):"4c":"505341004b45590000000000010000000110080001000000000000000a030209010000004c"
+
+PSA storage save: alg: KEY_AGREEMENT(FFDH, HKDF(SHA_384))
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_KEY_AGREEMENT(PSA_ALG_FFDH, PSA_ALG_HKDF(PSA_ALG_SHA_384)):0x0000:"4b":"505341004b455900000000000100000001100800010000000a01010900000000010000004b"
+
+PSA storage save: alg2: KEY_AGREEMENT(FFDH, HKDF(SHA_384))
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_KEY_AGREEMENT(PSA_ALG_FFDH, PSA_ALG_HKDF(PSA_ALG_SHA_384)):"4c":"505341004b45590000000000010000000110080001000000000000000a010109010000004c"
+
+PSA storage save: alg: MD2
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_MD2:0x0000:"4b":"505341004b455900000000000100000001100800010000000100000200000000010000004b"
+
+PSA storage save: alg2: MD2
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_MD2:"4c":"505341004b455900000000000100000001100800010000000000000001000002010000004c"
+
+PSA storage save: alg: MD4
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_MD4:0x0000:"4b":"505341004b455900000000000100000001100800010000000200000200000000010000004b"
+
+PSA storage save: alg2: MD4
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_MD4:"4c":"505341004b455900000000000100000001100800010000000000000002000002010000004c"
+
+PSA storage save: alg: MD5
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_MD5:0x0000:"4b":"505341004b455900000000000100000001100800010000000300000200000000010000004b"
+
+PSA storage save: alg2: MD5
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_MD5:"4c":"505341004b455900000000000100000001100800010000000000000003000002010000004c"
+
+PSA storage save: alg: OFB
+depends_on:PSA_WANT_ALG_OFB:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_OFB:0x0000:"4b":"505341004b455900000000000100000001100800010000000012c00400000000010000004b"
+
+PSA storage save: alg2: OFB
+depends_on:PSA_WANT_ALG_OFB:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_OFB:"4c":"505341004b45590000000000010000000110080001000000000000000012c004010000004c"
+
+PSA storage save: alg: PURE_EDDSA
+depends_on:PSA_WANT_ALG_PURE_EDDSA:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_PURE_EDDSA:0x0000:"4b":"505341004b455900000000000100000001100800010000000008000600000000010000004b"
+
+PSA storage save: alg2: PURE_EDDSA
+depends_on:PSA_WANT_ALG_PURE_EDDSA:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_PURE_EDDSA:"4c":"505341004b455900000000000100000001100800010000000000000000080006010000004c"
+
+PSA storage save: alg: RIPEMD160
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RIPEMD160:0x0000:"4b":"505341004b455900000000000100000001100800010000000400000200000000010000004b"
+
+PSA storage save: alg2: RIPEMD160
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RIPEMD160:"4c":"505341004b455900000000000100000001100800010000000000000004000002010000004c"
+
+PSA storage save: alg: RSA_OAEP(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000103000700000000010000004b"
+
+PSA storage save: alg2: RSA_OAEP(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001030007010000004c"
+
+PSA storage save: alg: RSA_OAEP(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000203000700000000010000004b"
+
+PSA storage save: alg2: RSA_OAEP(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002030007010000004c"
+
+PSA storage save: alg: RSA_OAEP(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000303000700000000010000004b"
+
+PSA storage save: alg2: RSA_OAEP(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003030007010000004c"
+
+PSA storage save: alg: RSA_OAEP(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000403000700000000010000004b"
+
+PSA storage save: alg2: RSA_OAEP(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004030007010000004c"
+
+PSA storage save: alg: RSA_OAEP(SHA_1)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000503000700000000010000004b"
+
+PSA storage save: alg2: RSA_OAEP(SHA_1)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005030007010000004c"
+
+PSA storage save: alg: RSA_OAEP(SHA_224)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000803000700000000010000004b"
+
+PSA storage save: alg2: RSA_OAEP(SHA_224)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008030007010000004c"
+
+PSA storage save: alg: RSA_OAEP(SHA_256)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000903000700000000010000004b"
+
+PSA storage save: alg2: RSA_OAEP(SHA_256)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009030007010000004c"
+
+PSA storage save: alg: RSA_OAEP(SHA_384)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a03000700000000010000004b"
+
+PSA storage save: alg2: RSA_OAEP(SHA_384)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a030007010000004c"
+
+PSA storage save: alg: RSA_OAEP(SHA_512)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b03000700000000010000004b"
+
+PSA storage save: alg2: RSA_OAEP(SHA_512)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b030007010000004c"
+
+PSA storage save: alg: RSA_PKCS1V15_CRYPT
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_CRYPT:0x0000:"4b":"505341004b455900000000000100000001100800010000000002000700000000010000004b"
+
+PSA storage save: alg2: RSA_PKCS1V15_CRYPT
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_CRYPT:"4c":"505341004b455900000000000100000001100800010000000000000000020007010000004c"
+
+PSA storage save: alg: RSA_PKCS1V15_SIGN(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000102000600000000010000004b"
+
+PSA storage save: alg2: RSA_PKCS1V15_SIGN(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001020006010000004c"
+
+PSA storage save: alg: RSA_PKCS1V15_SIGN(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000202000600000000010000004b"
+
+PSA storage save: alg2: RSA_PKCS1V15_SIGN(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002020006010000004c"
+
+PSA storage save: alg: RSA_PKCS1V15_SIGN(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000302000600000000010000004b"
+
+PSA storage save: alg2: RSA_PKCS1V15_SIGN(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003020006010000004c"
+
+PSA storage save: alg: RSA_PKCS1V15_SIGN(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000402000600000000010000004b"
+
+PSA storage save: alg2: RSA_PKCS1V15_SIGN(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004020006010000004c"
+
+PSA storage save: alg: RSA_PKCS1V15_SIGN(SHA_1)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000502000600000000010000004b"
+
+PSA storage save: alg2: RSA_PKCS1V15_SIGN(SHA_1)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005020006010000004c"
+
+PSA storage save: alg: RSA_PKCS1V15_SIGN(SHA_224)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000802000600000000010000004b"
+
+PSA storage save: alg2: RSA_PKCS1V15_SIGN(SHA_224)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008020006010000004c"
+
+PSA storage save: alg: RSA_PKCS1V15_SIGN(SHA_256)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000902000600000000010000004b"
+
+PSA storage save: alg2: RSA_PKCS1V15_SIGN(SHA_256)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009020006010000004c"
+
+PSA storage save: alg: RSA_PKCS1V15_SIGN(SHA_384)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a02000600000000010000004b"
+
+PSA storage save: alg2: RSA_PKCS1V15_SIGN(SHA_384)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a020006010000004c"
+
+PSA storage save: alg: RSA_PKCS1V15_SIGN(SHA_512)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b02000600000000010000004b"
+
+PSA storage save: alg2: RSA_PKCS1V15_SIGN(SHA_512)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b020006010000004c"
+
+PSA storage save: alg: RSA_PKCS1V15_SIGN(ANY_HASH)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):0x0000:"4b":"505341004b45590000000000010000000110080001000000ff02000600000000010000004b"
+
+PSA storage save: alg2: RSA_PKCS1V15_SIGN(ANY_HASH)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):"4c":"505341004b4559000000000001000000011008000100000000000000ff020006010000004c"
+
+PSA storage save: alg: RSA_PKCS1V15_SIGN_RAW
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0x0000:"4b":"505341004b455900000000000100000001100800010000000002000600000000010000004b"
+
+PSA storage save: alg2: RSA_PKCS1V15_SIGN_RAW
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"4c":"505341004b455900000000000100000001100800010000000000000000020006010000004c"
+
+PSA storage save: alg: RSA_PSS(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000103000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001030006010000004c"
+
+PSA storage save: alg: RSA_PSS(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000203000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002030006010000004c"
+
+PSA storage save: alg: RSA_PSS(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000303000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003030006010000004c"
+
+PSA storage save: alg: RSA_PSS(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000403000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004030006010000004c"
+
+PSA storage save: alg: RSA_PSS(SHA_1)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000503000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS(SHA_1)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005030006010000004c"
+
+PSA storage save: alg: RSA_PSS(SHA_224)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000803000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS(SHA_224)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008030006010000004c"
+
+PSA storage save: alg: RSA_PSS(SHA_256)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000903000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS(SHA_256)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009030006010000004c"
+
+PSA storage save: alg: RSA_PSS(SHA_384)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a03000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS(SHA_384)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a030006010000004c"
+
+PSA storage save: alg: RSA_PSS(SHA_512)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b03000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS(SHA_512)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b030006010000004c"
+
+PSA storage save: alg: RSA_PSS(ANY_HASH)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):0x0000:"4b":"505341004b45590000000000010000000110080001000000ff03000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS(ANY_HASH)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):"4c":"505341004b4559000000000001000000011008000100000000000000ff030006010000004c"
+
+PSA storage save: alg: RSA_PSS_ANY_SALT(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000113000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS_ANY_SALT(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001130006010000004c"
+
+PSA storage save: alg: RSA_PSS_ANY_SALT(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000213000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS_ANY_SALT(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002130006010000004c"
+
+PSA storage save: alg: RSA_PSS_ANY_SALT(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000313000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS_ANY_SALT(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003130006010000004c"
+
+PSA storage save: alg: RSA_PSS_ANY_SALT(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000413000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS_ANY_SALT(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004130006010000004c"
+
+PSA storage save: alg: RSA_PSS_ANY_SALT(SHA_1)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000513000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS_ANY_SALT(SHA_1)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005130006010000004c"
+
+PSA storage save: alg: RSA_PSS_ANY_SALT(SHA_224)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000813000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS_ANY_SALT(SHA_224)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008130006010000004c"
+
+PSA storage save: alg: RSA_PSS_ANY_SALT(SHA_256)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000913000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS_ANY_SALT(SHA_256)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009130006010000004c"
+
+PSA storage save: alg: RSA_PSS_ANY_SALT(SHA_384)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a13000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS_ANY_SALT(SHA_384)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a130006010000004c"
+
+PSA storage save: alg: RSA_PSS_ANY_SALT(SHA_512)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b13000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS_ANY_SALT(SHA_512)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b130006010000004c"
+
+PSA storage save: alg: RSA_PSS_ANY_SALT(ANY_HASH)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH):0x0000:"4b":"505341004b45590000000000010000000110080001000000ff13000600000000010000004b"
+
+PSA storage save: alg2: RSA_PSS_ANY_SALT(ANY_HASH)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH):"4c":"505341004b4559000000000001000000011008000100000000000000ff130006010000004c"
+
+PSA storage save: alg: SHA3_224
+depends_on:PSA_WANT_ALG_SHA3_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA3_224:0x0000:"4b":"505341004b455900000000000100000001100800010000001000000200000000010000004b"
+
+PSA storage save: alg2: SHA3_224
+depends_on:PSA_WANT_ALG_SHA3_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA3_224:"4c":"505341004b455900000000000100000001100800010000000000000010000002010000004c"
+
+PSA storage save: alg: SHA3_256
+depends_on:PSA_WANT_ALG_SHA3_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA3_256:0x0000:"4b":"505341004b455900000000000100000001100800010000001100000200000000010000004b"
+
+PSA storage save: alg2: SHA3_256
+depends_on:PSA_WANT_ALG_SHA3_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA3_256:"4c":"505341004b455900000000000100000001100800010000000000000011000002010000004c"
+
+PSA storage save: alg: SHA3_384
+depends_on:PSA_WANT_ALG_SHA3_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA3_384:0x0000:"4b":"505341004b455900000000000100000001100800010000001200000200000000010000004b"
+
+PSA storage save: alg2: SHA3_384
+depends_on:PSA_WANT_ALG_SHA3_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA3_384:"4c":"505341004b455900000000000100000001100800010000000000000012000002010000004c"
+
+PSA storage save: alg: SHA3_512
+depends_on:PSA_WANT_ALG_SHA3_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA3_512:0x0000:"4b":"505341004b455900000000000100000001100800010000001300000200000000010000004b"
+
+PSA storage save: alg2: SHA3_512
+depends_on:PSA_WANT_ALG_SHA3_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA3_512:"4c":"505341004b455900000000000100000001100800010000000000000013000002010000004c"
+
+PSA storage save: alg: SHAKE256_512
+depends_on:PSA_WANT_ALG_SHAKE256_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHAKE256_512:0x0000:"4b":"505341004b455900000000000100000001100800010000001500000200000000010000004b"
+
+PSA storage save: alg2: SHAKE256_512
+depends_on:PSA_WANT_ALG_SHAKE256_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHAKE256_512:"4c":"505341004b455900000000000100000001100800010000000000000015000002010000004c"
+
+PSA storage save: alg: SHA_1
+depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA_1:0x0000:"4b":"505341004b455900000000000100000001100800010000000500000200000000010000004b"
+
+PSA storage save: alg2: SHA_1
+depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA_1:"4c":"505341004b455900000000000100000001100800010000000000000005000002010000004c"
+
+PSA storage save: alg: SHA_224
+depends_on:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA_224:0x0000:"4b":"505341004b455900000000000100000001100800010000000800000200000000010000004b"
+
+PSA storage save: alg2: SHA_224
+depends_on:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA_224:"4c":"505341004b455900000000000100000001100800010000000000000008000002010000004c"
+
+PSA storage save: alg: SHA_256
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA_256:0x0000:"4b":"505341004b455900000000000100000001100800010000000900000200000000010000004b"
+
+PSA storage save: alg2: SHA_256
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA_256:"4c":"505341004b455900000000000100000001100800010000000000000009000002010000004c"
+
+PSA storage save: alg: SHA_384
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA_384:0x0000:"4b":"505341004b455900000000000100000001100800010000000a00000200000000010000004b"
+
+PSA storage save: alg2: SHA_384
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA_384:"4c":"505341004b45590000000000010000000110080001000000000000000a000002010000004c"
+
+PSA storage save: alg: SHA_512
+depends_on:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA_512:0x0000:"4b":"505341004b455900000000000100000001100800010000000b00000200000000010000004b"
+
+PSA storage save: alg2: SHA_512
+depends_on:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA_512:"4c":"505341004b45590000000000010000000110080001000000000000000b000002010000004c"
+
+PSA storage save: alg: SHA_512_224
+depends_on:PSA_WANT_ALG_SHA_512_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA_512_224:0x0000:"4b":"505341004b455900000000000100000001100800010000000c00000200000000010000004b"
+
+PSA storage save: alg2: SHA_512_224
+depends_on:PSA_WANT_ALG_SHA_512_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA_512_224:"4c":"505341004b45590000000000010000000110080001000000000000000c000002010000004c"
+
+PSA storage save: alg: SHA_512_256
+depends_on:PSA_WANT_ALG_SHA_512_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA_512_256:0x0000:"4b":"505341004b455900000000000100000001100800010000000d00000200000000010000004b"
+
+PSA storage save: alg2: SHA_512_256
+depends_on:PSA_WANT_ALG_SHA_512_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA_512_256:"4c":"505341004b45590000000000010000000110080001000000000000000d000002010000004c"
+
+PSA storage save: alg: STREAM_CIPHER
+depends_on:PSA_WANT_ALG_STREAM_CIPHER:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_STREAM_CIPHER:0x0000:"4b":"505341004b455900000000000100000001100800010000000001800400000000010000004b"
+
+PSA storage save: alg2: STREAM_CIPHER
+depends_on:PSA_WANT_ALG_STREAM_CIPHER:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_STREAM_CIPHER:"4c":"505341004b455900000000000100000001100800010000000000000000018004010000004c"
+
+PSA storage save: alg: TLS12_PRF(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000102000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PRF(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001020008010000004c"
+
+PSA storage save: alg: TLS12_PRF(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000202000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PRF(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002020008010000004c"
+
+PSA storage save: alg: TLS12_PRF(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000302000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PRF(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003020008010000004c"
+
+PSA storage save: alg: TLS12_PRF(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000402000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PRF(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004020008010000004c"
+
+PSA storage save: alg: TLS12_PRF(SHA_1)
+depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000502000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PRF(SHA_1)
+depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005020008010000004c"
+
+PSA storage save: alg: TLS12_PRF(SHA_224)
+depends_on:PSA_WANT_ALG_SHA_224:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000802000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PRF(SHA_224)
+depends_on:PSA_WANT_ALG_SHA_224:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008020008010000004c"
+
+PSA storage save: alg: TLS12_PRF(SHA_256)
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000902000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PRF(SHA_256)
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009020008010000004c"
+
+PSA storage save: alg: TLS12_PRF(SHA_384)
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a02000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PRF(SHA_384)
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a020008010000004c"
+
+PSA storage save: alg: TLS12_PRF(SHA_512)
+depends_on:PSA_WANT_ALG_SHA_512:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b02000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PRF(SHA_512)
+depends_on:PSA_WANT_ALG_SHA_512:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b020008010000004c"
+
+PSA storage save: alg: TLS12_PSK_TO_MS(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000103000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PSK_TO_MS(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001030008010000004c"
+
+PSA storage save: alg: TLS12_PSK_TO_MS(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000203000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PSK_TO_MS(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002030008010000004c"
+
+PSA storage save: alg: TLS12_PSK_TO_MS(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000303000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PSK_TO_MS(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003030008010000004c"
+
+PSA storage save: alg: TLS12_PSK_TO_MS(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000403000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PSK_TO_MS(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004030008010000004c"
+
+PSA storage save: alg: TLS12_PSK_TO_MS(SHA_1)
+depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000503000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PSK_TO_MS(SHA_1)
+depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005030008010000004c"
+
+PSA storage save: alg: TLS12_PSK_TO_MS(SHA_224)
+depends_on:PSA_WANT_ALG_SHA_224:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000803000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PSK_TO_MS(SHA_224)
+depends_on:PSA_WANT_ALG_SHA_224:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008030008010000004c"
+
+PSA storage save: alg: TLS12_PSK_TO_MS(SHA_256)
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000903000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PSK_TO_MS(SHA_256)
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009030008010000004c"
+
+PSA storage save: alg: TLS12_PSK_TO_MS(SHA_384)
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a03000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PSK_TO_MS(SHA_384)
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a030008010000004c"
+
+PSA storage save: alg: TLS12_PSK_TO_MS(SHA_512)
+depends_on:PSA_WANT_ALG_SHA_512:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b03000800000000010000004b"
+
+PSA storage save: alg2: TLS12_PSK_TO_MS(SHA_512)
+depends_on:PSA_WANT_ALG_SHA_512:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b030008010000004c"
+
+PSA storage save: alg: TRUNCATED_MAC(CBC_MAC, 1)
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_CBC_MAC, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000001c10300000000010000004b"
+
+PSA storage save: alg2: TRUNCATED_MAC(CBC_MAC, 1)
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_CBC_MAC, 1):"4c":"505341004b45590000000000010000000110080001000000000000000001c103010000004c"
+
+PSA storage save: alg: TRUNCATED_MAC(CMAC, 1)
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000002c10300000000010000004b"
+
+PSA storage save: alg2: TRUNCATED_MAC(CMAC, 1)
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, 1):"4c":"505341004b45590000000000010000000110080001000000000000000002c103010000004c"
+
+PSA storage save: alg: TRUNCATED_MAC(HMAC(MD2), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_MD2), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000100810300000000010000004b"
+
+PSA storage save: alg2: TRUNCATED_MAC(HMAC(MD2), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_MD2), 1):"4c":"505341004b455900000000000100000001100800010000000000000001008103010000004c"
+
+PSA storage save: alg: TRUNCATED_MAC(HMAC(MD4), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_MD4), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000200810300000000010000004b"
+
+PSA storage save: alg2: TRUNCATED_MAC(HMAC(MD4), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_MD4), 1):"4c":"505341004b455900000000000100000001100800010000000000000002008103010000004c"
+
+PSA storage save: alg: TRUNCATED_MAC(HMAC(MD5), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_MD5), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000300810300000000010000004b"
+
+PSA storage save: alg2: TRUNCATED_MAC(HMAC(MD5), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_MD5), 1):"4c":"505341004b455900000000000100000001100800010000000000000003008103010000004c"
+
+PSA storage save: alg: TRUNCATED_MAC(HMAC(RIPEMD160), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_RIPEMD160), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000400810300000000010000004b"
+
+PSA storage save: alg2: TRUNCATED_MAC(HMAC(RIPEMD160), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_RIPEMD160), 1):"4c":"505341004b455900000000000100000001100800010000000000000004008103010000004c"
+
+PSA storage save: alg: TRUNCATED_MAC(HMAC(SHA_1), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_1), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000500810300000000010000004b"
+
+PSA storage save: alg2: TRUNCATED_MAC(HMAC(SHA_1), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_1), 1):"4c":"505341004b455900000000000100000001100800010000000000000005008103010000004c"
+
+PSA storage save: alg: TRUNCATED_MAC(HMAC(SHA_224), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_224), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000800810300000000010000004b"
+
+PSA storage save: alg2: TRUNCATED_MAC(HMAC(SHA_224), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_224), 1):"4c":"505341004b455900000000000100000001100800010000000000000008008103010000004c"
+
+PSA storage save: alg: TRUNCATED_MAC(HMAC(SHA_256), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000900810300000000010000004b"
+
+PSA storage save: alg2: TRUNCATED_MAC(HMAC(SHA_256), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 1):"4c":"505341004b455900000000000100000001100800010000000000000009008103010000004c"
+
+PSA storage save: alg: TRUNCATED_MAC(HMAC(SHA_384), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_384), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000a00810300000000010000004b"
+
+PSA storage save: alg2: TRUNCATED_MAC(HMAC(SHA_384), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_384), 1):"4c":"505341004b45590000000000010000000110080001000000000000000a008103010000004c"
+
+PSA storage save: alg: TRUNCATED_MAC(HMAC(SHA_512), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_512), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000b00810300000000010000004b"
+
+PSA storage save: alg2: TRUNCATED_MAC(HMAC(SHA_512), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_512), 1):"4c":"505341004b45590000000000010000000110080001000000000000000b008103010000004c"
+
+PSA storage save: alg: TRUNCATED_MAC(CBC_MAC, 63)
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_CBC_MAC, 63):0x0000:"4b":"505341004b455900000000000100000001100800010000000001ff0300000000010000004b"
+
+PSA storage save: alg2: TRUNCATED_MAC(CBC_MAC, 63)
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_CBC_MAC, 63):"4c":"505341004b45590000000000010000000110080001000000000000000001ff03010000004c"
+
+PSA storage save: alg: XTS
+depends_on:PSA_WANT_ALG_XTS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_XTS:0x0000:"4b":"505341004b4559000000000001000000011008000100000000ff400400000000010000004b"
+
+PSA storage save: alg2: XTS
+depends_on:PSA_WANT_ALG_XTS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_save:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_XTS:"4c":"505341004b455900000000000100000001100800010000000000000000ff4004010000004c"
+
+# End of automatically generated file.
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_storage_format.function b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_storage_format.function
new file mode 100644
index 0000000..b90ef6e
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_storage_format.function
@@ -0,0 +1,235 @@
+/* BEGIN_HEADER */
+
+#include <psa/crypto.h>
+
+#include <test/psa_crypto_helpers.h>
+#include <test/psa_exercise_key.h>
+
+#include <psa_crypto_its.h>
+
+#define TEST_FLAG_EXERCISE      0x00000001
+#define TEST_FLAG_READ_ONLY     0x00000002
+
+/** Write a key with the given attributes and key material to storage.
+ * Test that it has the expected representation.
+ *
+ * On error, including if the key representation in storage differs,
+ * mark the test case as failed and return 0. On success, return 1.
+ */
+static int test_written_key( const psa_key_attributes_t *attributes,
+                             const data_t *material,
+                             psa_storage_uid_t uid,
+                             const data_t *expected_representation )
+{
+    mbedtls_svc_key_id_t created_key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    uint8_t *actual_representation = NULL;
+    size_t length;
+    struct psa_storage_info_t storage_info;
+    int ok = 0;
+
+    /* Create a key with the given parameters. */
+    PSA_ASSERT( psa_import_key( attributes, material->x, material->len,
+                                &created_key_id ) );
+    TEST_ASSERT( mbedtls_svc_key_id_equal( psa_get_key_id( attributes ),
+                                           created_key_id ) );
+
+    /* Check that the key is represented as expected. */
+    PSA_ASSERT( psa_its_get_info( uid, &storage_info ) );
+    TEST_EQUAL( storage_info.size, expected_representation->len );
+    ASSERT_ALLOC( actual_representation, storage_info.size );
+    PSA_ASSERT( psa_its_get( uid, 0, storage_info.size,
+                             actual_representation, &length ) );
+    ASSERT_COMPARE( expected_representation->x, expected_representation->len,
+                    actual_representation, length );
+
+    ok = 1;
+
+exit:
+    mbedtls_free( actual_representation );
+    return( ok );
+}
+
+/** Check if a key is exportable. */
+static int can_export( const psa_key_attributes_t *attributes )
+{
+    if( psa_get_key_usage_flags( attributes ) & PSA_KEY_USAGE_EXPORT )
+        return( 1 );
+    else if( PSA_KEY_TYPE_IS_PUBLIC_KEY( psa_get_key_type( attributes ) ) )
+        return( 1 );
+    else
+        return( 0 );
+}
+
+/** Write a key with the given representation to storage, then check
+ * that it has the given attributes and (if exportable) key material.
+ *
+ * On error, including if the key representation in storage differs,
+ * mark the test case as failed and return 0. On success, return 1.
+ */
+static int test_read_key( const psa_key_attributes_t *expected_attributes,
+                          const data_t *expected_material,
+                          psa_storage_uid_t uid,
+                          const data_t *representation,
+                          int flags )
+{
+    psa_key_attributes_t actual_attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t key_id = psa_get_key_id( expected_attributes );
+    struct psa_storage_info_t storage_info;
+    int ok = 0;
+    uint8_t *exported_material = NULL;
+    size_t length;
+
+    /* Prime the storage with a key file. */
+    PSA_ASSERT( psa_its_set( uid, representation->len, representation->x, 0 ) );
+
+    /* Check that the injected key exists and looks as expected. */
+    PSA_ASSERT( psa_get_key_attributes( key_id, &actual_attributes ) );
+    TEST_ASSERT( mbedtls_svc_key_id_equal( key_id,
+                                           psa_get_key_id( &actual_attributes ) ) );
+    TEST_EQUAL( psa_get_key_lifetime( expected_attributes ),
+                psa_get_key_lifetime( &actual_attributes ) );
+    TEST_EQUAL( psa_get_key_type( expected_attributes ),
+                psa_get_key_type( &actual_attributes ) );
+    TEST_EQUAL( psa_get_key_bits( expected_attributes ),
+                psa_get_key_bits( &actual_attributes ) );
+    TEST_EQUAL( psa_get_key_usage_flags( expected_attributes ),
+                psa_get_key_usage_flags( &actual_attributes ) );
+    TEST_EQUAL( psa_get_key_algorithm( expected_attributes ),
+                psa_get_key_algorithm( &actual_attributes ) );
+    TEST_EQUAL( psa_get_key_enrollment_algorithm( expected_attributes ),
+                psa_get_key_enrollment_algorithm( &actual_attributes ) );
+    if( can_export( expected_attributes ) )
+    {
+        ASSERT_ALLOC( exported_material, expected_material->len );
+        PSA_ASSERT( psa_export_key( key_id,
+                                    exported_material, expected_material->len,
+                                    &length ) );
+        ASSERT_COMPARE( expected_material->x, expected_material->len,
+                        exported_material, length );
+    }
+
+    if( flags & TEST_FLAG_EXERCISE )
+    {
+        TEST_ASSERT( mbedtls_test_psa_exercise_key(
+                         key_id,
+                         psa_get_key_usage_flags( expected_attributes ),
+                         psa_get_key_algorithm( expected_attributes ) ) );
+    }
+
+
+    if( flags & TEST_FLAG_READ_ONLY )
+    {
+        /* Read-only keys cannot be removed through the API.
+         * The key will be removed through ITS in the cleanup code below. */
+        TEST_EQUAL( PSA_ERROR_NOT_PERMITTED, psa_destroy_key( key_id ) );
+    }
+    else
+    {
+        /* Destroy the key. Confirm through direct access to the storage. */
+        PSA_ASSERT( psa_destroy_key( key_id ) );
+        TEST_EQUAL( PSA_ERROR_DOES_NOT_EXIST,
+                    psa_its_get_info( uid, &storage_info ) );
+    }
+
+    ok = 1;
+
+exit:
+    psa_reset_key_attributes( &actual_attributes );
+    psa_its_remove( uid );
+    mbedtls_free( exported_material );
+    return( ok );
+}
+
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void key_storage_save( int lifetime_arg, int type_arg, int bits_arg,
+                       int usage_arg, int alg_arg, int alg2_arg,
+                       data_t *material,
+                       data_t *representation )
+{
+    /* Forward compatibility: save a key in the current format and
+     * check that it has the expected format so that future versions
+     * will still be able to read it. */
+
+    psa_key_lifetime_t lifetime = lifetime_arg;
+    psa_key_type_t type = type_arg;
+    size_t bits = bits_arg;
+    psa_key_usage_t usage = usage_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_algorithm_t alg2 = alg2_arg;
+    mbedtls_svc_key_id_t key_id = mbedtls_svc_key_id_make( 0, 1 );
+    psa_storage_uid_t uid = 1;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    PSA_INIT( );
+    TEST_USES_KEY_ID( key_id );
+
+    psa_set_key_lifetime( &attributes, lifetime );
+    psa_set_key_id( &attributes, key_id );
+    psa_set_key_type( &attributes, type );
+    psa_set_key_bits( &attributes, bits );
+    psa_set_key_usage_flags( &attributes, usage );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_enrollment_algorithm( &attributes, alg2 );
+
+    /* This is the current storage format. Test that we know exactly how
+     * the key is stored. The stability of the test data in future
+     * versions of Mbed TLS will guarantee that future versions
+     * can read back what this version wrote. */
+    TEST_ASSERT( test_written_key( &attributes, material,
+                                   uid, representation ) );
+
+exit:
+    psa_reset_key_attributes( &attributes );
+    psa_destroy_key( key_id );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void key_storage_read( int lifetime_arg, int type_arg, int bits_arg,
+                       int usage_arg, int alg_arg, int alg2_arg,
+                       data_t *material,
+                       data_t *representation, int flags )
+{
+    /* Backward compatibility: read a key in the format of a past version
+     * and check that this version can use it. */
+
+    psa_key_lifetime_t lifetime = lifetime_arg;
+    psa_key_type_t type = type_arg;
+    size_t bits = bits_arg;
+    psa_key_usage_t usage = usage_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_algorithm_t alg2 = alg2_arg;
+    mbedtls_svc_key_id_t key_id = mbedtls_svc_key_id_make( 0, 1 );
+    psa_storage_uid_t uid = 1;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    PSA_INIT( );
+    TEST_USES_KEY_ID( key_id );
+
+    psa_set_key_lifetime( &attributes, lifetime );
+    psa_set_key_id( &attributes, key_id );
+    psa_set_key_type( &attributes, type );
+    psa_set_key_bits( &attributes, bits );
+    psa_set_key_usage_flags( &attributes, usage );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_enrollment_algorithm( &attributes, alg2 );
+
+    /* Test that we can use a key with the given representation. This
+     * guarantees backward compatibility with keys that were stored by
+     * past versions of Mbed TLS. */
+    TEST_ASSERT( test_read_key( &attributes, material,
+                                uid, representation, flags ) );
+
+exit:
+    psa_reset_key_attributes( &attributes );
+    PSA_DONE( );
+}
+/* END_CASE */
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_storage_format.misc.data b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_storage_format.misc.data
new file mode 100644
index 0000000..48e3804
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_storage_format.misc.data
@@ -0,0 +1,11 @@
+# The following two manually crafted test cases are redundant with
+# systematically generated test cases, but useful to have as an anchor when
+# debugging changes to the test code or to the test case generation.
+
+PSA storage read: AES-GCM+CTR
+depends_on:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_GCM:PSA_WANT_ALG_CTR
+key_storage_read:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_GCM:PSA_ALG_CTR:"404142434445464748494a4b4c4d4e4f":"505341004b45590000000000010000000024800001010000000250050010c00410000000404142434445464748494a4b4c4d4e4f":1
+
+PSA storage save: AES-GCM+CTR
+depends_on:PSA_WANT_KEY_TYPE_AES
+key_storage_save:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_GCM:PSA_ALG_CTR:"404142434445464748494a4b4c4d4e4f":"505341004b45590000000000010000000024800001010000000250050010c00410000000404142434445464748494a4b4c4d4e4f"
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_storage_format.v0.data b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_storage_format.v0.data
new file mode 100644
index 0000000..c6be0a9
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_crypto_storage_format.v0.data
@@ -0,0 +1,2331 @@
+# Automatically generated by generate_psa_tests.py. Do not edit!
+
+PSA storage read: lifetime: (DEFAULT, LOCAL_STORAGE)
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_DEFAULT, PSA_KEY_LOCATION_LOCAL_STORAGE):PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"4c":"505341004b455900000000000100000001100800010000000000000000000000010000004c":0
+
+PSA storage read: lifetime: (READ_ONLY, LOCAL_STORAGE)
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_READ_ONLY, PSA_KEY_LOCATION_LOCAL_STORAGE):PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"4c":"505341004b45590000000000ff00000001100800010000000000000000000000010000004c":TEST_FLAG_READ_ONLY
+
+PSA storage read: lifetime: (2, LOCAL_STORAGE)
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(2, PSA_KEY_LOCATION_LOCAL_STORAGE):PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"4c":"505341004b455900000000000200000001100800010000000000000000000000010000004c":0
+
+PSA storage read: lifetime: (254, LOCAL_STORAGE)
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(254, PSA_KEY_LOCATION_LOCAL_STORAGE):PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"4c":"505341004b45590000000000fe00000001100800010000000000000000000000010000004c":0
+
+PSA storage read: lifetime: PERSISTENT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"4c":"505341004b455900000000000100000001100800010000000000000000000000010000004c":0
+
+PSA storage read: usage with implication: 0
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:0:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800000000000000000000000000010000004b":0
+
+PSA storage read: usage without implication: 0
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:0:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800000000000000000000000000010000004b":0
+
+PSA storage read: usage with implication: COPY
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_COPY:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800020000000000000000000000010000004b":0
+
+PSA storage read: usage without implication: COPY
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_COPY:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800020000000000000000000000010000004b":0
+
+PSA storage read: usage with implication: DECRYPT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_DECRYPT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800000200000000000000000000010000004b":0
+
+PSA storage read: usage without implication: DECRYPT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_DECRYPT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800000200000000000000000000010000004b":0
+
+PSA storage read: usage with implication: DERIVE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_DERIVE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800004000000000000000000000010000004b":0
+
+PSA storage read: usage without implication: DERIVE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_DERIVE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800004000000000000000000000010000004b":0
+
+PSA storage read: usage with implication: ENCRYPT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_ENCRYPT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800000100000000000000000000010000004b":0
+
+PSA storage read: usage without implication: ENCRYPT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_ENCRYPT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800000100000000000000000000010000004b":0
+
+PSA storage read: usage with implication: EXPORT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800010000000000000000000000010000004b":0
+
+PSA storage read: usage without implication: EXPORT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800010000000000000000000000010000004b":0
+
+PSA storage read: usage with implication: SIGN_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800001400000000000000000000010000004b":0
+
+PSA storage read: usage without implication: SIGN_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800001000000000000000000000010000004b":0
+
+PSA storage read: usage with implication: SIGN_MESSAGE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_MESSAGE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800000400000000000000000000010000004b":0
+
+PSA storage read: usage without implication: SIGN_MESSAGE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_MESSAGE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800000400000000000000000000010000004b":0
+
+PSA storage read: usage with implication: VERIFY_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800002800000000000000000000010000004b":0
+
+PSA storage read: usage without implication: VERIFY_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800002000000000000000000000010000004b":0
+
+PSA storage read: usage with implication: VERIFY_MESSAGE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_MESSAGE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800000800000000000000000000010000004b":0
+
+PSA storage read: usage without implication: VERIFY_MESSAGE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_MESSAGE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800000800000000000000000000010000004b":0
+
+PSA storage read: usage with implication: COPY | DECRYPT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800020200000000000000000000010000004b":0
+
+PSA storage read: usage without implication: COPY | DECRYPT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800020200000000000000000000010000004b":0
+
+PSA storage read: usage with implication: DECRYPT | DERIVE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_DERIVE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800004200000000000000000000010000004b":0
+
+PSA storage read: usage without implication: DECRYPT | DERIVE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_DERIVE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800004200000000000000000000010000004b":0
+
+PSA storage read: usage with implication: DERIVE | ENCRYPT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_ENCRYPT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800004100000000000000000000010000004b":0
+
+PSA storage read: usage without implication: DERIVE | ENCRYPT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_ENCRYPT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800004100000000000000000000010000004b":0
+
+PSA storage read: usage with implication: ENCRYPT | EXPORT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800010100000000000000000000010000004b":0
+
+PSA storage read: usage without implication: ENCRYPT | EXPORT
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800010100000000000000000000010000004b":0
+
+PSA storage read: usage with implication: EXPORT | SIGN_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800011400000000000000000000010000004b":0
+
+PSA storage read: usage without implication: EXPORT | SIGN_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800011000000000000000000000010000004b":0
+
+PSA storage read: usage with implication: SIGN_HASH | SIGN_MESSAGE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800001400000000000000000000010000004b":0
+
+PSA storage read: usage without implication: SIGN_HASH | SIGN_MESSAGE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800001400000000000000000000010000004b":0
+
+PSA storage read: usage with implication: SIGN_MESSAGE | VERIFY_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800002c00000000000000000000010000004b":0
+
+PSA storage read: usage without implication: SIGN_MESSAGE | VERIFY_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800002400000000000000000000010000004b":0
+
+PSA storage read: usage with implication: VERIFY_HASH | VERIFY_MESSAGE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800002800000000000000000000010000004b":0
+
+PSA storage read: usage without implication: VERIFY_HASH | VERIFY_MESSAGE
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800002800000000000000000000010000004b":0
+
+PSA storage read: usage with implication: VERIFY_MESSAGE | COPY
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800020800000000000000000000010000004b":0
+
+PSA storage read: usage without implication: VERIFY_MESSAGE | COPY
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800020800000000000000000000010000004b":0
+
+PSA storage read: usage: all known
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:0x0000:0x0000:"4b":"505341004b455900000000000100000001100800037f00000000000000000000010000004b":0
+
+PSA storage read: type: AES 128-bit
+depends_on:PSA_WANT_KEY_TYPE_AES
+key_storage_read:0x0001:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000002480000100000000000000000000001000000048657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: type: AES 192-bit
+depends_on:PSA_WANT_KEY_TYPE_AES
+key_storage_read:0x0001:PSA_KEY_TYPE_AES:192:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a0646174614865726500697320":"505341004b45590000000000010000000024c0000100000000000000000000001800000048657265006973206b6579a0646174614865726500697320":TEST_FLAG_EXERCISE
+
+PSA storage read: type: AES 256-bit
+depends_on:PSA_WANT_KEY_TYPE_AES
+key_storage_read:0x0001:PSA_KEY_TYPE_AES:256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000002400010100000000000000000000002000000048657265006973206b6579a06461746148657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ARC4 8-bit
+depends_on:PSA_WANT_KEY_TYPE_ARC4
+key_storage_read:0x0001:PSA_KEY_TYPE_ARC4:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48":"505341004b4559000000000001000000022008000100000000000000000000000100000048":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ARC4 128-bit
+depends_on:PSA_WANT_KEY_TYPE_ARC4
+key_storage_read:0x0001:PSA_KEY_TYPE_ARC4:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000022080000100000000000000000000001000000048657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ARC4 2048-bit
+depends_on:PSA_WANT_KEY_TYPE_ARC4
+key_storage_read:0x0001:PSA_KEY_TYPE_ARC4:2048:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000022000080100000000000000000000000001000048657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ARIA 128-bit
+depends_on:PSA_WANT_KEY_TYPE_ARIA
+key_storage_read:0x0001:PSA_KEY_TYPE_ARIA:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000062480000100000000000000000000001000000048657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ARIA 192-bit
+depends_on:PSA_WANT_KEY_TYPE_ARIA
+key_storage_read:0x0001:PSA_KEY_TYPE_ARIA:192:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a0646174614865726500697320":"505341004b45590000000000010000000624c0000100000000000000000000001800000048657265006973206b6579a0646174614865726500697320":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ARIA 256-bit
+depends_on:PSA_WANT_KEY_TYPE_ARIA
+key_storage_read:0x0001:PSA_KEY_TYPE_ARIA:256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000062400010100000000000000000000002000000048657265006973206b6579a06461746148657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: type: CAMELLIA 128-bit
+depends_on:PSA_WANT_KEY_TYPE_CAMELLIA
+key_storage_read:0x0001:PSA_KEY_TYPE_CAMELLIA:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000032480000100000000000000000000001000000048657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: type: CAMELLIA 192-bit
+depends_on:PSA_WANT_KEY_TYPE_CAMELLIA
+key_storage_read:0x0001:PSA_KEY_TYPE_CAMELLIA:192:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a0646174614865726500697320":"505341004b45590000000000010000000324c0000100000000000000000000001800000048657265006973206b6579a0646174614865726500697320":TEST_FLAG_EXERCISE
+
+PSA storage read: type: CAMELLIA 256-bit
+depends_on:PSA_WANT_KEY_TYPE_CAMELLIA
+key_storage_read:0x0001:PSA_KEY_TYPE_CAMELLIA:256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000032400010100000000000000000000002000000048657265006973206b6579a06461746148657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: type: CHACHA20 256-bit
+depends_on:PSA_WANT_KEY_TYPE_CHACHA20
+key_storage_read:0x0001:PSA_KEY_TYPE_CHACHA20:256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000042000010100000000000000000000002000000048657265006973206b6579a06461746148657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: type: DERIVE 120-bit
+depends_on:PSA_WANT_KEY_TYPE_DERIVE
+key_storage_read:0x0001:PSA_KEY_TYPE_DERIVE:120:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a0646174":"505341004b4559000000000001000000001278000100000000000000000000000f00000048657265006973206b6579a0646174":TEST_FLAG_EXERCISE
+
+PSA storage read: type: DERIVE 128-bit
+depends_on:PSA_WANT_KEY_TYPE_DERIVE
+key_storage_read:0x0001:PSA_KEY_TYPE_DERIVE:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000001280000100000000000000000000001000000048657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: type: DES 64-bit
+depends_on:PSA_WANT_KEY_TYPE_DES
+key_storage_read:0x0001:PSA_KEY_TYPE_DES:64:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"644573206b457901":"505341004b45590000000000010000000123400001000000000000000000000008000000644573206b457901":TEST_FLAG_EXERCISE
+
+PSA storage read: type: DES 128-bit
+depends_on:PSA_WANT_KEY_TYPE_DES
+key_storage_read:0x0001:PSA_KEY_TYPE_DES:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"644573206b457901644573206b457902":"505341004b45590000000000010000000123800001000000000000000000000010000000644573206b457901644573206b457902":TEST_FLAG_EXERCISE
+
+PSA storage read: type: DES 192-bit
+depends_on:PSA_WANT_KEY_TYPE_DES
+key_storage_read:0x0001:PSA_KEY_TYPE_DES:192:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"644573206b457901644573206b457902644573206b457904":"505341004b45590000000000010000000123c00001000000000000000000000018000000644573206b457901644573206b457902644573206b457904":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(BRAINPOOL_P_R1) 160-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_160:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):160:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"69502c4fdaf48d4fa617bdd24498b0406d0eeaac":"505341004b45590000000000010000003071a0000100000000000000000000001400000069502c4fdaf48d4fa617bdd24498b0406d0eeaac":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(BRAINPOOL_P_R1) 192-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_192:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):192:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"1688a2c5fbf4a3c851d76a98c3ec88f445a97996283db59f":"505341004b45590000000000010000003071c000010000000000000000000000180000001688a2c5fbf4a3c851d76a98c3ec88f445a97996283db59f":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(BRAINPOOL_P_R1) 224-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_224:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):224:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"a69835dafeb5da5ab89c59860dddebcfd80b529a99f59b880882923c":"505341004b45590000000000010000003071e0000100000000000000000000001c000000a69835dafeb5da5ab89c59860dddebcfd80b529a99f59b880882923c":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(BRAINPOOL_P_R1) 256-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"2161d6f2db76526fa62c16f356a80f01f32f776784b36aa99799a8b7662080ff":"505341004b455900000000000100000030710001010000000000000000000000200000002161d6f2db76526fa62c16f356a80f01f32f776784b36aa99799a8b7662080ff":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(BRAINPOOL_P_R1) 320-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_320:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):320:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"61b8daa7a6e5aa9fccf1ef504220b2e5a5b8c6dc7475d16d3172d7db0b2778414e4f6e8fa2032ead":"505341004b4559000000000001000000307140010100000000000000000000002800000061b8daa7a6e5aa9fccf1ef504220b2e5a5b8c6dc7475d16d3172d7db0b2778414e4f6e8fa2032ead":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(BRAINPOOL_P_R1) 384-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):384:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"3dd92e750d90d7d39fc1885cd8ad12ea9441f22b9334b4d965202adb1448ce24c5808a85dd9afc229af0a3124f755bcb":"505341004b455900000000000100000030718001010000000000000000000000300000003dd92e750d90d7d39fc1885cd8ad12ea9441f22b9334b4d965202adb1448ce24c5808a85dd9afc229af0a3124f755bcb":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(BRAINPOOL_P_R1) 512-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_512:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):512:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"372c9778f69f726cbca3f4a268f16b4d617d10280d79a6a029cd51879fe1012934dfe5395455337df6906dc7d6d2eea4dbb2065c0228f73b3ed716480e7d71d2":"505341004b45590000000000010000003071000201000000000000000000000040000000372c9778f69f726cbca3f4a268f16b4d617d10280d79a6a029cd51879fe1012934dfe5395455337df6906dc7d6d2eea4dbb2065c0228f73b3ed716480e7d71d2":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(MONTGOMERY) 255-bit
+depends_on:PSA_WANT_ECC_MONTGOMERY_255:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):255:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"70076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c6a":"505341004b45590000000000010000004171ff000100000000000000000000002000000070076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c6a":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(MONTGOMERY) 448-bit
+depends_on:PSA_WANT_ECC_MONTGOMERY_448:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):448:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"e4e49f52686f9ee3b638528f721f1596196ffd0a1cddb64c3f216f06541805cfeb1a286dc78018095cdfec050e8007b5f4908962ba20d6c1":"505341004b45590000000000010000004171c00101000000000000000000000038000000e4e49f52686f9ee3b638528f721f1596196ffd0a1cddb64c3f216f06541805cfeb1a286dc78018095cdfec050e8007b5f4908962ba20d6c1":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECP_K1) 192-bit
+depends_on:PSA_WANT_ECC_SECP_K1_192:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):192:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"297ac1722ccac7589ecb240dc719842538ca974beb79f228":"505341004b45590000000000010000001771c00001000000000000000000000018000000297ac1722ccac7589ecb240dc719842538ca974beb79f228":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECP_K1) 224-bit
+depends_on:PSA_WANT_ECC_SECP_K1_224:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):224:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0024122bf020fa113f6c0ac978dfbd41f749257a9468febdbe0dc9f7e8":"505341004b45590000000000010000001771e0000100000000000000000000001d0000000024122bf020fa113f6c0ac978dfbd41f749257a9468febdbe0dc9f7e8":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECP_K1) 256-bit
+depends_on:PSA_WANT_ECC_SECP_K1_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"7fa06fa02d0e911b9a47fdc17d2d962ca01e2f31d60c6212d0ed7e3bba23a7b9":"505341004b455900000000000100000017710001010000000000000000000000200000007fa06fa02d0e911b9a47fdc17d2d962ca01e2f31d60c6212d0ed7e3bba23a7b9":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECP_R1) 225-bit
+depends_on:PSA_WANT_ECC_SECP_R1_225:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):225:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"872f203b3ad35b7f2ecc803c3a0e1e0b1ed61cc1afe71b189cd4c995":"505341004b45590000000000010000001271e1000100000000000000000000001c000000872f203b3ad35b7f2ecc803c3a0e1e0b1ed61cc1afe71b189cd4c995":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECP_R1) 256-bit
+depends_on:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":"505341004b4559000000000001000000127100010100000000000000000000002000000049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECP_R1) 384-bit
+depends_on:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):384:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":"505341004b455900000000000100000012718001010000000000000000000000300000003f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECP_R1) 521-bit
+depends_on:PSA_WANT_ECC_SECP_R1_521:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):521:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"01b1b6ad07bb79e7320da59860ea28e055284f6058f279de666e06d435d2af7bda28d99fa47b7dd0963e16b0073078ee8b8a38d966a582f46d19ff95df3ad9685aae":"505341004b4559000000000001000000127109020100000000000000000000004200000001b1b6ad07bb79e7320da59860ea28e055284f6058f279de666e06d435d2af7bda28d99fa47b7dd0963e16b0073078ee8b8a38d966a582f46d19ff95df3ad9685aae":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECP_R2) 160-bit
+depends_on:PSA_WANT_ECC_SECP_R2_160:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R2):160:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"00bf539a1cdda0d7f71a50a3f98aec0a2e8e4ced1e":"505341004b45590000000000010000001b71a0000100000000000000000000001500000000bf539a1cdda0d7f71a50a3f98aec0a2e8e4ced1e":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECT_K1) 163-bit
+depends_on:PSA_WANT_ECC_SECT_K1_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):163:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"03ebc8fcded2d6ab72ec0f75bdb4fd080481273e71":"505341004b45590000000000010000002771a3000100000000000000000000001500000003ebc8fcded2d6ab72ec0f75bdb4fd080481273e71":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECT_K1) 233-bit
+depends_on:PSA_WANT_ECC_SECT_K1_233:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):233:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"41f08485ce587b06061c087e76e247c359de2ba9927ee013b2f1ed9ca8":"505341004b45590000000000010000002771e9000100000000000000000000001d00000041f08485ce587b06061c087e76e247c359de2ba9927ee013b2f1ed9ca8":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECT_K1) 239-bit
+depends_on:PSA_WANT_ECC_SECT_K1_239:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):239:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"1a8069ce2c2c8bdd7087f2a6ab49588797e6294e979495602ab9650b9c61":"505341004b45590000000000010000002771ef000100000000000000000000001e0000001a8069ce2c2c8bdd7087f2a6ab49588797e6294e979495602ab9650b9c61":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECT_K1) 283-bit
+depends_on:PSA_WANT_ECC_SECT_K1_283:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):283:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"006d627885dd48b9ec6facb5b3865377d755b75a5d51440e45211c1f600e15eff8a881a0":"505341004b455900000000000100000027711b0101000000000000000000000024000000006d627885dd48b9ec6facb5b3865377d755b75a5d51440e45211c1f600e15eff8a881a0":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECT_K1) 409-bit
+depends_on:PSA_WANT_ECC_SECT_K1_409:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):409:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"3ff5e74d932fa77db139b7c948c81e4069c72c24845574064beea8976b70267f1c6f9a503e3892ea1dcbb71fcea423faa370a8":"505341004b455900000000000100000027719901010000000000000000000000330000003ff5e74d932fa77db139b7c948c81e4069c72c24845574064beea8976b70267f1c6f9a503e3892ea1dcbb71fcea423faa370a8":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECT_K1) 571-bit
+depends_on:PSA_WANT_ECC_SECT_K1_571:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):571:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"005008c97b4a161c0db1bac6452c72846d57337aa92d8ecb4a66eb01d2f29555ffb61a5317225dcc8ca6917d91789e227efc0bfe9eeda7ee21998cd11c3c9885056b0e55b4f75d51":"505341004b455900000000000100000027713b0201000000000000000000000048000000005008c97b4a161c0db1bac6452c72846d57337aa92d8ecb4a66eb01d2f29555ffb61a5317225dcc8ca6917d91789e227efc0bfe9eeda7ee21998cd11c3c9885056b0e55b4f75d51":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECT_R1) 163-bit
+depends_on:PSA_WANT_ECC_SECT_R1_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):163:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"009b05dc82d46d64a04a22e6e5ca70ca1231e68c50":"505341004b45590000000000010000002271a30001000000000000000000000015000000009b05dc82d46d64a04a22e6e5ca70ca1231e68c50":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECT_R1) 233-bit
+depends_on:PSA_WANT_ECC_SECT_R1_233:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):233:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"00e5e42834e3c78758088b905deea975f28dc20ef6173e481f96e88afe7f":"505341004b45590000000000010000002271e9000100000000000000000000001e00000000e5e42834e3c78758088b905deea975f28dc20ef6173e481f96e88afe7f":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECT_R1) 283-bit
+depends_on:PSA_WANT_ECC_SECT_R1_283:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):283:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"004cecad915f6f3c9bbbd92d1eb101eda23f16c7dad60a57c87c7e1fd2b29b22f6d666ad":"505341004b455900000000000100000022711b0101000000000000000000000024000000004cecad915f6f3c9bbbd92d1eb101eda23f16c7dad60a57c87c7e1fd2b29b22f6d666ad":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECT_R1) 409-bit
+depends_on:PSA_WANT_ECC_SECT_R1_409:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):409:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"00c22422d265721a3ae2b3b2baeb77bee50416e19877af97b5fc1c700a0a88916ecb9050135883accb5e64edc77a3703f4f67a64":"505341004b4559000000000001000000227199010100000000000000000000003400000000c22422d265721a3ae2b3b2baeb77bee50416e19877af97b5fc1c700a0a88916ecb9050135883accb5e64edc77a3703f4f67a64":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECT_R1) 571-bit
+depends_on:PSA_WANT_ECC_SECT_R1_571:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):571:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"026ac1cdf92a13a1b8d282da9725847908745138f5c6706b52d164e3675fcfbf86fc3e6ab2de732193267db029dd35a0599a94a118f480231cfc6ccca2ebfc1d8f54176e0f5656a1":"505341004b455900000000000100000022713b0201000000000000000000000048000000026ac1cdf92a13a1b8d282da9725847908745138f5c6706b52d164e3675fcfbf86fc3e6ab2de732193267db029dd35a0599a94a118f480231cfc6ccca2ebfc1d8f54176e0f5656a1":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(SECT_R2) 163-bit
+depends_on:PSA_WANT_ECC_SECT_R2_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R2):163:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0210b482a458b4822d0cb21daa96819a67c8062d34":"505341004b45590000000000010000002b71a300010000000000000000000000150000000210b482a458b4822d0cb21daa96819a67c8062d34":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(TWISTED_EDWARDS) 255-bit
+depends_on:PSA_WANT_ECC_TWISTED_EDWARDS_255:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):255:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60":"505341004b45590000000000010000004271ff00010000000000000000000000200000009d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_KEY_PAIR(TWISTED_EDWARDS) 448-bit
+depends_on:PSA_WANT_ECC_TWISTED_EDWARDS_448:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):448:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b":"505341004b45590000000000010000004271c001010000000000000000000000390000006c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 160-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_160:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):160:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04d4b9186816358e2f9c59cf70748cb70641b22fbab65473db4b4e22a361ed7e3de7e8a8ddc4130c5c":"505341004b45590000000000010000003041a0000100000000000000000000002900000004d4b9186816358e2f9c59cf70748cb70641b22fbab65473db4b4e22a361ed7e3de7e8a8ddc4130c5c":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 192-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_192:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):192:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"043fdd168c179ff5363dd71dcd58de9617caad791ae0c37328be9ca0bfc79cebabf6a95d1c52df5b5f3c8b1a2441cf6c88":"505341004b45590000000000010000003041c00001000000000000000000000031000000043fdd168c179ff5363dd71dcd58de9617caad791ae0c37328be9ca0bfc79cebabf6a95d1c52df5b5f3c8b1a2441cf6c88":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 224-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_224:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):224:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"045fbea378fc8583b3837e3f21a457c31eaf20a54e18eb11d104b3adc47f9d1c97eb9ea4ac21740d70d88514b98bf0bc31addac1d19c4ab3cc":"505341004b45590000000000010000003041e00001000000000000000000000039000000045fbea378fc8583b3837e3f21a457c31eaf20a54e18eb11d104b3adc47f9d1c97eb9ea4ac21740d70d88514b98bf0bc31addac1d19c4ab3cc":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 256-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04768c8cae4abca6306db0ed81b0c4a6215c378066ec6d616c146e13f1c7df809b96ab6911c27d8a02339f0926840e55236d3d1efbe2669d090e4c4c660fada91d":"505341004b4559000000000001000000304100010100000000000000000000004100000004768c8cae4abca6306db0ed81b0c4a6215c378066ec6d616c146e13f1c7df809b96ab6911c27d8a02339f0926840e55236d3d1efbe2669d090e4c4c660fada91d":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 320-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_320:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):320:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"049caed8fb4742956cc2ad12a9a1c995e21759ef26a07bc2054136d3d2f28bb331a70e26c4c687275ab1f434be7871e115d2350c0c5f61d4d06d2bcdb67f5cb63fdb794e5947c87dc6849a58694e37e6cd":"505341004b45590000000000010000003041400101000000000000000000000051000000049caed8fb4742956cc2ad12a9a1c995e21759ef26a07bc2054136d3d2f28bb331a70e26c4c687275ab1f434be7871e115d2350c0c5f61d4d06d2bcdb67f5cb63fdb794e5947c87dc6849a58694e37e6cd":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 384-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_384:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):384:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04719f9d093a627e0d350385c661cebf00c61923566fe9006a3107af1d871bc6bb68985fd722ea32be316f8e783b7cd1957785f66cfc0cb195dd5c99a8e7abaa848553a584dfd2b48e76d445fe00dd8be59096d877d4696d23b4bc8db14724e66a":"505341004b4559000000000001000000304180010100000000000000000000006100000004719f9d093a627e0d350385c661cebf00c61923566fe9006a3107af1d871bc6bb68985fd722ea32be316f8e783b7cd1957785f66cfc0cb195dd5c99a8e7abaa848553a584dfd2b48e76d445fe00dd8be59096d877d4696d23b4bc8db14724e66a":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 512-bit
+depends_on:PSA_WANT_ECC_BRAINPOOL_P_R1_512:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):512:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0438b7ec92b61c5c6c7fbc28a4ec759d48fcd4e2e374defd5c4968a54dbef7510e517886fbfc38ea39aa529359d70a7156c35d3cbac7ce776bdb251dd64bce71234424ee7049eed072f0dbc4d79996e175d557e263763ae97095c081e73e7db2e38adc3d4c9a0487b1ede876dc1fca61c902e9a1d8722b8612928f18a24845591a":"505341004b455900000000000100000030410002010000000000000000000000810000000438b7ec92b61c5c6c7fbc28a4ec759d48fcd4e2e374defd5c4968a54dbef7510e517886fbfc38ea39aa529359d70a7156c35d3cbac7ce776bdb251dd64bce71234424ee7049eed072f0dbc4d79996e175d557e263763ae97095c081e73e7db2e38adc3d4c9a0487b1ede876dc1fca61c902e9a1d8722b8612928f18a24845591a":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(MONTGOMERY) 255-bit
+depends_on:PSA_WANT_ECC_MONTGOMERY_255:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_MONTGOMERY):255:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a":"505341004b45590000000000010000004141ff00010000000000000000000000200000008520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(MONTGOMERY) 448-bit
+depends_on:PSA_WANT_ECC_MONTGOMERY_448:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_MONTGOMERY):448:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"c0d3a5a2b416a573dc9909f92f134ac01323ab8f8e36804e578588ba2d09fe7c3e737f771ca112825b548a0ffded6d6a2fd09a3e77dec30e":"505341004b45590000000000010000004141c00101000000000000000000000038000000c0d3a5a2b416a573dc9909f92f134ac01323ab8f8e36804e578588ba2d09fe7c3e737f771ca112825b548a0ffded6d6a2fd09a3e77dec30e":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECP_K1) 192-bit
+depends_on:PSA_WANT_ECC_SECP_K1_192:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_K1):192:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0426b7bb38da649ac2138fc050c6548b32553dab68afebc36105d325b75538c12323cb0764789ecb992671beb2b6bef2f5":"505341004b45590000000000010000001741c000010000000000000000000000310000000426b7bb38da649ac2138fc050c6548b32553dab68afebc36105d325b75538c12323cb0764789ecb992671beb2b6bef2f5":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECP_K1) 224-bit
+depends_on:PSA_WANT_ECC_SECP_K1_224:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_K1):224:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"042cc7335f4b76042bed44ef45959a62aa215f7a5ff0c8111b8c44ed654ee71c1918326ad485b2d599fe2a6eab096ee26d977334d2bac6d61d":"505341004b45590000000000010000001741e00001000000000000000000000039000000042cc7335f4b76042bed44ef45959a62aa215f7a5ff0c8111b8c44ed654ee71c1918326ad485b2d599fe2a6eab096ee26d977334d2bac6d61d":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECP_K1) 256-bit
+depends_on:PSA_WANT_ECC_SECP_K1_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_K1):256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"045c39154579efd667adc73a81015a797d2c8682cdfbd3c3553c4a185d481cdc50e42a0e1cbc3ca29a32a645e927f54beaed14c9dbbf8279d725f5495ca924b24d":"505341004b45590000000000010000001741000101000000000000000000000041000000045c39154579efd667adc73a81015a797d2c8682cdfbd3c3553c4a185d481cdc50e42a0e1cbc3ca29a32a645e927f54beaed14c9dbbf8279d725f5495ca924b24d":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECP_R1) 225-bit
+depends_on:PSA_WANT_ECC_SECP_R1_225:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):225:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"046f00eadaa949fee3e9e1c7fa1247eecec86a0dce46418b9bd3117b981d4bd0ae7a990de912f9d060d6cb531a42d22e394ac29e81804bf160":"505341004b45590000000000010000001241e10001000000000000000000000039000000046f00eadaa949fee3e9e1c7fa1247eecec86a0dce46418b9bd3117b981d4bd0ae7a990de912f9d060d6cb531a42d22e394ac29e81804bf160":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECP_R1) 256-bit
+depends_on:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":"505341004b45590000000000010000001241000101000000000000000000000041000000047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECP_R1) 384-bit
+depends_on:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):384:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04d9c662b50ba29ca47990450e043aeaf4f0c69b15676d112f622a71c93059af999691c5680d2b44d111579db12f4a413a2ed5c45fcfb67b5b63e00b91ebe59d09a6b1ac2c0c4282aa12317ed5914f999bc488bb132e8342cc36f2ca5e3379c747":"505341004b4559000000000001000000124180010100000000000000000000006100000004d9c662b50ba29ca47990450e043aeaf4f0c69b15676d112f622a71c93059af999691c5680d2b44d111579db12f4a413a2ed5c45fcfb67b5b63e00b91ebe59d09a6b1ac2c0c4282aa12317ed5914f999bc488bb132e8342cc36f2ca5e3379c747":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECP_R1) 521-bit
+depends_on:PSA_WANT_ECC_SECP_R1_521:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):521:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04001de142d54f69eb038ee4b7af9d3ca07736fd9cf719eb354d69879ee7f3c136fb0fbf9f08f86be5fa128ec1a051d3e6c643e85ada8ffacf3663c260bd2c844b6f5600cee8e48a9e65d09cadd89f235dee05f3b8a646be715f1f67d5b434e0ff23a1fc07ef7740193e40eeff6f3bcdfd765aa9155033524fe4f205f5444e292c4c2f6ac1":"505341004b4559000000000001000000124109020100000000000000000000008500000004001de142d54f69eb038ee4b7af9d3ca07736fd9cf719eb354d69879ee7f3c136fb0fbf9f08f86be5fa128ec1a051d3e6c643e85ada8ffacf3663c260bd2c844b6f5600cee8e48a9e65d09cadd89f235dee05f3b8a646be715f1f67d5b434e0ff23a1fc07ef7740193e40eeff6f3bcdfd765aa9155033524fe4f205f5444e292c4c2f6ac1":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECP_R2) 160-bit
+depends_on:PSA_WANT_ECC_SECP_R2_160:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R2):160:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"049570d541398665adb5cfa16f5af73b3196926bbd4b876bdb80f8eab20d0f540c22f4de9c140f6d7b":"505341004b45590000000000010000001b41a00001000000000000000000000029000000049570d541398665adb5cfa16f5af73b3196926bbd4b876bdb80f8eab20d0f540c22f4de9c140f6d7b":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECT_K1) 163-bit
+depends_on:PSA_WANT_ECC_SECT_K1_163:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):163:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0406f88f90b4b65950f06ce433afdb097e320f433dc2062b8a65db8fafd3c110f46bc45663fbf021ee7eb9":"505341004b45590000000000010000002741a3000100000000000000000000002b0000000406f88f90b4b65950f06ce433afdb097e320f433dc2062b8a65db8fafd3c110f46bc45663fbf021ee7eb9":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECT_K1) 233-bit
+depends_on:PSA_WANT_ECC_SECT_K1_233:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):233:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0401e9d7189189f773bd8f71be2c10774ba18842434dfa9312595ea545104400f45a9d5675647513ba75b079fe66a29daac2ec86a6a5d4e75c5f290c1f":"505341004b45590000000000010000002741e9000100000000000000000000003d0000000401e9d7189189f773bd8f71be2c10774ba18842434dfa9312595ea545104400f45a9d5675647513ba75b079fe66a29daac2ec86a6a5d4e75c5f290c1f":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECT_K1) 239-bit
+depends_on:PSA_WANT_ECC_SECT_K1_239:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):239:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04068d76b9f4508762c2379db9ee8b87ad8d86d9535132ffba3b5680440cfa28eb133d4232faf1c9aba96af11aefe634a551440800d5f8185105d3072d":"505341004b45590000000000010000002741ef000100000000000000000000003d00000004068d76b9f4508762c2379db9ee8b87ad8d86d9535132ffba3b5680440cfa28eb133d4232faf1c9aba96af11aefe634a551440800d5f8185105d3072d":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECT_K1) 283-bit
+depends_on:PSA_WANT_ECC_SECT_K1_283:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):283:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0405f48374debceaadb46ba385fd92048fcc5b9af1a1c90408bf94a68b9378df1cbfdfb6fb026a96bea06d8f181bf10c020adbcc88b6ecff96bdc564a9649c247cede601c4be63afc3":"505341004b455900000000000100000027411b01010000000000000000000000490000000405f48374debceaadb46ba385fd92048fcc5b9af1a1c90408bf94a68b9378df1cbfdfb6fb026a96bea06d8f181bf10c020adbcc88b6ecff96bdc564a9649c247cede601c4be63afc3":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECT_K1) 409-bit
+depends_on:PSA_WANT_ECC_SECT_K1_409:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):409:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04012c587f69f68b308ba6dcb238797f4e22290ca939ae806604e2b5ab4d9caef5a74a98fd87c4f88d292dd39d92e556e16c6ecc3c019a105826eef507cd9a04119f54d5d850b3720b3792d5d03410e9105610f7e4b420166ed45604a7a1f229d80975ba6be2060e8b":"505341004b4559000000000001000000274199010100000000000000000000006900000004012c587f69f68b308ba6dcb238797f4e22290ca939ae806604e2b5ab4d9caef5a74a98fd87c4f88d292dd39d92e556e16c6ecc3c019a105826eef507cd9a04119f54d5d850b3720b3792d5d03410e9105610f7e4b420166ed45604a7a1f229d80975ba6be2060e8b":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECT_K1) 571-bit
+depends_on:PSA_WANT_ECC_SECT_K1_571:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):571:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04050172a7fd7adf98e4e2ed2742faa5cd12731a15fb0dbbdf75b1c3cc771a4369af6f2fa00e802735650881735759ea9c79961ded18e0daa0ac59afb1d513b5bbda9962e435f454fc020b4afe1445c2302ada07d295ec2580f8849b2dfa7f956b09b4cbe4c88d3b1c217049f75d3900d36df0fa12689256b58dd2ef784ebbeb0564600cf47a841485f8cf897a68accd5a":"505341004b455900000000000100000027413b020100000000000000000000009100000004050172a7fd7adf98e4e2ed2742faa5cd12731a15fb0dbbdf75b1c3cc771a4369af6f2fa00e802735650881735759ea9c79961ded18e0daa0ac59afb1d513b5bbda9962e435f454fc020b4afe1445c2302ada07d295ec2580f8849b2dfa7f956b09b4cbe4c88d3b1c217049f75d3900d36df0fa12689256b58dd2ef784ebbeb0564600cf47a841485f8cf897a68accd5a":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECT_R1) 163-bit
+depends_on:PSA_WANT_ECC_SECT_R1_163:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):163:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0400465eeb9e7258b11e33c02266bfe834b20bcb118700772796ee4704ec67651bd447e3011959a79a04cb":"505341004b45590000000000010000002241a3000100000000000000000000002b0000000400465eeb9e7258b11e33c02266bfe834b20bcb118700772796ee4704ec67651bd447e3011959a79a04cb":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECT_R1) 233-bit
+depends_on:PSA_WANT_ECC_SECT_R1_233:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):233:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0400cd68c8af4430c92ec7a7048becfdf00a6bae8d1b4c37286f2d336f2a0e017eca3748f4ad6d435c85867aa014eea1bd6d9d005bbd8319cab629001d":"505341004b45590000000000010000002241e9000100000000000000000000003d0000000400cd68c8af4430c92ec7a7048becfdf00a6bae8d1b4c37286f2d336f2a0e017eca3748f4ad6d435c85867aa014eea1bd6d9d005bbd8319cab629001d":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECT_R1) 283-bit
+depends_on:PSA_WANT_ECC_SECT_R1_283:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):283:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"04052f9ff887254c2d1440ba9e30f13e2185ba53c373b2c410dae21cf8c167f796c08134f601cbc4c570bffbc2433082cf4d9eb5ba173ecb8caec15d66a02673f60807b2daa729b765":"505341004b455900000000000100000022411b010100000000000000000000004900000004052f9ff887254c2d1440ba9e30f13e2185ba53c373b2c410dae21cf8c167f796c08134f601cbc4c570bffbc2433082cf4d9eb5ba173ecb8caec15d66a02673f60807b2daa729b765":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECT_R1) 409-bit
+depends_on:PSA_WANT_ECC_SECT_R1_409:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):409:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0401aa25466b1d291846db365957b25431591e50d9c109fe2106e93bb369775896925b15a7bfec397406ab4fe6f6b1a13bf8fdcb9300fa5500a813228676b0a6c572ed96b0f4aec7e87832e7e20f17ca98ecdfd36f59c82bddb8665f1f357a73900e827885ec9e1f22":"505341004b455900000000000100000022419901010000000000000000000000690000000401aa25466b1d291846db365957b25431591e50d9c109fe2106e93bb369775896925b15a7bfec397406ab4fe6f6b1a13bf8fdcb9300fa5500a813228676b0a6c572ed96b0f4aec7e87832e7e20f17ca98ecdfd36f59c82bddb8665f1f357a73900e827885ec9e1f22":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECT_R1) 571-bit
+depends_on:PSA_WANT_ECC_SECT_R1_571:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):571:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"040708f3403ee9948114855c17572152a08f8054d486defef5f29cbffcfb7cfd9280746a1ac5f751a6ad902ec1e0525120e9be56f03437af196fbe60ee7856e3542ab2cf87880632d80290e39b1a2bd03c6bbf6225511c567bd2ff41d2325dc58346f2b60b1feee4dc8b2af2296c2dc52b153e0556b5d24152b07f690c3fa24e4d1d19efbdeb1037833a733654d2366c74":"505341004b455900000000000100000022413b0201000000000000000000000091000000040708f3403ee9948114855c17572152a08f8054d486defef5f29cbffcfb7cfd9280746a1ac5f751a6ad902ec1e0525120e9be56f03437af196fbe60ee7856e3542ab2cf87880632d80290e39b1a2bd03c6bbf6225511c567bd2ff41d2325dc58346f2b60b1feee4dc8b2af2296c2dc52b153e0556b5d24152b07f690c3fa24e4d1d19efbdeb1037833a733654d2366c74":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(SECT_R2) 163-bit
+depends_on:PSA_WANT_ECC_SECT_R2_163:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R2):163:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"0403692601144c32a6cfa369ae20ae5d43c1c764678c037bafe80c6fd2e42b7ced96171d9c5367fd3dca6f":"505341004b45590000000000010000002b41a3000100000000000000000000002b0000000403692601144c32a6cfa369ae20ae5d43c1c764678c037bafe80c6fd2e42b7ced96171d9c5367fd3dca6f":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(TWISTED_EDWARDS) 255-bit
+depends_on:PSA_WANT_ECC_TWISTED_EDWARDS_255:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS):255:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a":"505341004b45590000000000010000004241ff0001000000000000000000000020000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a":TEST_FLAG_EXERCISE
+
+PSA storage read: type: ECC_PUBLIC_KEY(TWISTED_EDWARDS) 448-bit
+depends_on:PSA_WANT_ECC_TWISTED_EDWARDS_448:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS):448:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"5fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180":"505341004b45590000000000010000004241c001010000000000000000000000390000005fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180":TEST_FLAG_EXERCISE
+
+PSA storage read: type: HMAC 128-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+key_storage_read:0x0001:PSA_KEY_TYPE_HMAC:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000001180000100000000000000000000001000000048657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: type: HMAC 160-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+key_storage_read:0x0001:PSA_KEY_TYPE_HMAC:160:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265":"505341004b45590000000000010000000011a0000100000000000000000000001400000048657265006973206b6579a06461746148657265":TEST_FLAG_EXERCISE
+
+PSA storage read: type: HMAC 224-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+key_storage_read:0x0001:PSA_KEY_TYPE_HMAC:224:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a0":"505341004b45590000000000010000000011e0000100000000000000000000001c00000048657265006973206b6579a06461746148657265006973206b6579a0":TEST_FLAG_EXERCISE
+
+PSA storage read: type: HMAC 256-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+key_storage_read:0x0001:PSA_KEY_TYPE_HMAC:256:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000001100010100000000000000000000002000000048657265006973206b6579a06461746148657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: type: HMAC 384-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+key_storage_read:0x0001:PSA_KEY_TYPE_HMAC:384:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000001180010100000000000000000000003000000048657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: type: HMAC 512-bit
+depends_on:PSA_WANT_KEY_TYPE_HMAC
+key_storage_read:0x0001:PSA_KEY_TYPE_HMAC:512:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461":"505341004b4559000000000001000000001100020100000000000000000000004000000048657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a06461746148657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: type: RAW_DATA 8-bit
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48":"505341004b4559000000000001000000011008000100000000000000000000000100000048":0
+
+PSA storage read: type: RAW_DATA 40-bit
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:40:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"4865726500":"505341004b455900000000000100000001102800010000000000000000000000050000004865726500":0
+
+PSA storage read: type: RAW_DATA 128-bit
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:128:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000011080000100000000000000000000001000000048657265006973206b6579a064617461":0
+
+PSA storage read: type: RSA_KEY_PAIR 1024-bit
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"505341004b455900000000000100000001700004010000000000000000000000620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":TEST_FLAG_EXERCISE
+
+PSA storage read: type: RSA_KEY_PAIR 1536-bit
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_RSA_KEY_PAIR:1536:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"3082037b0201000281c100c870feb6ca6b1d2bd9f2dd99e20f1fe2d7e5192de662229dbe162bd1ba66336a7182903ca0b72796cd441c83d24bcdc3e9a2f5e4399c8a043f1c3ddf04754a66d4cfe7b3671a37dd31a9b4c13bfe06ee90f9d94ddaa06de67a52ac863e68f756736ceb014405a6160579640f831dddccc34ad0b05070e3f9954a58d1815813e1b83bcadba814789c87f1ef2ba5d738b793ec456a67360eea1b5faf1c7cc7bf24f3b2a9d0f8958b1096e0f0c335f8888d0c63a51c3c0337214fa3f5efdf6dcc3502030100010281c06d2d670047973a87752a9d5bc14f3dae00acb01f593aa0e24cf4a49f932931de4bbfb332e2d38083da80bc0b6d538edba479f7f77d0deffb4a28e6e67ff6273585bb4cd862535c946605ab0809d65f0e38f76e4ec2c3d9b8cd6e14bcf667943892cd4b34cc6420a439abbf3d7d35ef73976dd6f9cbde35a51fa5213f0107f83e3425835d16d3c9146fc9e36ce75a09bb66cdff21dd5a776899f1cb07e282cca27be46510e9c799f0d8db275a6be085d9f3f803218ee3384265bfb1a3640e8ca1026100e6848c31d466fffefc547e3a3b0d3785de6f78b0dd12610843512e495611a0675509b1650b27415009838dd8e68eec6e7530553b637d602424643b33e8bc5b762e1799bc79d56b13251d36d4f201da2182416ce13574e88278ff04467ad602d9026100de994fdf181f02be2bf9e5f5e4e517a94993b827d1eaf609033e3a6a6f2396ae7c44e9eb594cf1044cb3ad32ea258f0c82963b27bb650ed200cde82cb993374be34be5b1c7ead5446a2b82a4486e8c1810a0b01551609fb0841d474bada802bd026076ddae751b73a959d0bfb8ff49e7fcd378e9be30652ecefe35c82cb8003bc29cc60ae3809909baf20c95db9516fe680865417111d8b193dbcf30281f1249de57c858bf1ba32f5bb1599800e8398a9ef25c7a642c95261da6f9c17670e97265b10260732482b837d5f2a9443e23c1aa0106d83e82f6c3424673b5fdc3769c0f992d1c5c93991c7038e882fcda04414df4d7a5f4f698ead87851ce37344b60b72d7b70f9c60cae8566e7a257f8e1bef0e89df6e4c2f9d24d21d9f8889e4c7eccf91751026009050d94493da8f00a4ddbe9c800afe3d44b43f78a48941a79b2814a1f0b81a18a8b2347642a03b27998f5a18de9abc9ae0e54ab8294feac66dc87e854cce6f7278ac2710cb5878b592ffeb1f4f0a1853e4e8d1d0561b6efcc831a296cf7eeaf":"505341004b4559000000000001000000017000060100000000000000000000007f0300003082037b0201000281c100c870feb6ca6b1d2bd9f2dd99e20f1fe2d7e5192de662229dbe162bd1ba66336a7182903ca0b72796cd441c83d24bcdc3e9a2f5e4399c8a043f1c3ddf04754a66d4cfe7b3671a37dd31a9b4c13bfe06ee90f9d94ddaa06de67a52ac863e68f756736ceb014405a6160579640f831dddccc34ad0b05070e3f9954a58d1815813e1b83bcadba814789c87f1ef2ba5d738b793ec456a67360eea1b5faf1c7cc7bf24f3b2a9d0f8958b1096e0f0c335f8888d0c63a51c3c0337214fa3f5efdf6dcc3502030100010281c06d2d670047973a87752a9d5bc14f3dae00acb01f593aa0e24cf4a49f932931de4bbfb332e2d38083da80bc0b6d538edba479f7f77d0deffb4a28e6e67ff6273585bb4cd862535c946605ab0809d65f0e38f76e4ec2c3d9b8cd6e14bcf667943892cd4b34cc6420a439abbf3d7d35ef73976dd6f9cbde35a51fa5213f0107f83e3425835d16d3c9146fc9e36ce75a09bb66cdff21dd5a776899f1cb07e282cca27be46510e9c799f0d8db275a6be085d9f3f803218ee3384265bfb1a3640e8ca1026100e6848c31d466fffefc547e3a3b0d3785de6f78b0dd12610843512e495611a0675509b1650b27415009838dd8e68eec6e7530553b637d602424643b33e8bc5b762e1799bc79d56b13251d36d4f201da2182416ce13574e88278ff04467ad602d9026100de994fdf181f02be2bf9e5f5e4e517a94993b827d1eaf609033e3a6a6f2396ae7c44e9eb594cf1044cb3ad32ea258f0c82963b27bb650ed200cde82cb993374be34be5b1c7ead5446a2b82a4486e8c1810a0b01551609fb0841d474bada802bd026076ddae751b73a959d0bfb8ff49e7fcd378e9be30652ecefe35c82cb8003bc29cc60ae3809909baf20c95db9516fe680865417111d8b193dbcf30281f1249de57c858bf1ba32f5bb1599800e8398a9ef25c7a642c95261da6f9c17670e97265b10260732482b837d5f2a9443e23c1aa0106d83e82f6c3424673b5fdc3769c0f992d1c5c93991c7038e882fcda04414df4d7a5f4f698ead87851ce37344b60b72d7b70f9c60cae8566e7a257f8e1bef0e89df6e4c2f9d24d21d9f8889e4c7eccf91751026009050d94493da8f00a4ddbe9c800afe3d44b43f78a48941a79b2814a1f0b81a18a8b2347642a03b27998f5a18de9abc9ae0e54ab8294feac66dc87e854cce6f7278ac2710cb5878b592ffeb1f4f0a1853e4e8d1d0561b6efcc831a296cf7eeaf":TEST_FLAG_EXERCISE
+
+PSA storage read: type: RSA_PUBLIC_KEY 1024-bit
+depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":"505341004b4559000000000001000000014000040100000000000000000000008c00000030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":TEST_FLAG_EXERCISE
+
+PSA storage read: type: RSA_PUBLIC_KEY 1536-bit
+depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_RSA_PUBLIC_KEY:1536:PSA_KEY_USAGE_EXPORT:0x0000:0x0000:"3081c90281c100c870feb6ca6b1d2bd9f2dd99e20f1fe2d7e5192de662229dbe162bd1ba66336a7182903ca0b72796cd441c83d24bcdc3e9a2f5e4399c8a043f1c3ddf04754a66d4cfe7b3671a37dd31a9b4c13bfe06ee90f9d94ddaa06de67a52ac863e68f756736ceb014405a6160579640f831dddccc34ad0b05070e3f9954a58d1815813e1b83bcadba814789c87f1ef2ba5d738b793ec456a67360eea1b5faf1c7cc7bf24f3b2a9d0f8958b1096e0f0c335f8888d0c63a51c3c0337214fa3f5efdf6dcc350203010001":"505341004b455900000000000100000001400006010000000000000000000000cc0000003081c90281c100c870feb6ca6b1d2bd9f2dd99e20f1fe2d7e5192de662229dbe162bd1ba66336a7182903ca0b72796cd441c83d24bcdc3e9a2f5e4399c8a043f1c3ddf04754a66d4cfe7b3671a37dd31a9b4c13bfe06ee90f9d94ddaa06de67a52ac863e68f756736ceb014405a6160579640f831dddccc34ad0b05070e3f9954a58d1815813e1b83bcadba814789c87f1ef2ba5d738b793ec456a67360eea1b5faf1c7cc7bf24f3b2a9d0f8958b1096e0f0c335f8888d0c63a51c3c0337214fa3f5efdf6dcc350203010001":TEST_FLAG_EXERCISE
+
+PSA storage read: alg: AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(CCM, 1)
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000081410500000000010000004b":0
+
+PSA storage read: alg2: AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(CCM, 1)
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 1):"4c":"505341004b455900000000000100000001100800010000000000000000814105010000004c":0
+
+PSA storage read: alg: AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(CHACHA20_POLY1305, 1)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CHACHA20_POLY1305, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000085010500000000010000004b":0
+
+PSA storage read: alg2: AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(CHACHA20_POLY1305, 1)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CHACHA20_POLY1305, 1):"4c":"505341004b455900000000000100000001100800010000000000000000850105010000004c":0
+
+PSA storage read: alg: AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(GCM, 1)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_GCM, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000082410500000000010000004b":0
+
+PSA storage read: alg2: AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(GCM, 1)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_GCM, 1):"4c":"505341004b455900000000000100000001100800010000000000000000824105010000004c":0
+
+PSA storage read: alg: AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(CCM, 63)
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 63):0x0000:"4b":"505341004b4559000000000001000000011008000100000000817f0500000000010000004b":0
+
+PSA storage read: alg2: AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(CCM, 63)
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 63):"4c":"505341004b455900000000000100000001100800010000000000000000817f05010000004c":0
+
+PSA storage read: alg: AEAD_WITH_SHORTENED_TAG(CCM, 1)
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000001410500000000010000004b":0
+
+PSA storage read: alg2: AEAD_WITH_SHORTENED_TAG(CCM, 1)
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 1):"4c":"505341004b455900000000000100000001100800010000000000000000014105010000004c":0
+
+PSA storage read: alg: AEAD_WITH_SHORTENED_TAG(CHACHA20_POLY1305, 1)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000005010500000000010000004b":0
+
+PSA storage read: alg2: AEAD_WITH_SHORTENED_TAG(CHACHA20_POLY1305, 1)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 1):"4c":"505341004b455900000000000100000001100800010000000000000000050105010000004c":0
+
+PSA storage read: alg: AEAD_WITH_SHORTENED_TAG(GCM, 1)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000002410500000000010000004b":0
+
+PSA storage read: alg2: AEAD_WITH_SHORTENED_TAG(GCM, 1)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 1):"4c":"505341004b455900000000000100000001100800010000000000000000024105010000004c":0
+
+PSA storage read: alg: AEAD_WITH_SHORTENED_TAG(CCM, 63)
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 63):0x0000:"4b":"505341004b4559000000000001000000011008000100000000017f0500000000010000004b":0
+
+PSA storage read: alg2: AEAD_WITH_SHORTENED_TAG(CCM, 63)
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 63):"4c":"505341004b455900000000000100000001100800010000000000000000017f05010000004c":0
+
+PSA storage read: alg: ANY_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ANY_HASH:0x0000:"4b":"505341004b45590000000000010000000110080001000000ff00000200000000010000004b":0
+
+PSA storage read: alg2: ANY_HASH
+depends_on:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ANY_HASH:"4c":"505341004b4559000000000001000000011008000100000000000000ff000002010000004c":0
+
+PSA storage read: alg: AT_LEAST_THIS_LENGTH_MAC(CBC_MAC, 1)
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CBC_MAC, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000081c10300000000010000004b":0
+
+PSA storage read: alg2: AT_LEAST_THIS_LENGTH_MAC(CBC_MAC, 1)
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CBC_MAC, 1):"4c":"505341004b45590000000000010000000110080001000000000000000081c103010000004c":0
+
+PSA storage read: alg: AT_LEAST_THIS_LENGTH_MAC(CMAC, 1)
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CMAC, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000082c10300000000010000004b":0
+
+PSA storage read: alg2: AT_LEAST_THIS_LENGTH_MAC(CMAC, 1)
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CMAC, 1):"4c":"505341004b45590000000000010000000110080001000000000000000082c103010000004c":0
+
+PSA storage read: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(MD2), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_MD2), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000180810300000000010000004b":0
+
+PSA storage read: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(MD2), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_MD2), 1):"4c":"505341004b455900000000000100000001100800010000000000000001808103010000004c":0
+
+PSA storage read: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(MD4), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_MD4), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000280810300000000010000004b":0
+
+PSA storage read: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(MD4), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_MD4), 1):"4c":"505341004b455900000000000100000001100800010000000000000002808103010000004c":0
+
+PSA storage read: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(MD5), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_MD5), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000380810300000000010000004b":0
+
+PSA storage read: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(MD5), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_MD5), 1):"4c":"505341004b455900000000000100000001100800010000000000000003808103010000004c":0
+
+PSA storage read: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(RIPEMD160), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_RIPEMD160), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000480810300000000010000004b":0
+
+PSA storage read: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(RIPEMD160), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_RIPEMD160), 1):"4c":"505341004b455900000000000100000001100800010000000000000004808103010000004c":0
+
+PSA storage read: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_1), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_1), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000580810300000000010000004b":0
+
+PSA storage read: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_1), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_1), 1):"4c":"505341004b455900000000000100000001100800010000000000000005808103010000004c":0
+
+PSA storage read: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_224), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_224), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000880810300000000010000004b":0
+
+PSA storage read: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_224), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_224), 1):"4c":"505341004b455900000000000100000001100800010000000000000008808103010000004c":0
+
+PSA storage read: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_256), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000980810300000000010000004b":0
+
+PSA storage read: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_256), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 1):"4c":"505341004b455900000000000100000001100800010000000000000009808103010000004c":0
+
+PSA storage read: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_384), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_384), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000a80810300000000010000004b":0
+
+PSA storage read: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_384), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_384), 1):"4c":"505341004b45590000000000010000000110080001000000000000000a808103010000004c":0
+
+PSA storage read: alg: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_512), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_512), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000b80810300000000010000004b":0
+
+PSA storage read: alg2: AT_LEAST_THIS_LENGTH_MAC(HMAC(SHA_512), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_512), 1):"4c":"505341004b45590000000000010000000110080001000000000000000b808103010000004c":0
+
+PSA storage read: alg: AT_LEAST_THIS_LENGTH_MAC(CBC_MAC, 63)
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CBC_MAC, 63):0x0000:"4b":"505341004b455900000000000100000001100800010000000081ff0300000000010000004b":0
+
+PSA storage read: alg2: AT_LEAST_THIS_LENGTH_MAC(CBC_MAC, 63)
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CBC_MAC, 63):"4c":"505341004b45590000000000010000000110080001000000000000000081ff03010000004c":0
+
+PSA storage read: alg: CBC_MAC
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_CBC_MAC:0x0000:"4b":"505341004b455900000000000100000001100800010000000001c00300000000010000004b":0
+
+PSA storage read: alg2: CBC_MAC
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_CBC_MAC:"4c":"505341004b45590000000000010000000110080001000000000000000001c003010000004c":0
+
+PSA storage read: alg: CBC_NO_PADDING
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_CBC_NO_PADDING:0x0000:"4b":"505341004b455900000000000100000001100800010000000040400400000000010000004b":0
+
+PSA storage read: alg2: CBC_NO_PADDING
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_CBC_NO_PADDING:"4c":"505341004b455900000000000100000001100800010000000000000000404004010000004c":0
+
+PSA storage read: alg: CBC_PKCS7
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_CBC_PKCS7:0x0000:"4b":"505341004b455900000000000100000001100800010000000041400400000000010000004b":0
+
+PSA storage read: alg2: CBC_PKCS7
+depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_CBC_PKCS7:"4c":"505341004b455900000000000100000001100800010000000000000000414004010000004c":0
+
+PSA storage read: alg: CCM
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_CCM:0x0000:"4b":"505341004b455900000000000100000001100800010000000001500500000000010000004b":0
+
+PSA storage read: alg2: CCM
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_CCM:"4c":"505341004b455900000000000100000001100800010000000000000000015005010000004c":0
+
+PSA storage read: alg: CFB
+depends_on:PSA_WANT_ALG_CFB:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_CFB:0x0000:"4b":"505341004b455900000000000100000001100800010000000011c00400000000010000004b":0
+
+PSA storage read: alg2: CFB
+depends_on:PSA_WANT_ALG_CFB:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_CFB:"4c":"505341004b45590000000000010000000110080001000000000000000011c004010000004c":0
+
+PSA storage read: alg: CHACHA20_POLY1305
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_CHACHA20_POLY1305:0x0000:"4b":"505341004b455900000000000100000001100800010000000005100500000000010000004b":0
+
+PSA storage read: alg2: CHACHA20_POLY1305
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_CHACHA20_POLY1305:"4c":"505341004b455900000000000100000001100800010000000000000000051005010000004c":0
+
+PSA storage read: alg: CMAC
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_CMAC:0x0000:"4b":"505341004b455900000000000100000001100800010000000002c00300000000010000004b":0
+
+PSA storage read: alg2: CMAC
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_CMAC:"4c":"505341004b45590000000000010000000110080001000000000000000002c003010000004c":0
+
+PSA storage read: alg: CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:0x0000:"4b":"505341004b455900000000000100000001100800010000000010c00400000000010000004b":0
+
+PSA storage read: alg2: CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_CTR:"4c":"505341004b45590000000000010000000110080001000000000000000010c004010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_DSA(MD2)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000105000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_DSA(MD2)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001050006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_DSA(MD4)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000205000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_DSA(MD4)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002050006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_DSA(MD5)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000305000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_DSA(MD5)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003050006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_DSA(RIPEMD160)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000405000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_DSA(RIPEMD160)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004050006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_DSA(SHA_1)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000505000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_DSA(SHA_1)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005050006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_DSA(SHA_224)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000805000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_DSA(SHA_224)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008050006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_DSA(SHA_256)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000905000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_DSA(SHA_256)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009050006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_DSA(SHA_384)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a05000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_DSA(SHA_384)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a050006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_DSA(SHA_512)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b05000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_DSA(SHA_512)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_DSA:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_DSA(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b050006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_ECDSA(MD2)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000107000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_ECDSA(MD2)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001070006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_ECDSA(MD4)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000207000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_ECDSA(MD4)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002070006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_ECDSA(MD5)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000307000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_ECDSA(MD5)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003070006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_ECDSA(RIPEMD160)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000407000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_ECDSA(RIPEMD160)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004070006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_ECDSA(SHA_1)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000507000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_ECDSA(SHA_1)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005070006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_ECDSA(SHA_224)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000807000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_ECDSA(SHA_224)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008070006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_ECDSA(SHA_256)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000907000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_ECDSA(SHA_256)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009070006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_ECDSA(SHA_384)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a07000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_ECDSA(SHA_384)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a070006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_ECDSA(SHA_512)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b07000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_ECDSA(SHA_512)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b070006010000004c":0
+
+PSA storage read: alg: DETERMINISTIC_ECDSA(ANY_HASH)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH):0x0000:"4b":"505341004b45590000000000010000000110080001000000ff07000600000000010000004b":0
+
+PSA storage read: alg2: DETERMINISTIC_ECDSA(ANY_HASH)
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH):"4c":"505341004b4559000000000001000000011008000100000000000000ff070006010000004c":0
+
+PSA storage read: alg: DSA(MD2)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000104000600000000010000004b":0
+
+PSA storage read: alg2: DSA(MD2)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001040006010000004c":0
+
+PSA storage read: alg: DSA(MD4)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000204000600000000010000004b":0
+
+PSA storage read: alg2: DSA(MD4)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002040006010000004c":0
+
+PSA storage read: alg: DSA(MD5)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000304000600000000010000004b":0
+
+PSA storage read: alg2: DSA(MD5)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003040006010000004c":0
+
+PSA storage read: alg: DSA(RIPEMD160)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000404000600000000010000004b":0
+
+PSA storage read: alg2: DSA(RIPEMD160)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004040006010000004c":0
+
+PSA storage read: alg: DSA(SHA_1)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000504000600000000010000004b":0
+
+PSA storage read: alg2: DSA(SHA_1)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005040006010000004c":0
+
+PSA storage read: alg: DSA(SHA_224)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000804000600000000010000004b":0
+
+PSA storage read: alg2: DSA(SHA_224)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008040006010000004c":0
+
+PSA storage read: alg: DSA(SHA_256)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000904000600000000010000004b":0
+
+PSA storage read: alg2: DSA(SHA_256)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009040006010000004c":0
+
+PSA storage read: alg: DSA(SHA_384)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a04000600000000010000004b":0
+
+PSA storage read: alg2: DSA(SHA_384)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a040006010000004c":0
+
+PSA storage read: alg: DSA(SHA_512)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_DSA(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b04000600000000010000004b":0
+
+PSA storage read: alg2: DSA(SHA_512)
+depends_on:PSA_WANT_ALG_DSA:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_DSA(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b040006010000004c":0
+
+PSA storage read: alg: ECB_NO_PADDING
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECB_NO_PADDING:0x0000:"4b":"505341004b455900000000000100000001100800010000000044400400000000010000004b":0
+
+PSA storage read: alg2: ECB_NO_PADDING
+depends_on:PSA_WANT_ALG_ECB_NO_PADDING:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECB_NO_PADDING:"4c":"505341004b455900000000000100000001100800010000000000000000444004010000004c":0
+
+PSA storage read: alg: ECDH
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDH:0x0000:"4b":"505341004b455900000000000100000001100800010000000000020900000000010000004b":0
+
+PSA storage read: alg2: ECDH
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDH:"4c":"505341004b455900000000000100000001100800010000000000000000000209010000004c":0
+
+PSA storage read: alg: ECDSA(MD2)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000106000600000000010000004b":0
+
+PSA storage read: alg2: ECDSA(MD2)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001060006010000004c":0
+
+PSA storage read: alg: ECDSA(MD4)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000206000600000000010000004b":0
+
+PSA storage read: alg2: ECDSA(MD4)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002060006010000004c":0
+
+PSA storage read: alg: ECDSA(MD5)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000306000600000000010000004b":0
+
+PSA storage read: alg2: ECDSA(MD5)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003060006010000004c":0
+
+PSA storage read: alg: ECDSA(RIPEMD160)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000406000600000000010000004b":0
+
+PSA storage read: alg2: ECDSA(RIPEMD160)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004060006010000004c":0
+
+PSA storage read: alg: ECDSA(SHA_1)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000506000600000000010000004b":0
+
+PSA storage read: alg2: ECDSA(SHA_1)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005060006010000004c":0
+
+PSA storage read: alg: ECDSA(SHA_224)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000806000600000000010000004b":0
+
+PSA storage read: alg2: ECDSA(SHA_224)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008060006010000004c":0
+
+PSA storage read: alg: ECDSA(SHA_256)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000906000600000000010000004b":0
+
+PSA storage read: alg2: ECDSA(SHA_256)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009060006010000004c":0
+
+PSA storage read: alg: ECDSA(SHA_384)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a06000600000000010000004b":0
+
+PSA storage read: alg2: ECDSA(SHA_384)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a060006010000004c":0
+
+PSA storage read: alg: ECDSA(SHA_512)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b06000600000000010000004b":0
+
+PSA storage read: alg2: ECDSA(SHA_512)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b060006010000004c":0
+
+PSA storage read: alg: ECDSA(ANY_HASH)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0x0000:"4b":"505341004b45590000000000010000000110080001000000ff06000600000000010000004b":0
+
+PSA storage read: alg2: ECDSA(ANY_HASH)
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):"4c":"505341004b4559000000000001000000011008000100000000000000ff060006010000004c":0
+
+PSA storage read: alg: ECDSA_ANY
+depends_on:PSA_WANT_ALG_ECDSA_ANY:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA_ANY:0x0000:"4b":"505341004b455900000000000100000001100800010000000006000600000000010000004b":0
+
+PSA storage read: alg2: ECDSA_ANY
+depends_on:PSA_WANT_ALG_ECDSA_ANY:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ECDSA_ANY:"4c":"505341004b455900000000000100000001100800010000000000000000060006010000004c":0
+
+PSA storage read: alg: ED25519PH
+depends_on:PSA_WANT_ALG_ED25519PH:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ED25519PH:0x0000:"4b":"505341004b455900000000000100000001100800010000000b09000600000000010000004b":0
+
+PSA storage read: alg2: ED25519PH
+depends_on:PSA_WANT_ALG_ED25519PH:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ED25519PH:"4c":"505341004b45590000000000010000000110080001000000000000000b090006010000004c":0
+
+PSA storage read: alg: ED448PH
+depends_on:PSA_WANT_ALG_ED448PH:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_ED448PH:0x0000:"4b":"505341004b455900000000000100000001100800010000001509000600000000010000004b":0
+
+PSA storage read: alg2: ED448PH
+depends_on:PSA_WANT_ALG_ED448PH:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_ED448PH:"4c":"505341004b455900000000000100000001100800010000000000000015090006010000004c":0
+
+PSA storage read: alg: FFDH
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_FFDH:0x0000:"4b":"505341004b455900000000000100000001100800010000000000010900000000010000004b":0
+
+PSA storage read: alg2: FFDH
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_FFDH:"4c":"505341004b455900000000000100000001100800010000000000000000000109010000004c":0
+
+PSA storage read: alg: GCM
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_GCM:0x0000:"4b":"505341004b455900000000000100000001100800010000000002500500000000010000004b":0
+
+PSA storage read: alg2: GCM
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_GCM:"4c":"505341004b455900000000000100000001100800010000000000000000025005010000004c":0
+
+PSA storage read: alg: HKDF(MD2)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000101000800000000010000004b":0
+
+PSA storage read: alg2: HKDF(MD2)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001010008010000004c":0
+
+PSA storage read: alg: HKDF(MD4)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000201000800000000010000004b":0
+
+PSA storage read: alg2: HKDF(MD4)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002010008010000004c":0
+
+PSA storage read: alg: HKDF(MD5)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000301000800000000010000004b":0
+
+PSA storage read: alg2: HKDF(MD5)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003010008010000004c":0
+
+PSA storage read: alg: HKDF(RIPEMD160)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000401000800000000010000004b":0
+
+PSA storage read: alg2: HKDF(RIPEMD160)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004010008010000004c":0
+
+PSA storage read: alg: HKDF(SHA_1)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000501000800000000010000004b":0
+
+PSA storage read: alg2: HKDF(SHA_1)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005010008010000004c":0
+
+PSA storage read: alg: HKDF(SHA_224)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000801000800000000010000004b":0
+
+PSA storage read: alg2: HKDF(SHA_224)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008010008010000004c":0
+
+PSA storage read: alg: HKDF(SHA_256)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000901000800000000010000004b":0
+
+PSA storage read: alg2: HKDF(SHA_256)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009010008010000004c":0
+
+PSA storage read: alg: HKDF(SHA_384)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a01000800000000010000004b":0
+
+PSA storage read: alg2: HKDF(SHA_384)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a010008010000004c":0
+
+PSA storage read: alg: HKDF(SHA_512)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HKDF(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b01000800000000010000004b":0
+
+PSA storage read: alg2: HKDF(SHA_512)
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HKDF(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b010008010000004c":0
+
+PSA storage read: alg: HMAC(MD2)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000100800300000000010000004b":0
+
+PSA storage read: alg2: HMAC(MD2)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001008003010000004c":0
+
+PSA storage read: alg: HMAC(MD4)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000200800300000000010000004b":0
+
+PSA storage read: alg2: HMAC(MD4)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002008003010000004c":0
+
+PSA storage read: alg: HMAC(MD5)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000300800300000000010000004b":0
+
+PSA storage read: alg2: HMAC(MD5)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003008003010000004c":0
+
+PSA storage read: alg: HMAC(RIPEMD160)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000400800300000000010000004b":0
+
+PSA storage read: alg2: HMAC(RIPEMD160)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004008003010000004c":0
+
+PSA storage read: alg: HMAC(SHA_1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000500800300000000010000004b":0
+
+PSA storage read: alg2: HMAC(SHA_1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005008003010000004c":0
+
+PSA storage read: alg: HMAC(SHA_224)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000800800300000000010000004b":0
+
+PSA storage read: alg2: HMAC(SHA_224)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008008003010000004c":0
+
+PSA storage read: alg: HMAC(SHA_256)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000900800300000000010000004b":0
+
+PSA storage read: alg2: HMAC(SHA_256)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009008003010000004c":0
+
+PSA storage read: alg: HMAC(SHA_384)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a00800300000000010000004b":0
+
+PSA storage read: alg2: HMAC(SHA_384)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a008003010000004c":0
+
+PSA storage read: alg: HMAC(SHA_512)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_HMAC(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b00800300000000010000004b":0
+
+PSA storage read: alg2: HMAC(SHA_512)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_HMAC(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b008003010000004c":0
+
+PSA storage read: alg: KEY_AGREEMENT(ECDH, HKDF(SHA_256))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):0x0000:"4b":"505341004b455900000000000100000001100800010000000901020900000000010000004b":0
+
+PSA storage read: alg2: KEY_AGREEMENT(ECDH, HKDF(SHA_256))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):"4c":"505341004b455900000000000100000001100800010000000000000009010209010000004c":0
+
+PSA storage read: alg: KEY_AGREEMENT(FFDH, HKDF(SHA_256))
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_KEY_AGREEMENT(PSA_ALG_FFDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):0x0000:"4b":"505341004b455900000000000100000001100800010000000901010900000000010000004b":0
+
+PSA storage read: alg2: KEY_AGREEMENT(FFDH, HKDF(SHA_256))
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_KEY_AGREEMENT(PSA_ALG_FFDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):"4c":"505341004b455900000000000100000001100800010000000000000009010109010000004c":0
+
+PSA storage read: alg: KEY_AGREEMENT(ECDH, HKDF(SHA_384))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_384)):0x0000:"4b":"505341004b455900000000000100000001100800010000000a01020900000000010000004b":0
+
+PSA storage read: alg2: KEY_AGREEMENT(ECDH, HKDF(SHA_384))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_384)):"4c":"505341004b45590000000000010000000110080001000000000000000a010209010000004c":0
+
+PSA storage read: alg: KEY_AGREEMENT(ECDH, TLS12_PRF(SHA_256))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)):0x0000:"4b":"505341004b455900000000000100000001100800010000000902020900000000010000004b":0
+
+PSA storage read: alg2: KEY_AGREEMENT(ECDH, TLS12_PRF(SHA_256))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)):"4c":"505341004b455900000000000100000001100800010000000000000009020209010000004c":0
+
+PSA storage read: alg: KEY_AGREEMENT(ECDH, TLS12_PRF(SHA_384))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384)):0x0000:"4b":"505341004b455900000000000100000001100800010000000a02020900000000010000004b":0
+
+PSA storage read: alg2: KEY_AGREEMENT(ECDH, TLS12_PRF(SHA_384))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384)):"4c":"505341004b45590000000000010000000110080001000000000000000a020209010000004c":0
+
+PSA storage read: alg: KEY_AGREEMENT(ECDH, TLS12_PSK_TO_MS(SHA_256))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256)):0x0000:"4b":"505341004b455900000000000100000001100800010000000903020900000000010000004b":0
+
+PSA storage read: alg2: KEY_AGREEMENT(ECDH, TLS12_PSK_TO_MS(SHA_256))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256)):"4c":"505341004b455900000000000100000001100800010000000000000009030209010000004c":0
+
+PSA storage read: alg: KEY_AGREEMENT(ECDH, TLS12_PSK_TO_MS(SHA_384))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384)):0x0000:"4b":"505341004b455900000000000100000001100800010000000a03020900000000010000004b":0
+
+PSA storage read: alg2: KEY_AGREEMENT(ECDH, TLS12_PSK_TO_MS(SHA_384))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384)):"4c":"505341004b45590000000000010000000110080001000000000000000a030209010000004c":0
+
+PSA storage read: alg: KEY_AGREEMENT(FFDH, HKDF(SHA_384))
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_KEY_AGREEMENT(PSA_ALG_FFDH, PSA_ALG_HKDF(PSA_ALG_SHA_384)):0x0000:"4b":"505341004b455900000000000100000001100800010000000a01010900000000010000004b":0
+
+PSA storage read: alg2: KEY_AGREEMENT(FFDH, HKDF(SHA_384))
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_KEY_AGREEMENT(PSA_ALG_FFDH, PSA_ALG_HKDF(PSA_ALG_SHA_384)):"4c":"505341004b45590000000000010000000110080001000000000000000a010109010000004c":0
+
+PSA storage read: alg: MD2
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_MD2:0x0000:"4b":"505341004b455900000000000100000001100800010000000100000200000000010000004b":0
+
+PSA storage read: alg2: MD2
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_MD2:"4c":"505341004b455900000000000100000001100800010000000000000001000002010000004c":0
+
+PSA storage read: alg: MD4
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_MD4:0x0000:"4b":"505341004b455900000000000100000001100800010000000200000200000000010000004b":0
+
+PSA storage read: alg2: MD4
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_MD4:"4c":"505341004b455900000000000100000001100800010000000000000002000002010000004c":0
+
+PSA storage read: alg: MD5
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_MD5:0x0000:"4b":"505341004b455900000000000100000001100800010000000300000200000000010000004b":0
+
+PSA storage read: alg2: MD5
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_MD5:"4c":"505341004b455900000000000100000001100800010000000000000003000002010000004c":0
+
+PSA storage read: alg: OFB
+depends_on:PSA_WANT_ALG_OFB:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_OFB:0x0000:"4b":"505341004b455900000000000100000001100800010000000012c00400000000010000004b":0
+
+PSA storage read: alg2: OFB
+depends_on:PSA_WANT_ALG_OFB:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_OFB:"4c":"505341004b45590000000000010000000110080001000000000000000012c004010000004c":0
+
+PSA storage read: alg: PURE_EDDSA
+depends_on:PSA_WANT_ALG_PURE_EDDSA:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_PURE_EDDSA:0x0000:"4b":"505341004b455900000000000100000001100800010000000008000600000000010000004b":0
+
+PSA storage read: alg2: PURE_EDDSA
+depends_on:PSA_WANT_ALG_PURE_EDDSA:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_PURE_EDDSA:"4c":"505341004b455900000000000100000001100800010000000000000000080006010000004c":0
+
+PSA storage read: alg: RIPEMD160
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RIPEMD160:0x0000:"4b":"505341004b455900000000000100000001100800010000000400000200000000010000004b":0
+
+PSA storage read: alg2: RIPEMD160
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RIPEMD160:"4c":"505341004b455900000000000100000001100800010000000000000004000002010000004c":0
+
+PSA storage read: alg: RSA_OAEP(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000103000700000000010000004b":0
+
+PSA storage read: alg2: RSA_OAEP(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001030007010000004c":0
+
+PSA storage read: alg: RSA_OAEP(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000203000700000000010000004b":0
+
+PSA storage read: alg2: RSA_OAEP(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002030007010000004c":0
+
+PSA storage read: alg: RSA_OAEP(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000303000700000000010000004b":0
+
+PSA storage read: alg2: RSA_OAEP(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003030007010000004c":0
+
+PSA storage read: alg: RSA_OAEP(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000403000700000000010000004b":0
+
+PSA storage read: alg2: RSA_OAEP(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004030007010000004c":0
+
+PSA storage read: alg: RSA_OAEP(SHA_1)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000503000700000000010000004b":0
+
+PSA storage read: alg2: RSA_OAEP(SHA_1)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005030007010000004c":0
+
+PSA storage read: alg: RSA_OAEP(SHA_224)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000803000700000000010000004b":0
+
+PSA storage read: alg2: RSA_OAEP(SHA_224)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008030007010000004c":0
+
+PSA storage read: alg: RSA_OAEP(SHA_256)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000903000700000000010000004b":0
+
+PSA storage read: alg2: RSA_OAEP(SHA_256)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009030007010000004c":0
+
+PSA storage read: alg: RSA_OAEP(SHA_384)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a03000700000000010000004b":0
+
+PSA storage read: alg2: RSA_OAEP(SHA_384)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a030007010000004c":0
+
+PSA storage read: alg: RSA_OAEP(SHA_512)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b03000700000000010000004b":0
+
+PSA storage read: alg2: RSA_OAEP(SHA_512)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b030007010000004c":0
+
+PSA storage read: alg: RSA_PKCS1V15_CRYPT
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_CRYPT:0x0000:"4b":"505341004b455900000000000100000001100800010000000002000700000000010000004b":0
+
+PSA storage read: alg2: RSA_PKCS1V15_CRYPT
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_CRYPT:"4c":"505341004b455900000000000100000001100800010000000000000000020007010000004c":0
+
+PSA storage read: alg: RSA_PKCS1V15_SIGN(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000102000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PKCS1V15_SIGN(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001020006010000004c":0
+
+PSA storage read: alg: RSA_PKCS1V15_SIGN(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000202000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PKCS1V15_SIGN(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002020006010000004c":0
+
+PSA storage read: alg: RSA_PKCS1V15_SIGN(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000302000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PKCS1V15_SIGN(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003020006010000004c":0
+
+PSA storage read: alg: RSA_PKCS1V15_SIGN(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000402000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PKCS1V15_SIGN(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004020006010000004c":0
+
+PSA storage read: alg: RSA_PKCS1V15_SIGN(SHA_1)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000502000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PKCS1V15_SIGN(SHA_1)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005020006010000004c":0
+
+PSA storage read: alg: RSA_PKCS1V15_SIGN(SHA_224)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000802000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PKCS1V15_SIGN(SHA_224)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008020006010000004c":0
+
+PSA storage read: alg: RSA_PKCS1V15_SIGN(SHA_256)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000902000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PKCS1V15_SIGN(SHA_256)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009020006010000004c":0
+
+PSA storage read: alg: RSA_PKCS1V15_SIGN(SHA_384)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a02000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PKCS1V15_SIGN(SHA_384)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a020006010000004c":0
+
+PSA storage read: alg: RSA_PKCS1V15_SIGN(SHA_512)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b02000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PKCS1V15_SIGN(SHA_512)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b020006010000004c":0
+
+PSA storage read: alg: RSA_PKCS1V15_SIGN(ANY_HASH)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):0x0000:"4b":"505341004b45590000000000010000000110080001000000ff02000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PKCS1V15_SIGN(ANY_HASH)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):"4c":"505341004b4559000000000001000000011008000100000000000000ff020006010000004c":0
+
+PSA storage read: alg: RSA_PKCS1V15_SIGN_RAW
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0x0000:"4b":"505341004b455900000000000100000001100800010000000002000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PKCS1V15_SIGN_RAW
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"4c":"505341004b455900000000000100000001100800010000000000000000020006010000004c":0
+
+PSA storage read: alg: RSA_PSS(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000103000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001030006010000004c":0
+
+PSA storage read: alg: RSA_PSS(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000203000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002030006010000004c":0
+
+PSA storage read: alg: RSA_PSS(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000303000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003030006010000004c":0
+
+PSA storage read: alg: RSA_PSS(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000403000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004030006010000004c":0
+
+PSA storage read: alg: RSA_PSS(SHA_1)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000503000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS(SHA_1)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005030006010000004c":0
+
+PSA storage read: alg: RSA_PSS(SHA_224)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000803000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS(SHA_224)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008030006010000004c":0
+
+PSA storage read: alg: RSA_PSS(SHA_256)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000903000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS(SHA_256)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009030006010000004c":0
+
+PSA storage read: alg: RSA_PSS(SHA_384)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a03000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS(SHA_384)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a030006010000004c":0
+
+PSA storage read: alg: RSA_PSS(SHA_512)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b03000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS(SHA_512)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b030006010000004c":0
+
+PSA storage read: alg: RSA_PSS(ANY_HASH)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):0x0000:"4b":"505341004b45590000000000010000000110080001000000ff03000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS(ANY_HASH)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):"4c":"505341004b4559000000000001000000011008000100000000000000ff030006010000004c":0
+
+PSA storage read: alg: RSA_PSS_ANY_SALT(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000113000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS_ANY_SALT(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001130006010000004c":0
+
+PSA storage read: alg: RSA_PSS_ANY_SALT(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000213000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS_ANY_SALT(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002130006010000004c":0
+
+PSA storage read: alg: RSA_PSS_ANY_SALT(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000313000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS_ANY_SALT(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003130006010000004c":0
+
+PSA storage read: alg: RSA_PSS_ANY_SALT(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000413000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS_ANY_SALT(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004130006010000004c":0
+
+PSA storage read: alg: RSA_PSS_ANY_SALT(SHA_1)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000513000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS_ANY_SALT(SHA_1)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005130006010000004c":0
+
+PSA storage read: alg: RSA_PSS_ANY_SALT(SHA_224)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000813000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS_ANY_SALT(SHA_224)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008130006010000004c":0
+
+PSA storage read: alg: RSA_PSS_ANY_SALT(SHA_256)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000913000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS_ANY_SALT(SHA_256)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009130006010000004c":0
+
+PSA storage read: alg: RSA_PSS_ANY_SALT(SHA_384)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a13000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS_ANY_SALT(SHA_384)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a130006010000004c":0
+
+PSA storage read: alg: RSA_PSS_ANY_SALT(SHA_512)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b13000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS_ANY_SALT(SHA_512)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b130006010000004c":0
+
+PSA storage read: alg: RSA_PSS_ANY_SALT(ANY_HASH)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH):0x0000:"4b":"505341004b45590000000000010000000110080001000000ff13000600000000010000004b":0
+
+PSA storage read: alg2: RSA_PSS_ANY_SALT(ANY_HASH)
+depends_on:PSA_WANT_ALG_RSA_PSS_ANY_SALT:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH):"4c":"505341004b4559000000000001000000011008000100000000000000ff130006010000004c":0
+
+PSA storage read: alg: SHA3_224
+depends_on:PSA_WANT_ALG_SHA3_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA3_224:0x0000:"4b":"505341004b455900000000000100000001100800010000001000000200000000010000004b":0
+
+PSA storage read: alg2: SHA3_224
+depends_on:PSA_WANT_ALG_SHA3_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA3_224:"4c":"505341004b455900000000000100000001100800010000000000000010000002010000004c":0
+
+PSA storage read: alg: SHA3_256
+depends_on:PSA_WANT_ALG_SHA3_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA3_256:0x0000:"4b":"505341004b455900000000000100000001100800010000001100000200000000010000004b":0
+
+PSA storage read: alg2: SHA3_256
+depends_on:PSA_WANT_ALG_SHA3_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA3_256:"4c":"505341004b455900000000000100000001100800010000000000000011000002010000004c":0
+
+PSA storage read: alg: SHA3_384
+depends_on:PSA_WANT_ALG_SHA3_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA3_384:0x0000:"4b":"505341004b455900000000000100000001100800010000001200000200000000010000004b":0
+
+PSA storage read: alg2: SHA3_384
+depends_on:PSA_WANT_ALG_SHA3_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA3_384:"4c":"505341004b455900000000000100000001100800010000000000000012000002010000004c":0
+
+PSA storage read: alg: SHA3_512
+depends_on:PSA_WANT_ALG_SHA3_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA3_512:0x0000:"4b":"505341004b455900000000000100000001100800010000001300000200000000010000004b":0
+
+PSA storage read: alg2: SHA3_512
+depends_on:PSA_WANT_ALG_SHA3_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA3_512:"4c":"505341004b455900000000000100000001100800010000000000000013000002010000004c":0
+
+PSA storage read: alg: SHAKE256_512
+depends_on:PSA_WANT_ALG_SHAKE256_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHAKE256_512:0x0000:"4b":"505341004b455900000000000100000001100800010000001500000200000000010000004b":0
+
+PSA storage read: alg2: SHAKE256_512
+depends_on:PSA_WANT_ALG_SHAKE256_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHAKE256_512:"4c":"505341004b455900000000000100000001100800010000000000000015000002010000004c":0
+
+PSA storage read: alg: SHA_1
+depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA_1:0x0000:"4b":"505341004b455900000000000100000001100800010000000500000200000000010000004b":0
+
+PSA storage read: alg2: SHA_1
+depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA_1:"4c":"505341004b455900000000000100000001100800010000000000000005000002010000004c":0
+
+PSA storage read: alg: SHA_224
+depends_on:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA_224:0x0000:"4b":"505341004b455900000000000100000001100800010000000800000200000000010000004b":0
+
+PSA storage read: alg2: SHA_224
+depends_on:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA_224:"4c":"505341004b455900000000000100000001100800010000000000000008000002010000004c":0
+
+PSA storage read: alg: SHA_256
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA_256:0x0000:"4b":"505341004b455900000000000100000001100800010000000900000200000000010000004b":0
+
+PSA storage read: alg2: SHA_256
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA_256:"4c":"505341004b455900000000000100000001100800010000000000000009000002010000004c":0
+
+PSA storage read: alg: SHA_384
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA_384:0x0000:"4b":"505341004b455900000000000100000001100800010000000a00000200000000010000004b":0
+
+PSA storage read: alg2: SHA_384
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA_384:"4c":"505341004b45590000000000010000000110080001000000000000000a000002010000004c":0
+
+PSA storage read: alg: SHA_512
+depends_on:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA_512:0x0000:"4b":"505341004b455900000000000100000001100800010000000b00000200000000010000004b":0
+
+PSA storage read: alg2: SHA_512
+depends_on:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA_512:"4c":"505341004b45590000000000010000000110080001000000000000000b000002010000004c":0
+
+PSA storage read: alg: SHA_512_224
+depends_on:PSA_WANT_ALG_SHA_512_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA_512_224:0x0000:"4b":"505341004b455900000000000100000001100800010000000c00000200000000010000004b":0
+
+PSA storage read: alg2: SHA_512_224
+depends_on:PSA_WANT_ALG_SHA_512_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA_512_224:"4c":"505341004b45590000000000010000000110080001000000000000000c000002010000004c":0
+
+PSA storage read: alg: SHA_512_256
+depends_on:PSA_WANT_ALG_SHA_512_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_SHA_512_256:0x0000:"4b":"505341004b455900000000000100000001100800010000000d00000200000000010000004b":0
+
+PSA storage read: alg2: SHA_512_256
+depends_on:PSA_WANT_ALG_SHA_512_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_SHA_512_256:"4c":"505341004b45590000000000010000000110080001000000000000000d000002010000004c":0
+
+PSA storage read: alg: STREAM_CIPHER
+depends_on:PSA_WANT_ALG_STREAM_CIPHER:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_STREAM_CIPHER:0x0000:"4b":"505341004b455900000000000100000001100800010000000001800400000000010000004b":0
+
+PSA storage read: alg2: STREAM_CIPHER
+depends_on:PSA_WANT_ALG_STREAM_CIPHER:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_STREAM_CIPHER:"4c":"505341004b455900000000000100000001100800010000000000000000018004010000004c":0
+
+PSA storage read: alg: TLS12_PRF(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000102000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PRF(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001020008010000004c":0
+
+PSA storage read: alg: TLS12_PRF(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000202000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PRF(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002020008010000004c":0
+
+PSA storage read: alg: TLS12_PRF(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000302000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PRF(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003020008010000004c":0
+
+PSA storage read: alg: TLS12_PRF(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000402000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PRF(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004020008010000004c":0
+
+PSA storage read: alg: TLS12_PRF(SHA_1)
+depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000502000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PRF(SHA_1)
+depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005020008010000004c":0
+
+PSA storage read: alg: TLS12_PRF(SHA_224)
+depends_on:PSA_WANT_ALG_SHA_224:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000802000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PRF(SHA_224)
+depends_on:PSA_WANT_ALG_SHA_224:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008020008010000004c":0
+
+PSA storage read: alg: TLS12_PRF(SHA_256)
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000902000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PRF(SHA_256)
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009020008010000004c":0
+
+PSA storage read: alg: TLS12_PRF(SHA_384)
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a02000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PRF(SHA_384)
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a020008010000004c":0
+
+PSA storage read: alg: TLS12_PRF(SHA_512)
+depends_on:PSA_WANT_ALG_SHA_512:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b02000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PRF(SHA_512)
+depends_on:PSA_WANT_ALG_SHA_512:PSA_WANT_ALG_TLS12_PRF:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b020008010000004c":0
+
+PSA storage read: alg: TLS12_PSK_TO_MS(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_MD2):0x0000:"4b":"505341004b455900000000000100000001100800010000000103000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PSK_TO_MS(MD2)
+depends_on:PSA_WANT_ALG_MD2:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_MD2):"4c":"505341004b455900000000000100000001100800010000000000000001030008010000004c":0
+
+PSA storage read: alg: TLS12_PSK_TO_MS(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_MD4):0x0000:"4b":"505341004b455900000000000100000001100800010000000203000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PSK_TO_MS(MD4)
+depends_on:PSA_WANT_ALG_MD4:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_MD4):"4c":"505341004b455900000000000100000001100800010000000000000002030008010000004c":0
+
+PSA storage read: alg: TLS12_PSK_TO_MS(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_MD5):0x0000:"4b":"505341004b455900000000000100000001100800010000000303000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PSK_TO_MS(MD5)
+depends_on:PSA_WANT_ALG_MD5:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_MD5):"4c":"505341004b455900000000000100000001100800010000000000000003030008010000004c":0
+
+PSA storage read: alg: TLS12_PSK_TO_MS(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_RIPEMD160):0x0000:"4b":"505341004b455900000000000100000001100800010000000403000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PSK_TO_MS(RIPEMD160)
+depends_on:PSA_WANT_ALG_RIPEMD160:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_RIPEMD160):"4c":"505341004b455900000000000100000001100800010000000000000004030008010000004c":0
+
+PSA storage read: alg: TLS12_PSK_TO_MS(SHA_1)
+depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_1):0x0000:"4b":"505341004b455900000000000100000001100800010000000503000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PSK_TO_MS(SHA_1)
+depends_on:PSA_WANT_ALG_SHA_1:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_1):"4c":"505341004b455900000000000100000001100800010000000000000005030008010000004c":0
+
+PSA storage read: alg: TLS12_PSK_TO_MS(SHA_224)
+depends_on:PSA_WANT_ALG_SHA_224:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_224):0x0000:"4b":"505341004b455900000000000100000001100800010000000803000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PSK_TO_MS(SHA_224)
+depends_on:PSA_WANT_ALG_SHA_224:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_224):"4c":"505341004b455900000000000100000001100800010000000000000008030008010000004c":0
+
+PSA storage read: alg: TLS12_PSK_TO_MS(SHA_256)
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):0x0000:"4b":"505341004b455900000000000100000001100800010000000903000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PSK_TO_MS(SHA_256)
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"4c":"505341004b455900000000000100000001100800010000000000000009030008010000004c":0
+
+PSA storage read: alg: TLS12_PSK_TO_MS(SHA_384)
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384):0x0000:"4b":"505341004b455900000000000100000001100800010000000a03000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PSK_TO_MS(SHA_384)
+depends_on:PSA_WANT_ALG_SHA_384:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384):"4c":"505341004b45590000000000010000000110080001000000000000000a030008010000004c":0
+
+PSA storage read: alg: TLS12_PSK_TO_MS(SHA_512)
+depends_on:PSA_WANT_ALG_SHA_512:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_512):0x0000:"4b":"505341004b455900000000000100000001100800010000000b03000800000000010000004b":0
+
+PSA storage read: alg2: TLS12_PSK_TO_MS(SHA_512)
+depends_on:PSA_WANT_ALG_SHA_512:PSA_WANT_ALG_TLS12_PSK_TO_MS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_512):"4c":"505341004b45590000000000010000000110080001000000000000000b030008010000004c":0
+
+PSA storage read: alg: TRUNCATED_MAC(CBC_MAC, 1)
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_CBC_MAC, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000001c10300000000010000004b":0
+
+PSA storage read: alg2: TRUNCATED_MAC(CBC_MAC, 1)
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_CBC_MAC, 1):"4c":"505341004b45590000000000010000000110080001000000000000000001c103010000004c":0
+
+PSA storage read: alg: TRUNCATED_MAC(CMAC, 1)
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000002c10300000000010000004b":0
+
+PSA storage read: alg2: TRUNCATED_MAC(CMAC, 1)
+depends_on:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, 1):"4c":"505341004b45590000000000010000000110080001000000000000000002c103010000004c":0
+
+PSA storage read: alg: TRUNCATED_MAC(HMAC(MD2), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_MD2), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000100810300000000010000004b":0
+
+PSA storage read: alg2: TRUNCATED_MAC(HMAC(MD2), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_MD2), 1):"4c":"505341004b455900000000000100000001100800010000000000000001008103010000004c":0
+
+PSA storage read: alg: TRUNCATED_MAC(HMAC(MD4), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_MD4), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000200810300000000010000004b":0
+
+PSA storage read: alg2: TRUNCATED_MAC(HMAC(MD4), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_MD4), 1):"4c":"505341004b455900000000000100000001100800010000000000000002008103010000004c":0
+
+PSA storage read: alg: TRUNCATED_MAC(HMAC(MD5), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_MD5), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000300810300000000010000004b":0
+
+PSA storage read: alg2: TRUNCATED_MAC(HMAC(MD5), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_MD5), 1):"4c":"505341004b455900000000000100000001100800010000000000000003008103010000004c":0
+
+PSA storage read: alg: TRUNCATED_MAC(HMAC(RIPEMD160), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_RIPEMD160), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000400810300000000010000004b":0
+
+PSA storage read: alg2: TRUNCATED_MAC(HMAC(RIPEMD160), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_RIPEMD160), 1):"4c":"505341004b455900000000000100000001100800010000000000000004008103010000004c":0
+
+PSA storage read: alg: TRUNCATED_MAC(HMAC(SHA_1), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_1), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000500810300000000010000004b":0
+
+PSA storage read: alg2: TRUNCATED_MAC(HMAC(SHA_1), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_1), 1):"4c":"505341004b455900000000000100000001100800010000000000000005008103010000004c":0
+
+PSA storage read: alg: TRUNCATED_MAC(HMAC(SHA_224), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_224), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000800810300000000010000004b":0
+
+PSA storage read: alg2: TRUNCATED_MAC(HMAC(SHA_224), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_224), 1):"4c":"505341004b455900000000000100000001100800010000000000000008008103010000004c":0
+
+PSA storage read: alg: TRUNCATED_MAC(HMAC(SHA_256), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000900810300000000010000004b":0
+
+PSA storage read: alg2: TRUNCATED_MAC(HMAC(SHA_256), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_256), 1):"4c":"505341004b455900000000000100000001100800010000000000000009008103010000004c":0
+
+PSA storage read: alg: TRUNCATED_MAC(HMAC(SHA_384), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_384), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000a00810300000000010000004b":0
+
+PSA storage read: alg2: TRUNCATED_MAC(HMAC(SHA_384), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_384), 1):"4c":"505341004b45590000000000010000000110080001000000000000000a008103010000004c":0
+
+PSA storage read: alg: TRUNCATED_MAC(HMAC(SHA_512), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_512), 1):0x0000:"4b":"505341004b455900000000000100000001100800010000000b00810300000000010000004b":0
+
+PSA storage read: alg2: TRUNCATED_MAC(HMAC(SHA_512), 1)
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(PSA_ALG_SHA_512), 1):"4c":"505341004b45590000000000010000000110080001000000000000000b008103010000004c":0
+
+PSA storage read: alg: TRUNCATED_MAC(CBC_MAC, 63)
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_TRUNCATED_MAC(PSA_ALG_CBC_MAC, 63):0x0000:"4b":"505341004b455900000000000100000001100800010000000001ff0300000000010000004b":0
+
+PSA storage read: alg2: TRUNCATED_MAC(CBC_MAC, 63)
+depends_on:PSA_WANT_ALG_CBC_MAC:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_TRUNCATED_MAC(PSA_ALG_CBC_MAC, 63):"4c":"505341004b45590000000000010000000110080001000000000000000001ff03010000004c":0
+
+PSA storage read: alg: XTS
+depends_on:PSA_WANT_ALG_XTS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:PSA_ALG_XTS:0x0000:"4b":"505341004b4559000000000001000000011008000100000000ff400400000000010000004b":0
+
+PSA storage read: alg2: XTS
+depends_on:PSA_WANT_ALG_XTS:PSA_WANT_KEY_TYPE_RAW_DATA
+key_storage_read:0x0001:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0x0000:PSA_ALG_XTS:"4c":"505341004b455900000000000100000001100800010000000000000000ff4004010000004c":0
+
+PSA storage read: implied by SIGN_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_KEY_PAIR(BRAINPOOL_P_R1) 160-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_BRAINPOOL_P_R1_160:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):160:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"69502c4fdaf48d4fa617bdd24498b0406d0eeaac":"505341004b45590000000000010000003071a0000110000009070006000000001400000069502c4fdaf48d4fa617bdd24498b0406d0eeaac":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by SIGN_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_KEY_PAIR(SECP_K1) 192-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_K1_192:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):192:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"297ac1722ccac7589ecb240dc719842538ca974beb79f228":"505341004b45590000000000010000001771c00001100000090700060000000018000000297ac1722ccac7589ecb240dc719842538ca974beb79f228":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by SIGN_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_KEY_PAIR(SECP_R1) 225-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R1_225:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):225:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"872f203b3ad35b7f2ecc803c3a0e1e0b1ed61cc1afe71b189cd4c995":"505341004b45590000000000010000001271e1000110000009070006000000001c000000872f203b3ad35b7f2ecc803c3a0e1e0b1ed61cc1afe71b189cd4c995":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by SIGN_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_KEY_PAIR(SECP_R2) 160-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R2_160:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R2):160:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"00bf539a1cdda0d7f71a50a3f98aec0a2e8e4ced1e":"505341004b45590000000000010000001b71a0000110000009070006000000001500000000bf539a1cdda0d7f71a50a3f98aec0a2e8e4ced1e":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by SIGN_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_KEY_PAIR(SECT_K1) 163-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_K1_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"03ebc8fcded2d6ab72ec0f75bdb4fd080481273e71":"505341004b45590000000000010000002771a3000110000009070006000000001500000003ebc8fcded2d6ab72ec0f75bdb4fd080481273e71":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by SIGN_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_KEY_PAIR(SECT_R1) 163-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_R1_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"009b05dc82d46d64a04a22e6e5ca70ca1231e68c50":"505341004b45590000000000010000002271a30001100000090700060000000015000000009b05dc82d46d64a04a22e6e5ca70ca1231e68c50":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by SIGN_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_KEY_PAIR(SECT_R2) 163-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_R2_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R2):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"0210b482a458b4822d0cb21daa96819a67c8062d34":"505341004b45590000000000010000002b71a300011000000907000600000000150000000210b482a458b4822d0cb21daa96819a67c8062d34":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by SIGN_HASH: ECDSA(SHA_256) ECC_KEY_PAIR(BRAINPOOL_P_R1) 160-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_BRAINPOOL_P_R1_160:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):160:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"69502c4fdaf48d4fa617bdd24498b0406d0eeaac":"505341004b45590000000000010000003071a0000110000009060006000000001400000069502c4fdaf48d4fa617bdd24498b0406d0eeaac":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by SIGN_HASH: ECDSA(SHA_256) ECC_KEY_PAIR(SECP_K1) 192-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_K1_192:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):192:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"297ac1722ccac7589ecb240dc719842538ca974beb79f228":"505341004b45590000000000010000001771c00001100000090600060000000018000000297ac1722ccac7589ecb240dc719842538ca974beb79f228":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by SIGN_HASH: ECDSA(SHA_256) ECC_KEY_PAIR(SECP_R1) 225-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R1_225:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):225:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"872f203b3ad35b7f2ecc803c3a0e1e0b1ed61cc1afe71b189cd4c995":"505341004b45590000000000010000001271e1000110000009060006000000001c000000872f203b3ad35b7f2ecc803c3a0e1e0b1ed61cc1afe71b189cd4c995":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by SIGN_HASH: ECDSA(SHA_256) ECC_KEY_PAIR(SECP_R2) 160-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R2_160:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R2):160:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"00bf539a1cdda0d7f71a50a3f98aec0a2e8e4ced1e":"505341004b45590000000000010000001b71a0000110000009060006000000001500000000bf539a1cdda0d7f71a50a3f98aec0a2e8e4ced1e":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by SIGN_HASH: ECDSA(SHA_256) ECC_KEY_PAIR(SECT_K1) 163-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_K1_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"03ebc8fcded2d6ab72ec0f75bdb4fd080481273e71":"505341004b45590000000000010000002771a3000110000009060006000000001500000003ebc8fcded2d6ab72ec0f75bdb4fd080481273e71":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by SIGN_HASH: ECDSA(SHA_256) ECC_KEY_PAIR(SECT_R1) 163-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_R1_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"009b05dc82d46d64a04a22e6e5ca70ca1231e68c50":"505341004b45590000000000010000002271a30001100000090600060000000015000000009b05dc82d46d64a04a22e6e5ca70ca1231e68c50":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by SIGN_HASH: ECDSA(SHA_256) ECC_KEY_PAIR(SECT_R2) 163-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_R2_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R2):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"0210b482a458b4822d0cb21daa96819a67c8062d34":"505341004b45590000000000010000002b71a300011000000906000600000000150000000210b482a458b4822d0cb21daa96819a67c8062d34":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by SIGN_HASH: ED25519PH ECC_KEY_PAIR(TWISTED_EDWARDS) 255-bit
+depends_on:PSA_WANT_ALG_ED25519PH:PSA_WANT_ECC_TWISTED_EDWARDS_255:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):255:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ED25519PH:0x0000:"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60":"505341004b45590000000000010000004271ff00011000000b09000600000000200000009d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by SIGN_HASH: ED448PH ECC_KEY_PAIR(TWISTED_EDWARDS) 255-bit
+depends_on:PSA_WANT_ALG_ED448PH:PSA_WANT_ECC_TWISTED_EDWARDS_255:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):255:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ED448PH:0x0000:"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60":"505341004b45590000000000010000004271ff00011000001509000600000000200000009d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by SIGN_HASH: RSA_PKCS1V15_SIGN(SHA_256) RSA_KEY_PAIR 1024-bit
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0x0000:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"505341004b455900000000000100000001700004011000000902000600000000620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by SIGN_HASH: RSA_PSS(SHA_256) RSA_KEY_PAIR 1024-bit
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0x0000:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"505341004b455900000000000100000001700004011000000903000600000000620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_KEY_PAIR(BRAINPOOL_P_R1) 160-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_BRAINPOOL_P_R1_160:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):160:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"69502c4fdaf48d4fa617bdd24498b0406d0eeaac":"505341004b45590000000000010000003071a0000120000009070006000000001400000069502c4fdaf48d4fa617bdd24498b0406d0eeaac":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_KEY_PAIR(SECP_K1) 192-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_K1_192:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):192:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"297ac1722ccac7589ecb240dc719842538ca974beb79f228":"505341004b45590000000000010000001771c00001200000090700060000000018000000297ac1722ccac7589ecb240dc719842538ca974beb79f228":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_KEY_PAIR(SECP_R1) 225-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R1_225:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):225:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"872f203b3ad35b7f2ecc803c3a0e1e0b1ed61cc1afe71b189cd4c995":"505341004b45590000000000010000001271e1000120000009070006000000001c000000872f203b3ad35b7f2ecc803c3a0e1e0b1ed61cc1afe71b189cd4c995":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_KEY_PAIR(SECP_R2) 160-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R2_160:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R2):160:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"00bf539a1cdda0d7f71a50a3f98aec0a2e8e4ced1e":"505341004b45590000000000010000001b71a0000120000009070006000000001500000000bf539a1cdda0d7f71a50a3f98aec0a2e8e4ced1e":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_KEY_PAIR(SECT_K1) 163-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_K1_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"03ebc8fcded2d6ab72ec0f75bdb4fd080481273e71":"505341004b45590000000000010000002771a3000120000009070006000000001500000003ebc8fcded2d6ab72ec0f75bdb4fd080481273e71":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_KEY_PAIR(SECT_R1) 163-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_R1_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"009b05dc82d46d64a04a22e6e5ca70ca1231e68c50":"505341004b45590000000000010000002271a30001200000090700060000000015000000009b05dc82d46d64a04a22e6e5ca70ca1231e68c50":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_KEY_PAIR(SECT_R2) 163-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_R2_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R2):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"0210b482a458b4822d0cb21daa96819a67c8062d34":"505341004b45590000000000010000002b71a300012000000907000600000000150000000210b482a458b4822d0cb21daa96819a67c8062d34":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 160-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_BRAINPOOL_P_R1_160:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):160:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"04d4b9186816358e2f9c59cf70748cb70641b22fbab65473db4b4e22a361ed7e3de7e8a8ddc4130c5c":"505341004b45590000000000010000003041a0000120000009070006000000002900000004d4b9186816358e2f9c59cf70748cb70641b22fbab65473db4b4e22a361ed7e3de7e8a8ddc4130c5c":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_PUBLIC_KEY(SECP_K1) 192-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_K1_192:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_K1):192:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"0426b7bb38da649ac2138fc050c6548b32553dab68afebc36105d325b75538c12323cb0764789ecb992671beb2b6bef2f5":"505341004b45590000000000010000001741c000012000000907000600000000310000000426b7bb38da649ac2138fc050c6548b32553dab68afebc36105d325b75538c12323cb0764789ecb992671beb2b6bef2f5":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_PUBLIC_KEY(SECP_R1) 225-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R1_225:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):225:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"046f00eadaa949fee3e9e1c7fa1247eecec86a0dce46418b9bd3117b981d4bd0ae7a990de912f9d060d6cb531a42d22e394ac29e81804bf160":"505341004b45590000000000010000001241e10001200000090700060000000039000000046f00eadaa949fee3e9e1c7fa1247eecec86a0dce46418b9bd3117b981d4bd0ae7a990de912f9d060d6cb531a42d22e394ac29e81804bf160":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_PUBLIC_KEY(SECP_R2) 160-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R2_160:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R2):160:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"049570d541398665adb5cfa16f5af73b3196926bbd4b876bdb80f8eab20d0f540c22f4de9c140f6d7b":"505341004b45590000000000010000001b41a00001200000090700060000000029000000049570d541398665adb5cfa16f5af73b3196926bbd4b876bdb80f8eab20d0f540c22f4de9c140f6d7b":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_PUBLIC_KEY(SECT_K1) 163-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_K1_163:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"0406f88f90b4b65950f06ce433afdb097e320f433dc2062b8a65db8fafd3c110f46bc45663fbf021ee7eb9":"505341004b45590000000000010000002741a3000120000009070006000000002b0000000406f88f90b4b65950f06ce433afdb097e320f433dc2062b8a65db8fafd3c110f46bc45663fbf021ee7eb9":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_PUBLIC_KEY(SECT_R1) 163-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_R1_163:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"0400465eeb9e7258b11e33c02266bfe834b20bcb118700772796ee4704ec67651bd447e3011959a79a04cb":"505341004b45590000000000010000002241a3000120000009070006000000002b0000000400465eeb9e7258b11e33c02266bfe834b20bcb118700772796ee4704ec67651bd447e3011959a79a04cb":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: DETERMINISTIC_ECDSA(SHA_256) ECC_PUBLIC_KEY(SECT_R2) 163-bit
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_R2_163:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R2):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0x0000:"0403692601144c32a6cfa369ae20ae5d43c1c764678c037bafe80c6fd2e42b7ced96171d9c5367fd3dca6f":"505341004b45590000000000010000002b41a3000120000009070006000000002b0000000403692601144c32a6cfa369ae20ae5d43c1c764678c037bafe80c6fd2e42b7ced96171d9c5367fd3dca6f":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ECDSA(SHA_256) ECC_KEY_PAIR(BRAINPOOL_P_R1) 160-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_BRAINPOOL_P_R1_160:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):160:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"69502c4fdaf48d4fa617bdd24498b0406d0eeaac":"505341004b45590000000000010000003071a0000120000009060006000000001400000069502c4fdaf48d4fa617bdd24498b0406d0eeaac":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ECDSA(SHA_256) ECC_KEY_PAIR(SECP_K1) 192-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_K1_192:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):192:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"297ac1722ccac7589ecb240dc719842538ca974beb79f228":"505341004b45590000000000010000001771c00001200000090600060000000018000000297ac1722ccac7589ecb240dc719842538ca974beb79f228":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ECDSA(SHA_256) ECC_KEY_PAIR(SECP_R1) 225-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R1_225:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):225:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"872f203b3ad35b7f2ecc803c3a0e1e0b1ed61cc1afe71b189cd4c995":"505341004b45590000000000010000001271e1000120000009060006000000001c000000872f203b3ad35b7f2ecc803c3a0e1e0b1ed61cc1afe71b189cd4c995":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ECDSA(SHA_256) ECC_KEY_PAIR(SECP_R2) 160-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R2_160:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R2):160:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"00bf539a1cdda0d7f71a50a3f98aec0a2e8e4ced1e":"505341004b45590000000000010000001b71a0000120000009060006000000001500000000bf539a1cdda0d7f71a50a3f98aec0a2e8e4ced1e":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ECDSA(SHA_256) ECC_KEY_PAIR(SECT_K1) 163-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_K1_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_K1):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"03ebc8fcded2d6ab72ec0f75bdb4fd080481273e71":"505341004b45590000000000010000002771a3000120000009060006000000001500000003ebc8fcded2d6ab72ec0f75bdb4fd080481273e71":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ECDSA(SHA_256) ECC_KEY_PAIR(SECT_R1) 163-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_R1_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R1):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"009b05dc82d46d64a04a22e6e5ca70ca1231e68c50":"505341004b45590000000000010000002271a30001200000090600060000000015000000009b05dc82d46d64a04a22e6e5ca70ca1231e68c50":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ECDSA(SHA_256) ECC_KEY_PAIR(SECT_R2) 163-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_R2_163:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECT_R2):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"0210b482a458b4822d0cb21daa96819a67c8062d34":"505341004b45590000000000010000002b71a300012000000906000600000000150000000210b482a458b4822d0cb21daa96819a67c8062d34":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ECDSA(SHA_256) ECC_PUBLIC_KEY(BRAINPOOL_P_R1) 160-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_BRAINPOOL_P_R1_160:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):160:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"04d4b9186816358e2f9c59cf70748cb70641b22fbab65473db4b4e22a361ed7e3de7e8a8ddc4130c5c":"505341004b45590000000000010000003041a0000120000009060006000000002900000004d4b9186816358e2f9c59cf70748cb70641b22fbab65473db4b4e22a361ed7e3de7e8a8ddc4130c5c":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ECDSA(SHA_256) ECC_PUBLIC_KEY(SECP_K1) 192-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_K1_192:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_K1):192:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"0426b7bb38da649ac2138fc050c6548b32553dab68afebc36105d325b75538c12323cb0764789ecb992671beb2b6bef2f5":"505341004b45590000000000010000001741c000012000000906000600000000310000000426b7bb38da649ac2138fc050c6548b32553dab68afebc36105d325b75538c12323cb0764789ecb992671beb2b6bef2f5":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ECDSA(SHA_256) ECC_PUBLIC_KEY(SECP_R1) 225-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R1_225:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):225:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"046f00eadaa949fee3e9e1c7fa1247eecec86a0dce46418b9bd3117b981d4bd0ae7a990de912f9d060d6cb531a42d22e394ac29e81804bf160":"505341004b45590000000000010000001241e10001200000090600060000000039000000046f00eadaa949fee3e9e1c7fa1247eecec86a0dce46418b9bd3117b981d4bd0ae7a990de912f9d060d6cb531a42d22e394ac29e81804bf160":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ECDSA(SHA_256) ECC_PUBLIC_KEY(SECP_R2) 160-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECP_R2_160:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R2):160:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"049570d541398665adb5cfa16f5af73b3196926bbd4b876bdb80f8eab20d0f540c22f4de9c140f6d7b":"505341004b45590000000000010000001b41a00001200000090600060000000029000000049570d541398665adb5cfa16f5af73b3196926bbd4b876bdb80f8eab20d0f540c22f4de9c140f6d7b":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ECDSA(SHA_256) ECC_PUBLIC_KEY(SECT_K1) 163-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_K1_163:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_K1):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"0406f88f90b4b65950f06ce433afdb097e320f433dc2062b8a65db8fafd3c110f46bc45663fbf021ee7eb9":"505341004b45590000000000010000002741a3000120000009060006000000002b0000000406f88f90b4b65950f06ce433afdb097e320f433dc2062b8a65db8fafd3c110f46bc45663fbf021ee7eb9":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ECDSA(SHA_256) ECC_PUBLIC_KEY(SECT_R1) 163-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_R1_163:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R1):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"0400465eeb9e7258b11e33c02266bfe834b20bcb118700772796ee4704ec67651bd447e3011959a79a04cb":"505341004b45590000000000010000002241a3000120000009060006000000002b0000000400465eeb9e7258b11e33c02266bfe834b20bcb118700772796ee4704ec67651bd447e3011959a79a04cb":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ECDSA(SHA_256) ECC_PUBLIC_KEY(SECT_R2) 163-bit
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_ECC_SECT_R2_163:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECT_R2):163:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_SHA_256):0x0000:"0403692601144c32a6cfa369ae20ae5d43c1c764678c037bafe80c6fd2e42b7ced96171d9c5367fd3dca6f":"505341004b45590000000000010000002b41a3000120000009060006000000002b0000000403692601144c32a6cfa369ae20ae5d43c1c764678c037bafe80c6fd2e42b7ced96171d9c5367fd3dca6f":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ED25519PH ECC_KEY_PAIR(TWISTED_EDWARDS) 255-bit
+depends_on:PSA_WANT_ALG_ED25519PH:PSA_WANT_ECC_TWISTED_EDWARDS_255:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):255:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ED25519PH:0x0000:"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60":"505341004b45590000000000010000004271ff00012000000b09000600000000200000009d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ED25519PH ECC_PUBLIC_KEY(TWISTED_EDWARDS) 255-bit
+depends_on:PSA_WANT_ALG_ED25519PH:PSA_WANT_ECC_TWISTED_EDWARDS_255:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS):255:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ED25519PH:0x0000:"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a":"505341004b45590000000000010000004241ff00012000000b0900060000000020000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ED448PH ECC_KEY_PAIR(TWISTED_EDWARDS) 255-bit
+depends_on:PSA_WANT_ALG_ED448PH:PSA_WANT_ECC_TWISTED_EDWARDS_255:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS):255:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ED448PH:0x0000:"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60":"505341004b45590000000000010000004271ff00012000001509000600000000200000009d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: ED448PH ECC_PUBLIC_KEY(TWISTED_EDWARDS) 255-bit
+depends_on:PSA_WANT_ALG_ED448PH:PSA_WANT_ECC_TWISTED_EDWARDS_255:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS):255:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ED448PH:0x0000:"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a":"505341004b45590000000000010000004241ff0001200000150900060000000020000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: HMAC(MD2) HMAC 128-bit
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD2:PSA_WANT_KEY_TYPE_HMAC
+key_storage_read:0x0001:PSA_KEY_TYPE_HMAC:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_HMAC(PSA_ALG_MD2):0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000001180000120000001008003000000001000000048657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: HMAC(MD4) HMAC 128-bit
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD4:PSA_WANT_KEY_TYPE_HMAC
+key_storage_read:0x0001:PSA_KEY_TYPE_HMAC:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_HMAC(PSA_ALG_MD4):0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000001180000120000002008003000000001000000048657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: HMAC(MD5) HMAC 128-bit
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_MD5:PSA_WANT_KEY_TYPE_HMAC
+key_storage_read:0x0001:PSA_KEY_TYPE_HMAC:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_HMAC(PSA_ALG_MD5):0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000001180000120000003008003000000001000000048657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: HMAC(RIPEMD160) HMAC 128-bit
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_RIPEMD160:PSA_WANT_KEY_TYPE_HMAC
+key_storage_read:0x0001:PSA_KEY_TYPE_HMAC:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_HMAC(PSA_ALG_RIPEMD160):0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000001180000120000004008003000000001000000048657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: HMAC(SHA_1) HMAC 128-bit
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_1:PSA_WANT_KEY_TYPE_HMAC
+key_storage_read:0x0001:PSA_KEY_TYPE_HMAC:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_HMAC(PSA_ALG_SHA_1):0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000001180000120000005008003000000001000000048657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: HMAC(SHA_224) HMAC 128-bit
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_224:PSA_WANT_KEY_TYPE_HMAC
+key_storage_read:0x0001:PSA_KEY_TYPE_HMAC:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_HMAC(PSA_ALG_SHA_224):0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000001180000120000008008003000000001000000048657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: HMAC(SHA_256) HMAC 128-bit
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_HMAC
+key_storage_read:0x0001:PSA_KEY_TYPE_HMAC:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_HMAC(PSA_ALG_SHA_256):0x0000:"48657265006973206b6579a064617461":"505341004b4559000000000001000000001180000120000009008003000000001000000048657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: HMAC(SHA_384) HMAC 128-bit
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_HMAC
+key_storage_read:0x0001:PSA_KEY_TYPE_HMAC:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_HMAC(PSA_ALG_SHA_384):0x0000:"48657265006973206b6579a064617461":"505341004b455900000000000100000000118000012000000a008003000000001000000048657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: HMAC(SHA_512) HMAC 128-bit
+depends_on:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_512:PSA_WANT_KEY_TYPE_HMAC
+key_storage_read:0x0001:PSA_KEY_TYPE_HMAC:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_HMAC(PSA_ALG_SHA_512):0x0000:"48657265006973206b6579a064617461":"505341004b455900000000000100000000118000012000000b008003000000001000000048657265006973206b6579a064617461":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: RSA_PKCS1V15_SIGN(SHA_256) RSA_KEY_PAIR 1024-bit
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0x0000:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"505341004b455900000000000100000001700004012000000902000600000000620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: RSA_PKCS1V15_SIGN(SHA_256) RSA_PUBLIC_KEY 1024-bit
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0x0000:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":"505341004b4559000000000001000000014000040120000009020006000000008c00000030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: RSA_PSS(SHA_256) RSA_KEY_PAIR 1024-bit
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
+key_storage_read:0x0001:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0x0000:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":"505341004b455900000000000100000001700004012000000903000600000000620200003082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":TEST_FLAG_EXERCISE
+
+PSA storage read: implied by VERIFY_HASH: RSA_PSS(SHA_256) RSA_PUBLIC_KEY 1024-bit
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
+key_storage_read:0x0001:PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):0x0000:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":"505341004b4559000000000001000000014000040120000009030006000000008c00000030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":TEST_FLAG_EXERCISE
+
+# End of automatically generated file.
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_its.data b/third_party/mbedtls/repo/tests/suites/test_suite_psa_its.data
index 63ca129..9057a1a 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_its.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_its.data
@@ -63,3 +63,9 @@
 
 Get 1 byte of 10 at -1: out of range
 get_at:0:"40414243444546474849":-1:1:PSA_ERROR_INVALID_ARGUMENT
+
+Overwrite ITS header magic
+get_fail:0:"40414243444546474849":1:0:PSA_ERROR_DATA_CORRUPT
+
+Truncate ITS header
+get_fail:0:"40414243444546474849":0:1:PSA_ERROR_DATA_CORRUPT
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_psa_its.function b/third_party/mbedtls/repo/tests/suites/test_suite_psa_its.function
index a7ce7b1..fb9ce07 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_psa_its.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_psa_its.function
@@ -17,6 +17,7 @@
 #define PSA_ITS_STORAGE_FILENAME_LENGTH         \
     ( sizeof( PSA_ITS_STORAGE_PREFIX ) - 1 + /*prefix without terminating 0*/ \
       16 + /*UID (64-bit number in hex)*/                               \
+      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 \
@@ -231,3 +232,56 @@
     cleanup( );
 }
 /* END_CASE */
+
+/* BEGIN_CASE */
+void get_fail( int uid_arg, data_t *data,
+               int overwrite_magic, int cut_header,
+               int expected_status )
+{
+    psa_storage_uid_t uid = uid_arg;
+    unsigned char *buffer = NULL;
+    psa_status_t status;
+    size_t n;
+    size_t ret_len = 0;
+    char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];
+    FILE *stream = NULL;
+    char bad_char = 'X';
+
+    PSA_ASSERT( psa_its_set_wrap( uid, data->len, data->x, 0 ) );
+
+    psa_its_fill_filename( uid, filename );
+    stream = fopen( filename, "rb+" );
+    TEST_ASSERT( NULL != stream );
+    if( 0 != overwrite_magic )
+    {
+        /* Overwrite the 1st byte of the file, the ITS magic number */
+        TEST_ASSERT( fseek( stream, 0, SEEK_SET ) == 0 );
+        n = fwrite( &bad_char, 1, 1, stream );
+        TEST_ASSERT( 1 == n );
+    }
+    if( 0 != cut_header )
+    {
+        /* Reopen file and truncate it to 0 byte by specifying the 'w' flag */
+        stream = freopen( filename, "wb", stream );
+        TEST_ASSERT( NULL != stream );
+    }
+    fclose( stream );
+    stream = NULL;
+
+    status = psa_its_get( uid, 0, 0, buffer, &ret_len );
+    TEST_ASSERT( status == (psa_status_t) expected_status );
+    TEST_ASSERT( 0 == ret_len );
+    PSA_ASSERT( psa_its_remove( uid ) );
+
+    /* Check if the file is really deleted. */
+    stream = fopen( filename, "rb" );
+    TEST_ASSERT( NULL == stream );
+
+exit:
+    if( stream != NULL )
+        fclose( stream );
+
+    mbedtls_free( buffer );
+    cleanup( );
+}
+/* END_CASE */
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_random.data b/third_party/mbedtls/repo/tests/suites/test_suite_random.data
new file mode 100644
index 0000000..c23d922
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_random.data
@@ -0,0 +1,55 @@
+Generate random twice with CTR_DRBG
+random_twice_with_ctr_drbg:
+
+Generate random twice with HMAC_DRBG(SHA-1)
+depends_on:MBEDTLS_SHA1_C
+random_twice_with_hmac_drbg:MBEDTLS_MD_SHA1
+
+Generate random twice with HMAC_DRBG(SHA-256)
+depends_on:MBEDTLS_SHA256_C
+random_twice_with_hmac_drbg:MBEDTLS_MD_SHA256
+
+Generate random twice with HMAC_DRBG(SHA-512)
+depends_on:MBEDTLS_SHA512_C
+random_twice_with_hmac_drbg:MBEDTLS_MD_SHA512
+
+Generate random twice with PSA classic wrapper
+random_twice_with_psa_from_classic:
+
+Generate random twice with PSA API
+random_twice_with_psa_from_psa:
+
+# This bad-usage test case currently crashes in the default configuration
+# because CTR_DRBG crashes when given an unseeded context. This is arguably
+# a good thing because it prevents misuse of mbedtls_psa_get_random().
+#PSA classic wrapper: PSA not active
+#mbedtls_psa_get_random_no_init:
+
+PSA classic wrapper: 0 bytes
+mbedtls_psa_get_random_length:0
+
+PSA classic wrapper: 1 byte
+mbedtls_psa_get_random_length:1
+
+PSA classic wrapper: 256 bytes
+mbedtls_psa_get_random_length:256
+
+# An external RNG is supposed to handle arbitrary request lengths. Test it
+# with something larger than any RNG call made by Mbed TLS itself expects.
+# CTR_DRBG and HMAC_DRBG have their own maximum request lengths which may
+# be lower than the value chosen here and are tested separately.
+PSA classic wrapper: external RNG large
+depends_on:MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+mbedtls_psa_get_random_length:1024
+
+PSA classic wrapper: CTR_DRBG max
+depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG:MBEDTLS_CTR_DRBG_C
+mbedtls_psa_get_random_length:MBEDTLS_CTR_DRBG_MAX_REQUEST
+
+PSA classic wrapper: HMAC_DRBG max
+depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG:!MBEDTLS_CTR_DRBG_C:MBEDTLS_HMAC_DRBG_C
+mbedtls_psa_get_random_length:MBEDTLS_HMAC_DRBG_MAX_REQUEST
+
+PSA classic wrapper: ECDSA signature (SECP256R1)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+mbedtls_psa_get_random_ecdsa_sign:MBEDTLS_ECP_DP_SECP256R1
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_random.function b/third_party/mbedtls/repo/tests/suites/test_suite_random.function
new file mode 100644
index 0000000..37fa36e
--- /dev/null
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_random.function
@@ -0,0 +1,202 @@
+/* BEGIN_HEADER */
+
+/* Test random generation as a whole. */
+
+#include "mbedtls/bignum.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/ecdsa.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/hmac_drbg.h"
+#include "mbedtls/psa_util.h"
+#include "psa/crypto.h"
+
+/* How many bytes to generate in each test case for repeated generation.
+ * This must be high enough that the probability of generating the same
+ * output twice is infinitesimal, but low enough that random generators
+ * are willing to deliver that much. */
+#define OUTPUT_SIZE 32
+
+/* END_HEADER */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_C:!MBEDTLS_TEST_NULL_ENTROPY:MBEDTLS_CTR_DRBG_C */
+void random_twice_with_ctr_drbg( )
+{
+    mbedtls_entropy_context entropy;
+    mbedtls_ctr_drbg_context drbg;
+    unsigned char output1[OUTPUT_SIZE];
+    unsigned char output2[OUTPUT_SIZE];
+
+    /* First round */
+    mbedtls_entropy_init( &entropy );
+    mbedtls_ctr_drbg_init( &drbg );
+    TEST_EQUAL( 0, mbedtls_ctr_drbg_seed( &drbg,
+                                          mbedtls_entropy_func, &entropy,
+                                          NULL, 0 ) );
+    TEST_EQUAL( 0, mbedtls_ctr_drbg_random( &drbg,
+                                            output1, sizeof( output1 ) ) );
+    mbedtls_ctr_drbg_free( &drbg );
+    mbedtls_entropy_free( &entropy );
+
+    /* Second round */
+    mbedtls_entropy_init( &entropy );
+    mbedtls_ctr_drbg_init( &drbg );
+    TEST_EQUAL( 0, mbedtls_ctr_drbg_seed( &drbg,
+                                          mbedtls_entropy_func, &entropy,
+                                          NULL, 0 ) );
+    TEST_EQUAL( 0, mbedtls_ctr_drbg_random( &drbg,
+                                            output2, sizeof( output2 ) ) );
+    mbedtls_ctr_drbg_free( &drbg );
+    mbedtls_entropy_free( &entropy );
+
+    /* The two rounds must generate different random data. */
+    TEST_ASSERT( memcmp( output1, output2, OUTPUT_SIZE ) != 0 );
+
+exit:
+    mbedtls_ctr_drbg_free( &drbg );
+    mbedtls_entropy_free( &entropy );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_C:!MBEDTLS_TEST_NULL_ENTROPY:MBEDTLS_HMAC_DRBG_C */
+void random_twice_with_hmac_drbg( int md_type )
+{
+    mbedtls_entropy_context entropy;
+    mbedtls_hmac_drbg_context drbg;
+    unsigned char output1[OUTPUT_SIZE];
+    unsigned char output2[OUTPUT_SIZE];
+    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type );
+
+    /* First round */
+    mbedtls_entropy_init( &entropy );
+    mbedtls_hmac_drbg_init( &drbg );
+    TEST_EQUAL( 0, mbedtls_hmac_drbg_seed( &drbg, md_info,
+                                           mbedtls_entropy_func, &entropy,
+                                           NULL, 0 ) );
+    TEST_EQUAL( 0, mbedtls_hmac_drbg_random( &drbg,
+                                             output1, sizeof( output1 ) ) );
+    mbedtls_hmac_drbg_free( &drbg );
+    mbedtls_entropy_free( &entropy );
+
+    /* Second round */
+    mbedtls_entropy_init( &entropy );
+    mbedtls_hmac_drbg_init( &drbg );
+    TEST_EQUAL( 0, mbedtls_hmac_drbg_seed( &drbg, md_info,
+                                           mbedtls_entropy_func, &entropy,
+                                           NULL, 0 ) );
+    TEST_EQUAL( 0, mbedtls_hmac_drbg_random( &drbg,
+                                             output2, sizeof( output2 ) ) );
+    mbedtls_hmac_drbg_free( &drbg );
+    mbedtls_entropy_free( &entropy );
+
+    /* The two rounds must generate different random data. */
+    TEST_ASSERT( memcmp( output1, output2, OUTPUT_SIZE ) != 0 );
+
+exit:
+    mbedtls_hmac_drbg_free( &drbg );
+    mbedtls_entropy_free( &entropy );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:!MBEDTLS_TEST_NULL_ENTROPY:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+void random_twice_with_psa_from_classic( )
+{
+    unsigned char output1[OUTPUT_SIZE];
+    unsigned char output2[OUTPUT_SIZE];
+
+    /* First round */
+    PSA_ASSERT( psa_crypto_init( ) );
+    TEST_EQUAL( 0, mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
+                                           output1, sizeof( output1 ) ) );
+    PSA_DONE( );
+
+    /* Second round */
+    PSA_ASSERT( psa_crypto_init( ) );
+    TEST_EQUAL( 0, mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
+                                           output2, sizeof( output2 ) ) );
+    PSA_DONE( );
+
+    /* The two rounds must generate different random data. */
+    TEST_ASSERT( memcmp( output1, output2, OUTPUT_SIZE ) != 0 );
+
+exit:
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:!MBEDTLS_TEST_NULL_ENTROPY:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+void random_twice_with_psa_from_psa( )
+{
+    unsigned char output1[OUTPUT_SIZE];
+    unsigned char output2[OUTPUT_SIZE];
+
+    /* First round */
+    PSA_ASSERT( psa_crypto_init( ) );
+    PSA_ASSERT( psa_generate_random( output1, sizeof( output1 ) ) );
+    PSA_DONE( );
+
+    /* Second round */
+    PSA_ASSERT( psa_crypto_init( ) );
+    PSA_ASSERT( psa_generate_random( output2, sizeof( output2 ) ) );
+    PSA_DONE( );
+
+    /* The two rounds must generate different random data. */
+    TEST_ASSERT( memcmp( output1, output2, OUTPUT_SIZE ) != 0 );
+
+exit:
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C */
+void mbedtls_psa_get_random_no_init( )
+{
+    unsigned char output[1];
+
+    TEST_ASSERT( mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
+                                         output, sizeof( output ) ) != 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C */
+void mbedtls_psa_get_random_length( int n )
+{
+    unsigned char *output = NULL;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+    ASSERT_ALLOC( output, n );
+
+    TEST_EQUAL( 0, mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
+                                           output, n ) );
+exit:
+    mbedtls_free( output );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_ECDSA_C */
+void mbedtls_psa_get_random_ecdsa_sign( int curve )
+{
+    mbedtls_ecp_group grp;
+    mbedtls_mpi d, r, s;
+    unsigned char buf[] = "This is not a hash.";
+
+    mbedtls_ecp_group_init( &grp );
+    mbedtls_mpi_init( &d );
+    mbedtls_mpi_init( &r );
+    mbedtls_mpi_init( &s );
+
+    TEST_EQUAL( 0, mbedtls_mpi_lset( &d, 123456789 ) );
+    TEST_EQUAL( 0, mbedtls_ecp_group_load( &grp, curve ) );
+    PSA_ASSERT( psa_crypto_init( ) );
+    TEST_EQUAL( 0, mbedtls_ecdsa_sign( &grp, &r, &s, &d,
+                                       buf, sizeof( buf ),
+                                       mbedtls_psa_get_random,
+                                       MBEDTLS_PSA_RANDOM_STATE ) );
+exit:
+    mbedtls_mpi_free( &d );
+    mbedtls_mpi_free( &r );
+    mbedtls_mpi_free( &s );
+    mbedtls_ecp_group_free( &grp );
+    PSA_DONE( );
+}
+/* END_CASE */
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_rsa.data b/third_party/mbedtls/repo/tests/suites/test_suite_rsa.data
index 30919f3..2da814d 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_rsa.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_rsa.data
@@ -1,6 +1,12 @@
 RSA parameter validation
 rsa_invalid_param:
 
+RSA init-free-free
+rsa_init_free:0
+
+RSA init-free-init-free
+rsa_init_free:1
+
 RSA PKCS1 Verify v1.5 CAVS #1
 depends_on:MBEDTLS_SHA1_C:MBEDTLS_PKCS1_V15
 # Good padding but wrong hash
@@ -383,12 +389,18 @@
 RSA Private (Data larger than N)
 mbedtls_rsa_private:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":2048:16:"e79a373182bfaa722eb035f772ad2a9464bd842de59432c18bbab3a7dfeae318c9b915ee487861ab665a40bd6cda560152578e8579016c929df99fea05b4d64efca1d543850bc8164b40d71ed7f3fa4105df0fb9b9ad2a18ce182c8a4f4f975bea9aa0b9a1438a27a28e97ac8330ef37383414d1bd64607d6979ac050424fd17":16:"c6749cbb0db8c5a177672d4728a8b22392b2fc4d3b8361d5c0d5055a1b4e46d821f757c24eef2a51c561941b93b3ace7340074c058c9bb48e7e7414f42c41da4cccb5c2ba91deb30c586b7fb18af12a52995592ad139d3be429add6547e044becedaf31fa3b39421e24ee034fbf367d11f6b8f88ee483d163b431e1654ad3e89":16:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":16:"3":"605baf947c0de49e4f6a0dfb94a43ae318d5df8ed20ba4ba5a37a73fb009c5c9e5cce8b70a25b1c7580f389f0d7092485cdfa02208b70d33482edf07a7eafebdc54862ca0e0396a5a7d09991b9753eb1ffb6091971bb5789c6b121abbcd0a3cbaa39969fa7c28146fce96c6d03272e3793e5be8f5abfa9afcbebb986d7b3050604a2af4d3a40fa6c003781a539a60259d1e84f13322da9e538a49c369b83e7286bf7d30b64bbb773506705da5d5d5483a563a1ffacc902fb75c9a751b1e83cdc7a6db0470056883f48b5a5446b43b1d180ea12ba11a6a8d93b3b32a30156b6084b7fb142998a2a0d28014b84098ece7d9d5e4d55cc342ca26f5a0167a679dec8":MBEDTLS_ERR_RSA_PRIVATE_FAILED + MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
+RSA Private (Data = 0 )
+mbedtls_rsa_private:"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":2048:16:"e79a373182bfaa722eb035f772ad2a9464bd842de59432c18bbab3a7dfeae318c9b915ee487861ab665a40bd6cda560152578e8579016c929df99fea05b4d64efca1d543850bc8164b40d71ed7f3fa4105df0fb9b9ad2a18ce182c8a4f4f975bea9aa0b9a1438a27a28e97ac8330ef37383414d1bd64607d6979ac050424fd17":16:"c6749cbb0db8c5a177672d4728a8b22392b2fc4d3b8361d5c0d5055a1b4e46d821f757c24eef2a51c561941b93b3ace7340074c058c9bb48e7e7414f42c41da4cccb5c2ba91deb30c586b7fb18af12a52995592ad139d3be429add6547e044becedaf31fa3b39421e24ee034fbf367d11f6b8f88ee483d163b431e1654ad3e89":16:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":16:"3":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":0
+
 RSA Public (Correct)
 mbedtls_rsa_public:"59779fd2a39e56640c4fc1e67b60aeffcecd78aed7ad2bdfa464e93d04198d48466b8da7445f25bfa19db2844edd5c8f539cf772cc132b483169d390db28a43bc4ee0f038f6568ffc87447746cb72fefac2d6d90ee3143a915ac4688028805905a68eb8f8a96674b093c495eddd8704461eaa2b345efbb2ad6930acd8023f8700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":2048:16:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":16:"3":"1f5e927c13ff231090b0f18c8c3526428ed0f4a7561457ee5afe4d22d5d9220c34ef5b9a34d0c07f7248a1f3d57f95d10f7936b3063e40660b3a7ca3e73608b013f85a6e778ac7c60d576e9d9c0c5a79ad84ceea74e4722eb3553bdb0c2d7783dac050520cb27ca73478b509873cb0dcbd1d51dd8fccb96c29ad314f36d67cc57835d92d94defa0399feb095fd41b9f0b2be10f6041079ed4290040449f8a79aba50b0a1f8cf83c9fb8772b0686ec1b29cb1814bb06f9c024857db54d395a8da9a2c6f9f53b94bec612a0cb306a3eaa9fc80992e85d9d232e37a50cabe48c9343f039601ff7d95d60025e582aec475d031888310e8ec3833b394a5cf0599101e":0
 
 RSA Public (Data larger than N)
 mbedtls_rsa_public:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":2048:16:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":16:"3":"605baf947c0de49e4f6a0dfb94a43ae318d5df8ed20ba4ba5a37a73fb009c5c9e5cce8b70a25b1c7580f389f0d7092485cdfa02208b70d33482edf07a7eafebdc54862ca0e0396a5a7d09991b9753eb1ffb6091971bb5789c6b121abbcd0a3cbaa39969fa7c28146fce96c6d03272e3793e5be8f5abfa9afcbebb986d7b3050604a2af4d3a40fa6c003781a539a60259d1e84f13322da9e538a49c369b83e7286bf7d30b64bbb773506705da5d5d5483a563a1ffacc902fb75c9a751b1e83cdc7a6db0470056883f48b5a5446b43b1d180ea12ba11a6a8d93b3b32a30156b6084b7fb142998a2a0d28014b84098ece7d9d5e4d55cc342ca26f5a0167a679dec8":MBEDTLS_ERR_RSA_PUBLIC_FAILED + MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
+RSA Public (Data = 0)
+mbedtls_rsa_public:"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":2048:16:"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":16:"3":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":0
+
 RSA Generate Key - 128bit key
 mbedtls_rsa_gen_key:128:3:0
 
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_rsa.function b/third_party/mbedtls/repo/tests/suites/test_suite_rsa.function
index 6c73e39..2d7fb8e 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_rsa.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_rsa.function
@@ -338,6 +338,28 @@
                                                          buf ) );
 
     TEST_INVALID_PARAM_RET( MBEDTLS_ERR_RSA_BAD_INPUT_DATA,
+                            mbedtls_rsa_rsassa_pss_sign_ext( NULL, NULL, NULL,
+                                                             0, sizeof( buf ), buf,
+                                                             MBEDTLS_RSA_SALT_LEN_ANY,
+                                                             buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_RSA_BAD_INPUT_DATA,
+                            mbedtls_rsa_rsassa_pss_sign_ext( &ctx, NULL, NULL,
+                                                             0, sizeof( buf ), NULL,
+                                                             MBEDTLS_RSA_SALT_LEN_ANY,
+                                                             buf ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_RSA_BAD_INPUT_DATA,
+                            mbedtls_rsa_rsassa_pss_sign_ext( &ctx, NULL, NULL,
+                                                             0, sizeof( buf ), buf,
+                                                             MBEDTLS_RSA_SALT_LEN_ANY,
+                                                             NULL ) );
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_RSA_BAD_INPUT_DATA,
+                            mbedtls_rsa_rsassa_pss_sign_ext( &ctx, NULL, NULL,
+                                                             MBEDTLS_MD_SHA1,
+                                                             0, NULL,
+                                                             MBEDTLS_RSA_SALT_LEN_ANY,
+                                                             buf ) );
+
+    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_RSA_BAD_INPUT_DATA,
                             mbedtls_rsa_pkcs1_verify( NULL, NULL, NULL,
                                                       valid_mode,
                                                       0, sizeof( buf ), buf,
@@ -467,6 +489,29 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void rsa_init_free( int reinit )
+{
+    mbedtls_rsa_context ctx;
+
+    /* Double free is not explicitly documented to work, but we rely on it
+     * even inside the library so that you can call mbedtls_rsa_free()
+     * unconditionally on an error path without checking whether it has
+     * already been called in the success path. */
+
+    mbedtls_rsa_init( &ctx, 0, 0 );
+    mbedtls_rsa_free( &ctx );
+
+    if( reinit )
+        mbedtls_rsa_init( &ctx, 0, 0 );
+    mbedtls_rsa_free( &ctx );
+
+    /* This test case always succeeds, functionally speaking. A plausible
+     * bug might trigger an invalid pointer dereference or a memory leak. */
+    goto exit;
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void mbedtls_rsa_pkcs1_sign( data_t * message_str, int padding_mode,
                              int digest, int mod, int radix_P, char * input_P,
                              int radix_Q, char * input_Q, int radix_N,
@@ -487,10 +532,10 @@
     memset( output, 0x00, sizeof( output ) );
     memset( &rnd_info, 0, sizeof( mbedtls_test_rnd_pseudo_info ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &P, radix_P, input_P ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Q, radix_Q, input_Q ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
 
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, &P, &Q, NULL, &E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( mod / 8 ) );
@@ -533,8 +578,8 @@
     mbedtls_rsa_init( &ctx, padding_mode, 0 );
     memset( hash_result, 0x00, sizeof( hash_result ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, NULL, NULL, NULL, &E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( mod / 8 ) );
     TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == 0 );
@@ -571,10 +616,10 @@
     memset( output, 0x00, sizeof( output ) );
     memset( &rnd_info, 0, sizeof( mbedtls_test_rnd_pseudo_info ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &P, radix_P, input_P ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Q, radix_Q, input_Q ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
 
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, &P, &Q, NULL, &E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( mod / 8 ) );
@@ -642,8 +687,8 @@
     mbedtls_rsa_init( &ctx, padding_mode, 0 );
     memset( output, 0x00, sizeof( output ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
 
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, NULL, NULL, NULL, &E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( mod / 8 ) );
@@ -706,8 +751,8 @@
     mbedtls_rsa_init( &ctx, padding_mode, 0 );
     memset( output, 0x00, sizeof( output ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
 
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, NULL, NULL, NULL, &E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( mod / 8 ) );
@@ -747,8 +792,8 @@
     mbedtls_rsa_init( &ctx, padding_mode, 0 );
     memset( output, 0x00, sizeof( output ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
 
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, NULL, NULL, NULL, &E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( mod / 8 ) );
@@ -795,10 +840,10 @@
     memset( &rnd_info, 0, sizeof( mbedtls_test_rnd_pseudo_info ) );
 
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &P, radix_P, input_P ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Q, radix_Q, input_Q ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
 
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, &P, &Q, NULL, &E ) == 0 );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( mod / 8 ) );
@@ -841,14 +886,16 @@
     mbedtls_rsa_init( &ctx2, MBEDTLS_RSA_PKCS_V15, 0 );
     memset( output, 0x00, sizeof( output ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
 
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, NULL, NULL, NULL, &E ) == 0 );
+
+    /* Check test data consistency */
+    TEST_ASSERT( message_str->len == (size_t) ( mod / 8 ) );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( mod / 8 ) );
     TEST_ASSERT( mbedtls_rsa_check_pubkey( &ctx ) == 0 );
 
-
     TEST_ASSERT( mbedtls_rsa_public( &ctx, message_str->x, output ) == result );
     if( result == 0 )
     {
@@ -900,17 +947,19 @@
 
     memset( &rnd_info, 0, sizeof( mbedtls_test_rnd_pseudo_info ) );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &P, radix_P, input_P ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Q, radix_Q, input_Q ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
 
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, &P, &Q, NULL, &E ) == 0 );
+
+    /* Check test data consistency */
+    TEST_ASSERT( message_str->len == (size_t) ( mod / 8 ) );
     TEST_ASSERT( mbedtls_rsa_get_len( &ctx ) == (size_t) ( mod / 8 ) );
     TEST_ASSERT( mbedtls_rsa_complete( &ctx ) == 0 );
     TEST_ASSERT( mbedtls_rsa_check_privkey( &ctx ) == 0 );
 
-
     /* repeat three times to test updating of blinding values */
     for( i = 0; i < 3; i++ )
     {
@@ -976,11 +1025,11 @@
 
     if( strlen( input_N ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
     }
     if( strlen( input_E ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
     }
 
     TEST_ASSERT( mbedtls_rsa_import( &ctx, &N, NULL, NULL, NULL, &E ) == 0 );
@@ -1008,36 +1057,36 @@
     ctx.len = mod / 8;
     if( strlen( input_P ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &ctx.P, radix_P, input_P ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &ctx.P, radix_P, input_P ) == 0 );
     }
     if( strlen( input_Q ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &ctx.Q, radix_Q, input_Q ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &ctx.Q, radix_Q, input_Q ) == 0 );
     }
     if( strlen( input_N ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &ctx.N, radix_N, input_N ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &ctx.N, radix_N, input_N ) == 0 );
     }
     if( strlen( input_E ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &ctx.E, radix_E, input_E ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &ctx.E, radix_E, input_E ) == 0 );
     }
     if( strlen( input_D ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &ctx.D, radix_D, input_D ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &ctx.D, radix_D, input_D ) == 0 );
     }
 #if !defined(MBEDTLS_RSA_NO_CRT)
     if( strlen( input_DP ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &ctx.DP, radix_DP, input_DP ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &ctx.DP, radix_DP, input_DP ) == 0 );
     }
     if( strlen( input_DQ ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &ctx.DQ, radix_DQ, input_DQ ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &ctx.DQ, radix_DQ, input_DQ ) == 0 );
     }
     if( strlen( input_QP ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &ctx.QP, radix_QP, input_QP ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &ctx.QP, radix_QP, input_QP ) == 0 );
     }
 #else
     ((void) radix_DP); ((void) input_DP);
@@ -1072,45 +1121,45 @@
 
     if( strlen( input_Npub ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &pub.N, radix_Npub, input_Npub ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &pub.N, radix_Npub, input_Npub ) == 0 );
     }
     if( strlen( input_Epub ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &pub.E, radix_Epub, input_Epub ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &pub.E, radix_Epub, input_Epub ) == 0 );
     }
 
     if( strlen( input_P ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &prv.P, radix_P, input_P ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &prv.P, radix_P, input_P ) == 0 );
     }
     if( strlen( input_Q ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &prv.Q, radix_Q, input_Q ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &prv.Q, radix_Q, input_Q ) == 0 );
     }
     if( strlen( input_N ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &prv.N, radix_N, input_N ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &prv.N, radix_N, input_N ) == 0 );
     }
     if( strlen( input_E ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &prv.E, radix_E, input_E ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &prv.E, radix_E, input_E ) == 0 );
     }
     if( strlen( input_D ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &prv.D, radix_D, input_D ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &prv.D, radix_D, input_D ) == 0 );
     }
 #if !defined(MBEDTLS_RSA_NO_CRT)
     if( strlen( input_DP ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &prv.DP, radix_DP, input_DP ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &prv.DP, radix_DP, input_DP ) == 0 );
     }
     if( strlen( input_DQ ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &prv.DQ, radix_DQ, input_DQ ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &prv.DQ, radix_DQ, input_DQ ) == 0 );
     }
     if( strlen( input_QP ) )
     {
-        TEST_ASSERT( mbedtls_mpi_read_string( &prv.QP, radix_QP, input_QP ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &prv.QP, radix_QP, input_QP ) == 0 );
     }
 #else
     ((void) radix_DP); ((void) input_DP);
@@ -1171,11 +1220,11 @@
     mbedtls_mpi_init( &Pp ); mbedtls_mpi_init( &Qp );
     mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &D, radix_D, input_D ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Qp, radix_P, output_P ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Pp, radix_Q, output_Q ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &D, radix_D, input_D ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Qp, radix_P, output_P ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Pp, radix_Q, output_Q ) == 0 );
 
     if( corrupt )
         TEST_ASSERT( mbedtls_mpi_add_int( &D, &D, 2 ) == 0 );
@@ -1212,10 +1261,10 @@
     mbedtls_mpi_init( &E );
     mbedtls_mpi_init( &R ); mbedtls_mpi_init( &Rp );
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
-    TEST_ASSERT( mbedtls_mpi_read_string( &Dp, radix_D, output_D ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &P, radix_P, input_P ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Q, radix_Q, input_Q ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &Dp, radix_D, output_D ) == 0 );
 
     if( corrupt )
     {
@@ -1298,19 +1347,19 @@
                                 (const unsigned char *) pers, strlen( pers ) ) == 0 );
 
     if( have_N )
-        TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
 
     if( have_P )
-        TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &P, radix_P, input_P ) == 0 );
 
     if( have_Q )
-        TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &Q, radix_Q, input_Q ) == 0 );
 
     if( have_D )
-        TEST_ASSERT( mbedtls_mpi_read_string( &D, radix_D, input_D ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &D, radix_D, input_D ) == 0 );
 
     if( have_E )
-        TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
 
     if( !successive )
     {
@@ -1442,19 +1491,19 @@
     /* Setup RSA context */
 
     if( have_N )
-        TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
 
     if( have_P )
-        TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &P, radix_P, input_P ) == 0 );
 
     if( have_Q )
-        TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &Q, radix_Q, input_Q ) == 0 );
 
     if( have_D )
-        TEST_ASSERT( mbedtls_mpi_read_string( &D, radix_D, input_D ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &D, radix_D, input_D ) == 0 );
 
     if( have_E )
-        TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
 
     TEST_ASSERT( mbedtls_rsa_import( &ctx,
                                      strlen( input_N ) ? &N : NULL,
@@ -1562,19 +1611,19 @@
                                         strlen( pers ) ) == 0 );
 
     if( have_N )
-        TEST_ASSERT( mbedtls_mpi_read_string( &N, radix_N, input_N ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &N, radix_N, input_N ) == 0 );
 
     if( have_P )
-        TEST_ASSERT( mbedtls_mpi_read_string( &P, radix_P, input_P ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &P, radix_P, input_P ) == 0 );
 
     if( have_Q )
-        TEST_ASSERT( mbedtls_mpi_read_string( &Q, radix_Q, input_Q ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &Q, radix_Q, input_Q ) == 0 );
 
     if( have_D )
-        TEST_ASSERT( mbedtls_mpi_read_string( &D, radix_D, input_D ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &D, radix_D, input_D ) == 0 );
 
     if( have_E )
-        TEST_ASSERT( mbedtls_mpi_read_string( &E, radix_E, input_E ) == 0 );
+        TEST_ASSERT( mbedtls_test_read_mpi( &E, radix_E, input_E ) == 0 );
 
     TEST_ASSERT( mbedtls_rsa_validate_params( have_N ? &N : NULL,
                                         have_P ? &P : NULL,
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_ssl.data b/third_party/mbedtls/repo/tests/suites/test_suite_ssl.data
index 6e653ff..fe7d978 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_ssl.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_ssl.data
@@ -236,7 +236,7 @@
 handshake_cipher:"TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384":MBEDTLS_PK_ECDSA:0
 
 Handshake, PSK-WITH-AES-128-CBC-SHA
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_RSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_RSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA1_C
 handshake_psk_cipher:"TLS-PSK-WITH-AES-128-CBC-SHA":MBEDTLS_PK_RSA:"abc123":0
 
 DTLS Handshake, tls1_1
@@ -268,7 +268,7 @@
 handshake_cipher:"TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384":MBEDTLS_PK_ECDSA:1
 
 DTLS Handshake, PSK-WITH-AES-128-CBC-SHA
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_RSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SSL_PROTO_DTLS
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_RSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_SHA1_C
 handshake_psk_cipher:"TLS-PSK-WITH-AES-128-CBC-SHA":MBEDTLS_PK_RSA:"abc123":1
 
 DTLS Handshake with serialization, tls1_2
@@ -10503,7 +10503,7 @@
 
 SSL TLS 1.3 Key schedule: Derive-Secret( ., "c hs traffic", hash)
 # Vector from RFC 8448
-ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"005cb112fd8eb4ccc623bb88a07c64b3ede1605363fc7d0df8c7ce4ff0fb4ae6":tls1_3_label_c_hs_traffic:"f736cb34fe25e701551bee6fd24c1cc7102a7daf9405cb15d97aafe16f757d03"::32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"2faac08f851d35fea3604fcb4de82dc62c9b164a70974d0462e27f1ab278700f"
+ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"005cb112fd8eb4ccc623bb88a07c64b3ede1605363fc7d0df8c7ce4ff0fb4ae6":tls1_3_label_c_hs_traffic:"f736cb34fe25e701551bee6fd24c1cc7102a7daf9405cb15d97aafe16f757d03":32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"2faac08f851d35fea3604fcb4de82dc62c9b164a70974d0462e27f1ab278700f"
 
 SSL TLS 1.3 Key schedule: Derive-Secret( ., "s hs traffic", hash)
 # Vector from RFC 8448
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_ssl.function b/third_party/mbedtls/repo/tests/suites/test_suite_ssl.function
index f377ffa..74e60ae 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_ssl.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_ssl.function
@@ -8,7 +8,7 @@
 #include <mbedtls/debug.h>
 #include <ssl_tls13_keys.h>
 
-#include <ssl_invasive.h>
+#include <constant_time_internal.h>
 
 #include <test/constant_flow.h>
 
@@ -1354,7 +1354,8 @@
                     t_in->taglen = 8;
                     break;
                 default:
-                    return( 1 );
+                    ret = 1;
+                    goto cleanup;
             }
             break;
 
@@ -1374,7 +1375,8 @@
                     t_in->taglen = 8;
                     break;
                 default:
-                    return( 1 );
+                    ret = 1;
+                    goto cleanup;
             }
             break;
 
@@ -1395,11 +1397,13 @@
                     t_in->maclen = 10;
                     break;
                 default:
-                    return( 1 );
+                    ret = 1;
+                    goto cleanup;
             }
             break;
         default:
-            return( 1 );
+            ret = 1;
+            goto cleanup;
             break;
     }
 
@@ -2244,8 +2248,8 @@
 void ssl_mock_sanity( )
 {
     enum { MSGLEN = 105 };
-    unsigned char message[MSGLEN];
-    unsigned char received[MSGLEN];
+    unsigned char message[MSGLEN] = { 0 };
+    unsigned char received[MSGLEN] = { 0 };
     mbedtls_mock_socket socket;
 
     mbedtls_mock_socket_init( &socket );
@@ -2658,7 +2662,7 @@
 void ssl_message_mock_uninitialized( )
 {
     enum { MSGLEN = 10 };
-    unsigned char message[MSGLEN], received[MSGLEN];
+    unsigned char message[MSGLEN] = {0}, received[MSGLEN];
     mbedtls_mock_socket client, server;
     mbedtls_test_message_queue server_queue, client_queue;
     mbedtls_test_message_socket_context server_context, client_context;
@@ -3609,7 +3613,7 @@
      */
     for( i = block_size; i < buflen; i++ )
     {
-        test_set_step( i );
+        mbedtls_test_set_step( i );
 
         /* Restore correct pre-encryption record */
         rec = rec_save;
@@ -3646,7 +3650,7 @@
      */
     for( i = padlen; i <= pad_max_len; i++ )
     {
-        test_set_step( i );
+        mbedtls_test_set_step( i );
 
         /* Restore correct pre-encryption record */
         rec = rec_save;
@@ -3832,9 +3836,7 @@
     if( output == NULL )
         goto exit;
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    TEST_ASSERT( psa_crypto_init() == 0 );
-#endif
+    USE_PSA_INIT( );
 
     TEST_ASSERT( mbedtls_ssl_tls_prf( type, secret->x, secret->len,
                                       label, random->x, random->len,
@@ -3848,6 +3850,7 @@
 exit:
 
     mbedtls_free( output );
+    USE_PSA_DONE( );
 }
 /* END_CASE */
 
@@ -4425,7 +4428,7 @@
 void ssl_cf_hmac( int hash )
 {
     /*
-     * Test the function mbedtls_ssl_cf_hmac() against a reference
+     * Test the function mbedtls_ct_hmac() against a reference
      * implementation.
      */
     mbedtls_md_context_t ctx, ref_ctx;
@@ -4466,7 +4469,7 @@
      */
     for( max_in_len = 0; max_in_len <= 255 + block_size; max_in_len++ )
     {
-        test_set_step( max_in_len * 10000 );
+        mbedtls_test_set_step( max_in_len * 10000 );
 
         /* Use allocated in buffer to catch overreads */
         ASSERT_ALLOC( data, max_in_len );
@@ -4474,7 +4477,7 @@
         min_in_len = max_in_len > 255 ? max_in_len - 255 : 0;
         for( in_len = min_in_len; in_len <= max_in_len; in_len++ )
         {
-            test_set_step( max_in_len * 10000 + in_len );
+            mbedtls_test_set_step( max_in_len * 10000 + in_len );
 
             /* Set up dummy data and add_data */
             rec_num++;
@@ -4484,10 +4487,10 @@
 
             /* Get the function's result */
             TEST_CF_SECRET( &in_len, sizeof( in_len ) );
-            TEST_EQUAL( 0, mbedtls_ssl_cf_hmac( &ctx, add_data, sizeof( add_data ),
-                                                data, in_len,
-                                                min_in_len, max_in_len,
-                                                out ) );
+            TEST_EQUAL( 0, mbedtls_ct_hmac( &ctx, add_data, sizeof( add_data ),
+                                            data, in_len,
+                                            min_in_len, max_in_len,
+                                            out ) );
             TEST_CF_PUBLIC( &in_len, sizeof( in_len ) );
             TEST_CF_PUBLIC( out, out_len );
 
@@ -4531,11 +4534,11 @@
 
     for( secret = offset_min; secret <= (size_t) offset_max; secret++ )
     {
-        test_set_step( (int) secret );
+        mbedtls_test_set_step( (int) secret );
 
         TEST_CF_SECRET( &secret, sizeof( secret ) );
-        mbedtls_ssl_cf_memcpy_offset( dst, src, secret,
-                                      offset_min, offset_max, len );
+        mbedtls_ct_memcpy_offset( dst, src, secret,
+                                  offset_min, offset_max, len );
         TEST_CF_PUBLIC( &secret, sizeof( secret ) );
         TEST_CF_PUBLIC( dst, len );
 
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_version.data b/third_party/mbedtls/repo/tests/suites/test_suite_version.data
index 2b01227..60bd1b9 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_version.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_version.data
@@ -1,8 +1,8 @@
 Check compiletime library version
-check_compiletime_version:"2.25.0"
+check_compiletime_version:"2.28.0"
 
 Check runtime library version
-check_runtime_version:"2.25.0"
+check_runtime_version:"2.28.0"
 
 Check for MBEDTLS_VERSION_C
 check_feature:"MBEDTLS_VERSION_C":0
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_x509parse.data b/third_party/mbedtls/repo/tests/suites/test_suite_x509parse.data
index 3b84609..7ac91f6 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_x509parse.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_x509parse.data
@@ -211,7 +211,7 @@
 mbedtls_x509_crl_info:"data_files/crl_md2.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2009-07-19 19\:56\:37\nnext update   \: 2009-09-17 19\:56\:37\nRevoked certificates\:\nserial number\: 01 revocation date\: 2009-02-09 21\:12\:36\nserial number\: 03 revocation date\: 2009-02-09 21\:12\:36\nsigned using  \: RSA with MD2\n"
 
 X509 CRL Information MD4 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD4_C
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD4_C:MBEDTLS_RSA_C
 mbedtls_x509_crl_info:"data_files/crl_md4.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with MD4\n"
 
 X509 CRL Information MD5 Digest
@@ -559,12 +559,8 @@
 depends_on:MBEDTLS_SHA1_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 x509_verify:"data_files/cert_sha1.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":0:0:"compat":"NULL"
 
-X509 CRT verification #14 (Valid Cert SHA1 Digest allowed in compile-time default profile)
-depends_on:MBEDTLS_SHA1_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES
-x509_verify:"data_files/cert_sha1.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":0:0:"":"NULL"
-
 X509 CRT verification #14 (Valid Cert SHA1 Digest forbidden in default profile)
-depends_on:MBEDTLS_SHA1_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:!MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES
+depends_on:MBEDTLS_SHA1_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 x509_verify:"data_files/cert_sha1.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCRL_BAD_MD | MBEDTLS_X509_BADCERT_BAD_MD:"":"NULL"
 
 X509 CRT verification #15 (Valid Cert SHA224 Digest)
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_x509parse.function b/third_party/mbedtls/repo/tests/suites/test_suite_x509parse.function
index 2bba4e2..29d28f7 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_x509parse.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_x509parse.function
@@ -7,6 +7,7 @@
 #include "mbedtls/pem.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/base64.h"
+#include "mbedtls/error.h"
 #include "string.h"
 
 #if MBEDTLS_X509_MAX_INTERMEDIATE_CA > 19
@@ -320,18 +321,18 @@
         ret = mbedtls_asn1_get_tag( p, end, &len,
                                  MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
         if( ret != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
         if( *p + len != end )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
         /*
          * Cannot be an empty sequence.
          */
         if( len == 0 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
         while( *p < end )
         {
@@ -342,13 +343,13 @@
              */
             if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-                return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+                return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
             policy_end = *p + len;
 
             if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len,
                                               MBEDTLS_ASN1_OID ) ) != 0 )
-                return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+                return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
 
             /*
              * Recognize exclusively the policy with OID 1
@@ -366,7 +367,7 @@
             {
                 if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len,
                          MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-                    return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+                    return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
                 /*
                  * Skip the optional policy qualifiers.
                  */
@@ -374,13 +375,13 @@
             }
 
             if( *p != policy_end )
-                return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                        MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+                return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                        MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
         }
 
         if( *p != end )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
 
         return( parse_ret );
     }
@@ -388,7 +389,8 @@
              memcmp( new_oid->p, oid->p, oid->len ) == 0 )
         return( 0 );
     else
-        return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                   MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
 }
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 /* END_HEADER */
@@ -610,14 +612,12 @@
     char *      cn_name = NULL;
     const mbedtls_x509_crt_profile *profile;
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    TEST_ASSERT( psa_crypto_init() == 0 );
-#endif
-
     mbedtls_x509_crt_init( &crt );
     mbedtls_x509_crt_init( &ca );
     mbedtls_x509_crl_init( &crl );
 
+    USE_PSA_INIT( );
+
     if( strcmp( cn_name_str, "NULL" ) != 0 )
         cn_name = cn_name_str;
 
@@ -669,6 +669,7 @@
     mbedtls_x509_crt_free( &crt );
     mbedtls_x509_crt_free( &ca );
     mbedtls_x509_crl_free( &crl );
+    USE_PSA_DONE( );
 }
 /* END_CASE */
 
@@ -712,14 +713,12 @@
     uint32_t flags = 0;
     verify_print_context vrfy_ctx;
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    TEST_ASSERT( psa_crypto_init() == 0 );
-#endif
-
     mbedtls_x509_crt_init( &crt );
     mbedtls_x509_crt_init( &ca );
     verify_print_init( &vrfy_ctx );
 
+    USE_PSA_INIT( );
+
     TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == 0 );
     TEST_ASSERT( mbedtls_x509_crt_parse_file( &ca, ca_file ) == 0 );
 
@@ -737,6 +736,7 @@
 exit:
     mbedtls_x509_crt_free( &crt );
     mbedtls_x509_crt_free( &ca );
+    USE_PSA_DONE( );
 }
 /* END_CASE */
 
@@ -1024,10 +1024,6 @@
     uint32_t flags;
     mbedtls_x509_crt trusted, chain;
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    TEST_ASSERT( psa_crypto_init() == 0 );
-#endif
-
     /*
      * We expect chain_dir to contain certificates 00.crt, 01.crt, etc.
      * with NN.crt signed by NN-1.crt
@@ -1036,6 +1032,8 @@
     mbedtls_x509_crt_init( &trusted );
     mbedtls_x509_crt_init( &chain );
 
+    USE_PSA_INIT( );
+
     /* Load trusted root */
     TEST_ASSERT( mbedtls_x509_crt_parse_file( &trusted, ca_file ) == 0 );
 
@@ -1055,6 +1053,7 @@
 exit:
     mbedtls_x509_crt_free( &chain );
     mbedtls_x509_crt_free( &trusted );
+    USE_PSA_DONE( );
 }
 /* END_CASE */
 
@@ -1069,13 +1068,11 @@
     mbedtls_x509_crt trusted, chain;
     const mbedtls_x509_crt_profile *profile = NULL;
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    TEST_ASSERT( psa_crypto_init() == 0 );
-#endif
-
     mbedtls_x509_crt_init( &chain );
     mbedtls_x509_crt_init( &trusted );
 
+    USE_PSA_INIT( );
+
     while( ( act = mystrsep( &chain_paths, " " ) ) != NULL )
         TEST_ASSERT( mbedtls_x509_crt_parse_file( &chain, act ) == 0 );
     TEST_ASSERT( mbedtls_x509_crt_parse_file( &trusted, trusted_ca ) == 0 );
@@ -1100,6 +1097,7 @@
 exit:
     mbedtls_x509_crt_free( &trusted );
     mbedtls_x509_crt_free( &chain );
+    USE_PSA_DONE( );
 }
 /* END_CASE */
 
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_x509write.data b/third_party/mbedtls/repo/tests/suites/test_suite_x509write.data
index b3f209e..e0f80be 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_x509write.data
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_x509write.data
@@ -56,35 +56,43 @@
 
 Certificate write check Server1 SHA1
 depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:-1:"data_files/server1.crt":0
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:-1:"data_files/server1.crt":0:0
 
 Certificate write check Server1 SHA1, key_usage
 depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:0:0:1:-1:"data_files/server1.key_usage.crt":0
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:0:0:1:-1:"data_files/server1.key_usage.crt":0:0
 
 Certificate write check Server1 SHA1, ns_cert_type
 depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:1:-1:"data_files/server1.cert_type.crt":0
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:1:-1:"data_files/server1.cert_type.crt":0:0
 
 Certificate write check Server1 SHA1, version 1
 depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":0
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":0:0
+
+Certificate write check Server1 SHA1, CA
+depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:-1:"data_files/server1.ca.crt":0:1
 
 Certificate write check Server1 SHA1, RSA_ALT
 depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:0:-1:"data_files/server1.noauthid.crt":1
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:0:-1:"data_files/server1.noauthid.crt":1:0
 
 Certificate write check Server1 SHA1, RSA_ALT, key_usage
 depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:0:0:0:-1:"data_files/server1.key_usage_noauthid.crt":1
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:0:0:0:-1:"data_files/server1.key_usage_noauthid.crt":1:0
 
 Certificate write check Server1 SHA1, RSA_ALT, ns_cert_type
 depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:0:-1:"data_files/server1.cert_type_noauthid.crt":1
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER:1:0:-1:"data_files/server1.cert_type_noauthid.crt":1:0
 
 Certificate write check Server1 SHA1, RSA_ALT, version 1
 depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C
-x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:0:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":1
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:0:MBEDTLS_X509_CRT_VERSION_1:"data_files/server1.v1.crt":1:0
+
+Certificate write check Server1 SHA1, RSA_ALT, CA
+depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C
+x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:0:-1:"data_files/server1.ca_noauthid.crt":1:1
 
 
 X509 String to Names #1
diff --git a/third_party/mbedtls/repo/tests/suites/test_suite_x509write.function b/third_party/mbedtls/repo/tests/suites/test_suite_x509write.function
index 3803377..ce475e6 100644
--- a/third_party/mbedtls/repo/tests/suites/test_suite_x509write.function
+++ b/third_party/mbedtls/repo/tests/suites/test_suite_x509write.function
@@ -6,25 +6,6 @@
 #include "mbedtls/oid.h"
 #include "mbedtls/rsa.h"
 
-/* These are the same depends as the test function x509_crs_check_opaque(),
- * the only function using PSA here. Using a weaker condition would result in
- * warnings about the static functions defined in psa_crypto_helpers.h being
- * unused. */
-#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
-    defined(MBEDTLS_PEM_WRITE_C) && \
-    defined(MBEDTLS_X509_CSR_WRITE_C)
-#include "psa/crypto.h"
-#include "mbedtls/psa_util.h"
-#include "test/psa_crypto_helpers.h"
-#define PSA_INIT( ) PSA_ASSERT( psa_crypto_init( ) )
-#else
-/* Define empty macros so that we can use them in the preamble and teardown
- * of every test function that uses PSA conditionally based on
- * MBEDTLS_USE_PSA_CRYPTO. */
-#define PSA_INIT( ) ( (void) 0 )
-#define PSA_DONE( ) ( (void) 0 )
-#endif /* MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_PEM_WRITE_C && MBEDTLS_X509_CSR_WRITE_C */
-
 #if defined(MBEDTLS_RSA_C)
 int mbedtls_rsa_decrypt_func( void *ctx, int mode, size_t *olen,
                        const unsigned char *input, unsigned char *output,
@@ -219,7 +200,7 @@
                      char *serial_str, char *not_before, char *not_after,
                      int md_type, int key_usage, int set_key_usage,
                      int cert_type, int set_cert_type, int auth_ident,
-                     int ver, char *cert_check_file, int rsa_alt )
+                     int ver, char *cert_check_file, int rsa_alt, int is_ca )
 {
     mbedtls_pk_context subject_key, issuer_key, issuer_key_alt;
     mbedtls_pk_context *key = &issuer_key;
@@ -265,7 +246,7 @@
     (void) rsa_alt;
 #endif
 
-    TEST_ASSERT( mbedtls_mpi_read_string( &serial, 10, serial_str ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &serial, 10, serial_str ) == 0 );
 
     if( ver != -1 )
         mbedtls_x509write_crt_set_version( &crt, ver );
@@ -282,7 +263,9 @@
 
     if( crt.version >= MBEDTLS_X509_CRT_VERSION_3 )
     {
-        TEST_ASSERT( mbedtls_x509write_crt_set_basic_constraints( &crt, 0, 0 ) == 0 );
+        /* For the CA case, a path length of -1 means unlimited. */
+        TEST_ASSERT( mbedtls_x509write_crt_set_basic_constraints( &crt, is_ca,
+                                                                  (is_ca ? -1 : 0) ) == 0 );
         TEST_ASSERT( mbedtls_x509write_crt_set_subject_key_identifier( &crt ) == 0 );
         if( auth_ident )
             TEST_ASSERT( mbedtls_x509write_crt_set_authority_key_identifier( &crt ) == 0 );
diff --git a/third_party/mbedtls/repo/visualc/VS2010/benchmark.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/benchmark.vcxproj
index 3ff1445..0be32fc 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/benchmark.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/benchmark.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\test\benchmark.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>benchmark</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\test\benchmark.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>benchmark</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/cert_app.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/cert_app.vcxproj
index 8afb1ff..3fbcb52 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/cert_app.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/cert_app.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\x509\cert_app.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{D4D691D4-137C-CBFA-735B-D46636D7E4D8}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>cert_app</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\x509\cert_app.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{D4D691D4-137C-CBFA-735B-D46636D7E4D8}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>cert_app</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/cert_req.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/cert_req.vcxproj
index d7a3f9b..41fdf31 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/cert_req.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/cert_req.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\x509\cert_req.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>cert_req</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\x509\cert_req.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>cert_req</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/cert_write.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/cert_write.vcxproj
index d16ddd8..f1f93ea 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/cert_write.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/cert_write.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\x509\cert_write.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{35E52E46-3BA9-4361-41D3-53663C2E9B8A}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>cert_write</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\x509\cert_write.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{35E52E46-3BA9-4361-41D3-53663C2E9B8A}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>cert_write</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/crl_app.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/crl_app.vcxproj
index 030aa1f..4b8b216 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/crl_app.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/crl_app.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\x509\crl_app.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{DB904B85-AD31-B7FB-114F-88760CC485F2}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>crl_app</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\x509\crl_app.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{DB904B85-AD31-B7FB-114F-88760CC485F2}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>crl_app</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/crypt_and_hash.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/crypt_and_hash.vcxproj
index 6489dc1..885935b 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/crypt_and_hash.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/crypt_and_hash.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\aes\crypt_and_hash.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>crypt_and_hash</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\aes\crypt_and_hash.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>crypt_and_hash</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/crypto_examples.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/crypto_examples.vcxproj
index b81114b..3899f0e 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/crypto_examples.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/crypto_examples.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\psa\crypto_examples.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{020C31BD-C4DF-BABA-E537-F517C4E98537}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>crypto_examples</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\psa\crypto_examples.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{020C31BD-C4DF-BABA-E537-F517C4E98537}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>crypto_examples</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/dh_client.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/dh_client.vcxproj
index 400913d..043ab1a 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/dh_client.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/dh_client.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\dh_client.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>dh_client</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\dh_client.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>dh_client</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/dh_genprime.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/dh_genprime.vcxproj
index d53575b..f0366cb 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/dh_genprime.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/dh_genprime.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\dh_genprime.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{718960D9-5DA6-7B56-39AD-637E81076C71}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>dh_genprime</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\dh_genprime.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{718960D9-5DA6-7B56-39AD-637E81076C71}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>dh_genprime</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/dh_server.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/dh_server.vcxproj
index 31ca675..5a986bc 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/dh_server.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/dh_server.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\dh_server.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{8D91B804-E2CE-142D-8E06-FBB037ED1F65}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>dh_server</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\dh_server.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{8D91B804-E2CE-142D-8E06-FBB037ED1F65}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>dh_server</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/dtls_client.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/dtls_client.vcxproj
index 0027c9e..3fd6545 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/dtls_client.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/dtls_client.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\ssl\dtls_client.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>dtls_client</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\ssl\dtls_client.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>dtls_client</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/dtls_server.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/dtls_server.vcxproj
index ae78136..b10ec4d 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/dtls_server.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/dtls_server.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\ssl\dtls_server.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>dtls_server</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\ssl\dtls_server.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>dtls_server</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/ecdh_curve25519.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/ecdh_curve25519.vcxproj
index a1cf095..578e43b 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/ecdh_curve25519.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/ecdh_curve25519.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\ecdh_curve25519.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{82EE497E-12CC-7C5B-A072-665678ACB43E}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>ecdh_curve25519</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\ecdh_curve25519.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{82EE497E-12CC-7C5B-A072-665678ACB43E}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>ecdh_curve25519</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/ecdsa.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/ecdsa.vcxproj
index fc30bc4..f7ad2e9 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/ecdsa.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/ecdsa.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\ecdsa.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>ecdsa</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\ecdsa.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>ecdsa</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/gen_entropy.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/gen_entropy.vcxproj
index 17bc235..b7e45f9 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/gen_entropy.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/gen_entropy.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\random\gen_entropy.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{DE695064-13C3-18B0-378D-8B22672BF3F4}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>gen_entropy</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\random\gen_entropy.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{DE695064-13C3-18B0-378D-8B22672BF3F4}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>gen_entropy</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/gen_key.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/gen_key.vcxproj
index e148e9c..fa02614 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/gen_key.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/gen_key.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\gen_key.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>gen_key</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\gen_key.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>gen_key</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/gen_random_ctr_drbg.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/gen_random_ctr_drbg.vcxproj
index e259d6c..a385841 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/gen_random_ctr_drbg.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/gen_random_ctr_drbg.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\random\gen_random_ctr_drbg.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>gen_random_ctr_drbg</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\random\gen_random_ctr_drbg.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>gen_random_ctr_drbg</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/gen_random_havege.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/gen_random_havege.vcxproj
index dfec102..d4c008a 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/gen_random_havege.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/gen_random_havege.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\random\gen_random_havege.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{71257802-BBCA-99F5-E9D2-905738F30893}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>gen_random_havege</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\random\gen_random_havege.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{71257802-BBCA-99F5-E9D2-905738F30893}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>gen_random_havege</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/generic_sum.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/generic_sum.vcxproj
index d17776e..faad775 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/generic_sum.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/generic_sum.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\hash\generic_sum.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{D071CCF7-ACA0-21F8-D382-52A759AEA261}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>generic_sum</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\hash\generic_sum.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{D071CCF7-ACA0-21F8-D382-52A759AEA261}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>generic_sum</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/hello.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/hello.vcxproj
index 5595cb8..6a81d91 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/hello.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/hello.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\hash\hello.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>hello</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\hash\hello.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>hello</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/key_app.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/key_app.vcxproj
index 87ef50c..bba5841 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/key_app.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/key_app.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\key_app.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{10AE376F-1A70-0297-0216-1FD01AD15D19}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>key_app</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\key_app.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{10AE376F-1A70-0297-0216-1FD01AD15D19}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>key_app</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/key_app_writer.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/key_app_writer.vcxproj
index f147030..0d70137 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/key_app_writer.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/key_app_writer.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\key_app_writer.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>key_app_writer</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\key_app_writer.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>key_app_writer</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/key_ladder_demo.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/key_ladder_demo.vcxproj
index d08b998..8584aee 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/key_ladder_demo.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/key_ladder_demo.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\psa\key_ladder_demo.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{778777A0-393D-45E8-83C1-EAF487236F1F}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>key_ladder_demo</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\psa\key_ladder_demo.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{778777A0-393D-45E8-83C1-EAF487236F1F}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>key_ladder_demo</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/aescrypt2.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/load_roots.vcxproj
similarity index 97%
rename from third_party/mbedtls/repo/visualc/VS2010/aescrypt2.vcxproj
rename to third_party/mbedtls/repo/visualc/VS2010/load_roots.vcxproj
index 3861a62..1eed657 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/aescrypt2.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/load_roots.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\aes\aescrypt2.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>aescrypt2</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\x509\load_roots.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{65EB85E6-C928-689F-8335-126F78025220}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>load_roots</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/mbedTLS.sln b/third_party/mbedtls/repo/visualc/VS2010/mbedTLS.sln
index d979617..3624735 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/mbedTLS.sln
+++ b/third_party/mbedtls/repo/visualc/VS2010/mbedTLS.sln
@@ -1,702 +1,702 @@
-
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual C++ Express 2010
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mbedTLS", "mbedTLS.vcxproj", "{46CF2D25-6A36-4189-B59C-E4815388E554}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "aescrypt2", "aescrypt2.vcxproj", "{7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crypt_and_hash", "crypt_and_hash.vcxproj", "{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "generic_sum", "generic_sum.vcxproj", "{D071CCF7-ACA0-21F8-D382-52A759AEA261}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello", "hello.vcxproj", "{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dh_client", "dh_client.vcxproj", "{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dh_genprime", "dh_genprime.vcxproj", "{718960D9-5DA6-7B56-39AD-637E81076C71}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dh_server", "dh_server.vcxproj", "{8D91B804-E2CE-142D-8E06-FBB037ED1F65}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ecdh_curve25519", "ecdh_curve25519.vcxproj", "{82EE497E-12CC-7C5B-A072-665678ACB43E}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ecdsa", "ecdsa.vcxproj", "{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_key", "gen_key.vcxproj", "{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "key_app", "key_app.vcxproj", "{10AE376F-1A70-0297-0216-1FD01AD15D19}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "key_app_writer", "key_app_writer.vcxproj", "{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mpi_demo", "mpi_demo.vcxproj", "{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pk_decrypt", "pk_decrypt.vcxproj", "{1EC6CBA3-6187-D456-D9B7-A35399395D71}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pk_encrypt", "pk_encrypt.vcxproj", "{55007179-7746-9CFB-97EC-65102FB272C8}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pk_sign", "pk_sign.vcxproj", "{F2E8CA55-597F-7FDC-6456-D8650FB970A3}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pk_verify", "pk_verify.vcxproj", "{C429B336-1B30-119C-3B34-21A186D6744F}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_decrypt", "rsa_decrypt.vcxproj", "{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_encrypt", "rsa_encrypt.vcxproj", "{D06CF12E-F222-9273-41BF-B8A052FA5527}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_genkey", "rsa_genkey.vcxproj", "{F472475C-F677-0E7F-F127-45BF5B64F622}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_sign", "rsa_sign.vcxproj", "{10790F49-6887-AAB6-2D86-BCBD516F8D26}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_sign_pss", "rsa_sign_pss.vcxproj", "{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_verify", "rsa_verify.vcxproj", "{689E28CF-89ED-BA38-3A14-78A75D891D46}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_verify_pss", "rsa_verify_pss.vcxproj", "{95C50864-854C-2A11-4C91-BCE654E344FB}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crypto_examples", "crypto_examples.vcxproj", "{020C31BD-C4DF-BABA-E537-F517C4E98537}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "key_ladder_demo", "key_ladder_demo.vcxproj", "{778777A0-393D-45E8-83C1-EAF487236F1F}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "psa_constant_names", "psa_constant_names.vcxproj", "{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_entropy", "gen_entropy.vcxproj", "{DE695064-13C3-18B0-378D-8B22672BF3F4}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_random_ctr_drbg", "gen_random_ctr_drbg.vcxproj", "{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_random_havege", "gen_random_havege.vcxproj", "{71257802-BBCA-99F5-E9D2-905738F30893}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dtls_client", "dtls_client.vcxproj", "{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dtls_server", "dtls_server.vcxproj", "{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mini_client", "mini_client.vcxproj", "{C4FE29EA-266D-5295-4840-976B9B5B3843}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_client1", "ssl_client1.vcxproj", "{487A2F80-3CA3-678D-88D5-82194872CF08}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_client2", "ssl_client2.vcxproj", "{4E590E9D-E28F-87FF-385B-D58736388231}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_context_info", "ssl_context_info.vcxproj", "{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_fork_server", "ssl_fork_server.vcxproj", "{918CD402-047D-8467-E11C-E1132053F916}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_mail_client", "ssl_mail_client.vcxproj", "{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_server", "ssl_server.vcxproj", "{E08E0065-896A-7487-DEA5-D3B80B71F975}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_server2", "ssl_server2.vcxproj", "{A4DA7463-1047-BDF5-E1B3-5632CB573F41}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "benchmark", "benchmark.vcxproj", "{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "query_compile_time_config", "query_compile_time_config.vcxproj", "{D6F58AF2-9D80-562A-E2B0-F743281522B9}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "selftest", "selftest.vcxproj", "{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "udp_proxy", "udp_proxy.vcxproj", "{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zeroize", "zeroize.vcxproj", "{10C01E94-4926-063E-9F56-C84ED190D349}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pem2der", "pem2der.vcxproj", "{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "strerror", "strerror.vcxproj", "{23EF735C-CC4C-3EC4-A75E-903DB340F04A}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cert_app", "cert_app.vcxproj", "{D4D691D4-137C-CBFA-735B-D46636D7E4D8}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cert_req", "cert_req.vcxproj", "{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cert_write", "cert_write.vcxproj", "{35E52E46-3BA9-4361-41D3-53663C2E9B8A}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crl_app", "crl_app.vcxproj", "{DB904B85-AD31-B7FB-114F-88760CC485F2}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "req_app", "req_app.vcxproj", "{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}"
-	ProjectSection(ProjectDependencies) = postProject
-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}
-	EndProjectSection
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Win32 = Debug|Win32
-		Debug|x64 = Debug|x64
-		Release|Win32 = Release|Win32
-		Release|x64 = Release|x64
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|Win32.ActiveCfg = Debug|Win32
-		{46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|Win32.Build.0 = Debug|Win32
-		{46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|x64.ActiveCfg = Debug|x64
-		{46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|x64.Build.0 = Debug|x64
-		{46CF2D25-6A36-4189-B59C-E4815388E554}.Release|Win32.ActiveCfg = Release|Win32
-		{46CF2D25-6A36-4189-B59C-E4815388E554}.Release|Win32.Build.0 = Release|Win32
-		{46CF2D25-6A36-4189-B59C-E4815388E554}.Release|x64.ActiveCfg = Release|x64
-		{46CF2D25-6A36-4189-B59C-E4815388E554}.Release|x64.Build.0 = Release|x64
-		{7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}.Debug|Win32.ActiveCfg = Debug|Win32
-		{7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}.Debug|Win32.Build.0 = Debug|Win32
-		{7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}.Debug|x64.ActiveCfg = Debug|x64
-		{7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}.Debug|x64.Build.0 = Debug|x64
-		{7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}.Release|Win32.ActiveCfg = Release|Win32
-		{7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}.Release|Win32.Build.0 = Release|Win32
-		{7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}.Release|x64.ActiveCfg = Release|x64
-		{7A851DBD-7D57-E8F4-85E5-CCA72AEA7DF8}.Release|x64.Build.0 = Release|x64
-		{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Debug|Win32.ActiveCfg = Debug|Win32
-		{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Debug|Win32.Build.0 = Debug|Win32
-		{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Debug|x64.ActiveCfg = Debug|x64
-		{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Debug|x64.Build.0 = Debug|x64
-		{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Release|Win32.ActiveCfg = Release|Win32
-		{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Release|Win32.Build.0 = Release|Win32
-		{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Release|x64.ActiveCfg = Release|x64
-		{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Release|x64.Build.0 = Release|x64
-		{D071CCF7-ACA0-21F8-D382-52A759AEA261}.Debug|Win32.ActiveCfg = Debug|Win32
-		{D071CCF7-ACA0-21F8-D382-52A759AEA261}.Debug|Win32.Build.0 = Debug|Win32
-		{D071CCF7-ACA0-21F8-D382-52A759AEA261}.Debug|x64.ActiveCfg = Debug|x64
-		{D071CCF7-ACA0-21F8-D382-52A759AEA261}.Debug|x64.Build.0 = Debug|x64
-		{D071CCF7-ACA0-21F8-D382-52A759AEA261}.Release|Win32.ActiveCfg = Release|Win32
-		{D071CCF7-ACA0-21F8-D382-52A759AEA261}.Release|Win32.Build.0 = Release|Win32
-		{D071CCF7-ACA0-21F8-D382-52A759AEA261}.Release|x64.ActiveCfg = Release|x64
-		{D071CCF7-ACA0-21F8-D382-52A759AEA261}.Release|x64.Build.0 = Release|x64
-		{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Debug|Win32.ActiveCfg = Debug|Win32
-		{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Debug|Win32.Build.0 = Debug|Win32
-		{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Debug|x64.ActiveCfg = Debug|x64
-		{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Debug|x64.Build.0 = Debug|x64
-		{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Release|Win32.ActiveCfg = Release|Win32
-		{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Release|Win32.Build.0 = Release|Win32
-		{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Release|x64.ActiveCfg = Release|x64
-		{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Release|x64.Build.0 = Release|x64
-		{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Debug|Win32.ActiveCfg = Debug|Win32
-		{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Debug|Win32.Build.0 = Debug|Win32
-		{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Debug|x64.ActiveCfg = Debug|x64
-		{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Debug|x64.Build.0 = Debug|x64
-		{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Release|Win32.ActiveCfg = Release|Win32
-		{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Release|Win32.Build.0 = Release|Win32
-		{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Release|x64.ActiveCfg = Release|x64
-		{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Release|x64.Build.0 = Release|x64
-		{718960D9-5DA6-7B56-39AD-637E81076C71}.Debug|Win32.ActiveCfg = Debug|Win32
-		{718960D9-5DA6-7B56-39AD-637E81076C71}.Debug|Win32.Build.0 = Debug|Win32
-		{718960D9-5DA6-7B56-39AD-637E81076C71}.Debug|x64.ActiveCfg = Debug|x64
-		{718960D9-5DA6-7B56-39AD-637E81076C71}.Debug|x64.Build.0 = Debug|x64
-		{718960D9-5DA6-7B56-39AD-637E81076C71}.Release|Win32.ActiveCfg = Release|Win32
-		{718960D9-5DA6-7B56-39AD-637E81076C71}.Release|Win32.Build.0 = Release|Win32
-		{718960D9-5DA6-7B56-39AD-637E81076C71}.Release|x64.ActiveCfg = Release|x64
-		{718960D9-5DA6-7B56-39AD-637E81076C71}.Release|x64.Build.0 = Release|x64
-		{8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Debug|Win32.ActiveCfg = Debug|Win32
-		{8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Debug|Win32.Build.0 = Debug|Win32
-		{8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Debug|x64.ActiveCfg = Debug|x64
-		{8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Debug|x64.Build.0 = Debug|x64
-		{8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Release|Win32.ActiveCfg = Release|Win32
-		{8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Release|Win32.Build.0 = Release|Win32
-		{8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Release|x64.ActiveCfg = Release|x64
-		{8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Release|x64.Build.0 = Release|x64
-		{82EE497E-12CC-7C5B-A072-665678ACB43E}.Debug|Win32.ActiveCfg = Debug|Win32
-		{82EE497E-12CC-7C5B-A072-665678ACB43E}.Debug|Win32.Build.0 = Debug|Win32
-		{82EE497E-12CC-7C5B-A072-665678ACB43E}.Debug|x64.ActiveCfg = Debug|x64
-		{82EE497E-12CC-7C5B-A072-665678ACB43E}.Debug|x64.Build.0 = Debug|x64
-		{82EE497E-12CC-7C5B-A072-665678ACB43E}.Release|Win32.ActiveCfg = Release|Win32
-		{82EE497E-12CC-7C5B-A072-665678ACB43E}.Release|Win32.Build.0 = Release|Win32
-		{82EE497E-12CC-7C5B-A072-665678ACB43E}.Release|x64.ActiveCfg = Release|x64
-		{82EE497E-12CC-7C5B-A072-665678ACB43E}.Release|x64.Build.0 = Release|x64
-		{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Debug|Win32.ActiveCfg = Debug|Win32
-		{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Debug|Win32.Build.0 = Debug|Win32
-		{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Debug|x64.ActiveCfg = Debug|x64
-		{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Debug|x64.Build.0 = Debug|x64
-		{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Release|Win32.ActiveCfg = Release|Win32
-		{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Release|Win32.Build.0 = Release|Win32
-		{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Release|x64.ActiveCfg = Release|x64
-		{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Release|x64.Build.0 = Release|x64
-		{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Debug|Win32.ActiveCfg = Debug|Win32
-		{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Debug|Win32.Build.0 = Debug|Win32
-		{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Debug|x64.ActiveCfg = Debug|x64
-		{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Debug|x64.Build.0 = Debug|x64
-		{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Release|Win32.ActiveCfg = Release|Win32
-		{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Release|Win32.Build.0 = Release|Win32
-		{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Release|x64.ActiveCfg = Release|x64
-		{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Release|x64.Build.0 = Release|x64
-		{10AE376F-1A70-0297-0216-1FD01AD15D19}.Debug|Win32.ActiveCfg = Debug|Win32
-		{10AE376F-1A70-0297-0216-1FD01AD15D19}.Debug|Win32.Build.0 = Debug|Win32
-		{10AE376F-1A70-0297-0216-1FD01AD15D19}.Debug|x64.ActiveCfg = Debug|x64
-		{10AE376F-1A70-0297-0216-1FD01AD15D19}.Debug|x64.Build.0 = Debug|x64
-		{10AE376F-1A70-0297-0216-1FD01AD15D19}.Release|Win32.ActiveCfg = Release|Win32
-		{10AE376F-1A70-0297-0216-1FD01AD15D19}.Release|Win32.Build.0 = Release|Win32
-		{10AE376F-1A70-0297-0216-1FD01AD15D19}.Release|x64.ActiveCfg = Release|x64
-		{10AE376F-1A70-0297-0216-1FD01AD15D19}.Release|x64.Build.0 = Release|x64
-		{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Debug|Win32.ActiveCfg = Debug|Win32
-		{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Debug|Win32.Build.0 = Debug|Win32
-		{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Debug|x64.ActiveCfg = Debug|x64
-		{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Debug|x64.Build.0 = Debug|x64
-		{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Release|Win32.ActiveCfg = Release|Win32
-		{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Release|Win32.Build.0 = Release|Win32
-		{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Release|x64.ActiveCfg = Release|x64
-		{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Release|x64.Build.0 = Release|x64
-		{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Debug|Win32.ActiveCfg = Debug|Win32
-		{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Debug|Win32.Build.0 = Debug|Win32
-		{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Debug|x64.ActiveCfg = Debug|x64
-		{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Debug|x64.Build.0 = Debug|x64
-		{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Release|Win32.ActiveCfg = Release|Win32
-		{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Release|Win32.Build.0 = Release|Win32
-		{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Release|x64.ActiveCfg = Release|x64
-		{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Release|x64.Build.0 = Release|x64
-		{1EC6CBA3-6187-D456-D9B7-A35399395D71}.Debug|Win32.ActiveCfg = Debug|Win32
-		{1EC6CBA3-6187-D456-D9B7-A35399395D71}.Debug|Win32.Build.0 = Debug|Win32
-		{1EC6CBA3-6187-D456-D9B7-A35399395D71}.Debug|x64.ActiveCfg = Debug|x64
-		{1EC6CBA3-6187-D456-D9B7-A35399395D71}.Debug|x64.Build.0 = Debug|x64
-		{1EC6CBA3-6187-D456-D9B7-A35399395D71}.Release|Win32.ActiveCfg = Release|Win32
-		{1EC6CBA3-6187-D456-D9B7-A35399395D71}.Release|Win32.Build.0 = Release|Win32
-		{1EC6CBA3-6187-D456-D9B7-A35399395D71}.Release|x64.ActiveCfg = Release|x64
-		{1EC6CBA3-6187-D456-D9B7-A35399395D71}.Release|x64.Build.0 = Release|x64
-		{55007179-7746-9CFB-97EC-65102FB272C8}.Debug|Win32.ActiveCfg = Debug|Win32
-		{55007179-7746-9CFB-97EC-65102FB272C8}.Debug|Win32.Build.0 = Debug|Win32
-		{55007179-7746-9CFB-97EC-65102FB272C8}.Debug|x64.ActiveCfg = Debug|x64
-		{55007179-7746-9CFB-97EC-65102FB272C8}.Debug|x64.Build.0 = Debug|x64
-		{55007179-7746-9CFB-97EC-65102FB272C8}.Release|Win32.ActiveCfg = Release|Win32
-		{55007179-7746-9CFB-97EC-65102FB272C8}.Release|Win32.Build.0 = Release|Win32
-		{55007179-7746-9CFB-97EC-65102FB272C8}.Release|x64.ActiveCfg = Release|x64
-		{55007179-7746-9CFB-97EC-65102FB272C8}.Release|x64.Build.0 = Release|x64
-		{F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Debug|Win32.ActiveCfg = Debug|Win32
-		{F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Debug|Win32.Build.0 = Debug|Win32
-		{F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Debug|x64.ActiveCfg = Debug|x64
-		{F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Debug|x64.Build.0 = Debug|x64
-		{F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Release|Win32.ActiveCfg = Release|Win32
-		{F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Release|Win32.Build.0 = Release|Win32
-		{F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Release|x64.ActiveCfg = Release|x64
-		{F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Release|x64.Build.0 = Release|x64
-		{C429B336-1B30-119C-3B34-21A186D6744F}.Debug|Win32.ActiveCfg = Debug|Win32
-		{C429B336-1B30-119C-3B34-21A186D6744F}.Debug|Win32.Build.0 = Debug|Win32
-		{C429B336-1B30-119C-3B34-21A186D6744F}.Debug|x64.ActiveCfg = Debug|x64
-		{C429B336-1B30-119C-3B34-21A186D6744F}.Debug|x64.Build.0 = Debug|x64
-		{C429B336-1B30-119C-3B34-21A186D6744F}.Release|Win32.ActiveCfg = Release|Win32
-		{C429B336-1B30-119C-3B34-21A186D6744F}.Release|Win32.Build.0 = Release|Win32
-		{C429B336-1B30-119C-3B34-21A186D6744F}.Release|x64.ActiveCfg = Release|x64
-		{C429B336-1B30-119C-3B34-21A186D6744F}.Release|x64.Build.0 = Release|x64
-		{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Debug|Win32.ActiveCfg = Debug|Win32
-		{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Debug|Win32.Build.0 = Debug|Win32
-		{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Debug|x64.ActiveCfg = Debug|x64
-		{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Debug|x64.Build.0 = Debug|x64
-		{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Release|Win32.ActiveCfg = Release|Win32
-		{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Release|Win32.Build.0 = Release|Win32
-		{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Release|x64.ActiveCfg = Release|x64
-		{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Release|x64.Build.0 = Release|x64
-		{D06CF12E-F222-9273-41BF-B8A052FA5527}.Debug|Win32.ActiveCfg = Debug|Win32
-		{D06CF12E-F222-9273-41BF-B8A052FA5527}.Debug|Win32.Build.0 = Debug|Win32
-		{D06CF12E-F222-9273-41BF-B8A052FA5527}.Debug|x64.ActiveCfg = Debug|x64
-		{D06CF12E-F222-9273-41BF-B8A052FA5527}.Debug|x64.Build.0 = Debug|x64
-		{D06CF12E-F222-9273-41BF-B8A052FA5527}.Release|Win32.ActiveCfg = Release|Win32
-		{D06CF12E-F222-9273-41BF-B8A052FA5527}.Release|Win32.Build.0 = Release|Win32
-		{D06CF12E-F222-9273-41BF-B8A052FA5527}.Release|x64.ActiveCfg = Release|x64
-		{D06CF12E-F222-9273-41BF-B8A052FA5527}.Release|x64.Build.0 = Release|x64
-		{F472475C-F677-0E7F-F127-45BF5B64F622}.Debug|Win32.ActiveCfg = Debug|Win32
-		{F472475C-F677-0E7F-F127-45BF5B64F622}.Debug|Win32.Build.0 = Debug|Win32
-		{F472475C-F677-0E7F-F127-45BF5B64F622}.Debug|x64.ActiveCfg = Debug|x64
-		{F472475C-F677-0E7F-F127-45BF5B64F622}.Debug|x64.Build.0 = Debug|x64
-		{F472475C-F677-0E7F-F127-45BF5B64F622}.Release|Win32.ActiveCfg = Release|Win32
-		{F472475C-F677-0E7F-F127-45BF5B64F622}.Release|Win32.Build.0 = Release|Win32
-		{F472475C-F677-0E7F-F127-45BF5B64F622}.Release|x64.ActiveCfg = Release|x64
-		{F472475C-F677-0E7F-F127-45BF5B64F622}.Release|x64.Build.0 = Release|x64
-		{10790F49-6887-AAB6-2D86-BCBD516F8D26}.Debug|Win32.ActiveCfg = Debug|Win32
-		{10790F49-6887-AAB6-2D86-BCBD516F8D26}.Debug|Win32.Build.0 = Debug|Win32
-		{10790F49-6887-AAB6-2D86-BCBD516F8D26}.Debug|x64.ActiveCfg = Debug|x64
-		{10790F49-6887-AAB6-2D86-BCBD516F8D26}.Debug|x64.Build.0 = Debug|x64
-		{10790F49-6887-AAB6-2D86-BCBD516F8D26}.Release|Win32.ActiveCfg = Release|Win32
-		{10790F49-6887-AAB6-2D86-BCBD516F8D26}.Release|Win32.Build.0 = Release|Win32
-		{10790F49-6887-AAB6-2D86-BCBD516F8D26}.Release|x64.ActiveCfg = Release|x64
-		{10790F49-6887-AAB6-2D86-BCBD516F8D26}.Release|x64.Build.0 = Release|x64
-		{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Debug|Win32.ActiveCfg = Debug|Win32
-		{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Debug|Win32.Build.0 = Debug|Win32
-		{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Debug|x64.ActiveCfg = Debug|x64
-		{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Debug|x64.Build.0 = Debug|x64
-		{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Release|Win32.ActiveCfg = Release|Win32
-		{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Release|Win32.Build.0 = Release|Win32
-		{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Release|x64.ActiveCfg = Release|x64
-		{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Release|x64.Build.0 = Release|x64
-		{689E28CF-89ED-BA38-3A14-78A75D891D46}.Debug|Win32.ActiveCfg = Debug|Win32
-		{689E28CF-89ED-BA38-3A14-78A75D891D46}.Debug|Win32.Build.0 = Debug|Win32
-		{689E28CF-89ED-BA38-3A14-78A75D891D46}.Debug|x64.ActiveCfg = Debug|x64
-		{689E28CF-89ED-BA38-3A14-78A75D891D46}.Debug|x64.Build.0 = Debug|x64
-		{689E28CF-89ED-BA38-3A14-78A75D891D46}.Release|Win32.ActiveCfg = Release|Win32
-		{689E28CF-89ED-BA38-3A14-78A75D891D46}.Release|Win32.Build.0 = Release|Win32
-		{689E28CF-89ED-BA38-3A14-78A75D891D46}.Release|x64.ActiveCfg = Release|x64
-		{689E28CF-89ED-BA38-3A14-78A75D891D46}.Release|x64.Build.0 = Release|x64
-		{95C50864-854C-2A11-4C91-BCE654E344FB}.Debug|Win32.ActiveCfg = Debug|Win32
-		{95C50864-854C-2A11-4C91-BCE654E344FB}.Debug|Win32.Build.0 = Debug|Win32
-		{95C50864-854C-2A11-4C91-BCE654E344FB}.Debug|x64.ActiveCfg = Debug|x64
-		{95C50864-854C-2A11-4C91-BCE654E344FB}.Debug|x64.Build.0 = Debug|x64
-		{95C50864-854C-2A11-4C91-BCE654E344FB}.Release|Win32.ActiveCfg = Release|Win32
-		{95C50864-854C-2A11-4C91-BCE654E344FB}.Release|Win32.Build.0 = Release|Win32
-		{95C50864-854C-2A11-4C91-BCE654E344FB}.Release|x64.ActiveCfg = Release|x64
-		{95C50864-854C-2A11-4C91-BCE654E344FB}.Release|x64.Build.0 = Release|x64
-		{020C31BD-C4DF-BABA-E537-F517C4E98537}.Debug|Win32.ActiveCfg = Debug|Win32
-		{020C31BD-C4DF-BABA-E537-F517C4E98537}.Debug|Win32.Build.0 = Debug|Win32
-		{020C31BD-C4DF-BABA-E537-F517C4E98537}.Debug|x64.ActiveCfg = Debug|x64
-		{020C31BD-C4DF-BABA-E537-F517C4E98537}.Debug|x64.Build.0 = Debug|x64
-		{020C31BD-C4DF-BABA-E537-F517C4E98537}.Release|Win32.ActiveCfg = Release|Win32
-		{020C31BD-C4DF-BABA-E537-F517C4E98537}.Release|Win32.Build.0 = Release|Win32
-		{020C31BD-C4DF-BABA-E537-F517C4E98537}.Release|x64.ActiveCfg = Release|x64
-		{020C31BD-C4DF-BABA-E537-F517C4E98537}.Release|x64.Build.0 = Release|x64
-		{778777A0-393D-45E8-83C1-EAF487236F1F}.Debug|Win32.ActiveCfg = Debug|Win32
-		{778777A0-393D-45E8-83C1-EAF487236F1F}.Debug|Win32.Build.0 = Debug|Win32
-		{778777A0-393D-45E8-83C1-EAF487236F1F}.Debug|x64.ActiveCfg = Debug|x64
-		{778777A0-393D-45E8-83C1-EAF487236F1F}.Debug|x64.Build.0 = Debug|x64
-		{778777A0-393D-45E8-83C1-EAF487236F1F}.Release|Win32.ActiveCfg = Release|Win32
-		{778777A0-393D-45E8-83C1-EAF487236F1F}.Release|Win32.Build.0 = Release|Win32
-		{778777A0-393D-45E8-83C1-EAF487236F1F}.Release|x64.ActiveCfg = Release|x64
-		{778777A0-393D-45E8-83C1-EAF487236F1F}.Release|x64.Build.0 = Release|x64
-		{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Debug|Win32.ActiveCfg = Debug|Win32
-		{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Debug|Win32.Build.0 = Debug|Win32
-		{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Debug|x64.ActiveCfg = Debug|x64
-		{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Debug|x64.Build.0 = Debug|x64
-		{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Release|Win32.ActiveCfg = Release|Win32
-		{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Release|Win32.Build.0 = Release|Win32
-		{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Release|x64.ActiveCfg = Release|x64
-		{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Release|x64.Build.0 = Release|x64
-		{DE695064-13C3-18B0-378D-8B22672BF3F4}.Debug|Win32.ActiveCfg = Debug|Win32
-		{DE695064-13C3-18B0-378D-8B22672BF3F4}.Debug|Win32.Build.0 = Debug|Win32
-		{DE695064-13C3-18B0-378D-8B22672BF3F4}.Debug|x64.ActiveCfg = Debug|x64
-		{DE695064-13C3-18B0-378D-8B22672BF3F4}.Debug|x64.Build.0 = Debug|x64
-		{DE695064-13C3-18B0-378D-8B22672BF3F4}.Release|Win32.ActiveCfg = Release|Win32
-		{DE695064-13C3-18B0-378D-8B22672BF3F4}.Release|Win32.Build.0 = Release|Win32
-		{DE695064-13C3-18B0-378D-8B22672BF3F4}.Release|x64.ActiveCfg = Release|x64
-		{DE695064-13C3-18B0-378D-8B22672BF3F4}.Release|x64.Build.0 = Release|x64
-		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Debug|Win32.ActiveCfg = Debug|Win32
-		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Debug|Win32.Build.0 = Debug|Win32
-		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Debug|x64.ActiveCfg = Debug|x64
-		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Debug|x64.Build.0 = Debug|x64
-		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Release|Win32.ActiveCfg = Release|Win32
-		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Release|Win32.Build.0 = Release|Win32
-		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Release|x64.ActiveCfg = Release|x64
-		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Release|x64.Build.0 = Release|x64
-		{71257802-BBCA-99F5-E9D2-905738F30893}.Debug|Win32.ActiveCfg = Debug|Win32
-		{71257802-BBCA-99F5-E9D2-905738F30893}.Debug|Win32.Build.0 = Debug|Win32
-		{71257802-BBCA-99F5-E9D2-905738F30893}.Debug|x64.ActiveCfg = Debug|x64
-		{71257802-BBCA-99F5-E9D2-905738F30893}.Debug|x64.Build.0 = Debug|x64
-		{71257802-BBCA-99F5-E9D2-905738F30893}.Release|Win32.ActiveCfg = Release|Win32
-		{71257802-BBCA-99F5-E9D2-905738F30893}.Release|Win32.Build.0 = Release|Win32
-		{71257802-BBCA-99F5-E9D2-905738F30893}.Release|x64.ActiveCfg = Release|x64
-		{71257802-BBCA-99F5-E9D2-905738F30893}.Release|x64.Build.0 = Release|x64
-		{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Debug|Win32.ActiveCfg = Debug|Win32
-		{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Debug|Win32.Build.0 = Debug|Win32
-		{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Debug|x64.ActiveCfg = Debug|x64
-		{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Debug|x64.Build.0 = Debug|x64
-		{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Release|Win32.ActiveCfg = Release|Win32
-		{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Release|Win32.Build.0 = Release|Win32
-		{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Release|x64.ActiveCfg = Release|x64
-		{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Release|x64.Build.0 = Release|x64
-		{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Debug|Win32.ActiveCfg = Debug|Win32
-		{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Debug|Win32.Build.0 = Debug|Win32
-		{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Debug|x64.ActiveCfg = Debug|x64
-		{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Debug|x64.Build.0 = Debug|x64
-		{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Release|Win32.ActiveCfg = Release|Win32
-		{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Release|Win32.Build.0 = Release|Win32
-		{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Release|x64.ActiveCfg = Release|x64
-		{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Release|x64.Build.0 = Release|x64
-		{C4FE29EA-266D-5295-4840-976B9B5B3843}.Debug|Win32.ActiveCfg = Debug|Win32
-		{C4FE29EA-266D-5295-4840-976B9B5B3843}.Debug|Win32.Build.0 = Debug|Win32
-		{C4FE29EA-266D-5295-4840-976B9B5B3843}.Debug|x64.ActiveCfg = Debug|x64
-		{C4FE29EA-266D-5295-4840-976B9B5B3843}.Debug|x64.Build.0 = Debug|x64
-		{C4FE29EA-266D-5295-4840-976B9B5B3843}.Release|Win32.ActiveCfg = Release|Win32
-		{C4FE29EA-266D-5295-4840-976B9B5B3843}.Release|Win32.Build.0 = Release|Win32
-		{C4FE29EA-266D-5295-4840-976B9B5B3843}.Release|x64.ActiveCfg = Release|x64
-		{C4FE29EA-266D-5295-4840-976B9B5B3843}.Release|x64.Build.0 = Release|x64
-		{487A2F80-3CA3-678D-88D5-82194872CF08}.Debug|Win32.ActiveCfg = Debug|Win32
-		{487A2F80-3CA3-678D-88D5-82194872CF08}.Debug|Win32.Build.0 = Debug|Win32
-		{487A2F80-3CA3-678D-88D5-82194872CF08}.Debug|x64.ActiveCfg = Debug|x64
-		{487A2F80-3CA3-678D-88D5-82194872CF08}.Debug|x64.Build.0 = Debug|x64
-		{487A2F80-3CA3-678D-88D5-82194872CF08}.Release|Win32.ActiveCfg = Release|Win32
-		{487A2F80-3CA3-678D-88D5-82194872CF08}.Release|Win32.Build.0 = Release|Win32
-		{487A2F80-3CA3-678D-88D5-82194872CF08}.Release|x64.ActiveCfg = Release|x64
-		{487A2F80-3CA3-678D-88D5-82194872CF08}.Release|x64.Build.0 = Release|x64
-		{4E590E9D-E28F-87FF-385B-D58736388231}.Debug|Win32.ActiveCfg = Debug|Win32
-		{4E590E9D-E28F-87FF-385B-D58736388231}.Debug|Win32.Build.0 = Debug|Win32
-		{4E590E9D-E28F-87FF-385B-D58736388231}.Debug|x64.ActiveCfg = Debug|x64
-		{4E590E9D-E28F-87FF-385B-D58736388231}.Debug|x64.Build.0 = Debug|x64
-		{4E590E9D-E28F-87FF-385B-D58736388231}.Release|Win32.ActiveCfg = Release|Win32
-		{4E590E9D-E28F-87FF-385B-D58736388231}.Release|Win32.Build.0 = Release|Win32
-		{4E590E9D-E28F-87FF-385B-D58736388231}.Release|x64.ActiveCfg = Release|x64
-		{4E590E9D-E28F-87FF-385B-D58736388231}.Release|x64.Build.0 = Release|x64
-		{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}.Debug|Win32.ActiveCfg = Debug|Win32
-		{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}.Debug|Win32.Build.0 = Debug|Win32
-		{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}.Debug|x64.ActiveCfg = Debug|x64
-		{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}.Debug|x64.Build.0 = Debug|x64
-		{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}.Release|Win32.ActiveCfg = Release|Win32
-		{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}.Release|Win32.Build.0 = Release|Win32
-		{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}.Release|x64.ActiveCfg = Release|x64
-		{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}.Release|x64.Build.0 = Release|x64
-		{918CD402-047D-8467-E11C-E1132053F916}.Debug|Win32.ActiveCfg = Debug|Win32
-		{918CD402-047D-8467-E11C-E1132053F916}.Debug|Win32.Build.0 = Debug|Win32
-		{918CD402-047D-8467-E11C-E1132053F916}.Debug|x64.ActiveCfg = Debug|x64
-		{918CD402-047D-8467-E11C-E1132053F916}.Debug|x64.Build.0 = Debug|x64
-		{918CD402-047D-8467-E11C-E1132053F916}.Release|Win32.ActiveCfg = Release|Win32
-		{918CD402-047D-8467-E11C-E1132053F916}.Release|Win32.Build.0 = Release|Win32
-		{918CD402-047D-8467-E11C-E1132053F916}.Release|x64.ActiveCfg = Release|x64
-		{918CD402-047D-8467-E11C-E1132053F916}.Release|x64.Build.0 = Release|x64
-		{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Debug|Win32.ActiveCfg = Debug|Win32
-		{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Debug|Win32.Build.0 = Debug|Win32
-		{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Debug|x64.ActiveCfg = Debug|x64
-		{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Debug|x64.Build.0 = Debug|x64
-		{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Release|Win32.ActiveCfg = Release|Win32
-		{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Release|Win32.Build.0 = Release|Win32
-		{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Release|x64.ActiveCfg = Release|x64
-		{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Release|x64.Build.0 = Release|x64
-		{E08E0065-896A-7487-DEA5-D3B80B71F975}.Debug|Win32.ActiveCfg = Debug|Win32
-		{E08E0065-896A-7487-DEA5-D3B80B71F975}.Debug|Win32.Build.0 = Debug|Win32
-		{E08E0065-896A-7487-DEA5-D3B80B71F975}.Debug|x64.ActiveCfg = Debug|x64
-		{E08E0065-896A-7487-DEA5-D3B80B71F975}.Debug|x64.Build.0 = Debug|x64
-		{E08E0065-896A-7487-DEA5-D3B80B71F975}.Release|Win32.ActiveCfg = Release|Win32
-		{E08E0065-896A-7487-DEA5-D3B80B71F975}.Release|Win32.Build.0 = Release|Win32
-		{E08E0065-896A-7487-DEA5-D3B80B71F975}.Release|x64.ActiveCfg = Release|x64
-		{E08E0065-896A-7487-DEA5-D3B80B71F975}.Release|x64.Build.0 = Release|x64
-		{A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Debug|Win32.ActiveCfg = Debug|Win32
-		{A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Debug|Win32.Build.0 = Debug|Win32
-		{A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Debug|x64.ActiveCfg = Debug|x64
-		{A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Debug|x64.Build.0 = Debug|x64
-		{A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Release|Win32.ActiveCfg = Release|Win32
-		{A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Release|Win32.Build.0 = Release|Win32
-		{A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Release|x64.ActiveCfg = Release|x64
-		{A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Release|x64.Build.0 = Release|x64
-		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Debug|Win32.ActiveCfg = Debug|Win32
-		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Debug|Win32.Build.0 = Debug|Win32
-		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Debug|x64.ActiveCfg = Debug|x64
-		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Debug|x64.Build.0 = Debug|x64
-		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Release|Win32.ActiveCfg = Release|Win32
-		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Release|Win32.Build.0 = Release|Win32
-		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Release|x64.ActiveCfg = Release|x64
-		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Release|x64.Build.0 = Release|x64
-		{D6F58AF2-9D80-562A-E2B0-F743281522B9}.Debug|Win32.ActiveCfg = Debug|Win32
-		{D6F58AF2-9D80-562A-E2B0-F743281522B9}.Debug|Win32.Build.0 = Debug|Win32
-		{D6F58AF2-9D80-562A-E2B0-F743281522B9}.Debug|x64.ActiveCfg = Debug|x64
-		{D6F58AF2-9D80-562A-E2B0-F743281522B9}.Debug|x64.Build.0 = Debug|x64
-		{D6F58AF2-9D80-562A-E2B0-F743281522B9}.Release|Win32.ActiveCfg = Release|Win32
-		{D6F58AF2-9D80-562A-E2B0-F743281522B9}.Release|Win32.Build.0 = Release|Win32
-		{D6F58AF2-9D80-562A-E2B0-F743281522B9}.Release|x64.ActiveCfg = Release|x64
-		{D6F58AF2-9D80-562A-E2B0-F743281522B9}.Release|x64.Build.0 = Release|x64
-		{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Debug|Win32.ActiveCfg = Debug|Win32
-		{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Debug|Win32.Build.0 = Debug|Win32
-		{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Debug|x64.ActiveCfg = Debug|x64
-		{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Debug|x64.Build.0 = Debug|x64
-		{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Release|Win32.ActiveCfg = Release|Win32
-		{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Release|Win32.Build.0 = Release|Win32
-		{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Release|x64.ActiveCfg = Release|x64
-		{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Release|x64.Build.0 = Release|x64
-		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Debug|Win32.ActiveCfg = Debug|Win32
-		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Debug|Win32.Build.0 = Debug|Win32
-		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Debug|x64.ActiveCfg = Debug|x64
-		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Debug|x64.Build.0 = Debug|x64
-		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|Win32.ActiveCfg = Release|Win32
-		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|Win32.Build.0 = Release|Win32
-		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|x64.ActiveCfg = Release|x64
-		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|x64.Build.0 = Release|x64
-		{10C01E94-4926-063E-9F56-C84ED190D349}.Debug|Win32.ActiveCfg = Debug|Win32
-		{10C01E94-4926-063E-9F56-C84ED190D349}.Debug|Win32.Build.0 = Debug|Win32
-		{10C01E94-4926-063E-9F56-C84ED190D349}.Debug|x64.ActiveCfg = Debug|x64
-		{10C01E94-4926-063E-9F56-C84ED190D349}.Debug|x64.Build.0 = Debug|x64
-		{10C01E94-4926-063E-9F56-C84ED190D349}.Release|Win32.ActiveCfg = Release|Win32
-		{10C01E94-4926-063E-9F56-C84ED190D349}.Release|Win32.Build.0 = Release|Win32
-		{10C01E94-4926-063E-9F56-C84ED190D349}.Release|x64.ActiveCfg = Release|x64
-		{10C01E94-4926-063E-9F56-C84ED190D349}.Release|x64.Build.0 = Release|x64
-		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Debug|Win32.ActiveCfg = Debug|Win32
-		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Debug|Win32.Build.0 = Debug|Win32
-		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Debug|x64.ActiveCfg = Debug|x64
-		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Debug|x64.Build.0 = Debug|x64
-		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Release|Win32.ActiveCfg = Release|Win32
-		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Release|Win32.Build.0 = Release|Win32
-		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Release|x64.ActiveCfg = Release|x64
-		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Release|x64.Build.0 = Release|x64
-		{23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Debug|Win32.ActiveCfg = Debug|Win32
-		{23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Debug|Win32.Build.0 = Debug|Win32
-		{23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Debug|x64.ActiveCfg = Debug|x64
-		{23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Debug|x64.Build.0 = Debug|x64
-		{23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Release|Win32.ActiveCfg = Release|Win32
-		{23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Release|Win32.Build.0 = Release|Win32
-		{23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Release|x64.ActiveCfg = Release|x64
-		{23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Release|x64.Build.0 = Release|x64
-		{D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Debug|Win32.ActiveCfg = Debug|Win32
-		{D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Debug|Win32.Build.0 = Debug|Win32
-		{D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Debug|x64.ActiveCfg = Debug|x64
-		{D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Debug|x64.Build.0 = Debug|x64
-		{D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Release|Win32.ActiveCfg = Release|Win32
-		{D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Release|Win32.Build.0 = Release|Win32
-		{D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Release|x64.ActiveCfg = Release|x64
-		{D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Release|x64.Build.0 = Release|x64
-		{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Debug|Win32.ActiveCfg = Debug|Win32
-		{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Debug|Win32.Build.0 = Debug|Win32
-		{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Debug|x64.ActiveCfg = Debug|x64
-		{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Debug|x64.Build.0 = Debug|x64
-		{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Release|Win32.ActiveCfg = Release|Win32
-		{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Release|Win32.Build.0 = Release|Win32
-		{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Release|x64.ActiveCfg = Release|x64
-		{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Release|x64.Build.0 = Release|x64
-		{35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Debug|Win32.ActiveCfg = Debug|Win32
-		{35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Debug|Win32.Build.0 = Debug|Win32
-		{35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Debug|x64.ActiveCfg = Debug|x64
-		{35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Debug|x64.Build.0 = Debug|x64
-		{35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Release|Win32.ActiveCfg = Release|Win32
-		{35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Release|Win32.Build.0 = Release|Win32
-		{35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Release|x64.ActiveCfg = Release|x64
-		{35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Release|x64.Build.0 = Release|x64
-		{DB904B85-AD31-B7FB-114F-88760CC485F2}.Debug|Win32.ActiveCfg = Debug|Win32
-		{DB904B85-AD31-B7FB-114F-88760CC485F2}.Debug|Win32.Build.0 = Debug|Win32
-		{DB904B85-AD31-B7FB-114F-88760CC485F2}.Debug|x64.ActiveCfg = Debug|x64
-		{DB904B85-AD31-B7FB-114F-88760CC485F2}.Debug|x64.Build.0 = Debug|x64
-		{DB904B85-AD31-B7FB-114F-88760CC485F2}.Release|Win32.ActiveCfg = Release|Win32
-		{DB904B85-AD31-B7FB-114F-88760CC485F2}.Release|Win32.Build.0 = Release|Win32
-		{DB904B85-AD31-B7FB-114F-88760CC485F2}.Release|x64.ActiveCfg = Release|x64
-		{DB904B85-AD31-B7FB-114F-88760CC485F2}.Release|x64.Build.0 = Release|x64
-		{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Debug|Win32.ActiveCfg = Debug|Win32
-		{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Debug|Win32.Build.0 = Debug|Win32
-		{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Debug|x64.ActiveCfg = Debug|x64
-		{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Debug|x64.Build.0 = Debug|x64
-		{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Release|Win32.ActiveCfg = Release|Win32
-		{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Release|Win32.Build.0 = Release|Win32
-		{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Release|x64.ActiveCfg = Release|x64
-		{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Release|x64.Build.0 = Release|x64
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-EndGlobal
+

+Microsoft Visual Studio Solution File, Format Version 11.00

+# Visual C++ Express 2010

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mbedTLS", "mbedTLS.vcxproj", "{46CF2D25-6A36-4189-B59C-E4815388E554}"

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crypt_and_hash", "crypt_and_hash.vcxproj", "{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "generic_sum", "generic_sum.vcxproj", "{D071CCF7-ACA0-21F8-D382-52A759AEA261}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello", "hello.vcxproj", "{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dh_client", "dh_client.vcxproj", "{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dh_genprime", "dh_genprime.vcxproj", "{718960D9-5DA6-7B56-39AD-637E81076C71}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dh_server", "dh_server.vcxproj", "{8D91B804-E2CE-142D-8E06-FBB037ED1F65}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ecdh_curve25519", "ecdh_curve25519.vcxproj", "{82EE497E-12CC-7C5B-A072-665678ACB43E}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ecdsa", "ecdsa.vcxproj", "{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_key", "gen_key.vcxproj", "{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "key_app", "key_app.vcxproj", "{10AE376F-1A70-0297-0216-1FD01AD15D19}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "key_app_writer", "key_app_writer.vcxproj", "{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mpi_demo", "mpi_demo.vcxproj", "{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pk_decrypt", "pk_decrypt.vcxproj", "{1EC6CBA3-6187-D456-D9B7-A35399395D71}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pk_encrypt", "pk_encrypt.vcxproj", "{55007179-7746-9CFB-97EC-65102FB272C8}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pk_sign", "pk_sign.vcxproj", "{F2E8CA55-597F-7FDC-6456-D8650FB970A3}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pk_verify", "pk_verify.vcxproj", "{C429B336-1B30-119C-3B34-21A186D6744F}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_decrypt", "rsa_decrypt.vcxproj", "{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_encrypt", "rsa_encrypt.vcxproj", "{D06CF12E-F222-9273-41BF-B8A052FA5527}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_genkey", "rsa_genkey.vcxproj", "{F472475C-F677-0E7F-F127-45BF5B64F622}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_sign", "rsa_sign.vcxproj", "{10790F49-6887-AAB6-2D86-BCBD516F8D26}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_sign_pss", "rsa_sign_pss.vcxproj", "{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_verify", "rsa_verify.vcxproj", "{689E28CF-89ED-BA38-3A14-78A75D891D46}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsa_verify_pss", "rsa_verify_pss.vcxproj", "{95C50864-854C-2A11-4C91-BCE654E344FB}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crypto_examples", "crypto_examples.vcxproj", "{020C31BD-C4DF-BABA-E537-F517C4E98537}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "key_ladder_demo", "key_ladder_demo.vcxproj", "{778777A0-393D-45E8-83C1-EAF487236F1F}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "psa_constant_names", "psa_constant_names.vcxproj", "{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_entropy", "gen_entropy.vcxproj", "{DE695064-13C3-18B0-378D-8B22672BF3F4}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_random_ctr_drbg", "gen_random_ctr_drbg.vcxproj", "{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_random_havege", "gen_random_havege.vcxproj", "{71257802-BBCA-99F5-E9D2-905738F30893}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dtls_client", "dtls_client.vcxproj", "{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dtls_server", "dtls_server.vcxproj", "{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mini_client", "mini_client.vcxproj", "{C4FE29EA-266D-5295-4840-976B9B5B3843}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_client1", "ssl_client1.vcxproj", "{487A2F80-3CA3-678D-88D5-82194872CF08}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_client2", "ssl_client2.vcxproj", "{4E590E9D-E28F-87FF-385B-D58736388231}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_context_info", "ssl_context_info.vcxproj", "{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_fork_server", "ssl_fork_server.vcxproj", "{918CD402-047D-8467-E11C-E1132053F916}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_mail_client", "ssl_mail_client.vcxproj", "{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_server", "ssl_server.vcxproj", "{E08E0065-896A-7487-DEA5-D3B80B71F975}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_server2", "ssl_server2.vcxproj", "{A4DA7463-1047-BDF5-E1B3-5632CB573F41}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "benchmark", "benchmark.vcxproj", "{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "query_compile_time_config", "query_compile_time_config.vcxproj", "{D6F58AF2-9D80-562A-E2B0-F743281522B9}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "selftest", "selftest.vcxproj", "{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "udp_proxy", "udp_proxy.vcxproj", "{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zeroize", "zeroize.vcxproj", "{10C01E94-4926-063E-9F56-C84ED190D349}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pem2der", "pem2der.vcxproj", "{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "strerror", "strerror.vcxproj", "{23EF735C-CC4C-3EC4-A75E-903DB340F04A}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cert_app", "cert_app.vcxproj", "{D4D691D4-137C-CBFA-735B-D46636D7E4D8}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cert_req", "cert_req.vcxproj", "{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cert_write", "cert_write.vcxproj", "{35E52E46-3BA9-4361-41D3-53663C2E9B8A}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crl_app", "crl_app.vcxproj", "{DB904B85-AD31-B7FB-114F-88760CC485F2}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "load_roots", "load_roots.vcxproj", "{65EB85E6-C928-689F-8335-126F78025220}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "req_app", "req_app.vcxproj", "{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}"

+	ProjectSection(ProjectDependencies) = postProject

+		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

+	EndProjectSection

+EndProject

+Global

+	GlobalSection(SolutionConfigurationPlatforms) = preSolution

+		Debug|Win32 = Debug|Win32

+		Debug|x64 = Debug|x64

+		Release|Win32 = Release|Win32

+		Release|x64 = Release|x64

+	EndGlobalSection

+	GlobalSection(ProjectConfigurationPlatforms) = postSolution

+		{46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|Win32.ActiveCfg = Debug|Win32

+		{46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|Win32.Build.0 = Debug|Win32

+		{46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|x64.ActiveCfg = Debug|x64

+		{46CF2D25-6A36-4189-B59C-E4815388E554}.Debug|x64.Build.0 = Debug|x64

+		{46CF2D25-6A36-4189-B59C-E4815388E554}.Release|Win32.ActiveCfg = Release|Win32

+		{46CF2D25-6A36-4189-B59C-E4815388E554}.Release|Win32.Build.0 = Release|Win32

+		{46CF2D25-6A36-4189-B59C-E4815388E554}.Release|x64.ActiveCfg = Release|x64

+		{46CF2D25-6A36-4189-B59C-E4815388E554}.Release|x64.Build.0 = Release|x64

+		{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Debug|Win32.ActiveCfg = Debug|Win32

+		{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Debug|Win32.Build.0 = Debug|Win32

+		{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Debug|x64.ActiveCfg = Debug|x64

+		{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Debug|x64.Build.0 = Debug|x64

+		{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Release|Win32.ActiveCfg = Release|Win32

+		{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Release|Win32.Build.0 = Release|Win32

+		{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Release|x64.ActiveCfg = Release|x64

+		{5DBB9FC3-6FD6-CA8D-E0FA-35F1E75EFAE7}.Release|x64.Build.0 = Release|x64

+		{D071CCF7-ACA0-21F8-D382-52A759AEA261}.Debug|Win32.ActiveCfg = Debug|Win32

+		{D071CCF7-ACA0-21F8-D382-52A759AEA261}.Debug|Win32.Build.0 = Debug|Win32

+		{D071CCF7-ACA0-21F8-D382-52A759AEA261}.Debug|x64.ActiveCfg = Debug|x64

+		{D071CCF7-ACA0-21F8-D382-52A759AEA261}.Debug|x64.Build.0 = Debug|x64

+		{D071CCF7-ACA0-21F8-D382-52A759AEA261}.Release|Win32.ActiveCfg = Release|Win32

+		{D071CCF7-ACA0-21F8-D382-52A759AEA261}.Release|Win32.Build.0 = Release|Win32

+		{D071CCF7-ACA0-21F8-D382-52A759AEA261}.Release|x64.ActiveCfg = Release|x64

+		{D071CCF7-ACA0-21F8-D382-52A759AEA261}.Release|x64.Build.0 = Release|x64

+		{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Debug|Win32.ActiveCfg = Debug|Win32

+		{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Debug|Win32.Build.0 = Debug|Win32

+		{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Debug|x64.ActiveCfg = Debug|x64

+		{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Debug|x64.Build.0 = Debug|x64

+		{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Release|Win32.ActiveCfg = Release|Win32

+		{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Release|Win32.Build.0 = Release|Win32

+		{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Release|x64.ActiveCfg = Release|x64

+		{B02D4AE1-0218-1CD4-F44E-EFAE19B01B8D}.Release|x64.Build.0 = Release|x64

+		{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Debug|Win32.ActiveCfg = Debug|Win32

+		{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Debug|Win32.Build.0 = Debug|Win32

+		{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Debug|x64.ActiveCfg = Debug|x64

+		{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Debug|x64.Build.0 = Debug|x64

+		{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Release|Win32.ActiveCfg = Release|Win32

+		{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Release|Win32.Build.0 = Release|Win32

+		{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Release|x64.ActiveCfg = Release|x64

+		{4D29BE4A-979C-C5AE-44B5-30FB37D8D4EE}.Release|x64.Build.0 = Release|x64

+		{718960D9-5DA6-7B56-39AD-637E81076C71}.Debug|Win32.ActiveCfg = Debug|Win32

+		{718960D9-5DA6-7B56-39AD-637E81076C71}.Debug|Win32.Build.0 = Debug|Win32

+		{718960D9-5DA6-7B56-39AD-637E81076C71}.Debug|x64.ActiveCfg = Debug|x64

+		{718960D9-5DA6-7B56-39AD-637E81076C71}.Debug|x64.Build.0 = Debug|x64

+		{718960D9-5DA6-7B56-39AD-637E81076C71}.Release|Win32.ActiveCfg = Release|Win32

+		{718960D9-5DA6-7B56-39AD-637E81076C71}.Release|Win32.Build.0 = Release|Win32

+		{718960D9-5DA6-7B56-39AD-637E81076C71}.Release|x64.ActiveCfg = Release|x64

+		{718960D9-5DA6-7B56-39AD-637E81076C71}.Release|x64.Build.0 = Release|x64

+		{8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Debug|Win32.ActiveCfg = Debug|Win32

+		{8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Debug|Win32.Build.0 = Debug|Win32

+		{8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Debug|x64.ActiveCfg = Debug|x64

+		{8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Debug|x64.Build.0 = Debug|x64

+		{8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Release|Win32.ActiveCfg = Release|Win32

+		{8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Release|Win32.Build.0 = Release|Win32

+		{8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Release|x64.ActiveCfg = Release|x64

+		{8D91B804-E2CE-142D-8E06-FBB037ED1F65}.Release|x64.Build.0 = Release|x64

+		{82EE497E-12CC-7C5B-A072-665678ACB43E}.Debug|Win32.ActiveCfg = Debug|Win32

+		{82EE497E-12CC-7C5B-A072-665678ACB43E}.Debug|Win32.Build.0 = Debug|Win32

+		{82EE497E-12CC-7C5B-A072-665678ACB43E}.Debug|x64.ActiveCfg = Debug|x64

+		{82EE497E-12CC-7C5B-A072-665678ACB43E}.Debug|x64.Build.0 = Debug|x64

+		{82EE497E-12CC-7C5B-A072-665678ACB43E}.Release|Win32.ActiveCfg = Release|Win32

+		{82EE497E-12CC-7C5B-A072-665678ACB43E}.Release|Win32.Build.0 = Release|Win32

+		{82EE497E-12CC-7C5B-A072-665678ACB43E}.Release|x64.ActiveCfg = Release|x64

+		{82EE497E-12CC-7C5B-A072-665678ACB43E}.Release|x64.Build.0 = Release|x64

+		{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Debug|Win32.ActiveCfg = Debug|Win32

+		{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Debug|Win32.Build.0 = Debug|Win32

+		{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Debug|x64.ActiveCfg = Debug|x64

+		{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Debug|x64.Build.0 = Debug|x64

+		{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Release|Win32.ActiveCfg = Release|Win32

+		{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Release|Win32.Build.0 = Release|Win32

+		{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Release|x64.ActiveCfg = Release|x64

+		{F58142CC-0CC7-0B18-5A0F-53642CFBA18E}.Release|x64.Build.0 = Release|x64

+		{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Debug|Win32.ActiveCfg = Debug|Win32

+		{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Debug|Win32.Build.0 = Debug|Win32

+		{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Debug|x64.ActiveCfg = Debug|x64

+		{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Debug|x64.Build.0 = Debug|x64

+		{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Release|Win32.ActiveCfg = Release|Win32

+		{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Release|Win32.Build.0 = Release|Win32

+		{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Release|x64.ActiveCfg = Release|x64

+		{BF782A50-E9AE-00CC-C28A-C9DA8AAB4D52}.Release|x64.Build.0 = Release|x64

+		{10AE376F-1A70-0297-0216-1FD01AD15D19}.Debug|Win32.ActiveCfg = Debug|Win32

+		{10AE376F-1A70-0297-0216-1FD01AD15D19}.Debug|Win32.Build.0 = Debug|Win32

+		{10AE376F-1A70-0297-0216-1FD01AD15D19}.Debug|x64.ActiveCfg = Debug|x64

+		{10AE376F-1A70-0297-0216-1FD01AD15D19}.Debug|x64.Build.0 = Debug|x64

+		{10AE376F-1A70-0297-0216-1FD01AD15D19}.Release|Win32.ActiveCfg = Release|Win32

+		{10AE376F-1A70-0297-0216-1FD01AD15D19}.Release|Win32.Build.0 = Release|Win32

+		{10AE376F-1A70-0297-0216-1FD01AD15D19}.Release|x64.ActiveCfg = Release|x64

+		{10AE376F-1A70-0297-0216-1FD01AD15D19}.Release|x64.Build.0 = Release|x64

+		{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Debug|Win32.ActiveCfg = Debug|Win32

+		{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Debug|Win32.Build.0 = Debug|Win32

+		{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Debug|x64.ActiveCfg = Debug|x64

+		{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Debug|x64.Build.0 = Debug|x64

+		{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Release|Win32.ActiveCfg = Release|Win32

+		{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Release|Win32.Build.0 = Release|Win32

+		{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Release|x64.ActiveCfg = Release|x64

+		{E8ED79F9-8034-1B09-263E-D3F8C4C5C4A8}.Release|x64.Build.0 = Release|x64

+		{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Debug|Win32.ActiveCfg = Debug|Win32

+		{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Debug|Win32.Build.0 = Debug|Win32

+		{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Debug|x64.ActiveCfg = Debug|x64

+		{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Debug|x64.Build.0 = Debug|x64

+		{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Release|Win32.ActiveCfg = Release|Win32

+		{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Release|Win32.Build.0 = Release|Win32

+		{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Release|x64.ActiveCfg = Release|x64

+		{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}.Release|x64.Build.0 = Release|x64

+		{1EC6CBA3-6187-D456-D9B7-A35399395D71}.Debug|Win32.ActiveCfg = Debug|Win32

+		{1EC6CBA3-6187-D456-D9B7-A35399395D71}.Debug|Win32.Build.0 = Debug|Win32

+		{1EC6CBA3-6187-D456-D9B7-A35399395D71}.Debug|x64.ActiveCfg = Debug|x64

+		{1EC6CBA3-6187-D456-D9B7-A35399395D71}.Debug|x64.Build.0 = Debug|x64

+		{1EC6CBA3-6187-D456-D9B7-A35399395D71}.Release|Win32.ActiveCfg = Release|Win32

+		{1EC6CBA3-6187-D456-D9B7-A35399395D71}.Release|Win32.Build.0 = Release|Win32

+		{1EC6CBA3-6187-D456-D9B7-A35399395D71}.Release|x64.ActiveCfg = Release|x64

+		{1EC6CBA3-6187-D456-D9B7-A35399395D71}.Release|x64.Build.0 = Release|x64

+		{55007179-7746-9CFB-97EC-65102FB272C8}.Debug|Win32.ActiveCfg = Debug|Win32

+		{55007179-7746-9CFB-97EC-65102FB272C8}.Debug|Win32.Build.0 = Debug|Win32

+		{55007179-7746-9CFB-97EC-65102FB272C8}.Debug|x64.ActiveCfg = Debug|x64

+		{55007179-7746-9CFB-97EC-65102FB272C8}.Debug|x64.Build.0 = Debug|x64

+		{55007179-7746-9CFB-97EC-65102FB272C8}.Release|Win32.ActiveCfg = Release|Win32

+		{55007179-7746-9CFB-97EC-65102FB272C8}.Release|Win32.Build.0 = Release|Win32

+		{55007179-7746-9CFB-97EC-65102FB272C8}.Release|x64.ActiveCfg = Release|x64

+		{55007179-7746-9CFB-97EC-65102FB272C8}.Release|x64.Build.0 = Release|x64

+		{F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Debug|Win32.ActiveCfg = Debug|Win32

+		{F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Debug|Win32.Build.0 = Debug|Win32

+		{F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Debug|x64.ActiveCfg = Debug|x64

+		{F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Debug|x64.Build.0 = Debug|x64

+		{F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Release|Win32.ActiveCfg = Release|Win32

+		{F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Release|Win32.Build.0 = Release|Win32

+		{F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Release|x64.ActiveCfg = Release|x64

+		{F2E8CA55-597F-7FDC-6456-D8650FB970A3}.Release|x64.Build.0 = Release|x64

+		{C429B336-1B30-119C-3B34-21A186D6744F}.Debug|Win32.ActiveCfg = Debug|Win32

+		{C429B336-1B30-119C-3B34-21A186D6744F}.Debug|Win32.Build.0 = Debug|Win32

+		{C429B336-1B30-119C-3B34-21A186D6744F}.Debug|x64.ActiveCfg = Debug|x64

+		{C429B336-1B30-119C-3B34-21A186D6744F}.Debug|x64.Build.0 = Debug|x64

+		{C429B336-1B30-119C-3B34-21A186D6744F}.Release|Win32.ActiveCfg = Release|Win32

+		{C429B336-1B30-119C-3B34-21A186D6744F}.Release|Win32.Build.0 = Release|Win32

+		{C429B336-1B30-119C-3B34-21A186D6744F}.Release|x64.ActiveCfg = Release|x64

+		{C429B336-1B30-119C-3B34-21A186D6744F}.Release|x64.Build.0 = Release|x64

+		{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Debug|Win32.ActiveCfg = Debug|Win32

+		{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Debug|Win32.Build.0 = Debug|Win32

+		{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Debug|x64.ActiveCfg = Debug|x64

+		{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Debug|x64.Build.0 = Debug|x64

+		{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Release|Win32.ActiveCfg = Release|Win32

+		{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Release|Win32.Build.0 = Release|Win32

+		{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Release|x64.ActiveCfg = Release|x64

+		{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}.Release|x64.Build.0 = Release|x64

+		{D06CF12E-F222-9273-41BF-B8A052FA5527}.Debug|Win32.ActiveCfg = Debug|Win32

+		{D06CF12E-F222-9273-41BF-B8A052FA5527}.Debug|Win32.Build.0 = Debug|Win32

+		{D06CF12E-F222-9273-41BF-B8A052FA5527}.Debug|x64.ActiveCfg = Debug|x64

+		{D06CF12E-F222-9273-41BF-B8A052FA5527}.Debug|x64.Build.0 = Debug|x64

+		{D06CF12E-F222-9273-41BF-B8A052FA5527}.Release|Win32.ActiveCfg = Release|Win32

+		{D06CF12E-F222-9273-41BF-B8A052FA5527}.Release|Win32.Build.0 = Release|Win32

+		{D06CF12E-F222-9273-41BF-B8A052FA5527}.Release|x64.ActiveCfg = Release|x64

+		{D06CF12E-F222-9273-41BF-B8A052FA5527}.Release|x64.Build.0 = Release|x64

+		{F472475C-F677-0E7F-F127-45BF5B64F622}.Debug|Win32.ActiveCfg = Debug|Win32

+		{F472475C-F677-0E7F-F127-45BF5B64F622}.Debug|Win32.Build.0 = Debug|Win32

+		{F472475C-F677-0E7F-F127-45BF5B64F622}.Debug|x64.ActiveCfg = Debug|x64

+		{F472475C-F677-0E7F-F127-45BF5B64F622}.Debug|x64.Build.0 = Debug|x64

+		{F472475C-F677-0E7F-F127-45BF5B64F622}.Release|Win32.ActiveCfg = Release|Win32

+		{F472475C-F677-0E7F-F127-45BF5B64F622}.Release|Win32.Build.0 = Release|Win32

+		{F472475C-F677-0E7F-F127-45BF5B64F622}.Release|x64.ActiveCfg = Release|x64

+		{F472475C-F677-0E7F-F127-45BF5B64F622}.Release|x64.Build.0 = Release|x64

+		{10790F49-6887-AAB6-2D86-BCBD516F8D26}.Debug|Win32.ActiveCfg = Debug|Win32

+		{10790F49-6887-AAB6-2D86-BCBD516F8D26}.Debug|Win32.Build.0 = Debug|Win32

+		{10790F49-6887-AAB6-2D86-BCBD516F8D26}.Debug|x64.ActiveCfg = Debug|x64

+		{10790F49-6887-AAB6-2D86-BCBD516F8D26}.Debug|x64.Build.0 = Debug|x64

+		{10790F49-6887-AAB6-2D86-BCBD516F8D26}.Release|Win32.ActiveCfg = Release|Win32

+		{10790F49-6887-AAB6-2D86-BCBD516F8D26}.Release|Win32.Build.0 = Release|Win32

+		{10790F49-6887-AAB6-2D86-BCBD516F8D26}.Release|x64.ActiveCfg = Release|x64

+		{10790F49-6887-AAB6-2D86-BCBD516F8D26}.Release|x64.Build.0 = Release|x64

+		{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Debug|Win32.ActiveCfg = Debug|Win32

+		{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Debug|Win32.Build.0 = Debug|Win32

+		{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Debug|x64.ActiveCfg = Debug|x64

+		{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Debug|x64.Build.0 = Debug|x64

+		{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Release|Win32.ActiveCfg = Release|Win32

+		{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Release|Win32.Build.0 = Release|Win32

+		{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Release|x64.ActiveCfg = Release|x64

+		{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}.Release|x64.Build.0 = Release|x64

+		{689E28CF-89ED-BA38-3A14-78A75D891D46}.Debug|Win32.ActiveCfg = Debug|Win32

+		{689E28CF-89ED-BA38-3A14-78A75D891D46}.Debug|Win32.Build.0 = Debug|Win32

+		{689E28CF-89ED-BA38-3A14-78A75D891D46}.Debug|x64.ActiveCfg = Debug|x64

+		{689E28CF-89ED-BA38-3A14-78A75D891D46}.Debug|x64.Build.0 = Debug|x64

+		{689E28CF-89ED-BA38-3A14-78A75D891D46}.Release|Win32.ActiveCfg = Release|Win32

+		{689E28CF-89ED-BA38-3A14-78A75D891D46}.Release|Win32.Build.0 = Release|Win32

+		{689E28CF-89ED-BA38-3A14-78A75D891D46}.Release|x64.ActiveCfg = Release|x64

+		{689E28CF-89ED-BA38-3A14-78A75D891D46}.Release|x64.Build.0 = Release|x64

+		{95C50864-854C-2A11-4C91-BCE654E344FB}.Debug|Win32.ActiveCfg = Debug|Win32

+		{95C50864-854C-2A11-4C91-BCE654E344FB}.Debug|Win32.Build.0 = Debug|Win32

+		{95C50864-854C-2A11-4C91-BCE654E344FB}.Debug|x64.ActiveCfg = Debug|x64

+		{95C50864-854C-2A11-4C91-BCE654E344FB}.Debug|x64.Build.0 = Debug|x64

+		{95C50864-854C-2A11-4C91-BCE654E344FB}.Release|Win32.ActiveCfg = Release|Win32

+		{95C50864-854C-2A11-4C91-BCE654E344FB}.Release|Win32.Build.0 = Release|Win32

+		{95C50864-854C-2A11-4C91-BCE654E344FB}.Release|x64.ActiveCfg = Release|x64

+		{95C50864-854C-2A11-4C91-BCE654E344FB}.Release|x64.Build.0 = Release|x64

+		{020C31BD-C4DF-BABA-E537-F517C4E98537}.Debug|Win32.ActiveCfg = Debug|Win32

+		{020C31BD-C4DF-BABA-E537-F517C4E98537}.Debug|Win32.Build.0 = Debug|Win32

+		{020C31BD-C4DF-BABA-E537-F517C4E98537}.Debug|x64.ActiveCfg = Debug|x64

+		{020C31BD-C4DF-BABA-E537-F517C4E98537}.Debug|x64.Build.0 = Debug|x64

+		{020C31BD-C4DF-BABA-E537-F517C4E98537}.Release|Win32.ActiveCfg = Release|Win32

+		{020C31BD-C4DF-BABA-E537-F517C4E98537}.Release|Win32.Build.0 = Release|Win32

+		{020C31BD-C4DF-BABA-E537-F517C4E98537}.Release|x64.ActiveCfg = Release|x64

+		{020C31BD-C4DF-BABA-E537-F517C4E98537}.Release|x64.Build.0 = Release|x64

+		{778777A0-393D-45E8-83C1-EAF487236F1F}.Debug|Win32.ActiveCfg = Debug|Win32

+		{778777A0-393D-45E8-83C1-EAF487236F1F}.Debug|Win32.Build.0 = Debug|Win32

+		{778777A0-393D-45E8-83C1-EAF487236F1F}.Debug|x64.ActiveCfg = Debug|x64

+		{778777A0-393D-45E8-83C1-EAF487236F1F}.Debug|x64.Build.0 = Debug|x64

+		{778777A0-393D-45E8-83C1-EAF487236F1F}.Release|Win32.ActiveCfg = Release|Win32

+		{778777A0-393D-45E8-83C1-EAF487236F1F}.Release|Win32.Build.0 = Release|Win32

+		{778777A0-393D-45E8-83C1-EAF487236F1F}.Release|x64.ActiveCfg = Release|x64

+		{778777A0-393D-45E8-83C1-EAF487236F1F}.Release|x64.Build.0 = Release|x64

+		{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Debug|Win32.ActiveCfg = Debug|Win32

+		{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Debug|Win32.Build.0 = Debug|Win32

+		{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Debug|x64.ActiveCfg = Debug|x64

+		{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Debug|x64.Build.0 = Debug|x64

+		{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Release|Win32.ActiveCfg = Release|Win32

+		{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Release|Win32.Build.0 = Release|Win32

+		{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Release|x64.ActiveCfg = Release|x64

+		{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Release|x64.Build.0 = Release|x64

+		{DE695064-13C3-18B0-378D-8B22672BF3F4}.Debug|Win32.ActiveCfg = Debug|Win32

+		{DE695064-13C3-18B0-378D-8B22672BF3F4}.Debug|Win32.Build.0 = Debug|Win32

+		{DE695064-13C3-18B0-378D-8B22672BF3F4}.Debug|x64.ActiveCfg = Debug|x64

+		{DE695064-13C3-18B0-378D-8B22672BF3F4}.Debug|x64.Build.0 = Debug|x64

+		{DE695064-13C3-18B0-378D-8B22672BF3F4}.Release|Win32.ActiveCfg = Release|Win32

+		{DE695064-13C3-18B0-378D-8B22672BF3F4}.Release|Win32.Build.0 = Release|Win32

+		{DE695064-13C3-18B0-378D-8B22672BF3F4}.Release|x64.ActiveCfg = Release|x64

+		{DE695064-13C3-18B0-378D-8B22672BF3F4}.Release|x64.Build.0 = Release|x64

+		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Debug|Win32.ActiveCfg = Debug|Win32

+		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Debug|Win32.Build.0 = Debug|Win32

+		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Debug|x64.ActiveCfg = Debug|x64

+		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Debug|x64.Build.0 = Debug|x64

+		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Release|Win32.ActiveCfg = Release|Win32

+		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Release|Win32.Build.0 = Release|Win32

+		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Release|x64.ActiveCfg = Release|x64

+		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Release|x64.Build.0 = Release|x64

+		{71257802-BBCA-99F5-E9D2-905738F30893}.Debug|Win32.ActiveCfg = Debug|Win32

+		{71257802-BBCA-99F5-E9D2-905738F30893}.Debug|Win32.Build.0 = Debug|Win32

+		{71257802-BBCA-99F5-E9D2-905738F30893}.Debug|x64.ActiveCfg = Debug|x64

+		{71257802-BBCA-99F5-E9D2-905738F30893}.Debug|x64.Build.0 = Debug|x64

+		{71257802-BBCA-99F5-E9D2-905738F30893}.Release|Win32.ActiveCfg = Release|Win32

+		{71257802-BBCA-99F5-E9D2-905738F30893}.Release|Win32.Build.0 = Release|Win32

+		{71257802-BBCA-99F5-E9D2-905738F30893}.Release|x64.ActiveCfg = Release|x64

+		{71257802-BBCA-99F5-E9D2-905738F30893}.Release|x64.Build.0 = Release|x64

+		{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Debug|Win32.ActiveCfg = Debug|Win32

+		{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Debug|Win32.Build.0 = Debug|Win32

+		{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Debug|x64.ActiveCfg = Debug|x64

+		{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Debug|x64.Build.0 = Debug|x64

+		{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Release|Win32.ActiveCfg = Release|Win32

+		{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Release|Win32.Build.0 = Release|Win32

+		{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Release|x64.ActiveCfg = Release|x64

+		{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Release|x64.Build.0 = Release|x64

+		{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Debug|Win32.ActiveCfg = Debug|Win32

+		{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Debug|Win32.Build.0 = Debug|Win32

+		{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Debug|x64.ActiveCfg = Debug|x64

+		{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Debug|x64.Build.0 = Debug|x64

+		{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Release|Win32.ActiveCfg = Release|Win32

+		{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Release|Win32.Build.0 = Release|Win32

+		{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Release|x64.ActiveCfg = Release|x64

+		{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Release|x64.Build.0 = Release|x64

+		{C4FE29EA-266D-5295-4840-976B9B5B3843}.Debug|Win32.ActiveCfg = Debug|Win32

+		{C4FE29EA-266D-5295-4840-976B9B5B3843}.Debug|Win32.Build.0 = Debug|Win32

+		{C4FE29EA-266D-5295-4840-976B9B5B3843}.Debug|x64.ActiveCfg = Debug|x64

+		{C4FE29EA-266D-5295-4840-976B9B5B3843}.Debug|x64.Build.0 = Debug|x64

+		{C4FE29EA-266D-5295-4840-976B9B5B3843}.Release|Win32.ActiveCfg = Release|Win32

+		{C4FE29EA-266D-5295-4840-976B9B5B3843}.Release|Win32.Build.0 = Release|Win32

+		{C4FE29EA-266D-5295-4840-976B9B5B3843}.Release|x64.ActiveCfg = Release|x64

+		{C4FE29EA-266D-5295-4840-976B9B5B3843}.Release|x64.Build.0 = Release|x64

+		{487A2F80-3CA3-678D-88D5-82194872CF08}.Debug|Win32.ActiveCfg = Debug|Win32

+		{487A2F80-3CA3-678D-88D5-82194872CF08}.Debug|Win32.Build.0 = Debug|Win32

+		{487A2F80-3CA3-678D-88D5-82194872CF08}.Debug|x64.ActiveCfg = Debug|x64

+		{487A2F80-3CA3-678D-88D5-82194872CF08}.Debug|x64.Build.0 = Debug|x64

+		{487A2F80-3CA3-678D-88D5-82194872CF08}.Release|Win32.ActiveCfg = Release|Win32

+		{487A2F80-3CA3-678D-88D5-82194872CF08}.Release|Win32.Build.0 = Release|Win32

+		{487A2F80-3CA3-678D-88D5-82194872CF08}.Release|x64.ActiveCfg = Release|x64

+		{487A2F80-3CA3-678D-88D5-82194872CF08}.Release|x64.Build.0 = Release|x64

+		{4E590E9D-E28F-87FF-385B-D58736388231}.Debug|Win32.ActiveCfg = Debug|Win32

+		{4E590E9D-E28F-87FF-385B-D58736388231}.Debug|Win32.Build.0 = Debug|Win32

+		{4E590E9D-E28F-87FF-385B-D58736388231}.Debug|x64.ActiveCfg = Debug|x64

+		{4E590E9D-E28F-87FF-385B-D58736388231}.Debug|x64.Build.0 = Debug|x64

+		{4E590E9D-E28F-87FF-385B-D58736388231}.Release|Win32.ActiveCfg = Release|Win32

+		{4E590E9D-E28F-87FF-385B-D58736388231}.Release|Win32.Build.0 = Release|Win32

+		{4E590E9D-E28F-87FF-385B-D58736388231}.Release|x64.ActiveCfg = Release|x64

+		{4E590E9D-E28F-87FF-385B-D58736388231}.Release|x64.Build.0 = Release|x64

+		{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}.Debug|Win32.ActiveCfg = Debug|Win32

+		{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}.Debug|Win32.Build.0 = Debug|Win32

+		{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}.Debug|x64.ActiveCfg = Debug|x64

+		{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}.Debug|x64.Build.0 = Debug|x64

+		{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}.Release|Win32.ActiveCfg = Release|Win32

+		{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}.Release|Win32.Build.0 = Release|Win32

+		{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}.Release|x64.ActiveCfg = Release|x64

+		{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}.Release|x64.Build.0 = Release|x64

+		{918CD402-047D-8467-E11C-E1132053F916}.Debug|Win32.ActiveCfg = Debug|Win32

+		{918CD402-047D-8467-E11C-E1132053F916}.Debug|Win32.Build.0 = Debug|Win32

+		{918CD402-047D-8467-E11C-E1132053F916}.Debug|x64.ActiveCfg = Debug|x64

+		{918CD402-047D-8467-E11C-E1132053F916}.Debug|x64.Build.0 = Debug|x64

+		{918CD402-047D-8467-E11C-E1132053F916}.Release|Win32.ActiveCfg = Release|Win32

+		{918CD402-047D-8467-E11C-E1132053F916}.Release|Win32.Build.0 = Release|Win32

+		{918CD402-047D-8467-E11C-E1132053F916}.Release|x64.ActiveCfg = Release|x64

+		{918CD402-047D-8467-E11C-E1132053F916}.Release|x64.Build.0 = Release|x64

+		{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Debug|Win32.ActiveCfg = Debug|Win32

+		{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Debug|Win32.Build.0 = Debug|Win32

+		{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Debug|x64.ActiveCfg = Debug|x64

+		{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Debug|x64.Build.0 = Debug|x64

+		{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Release|Win32.ActiveCfg = Release|Win32

+		{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Release|Win32.Build.0 = Release|Win32

+		{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Release|x64.ActiveCfg = Release|x64

+		{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Release|x64.Build.0 = Release|x64

+		{E08E0065-896A-7487-DEA5-D3B80B71F975}.Debug|Win32.ActiveCfg = Debug|Win32

+		{E08E0065-896A-7487-DEA5-D3B80B71F975}.Debug|Win32.Build.0 = Debug|Win32

+		{E08E0065-896A-7487-DEA5-D3B80B71F975}.Debug|x64.ActiveCfg = Debug|x64

+		{E08E0065-896A-7487-DEA5-D3B80B71F975}.Debug|x64.Build.0 = Debug|x64

+		{E08E0065-896A-7487-DEA5-D3B80B71F975}.Release|Win32.ActiveCfg = Release|Win32

+		{E08E0065-896A-7487-DEA5-D3B80B71F975}.Release|Win32.Build.0 = Release|Win32

+		{E08E0065-896A-7487-DEA5-D3B80B71F975}.Release|x64.ActiveCfg = Release|x64

+		{E08E0065-896A-7487-DEA5-D3B80B71F975}.Release|x64.Build.0 = Release|x64

+		{A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Debug|Win32.ActiveCfg = Debug|Win32

+		{A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Debug|Win32.Build.0 = Debug|Win32

+		{A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Debug|x64.ActiveCfg = Debug|x64

+		{A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Debug|x64.Build.0 = Debug|x64

+		{A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Release|Win32.ActiveCfg = Release|Win32

+		{A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Release|Win32.Build.0 = Release|Win32

+		{A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Release|x64.ActiveCfg = Release|x64

+		{A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Release|x64.Build.0 = Release|x64

+		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Debug|Win32.ActiveCfg = Debug|Win32

+		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Debug|Win32.Build.0 = Debug|Win32

+		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Debug|x64.ActiveCfg = Debug|x64

+		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Debug|x64.Build.0 = Debug|x64

+		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Release|Win32.ActiveCfg = Release|Win32

+		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Release|Win32.Build.0 = Release|Win32

+		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Release|x64.ActiveCfg = Release|x64

+		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Release|x64.Build.0 = Release|x64

+		{D6F58AF2-9D80-562A-E2B0-F743281522B9}.Debug|Win32.ActiveCfg = Debug|Win32

+		{D6F58AF2-9D80-562A-E2B0-F743281522B9}.Debug|Win32.Build.0 = Debug|Win32

+		{D6F58AF2-9D80-562A-E2B0-F743281522B9}.Debug|x64.ActiveCfg = Debug|x64

+		{D6F58AF2-9D80-562A-E2B0-F743281522B9}.Debug|x64.Build.0 = Debug|x64

+		{D6F58AF2-9D80-562A-E2B0-F743281522B9}.Release|Win32.ActiveCfg = Release|Win32

+		{D6F58AF2-9D80-562A-E2B0-F743281522B9}.Release|Win32.Build.0 = Release|Win32

+		{D6F58AF2-9D80-562A-E2B0-F743281522B9}.Release|x64.ActiveCfg = Release|x64

+		{D6F58AF2-9D80-562A-E2B0-F743281522B9}.Release|x64.Build.0 = Release|x64

+		{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Debug|Win32.ActiveCfg = Debug|Win32

+		{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Debug|Win32.Build.0 = Debug|Win32

+		{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Debug|x64.ActiveCfg = Debug|x64

+		{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Debug|x64.Build.0 = Debug|x64

+		{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Release|Win32.ActiveCfg = Release|Win32

+		{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Release|Win32.Build.0 = Release|Win32

+		{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Release|x64.ActiveCfg = Release|x64

+		{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Release|x64.Build.0 = Release|x64

+		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Debug|Win32.ActiveCfg = Debug|Win32

+		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Debug|Win32.Build.0 = Debug|Win32

+		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Debug|x64.ActiveCfg = Debug|x64

+		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Debug|x64.Build.0 = Debug|x64

+		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|Win32.ActiveCfg = Release|Win32

+		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|Win32.Build.0 = Release|Win32

+		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|x64.ActiveCfg = Release|x64

+		{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|x64.Build.0 = Release|x64

+		{10C01E94-4926-063E-9F56-C84ED190D349}.Debug|Win32.ActiveCfg = Debug|Win32

+		{10C01E94-4926-063E-9F56-C84ED190D349}.Debug|Win32.Build.0 = Debug|Win32

+		{10C01E94-4926-063E-9F56-C84ED190D349}.Debug|x64.ActiveCfg = Debug|x64

+		{10C01E94-4926-063E-9F56-C84ED190D349}.Debug|x64.Build.0 = Debug|x64

+		{10C01E94-4926-063E-9F56-C84ED190D349}.Release|Win32.ActiveCfg = Release|Win32

+		{10C01E94-4926-063E-9F56-C84ED190D349}.Release|Win32.Build.0 = Release|Win32

+		{10C01E94-4926-063E-9F56-C84ED190D349}.Release|x64.ActiveCfg = Release|x64

+		{10C01E94-4926-063E-9F56-C84ED190D349}.Release|x64.Build.0 = Release|x64

+		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Debug|Win32.ActiveCfg = Debug|Win32

+		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Debug|Win32.Build.0 = Debug|Win32

+		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Debug|x64.ActiveCfg = Debug|x64

+		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Debug|x64.Build.0 = Debug|x64

+		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Release|Win32.ActiveCfg = Release|Win32

+		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Release|Win32.Build.0 = Release|Win32

+		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Release|x64.ActiveCfg = Release|x64

+		{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}.Release|x64.Build.0 = Release|x64

+		{23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Debug|Win32.ActiveCfg = Debug|Win32

+		{23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Debug|Win32.Build.0 = Debug|Win32

+		{23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Debug|x64.ActiveCfg = Debug|x64

+		{23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Debug|x64.Build.0 = Debug|x64

+		{23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Release|Win32.ActiveCfg = Release|Win32

+		{23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Release|Win32.Build.0 = Release|Win32

+		{23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Release|x64.ActiveCfg = Release|x64

+		{23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Release|x64.Build.0 = Release|x64

+		{D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Debug|Win32.ActiveCfg = Debug|Win32

+		{D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Debug|Win32.Build.0 = Debug|Win32

+		{D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Debug|x64.ActiveCfg = Debug|x64

+		{D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Debug|x64.Build.0 = Debug|x64

+		{D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Release|Win32.ActiveCfg = Release|Win32

+		{D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Release|Win32.Build.0 = Release|Win32

+		{D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Release|x64.ActiveCfg = Release|x64

+		{D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Release|x64.Build.0 = Release|x64

+		{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Debug|Win32.ActiveCfg = Debug|Win32

+		{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Debug|Win32.Build.0 = Debug|Win32

+		{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Debug|x64.ActiveCfg = Debug|x64

+		{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Debug|x64.Build.0 = Debug|x64

+		{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Release|Win32.ActiveCfg = Release|Win32

+		{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Release|Win32.Build.0 = Release|Win32

+		{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Release|x64.ActiveCfg = Release|x64

+		{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Release|x64.Build.0 = Release|x64

+		{35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Debug|Win32.ActiveCfg = Debug|Win32

+		{35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Debug|Win32.Build.0 = Debug|Win32

+		{35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Debug|x64.ActiveCfg = Debug|x64

+		{35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Debug|x64.Build.0 = Debug|x64

+		{35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Release|Win32.ActiveCfg = Release|Win32

+		{35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Release|Win32.Build.0 = Release|Win32

+		{35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Release|x64.ActiveCfg = Release|x64

+		{35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Release|x64.Build.0 = Release|x64

+		{DB904B85-AD31-B7FB-114F-88760CC485F2}.Debug|Win32.ActiveCfg = Debug|Win32

+		{DB904B85-AD31-B7FB-114F-88760CC485F2}.Debug|Win32.Build.0 = Debug|Win32

+		{DB904B85-AD31-B7FB-114F-88760CC485F2}.Debug|x64.ActiveCfg = Debug|x64

+		{DB904B85-AD31-B7FB-114F-88760CC485F2}.Debug|x64.Build.0 = Debug|x64

+		{DB904B85-AD31-B7FB-114F-88760CC485F2}.Release|Win32.ActiveCfg = Release|Win32

+		{DB904B85-AD31-B7FB-114F-88760CC485F2}.Release|Win32.Build.0 = Release|Win32

+		{DB904B85-AD31-B7FB-114F-88760CC485F2}.Release|x64.ActiveCfg = Release|x64

+		{DB904B85-AD31-B7FB-114F-88760CC485F2}.Release|x64.Build.0 = Release|x64

+		{65EB85E6-C928-689F-8335-126F78025220}.Debug|Win32.ActiveCfg = Debug|Win32

+		{65EB85E6-C928-689F-8335-126F78025220}.Debug|Win32.Build.0 = Debug|Win32

+		{65EB85E6-C928-689F-8335-126F78025220}.Debug|x64.ActiveCfg = Debug|x64

+		{65EB85E6-C928-689F-8335-126F78025220}.Debug|x64.Build.0 = Debug|x64

+		{65EB85E6-C928-689F-8335-126F78025220}.Release|Win32.ActiveCfg = Release|Win32

+		{65EB85E6-C928-689F-8335-126F78025220}.Release|Win32.Build.0 = Release|Win32

+		{65EB85E6-C928-689F-8335-126F78025220}.Release|x64.ActiveCfg = Release|x64

+		{65EB85E6-C928-689F-8335-126F78025220}.Release|x64.Build.0 = Release|x64

+		{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Debug|Win32.ActiveCfg = Debug|Win32

+		{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Debug|Win32.Build.0 = Debug|Win32

+		{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Debug|x64.ActiveCfg = Debug|x64

+		{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Debug|x64.Build.0 = Debug|x64

+		{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Release|Win32.ActiveCfg = Release|Win32

+		{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Release|Win32.Build.0 = Release|Win32

+		{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Release|x64.ActiveCfg = Release|x64

+		{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Release|x64.Build.0 = Release|x64

+	EndGlobalSection

+	GlobalSection(SolutionProperties) = preSolution

+		HideSolutionNode = FALSE

+	EndGlobalSection

+EndGlobal

diff --git a/third_party/mbedtls/repo/visualc/VS2010/mbedTLS.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/mbedTLS.vcxproj
index 35fa306..88ffe1b 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/mbedTLS.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/mbedTLS.vcxproj
@@ -1,364 +1,410 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{46CF2D25-6A36-4189-B59C-E4815388E554}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>mbedTLS</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>StaticLibrary</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>_USRDLL;MBEDTLS_EXPORTS;KRML_VERIFIED_UINT128;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../library;../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-      <CompileAs>CompileAsC</CompileAs>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>_USRDLL;MBEDTLS_EXPORTS;KRML_VERIFIED_UINT128;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../library;../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-      <CompileAs>CompileAsC</CompileAs>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;_USRDLL;MBEDTLS_EXPORTS;KRML_VERIFIED_UINT128;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../library;../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;MBEDTLS_EXPORTS;KRML_VERIFIED_UINT128;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../library;../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Windows</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClInclude Include="..\..\include\mbedtls\aes.h" />
-    <ClInclude Include="..\..\include\mbedtls\aesni.h" />
-    <ClInclude Include="..\..\include\mbedtls\arc4.h" />
-    <ClInclude Include="..\..\include\mbedtls\aria.h" />
-    <ClInclude Include="..\..\include\mbedtls\asn1.h" />
-    <ClInclude Include="..\..\include\mbedtls\asn1write.h" />
-    <ClInclude Include="..\..\include\mbedtls\base64.h" />
-    <ClInclude Include="..\..\include\mbedtls\bignum.h" />
-    <ClInclude Include="..\..\include\mbedtls\blowfish.h" />
-    <ClInclude Include="..\..\include\mbedtls\bn_mul.h" />
-    <ClInclude Include="..\..\include\mbedtls\camellia.h" />
-    <ClInclude Include="..\..\include\mbedtls\ccm.h" />
-    <ClInclude Include="..\..\include\mbedtls\certs.h" />
-    <ClInclude Include="..\..\include\mbedtls\chacha20.h" />
-    <ClInclude Include="..\..\include\mbedtls\chachapoly.h" />
-    <ClInclude Include="..\..\include\mbedtls\check_config.h" />
-    <ClInclude Include="..\..\include\mbedtls\cipher.h" />
-    <ClInclude Include="..\..\include\mbedtls\cipher_internal.h" />
-    <ClInclude Include="..\..\include\mbedtls\cmac.h" />
-    <ClInclude Include="..\..\include\mbedtls\compat-1.3.h" />
-    <ClInclude Include="..\..\include\mbedtls\config.h" />
-    <ClInclude Include="..\..\include\mbedtls\config_psa.h" />
-    <ClInclude Include="..\..\include\mbedtls\ctr_drbg.h" />
-    <ClInclude Include="..\..\include\mbedtls\debug.h" />
-    <ClInclude Include="..\..\include\mbedtls\des.h" />
-    <ClInclude Include="..\..\include\mbedtls\dhm.h" />
-    <ClInclude Include="..\..\include\mbedtls\ecdh.h" />
-    <ClInclude Include="..\..\include\mbedtls\ecdsa.h" />
-    <ClInclude Include="..\..\include\mbedtls\ecjpake.h" />
-    <ClInclude Include="..\..\include\mbedtls\ecp.h" />
-    <ClInclude Include="..\..\include\mbedtls\ecp_internal.h" />
-    <ClInclude Include="..\..\include\mbedtls\entropy.h" />
-    <ClInclude Include="..\..\include\mbedtls\entropy_poll.h" />
-    <ClInclude Include="..\..\include\mbedtls\error.h" />
-    <ClInclude Include="..\..\include\mbedtls\gcm.h" />
-    <ClInclude Include="..\..\include\mbedtls\havege.h" />
-    <ClInclude Include="..\..\include\mbedtls\hkdf.h" />
-    <ClInclude Include="..\..\include\mbedtls\hmac_drbg.h" />
-    <ClInclude Include="..\..\include\mbedtls\md.h" />
-    <ClInclude Include="..\..\include\mbedtls\md2.h" />
-    <ClInclude Include="..\..\include\mbedtls\md4.h" />
-    <ClInclude Include="..\..\include\mbedtls\md5.h" />
-    <ClInclude Include="..\..\include\mbedtls\md_internal.h" />
-    <ClInclude Include="..\..\include\mbedtls\memory_buffer_alloc.h" />
-    <ClInclude Include="..\..\include\mbedtls\net.h" />
-    <ClInclude Include="..\..\include\mbedtls\net_sockets.h" />
-    <ClInclude Include="..\..\include\mbedtls\nist_kw.h" />
-    <ClInclude Include="..\..\include\mbedtls\oid.h" />
-    <ClInclude Include="..\..\include\mbedtls\padlock.h" />
-    <ClInclude Include="..\..\include\mbedtls\pem.h" />
-    <ClInclude Include="..\..\include\mbedtls\pk.h" />
-    <ClInclude Include="..\..\include\mbedtls\pk_internal.h" />
-    <ClInclude Include="..\..\include\mbedtls\pkcs11.h" />
-    <ClInclude Include="..\..\include\mbedtls\pkcs12.h" />
-    <ClInclude Include="..\..\include\mbedtls\pkcs5.h" />
-    <ClInclude Include="..\..\include\mbedtls\platform.h" />
-    <ClInclude Include="..\..\include\mbedtls\platform_time.h" />
-    <ClInclude Include="..\..\include\mbedtls\platform_util.h" />
-    <ClInclude Include="..\..\include\mbedtls\poly1305.h" />
-    <ClInclude Include="..\..\include\mbedtls\psa_util.h" />
-    <ClInclude Include="..\..\include\mbedtls\ripemd160.h" />
-    <ClInclude Include="..\..\include\mbedtls\rsa.h" />
-    <ClInclude Include="..\..\include\mbedtls\rsa_internal.h" />
-    <ClInclude Include="..\..\include\mbedtls\sha1.h" />
-    <ClInclude Include="..\..\include\mbedtls\sha256.h" />
-    <ClInclude Include="..\..\include\mbedtls\sha512.h" />
-    <ClInclude Include="..\..\include\mbedtls\ssl.h" />
-    <ClInclude Include="..\..\include\mbedtls\ssl_cache.h" />
-    <ClInclude Include="..\..\include\mbedtls\ssl_ciphersuites.h" />
-    <ClInclude Include="..\..\include\mbedtls\ssl_cookie.h" />
-    <ClInclude Include="..\..\include\mbedtls\ssl_internal.h" />
-    <ClInclude Include="..\..\include\mbedtls\ssl_ticket.h" />
-    <ClInclude Include="..\..\include\mbedtls\threading.h" />
-    <ClInclude Include="..\..\include\mbedtls\timing.h" />
-    <ClInclude Include="..\..\include\mbedtls\version.h" />
-    <ClInclude Include="..\..\include\mbedtls\x509.h" />
-    <ClInclude Include="..\..\include\mbedtls\x509_crl.h" />
-    <ClInclude Include="..\..\include\mbedtls\x509_crt.h" />
-    <ClInclude Include="..\..\include\mbedtls\x509_csr.h" />
-    <ClInclude Include="..\..\include\mbedtls\xtea.h" />
-    <ClInclude Include="..\..\include\psa\crypto.h" />
-    <ClInclude Include="..\..\include\psa\crypto_accel_driver.h" />
-    <ClInclude Include="..\..\include\psa\crypto_compat.h" />
-    <ClInclude Include="..\..\include\psa\crypto_config.h" />
-    <ClInclude Include="..\..\include\psa\crypto_driver_common.h" />
-    <ClInclude Include="..\..\include\psa\crypto_entropy_driver.h" />
-    <ClInclude Include="..\..\include\psa\crypto_extra.h" />
-    <ClInclude Include="..\..\include\psa\crypto_platform.h" />
-    <ClInclude Include="..\..\include\psa\crypto_se_driver.h" />
-    <ClInclude Include="..\..\include\psa\crypto_sizes.h" />
-    <ClInclude Include="..\..\include\psa\crypto_struct.h" />
-    <ClInclude Include="..\..\include\psa\crypto_types.h" />
-    <ClInclude Include="..\..\include\psa\crypto_values.h" />
-    <ClInclude Include="..\..\tests\include\test\constant_flow.h" />
-    <ClInclude Include="..\..\tests\include\test\helpers.h" />
-    <ClInclude Include="..\..\tests\include\test\macros.h" />
-    <ClInclude Include="..\..\tests\include\test\psa_crypto_helpers.h" />
-    <ClInclude Include="..\..\tests\include\test\psa_helpers.h" />
-    <ClInclude Include="..\..\tests\include\test\random.h" />
-    <ClInclude Include="..\..\tests\include\test\drivers\cipher.h" />
-    <ClInclude Include="..\..\tests\include\test\drivers\key_management.h" />
-    <ClInclude Include="..\..\tests\include\test\drivers\signature.h" />
-    <ClInclude Include="..\..\tests\include\test\drivers\size.h" />
-    <ClInclude Include="..\..\tests\include\test\drivers\test_driver.h" />
-    <ClInclude Include="..\..\library\check_crypto_config.h" />
-    <ClInclude Include="..\..\library\common.h" />
-    <ClInclude Include="..\..\library\psa_crypto_core.h" />
-    <ClInclude Include="..\..\library\psa_crypto_driver_wrappers.h" />
-    <ClInclude Include="..\..\library\psa_crypto_invasive.h" />
-    <ClInclude Include="..\..\library\psa_crypto_its.h" />
-    <ClInclude Include="..\..\library\psa_crypto_se.h" />
-    <ClInclude Include="..\..\library\psa_crypto_service_integration.h" />
-    <ClInclude Include="..\..\library\psa_crypto_slot_management.h" />
-    <ClInclude Include="..\..\library\psa_crypto_storage.h" />
-    <ClInclude Include="..\..\library\ssl_invasive.h" />
-    <ClInclude Include="..\..\library\ssl_tls13_keys.h" />
-    <ClInclude Include="..\..\3rdparty\everest\include\everest\everest.h" />
-    <ClInclude Include="..\..\3rdparty\everest\include\everest\Hacl_Curve25519.h" />
-    <ClInclude Include="..\..\3rdparty\everest\include\everest\kremlib.h" />
-    <ClInclude Include="..\..\3rdparty\everest\include\everest\x25519.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\library\aes.c" />
-    <ClCompile Include="..\..\library\aesni.c" />
-    <ClCompile Include="..\..\library\arc4.c" />
-    <ClCompile Include="..\..\library\aria.c" />
-    <ClCompile Include="..\..\library\asn1parse.c" />
-    <ClCompile Include="..\..\library\asn1write.c" />
-    <ClCompile Include="..\..\library\base64.c" />
-    <ClCompile Include="..\..\library\bignum.c" />
-    <ClCompile Include="..\..\library\blowfish.c" />
-    <ClCompile Include="..\..\library\camellia.c" />
-    <ClCompile Include="..\..\library\ccm.c" />
-    <ClCompile Include="..\..\library\certs.c" />
-    <ClCompile Include="..\..\library\chacha20.c" />
-    <ClCompile Include="..\..\library\chachapoly.c" />
-    <ClCompile Include="..\..\library\cipher.c" />
-    <ClCompile Include="..\..\library\cipher_wrap.c" />
-    <ClCompile Include="..\..\library\cmac.c" />
-    <ClCompile Include="..\..\library\ctr_drbg.c" />
-    <ClCompile Include="..\..\library\debug.c" />
-    <ClCompile Include="..\..\library\des.c" />
-    <ClCompile Include="..\..\library\dhm.c" />
-    <ClCompile Include="..\..\library\ecdh.c" />
-    <ClCompile Include="..\..\library\ecdsa.c" />
-    <ClCompile Include="..\..\library\ecjpake.c" />
-    <ClCompile Include="..\..\library\ecp.c" />
-    <ClCompile Include="..\..\library\ecp_curves.c" />
-    <ClCompile Include="..\..\library\entropy.c" />
-    <ClCompile Include="..\..\library\entropy_poll.c" />
-    <ClCompile Include="..\..\library\error.c" />
-    <ClCompile Include="..\..\library\gcm.c" />
-    <ClCompile Include="..\..\library\havege.c" />
-    <ClCompile Include="..\..\library\hkdf.c" />
-    <ClCompile Include="..\..\library\hmac_drbg.c" />
-    <ClCompile Include="..\..\library\md.c" />
-    <ClCompile Include="..\..\library\md2.c" />
-    <ClCompile Include="..\..\library\md4.c" />
-    <ClCompile Include="..\..\library\md5.c" />
-    <ClCompile Include="..\..\library\memory_buffer_alloc.c" />
-    <ClCompile Include="..\..\library\net_sockets.c" />
-    <ClCompile Include="..\..\library\nist_kw.c" />
-    <ClCompile Include="..\..\library\oid.c" />
-    <ClCompile Include="..\..\library\padlock.c" />
-    <ClCompile Include="..\..\library\pem.c" />
-    <ClCompile Include="..\..\library\pk.c" />
-    <ClCompile Include="..\..\library\pk_wrap.c" />
-    <ClCompile Include="..\..\library\pkcs11.c" />
-    <ClCompile Include="..\..\library\pkcs12.c" />
-    <ClCompile Include="..\..\library\pkcs5.c" />
-    <ClCompile Include="..\..\library\pkparse.c" />
-    <ClCompile Include="..\..\library\pkwrite.c" />
-    <ClCompile Include="..\..\library\platform.c" />
-    <ClCompile Include="..\..\library\platform_util.c" />
-    <ClCompile Include="..\..\library\poly1305.c" />
-    <ClCompile Include="..\..\library\psa_crypto.c" />
-    <ClCompile Include="..\..\library\psa_crypto_driver_wrappers.c" />
-    <ClCompile Include="..\..\library\psa_crypto_se.c" />
-    <ClCompile Include="..\..\library\psa_crypto_slot_management.c" />
-    <ClCompile Include="..\..\library\psa_crypto_storage.c" />
-    <ClCompile Include="..\..\library\psa_its_file.c" />
-    <ClCompile Include="..\..\library\ripemd160.c" />
-    <ClCompile Include="..\..\library\rsa.c" />
-    <ClCompile Include="..\..\library\rsa_internal.c" />
-    <ClCompile Include="..\..\library\sha1.c" />
-    <ClCompile Include="..\..\library\sha256.c" />
-    <ClCompile Include="..\..\library\sha512.c" />
-    <ClCompile Include="..\..\library\ssl_cache.c" />
-    <ClCompile Include="..\..\library\ssl_ciphersuites.c" />
-    <ClCompile Include="..\..\library\ssl_cli.c" />
-    <ClCompile Include="..\..\library\ssl_cookie.c" />
-    <ClCompile Include="..\..\library\ssl_msg.c" />
-    <ClCompile Include="..\..\library\ssl_srv.c" />
-    <ClCompile Include="..\..\library\ssl_ticket.c" />
-    <ClCompile Include="..\..\library\ssl_tls.c" />
-    <ClCompile Include="..\..\library\ssl_tls13_keys.c" />
-    <ClCompile Include="..\..\library\threading.c" />
-    <ClCompile Include="..\..\library\timing.c" />
-    <ClCompile Include="..\..\library\version.c" />
-    <ClCompile Include="..\..\library\version_features.c" />
-    <ClCompile Include="..\..\library\x509.c" />
-    <ClCompile Include="..\..\library\x509_create.c" />
-    <ClCompile Include="..\..\library\x509_crl.c" />
-    <ClCompile Include="..\..\library\x509_crt.c" />
-    <ClCompile Include="..\..\library\x509_csr.c" />
-    <ClCompile Include="..\..\library\x509write_crt.c" />
-    <ClCompile Include="..\..\library\x509write_csr.c" />
-    <ClCompile Include="..\..\library\xtea.c" />
-    <ClCompile Include="..\..\tests\src\helpers.c" />
-    <ClCompile Include="..\..\tests\src\random.c" />
-    <ClCompile Include="..\..\3rdparty\everest\library\everest.c" />
-    <ClCompile Include="..\..\3rdparty\everest\library\Hacl_Curve25519_joined.c" />
-    <ClCompile Include="..\..\3rdparty\everest\library\x25519.c" />
-    <ClCompile Include="..\..\3rdparty\everest\library\kremlib\FStar_UInt128_extracted.c" />
-    <ClCompile Include="..\..\3rdparty\everest\library\kremlib\FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8.c" />
-    <ClCompile Include="..\..\3rdparty\everest\library\legacy\Hacl_Curve25519.c" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{46CF2D25-6A36-4189-B59C-E4815388E554}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>mbedTLS</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>_USRDLL;MBEDTLS_EXPORTS;KRML_VERIFIED_UINT128;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../library;../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+      <CompileAs>CompileAsC</CompileAs>

+    </ClCompile>

+    <Link>

+      <SubSystem>Windows</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>_USRDLL;MBEDTLS_EXPORTS;KRML_VERIFIED_UINT128;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../library;../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+      <CompileAs>CompileAsC</CompileAs>

+    </ClCompile>

+    <Link>

+      <SubSystem>Windows</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;_USRDLL;MBEDTLS_EXPORTS;KRML_VERIFIED_UINT128;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../library;../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Windows</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;MBEDTLS_EXPORTS;KRML_VERIFIED_UINT128;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../library;../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Windows</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemGroup>

+    <ClInclude Include="..\..\include\mbedtls\aes.h" />

+    <ClInclude Include="..\..\include\mbedtls\aesni.h" />

+    <ClInclude Include="..\..\include\mbedtls\arc4.h" />

+    <ClInclude Include="..\..\include\mbedtls\aria.h" />

+    <ClInclude Include="..\..\include\mbedtls\asn1.h" />

+    <ClInclude Include="..\..\include\mbedtls\asn1write.h" />

+    <ClInclude Include="..\..\include\mbedtls\base64.h" />

+    <ClInclude Include="..\..\include\mbedtls\bignum.h" />

+    <ClInclude Include="..\..\include\mbedtls\blowfish.h" />

+    <ClInclude Include="..\..\include\mbedtls\bn_mul.h" />

+    <ClInclude Include="..\..\include\mbedtls\camellia.h" />

+    <ClInclude Include="..\..\include\mbedtls\ccm.h" />

+    <ClInclude Include="..\..\include\mbedtls\certs.h" />

+    <ClInclude Include="..\..\include\mbedtls\chacha20.h" />

+    <ClInclude Include="..\..\include\mbedtls\chachapoly.h" />

+    <ClInclude Include="..\..\include\mbedtls\check_config.h" />

+    <ClInclude Include="..\..\include\mbedtls\cipher.h" />

+    <ClInclude Include="..\..\include\mbedtls\cipher_internal.h" />

+    <ClInclude Include="..\..\include\mbedtls\cmac.h" />

+    <ClInclude Include="..\..\include\mbedtls\compat-1.3.h" />

+    <ClInclude Include="..\..\include\mbedtls\config.h" />

+    <ClInclude Include="..\..\include\mbedtls\config_psa.h" />

+    <ClInclude Include="..\..\include\mbedtls\constant_time.h" />

+    <ClInclude Include="..\..\include\mbedtls\ctr_drbg.h" />

+    <ClInclude Include="..\..\include\mbedtls\debug.h" />

+    <ClInclude Include="..\..\include\mbedtls\des.h" />

+    <ClInclude Include="..\..\include\mbedtls\dhm.h" />

+    <ClInclude Include="..\..\include\mbedtls\ecdh.h" />

+    <ClInclude Include="..\..\include\mbedtls\ecdsa.h" />

+    <ClInclude Include="..\..\include\mbedtls\ecjpake.h" />

+    <ClInclude Include="..\..\include\mbedtls\ecp.h" />

+    <ClInclude Include="..\..\include\mbedtls\ecp_internal.h" />

+    <ClInclude Include="..\..\include\mbedtls\entropy.h" />

+    <ClInclude Include="..\..\include\mbedtls\entropy_poll.h" />

+    <ClInclude Include="..\..\include\mbedtls\error.h" />

+    <ClInclude Include="..\..\include\mbedtls\gcm.h" />

+    <ClInclude Include="..\..\include\mbedtls\havege.h" />

+    <ClInclude Include="..\..\include\mbedtls\hkdf.h" />

+    <ClInclude Include="..\..\include\mbedtls\hmac_drbg.h" />

+    <ClInclude Include="..\..\include\mbedtls\md.h" />

+    <ClInclude Include="..\..\include\mbedtls\md2.h" />

+    <ClInclude Include="..\..\include\mbedtls\md4.h" />

+    <ClInclude Include="..\..\include\mbedtls\md5.h" />

+    <ClInclude Include="..\..\include\mbedtls\md_internal.h" />

+    <ClInclude Include="..\..\include\mbedtls\memory_buffer_alloc.h" />

+    <ClInclude Include="..\..\include\mbedtls\net.h" />

+    <ClInclude Include="..\..\include\mbedtls\net_sockets.h" />

+    <ClInclude Include="..\..\include\mbedtls\nist_kw.h" />

+    <ClInclude Include="..\..\include\mbedtls\oid.h" />

+    <ClInclude Include="..\..\include\mbedtls\padlock.h" />

+    <ClInclude Include="..\..\include\mbedtls\pem.h" />

+    <ClInclude Include="..\..\include\mbedtls\pk.h" />

+    <ClInclude Include="..\..\include\mbedtls\pk_internal.h" />

+    <ClInclude Include="..\..\include\mbedtls\pkcs11.h" />

+    <ClInclude Include="..\..\include\mbedtls\pkcs12.h" />

+    <ClInclude Include="..\..\include\mbedtls\pkcs5.h" />

+    <ClInclude Include="..\..\include\mbedtls\platform.h" />

+    <ClInclude Include="..\..\include\mbedtls\platform_time.h" />

+    <ClInclude Include="..\..\include\mbedtls\platform_util.h" />

+    <ClInclude Include="..\..\include\mbedtls\poly1305.h" />

+    <ClInclude Include="..\..\include\mbedtls\psa_util.h" />

+    <ClInclude Include="..\..\include\mbedtls\ripemd160.h" />

+    <ClInclude Include="..\..\include\mbedtls\rsa.h" />

+    <ClInclude Include="..\..\include\mbedtls\rsa_internal.h" />

+    <ClInclude Include="..\..\include\mbedtls\sha1.h" />

+    <ClInclude Include="..\..\include\mbedtls\sha256.h" />

+    <ClInclude Include="..\..\include\mbedtls\sha512.h" />

+    <ClInclude Include="..\..\include\mbedtls\ssl.h" />

+    <ClInclude Include="..\..\include\mbedtls\ssl_cache.h" />

+    <ClInclude Include="..\..\include\mbedtls\ssl_ciphersuites.h" />

+    <ClInclude Include="..\..\include\mbedtls\ssl_cookie.h" />

+    <ClInclude Include="..\..\include\mbedtls\ssl_internal.h" />

+    <ClInclude Include="..\..\include\mbedtls\ssl_ticket.h" />

+    <ClInclude Include="..\..\include\mbedtls\threading.h" />

+    <ClInclude Include="..\..\include\mbedtls\timing.h" />

+    <ClInclude Include="..\..\include\mbedtls\version.h" />

+    <ClInclude Include="..\..\include\mbedtls\x509.h" />

+    <ClInclude Include="..\..\include\mbedtls\x509_crl.h" />

+    <ClInclude Include="..\..\include\mbedtls\x509_crt.h" />

+    <ClInclude Include="..\..\include\mbedtls\x509_csr.h" />

+    <ClInclude Include="..\..\include\mbedtls\xtea.h" />

+    <ClInclude Include="..\..\include\psa\crypto.h" />

+    <ClInclude Include="..\..\include\psa\crypto_builtin_composites.h" />

+    <ClInclude Include="..\..\include\psa\crypto_builtin_primitives.h" />

+    <ClInclude Include="..\..\include\psa\crypto_compat.h" />

+    <ClInclude Include="..\..\include\psa\crypto_config.h" />

+    <ClInclude Include="..\..\include\psa\crypto_driver_common.h" />

+    <ClInclude Include="..\..\include\psa\crypto_driver_contexts_composites.h" />

+    <ClInclude Include="..\..\include\psa\crypto_driver_contexts_primitives.h" />

+    <ClInclude Include="..\..\include\psa\crypto_extra.h" />

+    <ClInclude Include="..\..\include\psa\crypto_platform.h" />

+    <ClInclude Include="..\..\include\psa\crypto_se_driver.h" />

+    <ClInclude Include="..\..\include\psa\crypto_sizes.h" />

+    <ClInclude Include="..\..\include\psa\crypto_struct.h" />

+    <ClInclude Include="..\..\include\psa\crypto_types.h" />

+    <ClInclude Include="..\..\include\psa\crypto_values.h" />

+    <ClInclude Include="..\..\tests\include\test\asn1_helpers.h" />

+    <ClInclude Include="..\..\tests\include\test\constant_flow.h" />

+    <ClInclude Include="..\..\tests\include\test\fake_external_rng_for_test.h" />

+    <ClInclude Include="..\..\tests\include\test\helpers.h" />

+    <ClInclude Include="..\..\tests\include\test\macros.h" />

+    <ClInclude Include="..\..\tests\include\test\psa_crypto_helpers.h" />

+    <ClInclude Include="..\..\tests\include\test\psa_exercise_key.h" />

+    <ClInclude Include="..\..\tests\include\test\psa_helpers.h" />

+    <ClInclude Include="..\..\tests\include\test\random.h" />

+    <ClInclude Include="..\..\tests\include\test\drivers\aead.h" />

+    <ClInclude Include="..\..\tests\include\test\drivers\cipher.h" />

+    <ClInclude Include="..\..\tests\include\test\drivers\config_test_driver.h" />

+    <ClInclude Include="..\..\tests\include\test\drivers\crypto_config_test_driver_extension.h" />

+    <ClInclude Include="..\..\tests\include\test\drivers\hash.h" />

+    <ClInclude Include="..\..\tests\include\test\drivers\key_management.h" />

+    <ClInclude Include="..\..\tests\include\test\drivers\mac.h" />

+    <ClInclude Include="..\..\tests\include\test\drivers\signature.h" />

+    <ClInclude Include="..\..\tests\include\test\drivers\size.h" />

+    <ClInclude Include="..\..\tests\include\test\drivers\test_driver.h" />

+    <ClInclude Include="..\..\library\check_crypto_config.h" />

+    <ClInclude Include="..\..\library\common.h" />

+    <ClInclude Include="..\..\library\constant_time_internal.h" />

+    <ClInclude Include="..\..\library\constant_time_invasive.h" />

+    <ClInclude Include="..\..\library\ecp_invasive.h" />

+    <ClInclude Include="..\..\library\mps_common.h" />

+    <ClInclude Include="..\..\library\mps_error.h" />

+    <ClInclude Include="..\..\library\mps_reader.h" />

+    <ClInclude Include="..\..\library\mps_trace.h" />

+    <ClInclude Include="..\..\library\psa_crypto_aead.h" />

+    <ClInclude Include="..\..\library\psa_crypto_cipher.h" />

+    <ClInclude Include="..\..\library\psa_crypto_core.h" />

+    <ClInclude Include="..\..\library\psa_crypto_driver_wrappers.h" />

+    <ClInclude Include="..\..\library\psa_crypto_ecp.h" />

+    <ClInclude Include="..\..\library\psa_crypto_hash.h" />

+    <ClInclude Include="..\..\library\psa_crypto_invasive.h" />

+    <ClInclude Include="..\..\library\psa_crypto_its.h" />

+    <ClInclude Include="..\..\library\psa_crypto_mac.h" />

+    <ClInclude Include="..\..\library\psa_crypto_random_impl.h" />

+    <ClInclude Include="..\..\library\psa_crypto_rsa.h" />

+    <ClInclude Include="..\..\library\psa_crypto_se.h" />

+    <ClInclude Include="..\..\library\psa_crypto_slot_management.h" />

+    <ClInclude Include="..\..\library\psa_crypto_storage.h" />

+    <ClInclude Include="..\..\library\ssl_tls13_keys.h" />

+    <ClInclude Include="..\..\3rdparty\everest\include\everest\everest.h" />

+    <ClInclude Include="..\..\3rdparty\everest\include\everest\Hacl_Curve25519.h" />

+    <ClInclude Include="..\..\3rdparty\everest\include\everest\kremlib.h" />

+    <ClInclude Include="..\..\3rdparty\everest\include\everest\x25519.h" />

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\library\aes.c" />

+    <ClCompile Include="..\..\library\aesni.c" />

+    <ClCompile Include="..\..\library\arc4.c" />

+    <ClCompile Include="..\..\library\aria.c" />

+    <ClCompile Include="..\..\library\asn1parse.c" />

+    <ClCompile Include="..\..\library\asn1write.c" />

+    <ClCompile Include="..\..\library\base64.c" />

+    <ClCompile Include="..\..\library\bignum.c" />

+    <ClCompile Include="..\..\library\blowfish.c" />

+    <ClCompile Include="..\..\library\camellia.c" />

+    <ClCompile Include="..\..\library\ccm.c" />

+    <ClCompile Include="..\..\library\certs.c" />

+    <ClCompile Include="..\..\library\chacha20.c" />

+    <ClCompile Include="..\..\library\chachapoly.c" />

+    <ClCompile Include="..\..\library\cipher.c" />

+    <ClCompile Include="..\..\library\cipher_wrap.c" />

+    <ClCompile Include="..\..\library\cmac.c" />

+    <ClCompile Include="..\..\library\constant_time.c" />

+    <ClCompile Include="..\..\library\ctr_drbg.c" />

+    <ClCompile Include="..\..\library\debug.c" />

+    <ClCompile Include="..\..\library\des.c" />

+    <ClCompile Include="..\..\library\dhm.c" />

+    <ClCompile Include="..\..\library\ecdh.c" />

+    <ClCompile Include="..\..\library\ecdsa.c" />

+    <ClCompile Include="..\..\library\ecjpake.c" />

+    <ClCompile Include="..\..\library\ecp.c" />

+    <ClCompile Include="..\..\library\ecp_curves.c" />

+    <ClCompile Include="..\..\library\entropy.c" />

+    <ClCompile Include="..\..\library\entropy_poll.c" />

+    <ClCompile Include="..\..\library\error.c" />

+    <ClCompile Include="..\..\library\gcm.c" />

+    <ClCompile Include="..\..\library\havege.c" />

+    <ClCompile Include="..\..\library\hkdf.c" />

+    <ClCompile Include="..\..\library\hmac_drbg.c" />

+    <ClCompile Include="..\..\library\md.c" />

+    <ClCompile Include="..\..\library\md2.c" />

+    <ClCompile Include="..\..\library\md4.c" />

+    <ClCompile Include="..\..\library\md5.c" />

+    <ClCompile Include="..\..\library\memory_buffer_alloc.c" />

+    <ClCompile Include="..\..\library\mps_reader.c" />

+    <ClCompile Include="..\..\library\mps_trace.c" />

+    <ClCompile Include="..\..\library\net_sockets.c" />

+    <ClCompile Include="..\..\library\nist_kw.c" />

+    <ClCompile Include="..\..\library\oid.c" />

+    <ClCompile Include="..\..\library\padlock.c" />

+    <ClCompile Include="..\..\library\pem.c" />

+    <ClCompile Include="..\..\library\pk.c" />

+    <ClCompile Include="..\..\library\pk_wrap.c" />

+    <ClCompile Include="..\..\library\pkcs11.c" />

+    <ClCompile Include="..\..\library\pkcs12.c" />

+    <ClCompile Include="..\..\library\pkcs5.c" />

+    <ClCompile Include="..\..\library\pkparse.c" />

+    <ClCompile Include="..\..\library\pkwrite.c" />

+    <ClCompile Include="..\..\library\platform.c" />

+    <ClCompile Include="..\..\library\platform_util.c" />

+    <ClCompile Include="..\..\library\poly1305.c" />

+    <ClCompile Include="..\..\library\psa_crypto.c" />

+    <ClCompile Include="..\..\library\psa_crypto_aead.c" />

+    <ClCompile Include="..\..\library\psa_crypto_cipher.c" />

+    <ClCompile Include="..\..\library\psa_crypto_client.c" />

+    <ClCompile Include="..\..\library\psa_crypto_driver_wrappers.c" />

+    <ClCompile Include="..\..\library\psa_crypto_ecp.c" />

+    <ClCompile Include="..\..\library\psa_crypto_hash.c" />

+    <ClCompile Include="..\..\library\psa_crypto_mac.c" />

+    <ClCompile Include="..\..\library\psa_crypto_rsa.c" />

+    <ClCompile Include="..\..\library\psa_crypto_se.c" />

+    <ClCompile Include="..\..\library\psa_crypto_slot_management.c" />

+    <ClCompile Include="..\..\library\psa_crypto_storage.c" />

+    <ClCompile Include="..\..\library\psa_its_file.c" />

+    <ClCompile Include="..\..\library\ripemd160.c" />

+    <ClCompile Include="..\..\library\rsa.c" />

+    <ClCompile Include="..\..\library\rsa_internal.c" />

+    <ClCompile Include="..\..\library\sha1.c" />

+    <ClCompile Include="..\..\library\sha256.c" />

+    <ClCompile Include="..\..\library\sha512.c" />

+    <ClCompile Include="..\..\library\ssl_cache.c" />

+    <ClCompile Include="..\..\library\ssl_ciphersuites.c" />

+    <ClCompile Include="..\..\library\ssl_cli.c" />

+    <ClCompile Include="..\..\library\ssl_cookie.c" />

+    <ClCompile Include="..\..\library\ssl_msg.c" />

+    <ClCompile Include="..\..\library\ssl_srv.c" />

+    <ClCompile Include="..\..\library\ssl_ticket.c" />

+    <ClCompile Include="..\..\library\ssl_tls.c" />

+    <ClCompile Include="..\..\library\ssl_tls13_keys.c" />

+    <ClCompile Include="..\..\library\threading.c" />

+    <ClCompile Include="..\..\library\timing.c" />

+    <ClCompile Include="..\..\library\version.c" />

+    <ClCompile Include="..\..\library\version_features.c" />

+    <ClCompile Include="..\..\library\x509.c" />

+    <ClCompile Include="..\..\library\x509_create.c" />

+    <ClCompile Include="..\..\library\x509_crl.c" />

+    <ClCompile Include="..\..\library\x509_crt.c" />

+    <ClCompile Include="..\..\library\x509_csr.c" />

+    <ClCompile Include="..\..\library\x509write_crt.c" />

+    <ClCompile Include="..\..\library\x509write_csr.c" />

+    <ClCompile Include="..\..\library\xtea.c" />

+    <ClCompile Include="..\..\tests\src\asn1_helpers.c" />

+    <ClCompile Include="..\..\tests\src\fake_external_rng_for_test.c" />

+    <ClCompile Include="..\..\tests\src\helpers.c" />

+    <ClCompile Include="..\..\tests\src\psa_crypto_helpers.c" />

+    <ClCompile Include="..\..\tests\src\psa_exercise_key.c" />

+    <ClCompile Include="..\..\tests\src\random.c" />

+    <ClCompile Include="..\..\tests\src\threading_helpers.c" />

+    <ClCompile Include="..\..\tests\src\drivers\hash.c" />

+    <ClCompile Include="..\..\tests\src\drivers\platform_builtin_keys.c" />

+    <ClCompile Include="..\..\tests\src\drivers\test_driver_aead.c" />

+    <ClCompile Include="..\..\tests\src\drivers\test_driver_cipher.c" />

+    <ClCompile Include="..\..\tests\src\drivers\test_driver_key_management.c" />

+    <ClCompile Include="..\..\tests\src\drivers\test_driver_mac.c" />

+    <ClCompile Include="..\..\tests\src\drivers\test_driver_signature.c" />

+    <ClCompile Include="..\..\tests\src\drivers\test_driver_size.c" />

+    <ClCompile Include="..\..\3rdparty\everest\library\everest.c" />

+    <ClCompile Include="..\..\3rdparty\everest\library\Hacl_Curve25519_joined.c" />

+    <ClCompile Include="..\..\3rdparty\everest\library\x25519.c" />

+    <ClCompile Include="..\..\3rdparty\everest\library\kremlib\FStar_UInt128_extracted.c" />

+    <ClCompile Include="..\..\3rdparty\everest\library\kremlib\FStar_UInt64_FStar_UInt32_FStar_UInt16_FStar_UInt8.c" />

+    <ClCompile Include="..\..\3rdparty\everest\library\legacy\Hacl_Curve25519.c" />

+  </ItemGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/mini_client.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/mini_client.vcxproj
index 7d0c82b..e4ee166 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/mini_client.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/mini_client.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\ssl\mini_client.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{C4FE29EA-266D-5295-4840-976B9B5B3843}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>mini_client</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\ssl\mini_client.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{C4FE29EA-266D-5295-4840-976B9B5B3843}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>mini_client</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/mpi_demo.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/mpi_demo.vcxproj
index 8f200bb..b0fee89 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/mpi_demo.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/mpi_demo.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\mpi_demo.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>mpi_demo</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\mpi_demo.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{A59FAA0B-9C34-1F99-794D-A365A3AA8CCE}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>mpi_demo</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/pem2der.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/pem2der.vcxproj
index 2132a5e..84c2e8c 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/pem2der.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/pem2der.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\util\pem2der.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>pem2der</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\util\pem2der.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{D3C6FBD6-D78E-7180-8345-5E09B492DBEC}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>pem2der</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/pk_decrypt.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/pk_decrypt.vcxproj
index 11e49ed..da3e8d8 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/pk_decrypt.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/pk_decrypt.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\pk_decrypt.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{1EC6CBA3-6187-D456-D9B7-A35399395D71}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>pk_decrypt</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\pk_decrypt.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{1EC6CBA3-6187-D456-D9B7-A35399395D71}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>pk_decrypt</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/pk_encrypt.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/pk_encrypt.vcxproj
index 1772cad..829e072 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/pk_encrypt.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/pk_encrypt.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\pk_encrypt.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{55007179-7746-9CFB-97EC-65102FB272C8}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>pk_encrypt</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\pk_encrypt.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{55007179-7746-9CFB-97EC-65102FB272C8}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>pk_encrypt</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/pk_sign.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/pk_sign.vcxproj
index b040f57..d93d114 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/pk_sign.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/pk_sign.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\pk_sign.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{F2E8CA55-597F-7FDC-6456-D8650FB970A3}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>pk_sign</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\pk_sign.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{F2E8CA55-597F-7FDC-6456-D8650FB970A3}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>pk_sign</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/pk_verify.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/pk_verify.vcxproj
index 6b11e59..5933b92 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/pk_verify.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/pk_verify.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\pk_verify.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{C429B336-1B30-119C-3B34-21A186D6744F}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>pk_verify</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\pk_verify.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{C429B336-1B30-119C-3B34-21A186D6744F}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>pk_verify</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/psa_constant_names.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/psa_constant_names.vcxproj
index 7a78a78..d35dd19 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/psa_constant_names.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/psa_constant_names.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\psa\psa_constant_names.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>psa_constant_names</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\psa\psa_constant_names.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{A0BAD8F0-69B5-8382-86ED-C36ACBE54117}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>psa_constant_names</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/query_compile_time_config.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/query_compile_time_config.vcxproj
index cb75e52..d0e0a6d 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/query_compile_time_config.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/query_compile_time_config.vcxproj
@@ -1,168 +1,168 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\test\query_compile_time_config.c" />
-    <ClCompile Include="..\..\programs\test\query_config.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{D6F58AF2-9D80-562A-E2B0-F743281522B9}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>query_compile_time_config</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\test\query_compile_time_config.c" />

+    <ClCompile Include="..\..\programs\test\query_config.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{D6F58AF2-9D80-562A-E2B0-F743281522B9}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>query_compile_time_config</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/req_app.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/req_app.vcxproj
index a18cc47..900e415 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/req_app.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/req_app.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\x509\req_app.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>req_app</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\x509\req_app.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>req_app</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/rsa_decrypt.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/rsa_decrypt.vcxproj
index c8dcf55..188b17e 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/rsa_decrypt.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/rsa_decrypt.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\rsa_decrypt.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>rsa_decrypt</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\rsa_decrypt.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{E0D71D72-8DF4-CCFC-EF60-741EADAB8BF9}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>rsa_decrypt</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/rsa_encrypt.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/rsa_encrypt.vcxproj
index c0f88ab..a44f676 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/rsa_encrypt.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/rsa_encrypt.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\rsa_encrypt.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{D06CF12E-F222-9273-41BF-B8A052FA5527}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>rsa_encrypt</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\rsa_encrypt.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{D06CF12E-F222-9273-41BF-B8A052FA5527}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>rsa_encrypt</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/rsa_genkey.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/rsa_genkey.vcxproj
index 8459968..35b27b7 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/rsa_genkey.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/rsa_genkey.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\rsa_genkey.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{F472475C-F677-0E7F-F127-45BF5B64F622}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>rsa_genkey</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\rsa_genkey.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{F472475C-F677-0E7F-F127-45BF5B64F622}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>rsa_genkey</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/rsa_sign.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/rsa_sign.vcxproj
index 9edb632..90a7ac8 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/rsa_sign.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/rsa_sign.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\rsa_sign.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{10790F49-6887-AAB6-2D86-BCBD516F8D26}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>rsa_sign</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\rsa_sign.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{10790F49-6887-AAB6-2D86-BCBD516F8D26}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>rsa_sign</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/rsa_sign_pss.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/rsa_sign_pss.vcxproj
index 4cd0125..5d2ac82 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/rsa_sign_pss.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/rsa_sign_pss.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\rsa_sign_pss.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>rsa_sign_pss</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\rsa_sign_pss.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{DCD3A1B6-5EC1-8266-93EF-BD2B9BEFE12D}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>rsa_sign_pss</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/rsa_verify.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/rsa_verify.vcxproj
index f231c88..a413ba8 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/rsa_verify.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/rsa_verify.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\rsa_verify.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{689E28CF-89ED-BA38-3A14-78A75D891D46}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>rsa_verify</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\rsa_verify.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{689E28CF-89ED-BA38-3A14-78A75D891D46}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>rsa_verify</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/rsa_verify_pss.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/rsa_verify_pss.vcxproj
index 8ef9bf1..369b145 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/rsa_verify_pss.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/rsa_verify_pss.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\pkey\rsa_verify_pss.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{95C50864-854C-2A11-4C91-BCE654E344FB}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>rsa_verify_pss</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\pkey\rsa_verify_pss.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{95C50864-854C-2A11-4C91-BCE654E344FB}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>rsa_verify_pss</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/selftest.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/selftest.vcxproj
index 76600be..6feb593 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/selftest.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/selftest.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\test\selftest.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>selftest</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\test\selftest.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{7DBC5F77-3DA1-5F73-8421-E693D95FC66A}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>selftest</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/ssl_client1.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/ssl_client1.vcxproj
index 8a731c1..860334e 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/ssl_client1.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/ssl_client1.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\ssl\ssl_client1.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{487A2F80-3CA3-678D-88D5-82194872CF08}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>ssl_client1</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\ssl\ssl_client1.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{487A2F80-3CA3-678D-88D5-82194872CF08}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>ssl_client1</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/ssl_client2.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/ssl_client2.vcxproj
index d7000a4..9884f23 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/ssl_client2.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/ssl_client2.vcxproj
@@ -1,168 +1,169 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\ssl\ssl_client2.c" />
-    <ClCompile Include="..\..\programs\test\query_config.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{4E590E9D-E28F-87FF-385B-D58736388231}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>ssl_client2</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\ssl\ssl_client2.c" />

+    <ClCompile Include="..\..\programs\test\query_config.c" />

+    <ClCompile Include="..\..\programs\ssl\ssl_test_lib.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{4E590E9D-E28F-87FF-385B-D58736388231}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>ssl_client2</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/ssl_context_info.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/ssl_context_info.vcxproj
index 99a95c2..1c98d34 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/ssl_context_info.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/ssl_context_info.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\ssl\ssl_context_info.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>ssl_context_info</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\ssl\ssl_context_info.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{017ECC7D-FB6D-46D8-076B-F64172E8E3BC}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>ssl_context_info</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/ssl_fork_server.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/ssl_fork_server.vcxproj
index 8534bba..6d44ef0 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/ssl_fork_server.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/ssl_fork_server.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\ssl\ssl_fork_server.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{918CD402-047D-8467-E11C-E1132053F916}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>ssl_fork_server</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\ssl\ssl_fork_server.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{918CD402-047D-8467-E11C-E1132053F916}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>ssl_fork_server</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/ssl_mail_client.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/ssl_mail_client.vcxproj
index 989ba91..e2253c6 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/ssl_mail_client.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/ssl_mail_client.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\ssl\ssl_mail_client.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>ssl_mail_client</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\ssl\ssl_mail_client.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>ssl_mail_client</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/ssl_server.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/ssl_server.vcxproj
index 4447fed..23ad7ec 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/ssl_server.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/ssl_server.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\ssl\ssl_server.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{E08E0065-896A-7487-DEA5-D3B80B71F975}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>ssl_server</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\ssl\ssl_server.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{E08E0065-896A-7487-DEA5-D3B80B71F975}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>ssl_server</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/ssl_server2.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/ssl_server2.vcxproj
index a21e6e0..d8f3e59 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/ssl_server2.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/ssl_server2.vcxproj
@@ -1,168 +1,169 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\ssl\ssl_server2.c" />
-    <ClCompile Include="..\..\programs\test\query_config.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{A4DA7463-1047-BDF5-E1B3-5632CB573F41}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>ssl_server2</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\ssl\ssl_server2.c" />

+    <ClCompile Include="..\..\programs\test\query_config.c" />

+    <ClCompile Include="..\..\programs\ssl\ssl_test_lib.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{A4DA7463-1047-BDF5-E1B3-5632CB573F41}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>ssl_server2</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/strerror.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/strerror.vcxproj
index 586693a..9e70dec 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/strerror.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/strerror.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\util\strerror.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{23EF735C-CC4C-3EC4-A75E-903DB340F04A}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>strerror</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\util\strerror.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{23EF735C-CC4C-3EC4-A75E-903DB340F04A}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>strerror</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/udp_proxy.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/udp_proxy.vcxproj
index 9977fd6..69678f6 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/udp_proxy.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/udp_proxy.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\test\udp_proxy.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>udp_proxy</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\test\udp_proxy.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>udp_proxy</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/mbedtls/repo/visualc/VS2010/zeroize.vcxproj b/third_party/mbedtls/repo/visualc/VS2010/zeroize.vcxproj
index 97c4fd5..9e0746d 100644
--- a/third_party/mbedtls/repo/visualc/VS2010/zeroize.vcxproj
+++ b/third_party/mbedtls/repo/visualc/VS2010/zeroize.vcxproj
@@ -1,167 +1,167 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Debug|x64">
-      <Configuration>Debug</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|x64">
-      <Configuration>Release</Configuration>
-      <Platform>x64</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="..\..\programs\test\zeroize.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>
-      <LinkLibraryDependencies>true</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{10C01E94-4926-063E-9F56-C84ED190D349}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>zeroize</RootNamespace>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>
-    </Link>
-    <ProjectReference>
-      <LinkLibraryDependencies>false</LinkLibraryDependencies>
-    </ProjectReference>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>
-../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>
-    </Link>
-  </ItemDefinitionGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Debug|Win32">

+      <Configuration>Debug</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|x64">

+      <Configuration>Debug</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="..\..\programs\test\zeroize.c" />

+  </ItemGroup>

+  <ItemGroup>

+    <ProjectReference Include="mbedTLS.vcxproj">

+      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

+      <LinkLibraryDependencies>true</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{10C01E94-4926-063E-9F56-C84ED190D349}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>zeroize</RootNamespace>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>true</UseDebugLibraries>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>Application</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <LinkIncremental>true</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <IntDir>$(Configuration)\$(TargetName)\</IntDir>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>Disabled</Optimization>

+      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

+    </Link>

+    <ProjectReference>

+      <LinkLibraryDependencies>false</LinkLibraryDependencies>

+    </ProjectReference>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <AdditionalIncludeDirectories>

+../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib;../../tests/include      </AdditionalIncludeDirectories>

+    </ClCompile>

+    <Link>

+      <SubSystem>Console</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

+      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>

diff --git a/third_party/tcplp/CMakeLists.txt b/third_party/tcplp/CMakeLists.txt
index 06323f4..3ea41b6 100644
--- a/third_party/tcplp/CMakeLists.txt
+++ b/third_party/tcplp/CMakeLists.txt
@@ -29,6 +29,15 @@
 project("TCPlp" C)
 
 set(src_tcplp
+    bsdtcp/cc/cc_newreno.c
+    bsdtcp/tcp_input.c
+    bsdtcp/tcp_output.c
+    bsdtcp/tcp_reass.c
+    bsdtcp/tcp_sack.c
+    bsdtcp/tcp_subr.c
+    bsdtcp/tcp_timer.c
+    bsdtcp/tcp_timewait.c
+    bsdtcp/tcp_usrreq.c
     lib/bitmap.c
     lib/cbuf.c
     lib/lbuf.c
@@ -36,7 +45,18 @@
 
 set(tcplp_static_target "tcplp")
 
+string(REPLACE "-Wsign-compare" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
+
+string(REPLACE "-Wconversion" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
+
+string(REPLACE "-Wunused-parameter" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
+
 add_library(${tcplp_static_target} STATIC ${src_tcplp})
+target_compile_options(${tcplp_static_target}
+    PRIVATE
+        "-Wno-sign-compare"
+        "-Wno-unused-parameter"
+)
 set_target_properties(${tcplp_static_target} PROPERTIES OUTPUT_NAME tcplp)
 target_include_directories(${tcplp_static_target}
     PUBLIC
diff --git a/third_party/tcplp/Makefile.am b/third_party/tcplp/Makefile.am
index 282e8e0..b7a5aba 100644
--- a/third_party/tcplp/Makefile.am
+++ b/third_party/tcplp/Makefile.am
@@ -29,6 +29,19 @@
 include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
 
 EXTRA_DIST                                    = \
+    bsdtcp/cc/cc_module.h                       \
+    bsdtcp/sys/queue.h                          \
+    bsdtcp/cc.h                                 \
+    bsdtcp/icmp_var.h                           \
+    bsdtcp/ip6.h                                \
+    bsdtcp/ip.h                                 \
+    bsdtcp/tcp_const.h                          \
+    bsdtcp/tcp_fsm.h                            \
+    bsdtcp/tcp.h                                \
+    bsdtcp/tcp_seq.h                            \
+    bsdtcp/tcp_timer.h                          \
+    bsdtcp/tcp_var.h                            \
+    bsdtcp/types.h                              \
     lib/bitmap.h                                \
     lib/cbuf.h                                  \
     lib/lbuf.h                                  \
@@ -43,6 +56,13 @@
 override CFLAGS                              := $(filter-out -Wsign-compare,$(CFLAGS))
 override CFLAGS                              := $(CFLAGS) -Wno-sign-compare
 
+# Do not enable -Wconversion for TCPlp
+override CFLAGS                              := $(filter-out -Wconversion,$(CFLAGS))
+
+# Do not enable -Wcast-align for TCPlp
+override CFLAGS                              := $(filter-out -Wcast-align,$(CFLAGS))
+override CFLAGS                              := $(CFLAGS) -Wno-cast-align
+
 # Do not enable -Wunused-parameter for TCPlp
 override CFLAGS                              := $(filter-out -Wunused-parameter,$(CFLAGS))
 override CFLAGS                              := $(CFLAGS) -Wno-unused-parameter
@@ -65,6 +85,15 @@
     $(NULL)
 
 libtcplp_a_SOURCES                            = \
+    bsdtcp/cc/cc_newreno.c                      \
+    bsdtcp/tcp_input.c                          \
+    bsdtcp/tcp_output.c                         \
+    bsdtcp/tcp_reass.c                          \
+    bsdtcp/tcp_sack.c                           \
+    bsdtcp/tcp_subr.c                           \
+    bsdtcp/tcp_timer.c                          \
+    bsdtcp/tcp_timewait.c                       \
+    bsdtcp/tcp_usrreq.c                         \
     lib/bitmap.c                                \
     lib/cbuf.c                                  \
     lib/lbuf.c                                  \
diff --git a/third_party/tcplp/bsdtcp/cc.h b/third_party/tcplp/bsdtcp/cc.h
new file mode 100644
index 0000000..a213f55
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/cc.h
@@ -0,0 +1,163 @@
+/*-
+ * Copyright (c) 2007-2008
+ * 	Swinburne University of Technology, Melbourne, Australia.
+ * Copyright (c) 2009-2010 Lawrence Stewart <lstewart@freebsd.org>
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed at the Centre for Advanced Internet
+ * Architectures, Swinburne University of Technology, by Lawrence Stewart and
+ * James Healy, made possible in part by a grant from the Cisco University
+ * Research Program Fund at Community Foundation Silicon Valley.
+ *
+ * Portions of this software were developed at the Centre for Advanced
+ * Internet Architectures, Swinburne University of Technology, Melbourne,
+ * Australia by David Hayes under sponsorship from the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * This software was first released in 2007 by James Healy and Lawrence Stewart
+ * whilst working on the NewTCP research project at Swinburne University of
+ * Technology's Centre for Advanced Internet Architectures, Melbourne,
+ * Australia, which was made possible in part by a grant from the Cisco
+ * University Research Program Fund at Community Foundation Silicon Valley.
+ * More details are available at:
+ *   http://caia.swin.edu.au/urp/newtcp/
+ */
+
+/*
+ * samkumar: The FreeBSD implementation supports many congestion control
+ * algorithms, each represented by a struct. Each tcpcb has a pointer to the
+ * relevant congestion control struct, and the congestion control structs are
+ * themselves part of an intrusive linked list. TCPlp hardcodes the congestion
+ * control algorithm to New Reno, so the fields corresponding to maintaining
+ * the global linked list are removed.
+ */
+
+#ifndef TCPLP_NETINET_CC_H_
+#define TCPLP_NETINET_CC_H_
+
+/* XXX: TCP_CA_NAME_MAX define lives in tcp.h for compat reasons. */
+#include "tcp.h"
+
+extern const struct cc_algo newreno_cc_algo;
+
+/*
+ * Wrapper around transport structs that contain same-named congestion
+ * control variables. Allows algos to be shared amongst multiple CC aware
+ * transprots.
+ */
+struct cc_var {
+	void		*cc_data; /* Per-connection private CC algorithm data. */
+	int		bytes_this_ack; /* # bytes acked by the current ACK. */
+	tcp_seq		curack; /* Most recent ACK. */
+	uint32_t	flags; /* Flags for cc_var (see below) */
+	/* samkumar: removing type, since TCPlp uses TCP congestion control. */
+	//int		type; /* Indicates which ptr is valid in ccvc. */
+	union ccv_container {
+		struct tcpcb		*tcp;
+		struct sctp_nets	*sctp;
+	} ccvc;
+};
+
+/* cc_var flags. */
+#define	CCF_ABC_SENTAWND	0x0001	/* ABC counted cwnd worth of bytes? */
+#define	CCF_CWND_LIMITED	0x0002	/* Are we currently cwnd limited? */
+#define	CCF_DELACK		0x0004	/* Is this ack delayed? */
+#define	CCF_ACKNOW		0x0008	/* Will this ack be sent now? */
+#define	CCF_IPHDR_CE		0x0010	/* Does this packet set CE bit? */
+#define	CCF_TCPHDR_CWR		0x0020	/* Does this packet set CWR bit? */
+
+/* ACK types passed to the ack_received() hook. */
+#define	CC_ACK		0x0001	/* Regular in sequence ACK. */
+#define	CC_DUPACK	0x0002	/* Duplicate ACK. */
+#define	CC_PARTIALACK	0x0004	/* Not yet. */
+#define	CC_SACK		0x0008	/* Not yet. */
+
+/*
+ * Congestion signal types passed to the cong_signal() hook. The highest order 8
+ * bits (0x01000000 - 0x80000000) are reserved for CC algos to declare their own
+ * congestion signal types.
+ */
+#define	CC_ECN		0x00000001	/* ECN marked packet received. */
+#define	CC_RTO		0x00000002	/* RTO fired. */
+#define	CC_RTO_ERR	0x00000004	/* RTO fired in error. */
+#define	CC_NDUPACK	0x00000008	/* Threshold of dupack's reached. */
+
+#define	CC_SIGPRIVMASK	0xFF000000	/* Mask to check if sig is private. */
+
+/*
+ * Structure to hold data and function pointers that together represent a
+ * congestion control algorithm.
+ */
+struct cc_algo {
+	char	name[TCP_CA_NAME_MAX];
+
+	/* Init global module state on kldload. */
+	int	(*mod_init)(void);
+
+	/* Cleanup global module state on kldunload. */
+	int	(*mod_destroy)(void);
+
+	/* Init CC state for a new control block. */
+	int	(*cb_init)(struct cc_var *ccv);
+
+	/* Cleanup CC state for a terminating control block. */
+	void	(*cb_destroy)(struct cc_var *ccv);
+
+	/* Init variables for a newly established connection. */
+	void	(*conn_init)(struct cc_var *ccv);
+
+	/* Called on receipt of an ack. */
+	void	(*ack_received)(struct cc_var *ccv, uint16_t type);
+
+	/* Called on detection of a congestion signal. */
+	void	(*cong_signal)(struct cc_var *ccv, uint32_t type);
+
+	/* Called after exiting congestion recovery. */
+	void	(*post_recovery)(struct cc_var *ccv);
+
+	/* Called when data transfer resumes after an idle period. */
+	void	(*after_idle)(struct cc_var *ccv);
+
+	/* Called for an additional ECN processing apart from RFC3168. */
+	void	(*ecnpkt_handler)(struct cc_var *ccv);
+
+	/*
+	 * samkumar: This field is removed since we no longer use the intrusive
+	 * linked list.
+	 */
+	//STAILQ_ENTRY (cc_algo) entries;
+};
+
+/* Macro to obtain the CC algo's struct ptr. */
+//#define	CC_ALGO(tp)	((tp)->cc_algo)
+#define CC_ALGO(tp) (&newreno_cc_algo) // samkumar: This allows the #defines in cc_newreno.c to work as intended
+
+/* Macro to obtain the CC algo's data ptr. */
+#define	CC_DATA(tp)	((tp)->ccv->cc_data)
+
+#endif /* _NETINET_CC_H_ */
diff --git a/third_party/tcplp/bsdtcp/cc/cc_module.h b/third_party/tcplp/bsdtcp/cc/cc_module.h
new file mode 100644
index 0000000..9d83f29
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/cc/cc_module.h
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 2009-2010 Lawrence Stewart <lstewart@freebsd.org>
+ * All rights reserved.
+ *
+ * This software was developed by Lawrence Stewart while studying at the Centre
+ * for Advanced Internet Architectures, Swinburne University of Technology, made
+ * possible in part by a grant from the Cisco University Research Program Fund
+ * at Community Foundation Silicon Valley.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * This software was first released in 2009 by Lawrence Stewart as part of the
+ * NewTCP research project at Swinburne University of Technology's Centre for
+ * Advanced Internet Architectures, Melbourne, Australia, which was made
+ * possible in part by a grant from the Cisco University Research Program Fund
+ * at Community Foundation Silicon Valley. More details are available at:
+ *   http://caia.swin.edu.au/urp/newtcp/
+ */
+
+#ifndef TCPLP_NETINET_CC_MODULE_H_
+#define TCPLP_NETINET_CC_MODULE_H_
+
+/* samkumar: This was already commented out in FreeBSD (I didn't do it). */
+/*
+ * Allows a CC algorithm to manipulate a commonly named CC variable regardless
+ * of the transport protocol and associated C struct.
+ * XXXLAS: Out of action until the work to support SCTP is done.
+ *
+#define	CCV(ccv, what)							\
+(*(									\
+	(ccv)->type == IPPROTO_TCP ?	&(ccv)->ccvc.tcp->what :	\
+					&(ccv)->ccvc.sctp->what		\
+))
+ */
+#define	CCV(ccv, what) (ccv)->ccvc.tcp->what
+
+/*
+ * samkumar: I've commented this out (using #if 0) because our current TCPlp
+ * implementation hardcodes New Reno. Thus, we don't need FreeBSD's "module"
+ * mechanism to choose a congestion control algorithm.
+ */
+#if 0
+#define	DECLARE_CC_MODULE(ccname, ccalgo) 				\
+	static moduledata_t cc_##ccname = {				\
+		.name = #ccname,					\
+		.evhand = cc_modevent,					\
+		.priv = ccalgo						\
+	};								\
+	DECLARE_MODULE(ccname, cc_##ccname,				\
+	    SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY)
+
+int	cc_modevent(module_t mod, int type, void *data);
+#endif
+
+#endif /* _NETINET_CC_MODULE_H_ */
diff --git a/third_party/tcplp/bsdtcp/cc/cc_newreno.c b/third_party/tcplp/bsdtcp/cc/cc_newreno.c
new file mode 100644
index 0000000..adb7e86
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/cc/cc_newreno.c
@@ -0,0 +1,246 @@
+/*-
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995
+ *	The Regents of the University of California.
+ * Copyright (c) 2007-2008,2010
+ *	Swinburne University of Technology, Melbourne, Australia.
+ * Copyright (c) 2009-2010 Lawrence Stewart <lstewart@freebsd.org>
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed at the Centre for Advanced Internet
+ * Architectures, Swinburne University of Technology, by Lawrence Stewart, James
+ * Healy and David Hayes, made possible in part by a grant from the Cisco
+ * University Research Program Fund at Community Foundation Silicon Valley.
+ *
+ * Portions of this software were developed at the Centre for Advanced
+ * Internet Architectures, Swinburne University of Technology, Melbourne,
+ * Australia by David Hayes under sponsorship from the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * This software was first released in 2007 by James Healy and Lawrence Stewart
+ * whilst working on the NewTCP research project at Swinburne University of
+ * Technology's Centre for Advanced Internet Architectures, Melbourne,
+ * Australia, which was made possible in part by a grant from the Cisco
+ * University Research Program Fund at Community Foundation Silicon Valley.
+ * More details are available at:
+ *   http://caia.swin.edu.au/urp/newtcp/
+ */
+
+/* samkumar: Removed/replaced a bunch of #include's. */
+
+#include "../cc.h"
+#include "../tcp.h"
+#include "../tcp_seq.h"
+#include "../tcp_var.h"
+#include "cc_module.h"
+
+#include "../tcp_const.h"
+
+static int min(int a, int b) { return (a < b) ? a : b; }
+
+static void	newreno_ack_received(struct cc_var *ccv, uint16_t type);
+static void	newreno_after_idle(struct cc_var *ccv);
+static void	newreno_cong_signal(struct cc_var *ccv, uint32_t type);
+static void	newreno_post_recovery(struct cc_var *ccv);
+
+const struct cc_algo newreno_cc_algo = {
+	.name = "newreno",
+	.ack_received = newreno_ack_received,
+	.after_idle = newreno_after_idle,
+	.cong_signal = newreno_cong_signal,
+	.post_recovery = newreno_post_recovery,
+};
+
+/*
+ * samkumar: Normally, this is done in cc.c. It's commented out since we
+ * just hardcode using New Reno in TCPlp (for now). We don't use FreeBSD's
+ * mechanism to have multiple congestion control modules and choose among
+ * them.
+ */
+//struct cc_algo* V_default_cc_ptr = &newreno_cc_algo;
+
+/* samkumar: Constant that is referenced (may want to change this later) */
+enum {
+    V_tcp_do_rfc3465 = 1
+};
+
+static void
+newreno_ack_received(struct cc_var *ccv, uint16_t type)
+{
+	if (type == CC_ACK && !IN_RECOVERY(CCV(ccv, t_flags)) &&
+	    (ccv->flags & CCF_CWND_LIMITED)) {
+		uint32_t cw = CCV(ccv, snd_cwnd);
+		uint32_t incr = CCV(ccv, t_maxseg);
+
+		/*
+		 * Regular in-order ACK, open the congestion window.
+		 * Method depends on which congestion control state we're
+		 * in (slow start or cong avoid) and if ABC (RFC 3465) is
+		 * enabled.
+		 *
+		 * slow start: cwnd <= ssthresh
+		 * cong avoid: cwnd > ssthresh
+		 *
+		 * slow start and ABC (RFC 3465):
+		 *   Grow cwnd exponentially by the amount of data
+		 *   ACKed capping the max increment per ACK to
+		 *   (abc_l_var * maxseg) bytes.
+		 *
+		 * slow start without ABC (RFC 5681):
+		 *   Grow cwnd exponentially by maxseg per ACK.
+		 *
+		 * cong avoid and ABC (RFC 3465):
+		 *   Grow cwnd linearly by maxseg per RTT for each
+		 *   cwnd worth of ACKed data.
+		 *
+		 * cong avoid without ABC (RFC 5681):
+		 *   Grow cwnd linearly by approximately maxseg per RTT using
+		 *   maxseg^2 / cwnd per ACK as the increment.
+		 *   If cwnd > maxseg^2, fix the cwnd increment at 1 byte to
+		 *   avoid capping cwnd.
+		 */
+		if (cw > CCV(ccv, snd_ssthresh)) {
+			if (V_tcp_do_rfc3465) {
+				if (ccv->flags & CCF_ABC_SENTAWND)
+					ccv->flags &= ~CCF_ABC_SENTAWND;
+				else
+					incr = 0;
+			} else
+				incr = max((incr * incr / cw), 1);
+		} else if (V_tcp_do_rfc3465) {
+			/*
+			 * In slow-start with ABC enabled and no RTO in sight?
+			 * (Must not use abc_l_var > 1 if slow starting after
+			 * an RTO. On RTO, snd_nxt = snd_una, so the
+			 * snd_nxt == snd_max check is sufficient to
+			 * handle this).
+			 *
+			 * XXXLAS: Find a way to signal SS after RTO that
+			 * doesn't rely on tcpcb vars.
+			 */
+			if (CCV(ccv, snd_nxt) == CCV(ccv, snd_max))
+				incr = min(ccv->bytes_this_ack,
+				    V_tcp_abc_l_var * CCV(ccv, t_maxseg));
+			else
+				incr = min(ccv->bytes_this_ack, CCV(ccv, t_maxseg));
+		}
+		/* ABC is on by default, so incr equals 0 frequently. */
+		if (incr > 0)
+			CCV(ccv, snd_cwnd) = min(cw + incr,
+			    TCP_MAXWIN << CCV(ccv, snd_scale));
+	}
+}
+
+static void
+newreno_after_idle(struct cc_var *ccv)
+{
+	int rw;
+
+	/*
+	 * If we've been idle for more than one retransmit timeout the old
+	 * congestion window is no longer current and we have to reduce it to
+	 * the restart window before we can transmit again.
+	 *
+	 * The restart window is the initial window or the last CWND, whichever
+	 * is smaller.
+	 *
+	 * This is done to prevent us from flooding the path with a full CWND at
+	 * wirespeed, overloading router and switch buffers along the way.
+	 *
+	 * See RFC5681 Section 4.1. "Restarting Idle Connections".
+	 */
+	if (V_tcp_do_rfc3390)
+		rw = min(4 * CCV(ccv, t_maxseg),
+		    max(2 * CCV(ccv, t_maxseg), 4380));
+	else
+		rw = CCV(ccv, t_maxseg) * 2;
+
+	CCV(ccv, snd_cwnd) = min(rw, CCV(ccv, snd_cwnd));
+}
+
+/*
+ * Perform any necessary tasks before we enter congestion recovery.
+ */
+static void
+newreno_cong_signal(struct cc_var *ccv, uint32_t type)
+{
+	uint32_t win;
+
+	/* Catch algos which mistakenly leak private signal types. */
+	KASSERT((type & CC_SIGPRIVMASK) == 0,
+	    ("%s: congestion signal type 0x%08x is private", __func__, (unsigned int) type));
+
+	win = max(CCV(ccv, snd_cwnd) / 2 / CCV(ccv, t_maxseg), 2) *
+	    CCV(ccv, t_maxseg);
+
+	switch (type) {
+	case CC_NDUPACK:
+		if (!IN_FASTRECOVERY(CCV(ccv, t_flags))) {
+			if (!IN_CONGRECOVERY(CCV(ccv, t_flags)))
+				CCV(ccv, snd_ssthresh) = win;
+			ENTER_RECOVERY(CCV(ccv, t_flags));
+		}
+		break;
+	case CC_ECN:
+		if (!IN_CONGRECOVERY(CCV(ccv, t_flags))) {
+			CCV(ccv, snd_ssthresh) = win;
+			CCV(ccv, snd_cwnd) = win;
+			ENTER_CONGRECOVERY(CCV(ccv, t_flags));
+		}
+		break;
+	}
+}
+
+/*
+ * Perform any necessary tasks before we exit congestion recovery.
+ */
+static void
+newreno_post_recovery(struct cc_var *ccv)
+{
+	if (IN_FASTRECOVERY(CCV(ccv, t_flags))) {
+		/*
+		 * Fast recovery will conclude after returning from this
+		 * function. Window inflation should have left us with
+		 * approximately snd_ssthresh outstanding data. But in case we
+		 * would be inclined to send a burst, better to do it via the
+		 * slow start mechanism.
+		 *
+		 * XXXLAS: Find a way to do this without needing curack
+		 */
+		if (SEQ_GT(ccv->curack + CCV(ccv, snd_ssthresh),
+		    CCV(ccv, snd_max)))
+			CCV(ccv, snd_cwnd) = CCV(ccv, snd_max) -
+			ccv->curack + CCV(ccv, t_maxseg);
+		else
+			CCV(ccv, snd_cwnd) = CCV(ccv, snd_ssthresh);
+	}
+}
+
+/*
+ * samkumar: I commented this out because it's not necessary for TCPlp. See the
+ * comment above about not using FreeBSD's mechanism for having multiple
+ * congestion control modules.
+ */
+//DECLARE_CC_MODULE(newreno, &newreno_cc_algo);
diff --git a/third_party/tcplp/bsdtcp/icmp_var.h b/third_party/tcplp/bsdtcp/icmp_var.h
new file mode 100644
index 0000000..2767b82
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/icmp_var.h
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)icmp_var.h	8.1 (Berkeley) 6/10/93
+ * $FreeBSD$
+ */
+
+/*
+ * samkumar: Removed some #if guards and several definitions/declarations that
+ * weren't necessary (and often introduced additional dependencies).
+ */
+
+#ifndef TCPLP_NETINET_ICMP_VAR_H_
+#define TCPLP_NETINET_ICMP_VAR_H_
+/*
+ * Identifiers for ICMP sysctl nodes
+ */
+#define	ICMPCTL_MASKREPL	1	/* allow replies to netmask requests */
+#define	ICMPCTL_STATS		2	/* statistics (read-only) */
+#define ICMPCTL_ICMPLIM		3
+
+#define BANDLIM_UNLIMITED -1
+#define BANDLIM_ICMP_UNREACH 0
+#define BANDLIM_ICMP_ECHO 1
+#define BANDLIM_ICMP_TSTAMP 2
+#define BANDLIM_RST_CLOSEDPORT 3 /* No connection, and no listeners */
+#define BANDLIM_RST_OPENPORT 4   /* No connection, listener */
+#define BANDLIM_ICMP6_UNREACH 5
+#define BANDLIM_SCTP_OOTB 6
+#define BANDLIM_MAX 6
+
+#endif
diff --git a/third_party/tcplp/bsdtcp/ip.h b/third_party/tcplp/bsdtcp/ip.h
new file mode 100644
index 0000000..247c6f8
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/ip.h
@@ -0,0 +1,151 @@
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.
+ * All rights reserved.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)ip.h	8.2 (Berkeley) 6/1/94
+ * $FreeBSD$
+ */
+
+#ifndef TCPLP_NETINET_IP_H_
+#define TCPLP_NETINET_IP_H_
+
+#define	IP_MAXPACKET	65535		/* maximum packet size */
+
+/*
+ * Definitions for IP type of service (ip_tos).
+ */
+#define	IPTOS_LOWDELAY		0x10
+#define	IPTOS_THROUGHPUT	0x08
+#define	IPTOS_RELIABILITY	0x04
+#define	IPTOS_MINCOST		0x02
+
+/*
+ * Definitions for IP precedence (also in ip_tos) (deprecated).
+ */
+#define	IPTOS_PREC_NETCONTROL		IPTOS_DSCP_CS7
+#define	IPTOS_PREC_INTERNETCONTROL	IPTOS_DSCP_CS6
+#define	IPTOS_PREC_CRITIC_ECP		IPTOS_DSCP_CS5
+#define	IPTOS_PREC_FLASHOVERRIDE	IPTOS_DSCP_CS4
+#define	IPTOS_PREC_FLASH		IPTOS_DSCP_CS3
+#define	IPTOS_PREC_IMMEDIATE		IPTOS_DSCP_CS2
+#define	IPTOS_PREC_PRIORITY		IPTOS_DSCP_CS1
+#define	IPTOS_PREC_ROUTINE		IPTOS_DSCP_CS0
+
+/*
+ * Definitions for DiffServ Codepoints as per RFC2474 and RFC5865.
+ */
+#define	IPTOS_DSCP_CS0		0x00
+#define	IPTOS_DSCP_CS1		0x20
+#define	IPTOS_DSCP_AF11		0x28
+#define	IPTOS_DSCP_AF12		0x30
+#define	IPTOS_DSCP_AF13		0x38
+#define	IPTOS_DSCP_CS2		0x40
+#define	IPTOS_DSCP_AF21		0x48
+#define	IPTOS_DSCP_AF22		0x50
+#define	IPTOS_DSCP_AF23		0x58
+#define	IPTOS_DSCP_CS3		0x60
+#define	IPTOS_DSCP_AF31		0x68
+#define	IPTOS_DSCP_AF32		0x70
+#define	IPTOS_DSCP_AF33		0x78
+#define	IPTOS_DSCP_CS4		0x80
+#define	IPTOS_DSCP_AF41		0x88
+#define	IPTOS_DSCP_AF42		0x90
+#define	IPTOS_DSCP_AF43		0x98
+#define	IPTOS_DSCP_CS5		0xa0
+#define	IPTOS_DSCP_VA		0xb0
+#define	IPTOS_DSCP_EF		0xb8
+#define	IPTOS_DSCP_CS6		0xc0
+#define	IPTOS_DSCP_CS7		0xe0
+
+/*
+ * ECN (Explicit Congestion Notification) codepoints in RFC3168 mapped to the
+ * lower 2 bits of the TOS field.
+ */
+#define	IPTOS_ECN_NOTECT	0x00	/* not-ECT */
+#define	IPTOS_ECN_ECT1		0x01	/* ECN-capable transport (1) */
+#define	IPTOS_ECN_ECT0		0x02	/* ECN-capable transport (0) */
+#define	IPTOS_ECN_CE		0x03	/* congestion experienced */
+#define	IPTOS_ECN_MASK		0x03	/* ECN field mask */
+
+/*
+ * Definitions for options.
+ */
+#define	IPOPT_COPIED(o)		((o)&0x80)
+#define	IPOPT_CLASS(o)		((o)&0x60)
+#define	IPOPT_NUMBER(o)		((o)&0x1f)
+
+#define	IPOPT_CONTROL		0x00
+#define	IPOPT_RESERVED1		0x20
+#define	IPOPT_DEBMEAS		0x40
+#define	IPOPT_RESERVED2		0x60
+
+#define	IPOPT_EOL		0		/* end of option list */
+#define	IPOPT_NOP		1		/* no operation */
+
+#define	IPOPT_RR		7		/* record packet route */
+#define	IPOPT_TS		68		/* timestamp */
+#define	IPOPT_SECURITY		130		/* provide s,c,h,tcc */
+#define	IPOPT_LSRR		131		/* loose source route */
+#define	IPOPT_ESO		133		/* extended security */
+#define	IPOPT_CIPSO		134		/* commerical security */
+#define	IPOPT_SATID		136		/* satnet id */
+#define	IPOPT_SSRR		137		/* strict source route */
+#define	IPOPT_RA		148		/* router alert */
+
+/*
+ * Offsets to fields in options other than EOL and NOP.
+ */
+#define	IPOPT_OPTVAL		0		/* option ID */
+#define	IPOPT_OLEN		1		/* option length */
+#define	IPOPT_OFFSET		2		/* offset within option */
+#define	IPOPT_MINOFF		4		/* min value of above */
+
+/* Flag bits for ipt_flg. */
+#define	IPOPT_TS_TSONLY		0		/* timestamps only */
+#define	IPOPT_TS_TSANDADDR	1		/* timestamps and addresses */
+#define	IPOPT_TS_PRESPEC	3		/* specified modules only */
+
+/* Bits for security (not byte swapped). */
+#define	IPOPT_SECUR_UNCLASS	0x0000
+#define	IPOPT_SECUR_CONFID	0xf135
+#define	IPOPT_SECUR_EFTO	0x789a
+#define	IPOPT_SECUR_MMMM	0xbc4d
+#define	IPOPT_SECUR_RESTR	0xaf13
+#define	IPOPT_SECUR_SECRET	0xd788
+#define	IPOPT_SECUR_TOPSECRET	0x6bc5
+
+/*
+ * Internet implementation parameters.
+ */
+#define	MAXTTL		255		/* maximum time to live (seconds) */
+#define	IPDEFTTL	64		/* default ttl, from RFC 1340 */
+#define	IPFRAGTTL	60		/* time to live for frags, slowhz */
+#define	IPTTLDEC	1		/* subtracted when forwarding */
+#define	IP_MSS		576		/* default maximum segment size */
+
+#endif
diff --git a/third_party/tcplp/bsdtcp/ip6.h b/third_party/tcplp/bsdtcp/ip6.h
new file mode 100644
index 0000000..3326d26
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/ip6.h
@@ -0,0 +1,164 @@
+/*	$FreeBSD$	*/
+/*	$KAME: ip6.h,v 1.18 2001/03/29 05:34:30 itojun Exp $	*/
+
+/*-
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * 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 project 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 PROJECT 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 PROJECT 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 (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)ip.h	8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef TCPLP_NETINET_IP6_H_
+#define TCPLP_NETINET_IP6_H_
+
+#include "types.h"
+
+/* samkumar: Copied from netinet/in6.h */
+struct in6_addr {
+	union {
+		uint8_t		__u6_addr8[16];
+		uint16_t	__u6_addr16[8];
+		uint32_t	__u6_addr32[4];
+	} __u6_addr;			/* 128-bit IP6 address */
+} __attribute__((packed)); // added this to allow unaligned access
+#define s6_addr   __u6_addr.__u6_addr8
+
+struct sockaddr_in6 {
+	uint8_t		sin6_len;	/* length of this struct */
+	int			sin6_family;	/* AF_INET6 */
+	uint16_t	sin6_port;	/* Transport layer port # */
+	uint32_t	sin6_flowinfo;	/* IP6 flow information */
+	struct in6_addr	sin6_addr;	/* IP6 address */
+	uint32_t	sin6_scope_id;	/* scope zone index */
+};
+
+/*
+ * Definition for internet protocol version 6.
+ * RFC 2460
+ */
+struct ip6_hdr {
+	union {
+		struct ip6_hdrctl {
+			u_int32_t ip6_un1_flow;	/* 20 bits of flow-ID */
+			u_int16_t ip6_un1_plen;	/* payload length */
+			u_int8_t  ip6_un1_nxt;	/* next header */
+			u_int8_t  ip6_un1_hlim;	/* hop limit */
+		} ip6_un1;
+		u_int8_t ip6_un2_vfc;	/* 4 bits version, top 4 bits class */
+	} ip6_ctlun;
+	struct in6_addr ip6_src;	/* source address */
+	struct in6_addr ip6_dst;	/* destination address */
+} __attribute__((packed));
+
+#define ip6_vfc		ip6_ctlun.ip6_un2_vfc
+#define ip6_flow	ip6_ctlun.ip6_un1.ip6_un1_flow
+#define ip6_plen	ip6_ctlun.ip6_un1.ip6_un1_plen
+#define ip6_nxt		ip6_ctlun.ip6_un1.ip6_un1_nxt
+#define ip6_hlim	ip6_ctlun.ip6_un1.ip6_un1_hlim
+#define ip6_hops	ip6_ctlun.ip6_un1.ip6_un1_hlim
+
+#define IPV6_VERSION		0x60
+#define IPV6_VERSION_MASK	0xf0
+
+/* samkumar: Removed #if guard since ECN is enabled in TCPlp. */
+/* ECN bits proposed by Sally Floyd */
+#define IP6TOS_CE		0x01	/* congestion experienced */
+#define IP6TOS_ECT		0x02	/* ECN-capable transport */
+
+// samkumar: Copied from in6.h
+#define IN6_ARE_ADDR_EQUAL(a, b)			\
+    (memcmp(&(a)->s6_addr[0], &(b)->s6_addr[0], sizeof(struct in6_addr)) == 0)
+
+/* Multicast */
+#define IN6_IS_ADDR_MULTICAST(a)	((a)->s6_addr[0] == 0xff)
+
+/*
+ * Unspecified
+ */
+#define IN6_IS_ADDR_UNSPECIFIED(a)	\
+	((a)->__u6_addr.__u6_addr32[0] == 0 &&	\
+	 (a)->__u6_addr.__u6_addr32[1] == 0 &&	\
+	 (a)->__u6_addr.__u6_addr32[2] == 0 &&	\
+	 (a)->__u6_addr.__u6_addr32[3] == 0)
+
+/*
+ * Loopback
+ */
+#define IN6_IS_ADDR_LOOPBACK(a)		\
+	((a)->__u6_addr.__u6_addr32[0] == 0 &&	\
+	 (a)->__u6_addr.__u6_addr32[1] == 0 &&	\
+	 (a)->__u6_addr.__u6_addr32[2] == 0 &&	\
+	 (a)->__u6_addr.__u6_addr32[3] == ntohl(1))
+
+/*
+ * Unicast Scope
+ * Note that we must check topmost 10 bits only, not 16 bits (see RFC2373).
+ */
+#define IN6_IS_ADDR_LINKLOCAL(a)	\
+	(((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0x80))
+#define IN6_IS_ADDR_SITELOCAL(a)	\
+	(((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0))
+
+/*
+ * Mapped
+ */
+
+#define IN6_IS_ADDR_V4MAPPED(a)		      \
+	((a)->__u6_addr.__u6_addr32[0] == 0 &&	\
+	 (a)->__u6_addr.__u6_addr32[1] == 0 &&	\
+	 (a)->__u6_addr.__u6_addr32[2] == ntohl(0x0000ffff))
+
+#endif /* not _NETINET_IP6_H_ */
diff --git a/third_party/tcplp/bsdtcp/sys/queue.h b/third_party/tcplp/bsdtcp/sys/queue.h
new file mode 100644
index 0000000..4ed5c7c
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/sys/queue.h
@@ -0,0 +1,754 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)queue.h	8.5 (Berkeley) 8/20/94
+ * $FreeBSD$
+ */
+
+#ifndef TCPLP_SYS_QUEUE_H_
+#define	TCPLP_SYS_QUEUE_H_
+
+/* samkumar: Removing this, as it adds yet another dependency. */
+//#include <sys/cdefs.h>
+
+/*
+ * This file defines four types of data structures: singly-linked lists,
+ * singly-linked tail queues, lists and tail queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction.  Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may be traversed in either direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ *				SLIST	LIST	STAILQ	TAILQ
+ * _HEAD			+	+	+	+
+ * _CLASS_HEAD			+	+	+	+
+ * _HEAD_INITIALIZER		+	+	+	+
+ * _ENTRY			+	+	+	+
+ * _CLASS_ENTRY			+	+	+	+
+ * _INIT			+	+	+	+
+ * _EMPTY			+	+	+	+
+ * _FIRST			+	+	+	+
+ * _NEXT			+	+	+	+
+ * _PREV			-	+	-	+
+ * _LAST			-	-	+	+
+ * _FOREACH			+	+	+	+
+ * _FOREACH_FROM		+	+	+	+
+ * _FOREACH_SAFE		+	+	+	+
+ * _FOREACH_FROM_SAFE		+	+	+	+
+ * _FOREACH_REVERSE		-	-	-	+
+ * _FOREACH_REVERSE_FROM	-	-	-	+
+ * _FOREACH_REVERSE_SAFE	-	-	-	+
+ * _FOREACH_REVERSE_FROM_SAFE	-	-	-	+
+ * _INSERT_HEAD			+	+	+	+
+ * _INSERT_BEFORE		-	+	-	+
+ * _INSERT_AFTER		+	+	+	+
+ * _INSERT_TAIL			-	-	+	+
+ * _CONCAT			-	-	+	+
+ * _REMOVE_AFTER		+	-	+	-
+ * _REMOVE_HEAD			+	-	+	-
+ * _REMOVE			+	+	+	+
+ * _SWAP			+	+	+	+
+ *
+ */
+#ifdef QUEUE_MACRO_DEBUG
+/* Store the last 2 places the queue element or head was altered */
+struct qm_trace {
+	unsigned long	 lastline;
+	unsigned long	 prevline;
+	const char	*lastfile;
+	const char	*prevfile;
+};
+
+#define	TRACEBUF	struct qm_trace trace;
+#define	TRACEBUF_INITIALIZER	{ __LINE__, 0, __FILE__, NULL } ,
+#define	TRASHIT(x)	do {(x) = (void *)-1;} while (0)
+#define	QMD_SAVELINK(name, link)	void **name = (void *)&(link)
+
+#define	QMD_TRACE_HEAD(head) do {					\
+	(head)->trace.prevline = (head)->trace.lastline;		\
+	(head)->trace.prevfile = (head)->trace.lastfile;		\
+	(head)->trace.lastline = __LINE__;				\
+	(head)->trace.lastfile = __FILE__;				\
+} while (0)
+
+#define	QMD_TRACE_ELEM(elem) do {					\
+	(elem)->trace.prevline = (elem)->trace.lastline;		\
+	(elem)->trace.prevfile = (elem)->trace.lastfile;		\
+	(elem)->trace.lastline = __LINE__;				\
+	(elem)->trace.lastfile = __FILE__;				\
+} while (0)
+
+#else
+#define	QMD_TRACE_ELEM(elem)
+#define	QMD_TRACE_HEAD(head)
+#define	QMD_SAVELINK(name, link)
+#define	TRACEBUF
+#define	TRACEBUF_INITIALIZER
+#define	TRASHIT(x)
+#endif	/* QUEUE_MACRO_DEBUG */
+
+#ifdef __cplusplus
+/*
+ * In C++ there can be structure lists and class lists:
+ */
+#define	QUEUE_TYPEOF(type) type
+#else
+#define	QUEUE_TYPEOF(type) struct type
+#endif
+
+/*
+ * Singly-linked List declarations.
+ */
+#define	SLIST_HEAD(name, type)						\
+struct name {								\
+	struct type *slh_first;	/* first element */			\
+}
+
+#define	SLIST_CLASS_HEAD(name, type)					\
+struct name {								\
+	class type *slh_first;	/* first element */			\
+}
+
+#define	SLIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define	SLIST_ENTRY(type)						\
+struct {								\
+	struct type *sle_next;	/* next element */			\
+}
+
+#define	SLIST_CLASS_ENTRY(type)						\
+struct {								\
+	class type *sle_next;		/* next element */		\
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define	SLIST_EMPTY(head)	((head)->slh_first == NULL)
+
+#define	SLIST_FIRST(head)	((head)->slh_first)
+
+#define	SLIST_FOREACH(var, head, field)					\
+	for ((var) = SLIST_FIRST((head));				\
+	    (var);							\
+	    (var) = SLIST_NEXT((var), field))
+
+#define	SLIST_FOREACH_FROM(var, head, field)				\
+	for ((var) = ((var) ? (var) : SLIST_FIRST((head)));		\
+	    (var);							\
+	    (var) = SLIST_NEXT((var), field))
+
+#define	SLIST_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = SLIST_FIRST((head));				\
+	    (var) && ((tvar) = SLIST_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	SLIST_FOREACH_FROM_SAFE(var, head, field, tvar)			\
+	for ((var) = ((var) ? (var) : SLIST_FIRST((head)));		\
+	    (var) && ((tvar) = SLIST_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	SLIST_FOREACH_PREVPTR(var, varp, head, field)			\
+	for ((varp) = &SLIST_FIRST((head));				\
+	    ((var) = *(varp)) != NULL;					\
+	    (varp) = &SLIST_NEXT((var), field))
+
+#define	SLIST_INIT(head) do {						\
+	SLIST_FIRST((head)) = NULL;					\
+} while (0)
+
+#define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
+	SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);	\
+	SLIST_NEXT((slistelm), field) = (elm);				\
+} while (0)
+
+#define	SLIST_INSERT_HEAD(head, elm, field) do {			\
+	SLIST_NEXT((elm), field) = SLIST_FIRST((head));			\
+	SLIST_FIRST((head)) = (elm);					\
+} while (0)
+
+#define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
+
+#define	SLIST_REMOVE(head, elm, type, field) do {			\
+	QMD_SAVELINK(oldnext, (elm)->field.sle_next);			\
+	if (SLIST_FIRST((head)) == (elm)) {				\
+		SLIST_REMOVE_HEAD((head), field);			\
+	}								\
+	else {								\
+		QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head);		\
+		while (SLIST_NEXT(curelm, field) != (elm))		\
+			curelm = SLIST_NEXT(curelm, field);		\
+		SLIST_REMOVE_AFTER(curelm, field);			\
+	}								\
+	TRASHIT(*oldnext);						\
+} while (0)
+
+#define SLIST_REMOVE_AFTER(elm, field) do {				\
+	SLIST_NEXT(elm, field) =					\
+	    SLIST_NEXT(SLIST_NEXT(elm, field), field);			\
+} while (0)
+
+#define	SLIST_REMOVE_HEAD(head, field) do {				\
+	SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);	\
+} while (0)
+
+#define SLIST_SWAP(head1, head2, type) do {				\
+	QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1);		\
+	SLIST_FIRST(head1) = SLIST_FIRST(head2);			\
+	SLIST_FIRST(head2) = swap_first;				\
+} while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define	STAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *stqh_first;/* first element */			\
+	struct type **stqh_last;/* addr of last next element */		\
+}
+
+#define	STAILQ_CLASS_HEAD(name, type)					\
+struct name {								\
+	class type *stqh_first;	/* first element */			\
+	class type **stqh_last;	/* addr of last next element */		\
+}
+
+#define	STAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).stqh_first }
+
+#define	STAILQ_ENTRY(type)						\
+struct {								\
+	struct type *stqe_next;	/* next element */			\
+}
+
+#define	STAILQ_CLASS_ENTRY(type)					\
+struct {								\
+	class type *stqe_next;	/* next element */			\
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define	STAILQ_CONCAT(head1, head2) do {				\
+	if (!STAILQ_EMPTY((head2))) {					\
+		*(head1)->stqh_last = (head2)->stqh_first;		\
+		(head1)->stqh_last = (head2)->stqh_last;		\
+		STAILQ_INIT((head2));					\
+	}								\
+} while (0)
+
+#define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
+
+#define	STAILQ_FIRST(head)	((head)->stqh_first)
+
+#define	STAILQ_FOREACH(var, head, field)				\
+	for((var) = STAILQ_FIRST((head));				\
+	   (var);							\
+	   (var) = STAILQ_NEXT((var), field))
+
+#define	STAILQ_FOREACH_FROM(var, head, field)				\
+	for ((var) = ((var) ? (var) : STAILQ_FIRST((head)));		\
+	   (var);							\
+	   (var) = STAILQ_NEXT((var), field))
+
+#define	STAILQ_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = STAILQ_FIRST((head));				\
+	    (var) && ((tvar) = STAILQ_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar)		\
+	for ((var) = ((var) ? (var) : STAILQ_FIRST((head)));		\
+	    (var) && ((tvar) = STAILQ_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	STAILQ_INIT(head) do {						\
+	STAILQ_FIRST((head)) = NULL;					\
+	(head)->stqh_last = &STAILQ_FIRST((head));			\
+} while (0)
+
+#define	STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\
+	if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
+		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
+	STAILQ_NEXT((tqelm), field) = (elm);				\
+} while (0)
+
+#define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL)	\
+		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
+	STAILQ_FIRST((head)) = (elm);					\
+} while (0)
+
+#define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
+	STAILQ_NEXT((elm), field) = NULL;				\
+	*(head)->stqh_last = (elm);					\
+	(head)->stqh_last = &STAILQ_NEXT((elm), field);			\
+} while (0)
+
+#define	STAILQ_LAST(head, type, field)				\
+	(STAILQ_EMPTY((head)) ? NULL :				\
+	    __containerof((head)->stqh_last,			\
+	    QUEUE_TYPEOF(type), field.stqe_next))
+
+#define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
+
+#define	STAILQ_REMOVE(head, elm, type, field) do {			\
+	QMD_SAVELINK(oldnext, (elm)->field.stqe_next);			\
+	if (STAILQ_FIRST((head)) == (elm)) {				\
+		STAILQ_REMOVE_HEAD((head), field);			\
+	}								\
+	else {								\
+		QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head);	\
+		while (STAILQ_NEXT(curelm, field) != (elm))		\
+			curelm = STAILQ_NEXT(curelm, field);		\
+		STAILQ_REMOVE_AFTER(head, curelm, field);		\
+	}								\
+	TRASHIT(*oldnext);						\
+} while (0)
+
+#define STAILQ_REMOVE_AFTER(head, elm, field) do {			\
+	if ((STAILQ_NEXT(elm, field) =					\
+	     STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL)	\
+		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
+} while (0)
+
+#define	STAILQ_REMOVE_HEAD(head, field) do {				\
+	if ((STAILQ_FIRST((head)) =					\
+	     STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)		\
+		(head)->stqh_last = &STAILQ_FIRST((head));		\
+} while (0)
+
+#define STAILQ_SWAP(head1, head2, type) do {				\
+	QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1);		\
+	QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last;		\
+	STAILQ_FIRST(head1) = STAILQ_FIRST(head2);			\
+	(head1)->stqh_last = (head2)->stqh_last;			\
+	STAILQ_FIRST(head2) = swap_first;				\
+	(head2)->stqh_last = swap_last;					\
+	if (STAILQ_EMPTY(head1))					\
+		(head1)->stqh_last = &STAILQ_FIRST(head1);		\
+	if (STAILQ_EMPTY(head2))					\
+		(head2)->stqh_last = &STAILQ_FIRST(head2);		\
+} while (0)
+
+
+/*
+ * List declarations.
+ */
+#define	LIST_HEAD(name, type)						\
+struct name {								\
+	struct type *lh_first;	/* first element */			\
+}
+
+#define	LIST_CLASS_HEAD(name, type)					\
+struct name {								\
+	class type *lh_first;	/* first element */			\
+}
+
+#define	LIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define	LIST_ENTRY(type)						\
+struct {								\
+	struct type *le_next;	/* next element */			\
+	struct type **le_prev;	/* address of previous next element */	\
+}
+
+#define	LIST_CLASS_ENTRY(type)						\
+struct {								\
+	class type *le_next;	/* next element */			\
+	class type **le_prev;	/* address of previous next element */	\
+}
+
+/*
+ * List functions.
+ */
+
+#if (defined(_KERNEL) && defined(INVARIANTS))
+#define	QMD_LIST_CHECK_HEAD(head, field) do {				\
+	if (LIST_FIRST((head)) != NULL &&				\
+	    LIST_FIRST((head))->field.le_prev !=			\
+	     &LIST_FIRST((head)))					\
+		panic("Bad list head %p first->prev != head", (head));	\
+} while (0)
+
+#define	QMD_LIST_CHECK_NEXT(elm, field) do {				\
+	if (LIST_NEXT((elm), field) != NULL &&				\
+	    LIST_NEXT((elm), field)->field.le_prev !=			\
+	     &((elm)->field.le_next))					\
+	     	panic("Bad link elm %p next->prev != elm", (elm));	\
+} while (0)
+
+#define	QMD_LIST_CHECK_PREV(elm, field) do {				\
+	if (*(elm)->field.le_prev != (elm))				\
+		panic("Bad link elm %p prev->next != elm", (elm));	\
+} while (0)
+#else
+#define	QMD_LIST_CHECK_HEAD(head, field)
+#define	QMD_LIST_CHECK_NEXT(elm, field)
+#define	QMD_LIST_CHECK_PREV(elm, field)
+#endif /* (_KERNEL && INVARIANTS) */
+
+#define	LIST_EMPTY(head)	((head)->lh_first == NULL)
+
+#define	LIST_FIRST(head)	((head)->lh_first)
+
+#define	LIST_FOREACH(var, head, field)					\
+	for ((var) = LIST_FIRST((head));				\
+	    (var);							\
+	    (var) = LIST_NEXT((var), field))
+
+#define	LIST_FOREACH_FROM(var, head, field)				\
+	for ((var) = ((var) ? (var) : LIST_FIRST((head)));		\
+	    (var);							\
+	    (var) = LIST_NEXT((var), field))
+
+#define	LIST_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = LIST_FIRST((head));				\
+	    (var) && ((tvar) = LIST_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	LIST_FOREACH_FROM_SAFE(var, head, field, tvar)			\
+	for ((var) = ((var) ? (var) : LIST_FIRST((head)));		\
+	    (var) && ((tvar) = LIST_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	LIST_INIT(head) do {						\
+	LIST_FIRST((head)) = NULL;					\
+} while (0)
+
+#define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
+	QMD_LIST_CHECK_NEXT(listelm, field);				\
+	if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
+		LIST_NEXT((listelm), field)->field.le_prev =		\
+		    &LIST_NEXT((elm), field);				\
+	LIST_NEXT((listelm), field) = (elm);				\
+	(elm)->field.le_prev = &LIST_NEXT((listelm), field);		\
+} while (0)
+
+#define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
+	QMD_LIST_CHECK_PREV(listelm, field);				\
+	(elm)->field.le_prev = (listelm)->field.le_prev;		\
+	LIST_NEXT((elm), field) = (listelm);				\
+	*(listelm)->field.le_prev = (elm);				\
+	(listelm)->field.le_prev = &LIST_NEXT((elm), field);		\
+} while (0)
+
+#define	LIST_INSERT_HEAD(head, elm, field) do {				\
+	QMD_LIST_CHECK_HEAD((head), field);				\
+	if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)	\
+		LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
+	LIST_FIRST((head)) = (elm);					\
+	(elm)->field.le_prev = &LIST_FIRST((head));			\
+} while (0)
+
+#define	LIST_NEXT(elm, field)	((elm)->field.le_next)
+
+#define	LIST_PREV(elm, head, type, field)			\
+	((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL :	\
+	    __containerof((elm)->field.le_prev,			\
+	    QUEUE_TYPEOF(type), field.le_next))
+
+#define	LIST_REMOVE(elm, field) do {					\
+	QMD_SAVELINK(oldnext, (elm)->field.le_next);			\
+	QMD_SAVELINK(oldprev, (elm)->field.le_prev);			\
+	QMD_LIST_CHECK_NEXT(elm, field);				\
+	QMD_LIST_CHECK_PREV(elm, field);				\
+	if (LIST_NEXT((elm), field) != NULL)				\
+		LIST_NEXT((elm), field)->field.le_prev = 		\
+		    (elm)->field.le_prev;				\
+	*(elm)->field.le_prev = LIST_NEXT((elm), field);		\
+	TRASHIT(*oldnext);						\
+	TRASHIT(*oldprev);						\
+} while (0)
+
+#define LIST_SWAP(head1, head2, type, field) do {			\
+	QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1);		\
+	LIST_FIRST((head1)) = LIST_FIRST((head2));			\
+	LIST_FIRST((head2)) = swap_tmp;					\
+	if ((swap_tmp = LIST_FIRST((head1))) != NULL)			\
+		swap_tmp->field.le_prev = &LIST_FIRST((head1));		\
+	if ((swap_tmp = LIST_FIRST((head2))) != NULL)			\
+		swap_tmp->field.le_prev = &LIST_FIRST((head2));		\
+} while (0)
+
+/*
+ * Tail queue declarations.
+ */
+#define	TAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *tqh_first;	/* first element */			\
+	struct type **tqh_last;	/* addr of last next element */		\
+	TRACEBUF							\
+}
+
+#define	TAILQ_CLASS_HEAD(name, type)					\
+struct name {								\
+	class type *tqh_first;	/* first element */			\
+	class type **tqh_last;	/* addr of last next element */		\
+	TRACEBUF							\
+}
+
+#define	TAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
+
+#define	TAILQ_ENTRY(type)						\
+struct {								\
+	struct type *tqe_next;	/* next element */			\
+	struct type **tqe_prev;	/* address of previous next element */	\
+	TRACEBUF							\
+}
+
+#define	TAILQ_CLASS_ENTRY(type)						\
+struct {								\
+	class type *tqe_next;	/* next element */			\
+	class type **tqe_prev;	/* address of previous next element */	\
+	TRACEBUF							\
+}
+
+/*
+ * Tail queue functions.
+ */
+#if (defined(_KERNEL) && defined(INVARIANTS))
+#define	QMD_TAILQ_CHECK_HEAD(head, field) do {				\
+	if (!TAILQ_EMPTY(head) &&					\
+	    TAILQ_FIRST((head))->field.tqe_prev !=			\
+	     &TAILQ_FIRST((head)))					\
+		panic("Bad tailq head %p first->prev != head", (head));	\
+} while (0)
+
+#define	QMD_TAILQ_CHECK_TAIL(head, field) do {				\
+	if (*(head)->tqh_last != NULL)					\
+	    	panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); 	\
+} while (0)
+
+#define	QMD_TAILQ_CHECK_NEXT(elm, field) do {				\
+	if (TAILQ_NEXT((elm), field) != NULL &&				\
+	    TAILQ_NEXT((elm), field)->field.tqe_prev !=			\
+	     &((elm)->field.tqe_next))					\
+		panic("Bad link elm %p next->prev != elm", (elm));	\
+} while (0)
+
+#define	QMD_TAILQ_CHECK_PREV(elm, field) do {				\
+	if (*(elm)->field.tqe_prev != (elm))				\
+		panic("Bad link elm %p prev->next != elm", (elm));	\
+} while (0)
+#else
+#define	QMD_TAILQ_CHECK_HEAD(head, field)
+#define	QMD_TAILQ_CHECK_TAIL(head, headname)
+#define	QMD_TAILQ_CHECK_NEXT(elm, field)
+#define	QMD_TAILQ_CHECK_PREV(elm, field)
+#endif /* (_KERNEL && INVARIANTS) */
+
+#define	TAILQ_CONCAT(head1, head2, field) do {				\
+	if (!TAILQ_EMPTY(head2)) {					\
+		*(head1)->tqh_last = (head2)->tqh_first;		\
+		(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last;	\
+		(head1)->tqh_last = (head2)->tqh_last;			\
+		TAILQ_INIT((head2));					\
+		QMD_TRACE_HEAD(head1);					\
+		QMD_TRACE_HEAD(head2);					\
+	}								\
+} while (0)
+
+#define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)
+
+#define	TAILQ_FIRST(head)	((head)->tqh_first)
+
+#define	TAILQ_FOREACH(var, head, field)					\
+	for ((var) = TAILQ_FIRST((head));				\
+	    (var);							\
+	    (var) = TAILQ_NEXT((var), field))
+
+#define	TAILQ_FOREACH_FROM(var, head, field)				\
+	for ((var) = ((var) ? (var) : TAILQ_FIRST((head)));		\
+	    (var);							\
+	    (var) = TAILQ_NEXT((var), field))
+
+#define	TAILQ_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = TAILQ_FIRST((head));				\
+	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar)			\
+	for ((var) = ((var) ? (var) : TAILQ_FIRST((head)));		\
+	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
+	for ((var) = TAILQ_LAST((head), headname);			\
+	    (var);							\
+	    (var) = TAILQ_PREV((var), headname, field))
+
+#define	TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field)		\
+	for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname));	\
+	    (var);							\
+	    (var) = TAILQ_PREV((var), headname, field))
+
+#define	TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)	\
+	for ((var) = TAILQ_LAST((head), headname);			\
+	    (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1);	\
+	    (var) = (tvar))
+
+#define	TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \
+	for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname));	\
+	    (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1);	\
+	    (var) = (tvar))
+
+#define	TAILQ_INIT(head) do {						\
+	TAILQ_FIRST((head)) = NULL;					\
+	(head)->tqh_last = &TAILQ_FIRST((head));			\
+	QMD_TRACE_HEAD(head);						\
+} while (0)
+
+#define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	QMD_TAILQ_CHECK_NEXT(listelm, field);				\
+	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
+		    &TAILQ_NEXT((elm), field);				\
+	else {								\
+		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
+		QMD_TRACE_HEAD(head);					\
+	}								\
+	TAILQ_NEXT((listelm), field) = (elm);				\
+	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);		\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+	QMD_TRACE_ELEM(&(listelm)->field);				\
+} while (0)
+
+#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
+	QMD_TAILQ_CHECK_PREV(listelm, field);				\
+	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
+	TAILQ_NEXT((elm), field) = (listelm);				\
+	*(listelm)->field.tqe_prev = (elm);				\
+	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);		\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+	QMD_TRACE_ELEM(&(listelm)->field);				\
+} while (0)
+
+#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
+	QMD_TAILQ_CHECK_HEAD(head, field);				\
+	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
+		TAILQ_FIRST((head))->field.tqe_prev =			\
+		    &TAILQ_NEXT((elm), field);				\
+	else								\
+		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
+	TAILQ_FIRST((head)) = (elm);					\
+	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
+	QMD_TRACE_HEAD(head);						\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+} while (0)
+
+#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
+	QMD_TAILQ_CHECK_TAIL(head, field);				\
+	TAILQ_NEXT((elm), field) = NULL;				\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
+	QMD_TRACE_HEAD(head);						\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+} while (0)
+
+#define	TAILQ_LAST(head, headname)					\
+	(*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define	TAILQ_PREV(elm, headname, field)				\
+	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#define	TAILQ_REMOVE(head, elm, field) do {				\
+	QMD_SAVELINK(oldnext, (elm)->field.tqe_next);			\
+	QMD_SAVELINK(oldprev, (elm)->field.tqe_prev);			\
+	QMD_TAILQ_CHECK_NEXT(elm, field);				\
+	QMD_TAILQ_CHECK_PREV(elm, field);				\
+	if ((TAILQ_NEXT((elm), field)) != NULL)				\
+		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
+		    (elm)->field.tqe_prev;				\
+	else {								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+		QMD_TRACE_HEAD(head);					\
+	}								\
+	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
+	TRASHIT(*oldnext);						\
+	TRASHIT(*oldprev);						\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+} while (0)
+
+#define TAILQ_SWAP(head1, head2, type, field) do {			\
+	QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first;		\
+	QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last;		\
+	(head1)->tqh_first = (head2)->tqh_first;			\
+	(head1)->tqh_last = (head2)->tqh_last;				\
+	(head2)->tqh_first = swap_first;				\
+	(head2)->tqh_last = swap_last;					\
+	if ((swap_first = (head1)->tqh_first) != NULL)			\
+		swap_first->field.tqe_prev = &(head1)->tqh_first;	\
+	else								\
+		(head1)->tqh_last = &(head1)->tqh_first;		\
+	if ((swap_first = (head2)->tqh_first) != NULL)			\
+		swap_first->field.tqe_prev = &(head2)->tqh_first;	\
+	else								\
+		(head2)->tqh_last = &(head2)->tqh_first;		\
+} while (0)
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/third_party/tcplp/bsdtcp/tcp.h b/third_party/tcplp/bsdtcp/tcp.h
new file mode 100644
index 0000000..1faf353
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/tcp.h
@@ -0,0 +1,201 @@
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)tcp.h	8.1 (Berkeley) 6/10/93
+ * $FreeBSD$
+ */
+
+/*
+ * samkumar: In one instance (in struct tcphdr), where there are Big Endian
+ * and Little Endian alternatives for ordering two fields, I hardcoded the
+ * Little Endian alternative. If ever we port this to a Big Endian platform,
+ * we should look at that very closely, and consider rewriting it.
+ */
+
+#ifndef TCPLP_NETINET_TCP_H_
+#define TCPLP_NETINET_TCP_H_
+
+#include <stdint.h>
+#include <stdio.h>
+
+#define KASSERT(COND, MSG) if (!(COND)) tcplp_sys_panic MSG
+
+typedef	uint32_t tcp_seq;
+
+#define tcp6_seq	tcp_seq	/* for KAME src sync over BSD*'s */
+#define tcp6hdr		tcphdr	/* for KAME src sync over BSD*'s */
+
+/*
+ * TCP header.
+ * Per RFC 793, September, 1981.
+ */
+struct tcphdr {
+	uint16_t	th_sport;		/* source port */
+	uint16_t	th_dport;		/* destination port */
+	tcp_seq	th_seq;			/* sequence number */
+	tcp_seq	th_ack;			/* acknowledgement number */
+
+	/*
+	 * samkumar: The original FreeBSD code used bit fields for the offset and
+	 * unused bits, within this byte. I've rewritten it to avoid the use of
+	 * bit fields, so that the code is more portable. The original code, which
+	 * defined the order of bit fields based on the platform's endianness, is
+	 * included below, commented out using "#if 0".
+	 */
+	uint8_t th_off_x2; /* data offset and unused bits */
+#define	TH_OFF_SHIFT	4
+
+#if 0
+#if BYTE_ORDER == LITTLE_ENDIAN
+	uint8_t	th_x2:4,		/* (unused) */
+		th_off:4;		/* data offset */
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+	uint8_t	th_off:4,		/* data offset */
+		th_x2:4;		/* (unused) */
+#endif
+#endif
+
+	uint8_t	th_flags;
+#define	TH_FIN	0x01
+#define	TH_SYN	0x02
+#define	TH_RST	0x04
+#define	TH_PUSH	0x08
+#define	TH_ACK	0x10
+#define	TH_URG	0x20
+#define	TH_ECE	0x40
+#define	TH_CWR	0x80
+#define	TH_FLAGS	(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG|TH_ECE|TH_CWR)
+#define	PRINT_TH_FLAGS	"\20\1FIN\2SYN\3RST\4PUSH\5ACK\6URG\7ECE\10CWR"
+
+	uint16_t	th_win;			/* window */
+	uint16_t	th_sum;			/* checksum */
+	uint16_t	th_urp;			/* urgent pointer */
+};
+
+#define	TCPOPT_EOL		0
+#define	   TCPOLEN_EOL			1
+#define	TCPOPT_PAD		0		/* padding after EOL */
+#define	   TCPOLEN_PAD			1
+#define	TCPOPT_NOP		1
+#define	   TCPOLEN_NOP			1
+#define	TCPOPT_MAXSEG		2
+#define    TCPOLEN_MAXSEG		4
+#define TCPOPT_WINDOW		3
+#define    TCPOLEN_WINDOW		3
+#define TCPOPT_SACK_PERMITTED	4
+#define    TCPOLEN_SACK_PERMITTED	2
+#define TCPOPT_SACK		5
+#define	   TCPOLEN_SACKHDR		2
+#define    TCPOLEN_SACK			8	/* 2*sizeof(tcp_seq) */
+#define TCPOPT_TIMESTAMP	8
+#define    TCPOLEN_TIMESTAMP		10
+#define    TCPOLEN_TSTAMP_APPA		(TCPOLEN_TIMESTAMP+2) /* appendix A */
+#define	TCPOPT_SIGNATURE	19		/* Keyed MD5: RFC 2385 */
+#define	   TCPOLEN_SIGNATURE		18
+
+/* Miscellaneous constants */
+#define	MAX_SACK_BLKS	6	/* Max # SACK blocks stored at receiver side */
+#define	TCP_MAX_SACK	4	/* MAX # SACKs sent in any segment */
+
+
+/*
+ * The default maximum segment size (MSS) to be used for new TCP connections
+ * when path MTU discovery is not enabled.
+ *
+ * RFC879 derives the default MSS from the largest datagram size hosts are
+ * minimally required to handle directly or through IP reassembly minus the
+ * size of the IP and TCP header.  With IPv6 the minimum MTU is specified
+ * in RFC2460.
+ *
+ * For IPv4 the MSS is 576 - sizeof(struct tcpiphdr)
+ * For IPv6 the MSS is IPV6_MMTU - sizeof(struct ip6_hdr) - sizeof(struct tcphdr)
+ *
+ * We use explicit numerical definition here to avoid header pollution.
+ */
+#define	TCP_MSS		536
+#define	TCP6_MSS	1220
+
+/*
+ * Limit the lowest MSS we accept for path MTU discovery and the TCP SYN MSS
+ * option.  Allowing low values of MSS can consume significant resources and
+ * be used to mount a resource exhaustion attack.
+ * Connections requesting lower MSS values will be rounded up to this value
+ * and the IP_DF flag will be cleared to allow fragmentation along the path.
+ *
+ * See tcp_subr.c tcp_minmss SYSCTL declaration for more comments.  Setting
+ * it to "0" disables the minmss check.
+ *
+ * The default value is fine for TCP across the Internet's smallest official
+ * link MTU (256 bytes for AX.25 packet radio).  However, a connection is very
+ * unlikely to come across such low MTU interfaces these days (anno domini 2003).
+ */
+#define	TCP_MINMSS 216
+
+#define	TCP_MAXWIN	65535	/* largest value for (unscaled) window */
+#define	TTCP_CLIENT_SND_WND	4096	/* dflt send window for T/TCP client */
+
+#define TCP_MAX_WINSHIFT	14	/* maximum window shift */
+
+#define TCP_MAXBURST		4	/* maximum segments in a burst */
+
+#define TCP_MAXHLEN	(0xf<<2)	/* max length of header in bytes */
+#define TCP_MAXOLEN	(TCP_MAXHLEN - sizeof(struct tcphdr))
+					/* max space left for options */
+
+/*
+ * User-settable options (used with setsockopt).  These are discrete
+ * values and are not masked together.  Some values appear to be
+ * bitmasks for historical reasons.
+ */
+#define	TCP_NODELAY	1	/* don't delay send to coalesce packets */
+#define	TCP_MAXSEG	2	/* set maximum segment size */
+#define TCP_NOPUSH	4	/* don't push last block of write */
+#define TCP_NOOPT	8	/* don't use TCP options */
+#define TCP_MD5SIG	16	/* use MD5 digests (RFC2385) */
+#define	TCP_INFO	32	/* retrieve tcp_info structure */
+#define	TCP_CONGESTION	64	/* get/set congestion control algorithm */
+#define	TCP_KEEPINIT	128	/* N, time to establish connection */
+#define	TCP_KEEPIDLE	256	/* L,N,X start keeplives after this period */
+#define	TCP_KEEPINTVL	512	/* L,N interval between keepalives */
+#define	TCP_KEEPCNT	1024	/* L,N number of keepalives before close */
+#define	TCP_PCAP_OUT	2048	/* number of output packets to keep */
+#define	TCP_PCAP_IN	4096	/* number of input packets to keep */
+
+/* Start of reserved space for third-party user-settable options. */
+#define	TCP_VENDOR	SO_VENDOR
+
+#define	TCP_CA_NAME_MAX	16	/* max congestion control name length */
+
+#define	TCPI_OPT_TIMESTAMPS	0x01
+#define	TCPI_OPT_SACK		0x02
+#define	TCPI_OPT_WSCALE		0x04
+#define	TCPI_OPT_ECN		0x08
+#define	TCPI_OPT_TOE		0x10
+
+#endif /* !_NETINET_TCP_H_ */
diff --git a/third_party/tcplp/bsdtcp/tcp_const.h b/third_party/tcplp/bsdtcp/tcp_const.h
new file mode 100644
index 0000000..8516438
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/tcp_const.h
@@ -0,0 +1,112 @@
+/*
+ *  Copyright (c) 2018, Sam Kumar <samkumar@cs.berkeley.edu>
+ *  Copyright (c) 2018, University of California, Berkeley
+ *  All rights reserved.
+ *
+ *  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, 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.
+ */
+
+/*
+ * samkumar: I created this file to store many of the constants shared by the
+ * various files in the FreeBSD protocol logic. The original variables were
+ * often virtualized ("V_"-prefixed) variables. I've changed the definitions to
+ * be enumerations rather than globals, to save some memory. These variables
+ * often serve to enable, disable, or configure certain TCP-related features.
+ */
+
+#ifndef TCPLP_TCP_CONST_H_
+#define TCPLP_TCP_CONST_H_
+
+#include "../tcplp.h"
+
+#include "tcp_var.h"
+#include "tcp_timer.h"
+
+/*
+ * samkumar: these are TCPlp-specific constants that I added. They were not
+ * present in the FreeBSD-derived code.
+ */
+
+#define FRAMES_PER_SEG 5
+#define FRAMECAP_6LOWPAN (122 - 11 - 5)
+#define IP6HDR_SIZE (2 + 1 + 1 + 16 + 16) // IPHC header (2) + Next header (1) + Hop count (1) + Dest. addr (16) + Src. addr (16)
+#define MSS_6LOWPAN ((FRAMES_PER_SEG * FRAMECAP_6LOWPAN) - IP6HDR_SIZE - sizeof(struct tcphdr))
+
+/*
+ * samkumar: The remaining constants were present in the original FreeBSD code,
+ * but I set their values.
+ */
+
+#define hz 1000 // number of ticks per second, assuming millisecond ticks
+
+enum tcp_input_consts {
+	tcp_keepcnt = TCPTV_KEEPCNT,
+	tcp_fast_finwait2_recycle = 0,
+	tcprexmtthresh = 3,
+	V_drop_synfin = 0,
+	V_tcp_do_ecn = 1,
+	V_tcp_ecn_maxretries = 3,
+	V_tcp_do_rfc3042 = 1,
+	V_path_mtu_discovery = 0,
+	V_tcp_delack_enabled = 1,
+	V_tcp_initcwnd_segments = 0,
+	V_tcp_do_rfc3390 = 0,
+	V_tcp_abc_l_var = 2 // this is what was in the original tcp_input.c
+};
+
+enum tcp_subr_consts {
+	tcp_delacktime = TCPTV_DELACK,
+	tcp_keepinit = TCPTV_KEEP_INIT,
+	tcp_keepidle = TCPTV_KEEP_IDLE,
+	tcp_keepintvl = TCPTV_KEEPINTVL,
+	tcp_maxpersistidle = TCPTV_KEEP_IDLE,
+	tcp_msl = TCPTV_MSL,
+	tcp_rexmit_slop = TCPTV_CPU_VAR,
+	tcp_finwait2_timeout = TCPTV_FINWAIT2_TIMEOUT,
+
+	V_tcp_do_rfc1323 = 1,
+	V_tcp_v6mssdflt = MSS_6LOWPAN,
+	/* Normally, this is used to prevent DoS attacks by sending tiny MSS values in the options. */
+	V_tcp_minmss = TCP_MAXOLEN + 1, // Must have enough space for TCP options, and one more byte for data. Default is 216.
+	V_tcp_do_sack = 1
+};
+
+enum tcp_timer_consts {
+//	V_tcp_v6pmtud_blackhole_mss = FRAMECAP_6LOWPAN - sizeof(struct ip6_hdr) - sizeof(struct tcphdr), // Doesn't matter unless blackhole_detect is 1.
+	tcp_rexmit_drop_options = 0, // drop options after a few retransmits
+	always_keepalive = 1,
+};
+
+/*
+ * Force a time value to be in a certain range.
+ */
+#define	TCPT_RANGESET(tv, value, tvmin, tvmax) do { \
+	(tv) = (value) + tcp_rexmit_slop; \
+	if ((uint64_t)(tv) < (uint64_t)(tvmin)) \
+		(tv) = (tvmin); \
+	if ((uint64_t)(tv) > (uint64_t)(tvmax)) \
+		(tv) = (tvmax); \
+} while(0)
+
+#endif
diff --git a/third_party/tcplp/bsdtcp/tcp_fsm.h b/third_party/tcplp/bsdtcp/tcp_fsm.h
new file mode 100644
index 0000000..4edc351
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/tcp_fsm.h
@@ -0,0 +1,112 @@
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.
+ * All rights reserved.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)tcp_fsm.h	8.1 (Berkeley) 6/10/93
+ * $FreeBSD$
+ */
+
+/* samkumar: Removed some #ifdef guards around constants needed for TCPlp. */
+
+#ifndef TCPLP_NETINET_TCP_FSM_H_
+#define	TCPLP_NETINET_TCP_FSM_H_
+
+#include "types.h"
+
+/*
+ * TCP FSM state definitions.
+ *
+ * Per RFC793, September, 1981.
+ */
+
+#define	TCP_NSTATES	11
+
+#define	TCPS_CLOSED		0	/* closed */
+#define	TCPS_LISTEN		1	/* listening for connection */
+#define	TCPS_SYN_SENT		2	/* active, have sent syn */
+#define	TCPS_SYN_RECEIVED	3	/* have sent and received syn */
+/* states < TCPS_ESTABLISHED are those where connections not established */
+#define	TCPS_ESTABLISHED	4	/* established */
+#define	TCPS_CLOSE_WAIT		5	/* rcvd fin, waiting for close */
+/* states > TCPS_CLOSE_WAIT are those where user has closed */
+#define	TCPS_FIN_WAIT_1		6	/* have closed, sent fin */
+#define	TCPS_CLOSING		7	/* closed xchd FIN; await FIN ACK */
+#define	TCPS_LAST_ACK		8	/* had fin and close; await FIN ACK */
+/* states > TCPS_CLOSE_WAIT && < TCPS_FIN_WAIT_2 await ACK of FIN */
+#define	TCPS_FIN_WAIT_2		9	/* have closed, fin is acked */
+#define	TCPS_TIME_WAIT		10	/* in 2*msl quiet wait after close */
+
+/* for KAME src sync over BSD*'s */
+#define	TCP6_NSTATES		TCP_NSTATES
+#define	TCP6S_CLOSED		TCPS_CLOSED
+#define	TCP6S_LISTEN		TCPS_LISTEN
+#define	TCP6S_SYN_SENT		TCPS_SYN_SENT
+#define	TCP6S_SYN_RECEIVED	TCPS_SYN_RECEIVED
+#define	TCP6S_ESTABLISHED	TCPS_ESTABLISHED
+#define	TCP6S_CLOSE_WAIT	TCPS_CLOSE_WAIT
+#define	TCP6S_FIN_WAIT_1	TCPS_FIN_WAIT_1
+#define	TCP6S_CLOSING		TCPS_CLOSING
+#define	TCP6S_LAST_ACK		TCPS_LAST_ACK
+#define	TCP6S_FIN_WAIT_2	TCPS_FIN_WAIT_2
+#define	TCP6S_TIME_WAIT		TCPS_TIME_WAIT
+
+#define	TCPS_HAVERCVDSYN(s)	((s) >= TCPS_SYN_RECEIVED)
+#define	TCPS_HAVEESTABLISHED(s)	((s) >= TCPS_ESTABLISHED)
+#define	TCPS_HAVERCVDFIN(s)	((s) >= TCPS_TIME_WAIT)
+
+ /*
+ * Flags used when sending segments in tcp_output.  Basic flags (TH_RST,
+ * TH_ACK,TH_SYN,TH_FIN) are totally determined by state, with the proviso
+ * that TH_FIN is sent only if all data queued for output is included in the
+ * segment.
+ */
+static const uint8_t	tcp_outflags[TCP_NSTATES] = {
+	TH_RST|TH_ACK,		/* 0, CLOSED */
+	0,			/* 1, LISTEN */
+	TH_SYN,			/* 2, SYN_SENT */
+	TH_SYN|TH_ACK,		/* 3, SYN_RECEIVED */
+	TH_ACK,			/* 4, ESTABLISHED */
+	TH_ACK,			/* 5, CLOSE_WAIT */
+	TH_FIN|TH_ACK,		/* 6, FIN_WAIT_1 */
+	TH_FIN|TH_ACK,		/* 7, CLOSING */
+	TH_FIN|TH_ACK,		/* 8, LAST_ACK */
+	TH_ACK,			/* 9, FIN_WAIT_2 */
+	TH_ACK,			/* 10, TIME_WAIT */
+};
+
+#ifdef KPROF
+int	tcp_acounts[TCP_NSTATES][PRU_NREQ];
+#endif
+
+static char const * const tcpstates[] = {
+	"CLOSED",	"LISTEN",	"SYN_SENT",	"SYN_RCVD",
+	"ESTABLISHED",	"CLOSE_WAIT",	"FIN_WAIT_1",	"CLOSING",
+	"LAST_ACK",	"FIN_WAIT_2",	"TIME_WAIT",
+};
+
+#endif
diff --git a/third_party/tcplp/bsdtcp/tcp_input.c b/third_party/tcplp/bsdtcp/tcp_input.c
new file mode 100644
index 0000000..8211f2f
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/tcp_input.c
@@ -0,0 +1,3094 @@
+/*-
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 2007-2008,2010
+ *	Swinburne University of Technology, Melbourne, Australia.
+ * Copyright (c) 2009-2010 Lawrence Stewart <lstewart@freebsd.org>
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * Copyright (c) 2010-2011 Juniper Networks, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed at the Centre for Advanced Internet
+ * Architectures, Swinburne University of Technology, by Lawrence Stewart,
+ * James Healy and David Hayes, made possible in part by a grant from the Cisco
+ * University Research Program Fund at Community Foundation Silicon Valley.
+ *
+ * Portions of this software were developed at the Centre for Advanced
+ * Internet Architectures, Swinburne University of Technology, Melbourne,
+ * Australia by David Hayes under sponsorship from the FreeBSD Foundation.
+ *
+ * Portions of this software were developed by Robert N. M. Watson under
+ * contract to Juniper Networks, Inc.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)tcp_input.c	8.12 (Berkeley) 5/24/95
+ */
+
+
+/*
+ * Determine a reasonable value for maxseg size.
+ * If the route is known, check route for mtu.
+ * If none, use an mss that can be handled on the outgoing interface
+ * without forcing IP to fragment.  If no route is found, route has no mtu,
+ * or the destination isn't local, use a default, hopefully conservative
+ * size (usually 512 or the default IP max size, but no more than the mtu
+ * of the interface), as we can't discover anything about intervening
+ * gateways or networks.  We also initialize the congestion/slow start
+ * window to be a single segment if the destination isn't local.
+ * While looking at the routing entry, we also initialize other path-dependent
+ * parameters from pre-set or cached values in the routing entry.
+ *
+ * Also take into account the space needed for options that we
+ * send regularly.  Make maxseg shorter by that amount to assure
+ * that we can send maxseg amount of data even when the options
+ * are present.  Store the upper limit of the length of options plus
+ * data in maxopd.
+ *
+ * NOTE that this routine is only called when we process an incoming
+ * segment, or an ICMP need fragmentation datagram. Outgoing SYN/ACK MSS
+ * settings are handled in tcp_mssopt().
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+
+#include "tcp.h"
+#include "tcp_fsm.h"
+#include "tcp_seq.h"
+#include "tcp_timer.h"
+#include "tcp_var.h"
+#include "../lib/bitmap.h"
+#include "../lib/cbuf.h"
+#include "icmp_var.h"
+#include "ip.h"
+#include "ip6.h"
+#include "sys/queue.h"
+
+#include "tcp_const.h"
+
+/* samkumar: Copied from in.h */
+#define IPPROTO_DONE 267
+
+/* samkumar: Copied from sys/libkern.h */
+static int imax(int a, int b) { return (a > b ? a : b); }
+static int imin(int a, int b) { return (a < b ? a : b); }
+
+static int min(int a, int b) { return imin(a, b); }
+
+static void	 tcp_dooptions(struct tcpopt *, uint8_t *, int, int);
+static void
+tcp_do_segment(struct ip6_hdr* ip6, struct tcphdr *th, otMessage* msg,
+    struct tcpcb *tp, int drop_hdrlen, int tlen, uint8_t iptos,
+    struct tcplp_signals* sig);
+static void	 tcp_xmit_timer(struct tcpcb *, int);
+void tcp_hc_get(/*struct in_conninfo *inc*/ struct tcpcb* tp, struct hc_metrics_lite *hc_metrics_lite);
+static void	 tcp_newreno_partial_ack(struct tcpcb *, struct tcphdr *);
+
+/*
+ * CC wrapper hook functions
+ */
+static inline void
+cc_ack_received(struct tcpcb *tp, struct tcphdr *th, uint16_t type)
+{
+	tp->ccv->bytes_this_ack = BYTES_THIS_ACK(tp, th);
+	if (tp->snd_cwnd <= tp->snd_wnd)
+		tp->ccv->flags |= CCF_CWND_LIMITED;
+	else
+		tp->ccv->flags &= ~CCF_CWND_LIMITED;
+
+	if (type == CC_ACK) {
+		if (tp->snd_cwnd > tp->snd_ssthresh) {
+			tp->t_bytes_acked += min(tp->ccv->bytes_this_ack,
+			     V_tcp_abc_l_var * tp->t_maxseg);
+			if (tp->t_bytes_acked >= tp->snd_cwnd) {
+				tp->t_bytes_acked -= tp->snd_cwnd;
+				tp->ccv->flags |= CCF_ABC_SENTAWND;
+			}
+		} else {
+				tp->ccv->flags &= ~CCF_ABC_SENTAWND;
+				tp->t_bytes_acked = 0;
+		}
+	}
+
+	if (CC_ALGO(tp)->ack_received != NULL) {
+		/* XXXLAS: Find a way to live without this */
+		tp->ccv->curack = th->th_ack;
+		CC_ALGO(tp)->ack_received(tp->ccv, type);
+	}
+}
+
+static inline void
+cc_conn_init(struct tcpcb *tp)
+{
+	struct hc_metrics_lite metrics;
+	int rtt;
+
+	/*
+	 * samkumar: remove locks, inpcb, and stats.
+	 */
+
+	/* samkumar: Used to take &inp->inp_inc as an argument. */
+	tcp_hc_get(tp, &metrics);
+
+	if (tp->t_srtt == 0 && (rtt = metrics.rmx_rtt)) {
+		tp->t_srtt = rtt;
+		tp->t_rttbest = tp->t_srtt + TCP_RTT_SCALE;
+		if (metrics.rmx_rttvar) {
+			tp->t_rttvar = metrics.rmx_rttvar;
+		} else {
+			/* default variation is +- 1 rtt */
+			tp->t_rttvar =
+			    tp->t_srtt * TCP_RTTVAR_SCALE / TCP_RTT_SCALE;
+		}
+		TCPT_RANGESET(tp->t_rxtcur,
+		    ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1,
+		    tp->t_rttmin, TCPTV_REXMTMAX);
+	}
+	if (metrics.rmx_ssthresh) {
+		/*
+		 * There's some sort of gateway or interface
+		 * buffer limit on the path.  Use this to set
+		 * the slow start threshhold, but set the
+		 * threshold to no less than 2*mss.
+		 */
+		tp->snd_ssthresh = max(2 * tp->t_maxseg, metrics.rmx_ssthresh);
+	}
+
+	/*
+	 * Set the initial slow-start flight size.
+	 *
+	 * RFC5681 Section 3.1 specifies the default conservative values.
+	 * RFC3390 specifies slightly more aggressive values.
+	 * RFC6928 increases it to ten segments.
+	 * Support for user specified value for initial flight size.
+	 *
+	 * If a SYN or SYN/ACK was lost and retransmitted, we have to
+	 * reduce the initial CWND to one segment as congestion is likely
+	 * requiring us to be cautious.
+	 */
+	if (tp->snd_cwnd == 1)
+		tp->snd_cwnd = tp->t_maxseg;		/* SYN(-ACK) lost */
+	else if (V_tcp_initcwnd_segments)
+		tp->snd_cwnd = min(V_tcp_initcwnd_segments * tp->t_maxseg,
+		    max(2 * tp->t_maxseg, V_tcp_initcwnd_segments * 1460));
+	else if (V_tcp_do_rfc3390)
+		tp->snd_cwnd = min(4 * tp->t_maxseg,
+		    max(2 * tp->t_maxseg, 4380));
+	else {
+		/* Per RFC5681 Section 3.1 */
+		if (tp->t_maxseg > 2190)
+			tp->snd_cwnd = 2 * tp->t_maxseg;
+		else if (tp->t_maxseg > 1095)
+			tp->snd_cwnd = 3 * tp->t_maxseg;
+		else
+			tp->snd_cwnd = 4 * tp->t_maxseg;
+	}
+
+	if (CC_ALGO(tp)->conn_init != NULL)
+		CC_ALGO(tp)->conn_init(tp->ccv);
+
+	/* samkumar: print statement for debugging. Resurrect with DEBUG macro? */
+#ifdef INSTRUMENT_TCP
+	tcplp_sys_log("TCP CC_INIT %u %d %d", (unsigned int) tcplp_sys_get_millis(), (int) tp->snd_cwnd, (int) tp->snd_ssthresh);
+#endif
+}
+
+inline void
+cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type)
+{
+	/* samkumar: Remove locks and stats from this function. */
+
+	switch(type) {
+	case CC_NDUPACK:
+		if (!IN_FASTRECOVERY(tp->t_flags)) {
+			tp->snd_recover = tp->snd_max;
+			if (tp->t_flags & TF_ECN_PERMIT)
+				tp->t_flags |= TF_ECN_SND_CWR;
+		}
+		break;
+	case CC_ECN:
+		if (!IN_CONGRECOVERY(tp->t_flags)) {
+			tp->snd_recover = tp->snd_max;
+			if (tp->t_flags & TF_ECN_PERMIT)
+				tp->t_flags |= TF_ECN_SND_CWR;
+		}
+		break;
+	case CC_RTO:
+		tp->t_dupacks = 0;
+		tp->t_bytes_acked = 0;
+		EXIT_RECOVERY(tp->t_flags);
+		tp->snd_ssthresh = max(2, min(tp->snd_wnd, tp->snd_cwnd) / 2 /
+		    tp->t_maxseg) * tp->t_maxseg;
+		tp->snd_cwnd = tp->t_maxseg;
+
+		/*
+		 * samkumar: Stats for TCPlp: count the number of timeouts (RTOs).
+		 * I've commented this out (with #if 0) because it isn't part of TCP
+		 * functionality. At some point, we may want to bring it back to
+		 * measure performance.
+		 */
+#if 0
+		tcplp_timeoutRexmitCnt++;
+#endif
+#ifdef INSTRUMENT_TCP
+		tcplp_sys_log("TCP CC_RTO %u %d %d", (unsigned int) tcplp_sys_get_millis(), (int) tp->snd_cwnd, (int) tp->snd_ssthresh);
+#endif
+		break;
+	case CC_RTO_ERR:
+		/* RTO was unnecessary, so reset everything. */
+		tp->snd_cwnd = tp->snd_cwnd_prev;
+		tp->snd_ssthresh = tp->snd_ssthresh_prev;
+		tp->snd_recover = tp->snd_recover_prev;
+		if (tp->t_flags & TF_WASFRECOVERY)
+			ENTER_FASTRECOVERY(tp->t_flags);
+		if (tp->t_flags & TF_WASCRECOVERY)
+			ENTER_CONGRECOVERY(tp->t_flags);
+		tp->snd_nxt = tp->snd_max;
+		tp->t_flags &= ~TF_PREVVALID;
+		tp->t_badrxtwin = 0;
+#ifdef INSTRUMENT_TCP
+		tcplp_sys_log("TCP CC_RTO_ERR %u %d %d", (unsigned int) tcplp_sys_get_millis(), (int) tp->snd_cwnd, (int) tp->snd_ssthresh);
+#endif
+		break;
+	}
+
+	if (CC_ALGO(tp)->cong_signal != NULL) {
+		if (th != NULL)
+			tp->ccv->curack = th->th_ack;
+		CC_ALGO(tp)->cong_signal(tp->ccv, type);
+	}
+}
+
+static inline void
+cc_post_recovery(struct tcpcb *tp, struct tcphdr *th)
+{
+	/* samkumar: remove lock */
+
+	/* XXXLAS: KASSERT that we're in recovery? */
+	if (CC_ALGO(tp)->post_recovery != NULL) {
+		tp->ccv->curack = th->th_ack;
+		CC_ALGO(tp)->post_recovery(tp->ccv);
+	}
+	/* XXXLAS: EXIT_RECOVERY ? */
+	tp->t_bytes_acked = 0;
+}
+
+
+/*
+ * Indicate whether this ack should be delayed.  We can delay the ack if
+ * following conditions are met:
+ *	- There is no delayed ack timer in progress.
+ *	- Our last ack wasn't a 0-sized window. We never want to delay
+ *	  the ack that opens up a 0-sized window.
+ *	- LRO wasn't used for this segment. We make sure by checking that the
+ *	  segment size is not larger than the MSS.
+ *	- Delayed acks are enabled or this is a half-synchronized T/TCP
+ *	  connection.
+ */
+#define DELAY_ACK(tp, tlen)						\
+	((!tcp_timer_active(tp, TT_DELACK) &&				\
+	    (tp->t_flags & TF_RXWIN0SENT) == 0) &&			\
+	    (tlen <= tp->t_maxopd) &&					\
+	    (V_tcp_delack_enabled || (tp->t_flags & TF_NEEDSYN)))
+
+static inline void
+cc_ecnpkt_handler(struct tcpcb *tp, struct tcphdr *th, uint8_t iptos)
+{
+	/* samkumar: remove lock */
+
+	if (CC_ALGO(tp)->ecnpkt_handler != NULL) {
+		switch (iptos & IPTOS_ECN_MASK) {
+		case IPTOS_ECN_CE:
+			tp->ccv->flags |= CCF_IPHDR_CE;
+			break;
+		case IPTOS_ECN_ECT0:
+			tp->ccv->flags &= ~CCF_IPHDR_CE;
+			break;
+		case IPTOS_ECN_ECT1:
+			tp->ccv->flags &= ~CCF_IPHDR_CE;
+			break;
+		}
+
+		if (th->th_flags & TH_CWR)
+			tp->ccv->flags |= CCF_TCPHDR_CWR;
+		else
+			tp->ccv->flags &= ~CCF_TCPHDR_CWR;
+
+		if (tp->t_flags & TF_DELACK)
+			tp->ccv->flags |= CCF_DELACK;
+		else
+			tp->ccv->flags &= ~CCF_DELACK;
+
+		CC_ALGO(tp)->ecnpkt_handler(tp->ccv);
+
+		if (tp->ccv->flags & CCF_ACKNOW)
+			tcp_timer_activate(tp, TT_DELACK, tcp_delacktime);
+	}
+}
+
+/*
+ * External function: look up an entry in the hostcache and fill out the
+ * supplied TCP metrics structure.  Fills in NULL when no entry was found or
+ * a value is not set.
+ */
+/*
+ * samkumar: This function is taken from tcp_hostcache.c. We have no host cache
+ * in TCPlp, so I changed this to always act as if there is a miss. I removed
+ * the first argument, formerly "struct in_coninfo *inc".
+ */
+void
+tcp_hc_get(struct tcpcb* tp, struct hc_metrics_lite *hc_metrics_lite)
+{
+	bzero(hc_metrics_lite, sizeof(*hc_metrics_lite));
+}
+
+/*
+ * External function: look up an entry in the hostcache and return the
+ * discovered path MTU.  Returns NULL if no entry is found or value is not
+ * set.
+ */
+ /*
+  * samkumar: This function is taken from tcp_hostcache.c. We have no host cache
+  * in TCPlp, so I changed this to always act as if there is a miss.
+  */
+uint64_t
+tcp_hc_getmtu(struct tcpcb* tp)
+{
+	return 0;
+}
+
+
+/*
+ * Issue RST and make ACK acceptable to originator of segment.
+ * The mbuf must still include the original packet header.
+ * tp may be NULL.
+ */
+/*
+ * samkumar: Original signature was:
+ * static void tcp_dropwithreset(struct mbuf *m, struct tcphdr *th, struct tcpcb *tp,
+ *    int tlen, int rstreason)
+ */
+void
+tcp_dropwithreset(struct ip6_hdr* ip6, struct tcphdr *th, struct tcpcb *tp, otInstance* instance,
+    int tlen, int rstreason)
+{
+	/*
+	 * samkumar: I removed logic to skip this for broadcast or multicast
+	 * packets. In the FreeBSD version of this function, it would just
+	 * call m_freem(m), if m->m_flags has M_BCAST or M_MCAST set, and not
+	 * send a response packet.
+	 * I also removed bandwidth limiting.
+	 */
+	if (th->th_flags & TH_RST)
+		return;
+
+	/* tcp_respond consumes the mbuf chain. */
+	if (th->th_flags & TH_ACK) {
+		tcp_respond(tp, instance, ip6, th, (tcp_seq) 0, th->th_ack, TH_RST);
+	} else {
+		if (th->th_flags & TH_SYN)
+			tlen++;
+		tcp_respond(tp, instance, ip6, th, th->th_seq + tlen, (tcp_seq) 0, TH_RST | TH_ACK);
+	}
+	return;
+}
+
+/*
+ * TCP input handling is split into multiple parts:
+ *   tcp6_input is a thin wrapper around tcp_input for the extended
+ *	ip6_protox[] call format in ip6_input
+ *   tcp_input handles primary segment validation, inpcb lookup and
+ *	SYN processing on listen sockets
+ *   tcp_do_segment processes the ACK and text of the segment for
+ *	establishing, established and closing connections
+ */
+/* samkumar: The signature of this function was originally:
+   tcp_input(struct mbuf **mp, int *offp, int proto) */
+/* NOTE: tcp_fields_to_host(th) must be called before this function is called. */
+int
+tcp_input(struct ip6_hdr* ip6, struct tcphdr* th, otMessage* msg, struct tcpcb* tp, struct tcpcb_listen* tpl,
+          struct tcplp_signals* sig)
+{
+	/*
+	 * samkumar: I significantly modified this function, compared to the
+	 * FreeBSD version. This function used to be reponsible for matching an
+	 * incoming TCP segment to its TCB. That functionality is now done by
+	 * TCPlp, and this function is only called once a match has been
+	 * identified.
+	 *
+	 * The tp and tpl arguments are used to indicate the match. Exactly one of
+	 * them must be NULL, and the other must be set. If tp is non-NULL, then
+	 * this function assumes that the packet was matched to an active socket
+	 * (connection endpoint). If tpl is non-NULL, then this function assumes
+	 * that this packet is a candidate match for a passive socket (listener)
+	 * and attempts to set up a new connection if the flags, sequence numbers,
+	 * etc. look OK.
+	 *
+	 * TCPlp assumes that the packets are IPv6, so I removed any logic specific
+	 * to IPv4.
+	 *
+	 * And of course, all code pertaining to locks and stats has been removed.
+	 */
+	int tlen = 0, off;
+	int thflags;
+	uint8_t iptos = 0;
+	int drop_hdrlen;
+	int rstreason = 0;
+	struct tcpopt to;		/* options in this segment */
+	uint8_t* optp = NULL;
+	int optlen = 0;
+	to.to_flags = 0;
+	KASSERT(tp || tpl, ("One of tp and tpl must be positive"));
+
+	/*
+	 * samkumar: Here, there used to be code that handled preprocessing:
+	 * calling m_pullup(m, sizeof(*ip6) + sizeof(*th)) to get the headers
+	 * contiguous in memory, setting the ip6 and th pointers, validating the
+	 * checksum, and dropping packets with unspecified source address. In
+	 * TCPlp, all of this is done for a packet before this function is called.
+	 */
+
+	tlen = ntohs(ip6->ip6_plen); // assume *off == sizeof(*ip6)
+
+	/*
+	 * samkumar: Logic that handled IPv4 was deleted below. I won't add a
+	 * comment every time this is done, but I'm putting it here (one of the
+	 * first instances of this) for clarity.
+	 */
+	iptos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
+
+	/*
+	 * Check that TCP offset makes sense,
+	 * pull out TCP options and adjust length.		XXX
+	 */
+	off = (th->th_off_x2 >> TH_OFF_SHIFT) << 2;
+	if (off < sizeof (struct tcphdr) || off > tlen) {
+		goto drop;
+	}
+	tlen -= off;	/* tlen is used instead of ti->ti_len */
+	/* samkumar: now, tlen is the length of the data */
+
+	if (off > sizeof (struct tcphdr)) {
+		/*
+		 * samkumar: I removed a call to IP6_EXTHDR_CHECK, which I believe
+		 * checks for IPv6 extension headers. In TCPlp, we assume that these
+		 * are handled elsewhere in the networking stack, before the incoming
+		 * packet is processed at the TCP layer. I also removed the followup
+		 * calls to reassign the ip6 and th pointers.
+		 */
+		optlen = off - sizeof (struct tcphdr);
+		optp = (uint8_t *)(th + 1);
+	}
+
+	thflags = th->th_flags;
+
+	/*
+	 * samkumar: There used to be a call here to tcp_fields_to_host(th), which
+	 * changes the byte order of various fields to host format. I removed this
+	 * call from there and handle it in TCPlp, before calling this. The reason
+	 * is that it's possible for this function to be called twice by TCPlp's
+	 * logic (e.g., if the packet matches a TIME-WAIT socket this function
+	 * returns early, and the packet may then match a listening socket, at
+ 	 * which ppoint this function will be called again). Thus, any operations
+	 * like this, which mutate the packet itself, need to happen before calling
+	 * this function.
+	 */
+
+	/*
+	 * Delay dropping TCP, IP headers, IPv6 ext headers, and TCP options.
+	 *
+	 * samkumar: My TCP header is in a different buffer from the IP header.
+	 * drop_hdrlen is only meaningful as an offset into the TCP buffer,
+	 * because it is used to determine how much of the packet to discard
+	 * before copying it into the receive buffer. Therefore, my offset does
+	 * not include the length of IP header and options, only the length of
+	 * the TCP header and options.
+	 */
+	drop_hdrlen = /*off0 +*/ off;
+
+	/*
+	 * Locate pcb for segment; if we're likely to add or remove a
+	 * connection then first acquire pcbinfo lock.  There are three cases
+	 * where we might discover later we need a write lock despite the
+	 * flags: ACKs moving a connection out of the syncache, ACKs for a
+	 * connection in TIMEWAIT and SYNs not targeting a listening socket.
+	 */
+
+	/*
+	 * samkumar: Locking code is removed, invalidating most of the above
+	 * comment.
+	 */
+
+	/*
+	 * samkumar: The FreeBSD code at logic here to check m->m_flags for the
+	 * M_IP6_NEXTHOP flag, and search for the PACKET_TAG_IPFORWARD tag and
+	 * store it in fwd_tag if so. In TCPlp, we assume that the IPv6 layer of
+	 * the host network stack handles this kind of IPv6-related functionality,
+	 * so this logic has been removed.
+	 */
+
+	/*
+	 * samkumar: Here, there was code to match the packet to an inpcb and reply
+	 * with an RST segment if no match is found. This included taking the
+	 * fwd_tag into account, if set above (see the previous comment). I removed
+	 * this code because, in TCPlp, this is done before calling this function.
+	 */
+
+	/*
+	 * A previous connection in TIMEWAIT state is supposed to catch stray
+	 * or duplicate segments arriving late.  If this segment was a
+	 * legitimate new connection attempt, the old INPCB gets removed and
+	 * we can try again to find a listening socket.
+	 *
+	 * At this point, due to earlier optimism, we may hold only an inpcb
+	 * lock, and not the inpcbinfo write lock.  If so, we need to try to
+	 * acquire it, or if that fails, acquire a reference on the inpcb,
+	 * drop all locks, acquire a global write lock, and then re-acquire
+	 * the inpcb lock.  We may at that point discover that another thread
+	 * has tried to free the inpcb, in which case we need to loop back
+	 * and try to find a new inpcb to deliver to.
+	 *
+	 * XXXRW: It may be time to rethink timewait locking.
+	 */
+	/*
+	 * samkumar: The original code checked inp->inp_flags & INP_TIMEWAIT. I
+	 * changed it to instead check tp->t_state, since we don't use inpcbs in
+	 * TCPlp.
+	 */
+	if (tp && tp->t_state == TCP6S_TIME_WAIT) {
+		/*
+		 * samkumar: There's nothing wrong with the call to tcp_dooptions call
+		 * that I've commented out below; it's just that the modified
+		 * "tcp_twcheck" function no longer needs the options structure, so
+		 * I figured that there's no longer a good reason to parse the options.
+		 * In fact, this call was probably unnecessary even in the original
+		 * FreeBSD TCP code, since tcp_twcheck, even without my modifications,
+		 * did not use the pointer to the options structure!
+		 */
+		//if (thflags & TH_SYN)
+			//tcp_dooptions(&to, optp, optlen, TO_SYN);
+		/*
+		 * samkumar: The original code would "goto findpcb;" if this branch is
+		 * taken. Matching with a TCB is done outside of this function in
+		 * TCPlp, so we instead return a special value so that the caller knows
+		 * to try re-matching this packet to a socket.
+		 */
+		if (tcp_twcheck(tp,/*inp, &to,*/ th, /*m,*/ tlen))
+			return (RELOOKUP_REQUIRED);
+		return (IPPROTO_DONE);
+	}
+	/*
+	 * The TCPCB may no longer exist if the connection is winding
+	 * down or it is in the CLOSED state.  Either way we drop the
+	 * segment and send an appropriate response.
+	 */
+	/*
+	 * samkumar: There used to be code here that grabs the tp from the inpcb
+	 * and drops with reset if the connection is in the closed state or if
+	 * the tp is NULL. In TCPlp, the equivalent logic is done before entering
+	 * this function. There was also code here to handle TCP offload, which
+	 * TCPlp does not handle.
+	 */
+
+	/*
+	 * We've identified a valid inpcb, but it could be that we need an
+	 * inpcbinfo write lock but don't hold it.  In this case, attempt to
+	 * acquire using the same strategy as the TIMEWAIT case above.  If we
+	 * relock, we have to jump back to 'relocked' as the connection might
+	 * now be in TIMEWAIT.
+	 */
+	/*
+	 * samkumar: There used to be some code here for synchronization, MAC
+	 * management, and debugging.
+	 */
+
+	/*
+	 * When the socket is accepting connections (the INPCB is in LISTEN
+	 * state) we look into the SYN cache if this is a new connection
+	 * attempt or the completion of a previous one. Instead of checking
+	 * so->so_options to check if the socket is listening, we rely on the
+	 * arguments passed to this function (if tp == NULL, then tpl is not NULL
+	 * and is the matching listen socket).
+	 */
+
+	if (/*so->so_options & SO_ACCEPTCONN*/tp == NULL) {
+		/* samkumar: NULL check isn't needed but prevents a compiler warning */
+		KASSERT(tpl != NULL && tpl->t_state == TCP6S_LISTEN, ("listen socket must be in listening state!"));
+
+		/*
+		 * samkumar: There used to be some code here that checks if the
+		 * received segment is an ACK, and if so, searches the SYN cache to
+		 * find an entry whose connection establishment handshake this segment
+		 * completes. If such an entry is found, then a socket is created and
+		 * then tcp_do_segment is called to actually run the code to mark the
+		 * connection as established. If the received segment is an RST, then
+		 * that is processed in the syncache as well. In TCPlp we do not use a
+		 * SYN cache, so I've removed that code. The actual connection
+		 * establishment/processing logic happens in tcp_do_segment anyway,
+		 * which is called at the bottom of this function, so there's no need
+		 * to rewrite this code with special-case logic for that.
+		 */
+
+		/*
+		 * We can't do anything without SYN.
+		 */
+		if ((thflags & TH_SYN) == 0) {
+			/*
+			 * samkumar: Here, and in several other instances, the FreeBSD
+			 * code would call tcp_log_addrs. Improving logging in these
+			 * edge cases in TCPlp is left for the future --- for now, I just
+			 * put "<addrs go here>" where the address string would go.
+			 */
+			tcplp_sys_log("%s; %s: Listen socket: "
+			    "SYN is missing, segment ignored",
+			    "<addrs go here>", __func__);
+			goto dropunlock;
+		}
+		/*
+		 * (SYN|ACK) is bogus on a listen socket.
+		 */
+		if (thflags & TH_ACK) {
+			/* samkumar: See above comment regarding tcp_log_addrs. */
+			tcplp_sys_log("%s; %s: Listen socket: "
+			    "SYN|ACK invalid, segment rejected",
+			    "<addrs go here>", __func__);
+			/* samkumar: Removed call to syncache_badack(&inc); */
+			rstreason = BANDLIM_RST_OPENPORT;
+			goto dropwithreset;
+		}
+		/*
+		 * If the drop_synfin option is enabled, drop all
+		 * segments with both the SYN and FIN bits set.
+		 * This prevents e.g. nmap from identifying the
+		 * TCP/IP stack.
+		 * XXX: Poor reasoning.  nmap has other methods
+		 * and is constantly refining its stack detection
+		 * strategies.
+		 * XXX: This is a violation of the TCP specification
+		 * and was used by RFC1644.
+		 */
+		if ((thflags & TH_FIN) && V_drop_synfin) {
+			/* samkumar: See above comment regarding tcp_log_addrs. */
+			tcplp_sys_log("%s; %s: Listen socket: "
+			    "SYN|FIN segment ignored (based on "
+			    "sysctl setting)", "<addrs go here>", __func__);
+			goto dropunlock;
+		}
+		/*
+		 * Segment's flags are (SYN) or (SYN|FIN).
+		 *
+		 * TH_PUSH, TH_URG, TH_ECE, TH_CWR are ignored
+		 * as they do not affect the state of the TCP FSM.
+		 * The data pointed to by TH_URG and th_urp is ignored.
+		 */
+		KASSERT((thflags & (TH_RST|TH_ACK)) == 0,
+		    ("%s: Listen socket: TH_RST or TH_ACK set", __func__));
+		KASSERT(thflags & (TH_SYN),
+		    ("%s: Listen socket: TH_SYN not set", __func__));
+
+		/*
+		 * samkumar: There used to be some code here to reject incoming
+		 * SYN packets for deprecated interface addresses unless
+		 * V_ip6_use_deprecated is true. Rejecting the packet, in this case,
+		 * means to "goto dropwithreset". I removed this functionality.
+		 */
+
+		/*
+		 * Basic sanity checks on incoming SYN requests:
+		 *   Don't respond if the destination is a link layer
+		 *	broadcast according to RFC1122 4.2.3.10, p. 104.
+		 *   If it is from this socket it must be forged.
+		 *   Don't respond if the source or destination is a
+		 *	global or subnet broad- or multicast address.
+		 *   Note that it is quite possible to receive unicast
+		 *	link-layer packets with a broadcast IP address. Use
+		 *	in_broadcast() to find them.
+		 */
+
+		/*
+		 * samkumar: There used to be a sanity check that drops (via
+		 * "goto dropunlock") any broadcast or multicast packets. This check is
+		 * done by checking m->m_flags for (M_BAST|M_MCAST). The original
+		 * FreeBSD code for this has been removed (since checking m->m_flags
+		 * isn't really useful to us anyway). Note that other FreeBSD code that
+		 * checks for multicast source/destination addresses is retained below
+		 * (but only for the IPv6 case; the original FreeBSD code also handled
+	 	 * it for IPv4 addresses).
+		 */
+
+		if (th->th_dport == th->th_sport &&
+		    IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &ip6->ip6_src)) {
+			/* samkumar: See above comment regarding tcp_log_addrs. */
+			tcplp_sys_log("%s; %s: Listen socket: "
+			"Connection attempt to/from self "
+			"ignored", "<addrs go here>", __func__);
+			goto dropunlock;
+		}
+		if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
+		    IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) {
+			/* samkumar: See above comment regarding tcp_log_addrs. */
+			tcplp_sys_log("%s; %s: Listen socket: "
+			"Connection attempt from/to multicast "
+			"address ignored", "<addrs go here>", __func__);
+			goto dropunlock;
+		}
+
+		/*
+		 * samkumar: The FreeBSD code would call
+		 * syncache_add(&inc, &to, th, inp, &so, m, NULL, NULL);
+		 * to add an entry to the SYN cache at this point. TCPlp doesn't use a
+		 * syncache, so we initialize the new socket right away. The code to
+		 * initialize the socket is taken from the syncache_socket function.
+		 */
+
+		tcp_dooptions(&to, optp, optlen, TO_SYN);
+		tp = tcplp_sys_accept_ready(tpl, &ip6->ip6_dst, th->th_sport); // Try to allocate an active socket to accept into
+		if (tp == NULL) {
+			/* If we couldn't allocate, just ignore the SYN. */
+			return IPPROTO_DONE;
+		}
+		if (tp == (struct tcpcb *) -1) {
+			rstreason = ECONNREFUSED;
+			goto dropwithreset;
+		}
+		tcp_state_change(tp, TCPS_SYN_RECEIVED);
+		tpmarkpassiveopen(tp);
+		tp->t_flags |= TF_ACKNOW; // samkumar: my addition
+		tp->iss = tcp_new_isn(tp);
+		tp->irs = th->th_seq;
+		tcp_rcvseqinit(tp);
+		tcp_sendseqinit(tp);
+		tp->snd_wl1 = th->th_seq;
+		tp->snd_max = tp->iss/* + 1*/;
+		tp->snd_nxt = tp->iss/* + 1*/;
+		tp->rcv_up = th->th_seq + 1;
+		tp->rcv_wnd = imin(imax(cbuf_free_space(&tp->recvbuf), 0), TCP_MAXWIN);
+		tp->rcv_adv += tp->rcv_wnd;
+		tp->last_ack_sent = tp->rcv_nxt;
+		memcpy(&tp->laddr, &ip6->ip6_dst, sizeof(tp->laddr));
+		memcpy(&tp->faddr, &ip6->ip6_src, sizeof(tp->faddr));
+		tp->fport = th->th_sport;
+		tp->lport = tpl->lport;
+
+		/*
+		 * samkumar: Several of the checks below (taken from syncache_socket!)
+		 * check for flags in sc->sc_flags. They have been written to directly
+		 * check for the conditions on the TCP options structure or in the TCP
+		 * header that would ordinarily be used to set flags in sc->sc_flags
+		 * when adding an entry to the SYN cache.
+		 *
+		 * In effect, we combine the logic in syncache_add to set elements of
+		 * sc with the logic in syncache_socket to transfer state from sc
+		 * to the socket, but short-circuit the process to avoid ever storing
+		 * data in sc. Since this isn't just adding or deleting code, I decided
+		 * that it's better to keep comments indicating exactly how I composed
+		 * these two functions.
+		 */
+		tp->t_flags = tp->t_flags & (TF_NOPUSH | TF_NODELAY | TF_NOOPT);
+//		tp->t_flags = sototcpcb(lso)->t_flags & (TF_NOPUSH|TF_NODELAY);
+//		if (sc->sc_flags & SCF_NOOPT)
+//			tp->t_flags |= TF_NOOPT;
+//		else {
+		if (!(tp->t_flags & TF_NOOPT) && V_tcp_do_rfc1323) {
+			if (/*sc->sc_flags & SCF_WINSCALE*/to.to_flags & TOF_SCALE) {
+				int wscale = 0;
+
+				/*
+				 * Pick the smallest possible scaling factor that
+				 * will still allow us to scale up to sb_max, aka
+				 * kern.ipc.maxsockbuf.
+				 *
+				 * We do this because there are broken firewalls that
+				 * will corrupt the window scale option, leading to
+				 * the other endpoint believing that our advertised
+				 * window is unscaled.  At scale factors larger than
+				 * 5 the unscaled window will drop below 1500 bytes,
+				 * leading to serious problems when traversing these
+				 * broken firewalls.
+				 *
+				 * With the default maxsockbuf of 256K, a scale factor
+				 * of 3 will be chosen by this algorithm.  Those who
+				 * choose a larger maxsockbuf should watch out
+				 * for the compatiblity problems mentioned above.
+				 *
+				 * RFC1323: The Window field in a SYN (i.e., a <SYN>
+				 * or <SYN,ACK>) segment itself is never scaled.
+				 */
+
+				/*
+				 * samkumar: The original logic, taken from syncache_add, is
+				 * listed below, commented out. In practice, we just use
+				 * wscale = 0 because in TCPlp we assume that the buffers
+				 * aren't big enough for window scaling to be all that useful.
+				 */
+#if 0
+				while (wscale < TCP_MAX_WINSHIFT &&
+					(TCP_MAXWIN << wscale) < sb_max)
+					wscale++;
+#endif
+
+				tp->t_flags |= TF_REQ_SCALE|TF_RCVD_SCALE;
+				tp->snd_scale = /*sc->sc_requested_s_scale*/to.to_wscale;
+				tp->request_r_scale = wscale;
+			}
+			if (/*sc->sc_flags & SCF_TIMESTAMP*/to.to_flags & TOF_TS) {
+				tp->t_flags |= TF_REQ_TSTMP|TF_RCVD_TSTMP;
+				tp->ts_recent = /*sc->sc_tsreflect*/to.to_tsval;
+				tp->ts_recent_age = tcp_ts_getticks();
+				tp->ts_offset = /*sc->sc_tsoff*/0; // No syncookies, so this should always be 0
+			}
+
+			/*
+			 * samkumar: there used to be code here that would set the
+			 * TF_SIGNATURE flag on tp->t_flags if SCF_SIGNATURE is set on
+			 * sc->sc_flags. I've left it in below, commented out.
+			 */
+#if 0
+	#ifdef TCP_SIGNATURE
+			if (sc->sc_flags & SCF_SIGNATURE)
+				tp->t_flags |= TF_SIGNATURE;
+	#endif
+#endif
+			if (/*sc->sc_flags & SCF_SACK*/ to.to_flags & TOF_SACKPERM)
+				tp->t_flags |= TF_SACK_PERMIT;
+		}
+		if (/*sc->sc_flags & SCF_ECN*/(th->th_flags & (TH_ECE|TH_CWR)) && V_tcp_do_ecn)
+			tp->t_flags |= TF_ECN_PERMIT;
+
+		/*
+		 * Set up MSS and get cached values from tcp_hostcache.
+		 * This might overwrite some of the defaults we just set.
+		 */
+		tcp_mss(tp, /*sc->sc_peer_mss*/(to.to_flags & TOF_MSS) ? to.to_mss : 0);
+
+		tcp_output(tp); // to send the SYN-ACK
+
+		tp->accepted_from = tpl;
+		return (IPPROTO_DONE);
+	} else if (tp->t_state == TCPS_LISTEN) {
+		/*
+		 * When a listen socket is torn down the SO_ACCEPTCONN
+		 * flag is removed first while connections are drained
+		 * from the accept queue in a unlock/lock cycle of the
+		 * ACCEPT_LOCK, opening a race condition allowing a SYN
+		 * attempt go through unhandled.
+		 */
+		goto dropunlock;
+	}
+
+	KASSERT(tp, ("tp is still NULL!"));
+
+	/*
+	 * samkumar: There used to be code here to verify TCP signatures. We don't
+	 * support TCP signatures in TCPlp.
+	 */
+
+	/*
+	 * Segment belongs to a connection in SYN_SENT, ESTABLISHED or later
+	 * state.  tcp_do_segment() always consumes the mbuf chain, unlocks
+	 * the inpcb, and unlocks pcbinfo.
+	 */
+	tcp_do_segment(ip6, th, msg, tp, drop_hdrlen, tlen, iptos, sig);
+	return (IPPROTO_DONE);
+
+	/*
+	 * samkumar: Removed some locking and debugging code under all three of
+	 * these labels: dropwithreset, dropunlock, and drop. I also removed some
+	 * memory management code (e.g., calling m_freem(m) if m != NULL) since
+	 * the caller of this function will take care of that kind of memory
+	 * management in TCPlp.
+	 */
+dropwithreset:
+
+	/*
+	 * samkumar: The check against inp != NULL is now a check on tp != NULL.
+	 */
+	if (tp != NULL) {
+		tcp_dropwithreset(ip6, th, tp, tp->instance, tlen, rstreason);
+	} else
+		tcp_dropwithreset(ip6, th, NULL, tpl->instance, tlen, rstreason);
+	goto drop;
+
+dropunlock:
+drop:
+	return (IPPROTO_DONE);
+}
+
+/*
+ * samkumar: Original signature
+ * static void
+ * tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
+ *     struct tcpcb *tp, int drop_hdrlen, int tlen, uint8_t iptos,
+ *     int ti_locked)
+ */
+static void
+tcp_do_segment(struct ip6_hdr* ip6, struct tcphdr *th, otMessage* msg,
+    struct tcpcb *tp, int drop_hdrlen, int tlen, uint8_t iptos,
+    struct tcplp_signals* sig)
+{
+	/*
+	 * samkumar: All code pertaining to locks, stats, and debug has been
+	 * removed from this function.
+	 */
+
+	int thflags, acked, ourfinisacked, needoutput = 0;
+	int rstreason, todrop, win;
+	uint64_t tiwin;
+	struct tcpopt to;
+	uint32_t ticks = tcplp_sys_get_ticks();
+	otInstance* instance = tp->instance;
+	thflags = th->th_flags;
+	tp->sackhint.last_sack_ack = 0;
+
+	/*
+	 * If this is either a state-changing packet or current state isn't
+	 * established, we require a write lock on tcbinfo.  Otherwise, we
+	 * allow the tcbinfo to be in either alocked or unlocked, as the
+	 * caller may have unnecessarily acquired a write lock due to a race.
+	 */
+
+	/* samkumar: There used to be synchronization code here. */
+	KASSERT(tp->t_state > TCPS_LISTEN, ("%s: TCPS_LISTEN",
+	    __func__));
+	KASSERT(tp->t_state != TCPS_TIME_WAIT, ("%s: TCPS_TIME_WAIT",
+	    __func__));
+
+	/*
+	 * Segment received on connection.
+	 * Reset idle time and keep-alive timer.
+	 * XXX: This should be done after segment
+	 * validation to ignore broken/spoofed segs.
+	 */
+	tp->t_rcvtime = ticks;
+	if (TCPS_HAVEESTABLISHED(tp->t_state))
+		tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp));
+
+	/*
+	 * Scale up the window into a 32-bit value.
+	 * For the SYN_SENT state the scale is zero.
+	 */
+	tiwin = th->th_win << tp->snd_scale;
+
+	/*
+	 * TCP ECN processing.
+	 */
+	/*
+	 * samkumar: I intentionally left the TCPSTAT_INC lines below commented
+	 * out, to avoid altering the structure of the code too much by
+	 * reorganizing the switch statement.
+	 */
+	if (tp->t_flags & TF_ECN_PERMIT) {
+		if (thflags & TH_CWR)
+			tp->t_flags &= ~TF_ECN_SND_ECE;
+		switch (iptos & IPTOS_ECN_MASK) {
+		case IPTOS_ECN_CE:
+			tp->t_flags |= TF_ECN_SND_ECE;
+			//TCPSTAT_INC(tcps_ecn_ce);
+			break;
+		case IPTOS_ECN_ECT0:
+			//TCPSTAT_INC(tcps_ecn_ect0);
+			break;
+		case IPTOS_ECN_ECT1:
+			//TCPSTAT_INC(tcps_ecn_ect1);
+			break;
+		}
+
+		/* Process a packet differently from RFC3168. */
+		cc_ecnpkt_handler(tp, th, iptos);
+
+		/* Congestion experienced. */
+		if (thflags & TH_ECE) {
+			cc_cong_signal(tp, th, CC_ECN);
+		}
+	}
+
+	/*
+	 * Parse options on any incoming segment.
+	 */
+	tcp_dooptions(&to, (uint8_t *)(th + 1),
+	    ((th->th_off_x2 >> TH_OFF_SHIFT) << 2) - sizeof(struct tcphdr),
+	    (thflags & TH_SYN) ? TO_SYN : 0);
+
+	/*
+	 * If echoed timestamp is later than the current time,
+	 * fall back to non RFC1323 RTT calculation.  Normalize
+	 * timestamp if syncookies were used when this connection
+	 * was established.
+	 */
+
+	if ((to.to_flags & TOF_TS) && (to.to_tsecr != 0)) {
+		to.to_tsecr -= tp->ts_offset;
+		if (TSTMP_GT(to.to_tsecr, tcp_ts_getticks()))
+			to.to_tsecr = 0;
+	}
+	/*
+	 * If timestamps were negotiated during SYN/ACK they should
+	 * appear on every segment during this session and vice versa.
+	 */
+	if ((tp->t_flags & TF_RCVD_TSTMP) && !(to.to_flags & TOF_TS)) {
+		/* samkumar: See above comment regarding tcp_log_addrs. */
+		tcplp_sys_log("%s; %s: Timestamp missing, "
+			"no action", "<addrs go here>", __func__);
+	}
+	if (!(tp->t_flags & TF_RCVD_TSTMP) && (to.to_flags & TOF_TS)) {
+		/* samkumar: See above comment regarding tcp_log_addrs. */
+		tcplp_sys_log("%s; %s: Timestamp not expected, "
+			"no action", "<addrs go here>", __func__);
+	}
+
+	/*
+	 * Process options only when we get SYN/ACK back. The SYN case
+	 * for incoming connections is handled in tcp_syncache.
+	 * According to RFC1323 the window field in a SYN (i.e., a <SYN>
+	 * or <SYN,ACK>) segment itself is never scaled.
+	 * XXX this is traditional behavior, may need to be cleaned up.
+	 */
+	if (tp->t_state == TCPS_SYN_SENT && (thflags & TH_SYN)) {
+		if ((to.to_flags & TOF_SCALE) &&
+		    (tp->t_flags & TF_REQ_SCALE)) {
+			tp->t_flags |= TF_RCVD_SCALE;
+			tp->snd_scale = to.to_wscale;
+		}
+		/*
+		 * Initial send window.  It will be updated with
+		 * the next incoming segment to the scaled value.
+		 */
+		tp->snd_wnd = th->th_win;
+		if (to.to_flags & TOF_TS) {
+			tp->t_flags |= TF_RCVD_TSTMP;
+			tp->ts_recent = to.to_tsval;
+			tp->ts_recent_age = tcp_ts_getticks();
+		}
+		if (to.to_flags & TOF_MSS)
+			tcp_mss(tp, to.to_mss);
+		if ((tp->t_flags & TF_SACK_PERMIT) &&
+		    (to.to_flags & TOF_SACKPERM) == 0)
+			tp->t_flags &= ~TF_SACK_PERMIT;
+	}
+	/*
+	 * Header prediction: check for the two common cases
+	 * of a uni-directional data xfer.  If the packet has
+	 * no control flags, is in-sequence, the window didn't
+	 * change and we're not retransmitting, it's a
+	 * candidate.  If the length is zero and the ack moved
+	 * forward, we're the sender side of the xfer.  Just
+	 * free the data acked & wake any higher level process
+	 * that was blocked waiting for space.  If the length
+	 * is non-zero and the ack didn't move, we're the
+	 * receiver side.  If we're getting packets in-order
+	 * (the reassembly queue is empty), add the data to
+	 * the socket buffer and note that we need a delayed ack.
+	 * Make sure that the hidden state-flags are also off.
+	 * Since we check for TCPS_ESTABLISHED first, it can only
+	 * be TH_NEEDSYN.
+	 */
+	/*
+	 * samkumar: Replaced LIST_EMPTY(&tp->tsegq with the call to bmp_isempty).
+	 */
+	if (tp->t_state == TCPS_ESTABLISHED &&
+	    th->th_seq == tp->rcv_nxt &&
+	    (thflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK &&
+	    tp->snd_nxt == tp->snd_max &&
+	    tiwin && tiwin == tp->snd_wnd &&
+	    ((tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) == 0) &&
+	    bmp_isempty(tp->reassbmp, REASSBMP_SIZE(tp)) &&
+	    ((to.to_flags & TOF_TS) == 0 ||
+	     TSTMP_GEQ(to.to_tsval, tp->ts_recent)) ) {
+
+		/*
+		 * If last ACK falls within this segment's sequence numbers,
+		 * record the timestamp.
+		 * NOTE that the test is modified according to the latest
+		 * proposal of the tcplw@cray.com list (Braden 1993/04/26).
+		 */
+		if ((to.to_flags & TOF_TS) != 0 &&
+		    SEQ_LEQ(th->th_seq, tp->last_ack_sent)) {
+			tp->ts_recent_age = tcp_ts_getticks();
+			tp->ts_recent = to.to_tsval;
+		}
+
+		if (tlen == 0) {
+			if (SEQ_GT(th->th_ack, tp->snd_una) &&
+			    SEQ_LEQ(th->th_ack, tp->snd_max) &&
+			    !IN_RECOVERY(tp->t_flags) &&
+			    (to.to_flags & TOF_SACK) == 0 &&
+			    TAILQ_EMPTY(&tp->snd_holes)) {
+				/*
+				 * This is a pure ack for outstanding data.
+				 */
+
+				/*
+				 * "bad retransmit" recovery.
+				 */
+				if (tp->t_rxtshift == 1 &&
+				    tp->t_flags & TF_PREVVALID &&
+				    (int)(ticks - tp->t_badrxtwin) < 0) {
+					cc_cong_signal(tp, th, CC_RTO_ERR);
+				}
+
+				/*
+				 * Recalculate the transmit timer / rtt.
+				 *
+				 * Some boxes send broken timestamp replies
+				 * during the SYN+ACK phase, ignore
+				 * timestamps of 0 or we could calculate a
+				 * huge RTT and blow up the retransmit timer.
+				 */
+
+				if ((to.to_flags & TOF_TS) != 0 &&
+				    to.to_tsecr) {
+					uint32_t t;
+
+					t = tcp_ts_getticks() - to.to_tsecr;
+					if (!tp->t_rttlow || tp->t_rttlow > t)
+						tp->t_rttlow = t;
+					tcp_xmit_timer(tp,
+					    TCP_TS_TO_TICKS(t) + 1);
+				} else if (tp->t_rtttime &&
+				    SEQ_GT(th->th_ack, tp->t_rtseq)) {
+					if (!tp->t_rttlow ||
+					    tp->t_rttlow > ticks - tp->t_rtttime)
+						tp->t_rttlow = ticks - tp->t_rtttime;
+					tcp_xmit_timer(tp,
+							ticks - tp->t_rtttime);
+				}
+
+				acked = BYTES_THIS_ACK(tp, th);
+
+				/*
+				 * samkumar: Replaced sbdrop(&so->so_snd, acked) with this call
+				 * to lbuf_pop.
+				 */
+				{
+					uint32_t poppedbytes = lbuf_pop(&tp->sendbuf, acked, &sig->links_popped);
+					KASSERT(poppedbytes == acked, ("More bytes were acked than are in the send buffer"));
+					sig->bytes_acked += poppedbytes;
+				}
+				if (SEQ_GT(tp->snd_una, tp->snd_recover) &&
+				    SEQ_LEQ(th->th_ack, tp->snd_recover))
+					tp->snd_recover = th->th_ack - 1;
+
+				/*
+				 * Let the congestion control algorithm update
+				 * congestion control related information. This
+				 * typically means increasing the congestion
+				 * window.
+				 */
+				cc_ack_received(tp, th, CC_ACK);
+
+				tp->snd_una = th->th_ack;
+				/*
+				 * Pull snd_wl2 up to prevent seq wrap relative
+				 * to th_ack.
+				 */
+				tp->snd_wl2 = th->th_ack;
+				tp->t_dupacks = 0;
+
+				/*
+				 * If all outstanding data are acked, stop
+				 * retransmit timer, otherwise restart timer
+				 * using current (possibly backed-off) value.
+				 * If process is waiting for space,
+				 * wakeup/selwakeup/signal.  If data
+				 * are ready to send, let tcp_output
+				 * decide between more output or persist.
+				 */
+
+				if (tp->snd_una == tp->snd_max)
+					tcp_timer_activate(tp, TT_REXMT, 0);
+				else if (!tcp_timer_active(tp, TT_PERSIST))
+					tcp_timer_activate(tp, TT_REXMT,
+						      tp->t_rxtcur);
+
+				/*
+				 * samkumar: There used to be a call to sowwakeup(so); here,
+				 * which wakes up any threads waiting for the socket to
+				 * become ready for writing. TCPlp handles its send buffer
+				 * differently so we do not need to replace this call with
+				 * specialized code to handle this.
+				 */
+
+				/*
+				 * samkumar: Replaced sbavail(&so->so_snd) with this call to
+				 * lbuf_used_space.
+				 */
+				if (lbuf_used_space(&tp->sendbuf))
+					(void) tcp_output(tp);
+				goto check_delack;
+			}
+		} else if (th->th_ack == tp->snd_una &&
+			/*
+			 * samkumar: Replaced sbspace(&so->so_rcv) with this call to
+			 * cbuf_free_space.
+			 */
+		    tlen <= cbuf_free_space(&tp->recvbuf)) {
+
+			/*
+			 * This is a pure, in-sequence data packet with
+			 * nothing on the reassembly queue and we have enough
+			 * buffer space to take it.
+			 */
+			/* Clean receiver SACK report if present */
+			if ((tp->t_flags & TF_SACK_PERMIT) && tp->rcv_numsacks)
+				tcp_clean_sackreport(tp);
+
+			tp->rcv_nxt += tlen;
+			/*
+			 * Pull snd_wl1 up to prevent seq wrap relative to
+			 * th_seq.
+			 */
+			tp->snd_wl1 = th->th_seq;
+			/*
+			 * Pull rcv_up up to prevent seq wrap relative to
+			 * rcv_nxt.
+			 */
+			tp->rcv_up = tp->rcv_nxt;
+
+		/*
+		 * Automatic sizing of receive socket buffer.  Often the send
+		 * buffer size is not optimally adjusted to the actual network
+		 * conditions at hand (delay bandwidth product).  Setting the
+		 * buffer size too small limits throughput on links with high
+		 * bandwidth and high delay (eg. trans-continental/oceanic links).
+		 *
+		 * On the receive side the socket buffer memory is only rarely
+		 * used to any significant extent.  This allows us to be much
+		 * more aggressive in scaling the receive socket buffer.  For
+		 * the case that the buffer space is actually used to a large
+		 * extent and we run out of kernel memory we can simply drop
+		 * the new segments; TCP on the sender will just retransmit it
+		 * later.  Setting the buffer size too big may only consume too
+		 * much kernel memory if the application doesn't read() from
+		 * the socket or packet loss or reordering makes use of the
+		 * reassembly queue.
+		 *
+		 * The criteria to step up the receive buffer one notch are:
+		 *  1. Application has not set receive buffer size with
+		 *     SO_RCVBUF. Setting SO_RCVBUF clears SB_AUTOSIZE.
+		 *  2. the number of bytes received during the time it takes
+		 *     one timestamp to be reflected back to us (the RTT);
+		 *  3. received bytes per RTT is within seven eighth of the
+		 *     current socket buffer size;
+		 *  4. receive buffer size has not hit maximal automatic size;
+		 *
+		 * This algorithm does one step per RTT at most and only if
+		 * we receive a bulk stream w/o packet losses or reorderings.
+		 * Shrinking the buffer during idle times is not necessary as
+		 * it doesn't consume any memory when idle.
+		 *
+		 * TODO: Only step up if the application is actually serving
+		 * the buffer to better manage the socket buffer resources.
+		 */
+
+			/*
+			 * samkumar: There used to be code here to dynamically size the
+			 * receive buffer (tp->rfbuf_ts, rp->rfbuf_cnt, and the local
+			 * newsize variable). In TCPlp, we don't support this, as the user
+			 * allocates the receive buffer and its size can't be changed here.
+			 * Therefore, I removed the code that does this. Note that the
+			 * actual resizing of the buffer is done using sbreserve_locked,
+			 * whose call comes later (not exactly where this comment is).
+			 */
+
+			/* Add data to socket buffer. */
+
+			/*
+			 * samkumar: The code that was here would just free the mbuf
+			 * (with m_freem(m)) if SBS_CANTRCVMORE is set in
+			 * so->so_rcv.sb_state. Otherwise, it would cut drop_hdrlen bytes
+			 * from the mbuf (using m_adj(m, drop_hdrlen)) to discard the
+			 * headers and then append the mbuf to the receive buffer using
+			 * sbappendstream_locked(&so->so_rcv, m, 0). I've rewritten this
+			 * to work the TCPlp way. The check to so->so_rcv.sb_state is
+			 * replaced by a tcpiscantrcv call, and we copy bytes into
+			 * TCPlp's circular buffer (since we designed it to avoid
+			 * having dynamically-allocated memory for the receive buffer).
+			 */
+
+			if (!tpiscantrcv(tp)) {
+				cbuf_write(&tp->recvbuf, msg, otMessageGetOffset(msg) + drop_hdrlen, tlen, cbuf_copy_from_message);
+				if (tlen > 0) {
+					sig->recvbuf_added = true;
+				}
+			} else {
+				/*
+				 * samkumar: We already know tlen != 0, so if we got here, then
+				 * it means that we got data after we called SHUT_RD, or after
+				 * receiving a FIN. I'm going to drop the connection in this
+				 * case. I think FreeBSD might have just dropped the packet
+				 * silently, but Linux handles it this way; this seems to be
+				 * the right approach to me.
+				 */
+				tcp_drop(tp, ECONNABORTED);
+				goto drop;
+			}
+			/* NB: sorwakeup_locked() does an implicit unlock. */
+			/*
+			 * samkumar: There used to be a call to sorwakeup_locked(so); here,
+			 * which wakes up any threads waiting for the socket to become
+			 * become ready for reading. TCPlp handles its buffering
+			 * differently so we do not need to replace this call with
+			 * specialized code to handle this.
+			 */
+			if (DELAY_ACK(tp, tlen)) {
+				tp->t_flags |= TF_DELACK;
+			} else {
+				tp->t_flags |= TF_ACKNOW;
+				tcp_output(tp);
+			}
+			goto check_delack;
+		}
+	}
+
+	/*
+	 * Calculate amount of space in receive window,
+	 * and then do TCP input processing.
+	 * Receive window is amount of space in rcv queue,
+	 * but not less than advertised window.
+	 */
+	/* samkumar: Replaced sbspace(&so->so_rcv) with call to cbuf_free_space. */
+	win = cbuf_free_space(&tp->recvbuf);
+	if (win < 0)
+		win = 0;
+	tp->rcv_wnd = imax(win, (int)(tp->rcv_adv - tp->rcv_nxt));
+
+	/* Reset receive buffer auto scaling when not in bulk receive mode. */
+	/* samkumar: Removed this receive buffer autoscaling code. */
+
+	switch (tp->t_state) {
+
+	/*
+	 * If the state is SYN_RECEIVED:
+	 *	if seg contains an ACK, but not for our SYN/ACK, send a RST.
+	 *  (Added by Sam) if seg is resending the original SYN, resend the SYN/ACK
+	 */
+	/*
+	 * samkumar: If we receive a retransmission of the original SYN, then
+	 * resend the SYN/ACK segment. This case was probably handled by the
+	 * SYN cache. Because TCPlp does not use a SYN cache, we need to write
+	 * custom logic for it. It is handled in the "else if" clause below.
+	 */
+	case TCPS_SYN_RECEIVED:
+		if ((thflags & TH_ACK) &&
+		    (SEQ_LEQ(th->th_ack, tp->snd_una) ||
+		     SEQ_GT(th->th_ack, tp->snd_max))) {
+				rstreason = BANDLIM_RST_OPENPORT;
+				goto dropwithreset;
+		} else if ((thflags & TH_SYN) && !(thflags & TH_ACK) && (th->th_seq == tp->irs)) {
+			tp->t_flags |= TF_ACKNOW;
+		}
+		break;
+
+	/*
+	 * If the state is SYN_SENT:
+	 *	if seg contains an ACK, but not for our SYN, drop the input.
+	 *	if seg contains a RST, then drop the connection.
+	 *	if seg does not contain SYN, then drop it.
+	 * Otherwise this is an acceptable SYN segment
+	 *	initialize tp->rcv_nxt and tp->irs
+	 *	if seg contains ack then advance tp->snd_una
+	 *	if seg contains an ECE and ECN support is enabled, the stream
+	 *	    is ECN capable.
+	 *	if SYN has been acked change to ESTABLISHED else SYN_RCVD state
+	 *	arrange for segment to be acked (eventually)
+	 *	continue processing rest of data/controls, beginning with URG
+	 */
+	case TCPS_SYN_SENT:
+		if ((thflags & TH_ACK) &&
+		    (SEQ_LEQ(th->th_ack, tp->iss) ||
+		     SEQ_GT(th->th_ack, tp->snd_max))) {
+			rstreason = BANDLIM_UNLIMITED;
+			goto dropwithreset;
+		}
+		if ((thflags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)) {
+			tp = tcp_drop(tp, ECONNREFUSED);
+		}
+		if (thflags & TH_RST)
+			goto drop;
+		if (!(thflags & TH_SYN))
+			goto drop;
+
+		tp->irs = th->th_seq;
+		tcp_rcvseqinit(tp);
+		if (thflags & TH_ACK) {
+			/*
+			 * samkumar: Removed call to soisconnected(so), since TCPlp has its
+			 * own buffering.
+			 */
+
+			/* Do window scaling on this connection? */
+			if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
+				(TF_RCVD_SCALE|TF_REQ_SCALE)) {
+				tp->rcv_scale = tp->request_r_scale;
+			}
+			tp->rcv_adv += imin(tp->rcv_wnd,
+			    TCP_MAXWIN << tp->rcv_scale);
+			tp->snd_una++;		/* SYN is acked */
+			/*
+			 * If there's data, delay ACK; if there's also a FIN
+			 * ACKNOW will be turned on later.
+			 */
+			if (DELAY_ACK(tp, tlen) && tlen != 0)
+				tcp_timer_activate(tp, TT_DELACK,
+				    tcp_delacktime);
+			else
+				tp->t_flags |= TF_ACKNOW;
+
+			if ((thflags & TH_ECE) && V_tcp_do_ecn) {
+				tp->t_flags |= TF_ECN_PERMIT;
+			}
+
+			/*
+			 * Received <SYN,ACK> in SYN_SENT[*] state.
+			 * Transitions:
+			 *	SYN_SENT  --> ESTABLISHED
+			 *	SYN_SENT* --> FIN_WAIT_1
+			 */
+			tp->t_starttime = ticks;
+			if (tp->t_flags & TF_NEEDFIN) {
+				tcp_state_change(tp, TCPS_FIN_WAIT_1);
+				tp->t_flags &= ~TF_NEEDFIN;
+				thflags &= ~TH_SYN;
+			} else {
+				tcp_state_change(tp, TCPS_ESTABLISHED);
+				/* samkumar: Set conn_established signal for TCPlp. */
+				sig->conn_established = true;
+				cc_conn_init(tp);
+				tcp_timer_activate(tp, TT_KEEP,
+				    TP_KEEPIDLE(tp));
+			}
+		} else {
+			/*
+			 * Received initial SYN in SYN-SENT[*] state =>
+			 * simultaneous open.
+			 * If it succeeds, connection is * half-synchronized.
+			 * Otherwise, do 3-way handshake:
+			 *        SYN-SENT -> SYN-RECEIVED
+			 *        SYN-SENT* -> SYN-RECEIVED*
+			 */
+			tp->t_flags |= (TF_ACKNOW | TF_NEEDSYN);
+			tcp_timer_activate(tp, TT_REXMT, 0);
+			tcp_state_change(tp, TCPS_SYN_RECEIVED);
+			/*
+			 * samkumar: We would have incremented snd_next in tcp_output when
+			 * we sent the original SYN, so decrement it here. (Another
+			 * consequence of removing the SYN cache.)
+			 */
+			tp->snd_nxt--;
+		}
+
+		/*
+		 * Advance th->th_seq to correspond to first data byte.
+		 * If data, trim to stay within window,
+		 * dropping FIN if necessary.
+		 */
+		th->th_seq++;
+		if (tlen > tp->rcv_wnd) {
+			todrop = tlen - tp->rcv_wnd;
+			/*
+			 * samkumar: I removed a call to m_adj(m, -todrop), which intends
+			 * to trim the data so it fits in the window. We can just read less
+			 * when copying into the receive buffer in TCPlp, so we don't need
+			 * to do this.
+			 */
+			(void) todrop; /* samkumar: Prevent a compiler warning */
+			tlen = tp->rcv_wnd;
+			thflags &= ~TH_FIN;
+		}
+		tp->snd_wl1 = th->th_seq - 1;
+		tp->rcv_up = th->th_seq;
+		/*
+		 * Client side of transaction: already sent SYN and data.
+		 * If the remote host used T/TCP to validate the SYN,
+		 * our data will be ACK'd; if so, enter normal data segment
+		 * processing in the middle of step 5, ack processing.
+		 * Otherwise, goto step 6.
+		 */
+		if (thflags & TH_ACK)
+			goto process_ACK;
+
+		goto step6;
+
+	/*
+	 * If the state is LAST_ACK or CLOSING or TIME_WAIT:
+	 *      do normal processing.
+	 *
+	 * NB: Leftover from RFC1644 T/TCP.  Cases to be reused later.
+	 */
+	case TCPS_LAST_ACK:
+	case TCPS_CLOSING:
+		break;  /* continue normal processing */
+	}
+
+	/*
+	 * States other than LISTEN or SYN_SENT.
+	 * First check the RST flag and sequence number since reset segments
+	 * are exempt from the timestamp and connection count tests.  This
+	 * fixes a bug introduced by the Stevens, vol. 2, p. 960 bugfix
+	 * below which allowed reset segments in half the sequence space
+	 * to fall though and be processed (which gives forged reset
+	 * segments with a random sequence number a 50 percent chance of
+	 * killing a connection).
+	 * Then check timestamp, if present.
+	 * Then check the connection count, if present.
+	 * Then check that at least some bytes of segment are within
+	 * receive window.  If segment begins before rcv_nxt,
+	 * drop leading data (and SYN); if nothing left, just ack.
+	 */
+	if (thflags & TH_RST) {
+		/*
+		 * RFC5961 Section 3.2
+		 *
+		 * - RST drops connection only if SEG.SEQ == RCV.NXT.
+		 * - If RST is in window, we send challenge ACK.
+		 *
+		 * Note: to take into account delayed ACKs, we should
+		 *   test against last_ack_sent instead of rcv_nxt.
+		 * Note 2: we handle special case of closed window, not
+		 *   covered by the RFC.
+		 */
+		if ((SEQ_GEQ(th->th_seq, tp->last_ack_sent) &&
+		    SEQ_LT(th->th_seq, tp->last_ack_sent + tp->rcv_wnd)) ||
+		    (tp->rcv_wnd == 0 && tp->last_ack_sent == th->th_seq)) {
+
+			/*
+			 * samkumar: This if statement used to also be prefaced with
+			 * "V_tcp_insecure_rst ||". But I removed it, since there's no
+			 * reason to support an insecure option in TCPlp (my guess is that
+			 * FreeBSD supported it for legacy reasons).
+			 */
+			if (tp->last_ack_sent == th->th_seq) {
+				/*
+				 * samkumar: Normally, the error number would be stored in
+				 * so->so_error. Instead, we put it in this "droperror" local
+				 * variable and then pass it to tcplp_sys_connection_lost.
+				 */
+				int droperror = 0;
+				/* Drop the connection. */
+				switch (tp->t_state) {
+				case TCPS_SYN_RECEIVED:
+					droperror = ECONNREFUSED;
+					goto close;
+				case TCPS_ESTABLISHED:
+				case TCPS_FIN_WAIT_1:
+				case TCPS_FIN_WAIT_2:
+				case TCPS_CLOSE_WAIT:
+					droperror = ECONNRESET;
+				close:
+					tcp_state_change(tp, TCPS_CLOSED);
+					/* FALLTHROUGH */
+				default:
+					tp = tcp_close(tp);
+					tcplp_sys_connection_lost(tp, droperror);
+				}
+			} else {
+				/* Send challenge ACK. */
+				tcp_respond(tp, tp->instance, ip6, th, tp->rcv_nxt, tp->snd_nxt, TH_ACK);
+				tp->last_ack_sent = tp->rcv_nxt;
+			}
+		}
+		goto drop;
+	}
+
+	/*
+	 * RFC5961 Section 4.2
+	 * Send challenge ACK for any SYN in synchronized state.
+	 */
+	/*
+	 * samkumar: I added the check for the SYN-RECEIVED state in this if
+	 * statement (another consequence of removing the SYN cache).
+	 */
+	if ((thflags & TH_SYN) && tp->t_state != TCPS_SYN_SENT && tp->t_state != TCP6S_SYN_RECEIVED) {
+		/*
+		 * samkumar: The modern way to handle this is to send a Challenge ACK.
+		 * FreeBSD supports this, but it also has this V_tcp_insecure_syn
+		 * options that will cause it to drop the connection if the SYN falls
+		 * in the receive window. In TCPlp we *only* support Challenge ACKs
+		 * (the secure way of doing it), so I've removed code for the insecure
+		 * way. (Presumably the reason why FreeBSD supports the insecure way is
+		 * for legacy code, which we don't really care about in TCPlp).
+		 */
+		/* Send challenge ACK. */
+		tcplp_sys_log("Sending challenge ACK");
+		tcp_respond(tp, tp->instance, ip6, th, tp->rcv_nxt, tp->snd_nxt, TH_ACK);
+		tp->last_ack_sent = tp->rcv_nxt;
+		goto drop;
+	}
+
+	/*
+	 * RFC 1323 PAWS: If we have a timestamp reply on this segment
+	 * and it's less than ts_recent, drop it.
+	 */
+	if ((to.to_flags & TOF_TS) != 0 && tp->ts_recent &&
+	    TSTMP_LT(to.to_tsval, tp->ts_recent)) {
+
+		/* Check to see if ts_recent is over 24 days old.  */
+		if (tcp_ts_getticks() - tp->ts_recent_age > TCP_PAWS_IDLE) {
+			/*
+			 * Invalidate ts_recent.  If this segment updates
+			 * ts_recent, the age will be reset later and ts_recent
+			 * will get a valid value.  If it does not, setting
+			 * ts_recent to zero will at least satisfy the
+			 * requirement that zero be placed in the timestamp
+			 * echo reply when ts_recent isn't valid.  The
+			 * age isn't reset until we get a valid ts_recent
+			 * because we don't want out-of-order segments to be
+			 * dropped when ts_recent is old.
+			 */
+			tp->ts_recent = 0;
+		} else {
+			if (tlen)
+				goto dropafterack;
+			goto drop;
+		}
+	}
+
+	/*
+	 * In the SYN-RECEIVED state, validate that the packet belongs to
+	 * this connection before trimming the data to fit the receive
+	 * window.  Check the sequence number versus IRS since we know
+	 * the sequence numbers haven't wrapped.  This is a partial fix
+	 * for the "LAND" DoS attack.
+	 */
+	if (tp->t_state == TCPS_SYN_RECEIVED && SEQ_LT(th->th_seq, tp->irs)) {
+		rstreason = BANDLIM_RST_OPENPORT;
+		goto dropwithreset;
+	}
+
+	todrop = tp->rcv_nxt - th->th_seq;
+	if (todrop > 0) {
+		if (thflags & TH_SYN) {
+			thflags &= ~TH_SYN;
+			th->th_seq++;
+			if (th->th_urp > 1)
+				th->th_urp--;
+			else
+				thflags &= ~TH_URG;
+			todrop--;
+		}
+		/*
+		 * Following if statement from Stevens, vol. 2, p. 960.
+		 */
+		if (todrop > tlen
+		    || (todrop == tlen && (thflags & TH_FIN) == 0)) {
+			/*
+			 * Any valid FIN must be to the left of the window.
+			 * At this point the FIN must be a duplicate or out
+			 * of sequence; drop it.
+			 */
+			thflags &= ~TH_FIN;
+
+			/*
+			 * Send an ACK to resynchronize and drop any data.
+			 * But keep on processing for RST or ACK.
+			 */
+			tp->t_flags |= TF_ACKNOW;
+			todrop = tlen;
+		}
+		/* samkumar: There was an else case that only collected stats. */
+		drop_hdrlen += todrop;	/* drop from the top afterwards */
+		th->th_seq += todrop;
+		tlen -= todrop;
+		if (th->th_urp > todrop)
+			th->th_urp -= todrop;
+		else {
+			thflags &= ~TH_URG;
+			th->th_urp = 0;
+		}
+	}
+
+	/*
+	 * If new data are received on a connection after the
+	 * user processes are gone, then RST the other end.
+	 */
+	/*
+	 * samkumar: TCPlp is designed for embedded systems where there is no
+	 * concept of a "process" that has allocated a TCP socket. Therefore, we
+	 * do not implement the functionality in the above comment (the code for
+	 * it used to be here, and I removed it).
+	 */
+	/*
+	 * If segment ends after window, drop trailing data
+	 * (and PUSH and FIN); if nothing left, just ACK.
+	 */
+	todrop = (th->th_seq + tlen) - (tp->rcv_nxt + tp->rcv_wnd);
+	if (todrop > 0) {
+		if (todrop >= tlen) {
+			/*
+			 * If window is closed can only take segments at
+			 * window edge, and have to drop data and PUSH from
+			 * incoming segments.  Continue processing, but
+			 * remember to ack.  Otherwise, drop segment
+			 * and ack.
+			 */
+			if (tp->rcv_wnd == 0 && th->th_seq == tp->rcv_nxt) {
+				tp->t_flags |= TF_ACKNOW;
+			} else
+				goto dropafterack;
+		}
+		/*
+		 * samkumar: I removed a call to m_adj(m, -todrop), which intends
+		 * to trim the data so it fits in the window. We can just read less
+		 * when copying into the receive buffer in TCPlp, so we don't need
+		 * to do this. Subtracting it from tlen gives us enough information to
+		 * do this later. In FreeBSD, this isn't possible because the mbuf
+		 * itself becomes part of the receive buffer, so the mbuf has to be
+		 * trimmed in order for this to work out.
+		 */
+		tlen -= todrop;
+		thflags &= ~(TH_PUSH|TH_FIN);
+	}
+
+	/*
+	 * If last ACK falls within this segment's sequence numbers,
+	 * record its timestamp.
+	 * NOTE:
+	 * 1) That the test incorporates suggestions from the latest
+	 *    proposal of the tcplw@cray.com list (Braden 1993/04/26).
+	 * 2) That updating only on newer timestamps interferes with
+	 *    our earlier PAWS tests, so this check should be solely
+	 *    predicated on the sequence space of this segment.
+	 * 3) That we modify the segment boundary check to be
+	 *        Last.ACK.Sent <= SEG.SEQ + SEG.Len
+	 *    instead of RFC1323's
+	 *        Last.ACK.Sent < SEG.SEQ + SEG.Len,
+	 *    This modified check allows us to overcome RFC1323's
+	 *    limitations as described in Stevens TCP/IP Illustrated
+	 *    Vol. 2 p.869. In such cases, we can still calculate the
+	 *    RTT correctly when RCV.NXT == Last.ACK.Sent.
+	 */
+
+	if ((to.to_flags & TOF_TS) != 0 &&
+	    SEQ_LEQ(th->th_seq, tp->last_ack_sent) &&
+	    SEQ_LEQ(tp->last_ack_sent, th->th_seq + tlen +
+		((thflags & (TH_SYN|TH_FIN)) != 0))) {
+		tp->ts_recent_age = tcp_ts_getticks();
+		tp->ts_recent = to.to_tsval;
+	}
+
+	/*
+	 * If the ACK bit is off:  if in SYN-RECEIVED state or SENDSYN
+	 * flag is on (half-synchronized state), then queue data for
+	 * later processing; else drop segment and return.
+	 */
+	if ((thflags & TH_ACK) == 0) {
+		if (tp->t_state == TCPS_SYN_RECEIVED ||
+		    (tp->t_flags & TF_NEEDSYN))
+			goto step6;
+		else if (tp->t_flags & TF_ACKNOW)
+			goto dropafterack;
+		else
+			goto drop;
+	}
+
+	tcplp_sys_log("Processing ACK");
+
+	/*
+	 * Ack processing.
+	 */
+	switch (tp->t_state) {
+
+	/*
+	 * In SYN_RECEIVED state, the ack ACKs our SYN, so enter
+	 * ESTABLISHED state and continue processing.
+	 * The ACK was checked above.
+	 */
+	case TCPS_SYN_RECEIVED:
+		/*
+		 * samkumar: Removed call to soisconnected(so), since TCPlp has its
+		 * own buffering.
+		 */
+		/* Do window scaling? */
+		if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
+			(TF_RCVD_SCALE|TF_REQ_SCALE)) {
+			tp->rcv_scale = tp->request_r_scale;
+			tp->snd_wnd = tiwin;
+		}
+		/*
+		 * Make transitions:
+		 *      SYN-RECEIVED  -> ESTABLISHED
+		 *      SYN-RECEIVED* -> FIN-WAIT-1
+		 */
+		tp->t_starttime = ticks;
+		if (tp->t_flags & TF_NEEDFIN) {
+			tcp_state_change(tp, TCPS_FIN_WAIT_1);
+			tp->t_flags &= ~TF_NEEDFIN;
+		} else {
+			tcp_state_change(tp, TCPS_ESTABLISHED);
+			/* samkumar: Set conn_established signal for TCPlp. */
+			sig->conn_established = true;
+			cc_conn_init(tp);
+			tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp));
+			/*
+			 * samkumar: I added this check to account for simultaneous open.
+			 * If this socket was opened actively, then the fact that we are
+			 * in SYN-RECEIVED indicates that we are in simultaneous open.
+			 * Therefore, don't ACK the SYN-ACK (unless it contains data or
+			 * something, which will be processed later).
+			 */
+			if (!tpispassiveopen(tp)) {
+				tp->t_flags &= ~TF_ACKNOW;
+			} else {
+				/*
+				 * samkumar: Otherwise, we entered the ESTABLISHED state by
+				 * accepting a connection, so call the appropriate callback in
+				 * TCPlp. TODO: consider using signals to handle this?
+				 */
+				 bool accepted = tcplp_sys_accepted_connection(tp->accepted_from, tp, &ip6->ip6_src, th->th_sport);
+				 if (!accepted) {
+					 rstreason = ECONNREFUSED;
+					 goto dropwithreset;
+				 }
+			 }
+		}
+		/*
+		 * If segment contains data or ACK, will call tcp_reass()
+		 * later; if not, do so now to pass queued data to user.
+		 */
+		if (tlen == 0 && (thflags & TH_FIN) == 0)
+			(void) tcp_reass(tp, (struct tcphdr *)0, 0,
+			    (otMessage*)0, 0, sig);
+
+		tp->snd_wl1 = th->th_seq - 1;
+		/* FALLTHROUGH */
+
+	/*
+	 * In ESTABLISHED state: drop duplicate ACKs; ACK out of range
+	 * ACKs.  If the ack is in the range
+	 *	tp->snd_una < th->th_ack <= tp->snd_max
+	 * then advance tp->snd_una to th->th_ack and drop
+	 * data from the retransmission queue.  If this ACK reflects
+	 * more up to date window information we update our window information.
+	 */
+	case TCPS_ESTABLISHED:
+	case TCPS_FIN_WAIT_1:
+	case TCPS_FIN_WAIT_2:
+	case TCPS_CLOSE_WAIT:
+	case TCPS_CLOSING:
+	case TCPS_LAST_ACK:
+		if (SEQ_GT(th->th_ack, tp->snd_max)) {
+			goto dropafterack;
+		}
+
+		if ((tp->t_flags & TF_SACK_PERMIT) &&
+		    ((to.to_flags & TOF_SACK) ||
+		     !TAILQ_EMPTY(&tp->snd_holes)))
+			tcp_sack_doack(tp, &to, th->th_ack);
+
+		if (SEQ_LEQ(th->th_ack, tp->snd_una)) {
+			if (tlen == 0 && tiwin == tp->snd_wnd) {
+				/*
+				 * If this is the first time we've seen a
+				 * FIN from the remote, this is not a
+				 * duplicate and it needs to be processed
+				 * normally.  This happens during a
+				 * simultaneous close.
+				 */
+				if ((thflags & TH_FIN) &&
+				    (TCPS_HAVERCVDFIN(tp->t_state) == 0)) {
+					tp->t_dupacks = 0;
+					break;
+				}
+				/*
+				 * If we have outstanding data (other than
+				 * a window probe), this is a completely
+				 * duplicate ack (ie, window info didn't
+				 * change and FIN isn't set),
+				 * the ack is the biggest we've
+				 * seen and we've seen exactly our rexmt
+				 * threshhold of them, assume a packet
+				 * has been dropped and retransmit it.
+				 * Kludge snd_nxt & the congestion
+				 * window so we send only this one
+				 * packet.
+				 *
+				 * We know we're losing at the current
+				 * window size so do congestion avoidance
+				 * (set ssthresh to half the current window
+				 * and pull our congestion window back to
+				 * the new ssthresh).
+				 *
+				 * Dup acks mean that packets have left the
+				 * network (they're now cached at the receiver)
+				 * so bump cwnd by the amount in the receiver
+				 * to keep a constant cwnd packets in the
+				 * network.
+				 *
+				 * When using TCP ECN, notify the peer that
+				 * we reduced the cwnd.
+				 */
+				if (!tcp_timer_active(tp, TT_REXMT) ||
+				    th->th_ack != tp->snd_una)
+					tp->t_dupacks = 0;
+				else if (++tp->t_dupacks > tcprexmtthresh ||
+				     IN_FASTRECOVERY(tp->t_flags)) {
+					cc_ack_received(tp, th, CC_DUPACK);
+					if ((tp->t_flags & TF_SACK_PERMIT) &&
+					    IN_FASTRECOVERY(tp->t_flags)) {
+						int awnd;
+
+						/*
+						 * Compute the amount of data in flight first.
+						 * We can inject new data into the pipe iff
+						 * we have less than 1/2 the original window's
+						 * worth of data in flight.
+						 */
+						awnd = (tp->snd_nxt - tp->snd_fack) +
+							tp->sackhint.sack_bytes_rexmit;
+						if (awnd < tp->snd_ssthresh) {
+							tp->snd_cwnd += tp->t_maxseg;
+							if (tp->snd_cwnd > tp->snd_ssthresh)
+								tp->snd_cwnd = tp->snd_ssthresh;
+						}
+					} else
+						tp->snd_cwnd += tp->t_maxseg;
+#ifdef INSTRUMENT_TCP
+					tcplp_sys_log("TCP DUPACK");
+#endif
+					(void) tcp_output(tp);
+					goto drop;
+				} else if (tp->t_dupacks == tcprexmtthresh) {
+					tcp_seq onxt = tp->snd_nxt;
+
+					/*
+					 * If we're doing sack, check to
+					 * see if we're already in sack
+					 * recovery. If we're not doing sack,
+					 * check to see if we're in newreno
+					 * recovery.
+					 */
+					if (tp->t_flags & TF_SACK_PERMIT) {
+						if (IN_FASTRECOVERY(tp->t_flags)) {
+							tp->t_dupacks = 0;
+							break;
+						}
+					} else {
+						if (SEQ_LEQ(th->th_ack,
+						    tp->snd_recover)) {
+							tp->t_dupacks = 0;
+							break;
+						}
+					}
+					/* Congestion signal before ack. */
+					cc_cong_signal(tp, th, CC_NDUPACK);
+					cc_ack_received(tp, th, CC_DUPACK);
+					tcp_timer_activate(tp, TT_REXMT, 0);
+					tp->t_rtttime = 0;
+
+#ifdef INSTRUMENT_TCP
+					tcplp_sys_log("TCP DUPACK_THRESH");
+#endif
+					if (tp->t_flags & TF_SACK_PERMIT) {
+						tp->sack_newdata = tp->snd_nxt;
+						tp->snd_cwnd = tp->t_maxseg;
+						(void) tcp_output(tp);
+						goto drop;
+					}
+
+					tp->snd_nxt = th->th_ack;
+					tp->snd_cwnd = tp->t_maxseg;
+					(void) tcp_output(tp);
+					tp->snd_cwnd = tp->snd_ssthresh +
+					     tp->t_maxseg *
+					     (tp->t_dupacks - tp->snd_limited);
+#ifdef INSTRUMENT_TCP
+					tcplp_sys_log("TCP SET_cwnd %d", (int) tp->snd_cwnd);
+#endif
+					if (SEQ_GT(onxt, tp->snd_nxt))
+						tp->snd_nxt = onxt;
+					goto drop;
+				} else if (V_tcp_do_rfc3042) {
+					/*
+					 * Process first and second duplicate
+					 * ACKs. Each indicates a segment
+					 * leaving the network, creating room
+					 * for more. Make sure we can send a
+					 * packet on reception of each duplicate
+					 * ACK by increasing snd_cwnd by one
+					 * segment. Restore the original
+					 * snd_cwnd after packet transmission.
+					 */
+					uint64_t oldcwnd;
+					tcp_seq oldsndmax;
+					uint32_t sent;
+					int avail;
+					cc_ack_received(tp, th, CC_DUPACK);
+					oldcwnd = tp->snd_cwnd;
+					oldsndmax = tp->snd_max;
+
+#ifdef INSTRUMENT_TCP
+					tcplp_sys_log("TCP LIM_TRANS");
+#endif
+
+					KASSERT(tp->t_dupacks == 1 ||
+					    tp->t_dupacks == 2,
+					    ("%s: dupacks not 1 or 2",
+					    __func__));
+					if (tp->t_dupacks == 1)
+						tp->snd_limited = 0;
+					tp->snd_cwnd =
+					    (tp->snd_nxt - tp->snd_una) +
+					    (tp->t_dupacks - tp->snd_limited) *
+					    tp->t_maxseg;
+					/*
+					 * Only call tcp_output when there
+					 * is new data available to be sent.
+					 * Otherwise we would send pure ACKs.
+					 */
+					/*
+					 * samkumar: Replace sbavail(&so->so_snd) with the call to
+					 * lbuf_used_space.
+					 */
+					avail = lbuf_used_space(&tp->sendbuf) -
+					    (tp->snd_nxt - tp->snd_una);
+					if (avail > 0)
+						(void) tcp_output(tp);
+					sent = tp->snd_max - oldsndmax;
+					if (sent > tp->t_maxseg) {
+						KASSERT((tp->t_dupacks == 2 &&
+						    tp->snd_limited == 0) ||
+						   (sent == tp->t_maxseg + 1 &&
+						    tp->t_flags & TF_SENTFIN),
+						    ("%s: sent too much",
+						    __func__));
+						tp->snd_limited = 2;
+					} else if (sent > 0)
+						++tp->snd_limited;
+					tp->snd_cwnd = oldcwnd;
+#ifdef INSTRUMENT_TCP
+					tcplp_sys_log("TCP RESET_cwnd %d", (int) tp->snd_cwnd);
+#endif
+					goto drop;
+				}
+			} else
+				tp->t_dupacks = 0;
+			break;
+		}
+
+		KASSERT(SEQ_GT(th->th_ack, tp->snd_una),
+		    ("%s: th_ack <= snd_una", __func__));
+
+		/*
+		 * If the congestion window was inflated to account
+		 * for the other side's cached packets, retract it.
+		 */
+		if (IN_FASTRECOVERY(tp->t_flags)) {
+			if (SEQ_LT(th->th_ack, tp->snd_recover)) {
+				if (tp->t_flags & TF_SACK_PERMIT)
+					tcp_sack_partialack(tp, th);
+				else
+					tcp_newreno_partial_ack(tp, th);
+			} else
+				cc_post_recovery(tp, th);
+		}
+
+		tp->t_dupacks = 0;
+		/*
+		 * If we reach this point, ACK is not a duplicate,
+		 *     i.e., it ACKs something we sent.
+		 */
+		if (tp->t_flags & TF_NEEDSYN) {
+			/*
+			 * T/TCP: Connection was half-synchronized, and our
+			 * SYN has been ACK'd (so connection is now fully
+			 * synchronized).  Go to non-starred state,
+			 * increment snd_una for ACK of SYN, and check if
+			 * we can do window scaling.
+			 */
+			tp->t_flags &= ~TF_NEEDSYN;
+			tp->snd_una++;
+			/* Do window scaling? */
+			if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
+				(TF_RCVD_SCALE|TF_REQ_SCALE)) {
+				tp->rcv_scale = tp->request_r_scale;
+				/* Send window already scaled. */
+			}
+		}
+
+process_ACK:
+		acked = BYTES_THIS_ACK(tp, th);
+
+		tcplp_sys_log("Bytes acked: %d", acked);
+		/*
+		 * If we just performed our first retransmit, and the ACK
+		 * arrives within our recovery window, then it was a mistake
+		 * to do the retransmit in the first place.  Recover our
+		 * original cwnd and ssthresh, and proceed to transmit where
+		 * we left off.
+		 */
+		if (tp->t_rxtshift == 1 && tp->t_flags & TF_PREVVALID &&
+		    (int)(ticks - tp->t_badrxtwin) < 0)
+			cc_cong_signal(tp, th, CC_RTO_ERR);
+
+		/*
+		 * If we have a timestamp reply, update smoothed
+		 * round trip time.  If no timestamp is present but
+		 * transmit timer is running and timed sequence
+		 * number was acked, update smoothed round trip time.
+		 * Since we now have an rtt measurement, cancel the
+		 * timer backoff (cf., Phil Karn's retransmit alg.).
+		 * Recompute the initial retransmit timer.
+		 *
+		 * Some boxes send broken timestamp replies
+		 * during the SYN+ACK phase, ignore
+		 * timestamps of 0 or we could calculate a
+		 * huge RTT and blow up the retransmit timer.
+		 */
+
+		if ((to.to_flags & TOF_TS) != 0 && to.to_tsecr) {
+			uint32_t t;
+
+			t = tcp_ts_getticks() - to.to_tsecr;
+			if (!tp->t_rttlow || tp->t_rttlow > t)
+				tp->t_rttlow = t;
+			tcp_xmit_timer(tp, TCP_TS_TO_TICKS(t) + 1);
+		} else if (tp->t_rtttime && SEQ_GT(th->th_ack, tp->t_rtseq)) {
+			if (!tp->t_rttlow || tp->t_rttlow > ticks - tp->t_rtttime)
+				tp->t_rttlow = ticks - tp->t_rtttime;
+			tcp_xmit_timer(tp, ticks - tp->t_rtttime);
+		}
+
+		/*
+		 * If all outstanding data is acked, stop retransmit
+		 * timer and remember to restart (more output or persist).
+		 * If there is more data to be acked, restart retransmit
+		 * timer, using current (possibly backed-off) value.
+		 */
+		if (th->th_ack == tp->snd_max) {
+			tcp_timer_activate(tp, TT_REXMT, 0);
+			needoutput = 1;
+		} else if (!tcp_timer_active(tp, TT_PERSIST)) {
+			tcp_timer_activate(tp, TT_REXMT, tp->t_rxtcur);
+		}
+
+		/*
+		 * If no data (only SYN) was ACK'd,
+		 *    skip rest of ACK processing.
+		 */
+		if (acked == 0)
+			goto step6;
+
+		/*
+		 * Let the congestion control algorithm update congestion
+		 * control related information. This typically means increasing
+		 * the congestion window.
+		 */
+		cc_ack_received(tp, th, CC_ACK);
+
+		/*
+		 * samkumar: I replaced the calls to sbavail(&so->so_snd) with new
+		 * calls to lbuf_used_space, and then I modified the code to actually
+		 * remove code from the send buffer, formerly done via
+		 * sbcut_locked(&so->so_send, (int)sbavail(&so->so_snd)) in the if case
+		 * and sbcut_locked(&so->so_snd, acked) in the else case, to use the
+		 * data structures for TCPlp's data buffering.
+		 */
+		if (acked > lbuf_used_space(&tp->sendbuf)) {
+			uint32_t poppedbytes;
+			uint32_t usedspace = lbuf_used_space(&tp->sendbuf);
+			tp->snd_wnd -= usedspace;
+			poppedbytes = lbuf_pop(&tp->sendbuf, usedspace, &sig->links_popped);
+			KASSERT(poppedbytes == usedspace, ("Could not fully empty send buffer"));
+			sig->bytes_acked += poppedbytes;
+			ourfinisacked = 1;
+		} else {
+			uint32_t poppedbytes = lbuf_pop(&tp->sendbuf, acked, &sig->links_popped);
+			KASSERT(poppedbytes == acked, ("Could not remove acked bytes from send buffer"));
+			sig->bytes_acked += poppedbytes;
+			tp->snd_wnd -= acked;
+			ourfinisacked = 0;
+		}
+		/* NB: sowwakeup_locked() does an implicit unlock. */
+		/*
+		 * samkumar: There used to be a call to sowwakeup(so); here,
+		 * which wakes up any threads waiting for the socket to
+		 * become ready for writing. TCPlp handles its send buffer
+		 * differently so we do not need to replace this call with
+		 * specialized code to handle this.
+		 */
+		/* Detect una wraparound. */
+		if (!IN_RECOVERY(tp->t_flags) &&
+		    SEQ_GT(tp->snd_una, tp->snd_recover) &&
+		    SEQ_LEQ(th->th_ack, tp->snd_recover))
+			tp->snd_recover = th->th_ack - 1;
+		/* XXXLAS: Can this be moved up into cc_post_recovery? */
+		if (IN_RECOVERY(tp->t_flags) &&
+		    SEQ_GEQ(th->th_ack, tp->snd_recover)) {
+			EXIT_RECOVERY(tp->t_flags);
+		}
+		tp->snd_una = th->th_ack;
+		if (tp->t_flags & TF_SACK_PERMIT) {
+			if (SEQ_GT(tp->snd_una, tp->snd_recover))
+				tp->snd_recover = tp->snd_una;
+		}
+		if (SEQ_LT(tp->snd_nxt, tp->snd_una))
+			tp->snd_nxt = tp->snd_una;
+
+		switch (tp->t_state) {
+
+		/*
+		 * In FIN_WAIT_1 STATE in addition to the processing
+		 * for the ESTABLISHED state if our FIN is now acknowledged
+		 * then enter FIN_WAIT_2.
+		 */
+		case TCPS_FIN_WAIT_1:
+			if (ourfinisacked) {
+				/*
+				 * If we can't receive any more
+				 * data, then closing user can proceed.
+				 * Starting the timer is contrary to the
+				 * specification, but if we don't get a FIN
+				 * we'll hang forever.
+				 *
+				 * XXXjl:
+				 * we should release the tp also, and use a
+				 * compressed state.
+				 */
+				/*
+				 * samkumar: I replaced a check for the SBS_CANTRCVMORE flag
+				 * in so->so_rcv.sb_state with a call to tcpiscantrcv.
+				 */
+				if (tpiscantrcv(tp)) {
+					/* samkumar: Removed a call to soisdisconnected(so). */
+					tcp_timer_activate(tp, TT_2MSL,
+					    (tcp_fast_finwait2_recycle ?
+					    tcp_finwait2_timeout :
+					    TP_MAXIDLE(tp)));
+				}
+				tcp_state_change(tp, TCPS_FIN_WAIT_2);
+			}
+			break;
+
+		/*
+		 * In CLOSING STATE in addition to the processing for
+		 * the ESTABLISHED state if the ACK acknowledges our FIN
+		 * then enter the TIME-WAIT state, otherwise ignore
+		 * the segment.
+		 */
+		case TCPS_CLOSING:
+			if (ourfinisacked) {
+				/*
+				 * samkumar: I added the line below. We need to avoid sending
+				 * an ACK in the TIME-WAIT state, since we don't want to
+				 * ACK ACKs. This edge case appears because TCPlp, unlike the
+				 * original FreeBSD code, uses tcpcbs for connections in the
+				 * TIME-WAIT state (FreeBSD uses a different, smaller
+				 * structure).
+				 */
+				tp->t_flags &= ~TF_ACKNOW;
+				tcp_twstart(tp);
+				return;
+			}
+			break;
+
+		/*
+		 * In LAST_ACK, we may still be waiting for data to drain
+		 * and/or to be acked, as well as for the ack of our FIN.
+		 * If our FIN is now acknowledged, delete the TCB,
+		 * enter the closed state and return.
+		 */
+		case TCPS_LAST_ACK:
+			if (ourfinisacked) {
+				tp = tcp_close(tp);
+				tcplp_sys_connection_lost(tp, CONN_LOST_NORMAL);
+				goto drop;
+			}
+			break;
+		}
+	}
+
+step6:
+
+	/*
+	 * Update window information.
+	 * Don't look at window if no ACK: TAC's send garbage on first SYN.
+	 */
+	if ((thflags & TH_ACK) &&
+	    (SEQ_LT(tp->snd_wl1, th->th_seq) ||
+	    (tp->snd_wl1 == th->th_seq && (SEQ_LT(tp->snd_wl2, th->th_ack) ||
+	     (tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd))))) {
+		/* keep track of pure window updates */
+		/*
+		 * samkumar: There used to be an if statement here that would check if
+		 * this is a "pure" window update (tlen == 0 &&
+		 * tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd) and keep
+		 * statistics for how often that happens.
+		 */
+		tp->snd_wnd = tiwin;
+		tp->snd_wl1 = th->th_seq;
+		tp->snd_wl2 = th->th_ack;
+		if (tp->snd_wnd > tp->max_sndwnd)
+			tp->max_sndwnd = tp->snd_wnd;
+		needoutput = 1;
+	}
+
+	/*
+	 * Process segments with URG.
+	 */
+	/*
+	 * samkumar: TCPlp does not support the urgent pointer, so we omit all
+	 * urgent-pointer-related processing and buffering. The code below is the
+	 * code that was in the "else" case that handles no valid urgent data in
+	 * the received packet.
+	 */
+	{
+		/*
+		 * If no out of band data is expected,
+		 * pull receive urgent pointer along
+		 * with the receive window.
+		 */
+		if (SEQ_GT(tp->rcv_nxt, tp->rcv_up))
+			tp->rcv_up = tp->rcv_nxt;
+	}
+
+	/*
+	 * Process the segment text, merging it into the TCP sequencing queue,
+	 * and arranging for acknowledgment of receipt if necessary.
+	 * This process logically involves adjusting tp->rcv_wnd as data
+	 * is presented to the user (this happens in tcp_usrreq.c,
+	 * case PRU_RCVD).  If a FIN has already been received on this
+	 * connection then we just ignore the text.
+	 */
+	if ((tlen || (thflags & TH_FIN)) &&
+	    TCPS_HAVERCVDFIN(tp->t_state) == 0) {
+		tcp_seq save_start = th->th_seq;
+		/*
+		 * samkumar: I removed a call to m_adj(m, drop_hdrlen), which intends
+		 * to drop data from the mbuf so it can be chained into the receive
+		 * header. This is not necessary for TCPlp because we copy the data
+		 * anyway; we just add the offset when copying data into the receive
+		 * buffer.
+		 */
+		/*
+		 * Insert segment which includes th into TCP reassembly queue
+		 * with control block tp.  Set thflags to whether reassembly now
+		 * includes a segment with FIN.  This handles the common case
+		 * inline (segment is the next to be received on an established
+		 * connection, and the queue is empty), avoiding linkage into
+		 * and removal from the queue and repetition of various
+		 * conversions.
+		 * Set DELACK for segments received in order, but ack
+		 * immediately when segments are out of order (so
+		 * fast retransmit can work).
+		 */
+		/*
+		 * samkumar: I replaced LIST_EMPTY(&tp->t_segq) with the calls to
+		 * tpiscantrcv and bmp_isempty on the second line below.
+		 */
+		if (th->th_seq == tp->rcv_nxt &&
+		    (tpiscantrcv(tp) || bmp_isempty(tp->reassbmp, REASSBMP_SIZE(tp))) &&
+		    TCPS_HAVEESTABLISHED(tp->t_state)) {
+			if (DELAY_ACK(tp, tlen))
+				tp->t_flags |= TF_DELACK;
+			else
+				tp->t_flags |= TF_ACKNOW;
+			tp->rcv_nxt += tlen;
+			thflags = th->th_flags & TH_FIN;
+
+			/*
+			 * samkumar: I replaced the code that used to be here (which would
+			 * free the mbuf with m_freem(m) if the SBS_CANTRCVMORE flag is set
+			 * on so->so_rcv.sb_state, and otherwise call
+			 * sbappendstream_locked(&so->so_rcv, m, 0);).
+			 */
+			if (!tpiscantrcv(tp)) {
+				cbuf_write(&tp->recvbuf, msg, otMessageGetOffset(msg) + drop_hdrlen, tlen, cbuf_copy_from_message);
+				if (tlen > 0) {
+					sig->recvbuf_added = true;
+				}
+			} else if (tlen > 0) {
+				/*
+				 * samkumar: We already know tlen != 0, so if we got here, then
+				 * it means that we got data after we called SHUT_RD, or after
+				 * receiving a FIN. I'm going to drop the connection in this
+				 * case. I think FreeBSD might have just dropped the packet
+				 * silently, but Linux handles it this way; this seems to be
+				 * the right approach to me.
+				 */
+				tcp_drop(tp, ECONNABORTED);
+				goto drop;
+			}
+			/* NB: sorwakeup_locked() does an implicit unlock. */
+			/*
+			 * samkumar: There used to be a call to sorwakeup_locked(so); here,
+			 * which wakes up any threads waiting for the socket to become
+			 * become ready for reading. TCPlp handles its buffering
+			 * differently so we do not need to replace this call with
+			 * specialized code to handle this.
+			 */
+		} else if (tpiscantrcv(tp)) {
+			/*
+			 * samkumar: We will reach this point if we get out-of-order data
+			 * on a socket which was shut down with SHUT_RD, or where we
+			 * already received a FIN. My response here is to drop the segment
+			 * and send an RST.
+			 */
+			tcp_drop(tp, ECONNABORTED);
+			goto drop;
+		} else {
+			/*
+			 * XXX: Due to the header drop above "th" is
+			 * theoretically invalid by now.  Fortunately
+			 * m_adj() doesn't actually frees any mbufs
+			 * when trimming from the head.
+			 */
+			thflags = tcp_reass(tp, th, &tlen, msg, otMessageGetOffset(msg) + drop_hdrlen, sig);
+			tp->t_flags |= TF_ACKNOW;
+		}
+		// Only place tlen is used after the call to tcp_reass is below
+		if (tlen > 0 && (tp->t_flags & TF_SACK_PERMIT))
+			tcp_update_sack_list(tp, save_start, save_start + tlen);
+		/*
+		 * samkumar: This is not me commenting things out; this was already
+		 * commented out in the FreeBSD code.
+		 */
+#if 0
+		/*
+		 * Note the amount of data that peer has sent into
+		 * our window, in order to estimate the sender's
+		 * buffer size.
+		 * XXX: Unused.
+		 */
+		if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt))
+			len = so->so_rcv.sb_hiwat - (tp->rcv_adv - tp->rcv_nxt);
+		else
+			len = so->so_rcv.sb_hiwat;
+#endif
+	} else {
+		thflags &= ~TH_FIN;
+	}
+
+	/*
+	 * If FIN is received ACK the FIN and let the user know
+	 * that the connection is closing.
+	 */
+	if (thflags & TH_FIN) {
+		tcplp_sys_log("FIN Processing start");
+		if (TCPS_HAVERCVDFIN(tp->t_state) == 0) {
+			/* samkumar: replace socantrcvmore with tpcantrcvmore */
+			tpcantrcvmore(tp);
+			/*
+			 * If connection is half-synchronized
+			 * (ie NEEDSYN flag on) then delay ACK,
+			 * so it may be piggybacked when SYN is sent.
+			 * Otherwise, since we received a FIN then no
+			 * more input can be expected, send ACK now.
+			 */
+			if (tp->t_flags & TF_NEEDSYN)
+				tp->t_flags |= TF_DELACK;
+			else
+				tp->t_flags |= TF_ACKNOW;
+			tp->rcv_nxt++;
+		}
+		/*
+		 * samkumar: This -2 state is added by me, so that we do not consider
+		 * any more FINs in reassembly.
+		 */
+		if (tp->reass_fin_index != -2) {
+			sig->rcvd_fin = true;
+			tp->reass_fin_index = -2;
+		}
+		switch (tp->t_state) {
+
+		/*
+		 * In SYN_RECEIVED and ESTABLISHED STATES
+		 * enter the CLOSE_WAIT state.
+		 */
+		case TCPS_SYN_RECEIVED:
+			tp->t_starttime = ticks;
+			/* FALLTHROUGH */
+		case TCPS_ESTABLISHED:
+			tcp_state_change(tp, TCPS_CLOSE_WAIT);
+			break;
+
+		/*
+		 * If still in FIN_WAIT_1 STATE FIN has not been acked so
+		 * enter the CLOSING state.
+		 */
+		case TCPS_FIN_WAIT_1:
+			tcp_state_change(tp, TCPS_CLOSING);
+			break;
+
+		/*
+		 * In FIN_WAIT_2 state enter the TIME_WAIT state,
+		 * starting the time-wait timer, turning off the other
+		 * standard timers.
+		 */
+		case TCPS_FIN_WAIT_2:
+			tcp_twstart(tp);
+			return;
+		}
+	}
+
+	/*
+	 * samkumar: Remove code for synchronization and debugging, here and in
+	 * the labels below. I also removed the line to free the mbuf if it hasn't
+	 * been freed already (the line was "m_freem(m)").
+	 */
+	/*
+	 * Return any desired output.
+	 */
+	if (needoutput || (tp->t_flags & TF_ACKNOW))
+		(void) tcp_output(tp);
+
+check_delack:
+	if (tp->t_flags & TF_DELACK) {
+		tp->t_flags &= ~TF_DELACK;
+		tcp_timer_activate(tp, TT_DELACK, tcp_delacktime);
+	}
+	return;
+
+dropafterack:
+	/*
+	 * Generate an ACK dropping incoming segment if it occupies
+	 * sequence space, where the ACK reflects our state.
+	 *
+	 * We can now skip the test for the RST flag since all
+	 * paths to this code happen after packets containing
+	 * RST have been dropped.
+	 *
+	 * In the SYN-RECEIVED state, don't send an ACK unless the
+	 * segment we received passes the SYN-RECEIVED ACK test.
+	 * If it fails send a RST.  This breaks the loop in the
+	 * "LAND" DoS attack, and also prevents an ACK storm
+	 * between two listening ports that have been sent forged
+	 * SYN segments, each with the source address of the other.
+	 */
+	if (tp->t_state == TCPS_SYN_RECEIVED && (thflags & TH_ACK) &&
+	    (SEQ_GT(tp->snd_una, th->th_ack) ||
+	     SEQ_GT(th->th_ack, tp->snd_max)) ) {
+		rstreason = BANDLIM_RST_OPENPORT;
+		goto dropwithreset;
+	}
+
+	tp->t_flags |= TF_ACKNOW;
+	(void) tcp_output(tp);
+	return;
+
+dropwithreset:
+	if (tp != NULL) {
+		tcp_dropwithreset(ip6, th, tp, instance, tlen, rstreason);
+	} else
+		tcp_dropwithreset(ip6, th, NULL, instance, tlen, rstreason);
+	return;
+
+drop:
+	return;
+}
+
+/*
+ * Parse TCP options and place in tcpopt.
+ */
+static void
+tcp_dooptions(struct tcpopt *to, uint8_t *cp, int cnt, int flags)
+{
+	int opt, optlen;
+
+	to->to_flags = 0;
+	for (; cnt > 0; cnt -= optlen, cp += optlen) {
+		opt = cp[0];
+		if (opt == TCPOPT_EOL)
+			break;
+		if (opt == TCPOPT_NOP)
+			optlen = 1;
+		else {
+			if (cnt < 2)
+				break;
+			optlen = cp[1];
+			if (optlen < 2 || optlen > cnt)
+				break;
+		}
+		switch (opt) {
+		case TCPOPT_MAXSEG:
+			if (optlen != TCPOLEN_MAXSEG)
+				continue;
+			if (!(flags & TO_SYN))
+				continue;
+			to->to_flags |= TOF_MSS;
+			bcopy((char *)cp + 2,
+			    (char *)&to->to_mss, sizeof(to->to_mss));
+			to->to_mss = ntohs(to->to_mss);
+			break;
+		case TCPOPT_WINDOW:
+			if (optlen != TCPOLEN_WINDOW)
+				continue;
+			if (!(flags & TO_SYN))
+				continue;
+			to->to_flags |= TOF_SCALE;
+			to->to_wscale = min(cp[2], TCP_MAX_WINSHIFT);
+			break;
+		case TCPOPT_TIMESTAMP:
+			if (optlen != TCPOLEN_TIMESTAMP)
+				continue;
+			to->to_flags |= TOF_TS;
+			bcopy((char *)cp + 2,
+			    (char *)&to->to_tsval, sizeof(to->to_tsval));
+			to->to_tsval = ntohl(to->to_tsval);
+			bcopy((char *)cp + 6,
+			    (char *)&to->to_tsecr, sizeof(to->to_tsecr));
+			to->to_tsecr = ntohl(to->to_tsecr);
+			break;
+#ifdef TCP_SIGNATURE
+		/*
+		 * XXX In order to reply to a host which has set the
+		 * TCP_SIGNATURE option in its initial SYN, we have to
+		 * record the fact that the option was observed here
+		 * for the syncache code to perform the correct response.
+		 */
+		case TCPOPT_SIGNATURE:
+			if (optlen != TCPOLEN_SIGNATURE)
+				continue;
+			to->to_flags |= TOF_SIGNATURE;
+			to->to_signature = cp + 2;
+			break;
+#endif
+		case TCPOPT_SACK_PERMITTED:
+			if (optlen != TCPOLEN_SACK_PERMITTED)
+				continue;
+			if (!(flags & TO_SYN))
+				continue;
+			if (!V_tcp_do_sack)
+				continue;
+			to->to_flags |= TOF_SACKPERM;
+			break;
+		case TCPOPT_SACK:
+			if (optlen <= 2 || (optlen - 2) % TCPOLEN_SACK != 0)
+				continue;
+			if (flags & TO_SYN)
+				continue;
+			to->to_flags |= TOF_SACK;
+			to->to_nsacks = (optlen - 2) / TCPOLEN_SACK;
+			to->to_sacks = cp + 2;
+			break;
+		default:
+			continue;
+		}
+	}
+}
+
+
+/*
+ * Collect new round-trip time estimate
+ * and update averages and current timeout.
+ */
+static void
+tcp_xmit_timer(struct tcpcb *tp, int rtt)
+{
+	int delta;
+
+	tp->t_rttupdated++;
+	if (tp->t_srtt != 0) {
+		/*
+		 * srtt is stored as fixed point with 5 bits after the
+		 * binary point (i.e., scaled by 8).  The following magic
+		 * is equivalent to the smoothing algorithm in rfc793 with
+		 * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed
+		 * point).  Adjust rtt to origin 0.
+		 */
+		delta = ((rtt - 1) << TCP_DELTA_SHIFT)
+			- (tp->t_srtt >> (TCP_RTT_SHIFT - TCP_DELTA_SHIFT));
+
+		if ((tp->t_srtt += delta) <= 0)
+			tp->t_srtt = 1;
+
+		/*
+		 * We accumulate a smoothed rtt variance (actually, a
+		 * smoothed mean difference), then set the retransmit
+		 * timer to smoothed rtt + 4 times the smoothed variance.
+		 * rttvar is stored as fixed point with 4 bits after the
+		 * binary point (scaled by 16).  The following is
+		 * equivalent to rfc793 smoothing with an alpha of .75
+		 * (rttvar = rttvar*3/4 + |delta| / 4).  This replaces
+		 * rfc793's wired-in beta.
+		 */
+		if (delta < 0)
+			delta = -delta;
+		delta -= tp->t_rttvar >> (TCP_RTTVAR_SHIFT - TCP_DELTA_SHIFT);
+		if ((tp->t_rttvar += delta) <= 0)
+			tp->t_rttvar = 1;
+		if (tp->t_rttbest > tp->t_srtt + tp->t_rttvar)
+		    tp->t_rttbest = tp->t_srtt + tp->t_rttvar;
+	} else {
+		/*
+		 * No rtt measurement yet - use the unsmoothed rtt.
+		 * Set the variance to half the rtt (so our first
+		 * retransmit happens at 3*rtt).
+		 */
+		tp->t_srtt = rtt << TCP_RTT_SHIFT;
+		tp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT - 1);
+		tp->t_rttbest = tp->t_srtt + tp->t_rttvar;
+	}
+	tp->t_rtttime = 0;
+	tp->t_rxtshift = 0;
+
+	/*
+	 * the retransmit should happen at rtt + 4 * rttvar.
+	 * Because of the way we do the smoothing, srtt and rttvar
+	 * will each average +1/2 tick of bias.  When we compute
+	 * the retransmit timer, we want 1/2 tick of rounding and
+	 * 1 extra tick because of +-1/2 tick uncertainty in the
+	 * firing of the timer.  The bias will give us exactly the
+	 * 1.5 tick we need.  But, because the bias is
+	 * statistical, we have to test that we don't drop below
+	 * the minimum feasible timer (which is 2 ticks).
+	 */
+	TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp),
+		      max(tp->t_rttmin, rtt + 2), TCPTV_REXMTMAX);
+
+#ifdef INSTRUMENT_TCP
+	tcplp_sys_log("TCP timer %u %d %d %d", (unsigned int) tcplp_sys_get_millis(), rtt, (int) tp->t_srtt, (int) tp->t_rttvar);
+#endif
+
+
+	/*
+	 * We received an ack for a packet that wasn't retransmitted;
+	 * it is probably safe to discard any error indications we've
+	 * received recently.  This isn't quite right, but close enough
+	 * for now (a route might have failed after we sent a segment,
+	 * and the return path might not be symmetrical).
+	 */
+	tp->t_softerror = 0;
+}
+
+/*
+ * samkumar: Taken from netinet6/in6.c.
+ *
+ * This function is supposed to check whether the provided address is an
+ * IPv6 address of this host. This function, however, is used only as a hint,
+ * as the MSS is clamped at V_tcp_v6mssdflt for connections to non-local
+ * addresses. It is difficult for us to actually determine if the address
+ * belongs to us, so we are conservative and only return 1 (true) if it is
+ * obviously so---we keep the part of the function that checks for loopback or
+ * link local and remove the rest of the code that checks for the addresses
+ * assigned to interfaces. In cases where we return 0 but should have returned
+ * 1, we may conservatively clamp the MTU, but that should be OK for TCPlp.
+ * In fact, the constants are set such that we'll get the right answer whether
+ * we clamp or not, so this shouldn't really matter at all.
+ */
+int
+in6_localaddr(struct in6_addr *in6)
+{
+	if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_ADDR_LINKLOCAL(in6))
+		return 1;
+	return (0);
+}
+
+/*
+ * Determine a reasonable value for maxseg size.
+ * If the route is known, check route for mtu.
+ * If none, use an mss that can be handled on the outgoing interface
+ * without forcing IP to fragment.  If no route is found, route has no mtu,
+ * or the destination isn't local, use a default, hopefully conservative
+ * size (usually 512 or the default IP max size, but no more than the mtu
+ * of the interface), as we can't discover anything about intervening
+ * gateways or networks.  We also initialize the congestion/slow start
+ * window to be a single segment if the destination isn't local.
+ * While looking at the routing entry, we also initialize other path-dependent
+ * parameters from pre-set or cached values in the routing entry.
+ *
+ * Also take into account the space needed for options that we
+ * send regularly.  Make maxseg shorter by that amount to assure
+ * that we can send maxseg amount of data even when the options
+ * are present.  Store the upper limit of the length of options plus
+ * data in maxopd.
+ *
+ * NOTE that this routine is only called when we process an incoming
+ * segment, or an ICMP need fragmentation datagram. Outgoing SYN/ACK MSS
+ * settings are handled in tcp_mssopt().
+ */
+/*
+ * samkumar: Using struct tcpcb instead of the inpcb.
+ */
+void
+tcp_mss_update(struct tcpcb *tp, int offer, int mtuoffer,
+    struct hc_metrics_lite *metricptr, struct tcp_ifcap *cap)
+{
+	/*
+	 * samkumar: I removed all IPv4-specific logic and cases, including logic
+	 * to check for IPv4 vs. IPv6, as well as all locking and debugging code.
+	 */
+	int mss = 0;
+	uint64_t maxmtu = 0;
+	struct hc_metrics_lite metrics;
+	int origoffer;
+	size_t min_protoh = IP6HDR_SIZE + sizeof (struct tcphdr);
+
+	if (mtuoffer != -1) {
+		KASSERT(offer == -1, ("%s: conflict", __func__));
+		offer = mtuoffer - min_protoh;
+	}
+	origoffer = offer;
+
+	maxmtu = tcp_maxmtu6(tp, cap);
+	tp->t_maxopd = tp->t_maxseg = V_tcp_v6mssdflt;
+
+	/*
+	 * No route to sender, stay with default mss and return.
+	 */
+	if (maxmtu == 0) {
+		/*
+		 * In case we return early we need to initialize metrics
+		 * to a defined state as tcp_hc_get() would do for us
+		 * if there was no cache hit.
+		 */
+		if (metricptr != NULL)
+			bzero(metricptr, sizeof(struct hc_metrics_lite));
+		return;
+	}
+
+	/* What have we got? */
+	switch (offer) {
+		case 0:
+			/*
+			 * Offer == 0 means that there was no MSS on the SYN
+			 * segment, in this case we use tcp_mssdflt as
+			 * already assigned to t_maxopd above.
+			 */
+			offer = tp->t_maxopd;
+			break;
+
+		case -1:
+			/*
+			 * Offer == -1 means that we didn't receive SYN yet.
+			 */
+			/* FALLTHROUGH */
+
+		default:
+			/*
+			 * Prevent DoS attack with too small MSS. Round up
+			 * to at least minmss.
+			 */
+			offer = max(offer, V_tcp_minmss);
+	}
+
+	/*
+	 * rmx information is now retrieved from tcp_hostcache.
+	 */
+	tcp_hc_get(tp, &metrics);
+	if (metricptr != NULL)
+		bcopy(&metrics, metricptr, sizeof(struct hc_metrics_lite));
+
+	/*
+	 * If there's a discovered mtu in tcp hostcache, use it.
+	 * Else, use the link mtu.
+	 */
+	if (metrics.rmx_mtu)
+		mss = min(metrics.rmx_mtu, maxmtu) - min_protoh;
+	else {
+		mss = maxmtu - min_protoh;
+		if (!V_path_mtu_discovery &&
+		    !in6_localaddr(&tp->faddr))
+			mss = min(mss, V_tcp_v6mssdflt);
+		/*
+		 * XXX - The above conditional (mss = maxmtu - min_protoh)
+		 * probably violates the TCP spec.
+		 * The problem is that, since we don't know the
+		 * other end's MSS, we are supposed to use a conservative
+		 * default.  But, if we do that, then MTU discovery will
+		 * never actually take place, because the conservative
+		 * default is much less than the MTUs typically seen
+		 * on the Internet today.  For the moment, we'll sweep
+		 * this under the carpet.
+		 *
+		 * The conservative default might not actually be a problem
+		 * if the only case this occurs is when sending an initial
+		 * SYN with options and data to a host we've never talked
+		 * to before.  Then, they will reply with an MSS value which
+		 * will get recorded and the new parameters should get
+		 * recomputed.  For Further Study.
+		 */
+	}
+	mss = min(mss, offer);
+
+	/*
+	 * Sanity check: make sure that maxopd will be large
+	 * enough to allow some data on segments even if the
+	 * all the option space is used (40bytes).  Otherwise
+	 * funny things may happen in tcp_output.
+	 */
+	/*
+	 * samkumar: When I was experimenting with different MSS values, I had
+	 * changed this to "mss = max(mss, TCP_MAXOLEN + 1);" but I am changing it
+	 * back for the version that will be merged into OpenThread.
+	 */
+	mss = max(mss, 64);
+
+	/*
+	 * maxopd stores the maximum length of data AND options
+	 * in a segment; maxseg is the amount of data in a normal
+	 * segment.  We need to store this value (maxopd) apart
+	 * from maxseg, because now every segment carries options
+	 * and thus we normally have somewhat less data in segments.
+	 */
+	tp->t_maxopd = mss;
+
+	/*
+	 * origoffer==-1 indicates that no segments were received yet.
+	 * In this case we just guess.
+	 */
+	if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
+	    (origoffer == -1 ||
+	     (tp->t_flags & TF_RCVD_TSTMP) == TF_RCVD_TSTMP))
+		mss -= TCPOLEN_TSTAMP_APPA;
+
+	tp->t_maxseg = mss;
+}
+
+void
+tcp_mss(struct tcpcb *tp, int offer)
+{
+	struct hc_metrics_lite metrics;
+	struct tcp_ifcap cap;
+
+	KASSERT(tp != NULL, ("%s: tp == NULL", __func__));
+
+	bzero(&cap, sizeof(cap));
+	tcp_mss_update(tp, offer, -1, &metrics, &cap);
+
+	/*
+	 * samkumar: There used to be code below that might modify the MSS, but I
+	 * removed all of it (see the comments below for the reason). It used to
+	 * read tp->t_maxseg into the local variable mss, modify mss, and then
+	 * reassign tp->t_maxseg to mss. I've kept the assignments, commented out,
+	 * for clarity.
+	 */
+	//mss = tp->t_maxseg;
+
+	/*
+	 * If there's a pipesize, change the socket buffer to that size,
+	 * don't change if sb_hiwat is different than default (then it
+	 * has been changed on purpose with setsockopt).
+	 * Make the socket buffers an integral number of mss units;
+	 * if the mss is larger than the socket buffer, decrease the mss.
+	 */
+
+	/*
+	 * samkumar: There used to be code here would would limit the MSS to at
+	 * most the size of the send buffer, and then round up the send buffer to
+	 * a multiple of the MSS using
+	 * "sbreserve_locked(&so->so_snd, bufsize, so, NULL);". With TCPlp, we do
+	 * not do this, because the linked buffer used at the send buffer doesn't
+	 * have a real limit. Had we used a circular buffer, then limiting the MSS
+	 * to the buffer size would have made sense, but we still would not be able
+	 * to resize the send buffer because it is not allocated by TCPlp.
+	 */
+
+	/*
+	 * samkumar: See the comment above about me removing code that modifies
+	 * the MSS, making this assignment and the one above both unnecessary.
+	 */
+	//tp->t_maxseg = mss;
+
+	/*
+	 * samkumar: There used to be code here that would round up the receive
+	 * buffer size to a multiple of the MSS, assuming that the receive buffer
+	 * size is bigger than the MSS. The new buffer size is set using
+	 * "sbreserve_locked(&so->so_rcv, bufsize, so, NULL);". In TCPlp, the
+	 * buffer is not allocated by TCPlp so I removed the code for this.
+	 */
+	/*
+	 * samkumar: There used to be code here to handle TCP Segmentation
+	 * Offloading (TSO); I removed it becuase we don't support that in TCPlp.
+	 */
+}
+
+/*
+ * Determine the MSS option to send on an outgoing SYN.
+ */
+/*
+ * samkumar: In the signature, changed "struct in_conninfo *inc" to
+ * "struct tcpcb* tp".
+ */
+int
+tcp_mssopt(struct tcpcb* tp)
+{
+	/*
+	 * samkumar: I removed all processing code specific to IPv4, or to decide
+	 * between IPv4 and IPv6. This is OK because TCPlp assumes IPv6.
+	 */
+	int mss = 0;
+	uint64_t maxmtu = 0;
+	uint64_t thcmtu = 0;
+	size_t min_protoh;
+
+	KASSERT(tp != NULL, ("tcp_mssopt with NULL tcpcb pointer"));
+
+	mss = V_tcp_v6mssdflt;
+	maxmtu = tcp_maxmtu6(tp, NULL);
+	min_protoh = IP6HDR_SIZE + sizeof(struct tcphdr);
+
+	thcmtu = tcp_hc_getmtu(tp); /* IPv4 and IPv6 */
+
+	if (maxmtu && thcmtu)
+		mss = min(maxmtu, thcmtu) - min_protoh;
+	else if (maxmtu || thcmtu)
+		mss = max(maxmtu, thcmtu) - min_protoh;
+
+	return (mss);
+}
+
+/*
+ * On a partial ack arrives, force the retransmission of the
+ * next unacknowledged segment.  Do not clear tp->t_dupacks.
+ * By setting snd_nxt to ti_ack, this forces retransmission timer to
+ * be started again.
+ */
+static void
+tcp_newreno_partial_ack(struct tcpcb *tp, struct tcphdr *th)
+{
+	tcp_seq onxt = tp->snd_nxt;
+	uint64_t  ocwnd = tp->snd_cwnd;
+
+	tcp_timer_activate(tp, TT_REXMT, 0);
+	tp->t_rtttime = 0;
+	tp->snd_nxt = th->th_ack;
+	/*
+	 * Set snd_cwnd to one segment beyond acknowledged offset.
+	 * (tp->snd_una has not yet been updated when this function is called.)
+	 */
+	tp->snd_cwnd = tp->t_maxseg + BYTES_THIS_ACK(tp, th);
+	tp->t_flags |= TF_ACKNOW;
+#ifdef INSTRUMENT_TCP
+	tcplp_sys_log("TCP Partial_ACK");
+#endif
+	(void) tcp_output(tp);
+	tp->snd_cwnd = ocwnd;
+	if (SEQ_GT(onxt, tp->snd_nxt))
+		tp->snd_nxt = onxt;
+	/*
+	 * Partial window deflation.  Relies on fact that tp->snd_una
+	 * not updated yet.
+	 */
+	if (tp->snd_cwnd > BYTES_THIS_ACK(tp, th))
+		tp->snd_cwnd -= BYTES_THIS_ACK(tp, th);
+	else
+		tp->snd_cwnd = 0;
+	tp->snd_cwnd += tp->t_maxseg;
+#ifdef INSTRUMENT_TCP
+	tcplp_sys_log("TCP Partial_ACK_final %d", (int) tp->snd_cwnd);
+#endif
+}
diff --git a/third_party/tcplp/bsdtcp/tcp_output.c b/third_party/tcplp/bsdtcp/tcp_output.c
new file mode 100644
index 0000000..0e4f2fd
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/tcp_output.c
@@ -0,0 +1,1480 @@
+/*-
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)tcp_output.c	8.4 (Berkeley) 5/24/95
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include "../tcplp.h"
+#include "tcp.h"
+#include "tcp_fsm.h"
+#include "tcp_var.h"
+#include "tcp_seq.h"
+#include "tcp_timer.h"
+#include "ip.h"
+#include "../lib/cbuf.h"
+
+#include "tcp_const.h"
+
+#include <openthread/ip6.h>
+#include <openthread/message.h>
+#include <openthread/tcp.h>
+
+static inline void
+cc_after_idle(struct tcpcb *tp)
+{
+	/* samkumar: Removed synchronization. */
+	if (CC_ALGO(tp)->after_idle != NULL)
+		CC_ALGO(tp)->after_idle(tp->ccv);
+}
+
+long min(long a, long b) {
+	if (a < b) {
+		return a;
+	} else {
+		return b;
+	}
+}
+
+unsigned long ulmin(unsigned long a, unsigned long b) {
+	if (a < b) {
+		return a;
+	} else {
+		return b;
+	}
+}
+
+#define lmin(a, b) min(a, b)
+
+void
+tcp_setpersist(struct tcpcb *tp)
+{
+	int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;
+	int tt;
+
+	tp->t_flags &= ~TF_PREVVALID;
+	if (tcp_timer_active(tp, TT_REXMT))
+		tcplp_sys_panic("PANIC: tcp_setpersist: retransmit pending");
+	/*
+	 * Start/restart persistance timer.
+	 */
+	TCPT_RANGESET(tt, t * tcp_backoff[tp->t_rxtshift],
+		      TCPTV_PERSMIN, TCPTV_PERSMAX);
+	tcp_timer_activate(tp, TT_PERSIST, tt);
+	if (tp->t_rxtshift < TCP_MAXRXTSHIFT)
+		tp->t_rxtshift++;
+}
+
+/*
+ * Tcp output routine: figure out what should be sent and send it.
+ */
+int
+tcp_output(struct tcpcb *tp)
+{
+	/*
+	 * samkumar: The biggest change in this function is in how outgoing
+	 * segments are built and sent out. That code has been updated to account
+	 * for TCPlp's buffering, and using otMessages rather than mbufs to
+	 * construct the outgoing segments.
+	 *
+	 * And, of course, all code corresponding to locks, stats, and debugging
+	 * has been removed, and all code specific to IPv4 or to decide between
+	 * IPv6 and IPv4 handling has been removed.
+	 */
+
+	struct tcphdr* th = NULL;
+	int idle;
+	long len, recwin, sendwin;
+	int off, flags, error = 0;	/* Keep compiler happy */
+	int sendalot, mtu;
+	int sack_rxmit, sack_bytes_rxmt;
+	struct sackhole* p;
+	unsigned ipoptlen, optlen, hdrlen;
+	struct tcpopt to;
+	uint8_t opt[TCP_MAXOLEN];
+	uint32_t ticks = tcplp_sys_get_ticks();
+
+	/* samkumar: Code for TCP offload has been removed. */
+
+	/*
+	 * Determine length of data that should be transmitted,
+	 * and flags that will be used.
+	 * If there is some data or critical controls (SYN, RST)
+	 * to send, then transmit; otherwise, investigate further.
+	 */
+	idle = (tp->t_flags & TF_LASTIDLE) || (tp->snd_max == tp->snd_una);
+	if (idle && ticks - tp->t_rcvtime >= tp->t_rxtcur)
+		cc_after_idle(tp);
+
+	tp->t_flags &= ~TF_LASTIDLE;
+	if (idle) {
+		if (tp->t_flags & TF_MORETOCOME) {
+			tp->t_flags |= TF_LASTIDLE;
+			idle = 0;
+		}
+	}
+	/* samkumar: This would be printed once per _window_ that is transmitted. */
+#ifdef INSTRUMENT_TCP
+	tcplp_sys_log("TCP output %u %d %d", (unsigned int) tcplp_sys_get_millis(), (int) tp->snd_wnd, (int) tp->snd_cwnd);
+#endif
+
+again:
+	/*
+	 * If we've recently taken a timeout, snd_max will be greater than
+	 * snd_nxt.  There may be SACK information that allows us to avoid
+	 * resending already delivered data.  Adjust snd_nxt accordingly.
+	 */
+	if ((tp->t_flags & TF_SACK_PERMIT) &&
+	    SEQ_LT(tp->snd_nxt, tp->snd_max))
+		tcp_sack_adjust(tp);
+	sendalot = 0;
+	/* samkumar: Removed code for supporting TSO. */
+	mtu = 0;
+	off = tp->snd_nxt - tp->snd_una;
+	sendwin = min(tp->snd_wnd, tp->snd_cwnd);
+
+	flags = tcp_outflags[tp->t_state];
+	/*
+	 * Send any SACK-generated retransmissions.  If we're explicitly trying
+	 * to send out new data (when sendalot is 1), bypass this function.
+	 * If we retransmit in fast recovery mode, decrement snd_cwnd, since
+	 * we're replacing a (future) new transmission with a retransmission
+	 * now, and we previously incremented snd_cwnd in tcp_input().
+	 */
+	/*
+	 * Still in sack recovery , reset rxmit flag to zero.
+	 */
+	sack_rxmit = 0;
+	sack_bytes_rxmt = 0;
+	len = 0;
+	p = NULL;
+	if ((tp->t_flags & TF_SACK_PERMIT) && IN_FASTRECOVERY(tp->t_flags) &&
+	    (p = tcp_sack_output(tp, &sack_bytes_rxmt))) {
+		long cwin;
+
+		cwin = min(tp->snd_wnd, tp->snd_cwnd) - sack_bytes_rxmt;
+		if (cwin < 0)
+			cwin = 0;
+		/* Do not retransmit SACK segments beyond snd_recover */
+		if (SEQ_GT(p->end, tp->snd_recover)) {
+			/*
+			 * (At least) part of sack hole extends beyond
+			 * snd_recover. Check to see if we can rexmit data
+			 * for this hole.
+			 */
+			if (SEQ_GEQ(p->rxmit, tp->snd_recover)) {
+				/*
+				 * Can't rexmit any more data for this hole.
+				 * That data will be rexmitted in the next
+				 * sack recovery episode, when snd_recover
+				 * moves past p->rxmit.
+				 */
+				p = NULL;
+				goto after_sack_rexmit;
+			} else
+				/* Can rexmit part of the current hole */
+				len = ((long)ulmin(cwin,
+						   tp->snd_recover - p->rxmit));
+		} else
+			len = ((long)ulmin(cwin, p->end - p->rxmit));
+		off = p->rxmit - tp->snd_una;
+		KASSERT(off >= 0,("%s: sack block to the left of una : %d",
+		    __func__, off));
+		if (len > 0) {
+			sack_rxmit = 1;
+			sendalot = 1;
+		}
+	}
+after_sack_rexmit:
+	/*
+	 * Get standard flags, and add SYN or FIN if requested by 'hidden'
+	 * state flags.
+	 */
+	if (tp->t_flags & TF_NEEDFIN)
+		flags |= TH_FIN;
+	if (tp->t_flags & TF_NEEDSYN)
+		flags |= TH_SYN;
+
+	/*
+	 * If in persist timeout with window of 0, send 1 byte.
+	 * Otherwise, if window is small but nonzero
+	 * and timer expired, we will send what we can
+	 * and go to transmit state.
+	 */
+	if (tp->t_flags & TF_FORCEDATA) {
+		if (sendwin == 0) {
+			/*
+			 * If we still have some data to send, then
+			 * clear the FIN bit.  Usually this would
+			 * happen below when it realizes that we
+			 * aren't sending all the data.  However,
+			 * if we have exactly 1 byte of unsent data,
+			 * then it won't clear the FIN bit below,
+			 * and if we are in persist state, we wind
+			 * up sending the packet without recording
+			 * that we sent the FIN bit.
+			 *
+			 * We can't just blindly clear the FIN bit,
+			 * because if we don't have any more data
+			 * to send then the probe will be the FIN
+			 * itself.
+			 */
+			/*
+			 * samkumar: Replaced call to sbused(&so->so_snd) with the call to
+			 * lbuf_used_space below.
+			 */
+			if (off < lbuf_used_space(&tp->sendbuf))
+				flags &= ~TH_FIN;
+			sendwin = 1;
+		} else {
+			tcp_timer_activate(tp, TT_PERSIST, 0);
+			tp->t_rxtshift = 0;
+		}
+	}
+
+	/*
+	 * If snd_nxt == snd_max and we have transmitted a FIN, the
+	 * offset will be > 0 even if so_snd.sb_cc is 0, resulting in
+	 * a negative length.  This can also occur when TCP opens up
+	 * its congestion window while receiving additional duplicate
+	 * acks after fast-retransmit because TCP will reset snd_nxt
+	 * to snd_max after the fast-retransmit.
+	 *
+	 * In the normal retransmit-FIN-only case, however, snd_nxt will
+	 * be set to snd_una, the offset will be 0, and the length may
+	 * wind up 0.
+	 *
+	 * If sack_rxmit is true we are retransmitting from the scoreboard
+	 * in which case len is already set.
+	 */
+	if (sack_rxmit == 0) {
+		if (sack_bytes_rxmt == 0)
+			/*
+			 * samkumar: Replaced sbavail(&so->so_snd) with this call to
+			 * lbuf_used_space.
+			 */
+			len = ((long)ulmin(lbuf_used_space(&tp->sendbuf), sendwin) -
+			    off);
+		else {
+			long cwin;
+
+			/*
+			 * We are inside of a SACK recovery episode and are
+			 * sending new data, having retransmitted all the
+			 * data possible in the scoreboard.
+			 */
+			/*
+			 * samkumar: Replaced sbavail(&so->so_snd) with this call to
+			 * lbuf_used_space.
+			 */
+			len = ((long)ulmin(lbuf_used_space(&tp->sendbuf), tp->snd_wnd) -
+			    off);
+			/*
+			 * Don't remove this (len > 0) check !
+			 * We explicitly check for len > 0 here (although it
+			 * isn't really necessary), to work around a gcc
+			 * optimization issue - to force gcc to compute
+			 * len above. Without this check, the computation
+			 * of len is bungled by the optimizer.
+			 */
+			if (len > 0) {
+				cwin = tp->snd_cwnd -
+					(tp->snd_nxt - tp->sack_newdata) -
+					sack_bytes_rxmt;
+				if (cwin < 0)
+					cwin = 0;
+				len = lmin(len, cwin);
+			}
+		}
+	}
+
+	/*
+	 * Lop off SYN bit if it has already been sent.  However, if this
+	 * is SYN-SENT state and if segment contains data and if we don't
+	 * know that foreign host supports TAO, suppress sending segment.
+	 */
+	if ((flags & TH_SYN) && SEQ_GT(tp->snd_nxt, tp->snd_una)) {
+		if (tp->t_state != TCPS_SYN_RECEIVED)
+			flags &= ~TH_SYN;
+		off--, len++;
+	}
+
+	/*
+	 * Be careful not to send data and/or FIN on SYN segments.
+	 * This measure is needed to prevent interoperability problems
+	 * with not fully conformant TCP implementations.
+	 */
+	if ((flags & TH_SYN) && (tp->t_flags & TF_NOOPT)) {
+		len = 0;
+		flags &= ~TH_FIN;
+	}
+
+	if (len <= 0) {
+		/*
+		 * If FIN has been sent but not acked,
+		 * but we haven't been called to retransmit,
+		 * len will be < 0.  Otherwise, window shrank
+		 * after we sent into it.  If window shrank to 0,
+		 * cancel pending retransmit, pull snd_nxt back
+		 * to (closed) window, and set the persist timer
+		 * if it isn't already going.  If the window didn't
+		 * close completely, just wait for an ACK.
+		 *
+		 * We also do a general check here to ensure that
+		 * we will set the persist timer when we have data
+		 * to send, but a 0-byte window. This makes sure
+		 * the persist timer is set even if the packet
+		 * hits one of the "goto send" lines below.
+		 */
+		len = 0;
+		/*
+		 * samkumar: Replaced sbavail(&so->so_snd) with this call to
+		 * lbuf_used_space.
+		 */
+		if ((sendwin == 0) && (TCPS_HAVEESTABLISHED(tp->t_state)) &&
+			(off < (int) lbuf_used_space(&tp->sendbuf))) {
+			tcp_timer_activate(tp, TT_REXMT, 0);
+			tp->t_rxtshift = 0;
+			tp->snd_nxt = tp->snd_una;
+			if (!tcp_timer_active(tp, TT_PERSIST)) {
+				tcp_setpersist(tp);
+			}
+		}
+	}
+
+
+	/* len will be >= 0 after this point. */
+	KASSERT(len >= 0, ("[%s:%d]: len < 0", __func__, __LINE__));
+
+	/*
+	 * Automatic sizing of send socket buffer.  Often the send buffer
+	 * size is not optimally adjusted to the actual network conditions
+	 * at hand (delay bandwidth product).  Setting the buffer size too
+	 * small limits throughput on links with high bandwidth and high
+	 * delay (eg. trans-continental/oceanic links).  Setting the
+	 * buffer size too big consumes too much real kernel memory,
+	 * especially with many connections on busy servers.
+	 *
+	 * The criteria to step up the send buffer one notch are:
+	 *  1. receive window of remote host is larger than send buffer
+	 *     (with a fudge factor of 5/4th);
+	 *  2. send buffer is filled to 7/8th with data (so we actually
+	 *     have data to make use of it);
+	 *  3. send buffer fill has not hit maximal automatic size;
+	 *  4. our send window (slow start and cogestion controlled) is
+	 *     larger than sent but unacknowledged data in send buffer.
+	 *
+	 * The remote host receive window scaling factor may limit the
+	 * growing of the send buffer before it reaches its allowed
+	 * maximum.
+	 *
+	 * It scales directly with slow start or congestion window
+	 * and does at most one step per received ACK.  This fast
+	 * scaling has the drawback of growing the send buffer beyond
+	 * what is strictly necessary to make full use of a given
+	 * delay*bandwith product.  However testing has shown this not
+	 * to be much of an problem.  At worst we are trading wasting
+	 * of available bandwith (the non-use of it) for wasting some
+	 * socket buffer memory.
+	 *
+	 * TODO: Shrink send buffer during idle periods together
+	 * with congestion window.  Requires another timer.  Has to
+	 * wait for upcoming tcp timer rewrite.
+	 *
+	 * XXXGL: should there be used sbused() or sbavail()?
+	 */
+	 /*
+	 * samkumar: There used to be code here to dynamically size the
+	 * send buffer (by calling sbreserve_locked). In TCPlp, we don't support
+	 * this, as the send buffer doesn't have a well-defined size (and even if
+	 * we were to use a circular buffer, it would be a fixed-size buffer
+	 * allocated by the application). Therefore, I removed the code that does
+	 * this.
+	 */
+
+	 /*
+ 	 * samkumar: There used to be code here to handle TCP Segmentation
+ 	 * Offloading (TSO); I removed it becuase we don't support that in TCPlp.
+ 	 */
+
+	if (sack_rxmit) {
+		/*
+		 * samkumar: Replaced sbused(&so->so_snd) with this call to
+		 * lbuf_used_space.
+		 */
+		if (SEQ_LT(p->rxmit + len, tp->snd_una + lbuf_used_space(&tp->sendbuf)))
+			flags &= ~TH_FIN;
+	} else {
+		if (SEQ_LT(tp->snd_nxt + len, tp->snd_una +
+			/*
+			 * samkumar: Replaced sbused(&so->so_snd) with this call to
+			 * lbuf_used_space.
+			 */
+			lbuf_used_space(&tp->sendbuf)))
+			flags &= ~TH_FIN;
+	}
+
+	/*
+	 * samkumar: Replaced sbspace(&so->so_rcv) with this call to
+	 * cbuf_free_space.
+	 */
+	recwin = cbuf_free_space(&tp->recvbuf);
+
+	/*
+	 * Sender silly window avoidance.   We transmit under the following
+	 * conditions when len is non-zero:
+	 *
+	 *	- We have a full segment (or more with TSO)
+	 *	- This is the last buffer in a write()/send() and we are
+	 *	  either idle or running NODELAY
+	 *	- we've timed out (e.g. persist timer)
+	 *	- we have more then 1/2 the maximum send window's worth of
+	 *	  data (receiver may be limited the window size)
+	 *	- we need to retransmit
+	 */
+	if (len) {
+		if (len >= tp->t_maxseg)
+			goto send;
+		/*
+		 * NOTE! on localhost connections an 'ack' from the remote
+		 * end may occur synchronously with the output and cause
+		 * us to flush a buffer queued with moretocome.  XXX
+		 *
+		 * note: the len + off check is almost certainly unnecessary.
+		 */
+		/*
+ 		 * samkumar: Replaced sbavail(&so->so_snd) with this call to
+ 		 * lbuf_used_space.
+ 		 */
+		if (!(tp->t_flags & TF_MORETOCOME) &&	/* normal case */
+		    (idle || (tp->t_flags & TF_NODELAY)) &&
+		    len + off >= lbuf_used_space(&tp->sendbuf) &&
+		    (tp->t_flags & TF_NOPUSH) == 0) {
+			goto send;
+		}
+		if (tp->t_flags & TF_FORCEDATA)		/* typ. timeout case */
+			goto send;
+		if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0)
+			goto send;
+		if (SEQ_LT(tp->snd_nxt, tp->snd_max))	/* retransmit case */
+			goto send;
+		if (sack_rxmit)
+			goto send;
+	}
+
+	/*
+	 * Sending of standalone window updates.
+	 *
+	 * Window updates are important when we close our window due to a
+	 * full socket buffer and are opening it again after the application
+	 * reads data from it.  Once the window has opened again and the
+	 * remote end starts to send again the ACK clock takes over and
+	 * provides the most current window information.
+	 *
+	 * We must avoid the silly window syndrome whereas every read
+	 * from the receive buffer, no matter how small, causes a window
+	 * update to be sent.  We also should avoid sending a flurry of
+	 * window updates when the socket buffer had queued a lot of data
+	 * and the application is doing small reads.
+	 *
+	 * Prevent a flurry of pointless window updates by only sending
+	 * an update when we can increase the advertized window by more
+	 * than 1/4th of the socket buffer capacity.  When the buffer is
+	 * getting full or is very small be more aggressive and send an
+	 * update whenever we can increase by two mss sized segments.
+	 * In all other situations the ACK's to new incoming data will
+	 * carry further window increases.
+	 *
+	 * Don't send an independent window update if a delayed
+	 * ACK is pending (it will get piggy-backed on it) or the
+	 * remote side already has done a half-close and won't send
+	 * more data.  Skip this if the connection is in T/TCP
+	 * half-open state.
+	 */
+	if (recwin > 0 && !(tp->t_flags & TF_NEEDSYN) &&
+	    !(tp->t_flags & TF_DELACK) &&
+	    !TCPS_HAVERCVDFIN(tp->t_state)) {
+		/*
+		 * "adv" is the amount we could increase the window,
+		 * taking into account that we are limited by
+		 * TCP_MAXWIN << tp->rcv_scale.
+		 */
+		long adv;
+		int oldwin;
+
+		adv = min(recwin, (long)TCP_MAXWIN << tp->rcv_scale);
+		if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt)) {
+			oldwin = (tp->rcv_adv - tp->rcv_nxt);
+			adv -= oldwin;
+		} else
+			oldwin = 0;
+
+		/*
+		 * If the new window size ends up being the same as the old
+		 * size when it is scaled, then don't force a window update.
+		 */
+		if (oldwin >> tp->rcv_scale == (adv + oldwin) >> tp->rcv_scale)
+			goto dontupdate;
+
+		/*
+		 * samkumar: Here, FreeBSD has some heuristics to decide whether or
+		 * not to send a window update. The code for the original heuristics
+		 * is commented out, using #if 0. These heuristics compare "adv,"
+		 * the size of the window update, with the size of the local receive
+		 * buffer. The FreeBSD heuristics aren't applicable because they are
+		 * orders of magnitude off from what we see in TCPlp. For example,
+		 * FreeBSD only sends a window update if it is at least two segments
+		 * big. Note that, in the experiments I did, the second case did not
+		 * filter window updates further because, in the experiments, the
+		 * receive buffer was smaller than 8 segments.
+		 *
+		 * I replaced these heuristics with a simpler version, which you can
+		 * see below. For the experiments I did, the first condition
+		 * (checking if adv >= (long)(2 * tp->t_maxseg)) wasn't included; this
+		 * did not matter because the receive buffer was smaller than 8
+		 * segments, so any condition that would have triggered the first
+		 * condition would have triggered the second one anyway. I've included
+		 * the first condition in this version in an effort to be more robust,
+		 * in case someone does try to run TCPlp with a large receive buffer.
+		 *
+		 * It may be worth studying this more and revisiting the heuristic to
+		 * use here. In case we try to resurrect the old FreeBSD heuristics,
+		 * note that so->so_rcv.sb_hiwat in FreeBSD corresponds roughly to
+		 * cbuf_size(&tp->recvbuf) in TCPlp.
+		 */
+#if 0
+		if (adv >= (long)(2 * tp->t_maxseg) &&
+		    (adv >= (long)(so->so_rcv.sb_hiwat / 4) ||
+		     recwin <= (long)(so->so_rcv.sb_hiwat / 8) ||
+		     so->so_rcv.sb_hiwat <= 8 * tp->t_maxseg))
+			goto send;
+#endif
+		if (adv >= (long)(2 * tp->t_maxseg) ||
+		    adv >= (long)cbuf_size(&tp->recvbuf) / 4)
+			goto send;
+	}
+dontupdate:
+
+	/*
+	 * Send if we owe the peer an ACK, RST, SYN, or urgent data.  ACKNOW
+	 * is also a catch-all for the retransmit timer timeout case.
+	 */
+	if (tp->t_flags & TF_ACKNOW) {
+		goto send;
+	}
+	if ((flags & TH_RST) ||
+	    ((flags & TH_SYN) && (tp->t_flags & TF_NEEDSYN) == 0))
+		goto send;
+	if (SEQ_GT(tp->snd_up, tp->snd_una))
+		goto send;
+	/*
+	 * If our state indicates that FIN should be sent
+	 * and we have not yet done so, then we need to send.
+	 */
+	if (flags & TH_FIN &&
+	    ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una))
+		goto send;
+	/*
+	 * In SACK, it is possible for tcp_output to fail to send a segment
+	 * after the retransmission timer has been turned off.  Make sure
+	 * that the retransmission timer is set.
+	 */
+	if ((tp->t_flags & TF_SACK_PERMIT) &&
+	    SEQ_GT(tp->snd_max, tp->snd_una) &&
+	    !tcp_timer_active(tp, TT_REXMT) &&
+	    !tcp_timer_active(tp, TT_PERSIST)) {
+		tcp_timer_activate(tp, TT_REXMT, tp->t_rxtcur);
+		goto just_return;
+	}
+
+	/*
+	 * TCP window updates are not reliable, rather a polling protocol
+	 * using ``persist'' packets is used to insure receipt of window
+	 * updates.  The three ``states'' for the output side are:
+	 *	idle			not doing retransmits or persists
+	 *	persisting		to move a small or zero window
+	 *	(re)transmitting	and thereby not persisting
+	 *
+	 * tcp_timer_active(tp, TT_PERSIST)
+	 *	is true when we are in persist state.
+	 * (tp->t_flags & TF_FORCEDATA)
+	 *	is set when we are called to send a persist packet.
+	 * tcp_timer_active(tp, TT_REXMT)
+	 *	is set when we are retransmitting
+	 * The output side is idle when both timers are zero.
+	 *
+	 * If send window is too small, there is data to transmit, and no
+	 * retransmit or persist is pending, then go to persist state.
+	 * If nothing happens soon, send when timer expires:
+	 * if window is nonzero, transmit what we can,
+	 * otherwise force out a byte.
+	 */
+	/*
+	 * samkumar: Replaced sbavail(&so->so_snd) with this call to
+	 * lbuf_used_space.
+	 */
+	if (lbuf_used_space(&tp->sendbuf) && !tcp_timer_active(tp, TT_REXMT) &&
+	    !tcp_timer_active(tp, TT_PERSIST)) {
+		tp->t_rxtshift = 0;
+		tcp_setpersist(tp);
+	}
+
+	/*
+	 * No reason to send a segment, just return.
+	 */
+just_return:
+	return (0);
+
+send:
+	if (len > 0) {
+		if (len >= tp->t_maxseg)
+			tp->t_flags2 |= TF2_PLPMTU_MAXSEGSNT;
+		else
+			tp->t_flags2 &= ~TF2_PLPMTU_MAXSEGSNT;
+	}
+	/*
+	 * Before ESTABLISHED, force sending of initial options
+	 * unless TCP set not to do any options.
+	 * NOTE: we assume that the IP/TCP header plus TCP options
+	 * always fit in a single mbuf, leaving room for a maximum
+	 * link header, i.e.
+	 *	max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MCLBYTES
+	 */
+	optlen = 0;
+	hdrlen = sizeof (struct ip6_hdr) + sizeof (struct tcphdr);
+
+	/*
+	 * Compute options for segment.
+	 * We only have to care about SYN and established connection
+	 * segments.  Options for SYN-ACK segments are handled in TCP
+	 * syncache.
+	 * Sam: I've done away with the syncache. However, it seems that
+	 * the existing logic works fine for SYN-ACK as well
+	 */
+	if ((tp->t_flags & TF_NOOPT) == 0) {
+		to.to_flags = 0;
+		/* Maximum segment size. */
+		if (flags & TH_SYN) {
+			tp->snd_nxt = tp->iss;
+			to.to_mss = tcp_mssopt(tp);
+			to.to_flags |= TOF_MSS;
+		}
+		/* Window scaling. */
+		if ((flags & TH_SYN) && (tp->t_flags & TF_REQ_SCALE)) {
+			to.to_wscale = tp->request_r_scale;
+			to.to_flags |= TOF_SCALE;
+		}
+		/* Timestamps. */
+		if ((tp->t_flags & TF_RCVD_TSTMP) ||
+		    ((flags & TH_SYN) && (tp->t_flags & TF_REQ_TSTMP))) {
+			to.to_tsval = tcp_ts_getticks() + tp->ts_offset;
+			to.to_tsecr = tp->ts_recent;
+			to.to_flags |= TOF_TS;
+			/*
+			 * samkumar: I removed the code to set the timestamp tp->rfbuf_ts
+			 * for receive buffer autosizing, since we don't do autosizing on
+			 * the receive buffer in TCPlp.
+			 */
+		}
+
+		/* Selective ACK's. */
+		if (tp->t_flags & TF_SACK_PERMIT) {
+			if (flags & TH_SYN)
+				to.to_flags |= TOF_SACKPERM;
+			else if (TCPS_HAVEESTABLISHED(tp->t_state) &&
+			    (tp->t_flags & TF_SACK_PERMIT) &&
+			    tp->rcv_numsacks > 0) {
+				to.to_flags |= TOF_SACK;
+				to.to_nsacks = tp->rcv_numsacks;
+				to.to_sacks = (uint8_t *)tp->sackblks;
+			}
+		}
+
+		/*
+		 * samkumar: Remove logic to set TOF_SIGNATURE flag in to.to_flags,
+		 * since TCPlp does not support TCP signatures.
+		 */
+
+		/* Processing the options. */
+		hdrlen += optlen = tcp_addoptions(&to, opt);
+	}
+	/*
+	 * samkumar: This used to be set to ip6_optlen(tp->t_inpcb), instead of 0,
+	 * along with some additional code to handle IPSEC. In TCPlp we don't set
+	 * IPv6 options here; we expect those to be set by the host network stack.
+	 * Of course, code that supports IPv4 has been removed as well.
+	 */
+	ipoptlen = 0;
+
+	/*
+	 * Adjust data length if insertion of options will
+	 * bump the packet length beyond the t_maxopd length.
+	 * Clear the FIN bit because we cut off the tail of
+	 * the segment.
+	 */
+	if (len + optlen + ipoptlen > tp->t_maxopd) {
+		flags &= ~TH_FIN;
+		/*
+		 * samkumar: Remove code for TCP segmentation offloading.
+		 */
+		len = tp->t_maxopd - optlen - ipoptlen;
+		sendalot = 1;
+	}
+	/*
+	 * samkumar: The else case of the above "if" statement would set tso to 0.
+	 * Removing this since we no longer need a tso variable.
+	 */
+	KASSERT(len + hdrlen + ipoptlen <= IP_MAXPACKET,
+	    ("%s: len > IP_MAXPACKET", __func__));
+
+	/*
+	 * This KASSERT is here to catch edge cases at a well defined place.
+	 * Before, those had triggered (random) panic conditions further down.
+	 */
+	KASSERT(len >= 0, ("[%s:%d]: len < 0", __func__, __LINE__));
+
+	/*
+	 * Grab a header mbuf, attaching a copy of data to
+	 * be transmitted, and initialize the header from
+	 * the template for sends on this connection.
+	 */
+
+	/*
+	 * samkumar: The code to allocate, build, and send outgoing segments has
+	 * been rewritten. I've left the original code to build the output mbuf
+	 * here in a comment, for reference. The new code is below.
+	 */
+#if 0
+	if (len) {
+		struct mbuf *mb;
+		uint32_t moff;
+
+		if ((tp->t_flags & TF_FORCEDATA) && len == 1)
+			TCPSTAT_INC(tcps_sndprobe);
+		else if (SEQ_LT(tp->snd_nxt, tp->snd_max) || sack_rxmit) {
+			tp->t_sndrexmitpack++;
+			TCPSTAT_INC(tcps_sndrexmitpack);
+			TCPSTAT_ADD(tcps_sndrexmitbyte, len);
+		} else {
+			TCPSTAT_INC(tcps_sndpack);
+			TCPSTAT_ADD(tcps_sndbyte, len);
+		}
+#ifdef INET6
+		if (MHLEN < hdrlen + max_linkhdr)
+			m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+		else
+#endif
+			m = m_gethdr(M_NOWAIT, MT_DATA);
+
+		if (m == NULL) {
+			SOCKBUF_UNLOCK(&so->so_snd);
+			error = ENOBUFS;
+			sack_rxmit = 0;
+			goto out;
+		}
+
+		m->m_data += max_linkhdr;
+		m->m_len = hdrlen;
+
+		/*
+		 * Start the m_copy functions from the closest mbuf
+		 * to the offset in the socket buffer chain.
+		 */
+		mb = sbsndptr(&so->so_snd, off, len, &moff);
+
+		if (len <= MHLEN - hdrlen - max_linkhdr) {
+			m_copydata(mb, moff, (int)len,
+			    mtod(m, caddr_t) + hdrlen);
+			m->m_len += len;
+		} else {
+			m->m_next = m_copy(mb, moff, (int)len);
+			if (m->m_next == NULL) {
+				SOCKBUF_UNLOCK(&so->so_snd);
+				(void) m_free(m);
+				error = ENOBUFS;
+				sack_rxmit = 0;
+				goto out;
+			}
+		}
+
+		/*
+		 * If we're sending everything we've got, set PUSH.
+		 * (This will keep happy those implementations which only
+		 * give data to the user when a buffer fills or
+		 * a PUSH comes in.)
+		 */
+		if (off + len == sbused(&so->so_snd))
+			flags |= TH_PUSH;
+		SOCKBUF_UNLOCK(&so->so_snd);
+	} else {
+		SOCKBUF_UNLOCK(&so->so_snd);
+		if (tp->t_flags & TF_ACKNOW)
+			TCPSTAT_INC(tcps_sndacks);
+		else if (flags & (TH_SYN|TH_FIN|TH_RST))
+			TCPSTAT_INC(tcps_sndctrl);
+		else if (SEQ_GT(tp->snd_up, tp->snd_una))
+			TCPSTAT_INC(tcps_sndurg);
+		else
+			TCPSTAT_INC(tcps_sndwinup);
+
+		m = m_gethdr(M_NOWAIT, MT_DATA);
+		if (m == NULL) {
+			error = ENOBUFS;
+			sack_rxmit = 0;
+			goto out;
+		}
+#ifdef INET6
+		if (isipv6 && (MHLEN < hdrlen + max_linkhdr) &&
+		    MHLEN >= hdrlen) {
+			M_ALIGN(m, hdrlen);
+		} else
+#endif
+		m->m_data += max_linkhdr;
+		m->m_len = hdrlen;
+	}
+#endif
+
+	KASSERT(ipoptlen == 0, ("No IP options supported")); // samkumar
+
+	otMessage* message = tcplp_sys_new_message(tp->instance);
+	if (message == NULL) {
+		error = ENOBUFS;
+		sack_rxmit = 0;
+		goto out;
+	}
+	if (otMessageSetLength(message, sizeof(struct tcphdr) + optlen + len) != OT_ERROR_NONE) {
+		tcplp_sys_free_message(tp->instance, message);
+		error = ENOBUFS;
+		sack_rxmit = 0;
+		goto out;
+	}
+	if (len) {
+	    uint32_t used_space = lbuf_used_space(&tp->sendbuf);
+
+		/*
+		 * The TinyOS version has a way to avoid the copying we have to do here.
+		 * Because it is possible to send iovecs directly in the BLIP stack, and
+		 * an lbuf is made of iovecs, we could just "save" the starting and ending
+		 * iovecs, modify them to get exactly the slice we want, call "send" on
+		 * the resulting chain, and then restore the starting and ending iovecs
+		 * once "send" returns.
+		 *
+		 * In RIOT, pktsnips have additional behavior regarding memory management
+		 * that precludes this optimization. But, now that we have moved to
+		 * cbufs, this is not relevant anymore.
+		 */
+		{
+			otLinkedBuffer* start;
+			size_t start_offset;
+			otLinkedBuffer* end;
+			size_t end_offset;
+			otLinkedBuffer* curr;
+			int rv = lbuf_getrange(&tp->sendbuf, off, len, &start, &start_offset, &end, &end_offset);
+			size_t message_offset = otMessageGetOffset(message) + sizeof(struct tcphdr) + optlen;
+			KASSERT(rv == 0, ("Reading send buffer out of range!"));
+			for (curr = start; curr != end->mNext; curr = curr->mNext) {
+				const uint8_t* data_to_copy = curr->mData;
+				size_t length_to_copy = curr->mLength;
+				if (curr == start) {
+					data_to_copy += start_offset;
+					length_to_copy -= start_offset;
+				}
+				if (curr == end) {
+					length_to_copy -= end_offset;
+				}
+				otMessageWrite(message, message_offset, data_to_copy, length_to_copy);
+				message_offset += length_to_copy;
+			}
+		}
+
+		/*
+		 * If we're sending everything we've got, set PUSH.
+		 * (This will keep happy those implementations which only
+		 * give data to the user when a buffer fills or
+		 * a PUSH comes in.)
+		 */
+		/* samkumar: Replaced call to sbused(&so->so_snd) with used_space. */
+		if (off + len == used_space)
+			flags |= TH_PUSH;
+	}
+
+	char outbuf[sizeof(struct tcphdr) + TCP_MAXOLEN];
+	th = (struct tcphdr*) (&outbuf[0]);
+
+	/*
+	 * samkumar: I replaced the original call to tcpip_fillheaders with the
+	 * one below.
+	 */
+	otMessageInfo ip6info;
+	tcpip_fillheaders(tp, &ip6info, th);
+
+	/*
+	 * Fill in fields, remembering maximum advertised
+	 * window for use in delaying messages about window sizes.
+	 * If resending a FIN, be sure not to use a new sequence number.
+	 */
+	if (flags & TH_FIN && tp->t_flags & TF_SENTFIN &&
+	    tp->snd_nxt == tp->snd_max)
+		tp->snd_nxt--;
+	/*
+	 * If we are starting a connection, send ECN setup
+	 * SYN packet. If we are on a retransmit, we may
+	 * resend those bits a number of times as per
+	 * RFC 3168.
+	 */
+	if (tp->t_state == TCPS_SYN_SENT && V_tcp_do_ecn) {
+		if (tp->t_rxtshift >= 1) {
+			if (tp->t_rxtshift <= V_tcp_ecn_maxretries)
+				flags |= TH_ECE|TH_CWR;
+		} else
+			flags |= TH_ECE|TH_CWR;
+	}
+
+	/*
+	 * samkumar: Make tcp_output reply with ECE flag in the SYN-ACK for
+	 * ECN-enabled connections. The existing code in FreeBSD didn't have to do
+	 * this, because it didn't use tcp_output to send the SYN-ACK; it
+	 * constructed the SYN-ACK segment manually. Yet another consequnce of
+	 * removing the SYN cache...
+	 */
+	if (tp->t_state == TCPS_SYN_RECEIVED && tp->t_flags & TF_ECN_PERMIT &&
+		V_tcp_do_ecn) {
+		flags |= TH_ECE;
+	}
+
+	if (tp->t_state == TCPS_ESTABLISHED &&
+	    (tp->t_flags & TF_ECN_PERMIT)) {
+		/*
+		 * If the peer has ECN, mark data packets with
+		 * ECN capable transmission (ECT).
+		 * Ignore pure ack packets, retransmissions and window probes.
+		 */
+		if (len > 0 && SEQ_GEQ(tp->snd_nxt, tp->snd_max) &&
+		    !((tp->t_flags & TF_FORCEDATA) && len == 1)) {
+			/*
+			 * samkumar: Replaced ip6->ip6_flow |= htonl(IPTOS_ECN_ECT0 << 20);
+			 * with the following code, which will cause OpenThread to set the
+			 * ECT0 bit in the header.
+			 */
+			ip6info.mEcn = OT_ECN_CAPABLE_0;
+		}
+
+		/*
+		 * Reply with proper ECN notifications.
+		 */
+		if (tp->t_flags & TF_ECN_SND_CWR) {
+			flags |= TH_CWR;
+			tp->t_flags &= ~TF_ECN_SND_CWR;
+		}
+		if (tp->t_flags & TF_ECN_SND_ECE)
+			flags |= TH_ECE;
+	}
+
+	/*
+	 * If we are doing retransmissions, then snd_nxt will
+	 * not reflect the first unsent octet.  For ACK only
+	 * packets, we do not want the sequence number of the
+	 * retransmitted packet, we want the sequence number
+	 * of the next unsent octet.  So, if there is no data
+	 * (and no SYN or FIN), use snd_max instead of snd_nxt
+	 * when filling in ti_seq.  But if we are in persist
+	 * state, snd_max might reflect one byte beyond the
+	 * right edge of the window, so use snd_nxt in that
+	 * case, since we know we aren't doing a retransmission.
+	 * (retransmit and persist are mutually exclusive...)
+	 */
+	if (sack_rxmit == 0) {
+		if (len || (flags & (TH_SYN|TH_FIN)) ||
+		    tcp_timer_active(tp, TT_PERSIST))
+			th->th_seq = htonl(tp->snd_nxt);
+		else
+			th->th_seq = htonl(tp->snd_max);
+	} else {
+		th->th_seq = htonl(p->rxmit);
+		p->rxmit += len;
+		tp->sackhint.sack_bytes_rexmit += len;
+	}
+
+	/*
+	 * samkumar: Check if this is a retransmission (added as part of TCPlp).
+	 * This kind of stats collection is useful but not necessary for TCP, so
+	 * I've left it as a comment in case we want to bring this back to measure
+	 * performance.
+	 */
+#if 0
+	if (len > 0 && !tcp_timer_active(tp, TT_PERSIST) && SEQ_LT(ntohl(th->th_seq), tp->snd_max)) {
+		tcplp_totalRexmitCnt++;
+	}
+#endif
+
+	th->th_ack = htonl(tp->rcv_nxt);
+	if (optlen) {
+		bcopy(opt, th + 1, optlen);
+		th->th_off_x2 = ((sizeof (struct tcphdr) + optlen) >> 2) << TH_OFF_SHIFT;
+	}
+	th->th_flags = flags;
+	/*
+	 * Calculate receive window.  Don't shrink window,
+	 * but avoid silly window syndrome.
+	 */
+	/* samkumar: Replaced so->so_rcv.sb_hiwat with this call to cbuf_size. */
+	if (recwin < (long)(cbuf_size(&tp->recvbuf) / 4) &&
+	    recwin < (long)tp->t_maxseg)
+		recwin = 0;
+	if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt) &&
+	    recwin < (long)(tp->rcv_adv - tp->rcv_nxt))
+		recwin = (long)(tp->rcv_adv - tp->rcv_nxt);
+	if (recwin > (long)TCP_MAXWIN << tp->rcv_scale)
+		recwin = (long)TCP_MAXWIN << tp->rcv_scale;
+
+	/*
+	 * According to RFC1323 the window field in a SYN (i.e., a <SYN>
+	 * or <SYN,ACK>) segment itself is never scaled.  The <SYN,ACK>
+	 * case is handled in syncache.
+	 */
+	if (flags & TH_SYN)
+		th->th_win = htons((uint16_t)
+				(min(cbuf_size(&tp->recvbuf), TCP_MAXWIN)));
+	else
+		th->th_win = htons((uint16_t)(recwin >> tp->rcv_scale));
+
+	/*
+	 * Adjust the RXWIN0SENT flag - indicate that we have advertised
+	 * a 0 window.  This may cause the remote transmitter to stall.  This
+	 * flag tells soreceive() to disable delayed acknowledgements when
+	 * draining the buffer.  This can occur if the receiver is attempting
+	 * to read more data than can be buffered prior to transmitting on
+	 * the connection.
+	 */
+	if (th->th_win == 0) {
+		tp->t_flags |= TF_RXWIN0SENT;
+	} else
+		tp->t_flags &= ~TF_RXWIN0SENT;
+	if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
+		th->th_urp = htons((uint16_t)(tp->snd_up - tp->snd_nxt));
+		th->th_flags |= TH_URG;
+	} else
+		/*
+		 * If no urgent pointer to send, then we pull
+		 * the urgent pointer to the left edge of the send window
+		 * so that it doesn't drift into the send window on sequence
+		 * number wraparound.
+		 */
+		tp->snd_up = tp->snd_una;		/* drag it along */
+
+	/*
+	 * samkumar: Removed code for TCP signatures.
+	 */
+	/*
+	 * Put TCP length in extended header, and then
+	 * checksum extended header and data.
+	 */
+	/*
+	 * samkumar: The code to implement the above comment isn't relevant to us.
+	 * Checksum computation is not handled using FreeBSD code, so we don't need
+	 * to build an extended header.
+	 */
+	/*
+	 * samkumar: Removed code for TCP Segmentation Offloading.
+	 */
+	/* samkumar: Removed mbuf-specific assertions an debug code. */
+	/*
+	 * Fill in IP length and desired time to live and
+	 * send to IP level.  There should be a better way
+	 * to handle ttl and tos; we could keep them in
+	 * the template, but need a way to checksum without them.
+	 */
+	/*
+	 * m->m_pkthdr.len should have been set before checksum calculation,
+	 * because in6_cksum() need it.
+	 */
+	/*
+	 * samkumar: The IPv6 packet length and hop limit are handled by the host
+	 * network stack, not by TCPlp. I've also removed code for Path MTU
+	 * discovery. And of course, I've removed debug code as well.
+	 */
+	/* samkumar: I've replaced the call to ip6_output with the following. */
+	otMessageWrite(message, 0, outbuf, sizeof(struct tcphdr) + optlen);
+	tcplp_sys_send_message(tp->instance, message, &ip6info);
+
+out:
+	/*
+	 * In transmit state, time the transmission and arrange for
+	 * the retransmit.  In persist state, just set snd_max.
+	 */
+	if ((tp->t_flags & TF_FORCEDATA) == 0 ||
+	    !tcp_timer_active(tp, TT_PERSIST)) {
+		tcp_seq startseq = tp->snd_nxt;
+
+		/*
+		 * Advance snd_nxt over sequence space of this segment.
+		 */
+		if (flags & (TH_SYN|TH_FIN)) {
+			if (flags & TH_SYN)
+				tp->snd_nxt++;
+			if (flags & TH_FIN) {
+				tp->snd_nxt++;
+				tp->t_flags |= TF_SENTFIN;
+			}
+		}
+		if (sack_rxmit)
+			goto timer;
+		tp->snd_nxt += len;
+		if (SEQ_GT(tp->snd_nxt, tp->snd_max)) {
+			tp->snd_max = tp->snd_nxt;
+			/*
+			 * Time this transmission if not a retransmission and
+			 * not currently timing anything.
+			 */
+			if (tp->t_rtttime == 0) {
+				tp->t_rtttime = ticks;
+				tp->t_rtseq = startseq;
+			}
+		}
+
+		/*
+		 * Set retransmit timer if not currently set,
+		 * and not doing a pure ack or a keep-alive probe.
+		 * Initial value for retransmit timer is smoothed
+		 * round-trip time + 2 * round-trip time variance.
+		 * Initialize shift counter which is used for backoff
+		 * of retransmit time.
+		 */
+timer:
+		if (!tcp_timer_active(tp, TT_REXMT) &&
+		    ((sack_rxmit && tp->snd_nxt != tp->snd_max) ||
+		     (tp->snd_nxt != tp->snd_una))) {
+			if (tcp_timer_active(tp, TT_PERSIST)) {
+				tcp_timer_activate(tp, TT_PERSIST, 0);
+				tp->t_rxtshift = 0;
+			}
+			tcp_timer_activate(tp, TT_REXMT, tp->t_rxtcur);
+			/*
+			 * samkumar: Replaced sbavail(&so->so_snd) with this call to
+			 * lbuf_used_space.
+			 */
+		} else if (len == 0 && lbuf_used_space(&tp->sendbuf) &&
+		    !tcp_timer_active(tp, TT_REXMT) &&
+		    !tcp_timer_active(tp, TT_PERSIST)) {
+			/*
+			 * Avoid a situation where we do not set persist timer
+			 * after a zero window condition. For example:
+			 * 1) A -> B: packet with enough data to fill the window
+			 * 2) B -> A: ACK for #1 + new data (0 window
+			 *    advertisement)
+			 * 3) A -> B: ACK for #2, 0 len packet
+			 *
+			 * In this case, A will not activate the persist timer,
+			 * because it chose to send a packet. Unless tcp_output
+			 * is called for some other reason (delayed ack timer,
+			 * another input packet from B, socket syscall), A will
+			 * not send zero window probes.
+			 *
+			 * So, if you send a 0-length packet, but there is data
+			 * in the socket buffer, and neither the rexmt or
+			 * persist timer is already set, then activate the
+			 * persist timer.
+			 */
+			tp->t_rxtshift = 0;
+			tcp_setpersist(tp);
+		}
+	} else {
+		/*
+		 * Persist case, update snd_max but since we are in
+		 * persist mode (no window) we do not update snd_nxt.
+		 */
+		int xlen = len;
+		if (flags & TH_SYN)
+			++xlen;
+		if (flags & TH_FIN) {
+			++xlen;
+			tp->t_flags |= TF_SENTFIN;
+		}
+		if (SEQ_GT(tp->snd_nxt + xlen, tp->snd_max))
+			tp->snd_max = tp->snd_nxt + len;
+	}
+
+	if (error) {
+
+		/*
+		 * We know that the packet was lost, so back out the
+		 * sequence number advance, if any.
+		 *
+		 * If the error is EPERM the packet got blocked by the
+		 * local firewall.  Normally we should terminate the
+		 * connection but the blocking may have been spurious
+		 * due to a firewall reconfiguration cycle.  So we treat
+		 * it like a packet loss and let the retransmit timer and
+		 * timeouts do their work over time.
+		 * XXX: It is a POLA question whether calling tcp_drop right
+		 * away would be the really correct behavior instead.
+		 */
+		if (((tp->t_flags & TF_FORCEDATA) == 0 ||
+		    !tcp_timer_active(tp, TT_PERSIST)) &&
+		    ((flags & TH_SYN) == 0) &&
+		    (error != EPERM)) {
+			if (sack_rxmit) {
+				p->rxmit -= len;
+				tp->sackhint.sack_bytes_rexmit -= len;
+				KASSERT(tp->sackhint.sack_bytes_rexmit >= 0,
+				    ("sackhint bytes rtx >= 0"));
+			} else
+				tp->snd_nxt -= len;
+		}
+		switch (error) {
+		case EPERM:
+			tp->t_softerror = error;
+			return (error);
+		case ENOBUFS:
+	                if (!tcp_timer_active(tp, TT_REXMT) &&
+			    !tcp_timer_active(tp, TT_PERSIST))
+	                        tcp_timer_activate(tp, TT_REXMT, tp->t_rxtcur);
+			tp->snd_cwnd = tp->t_maxseg;
+#ifdef INSTRUMENT_TCP
+			tcplp_sys_log("TCP ALLOCFAIL %u %d", (unsigned int) tcplp_sys_get_millis(), (int) tp->snd_cwnd);
+#endif
+			return (0);
+		case EMSGSIZE:
+			/*
+			 * For some reason the interface we used initially
+			 * to send segments changed to another or lowered
+			 * its MTU.
+			 * If TSO was active we either got an interface
+			 * without TSO capabilits or TSO was turned off.
+			 * If we obtained mtu from ip_output() then update
+			 * it and try again.
+			 */
+			/* samkumar: Removed code for TCP Segmentation Offloading. */
+			if (mtu != 0) {
+				tcp_mss_update(tp, -1, mtu, NULL, NULL);
+				goto again;
+			}
+			return (error);
+		case EHOSTDOWN:
+		case EHOSTUNREACH:
+		case ENETDOWN:
+		case ENETUNREACH:
+			if (TCPS_HAVERCVDSYN(tp->t_state)) {
+				tp->t_softerror = error;
+				return (0);
+			}
+			/* FALLTHROUGH */
+		default:
+			return (error);
+		}
+	}
+
+	/*
+	 * Data sent (as far as we can tell).
+	 * If this advertises a larger window than any other segment,
+	 * then remember the size of the advertised window.
+	 * Any pending ACK has now been sent.
+	 */
+	if (recwin >= 0 && SEQ_GT(tp->rcv_nxt + recwin, tp->rcv_adv))
+		tp->rcv_adv = tp->rcv_nxt + recwin;
+	tp->last_ack_sent = tp->rcv_nxt;
+	tp->t_flags &= ~(TF_ACKNOW | TF_DELACK);
+	if (tcp_timer_active(tp, TT_DELACK))
+		tcp_timer_activate(tp, TT_DELACK, 0);
+
+	/*
+	 * samkumar: This was already commented out (using #if 0) in the original
+	 * FreeBSD code.
+	 */
+#if 0
+	/*
+	 * This completely breaks TCP if newreno is turned on.  What happens
+	 * is that if delayed-acks are turned on on the receiver, this code
+	 * on the transmitter effectively destroys the TCP window, forcing
+	 * it to four packets (1.5Kx4 = 6K window).
+	 */
+	if (sendalot && --maxburst)
+		goto again;
+#endif
+	if (sendalot)
+		goto again;
+	return (0);
+}
+
+/*
+ * Insert TCP options according to the supplied parameters to the place
+ * optp in a consistent way.  Can handle unaligned destinations.
+ *
+ * The order of the option processing is crucial for optimal packing and
+ * alignment for the scarce option space.
+ *
+ * The optimal order for a SYN/SYN-ACK segment is:
+ *   MSS (4) + NOP (1) + Window scale (3) + SACK permitted (2) +
+ *   Timestamp (10) + Signature (18) = 38 bytes out of a maximum of 40.
+ *
+ * The SACK options should be last.  SACK blocks consume 8*n+2 bytes.
+ * So a full size SACK blocks option is 34 bytes (with 4 SACK blocks).
+ * At minimum we need 10 bytes (to generate 1 SACK block).  If both
+ * TCP Timestamps (12 bytes) and TCP Signatures (18 bytes) are present,
+ * we only have 10 bytes for SACK options (40 - (12 + 18)).
+ */
+int
+tcp_addoptions(struct tcpopt *to, uint8_t *optp)
+{
+	uint32_t mask, optlen = 0;
+
+	for (mask = 1; mask < TOF_MAXOPT; mask <<= 1) {
+		if ((to->to_flags & mask) != mask)
+			continue;
+		if (optlen == TCP_MAXOLEN)
+			break;
+		switch (to->to_flags & mask) {
+		case TOF_MSS:
+			while (optlen % 4) {
+				optlen += TCPOLEN_NOP;
+				*optp++ = TCPOPT_NOP;
+			}
+			if (TCP_MAXOLEN - optlen < TCPOLEN_MAXSEG)
+				continue;
+			optlen += TCPOLEN_MAXSEG;
+			*optp++ = TCPOPT_MAXSEG;
+			*optp++ = TCPOLEN_MAXSEG;
+			to->to_mss = htons(to->to_mss);
+			bcopy((uint8_t *)&to->to_mss, optp, sizeof(to->to_mss));
+			optp += sizeof(to->to_mss);
+			break;
+		case TOF_SCALE:
+			while (!optlen || optlen % 2 != 1) {
+				optlen += TCPOLEN_NOP;
+				*optp++ = TCPOPT_NOP;
+			}
+			if (TCP_MAXOLEN - optlen < TCPOLEN_WINDOW)
+				continue;
+			optlen += TCPOLEN_WINDOW;
+			*optp++ = TCPOPT_WINDOW;
+			*optp++ = TCPOLEN_WINDOW;
+			*optp++ = to->to_wscale;
+			break;
+		case TOF_SACKPERM:
+			while (optlen % 2) {
+				optlen += TCPOLEN_NOP;
+				*optp++ = TCPOPT_NOP;
+			}
+			if (TCP_MAXOLEN - optlen < TCPOLEN_SACK_PERMITTED)
+				continue;
+			optlen += TCPOLEN_SACK_PERMITTED;
+			*optp++ = TCPOPT_SACK_PERMITTED;
+			*optp++ = TCPOLEN_SACK_PERMITTED;
+			break;
+		case TOF_TS:
+			while (!optlen || optlen % 4 != 2) {
+				optlen += TCPOLEN_NOP;
+				*optp++ = TCPOPT_NOP;
+			}
+			if (TCP_MAXOLEN - optlen < TCPOLEN_TIMESTAMP)
+				continue;
+			optlen += TCPOLEN_TIMESTAMP;
+			*optp++ = TCPOPT_TIMESTAMP;
+			*optp++ = TCPOLEN_TIMESTAMP;
+			to->to_tsval = htonl(to->to_tsval);
+			to->to_tsecr = htonl(to->to_tsecr);
+			bcopy((uint8_t *)&to->to_tsval, optp, sizeof(to->to_tsval));
+			optp += sizeof(to->to_tsval);
+			bcopy((uint8_t *)&to->to_tsecr, optp, sizeof(to->to_tsecr));
+			optp += sizeof(to->to_tsecr);
+			break;
+		case TOF_SIGNATURE:
+			{
+			int siglen = TCPOLEN_SIGNATURE - 2;
+
+			while (!optlen || optlen % 4 != 2) {
+				optlen += TCPOLEN_NOP;
+				*optp++ = TCPOPT_NOP;
+			}
+			if (TCP_MAXOLEN - optlen < TCPOLEN_SIGNATURE)
+				continue;
+			optlen += TCPOLEN_SIGNATURE;
+			*optp++ = TCPOPT_SIGNATURE;
+			*optp++ = TCPOLEN_SIGNATURE;
+			to->to_signature = optp;
+			while (siglen--)
+				 *optp++ = 0;
+			break;
+			}
+		case TOF_SACK:
+			{
+			int sackblks = 0;
+			struct sackblk *sack = (struct sackblk *)to->to_sacks;
+			tcp_seq sack_seq;
+
+			while (!optlen || optlen % 4 != 2) {
+				optlen += TCPOLEN_NOP;
+				*optp++ = TCPOPT_NOP;
+			}
+			if (TCP_MAXOLEN - optlen < TCPOLEN_SACKHDR + TCPOLEN_SACK)
+				continue;
+			optlen += TCPOLEN_SACKHDR;
+			*optp++ = TCPOPT_SACK;
+			sackblks = min(to->to_nsacks,
+					(TCP_MAXOLEN - optlen) / TCPOLEN_SACK);
+			*optp++ = TCPOLEN_SACKHDR + sackblks * TCPOLEN_SACK;
+			while (sackblks--) {
+				sack_seq = htonl(sack->start);
+				bcopy((uint8_t *)&sack_seq, optp, sizeof(sack_seq));
+				optp += sizeof(sack_seq);
+				sack_seq = htonl(sack->end);
+				bcopy((uint8_t *)&sack_seq, optp, sizeof(sack_seq));
+				optp += sizeof(sack_seq);
+				optlen += TCPOLEN_SACK;
+				sack++;
+			}
+			/* samkumar: Removed TCPSTAT_INC(tcps_sack_send_blocks); */
+			break;
+			}
+		default:
+			tcplp_sys_panic("PANIC: %s: unknown TCP option type", __func__);
+			break;
+		}
+	}
+
+	/* Terminate and pad TCP options to a 4 byte boundary. */
+	if (optlen % 4) {
+		optlen += TCPOLEN_EOL;
+		*optp++ = TCPOPT_EOL;
+	}
+	/*
+	 * According to RFC 793 (STD0007):
+	 *   "The content of the header beyond the End-of-Option option
+	 *    must be header padding (i.e., zero)."
+	 *   and later: "The padding is composed of zeros."
+	 */
+	while (optlen % 4) {
+		optlen += TCPOLEN_PAD;
+		*optp++ = TCPOPT_PAD;
+	}
+
+	KASSERT(optlen <= TCP_MAXOLEN, ("%s: TCP options too long", __func__));
+	return (optlen);
+}
diff --git a/third_party/tcplp/bsdtcp/tcp_reass.c b/third_party/tcplp/bsdtcp/tcp_reass.c
new file mode 100644
index 0000000..19650e3
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/tcp_reass.c
@@ -0,0 +1,316 @@
+/*-
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)tcp_input.c	8.12 (Berkeley) 5/24/95
+ */
+
+#include "../tcplp.h"
+#include "../lib/bitmap.h"
+#include "../lib/cbuf.h"
+#include "tcp.h"
+#include "tcp_fsm.h"
+#include "tcp_seq.h"
+#include "tcp_var.h"
+
+/*
+ * samkumar: Segments are only reassembled within the window; data outside the
+ * window is thrown away. So, the total amount of reassembly data cannot exceed
+ * the size of the receive window.
+ *
+ * I have essentially rewritten it to use TCPlp's data structure for the
+ * reassembly buffer. I have kept the original code as a comment below this
+ * function, for reference.
+ *
+ * Looking at the usage of this function in tcp_input, this just has to set
+ * *tlenp to 0 if the received segment is already completely buffered; it does
+ * not need to update it if only part of the segment is trimmed off.
+ */
+int
+tcp_reass(struct tcpcb* tp, struct tcphdr* th, int* tlenp, otMessage* data, off_t data_offset, struct tcplp_signals* sig)
+{
+	size_t mergeable, written;
+	size_t offset;
+	size_t start_index;
+	size_t usedbefore;
+	int tlen;
+	size_t merged = 0;
+	int flags = 0;
+
+	/*
+	 * Call with th==NULL after become established to
+	 * force pre-ESTABLISHED data up to user socket.
+	 */
+	if (th == NULL)
+		goto present;
+
+	tlen = *tlenp;
+
+	/* Insert the new segment queue entry into place. */
+	KASSERT(SEQ_GEQ(th->th_seq, tp->rcv_nxt), ("Adding past segment to the reassembly queue"));
+	offset = (size_t) (th->th_seq - tp->rcv_nxt);
+
+	if (cbuf_reass_count_set(&tp->recvbuf, (size_t) offset, tp->reassbmp, tlen) >= (size_t) tlen) {
+		*tlenp = 0;
+		goto present;
+	}
+	written = cbuf_reass_write(&tp->recvbuf, (size_t) offset, data, data_offset, tlen, tp->reassbmp, &start_index, cbuf_copy_from_message);
+
+	if ((th->th_flags & TH_FIN) && (tp->reass_fin_index == -1)) {
+		tp->reass_fin_index = (int16_t) (start_index + tlen);
+	}
+	KASSERT(written == tlen, ("Reassembly write out of bounds: tried to write %d, but wrote %d", tlen, (int) written));
+
+present:
+	/*
+	 * Present data to user, advancing rcv_nxt through
+	 * completed sequence space.
+	 */
+	mergeable = cbuf_reass_count_set(&tp->recvbuf, 0, tp->reassbmp, (size_t) 0xFFFFFFFF);
+	usedbefore = cbuf_used_space(&tp->recvbuf);
+	if (!tpiscantrcv(tp) || usedbefore == 0) {
+		/* If usedbefore == 0, but we can't receive more, then we still need to move the buffer
+		   along by merging and then popping, in case we receive a FIN later on. */
+		if (tp->reass_fin_index >= 0 && cbuf_reass_within_offset(&tp->recvbuf, mergeable, (size_t) tp->reass_fin_index)) {
+			tp->reass_fin_index = -2; // So we won't consider any more FINs
+			flags = TH_FIN;
+		}
+		merged = cbuf_reass_merge(&tp->recvbuf, mergeable, tp->reassbmp);
+		KASSERT(merged == mergeable, ("Reassembly merge out of bounds: tried to merge %d, but merged %d", (int) mergeable, (int) merged));
+		if (tpiscantrcv(tp)) {
+			cbuf_pop(&tp->recvbuf, merged); // So no data really enters the buffer
+		} else if (merged > 0) {
+			sig->recvbuf_added = true;
+		}
+	} else {
+		/* If there is data in the buffer AND we can't receive more, then that must be because we received a FIN,
+		   but the user hasn't yet emptied the buffer of its contents. */
+		KASSERT (tp->reass_fin_index == -2, ("Can't receive more, and data in buffer, but haven't received a FIN"));
+	}
+
+	tp->rcv_nxt += mergeable;
+
+	return flags;
+}
+#if 0
+int
+tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
+{
+	struct tseg_qent *q;
+	struct tseg_qent *p = NULL;
+	struct tseg_qent *nq;
+	struct tseg_qent *te = NULL;
+	struct socket *so = tp->t_inpcb->inp_socket;
+	char *s = NULL;
+	int flags;
+	struct tseg_qent tqs;
+
+	INP_WLOCK_ASSERT(tp->t_inpcb);
+
+	/*
+	 * XXX: tcp_reass() is rather inefficient with its data structures
+	 * and should be rewritten (see NetBSD for optimizations).
+	 */
+
+	/*
+	 * Call with th==NULL after become established to
+	 * force pre-ESTABLISHED data up to user socket.
+	 */
+	if (th == NULL)
+		goto present;
+
+	/*
+	 * Limit the number of segments that can be queued to reduce the
+	 * potential for mbuf exhaustion. For best performance, we want to be
+	 * able to queue a full window's worth of segments. The size of the
+	 * socket receive buffer determines our advertised window and grows
+	 * automatically when socket buffer autotuning is enabled. Use it as the
+	 * basis for our queue limit.
+	 * Always let the missing segment through which caused this queue.
+	 * NB: Access to the socket buffer is left intentionally unlocked as we
+	 * can tolerate stale information here.
+	 *
+	 * XXXLAS: Using sbspace(so->so_rcv) instead of so->so_rcv.sb_hiwat
+	 * should work but causes packets to be dropped when they shouldn't.
+	 * Investigate why and re-evaluate the below limit after the behaviour
+	 * is understood.
+	 */
+	if ((th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) &&
+	    tp->t_segqlen >= (so->so_rcv.sb_hiwat / tp->t_maxseg) + 1) {
+		TCPSTAT_INC(tcps_rcvreassfull);
+		*tlenp = 0;
+		if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) {
+			log(LOG_DEBUG, "%s; %s: queue limit reached, "
+			    "segment dropped\n", s, __func__);
+			free(s, M_TCPLOG);
+		}
+		m_freem(m);
+		return (0);
+	}
+
+	/*
+	 * Allocate a new queue entry. If we can't, or hit the zone limit
+	 * just drop the pkt.
+	 *
+	 * Use a temporary structure on the stack for the missing segment
+	 * when the zone is exhausted. Otherwise we may get stuck.
+	 */
+	te = uma_zalloc(tcp_reass_zone, M_NOWAIT);
+	if (te == NULL) {
+		if (th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) {
+			TCPSTAT_INC(tcps_rcvmemdrop);
+			m_freem(m);
+			*tlenp = 0;
+			if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL,
+			    NULL))) {
+				log(LOG_DEBUG, "%s; %s: global zone limit "
+				    "reached, segment dropped\n", s, __func__);
+				free(s, M_TCPLOG);
+			}
+			return (0);
+		} else {
+			bzero(&tqs, sizeof(struct tseg_qent));
+			te = &tqs;
+			if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL,
+			    NULL))) {
+				log(LOG_DEBUG,
+				    "%s; %s: global zone limit reached, using "
+				    "stack for missing segment\n", s, __func__);
+				free(s, M_TCPLOG);
+			}
+		}
+	}
+	tp->t_segqlen++;
+
+	/*
+	 * Find a segment which begins after this one does.
+	 */
+	LIST_FOREACH(q, &tp->t_segq, tqe_q) {
+		if (SEQ_GT(q->tqe_th->th_seq, th->th_seq))
+			break;
+		p = q;
+	}
+
+	/*
+	 * If there is a preceding segment, it may provide some of
+	 * our data already.  If so, drop the data from the incoming
+	 * segment.  If it provides all of our data, drop us.
+	 */
+	if (p != NULL) {
+		int i;
+		/* conversion to int (in i) handles seq wraparound */
+		i = p->tqe_th->th_seq + p->tqe_len - th->th_seq;
+		if (i > 0) {
+			if (i >= *tlenp) {
+				TCPSTAT_INC(tcps_rcvduppack);
+				TCPSTAT_ADD(tcps_rcvdupbyte, *tlenp);
+				m_freem(m);
+				if (te != &tqs)
+					uma_zfree(tcp_reass_zone, te);
+				tp->t_segqlen--;
+				/*
+				 * Try to present any queued data
+				 * at the left window edge to the user.
+				 * This is needed after the 3-WHS
+				 * completes.
+				 */
+				goto present;	/* ??? */
+			}
+			m_adj(m, i);
+			*tlenp -= i;
+			th->th_seq += i;
+		}
+	}
+	tp->t_rcvoopack++;
+	TCPSTAT_INC(tcps_rcvoopack);
+	TCPSTAT_ADD(tcps_rcvoobyte, *tlenp);
+
+	/*
+	 * While we overlap succeeding segments trim them or,
+	 * if they are completely covered, dequeue them.
+	 */
+	while (q) {
+		int i = (th->th_seq + *tlenp) - q->tqe_th->th_seq;
+		if (i <= 0)
+			break;
+		if (i < q->tqe_len) {
+			q->tqe_th->th_seq += i;
+			q->tqe_len -= i;
+			m_adj(q->tqe_m, i);
+			break;
+		}
+
+		nq = LIST_NEXT(q, tqe_q);
+		LIST_REMOVE(q, tqe_q);
+		m_freem(q->tqe_m);
+		uma_zfree(tcp_reass_zone, q);
+		tp->t_segqlen--;
+		q = nq;
+	}
+
+	/* Insert the new segment queue entry into place. */
+	te->tqe_m = m;
+	te->tqe_th = th;
+	te->tqe_len = *tlenp;
+
+	if (p == NULL) {
+		LIST_INSERT_HEAD(&tp->t_segq, te, tqe_q);
+	} else {
+		KASSERT(te != &tqs, ("%s: temporary stack based entry not "
+		    "first element in queue", __func__));
+		LIST_INSERT_AFTER(p, te, tqe_q);
+	}
+
+present:
+	/*
+	 * Present data to user, advancing rcv_nxt through
+	 * completed sequence space.
+	 */
+	if (!TCPS_HAVEESTABLISHED(tp->t_state))
+		return (0);
+	q = LIST_FIRST(&tp->t_segq);
+	if (!q || q->tqe_th->th_seq != tp->rcv_nxt)
+		return (0);
+	SOCKBUF_LOCK(&so->so_rcv);
+	do {
+		tp->rcv_nxt += q->tqe_len;
+		flags = q->tqe_th->th_flags & TH_FIN;
+		nq = LIST_NEXT(q, tqe_q);
+		LIST_REMOVE(q, tqe_q);
+		if (so->so_rcv.sb_state & SBS_CANTRCVMORE)
+			m_freem(q->tqe_m);
+		else
+			sbappendstream_locked(&so->so_rcv, q->tqe_m, 0);
+		if (q != &tqs)
+			uma_zfree(tcp_reass_zone, q);
+		tp->t_segqlen--;
+		q = nq;
+	} while (q && q->tqe_th->th_seq == tp->rcv_nxt);
+	sorwakeup_locked(so);
+	return (flags);
+}
+#endif
diff --git a/third_party/tcplp/bsdtcp/tcp_sack.c b/third_party/tcplp/bsdtcp/tcp_sack.c
new file mode 100644
index 0000000..8006a7a
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/tcp_sack.c
@@ -0,0 +1,665 @@
+/*-
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995
+ *	The Regents of the University of California.
+ * All rights reserved.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)tcp_sack.c	8.12 (Berkeley) 5/24/95
+ */
+
+/*-
+ *	@@(#)COPYRIGHT	1.1 (NRL) 17 January 1995
+ *
+ * NRL grants permission for redistribution and use in source and binary
+ * forms, with or without modification, of the software and documentation
+ * created at NRL 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgements:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ *	This product includes software developed at the Information
+ *	Technology Division, US Naval Research Laboratory.
+ * 4. Neither the name of the NRL nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL 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 NRL 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.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as representing
+ * official policies, either expressed or implied, of the US Naval
+ * Research Laboratory (NRL).
+ */
+
+/* samkumar: Removed a bunch of #include's and VNET declarations. */
+
+#include <strings.h>
+#include "tcp.h"
+#include "tcp_fsm.h"
+#include "tcp_seq.h"
+#include "tcp_timer.h"
+#include "tcp_var.h"
+#include "sys/queue.h"
+
+enum tcp_sack_consts {
+	V_tcp_sack_maxholes = MAX_SACKHOLES
+};
+
+/*
+ * samkumar: Removed tcp_sack_globalmaxholes and tcp_sack_globalholes.
+ * There used to be a counter, V_tcp_sack_globalholes, that kept track of the
+ * total number of SACK holes allocated across all TCP connections.
+ */
+
+/*
+ * samkumar: I added these three functions. The first, tcp_sack_init,
+ * initializes a per-connection pool of SACK holes.
+ *
+ * The next two, sackhole_alloc and sackhole_free, allocate and deallocate SACK
+ * holes from the pool. Previously, the FreeBSD code would allocate SACK holes
+ * dynamically, for example, using the code
+ * "hole = (struct sackhole *)uma_zalloc(V_sack_hole_zone, M_NOWAIT);".
+ * TCPlp avoids dynamic memory allocation in the TCP implementation, so we
+ * replace it with this per-connection pool.
+ */
+
+void
+tcp_sack_init(struct tcpcb* tp)
+{
+	bmp_init(tp->sackhole_bmp, SACKHOLE_BMP_SIZE);
+}
+
+struct sackhole* sackhole_alloc(struct tcpcb* tp) {
+    size_t freeindex = bmp_countset(tp->sackhole_bmp, SACKHOLE_BMP_SIZE, 0, SACKHOLE_BMP_SIZE);
+    if (freeindex >= SACKHOLE_BMP_SIZE) {
+    	return NULL; // all sackholes are allocated already!
+    }
+    bmp_setrange(tp->sackhole_bmp, freeindex, 1);
+    return &tp->sackhole_pool[freeindex];
+}
+
+void sackhole_free(struct tcpcb* tp, struct sackhole* tofree) {
+	size_t freeindex = (size_t) (tofree - &tp->sackhole_pool[0]);
+	KASSERT(tofree == &tp->sackhole_pool[freeindex], ("sackhole pool unaligned"));
+	bmp_clrrange(tp->sackhole_bmp, freeindex, 1);
+}
+
+/*
+ * samkumar: Throughout the remaining functions, I have replaced allocation and
+ * deallocation of SACK holes, which previously used uma_zalloc and uma_zfree,
+ * with calls to sackhole_alloc and sackhole_free. I've also removed code for
+ * locking, global stats collection, global SACK hole limits, and debugging
+ * probes.
+ */
+
+
+/*
+ * This function is called upon receipt of new valid data (while not in
+ * header prediction mode), and it updates the ordered list of sacks.
+ */
+void
+tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_start, tcp_seq rcv_end)
+{
+	/*
+	 * First reported block MUST be the most recent one.  Subsequent
+	 * blocks SHOULD be in the order in which they arrived at the
+	 * receiver.  These two conditions make the implementation fully
+	 * compliant with RFC 2018.
+	 */
+	struct sackblk head_blk, saved_blks[MAX_SACK_BLKS];
+	int num_head, num_saved, i;
+
+	/* Check arguments. */
+	KASSERT(SEQ_LT(rcv_start, rcv_end), ("rcv_start < rcv_end"));
+
+	/* SACK block for the received segment. */
+	head_blk.start = rcv_start;
+	head_blk.end = rcv_end;
+
+	/*
+	 * Merge updated SACK blocks into head_blk, and save unchanged SACK
+	 * blocks into saved_blks[].  num_saved will have the number of the
+	 * saved SACK blocks.
+	 */
+	num_saved = 0;
+	for (i = 0; i < tp->rcv_numsacks; i++) {
+		tcp_seq start = tp->sackblks[i].start;
+		tcp_seq end = tp->sackblks[i].end;
+		if (SEQ_GEQ(start, end) || SEQ_LEQ(start, tp->rcv_nxt)) {
+			/*
+			 * Discard this SACK block.
+			 */
+		} else if (SEQ_LEQ(head_blk.start, end) &&
+			   SEQ_GEQ(head_blk.end, start)) {
+			/*
+			 * Merge this SACK block into head_blk.  This SACK
+			 * block itself will be discarded.
+			 */
+			if (SEQ_GT(head_blk.start, start))
+				head_blk.start = start;
+			if (SEQ_LT(head_blk.end, end))
+				head_blk.end = end;
+		} else {
+			/*
+			 * Save this SACK block.
+			 */
+			saved_blks[num_saved].start = start;
+			saved_blks[num_saved].end = end;
+			num_saved++;
+		}
+	}
+
+	/*
+	 * Update SACK list in tp->sackblks[].
+	 */
+	num_head = 0;
+	if (SEQ_GT(head_blk.start, tp->rcv_nxt)) {
+		/*
+		 * The received data segment is an out-of-order segment.  Put
+		 * head_blk at the top of SACK list.
+		 */
+		tp->sackblks[0] = head_blk;
+		num_head = 1;
+		/*
+		 * If the number of saved SACK blocks exceeds its limit,
+		 * discard the last SACK block.
+		 */
+		if (num_saved >= MAX_SACK_BLKS)
+			num_saved--;
+	}
+	if (num_saved > 0) {
+		/*
+		 * Copy the saved SACK blocks back.
+		 */
+		bcopy(saved_blks, &tp->sackblks[num_head],
+		      sizeof(struct sackblk) * num_saved);
+	}
+
+	/* Save the number of SACK blocks. */
+	tp->rcv_numsacks = num_head + num_saved;
+}
+
+/*
+ * Delete all receiver-side SACK information.
+ */
+void
+tcp_clean_sackreport(struct tcpcb *tp)
+{
+	int i;
+
+	tp->rcv_numsacks = 0;
+	for (i = 0; i < MAX_SACK_BLKS; i++)
+		tp->sackblks[i].start = tp->sackblks[i].end=0;
+}
+
+/*
+ * Allocate struct sackhole.
+ */
+static struct sackhole *
+tcp_sackhole_alloc(struct tcpcb *tp, tcp_seq start, tcp_seq end)
+{
+	struct sackhole *hole;
+
+	/*
+	 * samkumar: This if block also used to also return NULL if
+	 * V_tcp_sack_globalholes >= V_tcp_sack_globalmaxholes
+	 * but I removed that check since it doesn't make sense to enforce a global
+	 * limit on SACK holes when we have a fixed-size pool (moreover, a separate
+	 * pool per connection). The per-connection limit is sufficient.
+	 */
+	if (tp->snd_numholes >= V_tcp_sack_maxholes) {
+		return NULL;
+	}
+
+	hole = sackhole_alloc(tp);
+	if (hole == NULL)
+		return NULL;
+
+	hole->start = start;
+	hole->end = end;
+	hole->rxmit = start;
+
+	tp->snd_numholes++;
+
+	return hole;
+}
+
+/*
+ * Free struct sackhole.
+ */
+static void
+tcp_sackhole_free(struct tcpcb *tp, struct sackhole *hole)
+{
+	sackhole_free(tp, hole);
+
+	tp->snd_numholes--;
+
+	KASSERT(tp->snd_numholes >= 0, ("tp->snd_numholes >= 0"));
+}
+
+/*
+ * Insert new SACK hole into scoreboard.
+ */
+static struct sackhole *
+tcp_sackhole_insert(struct tcpcb *tp, tcp_seq start, tcp_seq end,
+    struct sackhole *after)
+{
+	struct sackhole *hole;
+
+	/* Allocate a new SACK hole. */
+	hole = tcp_sackhole_alloc(tp, start, end);
+	if (hole == NULL)
+		return NULL;
+
+	/* Insert the new SACK hole into scoreboard. */
+	if (after != NULL)
+		TAILQ_INSERT_AFTER(&tp->snd_holes, after, hole, scblink);
+	else
+		TAILQ_INSERT_TAIL(&tp->snd_holes, hole, scblink);
+
+	/* Update SACK hint. */
+	if (tp->sackhint.nexthole == NULL)
+		tp->sackhint.nexthole = hole;
+
+	return hole;
+}
+
+/*
+ * Remove SACK hole from scoreboard.
+ */
+static void
+tcp_sackhole_remove(struct tcpcb *tp, struct sackhole *hole)
+{
+
+	/* Update SACK hint. */
+	if (tp->sackhint.nexthole == hole)
+		tp->sackhint.nexthole = TAILQ_NEXT(hole, scblink);
+
+	/* Remove this SACK hole. */
+	TAILQ_REMOVE(&tp->snd_holes, hole, scblink);
+
+	/* Free this SACK hole. */
+	tcp_sackhole_free(tp, hole);
+}
+
+/*
+ * Process cumulative ACK and the TCP SACK option to update the scoreboard.
+ * tp->snd_holes is an ordered list of holes (oldest to newest, in terms of
+ * the sequence space).
+ */
+void
+tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack)
+{
+	struct sackhole *cur, *temp;
+	struct sackblk sack, sack_blocks[TCP_MAX_SACK + 1], *sblkp;
+	int i, j, num_sack_blks;
+
+	num_sack_blks = 0;
+	/*
+	 * If SND.UNA will be advanced by SEG.ACK, and if SACK holes exist,
+	 * treat [SND.UNA, SEG.ACK) as if it is a SACK block.
+	 */
+	if (SEQ_LT(tp->snd_una, th_ack) && !TAILQ_EMPTY(&tp->snd_holes)) {
+		sack_blocks[num_sack_blks].start = tp->snd_una;
+		sack_blocks[num_sack_blks++].end = th_ack;
+	}
+	/*
+	 * Append received valid SACK blocks to sack_blocks[], but only if we
+	 * received new blocks from the other side.
+	 */
+	if (to->to_flags & TOF_SACK) {
+		for (i = 0; i < to->to_nsacks; i++) {
+			bcopy((to->to_sacks + i * TCPOLEN_SACK),
+			    &sack, sizeof(sack));
+			sack.start = ntohl(sack.start);
+			sack.end = ntohl(sack.end);
+			if (SEQ_GT(sack.end, sack.start) &&
+			    SEQ_GT(sack.start, tp->snd_una) &&
+			    SEQ_GT(sack.start, th_ack) &&
+			    SEQ_LT(sack.start, tp->snd_max) &&
+			    SEQ_GT(sack.end, tp->snd_una) &&
+			    SEQ_LEQ(sack.end, tp->snd_max))
+				sack_blocks[num_sack_blks++] = sack;
+		}
+	}
+	/*
+	 * Return if SND.UNA is not advanced and no valid SACK block is
+	 * received.
+	 */
+	if (num_sack_blks == 0)
+		return;
+
+	/*
+	 * Sort the SACK blocks so we can update the scoreboard with just one
+	 * pass. The overhead of sorting upto 4+1 elements is less than
+	 * making upto 4+1 passes over the scoreboard.
+	 */
+	for (i = 0; i < num_sack_blks; i++) {
+		for (j = i + 1; j < num_sack_blks; j++) {
+			if (SEQ_GT(sack_blocks[i].end, sack_blocks[j].end)) {
+				sack = sack_blocks[i];
+				sack_blocks[i] = sack_blocks[j];
+				sack_blocks[j] = sack;
+			}
+		}
+	}
+	if (TAILQ_EMPTY(&tp->snd_holes))
+		/*
+		 * Empty scoreboard. Need to initialize snd_fack (it may be
+		 * uninitialized or have a bogus value). Scoreboard holes
+		 * (from the sack blocks received) are created later below
+		 * (in the logic that adds holes to the tail of the
+		 * scoreboard).
+		 */
+		tp->snd_fack = SEQ_MAX(tp->snd_una, th_ack);
+	/*
+	 * In the while-loop below, incoming SACK blocks (sack_blocks[]) and
+	 * SACK holes (snd_holes) are traversed from their tails with just
+	 * one pass in order to reduce the number of compares especially when
+	 * the bandwidth-delay product is large.
+	 *
+	 * Note: Typically, in the first RTT of SACK recovery, the highest
+	 * three or four SACK blocks with the same ack number are received.
+	 * In the second RTT, if retransmitted data segments are not lost,
+	 * the highest three or four SACK blocks with ack number advancing
+	 * are received.
+	 */
+	sblkp = &sack_blocks[num_sack_blks - 1];	/* Last SACK block */
+	tp->sackhint.last_sack_ack = sblkp->end;
+	if (SEQ_LT(tp->snd_fack, sblkp->start)) {
+		/*
+		 * The highest SACK block is beyond fack.  Append new SACK
+		 * hole at the tail.  If the second or later highest SACK
+		 * blocks are also beyond the current fack, they will be
+		 * inserted by way of hole splitting in the while-loop below.
+		 */
+		temp = tcp_sackhole_insert(tp, tp->snd_fack,sblkp->start,NULL);
+		if (temp != NULL) {
+			tp->snd_fack = sblkp->end;
+			/* Go to the previous sack block. */
+			sblkp--;
+		} else {
+			/*
+			 * We failed to add a new hole based on the current
+			 * sack block.  Skip over all the sack blocks that
+			 * fall completely to the right of snd_fack and
+			 * proceed to trim the scoreboard based on the
+			 * remaining sack blocks.  This also trims the
+			 * scoreboard for th_ack (which is sack_blocks[0]).
+			 */
+			while (sblkp >= sack_blocks &&
+			       SEQ_LT(tp->snd_fack, sblkp->start))
+				sblkp--;
+			if (sblkp >= sack_blocks &&
+			    SEQ_LT(tp->snd_fack, sblkp->end))
+				tp->snd_fack = sblkp->end;
+		}
+	} else if (SEQ_LT(tp->snd_fack, sblkp->end))
+		/* fack is advanced. */
+		tp->snd_fack = sblkp->end;
+	/* We must have at least one SACK hole in scoreboard. */
+	KASSERT(!TAILQ_EMPTY(&tp->snd_holes),
+	    ("SACK scoreboard must not be empty"));
+	cur = TAILQ_LAST(&tp->snd_holes, sackhole_head); /* Last SACK hole. */
+	/*
+	 * Since the incoming sack blocks are sorted, we can process them
+	 * making one sweep of the scoreboard.
+	 */
+	while (sblkp >= sack_blocks  && cur != NULL) {
+		if (SEQ_GEQ(sblkp->start, cur->end)) {
+			/*
+			 * SACKs data beyond the current hole.  Go to the
+			 * previous sack block.
+			 */
+			sblkp--;
+			continue;
+		}
+		if (SEQ_LEQ(sblkp->end, cur->start)) {
+			/*
+			 * SACKs data before the current hole.  Go to the
+			 * previous hole.
+			 */
+			cur = TAILQ_PREV(cur, sackhole_head, scblink);
+			continue;
+		}
+		tp->sackhint.sack_bytes_rexmit -= (cur->rxmit - cur->start);
+		KASSERT(tp->sackhint.sack_bytes_rexmit >= 0,
+		    ("sackhint bytes rtx >= 0"));
+		if (SEQ_LEQ(sblkp->start, cur->start)) {
+			/* Data acks at least the beginning of hole. */
+			if (SEQ_GEQ(sblkp->end, cur->end)) {
+				/* Acks entire hole, so delete hole. */
+				temp = cur;
+				cur = TAILQ_PREV(cur, sackhole_head, scblink);
+				tcp_sackhole_remove(tp, temp);
+				/*
+				 * The sack block may ack all or part of the
+				 * next hole too, so continue onto the next
+				 * hole.
+				 */
+				continue;
+			} else {
+				/* Move start of hole forward. */
+				cur->start = sblkp->end;
+				cur->rxmit = SEQ_MAX(cur->rxmit, cur->start);
+			}
+		} else {
+			/* Data acks at least the end of hole. */
+			if (SEQ_GEQ(sblkp->end, cur->end)) {
+				/* Move end of hole backward. */
+				cur->end = sblkp->start;
+				cur->rxmit = SEQ_MIN(cur->rxmit, cur->end);
+			} else {
+				/*
+				 * ACKs some data in middle of a hole; need
+				 * to split current hole
+				 */
+				temp = tcp_sackhole_insert(tp, sblkp->end,
+				    cur->end, cur);
+				if (temp != NULL) {
+					if (SEQ_GT(cur->rxmit, temp->rxmit)) {
+						temp->rxmit = cur->rxmit;
+						tp->sackhint.sack_bytes_rexmit
+						    += (temp->rxmit
+						    - temp->start);
+					}
+					cur->end = sblkp->start;
+					cur->rxmit = SEQ_MIN(cur->rxmit,
+					    cur->end);
+				}
+			}
+		}
+		tp->sackhint.sack_bytes_rexmit += (cur->rxmit - cur->start);
+		/*
+		 * Testing sblkp->start against cur->start tells us whether
+		 * we're done with the sack block or the sack hole.
+		 * Accordingly, we advance one or the other.
+		 */
+		if (SEQ_LEQ(sblkp->start, cur->start))
+			cur = TAILQ_PREV(cur, sackhole_head, scblink);
+		else
+			sblkp--;
+	}
+}
+
+/*
+ * Free all SACK holes to clear the scoreboard.
+ */
+void
+tcp_free_sackholes(struct tcpcb *tp)
+{
+	struct sackhole *q;
+
+	while ((q = TAILQ_FIRST(&tp->snd_holes)) != NULL)
+		tcp_sackhole_remove(tp, q);
+	tp->sackhint.sack_bytes_rexmit = 0;
+
+	KASSERT(tp->snd_numholes == 0, ("tp->snd_numholes == 0"));
+	KASSERT(tp->sackhint.nexthole == NULL,
+		("tp->sackhint.nexthole == NULL"));
+}
+
+/*
+ * Partial ack handling within a sack recovery episode.  Keeping this very
+ * simple for now.  When a partial ack is received, force snd_cwnd to a value
+ * that will allow the sender to transmit no more than 2 segments.  If
+ * necessary, a better scheme can be adopted at a later point, but for now,
+ * the goal is to prevent the sender from bursting a large amount of data in
+ * the midst of sack recovery.
+ */
+void
+tcp_sack_partialack(struct tcpcb *tp, struct tcphdr *th)
+{
+	int num_segs = 1;
+
+	tcp_timer_activate(tp, TT_REXMT, 0);
+	tp->t_rtttime = 0;
+	/* Send one or 2 segments based on how much new data was acked. */
+	if ((BYTES_THIS_ACK(tp, th) / tp->t_maxseg) >= 2)
+		num_segs = 2;
+	tp->snd_cwnd = (tp->sackhint.sack_bytes_rexmit +
+	    (tp->snd_nxt - tp->sack_newdata) + num_segs * tp->t_maxseg);
+	if (tp->snd_cwnd > tp->snd_ssthresh)
+		tp->snd_cwnd = tp->snd_ssthresh;
+	tp->t_flags |= TF_ACKNOW;
+	(void) tcp_output(tp);
+}
+
+/*
+ * samkumar: Removed this function for now, but I left it in as a comment
+ * (using #if 0) in case it is useful later for debugging.
+ */
+#if 0
+/*
+ * Debug version of tcp_sack_output() that walks the scoreboard.  Used for
+ * now to sanity check the hint.
+ */
+static struct sackhole *
+tcp_sack_output_debug(struct tcpcb *tp, int *sack_bytes_rexmt)
+{
+	struct sackhole *p;
+
+	INP_WLOCK_ASSERT(tp->t_inpcb);
+	*sack_bytes_rexmt = 0;
+	TAILQ_FOREACH(p, &tp->snd_holes, scblink) {
+		if (SEQ_LT(p->rxmit, p->end)) {
+			if (SEQ_LT(p->rxmit, tp->snd_una)) {/* old SACK hole */
+				continue;
+			}
+			*sack_bytes_rexmt += (p->rxmit - p->start);
+			break;
+		}
+		*sack_bytes_rexmt += (p->rxmit - p->start);
+	}
+	return (p);
+}
+#endif
+
+/*
+ * Returns the next hole to retransmit and the number of retransmitted bytes
+ * from the scoreboard.  We store both the next hole and the number of
+ * retransmitted bytes as hints (and recompute these on the fly upon SACK/ACK
+ * reception).  This avoids scoreboard traversals completely.
+ *
+ * The loop here will traverse *at most* one link.  Here's the argument.  For
+ * the loop to traverse more than 1 link before finding the next hole to
+ * retransmit, we would need to have at least 1 node following the current
+ * hint with (rxmit == end).  But, for all holes following the current hint,
+ * (start == rxmit), since we have not yet retransmitted from them.
+ * Therefore, in order to traverse more 1 link in the loop below, we need to
+ * have at least one node following the current hint with (start == rxmit ==
+ * end).  But that can't happen, (start == end) means that all the data in
+ * that hole has been sacked, in which case, the hole would have been removed
+ * from the scoreboard.
+ */
+struct sackhole *
+tcp_sack_output(struct tcpcb *tp, int *sack_bytes_rexmt)
+{
+	struct sackhole *hole = NULL;
+
+	*sack_bytes_rexmt = tp->sackhint.sack_bytes_rexmit;
+	hole = tp->sackhint.nexthole;
+	if (hole == NULL || SEQ_LT(hole->rxmit, hole->end))
+		goto out;
+	while ((hole = TAILQ_NEXT(hole, scblink)) != NULL) {
+		if (SEQ_LT(hole->rxmit, hole->end)) {
+			tp->sackhint.nexthole = hole;
+			break;
+		}
+	}
+out:
+	return (hole);
+}
+
+/*
+ * After a timeout, the SACK list may be rebuilt.  This SACK information
+ * should be used to avoid retransmitting SACKed data.  This function
+ * traverses the SACK list to see if snd_nxt should be moved forward.
+ */
+void
+tcp_sack_adjust(struct tcpcb *tp)
+{
+	struct sackhole *p, *cur = TAILQ_FIRST(&tp->snd_holes);
+
+	if (cur == NULL)
+		return; /* No holes */
+	if (SEQ_GEQ(tp->snd_nxt, tp->snd_fack))
+		return; /* We're already beyond any SACKed blocks */
+	/*-
+	 * Two cases for which we want to advance snd_nxt:
+	 * i) snd_nxt lies between end of one hole and beginning of another
+	 * ii) snd_nxt lies between end of last hole and snd_fack
+	 */
+	while ((p = TAILQ_NEXT(cur, scblink)) != NULL) {
+		if (SEQ_LT(tp->snd_nxt, cur->end))
+			return;
+		if (SEQ_GEQ(tp->snd_nxt, p->start))
+			cur = p;
+		else {
+			tp->snd_nxt = p->start;
+			return;
+		}
+	}
+	if (SEQ_LT(tp->snd_nxt, cur->end))
+		return;
+	tp->snd_nxt = tp->snd_fack;
+}
diff --git a/third_party/tcplp/bsdtcp/tcp_seq.h b/third_party/tcplp/bsdtcp/tcp_seq.h
new file mode 100644
index 0000000..c3caae4
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/tcp_seq.h
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 1982, 1986, 1993, 1995
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)tcp_seq.h	8.3 (Berkeley) 6/21/95
+ * $FreeBSD$
+ */
+
+#ifndef TCPLP_NETINET_TCP_SEQ_H_
+#define TCPLP_NETINET_TCP_SEQ_H_
+
+#include "../tcplp.h"
+
+/*
+ * TCP sequence numbers are 32 bit integers operated
+ * on with modular arithmetic.  These macros can be
+ * used to compare such integers.
+ */
+#define	SEQ_LT(a,b)	((int)((a)-(b)) < 0)
+#define	SEQ_LEQ(a,b)	((int)((a)-(b)) <= 0)
+#define	SEQ_GT(a,b)	((int)((a)-(b)) > 0)
+#define	SEQ_GEQ(a,b)	((int)((a)-(b)) >= 0)
+
+#define	SEQ_MIN(a, b)	((SEQ_LT(a, b)) ? (a) : (b))
+#define	SEQ_MAX(a, b)	((SEQ_GT(a, b)) ? (a) : (b))
+
+/* for modulo comparisons of timestamps */
+#define TSTMP_LT(a,b)	((int)((a)-(b)) < 0)
+#define TSTMP_GT(a,b)	((int)((a)-(b)) > 0)
+#define TSTMP_GEQ(a,b)	((int)((a)-(b)) >= 0)
+
+/*
+ * Macros to initialize tcp sequence numbers for
+ * send and receive from initial send and receive
+ * sequence numbers.
+ */
+#define	tcp_rcvseqinit(tp) \
+	(tp)->rcv_adv = (tp)->rcv_nxt = (tp)->irs + 1
+
+#define	tcp_sendseqinit(tp) \
+	(tp)->snd_una = (tp)->snd_nxt = (tp)->snd_max = (tp)->snd_up = \
+	    (tp)->snd_recover = (tp)->iss
+
+/*
+ * Clock macros for RFC 1323 timestamps.
+ */
+#define	TCP_TS_TO_TICKS(_t)	((_t) * hz / 1000)
+
+/* Timestamp wrap-around time, 24 days. */
+#define TCP_PAWS_IDLE	(24 * 24 * 60 * 60 * 1000)
+
+/*
+ * tcp_ts_getticks() in ms, should be 1ms < x < 1000ms according to RFC 1323.
+ * We always use 1ms granularity independent of hz.
+ */
+static __inline uint32_t
+tcp_ts_getticks(void)
+{
+	/* samkumar: This used to be implemented using getmicrouptime(). */
+	return tcplp_sys_get_millis();
+}
+
+#endif /* _NETINET_TCP_SEQ_H_ */
diff --git a/third_party/tcplp/bsdtcp/tcp_subr.c b/third_party/tcplp/bsdtcp/tcp_subr.c
new file mode 100644
index 0000000..4dc58b0
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/tcp_subr.c
@@ -0,0 +1,378 @@
+/*-
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)tcp_subr.c	8.2 (Berkeley) 5/24/95
+ */
+
+#include <errno.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "../tcplp.h"
+#include "ip.h"
+#include "ip6.h"
+#include "tcp.h"
+#include "tcp_fsm.h"
+#include "tcp_var.h"
+#include "tcp_seq.h"
+#include "tcp_timer.h"
+#include "sys/queue.h"
+#include "../lib/bitmap.h"
+#include "../lib/cbuf.h"
+#include "cc.h"
+
+#include "tcp_const.h"
+
+/*
+ * samkumar: This is rewritten to have the host network stack to generate the
+ * ISN with appropriate randomness.
+ */
+tcp_seq tcp_new_isn(struct tcpcb* tp) {
+	return (uint32_t) tcplp_sys_generate_isn();
+}
+
+/*
+ * samkumar: There used to be a function, void tcp_init(void), that would
+ * initialize global state for TCP, including a hash table to store TCBs,
+ * allocating memory zones for sockets, and setting global configurable state.
+ * None of that is needed for TCPlp: TCB allocation and matching is done by
+ * the host system and global configurable state is removed with hardcoded
+ * values in order to save memory, for example. Thus, I've removed the function
+ * entirely.
+ */
+
+/*
+ * A subroutine which makes it easy to track TCP state changes with DTrace.
+ * This function shouldn't be called for t_state initializations that don't
+ * correspond to actual TCP state transitions.
+ */
+void
+tcp_state_change(struct tcpcb *tp, int newstate)
+{
+#if 0
+#if defined(KDTRACE_HOOKS)
+	int pstate = tp->t_state;
+#endif
+#endif
+	tcplp_sys_log("Socket %p: %s --> %s", tp, tcpstates[tp->t_state], tcpstates[newstate]);
+	tp->t_state = newstate;
+
+	// samkumar: may need to do other actions too, so call into the host
+	tcplp_sys_on_state_change(tp, newstate);
+#if 0
+	TCP_PROBE6(state__change, NULL, tp, NULL, tp, NULL, pstate);
+#endif
+}
+
+ /* samkumar: Based on tcp_newtcb in tcp_subr.c, and tcp_usr_attach in tcp_usrreq.c. */
+__attribute__((used)) void initialize_tcb(struct tcpcb* tp) {
+	uint32_t ticks = tcplp_sys_get_ticks();
+
+	/* samkumar: Clear all fields starting laddr; rest are initialized by the host. */
+	memset(((uint8_t*) tp) + offsetof(struct tcpcb, laddr), 0x00, sizeof(struct tcpcb) - offsetof(struct tcpcb, laddr));
+	tp->reass_fin_index = -1;
+
+	/*
+	 * samkumar: Only New Reno congestion control is implemented at the moment,
+	 * so there's no need to record the congestion control algorithm used for
+	 * each TCB.
+	 */
+	// CC_ALGO(tp) = CC_DEFAULT();
+	// tp->ccv->type = IPPROTO_TCP;
+	tp->ccv->ccvc.tcp = tp;
+
+	/*
+	 * samkumar: The original code used to choose a different constant
+	 * depending on whether it's an IPv4 or IPv6 connection. In TCPlp, we
+	 * unconditionally choose the IPv6 branch.
+	 */
+	tp->t_maxseg = tp->t_maxopd =
+//#ifdef INET6
+		/*isipv6 ? */V_tcp_v6mssdflt /*:*/
+//#endif /* INET6 */
+		/*V_tcp_mssdflt*/;
+
+	if (V_tcp_do_rfc1323)
+		tp->t_flags = (TF_REQ_SCALE|TF_REQ_TSTMP);
+	if (V_tcp_do_sack)
+		tp->t_flags |= TF_SACK_PERMIT;
+	TAILQ_INIT(&tp->snd_holes);
+
+	/*
+	 * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
+	 * rtt estimate.  Set rttvar so that srtt + 4 * rttvar gives
+	 * reasonable initial retransmit time.
+	 */
+	tp->t_srtt = TCPTV_SRTTBASE;
+	tp->t_rttvar = ((TCPTV_RTOBASE - TCPTV_SRTTBASE) << TCP_RTTVAR_SHIFT) / 4;
+	tp->t_rttmin = TCPTV_MIN < 1 ? 1 : TCPTV_MIN; /* samkumar: used to be tcp_rexmit_min, which was set in tcp_init */
+	tp->t_rxtcur = TCPTV_RTOBASE;
+	tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
+	tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
+	tp->t_rcvtime = ticks;
+
+	/* samkumar: Taken from tcp_usr_attach in tcp_usrreq.c. */
+	tp->t_state = TCP6S_CLOSED;
+
+	/* samkumar: Added to initialize the per-TCP sackhole pool. */
+	tcp_sack_init(tp);
+}
+
+
+/*
+ * samkumar: Most of this function was no longer needed. It did things like
+ * reference-counting for the TCB, updating host cache stats for better
+ * starting values of, e.g., ssthresh, for new connections, freeing resources
+ * for TCP offloading, etc. There's no host cache in TCPlp and the host system
+ * is responsible for managing TCB memory, so much of this isn't needed. I just
+ * kept (and adpated) the few parts of the function that appeared to be needed
+ * for TCPlp.
+ */
+void
+tcp_discardcb(struct tcpcb *tp)
+{
+	tcp_cancel_timers(tp);
+
+	/* Allow the CC algorithm to clean up after itself. */
+	if (CC_ALGO(tp)->cb_destroy != NULL)
+		CC_ALGO(tp)->cb_destroy(tp->ccv);
+
+	tcp_free_sackholes(tp);
+}
+
+
+ /*
+ * Attempt to close a TCP control block, marking it as dropped, and freeing
+ * the socket if we hold the only reference.
+ */
+/*
+ * samkumar: Most of this function has to do with dropping the reference to
+ * the inpcb, freeing resources at the socket layer and marking it as
+ * disconnected, and miscellaneous cleanup. I've rewritten this to do what is
+ * needed for TCP.
+ */
+struct tcpcb *
+tcp_close(struct tcpcb *tp)
+{
+	tcp_state_change(tp, TCP6S_CLOSED); // for the print statement
+	tcp_discardcb(tp);
+	// Don't reset the TCB by calling initialize_tcb, since that overwrites the buffer contents.
+	return tp;
+}
+
+/*
+ * Create template to be used to send tcp packets on a connection.
+ * Allocates an mbuf and fills in a skeletal tcp/ip header.  The only
+ * use for this function is in keepalives, which use tcp_respond.
+ */
+/* samkumar: I changed the signature of this function. Instead of allocating
+ * the struct tcptemp using malloc, populating it, and then returning it, I
+ * have the caller allocate it. This function merely populates it now.
+ */
+void
+tcpip_maketemplate(struct tcpcb* tp, struct tcptemp* t)
+{
+	tcpip_fillheaders(tp, (void *)&t->tt_ipgen, (void *)&t->tt_t);
+}
+
+/*
+ * Fill in the IP and TCP headers for an outgoing packet, given the tcpcb.
+ * tcp_template used to store this data in mbufs, but we now recopy it out
+ * of the tcpcb each time to conserve mbufs.
+ */
+/*
+ * samkumar: This has a different signature from the original function in
+ * tcp_subr.c. In particular, IP header information is filled into an
+ * otMessageInfo rather than into a struct representing the on-wire header
+ * format. Additionally, I have changed it to always assume IPv6; I removed the
+ * code for IPv4.
+ */
+void
+tcpip_fillheaders(struct tcpcb* tp, otMessageInfo* ip_ptr, void *tcp_ptr)
+{
+	struct tcphdr *th = (struct tcphdr *)tcp_ptr;
+
+	/* Fill in the IP header */
+
+    /* samkumar: The old IPv6 code, for reference. */
+	// ip6 = (struct ip6_hdr *)ip_ptr;
+	// ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
+	//     (inp->inp_flow & IPV6_FLOWINFO_MASK);
+	// ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
+	//     (IPV6_VERSION & IPV6_VERSION_MASK);
+	// ip6->ip6_nxt = IPPROTO_TCP;
+	// ip6->ip6_plen = htons(sizeof(struct tcphdr));
+	// ip6->ip6_src = inp->in6p_laddr;
+	// ip6->ip6_dst = inp->in6p_faddr;
+
+	memset(ip_ptr, 0x00, sizeof(otMessageInfo));
+	memcpy(&ip_ptr->mSockAddr, &tp->laddr, sizeof(ip_ptr->mSockAddr));
+	memcpy(&ip_ptr->mPeerAddr, &tp->faddr, sizeof(ip_ptr->mPeerAddr));
+
+	/* Fill in the TCP header */
+	/* samkumar: I kept the old code commented out, for reference. */
+	//th->th_sport = inp->inp_lport;
+	//th->th_dport = inp->inp_fport;
+	th->th_sport = tp->lport;
+	th->th_dport = tp->fport;
+	th->th_seq = 0;
+	th->th_ack = 0;
+	// th->th_x2 = 0;
+	// th->th_off = 5;
+	th->th_off_x2 = (5 << TH_OFF_SHIFT);
+	th->th_flags = 0;
+	th->th_win = 0;
+	th->th_urp = 0;
+	th->th_sum = 0;		/* in_pseudo() is called later for ipv4 */
+}
+
+/*
+ * Send a single message to the TCP at address specified by
+ * the given TCP/IP header.  If m == NULL, then we make a copy
+ * of the tcpiphdr at th and send directly to the addressed host.
+ * This is used to force keep alive messages out using the TCP
+ * template for a connection.  If flags are given then we send
+ * a message back to the TCP which originated the segment th,
+ * and discard the mbuf containing it and any other attached mbufs.
+ *
+ * In any case the ack and sequence number of the transmitted
+ * segment are as specified by the parameters.
+ *
+ * NOTE: If m != NULL, then th must point to *inside* the mbuf.
+ */
+/* samkumar: Original signature was
+void
+tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m,
+	tcp_seq ack, tcp_seq seq, int flags)
+*/
+/*
+ * samkumar: Essentially all of the code had to be discarded/rewritten since I
+ * have to send out packets by allocating buffers from the host system,
+ * populating them, and passing them back to the host system to send out. I
+ * simplified the code by only using the logic that was fully necessary,
+ * eliminating the code for IPv4 packets and keeping only the code for IPv6
+ * packets. I also removed all of the mbuf logic, instead using the logic for
+ * using the host system's buffering (in particular, the code to reuse the
+ * provided mbuf is no longer there).
+ */
+void
+tcp_respond(struct tcpcb *tp, otInstance* instance, struct ip6_hdr* ip6gen, struct tcphdr *thgen,
+	tcp_seq ack, tcp_seq seq, int flags)
+{
+	otMessage* message = tcplp_sys_new_message(instance);
+	if (message == NULL) {
+		return;
+	}
+	if (otMessageSetLength(message, sizeof(struct tcphdr)) != OT_ERROR_NONE) {
+		tcplp_sys_free_message(instance, message);
+		return;
+	}
+
+	struct tcphdr th;
+	struct tcphdr* nth = &th;
+	otMessageInfo ip6info;
+	int win = 0;
+	if (tp != NULL) {
+		if (!(flags & TH_RST)) {
+			win = cbuf_free_space(&tp->recvbuf);
+			if (win > (long)TCP_MAXWIN << tp->rcv_scale)
+				win = (long)TCP_MAXWIN << tp->rcv_scale;
+		}
+	}
+	memset(&ip6info, 0x00, sizeof(otMessageInfo));
+	memcpy(&ip6info.mSockAddr, &ip6gen->ip6_dst, sizeof(ip6info.mSockAddr));
+	memcpy(&ip6info.mPeerAddr, &ip6gen->ip6_src, sizeof(ip6info.mPeerAddr));
+	nth->th_sport = thgen->th_dport;
+	nth->th_dport = thgen->th_sport;
+	nth->th_seq = htonl(seq);
+	nth->th_ack = htonl(ack);
+	/* samkumar: original code for setting th_x2 and th_off, for reference. */
+	// nth->th_x2 = 0;
+	// nth->th_off = (sizeof (struct tcphdr) + optlen) >> 2;
+	nth->th_off_x2 = (sizeof(struct tcphdr) >> 2) << TH_OFF_SHIFT;
+	nth->th_flags = flags;
+	if (tp != NULL)
+		nth->th_win = htons((uint16_t) (win >> tp->rcv_scale));
+	else
+		nth->th_win = htons((uint16_t)win);
+	nth->th_urp = 0;
+	nth->th_sum = 0;
+
+	otMessageWrite(message, 0, &th, sizeof(struct tcphdr));
+
+	tcplp_sys_send_message(instance, message, &ip6info);
+}
+
+/*
+ * Drop a TCP connection, reporting
+ * the specified error.  If connection is synchronized,
+ * then send a RST to peer.
+ */
+/*
+ * samkumar: I changed the parameter "errno" to "errnum" since it caused
+ * problems during compilation. I also the code for asserting locks,
+ * incermenting stats, and managing the sockets layer.
+ */
+struct tcpcb *
+tcp_drop(struct tcpcb *tp, int errnum)
+{
+	if (TCPS_HAVERCVDSYN(tp->t_state)) {
+		tcp_state_change(tp, TCPS_CLOSED);
+		(void) tcp_output(tp);
+	}
+	if (errnum == ETIMEDOUT && tp->t_softerror)
+		errnum = tp->t_softerror;
+	tp = tcp_close(tp);
+	tcplp_sys_connection_lost(tp, errnum);
+	return tp;
+}
+
+/*
+ * Look-up the routing entry to the peer of this inpcb.  If no route
+ * is found and it cannot be allocated, then return 0.  This routine
+ * is called by TCP routines that access the rmx structure and by
+ * tcp_mss_update to get the peer/interface MTU.
+ */
+/*
+ * samkumar: In TCPlp, we don't bother with keeping track of the MTU for each
+ * route. The MSS we choose for the 6LoWPAN/802.15.4 network is probably the
+ * bottleneck, so we just use that. (I also removed the struct in_conninfo *
+ * that was formerly the first argument).
+ */
+uint64_t
+tcp_maxmtu6(struct tcpcb* tp, struct tcp_ifcap *cap)
+{
+	uint64_t maxmtu = 0;
+
+	KASSERT (tp != NULL, ("tcp_maxmtu6 with NULL tcpcb pointer"));
+	if (!IN6_IS_ADDR_UNSPECIFIED(&tp->faddr)) {
+		maxmtu = FRAMES_PER_SEG * FRAMECAP_6LOWPAN;
+	}
+
+	return (maxmtu);
+}
diff --git a/third_party/tcplp/bsdtcp/tcp_timer.c b/third_party/tcplp/bsdtcp/tcp_timer.c
new file mode 100644
index 0000000..bdc6d42
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/tcp_timer.c
@@ -0,0 +1,501 @@
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)tcp_timer.h	8.1 (Berkeley) 6/10/93
+ * $FreeBSD$
+ */
+
+#include <errno.h>
+#include <stdio.h>
+
+#include "../tcplp.h"
+#include "../lib/lbuf.h"
+#include "tcp_fsm.h"
+#include "tcp_timer.h"
+#include "tcp_var.h"
+
+#include "tcp_const.h"
+
+/*
+ * samkumar: These options only matter if we do blackhole detection, which we
+ * are not doing in TCPlp.
+ */
+#if 0
+int V_tcp_pmtud_blackhole_detect = 0;
+int V_tcp_pmtud_blackhole_failed = 0;
+int V_tcp_pmtud_blackhole_activated = 0;
+int V_tcp_pmtud_blackhole_activated_min_mss = 0;
+#endif
+
+/*
+ * TCP timer processing.
+ */
+
+/*
+ * samkumar: I changed these functions to accept "struct tcpcb* tp" their
+ * argument instead of "void *xtp". This is possible since we're no longer
+ * relying on FreeBSD's callout subsystem in TCPlp. I also changed them to
+ * return 1 if the connection is dropped, or 0 otherwise.
+ */
+
+int
+tcp_timer_delack(struct tcpcb* tp)
+{
+	/* samkumar: I added this, to replace the code I removed below. */
+	KASSERT(tpistimeractive(tp, TT_DELACK), ("Delack timer running, but unmarked"));
+	tpcleartimeractive(tp, TT_DELACK);
+
+	/*
+	 * samkumar: There used to be code here to properly handle the callout,
+	 * including edge cases (return early if the callout was reset after this
+	 * function was scheduled for execution, deactivate the callout, return
+	 * early if the INP_DROPPED flag is set on the inpcb, and assert that the
+	 * tp->t_timers state is correct).
+	 *
+	 * I also removed stats collection, locking, and vnet, throughout the code.
+	 */
+	tp->t_flags |= TF_ACKNOW;
+	(void) tcp_output(tp);
+	return 0;
+}
+
+int
+tcp_timer_keep(struct tcpcb* tp)
+{
+	uint32_t ticks = tcplp_sys_get_ticks();
+	struct tcptemp t_template;
+
+	/* samkumar: I added this, to replace the code I removed below. */
+	KASSERT(tpistimeractive(tp, TT_KEEP), ("Keep timer running, but unmarked"));
+	tpcleartimeractive(tp, TT_KEEP);
+
+	/*
+	 * samkumar: There used to be code here to properly handle the callout,
+	 * including edge cases (return early if the callout was reset after this
+	 * function was scheduled for execution, deactivate the callout, return
+	 * early if the INP_DROPPED flag is set on the inpcb, and assert that the
+	 * tp->t_timers state is correct).
+	 *
+	 * I also removed stats collection, locking, and vnet, throughout the code.
+	 * I commented out checks on socket options (since we don't support those).
+	 *
+	 * I also allocate t_template on the stack instead of allocating it
+	 * dynamically, on the heap.
+	 */
+
+	/*
+	 * Keep-alive timer went off; send something
+	 * or drop connection if idle for too long.
+	 */
+	if (tp->t_state < TCPS_ESTABLISHED)
+		goto dropit;
+	if ((always_keepalive/* || inp->inp_socket->so_options & SO_KEEPALIVE*/) &&
+	    tp->t_state <= TCPS_CLOSING) {
+		if (ticks - tp->t_rcvtime >= TP_KEEPIDLE(tp) + TP_MAXIDLE(tp))
+			goto dropit;
+		/*
+		 * Send a packet designed to force a response
+		 * if the peer is up and reachable:
+		 * either an ACK if the connection is still alive,
+		 * or an RST if the peer has closed the connection
+		 * due to timeout or reboot.
+		 * Using sequence number tp->snd_una-1
+		 * causes the transmitted zero-length segment
+		 * to lie outside the receive window;
+		 * by the protocol spec, this requires the
+		 * correspondent TCP to respond.
+		 */
+		tcpip_maketemplate(tp, &t_template);
+		/*
+		 * samkumar: I removed checks to make sure t_template was successfully
+		 * allocated and then free it as appropriate. This is not necessary
+		 * because I rewrote this part of the code to allocate t_template on
+		 * the stack.
+		 */
+		tcp_respond(tp, tp->instance, (struct ip6_hdr*) t_template.tt_ipgen,
+			    &t_template.tt_t,
+			    tp->rcv_nxt, tp->snd_una - 1, 0);
+		/*
+		 * samkumar: I replaced a call to callout_reset with the following
+		 * code, which resets the timer the TCPlp way.
+		 */
+		tpmarktimeractive(tp, TT_KEEP);
+		tcplp_sys_set_timer(tp, TT_KEEP, TP_KEEPINTVL(tp));
+	} else {
+		/*
+		 * samkumar: I replaced a call to callout_reset with the following
+		 * code, which resets the timer the TCPlp way.
+		 */
+		tpmarktimeractive(tp, TT_KEEP);
+		tcplp_sys_set_timer(tp, TT_KEEP, TP_KEEPIDLE(tp));
+	}
+
+	/*
+	 * samkumar: There used to be some code here and below the "dropit" label
+	 * that handled debug tracing/probes, vnet, and locking. I removed that
+	 * code.
+	 */
+	return 0;
+
+dropit:
+	tp = tcp_drop(tp, ETIMEDOUT);
+	(void) tp; /* samkumar: prevent a compiler warning */
+	return 1;
+}
+
+int
+tcp_timer_persist(struct tcpcb* tp)
+{
+	uint32_t ticks = tcplp_sys_get_ticks();
+	int dropped = 0;
+
+	/* samkumar: I added this, to replace the code I removed below. */
+	KASSERT(tpistimeractive(tp, TT_PERSIST), ("Persist timer running, but unmarked"));
+	tpcleartimeractive(tp, TT_PERSIST); // mark that this timer is no longer active
+
+	/*
+	 * samkumar: There used to be code here to properly handle the callout,
+	 * including edge cases (return early if the callout was reset after this
+	 * function was scheduled for execution, deactivate the callout, return
+	 * early if the INP_DROPPED flag is set on the inpcb, and assert that the
+	 * tp->t_timers state is correct).
+	 *
+	 * I also removed stats collection, locking, and vnet, throughout the code.
+	 * I commented out checks on socket options (since we don't support those).
+	 */
+
+	/*
+	 * Persistance timer into zero window.
+	 * Force a byte to be output, if possible.
+	 */
+	/*
+
+	 * Hack: if the peer is dead/unreachable, we do not
+	 * time out if the window is closed.  After a full
+	 * backoff, drop the connection if the idle time
+	 * (no responses to probes) reaches the maximum
+	 * backoff that we would use if retransmitting.
+	 */
+
+	if (tp->t_rxtshift == TCP_MAXRXTSHIFT &&
+	    (ticks - tp->t_rcvtime >= tcp_maxpersistidle ||
+	     ticks - tp->t_rcvtime >= TCP_REXMTVAL(tp) * tcp_totbackoff)) {
+		tp = tcp_drop(tp, ETIMEDOUT);
+		dropped = 1;
+		goto out;
+	}
+
+	/*
+	 * If the user has closed the socket then drop a persisting
+	 * connection after a much reduced timeout.
+	 */
+	if (tp->t_state > TCPS_CLOSE_WAIT &&
+	    (ticks - tp->t_rcvtime) >= TCPTV_PERSMAX) {
+		tp = tcp_drop(tp, ETIMEDOUT);
+		dropped = 1;
+		goto out;
+	}
+
+	tcp_setpersist(tp);
+	tp->t_flags |= TF_FORCEDATA;
+	tcplp_sys_log("Persist output: %zu bytes in sendbuf", lbuf_used_space(&tp->sendbuf));
+	(void) tcp_output(tp);
+	tp->t_flags &= ~TF_FORCEDATA;
+
+out:
+	/*
+	 * samkumar: There used to be some code here that handled debug
+	 * tracing/probes, vnet, and locking. I removed that code.
+	 */
+	(void) tp; /* samkumar: prevent a compiler warning */
+	return dropped;
+}
+
+int
+tcp_timer_2msl(struct tcpcb* tp)
+{
+	uint32_t ticks = tcplp_sys_get_ticks();
+	int dropped = 0;
+
+	/* samkumar: I added this, to replace the code I removed below. */
+	KASSERT(tpistimeractive(tp, TT_2MSL), ("2MSL timer running, but unmarked"));
+	tpcleartimeractive(tp, TT_2MSL);
+
+	/*
+	 * samkumar: There used to be code here to properly handle the callout,
+	 * including edge cases (return early if the callout was reset after this
+	 * function was scheduled for execution, deactivate the callout, return
+	 * early if the INP_DROPPED flag is set on the inpcb, and assert that the
+	 * tp->t_timers state is correct).
+	 *
+	 * I also removed stats collection, locking, and vnet, throughout the code.
+	 */
+
+	/*
+	 * 2 MSL timeout in shutdown went off.  If we're closed but
+	 * still waiting for peer to close and connection has been idle
+	 * too long delete connection control block.  Otherwise, check
+	 * again in a bit.
+	 *
+	 * If in TIME_WAIT state just ignore as this timeout is handled in
+	 * tcp_tw_2msl_scan().
+	 *
+	 * If fastrecycle of FIN_WAIT_2, in FIN_WAIT_2 and receiver has closed,
+	 * there's no point in hanging onto FIN_WAIT_2 socket. Just close it.
+	 * Ignore fact that there were recent incoming segments.
+	 */
+
+	/*
+	 * samkumar: The above comment about ignoring this timeout if we're in the
+	 * TIME_WAIT state no longer is true, since in TCPlp we changed how
+	 * TIME_WAIT is handled. In FreeBSD, this timer isn't used for sockets in
+	 * the TIME_WAIT state; instead the tcp_tw_2msl_scan method is called
+	 * periodically on the slow timer, and expired tcptw structs are closed and
+	 * freed. I changed it so that TIME-WAIT connections are still represented
+	 * as tcpcb's, not tcptw's, and to rely on this timer to close the
+	 * connection.
+	 *
+	 * Below, there used to be an if statement that checks the inpcb to tell
+	 * if we're in TIME-WAIT state, and return early if so. I've replaced this
+	 * with an if statement that checks the tcpcb if we're in the TIME-WAIT
+	 * state, and acts appropriately if so.
+	 */
+	if (tp->t_state == TCP6S_TIME_WAIT) {
+		tp = tcp_close(tp);
+		tcplp_sys_connection_lost(tp, CONN_LOST_NORMAL);
+		dropped = 1;
+		return dropped;
+	}
+	/*
+	 * samkumar: This if statement also used to check that an inpcb is still
+	 * attached and also
+	 * (tp->t_inpcb->inp_socket->so_rcv.sb_state & SBS_CANTRCVMORE).
+	 * We replaced the check on that flag with a call to tpiscantrcv. We
+	 * haven't received a FIN, since we're in FIN-WAIT-2, so the only way it
+	 * would pass the check is if the user called shutdown(SHUT_RD)
+	 * or shutdown(SHUT_RDWR), which is impossible unless the host system
+	 * provides an API for that.
+	 */
+	if (tcp_fast_finwait2_recycle && tp->t_state == TCPS_FIN_WAIT_2 &&
+	    tpiscantrcv(tp)) {
+		tp = tcp_close(tp);
+		tcplp_sys_connection_lost(tp, CONN_LOST_NORMAL);
+		dropped = 1;
+	} else {
+		if (ticks - tp->t_rcvtime <= TP_MAXIDLE(tp)) {
+			/*
+			 * samkumar: I replaced a call to callout_reset with the following
+			 * code, which resets the timer the TCPlp way.
+			 */
+			tpmarktimeractive(tp, TT_2MSL);
+			tcplp_sys_set_timer(tp, TT_2MSL, TP_KEEPINTVL(tp));
+		} else {
+			tp = tcp_close(tp);
+			tcplp_sys_connection_lost(tp, CONN_LOST_NORMAL);
+			dropped = 1;
+		}
+	}
+	/*
+	 * samkumar: There used to be some code here that handled debug
+	 * tracing/probes, vnet, and locking. I removed that code.
+	 */
+	return dropped;
+}
+
+int
+tcp_timer_rexmt(struct tcpcb *tp)
+{
+	int rexmt;
+	uint32_t ticks = tcplp_sys_get_ticks();
+	int dropped = 0;
+
+	/* samkumar: I added this, to replace the code I removed below. */
+	KASSERT(tpistimeractive(tp, TT_REXMT), ("Rexmt timer running, but unmarked"));
+	tpcleartimeractive(tp, TT_REXMT);
+
+	/*
+	 * samkumar: There used to be code here to properly handle the callout,
+	 * including edge cases (return early if the callout was reset after this
+	 * function was scheduled for execution, deactivate the callout, return
+	 * early if the INP_DROPPED flag is set on the inpcb, and assert that the
+	 * tp->t_timers state is correct).
+	 *
+	 * I also removed stats collection, locking, and vnet, throughout the code.
+	 */
+
+	tcp_free_sackholes(tp);
+	/*
+	 * Retransmission timer went off.  Message has not
+	 * been acked within retransmit interval.  Back off
+	 * to a longer retransmit interval and retransmit one segment.
+	 */
+	tcplp_sys_log("rxtshift is %d", (int) tp->t_rxtshift);
+	if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
+		tp->t_rxtshift = TCP_MAXRXTSHIFT;
+
+		tp = tcp_drop(tp, tp->t_softerror ?
+			      tp->t_softerror : ETIMEDOUT);
+		dropped = 1;
+		goto out;
+	}
+	if (tp->t_state == TCPS_SYN_SENT) {
+		/*
+		 * If the SYN was retransmitted, indicate CWND to be
+		 * limited to 1 segment in cc_conn_init().
+		 */
+		tp->snd_cwnd = 1;
+	} else if (tp->t_rxtshift == 1) {
+		/*
+		 * first retransmit; record ssthresh and cwnd so they can
+		 * be recovered if this turns out to be a "bad" retransmit.
+		 * A retransmit is considered "bad" if an ACK for this
+		 * segment is received within RTT/2 interval; the assumption
+		 * here is that the ACK was already in flight.  See
+		 * "On Estimating End-to-End Network Path Properties" by
+		 * Allman and Paxson for more details.
+		 */
+		tp->snd_cwnd_prev = tp->snd_cwnd;
+		tp->snd_ssthresh_prev = tp->snd_ssthresh;
+		tp->snd_recover_prev = tp->snd_recover;
+		if (IN_FASTRECOVERY(tp->t_flags))
+			tp->t_flags |= TF_WASFRECOVERY;
+		else
+			tp->t_flags &= ~TF_WASFRECOVERY;
+		if (IN_CONGRECOVERY(tp->t_flags))
+			tp->t_flags |= TF_WASCRECOVERY;
+		else
+			tp->t_flags &= ~TF_WASCRECOVERY;
+		tp->t_badrxtwin = ticks + (tp->t_srtt >> (TCP_RTT_SHIFT + 1));
+		tp->t_flags |= TF_PREVVALID;
+	} else
+		tp->t_flags &= ~TF_PREVVALID;
+	if (tp->t_state == TCPS_SYN_SENT)
+		rexmt = TCPTV_RTOBASE * tcp_syn_backoff[tp->t_rxtshift];
+	else
+		rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
+	TCPT_RANGESET(tp->t_rxtcur, rexmt,
+		      tp->t_rttmin, TCPTV_REXMTMAX);
+
+	/*
+	 * samkumar: There used to be more than 100 lines of code here, which
+	 * implemented a feature called blackhole detection. The idea here is that
+	 * some routers may silently discard packets whose MTU is too large,
+	 * instead of fragmenting the packet or sending an ICMP packet to give
+	 * feedback to the host. Blackhole detection decreases the MTU in response
+	 * to packet loss in case the packets are being dropped by such a router.
+	 *
+	 * In TCPlp, we do not do blackhole detection because we use a small MTU
+	 * (hundreds of bytes) that is unlikely to be too large for intermediate
+	 * routers in the Internet. The edge low-power wireless network is
+	 * assumed to be engineered to handle 6LoWPAN correctly.
+	 */
+
+	/*
+	 * Disable RFC1323 and SACK if we haven't got any response to
+	 * our third SYN to work-around some broken terminal servers
+	 * (most of which have hopefully been retired) that have bad VJ
+	 * header compression code which trashes TCP segments containing
+	 * unknown-to-them TCP options.
+	 */
+	if (tcp_rexmit_drop_options && (tp->t_state == TCPS_SYN_SENT) &&
+	    (tp->t_rxtshift == 3))
+		tp->t_flags &= ~(TF_REQ_SCALE|TF_REQ_TSTMP|TF_SACK_PERMIT);
+	/*
+	 * If we backed off this far, our srtt estimate is probably bogus.
+	 * Clobber it so we'll take the next rtt measurement as our srtt;
+	 * move the current srtt into rttvar to keep the current
+	 * retransmit times until then.
+	 */
+	if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) {
+		/*
+		 * samkumar: Here, there used to be a call to "in6_losing", used to
+		 * inform the lower layers about bad connectivity so it can search for
+		 * different routes. The call was wrapped in a check on the inpcb's
+		 * flags to check for IPv6 (which isn't relevant to us, since TCPlp
+		 * assumes IPv6).
+		 */
+		tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT);
+		tp->t_srtt = 0;
+	}
+	tp->snd_nxt = tp->snd_una;
+	tp->snd_recover = tp->snd_max;
+	/*
+	 * Force a segment to be sent.
+	 */
+	tp->t_flags |= TF_ACKNOW;
+	/*
+	 * If timing a segment in this window, stop the timer.
+	 */
+	tp->t_rtttime = 0;
+
+	cc_cong_signal(tp, NULL, CC_RTO);
+
+	(void) tcp_output(tp);
+
+out:
+	/*
+	 * samkumar: There used to be some code here that handled debug
+	 * tracing/probes, vnet, and locking. I removed that code.
+	 */
+	(void) tp; /* samkumar: Prevent a compiler warning */
+	return dropped;
+}
+
+int
+tcp_timer_active(struct tcpcb *tp, uint32_t timer_type)
+{
+	return tpistimeractive(tp, timer_type);
+}
+
+void
+tcp_timer_activate(struct tcpcb *tp, uint32_t timer_type, uint32_t delta) {
+	if (delta) {
+		tpmarktimeractive(tp, timer_type);
+		if (tpistimeractive(tp, TT_REXMT) && tpistimeractive(tp, TT_PERSIST)) {
+			tcplp_sys_panic("TCP CRITICAL FAILURE: Retransmit and Persist timers are simultaneously running!");
+		}
+		tcplp_sys_set_timer(tp, timer_type, (uint32_t) delta);
+	} else {
+		tpcleartimeractive(tp, timer_type);
+		tcplp_sys_stop_timer(tp, timer_type);
+	}
+}
+
+void
+tcp_cancel_timers(struct tcpcb* tp) {
+	tpcleartimeractive(tp, TT_DELACK);
+	tcplp_sys_stop_timer(tp, TT_DELACK);
+	tpcleartimeractive(tp, TT_REXMT);
+	tcplp_sys_stop_timer(tp, TT_REXMT);
+	tpcleartimeractive(tp, TT_PERSIST);
+	tcplp_sys_stop_timer(tp, TT_PERSIST);
+	tpcleartimeractive(tp, TT_KEEP);
+	tcplp_sys_stop_timer(tp, TT_KEEP);
+	tpcleartimeractive(tp, TT_2MSL);
+	tcplp_sys_stop_timer(tp, TT_2MSL);
+}
diff --git a/third_party/tcplp/bsdtcp/tcp_timer.h b/third_party/tcplp/bsdtcp/tcp_timer.h
new file mode 100644
index 0000000..45bafc4
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/tcp_timer.h
@@ -0,0 +1,184 @@
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)tcp_timer.h	8.1 (Berkeley) 6/10/93
+ * $FreeBSD$
+ */
+
+/**
+ * samkumar: The FreeBSD Operating System uses its callout subsystem to
+ * implement TCP timers. I've removed the relevant definitions/declarations
+ * below, since TCPlp relies on the host system to implement TCP timers. To
+ * save memory, I've removed some configurability (e.g., per-TCB keepalive
+ * parameters) and global statistics (e.g. tcp_keepcnt).
+ */
+
+#ifndef TCPLP_NETINET_TCP_TIMER_H_
+#define TCPLP_NETINET_TCP_TIMER_H_
+
+#include "tcp_var.h"
+
+/*
+ * The TCPT_REXMT timer is used to force retransmissions.
+ * The TCP has the TCPT_REXMT timer set whenever segments
+ * have been sent for which ACKs are expected but not yet
+ * received.  If an ACK is received which advances tp->snd_una,
+ * then the retransmit timer is cleared (if there are no more
+ * outstanding segments) or reset to the base value (if there
+ * are more ACKs expected).  Whenever the retransmit timer goes off,
+ * we retransmit one unacknowledged segment, and do a backoff
+ * on the retransmit timer.
+ *
+ * The TCPT_PERSIST timer is used to keep window size information
+ * flowing even if the window goes shut.  If all previous transmissions
+ * have been acknowledged (so that there are no retransmissions in progress),
+ * and the window is too small to bother sending anything, then we start
+ * the TCPT_PERSIST timer.  When it expires, if the window is nonzero,
+ * we go to transmit state.  Otherwise, at intervals send a single byte
+ * into the peer's window to force him to update our window information.
+ * We do this at most as often as TCPT_PERSMIN time intervals,
+ * but no more frequently than the current estimate of round-trip
+ * packet time.  The TCPT_PERSIST timer is cleared whenever we receive
+ * a window update from the peer.
+ *
+ * The TCPT_KEEP timer is used to keep connections alive.  If an
+ * connection is idle (no segments received) for TCPTV_KEEP_INIT amount of time,
+ * but not yet established, then we drop the connection.  Once the connection
+ * is established, if the connection is idle for TCPTV_KEEP_IDLE time
+ * (and keepalives have been enabled on the socket), we begin to probe
+ * the connection.  We force the peer to send us a segment by sending:
+ *	<SEQ=SND.UNA-1><ACK=RCV.NXT><CTL=ACK>
+ * This segment is (deliberately) outside the window, and should elicit
+ * an ack segment in response from the peer.  If, despite the TCPT_KEEP
+ * initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE
+ * amount of time probing, then we drop the connection.
+ */
+
+#define TT_DELACK	0x0001
+#define TT_REXMT	0x0002
+#define TT_PERSIST	0x0004
+#define TT_KEEP		0x0008
+#define TT_2MSL		0x0010
+
+/*
+ * Time constants.
+ */
+#define	TCPTV_MSL	( 30*hz)		/* max seg lifetime (hah!) */
+#define	TCPTV_SRTTBASE	0			/* base roundtrip time;
+						   if 0, no idea yet */
+#define	TCPTV_RTOBASE	(  3*hz)		/* assumed RTO if no info */
+
+#define	TCPTV_PERSMIN	(  5*hz)		/* retransmit persistence */
+#define	TCPTV_PERSMAX	( 60*hz)		/* maximum persist interval */
+
+#define	TCPTV_KEEP_INIT	( 75*hz)		/* initial connect keepalive */
+#define	TCPTV_KEEP_IDLE	(120*60*hz)		/* dflt time before probing */
+#define	TCPTV_KEEPINTVL	( 75*hz)		/* default probe interval */
+#define	TCPTV_KEEPCNT	8			/* max probes before drop */
+
+#define TCPTV_FINWAIT2_TIMEOUT (60*hz)         /* FIN_WAIT_2 timeout if no receiver */
+
+/*
+ * Minimum retransmit timer is 3 ticks, for algorithmic stability.
+ * TCPT_RANGESET() will add another TCPTV_CPU_VAR to deal with
+ * the expected worst-case processing variances by the kernels
+ * representing the end points.  Such variances do not always show
+ * up in the srtt because the timestamp is often calculated at
+ * the interface rather then at the TCP layer.  This value is
+ * typically 50ms.  However, it is also possible that delayed
+ * acks (typically 100ms) could create issues so we set the slop
+ * to 200ms to try to cover it.  Note that, properly speaking,
+ * delayed-acks should not create a major issue for interactive
+ * environments which 'P'ush the last segment, at least as
+ * long as implementations do the required 'at least one ack
+ * for every two packets' for the non-interactive streaming case.
+ * (maybe the RTO calculation should use 2*RTT instead of RTT
+ * to handle the ack-every-other-packet case).
+ *
+ * The prior minimum of 1*hz (1 second) badly breaks throughput on any
+ * networks faster then a modem that has minor (e.g. 1%) packet loss.
+ */
+#define	TCPTV_MIN	( hz/33 )		/* minimum allowable value */
+#define TCPTV_CPU_VAR	( hz/5 )		/* cpu variance allowed (200ms) */
+#define	TCPTV_REXMTMAX	( 64*hz)		/* max allowable REXMT value */
+
+#define TCPTV_TWTRUNC	8			/* RTO factor to truncate TW */
+
+#define	TCP_LINGERTIME	120			/* linger at most 2 minutes */
+
+#define	TCP_MAXRXTSHIFT	12			/* maximum retransmits */
+
+#define	TCPTV_DELACK	( hz/10 )		/* 100ms timeout */
+
+#ifdef	TCPTIMERS
+static const char *tcptimers[] =
+    { "REXMT", "PERSIST", "KEEP", "2MSL", "DELACK" };
+#endif
+
+int tcp_timer_active(struct tcpcb *tp, uint32_t timer_type);
+void tcp_timer_activate(struct tcpcb *tp, uint32_t timer_type, uint32_t delta);
+void tcp_cancel_timers(struct tcpcb* tp);
+
+/* I moved the definition of TCPT_RANGESET to tcp_const.h. */
+
+static const int	tcp_syn_backoff[TCP_MAXRXTSHIFT + 1] =
+    { 1, 1, 1, 1, 1, 2, 4, 8, 16, 32, 64, 64, 64 };
+
+static const int	tcp_backoff[TCP_MAXRXTSHIFT + 1] =
+    { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 512, 512, 512 };
+
+static const int tcp_totbackoff = 2559;	/* sum of tcp_backoff[] */
+
+/*
+ * samkumar: Changed return value to int to indicate whether connection was
+ * dropped or not.
+ */
+int tcp_timer_delack(struct tcpcb* tp);
+int tcp_timer_keep(struct tcpcb* tp);
+int tcp_timer_persist(struct tcpcb* tp);
+int tcp_timer_2msl(struct tcpcb* tp);
+int tcp_timer_rexmt(struct tcpcb *tp);
+int tcp_timer_active(struct tcpcb *tp, uint32_t timer_type);
+
+/*
+ * samkumar: Modified to use default keepalive parameters, since we removed
+ * the fields from tcpcb that allow them to be set on a per-connection basis.
+ */
+#define	TP_KEEPINIT(tp)	(/*(tp)->t_keepinit ? (tp)->t_keepinit :*/ tcp_keepinit)
+#define	TP_KEEPIDLE(tp)	(/*(tp)->t_keepidle ? (tp)->t_keepidle :*/ tcp_keepidle)
+#define	TP_KEEPINTVL(tp) (/*(tp)->t_keepintvl ? (tp)->t_keepintvl :*/ tcp_keepintvl)
+#define	TP_KEEPCNT(tp)	(/*(tp)->t_keepcnt ? (tp)->t_keepcnt :*/ tcp_keepcnt)
+#define	TP_MAXIDLE(tp)	(TP_KEEPCNT(tp) * TP_KEEPINTVL(tp))
+
+/*
+ * samkumar: MOVED NECESSARY EXTERN DECLARATIONS TO TCP_SUBR.C
+ * Removed timer declarations that aren't needed since timers are handled
+ * by the host system (in this case, OpenThread), in TCPlp.
+ */
+
+#endif /* !_NETINET_TCP_TIMER_H_ */
diff --git a/third_party/tcplp/bsdtcp/tcp_timewait.c b/third_party/tcplp/bsdtcp/tcp_timewait.c
new file mode 100644
index 0000000..61ef748
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/tcp_timewait.c
@@ -0,0 +1,395 @@
+/*-
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)tcp_subr.c	8.2 (Berkeley) 5/24/95
+ */
+
+#include <string.h>
+
+#include "tcp.h"
+#include "tcp_fsm.h"
+#include "tcp_seq.h"
+#include "tcp_timer.h"
+#include "tcp_var.h"
+
+#include "tcp_const.h"
+#include <openthread/ip6.h>
+#include <openthread/message.h>
+
+/*
+ * samkumar: The V_nolocaltimewait variable corresponds to the
+ * net.inet.tcp.nolocaltimewait option in FreeBSD. When set to 1, it skips the
+ * TIME-WAIT state for TCP connections where both endpoints are local IP
+ * addresses, to save resources on HTTP accelerators, database servers/clients,
+ * etc. In TCPlp, I eliminated support for this feature, but I have kept the
+ * code for it, commented out with "#if 0", in case we choose to bring it back
+ * at a later time.
+ *
+ * See also the "#if 0" block in tcp_twstart.
+ */
+#if 0
+enum tcp_timewait_consts {
+	V_nolocaltimewait = 0
+};
+#endif
+
+/*
+ * samkumar: The FreeBSD code used a separate, smaller structure, called
+ * struct tcptw, to respresent connections in the TIME-WAIT state. In TCPlp,
+ * we use the full struct tcpcb structure even in the TIME-WAIT state. This
+ * consumes more memory, but switching to a different structure like
+ * struct tcptw to save memory would be difficult because the host system or
+ * application has allocated these structures; we can't simply "free" the
+ * struct tcpcb. It would have to have been done via a callback or something,
+ * and in the common case of statically allocated sockets, this would actually
+ * result in more memory (since an application would need to allocate both the
+ * struct tcpcb and the struct tcptw, if it uses a static allocation approach).
+ *
+ * Below, I've changed the function signatures to accept "struct tcpcb* tp"
+ * instead of "struct tcptw *tw" and I have reimplemented the functions
+ * to work using tp (of type struct tcpcb) instead of tw (of type
+ * struct tcptw).
+ *
+ * Conceptually, the biggest change is in how timers are handled. The FreeBSD
+ * code had a 2MSL timer, which was set for sockets that enter certain
+ * "closing" states of the TCP state machine. But when the TIME-WAIT state was
+ * entered, the state is transferred from struct tcpcb into struct tcptw.
+ * The final timeout is handled as follows; the function tcp_tw_2msl_scan is
+ * called periodically on the slow timer, and it iterates over a linked list
+ * of all the struct tcptw and checks the tw->tw_time field to identify which
+ * TIME-WAIT sockets have expired.
+ *
+ * In our switch to using struct tcpcb even in the TIME-WAIT state, we rely on
+ * the timer system for struct tcpcb. I modified the 2msl callback in
+ * tcp_timer.c to check for the TIME-WAIT case and handle it correctly.
+ */
+
+static void
+tcp_tw_2msl_reset(struct tcpcb* tp, int rearm)
+{
+	/*
+	 * samkumar: This function used to set tw->tw_time to ticks + 2 * tcp_msl
+	 * and insert tw into the linked list V_twq_2msl. I've replaced this, along
+	 * with the associated locking logic, with the following call, which uses
+	 * the timer system in place for full TCBs.
+	 */
+	tcp_timer_activate(tp, TT_2MSL, 2 * tcp_msl);
+}
+
+/*
+ * samkumar: I've rewritten this code since I need to send out packets via the
+ * host system for TCPlp: allocating buffers from the host system, populate
+ * them, and then pass them back to the host system. I simplified the code by
+ * only using the logic that was fully necessary, eliminating the code for IPv4
+ * packets and keeping only the code for IPv6 packets. I also removed all of
+ * the mbuf logic, instead using the logic for using the host system's
+ * buffering.
+ *
+ * This rewritten code always returns 0. The original code would return
+ * whatever is returned by ip_output or ip6_output (FreeBSD's functions for
+ * sending out IP packets). I believe 0 indicates success, and a nonzero
+ * value represents an error code. It seems that the return value of
+ * tcp_twrespond is ignored by all instances of its use in TCPlp (maybe even
+ * in all of FreeBSD), so this is a moot point.
+ */
+static int
+tcp_twrespond(struct tcpcb* tp, int flags)
+{
+	struct tcphdr* nth;
+	struct tcpopt to;
+	uint32_t optlen = 0;
+	uint8_t opt[TCP_MAXOLEN];
+
+	to.to_flags = 0;
+
+	/*
+	 * Send a timestamp and echo-reply if both our side and our peer
+	 * have sent timestamps in our SYN's and this is not a RST.
+	 */
+	if ((tp->t_flags & TF_RCVD_TSTMP) && flags == TH_ACK) {
+		to.to_flags |= TOF_TS;
+		to.to_tsval = tcp_ts_getticks() + tp->ts_offset;
+		to.to_tsecr = tp->ts_recent;
+	}
+	optlen = tcp_addoptions(&to, opt);
+
+	otMessage* message = tcplp_sys_new_message(tp->instance);
+	if (message == NULL) {
+		return 0; // drop the message
+	}
+	if (otMessageSetLength(message, sizeof(struct tcphdr) + optlen) != OT_ERROR_NONE) {
+		tcplp_sys_free_message(tp->instance, message);
+		return 0; // drop the message
+	}
+
+	char outbuf[sizeof(struct tcphdr) + optlen];
+	nth = (struct tcphdr*) &outbuf[0];
+	otMessageInfo ip6info;
+	memset(&ip6info, 0x00, sizeof(ip6info));
+
+	memcpy(&ip6info.mSockAddr, &tp->laddr, sizeof(ip6info.mSockAddr));
+	memcpy(&ip6info.mPeerAddr, &tp->faddr, sizeof(ip6info.mPeerAddr));
+	nth->th_sport = tp->lport;
+	nth->th_dport = tp->fport;
+	nth->th_seq = htonl(tp->snd_nxt);
+	nth->th_ack = htonl(tp->rcv_nxt);
+	nth->th_off_x2 = ((sizeof(struct tcphdr) + optlen) >> 2) << TH_OFF_SHIFT;
+	nth->th_flags = flags;
+	nth->th_win = htons(tp->tw_last_win);
+	nth->th_urp = 0;
+	nth->th_sum = 0;
+
+	memcpy(nth + 1, opt, optlen);
+	otMessageWrite(message, 0, outbuf, sizeof(struct tcphdr) + optlen);
+	tcplp_sys_send_message(tp->instance, message, &ip6info);
+
+	return 0;
+}
+
+/*
+ * Move a TCP connection into TIME_WAIT state.
+ *    tcbinfo is locked.
+ *    inp is locked, and is unlocked before returning.
+ */
+/*
+ * samkumar: Locking is removed (so above comments regarding locks are no
+ * not relevant for TCPlp). Rather than allocating a struct tcptw and
+ * discarding the struct tcpcb, this function just switches the tcpcb state
+ * to correspond to TIME-WAIT (updating variables as appropriate). We also
+ * eliminate the "V_nolocaltimewait" optimization.
+ */
+void
+tcp_twstart(struct tcpcb *tp)
+{
+	int acknow;
+
+	/*
+	 * samkumar: The following code, commented out using "#if 0", handles the
+	 * net.inet.tcp.nolocaltimewait option in FreeBSD. The option skips the
+	 * TIME-WAIT state for TCP connections where both endpoints are local.
+	 * I'm removing this optimization for TCPlp, but I've left the code
+	 * commented out as it's a potentially useful feature that we may choose
+	 * to restore later.
+	 *
+	 * See also the "#if 0" block near the top of this file.
+	 */
+#if 0
+	if (V_nolocaltimewait) {
+		int error = 0;
+#ifdef INET6
+		if (isipv6)
+			error = in6_localaddr(&inp->in6p_faddr);
+#endif
+#if defined(INET6) && defined(INET)
+		else
+#endif
+#ifdef INET
+			error = in_localip(inp->inp_faddr);
+#endif
+		if (error) {
+			tp = tcp_close(tp);
+			if (tp != NULL)
+				INP_WUNLOCK(inp);
+			return;
+		}
+	}
+#endif
+
+	/*
+	 * For use only by DTrace.  We do not reference the state
+	 * after this point so modifying it in place is not a problem.
+	 */
+	/*
+	 * samkumar: The above comment is not true anymore. I use this state, since
+	 * I don't associate every struct tcpcb with a struct inpcb.
+	 */
+	tcp_state_change(tp, TCPS_TIME_WAIT);
+
+	/*
+	 * samkumar: There used to be code here to allocate a struct tcptw
+	 * using "tw = uma_zalloc(V_tcptw_zone, M_NOWAIT);" and if it fails, close
+	 * an existing TIME-WAIT connection, in LRU fashion, to allocate memory.
+	 */
+
+	/*
+	 * Recover last window size sent.
+	 */
+	if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt))
+		tp->tw_last_win = (tp->rcv_adv - tp->rcv_nxt) >> tp->rcv_scale;
+	else
+		tp->tw_last_win = 0;
+
+	/*
+	 * Set t_recent if timestamps are used on the connection.
+	 */
+	if ((tp->t_flags & (TF_REQ_TSTMP|TF_RCVD_TSTMP|TF_NOOPT)) ==
+	    (TF_REQ_TSTMP|TF_RCVD_TSTMP)) {
+		/*
+		 * samkumar: This used to do:
+		 * tw->t_recent = tp->ts_recent;
+		 * tw->ts_offset = tp->ts_offset;
+		 * But since we're keeping the state in tp, we don't need to do this
+		 * anymore. */
+	} else {
+		tp->ts_recent = 0;
+		tp->ts_offset = 0;
+	}
+
+	/*
+	 * samkumar: There used to be code here to populate various fields in
+	 * tw based on their values in tp, but there's no need for that now since
+	 * we can just read the values from tp. tw->tw_time was set to 0, but we
+	 * don't need to do that either since we're relying on the old timer system
+	 * anyway.
+	 */
+
+/* XXX
+ * If this code will
+ * be used for fin-wait-2 state also, then we may need
+ * a ts_recent from the last segment.
+ */
+	acknow = tp->t_flags & TF_ACKNOW;
+
+	/*
+	 * First, discard tcpcb state, which includes stopping its timers and
+	 * freeing it.  tcp_discardcb() used to also release the inpcb, but
+	 * that work is now done in the caller.
+	 *
+	 * Note: soisdisconnected() call used to be made in tcp_discardcb(),
+	 * and might not be needed here any longer.
+	 */
+	/*
+	 * samkumar: Below, I removed the code to discard tp, update inpcb and
+	 * release a reference to socket, but kept the rest. I also added a call
+	 * to cancel any pending timers on the TCB (which discarding it, as the
+	 * original code did, would have done).
+	 */
+	tcp_cancel_timers(tp);
+	if (acknow)
+		tcp_twrespond(tp, TH_ACK);
+	tcp_tw_2msl_reset(tp, 0);
+}
+
+/*
+ * Returns 1 if the TIME_WAIT state was killed and we should start over,
+ * looking for a pcb in the listen state.  Returns 0 otherwise.
+ */
+/*
+ * samkumar: Old signature was
+ * int
+ * tcp_twcheck(struct inpcb *inp, struct tcpopt *to, struct tcphdr *th,
+ *    struct mbuf *m, int tlen)
+ */
+int
+tcp_twcheck(struct tcpcb* tp, struct tcphdr *th, int tlen)
+{
+	int thflags;
+	tcp_seq seq;
+
+	/*
+	 * samkumar: There used to be code here that obtains the struct tcptw from
+	 * the inpcb, and does "goto drop" if that fails.
+	 */
+
+	thflags = th->th_flags;
+
+	/*
+	 * NOTE: for FIN_WAIT_2 (to be added later),
+	 * must validate sequence number before accepting RST
+	 */
+
+	/*
+	 * If the segment contains RST:
+	 *	Drop the segment - see Stevens, vol. 2, p. 964 and
+	 *      RFC 1337.
+	 */
+	if (thflags & TH_RST)
+		goto drop;
+
+	/*
+	 * samkumar: This was commented out (using #if 0) in the original FreeBSD
+	 * code.
+	 */
+#if 0
+/* PAWS not needed at the moment */
+	/*
+	 * RFC 1323 PAWS: If we have a timestamp reply on this segment
+	 * and it's less than ts_recent, drop it.
+	 */
+	if ((to.to_flags & TOF_TS) != 0 && tp->ts_recent &&
+	    TSTMP_LT(to.to_tsval, tp->ts_recent)) {
+		if ((thflags & TH_ACK) == 0)
+			goto drop;
+		goto ack;
+	}
+	/*
+	 * ts_recent is never updated because we never accept new segments.
+	 */
+#endif
+
+	/*
+	 * If a new connection request is received
+	 * while in TIME_WAIT, drop the old connection
+	 * and start over if the sequence numbers
+	 * are above the previous ones.
+	 */
+	if ((thflags & TH_SYN) && SEQ_GT(th->th_seq, tp->rcv_nxt)) {
+		/*
+		 * samkumar: The FreeBSD code would call tcp_twclose(tw, 0); but we
+		 * do it as below since TCPlp represents TIME-WAIT connects as
+		 * struct tcpcb's.
+		 */
+		tcp_close(tp);
+		tcplp_sys_connection_lost(tp, CONN_LOST_NORMAL);
+		return (1);
+	}
+
+	/*
+	 * Drop the segment if it does not contain an ACK.
+	 */
+	if ((thflags & TH_ACK) == 0)
+		goto drop;
+
+	/*
+	 * Reset the 2MSL timer if this is a duplicate FIN.
+	 */
+	if (thflags & TH_FIN) {
+		seq = th->th_seq + tlen + (thflags & TH_SYN ? 1 : 0);
+		if (seq + 1 == tp->rcv_nxt)
+			tcp_tw_2msl_reset(tp, 1);
+	}
+
+	/*
+	 * Acknowledge the segment if it has data or is not a duplicate ACK.
+	 */
+	if (thflags != TH_ACK || tlen != 0 ||
+	    th->th_seq != tp->rcv_nxt || th->th_ack != tp->snd_nxt)
+		tcp_twrespond(tp, TH_ACK);
+drop:
+	return (0);
+}
diff --git a/third_party/tcplp/bsdtcp/tcp_usrreq.c b/third_party/tcplp/bsdtcp/tcp_usrreq.c
new file mode 100644
index 0000000..3afb201
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/tcp_usrreq.c
@@ -0,0 +1,510 @@
+/*-
+ * Copyright (c) 1982, 1986, 1988, 1993
+ *	The Regents of the University of California.
+ * Copyright (c) 2006-2007 Robert N. M. Watson
+ * Copyright (c) 2010-2011 Juniper Networks, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Robert N. M. Watson under
+ * contract to Juniper Networks, Inc.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	From: @(#)tcp_usrreq.c	8.2 (Berkeley) 1/3/94
+ */
+
+#include <errno.h>
+#include <string.h>
+#include "../tcplp.h"
+#include "../lib/cbuf.h"
+#include "tcp.h"
+#include "tcp_fsm.h"
+#include "tcp_seq.h"
+#include "tcp_var.h"
+#include "tcp_timer.h"
+//#include <sys/socket.h>
+#include "ip6.h"
+
+#include "tcp_const.h"
+
+#include <openthread/tcp.h>
+
+//static void	tcp_disconnect(struct tcpcb *);
+static void	tcp_usrclosed(struct tcpcb *);
+
+/*
+ * samkumar: Removed tcp6_usr_bind, since checking if an address/port is free
+ * needs to be done at the host system (along with other socket management
+ * duties). TCPlp doesn't know what other sockets are in the system, or which
+ * other addresses/ports are busy.
+ */
+
+/* samkumar: This is based on a function in in6_pcb.c. */
+static int in6_pcbconnect(struct tcpcb* tp, struct sockaddr_in6* nam) {
+	register struct sockaddr_in6 *sin6 = nam;
+	tp->faddr = sin6->sin6_addr;
+	tp->fport = sin6->sin6_port;
+	return 0;
+}
+
+/*
+ * Initiate connection to peer.
+ * Create a template for use in transmissions on this connection.
+ * Enter SYN_SENT state, and mark socket as connecting.
+ * Start keep-alive timer, and seed output sequence space.
+ * Send initial segment on connection.
+ */
+/*
+ * samkumar: I removed locking, statistics, and inpcb management. The signature
+ * used to be
+ *
+ * static int
+ * tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
+ */
+static int
+tcp6_connect(struct tcpcb *tp, struct sockaddr_in6 *nam)
+{
+	int error;
+
+	int sb_max = cbuf_free_space(&tp->recvbuf); // same as sendbuf
+
+	/*
+	 * samkumar: For autobind, the original BSD code assigned the port first
+	 * (with logic that also looked at the address) and then the address. This
+	 * was done by calling into other parts of the FreeBSD network stack,
+	 * outside of the TCP stack. Here, we just use the tcplp_sys_autobind
+	 * function to do all of that work.
+	 */
+	bool autobind_addr = IN6_IS_ADDR_UNSPECIFIED(&tp->laddr);
+	bool autobind_port = (tp->lport == 0);
+	if (autobind_addr || autobind_port) {
+		otSockAddr foreign;
+		otSockAddr local;
+
+		memcpy(&foreign.mAddress, &nam->sin6_addr, sizeof(foreign.mAddress));
+		foreign.mPort = ntohs(nam->sin6_port);
+
+		if (!autobind_addr) {
+			memcpy(&local.mAddress, &tp->laddr, sizeof(local.mAddress));
+		}
+
+		if (!autobind_port) {
+			local.mPort = ntohs(tp->lport);
+		}
+
+		if (!tcplp_sys_autobind(tp->instance, &foreign, &local, autobind_addr, autobind_port)) {
+			// Autobind failed
+			error = EINVAL;
+			goto out;
+		}
+
+		if (autobind_addr) {
+			memcpy(&tp->laddr, &local.mAddress, sizeof(tp->laddr));
+		}
+
+		if (autobind_port) {
+			tp->lport = htons(local.mPort);
+		}
+	}
+	error = in6_pcbconnect(tp, nam);
+	if (error != 0)
+		goto out;
+
+	/* Compute window scaling to request.  */
+	while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
+	    (TCP_MAXWIN << tp->request_r_scale) < sb_max)
+		tp->request_r_scale++;
+
+	tcp_state_change(tp, TCPS_SYN_SENT);
+	tp->iss = tcp_new_isn(tp);
+	tcp_sendseqinit(tp);
+
+	return 0;
+
+out:
+	return error;
+}
+
+/*
+ * samkumar: I removed locking, statistics, inpcb management, and debug probes.
+ * I also remove codepaths that check for IPv6, since the address is assumed to
+ * be IPv6. The signature used to be
+ *
+ * static int
+ * tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
+ */
+int
+tcp6_usr_connect(struct tcpcb* tp, struct sockaddr_in6* sin6p)
+{
+	int error = 0;
+
+	if (tp->t_state != TCPS_CLOSED) { // samkumar: This is a check that I added
+		return (EISCONN);
+	}
+
+	/* samkumar: I removed the following error check since we receive sin6p
+	 * in the function argument and don't need to convert a struct sockaddr to
+	 * a struct sockaddr_in6 anymore.
+	 *
+	 * if (nam->sa_len != sizeof (*sin6p))
+	 * 	return (EINVAL);
+	 */
+
+	/*
+	 * Must disallow TCP ``connections'' to multicast addresses.
+	 */
+	/* samkumar: I commented out the check on sin6p->sin6_family. */
+	if (/*sin6p->sin6_family == AF_INET6
+	    && */IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr))
+		return (EAFNOSUPPORT);
+
+	/*
+	 * samkumar: There was some code here that obtained the TCB (struct tcpcb*)
+	 * by getting the inpcb from the socket and the TCB from the inpcb. I
+	 * removed that code.
+	 */
+
+	/*
+	 * XXXRW: Some confusion: V4/V6 flags relate to binding, and
+	 * therefore probably require the hash lock, which isn't held here.
+	 * Is this a significant problem?
+	 */
+	if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) {
+		tcplp_sys_log("V4-Mapped Address!");
+
+		/*
+		 * samkumar: There used to be code that woulf handle the case of
+		 * v4-mapped addresses. It would call in6_sin6_2_sin to convert the
+		 * struct sockaddr_in6 to a struct sockaddr_in, set the INP_IPV4 flag
+		 * and clear the INP_IPV6 flag on inp->inp_vflag, do some other
+		 * processing, and finally call tcp_connect and tcp_output. However,
+		 * it would first check if the IN6P_IPV6_V6ONLY flag was set in
+		 * inp->inp_flags, and if so, it would return with EINVAL. In TCPlp, we
+		 * support IPv6 only, so I removed the check for IN6P_IPV6_V6ONLY and
+		 * always act as if that flag is set. I kept the code in that if
+		 * statement making the check, and removed the other code that actually
+		 * handled this case.
+		 */
+		error = EINVAL;
+		goto out;
+	}
+
+	/*
+	 * samkumar: I removed some code here that set/cleared some flags in the`
+	 * inpcb and called prison_remote_ip6.
+	 */
+
+	/*
+	 * samkumar: Originally, the struct thread *td was passed along to
+	 * tcp6_connect.
+	 */
+	if ((error = tcp6_connect(tp, sin6p)) != 0)
+		goto out;
+
+	tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp));
+	error = tcp_output(tp);
+
+out:
+	return (error);
+}
+
+/*
+ * Do a send by putting data in output queue and updating urgent
+ * marker if URG set.  Possibly send more data.  Unlike the other
+ * pru_*() routines, the mbuf chains are our responsibility.  We
+ * must either enqueue them or free them.  The other pru_* routines
+ * generally are caller-frees.
+ */
+/*
+ * samkumar: I removed locking, statistics, inpcb management, and debug probes.
+ * I also removed support for the urgent pointer.
+ *
+ * I changed the signature of this function. It used to be
+ * static int
+ * tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
+ *     struct sockaddr *nam, struct mbuf *control, struct thread *td)
+ *
+ * The new function signature works as follows. DATA is a new linked buffer to
+ * add to the end of the send buffer. EXTENDBY is the number of bytes by which
+ * to extend the final linked buffer of the send buffer. Either DATA should be
+ * NULL, or EXTENDBY should be 0.
+ */
+int tcp_usr_send(struct tcpcb* tp, int moretocome, otLinkedBuffer* data, size_t extendby)
+{
+	int error = 0;
+
+	/*
+	 * samkumar: This if statement and the next are checks that I added
+	 */
+	if (tp->t_state < TCPS_ESTABLISHED) {
+		error = ENOTCONN;
+		goto out;
+	}
+
+	if (tpiscantsend(tp)) {
+		error = EPIPE;
+		goto out;
+	}
+
+	/*
+	 * samkumar: There used to be logic here that acquired locks, dealt with
+	 * INP_TIMEWAIT and INP_DROPPED flags on inp->inp_flags, and handled the
+	 * control mbuf passed as an argument (which would result in an error since
+	 * TCP doesn't support control information). I've deleted that code, but
+	 * left the following if block.
+	 */
+	 if ((tp->t_state == TCPS_TIME_WAIT) || (tp->t_state == TCPS_CLOSED)) {
+		error = ECONNRESET;
+		goto out;
+	}
+
+	/*
+	 * The following code used to be wrapped in an if statement:
+	 * "if (!(flags & PRUS_OOB))", that only executed it if the "out of band"
+	 * flag was not set. In TCB, "out of band" data is conveyed via the urgent
+	 * pointer, and TCPlp does not support the urgent pointer. Therefore, I
+	 * removed the "if" check and put its body below.
+	 */
+
+	/*
+	 * samkumar; The FreeBSD code calls sbappendstream(&so->so_snd, m, flags);
+	 * I've replaced it with the following logic, which appends to the
+	 * send buffer according to TCPlp's data structures.
+	 */
+	if (data == NULL) {
+		if (extendby == 0) {
+			goto out;
+		}
+		lbuf_extend(&tp->sendbuf, extendby);
+	} else {
+		if (data->mLength == 0) {
+			goto out;
+		}
+		lbuf_append(&tp->sendbuf, data);
+	}
+
+	/*
+	 * samkumar: There used to be code here to handle "implied connect,"
+	 * which initiates the TCP handshake if sending data on a socket that
+	 * isn't yet connected. TCPlp doesn't support this at the moment, but
+	 * it might be worth revisiting  when implementing TCP Fast Open.
+	 */
+
+	/*
+	 * samkumar: There used to be code here handling the PRUS_EOF flag in
+	 * the former flags parameter. I've removed this code.
+	 */
+
+	/*
+	 * samkumar: The code below was previously wrapped in an if statement
+	 * that checked that the INP_DROPPED flag in inp->inp_flags and the
+	 * PRUS_NOTREADY flag in the former flags parameter were both clear.
+	 * If either one was set, then tcp_output would not be called.
+	 *
+	 * The "more to come" functionality was previously triggered via the
+	 * PRUS_MORETOCOME flag in the flags parameter to this function. Since
+	 * that's the only flag that TCPlp uses here, I replaced the flags
+	 * parameter with a "moretocome" parameter, which we check instead.
+	 */
+	if (moretocome)
+		tp->t_flags |= TF_MORETOCOME;
+	error = tcp_output(tp);
+	if (moretocome)
+		tp->t_flags &= ~TF_MORETOCOME;
+
+	/*
+	 * samkumar: This is where the "if (!(flags & PRUS_OOB))" block would end.
+	 * There used to be a large "else" block handling out-of-band data, but I
+	 * removed that entire block since we do not support the urgent pointer in
+	 * TCPlp.
+	 */
+out:
+	return (error);
+}
+
+/*
+ * After a receive, possibly send window update to peer.
+ */
+int
+tcp_usr_rcvd(struct tcpcb* tp)
+{
+	int error = 0;
+
+	/*
+	 * samkumar: There used to be logic here that acquired locks, dealt with
+	 * INP_TIMEWAIT and INP_DROPPED flags on inp->inp_flags, and added debug
+	 * probes I've deleted that code, but left the following if block.
+	 */
+	if ((tp->t_state == TCPS_TIME_WAIT) || (tp->t_state == TCPS_CLOSED)) {
+		error = ECONNRESET;
+		goto out;
+	}
+
+	tcp_output(tp);
+
+out:
+	return (error);
+}
+
+/*
+ * samkumar: Removed the tcp_disconnect function. It is meant to be a
+ * "friendly" disconnect to complement the unceremonious "abort" functionality
+ * that is also provbided. The FreeBSD implementation called it from
+ * tcp_usr_close, which we removed (see the comment below for the reason why).
+ * It's not called from anywhere else, so I'm removing this function entirely.
+ */
+
+/*
+ * Mark the connection as being incapable of further output.
+ */
+/*
+ * samkumar: Modified to remove locking, socket/inpcb handling, and debug
+ * probes.
+ */
+int
+tcp_usr_shutdown(struct tcpcb* tp)
+{
+	int error = 0;
+
+	/*
+	 * samkumar: replaced checks on the INP_TIMEWAIT and INP_DROPPED flags on
+	 * inp->inp_flags with these checks on tp->t_state.
+	 */
+	if ((tp->t_state == TCPS_TIME_WAIT) || (tp->t_state == TCPS_CLOSED)) {
+		error = ECONNRESET;
+		goto out;
+	}
+
+	/* samkumar: replaced socantsendmore with tpcantsendmore */
+	tpcantsendmore(tp);
+	tcp_usrclosed(tp);
+
+	/*
+	 * samkumar: replaced check on INP_DROPPED flag in inp->inp_flags with
+	 * this check on tp->t_state.
+	 */
+	if (tp->t_state != TCPS_CLOSED)
+		error = tcp_output(tp);
+
+out:
+	return (error);
+}
+
+
+/*
+ * User issued close, and wish to trail through shutdown states:
+ * if never received SYN, just forget it.  If got a SYN from peer,
+ * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
+ * If already got a FIN from peer, then almost done; go to LAST_ACK
+ * state.  In all other cases, have already sent FIN to peer (e.g.
+ * after PRU_SHUTDOWN), and just have to play tedious game waiting
+ * for peer to send FIN or not respond to keep-alives, etc.
+ * We can let the user exit from the close as soon as the FIN is acked.
+ */
+/*
+ * Removed locking, TCP Offload, and socket/inpcb handling.
+ */
+static void
+tcp_usrclosed(struct tcpcb *tp)
+{
+	switch (tp->t_state) {
+	case TCPS_LISTEN:
+		tcp_state_change(tp, TCPS_CLOSED);
+		/* FALLTHROUGH */
+	case TCPS_CLOSED:
+		tp = tcp_close(tp);
+		tcplp_sys_connection_lost(tp, CONN_LOST_NORMAL);
+		/*
+		 * tcp_close() should never return NULL here as the socket is
+		 * still open.
+		 */
+		KASSERT(tp != NULL,
+		    ("tcp_usrclosed: tcp_close() returned NULL"));
+		break;
+
+	case TCPS_SYN_SENT:
+	case TCPS_SYN_RECEIVED:
+		tp->t_flags |= TF_NEEDFIN;
+		break;
+
+	case TCPS_ESTABLISHED:
+		tcp_state_change(tp, TCPS_FIN_WAIT_1);
+		break;
+
+	case TCPS_CLOSE_WAIT:
+		tcp_state_change(tp, TCPS_LAST_ACK);
+		break;
+	}
+	if (tp->t_state >= TCPS_FIN_WAIT_2) {
+		/* samkumar: commented out the following "soisdisconnected" line. */
+		// soisdisconnected(tp->t_inpcb->inp_socket);
+		/* Prevent the connection hanging in FIN_WAIT_2 forever. */
+		if (tp->t_state == TCPS_FIN_WAIT_2) {
+			int timeout;
+
+			timeout = (tcp_fast_finwait2_recycle) ?
+			    tcp_finwait2_timeout : TP_MAXIDLE(tp);
+			tcp_timer_activate(tp, TT_2MSL, timeout);
+		}
+	}
+}
+
+/*
+ * samkumar: I removed the tcp_usr_close function. It was meant to be called in
+ * case the socket is closed. It calls tcp_disconnect if the underlying TCP
+ * connection is still alive when the socket is closed ("full TCP state").
+ * In TCPlp, we can't handle this because we want to free up the underlying
+ * memory immediately when the user deallocates a TCP connection, making it
+ * unavailable for the somewhat more ceremonious closing that tcp_disconnect
+ * would allow. The host system is expected to simply abort the connection if
+ * the application deallocates it.
+ */
+
+/*
+ * Abort the TCP.  Drop the connection abruptly.
+ */
+/*
+ * samkumar: Modified to remove locking, socket/inpcb handling, and debug
+ * probes.
+ */
+void
+tcp_usr_abort(struct tcpcb* tp)
+{
+	/*
+	 * If we still have full TCP state, and we're not dropped, drop.
+	 */
+	/*
+	 * I replaced the checks on inp->inp_flags (which tested for the absence of
+	 * INP_TIMEWAIT and INP_DROPPED flags), with the following checks on
+	 * tp->t_state.
+	 */
+	if (tp->t_state != TCP6S_TIME_WAIT &&
+		tp->t_state != TCP6S_CLOSED) {
+		tcp_drop(tp, ECONNABORTED);
+	} else if (tp->t_state == TCPS_TIME_WAIT) { // samkumar: I added this clause
+		tp = tcp_close(tp);
+		tcplp_sys_connection_lost(tp, CONN_LOST_NORMAL);
+	}
+}
diff --git a/third_party/tcplp/bsdtcp/tcp_var.h b/third_party/tcplp/bsdtcp/tcp_var.h
new file mode 100644
index 0000000..c21b827
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/tcp_var.h
@@ -0,0 +1,617 @@
+/*-
+ * Copyright (c) 1982, 1986, 1993, 1994, 1995
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)tcp_var.h	8.4 (Berkeley) 5/24/95
+ * $FreeBSD$
+ */
+
+#ifndef TCPLP_NETINET_TCP_VAR_H_
+#define TCPLP_NETINET_TCP_VAR_H_
+
+/* For memmove(). */
+#include <string.h>
+
+/* Dependencies on OpenThread. */
+#include <openthread/ip6.h>
+#include <openthread/message.h>
+
+/* Dependencies on TCPlp buffering libraries. */
+#include "../lib/bitmap.h"
+#include "../lib/cbuf.h"
+#include "../lib/lbuf.h"
+
+#include "cc.h"
+#include "tcp.h"
+#include "types.h"
+#include "ip6.h"
+
+/* Implement byte-order-specific functions using OpenThread. */
+uint16_t tcplp_sys_hostswap16(uint16_t hostport);
+uint32_t tcplp_sys_hostswap32(uint32_t hostport);
+
+/*
+ * It seems that these are defined as macros in Mac OS X, which is why we need
+ * the #ifndef checks. Simply redefining them as functions would break the
+ * build.
+ */
+
+#ifndef htons
+static inline uint16_t htons(uint16_t hostport) {
+	return tcplp_sys_hostswap16(hostport);
+}
+#endif
+
+#ifndef ntohs
+static inline uint16_t ntohs(uint16_t hostport) {
+	return tcplp_sys_hostswap16(hostport);
+}
+#endif
+
+#ifndef htonl
+static inline uint32_t htonl(uint32_t hostport) {
+	return tcplp_sys_hostswap32(hostport);
+}
+#endif
+
+#ifndef ntohl
+static inline uint32_t ntohl(uint32_t hostport) {
+	return tcplp_sys_hostswap32(hostport);
+}
+#endif
+
+// From ip_compat.h
+#ifndef bcopy
+#define	bcopy(a,b,c)	memmove(b,a,c)
+#endif
+
+#ifndef bzero
+#define bzero(a,b)	memset(a,0x00,b)
+#endif
+
+struct sackblk {
+	tcp_seq start;		/* start seq no. of sack block */
+	tcp_seq end;		/* end seq no. */
+};
+
+struct sackhole {
+	tcp_seq start;		/* start seq no. of hole */
+	tcp_seq end;		/* end seq no. */
+	tcp_seq rxmit;		/* next seq. no in hole to be retransmitted */
+
+	/*
+	 * samkumar: I'm using this instead of the TAILQ_ENTRY macro to avoid
+	 * including sys/queue.h from this file. It's undesirable to include
+	 * sys/queue.h from this file because this file is part of the external
+	 * interface to TCPlp, and sys/queue.h pollutes the global namespace.
+	 * The original code that uses TAILQ_ENTRY is in a comment below.
+	 */
+	struct {
+		struct sackhole *tqe_next;	/* next element */
+		struct sackhole **tqe_prev;	/* address of previous next element */
+	} scblink;	/* scoreboard linkage */
+	// TAILQ_ENTRY(sackhole) scblink;	/* scoreboard linkage */
+};
+
+struct sackhint {
+	struct sackhole	*nexthole;
+	int		sack_bytes_rexmit;
+	tcp_seq		last_sack_ack;	/* Most recent/largest sacked ack */
+};
+
+struct tcptemp {
+	uint8_t	tt_ipgen[40]; /* the size must be of max ip header, now IPv6 */
+	struct	tcphdr tt_t;
+};
+
+#define tcp6cb		tcpcb  /* for KAME src sync over BSD*'s */
+
+/* Abridged TCB for passive sockets. */
+struct tcpcb_listen {
+    int t_state;     /* Always CLOSED or LISTEN. */
+    otInstance* instance;
+	struct in6_addr laddr;
+    uint16_t lport;
+};
+
+#define TCB_CANTRCVMORE 0x20
+#define TCB_CANTSENDMORE 0x40
+
+#define TCB_PASSIVE 0x80
+
+#define tpcantrcvmore(tp) (tp)->miscflags |= TCB_CANTRCVMORE
+#define tpcantsendmore(tp) (tp)->miscflags |= TCB_CANTSENDMORE
+#define tpiscantrcv(tp) (((tp)->miscflags & TCB_CANTRCVMORE) != 0)
+#define tpiscantsend(tp) (((tp)->miscflags & TCB_CANTSENDMORE) != 0)
+#define tpmarktimeractive(tp, timer) (tp)->miscflags |= timer
+#define tpistimeractive(tp, timer) (((tp)->miscflags & timer) != 0)
+#define tpcleartimeractive(tp, timer) (tp)->miscflags &= ~timer
+#define tpmarkpassiveopen(tp) (tp)->miscflags |= TCB_PASSIVE
+#define tpispassiveopen(tp) (((tp)->miscflags & TCB_PASSIVE) != 0)
+
+#define REASSBMP_SIZE(tp) BITS_TO_BYTES((tp)->recvbuf.size)
+
+/* These estimates are used to allocate sackholes (see tcp_sack.c). */
+#define AVG_SACKHOLES 2 // per TCB
+#define MAX_SACKHOLES 5 // per TCB
+#define SACKHOLE_POOL_SIZE MAX_SACKHOLES
+#define SACKHOLE_BMP_SIZE BITS_TO_BYTES(SACKHOLE_POOL_SIZE)
+
+struct tcplp_signals;
+
+/*
+ * Tcp control block, one per tcp; fields:
+ * Organized for 16 byte cacheline efficiency.
+ */
+/*
+ * samkumar: I added some fields for TCPlp to the beginning of this structure,
+ * replaced the fields for buffering and timers, and deleted unused fields to
+ * save memory. I've left some of the deleted fields in, as comments, for
+ * clarity. At times, I reduced the configurability of the implementation
+ * (e.g., by removing the ability to set keepalive parameters) in order to
+ * reduce the size of this structure.
+ */
+struct tcpcb {
+	/*
+	 * samkumar: Extra fields that I added. TCPlp doesn't have a struct inpcb,
+	 * so some of the fields I added represent data that would normally be
+	 * stored in the inpcb.
+	 */
+	otInstance *instance;
+
+	struct tcpcb_listen* accepted_from;
+
+	struct lbufhead sendbuf;
+	struct cbufhead recvbuf;
+	uint8_t* reassbmp;
+	int32_t reass_fin_index;
+
+	struct in6_addr laddr; // local IP address
+	struct in6_addr faddr; // foreign IP address
+
+	uint16_t lport; // local port, network byte order
+	uint16_t fport; // foreign port, network byte order
+	uint8_t miscflags;
+
+	/* samkumar: This field was there previously. */
+	uint8_t	t_state;		/* state of this connection */
+
+	/* Pool of SACK holes (on per-connection basis, for OpenThread port). */
+	struct sackhole sackhole_pool[SACKHOLE_POOL_SIZE];
+	uint8_t sackhole_bmp[SACKHOLE_BMP_SIZE];
+
+#if 0
+	struct	tsegqe_head t_segq;	/* segment reassembly queue */
+	void	*t_pspare[2];		/* new reassembly queue */
+	int	t_segqlen;		/* segment reassembly queue length */
+#endif
+
+	int32_t	t_dupacks;		/* consecutive dup acks recd */
+
+#if 0
+	struct tcp_timer *t_timers;	/* All the TCP timers in one struct */
+
+	struct	inpcb *t_inpcb;		/* back pointer to internet pcb */
+#endif
+
+	uint16_t	tw_last_win; // samkumar: Taken from struct tcptw
+
+	uint32_t	t_flags;
+
+//	struct	vnet *t_vnet;		/* back pointer to parent vnet */
+
+	tcp_seq	snd_una;		/* sent but unacknowledged */
+	tcp_seq	snd_max;		/* highest sequence number sent;
+					 * used to recognize retransmits
+					 */
+	tcp_seq	snd_nxt;		/* send next */
+	tcp_seq	snd_up;			/* send urgent pointer */
+
+	tcp_seq	snd_wl1;		/* window update seg seq number */
+	tcp_seq	snd_wl2;		/* window update seg ack number */
+	tcp_seq	iss;			/* initial send sequence number */
+	tcp_seq	irs;			/* initial receive sequence number */
+
+	tcp_seq	rcv_nxt;		/* receive next */
+	tcp_seq	rcv_adv;		/* advertised window */
+	tcp_seq	rcv_up;			/* receive urgent pointer */
+	uint64_t	rcv_wnd;		/* receive window */
+
+	uint64_t	snd_wnd;		/* send window */
+	uint64_t	snd_cwnd;		/* congestion-controlled window */
+//	uint64_t	snd_spare1;		/* unused */
+	uint64_t	snd_ssthresh;		/* snd_cwnd size threshold for
+					 * for slow start exponential to
+					 * linear switch
+					 */
+//	uint64_t	snd_spare2;		/* unused */
+	tcp_seq	snd_recover;		/* for use in NewReno Fast Recovery */
+
+	uint32_t	t_maxopd;		/* mss plus options */
+
+	uint32_t	t_rcvtime;		/* inactivity time */
+	uint32_t	t_starttime;		/* time connection was established */
+	uint32_t	t_rtttime;		/* RTT measurement start time */
+	tcp_seq	t_rtseq;		/* sequence number being timed */
+
+//	uint32_t	t_bw_spare1;		/* unused */
+//	tcp_seq	t_bw_spare2;		/* unused */
+
+	int32_t	t_rxtcur;		/* current retransmit value (ticks) */
+	uint32_t	t_maxseg;		/* maximum segment size */
+	int32_t	t_srtt;			/* smoothed round-trip time */
+	int32_t	t_rttvar;		/* variance in round-trip time */
+
+	int32_t	t_rxtshift;		/* log(2) of rexmt exp. backoff */
+	uint32_t	t_rttmin;		/* minimum rtt allowed */
+	uint32_t	t_rttbest;		/* best rtt we've seen */
+
+	int32_t	t_softerror;		/* possible error not yet reported */
+
+	uint64_t	t_rttupdated;		/* number of times rtt sampled */
+	uint64_t	max_sndwnd;		/* largest window peer has offered */
+/* out-of-band data */
+//	char	t_oobflags;		/* have some */
+//	char	t_iobc;			/* input character */
+
+	tcp_seq	last_ack_sent;
+/* experimental */
+	tcp_seq	snd_recover_prev;	/* snd_recover prior to retransmit */
+	uint64_t	snd_cwnd_prev;		/* cwnd prior to retransmit */
+	uint64_t	snd_ssthresh_prev;	/* ssthresh prior to retransmit */
+//	int	t_sndzerowin;		/* zero-window updates sent */
+	uint32_t	t_badrxtwin;		/* window for retransmit recovery */
+	uint8_t	snd_limited;		/* segments limited transmitted */
+
+/* RFC 1323 variables */
+/*
+ * samkumar: Moved "RFC 1323 variables" after "experimental" to reduce
+ * compiler-inserted padding.
+ */
+	uint8_t	snd_scale;		/* window scaling for send window */
+	uint8_t	rcv_scale;		/* window scaling for recv window */
+	uint8_t	request_r_scale;	/* pending window scaling */
+	u_int32_t  ts_recent;		/* timestamp echo data */
+	uint32_t	ts_recent_age;		/* when last updated */
+	u_int32_t  ts_offset;		/* our timestamp offset */
+
+/* SACK related state */
+	int32_t	snd_numholes;		/* number of holes seen by sender */
+	/*
+	 * samkumar: I replaced the TAILQ_HEAD macro invocation (commented out
+	 * below) with the code it stands for, to avoid having to #include
+	 * sys/queue.h in this file. See the comment above in struct sackhole for
+	 * more info.
+	 */
+	struct sackhole_head {
+		struct sackhole *tqh_first;	/* first element */
+		struct sackhole **tqh_last;	/* addr of last next element */
+	} snd_holes;
+	// TAILQ_HEAD(sackhole_head, sackhole) snd_holes;
+					/* SACK scoreboard (sorted) */
+	tcp_seq	snd_fack;		/* last seq number(+1) sack'd by rcv'r*/
+	int32_t	rcv_numsacks;		/* # distinct sack blks present */
+	struct sackblk sackblks[MAX_SACK_BLKS]; /* seq nos. of sack blocks */
+	tcp_seq sack_newdata;		/* New data xmitted in this recovery
+					   episode starts at this seq number */
+	struct sackhint	sackhint;	/* SACK scoreboard hint */
+
+	int32_t	t_rttlow;		/* smallest observed RTT */
+#if 0
+	u_int32_t	rfbuf_ts;	/* recv buffer autoscaling timestamp */
+	int	rfbuf_cnt;		/* recv buffer autoscaling byte count */
+	struct toedev	*tod;		/* toedev handling this connection */
+#endif
+//	int	t_sndrexmitpack;	/* retransmit packets sent */
+//	int	t_rcvoopack;		/* out-of-order packets received */
+//	void	*t_toe;			/* TOE pcb pointer */
+	int32_t	t_bytes_acked;		/* # bytes acked during current RTT */
+//	struct cc_algo	*cc_algo;	/* congestion control algorithm */
+	struct cc_var	ccv[1];		/* congestion control specific vars */
+#if 0
+	struct osd	*osd;		/* storage for Khelp module data */
+#endif
+#if 0 // Just use the default values for the KEEP constants (see tcp_timer.h)
+	uint32_t	t_keepinit;		/* time to establish connection */
+	uint32_t	t_keepidle;		/* time before keepalive probes begin */
+	uint32_t	t_keepintvl;		/* interval between keepalives */
+	uint32_t	t_keepcnt;		/* number of keepalives before close */
+#endif
+#if 0 // Don't support TCP Segment Offloading
+	uint32_t	t_tsomax;		/* TSO total burst length limit in bytes */
+	uint32_t	t_tsomaxsegcount;	/* TSO maximum segment count */
+	uint32_t	t_tsomaxsegsize;	/* TSO maximum segment size in bytes */
+#endif
+//	uint32_t	t_pmtud_saved_maxopd;	/* pre-blackhole MSS */
+	uint32_t	t_flags2;		/* More tcpcb flags storage */
+
+//	uint32_t t_ispare[8];		/* 5 UTO, 3 TBD */
+//	void	*t_pspare2[4];		/* 1 TCP_SIGNATURE, 3 TBD */
+#if 0
+#if defined(_KERNEL) && defined(TCPPCAP)
+	struct mbufq t_inpkts;		/* List of saved input packets. */
+	struct mbufq t_outpkts;		/* List of saved output packets. */
+#ifdef _LP64
+	uint64_t _pad[0];		/* all used! */
+#else
+	uint64_t _pad[2];		/* 2 are available */
+#endif /* _LP64 */
+#else
+	uint64_t _pad[6];
+#endif /* defined(_KERNEL) && defined(TCPPCAP) */
+#endif
+};
+
+/* Defined in tcp_subr.c. */
+void initialize_tcb(struct tcpcb* tp);
+
+/* Copied from the "dead" portions below. */
+
+void	 tcp_init(void);
+void	 tcp_state_change(struct tcpcb *, int);
+tcp_seq tcp_new_isn(struct tcpcb *);
+struct tcpcb *tcp_close(struct tcpcb *);
+struct tcpcb *tcp_drop(struct tcpcb *, int);
+void
+tcp_respond(struct tcpcb *tp, otInstance* instance, struct ip6_hdr* ip6gen, struct tcphdr *thgen,
+    tcp_seq ack, tcp_seq seq, int flags);
+void	 tcp_setpersist(struct tcpcb *);
+void	cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type);
+
+/* Added, since there is no header file for tcp_usrreq.c. */
+int tcp6_usr_connect(struct tcpcb* tp, struct sockaddr_in6* sinp6);
+int tcp_usr_send(struct tcpcb* tp, int moretocome, struct otLinkedBuffer* data, size_t extendby);
+int tcp_usr_rcvd(struct tcpcb* tp);
+int tcp_usr_shutdown(struct tcpcb* tp);
+void tcp_usr_abort(struct tcpcb* tp);
+
+/*
+ * Flags and utility macros for the t_flags field.
+ */
+#define	TF_ACKNOW	0x000001	/* ack peer immediately */
+#define	TF_DELACK	0x000002	/* ack, but try to delay it */
+#define	TF_NODELAY	0x000004	/* don't delay packets to coalesce */
+#define	TF_NOOPT	0x000008	/* don't use tcp options */
+#define	TF_SENTFIN	0x000010	/* have sent FIN */
+#define	TF_REQ_SCALE	0x000020	/* have/will request window scaling */
+#define	TF_RCVD_SCALE	0x000040	/* other side has requested scaling */
+#define	TF_REQ_TSTMP	0x000080	/* have/will request timestamps */
+#define	TF_RCVD_TSTMP	0x000100	/* a timestamp was received in SYN */
+#define	TF_SACK_PERMIT	0x000200	/* other side said I could SACK */
+#define	TF_NEEDSYN	0x000400	/* send SYN (implicit state) */
+#define	TF_NEEDFIN	0x000800	/* send FIN (implicit state) */
+#define	TF_NOPUSH	0x001000	/* don't push */
+#define	TF_PREVVALID	0x002000	/* saved values for bad rxmit valid */
+#define	TF_MORETOCOME	0x010000	/* More data to be appended to sock */
+#define	TF_LQ_OVERFLOW	0x020000	/* listen queue overflow */
+#define	TF_LASTIDLE	0x040000	/* connection was previously idle */
+#define	TF_RXWIN0SENT	0x080000	/* sent a receiver win 0 in response */
+#define	TF_FASTRECOVERY	0x100000	/* in NewReno Fast Recovery */
+#define	TF_WASFRECOVERY	0x200000	/* was in NewReno Fast Recovery */
+#define	TF_SIGNATURE	0x400000	/* require MD5 digests (RFC2385) */
+#define	TF_FORCEDATA	0x800000	/* force out a byte */
+#define	TF_TSO		0x1000000	/* TSO enabled on this connection */
+#define	TF_TOE		0x2000000	/* this connection is offloaded */
+#define	TF_ECN_PERMIT	0x4000000	/* connection ECN-ready */
+#define	TF_ECN_SND_CWR	0x8000000	/* ECN CWR in queue */
+#define	TF_ECN_SND_ECE	0x10000000	/* ECN ECE in queue */
+#define	TF_CONGRECOVERY	0x20000000	/* congestion recovery mode */
+#define	TF_WASCRECOVERY	0x40000000	/* was in congestion recovery */
+
+#define	IN_FASTRECOVERY(t_flags)	(t_flags & TF_FASTRECOVERY)
+#define	ENTER_FASTRECOVERY(t_flags)	t_flags |= TF_FASTRECOVERY
+#define	EXIT_FASTRECOVERY(t_flags)	t_flags &= ~TF_FASTRECOVERY
+
+#define	IN_CONGRECOVERY(t_flags)	(t_flags & TF_CONGRECOVERY)
+#define	ENTER_CONGRECOVERY(t_flags)	t_flags |= TF_CONGRECOVERY
+#define	EXIT_CONGRECOVERY(t_flags)	t_flags &= ~TF_CONGRECOVERY
+
+#define	IN_RECOVERY(t_flags) (t_flags & (TF_CONGRECOVERY | TF_FASTRECOVERY))
+#define	ENTER_RECOVERY(t_flags) t_flags |= (TF_CONGRECOVERY | TF_FASTRECOVERY)
+#define	EXIT_RECOVERY(t_flags) t_flags &= ~(TF_CONGRECOVERY | TF_FASTRECOVERY)
+
+#define	BYTES_THIS_ACK(tp, th)	(th->th_ack - tp->snd_una)
+
+/*
+ * Flags for the t_oobflags field.
+ */
+#define	TCPOOB_HAVEDATA	0x01
+#define	TCPOOB_HADDATA	0x02
+
+#ifdef TCP_SIGNATURE
+/*
+ * Defines which are needed by the xform_tcp module and tcp_[in|out]put
+ * for SADB verification and lookup.
+ */
+#define	TCP_SIGLEN	16	/* length of computed digest in bytes */
+#define	TCP_KEYLEN_MIN	1	/* minimum length of TCP-MD5 key */
+#define	TCP_KEYLEN_MAX	80	/* maximum length of TCP-MD5 key */
+/*
+ * Only a single SA per host may be specified at this time. An SPI is
+ * needed in order for the KEY_ALLOCSA() lookup to work.
+ */
+#define	TCP_SIG_SPI	0x1000
+#endif /* TCP_SIGNATURE */
+
+/*
+ * Flags for PLPMTU handling, t_flags2
+ */
+#define	TF2_PLPMTU_BLACKHOLE	0x00000001 /* Possible PLPMTUD Black Hole. */
+#define	TF2_PLPMTU_PMTUD	0x00000002 /* Allowed to attempt PLPMTUD. */
+#define	TF2_PLPMTU_MAXSEGSNT	0x00000004 /* Last seg sent was full seg. */
+
+/*
+ * Structure to hold TCP options that are only used during segment
+ * processing (in tcp_input), but not held in the tcpcb.
+ * It's basically used to reduce the number of parameters
+ * to tcp_dooptions and tcp_addoptions.
+ * The binary order of the to_flags is relevant for packing of the
+ * options in tcp_addoptions.
+ */
+struct tcpopt {
+	u_int64_t	to_flags;	/* which options are present */
+#define	TOF_MSS		0x0001		/* maximum segment size */
+#define	TOF_SCALE	0x0002		/* window scaling */
+#define	TOF_SACKPERM	0x0004		/* SACK permitted */
+#define	TOF_TS		0x0010		/* timestamp */
+#define	TOF_SIGNATURE	0x0040		/* TCP-MD5 signature option (RFC2385) */
+#define	TOF_SACK	0x0080		/* Peer sent SACK option */
+#define	TOF_MAXOPT	0x0100
+	u_int32_t	to_tsval;	/* new timestamp */
+	u_int32_t	to_tsecr;	/* reflected timestamp */
+	uint8_t		*to_sacks;	/* pointer to the first SACK blocks */
+	uint8_t		*to_signature;	/* pointer to the TCP-MD5 signature */
+	u_int16_t	to_mss;		/* maximum segment size */
+	u_int8_t	to_wscale;	/* window scaling */
+	u_int8_t	to_nsacks;	/* number of SACK blocks */
+	u_int32_t	to_spare;	/* UTO */
+};
+
+/*
+ * Flags for tcp_dooptions.
+ */
+#define	TO_SYN		0x01		/* parse SYN-only options */
+
+struct hc_metrics_lite {	/* must stay in sync with hc_metrics */
+	uint64_t	rmx_mtu;	/* MTU for this path */
+	uint64_t	rmx_ssthresh;	/* outbound gateway buffer limit */
+	uint64_t	rmx_rtt;	/* estimated round trip time */
+	uint64_t	rmx_rttvar;	/* estimated rtt variance */
+	uint64_t	rmx_bandwidth;	/* estimated bandwidth */
+	uint64_t	rmx_cwnd;	/* congestion window */
+	uint64_t	rmx_sendpipe;   /* outbound delay-bandwidth product */
+	uint64_t	rmx_recvpipe;   /* inbound delay-bandwidth product */
+};
+
+/*
+ * Used by tcp_maxmtu() to communicate interface specific features
+ * and limits at the time of connection setup.
+ */
+struct tcp_ifcap {
+	int	ifcap;
+	uint32_t	tsomax;
+	uint32_t	tsomaxsegcount;
+	uint32_t	tsomaxsegsize;
+};
+
+void	 tcp_mss(struct tcpcb *, int);
+void	 tcp_mss_update(struct tcpcb *, int, int, struct hc_metrics_lite *,
+	    struct tcp_ifcap *);
+
+/*
+ * The smoothed round-trip time and estimated variance
+ * are stored as fixed point numbers scaled by the values below.
+ * For convenience, these scales are also used in smoothing the average
+ * (smoothed = (1/scale)sample + ((scale-1)/scale)smoothed).
+ * With these scales, srtt has 3 bits to the right of the binary point,
+ * and thus an "ALPHA" of 0.875.  rttvar has 2 bits to the right of the
+ * binary point, and is smoothed with an ALPHA of 0.75.
+ */
+#define	TCP_RTT_SCALE		32	/* multiplier for srtt; 3 bits frac. */
+#define	TCP_RTT_SHIFT		5	/* shift for srtt; 3 bits frac. */
+#define	TCP_RTTVAR_SCALE	16	/* multiplier for rttvar; 2 bits */
+#define	TCP_RTTVAR_SHIFT	4	/* shift for rttvar; 2 bits */
+#define	TCP_DELTA_SHIFT		2	/* see tcp_input.c */
+
+/* My definition of the max macro */
+#define max(x, y) ((x) > (y) ? (x) : (y))
+
+/*
+ * The initial retransmission should happen at rtt + 4 * rttvar.
+ * Because of the way we do the smoothing, srtt and rttvar
+ * will each average +1/2 tick of bias.  When we compute
+ * the retransmit timer, we want 1/2 tick of rounding and
+ * 1 extra tick because of +-1/2 tick uncertainty in the
+ * firing of the timer.  The bias will give us exactly the
+ * 1.5 tick we need.  But, because the bias is
+ * statistical, we have to test that we don't drop below
+ * the minimum feasible timer (which is 2 ticks).
+ * This version of the macro adapted from a paper by Lawrence
+ * Brakmo and Larry Peterson which outlines a problem caused
+ * by insufficient precision in the original implementation,
+ * which results in inappropriately large RTO values for very
+ * fast networks.
+ */
+#define	TCP_REXMTVAL(tp) \
+	max((tp)->t_rttmin, (((tp)->t_srtt >> (TCP_RTT_SHIFT - TCP_DELTA_SHIFT))  \
+	  + (tp)->t_rttvar) >> TCP_DELTA_SHIFT)
+
+/* Copied from below. */
+static inline void
+tcp_fields_to_host(struct tcphdr *th)
+{
+
+	th->th_seq = ntohl(th->th_seq);
+	th->th_ack = ntohl(th->th_ack);
+	th->th_win = ntohs(th->th_win);
+	th->th_urp = ntohs(th->th_urp);
+}
+
+void	 tcp_twstart(struct tcpcb*);
+void	 tcp_twclose(struct tcpcb*, int);
+int	 tcp_twcheck(struct tcpcb*, struct tcphdr *, int);
+void tcp_dropwithreset(struct ip6_hdr* ip6, struct tcphdr *th, struct tcpcb *tp, otInstance* instance,
+    int tlen, int rstreason);
+int tcp_input(struct ip6_hdr* ip6, struct tcphdr* th, otMessage* msg, struct tcpcb* tp, struct tcpcb_listen* tpl,
+          struct tcplp_signals* sig);
+int	 tcp_output(struct tcpcb *);
+void tcpip_maketemplate(struct tcpcb *, struct tcptemp*);
+void	 tcpip_fillheaders(struct tcpcb *, otMessageInfo *, void *);
+uint64_t	 tcp_maxmtu6(struct tcpcb*, struct tcp_ifcap *);
+int	 tcp_addoptions(struct tcpopt *, uint8_t *);
+int	 tcp_mssopt(struct tcpcb*);
+int	 tcp_reass(struct tcpcb *, struct tcphdr *, int *, otMessage *, off_t, struct tcplp_signals*);
+void tcp_sack_init(struct tcpcb *); // Sam: new function that I added
+void	 tcp_sack_doack(struct tcpcb *, struct tcpopt *, tcp_seq);
+void	 tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_laststart, tcp_seq rcv_lastend);
+void	 tcp_clean_sackreport(struct tcpcb *tp);
+void	 tcp_sack_adjust(struct tcpcb *tp);
+struct sackhole *tcp_sack_output(struct tcpcb *tp, int *sack_bytes_rexmt);
+void	 tcp_sack_partialack(struct tcpcb *, struct tcphdr *);
+void	 tcp_free_sackholes(struct tcpcb *tp);
+
+#define	tcps_rcvmemdrop	tcps_rcvreassfull	/* compat */0
+
+/*
+ * Identifiers for TCP sysctl nodes
+ */
+#define	TCPCTL_DO_RFC1323	1	/* use RFC-1323 extensions */
+#define	TCPCTL_MSSDFLT		3	/* MSS default */
+#define TCPCTL_STATS		4	/* statistics (read-only) */
+#define	TCPCTL_RTTDFLT		5	/* default RTT estimate */
+#define	TCPCTL_KEEPIDLE		6	/* keepalive idle timer */
+#define	TCPCTL_KEEPINTVL	7	/* interval to send keepalives */
+#define	TCPCTL_SENDSPACE	8	/* send buffer space */
+#define	TCPCTL_RECVSPACE	9	/* receive buffer space */
+#define	TCPCTL_KEEPINIT		10	/* timeout for establishing syn */
+#define	TCPCTL_PCBLIST		11	/* list of all outstanding PCBs */
+#define	TCPCTL_DELACKTIME	12	/* time before sending delayed ACK */
+#define	TCPCTL_V6MSSDFLT	13	/* MSS default for IPv6 */
+#define	TCPCTL_SACK		14	/* Selective Acknowledgement,rfc 2018 */
+#define	TCPCTL_DROP		15	/* drop tcp connection */
+
+#endif /* _NETINET_TCP_VAR_H_ */
diff --git a/third_party/tcplp/bsdtcp/types.h b/third_party/tcplp/bsdtcp/types.h
new file mode 100644
index 0000000..cf1176c
--- /dev/null
+++ b/third_party/tcplp/bsdtcp/types.h
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 1982, 1986, 1991, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)types.h	8.6 (Berkeley) 2/19/95
+ * $FreeBSD$
+ */
+
+/*
+ * bukepo: omitted unused definitions for quad_t, u_quad_t, etc., because they
+ * come predefined by certain compilers. Also omitted unused definitions for
+ * __uint8_t, __uint16_t, caddr_t, etc.
+ *
+ * samkumar: I've omitted definitions for u_char, u_short, u_int, etc., because
+ * they come predefined by certain compilers, sometimes differently. I just
+ * replaced all usages of these types in the code with the corresponding
+ * standard integer types (uint8_t, uint16_t, etc.).
+ */
+
+#ifndef TCPLP_SYS_TYPES_H_
+#define TCPLP_SYS_TYPES_H_
+
+#include <stdint.h>
+
+typedef uint8_t	    u_int8_t;	/* unsigned integrals (deprecated) */
+typedef uint16_t	u_int16_t;
+typedef uint32_t	u_int32_t;
+typedef uint64_t	u_int64_t;
+
+#endif
diff --git a/third_party/tcplp/lib/bitmap.c b/third_party/tcplp/lib/bitmap.c
index 722859b..70d03c1 100644
--- a/third_party/tcplp/lib/bitmap.c
+++ b/third_party/tcplp/lib/bitmap.c
@@ -141,6 +141,11 @@
     return 1;
 }
 
+/*
+ * This function is unused, but I'm leaving it in the code as a comment in case
+ * it becomes useful for debugging later on.
+ */
+#if 0
 void bmp_print(uint8_t* buf, size_t buflen) {
     size_t i;
     for (i = 0; i < buflen; i++) {
@@ -148,3 +153,4 @@
     }
     printf("\n");
 }
+#endif
diff --git a/third_party/tcplp/lib/lbuf.c b/third_party/tcplp/lib/lbuf.c
index f4ee16f..91dd456 100644
--- a/third_party/tcplp/lib/lbuf.c
+++ b/third_party/tcplp/lib/lbuf.c
@@ -57,7 +57,7 @@
     buffer->tail->mLength += numbytes;
 }
 
-size_t lbuf_pop(struct lbufhead* buffer, size_t numbytes, int* ntraversed) {
+size_t lbuf_pop(struct lbufhead* buffer, size_t numbytes, uint32_t* ntraversed) {
     otLinkedBuffer* curr = buffer->head;
     size_t bytesleft = numbytes;
     size_t curroffset = buffer->offset;
@@ -109,6 +109,6 @@
     return 0;
 }
 
-size_t lbuf_used_space(struct lbufhead* buffer) {
+size_t lbuf_used_space(const struct lbufhead* buffer) {
     return buffer->length;
 }
diff --git a/third_party/tcplp/lib/lbuf.h b/third_party/tcplp/lib/lbuf.h
index 38b1177..66424a3 100644
--- a/third_party/tcplp/lib/lbuf.h
+++ b/third_party/tcplp/lib/lbuf.h
@@ -65,7 +65,7 @@
    NUMBYTES bytes in the buffer to begin with). *NTRAVERSED is incremented once
    for each entry in the buffer that is no longer referenced and can be
    reclaimed. */
-size_t lbuf_pop(struct lbufhead* buffer, size_t numbytes, int* ntraversed);
+size_t lbuf_pop(struct lbufhead* buffer, size_t numbytes, uint32_t* ntraversed);
 
 /* Given a range of indices, specified by an OFFSET from the start and a
    length NUMBYTES, this function locates the chain of linked buffer entries
@@ -83,6 +83,6 @@
                   struct otLinkedBuffer** last, size_t* lastextra);
 
 /* Returns the total number of bytes stored in the buffer. */
-size_t lbuf_used_space(struct lbufhead* buffer);
+size_t lbuf_used_space(const struct lbufhead* buffer);
 
 #endif
diff --git a/third_party/tcplp/tcplp.h b/third_party/tcplp/tcplp.h
index e69de29..891d9d0 100644
--- a/third_party/tcplp/tcplp.h
+++ b/third_party/tcplp/tcplp.h
@@ -0,0 +1,96 @@
+/*
+ *  Copyright (c) 2018, Sam Kumar <samkumar@cs.berkeley.edu>
+ *  Copyright (c) 2018, University of California, Berkeley
+ *  All rights reserved.
+ *
+ *  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, 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
+ *   This file defines the interface between TCPlp and the host network stack
+ *   (OpenThread, in this case). It is based on content taken from TCPlp,
+ *   modified to work with this port of TCPlp to OpenThread.
+ */
+
+#ifndef TCPLP_H_
+#define TCPLP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <errno.h>
+#include <openthread/ip6.h>
+#include <openthread/message.h>
+#include "bsdtcp/ip6.h"
+#include "bsdtcp/tcp.h"
+#include "bsdtcp/tcp_fsm.h"
+#include "bsdtcp/tcp_timer.h"
+#include "bsdtcp/tcp_var.h"
+
+#define RELOOKUP_REQUIRED -1
+#define CONN_LOST_NORMAL 0
+
+struct tcplp_signals
+{
+    uint32_t links_popped;
+    uint32_t bytes_acked;
+    bool     conn_established;
+    bool     recvbuf_added;
+    bool     rcvd_fin;
+};
+
+/*
+ * Functions that the TCP protocol logic can call to interact with the rest of
+ * the system.
+ */
+otMessage *   tcplp_sys_new_message(otInstance *instance);
+void          tcplp_sys_free_message(otInstance *instance, otMessage *pkt);
+void          tcplp_sys_send_message(otInstance *instance, otMessage *pkt, otMessageInfo *info);
+uint32_t      tcplp_sys_get_ticks();
+uint32_t      tcplp_sys_get_millis();
+void          tcplp_sys_set_timer(struct tcpcb *tcb, uint8_t timer_flag, uint32_t delay);
+void          tcplp_sys_stop_timer(struct tcpcb *tcb, uint8_t timer_flag);
+struct tcpcb *tcplp_sys_accept_ready(struct tcpcb_listen *tpl, struct in6_addr *addr, uint16_t port);
+bool          tcplp_sys_accepted_connection(struct tcpcb_listen *tpl,
+                                            struct tcpcb *       accepted,
+                                            struct in6_addr *    addr,
+                                            uint16_t             port);
+void          tcplp_sys_connection_lost(struct tcpcb *tcb, uint8_t errnum);
+void          tcplp_sys_on_state_change(struct tcpcb *tcb, int newstate);
+void          tcplp_sys_log(const char *format, ...);
+void          tcplp_sys_panic(const char *format, ...);
+bool          tcplp_sys_autobind(otInstance *      aInstance,
+                                 const otSockAddr *aPeer,
+                                 otSockAddr *      aToBind,
+                                 bool              aBindAddress,
+                                 bool              aBindPort);
+uint32_t      tcplp_sys_generate_isn();
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // TCPLP_H_
diff --git a/tools/harness-simulation/README.md b/tools/harness-simulation/README.md
new file mode 100644
index 0000000..1412e9c
--- /dev/null
+++ b/tools/harness-simulation/README.md
@@ -0,0 +1,49 @@
+# Test Harness on Simulation Environment Setup
+
+THCI (Thread Host Controller Interface) is an implementation of the Python abstract class template `IThci`, which is used by the Thread Test Harness Software to control OpenThread-based reference devices according to each test scenario.
+
+SI (Sniffer Interface) is an implementation of the sniffer abstract class template `ISniffer`, which is used by the Thread Test Harness Software to sniff all packets sent by devices.
+
+Both OpenThread simulation and sniffer simulation are required to run on a POSIX environment. However, Harness has to be run on Windows, which is a non-POSIX environment. So both two systems are needed, and their setup procedures in detail are listed in the following sections. Either two machines or one machine running two (sub)systems (for example, VM, WSL) is feasible.
+
+Platform developers should modify the THCI implementation and/or the SI implementation directly to match their platform (for example, the path of the OpenThread repository).
+
+## POSIX Environment Setup
+
+1. Build OpenThread to generate standalone OpenThread simulation `ot-cli-ftd`. For example, run the following command in the top directory of OpenThread.
+   ```bash
+   $ script/cmake-build simulation
+   ```
+   Then `ot-cli-ftd` is built in the directory `build/simulation/examples/apps/cli/`.
+
+## Test Harness Environment Setup
+
+1. Double click the file `harness\install.bat` on the machine which installed Harness.
+
+2. Check the configuration file `C:\GRL\Thread1.2\Thread_Harness\simulation\config.py`
+
+   - Edit the value of `REMOTE_USERNAME` to the username expected to connect to on the remote POSIX environment.
+   - Edit the value of `REMOTE_PASSWORD` to the password corresponding to the username above.
+   - Edit the value of `REMOTE_OT_PATH` to the absolute path where the top directory of the OpenThread repository is located.
+
+3. Add the additional simulation device information in `harness\Web\data\deviceInputFields.xml` to `C:\GRL\Thread1.2\Web\data\deviceInputFields.xml`.
+
+## Run Test Harness on Simulation
+
+1. On POSIX machine, change directory to the top of OpenThread repository, and run the following commands.
+
+   ```bash
+   $ cd tools/harness-simulation/posix
+   $ python harness_dev_discovery.py \
+         --interface=eth0            \
+         --ot1.1=24                  \
+         --sniffer=2
+   ```
+
+   It starts 24 OT FTD simulations and 2 sniffer simulations and can be discovered on eth0.
+
+   The arguments can be adjusted according to the requirement of test cases.
+
+2. Run Test Harness. The information field of the device is encoded as `<node_id>@<ip_addr>`. Choose the proper device as the DUT accordingly.
+
+3. Select one or more test cases to start the test.
diff --git a/tools/harness-simulation/harness/Thread_Harness/Sniffer/SimSniffer.py b/tools/harness-simulation/harness/Thread_Harness/Sniffer/SimSniffer.py
new file mode 100644
index 0000000..fffdc83
--- /dev/null
+++ b/tools/harness-simulation/harness/Thread_Harness/Sniffer/SimSniffer.py
@@ -0,0 +1,225 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2022, The OpenThread Authors.
+# All rights reserved.
+#
+# 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, 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.
+#
+
+import ipaddress
+import netifaces
+import os
+import paramiko
+import select
+import socket
+import struct
+import subprocess
+import time
+import winreg as wr
+
+from ISniffer import ISniffer
+from THCI.OpenThread import watched
+from simulation.config import (
+    REMOTE_PORT,
+    REMOTE_USERNAME,
+    REMOTE_PASSWORD,
+    REMOTE_OT_PATH,
+    REMOTE_SNIFFER_OUTPUT_PREFIX,
+    EDITCAP_PATH,
+)
+
+DISCOVERY_ADDR = ('ff02::114', 12345)
+
+IFNAME = 'WLAN'
+
+SCAN_TIME = 3
+
+# `socket.IPPROTO_IPV6` only exists in Python 3, so the constant is manually defined.
+IPPROTO_IPV6 = 41
+
+# The subkey represents the class of network adapter devices supported by the system,
+# which is used to filter physical network cards and avoid virtual network adapters.
+WINREG_KEY = r'SYSTEM\CurrentControlSet\Control\Network\{4d36e972-e325-11ce-bfc1-08002be10318}'
+
+
+class SimSniffer(ISniffer):
+
+    @watched
+    def __init__(self, **kwargs):
+        self.channel = kwargs.get('channel')
+        self.ipaddr = kwargs.get('addressofDevice')
+        self.is_active = False
+        self._local_pcapng_location = None
+        self._ssh = None
+        self._remote_pcap_location = None
+        self._remote_pid = None
+
+    def __repr__(self):
+        return '%r' % self.__dict__
+
+    def _get_connection_name_from_guid(self, iface_guids):
+        iface_names = ['(unknown)' for i in range(len(iface_guids))]
+        reg = wr.ConnectRegistry(None, wr.HKEY_LOCAL_MACHINE)
+        reg_key = wr.OpenKey(reg, WINREG_KEY)
+        for i in range(len(iface_guids)):
+            try:
+                reg_subkey = wr.OpenKey(reg_key, iface_guids[i] + r'\Connection')
+                iface_names[i] = wr.QueryValueEx(reg_subkey, 'Name')[0]
+            except Exception, e:
+                pass
+        return iface_names
+
+    def _find_index(self, iface_name):
+        ifaces_guid = netifaces.interfaces()
+        absolute_iface_name = self._get_connection_name_from_guid(ifaces_guid)
+        try:
+            _required_iface_index = absolute_iface_name.index(iface_name)
+            _required_guid = ifaces_guid[_required_iface_index]
+            ip = netifaces.ifaddresses(_required_guid)[netifaces.AF_INET6][-1]['addr']
+            self.log('Local IP: %s', ip)
+            return int(ip.split('%')[1])
+        except Exception, e:
+            self.log('%r', e)
+            self.log('Interface %s not found', iface_name)
+            return None
+
+    def _encode_address_port(self, addr, port):
+        port = str(port)
+        if isinstance(ipaddress.ip_address(addr), ipaddress.IPv6Address):
+            return '[' + addr + ']:' + port
+        return addr + ':' + port
+
+    @watched
+    def discoverSniffer(self):
+        sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
+
+        # Define the output interface of the socket
+        ifn = self._find_index(IFNAME)
+        if ifn is None:
+            self.log('%s interface has not enabled IPv6.', IFNAME)
+            return []
+        ifn = struct.pack('I', ifn)
+        sock.setsockopt(IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, ifn)
+
+        # Send the request
+        sock.sendto(('Sniffer').encode(), DISCOVERY_ADDR)
+
+        # Scan for responses
+        devs = set()
+        start = time.time()
+        while time.time() - start < SCAN_TIME:
+            if select.select([sock], [], [], 1)[0]:
+                addr, _ = sock.recvfrom(1024)
+                devs.add(addr)
+            else:
+                # Re-send the request, due to unreliability of UDP especially on WLAN
+                sock.sendto(('Sniffer').encode(), DISCOVERY_ADDR)
+
+        devs = [SimSniffer(addressofDevice=addr, channel=None) for addr in devs]
+        self.log('List of SimSniffers: %r', devs)
+
+        return devs
+
+    @watched
+    def startSniffer(self, channelToCapture, captureFileLocation, includeEthernet=False):
+        self.channel = channelToCapture
+        self._local_pcapng_location = captureFileLocation
+        self._remote_pcap_location = os.path.join(REMOTE_SNIFFER_OUTPUT_PREFIX, self.ipaddr.split('@')[0] + '.pcap')
+
+        self._ssh = paramiko.SSHClient()
+        self._ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+        remote_ip = self.ipaddr.split('@')[1]
+        self._ssh.connect(remote_ip, port=REMOTE_PORT, username=REMOTE_USERNAME, password=REMOTE_PASSWORD)
+
+        _, stdout, _ = self._ssh.exec_command(
+            'echo $$ && exec python3 %s -o %s -c %d' %
+            (os.path.join(REMOTE_OT_PATH, 'tools/harness-simulation/posix/sniffer_sim/sniffer.py'),
+             self._remote_pcap_location, self.channel))
+        self._remote_pid = int(stdout.readline())
+
+        self.log('local pcapng location = %s', self._local_pcapng_location)
+        self.log('remote pcap location = %s', self._remote_pcap_location)
+        self.log('remote pid = %d', self._remote_pid)
+
+        self.is_active = True
+
+    @watched
+    def stopSniffer(self):
+        if not self.is_active:
+            return
+        self.is_active = False
+
+        assert self._ssh is not None
+        self._ssh.exec_command('kill -s TERM %d' % self._remote_pid)
+        # Wait to make sure the file is closed
+        time.sleep(3)
+
+        # Truncate suffix from .pcapng to .pcap
+        local_pcap_location = self._local_pcapng_location[:-2]
+
+        with self._ssh.open_sftp() as sftp:
+            sftp.get(self._remote_pcap_location, local_pcap_location)
+
+        self._ssh.close()
+
+        cmd = [EDITCAP_PATH, '-F', 'pcapng', local_pcap_location, self._local_pcapng_location]
+        self.log('running editcap: %r', cmd)
+        subprocess.Popen(cmd).wait()
+        self.log('editcap done')
+
+        self._local_pcapng_location = None
+        self._ssh = None
+        self._remote_pcap_location = None
+        self._remote_pid = None
+
+    @watched
+    def setChannel(self, channelToCapture):
+        self.channel = channelToCapture
+
+    @watched
+    def getChannel(self):
+        return self.channel
+
+    @watched
+    def validateFirmwareVersion(self, device):
+        return True
+
+    @watched
+    def isSnifferCapturing(self):
+        return self.is_active
+
+    @watched
+    def getSnifferAddress(self):
+        return self.ipaddr
+
+    @watched
+    def globalReset(self):
+        pass
+
+    def log(self, fmt, *args):
+        try:
+            msg = fmt % args
+            print('%s - %s - %s' % ('SimSniffer', time.strftime('%b %d %H:%M:%S'), msg))
+        except Exception:
+            pass
diff --git a/tools/harness-simulation/harness/Thread_Harness/THCI/OpenThread_Sim.py b/tools/harness-simulation/harness/Thread_Harness/THCI/OpenThread_Sim.py
new file mode 100644
index 0000000..e0db9bd
--- /dev/null
+++ b/tools/harness-simulation/harness/Thread_Harness/THCI/OpenThread_Sim.py
@@ -0,0 +1,144 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2022, The OpenThread Authors.
+# All rights reserved.
+#
+# 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, 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.
+#
+"""
+>> Thread Host Controller Interface
+>> Device : OpenThread_Sim THCI
+>> Class : OpenThread_Sim
+"""
+
+import ipaddress
+import os
+import paramiko
+import socket
+import time
+
+from IThci import IThci
+from OpenThread import OpenThreadTHCI, watched
+from simulation.config import REMOTE_OT_PATH
+
+
+class SSHHandle(object):
+
+    def __init__(self, ip, port, username, password, device, node_id):
+        ipaddress.ip_address(ip)
+        self.ip = ip
+        self.port = int(port)
+        self.username = username
+        self.password = password
+        self.__handle = None
+        self.__stdin = None
+        self.__stdout = None
+        self.__connect(device, node_id)
+
+    @watched
+    def __connect(self, device, node_id):
+        self.close()
+
+        self.__handle = paramiko.SSHClient()
+        self.__handle.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+        try:
+            self.log('Connecting to %s:%s with username=%s', self.ip, self.port, self.username)
+            self.__handle.connect(self.ip, port=self.port, username=self.username, password=self.password)
+        except paramiko.AuthenticationException:
+            if not self.password:
+                self.__handle.get_transport().auth_none(self.username)
+            else:
+                raise Exception('Password error')
+
+        self.__stdin, self.__stdout, _ = self.__handle.exec_command(device + ' ' + str(node_id), get_pty=True)
+        self.__stdout.channel.setblocking(0)
+
+        # Wait some time for initiation
+        time.sleep(0.1)
+
+    @watched
+    def close(self):
+        if self.__handle is None:
+            return
+        self.__stdin.write('exit\n')
+        # Wait some time for termination
+        time.sleep(0.1)
+        self.__handle.close()
+        self.__stdin = None
+        self.__stdout = None
+        self.__handle = None
+
+    def send(self, cmd):
+        self.__stdin.write(cmd)
+
+    def recv(self):
+        try:
+            return self.__stdout.readline().rstrip()
+        except socket.timeout:
+            return ''
+
+    def log(self, fmt, *args):
+        try:
+            msg = fmt % args
+            print('%s - %s - %s' % (self.port, time.strftime('%b %d %H:%M:%S'), msg))
+        except Exception:
+            pass
+
+
+class OpenThread_Sim(OpenThreadTHCI, IThci):
+    DEFAULT_COMMAND_TIMEOUT = 20
+
+    __handle = None
+
+    device = os.path.join(REMOTE_OT_PATH, 'build/simulation/examples/apps/cli/ot-cli-ftd')
+
+    @watched
+    def _connect(self):
+        # Only actually connect once.
+        if self.__handle is None:
+            assert self.connectType == 'ip'
+            assert '@' in self.telnetIp
+            self.log('SSH connecting ...')
+            node_id, ssh_ip = self.telnetIp.split('@')
+            self.__handle = SSHHandle(ssh_ip, self.telnetPort, self.telnetUsername, self.telnetPassword, self.device,
+                                      node_id)
+
+        self.log('connected to %s successfully', self.telnetIp)
+
+    @watched
+    def _disconnect(self):
+        pass
+
+    def _cliReadLine(self):
+        tail = self.__handle.recv()
+        return tail if tail else None
+
+    def _cliWriteLine(self, line):
+        self.__handle.send(line + '\n')
+
+    def _onCommissionStart(self):
+        pass
+
+    def _onCommissionStop(self):
+        pass
diff --git a/third_party/tcplp/tcplp.c b/tools/harness-simulation/harness/Thread_Harness/simulation/__init__.py
similarity index 100%
rename from third_party/tcplp/tcplp.c
rename to tools/harness-simulation/harness/Thread_Harness/simulation/__init__.py
diff --git a/tools/harness-simulation/harness/Thread_Harness/simulation/config.py b/tools/harness-simulation/harness/Thread_Harness/simulation/config.py
new file mode 100644
index 0000000..44e866e
--- /dev/null
+++ b/tools/harness-simulation/harness/Thread_Harness/simulation/config.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2022, The OpenThread Authors.
+# All rights reserved.
+#
+# 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, 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.
+#
+
+REMOTE_PORT = 22
+REMOTE_USERNAME = 'pi'
+REMOTE_PASSWORD = 'raspberry'
+
+REMOTE_SNIFFER_OUTPUT_PREFIX = '/tmp/'
+
+REMOTE_OT_PATH = '/home/pi/work/src/openthread-pr/'
+
+EDITCAP_PATH = r'C:\Program Files (x86)\Wireshark_Thread\editcap.exe'
diff --git a/tools/harness-simulation/harness/Web/data/deviceInputFields.xml b/tools/harness-simulation/harness/Web/data/deviceInputFields.xml
new file mode 100644
index 0000000..a9e09d4
--- /dev/null
+++ b/tools/harness-simulation/harness/Web/data/deviceInputFields.xml
@@ -0,0 +1,10 @@
+<DEVICE_FIELDS>
+    <DEVICE name="OpenThread_Sim" thumbnail="OpenThread.png" description = "OpenThread Simulation" THCI="OpenThread_Sim">
+        <ITEM label="Serial Line"
+              type="text"
+              forParam="SerialPort"
+              validation="COM"
+              hint="eg: COM1">COM1
+        </ITEM>
+    </DEVICE>
+</DEVICE_FIELDS>
diff --git a/tools/harness-simulation/harness/install.bat b/tools/harness-simulation/harness/install.bat
new file mode 100644
index 0000000..0b4a898
--- /dev/null
+++ b/tools/harness-simulation/harness/install.bat
@@ -0,0 +1,2 @@
+xcopy /E /Y Thread_Harness %systemdrive%\GRL\Thread1.2\Thread_Harness
+copy /Y ..\..\harness-thci\OpenThread.py %systemdrive%\GRL\Thread1.2\Thread_Harness\THCI
diff --git a/tools/harness-simulation/posix/harness_dev_discovery.py b/tools/harness-simulation/posix/harness_dev_discovery.py
new file mode 100644
index 0000000..1587c99
--- /dev/null
+++ b/tools/harness-simulation/posix/harness_dev_discovery.py
@@ -0,0 +1,169 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+import argparse
+import ctypes
+import ctypes.util
+import json
+import logging
+import os
+import socket
+import struct
+
+GROUP = 'ff02::114'
+PORT = 12345
+MAX_OT11_NUM = 33
+MAX_SNIFFER_NUM = 4
+
+
+def if_nametoindex(ifname: str) -> int:
+    libc = ctypes.CDLL(ctypes.util.find_library('c'))
+    ret = libc.if_nametoindex(ifname.encode('ascii'))
+    if not ret:
+        raise RuntimeError('Invalid interface name')
+    return ret
+
+
+def get_ipaddr(ifname: str) -> str:
+    for line in os.popen(f'ip addr list dev {ifname} | grep inet | grep global'):
+        addr = line.strip().split()[1]
+        return addr.split('/')[0]
+    raise RuntimeError(f'No IP address on dev {ifname}')
+
+
+def init_socket(ifname: str, group: str, port: int) -> socket.socket:
+    # Look up multicast group address in name server and find out IP version
+    addrinfo = socket.getaddrinfo(group, None)[0]
+    assert addrinfo[0] == socket.AF_INET6
+
+    # Create a socket
+    s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)
+    s.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, (ifname + '\0').encode('ascii'))
+
+    # Bind it to the port
+    s.bind((group, port))
+
+    group_bin = socket.inet_pton(addrinfo[0], addrinfo[4][0])
+    # Join group
+    interface_index = if_nametoindex(ifname)
+    mreq = group_bin + struct.pack('@I', interface_index)
+    s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
+
+    return s
+
+
+def advertise_ftd(s: socket.socket, dst, ven: str, ver: str, add: str, por: int, number: int):
+    # Node ID of ot-cli-ftd is 1-indexed
+    for i in range(1, number + 1):
+        info = {
+            'ven': ven,
+            'mod': f'{ven}_{i}',
+            'ver': ver,
+            'add': f'{i}@{add}',
+            'por': por,
+        }
+        logging.info('Advertise: %r', info)
+        s.sendto(json.dumps(info).encode('utf-8'), dst)
+
+
+def advertise_sniffer(s: socket.socket, dst, add: str, number: int):
+    for i in range(number):
+        info = 'Sniffer_%d@%s' % (i, add)
+        logging.info('Advertise: %r', info)
+        s.sendto(info.encode('utf-8'), dst)
+
+
+def main():
+    logging.basicConfig(level=logging.INFO)
+
+    # Parse arguments
+    parser = argparse.ArgumentParser()
+
+    # Determine the interface
+    parser.add_argument('-i',
+                        '--interface',
+                        dest='ifname',
+                        type=str,
+                        required=True,
+                        help='the interface used for discovery')
+
+    # Determine the number of OpenThread 1.1 FTD simulations to be "detected" and then initiated
+    parser.add_argument('--ot1.1',
+                        dest='ot11_num',
+                        type=int,
+                        required=False,
+                        default=0,
+                        help=f'the number of OpenThread FTD simulations, no more than {MAX_OT11_NUM}')
+
+    # Determine the number of sniffer simulations to be initiated and then detected
+    parser.add_argument('-s',
+                        '--sniffer',
+                        dest='sniffer_num',
+                        type=int,
+                        required=False,
+                        default=0,
+                        help=f'the number of sniffer simulations, no more than {MAX_SNIFFER_NUM}')
+
+    args = parser.parse_args()
+
+    # Check validation of arguments
+    if not 0 <= args.ot11_num <= MAX_OT11_NUM:
+        raise ValueError(f'The number of FTDs should be between 0 and {MAX_OT11_NUM}')
+
+    if not 0 <= args.sniffer_num <= MAX_SNIFFER_NUM:
+        raise ValueError(f'The number of FTDs should be between 0 and {MAX_SNIFFER_NUM}')
+
+    if args.ot11_num == args.sniffer_num == 0:
+        raise ValueError('At least one device is required')
+
+    # Get the local IP address on the specified interface
+    addr = get_ipaddr(args.ifname)
+
+    s = init_socket(args.ifname, GROUP, PORT)
+
+    logging.info('Advertising on interface %s group %s ...', args.ifname, GROUP)
+
+    # Loop, printing any data we receive
+    while True:
+        data, src = s.recvfrom(64)
+
+        if data == b'BBR':
+            logging.info('Received OpenThread simulation query, advertising')
+            advertise_ftd(s, src, ven='OpenThread_Sim', ver='4', add=addr, por=22, number=args.ot11_num)
+
+        elif data == b'Sniffer':
+            logging.info('Received sniffer simulation query, advertising')
+            advertise_sniffer(s, src, add=addr, number=args.sniffer_num)
+
+        else:
+            logging.warning('Received %r, but ignored', data)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tools/harness-simulation/posix/sniffer_sim/pcap_codec.py b/tools/harness-simulation/posix/sniffer_sim/pcap_codec.py
new file mode 100644
index 0000000..ff25356
--- /dev/null
+++ b/tools/harness-simulation/posix/sniffer_sim/pcap_codec.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+""" Module to provide codec utilities for .pcap formatters. """
+
+import struct
+import time
+
+# https://www.tcpdump.org/linktypes.html
+DLT_IEEE802_15_4_WITHFCS = 195
+
+PCAP_MAGIC_NUMBER = 0xA1B2C3D4
+PCAP_VERSION_MAJOR = 2
+PCAP_VERSION_MINOR = 4
+
+
+class PcapCodec(object):
+    """ Utility class for .pcap formatters. """
+
+    def __init__(self, filename, channel):
+        self._dlt = DLT_IEEE802_15_4_WITHFCS
+        if not filename.endswith('.pcap'):
+            raise ValueError('Filename should end with .pcap')
+        self._pcap_file = open(filename, 'wb')
+        self._pcap_file.write(self.encode_header())
+        self._channel = channel
+
+    def encode_header(self):
+        """ Return a pcap file header. """
+        return struct.pack(
+            '<LHHLLLL',
+            PCAP_MAGIC_NUMBER,
+            PCAP_VERSION_MAJOR,
+            PCAP_VERSION_MINOR,
+            0,
+            0,
+            256,
+            self._dlt,
+        )
+
+    def encode_frame(self, frame, sec, usec):
+        """ Return a pcap encapsulation of the given frame. """
+
+        # Ignore the first byte storing channel.
+        frame = frame[1:]
+
+        length = len(frame)
+        pcap_frame = struct.pack('<LLLL', sec, usec, length, length)
+        pcap_frame += frame
+        return pcap_frame
+
+    def _get_timestamp(self):
+        """ Return the internal timestamp. """
+        timestamp = time.time()
+        timestamp_sec = int(timestamp)
+        timestamp_usec = int((timestamp - timestamp_sec) * 1000000)
+        return timestamp_sec, timestamp_usec
+
+    def append(self, frame):
+        """ Append a frame. """
+
+        # Filter channel.
+        if frame[0] != self._channel:
+            return
+
+        timestamp = self._get_timestamp()
+        pkt = self.encode_frame(frame, *timestamp)
+        self._pcap_file.write(pkt)
+        self._pcap_file.flush()
+
+    def close(self):
+        """ Close the pcap file. """
+
+        self._pcap_file.close()
diff --git a/tools/harness-simulation/posix/sniffer_sim/sniffer.py b/tools/harness-simulation/posix/sniffer_sim/sniffer.py
new file mode 100644
index 0000000..0ef6899
--- /dev/null
+++ b/tools/harness-simulation/posix/sniffer_sim/sniffer.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+import argparse
+import logging
+import signal
+import time
+import pcap_codec
+import sys
+import threading
+
+import sniffer_transport
+
+
+class Sniffer:
+    """ Class representing the Sniffing node, whose main task is listening.
+    """
+
+    logger = logging.getLogger('sniffer.Sniffer')
+
+    RECV_BUFFER_SIZE = 4096
+
+    def __init__(self, filename, channel):
+        self._pcap = pcap_codec.PcapCodec(filename, channel)
+
+        # Create transport
+        transport_factory = sniffer_transport.SnifferTransportFactory()
+        self._transport = transport_factory.create_transport()
+
+        self._thread = None
+        self._thread_alive = threading.Event()
+        self._thread_alive.clear()
+
+    def _sniffer_main_loop(self):
+        """ Sniffer main loop. """
+
+        self.logger.debug('Sniffer started.')
+
+        while self._thread_alive.is_set():
+            data, nodeid = self._transport.recv(self.RECV_BUFFER_SIZE)
+            self._pcap.append(data)
+
+        self.logger.debug('Sniffer stopped.')
+
+    def start(self):
+        """ Start sniffing. """
+
+        self._thread = threading.Thread(target=self._sniffer_main_loop)
+        self._thread.daemon = True
+
+        self._transport.open()
+
+        self._thread_alive.set()
+        self._thread.start()
+
+    def stop(self):
+        """ Stop sniffing. """
+
+        self._thread_alive.clear()
+
+        self._transport.close()
+
+        self._thread.join(timeout=1)
+        self._thread = None
+
+    def close(self):
+        """ Close the pcap file. """
+
+        self._pcap.close()
+
+
+def run_sniffer():
+    parser = argparse.ArgumentParser()
+    parser.add_argument('-o',
+                        '--output',
+                        dest='output',
+                        type=str,
+                        required=True,
+                        help='the path of the output .pcap file')
+    parser.add_argument('-c',
+                        '--channel',
+                        dest='channel',
+                        type=int,
+                        required=True,
+                        help='the channel which is sniffered')
+    args = parser.parse_args()
+
+    sniffer = Sniffer(args.output, args.channel)
+    sniffer.start()
+
+    def atexit(signum, frame):
+        sniffer.stop()
+        sniffer.close()
+        sys.exit(0)
+
+    signal.signal(signal.SIGTERM, atexit)
+
+    while sniffer._thread_alive.is_set():
+        time.sleep(0.5)
+
+    sniffer.stop()
+    sniffer.close()
+
+
+if __name__ == '__main__':
+    run_sniffer()
diff --git a/tools/harness-simulation/posix/sniffer_sim/sniffer_transport.py b/tools/harness-simulation/posix/sniffer_sim/sniffer_transport.py
new file mode 100644
index 0000000..62cf179
--- /dev/null
+++ b/tools/harness-simulation/posix/sniffer_sim/sniffer_transport.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python3
+#
+#  Copyright (c) 2022, The OpenThread Authors.
+#  All rights reserved.
+#
+#  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, 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.
+#
+
+import os
+import socket
+
+
+class SnifferTransport(object):
+    """ Interface for transport that allows eavesdrop other nodes. """
+
+    def open(self):
+        """ Open transport.
+
+        Raises:
+            RuntimeError: when transport is already opened or when transport opening failed.
+        """
+        raise NotImplementedError
+
+    def close(self):
+        """ Close transport.
+
+        Raises:
+            RuntimeError: when transport is already closed.
+        """
+        raise NotImplementedError
+
+    @property
+    def is_opened(self):
+        """ Check if transport is opened.
+
+        Returns:
+            bool: True if the transport is opened, False in otherwise
+        """
+        raise NotImplementedError
+
+    def send(self, data, nodeid):
+        """ Send data to the node with nodeid.
+
+        Args:
+            data (bytearray): outcoming data.
+            nodeid (int): node id
+
+        Returns:
+            int: number of sent bytes
+        """
+        raise NotImplementedError
+
+    def recv(self, bufsize):
+        """ Receive data sent by other node.
+
+        Args:
+            bufsize (int): size of buffer for incoming data.
+
+        Returns:
+            A tuple contains data and node id.
+
+            For example:
+            (bytearray([0x00, 0x01...], 1)
+        """
+        raise NotImplementedError
+
+
+class SnifferSocketTransport(SnifferTransport):
+    """ Socket based implementation of sniffer transport. """
+
+    BASE_PORT = 9000
+
+    MAX_NETWORK_SIZE = int(os.getenv('MAX_NETWORK_SIZE', '33'))
+
+    PORT_OFFSET = int(os.getenv('PORT_OFFSET', '0'))
+
+    RADIO_GROUP = '224.0.0.116'
+
+    def __init__(self):
+        self._socket = None
+
+    def __del__(self):
+        if not self.is_opened:
+            return
+
+        self.close()
+
+    def _nodeid_to_port(self, nodeid: int):
+        return self.BASE_PORT + (self.PORT_OFFSET * (self.MAX_NETWORK_SIZE + 1)) + nodeid
+
+    def _port_to_nodeid(self, port):
+        return (port - self.BASE_PORT - (self.PORT_OFFSET * (self.MAX_NETWORK_SIZE + 1)))
+
+    def open(self):
+        if self.is_opened:
+            raise RuntimeError('Transport is already opened.')
+
+        self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+
+        if not self.is_opened:
+            raise RuntimeError('Transport opening failed.')
+
+        self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+        self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
+        self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2 * 1024 * 1024)
+        self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2 * 1024 * 1024)
+        self._socket.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP,
+                                socket.inet_aton(self.RADIO_GROUP) + socket.inet_aton('127.0.0.1'))
+        self._socket.bind((self.RADIO_GROUP, self._nodeid_to_port(0)))
+
+    def close(self):
+        if not self.is_opened:
+            raise RuntimeError('Transport is closed.')
+
+        self._socket.close()
+        self._socket = None
+
+    @property
+    def is_opened(self):
+        return bool(self._socket is not None)
+
+    def send(self, data, nodeid):
+        address = ('127.0.0.1', self._nodeid_to_port(nodeid))
+
+        return self._socket.sendto(data, address)
+
+    def recv(self, bufsize):
+        data, address = self._socket.recvfrom(bufsize)
+
+        nodeid = self._port_to_nodeid(address[1])
+
+        return bytearray(data), nodeid
+
+
+class SnifferTransportFactory(object):
+
+    def create_transport(self):
+        return SnifferSocketTransport()
diff --git a/tools/harness-thci/OpenThread.py b/tools/harness-thci/OpenThread.py
index 9d87471..86bcb46 100644
--- a/tools/harness-thci/OpenThread.py
+++ b/tools/harness-thci/OpenThread.py
@@ -30,28 +30,22 @@
 >> Device : OpenThread THCI
 >> Class : OpenThread
 """
-
+import base64
 import functools
 import ipaddress
 import logging
 import random
+import traceback
 import re
 import socket
 import time
+import json
 from abc import abstractmethod
 
 import serial
 from Queue import Queue
 from serial.serialutil import SerialException
 
-TESTHARNESS_1_1 = '1.1'
-TESTHARNESS_1_2 = '1.2'
-
-if 'Thread1.2' in __file__:
-    TESTHARNESS_VERSION = TESTHARNESS_1_2
-else:
-    TESTHARNESS_VERSION = TESTHARNESS_1_1
-
 from GRLLibs.ThreadPacket.PlatformPackets import (
     PlatformDiagnosticPacket,
     PlatformPackets,
@@ -67,38 +61,43 @@
     PlatformDiagnosticPacket_Direction,
     PlatformDiagnosticPacket_Type,
 )
-
-if TESTHARNESS_VERSION == TESTHARNESS_1_2:
-    from GRLLibs.UtilityModules.enums import (
-        DevCapb,)
-
-    import commissioner
-    from commissioner_impl import OTCommissioner
+from GRLLibs.UtilityModules.enums import DevCapb
 
 from IThci import IThci
+import commissioner
+from commissioner_impl import OTCommissioner
+
+# Replace by the actual version string for the vendor's reference device
+OT11_VERSION = 'OPENTHREAD'
+OT12_VERSION = 'OPENTHREAD'
+OT13_VERSION = 'OPENTHREAD'
+
+# Supported device capabilites in this THCI implementation
+OT11_CAPBS = DevCapb.V1_1
+OT12_CAPBS = (DevCapb.L_AIO | DevCapb.C_FFD | DevCapb.C_RFD)
+OT12BR_CAPBS = (DevCapb.C_BBR | DevCapb.C_Host | DevCapb.C_Comm)
+OT13_CAPBS = (DevCapb.C_FTD13 | DevCapb.C_MTD13)
+OT13BR_CAPBS = (DevCapb.C_BR13 | DevCapb.C_Host13)
 
 ZEPHYR_PREFIX = 'ot '
+"""CLI prefix used for OpenThread commands in Zephyr systems"""
 
 LINESEPX = re.compile(r'\r\n|\n')
 """regex: used to split lines"""
 
-LOGX = re.compile(r'((\[(NONE|CRIT|WARN|NOTE|INFO|DEBG)\])'
-                  r'|(-(CLI|MLR|API|MLE|BBR|DUA|ARP|N-DATA|ICMP|IP6|MAC|MEM|NCP|MESH-CP|DIAG|PLAT|COAP|CORE|UTIL)-+: )'
+LOGX = re.compile(r'((\[(-|C|W|N|I|D)\])'
                   r'|(-+$)'  # e.x. ------------------------------------------------------------------------
                   r'|(=+\[.*\]=+$)'  # e.x. ==============================[TX len=108]===============================
                   r'|(\|.+\|.+\|.+)'  # e.x. | 61 DC D2 CE FA 04 00 00 | 00 00 0A 6E 16 01 00 00 | aRNz......n....
                   r')')
 """regex used to filter logs"""
 
-assert LOGX.match('[NONE]')
-assert LOGX.match('[CRIT]')
-assert LOGX.match('[WARN]')
-assert LOGX.match('[NOTE]')
-assert LOGX.match('[INFO]')
-assert LOGX.match('[DEBG]')
-assert LOGX.match('-CLI-----: ')
-assert LOGX.match('-N-DATA--: ')
-assert LOGX.match('-MESH-CP-: ')
+assert LOGX.match('[-]')
+assert LOGX.match('[C]')
+assert LOGX.match('[W]')
+assert LOGX.match('[N]')
+assert LOGX.match('[I]')
+assert LOGX.match('[D]')
 assert LOGX.match('------------------------------------------------------------------------')
 assert LOGX.match('==============================[TX len=108]===============================')
 assert LOGX.match('| 61 DC D2 CE FA 04 00 00 | 00 00 0A 6E 16 01 00 00 | aRNz......n....')
@@ -130,6 +129,8 @@
             raise
         finally:
             _callStackDepth -= 1
+            if _callStackDepth == 0:
+                print('\n')
 
     return wrapped_api_func
 
@@ -156,7 +157,12 @@
 
 
 def API(api_func):
-    return watched(api_func)
+    try:
+        return watched(api_func)
+    except Exception:
+        tb = traceback.format_exc()
+        ModuleHelper.WriteIntoDebugLogger("Exception raised while calling %s:\n%s" % (api_func.func_name, tb))
+        raise
 
 
 def commissioning(func):
@@ -192,26 +198,24 @@
     NETWORK_ATTACHMENT_TIMEOUT = 10
 
     IsBorderRouter = False
-    IsBackboneRouter = False
     IsHost = False
 
     externalCommissioner = None
     _update_router_status = False
 
-    __cmdPrefix = ''
-    __lineSepX = LINESEPX
+    _cmdPrefix = ''
+    _lineSepX = LINESEPX
 
-    if TESTHARNESS_VERSION == TESTHARNESS_1_2:
-        _ROLE_MODE_DICT = {
-            Thread_Device_Role.Leader: 'rdn',
-            Thread_Device_Role.Router: 'rdn',
-            Thread_Device_Role.SED: '-',
-            Thread_Device_Role.EndDevice: 'rn',
-            Thread_Device_Role.REED: 'rdn',
-            Thread_Device_Role.EndDevice_FED: 'rdn',
-            Thread_Device_Role.EndDevice_MED: 'rn',
-            Thread_Device_Role.SSED: '-',
-        }
+    _ROLE_MODE_DICT = {
+        Thread_Device_Role.Leader: 'rdn',
+        Thread_Device_Role.Router: 'rdn',
+        Thread_Device_Role.SED: '-',
+        Thread_Device_Role.EndDevice: 'rn',
+        Thread_Device_Role.REED: 'rdn',
+        Thread_Device_Role.EndDevice_FED: 'rdn',
+        Thread_Device_Role.EndDevice_MED: 'rn',
+        Thread_Device_Role.SSED: '-',
+    }
 
     def __init__(self, **kwargs):
         """initialize the serial port and default network parameters
@@ -258,8 +262,8 @@
         """Called when commissioning stops."""
 
     def __sendCommand(self, cmd, expectEcho=True):
-        cmd = self.__cmdPrefix + cmd
-        self.log("command: %s", cmd)
+        cmd = self._cmdPrefix + cmd
+        # self.log("command: %s", cmd)
         self._cliWriteLine(cmd)
         if expectEcho:
             self.__expect(cmd, endswith=True)
@@ -296,8 +300,10 @@
                     time.sleep(0.01)
                     continue
 
-                self.log("readline: %s", line)
-                response.append(line)
+                # self.log("readline: %s", line)
+                # skip empty lines
+                if line:
+                    response.append(line)
 
                 if line.endswith('Done'):
                     break
@@ -324,13 +330,14 @@
             expected    str: the expected string
             times       int: number of tries
         """
-        print('[%s] Expecting [%s]' % (self, expected))
+        #self.log('Expecting [%s]' % (expected))
 
         deadline = time.time() + timeout
         while True:
             line = self.__readCliLine()
             if line is not None:
-                self.log("readline: %s", line)
+                #self.log("readline: %s", line)
+                pass
 
             if line is None:
                 if time.time() >= deadline:
@@ -341,7 +348,7 @@
 
             matched = line.endswith(expected) if endswith else line == expected
             if matched:
-                print('[%s] Expected [%s]' % (self, expected))
+                #self.log('Expected [%s]' % (expected))
                 return
 
         raise Exception('failed to find expected string[%s]' % expected)
@@ -363,7 +370,8 @@
     def log(self, fmt, *args):
         try:
             msg = fmt % args
-            print('%s - %s - %s' % (self.port, time.strftime('%b %d %H:%M:%S'), msg))
+            # print('%s - %s - %s' % (self.port, time.strftime('%b %d %H:%M:%S'), msg))
+            print('%s %s' % (self.port, msg))
         except Exception:
             pass
 
@@ -376,7 +384,6 @@
     def intialize(self, params):
         """initialize the serial port with baudrate, timeout parameters"""
         self.port = params.get('SerialPort', '')
-        self.log('%s intialize: %r', self.__class__.__name__, params)
         # params example: {'EUI': 1616240311388864514L, 'SerialBaudRate': None, 'TelnetIP': '192.168.8.181', 'SerialPort': None, 'Param7': None, 'Param6': None, 'Param5': 'ip', 'TelnetPort': '22', 'Param9': None, 'Param8': None}
 
         try:
@@ -386,8 +393,8 @@
             self.connectType = 'ip'
             self.telnetIp = self.port
             self.telnetPort = 22
-            self.telnetUsername = 'pi'
-            self.telnetPassword = 'raspberry'
+            self.telnetUsername = 'pi' if params.get('Param6') is None else params.get('Param6')
+            self.telnetPassword = 'raspberry' if params.get('Param7') is None else params.get('Param7')
         except ValueError:
             self.connectType = (params.get('Param5') or 'usb').lower()
             self.telnetIp = params.get('TelnetIP')
@@ -398,9 +405,12 @@
             self.telnetPassword = 'raspberry' if params.get('Param7') is None else params.get('Param7')
 
         self.mac = params.get('EUI')
+        self.backboneNetif = params.get('Param8') or 'eth0'
+        self.extraParams = self.__parseExtraParams(params.get('Param9'))
 
         self.UIStatusMsg = ''
         self.AutoDUTEnable = False
+        self.isPowerDown = False
         self._is_net = False  # whether device is through ser2net
         self.logStatus = {
             'stop': 'stop',
@@ -420,9 +430,9 @@
 
         # init serial port
         self._connect()
-        self.__detectZephyr()
-        if TESTHARNESS_VERSION == TESTHARNESS_1_2:
-            self.__discoverDeviceCapability()
+        if not self.IsBorderRouter:
+            self.__detectZephyr()
+        self.__discoverDeviceCapability()
         self.UIStatusMsg = self.getVersionNumber()
 
         if self.firmwarePrefix in self.UIStatusMsg:
@@ -438,6 +448,35 @@
         else:
             return '[%s]' % self.port
 
+    @watched
+    def __parseExtraParams(self, Param9):
+        """
+        Parse `Param9` for extra THCI parameters.
+
+        `Param9` should be a JSON string encoded in URL-safe base64 encoding.
+
+        Defined Extra THCI Parameters:
+        - "cmd-start-otbr-agent"   : The command to start otbr-agent (default: systemctl start otbr-agent)
+        - "cmd-stop-otbr-agent"    : The command to stop otbr-agent (default: systemctl stop otbr-agent)
+        - "cmd-restart-otbr-agent" : The command to restart otbr-agent (default: systemctl restart otbr-agent)
+
+        For example, Param9 can be generated as below:
+        Param9 = base64.urlsafe_b64encode(json.dumps({
+            "cmd-start-otbr-agent": "service otbr-agent start",
+            "cmd-stop-otbr-agent": "service otbr-agent stop",
+            "cmd-restart-otbr-agent": "service otbr-agent restart",
+        }))
+
+        :param Param9: A JSON string encoded in URL-safe base64 encoding.
+        :return: A dict containing extra THCI parameters.
+        """
+        if not Param9 or not Param9.strip():
+            return {}
+
+        jsonStr = base64.urlsafe_b64decode(Param9)
+        params = json.loads(jsonStr)
+        return params
+
     @API
     def closeConnection(self):
         """close current serial port connection"""
@@ -446,12 +485,8 @@
     def __disableRouterEligible(self):
         """disable router role
         """
-        print('call __disableRouterEligible')
-        try:
-            cmd = 'routereligible disable'
-            self.__executeCommand(cmd)
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('__disableRouterEligible() Error: ' + str(e))
+        cmd = 'routereligible disable'
+        self.__executeCommand(cmd)
 
     def __setDeviceMode(self, mode):
         """set thread device mode:
@@ -467,13 +502,8 @@
            True: successful to set the device mode
            False: fail to set the device mode
         """
-        print('call __setDeviceMode')
-        print(mode)
-        try:
-            cmd = 'mode %s' % mode
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setDeviceMode() Error: ' + str(e))
+        cmd = 'mode %s' % mode
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     def __setRouterUpgradeThreshold(self, iThreshold):
         """set router upgrade threshold
@@ -486,13 +516,8 @@
             True: successful to set the ROUTER_UPGRADE_THRESHOLD
             False: fail to set ROUTER_UPGRADE_THRESHOLD
         """
-        print('call __setRouterUpgradeThreshold')
-        try:
-            cmd = 'routerupgradethreshold %s' % str(iThreshold)
-            print(cmd)
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setRouterUpgradeThreshold() Error: ' + str(e))
+        cmd = 'routerupgradethreshold %s' % str(iThreshold)
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     def __setRouterDowngradeThreshold(self, iThreshold):
         """set router downgrade threshold
@@ -506,13 +531,8 @@
             True: successful to set the ROUTER_DOWNGRADE_THRESHOLD
             False: fail to set ROUTER_DOWNGRADE_THRESHOLD
         """
-        print('call __setRouterDowngradeThreshold')
-        try:
-            cmd = 'routerdowngradethreshold %s' % str(iThreshold)
-            print(cmd)
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setRouterDowngradeThreshold() Error: ' + str(e))
+        cmd = 'routerdowngradethreshold %s' % str(iThreshold)
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     def __setRouterSelectionJitter(self, iRouterJitter):
         """set ROUTER_SELECTION_JITTER parameter for REED to upgrade to Router
@@ -524,13 +544,8 @@
             True: successful to set the ROUTER_SELECTION_JITTER
             False: fail to set ROUTER_SELECTION_JITTER
         """
-        print('call _setRouterSelectionJitter')
-        try:
-            cmd = 'routerselectionjitter %s' % str(iRouterJitter)
-            print(cmd)
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setRouterSelectionJitter() Error: ' + str(e))
+        cmd = 'routerselectionjitter %s' % str(iRouterJitter)
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     def __setAddressfilterMode(self, mode):
         """set address filter mode
@@ -539,12 +554,8 @@
             True: successful to set address filter mode.
             False: fail to set address filter mode.
         """
-        print('call setAddressFilterMode() ' + mode)
-        try:
-            cmd = 'macfilter addr ' + mode
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('__setAddressFilterMode() Error: ' + str(e))
+        cmd = 'macfilter addr ' + mode
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     def __startOpenThread(self):
         """start OpenThread stack
@@ -553,7 +564,6 @@
             True: successful to start OpenThread stack and thread interface up
             False: fail to start OpenThread stack
         """
-        print('call startOpenThread')
         if self.hasActiveDatasetToCommit:
             if self.__executeCommand('dataset commit active')[0] != 'Done':
                 raise Exception('failed to commit active dataset')
@@ -579,13 +589,10 @@
                 Thread_Device_Role.REED,
         ]:
             self.__setRouterSelectionJitter(1)
-        elif TESTHARNESS_VERSION == TESTHARNESS_1_2 and self.deviceRole in [
-                Thread_Device_Role.BR_1, Thread_Device_Role.BR_2
-        ]:
-            self.IsBackboneRouter = True
+        elif self.deviceRole in [Thread_Device_Role.BR_1, Thread_Device_Role.BR_2]:
             self.__setRouterSelectionJitter(1)
 
-        if self.IsBackboneRouter:
+        if self.DeviceCapability == OT12BR_CAPBS:
             # Configure default BBR dataset
             self.__configBbrDataset(SeqNum=self.bbrSeqNum,
                                     MlrTimeout=self.bbrMlrTimeout,
@@ -594,32 +601,11 @@
             if self.__useDefaultDomainPrefix:
                 self.__addDefaultDomainPrefix()
 
-            self._deviceBeforeThreadStart()
-
         self.__executeCommand('ifconfig up')
         self.__executeCommand('thread start')
         self.isPowerDown = False
         return True
 
-    def _deviceBeforeThreadStart(self):
-        pass
-
-    def __stopOpenThread(self):
-        """stop OpenThread stack
-
-        Returns:
-            True: successful to stop OpenThread stack and thread interface down
-            False: fail to stop OpenThread stack
-        """
-        self.log('call stopOpenThread')
-        try:
-            if self.__executeCommand('thread stop')[-1] == 'Done':
-                return self.__executeCommand('ifconfig down')[-1] == 'Done'
-            else:
-                return False
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('stopOpenThread() Error: ' + str(e))
-
     @watched
     def __isOpenThreadRunning(self):
         """check whether or not OpenThread is running
@@ -641,8 +627,7 @@
         detached_states = ["detached", "disabled"]
         return self.__executeCommand('state')[0] not in detached_states
 
-    # rloc16 might be hex string or integer, need to return actual allocated
-    # router id
+    # rloc16 might be hex string or integer, need to return actual allocated router id
     def __convertRlocToRouterId(self, xRloc16):
         """mapping Rloc16 to router id
 
@@ -656,9 +641,6 @@
         rloc16 = None
         routerid = None
 
-        print(routerList)
-        print(xRloc16)
-
         for index in routerList:
             cmd = 'router %s' % index
             router = self.__executeCommand(cmd)
@@ -686,26 +668,6 @@
 
         return None
 
-    def __convertIp6PrefixStringToIp6Address(self, strIp6Prefix):
-        """convert IPv6 prefix string to IPv6 dotted-quad format
-           for example:
-           2001000000000000 -> 2001:0000:0000:0000::
-
-        Args:
-            strIp6Prefix: IPv6 address string
-
-        Returns:
-            IPv6 address dotted-quad format
-        """
-        prefix1 = strIp6Prefix.rstrip('L')
-        prefix2 = self.__lstrip0x(prefix1)
-        hexPrefix = str(prefix2).ljust(16, '0')
-        hexIter = iter(hexPrefix)
-        finalMac = ':'.join(a + b + c + d for a, b, c, d in zip(hexIter, hexIter, hexIter, hexIter))
-        prefix = str(finalMac)
-        strIp6Prefix = prefix[:19]
-        return strIp6Prefix + '::'
-
     # pylint: disable=no-self-use
     def __convertLongToHex(self, iValue, fillZeros=None):
         """convert a long hex integer to string
@@ -791,25 +753,17 @@
         return maskSet
 
     def __setChannelMask(self, channelMask):
-        self.log('call _setChannelMask')
-        try:
-            cmd = 'dataset channelmask %s' % channelMask
-            self.hasActiveDatasetToCommit = True
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setChannelMask() Error: ' + str(e))
+        cmd = 'dataset channelmask %s' % channelMask
+        self.hasActiveDatasetToCommit = True
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     def __setSecurityPolicy(self, securityPolicySecs, securityPolicyFlags):
-        print('call _setSecurityPolicy')
-        try:
-            cmd = 'dataset securitypolicy %s %s' % (
-                str(securityPolicySecs),
-                securityPolicyFlags,
-            )
-            self.hasActiveDatasetToCommit = True
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setSecurityPolicy() Error: ' + str(e))
+        cmd = 'dataset securitypolicy %s %s' % (
+            str(securityPolicySecs),
+            securityPolicyFlags,
+        )
+        self.hasActiveDatasetToCommit = True
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     def __setKeySwitchGuardTime(self, iKeySwitchGuardTime):
         """ set the Key switch guard time
@@ -821,21 +775,15 @@
             True: successful to set key switch guard time
             False: fail to set key switch guard time
         """
-        print('%s call setKeySwitchGuardTime' % self)
-        print(iKeySwitchGuardTime)
-        try:
-            cmd = 'keysequence guardtime %s' % str(iKeySwitchGuardTime)
-            if self.__executeCommand(cmd)[-1] == 'Done':
-                self.sleep(1)
-                return True
-            else:
-                return False
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setKeySwitchGuardTime() Error; ' + str(e))
+        cmd = 'keysequence guardtime %s' % str(iKeySwitchGuardTime)
+        if self.__executeCommand(cmd)[-1] == 'Done':
+            self.sleep(1)
+            return True
+        else:
+            return False
 
     def __getCommissionerSessionId(self):
         """ get the commissioner session id allocated from Leader """
-        print('%s call getCommissionerSessionId' % self)
         return self.__executeCommand('commissioner sessionid')[0]
 
     # pylint: disable=no-self-use
@@ -864,16 +812,11 @@
             True: successful to set the Thread Networkname
             False: fail to set the Thread Networkname
         """
-        print('%s call setNetworkName' % self)
-        print(networkName)
         networkName = self._deviceEscapeEscapable(networkName)
-        try:
-            cmd = 'networkname %s' % networkName
-            datasetCmd = 'dataset networkname %s' % networkName
-            self.hasActiveDatasetToCommit = True
-            return self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setNetworkName() Error: ' + str(e))
+        cmd = 'networkname %s' % networkName
+        datasetCmd = 'dataset networkname %s' % networkName
+        self.hasActiveDatasetToCommit = True
+        return self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done'
 
     @API
     def setChannel(self, channel=11):
@@ -889,21 +832,15 @@
             True: successful to set the channel
             False: fail to set the channel
         """
-        print('%s call setChannel' % self)
-        print(channel)
-        try:
-            cmd = 'channel %s' % channel
-            datasetCmd = 'dataset channel %s' % channel
-            self.hasSetChannel = True
-            self.hasActiveDatasetToCommit = True
-            return self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setChannel() Error: ' + str(e))
+        cmd = 'channel %s' % channel
+        datasetCmd = 'dataset channel %s' % channel
+        self.hasSetChannel = True
+        self.hasActiveDatasetToCommit = True
+        return self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done'
 
     @API
     def getChannel(self):
         """get current channel"""
-        print('%s call getChannel' % self)
         return self.__executeCommand('channel')[0]
 
     @API
@@ -917,23 +854,17 @@
             True: successful to set the extended address
             False: fail to set the extended address
         """
-        print('%s call setMAC' % self)
-        print(xEUI)
-        try:
-            if not isinstance(xEUI, str):
-                address64 = self.__convertLongToHex(xEUI, 16)
-            else:
-                address64 = xEUI
+        if not isinstance(xEUI, str):
+            address64 = self.__convertLongToHex(xEUI, 16)
+        else:
+            address64 = xEUI
 
-            cmd = 'extaddr %s' % address64
-            print(cmd)
-            if self.__executeCommand(cmd)[-1] == 'Done':
-                self.mac = address64
-                return True
-            else:
-                return False
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setMAC() Error: ' + str(e))
+        cmd = 'extaddr %s' % address64
+        if self.__executeCommand(cmd)[-1] == 'Done':
+            self.mac = address64
+            return True
+        else:
+            return False
 
     @API
     def getMAC(self, bType=MacType.RandomMac):
@@ -946,8 +877,6 @@
         Returns:
             specific type of MAC address
         """
-        print('%s call getMAC' % self)
-        print(bType)
         # if power down happens, return extended address assigned previously
         if self.isPowerDown:
             macAddr64 = self.mac
@@ -956,38 +885,33 @@
                 macAddr64 = self.__executeCommand('eui64')[0]
             elif bType == MacType.HashMac:
                 macAddr64 = self.__executeCommand('joiner id')[0]
-            elif TESTHARNESS_VERSION == TESTHARNESS_1_2 and bType == MacType.EthMac:
+            elif bType == MacType.EthMac and self.IsBorderRouter:
                 return self._deviceGetEtherMac()
             else:
                 macAddr64 = self.__executeCommand('extaddr')[0]
-        print(macAddr64)
 
         return int(macAddr64, 16)
 
     @API
     def getLL64(self):
         """get link local unicast IPv6 address"""
-        print('%s call getLL64' % self)
         return self.__executeCommand('ipaddr linklocal')[0]
 
     @API
     def getRloc16(self):
         """get rloc16 short address"""
-        print('%s call getRloc16' % self)
         rloc16 = self.__executeCommand('rloc16')[0]
         return int(rloc16, 16)
 
     @API
     def getRloc(self):
         """get router locator unicast Ipv6 address"""
-        print('%s call getRloc' % self)
         return self.__executeCommand('ipaddr rloc')[0]
 
     def __getGlobal(self):
         """get global unicast IPv6 address set
            if configuring multiple entries
         """
-        print('%s call getGlobal' % self)
         globalAddrs = []
         rlocAddr = self.getRloc()
 
@@ -1002,18 +926,10 @@
 
             fullIp = ModuleHelper.GetFullIpv6Address(ip6Addr).lower()
 
-            print('address %s' % fullIp)
-
-            if fullIp.startswith('fe80'):
-                print('link local')
-                continue
-
-            if fullIp.startswith(rlocAddr[0:19]):
-                print('mesh local')
+            if fullIp.startswith('fe80') or fullIp.startswith(rlocAddr[0:19]):
                 continue
 
             globalAddrs.append(fullIp)
-            print('global')
 
         return globalAddrs
 
@@ -1028,24 +944,18 @@
             True: successful to set the Thread network key
             False: fail to set the Thread network key
         """
-        print('%s call setNetworkKey' % self)
-        print(key)
+        if not isinstance(key, str):
+            networkKey = self.__convertLongToHex(key, 32)
+            cmd = 'networkkey %s' % networkKey
+            datasetCmd = 'dataset networkkey %s' % networkKey
+        else:
+            networkKey = key
+            cmd = 'networkkey %s' % networkKey
+            datasetCmd = 'dataset networkkey %s' % networkKey
 
-        try:
-            if not isinstance(key, str):
-                networkKey = self.__convertLongToHex(key, 32)
-                cmd = 'networkkey %s' % networkKey
-                datasetCmd = 'dataset networkkey %s' % networkKey
-            else:
-                networkKey = key
-                cmd = 'networkkey %s' % networkKey
-                datasetCmd = 'dataset networkkey %s' % networkKey
-
-            self.networkKey = networkKey
-            self.hasActiveDatasetToCommit = True
-            return self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setNetworkkey() Error: ' + str(e))
+        self.networkKey = networkKey
+        self.hasActiveDatasetToCommit = True
+        return self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done'
 
     @API
     def addBlockedMAC(self, xEUI):
@@ -1058,35 +968,29 @@
             True: successful to add a given extended address to the denylist entry
             False: fail to add a given extended address to the denylist entry
         """
-        print('%s call addBlockedMAC' % self)
-        print(xEUI)
         if isinstance(xEUI, str):
             macAddr = xEUI
         else:
             macAddr = self.__convertLongToHex(xEUI)
 
-        try:
-            # if blocked device is itself
-            if macAddr == self.mac:
-                print('block device itself')
-                return True
+        # if blocked device is itself
+        if macAddr == self.mac:
+            print('block device itself')
+            return True
 
-            if self._addressfilterMode != 'denylist':
-                if self.__setAddressfilterMode('denylist'):
-                    self._addressfilterMode = 'denylist'
+        if self._addressfilterMode != 'denylist':
+            if self.__setAddressfilterMode('denylist'):
+                self._addressfilterMode = 'denylist'
 
-            cmd = 'macfilter addr add %s' % macAddr
-            print(cmd)
-            ret = self.__executeCommand(cmd)[-1] == 'Done'
+        cmd = 'macfilter addr add %s' % macAddr
+        ret = self.__executeCommand(cmd)[-1] == 'Done'
 
-            self._addressfilterSet.add(macAddr)
-            print('current denylist entries:')
-            for addr in self._addressfilterSet:
-                print(addr)
+        self._addressfilterSet.add(macAddr)
+        print('current denylist entries:')
+        for addr in self._addressfilterSet:
+            print(addr)
 
-            return ret
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('addBlockedMAC() Error: ' + str(e))
+        return ret
 
     @API
     def addAllowMAC(self, xEUI):
@@ -1099,30 +1003,23 @@
             True: successful to add a given extended address to the allowlist entry
             False: fail to add a given extended address to the allowlist entry
         """
-        print('%s call addAllowMAC' % self)
-        print(xEUI)
         if isinstance(xEUI, str):
             macAddr = xEUI
         else:
             macAddr = self.__convertLongToHex(xEUI)
 
-        try:
-            if self._addressfilterMode != 'allowlist':
-                if self.__setAddressfilterMode('allowlist'):
-                    self._addressfilterMode = 'allowlist'
+        if self._addressfilterMode != 'allowlist':
+            if self.__setAddressfilterMode('allowlist'):
+                self._addressfilterMode = 'allowlist'
 
-            cmd = 'macfilter addr add %s' % macAddr
-            print(cmd)
-            ret = self.__executeCommand(cmd)[-1] == 'Done'
+        cmd = 'macfilter addr add %s' % macAddr
+        ret = self.__executeCommand(cmd)[-1] == 'Done'
 
-            self._addressfilterSet.add(macAddr)
-            print('current allowlist entries:')
-            for addr in self._addressfilterSet:
-                print(addr)
-            return ret
-
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('addAllowMAC() Error: ' + str(e))
+        self._addressfilterSet.add(macAddr)
+        print('current allowlist entries:')
+        for addr in self._addressfilterSet:
+            print(addr)
+        return ret
 
     @API
     def clearBlockList(self):
@@ -1132,25 +1029,20 @@
             True: successful to clear the denylist
             False: fail to clear the denylist
         """
-        print('%s call clearBlockList' % self)
-
         # remove all entries in denylist
-        try:
-            print('clearing denylist entries:')
-            for addr in self._addressfilterSet:
-                print(addr)
+        print('clearing denylist entries:')
+        for addr in self._addressfilterSet:
+            print(addr)
 
-            # disable denylist
-            if self.__setAddressfilterMode('disable'):
-                self._addressfilterMode = 'disable'
-                # clear ops
-                cmd = 'macfilter addr clear'
-                if self.__executeCommand(cmd)[-1] == 'Done':
-                    self._addressfilterSet.clear()
-                    return True
-            return False
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('clearBlockList() Error: ' + str(e))
+        # disable denylist
+        if self.__setAddressfilterMode('disable'):
+            self._addressfilterMode = 'disable'
+            # clear ops
+            cmd = 'macfilter addr clear'
+            if self.__executeCommand(cmd)[-1] == 'Done':
+                self._addressfilterSet.clear()
+                return True
+        return False
 
     @API
     def clearAllowList(self):
@@ -1160,30 +1052,24 @@
             True: successful to clear the allowlist
             False: fail to clear the allowlist
         """
-        print('%s call clearAllowList' % self)
-
         # remove all entries in allowlist
-        try:
-            print('clearing allowlist entries:')
-            for addr in self._addressfilterSet:
-                print(addr)
+        print('clearing allowlist entries:')
+        for addr in self._addressfilterSet:
+            print(addr)
 
-            # disable allowlist
-            if self.__setAddressfilterMode('disable'):
-                self._addressfilterMode = 'disable'
-                # clear ops
-                cmd = 'macfilter addr clear'
-                if self.__executeCommand(cmd)[-1] == 'Done':
-                    self._addressfilterSet.clear()
-                    return True
-            return False
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('clearAllowList() Error: ' + str(e))
+        # disable allowlist
+        if self.__setAddressfilterMode('disable'):
+            self._addressfilterMode = 'disable'
+            # clear ops
+            cmd = 'macfilter addr clear'
+            if self.__executeCommand(cmd)[-1] == 'Done':
+                self._addressfilterSet.clear()
+                return True
+        return False
 
     @API
     def getDeviceRole(self):
         """get current device role in Thread Network"""
-        print('%s call getDeviceRole' % self)
         return self.__executeCommand('state')[0]
 
     @API
@@ -1196,74 +1082,73 @@
         Returns:
             True: ready to set Thread Network parameter for joining desired Network
         """
-        print('%s call joinNetwork' % self)
-        print(eRoleId)
-
         self.deviceRole = eRoleId
         mode = '-'
-        try:
-            if ModuleHelper.LeaderDutChannelFound and not self.hasSetChannel:
-                self.channel = ModuleHelper.Default_Channel
+        if ModuleHelper.LeaderDutChannelFound and not self.hasSetChannel:
+            self.channel = ModuleHelper.Default_Channel
 
-            # FIXME: when Harness call setNetworkDataRequirement()?
-            # only sleep end device requires stable networkdata now
-            if eRoleId == Thread_Device_Role.Leader:
-                print('join as leader')
-                mode = 'rdn'
-                if self.AutoDUTEnable is False:
-                    # set ROUTER_DOWNGRADE_THRESHOLD
-                    self.__setRouterDowngradeThreshold(33)
-            elif eRoleId == Thread_Device_Role.Router:
-                print('join as router')
-                mode = 'rdn'
-                if self.AutoDUTEnable is False:
-                    # set ROUTER_DOWNGRADE_THRESHOLD
-                    self.__setRouterDowngradeThreshold(33)
-            elif eRoleId in (Thread_Device_Role.BR_1, Thread_Device_Role.BR_2):
+        # FIXME: when Harness call setNetworkDataRequirement()?
+        # only sleep end device requires stable networkdata now
+        if eRoleId == Thread_Device_Role.Leader:
+            print('join as leader')
+            mode = 'rdn'
+            if self.AutoDUTEnable is False:
+                # set ROUTER_DOWNGRADE_THRESHOLD
+                self.__setRouterDowngradeThreshold(33)
+        elif eRoleId == Thread_Device_Role.Router:
+            print('join as router')
+            mode = 'rdn'
+            if self.AutoDUTEnable is False:
+                # set ROUTER_DOWNGRADE_THRESHOLD
+                self.__setRouterDowngradeThreshold(33)
+        elif eRoleId in (Thread_Device_Role.BR_1, Thread_Device_Role.BR_2):
+            if self.DeviceCapability == OT12BR_CAPBS:
                 print('join as BBR')
-                mode = 'rdn'
-                if self.AutoDUTEnable is False:
-                    # set ROUTER_DOWNGRADE_THRESHOLD
-                    self.__setRouterDowngradeThreshold(33)
-            elif eRoleId == Thread_Device_Role.SED:
-                print('join as sleepy end device')
-                mode = '-'
-                self.__setPollPeriod(self.__sedPollPeriod)
-            elif eRoleId == Thread_Device_Role.SSED:
-                print('join as SSED')
-                mode = '-'
-                self.setCSLperiod(self.cslPeriod)
-            elif eRoleId == Thread_Device_Role.EndDevice:
-                print('join as end device')
-                mode = 'rn'
-            elif eRoleId == Thread_Device_Role.REED:
-                print('join as REED')
-                mode = 'rdn'
-                if self.AutoDUTEnable is False:
-                    # set ROUTER_UPGRADE_THRESHOLD
-                    self.__setRouterUpgradeThreshold(0)
-            elif eRoleId == Thread_Device_Role.EndDevice_FED:
-                print('join as FED')
-                mode = 'rdn'
-                # always remain an ED, never request to be a router
-                self.__disableRouterEligible()
-            elif eRoleId == Thread_Device_Role.EndDevice_MED:
-                print('join as MED')
-                mode = 'rn'
             else:
-                pass
+                print('join as BR')
+            mode = 'rdn'
+            if self.AutoDUTEnable is False:
+                # set ROUTER_DOWNGRADE_THRESHOLD
+                self.__setRouterDowngradeThreshold(33)
+        elif eRoleId == Thread_Device_Role.SED:
+            print('join as sleepy end device')
+            mode = '-'
+            self.__setPollPeriod(self.__sedPollPeriod)
+        elif eRoleId == Thread_Device_Role.SSED:
+            print('join as SSED')
+            mode = '-'
+            self.setCSLperiod(self.cslPeriod)
+            self.setCSLtout(self.ssedTimeout)
+            self.setCSLsuspension(False)
+        elif eRoleId == Thread_Device_Role.EndDevice:
+            print('join as end device')
+            mode = 'rn'
+        elif eRoleId == Thread_Device_Role.REED:
+            print('join as REED')
+            mode = 'rdn'
+            if self.AutoDUTEnable is False:
+                # set ROUTER_UPGRADE_THRESHOLD
+                self.__setRouterUpgradeThreshold(0)
+        elif eRoleId == Thread_Device_Role.EndDevice_FED:
+            print('join as FED')
+            mode = 'rdn'
+            # always remain an ED, never request to be a router
+            self.__disableRouterEligible()
+        elif eRoleId == Thread_Device_Role.EndDevice_MED:
+            print('join as MED')
+            mode = 'rn'
+        else:
+            pass
 
-            # set Thread device mode with a given role
-            self.__setDeviceMode(mode)
+        # set Thread device mode with a given role
+        self.__setDeviceMode(mode)
 
-            # start OpenThread
-            self.__startOpenThread()
-            self.wait_for_attach_to_the_network(expected_role=eRoleId,
-                                                timeout=self.NETWORK_ATTACHMENT_TIMEOUT,
-                                                raise_assert=True)
-            return True
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('joinNetwork() Error: ' + str(e))
+        # start OpenThread
+        self.__startOpenThread()
+        self.wait_for_attach_to_the_network(expected_role=eRoleId,
+                                            timeout=self.NETWORK_ATTACHMENT_TIMEOUT,
+                                            raise_assert=True)
+        return True
 
     def wait_for_attach_to_the_network(self, expected_role, timeout, raise_assert=False):
         start_time = time.time()
@@ -1294,7 +1179,10 @@
                 else:
                     return False
 
-            return True
+        if self.IsBorderRouter:
+            self._waitBorderRoutingStabilize()
+
+        return True
 
     @API
     def getNetworkFragmentID(self):
@@ -1303,9 +1191,7 @@
         Returns:
             The Thread network Partition Id
         """
-        print('%s call getNetworkFragmentID' % self)
         if not self.__isOpenThreadRunning():
-            print('OpenThread is not running')
             return None
 
         leaderData = self.__executeCommand('leaderdata')
@@ -1318,7 +1204,6 @@
         Returns:
             The extended address of parent in hex format
         """
-        print('%s call getParentAddress' % self)
         eui = None
         parentInfo = self.__executeCommand('parent')
 
@@ -1327,10 +1212,6 @@
                 break
             elif 'Ext Addr' in line:
                 eui = line.split()[2]
-                print(eui)
-            # elif 'Rloc' in line:
-            #    rloc16 = line.split()[1]
-            #    print(rloc16)
             else:
                 pass
 
@@ -1339,7 +1220,6 @@
     @API
     def powerDown(self):
         """power down the Thread device"""
-        print('%s call powerDown' % self)
         self.__sendCommand('reset', expectEcho=False)
 
         if not self.IsBorderRouter:
@@ -1351,10 +1231,11 @@
     @API
     def powerUp(self):
         """power up the Thread device"""
-        print('%s call powerUp' % self)
         self.isPowerDown = False
 
         if not self.__isOpenThreadRunning():
+            if self.deviceRole == Thread_Device_Role.SED:
+                self.__setPollPeriod(self.__sedPollPeriod)
             self.__startOpenThread()
 
     def reset_and_wait_for_connection(self, timeout=3):
@@ -1365,7 +1246,7 @@
 
         while time.time() < start_time + timeout:
             time.sleep(0.3)
-            if TESTHARNESS_VERSION == TESTHARNESS_1_2 and not self.IsBorderRouter:
+            if not self.IsBorderRouter:
                 self._disconnect()
                 self._connect()
             try:
@@ -1387,13 +1268,9 @@
             True: successful to reset and rejoin the Thread Network
             False: fail to reset and rejoin the Thread Network
         """
-        print('%s call reboot' % self)
-        try:
-            self.reset_and_wait_for_connection()
-            self.__startOpenThread()
-            return self.wait_for_attach_to_the_network(expected_role="", timeout=self.NETWORK_ATTACHMENT_TIMEOUT)
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('reboot() Error: ' + str(e))
+        self.reset_and_wait_for_connection()
+        self.__startOpenThread()
+        return self.wait_for_attach_to_the_network(expected_role="", timeout=self.NETWORK_ATTACHMENT_TIMEOUT)
 
     @API
     def resetAndRejoin(self, timeout):
@@ -1406,13 +1283,10 @@
             True: successful to reset and rejoin Thread Network
             False: fail to reset and rejoin the Thread Network
         """
-        print('%s call resetAndRejoin' % self)
-        try:
-            self.reset_and_wait_for_connection(timeout=timeout)
-            self.__startOpenThread()
-            return self.wait_for_attach_to_the_network(expected_role="", timeout=self.NETWORK_ATTACHMENT_TIMEOUT)
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('resetAndRejoin() Error: ' + str(e))
+        self.powerDown()
+        time.sleep(timeout)
+        self.powerUp()
+        return self.wait_for_attach_to_the_network(expected_role="", timeout=self.NETWORK_ATTACHMENT_TIMEOUT)
 
     @API
     def ping(self, strDestination, ilength=0, hop_limit=64, timeout=5):
@@ -1424,11 +1298,8 @@
             hop_limit: hop limit
 
         """
-        print('%s call ping' % self.port)
-        print('destination: %s' % strDestination)
         cmd = 'ping %s %s 1 1 %d %d' % (strDestination, str(ilength), hop_limit, timeout)
         self.__executeCommand(cmd)
-        time.sleep(1)
 
     @API
     def multicast_Ping(self, destination, length=20):
@@ -1439,16 +1310,10 @@
             destination: the multicast destination address of ICMPv6 echo request
             length: the size of ICMPv6 echo request payload
         """
-        print('%s call multicast_Ping' % self)
-        print('destination: %s' % destination)
-        try:
-            cmd = 'ping %s %s' % (destination, str(length))
-            print(cmd)
-            self.__sendCommand(cmd)
-            # wait echo reply
-            self.sleep(1)
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('multicast_ping() Error: ' + str(e))
+        cmd = 'ping %s %s' % (destination, str(length))
+        self.__sendCommand(cmd)
+        # wait echo reply
+        self.sleep(1)
 
     @API
     def setPANID(self, xPAN):
@@ -1461,26 +1326,18 @@
             True: successful to set the Thread Network PAN ID
             False: fail to set the Thread Network PAN ID
         """
-        print('%s call setPANID' % self)
-        print(xPAN)
         panid = ''
-        try:
-            if not isinstance(xPAN, str):
-                panid = str(hex(xPAN))
-                print(panid)
+        if not isinstance(xPAN, str):
+            panid = str(hex(xPAN))
 
-            cmd = 'panid %s' % panid
-            datasetCmd = 'dataset panid %s' % panid
-            self.hasActiveDatasetToCommit = True
-            return self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setPANID() Error: ' + str(e))
+        cmd = 'panid %s' % panid
+        datasetCmd = 'dataset panid %s' % panid
+        self.hasActiveDatasetToCommit = True
+        return self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done'
 
     @API
     def reset(self):
         """factory reset"""
-        print('%s call reset' % self)
-
         self._deviceBeforeReset()
 
         self.__sendCommand('factoryreset', expectEcho=False)
@@ -1488,14 +1345,18 @@
 
         start_time = time.time()
         while time.time() < start_time + timeout:
-            time.sleep(0.3)
-            if TESTHARNESS_VERSION == TESTHARNESS_1_2 and not self.IsBorderRouter:
+            time.sleep(0.5)
+            if not self.IsBorderRouter:
                 self._disconnect()
                 self._connect()
             try:
                 self.__executeCommand('state', timeout=0.1)
                 break
             except Exception:
+                self.__restartAgentService()
+                time.sleep(2)
+                self.__sendCommand('factoryreset', expectEcho=False)
+                time.sleep(0.5)
                 continue
         else:
             raise AssertionError("Could not connect with OT device {} after reset.".format(self))
@@ -1514,26 +1375,17 @@
             True: successful to remove the router from the Thread Network
             False: fail to remove the router from the Thread Network
         """
-        print('%s call removeRouter' % self)
-        print(xRouterId)
         routerId = self.__convertRlocToRouterId(xRouterId)
-        print(routerId)
 
         if routerId is None:
-            print('no matched xRouterId')
             return False
 
-        try:
-            cmd = 'releaserouterid %s' % routerId
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('removeRouter() Error: ' + str(e))
+        cmd = 'releaserouterid %s' % routerId
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def setDefaultValues(self):
         """set default mandatory Thread Network parameter value"""
-        print('%s call setDefaultValues' % self)
-
         # initialize variables
         self.networkName = ModuleHelper.Default_NwkName
         self.networkKey = ModuleHelper.Default_NwkKey
@@ -1542,13 +1394,15 @@
         self.panId = ModuleHelper.Default_PanId
         self.xpanId = ModuleHelper.Default_XpanId
         self.meshLocalPrefix = ModuleHelper.Default_MLPrefix
-        # OT only accept hex format PSKc for now
-        self.pskc = '00000000000000000000000000000001'
+        stretchedPSKc = Thread_PBKDF2.get(ModuleHelper.Default_PSKc, ModuleHelper.Default_XpanId,
+                                          ModuleHelper.Default_NwkName)
+        self.pskc = hex(stretchedPSKc).rstrip('L').lstrip('0x')
         self.securityPolicySecs = ModuleHelper.Default_SecurityPolicy
-        self.securityPolicyFlags = 'onrcb'
+        self.securityPolicyFlags = 'onrc'
         self.activetimestamp = ModuleHelper.Default_ActiveTimestamp
         # self.sedPollingRate = ModuleHelper.Default_Harness_SED_Polling_Rate
         self.__sedPollPeriod = 3 * 1000  # in milliseconds
+        self.ssedTimeout = 30  # in seconds
         self.cslPeriod = 500  # in milliseconds
         self.deviceRole = None
         self.provisioningUrl = ''
@@ -1569,36 +1423,36 @@
         # to default when joining network
         self.hasSetChannel = False
         # indicate whether the default domain prefix is used.
-        self.__useDefaultDomainPrefix = True
+        self.__useDefaultDomainPrefix = (self.DeviceCapability == OT12BR_CAPBS)
         self.__isUdpOpened = False
-        self.IsBackboneRouter = False
         self.IsHost = False
 
+        # remove stale multicast addresses
+        if self.IsBorderRouter:
+            self.stopListeningToAddrAll()
+
         # BBR dataset
-        self.bbrSeqNum = random.randint(0, 254)  # random seqnum except 255, so that BBR-TC-02 never need re-run
-        self.bbrMlrTimeout = 3600
-        self.bbrReRegDelay = 5
+        if self.DeviceCapability == OT12BR_CAPBS:
+            self.bbrSeqNum = random.randint(0, 126)  # 5.21.4.2
+            self.bbrMlrTimeout = 3600
+            self.bbrReRegDelay = 5
 
         # initialize device configuration
-        try:
-            self.setMAC(self.mac)
-            self.__setChannelMask(self.channelMask)
-            self.__setSecurityPolicy(self.securityPolicySecs, self.securityPolicyFlags)
-            self.setChannel(self.channel)
-            self.setPANID(self.panId)
-            self.setXpanId(self.xpanId)
-            self.setNetworkName(self.networkName)
-            self.setNetworkKey(self.networkKey)
-            self.setMLPrefix(self.meshLocalPrefix)
-            self.setPSKc(self.pskc)
-            self.setActiveTimestamp(self.activetimestamp)
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setDefaultValue() Error: ' + str(e))
+        self.setMAC(self.mac)
+        self.__setChannelMask(self.channelMask)
+        self.__setSecurityPolicy(self.securityPolicySecs, self.securityPolicyFlags)
+        self.setChannel(self.channel)
+        self.setPANID(self.panId)
+        self.setXpanId(self.xpanId)
+        self.setNetworkName(self.networkName)
+        self.setNetworkKey(self.networkKey)
+        self.setMLPrefix(self.meshLocalPrefix)
+        self.setPSKc(self.pskc)
+        self.setActiveTimestamp(self.activetimestamp)
 
     @API
     def getDeviceConncetionStatus(self):
         """check if serial port connection is ready or not"""
-        print('%s call getDeviceConnectionStatus' % self)
         return self.deviceConnected
 
     @API
@@ -1612,12 +1466,13 @@
             True: successful to set the data polling rate for sleepy end device
             False: fail to set the data polling rate for sleepy end device
         """
-        print('%s call setPollingRate' % self)
-
         iPollingRate = int(iPollingRate * 1000)
-        print(iPollingRate)
 
         if self.__sedPollPeriod != iPollingRate:
+            if not iPollingRate:
+                iPollingRate = 0xFFFF  # T5.2.1, disable polling
+            elif iPollingRate < 1:
+                iPollingRate = 1  # T9.2.13
             self.__sedPollPeriod = iPollingRate
 
             # apply immediately
@@ -1636,12 +1491,8 @@
             True: successful to set the data poll period for sleepy end device
             False: fail to set the data poll period for sleepy end device
         """
-        try:
-            cmd = 'pollperiod %d' % iPollPeriod
-            print(cmd)
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('__setPollPeriod() Error: ' + str(e))
+        cmd = 'pollperiod %d' % iPollPeriod
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def setLinkQuality(self, EUIadr, LinkQuality):
@@ -1660,27 +1511,20 @@
             True: successful to set the link quality
             False: fail to set the link quality
         """
-        print('%s call setLinkQuality' % self)
-        print(EUIadr)
-        print(LinkQuality)
-        try:
-            # process EUIadr
-            euiHex = hex(EUIadr)
-            euiStr = str(euiHex)
-            euiStr = euiStr.rstrip('L')
-            address64 = ''
-            if '0x' in euiStr:
-                address64 = self.__lstrip0x(euiStr)
-                # prepend 0 at the beginning
-                if len(address64) < 16:
-                    address64 = address64.zfill(16)
-                    print(address64)
+        # process EUIadr
+        euiHex = hex(EUIadr)
+        euiStr = str(euiHex)
+        euiStr = euiStr.rstrip('L')
+        address64 = ''
+        if '0x' in euiStr:
+            address64 = self.__lstrip0x(euiStr)
+            # prepend 0 at the beginning
+            if len(address64) < 16:
+                address64 = address64.zfill(16)
+                print(address64)
 
-            cmd = 'macfilter rss add-lqi %s %s' % (address64, str(LinkQuality))
-            print(cmd)
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setLinkQuality() Error: ' + str(e))
+        cmd = 'macfilter rss add-lqi %s %s' % (address64, str(LinkQuality))
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def setOutBoundLinkQuality(self, LinkQuality):
@@ -1698,45 +1542,32 @@
             True: successful to set the link quality
             False: fail to set the link quality
         """
-        print('%s call setOutBoundLinkQuality' % self)
-        print(LinkQuality)
-        try:
-            cmd = 'macfilter rss add-lqi * %s' % str(LinkQuality)
-            print(cmd)
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setOutBoundLinkQuality() Error: ' + str(e))
+        cmd = 'macfilter rss add-lqi * %s' % str(LinkQuality)
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def removeRouterPrefix(self, prefixEntry):
         """remove the configured prefix on a border router
 
         Args:
-            prefixEntry: a on-mesh prefix entry
+            prefixEntry: a on-mesh prefix entry in IPv6 dotted-quad format
 
         Returns:
             True: successful to remove the prefix entry from border router
             False: fail to remove the prefix entry from border router
         """
-        print('%s call removeRouterPrefix' % self)
-        print(prefixEntry)
-        prefix = self.__convertIp6PrefixStringToIp6Address(str(prefixEntry))
-        try:
-            prefixLen = 64
-            cmd = 'prefix remove %s/%d' % (prefix, prefixLen)
-            print(cmd)
-            if self.__executeCommand(cmd)[-1] == 'Done':
-                # send server data ntf to leader
-                return self.__executeCommand('netdata register')[-1] == 'Done'
-            else:
-                return False
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('removeRouterPrefix() Error: ' + str(e))
+        assert (ipaddress.IPv6Network(prefixEntry.decode()))
+        cmd = 'prefix remove %s/64' % prefixEntry
+        if self.__executeCommand(cmd)[-1] == 'Done':
+            # send server data ntf to leader
+            return self.__executeCommand('netdata register')[-1] == 'Done'
+        else:
+            return False
 
     @API
     def configBorderRouter(
         self,
-        P_Prefix=None,
+        P_Prefix="fd00:7d03:7d03:7d03::",
         P_stable=1,
         P_default=1,
         P_slaac_preferred=0,
@@ -1749,7 +1580,7 @@
         """configure the border router with a given prefix entry parameters
 
         Args:
-            P_Prefix: IPv6 prefix that is available on the Thread Network
+            P_Prefix: IPv6 prefix that is available on the Thread Network in IPv6 dotted-quad format
             P_stable: true if the default router is expected to be stable network data
             P_default: true if border router offers the default route for P_Prefix
             P_slaac_preferred: true if allowing auto-configure address using P_Prefix
@@ -1762,26 +1593,12 @@
             True: successful to configure the border router with a given prefix entry
             False: fail to configure the border router with a given prefix entry
         """
-        print('%s call configBorderRouter' % self)
-        assert TESTHARNESS_VERSION == TESTHARNESS_1_2 or P_dp == 0
+        assert (ipaddress.IPv6Network(P_Prefix.decode()))
 
         # turn off default domain prefix if configBorderRouter is called before joining network
-        if TESTHARNESS_VERSION == TESTHARNESS_1_2 and P_dp == 0 and not self.__isOpenThreadRunning():
+        if P_dp == 0 and not self.__isOpenThreadRunning():
             self.__useDefaultDomainPrefix = False
 
-        if TESTHARNESS_VERSION == TESTHARNESS_1_2:
-            # TestHarness 1.2 converts 0x2001000000000000 to "2001000000000000"
-            if P_Prefix is None:
-                P_Prefix = 0xfd007d037d037d03
-
-            P_Prefix = '%016x' % P_Prefix
-        else:
-            # TestHarness 1.1 converts 2001000000000000 to "2001000000000000" (it's wrong, but not fixed yet.)
-            P_Prefix = str(P_Prefix)
-            int(P_Prefix, 16)
-
-        prefix = self.__convertIp6PrefixStringToIp6Address(P_Prefix)
-        print(prefix)
         parameter = ''
         prf = ''
 
@@ -1817,8 +1634,7 @@
         else:
             pass
 
-        cmd = 'prefix add %s/64 %s %s' % (prefix, parameter, prf)
-        print(cmd)
+        cmd = 'prefix add %s/64 %s %s' % (P_Prefix, parameter, prf)
         if self.__executeCommand(cmd)[-1] == 'Done':
             # if prefix configured before starting OpenThread stack
             # do not send out server data ntf pro-actively
@@ -1830,6 +1646,30 @@
         else:
             return False
 
+    @watched
+    def getNetworkData(self):
+        lines = self.__executeCommand('netdata show')
+        prefixes, routes, services = [], [], []
+        classify = None
+
+        for line in lines:
+            if line == 'Prefixes:':
+                classify = prefixes
+            elif line == 'Routes:':
+                classify = routes
+            elif line == 'Services:':
+                classify = services
+            elif line == 'Done':
+                classify = None
+            else:
+                classify.append(line)
+
+        return {
+            'Prefixes': prefixes,
+            'Routes': routes,
+            'Services': services,
+        }
+
     @API
     def setNetworkIDTimeout(self, iNwkIDTimeOut):
         """set networkid timeout for Thread device
@@ -1841,37 +1681,23 @@
             True: successful to set NETWORK_ID_TIMEOUT
             False: fail to set NETWORK_ID_TIMEOUT
         """
-        print('%s call setNetworkIDTimeout' % self)
-        print(iNwkIDTimeOut)
         iNwkIDTimeOut /= 1000
-        try:
-            cmd = 'networkidtimeout %s' % str(iNwkIDTimeOut)
-            print(cmd)
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setNetworkIDTimeout() Error: ' + str(e))
+        cmd = 'networkidtimeout %s' % str(iNwkIDTimeOut)
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def setKeepAliveTimeOut(self, iTimeOut):
-        """set keep alive timeout for device
-           has been deprecated and also set SED polling rate
+        """set child timeout for device
 
         Args:
-            iTimeOut: data poll period for sleepy end device
+            iTimeOut: child timeout for device
 
         Returns:
-            True: successful to set the data poll period for SED
-            False: fail to set the data poll period for SED
+            True: successful to set the child timeout for device
+            False: fail to set the child timeout for device
         """
-        print('%s call setKeepAliveTimeOut' % self)
-        iTimeOut *= 1000
-        print(int(iTimeOut))
-        try:
-            cmd = 'pollperiod %d' % int(iTimeOut)
-            print(cmd)
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setKeepAliveTimeOut() Error: ' + str(e))
+        cmd = 'childtimeout %d' % iTimeOut
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def setKeySequenceCounter(self, iKeySequenceValue):
@@ -1884,25 +1710,19 @@
             True: successful to set the key sequence
             False: fail to set the key sequence
         """
-        print('%s call setKeySequenceCounter' % self)
-        print(iKeySequenceValue)
-        try:
-            # avoid key switch guard timer protection for reference device
-            self.__setKeySwitchGuardTime(0)
+        # avoid key switch guard timer protection for reference device
+        self.__setKeySwitchGuardTime(0)
 
-            cmd = 'keysequence counter %s' % str(iKeySequenceValue)
-            if self.__executeCommand(cmd)[-1] == 'Done':
-                self.sleep(1)
-                return True
-            else:
-                return False
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setKeySequenceCounter() Error; ' + str(e))
+        cmd = 'keysequence counter %s' % str(iKeySequenceValue)
+        if self.__executeCommand(cmd)[-1] == 'Done':
+            self.sleep(1)
+            return True
+        else:
+            return False
 
     @API
     def getKeySequenceCounter(self):
         """get current Thread Network key sequence"""
-        print('%s call getKeySequenceCounter' % self)
         keySequence = self.__executeCommand('keysequence counter')[0]
         return keySequence
 
@@ -1917,17 +1737,11 @@
             True: successful to increment the key sequence with a given value
             False: fail to increment the key sequence with a given value
         """
-        print('%s call incrementKeySequenceCounter' % self)
-        print(iIncrementValue)
-        try:
-            # avoid key switch guard timer protection for reference device
-            self.__setKeySwitchGuardTime(0)
-            currentKeySeq = self.getKeySequenceCounter()
-            keySequence = int(currentKeySeq, 10) + iIncrementValue
-            print(keySequence)
-            return self.setKeySequenceCounter(keySequence)
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('incrementKeySequenceCounter() Error: ' + str(e))
+        # avoid key switch guard timer protection for reference device
+        self.__setKeySwitchGuardTime(0)
+        currentKeySeq = self.getKeySequenceCounter()
+        keySequence = int(currentKeySeq, 10) + iIncrementValue
+        return self.setKeySequenceCounter(keySequence)
 
     @API
     def setNetworkDataRequirement(self, eDataRequirement):
@@ -1940,9 +1754,6 @@
         Returns:
             True: successful to set the network requirement
         """
-        print('%s call setNetworkDataRequirement' % self)
-        print(eDataRequirement)
-
         if eDataRequirement == Device_Data_Requirement.ALL_DATA:
             self.networkDataRequirement = 'n'
         return True
@@ -1952,7 +1763,7 @@
         """configure border router with a given external route prefix entry
 
         Args:
-            P_Prefix: IPv6 prefix for the route
+            P_Prefix: IPv6 prefix for the route in IPv6 dotted-quad format
             P_Stable: is true if the external route prefix is stable network data
             R_Preference: a two-bit signed integer indicating Router preference
                           1: high
@@ -1963,33 +1774,27 @@
             True: successful to configure the border router with a given external route prefix
             False: fail to configure the border router with a given external route prefix
         """
-        print('%s call configExternalRouter' % self)
-        print(P_Prefix)
+        assert (ipaddress.IPv6Network(P_Prefix.decode()))
         prf = ''
         stable = ''
-        prefix = self.__convertIp6PrefixStringToIp6Address(str(P_Prefix))
-        try:
-            if R_Preference == 1:
-                prf = 'high'
-            elif R_Preference == 0:
-                prf = 'med'
-            elif R_Preference == -1:
-                prf = 'low'
-            else:
-                pass
+        if R_Preference == 1:
+            prf = 'high'
+        elif R_Preference == 0:
+            prf = 'med'
+        elif R_Preference == -1:
+            prf = 'low'
+        else:
+            pass
 
-            if P_stable:
-                stable += 's'
-                cmd = 'route add %s/64 %s %s' % (prefix, stable, prf)
-            else:
-                cmd = 'route add %s/64 %s' % (prefix, prf)
-            print(cmd)
+        if P_stable:
+            stable += 's'
+            cmd = 'route add %s/64 %s %s' % (P_Prefix, stable, prf)
+        else:
+            cmd = 'route add %s/64 %s' % (P_Prefix, prf)
 
-            if self.__executeCommand(cmd)[-1] == 'Done':
-                # send server data ntf to leader
-                return self.__executeCommand('netdata register')[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('configExternalRouter() Error: ' + str(e))
+        if self.__executeCommand(cmd)[-1] == 'Done':
+            # send server data ntf to leader
+            return self.__executeCommand('netdata register')[-1] == 'Done'
 
     @API
     def getNeighbouringRouters(self):
@@ -1998,40 +1803,33 @@
         Returns:
             neighboring routers' extended address
         """
-        print('%s call getNeighbouringRouters' % self)
-        try:
-            routerInfo = []
-            routerList = self.__executeCommand('router list')[0].split()
-            print(routerList)
+        routerInfo = []
+        routerList = self.__executeCommand('router list')[0].split()
 
-            if 'Done' in routerList:
-                print('no neighbouring routers')
-                return None
+        if 'Done' in routerList:
+            return None
 
-            for index in routerList:
-                router = []
-                cmd = 'router %s' % index
-                router = self.__executeCommand(cmd)
+        for index in routerList:
+            router = []
+            cmd = 'router %s' % index
+            router = self.__executeCommand(cmd)
 
-                for line in router:
-                    if 'Done' in line:
-                        break
-                    # elif 'Rloc' in line:
-                    #    rloc16 = line.split()[1]
-                    elif 'Ext Addr' in line:
-                        eui = line.split()[2]
-                        routerInfo.append(int(eui, 16))
-                    # elif 'LQI In' in line:
-                    #    lqi_in = line.split()[1]
-                    # elif 'LQI Out' in line:
-                    #    lqi_out = line.split()[1]
-                    else:
-                        pass
+            for line in router:
+                if 'Done' in line:
+                    break
+                # elif 'Rloc' in line:
+                #    rloc16 = line.split()[1]
+                elif 'Ext Addr' in line:
+                    eui = line.split()[2]
+                    routerInfo.append(int(eui, 16))
+                # elif 'LQI In' in line:
+                #    lqi_in = line.split()[1]
+                # elif 'LQI Out' in line:
+                #    lqi_out = line.split()[1]
+                else:
+                    pass
 
-            print(routerInfo)
-            return routerInfo
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('getNeighbouringDevice() Error: ' + str(e))
+        return routerInfo
 
     @API
     def getChildrenInfo(self):
@@ -2042,49 +1840,40 @@
         """
         eui = None
         rloc16 = None
+        childrenInfoAll = []
+        childrenInfo = {'EUI': 0, 'Rloc16': 0, 'MLEID': ''}
+        childrenList = self.__executeCommand('child list')[0].split()
 
-        print('%s call getChildrenInfo' % self)
+        if 'Done' in childrenList:
+            return None
 
-        try:
-            childrenInfoAll = []
-            childrenInfo = {'EUI': 0, 'Rloc16': 0, 'MLEID': ''}
-            childrenList = self.__executeCommand('child list')[0].split()
-            print(childrenList)
+        for index in childrenList:
+            cmd = 'child %s' % index
+            child = []
+            child = self.__executeCommand(cmd)
 
-            if 'Done' in childrenList:
-                print('no children')
-                return None
+            for line in child:
+                if 'Done' in line:
+                    break
+                elif 'Rloc' in line:
+                    rloc16 = line.split()[1]
+                elif 'Ext Addr' in line:
+                    eui = line.split()[2]
+                # elif 'Child ID' in line:
+                #    child_id = line.split()[2]
+                # elif 'Mode' in line:
+                #    mode = line.split()[1]
+                else:
+                    pass
 
-            for index in childrenList:
-                cmd = 'child %s' % index
-                child = []
-                child = self.__executeCommand(cmd)
+            childrenInfo['EUI'] = int(eui, 16)
+            childrenInfo['Rloc16'] = int(rloc16, 16)
+            # children_info['MLEID'] = self.getMLEID()
 
-                for line in child:
-                    if 'Done' in line:
-                        break
-                    elif 'Rloc' in line:
-                        rloc16 = line.split()[1]
-                    elif 'Ext Addr' in line:
-                        eui = line.split()[2]
-                    # elif 'Child ID' in line:
-                    #    child_id = line.split()[2]
-                    # elif 'Mode' in line:
-                    #    mode = line.split()[1]
-                    else:
-                        pass
+            childrenInfoAll.append(childrenInfo['EUI'])
+            # childrenInfoAll.append(childrenInfo)
 
-                childrenInfo['EUI'] = int(eui, 16)
-                childrenInfo['Rloc16'] = int(rloc16, 16)
-                # children_info['MLEID'] = self.getMLEID()
-
-                childrenInfoAll.append(childrenInfo['EUI'])
-                # childrenInfoAll.append(childrenInfo)
-
-            print(childrenInfoAll)
-            return childrenInfoAll
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('getChildrenInfo() Error: ' + str(e))
+        return childrenInfoAll
 
     @API
     def setXpanId(self, xPanId):
@@ -2098,23 +1887,18 @@
             False: fail to set the extended PAN ID
         """
         xpanid = ''
-        print('%s call setXpanId' % self)
-        print(xPanId)
-        try:
-            if not isinstance(xPanId, str):
-                xpanid = self.__convertLongToHex(xPanId, 16)
-                cmd = 'extpanid %s' % xpanid
-                datasetCmd = 'dataset extpanid %s' % xpanid
-            else:
-                xpanid = xPanId
-                cmd = 'extpanid %s' % xpanid
-                datasetCmd = 'dataset extpanid %s' % xpanid
+        if not isinstance(xPanId, str):
+            xpanid = self.__convertLongToHex(xPanId, 16)
+            cmd = 'extpanid %s' % xpanid
+            datasetCmd = 'dataset extpanid %s' % xpanid
+        else:
+            xpanid = xPanId
+            cmd = 'extpanid %s' % xpanid
+            datasetCmd = 'dataset extpanid %s' % xpanid
 
-            self.xpanId = xpanid
-            self.hasActiveDatasetToCommit = True
-            return self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setXpanId() Error: ' + str(e))
+        self.xpanId = xpanid
+        self.hasActiveDatasetToCommit = True
+        return self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done'
 
     @API
     def getNeighbouringDevices(self):
@@ -2125,7 +1909,6 @@
             A list including extended address of neighboring routers, parent
             as well as children
         """
-        print('%s call getNeighbouringDevices' % self)
         neighbourList = []
 
         # get parent info
@@ -2145,7 +1928,6 @@
             for entry in routerNeighbours:
                 neighbourList.append(entry)
 
-        print(neighbourList)
         return neighbourList
 
     @API
@@ -2159,11 +1941,7 @@
             True: successful to set the Partition ID
             False: fail to set the Partition ID
         """
-        print('%s call setPartationId' % self)
-        print(partationId)
-
         cmd = 'partitionid preferred %s' % (str(hex(partationId)).rstrip('L'))
-        print(cmd)
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
@@ -2188,38 +1966,29 @@
         else:
             for fullIp in globalAddrs:
                 if fullIp.startswith(filterByPrefix):
-                    print('target global %s' % fullIp)
                     return fullIp
-            print('no global address matched')
             return str(globalAddrs[0])
 
     @API
     def getShortAddress(self):
         """get Rloc16 short address of Thread device"""
-        print('%s call getShortAddress' % self)
         return self.getRloc16()
 
     @API
     def getULA64(self):
         """get mesh local EID of Thread device"""
-        print('%s call getULA64' % self)
         return self.__executeCommand('ipaddr mleid')[0]
 
     @API
     def setMLPrefix(self, sMeshLocalPrefix):
         """set mesh local prefix"""
-        print('%s call setMLPrefix' % self)
-        try:
-            cmd = 'dataset meshlocalprefix %s' % sMeshLocalPrefix
-            self.hasActiveDatasetToCommit = True
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setMLPrefix() Error: ' + str(e))
+        cmd = 'dataset meshlocalprefix %s' % sMeshLocalPrefix
+        self.hasActiveDatasetToCommit = True
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def getML16(self):
         """get mesh local 16 unicast address (Rloc)"""
-        print('%s call getML16' % self)
         return self.getRloc()
 
     @API
@@ -2241,14 +2010,8 @@
             True: successful to set slaac address to Thread interface
             False: fail to set slaac address to Thread interface
         """
-        print('%s call forceSetSlaac' % self)
-        print(slaacAddress)
-        try:
-            cmd = 'ipaddr add %s' % str(slaacAddress)
-            print(cmd)
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('forceSetSlaac() Error: ' + str(e))
+        cmd = 'ipaddr add %s' % str(slaacAddress)
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def setSleepyNodePollTime(self):
@@ -2257,13 +2020,11 @@
     @API
     def enableAutoDUTObjectFlag(self):
         """set AutoDUTenable flag"""
-        print('%s call enableAutoDUTObjectFlag' % self)
         self.AutoDUTEnable = True
 
     @API
     def getChildTimeoutValue(self):
         """get child timeout"""
-        print('%s call getChildTimeoutValue' % self)
         childTimeout = self.__executeCommand('childtimeout')[0]
         return int(childTimeout)
 
@@ -2279,7 +2040,6 @@
             strDestinationAddr,
             ' '.join([str(tlv) for tlv in listTLV_ids]),
         )
-        print(cmd)
 
         return self.__sendCommand(cmd, expectEcho=False)
 
@@ -2295,7 +2055,6 @@
             strDestinationAddr,
             ' '.join([str(tlv) for tlv in listTLV_ids]),
         )
-        print(cmd)
 
         return self.__executeCommand(cmd)
 
@@ -2308,17 +2067,11 @@
         # TODO: Support the whole Native Commissioner functionality
         # Currently it only aims to trigger a Discovery Request message to pass
         # Certification test 5.8.4
-        print('%s call startNativeCommissioner' % self)
         self.__executeCommand('ifconfig up')
         cmd = 'joiner start %s' % (strPSKc)
-        print(cmd)
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
-    def getBorderAgentPort(self):
-        return int(self.__executeCommand('ba port')[0])
-
-    @API
     def startExternalCommissioner(self, baAddr, baPort):
         """Start external commissioner
         Args:
@@ -2349,7 +2102,6 @@
         Returns:
             A boolean indicates whether this function succeed.
         """
-
         if self.externalCommissioner is not None:
             self.externalCommissioner.stop()
             return not self.externalCommissioner.isActive()
@@ -2362,13 +2114,11 @@
             True: successful to start Commissioner
             False: fail to start Commissioner
         """
-        print('%s call startCollapsedCommissioner' % self)
         if self.__startOpenThread():
             self.wait_for_attach_to_the_network(expected_role=self.deviceRole,
                                                 timeout=self.NETWORK_ATTACHMENT_TIMEOUT,
                                                 raise_assert=True)
             cmd = 'commissioner start'
-            print(cmd)
             if self.__executeCommand(cmd)[-1] == 'Done':
                 self.isActiveCommissioner = True
                 self.sleep(20)  # time for petition process
@@ -2409,7 +2159,6 @@
             str(timeout),
         )
 
-        print(cmd)
         if self.__executeCommand(cmd)[-1] == 'Done':
             if self.logThreadStatus == self.logStatus['stop']:
                 self.logThread = ThreadRunner.run(target=self.__readCommissioningLogs, args=(120,))
@@ -2432,7 +2181,6 @@
             True: successful to set provisioning Url
             False: fail to set provisioning Url
         """
-        print('%s call setProvisioningUrl' % self)
         self.provisioningUrl = strURL
         if self.deviceRole == Thread_Device_Role.Commissioner:
             cmd = 'commissioner provisioningurl %s' % (strURL)
@@ -2447,19 +2195,14 @@
             True: successful to start commissioner candidate petition process
             False: fail to start commissioner candidate petition process
         """
-        print('%s call allowCommission' % self)
-        try:
-            cmd = 'commissioner start'
-            print(cmd)
-            if self.__executeCommand(cmd)[-1] == 'Done':
-                self.isActiveCommissioner = True
-                # time for petition process and at least one keep alive
-                self.sleep(3)
-                return True
-            else:
-                return False
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('allowcommission() error: ' + str(e))
+        cmd = 'commissioner start'
+        if self.__executeCommand(cmd)[-1] == 'Done':
+            self.isActiveCommissioner = True
+            # time for petition process and at least one keep alive
+            self.sleep(3)
+            return True
+        else:
+            return False
 
     @API
     def joinCommissioned(self, strPSKd='THREADJPAKETEST', waitTime=20):
@@ -2473,10 +2216,16 @@
             False: fail to start joiner
         """
         self.log("joinCommissioned on channel %s", self.getChannel())
+
+        if self.deviceRole in [
+                Thread_Device_Role.Leader,
+                Thread_Device_Role.Router,
+                Thread_Device_Role.REED,
+        ]:
+            self.__setRouterSelectionJitter(1)
         self.__executeCommand('ifconfig up')
         strPSKd = self.__normalizePSKd(strPSKd)
         cmd = 'joiner start %s %s' % (strPSKd, self.provisioningUrl)
-        print(cmd)
         if self.__executeCommand(cmd)[-1] == 'Done':
             maxDuration = 150  # seconds
             self.joinCommissionedStatus = self.joinStatus['ongoing']
@@ -2493,8 +2242,11 @@
 
                 self.sleep(1)
 
+            self.setMAC(self.mac)
             self.__executeCommand('thread start')
-            self.sleep(30)
+            self.wait_for_attach_to_the_network(expected_role=self.deviceRole,
+                                                timeout=self.NETWORK_ATTACHMENT_TIMEOUT,
+                                                raise_assert=True)
             return True
         else:
             return False
@@ -2509,16 +2261,15 @@
         rawLogs = self.logThread.get()
         ProcessedLogs = []
         payload = []
+
         while not rawLogs.empty():
             rawLogEach = rawLogs.get()
-            print(rawLogEach)
             if '[THCI]' not in rawLogEach:
                 continue
 
             EncryptedPacket = PlatformDiagnosticPacket()
             infoList = rawLogEach.split('[THCI]')[1].split(']')[0].split('|')
             for eachInfo in infoList:
-                print(eachInfo)
                 info = eachInfo.split('=')
                 infoType = info[0].strip()
                 infoValue = info[1].strip()
@@ -2577,20 +2328,15 @@
             True: successful to send MGMT_ED_SCAN message.
             False: fail to send MGMT_ED_SCAN message
         """
-        print('%s call MGMT_ED_SCAN' % self)
         channelMask = '0x' + self.__convertLongToHex(self.__convertChannelMask(listChannelMask))
-        try:
-            cmd = 'commissioner energy %s %s %s %s %s' % (
-                channelMask,
-                xCount,
-                xPeriod,
-                xScanDuration,
-                sAddr,
-            )
-            print(cmd)
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('MGMT_ED_SCAN() error: ' + str(e))
+        cmd = 'commissioner energy %s %s %s %s %s' % (
+            channelMask,
+            xCount,
+            xPeriod,
+            xScanDuration,
+            sAddr,
+        )
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def MGMT_PANID_QUERY(self, sAddr, xCommissionerSessionId, listChannelMask, xPanId):
@@ -2603,19 +2349,14 @@
             True: successful to send MGMT_PANID_QUERY message.
             False: fail to send MGMT_PANID_QUERY message.
         """
-        print('%s call MGMT_PANID_QUERY' % self)
         panid = ''
         channelMask = '0x' + self.__convertLongToHex(self.__convertChannelMask(listChannelMask))
 
         if not isinstance(xPanId, str):
             panid = str(hex(xPanId))
 
-        try:
-            cmd = 'commissioner panid %s %s %s' % (panid, channelMask, sAddr)
-            print(cmd)
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('MGMT_PANID_QUERY() error: ' + str(e))
+        cmd = 'commissioner panid %s %s %s' % (panid, channelMask, sAddr)
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def MGMT_ANNOUNCE_BEGIN(self, sAddr, xCommissionerSessionId, listChannelMask, xCount, xPeriod):
@@ -2625,19 +2366,14 @@
             True: successful to send MGMT_ANNOUNCE_BEGIN message.
             False: fail to send MGMT_ANNOUNCE_BEGIN message.
         """
-        print('%s call MGMT_ANNOUNCE_BEGIN' % self)
         channelMask = '0x' + self.__convertLongToHex(self.__convertChannelMask(listChannelMask))
-        try:
-            cmd = 'commissioner announce %s %s %s %s' % (
-                channelMask,
-                xCount,
-                xPeriod,
-                sAddr,
-            )
-            print(cmd)
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('MGMT_ANNOUNCE_BEGIN() error: ' + str(e))
+        cmd = 'commissioner announce %s %s %s %s' % (
+            channelMask,
+            xCount,
+            xPeriod,
+            sAddr,
+        )
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def MGMT_ACTIVE_GET(self, Addr='', TLVs=()):
@@ -2647,25 +2383,18 @@
             True: successful to send MGMT_ACTIVE_GET
             False: fail to send MGMT_ACTIVE_GET
         """
-        print('%s call MGMT_ACTIVE_GET' % self)
-        try:
-            cmd = 'dataset mgmtgetcommand active'
+        cmd = 'dataset mgmtgetcommand active'
 
-            if Addr != '':
-                cmd += ' address '
-                cmd += Addr
+        if Addr != '':
+            cmd += ' address '
+            cmd += Addr
 
-            if len(TLVs) != 0:
-                tlvs = ''.join('%02x' % tlv for tlv in TLVs)
-                cmd += ' -x '
-                cmd += tlvs
+        if len(TLVs) != 0:
+            tlvs = ''.join('%02x' % tlv for tlv in TLVs)
+            cmd += ' -x '
+            cmd += tlvs
 
-            print(cmd)
-
-            return self.__executeCommand(cmd)[-1] == 'Done'
-
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('MGMT_ACTIVE_GET() Error: ' + str(e))
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def MGMT_ACTIVE_SET(
@@ -2694,135 +2423,140 @@
             True: successful to send MGMT_ACTIVE_SET
             False: fail to send MGMT_ACTIVE_SET
         """
-        print('%s call MGMT_ACTIVE_SET' % self)
-        try:
-            cmd = 'dataset mgmtsetcommand active'
+        cmd = 'dataset mgmtsetcommand active'
 
-            if listActiveTimestamp is not None:
-                cmd += ' activetimestamp '
-                cmd += str(listActiveTimestamp[0])
+        if listActiveTimestamp is not None:
+            cmd += ' activetimestamp '
+            cmd += str(listActiveTimestamp[0])
 
-            if xExtendedPanId is not None:
-                cmd += ' extpanid '
-                xpanid = self.__convertLongToHex(xExtendedPanId, 16)
+        if xExtendedPanId is not None:
+            cmd += ' extpanid '
+            xpanid = self.__convertLongToHex(xExtendedPanId, 16)
 
-                cmd += xpanid
+            cmd += xpanid
 
-            if sNetworkName is not None:
-                cmd += ' networkname '
-                cmd += self._deviceEscapeEscapable(str(sNetworkName))
+        if sNetworkName is not None:
+            cmd += ' networkname '
+            cmd += self._deviceEscapeEscapable(str(sNetworkName))
 
-            if xChannel is not None:
-                cmd += ' channel '
-                cmd += str(xChannel)
+        if xChannel is not None:
+            cmd += ' channel '
+            cmd += str(xChannel)
 
-            if sMeshLocalPrefix is not None:
-                cmd += ' localprefix '
-                cmd += str(sMeshLocalPrefix)
+        if sMeshLocalPrefix is not None:
+            cmd += ' localprefix '
+            cmd += str(sMeshLocalPrefix)
 
-            if xMasterKey is not None:
-                cmd += ' networkkey '
-                key = self.__convertLongToHex(xMasterKey, 32)
+        if xMasterKey is not None:
+            cmd += ' networkkey '
+            key = self.__convertLongToHex(xMasterKey, 32)
 
-                cmd += key
+            cmd += key
 
-            if xPanId is not None:
-                cmd += ' panid '
-                cmd += str(xPanId)
+        if xPanId is not None:
+            cmd += ' panid '
+            cmd += str(xPanId)
 
-            if listChannelMask is not None:
-                cmd += ' channelmask '
-                cmd += '0x' + self.__convertLongToHex(self.__convertChannelMask(listChannelMask))
+        if listChannelMask is not None:
+            cmd += ' channelmask '
+            cmd += '0x' + self.__convertLongToHex(self.__convertChannelMask(listChannelMask))
 
-            if (sPSKc is not None or listSecurityPolicy is not None or xCommissioningSessionId is not None or
-                    xTmfPort is not None or xSteeringData is not None or xBorderRouterLocator is not None or
-                    BogusTLV is not None):
-                cmd += ' -x '
+        if (sPSKc is not None or listSecurityPolicy is not None or xCommissioningSessionId is not None or
+                xTmfPort is not None or xSteeringData is not None or xBorderRouterLocator is not None or
+                BogusTLV is not None):
+            cmd += ' -x '
 
-            if sPSKc is not None:
-                cmd += '0410'
-                stretchedPskc = Thread_PBKDF2.get(
-                    sPSKc,
-                    ModuleHelper.Default_XpanId,
-                    ModuleHelper.Default_NwkName,
-                )
-                pskc = '%x' % stretchedPskc
+        if sPSKc is not None:
+            cmd += '0410'
+            stretchedPskc = Thread_PBKDF2.get(
+                sPSKc,
+                ModuleHelper.Default_XpanId,
+                ModuleHelper.Default_NwkName,
+            )
+            pskc = '%x' % stretchedPskc
 
-                if len(pskc) < 32:
-                    pskc = pskc.zfill(32)
+            if len(pskc) < 32:
+                pskc = pskc.zfill(32)
 
-                cmd += pskc
+            cmd += pskc
 
-            if listSecurityPolicy is not None:
+        if listSecurityPolicy is not None:
+            if self.DeviceCapability == DevCapb.V1_1:
                 cmd += '0c03'
+            else:
+                cmd += '0c04'
 
-                rotationTime = 0
-                policyBits = 0
+            rotationTime = 0
+            policyBits = 0
 
-                # previous passing way listSecurityPolicy=[True, True, 3600,
-                # False, False, True]
-                if len(listSecurityPolicy) == 6:
-                    rotationTime = listSecurityPolicy[2]
+            # previous passing way listSecurityPolicy=[True, True, 3600,
+            # False, False, True]
+            if len(listSecurityPolicy) == 6:
+                rotationTime = listSecurityPolicy[2]
 
-                    # the last three reserved bits must be 1
-                    policyBits = 0b00000111
+                # the last three reserved bits must be 1
+                policyBits = 0b00000111
 
-                    if listSecurityPolicy[0]:
-                        policyBits = policyBits | 0b10000000
-                    if listSecurityPolicy[1]:
-                        policyBits = policyBits | 0b01000000
-                    if listSecurityPolicy[3]:
-                        policyBits = policyBits | 0b00100000
-                    if listSecurityPolicy[4]:
-                        policyBits = policyBits | 0b00010000
-                    if listSecurityPolicy[5]:
-                        policyBits = policyBits | 0b00001000
+                if listSecurityPolicy[0]:
+                    policyBits = policyBits | 0b10000000
+                if listSecurityPolicy[1]:
+                    policyBits = policyBits | 0b01000000
+                if listSecurityPolicy[3]:
+                    policyBits = policyBits | 0b00100000
+                if listSecurityPolicy[4]:
+                    policyBits = policyBits | 0b00010000
+                if listSecurityPolicy[5]:
+                    policyBits = policyBits | 0b00001000
+            else:
+                # new passing way listSecurityPolicy=[3600, 0b11001111]
+                rotationTime = listSecurityPolicy[0]
+                # bit order
+                if len(listSecurityPolicy) > 2:
+                    policyBits = listSecurityPolicy[2] << 8 | listSecurityPolicy[1]
                 else:
-                    # new passing way listSecurityPolicy=[3600, 0b11001111]
-                    rotationTime = listSecurityPolicy[0]
                     policyBits = listSecurityPolicy[1]
 
-                policy = str(hex(rotationTime))[2:]
+            policy = str(hex(rotationTime))[2:]
 
-                if len(policy) < 4:
-                    policy = policy.zfill(4)
+            if len(policy) < 4:
+                policy = policy.zfill(4)
 
-                cmd += policy
+            cmd += policy
 
-                cmd += str(hex(policyBits))[2:]
+            flags0 = ('%x' % (policyBits & 0x00ff)).ljust(2, '0')
+            cmd += flags0
 
-            if xCommissioningSessionId is not None:
-                cmd += '0b02'
-                sessionid = str(hex(xCommissioningSessionId))[2:]
+            if self.DeviceCapability != DevCapb.V1_1:
+                flags1 = ('%x' % ((policyBits & 0xff00) >> 8)).ljust(2, '0')
+                cmd += flags1
 
-                if len(sessionid) < 4:
-                    sessionid = sessionid.zfill(4)
+        if xCommissioningSessionId is not None:
+            cmd += '0b02'
+            sessionid = str(hex(xCommissioningSessionId))[2:]
 
-                cmd += sessionid
+            if len(sessionid) < 4:
+                sessionid = sessionid.zfill(4)
 
-            if xBorderRouterLocator is not None:
-                cmd += '0902'
-                locator = str(hex(xBorderRouterLocator))[2:]
+            cmd += sessionid
 
-                if len(locator) < 4:
-                    locator = locator.zfill(4)
+        if xBorderRouterLocator is not None:
+            cmd += '0902'
+            locator = str(hex(xBorderRouterLocator))[2:]
 
-                cmd += locator
+            if len(locator) < 4:
+                locator = locator.zfill(4)
 
-            if xSteeringData is not None:
-                steeringData = self.__convertLongToHex(xSteeringData)
-                cmd += '08' + str(len(steeringData) / 2).zfill(2)
-                cmd += steeringData
+            cmd += locator
 
-            if BogusTLV is not None:
-                cmd += '8202aa55'
+        if xSteeringData is not None:
+            steeringData = self.__convertLongToHex(xSteeringData)
+            cmd += '08' + str(len(steeringData) / 2).zfill(2)
+            cmd += steeringData
 
-            print(cmd)
+        if BogusTLV is not None:
+            cmd += '8202aa55'
 
-            return self.__executeCommand(cmd)[-1] == 'Done'
-
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('MGMT_ACTIVE_SET() Error: ' + str(e))
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def MGMT_PENDING_GET(self, Addr='', TLVs=()):
@@ -2832,25 +2566,18 @@
             True: successful to send MGMT_PENDING_GET
             False: fail to send MGMT_PENDING_GET
         """
-        print('%s call MGMT_PENDING_GET' % self)
-        try:
-            cmd = 'dataset mgmtgetcommand pending'
+        cmd = 'dataset mgmtgetcommand pending'
 
-            if Addr != '':
-                cmd += ' address '
-                cmd += Addr
+        if Addr != '':
+            cmd += ' address '
+            cmd += Addr
 
-            if len(TLVs) != 0:
-                tlvs = ''.join('%02x' % tlv for tlv in TLVs)
-                cmd += ' -x '
-                cmd += tlvs
+        if len(TLVs) != 0:
+            tlvs = ''.join('%02x' % tlv for tlv in TLVs)
+            cmd += ' -x '
+            cmd += tlvs
 
-            print(cmd)
-
-            return self.__executeCommand(cmd)[-1] == 'Done'
-
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('MGMT_PENDING_GET() Error: ' + str(e))
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def MGMT_PENDING_SET(
@@ -2872,61 +2599,54 @@
             True: successful to send MGMT_PENDING_SET
             False: fail to send MGMT_PENDING_SET
         """
-        print('%s call MGMT_PENDING_SET' % self)
-        try:
-            cmd = 'dataset mgmtsetcommand pending'
+        cmd = 'dataset mgmtsetcommand pending'
 
-            if listPendingTimestamp is not None:
-                cmd += ' pendingtimestamp '
-                cmd += str(listPendingTimestamp[0])
+        if listPendingTimestamp is not None:
+            cmd += ' pendingtimestamp '
+            cmd += str(listPendingTimestamp[0])
 
-            if listActiveTimestamp is not None:
-                cmd += ' activetimestamp '
-                cmd += str(listActiveTimestamp[0])
+        if listActiveTimestamp is not None:
+            cmd += ' activetimestamp '
+            cmd += str(listActiveTimestamp[0])
 
-            if xDelayTimer is not None:
-                cmd += ' delaytimer '
-                cmd += str(xDelayTimer)
-                # cmd += ' delaytimer 3000000'
+        if xDelayTimer is not None:
+            cmd += ' delaytimer '
+            cmd += str(xDelayTimer)
+            # cmd += ' delaytimer 3000000'
 
-            if xChannel is not None:
-                cmd += ' channel '
-                cmd += str(xChannel)
+        if xChannel is not None:
+            cmd += ' channel '
+            cmd += str(xChannel)
 
-            if xPanId is not None:
-                cmd += ' panid '
-                cmd += str(xPanId)
+        if xPanId is not None:
+            cmd += ' panid '
+            cmd += str(xPanId)
 
-            if xMasterKey is not None:
-                cmd += ' networkkey '
-                key = self.__convertLongToHex(xMasterKey, 32)
+        if xMasterKey is not None:
+            cmd += ' networkkey '
+            key = self.__convertLongToHex(xMasterKey, 32)
 
-                cmd += key
+            cmd += key
 
-            if sMeshLocalPrefix is not None:
-                cmd += ' localprefix '
-                cmd += str(sMeshLocalPrefix)
+        if sMeshLocalPrefix is not None:
+            cmd += ' localprefix '
+            cmd += str(sMeshLocalPrefix)
 
-            if sNetworkName is not None:
-                cmd += ' networkname '
-                cmd += self._deviceEscapeEscapable(str(sNetworkName))
+        if sNetworkName is not None:
+            cmd += ' networkname '
+            cmd += self._deviceEscapeEscapable(str(sNetworkName))
 
-            if xCommissionerSessionId is not None:
-                cmd += ' -x '
-                cmd += '0b02'
-                sessionid = str(hex(xCommissionerSessionId))[2:]
+        if xCommissionerSessionId is not None:
+            cmd += ' -x '
+            cmd += '0b02'
+            sessionid = str(hex(xCommissionerSessionId))[2:]
 
-                if len(sessionid) < 4:
-                    sessionid = sessionid.zfill(4)
+            if len(sessionid) < 4:
+                sessionid = sessionid.zfill(4)
 
-                cmd += sessionid
+            cmd += sessionid
 
-            print(cmd)
-
-            return self.__executeCommand(cmd)[-1] == 'Done'
-
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('MGMT_PENDING_SET() Error: ' + str(e))
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def MGMT_COMM_GET(self, Addr='ff02::1', TLVs=()):
@@ -2936,21 +2656,14 @@
             True: successful to send MGMT_COMM_GET
             False: fail to send MGMT_COMM_GET
         """
-        print('%s call MGMT_COMM_GET' % self)
-        try:
-            cmd = 'commissioner mgmtget'
+        cmd = 'commissioner mgmtget'
 
-            if len(TLVs) != 0:
-                tlvs = ''.join('%02x' % tlv for tlv in TLVs)
-                cmd += ' -x '
-                cmd += tlvs
+        if len(TLVs) != 0:
+            tlvs = ''.join('%02x' % tlv for tlv in TLVs)
+            cmd += ' -x '
+            cmd += tlvs
 
-            print(cmd)
-
-            return self.__executeCommand(cmd)[-1] == 'Done'
-
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('MGMT_COMM_GET() Error: ' + str(e))
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def MGMT_COMM_SET(
@@ -2968,69 +2681,56 @@
             True: successful to send MGMT_COMM_SET
             False: fail to send MGMT_COMM_SET
         """
-        print('%s call MGMT_COMM_SET' % self)
-        try:
-            cmd = 'commissioner mgmtset'
+        cmd = 'commissioner mgmtset'
 
-            if xCommissionerSessionID is not None:
-                # use assigned session id
+        if xCommissionerSessionID is not None:
+            # use assigned session id
+            cmd += ' sessionid '
+            cmd += str(xCommissionerSessionID)
+        elif xCommissionerSessionID is None:
+            # use original session id
+            if self.isActiveCommissioner is True:
                 cmd += ' sessionid '
-                cmd += str(xCommissionerSessionID)
-            elif xCommissionerSessionID is None:
-                # use original session id
-                if self.isActiveCommissioner is True:
-                    cmd += ' sessionid '
-                    cmd += self.__getCommissionerSessionId()
-                else:
-                    pass
+                cmd += self.__getCommissionerSessionId()
+            else:
+                pass
 
-            if xSteeringData is not None:
-                cmd += ' steeringdata '
-                cmd += str(hex(xSteeringData)[2:])
+        if xSteeringData is not None:
+            cmd += ' steeringdata '
+            cmd += str(hex(xSteeringData)[2:])
 
-            if xBorderRouterLocator is not None:
-                cmd += ' locator '
-                cmd += str(hex(xBorderRouterLocator))
+        if xBorderRouterLocator is not None:
+            cmd += ' locator '
+            cmd += str(hex(xBorderRouterLocator))
 
-            if xChannelTlv is not None:
-                cmd += ' -x '
-                cmd += '000300' + '%04x' % xChannelTlv
+        if xChannelTlv is not None:
+            cmd += ' -x '
+            cmd += '000300' + '%04x' % xChannelTlv
 
-            print(cmd)
-
-            return self.__executeCommand(cmd)[-1] == 'Done'
-
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('MGMT_COMM_SET() Error: ' + str(e))
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def setActiveDataset(self, listActiveDataset=()):
-        print('%s call setActiveDataset' % self)
+        # Unused by the scripts
+        pass
 
     @API
     def setCommisionerMode(self):
-        print('%s call setCommissionerMode' % self)
+        # Unused by the scripts
+        pass
 
     @API
     def setPSKc(self, strPSKc):
-        print('%s call setPSKc' % self)
-        try:
-            cmd = 'dataset pskc %s' % strPSKc
-            self.hasActiveDatasetToCommit = True
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setPSKc() Error: ' + str(e))
+        cmd = 'dataset pskc %s' % strPSKc
+        self.hasActiveDatasetToCommit = True
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def setActiveTimestamp(self, xActiveTimestamp):
-        print('%s call setActiveTimestamp' % self)
-        try:
-            self.activetimestamp = xActiveTimestamp
-            cmd = 'dataset activetimestamp %s' % str(xActiveTimestamp)
-            self.hasActiveDatasetToCommit = True
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('setActiveTimestamp() Error: ' + str(e))
+        self.activetimestamp = xActiveTimestamp
+        self.hasActiveDatasetToCommit = True
+        cmd = 'dataset activetimestamp %s' % str(xActiveTimestamp)
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def setUdpJoinerPort(self, portNumber):
@@ -3043,9 +2743,7 @@
             True: successful to set Joiner UDP Port
             False: fail to set Joiner UDP Port
         """
-        print('%s call setUdpJoinerPort' % self)
         cmd = 'joinerport %d' % portNumber
-        print(cmd)
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
@@ -3056,16 +2754,12 @@
             True: successful to stop commissioner
             False: fail to stop commissioner
         """
-        print('%s call commissionerUnregister' % self)
         cmd = 'commissioner stop'
-        print(cmd)
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def sendBeacons(self, sAddr, xCommissionerSessionId, listChannelMask, xPanId):
-        print('%s call sendBeacons' % self)
         self.__sendCommand('scan', expectEcho=False)
-        return True
 
     @API
     def updateRouterStatus(self):
@@ -3074,7 +2768,6 @@
 
     @API
     def __updateRouterStatus(self):
-        print('%s call updateRouterStatus' % self)
         cmd = 'state'
         while True:
             state = self.__executeCommand(cmd)[0]
@@ -3090,21 +2783,26 @@
 
     @API
     def setRouterThresholdValues(self, upgradeThreshold, downgradeThreshold):
-        print('%s call setRouterThresholdValues' % self)
         self.__setRouterUpgradeThreshold(upgradeThreshold)
         self.__setRouterDowngradeThreshold(downgradeThreshold)
 
     @API
     def setMinDelayTimer(self, iSeconds):
-        print('%s call setMinDelayTimer' % self)
         cmd = 'delaytimermin %s' % iSeconds
-        print(cmd)
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def ValidateDeviceFirmware(self):
-        print('%s call ValidateDeviceFirmware' % self)
-        return 'OPENTHREAD' in self.UIStatusMsg
+        assert not self.IsBorderRouter, "Method not expected to be used with border router devices"
+
+        if self.DeviceCapability == OT11_CAPBS:
+            return OT11_VERSION in self.UIStatusMsg
+        elif self.DeviceCapability == OT12_CAPBS:
+            return OT12_VERSION in self.UIStatusMsg
+        elif self.DeviceCapability == OT13_CAPBS:
+            return OT13_VERSION in self.UIStatusMsg
+        else:
+            return False
 
     @API
     def setBbrDataset(self, SeqNumInc=False, SeqNum=None, MlrTimeout=None, ReRegDelay=None):
@@ -3123,10 +2821,22 @@
             False: fail to set BBR Dataset
         """
         assert not (SeqNumInc and SeqNum is not None), "Must not specify both SeqNumInc and SeqNum"
-        if SeqNumInc:
-            SeqNum = (self.bbrSeqNum + 1) % 256
 
-        return self.__configBbrDataset(SeqNum=SeqNum, MlrTimeout=MlrTimeout, ReRegDelay=ReRegDelay)
+        if (MlrTimeout and MlrTimeout != self.bbrMlrTimeout) or (ReRegDelay and ReRegDelay != self.bbrReRegDelay):
+            if SeqNum is None:
+                SeqNumInc = True
+
+        if SeqNumInc:
+            if self.bbrSeqNum in (126, 127):
+                self.bbrSeqNum = 0
+            elif self.bbrSeqNum in (254, 255):
+                self.bbrSeqNum = 128
+            else:
+                self.bbrSeqNum = (self.bbrSeqNum + 1) % 256
+        else:
+            self.bbrSeqNum = SeqNum
+
+        return self.__configBbrDataset(SeqNum=self.bbrSeqNum, MlrTimeout=MlrTimeout, ReRegDelay=ReRegDelay)
 
     def __configBbrDataset(self, SeqNum=None, MlrTimeout=None, ReRegDelay=None):
         if MlrTimeout is not None and ReRegDelay is None:
@@ -3157,16 +2867,13 @@
     # Low power THCI
     @API
     def setCSLtout(self, tout=30):
-        self.log('call setCSLtout')
-        cmd = 'csl timeout %u' % tout
-        print(cmd)
+        self.ssedTimeout = tout
+        cmd = 'csl timeout %u' % self.ssedTimeout
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def setCSLchannel(self, ch=11):
-        self.log('call setCSLchannel')
         cmd = 'csl channel %u' % ch
-        print(cmd)
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
@@ -3179,14 +2886,12 @@
         period is converted from unit ms to ten symbols (160us per 10 symbols).
 
         """
-        self.log('call setCSLperiod')
         cmd = 'csl period %u' % (period * 6.25)
-        print(cmd)
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     @staticmethod
-    def getForwardSeriesFlagsFromHexStr(flags):
-        hexFlags = int(flags, 16)
+    def getForwardSeriesFlagsFromHexOrStr(flags):
+        hexFlags = int(flags, 16) if isinstance(flags, str) else flags
         strFlags = ''
         if hexFlags == 0:
             strFlags = 'X'
@@ -3210,67 +2915,65 @@
             0x0a: 'm',
             0x0b: 'r',
         }
-        return metricsFlagMap.get(metrics, '?')
+        metricsReservedFlagMap = {0x11: 'q', 0x12: 'm', 0x13: 'r'}
+        if metricsFlagMap.get(metrics):
+            return metricsFlagMap.get(metrics), False
+        elif metricsReservedFlagMap.get(metrics):
+            return metricsReservedFlagMap.get(metrics), True
+        else:
+            logging.warning("Not found flag mapping for given metrics: {}".format(metrics))
+            return '', False
 
     @staticmethod
     def getMetricsFlagsFromHexStr(metrics):
+        strMetrics = ''
+        reserved_flag = ''
+
         if metrics.startswith('0x'):
             metrics = metrics[2:]
         hexMetricsArray = bytearray.fromhex(metrics)
 
-        strMetrics = ''
         for metric in hexMetricsArray:
-            strMetrics += OpenThreadTHCI.mapMetricsHexToChar(metric)
+            metric_flag, has_reserved_flag = OpenThreadTHCI.mapMetricsHexToChar(metric)
+            strMetrics += metric_flag
+            if has_reserved_flag:
+                reserved_flag = ' r'
 
-        return strMetrics
+        return strMetrics + reserved_flag
 
     @API
     def LinkMetricsSingleReq(self, dst_addr, metrics):
-        self.log('call LinkMetricsSingleReq')
         cmd = 'linkmetrics query %s single %s' % (dst_addr, self.getMetricsFlagsFromHexStr(metrics))
-        print(cmd)
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def LinkMetricsMgmtReq(self, dst_addr, type_, flags, metrics, series_id):
-        self.log('call LinkMetricsMgmtReq')
         cmd = 'linkmetrics mgmt %s ' % dst_addr
         if type_ == 'FWD':
-            cmd += 'forward %d %s' % (series_id, self.getForwardSeriesFlagsFromHexStr(flags))
+            cmd += 'forward %d %s' % (series_id, self.getForwardSeriesFlagsFromHexOrStr(flags))
             if flags != 0:
                 cmd += ' %s' % (self.getMetricsFlagsFromHexStr(metrics))
         elif type_ == 'ENH':
             cmd += 'enhanced-ack'
             if flags != 0:
-                cmd += ' register'
-                metricsFlags = self.getMetricsFlagsFromHexStr(metrics)
-                if '?' in metricsFlags:
-                    cmd += ' %s r' % metricsFlags.replace('?', '')
-                else:
-                    cmd += ' %s' % metricsFlags
+                cmd += ' register %s' % (self.getMetricsFlagsFromHexStr(metrics))
             else:
                 cmd += ' clear'
-        print(cmd)
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def LinkMetricsGetReport(self, dst_addr, series_id):
-        self.log('call LinkMetricsGetReport')
         cmd = 'linkmetrics query %s forward %d' % (dst_addr, series_id)
-        print(cmd)
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     # TODO: Series Id is not in this API.
     @API
     def LinkMetricsSendProbe(self, dst_addr, ack=True, size=0):
-        self.log('call LinkMetricsSendProbe')
         cmd = 'linkmetrics probe %s %d' % (dst_addr, size)
-        print(cmd)
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def setTxPower(self, level):
-        self.log('call setTxPower')
         cmd = 'txpower '
         if level == 'HIGH':
             cmd += '127'
@@ -3280,61 +2983,58 @@
             cmd += '-128'
         else:
             print('wrong Tx Power level')
-        print(cmd)
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def sendUdp(self, destination, port, payload='hello'):
-        self.log('call sendUdp')
         assert payload is not None, 'payload should not be none'
         cmd = 'udp send %s %d %s' % (destination, port, payload)
-        print(cmd)
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def send_udp(self, interface, destination, port, payload='12ABcd'):
         ''' payload hexstring
         '''
-        self.log('call send_udp')
         assert payload is not None, 'payload should not be none'
         assert interface == 0, "non-BR must send UDP to Thread interface"
         self.__udpOpen()
+        time.sleep(0.5)
         cmd = 'udp send %s %s -x %s' % (destination, port, payload)
-        print(cmd)
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     def __udpOpen(self):
         if not self.__isUdpOpened:
             cmd = 'udp open'
             self.__executeCommand(cmd)
+
+            # Bind to RLOC address and first dynamic port
+            rlocAddr = self.getRloc()
+
+            cmd = 'udp bind %s 49152' % rlocAddr
+            self.__executeCommand(cmd)
+
             self.__isUdpOpened = True
 
     @API
     def sendMACcmd(self, enh=False):
-        self.log('call sendMACcmd')
         cmd = 'mac send datarequest'
-        print(cmd)
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def sendMACdata(self, enh=False):
-        self.log('call sendMACdata')
         cmd = 'mac send emptydata'
-        print(cmd)
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def setCSLsuspension(self, suspend):
-        self.log('call setCSLsuspension')
         if suspend:
-            self.__setPollPeriod(1000000)
+            self.__setPollPeriod(240 * 1000)
         else:
-            self.__setPollPeriod(self.__sedPollPeriod)
+            self.__setPollPeriod(int(0.9 * self.ssedTimeout * 1000))
 
     @API
     def set_max_addrs_per_child(self, num):
-        cmd = 'childipmax %d' % int(num)
-        print(cmd)
+        cmd = 'childip max %d' % int(num)
         self.__executeCommand(cmd)
 
     @API
@@ -3358,7 +3058,7 @@
         return dua
 
     def __addDefaultDomainPrefix(self):
-        self.configBorderRouter(P_dp=1, P_slaac_preferred=1, P_stable=1, P_on_mesh=1, P_default=1)
+        self.configBorderRouter(P_dp=1, P_stable=1, P_on_mesh=1, P_default=1)
 
     def __setDUA(self, sDua):
         """specify the DUA before Thread Starts."""
@@ -3370,11 +3070,9 @@
 
     def __getMlIid(self):
         """get the Mesh Local IID."""
-        print('%s call __getMlIid' % self.port)
         # getULA64() would return the full string representation
         mleid = ModuleHelper.GetFullIpv6Address(self.getULA64()).lower()
         mliid = mleid[-19:].replace(':', '')
-        print('mliid: %s' % mliid)
         return mliid
 
     def __setMlIid(self, sMlIid):
@@ -3395,69 +3093,45 @@
     @API
     def setMLRtimeout(self, iMsecs):
         """Setup BBR MLR Timeout to `iMsecs` seconds."""
-        self.__configBbrDataset(MlrTimeout=iMsecs)
+        self.setBbrDataset(MlrTimeout=iMsecs)
 
     @API
     def stopListeningToAddr(self, sAddr):
-        print('%s call stopListeningToAddr' % self.port)
-
-        # convert to list for single element, for possible extension
-        # requirements.
-        if not isinstance(sAddr, list):
-            sAddr = [sAddr]
-
-        for addr in sAddr:
-            cmd = 'ipmaddr del ' + addr
-            try:
-                self.__executeCommand(cmd)
-            except CommandError as ex:
-                if ex.code == OT_ERROR_ALREADY:
-                    pass
-                else:
-                    raise
+        cmd = 'ipmaddr del ' + sAddr
+        try:
+            self.__executeCommand(cmd)
+        except CommandError as ex:
+            if ex.code == OT_ERROR_ALREADY:
+                pass
+            else:
+                raise
 
         return True
 
     @API
-    def registerMulticast(self, sAddr='ff04::1234:777a:1', timeout=MLR_TIMEOUT_MIN):
+    def registerMulticast(self, listAddr=('ff04::1234:777a:1',), timeout=MLR_TIMEOUT_MIN):
         """subscribe to the given ipv6 address (sAddr) in interface and send MLR.req OTA
 
         Args:
             sAddr   : str : Multicast address to be subscribed and notified OTA.
         """
-        # convert to list for single element, for possible extension
-        # requirements.
-        if not isinstance(sAddr, list):
-            sAddr = [sAddr]
+        for each_sAddr in listAddr:
+            self._beforeRegisterMulticast(each_sAddr, timeout)
 
-        if self.externalCommissioner is not None:
-            self.externalCommissioner.MLR(sAddr, timeout)
-            return True
+        sAddr = ' '.join(listAddr)
+        cmd = 'ipmaddr add ' + str(sAddr)
 
-        # subscribe address one by one
-        for addr in sAddr:
-            cmd = 'ipmaddr add ' + str(addr)
+        try:
+            self.__executeCommand(cmd)
+        except CommandError as ex:
+            if ex.code == OT_ERROR_ALREADY:
+                pass
+            else:
+                raise
 
-            try:
-                self.__executeCommand(cmd)
-            except CommandError as ex:
-                if ex.code == OT_ERROR_ALREADY:
-                    pass
-                else:
-                    raise
-
-    def deregisterMulticast(self, sAddr):
-        """
-        Unsubscribe to a given IPv6 address.
-        Only used by External Commissioner.
-
-        Args:
-            sAddr   : str : Multicast address to be unsubscribed.
-        """
-        if not isinstance(sAddr, list):
-            sAddr = [sAddr]
-        self.externalCommissioner.MLR(sAddr, 0)
-        return True
+    @API
+    def getMlrLogs(self):
+        return self.externalCommissioner.getMlrLogs()
 
     @API
     def migrateNetwork(self, channel=None, net_name=None):
@@ -3465,75 +3139,80 @@
             on specified 'channel'. Make sure same Mesh Local IID and DUA
             after migration for DUA-TC-06/06b (DEV-1923)
         """
-        try:
-            if channel is None:
-                raise Exception('channel None')
+        if channel is None:
+            raise Exception('channel None')
 
-            if channel not in range(11, 27):
-                raise Exception('channel %d not in [11, 26] Invalid' % channel)
+        if channel not in range(11, 27):
+            raise Exception('channel %d not in [11, 26] Invalid' % channel)
 
-            print('new partition %s on channel %d' % (net_name, channel))
+        print('new partition %s on channel %d' % (net_name, channel))
 
-            mliid = self.__getMlIid()
-            dua = self.getDUA()
-            self.reset()
-            deviceRole = self.deviceRole
-            self.setDefaultValues()
-            self.setChannel(channel)
-            if net_name is not None:
-                self.setNetworkName(net_name)
-            self.__setMlIid(mliid)
-            self.__setDUA(dua)
-            return self.joinNetwork(deviceRole)
-
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('migrateNetwork() Error: ' + str(e))
+        mliid = self.__getMlIid()
+        dua = self.getDUA()
+        self.reset()
+        deviceRole = self.deviceRole
+        self.setDefaultValues()
+        self.setChannel(channel)
+        if net_name is not None:
+            self.setNetworkName(net_name)
+        self.__setMlIid(mliid)
+        self.__setDUA(dua)
+        return self.joinNetwork(deviceRole)
 
     @API
     def setParentPrio(self, prio):
         cmd = 'parentpriority %u' % prio
-        print(cmd)
         return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def role_transition(self, role):
-        assert TESTHARNESS_VERSION == TESTHARNESS_1_2
-        try:
-            cmd = 'mode %s' % OpenThreadTHCI._ROLE_MODE_DICT[role]
-            return self.__executeCommand(cmd)[-1] == 'Done'
-        except Exception as e:
-            ModuleHelper.WriteIntoDebugLogger('role_transition() Error: ' + str(e))
+        cmd = 'mode %s' % OpenThreadTHCI._ROLE_MODE_DICT[role]
+        return self.__executeCommand(cmd)[-1] == 'Done'
 
     @API
     def setLeaderWeight(self, iWeight=72):
         self.__executeCommand('leaderweight %d' % iWeight)
 
+    @watched
+    def isBorderRoutingEnabled(self):
+        try:
+            self.__executeCommand('br omrprefix')
+            return True
+        except CommandError:
+            return False
+
     def __detectZephyr(self):
         """Detect if the device is running Zephyr and adapt in that case"""
 
         try:
+            self._lineSepX = re.compile(r'\r\n|\r|\n')
             if self.__executeCommand(ZEPHYR_PREFIX + 'thread version')[0].isdigit():
-                self.__cmdPrefix = ZEPHYR_PREFIX
-                self.__lineSepX = re.compile(r'\r\n|\r|\n')
+                self._cmdPrefix = ZEPHYR_PREFIX
         except CommandError:
-            pass
+            self._lineSepX = LINESEPX
 
     def __discoverDeviceCapability(self):
         """Discover device capability according to version"""
-        self.DeviceCapability = DevCapb.NotSpecified
-
-        if self.IsBorderRouter:
-            self.DeviceCapability = DevCapb.C_BBR | DevCapb.C_Host | DevCapb.C_Comm
+        thver = self.__executeCommand('thread version')[0]
+        if thver in ['1.3', '4'] and not self.IsBorderRouter:
+            self.log("Setting capability of {}: (DevCapb.C_FTD13 | DevCapb.C_MTD13)".format(self))
+            self.DeviceCapability = OT13_CAPBS
+        elif thver in ['1.3', '4'] and self.IsBorderRouter:
+            self.log("Setting capability of {}: (DevCapb.C_BR13 | DevCapb.C_Host13)".format(self))
+            self.DeviceCapability = OT13BR_CAPBS
+        elif thver in ['1.2', '3'] and not self.IsBorderRouter:
+            self.log("Setting capability of {}: DevCapb.L_AIO | DevCapb.C_FFD | DevCapb.C_RFD".format(self))
+            self.DeviceCapability = OT12_CAPBS
+        elif thver in ['1.2', '3'] and self.IsBorderRouter:
+            self.log("Setting capability of BR {}: DevCapb.C_BBR | DevCapb.C_Host | DevCapb.C_Comm".format(self))
+            self.DeviceCapability = OT12BR_CAPBS
+        elif thver in ['1.1', '2']:
+            self.log("Setting capability of {}: DevCapb.V1_1".format(self))
+            self.DeviceCapability = OT11_CAPBS
         else:
-            # Get Thread stack version to distinguish device capability.
-            thver = self.__executeCommand('thread version')[0]
-
-            if thver in ['1.2', '3']:
-                self.DeviceCapability = (DevCapb.C_FFD | DevCapb.C_RFD | DevCapb.L_AIO)
-            elif thver in ['1.1', '2']:
-                self.DeviceCapability = DevCapb.V1_1
-            else:
-                assert False, thver
+            self.log("Capability not specified for {}".format(self))
+            self.DeviceCapability = DevCapb.NotSpecified
+            assert False, thver
 
     @staticmethod
     def __lstrip0x(s):
@@ -3550,13 +3229,18 @@
 
         return s
 
+    @API
+    def setCcmState(self, state=0):
+        assert state in (0, 1), state
+        self.__executeCommand("ccm {}".format("enable" if state == 1 else "disable"))
+
+    @API
+    def setVrCheckSkip(self):
+        self.__executeCommand("tvcheck disable")
+
 
 class OpenThread(OpenThreadTHCI, IThci):
 
-    # Used for reference firmware version control for Test Harness.
-    # This variable will be updated to match the OpenThread reference firmware
-    # officially released.
-
     def _connect(self):
         print('My port is %s' % self)
         self.__lines = []
@@ -3567,7 +3251,7 @@
             for _ in range(int(timeout / 0.5)):
                 time.sleep(0.5)
                 try:
-                    self.__handle = serial.Serial(self.port, 115200, timeout=0)
+                    self.__handle = serial.Serial(self.port, 115200, timeout=0, write_timeout=1)
                     self.sleep(1)
                     self.__handle.write('\r\n')
                     self.sleep(0.1)
@@ -3596,6 +3280,12 @@
     def _deviceAfterReset(self):
         pass
 
+    def __restartAgentService(self):
+        pass
+
+    def _beforeRegisterMulticast(self, sAddr, timeout):
+        pass
+
     def __socRead(self, size=512):
         if self._is_net:
             return self.__handle.recv(size)
@@ -3622,14 +3312,14 @@
             logging.exception('%s: No new data', self)
             self.sleep(0.1)
 
-        self.__lines += self.__lineSepX.split(tail)
+        self.__lines += self._lineSepX.split(tail)
         if len(self.__lines) > 1:
             return self.__lines.pop(0)
 
     def _cliWriteLine(self, line):
-        if self.__cmdPrefix == ZEPHYR_PREFIX:
-            if not line.startswith(self.__cmdPrefix):
-                line = self.__cmdPrefix + line
+        if self._cmdPrefix == ZEPHYR_PREFIX:
+            if not line.startswith(self._cmdPrefix):
+                line = self._cmdPrefix + line
             self.__socWrite(line + '\r')
         else:
             self.__socWrite(line + '\r\n')
diff --git a/tools/harness-thci/OpenThread_BR.py b/tools/harness-thci/OpenThread_BR.py
index f388135..160d576 100644
--- a/tools/harness-thci/OpenThread_BR.py
+++ b/tools/harness-thci/OpenThread_BR.py
@@ -34,9 +34,9 @@
 import re
 import sys
 import time
+import ipaddress
 
 import serial
-from GRLLibs.UtilityModules.ModuleHelper import ModuleHelper
 from IThci import IThci
 from THCI.OpenThread import OpenThreadTHCI, watched, API
 
@@ -56,6 +56,8 @@
     'Jun 23 05:21:22 raspberrypi otbr-agent[323]: =========[[THCI] direction=send | type=JOIN_FIN.req | len=039]==========]'
 ).group(1) == '=========[[THCI] direction=send | type=JOIN_FIN.req | len=039]==========]'
 
+logging.getLogger('paramiko').setLevel(logging.WARNING)
+
 
 class SSHHandle(object):
 
@@ -75,7 +77,13 @@
 
         self.__handle = paramiko.SSHClient()
         self.__handle.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-        self.__handle.connect(self.ip, port=self.port, username=self.username, password=self.password)
+        try:
+            self.__handle.connect(self.ip, port=self.port, username=self.username, password=self.password)
+        except paramiko.ssh_exception.AuthenticationException:
+            if not self.password:
+                self.__handle.get_transport().auth_none(self.username)
+            else:
+                raise
 
     def close(self):
         if self.__handle is not None:
@@ -154,6 +162,13 @@
 
         self.bash('stty cols 256')
 
+    def log(self, fmt, *args):
+        try:
+            msg = fmt % args
+            print('%s - %s - %s' % (self.port, time.strftime('%b %d %H:%M:%S'), msg))
+        except Exception:
+            pass
+
     def close(self):
         self.__handle.close()
 
@@ -184,7 +199,7 @@
         raise Exception('%s: failed to find end of response' % self.port)
 
     def __bashExpect(self, expected, timeout=20, endswith=False):
-        print('[%s] Expecting [%r]' % (self.port, expected))
+        self.log('Expecting [%r]' % (expected))
 
         deadline = time.time() + timeout
         while time.time() < deadline:
@@ -276,46 +291,72 @@
     DEFAULT_COMMAND_TIMEOUT = 20
 
     IsBorderRouter = True
+    __is_root = False
 
     def _connect(self):
-        self.log("logining Raspberry Pi ...")
+        self.log("logging in to Raspberry Pi ...")
         self.__cli_output_lines = []
         self.__syslog_skip_lines = None
         self.__syslog_last_read_ts = 0
 
         if self.connectType == 'ip':
             self.__handle = SSHHandle(self.telnetIp, self.telnetPort, self.telnetUsername, self.telnetPassword)
+            self.__is_root = self.telnetUsername == 'root'
         else:
             self.__handle = SerialHandle(self.port, 115200)
 
-        self.__afterConnect()
-
     def _disconnect(self):
         if self.__handle:
             self.__handle.close()
             self.__handle = None
 
     def _deviceBeforeReset(self):
+        if self.isPowerDown:
+            self.log('Powering up the device')
+            self.powerUp()
         if self.IsHost:
             self.__stopRadvdService()
-            self.bash('sudo ip -6 addr del 910b::1 dev eth0 || true')
-            self.bash('sudo ip -6 addr del fd00:7d03:7d03:7d03::1 dev eth0 || true')
+            self.bash('ip -6 addr del 910b::1 dev %s || true' % self.backboneNetif)
+            self.bash('ip -6 addr del fd00:7d03:7d03:7d03::1 dev %s || true' % self.backboneNetif)
+
+        self.stopListeningToAddrAll()
 
     def _deviceAfterReset(self):
         self.__dumpSyslog()
         self.__truncateSyslog()
+        self.__enableAcceptRa()
+        if not self.IsHost:
+            self.__restartAgentService()
+            time.sleep(2)
 
-    @API
-    def setupHost(self, setDua=False):
-        self.IsHost = True
+    def __enableAcceptRa(self):
+        self.bash('sysctl net.ipv6.conf.%s.accept_ra=2' % self.backboneNetif)
 
-        if not setDua:
-            cmd = 'sudo ip -6 addr add 910b::1 dev eth0'
-        else:
-            cmd = 'sudo ip -6 addr add fd00:7d03:7d03:7d03::1 dev eth0'
+    def _beforeRegisterMulticast(self, sAddr='ff04::1234:777a:1', timeout=300):
+        """subscribe to the given ipv6 address (sAddr) in interface and send MLR.req OTA
+
+        Args:
+            sAddr   : str : Multicast address to be subscribed and notified OTA.
+        """
+
+        if self.externalCommissioner is not None:
+            self.externalCommissioner.MLR([sAddr], timeout)
+            return True
+
+        cmd = 'nohup ~/repo/openthread/tests/scripts/thread-cert/mcast6.py wpan0 %s' % sAddr
+        cmd = cmd + ' > /dev/null 2>&1 &'
         self.bash(cmd)
 
-        self.__startRadvdService()
+    @API
+    def setupHost(self, setDp=False, setDua=False):
+        self.IsHost = True
+
+        self.bash('ip -6 addr add 910b::1 dev %s' % self.backboneNetif)
+
+        if setDua:
+            self.bash('ip -6 addr add fd00:7d03:7d03:7d03::1 dev %s' % self.backboneNetif)
+
+        self.__startRadvdService(setDp)
 
     def _deviceEscapeEscapable(self, string):
         """Escape CLI escapable characters in the given string.
@@ -329,10 +370,13 @@
         return '"' + string + '"'
 
     @watched
-    def bash(self, cmd, timeout=DEFAULT_COMMAND_TIMEOUT):
-        return self.__handle.bash(cmd, timeout=timeout)
+    def bash(self, cmd, timeout=DEFAULT_COMMAND_TIMEOUT, sudo=True):
+        return self.bash_unwatched(cmd, timeout=timeout, sudo=sudo)
 
-    def bash_unwatched(self, cmd, timeout=DEFAULT_COMMAND_TIMEOUT):
+    def bash_unwatched(self, cmd, timeout=DEFAULT_COMMAND_TIMEOUT, sudo=True):
+        if sudo and not self.__is_root:
+            cmd = 'sudo ' + cmd
+
         return self.__handle.bash(cmd, timeout=timeout)
 
     # Override send_udp
@@ -343,39 +387,41 @@
             return
 
         if interface == 1:
-            ifname = 'eth0'
+            ifname = self.backboneNetif
         else:
-            print('invalid interface')
-            return
+            raise AssertionError('Invalid interface set to send UDP: {} '
+                                 'Available interface options: 0 - Thread; 1 - Ethernet'.format(interface))
+        cmd = '/home/pi/reference-device/send_udp.py %s %s %s %s' % (ifname, dst, port, payload)
+        self.bash(cmd)
 
-        cmd = 'sudo /home/pi/ot-br-posix/script/reference-device/send_udp.py %s %s %s %s' % (ifname, dst, port,
-                                                                                             payload)
-        print(cmd)
+    @API
+    def mldv2_query(self):
+        ifname = self.backboneNetif
+        dst = 'ff02::1'
+
+        cmd = '/home/pi/reference-device/send_mld_query.py %s %s' % (ifname, dst)
         self.bash(cmd)
 
     @API
     def ip_neighbors_flush(self):
-        print('%s call clear_cache' % self.port)
         # clear neigh cache on linux
-        cmd1 = 'sudo ip -6 neigh flush nud all nud failed nud noarp dev eth0'
-        cmd2 = 'sudo ip -6 neigh list nud all dev eth0 ' \
-               '| cut -d " " -f1 ' \
-               '| sudo xargs -I{} ip -6 neigh delete {} dev eth0'
+        cmd1 = 'sudo ip -6 neigh flush nud all nud failed nud noarp dev %s' % self.backboneNetif
+        cmd2 = ('sudo ip -6 neigh list nud all dev %s '
+                '| cut -d " " -f1 '
+                '| sudo xargs -I{} ip -6 neigh delete {} dev %s') % (self.backboneNetif, self.backboneNetif)
         cmd = '%s ; %s' % (cmd1, cmd2)
-        self.bash(cmd)
+        self.bash(cmd, sudo=False)
 
     @API
     def ip_neighbors_add(self, addr, lladdr, nud='noarp'):
-        print('%s ip_neighbors_add' % self.port)
-        cmd1 = 'sudo ip -6 neigh delete %s dev eth0' % addr
-        cmd2 = 'sudo ip -6 neigh add %s dev eth0 lladdr %s nud %s' % (addr, lladdr, nud)
+        cmd1 = 'sudo ip -6 neigh delete %s dev %s' % (addr, self.backboneNetif)
+        cmd2 = 'sudo ip -6 neigh add %s dev %s lladdr %s nud %s' % (addr, self.backboneNetif, lladdr, nud)
         cmd = '%s ; %s' % (cmd1, cmd2)
-        self.bash(cmd)
+        self.bash(cmd, sudo=False)
 
     @API
     def get_eth_ll(self):
-        print('%s get_eth_ll' % self.port)
-        cmd = "ip -6 addr list dev eth0 | grep 'inet6 fe80' | awk '{print $2}'"
+        cmd = "ip -6 addr list dev %s | grep 'inet6 fe80' | awk '{print $2}'" % self.backboneNetif
         ret = self.bash(cmd)[0].split('/')[0]
         return ret
 
@@ -393,8 +439,8 @@
         if hop_limit is None:
             hop_limit = 5
 
-        if self.IsHost or self.IsBackboneRouter:
-            ifName = 'eth0'
+        if self.IsHost or self.IsBorderRouter:
+            ifName = self.backboneNetif
         else:
             ifName = 'wpan0'
 
@@ -406,8 +452,8 @@
             int(hop_limit),
         )
 
-        self.bash(cmd)
-        time.sleep(1)
+        self.bash(cmd, sudo=False)
+        time.sleep(timeout)
 
     def multicast_Ping(self, destination, length=20):
         """send ICMPv6 echo request with a given length to a multicast destination
@@ -417,18 +463,16 @@
             destination: the multicast destination address of ICMPv6 echo request
             length: the size of ICMPv6 echo request payload
         """
-        print('%s call multicast_Ping' % self.port)
-        print('destination: %s' % destination)
         hop_limit = 5
 
-        if self.IsHost or self.IsBackboneRouter:
-            ifName = 'eth0'
+        if self.IsHost or self.IsBorderRouter:
+            ifName = self.backboneNetif
         else:
             ifName = 'wpan0'
 
         cmd = 'ping -6 -I %s %s -c 1 -s %d -t %d' % (ifName, destination, str(length), hop_limit)
 
-        self.bash(cmd)
+        self.bash(cmd, sudo=False)
 
     @API
     def getGUA(self, filterByPrefix=None, eth=False):
@@ -452,8 +496,8 @@
     def __getEthGUA(self, filterByPrefix=None):
         globalAddrs = []
 
-        cmd = 'ip -6 addr list dev eth0 | grep inet6'
-        output = self.bash(cmd)
+        cmd = 'ip -6 addr list dev %s | grep inet6' % self.backboneNetif
+        output = self.bash(cmd, sudo=False)
         for line in output:
             # example: inet6 2401:fa00:41:23:274a:1329:3ab9:d953/64 scope global dynamic noprefixroute
             line = line.strip().split()
@@ -465,14 +509,18 @@
                 continue
 
             addr = line[1].split('/')[0]
-            addr = ModuleHelper.GetFullIpv6Address(addr).lower()
+            addr = str(ipaddress.IPv6Address(addr.decode()).exploded)
             globalAddrs.append(addr)
 
         if not filterByPrefix:
             return globalAddrs[0]
         else:
+            if filterByPrefix[-2:] != '::':
+                filterByPrefix = '%s::' % filterByPrefix
+            prefix = ipaddress.IPv6Network((filterByPrefix + '/64').decode())
             for fullIp in globalAddrs:
-                if fullIp.startswith(filterByPrefix):
+                address = ipaddress.IPv6Address(fullIp.decode())
+                if address in prefix:
                     return fullIp
 
     def _cliReadLine(self):
@@ -489,12 +537,12 @@
     def _deviceGetEtherMac(self):
         # Harness wants it in string. Because wireshark filter for eth
         # cannot be applies in hex
-        return self.bash('ip addr list dev eth0 | grep ether')[0].strip().split()[1]
+        return self.bash('ip addr list dev %s | grep ether' % self.backboneNetif, sudo=False)[0].strip().split()[1]
 
     @watched
     def _onCommissionStart(self):
         assert self.__syslog_skip_lines is None
-        self.__syslog_skip_lines = int(self.bash('wc -l /var/log/syslog')[0].split()[0])
+        self.__syslog_skip_lines = int(self.bash('wc -l /var/log/syslog', sudo=False)[0].split()[0])
         self.__syslog_last_read_ts = 0
 
     @watched
@@ -502,45 +550,45 @@
         assert self.__syslog_skip_lines is not None
         self.__syslog_skip_lines = None
 
-    def _deviceBeforeThreadStart(self):
-        self.bash('sudo sysctl net.ipv6.conf.eth0.accept_ra=2')
-
     @watched
-    def __startRadvdService(self):
+    def __startRadvdService(self, setDp=False):
         assert self.IsHost, "radvd service runs on Host only"
 
-        self.bash("""sudo sh -c "cat >/etc/radvd.conf <<EOF
-interface eth0
-{
-    AdvSendAdvert on;
+        conf = "EOF"
+        conf += "\ninterface %s" % self.backboneNetif
+        conf += "\n{"
+        conf += "\n    AdvSendAdvert on;"
+        conf += "\n"
+        conf += "\n    MinRtrAdvInterval 3;"
+        conf += "\n    MaxRtrAdvInterval 30;"
+        conf += "\n    AdvDefaultPreference low;"
+        conf += "\n"
+        conf += "\n    prefix 910b::/64"
+        conf += "\n    {"
+        conf += "\n        AdvOnLink on;"
+        conf += "\n        AdvAutonomous on;"
+        conf += "\n        AdvRouterAddr on;"
+        conf += "\n    };"
+        if setDp:
+            conf += "\n"
+            conf += "\n    prefix fd00:7d03:7d03:7d03::/64"
+            conf += "\n    {"
+            conf += "\n        AdvOnLink on;"
+            conf += "\n        AdvAutonomous off;"
+            conf += "\n        AdvRouterAddr off;"
+            conf += "\n    };"
+        conf += "\n};"
+        conf += "\nEOF"
+        cmd = 'sh -c "cat >/etc/radvd.conf <<%s"' % conf
 
-    MinRtrAdvInterval 3;
-    MaxRtrAdvInterval 30;
-    AdvDefaultPreference low;
-
-    prefix 910b::/64
-    {
-        AdvOnLink on;
-        AdvAutonomous on;
-        AdvRouterAddr on;
-    };
-    
-    prefix fd00:7d03:7d03:7d03::/64
-    {
-        AdvOnLink on;
-        AdvAutonomous off;
-        AdvRouterAddr off;
-    };
-};
-EOF"
-""")
-        self.bash('sudo service radvd restart')
-        self.bash('sudo service radvd status')
+        self.bash(cmd)
+        self.bash('service radvd restart')
+        self.bash('service radvd status')
 
     @watched
     def __stopRadvdService(self):
         assert self.IsHost, "radvd service runs on Host only"
-        self.bash('sudo service radvd stop')
+        self.bash('service radvd stop')
 
     def __readSyslogToCli(self):
         if self.__syslog_skip_lines is None:
@@ -552,7 +600,7 @@
 
         self.__syslog_last_read_ts = time.time()
 
-        lines = self.bash_unwatched('tail +%d /var/log/syslog' % self.__syslog_skip_lines)
+        lines = self.bash_unwatched('tail +%d /var/log/syslog' % self.__syslog_skip_lines, sudo=False)
         for line in lines:
             m = OTBR_AGENT_SYSLOG_PATTERN.search(line)
             if not m:
@@ -564,25 +612,118 @@
         return len(lines)
 
     def _cliWriteLine(self, line):
-        cmd = 'sudo ot-ctl -- %s' % line
+        cmd = 'ot-ctl -- %s' % line
         output = self.bash(cmd)
         # fake the line echo back
         self.__cli_output_lines.append(line)
         for line in output:
             self.__cli_output_lines.append(line)
 
-    def __afterConnect(self):
-        self.__truncateSyslog()
-        self.__checkServiceStatus()
-
-    def __checkServiceStatus(self):
-        self.bash('sudo service radvd stop')
-        self.bash('sudo service otbr-agent restart')
+    def __restartAgentService(self):
+        restart_cmd = self.extraParams.get('cmd-restart-otbr-agent', 'systemctl restart otbr-agent')
+        self.bash(restart_cmd)
 
     def __truncateSyslog(self):
-        self.bash('sudo truncate -s 0 /var/log/syslog')
+        self.bash('truncate -s 0 /var/log/syslog')
 
     def __dumpSyslog(self):
-        output = self.bash_unwatched('sudo grep "otbr-agent" /var/log/syslog')
+        output = self.bash_unwatched('grep "otbr-agent" /var/log/syslog')
         for line in output:
             self.log('%s', line)
+
+    @API
+    def mdns_query(self, dst='ff02::fb', service='_meshcop._udp.local', addrs_blacklist=[]):
+        # For BBR-TC-03 or DH test cases (empty arguments) just send a query
+        if dst == 'ff02::fb' and not addrs_blacklist:
+            self.bash('dig -p 5353 @%s %s ptr' % (dst, service), sudo=False)
+            return
+
+        # For MATN-TC-17 and MATN-TC-18 use Zeroconf to get the BBR address and border agent port
+        cmd = 'python3 ~/repo/openthread/tests/scripts/thread-cert/find_border_agents.py'
+        output = self.bash(cmd)
+        for line in output:
+            print(line)
+            alias, addr, port, thread_status = eval(line)
+            if thread_status == 2 and addr:
+                if (dst and addr in dst) or (addr not in addrs_blacklist):
+                    if ipaddress.IPv6Address(addr.decode()).is_link_local:
+                        addr = '%s%%%s' % (addr, self.backboneNetif)
+                    return addr, port
+
+        raise Exception('No active Border Agents found')
+
+    # Override powerDown
+    @API
+    def powerDown(self):
+        self.log('Powering down BBR')
+        super(OpenThread_BR, self).powerDown()
+        stop_cmd = self.extraParams.get('cmd-stop-otbr-agent', 'systemctl stop otbr-agent')
+        self.bash(stop_cmd)
+
+    # Override powerUp
+    @API
+    def powerUp(self):
+        self.log('Powering up BBR')
+        start_cmd = self.extraParams.get('cmd-start-otbr-agent', 'systemctl start otbr-agent')
+        self.bash(start_cmd)
+        super(OpenThread_BR, self).powerUp()
+
+    # Override forceSetSlaac
+    @API
+    def forceSetSlaac(self, slaacAddress):
+        self.bash('ip -6 addr add %s/64 dev wpan0' % slaacAddress)
+
+    # Override stopListeningToAddr
+    @API
+    def stopListeningToAddr(self, sAddr):
+        """
+        Unsubscribe to a given IPv6 address which was subscribed earlier wiht `registerMulticast`.
+
+        Args:
+            sAddr   : str : Multicast address to be unsubscribed. Use an empty string to unsubscribe
+                            all the active multicast addresses.
+        """
+        cmd = 'pkill -f mcast6.*%s' % sAddr
+        self.bash(cmd)
+
+    def stopListeningToAddrAll(self):
+        return self.stopListeningToAddr('')
+
+    @API
+    def deregisterMulticast(self, sAddr):
+        """
+        Unsubscribe to a given IPv6 address.
+        Only used by External Commissioner.
+
+        Args:
+            sAddr   : str : Multicast address to be unsubscribed.
+        """
+        self.externalCommissioner.MLR([sAddr], 0)
+        return True
+
+    @watched
+    def _waitBorderRoutingStabilize(self):
+        """
+        Wait for Network Data to stabilize if BORDER_ROUTING is enabled.
+        """
+        if not self.isBorderRoutingEnabled():
+            return
+
+        MAX_TIMEOUT = 30
+        MIN_TIMEOUT = 15
+        CHECK_INTERVAL = 3
+
+        time.sleep(MIN_TIMEOUT)
+
+        lastNetData = self.getNetworkData()
+        for i in range((MAX_TIMEOUT - MIN_TIMEOUT) // CHECK_INTERVAL):
+            time.sleep(CHECK_INTERVAL)
+            curNetData = self.getNetworkData()
+
+            # Wait until the Network Data is not changing, and there is OMR Prefix and External Routes available
+            if curNetData == lastNetData and len(curNetData['Prefixes']) > 0 and len(curNetData['Routes']) > 0:
+                break
+
+            lastNetData = curNetData
+
+        return lastNetData
diff --git a/tools/harness-thci/OpenThread_WpanCtl.py b/tools/harness-thci/OpenThread_WpanCtl.py
index c7bb9d7..42d8aa9 100644
--- a/tools/harness-thci/OpenThread_WpanCtl.py
+++ b/tools/harness-thci/OpenThread_WpanCtl.py
@@ -648,8 +648,8 @@
         print('call _setSecurityPolicy')
         try:
             cmd1 = self.wpan_cmd_prefix + 'setprop Dataset:SecPolicy:KeyRotation %s' % str(securityPolicySecs)
-            if securityPolicyFlags == 'onrcb':
-                cmd2 = self.wpan_cmd_prefix + 'setprop Dataset:SecPolicy:Flags 0xff'
+            if securityPolicyFlags == 'onrc':
+                cmd2 = self.wpan_cmd_prefix + 'setprop Dataset:SecPolicy:Flags 0xf7'
             else:
                 print('unknown policy flag :' + securityPolicyFlags)
                 return False
@@ -1442,7 +1442,7 @@
         # OT only accept hex format PSKc for now
         self.pskc = '00000000000000000000000000000000'
         self.securityPolicySecs = ModuleHelper.Default_SecurityPolicy
-        self.securityPolicyFlags = 'onrcb'
+        self.securityPolicyFlags = 'onrc'
         self.activetimestamp = ModuleHelper.Default_ActiveTimestamp
         # self.sedPollingRate = ModuleHelper.Default_Harness_SED_Polling_Rate
         self.__sedPollPeriod = 3 * 1000  # in milliseconds
diff --git a/tools/otci/otci/command_handlers.py b/tools/otci/otci/command_handlers.py
index 3c50ddd..0055b1a 100644
--- a/tools/otci/otci/command_handlers.py
+++ b/tools/otci/otci/command_handlers.py
@@ -76,6 +76,9 @@
         """
         pass
 
+    def shell(self, cmd: str, timeout: float) -> List[str]:
+        raise NotImplementedError("shell command is not supported on %s" % self.__class__.__name__)
+
 
 class OtCliCommandRunner(OTCommandHandler):
     __PATTERN_COMMAND_DONE_OR_ERROR = re.compile(
@@ -83,9 +86,18 @@
 
     __PATTERN_LOG_LINE = re.compile(r'((\[(NONE|CRIT|WARN|NOTE|INFO|DEBG)\])'
                                     r'|(-.*-+: )'  # e.g. -CLI-----: 
+                                    r'|(\[[DINWC\-]\] (?=[\w\-]{14}:)\w+-*:)'  # e.g. [I] Mac-----------:
                                     r')')
     """regex used to filter logs"""
 
+    assert __PATTERN_LOG_LINE.match('[I] ChannelMonitor: debug log')
+    assert __PATTERN_LOG_LINE.match('[I] Mac-----------: info log')
+    assert __PATTERN_LOG_LINE.match('[N] MeshForwarder-: note    log')
+    assert __PATTERN_LOG_LINE.match('[W] Notifier------: warn log')
+    assert __PATTERN_LOG_LINE.match('[C] Mle-----------: critical log')
+    assert __PATTERN_LOG_LINE.match('[-] Settings------: none log')
+    assert not __PATTERN_LOG_LINE.match('[-] Settings-----: none log')  # not enough `-` after module name
+
     __ASYNC_COMMANDS = {'scan', 'ping', 'discover'}
 
     def __init__(self, otcli: OtCliHandler, is_spinel_cli=False):
@@ -104,6 +116,7 @@
         return repr(self.__otcli)
 
     def execute_command(self, cmd, timeout=10) -> List[str]:
+        assert not self.__should_close.is_set(), "OT CLI is already closed."
         self.__otcli.writeline(cmd)
 
         if cmd in ('reset', 'factoryreset'):
@@ -137,6 +150,7 @@
     def close(self):
         self.__should_close.set()
         self.__otcli.close()
+        self.__otcli_reader.join()
 
     def set_line_read_callback(self, callback: Optional[Callable[[str], Any]]):
         self.__line_read_callback = callback
@@ -178,10 +192,20 @@
         return output
 
     def __otcli_read_routine(self):
-        while not self.__should_close.isSet():
-            line = self.__otcli.readline()
+        while not self.__should_close.is_set():
+            try:
+                line = self.__otcli.readline()
+            except Exception:
+                if self.__should_close.is_set():
+                    break
+                else:
+                    raise
+
             logging.debug('%s: %r', self.__otcli, line)
 
+            if line is None:
+                break
+
             if line.startswith('> '):
                 line = line[2:]
 
@@ -224,16 +248,11 @@
         return f'{self.__host}:{self.__port}'
 
     def execute_command(self, cmd: str, timeout: float) -> List[str]:
-        sh_cmd = f'ot-ctl -- {cmd}'
+        sh_cmd = f'ot-ctl {cmd}'
         if self.__sudo:
             sh_cmd = 'sudo ' + sh_cmd
 
-        cmd_in, cmd_out, cmd_err = self.__ssh.exec_command(sh_cmd, timeout=int(timeout), bufsize=1024)
-        err = cmd_err.read().decode('utf-8')
-        if err:
-            raise CommandError(cmd, [err])
-
-        output = [l.rstrip('\r\n') for l in cmd_out.readlines()]
+        output = self.shell(sh_cmd, timeout=timeout)
 
         if self.__line_read_callback is not None:
             for line in output:
@@ -244,6 +263,16 @@
 
         return output
 
+    def shell(self, cmd: str, timeout: float) -> List[str]:
+        cmd_in, cmd_out, cmd_err = self.__ssh.exec_command(cmd, timeout=int(timeout), bufsize=1024)
+        errput = [l.rstrip('\r\n') for l in cmd_err.readlines()]
+        output = [l.rstrip('\r\n') for l in cmd_out.readlines()]
+
+        if errput:
+            raise CommandError(cmd, errput)
+
+        return output
+
     def close(self):
         self.__ssh.close()
 
diff --git a/tools/otci/otci/connectors.py b/tools/otci/otci/connectors.py
index 1785f11..713fbc3 100644
--- a/tools/otci/otci/connectors.py
+++ b/tools/otci/otci/connectors.py
@@ -30,6 +30,7 @@
 import subprocess
 import time
 from abc import abstractmethod
+from typing import Optional
 
 
 class OtCliHandler:
@@ -142,14 +143,25 @@
         self.__baudrate = baudrate
 
         import serial
-        self.__serial = serial.Serial(self.__dev, self.__baudrate, timeout=None, exclusive=True)
+        self.__serial = serial.Serial(self.__dev, self.__baudrate, timeout=0.1, exclusive=True)
+        self.__linebuffer = b''
 
     def __repr__(self):
         return self.__dev
 
-    def readline(self) -> str:
-        line = self.__serial.readline().decode('utf-8').rstrip('\r\n')
-        return line
+    def readline(self) -> Optional[str]:
+        while self.__serial.is_open:
+            line = self.__serial.readline()
+
+            if not line.endswith(b'\n'):
+                self.__linebuffer += line
+            else:
+                line = self.__linebuffer + line
+                self.__linebuffer = b''
+
+                return line.decode('utf-8', errors='ignore').rstrip('\r\n')
+
+        return None
 
     def writeline(self, s: str):
         self.__serial.write((s + '\n').encode('utf-8'))
diff --git a/tools/otci/otci/otci.py b/tools/otci/otci/otci.py
index b93bbc2..da6ef61 100644
--- a/tools/otci/otci/otci.py
+++ b/tools/otci/otci/otci.py
@@ -47,6 +47,10 @@
     manipulate an OpenThread device.
     """
 
+    DEFAULT_EXEC_COMMAND_RETRY = 4  # A command is retried 4 times if failed.
+
+    __exec_command_retry = DEFAULT_EXEC_COMMAND_RETRY
+
     def __init__(self, otcmd: OTCommandHandler):
         """
         This method initializes an OTCI instance.
@@ -67,7 +71,7 @@
         :param expect_line: The line expected to output if given.
                             Raise ExpectLineTimeoutError if expect_line is not found within the given duration.
         """
-        self.__logger and self.__logger.info("wait for %.3f seconds", duration)
+        self.log('info', "wait for %.3f seconds", duration)
         if expect_line is None:
             self.__otcmd.wait(duration)
         else:
@@ -88,7 +92,23 @@
         """Close the OTCI instance."""
         self.__otcmd.close()
 
-    def execute_command(self, cmd: str, timeout: float = 10, silent: bool = False) -> List[str]:
+    def execute_command(self,
+                        cmd: str,
+                        timeout: float = 10,
+                        silent: bool = False,
+                        already_is_ok: bool = True) -> List[str]:
+        for i in range(self.__exec_command_retry + 1):
+            try:
+                return self.__execute_command(cmd, timeout, silent, already_is_ok=already_is_ok)
+            except Exception:
+                if i == self.__exec_command_retry:
+                    raise
+
+    def __execute_command(self,
+                          cmd: str,
+                          timeout: float = 10,
+                          silent: bool = False,
+                          already_is_ok: bool = True) -> List[str]:
         """Execute the OpenThread CLI command.
 
         :param cmd: The command to execute.
@@ -97,27 +117,42 @@
         :returns: The command output as a list of lines.
         """
         if not silent:
-            self.__logger and self.__logger.info('> %s', cmd)
+            self.log('info', '> %s', cmd)
 
         output = self.__otcmd.execute_command(cmd, timeout)
 
         if not silent:
             for line in output:
-                self.__logger and self.__logger.info('%s', line)
+                self.log('info', '%s', line)
 
         if cmd in ('reset', 'factoryreset'):
             return output
 
-        if output[-1] == 'Done':
+        if output[-1] == 'Done' or (already_is_ok and output[-1] == 'Error 24: Already'):
             output = output[:-1]
             return output
         else:
             raise CommandError(cmd, output)
 
+    def set_execute_command_retry(self, n: int):
+        assert n >= 0
+        self.__exec_command_retry = n
+
+    def shell(self, cmd: str, timeout: float = 10):
+        self.log('info', '# %s', cmd)
+        output = self.__otcmd.shell(cmd, timeout=timeout)
+        for line in output:
+            self.log('info', '%s', line)
+        return output
+
     def set_logger(self, logger: logging.Logger):
         """Set the logger for the OTCI instance, or None to disable logging."""
         self.__logger = logger
 
+    def log(self, level, fmt, *args, **kwargs):
+        if self.__logger is not None:
+            getattr(self.__logger, level)('(%s) ' + fmt, repr(self), *args, **kwargs)
+
     def set_line_read_callback(self, callback: Optional[Callable[[str], Any]]):
         """Set the callback that will be called for each line output by the CLI."""
         self.__otcmd.set_line_read_callback(callback)
@@ -189,7 +224,7 @@
              interval: float = 1,
              hoplimit: int = 64,
              timeout: float = 3) -> Dict:
-        """Send an ICMPv6 Echo Request. 
+        """Send an ICMPv6 Echo Request.
         The default arguments are consistent with https://github.com/openthread/openthread/blob/main/src/core/utils/ping_sender.hpp.
 
         :param ip: The target IPv6 address to ping.
@@ -245,7 +280,12 @@
         for line in output[2:]:
             fields = line.strip().split('|')
 
-            _, J, netname, extpanid, panid, extaddr, ch, dbm, lqi, _ = fields
+            try:
+                _, J, netname, extpanid, panid, extaddr, ch, dbm, lqi, _ = fields
+            except Exception:
+                logging.warning('ignored output: %r', line)
+                continue
+
             networks.append({
                 'joinable': bool(int(J)),
                 'network_name': netname.strip(),
@@ -829,6 +869,7 @@
 
     def dns_resolve_service(self, instance: str, service: str) -> Dict:
         """Resolves aservice instance."""
+        instance = self.__escape_escapable(instance)
         cmd = f'dns service {instance} {service}'
         output = self.execute_command(cmd, 30.0)
 
@@ -935,7 +976,7 @@
                     info['addresses'] = list(map(Ip6Addr, v.split(', ')))
                 elif k == 'subtypes':
                     info[k] = list() if v == '(null)' else list(v.split(','))
-                elif k in ('port', 'weight', 'priority'):
+                elif k in ('port', 'weight', 'priority', 'ttl'):
                     info[k] = int(v)
                 elif k in ('host',):
                     info[k] = v
@@ -1089,6 +1130,7 @@
                                priority: int = 0,
                                weight: int = 0,
                                txt: Dict[str, Union[str, bytes, bool]] = None):
+        instance = self.__escape_escapable(instance)
         cmd = f'srp client service add {instance} {service} {port} {priority} {weight}'
         if txt:
             cmd += f' {self.__txt_to_hex(txt)}'
@@ -1098,6 +1140,10 @@
         """Remove a service from SRP client."""
         self.execute_command(f'srp client service remove {instance} {service}')
 
+    def srp_client_clear_service(self, instance: str, service: str):
+        """Remove a service from SRP client without notifying the SRP server."""
+        self.execute_command(f'srp client service clear {instance} {service}')
+
     def srp_client_get_key_lease_interval(self) -> int:
         """Get SRP client key lease interval (in seconds)."""
         return self.__parse_int(self.execute_command('srp client keyleaseinterval'))
@@ -1174,7 +1220,7 @@
             elif k == 'RSSI':
                 info['rssi'] = int(v)
             else:
-                self.__logger and self.__logger.warning("Child info %s: %s ignored", k, v)
+                self.log('warning', "Child info %s: %s ignored", k, v)
 
         return info
 
@@ -1671,7 +1717,7 @@
         # Network Name: OpenThread-7caa
         # PAN ID: 0x7caa
         # PSKc: 167d89fd169e439ca0b8266de248090f
-        # Security Policy: 0, onrcb
+        # Security Policy: 0, onrc
 
         dataset = {}
 
@@ -1715,6 +1761,14 @@
         hexstr = self.__parse_str(self.execute_command(cmd))
         return self.__hex_to_bytes(hexstr)
 
+    def set_dataset_bytes(self, dataset: str, data: bytes) -> None:
+        if dataset in ('active', 'pending'):
+            cmd = f'dataset set {dataset} {self.__bytes_to_hex(data)}'
+        else:
+            raise InvalidArgumentsError(f'Unkonwn dataset: {dataset}')
+
+        self.execute_command(cmd)
+
     def dataset_set_buffer(self,
                            active_timestamp: int = None,
                            channel: int = None,
@@ -1913,7 +1967,7 @@
 
     def get_backbone_router_state(self) -> str:
         """Get local Backbone state (Disabled or Primary or Secondary) for Thread 1.2 FTD."""
-        self.__parse_str(self.execute_command('bbr state'))
+        return self.__parse_str(self.execute_command('bbr state'))
 
     def get_primary_backbone_router_info(self) -> Optional[dict]:
         """Show current Primary Backbone Router information for Thread 1.2 device."""
@@ -2194,6 +2248,29 @@
         """Disable link security."""
         self.execute_command('udp linksecurity disable')
 
+    def netstat(self) -> List[Tuple[Tuple[Ip6Addr, int], Tuple[Ip6Addr, int]]]:
+        cmd = 'netstat'
+        output = self.execute_command(cmd)
+        if len(output) < 2:
+            raise UnexpectedCommandOutput(output)
+
+        socks = []
+        for line in output[2:]:
+            _, sock_addr, peer_addr = line.strip().split('|')[:3]
+            sock_addr = self.__parse_socket_addr(sock_addr.strip())
+            peer_addr = self.__parse_socket_addr(peer_addr.strip())
+            socks.append((sock_addr, peer_addr))
+
+        return socks
+
+    @staticmethod
+    def __parse_socket_addr(addr: str) -> Tuple[Ip6Addr, int]:
+        addr, port = addr.rsplit(':', 1)
+        if addr.startswith('[') and addr.endswith(']'):
+            addr = addr[1:-1]
+
+        return Ip6Addr(addr), int(port) if port != '*' else 0
+
     #
     # CoAP CLI (test) utilities
     #
@@ -2354,6 +2431,9 @@
         self.__validate_hex(hexstr)
         return bytes(int(hexstr[i:i + 2], 16) for i in range(0, len(hexstr), 2))
 
+    def __bytes_to_hex(self, data: bytes) -> str:
+        return ''.join('%02x' % b for b in data)
+
     def __escape_escapable(self, s: str) -> str:
         """Escape CLI escapable characters in the given string.
         """
diff --git a/tools/otci/tests/test_otci.py b/tools/otci/tests/test_otci.py
index c1eacef..38c5981 100644
--- a/tools/otci/tests/test_otci.py
+++ b/tools/otci/tests/test_otci.py
@@ -172,7 +172,7 @@
         self.assertEqual(leader.get_preferred_partition_id(), 0xabcddead)
 
         leader.thread_start()
-        leader.wait(5)
+        leader.wait(10)
         self.assertEqual('leader', leader.get_state())
         self.assertEqual(0xabcddead, leader.get_leader_data()['partition_id'])
         logging.info('leader key sequence counter = %d', leader.get_key_sequence_counter())
@@ -519,7 +519,7 @@
 
         node1.ifconfig_up()
         node1.thread_start()
-        node1.wait(5)
+        node1.wait(10)
         assert node1.get_state() == "leader"
 
         node1.commissioner_start()
@@ -533,7 +533,7 @@
         node2.joiner_start("TEST123")
         node2.wait(10, expect_line="Join success")
         node2.thread_start()
-        node2.wait(5)
+        node2.wait(10)
         assert node2.get_state() == "router"
 
     def _test_otci_multi_nodes(self, leader, commissioner, child1, child2):
@@ -571,7 +571,7 @@
         self.assertEqual('rdn', leader.get_mode())
 
         leader.thread_start()
-        leader.wait(5)
+        leader.wait(10)
         self.assertEqual('leader', leader.get_state())
         logging.info('leader key sequence counter = %d', leader.get_key_sequence_counter())
 
@@ -587,7 +587,7 @@
         commissioner.set_network_key(TEST_NETWORKKEY)
         commissioner.thread_start()
 
-        commissioner.wait(5)
+        commissioner.wait(10)
 
         self.assertEqual('router', commissioner.get_state())